diff --git a/.codeclimate.yml b/.codeclimate.yml deleted file mode 100644 index 299f85340..000000000 --- a/.codeclimate.yml +++ /dev/null @@ -1,16 +0,0 @@ -engines: - duplication: - enabled: true - config: - languages: - javascript: - mass_threshold: 50 - eslint: - enabled: true - channel: "eslint-3" - -ratings: - paths: - - "**.js" - -exclude_paths: diff --git a/.editorconfig b/.editorconfig index 219985c22..c35a00240 100644 --- a/.editorconfig +++ b/.editorconfig @@ -4,7 +4,6 @@ root = true - [*] end_of_line = lf charset = utf-8 diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..84717f967 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,26 @@ +# unconventional js +/blueprints/*/files/ +/vendor/ + +# compiled output +/dist/ +/tmp/ +/test-projects/*/dist/ +/test-projects/*/tmp/ + +# dependencies +/bower_components/ +/node_modules/ +/test-projects/*/node_modules/ + +# misc +/coverage/ +!.* +.*/ +.eslintcache + +# ember-try +/.node_modules.ember-try/ +/bower.json.ember-try +/package.json.ember-try +/yarn.lock.ember-try diff --git a/.eslintrc.js b/.eslintrc.js index cceb10f10..aefaed885 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,31 +1,58 @@ +'use strict'; + module.exports = { root: true, + parser: 'babel-eslint', parserOptions: { - ecmaVersion: 6, - sourceType: 'module' + ecmaVersion: 2018, + sourceType: 'module', + ecmaFeatures: { + legacyDecorators: true, + }, }, + plugins: ['ember'], extends: [ 'eslint:recommended', - 'plugin:ember-suave/recommended' + 'plugin:ember/recommended', + 'plugin:prettier/recommended', ], env: { - 'browser': true + browser: true, }, - rules: { - 'camelcase': 0, - 'ember-suave/no-direct-property-access': 0, - 'ember-suave/prefer-destructuring': 0, - 'object-curly-spacing': 0, - 'quotes': 0, - 'array-bracket-spacing': 0, - 'no-var': 0, - 'object-shorthand': 0, - 'arrow-parens': 0, - 'no-unused-vars': ['error', { 'args': 'none' }] - }, - globals: { - faker: true, - server: true, - $: true - } + rules: {}, + overrides: [ + // node files + { + files: [ + './.eslintrc.js', + './.prettierrc.js', + './.template-lintrc.js', + './ember-cli-build.js', + './index.js', + './testem.js', + './blueprints/*/index.js', + './config/**/*.js', + './tests/dummy/config/**/*.js', + './fastboot-tests/included-files-test.js', + './test-projects/*/ember-cli-build.js', + './test-projects/*/testem.js', + './test-projects/*/config/**/*.js', + './test-projects/*/fastboot-tests/**/*.js', + ], + parserOptions: { + sourceType: 'script', + }, + env: { + browser: false, + node: true, + }, + plugins: ['node'], + extends: ['plugin:node/recommended'], + }, + { + // Test files: + files: ['tests/**/*-test.{js,ts}'], + extends: ['plugin:qunit/recommended'], + }, + ], }; diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..d0a9746f6 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: +- package-ecosystem: npm + directory: "/" + schedule: + interval: daily diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..277e6a6e2 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,83 @@ +name: CI + +on: + push: + branches: + - main + - master + pull_request: {} + +jobs: + test: + name: "Tests" + runs-on: ubuntu-latest + timeout-minutes: 60 + + steps: + - uses: actions/checkout@v2 + - name: Install Node + uses: actions/setup-node@v2 + with: + node-version: 12.x + cache: yarn + - name: Install Dependencies + run: yarn install --frozen-lockfile + - name: Lint + run: yarn lint + - name: Run Browser Tests + run: yarn test:ember + - name: Run Node Tests + run: yarn test:test-projects + + floating: + name: "Floating Dependencies" + runs-on: ubuntu-latest + timeout-minutes: 60 + + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: 12.x + cache: yarn + - name: Install Dependencies + run: yarn install --no-lockfile + - name: Run Browser Tests + run: yarn test:ember + - name: Run Node Tests + run: yarn test:test-projects + + try-scenarios: + name: ${{ matrix.try-scenario }} + runs-on: ubuntu-latest + timeout-minutes: 60 + needs: 'test' + + strategy: + fail-fast: false + matrix: + try-scenario: + - ember-lts-3.12 + - ember-lts-3.16 + - ember-lts-3.20 + - ember-lts-3.24 + - ember-lts-3.28 + #- ember-release + #- ember-beta + #- ember-canary + - ember-classic + - ember-default-with-jquery + #- embroider-safe + #- embroider-optimized + + steps: + - uses: actions/checkout@v2 + - name: Install Node + uses: actions/setup-node@v2 + with: + node-version: 12.x + cache: yarn + - name: Install Dependencies + run: yarn install --frozen-lockfile + - name: Run Tests + run: ./node_modules/.bin/ember try:one ${{ matrix.try-scenario }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 000000000..28742da13 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,26 @@ +name: CI Publish + +on: + push: + tags: + - '*' + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install Node + uses: actions/setup-node@v2 + with: + node-version: 12.x + cache: yarn + - name: Install Dependencies + run: yarn install --frozen-lockfile + - name: Lint + run: yarn lint + - name: Run Browser Tests + run: yarn test:ember + - uses: JS-DevTools/npm-publish@v1 + with: + token: ${{ secrets.NPM_TOKEN }} diff --git a/.gitignore b/.gitignore index 9b1890c46..d3a027916 100644 --- a/.gitignore +++ b/.gitignore @@ -1,20 +1,31 @@ -# See http://help.github.com/ignore-files/ for more about ignoring files. +# See https://help.github.com/ignore-files/ for more about ignoring files. # compiled output -/dist -/tmp +/dist/ +/tmp/ # dependencies -/node_modules -/bower_components +/bower_components/ +/node_modules/ # misc +/.env* +/.pnp* /.sass-cache +/.eslintcache /connect.lock -/coverage/* +/coverage/ /libpeerconnection.log -npm-debug.log* -testem.log +/npm-debug.log* +/testem.log +/yarn-error.log + +# ember-try +/.node_modules.ember-try/ +/bower.json.ember-try +/package.json.ember-try + +# custom .floo _site jekyll-tmp @@ -22,3 +33,6 @@ jekyll-tmp # IDE /.idea/ /*.iml + +### macOS ### +*.DS_Store diff --git a/.node-version b/.node-version new file mode 100644 index 000000000..5b7269c0a --- /dev/null +++ b/.node-version @@ -0,0 +1 @@ +10.19.0 diff --git a/.npmignore b/.npmignore index 2c4ecf9a3..804020bd7 100644 --- a/.npmignore +++ b/.npmignore @@ -1,15 +1,43 @@ -/bower_components +# compiled output +/dist/ +/tmp/ + +# dependencies +/bower_components/ + +# misc +/.bowerrc +/.editorconfig +/.ember-cli +/.env* +/.eslintcache +/.eslintignore +/.eslintrc.js +/.git/ +/.gitignore +/.prettierignore +/.prettierrc.js +/.template-lintrc.js +/.travis.yml +/.watchmanconfig +/bower.json /config/ember-try.js -/dist -/tests -/tmp -**/.gitkeep -.bowerrc -.editorconfig -.ember-cli -.gitignore -.watchmanconfig -.travis.yml -bower.json -ember-cli-build.js -testem.js +/CONTRIBUTING.md +/ember-cli-build.js +/testem.js +/tests/ +/yarn-error.log +/yarn.lock +.gitkeep + +# ember-try +/.node_modules.ember-try/ +/bower.json.ember-try +/package.json.ember-try + +/.sass-cache +/jekyll-tmp +*.md + +/test-projects +/scripts diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..0eb446e29 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,22 @@ +# unconventional js +/blueprints/*/files/ +/vendor/ + +# compiled output +/dist/ +/tmp/ + +# dependencies +/bower_components/ +/node_modules/ +/test-projects/*/node_modules/ + +# misc +/coverage/ +!.* +.eslintcache + +# ember-try +/.node_modules.ember-try/ +/bower.json.ember-try +/package.json.ember-try diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 000000000..534e6d35a --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = { + singleQuote: true, +}; diff --git a/.template-lintrc.js b/.template-lintrc.js new file mode 100644 index 000000000..f35f61c7b --- /dev/null +++ b/.template-lintrc.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = { + extends: 'recommended', +}; diff --git a/.travis.yml b/.travis.yml index 331c7ac70..7406f4dce 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,42 +1,85 @@ --- language: node_js node_js: - - "4" - - "6" - - "7" + - "10" sudo: false +dist: trusty + +addons: + chrome: stable cache: - directories: - - $HOME/.npm - - $HOME/.cache # includes bower's cache + yarn: true env: - # we recommend testing LTS's and latest stable release (bonus points to beta/canary) - - EMBER_TRY_SCENARIO=ember-1.13 - - EMBER_TRY_SCENARIO=ember-lts-2.4 - - EMBER_TRY_SCENARIO=ember-release - - EMBER_TRY_SCENARIO=ember-beta - - EMBER_TRY_SCENARIO=ember-canary - -matrix: - fast_finish: true - allow_failures: + global: + # See https://git.io/vdao3 for details. + - JOBS=1 + +install: + - yarn install --no-lockfile --non-interactive + +notifications: + email: false + +# Identifies `a.b.c-xxx.n` tags as pre-releases, and `a.b.c` as stable releases +before_deploy: | + function npm_dist_tag() { + if [[ "$TRAVIS_TAG" = *"-"* ]]; then + echo "next" + else + echo "latest" + fi + } + +jobs: + fail_fast: true + + include: + - stage: locked dependencies + env: NAME=browser tests + install: yarn install + script: yarn test:browser + - env: NAME=node tests + install: yarn install + script: yarn test:test-projects + + - stage: floating dependencies + env: NAME=browser tests + script: yarn test:browser + - env: NAME=node tests + script: yarn test:test-projects + + - stage: versioned tests + env: EMBER_TRY_SCENARIO=ember-lts-3.20 + - env: EMBER_TRY_SCENARIO=ember-release + - env: EMBER_TRY_SCENARIO=ember-beta - env: EMBER_TRY_SCENARIO=ember-canary + - env: EMBER_TRY_SCENARIO=ember-default + - env: EMBER_TRY_SCENARIO=ember-default-with-jquery -before_install: - - npm config set spin false - - npm install -g bower - - bower --version - - npm install phantomjs-prebuilt - - node_modules/phantomjs-prebuilt/bin/phantomjs --version + - stage: deploy + if: (branch = master OR tag IS present) AND type = push + env: NAME=deploy + script: node_modules/.bin/ember deploy production -install: - - npm install - - bower install + - stage: npm release + install: skip + script: skip + deploy: + provider: npm + tag: $(npm_dist_tag) + email: sam.selikoff@gmail.com + api_key: + secure: O6cP0nTiCbA+MuD6hRKdyyd6DWTFR/dc9klB10zXTnrwajjzLmenvvshPUv+F6lHCpb2SfrWW6cpFjZ61BPwKaaalF9u8encNkGlDYGtO77sWJu6LuJFeWPZnAC9rdAw4hPjz+gqTL+leeDMHzjB32VRqy2cpwFzet3e+W2eUuk= + on: + tags: true + repo: miragejs/ember-cli-mirage + + allow_failures: + - env: EMBER_TRY_SCENARIO=ember-beta + - env: EMBER_TRY_SCENARIO=ember-canary script: - # Usually, it's ok to finish the test scenario without reverting - # to the addon's original dependency state, skipping "cleanup". - - ember try:one $EMBER_TRY_SCENARIO test --skip-cleanup + - node_modules/.bin/ember try:one $EMBER_TRY_SCENARIO diff --git a/CHANGELOG.md b/CHANGELOG.md index 195fd99f8..0ee0feb95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,665 +1,3 @@ -# Ember CLI Mirage Changelog +# Ember CLI Mirage Change log -## 0.2.9 - -Update notes: none - -Changes: - - - [ENHANCEMENT] [#1006](https://github.com/samselikoff/ember-cli-mirage/pull/1006) Make host/namespace support more robust @zinyando - -## 0.2.8 - -Update notes: none - -Changes: - - - [BUGFIX] [#1026](https://github.com/samselikoff/ember-cli-mirage/pull/1040) Import `require` to avoid issue in babel@6 @rwjblue - - [BUGFIX] [#1026](https://github.com/samselikoff/ember-cli-mirage/pull/1026) Fixes generated code for destroy app helper @NLincoln - -## 0.2.7 - -Update notes: 0.2.6 introduced a breaking change for PhantomJS users, so we've reverted a change and published 0.2.7. See [#1024](https://github.com/samselikoff/ember-cli-mirage/pull/1024) for details. - -Changes: - - - [BUGFIX [#1025](https://github.com/samselikoff/ember-cli-mirage/pull/1025) Fix factory association feature @yratanov - - [BUGFIX [#1024](https://github.com/samselikoff/ember-cli-mirage/pull/1024) Replace Number.isInteger with lodash isInteger @ilucin - - [ENHANCEMENT [#1023](https://github.com/samselikoff/ember-cli-mirage/pull/1023) Allow route handlers to return empty string responses @bendemboski - - [ENHANCEMENT [#1030](https://github.com/samselikoff/ember-cli-mirage/pull/1030) Code Climate config with ESLint and duplication @larkinscott - -## 0.2.6 - -Update notes: None - -Changes: - - - [ENHANCEMENT] [#1010](https://github.com/samselikoff/ember-cli-mirage/pull/1010) Better support for nested addons @samselikoff - - [ENHANCEMENT] [#998](https://github.com/samselikoff/ember-cli-mirage/pull/998) Adapting to use lodash 4 using latest ember-lodash @eturino - - [ENHANCEMENT] [#1008](https://github.com/samselikoff/ember-cli-mirage/pull/1008) Upgrade to Ember CLI 2.9 @cibernox - - [ENHANCEMENT] [#995](https://github.com/samselikoff/ember-cli-mirage/pull/995) Invoke _getAttrsForRequest with correct model name @bwbuchanan - - General improvements @azdaroth - -## 0.2.5 - -Update notes: None - -Changes: - - - [FEATURE] [#880](https://github.com/samselikoff/ember-cli-mirage/pull/880) Add association helper @azdaroth - - [FEATURE] [#948](https://github.com/samselikoff/ember-cli-mirage/pull/948) Add length to collections @mfazekas - - [FEATURE] [#957](https://github.com/samselikoff/ember-cli-mirage/pull/957) Add slice method to collections @alexparker - - [ENHANCEMENT] [#796](https://github.com/samselikoff/ember-cli-mirage/pull/796) improve `normalizedRequestAttrs` helper @jbailey4 - - [ENHANCEMENT] [#928](https://github.com/samselikoff/ember-cli-mirage/pull/928) add a default passthrough @anulman - - [ENHANCEMENT] [#987](https://github.com/samselikoff/ember-cli-mirage/pull/987) Added falsy condition to exclude faker.js & pretender.js in production build @renpinto - - [BUGFIX] [#984](https://github.com/samselikoff/ember-cli-mirage/pull/984) Blueprint.prototype.insertIntoFile is async @stefanpennar - - [BUGFIX] [#905](https://github.com/samselikoff/ember-cli-mirage/pull/905) Serialize on key instead of modelName @jessedijkstra - - [BUGFIX] [#950](https://github.com/samselikoff/ember-cli-mirage/pull/950) fix JSON:API includes @deepflame - - General improvements @jessedijkstra @bantic @alecho @alexparker @mfazekas @azdaroth - -## 0.2.4 - -Update notes: None - -Changes: - - - [ENHANCEMENT] Let faker float from 3.0.0 @Dhaulagiri - - To improve backwards compatibility concerns raised by the changes from [#863](https://github.com/samselikoff/ember-cli-mirage/pull/863), [#932](https://github.com/samselikoff/ember-cli-mirage/pull/932) allows the version of Faker.js used in ember-cli-mirage to float from `3.0.0`. If you need to use a specific older `3.x` version in your project you can specify it in your project's package.json. - - General improvements @Gaurav0 - -## 0.2.3 - -Update notes: None - -Changes: - - Newer versions of Pretender will [show a warning](https://github.com/pretenderjs/pretender/pull/178) - if you forget to shut down a pretender server before starting another one. Mirage does this - for you in acceptance tests, but if you are starting Mirage manually in other tests, remember - to shut down the server when you are done. - (see [#925](https://github.com/samselikoff/ember-cli-mirage/pull/925)) - -Changes: - - - [FEATURE] Add support for promises in route functions - ([#924](https://github.com/samselikoff/ember-cli-mirage/pull/924)) - @dustinfarris - - [BUGFIX] Adjust afterCreate callbacks execution order - ([#893](https://github.com/samselikoff/ember-cli-mirage/pull/893)) - @Azdaroth - - [INTERNAL] Shutdown pretender servers in unit tests - ([#917](https://github.com/samselikoff/ember-cli-mirage/pull/917)) - @dustinfarris - -## 0.2.2 - -Update notes: - - - None - -Changes: - - - [FEATURE] Add sort to orm/collection @lukemelia - - [FEATURE] Add :resource helper @Azdaroth - - [FEATURE] Add traits @Azdaroth - - [FEATURE] Extract .config out of constructor @Leooo - - [FEATURE] #795 Adds findBy to db/schema @promisedlandt - - [ENHANCEMENT] #837 Allow namespace of / to be used @jrjohnson - - [ENHANCEMENT] #869 improve logging format @mariogintili - - [ENHANCEMENT] #781 rewrite serializers @samselikoff - - [BUGFIX] #821 JSONAPIAdapter fix @chrisdpeters - - [BUGFIX] #846 Allow new attributes to be defined in #update @Leooo - - General improvements @fotinakis, @jtrees, @dfreeman, @escobera, @Azdaroth, @Dhaulagiri - -## 0.2.1 - -Update notes: - - - None - -Changes: - - - [ENHANCEMENT] Ensure mirage tree is linted @rwjblue - - [FEATURE] #762 adds `afterCreate` to factories @seanpdoyle, @samselikoff - - [BUGFIX] #769 ensure embedded collection keys are dynamic @arnodirlam - -## 0.2.0 - -Update notes: - - - The `inverseOf` options was renamed to `inverse`, to be consistent with Ember Data - -Changes: - - - [BREAKING CHANGE] #640 `inverseOf` was renamed to `inverse` @samselikoff - - [FEATURE] #729 Add `this.normalizedRequestAttrs` helper method to function route handler @samselikoff - - [ENHANCEMENT] #743 Ensure associations can be passed in during model creation @samselikoff - - [BUGFIX] #738 Ensure directory location can be configured @gthmb - - General cleanup, updates and docs @lizzerdrix, @timjcook, @samselikoff - -## 0.2.0-beta.9 - -This release contains some breaking changes from 0.2.0-beta.8. - -Update notes: - - - Schema model classes are now pluralized. They used to be singularized, taking after Rails' conventions, but I think it's better to match our db conventions (e.g. `db.users`). - - So you'll need to change - - ```js - schema.user.all() - schema.user.find(1) - ``` - - to - - ```js - schema.users.all() - schema.users.find(1) - ``` - - and so on. The upgrade should be a relatively straightforward. - - - Breaking changes on ORM/Collection: - - - There's now a `.models` property on Collections, which gives you access to the underlying JavaScript array. This should be used if you want to munge the collection using Lodash, Ramda et al. - - ```js - let usersCollection = schema.users.all(); - let uniqueUsers = _.uniqBy(usersCollection.models, 'firstName'); - ``` - - - Collection no longer attempts to mimic an array. This turned out to be confusing, since you can't really subclass arrays in JavaScript, and it would sometimes be compatible with functions that operate on arrays, but sometimes not. - - So, you can no longer use the array accessor on a collection, meaning the following won't work: - - ```js - let authors = schema.authors.all(); - - // The following no longer work - authors[1]; - authors.length; - authors.push(model); - authors.map(f); - authors.forEach(f); - authors.reduce(f); - authors.toArray(); // use authors.models instead - ``` - - Instead, if you need to use array-methods on `Collections`, access the `.models` property. You can always convert your transformed array back to a `Collection`, for example to tell Mirage to serialize your response: - - ```js - import { Collection } from 'ember-cli-mirage'; - - let authors = schema.authors.all().models; - let topPosts = authors.map((a) => a.topPost); - - return new Collection('post', topPosts); - ``` - -Changes: - - - [BREAKING CHANGE] #705 Drop Collection.[], add Collection.models @samselikoff - - [BREAKING CHANGE] #705 Pluralize Schema class names @samselikoff - - [FEATURE] #705 Add this.serialize to function route handlers @samselikoff - - [ENHANCEMENT] Server.create falls back to Models if Factories don't exist @samselikoff - - [ENHANCEMENT] Support aliases for --proxy @elbeezy - - [ENHANCEMENT] Do not include files if on Fastboot @locks - - [BUGFIX] #709 Fix Serializer include logic @cibernox - - [BUGFIX] #666 Ensure model serializers are used for JSONAPI @samselikoff - - General cleanup, updates and docs @lizzerdrix, @lependu, @amyrlam, @blimmer, @noslouch, @bgentry, @mitchlloyd, @BrianSipple, @acorncom, @stefanpennar - -## 0.2.0.beta-8 - -Update notes: - -Changes: - - - [FEATURE] #622 Add `links` method to JSONAPISerializer @richmolj - - [FEATURE] #655 Add importable rest-serializer @rondale-sc - - [FEATURE] #269 Dynamic factory attributes can reference other dynamic attributes @lazybensch - - [FEATURE] #603 Support inverse foreign keys @ef4 - - [ENHANCEMENT] #323 Extract startMirage from initializer @mitchlloyd - - [ENHANCEMENT] #617 JSON:API Serializer includes intermediate relationships when using dot paths @RSSchermer - - [ENHANCEMENT] #610 Allow Mirage to be a dependency of another addon @donovan-graham - - General cleanup and updates @lolmaus, @samselikoff - -## 0.2.0.beta-7 - -Update notes: none. - -Changes: - - - [BUGFIX] #602 Fix regression in Db IdentityManager @samselikoff - -## 0.2.0.beta-6 - -Update notes: None. - -Changes: - - - [BUGFIX] #585 Ensure DB autoincrement ids account for string ints @samselikoff - - [BUGFIX] #592 GET shorthands 404s for nonexistant singular resources @samselikoff - -## 0.2.0.beta-5 - -Update notes: None. - -Changes: - - - [ENHANCEMENT] Allow files to be excluded from non-prodution builds Danail Nachev - - [ENHANCEMENT] #552 Add default passthroughs @anulman - - [ENHANCEMENT] #427 Factories return models @ef4 - - [ENHANCEMENT] #561 Ensure foreign keys are picked up in shorthands @abuiles - - [ENHANCEMENT] #546 Add named associations @samselikoff - - [BUGFIX] #548 Shorthands can read ID from json:api request body @lkhaas - - General cleanup and updates @ef4 @abuiles @elwayman02 - -## 0.2.0.beta-4 - -Update notes: None. - -Changes: - - - [ENHANCEMENT] #501 Adds ModelClass.first @lependu - - [BUGFIX] #543 Ensure Mirage works within Addons @cibernox - - [BUGFIX] #535 Include original message on rethrow errors @hamled - - [BUGFIX] #515 Ensure serializer#serialize always receives request @2468ben - - [BUGFIX] #506 Ensure serializer#normalize looks up model-specific serializers @2468ben - - [BUGFIX] #507 Ensure foreign keys are added once @samselikoff - - General cleanup @bekzod, @alecho, @koriroys, @cibernox - -## 0.2.0.beta-3 - -Update notes: - - - There was a bug where dasherized multiword serializers and fixtures were not registered correctly. This has been fixed, so if you happen to have camelized multiword serializers or fixtures - - /mirage/serializers/blogPost.js - /mirage/fixtures/blogPosts.js - - you can rename these to dasherized names - - /mirage/serializers/blog-post.js - /mirage/fixtures/blog-posts.js - - In Mirage 0.2, all filenames should be dasherized, following the conventions of Ember CLI. If you ever encounter a situation where this doesn't work, please file an issue, as this is a bug. - -Changes: - - - [ENHANCEMENT] Better blueprints - - [BUGFIX] Ensure multiword dasherized serializers work #333 - - [BUGFIX] Ensure multiword dasherized fixtures work - -## 0.2.0.beta-2 - -Update notes: - - `Serializer#relationships` was renamed to `Serializer#include`. - - Before: - - ``` - export default Serializer.extend({ - relationships: ['comments'] - }); - ``` - - After: - - ``` - export default Serializer.extend({ - include: ['comments'] - }); - ``` - - - We now use `destroyApp` test helper in Ember-CLI to shutdown the Mirage server after each test to resolve a memory leak reported in #226. It's important to run `ember g ember-cli-mirage` when upgrading to take advantage of this fix. - - Inserting records with numerical IDs that have already have been used will throw an error per changes from #417 - - `model.type` was renamed to `model.modelName`, and is dasherized (instead of camelized) - -Changes: - - [BREAKING CHANGE] POST and PUT shorthands require a Serializer#normalize function, and will transform your attrs to camelCase. (If you're using JsonApiSerializer or ActiveModelSerializer, this is done for you). To keep using the db yourself, write custom POST and PUT route handlers. - - [BREAKING CHANGE] Serializer#relationships was renamed to Serializer#include #424 @lolmaus - - [BREAKING CHANGE] Change `model.type` to `model.modelName`, ensure it's dasherized #454 - - [BREAKING CHANGE] Inserting records with numerical IDs that have already have been used will throw an per changes from #417 - - [BREAKING CHANGE] DB stores ids as strings #462 @jherdman - - [BREAKING CHANGE] GET shorthand with single owner and many children throws an error. - - [BREAKING CHANGE] Arrays in shorthands should always contain singularzied model names (e.g. dasherized) - - [FEATURE] Add `?include` query param support in JSONAPISerializer @lolmaus - - [FEATURE] Add `build` & `buildList` to factories #459 @ballpointpenguin - - [ENHANCEMENT] JSONAPISerializer defaults to dasherized types and relationships (and other JSONAPI enhancements) @lolmaus - - [ENHANCEMENT] shutdown Mirage server on destroyAppp @blimmer - - [ENHANCEMENT] createList perf enhancement @alvinvogelzang - - [ENHANCEMENT] improve DB autoincrement @jherdman - - [ENHANCEMENT] #493 Ability to set timing parameter for individual routes @bekzod - - [FEATURE] [Allow nested factory objects](https://github.com/samselikoff/ember-cli-mirage/commit/a73a195c1b991d226429ee369e2af688a95c7d95) @john-kurkowski - - Other bugfixes/enhancements @jherdman, @ef4, @seanpdoyle, @alecho, @bekzod - -## 0.2.0.beta-1 - -Update notes: - - Move `/app/mirage` to `/mirage` - -Changes: - - [FEATURE] ORM, Serializers - - [ENHANCEMENT] @heroiceric - - [BREAKING CHANGE] missing routes will now throw an Error instead of logging to the Logger's `error` channel. - -## 0.1.11 - -Update notes: none - -Changes: - - [BUGFIX] - -## 0.1.10 - -Update notes: none - -Changes: - - [BUGFIX] - -## 0.1.9 - -Update notes: - - When this library first came out, you defined routes using `this.stub('get', '/path'...)` in your `mirage/config.js` file. `stub` has been removed, so if you happen to be using it, just replace those calls with the `this.get`, `this.post`, etc. helper methods. - - If you happen to be using the orm (it's private + not ready yet), know that there were some changes to how the data is stored. Contact me if you want to upgrade. - -Changes: - - [BREAKING CHANGE] remove #stub from Server (see update note) @samselikoff - - [FEATURE] add `.passthrough` API @samselikoff - - [FEATURE] add `.loadFixtures` API @samselikoff - - [FEATURE] add .random.number.range to faker @iamjulianacosta - - [IMPROVEMENT] better missing route message @blimmer - - [IMPROVEMENT] upgrade Ember CLI 1.13.8 @blimmer - - [IMPROVEMENT] improve logging @gaborsar - - [IMPROVEMENT] cleanup @jherdman - - [BUGFIX] fixup blueprints @samsinite - - [BUGFIX] fix ie8 bug @jerel - - [BUGFIX] avoid dep warning in Ember 2.x @mixonic - - -## 0.1.8 - -Update notes: none - -Changes: - - [BUGFIX] remove console.log from server.js - -## 0.1.7 - -Update notes: - - We use `ember-inflector` from NPM now, so after upgrading you should remove `ember-inflector` from your bower.json. - -Changes: - - [ENHANCEMENT] Add support for fully qualified domain name @jamesdixon - - [IMPROVEMENT] upgrade Ember CLI, Pretender 0.9 @cibernox @blimmer - - [IMPROVEMENT] use ember-inflector from NPM @alexlafroscia @eptis - - [IMPROVEMENT] note requirement of .bind @brettchalupa - -## 0.1.6 - -Update notes: - - If you happened to be manipulating db objects using object references instead of the db API, e.g. - - ``` - let contact = db.contacts.find(1); - contact.name = 'Gandalf'; - ``` - - this will no longer work, as the db query methods now return copies of db data. This was considered a private API. You'll need to use the db api (e.g. `db.update`) to make changes to db data. - -Changes: - - [ENHANCEMENT] add PATCH to mirage @samselikoff - - [ENHANCEMENT] update Faker to 3.0, expose all methods @blimmer - - [ENHANCEMENT] add basics of orm layer @samselikoff - - [IMPROVEMENT] general refactorings @makepanic @cibernox - -## 0.1.5 - -Update notes: none - -Changes: - - [BUGFIX] fixtures bug @bantic - - [BUGFIX] jshint on blueprint files @dukex - - [BUGFIX] allow beta to break build @bantic - -## 0.1.4 - -Update notes: - - If you run the generator to update deps, the blueprint will put a file under `/scenarios/default.js`. The presence of this file will mean your fixtures will be ignored during development. If you'd still like to use your fixtures, delete the `/scenarios` directory. - -Changes: - - [IMPROVEMENT] factory-focused initial blueprints - -## 0.1.3 - -Update notes: none - -Changes: - - [ENHANCEMENT] #29 add faker + list helpers @mupkoo - - [IMPROVEMENT] upgrade ember cli to 0.2.7 @blimmer - - [BUGFIX] #167 allow ids of 0 @samselikoff - -## 0.1.2 - -- empty release - -## 0.1.1 - -Update notes: none - -Changes: - - [IMPROVEMENT] remove unrelated folders from npm @mupkoo - - [BUGFIX] allow testConfig to be optional @samselikoff - -## 0.1.0 - -Update notes: none - -Changes: - - [ENHANCEMENT] Ability to use factories to seed development database @g-cassie - - [ENHANCEMENT] Ability to specify test-only Mirage routes @cball - - [BUGFIX] `db.where` now coerces query params to string @cibernox - - [BUGFIX] #146 fix es6 template bug with blueprint - -## 0.0.29 - -Update notes: none - -Changes: - - [BUGFIX] fix url with slash before ? @knownasilya - -## 0.0.28 - -Update notes: none - -Changes: - - [ENHANCEMENT] 'coalesce' option to support GET multiple ids @cibernox - - [ENHANCEMENT] #117 db.find supports array of ids @samselikoff - - [BUGFIX] #115 IE8 safe @samselikoff - - [BUGFIX] can remove collection then add records again @seawatts - - [IMPROVEMENT] automatically add server to .jshint @bdvholmes - - [IMPROVEMENT] use lodash.extend instead of jQuery.extend @seawatts - - [IMPROVEMENT] use 200 HTTP code if responseBody exists @cibernox - - [IMPROVEMENT] better logging @bdvholmes - -## 0.0.27 - -Update notes: none - -Changes: - - [IMPROVEMENT] remove `tmp` dir from git @ahmadsoe - - [BUGFIX] ensure string ids that start with ints can be used @cibernox - -## 0.0.26 - -Update notes: none. - -Changes: - - [ENHANCEMENT] #70 Allow function route handler to customize status - code, HTTP headers and data. See [the -wiki](https://github.com/samselikoff/ember-cli-mirage/wiki/HTTP%20Verb%20function%20handler#dynamic-status-codes-and-http-headers) -for details. - - [BUGFIX] #81 Include assets in dev build, in case users visit /tests - from `ember s`. - - [BUGFIX] smarter id coercion in controller @mikehollis - - [IMPROVEMENT] import mergeTrees and funnel @willrax @cibernox - - [IMPROVEMENT] better status code lookup @cibernox - - [IMPROVEMENT] use ember-try @willrax - -## 0.0.25 - - - npm is hard :( - -## 0.0.24 - -Update notes: The config options `force` or `disable` aren't support anymore, please use `enabled` as explained here: https://github.com/samselikoff/ember-cli-mirage/wiki/Configuration#enabled - -Changes: - - [BREAKING CHANGE] There's no more `force` or `disable` option, simply specify - - ENV['ember-cli-mirage'].enabled = [true|false] - - in whichever environment you need to override the default behavior. - - - [ENHANCEMENT] #51 Adds generators: `ember g factory contact` and `ember g fixture contacts` - - [ENHANCEMENT] Allow response logging in tests via `server.logging = true` - - [BUGFIX] #66 ignore query params in shorthands - -## 0.0.23 -Update notes: None. - -Change: - - - #53 allow arbitrary factory attrs - - #50 do not use Mirage if /server/proxies dir exists - - load fixtures in test environment if no factories exist - -## 0.0.22 -Update notes: - - Rename your `/app/mirage/data` directory to `/app/mirage/fixtures`. - - Move your `/tests/factories` directory to `/app/mirage/factories`. - - `store`, the data cache your routes interact with, has been renamed to `db` and its API has changed. - - Your shorthand routes should not be affected, but you'll need to update any routes where you passed in a function and interacted with the store.See [the wiki entry](../../wiki/Database) for more details, and the new API. - -Changes: - - - [BREAKING CHANGE] Rename `/data` directory to `/fixtures`. - - [BREAKING CHANGE] Move `/tests/factories` directory to `app/mirage/factories` - - #41 [BREAKING CHANGE] Renamed `store` to `db`, and changed API. See [the wiki entry](../../wiki/Database). - - #42 [ENHANCEMENT] Add ability to change timing within tests, e.g. to test the UI on long delays. - - #6 [ENHANCEMENT] Add ability to force an error response from a route. - - [ENHANCEMENT] Return POJO from route - - [BUGFIX] ignore assets if Mirage isn't being used - -## 0.0.21 -Update notes: - -This project has been renamed from ember-pretenderify to ember-cli-mirage. Please update your `package.json` dependency accordingly, and - - rename the `/app/pretender` dir to `/app/mirage` - - if you have factories, change - - import EP from 'ember-pretenderify'; - - to - - import Mirage from 'ember-cli-mirage'; - -Changes: - - - #26 [ENHANCEMENT] Added support for factory inheritance - - #36 [BUGFIX] Fix bug where createList didn't respect attr overrides @ashton - - #37 [INTERNAL] Add tests for createList @cibernox - - #35 [INTERNAL] Return [] from store#findAll - -## 0.0.20 - -- Deprecation notice for new name. - -## 0.0.19 -Hotfix for #34, no changes require to update. - -## 0.0.18 -Update notes: - - the testing API has changed. Before, you used `store.loadData`, now you use factories. See the Getting Started guide below for an example, or the factories wiki page for the full API. - -Changes: - - Basic factory support - -## 0.0.17 -Update notes: - - the testing API has changed. Before, you added data directly to `serverData`, e.g. - - serverData.contacts = [{id: 1, name: 'Link'}]; - - Now, use the store directly: - - store.loadData({ - contacts: [{id: 1, name: 'Link'}] - }); - - - `this` in your config file no longer refers to the Pretender instance; use `this.pretender` instead. - -Changes: - - [FEATURE] you can use `this.get`, `this.post`, `this.put` and `this.del` instead of `this.stub(verb)` now - - bug fixes + refactoring - -## 0.0.16 -Update notes: None. - -Changes: - - *actually* fix bower package version of inflector - -## 0.0.15 -Update notes: None. - -Changes: - - fix bower package version of inflector - -## 0.0.14 -Update notes: None. - -Changes: - - clean up [string].pluralize calls - -## 0.0.13 -Update notes: - - - Run `bower install`. This brings along `ember-inflector` as a separate package. - - This update contained one or more breaking changes (see below). - -Changes: - -- [breaking change] If you happen to be using `store.find(type)` to return a collection (e.g. without an `id`), use `store.findAll(type)` instead -- Various updates/refactorings to store -- Don't log server responses during testing -- Use standalone ember-inflector package, no more dependency on ember data - -## 0.0.12 -Update notes: - - Before, the following was part of the install: - - *Testing* - - In your `tests/helpers/start-app.js`, - - ```js - import pretenderifyTesting from '../../ember-pretenderify/testing'; - - export default function startApp(attrs) { - ... - - pretenderifyTesting.setup(application); - - return application; - } - ``` - - You no longer need this code, so just delete it all from the `start-app` file. The server will automatically instantiate via the initializer during tests. - -Changes: - -- fixed bug with stub#delete (so it works more than once. hah.) -- instantiate server in initializer +Releases (along with upgrade instructions) are documented on the Github [Releases](https://github.com/miragejs/ember-cli-mirage/releases) page. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7c1bee13a..f53c8ad47 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,53 +8,30 @@ It's best to ask a question with an attached Twiddle that demonstrates your bug/ ## Docs development -If you're just making a change to a single page in the docs, you can simply use GitHub's interface. Find the relevant doc and click "Edit". +The documentation site is built using [Ember CLI AddonDocs](https://ember-learn.github.io/ember-cli-addon-docs/), which means it is the Ember app located in the `tests/dummy` folder of this addon. -To make more substantial changes, you'll want to be able to write locally. The docs are a [Jekyll](https://jekyllrb.com/) site. Once you have Ruby, Bundler and Jekyll installed, +If you're just making a change to a single page in the docs, look for the "Edit this page" link at the bottom of that page. Click on that and propose your edits. -1. Fork `ember-cli-mirage` on GitHub, then create a local clone of your fork: +To make more substantial changes, you'll want to be able to develop the docs site locally. To run an AddonDocs site, - ``` - git clone git@github.com:[your-name]/ember-cli-mirage.git - cd ember-cli-mirage - ``` - -2. Checkout the `gh-pages` branch: - - ``` - git co gh-pages - ``` - -3. Start the Jekyll build: - - ``` - bundle install - bundle exec jekyll serve --watch --baseurl '' - ``` - -You should be able to visit `localhost:4000` and see the docs site running locally. Now checkout a new branch, make your changes, and submit a PR! +```shell +git clone git@github.com:miragejs/ember-cli-mirage.git +cd ember-cli-mirage +yarn install # (or npm install) +ember s +``` +You should be able to visit `localhost:4200` and see the docs site running locally. Now checkout a new branch, make your changes, and submit a PR! ## Mirage development To help out with Mirage development, first pull down the project locally and verify that all tests on `master` are passing. -1. Fork `ember-cli-mirage`, then create a local clone of your fork: - - ``` - git clone git@github.com:[your-name]/ember-cli-mirage.git - cd ember-cli-mirage - ``` - -2. Ensure `node` is installed. I use version 4.2.x, the LTS release. - - Ensure `npm` is installed -3. Ensure `ember-cli` is installed: `npm install -g ember-cli` -4. Ensure `phantomjs` v2.x is installed. -5. Install dependencies and run the tests: - - ``` - npm i && bower i - ember test - ``` +``` +git clone git@github.com:[your-name]/ember-cli-mirage.git +cd ember-cli-mirage +yarn install # (or npm install) +ember test +``` If all tests pass, you should be all set. Checkout a new branch to start developing, then submit a PR when you're ready! diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index 48fe09ce1..9af044d40 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -1,7 +1,15 @@ -If possible, please use the Mirage Boilerplate Twiddle to demonstrate your issue or bug: +# Feature request -- Open the [Mirage Boilerplate Twiddle](https://ember-twiddle.com/eedfd390d8394d54d5bfd0ed988a5d0f) -- Click File > Copy Twiddle -- Reproduce your issue -- Click File > Save to Github Gist -- Include the URL to your Twiddle in your issue +If this is a feature request, add a 👍 reaction to it. We use these to help us prioritize new feature development! + +# Bug or question + +If possible, please use the Mirage Boilerplate to demonstrate your issue or bug: + +1. Visit the [Ember CLI Mirage Boilerplate](https://github.com/miragejs/ember-cli-mirage-boilerplate) repo + +2. Click Fork + +3. Clone your fork locally, checkout a new branch, reproduce your issue and push + +4. Link to your branch in your issue diff --git a/README.md b/README.md index f94fc85cd..69ece7552 100644 --- a/README.md +++ b/README.md @@ -1,44 +1,40 @@ -[![Build Status](https://travis-ci.org/samselikoff/ember-cli-mirage.svg?branch=master)](https://travis-ci.org/samselikoff/ember-cli-mirage) -[![npm version](https://badge.fury.io/js/ember-cli-mirage.svg)](http://badge.fury.io/js/ember-cli-mirage) -[![Ember Observer Score](http://emberobserver.com/badges/ember-cli-mirage.svg)](http://emberobserver.com/addons/ember-cli-mirage) - # Ember CLI Mirage +[![Build Status](https://github.com/miragejs/ember-cli-mirage/actions/workflows/ci.yml/badge.svg)](https://github.com/miragejs/ember-cli-mirage/actions/workflows/ci.yml) +[![npm version](https://badge.fury.io/js/ember-cli-mirage.svg)](http://badge.fury.io/js/ember-cli-mirage) +[![Ember Observer Score](http://emberobserver.com/badges/ember-cli-mirage.svg)](http://emberobserver.com/addons/ember-cli-mirage) A client-side server to develop, test and prototype your Ember CLI app. - +[View the docs here.](https://www.ember-cli-mirage.com/) ---- -Are you tired of - -- Writing one set of fixtures for your tests, and another for development? -- Wiring up tests for each of your apps manually, from scratch? -- Changing lots of files/tests when your API changes? - -Ember CLI Mirage may be for you! It lets you create a client-side server using [Pretender](https://github.com/trek/pretender) to help you develop and test your app. By default, it only runs if you're not in production and if you're not proxying to an explicit API server via `ember serve --proxy`. - ## Installation ```sh -ember install ember-cli-mirage # install:addon for Ember CLI < 0.2.3 +ember install ember-cli-mirage ``` -## Updating - -This project is new and the API is subject to change. When updating your project to a newer version of Ember CLI Mirage, please consult [the changelog](/CHANGELOG.md) for any update notes. +## Feature requests -## Getting started +Please open an issue and add a :+1: emoji reaction. We will use the number of reactions as votes to indicate community interest, which will in turn help us prioritize feature development. -Check out the [Docs](http://www.ember-cli-mirage.com/docs/v0.2.x/)! +You can view the most-upvoted feature requests with [this link](https://github.com/miragejs/ember-cli-mirage/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3A%22Feature+%2F+Enhancement%22). ## Support -Having trouble? Open an issue! +Having trouble? -You can use the [Mirage Boilerplate Twiddle](https://ember-twiddle.com/eedfd390d8394d54d5bfd0ed988a5d0f) to reproduce your issue. +- **Join #ec-mirage** on the [Ember Community Discord server](https://discord.gg/zT3asNS) +- **Open an issue**, and if possible reproduce it using the [Mirage Boilerplate Twiddle](https://ember-twiddle.com/ec3a4c625c43e7a38f3c6c0c1b8232ec?openFiles=twiddle.json%2C). ## Contributing Have a look at our [Contributing guidelines](./CONTRIBUTING.md). + +## About + +This library is developed and maintained by [EmberMap](https://embermap.com/). We have a [Mirage tips and tricks](https://embermap.com/topics/mirage-tips-and-tricks) video series if you're looking to learn how to get the most out of Mirage. + +Thanks to all our amazing [contributors](https://github.com/miragejs/ember-cli-mirage/graphs/contributors)! diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..7aa47841c --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,11 @@ +# Security Policy + +## Supported Versions + +| Version | Supported | +| ------- | ------------------ | +| 2.x | :white_check_mark: | + +## Reporting a Vulnerability + +Email sam.selikoff@gmail.com to report a vulnerability. diff --git a/addon-test-support/index.js b/addon-test-support/index.js new file mode 100644 index 000000000..2a7030e54 --- /dev/null +++ b/addon-test-support/index.js @@ -0,0 +1,11 @@ +import setupMirage from './setup-mirage'; +export { setupMirage }; + +import { dependencySatisfies } from '@embroider/macros'; + +if (dependencySatisfies('ember-qunit', '*')) { + window.QUnit.config.urlConfig.push({ + id: 'mirageLogging', + label: 'Mirage logging', + }); +} diff --git a/addon-test-support/setup-mirage.js b/addon-test-support/setup-mirage.js new file mode 100644 index 000000000..aef8bfdb3 --- /dev/null +++ b/addon-test-support/setup-mirage.js @@ -0,0 +1,34 @@ +import startMirage from 'ember-cli-mirage/start-mirage'; +import { settled } from '@ember/test-helpers'; + +/** + Used to set up mirage for a test. Must be called after one of the + `ember-qunit` `setup*Test()` methods. It starts the server and sets + `this.server` to point to it, and shuts the server down when the test + finishes. + + NOTE: the `hooks = self` is for mocha support + @hide +*/ +export default function setupMirage(hooks = self) { + hooks.beforeEach(function () { + if (!this.owner) { + throw new Error( + 'You must call one of the ember-qunit setupTest(),' + + ' setupRenderingTest() or setupApplicationTest() methods before' + + ' calling setupMirage()' + ); + } + + this.server = startMirage(this.owner); + }); + + hooks.afterEach(function () { + return settled().then(() => { + if (this.server) { + this.server.shutdown(); + delete this.server; + } + }); + }); +} diff --git a/addon/assert.js b/addon/assert.js index 48d705dc2..24f68a498 100644 --- a/addon/assert.js +++ b/addon/assert.js @@ -1,43 +1 @@ -/* eslint no-console: 0 */ -let errorProps = [ - 'description', - 'fileName', - 'lineNumber', - 'message', - 'name', - 'number', - 'stack' -]; - -export default function assert(bool, text) { - if (typeof bool === 'string' && !text) { - throw new MirageError(bool); - } - - if (!bool) { - throw new MirageError(text.replace(/^ +/gm, '') || 'Assertion failed'); - } -} - -/** - @public - Copied from ember-metal/error -*/ -export function MirageError() { - let tmp = Error.apply(this, arguments); - - for (let idx = 0; idx < errorProps.length; idx++) { - let prop = errorProps[idx]; - - if (['description', 'message', 'stack'].indexOf(prop) > -1) { - this[prop] = `Mirage: ${tmp[prop]}`; - } else { - this[prop] = tmp[prop]; - } - } - - console.error(this.message); - console.error(this); -} - -MirageError.prototype = Object.create(Error.prototype); +export { _assert as default } from 'miragejs'; diff --git a/addon/association.js b/addon/association.js index bc5d67d18..cebb404e9 100644 --- a/addon/association.js +++ b/addon/association.js @@ -1,9 +1,15 @@ -let association = function(...traitsAndOverrides) { - let __isAssociation__ = true; - return { - __isAssociation__, - traitsAndOverrides - }; -}; +import { association } from 'miragejs'; +import { deprecateNestedImport } from './deprecate-imports'; -export default association; +/** + @function association + @hide + */ +export default function (...args) { + deprecateNestedImport( + "Importing 'association' from 'ember-cli-mirage/association' is deprecated. " + + "Add the `miragejs` package to devDependencies and use `import { association } from 'miragejs';` instead." + ); + + return association(...args); +} diff --git a/addon/db-collection.js b/addon/db-collection.js index e727dd41d..c6a2a9159 100644 --- a/addon/db-collection.js +++ b/addon/db-collection.js @@ -1,398 +1,18 @@ -import _assign from 'lodash/assign'; -import _map from 'lodash/map'; -import _isEqual from 'lodash/isEqual'; -import _sortBy from 'lodash/sortBy'; - -function duplicate(data) { - if (Array.isArray(data)) { - return data.map(duplicate); - } else { - return _assign({}, data); - } -} - -function isNumber(n) { - return (+n).toString() === n.toString(); -} +import { _DbCollection } from 'miragejs'; +import { deprecateNestedImport } from './deprecate-imports'; /** - * A collection of db records i.e. a database table. - * @class DbCollection - * @constructor - * @public + @class DeprecatedDbCollection + @hide */ -class DbCollection { - - constructor(name, initialData) { - this.name = name; - this._records = []; - this.identityManager = new IdentityManager(); - - if (initialData) { - this.insert(initialData); - } - } - - /** - * Returns a copy of the data, to prevent inadvertent data manipulation. - * @method all - * @public - */ - all() { - return duplicate(this._records); - } - - /** - * Inserts `data` into the collection. `data` can be a single object - * or an array of objects. Returns the inserted record. - * @method insert - * @param data - * @public - */ - insert(data) { - if (!Array.isArray(data)) { - return this._insertRecord(data); - } else { - // Need to sort in order to ensure IDs inserted in the correct order - let sorted = _sortBy(data, 'id'); - return _map(sorted, (x) => this._insertRecord(x)); - } - } - - /** - * Returns a single record from the `collection` if `ids` is a single - * id, or an array of records if `ids` is an array of ids. Note - * each id can be an int or a string, but integer ids as strings - * (e.g. the string “1”) will be treated as integers. - * @method find - * @param ids - * @public - */ - find(ids) { - if (Array.isArray(ids)) { - let records = this._findRecords(ids) - .filter(Boolean) - .map(duplicate); // Return a copy - - return records; - } else { - let record = this._findRecord(ids); - if (!record) { - return null; - } - - // Return a copy - return duplicate(record); - } - } - - /** - * Returns the first model from `collection` that matches the - * key-value pairs in the `query` object. Note that a string - * comparison is used. `query` is a POJO. - * @method find - * @param query - * @public - */ - findBy(query) { - let record = this._findRecordBy(query); - if (!record) { - return null; - } - - // Return a copy - return duplicate(record); - } - - /** - * Returns an array of models from `collection` that match the - * key-value pairs in the `query` object. Note that a string - * comparison is used. `query` is a POJO. - * @method where - * @param query - * @public - */ - where(query) { - return this._findRecordsWhere(query).map(duplicate); - } - - /** - * Finds the first record matching the provided query in - * `collection`, or creates a new record using a merge of the - * `query` and optional `attributesForCreate`. - * @method firstOrCreate - * @param query - * @param attributesForCreate - * @public - */ - firstOrCreate(query, attributesForCreate = {}) { - let queryResult = this.where(query); - let [record] = queryResult; - - if (record) { - return record; - } else { - let mergedAttributes = _assign(attributesForCreate, query); - let createdRecord = this.insert(mergedAttributes); - - return createdRecord; - } - } - - /** - * Updates one or more records in collection. - * If attrs is the only arg present, updates all records - * in the collection according to the key-value pairs in attrs. - * If target is present, restricts updates to those that - * match target. If target is a number or string, finds a - * single record whose id is target to update. If target is - * a POJO, queries collection for records that match the - * key-value pairs in target, and updates their attrs. - * Returns the updated record or records. - * @method update - * @param target - * @param attrs - * @public - */ - update(target, attrs) { - let records; - - if (typeof attrs === 'undefined') { - attrs = target; - let changedRecords = []; - - this._records.forEach((record) => { - let oldRecord = _assign({}, record); - - this._updateRecord(record, attrs); - - if (!_isEqual(oldRecord, record)) { - changedRecords.push(record); - } - }); - - return changedRecords; - - } else if (typeof target === 'number' || typeof target === 'string') { - let id = target; - let record = this._findRecord(id); - - this._updateRecord(record, attrs); - - return record; - - } else if (Array.isArray(target)) { - let ids = target; - records = this._findRecords(ids); - - records.forEach((record) => { - this._updateRecord(record, attrs); - }); - - return records; - - } else if (typeof target === 'object') { - let query = target; - records = this._findRecordsWhere(query); - - records.forEach((record) => { - this._updateRecord(record, attrs); - }); - - return records; - } - } - - /** - * Removes one or more records in `collection`. - * If `target` is undefined, removes all records. - * If `target` is a number or string, removes a - * single record using `target` as id. If `target` is - * a POJO, queries `collection` for records that - * match the key-value pairs in `target`, and - * removes them from the collection. - * @method remove - * @param target - * @public - */ - remove(target) { - let records; - - if (typeof target === 'undefined') { - this._records = []; - this.identityManager.reset(); - - } else if (typeof target === 'number' || typeof target === 'string') { - let record = this._findRecord(target); - let index = this._records.indexOf(record); - this._records.splice(index, 1); - - } else if (Array.isArray(target)) { - records = this._findRecords(target); - records.forEach((record) => { - let index = this._records.indexOf(record); - this._records.splice(index, 1); - }); - - } else if (typeof target === 'object') { - records = this._findRecordsWhere(target); - records.forEach((record) => { - let index = this._records.indexOf(record); - this._records.splice(index, 1); - }); - } - } +export default class DeprecatedDbCollection extends _DbCollection { + constructor(...args) { + deprecateNestedImport( + `Importing 'DbCollection' from 'ember-cli-mirage/db-collection' is deprecated. ` + + `This wasn't intended to be a public API. If you absolute know what you are doing, ` + + `install the \`miragejs\` package and use \`import { _DbCollection } from 'miragejs';\` instead.` + ); - /* - Private methods. - - These return the actual db objects, whereas the public - API query methods return copies. - */ - - /** - * @method _findRecord - * @param id - * @private - */ - _findRecord(id) { - id = id.toString(); - - let [record] = this._records.filter((obj) => obj.id === id); - - return record; - } - - /** - * @method _findRecordBy - * @param query - * @private - */ - _findRecordBy(query) { - return this._findRecordsWhere(query)[0]; - } - - /** - * @method _findRecords - * @param ids - * @private - */ - _findRecords(ids) { - return ids.map(this._findRecord, this); - } - - /** - * @method _findRecordsWhere - * @param query - * @private - */ - _findRecordsWhere(query) { - let records = this._records; - - function defaultQueryFunction(record) { - let keys = Object.keys(query); - - return keys.every(function(key) { - return String(record[key]) === String(query[key]); - }); - } - - let queryFunction = typeof query === 'object' ? defaultQueryFunction : query; - - return records.filter(queryFunction); - } - - /** - * @method _insertRecord - * @param data - * @private - */ - _insertRecord(data) { - let attrs = duplicate(data); - - if (attrs && (attrs.id === undefined || attrs.id === null)) { - attrs.id = this.identityManager.fetch(); - } else { - attrs.id = attrs.id.toString(); - - this.identityManager.set(attrs.id); - } - - this._records.push(attrs); - - return duplicate(attrs); - } - - /** - * @method _updateRecord - * @param record - * @param attrs - * @private - */ - _updateRecord(record, attrs) { - let targetId = (attrs && attrs.hasOwnProperty('id')) ? attrs.id.toString() : null; - let currentId = record.id; - - if (targetId && currentId !== targetId) { - throw new Error('Updating the ID of a record is not permitted'); - } - - for (let attr in attrs) { - if (attr === 'id') { - continue; - } - - record[attr] = attrs[attr]; - } + super(...args); } } - -class IdentityManager { - constructor() { - this._nextId = 1; - this._ids = {}; - } - - get() { - return this._nextId; - } - - set(n) { - if (this._ids[n]) { - throw new Error(`Attempting to use the ID ${n}, but it's already been used`); - } - - if (isNumber(n) && +n >= this._nextId) { - this._nextId = +n + 1; - } - - this._ids[n] = true; - } - - inc() { - let nextValue = this.get() + 1; - - this._nextId = nextValue; - - return nextValue; - } - - fetch() { - let id = this.get(); - - this._ids[id] = true; - - this.inc(); - - return id.toString(); - } - - reset() { - this._nextId = 1; - this._ids = {}; - } -} - -export default DbCollection; - -export { IdentityManager }; diff --git a/addon/db.js b/addon/db.js index 9ae54264b..799904125 100644 --- a/addon/db.js +++ b/addon/db.js @@ -1,82 +1,18 @@ -import DbCollection from './db-collection'; +import { _Db } from 'miragejs'; +import { deprecateNestedImport } from './deprecate-imports'; /** - * The db, an identity map. - * @class Db - * @constructor - * @public + @class DeprecatedDB + @hide */ -class Db { - - constructor(initialData) { - this._collections = []; - - if (initialData) { - this.loadData(initialData); - } - } - - /** - * @method loadData - * @param data - * @public - */ - loadData(data) { - for (let key in data) { - this.createCollection(key, data[key]); - } - } - - /** - * @method createCollection - * @param name - * @param initialData - * @public - */ - createCollection(name, initialData) { - if (!this[name]) { - let newCollection = new DbCollection(name, initialData); - - Object.defineProperty(this, name, { - get() { - let recordsCopy = newCollection.all(); - - ['insert', 'find', 'findBy', 'where', 'update', 'remove', 'firstOrCreate'] - .forEach(function(method) { - recordsCopy[method] = function() { - return newCollection[method](...arguments); - }; - }); - - return recordsCopy; - } - }); - - this._collections.push(newCollection); - - } else if (initialData) { - this[name].insert(initialData); - } - - return this; - } - - /** - * @method createCollections - * @param ...collections - * @public - */ - createCollections(...collections) { - collections.forEach((c) => this.createCollection(c)); - } - - /** - * @method emptyData - * @public - */ - emptyData() { - this._collections.forEach((c) => c.remove()); +export default class DeprecatedDB extends _Db { + constructor(...args) { + deprecateNestedImport( + `Importing 'Db' from 'ember-cli-mirage/db' is deprecated. ` + + `This wasn't intended to be a public API. If you absolute know what you are doing, ` + + `install the \`miragejs\` package and use \`import { _Db } from 'miragejs';\` instead.` + ); + + super(...args); } } - -export default Db; diff --git a/addon/deprecate-imports.js b/addon/deprecate-imports.js new file mode 100644 index 000000000..3a3cbdf52 --- /dev/null +++ b/addon/deprecate-imports.js @@ -0,0 +1,43 @@ +import { deprecate } from '@ember/debug'; + +/** + @function getMessage + @hide + */ +export function getMessage(importName) { + return ( + `Importing '${importName}' from 'ember-cli-mirage' is deprecated. ` + + `Install the \`miragejs\` package and use ` + + `\`import { ${importName} } from 'miragejs';\` instead.` + ); +} + +/** + @function deprecateImport + @hide + */ +export function deprecateImport(importName) { + deprecate(getMessage(importName), false, { + id: 'ember-cli-mirage.miragejs.import', + until: '3.0.0', + for: 'ember-cli-mirage', + since: { + enabled: '2.3.0', + }, + }); +} + +/** + @function deprecateNestedImport + @hide + */ +export function deprecateNestedImport(message) { + deprecate(message, false, { + id: 'ember-cli-mirage.miragejs.import', + until: '3.0.0', + for: 'ember-cli-mirage', + since: { + enabled: '2.3.0', + }, + }); +} diff --git a/addon/deprecate-reexports.js b/addon/deprecate-reexports.js new file mode 100644 index 000000000..cba594200 --- /dev/null +++ b/addon/deprecate-reexports.js @@ -0,0 +1,56 @@ +import { deprecate } from '@ember/debug'; +import { importSync, isTesting, dependencySatisfies } from '@embroider/macros'; +import * as mirage from 'miragejs'; +import * as ecMirageExports from './index'; + +const nonDeprecatedImports = ['default']; + +/** + @function initDeprecatedReExports + @hide + */ +export function initDeprecatedReExports() { + Object.entries(mirage).forEach(([name, value]) => { + if (!nonDeprecatedImports.includes(name)) { + // eslint-disable-next-line no-import-assign + Object.defineProperty(ecMirageExports, name, { + get() { + if (isTesting() && dependencySatisfies('ember-qunit', '*')) { + const { waitUntil, getContext } = importSync('@ember/test-helpers'); + + window.QUnit.begin(function () { + // Make sure deprecation message does not get "swallowed" + // when tests run due to + // https://github.com/emberjs/ember-test-helpers/blob/master/addon-test-support/%40ember/test-helpers/setup-context.ts#L41 + waitUntil(() => getContext() !== undefined).then(() => + _deprecate(name) + ); + }); + } else { + _deprecate(name); + } + + return value; + }, + + enumerable: true, + }); + } + }); +} + +function _deprecate(name) { + const message = + `Importing '${name}' from 'ember-cli-mirage' is deprecated.` + + ` Install the \`miragejs\` package and use ` + + `\`import { ${name} } from 'miragejs';\` instead.`; + + deprecate(message, false, { + id: 'ember-cli-mirage.miragejs.import', + until: '3.0.0', + for: 'ember-cli-mirage', + since: { + enabled: '2.3.0', + }, + }); +} diff --git a/addon/ember-data.js b/addon/ember-data.js new file mode 100644 index 000000000..21f5fb0f0 --- /dev/null +++ b/addon/ember-data.js @@ -0,0 +1,230 @@ +/* global requirejs */ + +import require from 'require'; +import config from 'ember-get-config'; +import assert from './assert'; +import { hasEmberData, isDsModel } from 'ember-cli-mirage/utils/ember-data'; +import { Model, belongsTo, hasMany } from 'miragejs'; +import EmberDataSerializer from 'ember-cli-mirage/serializers/ember-data-serializer'; +import { _utilsInflectorCamelize as camelize } from 'miragejs'; + +const { modulePrefix, podModulePrefix } = config; + +// Caches +let DsModels, Models; +let DsSerializers, Serializers; + +/** + * Get all ember data models under the app's namespaces + * + * @method getDsModels + * @private + * @hide + * @return {Object} models + */ +export function getDsModels() { + if (DsModels) { + return DsModels; + } + + let moduleMap = requirejs.entries; + let classicModelMatchRegex = new RegExp(`^${modulePrefix}/models/(.*)$`, 'i'); + let podModelMatchRegex = new RegExp( + `^${podModulePrefix || modulePrefix}/(.*)/model$`, + 'i' + ); + + DsModels = {}; + + if (!hasEmberData) { + return DsModels; + } + + Object.keys(moduleMap).forEach((path) => { + let matches = + path.match(classicModelMatchRegex) || path.match(podModelMatchRegex); + if (matches && matches[1]) { + let modelName = matches[1]; + + let model = require(path, null, null, true).default; + if (isDsModel(model)) { + DsModels[modelName] = model; + } + } + }); + + return DsModels; +} + +/** + * Get all mirage models for each of the ember-data models + * + * @method discoverEmberDataModels + * @return {Object} models + */ +export function discoverEmberDataModels() { + if (Models) { + return Models; + } + + let emberDataModels = getDsModels(); + Models = {}; + + Object.keys(emberDataModels).forEach((modelName) => { + let model = emberDataModels[modelName]; + let attrs = {}; + + model.eachRelationship((name, r) => { + if (r.kind === 'belongsTo') { + attrs[name] = belongsTo(r.type, r.options); + } else if (r.kind === 'hasMany') { + attrs[name] = hasMany(r.type, r.options); + } + }); + + Models[modelName] = Model.extend(attrs); + }); + + return Models; +} + +/** + * A lookup method for an autogenerated model + * + * @method modelFor + * @private + * @param {String} name + * @return {Model} + * @hide + */ +export function modelFor(name) { + let models = discoverEmberDataModels(); + assert(!!models[name], `Model of type '${name}' does not exist.`); + return models[name]; +} + +/** + * Get all ember data serializers under the app's namespaces + * + * @method getDsSerializers + * @private + * @hide + * @return {Object} serializers + */ +export function getDsSerializers() { + if (DsSerializers) { + return DsSerializers; + } + + let moduleMap = requirejs.entries; + let classicSerializerMatchRegex = new RegExp( + `^${modulePrefix}/serializers/(.*)$`, + 'i' + ); + let podSerializerMatchRegex = new RegExp( + `^${podModulePrefix || modulePrefix}/(.*)/serializer$`, + 'i' + ); + + DsSerializers = {}; + + if (!hasEmberData) { + return DsSerializers; + } + + Object.keys(moduleMap).forEach((path) => { + let matches = + path.match(classicSerializerMatchRegex) || + path.match(podSerializerMatchRegex); + if (matches && matches[1]) { + let serializerName = matches[1]; + + let serializer = require(path, null, null, true).default; + // in mirage, registering models takes care of camelize, serializers do not + DsSerializers[camelize(serializerName)] = serializer; + } + }); + + return DsSerializers; +} + +/** + * Generate mirage serializers for each of the ember-data serializers + * if a mirage serializer already exists, apply the ember-data transforms + * + * @method applyEmberDataSerializers + * @return {Object} serializers + */ +export function applyEmberDataSerializers(mirageSerializers = {}) { + if (Serializers) { + return Serializers; + } + + let emberDataSerializers = getDsSerializers(); + + // Start off with the mirage serializers, + // so if there are any mirage serializers with no ED counterpart, they are in the list + Serializers = mirageSerializers; + + Object.keys(emberDataSerializers).forEach((serializerName) => { + let dsSerializer = emberDataSerializers[serializerName]; + + // Seems I have to create it to get access to some of the properties + dsSerializer = dsSerializer.create + ? dsSerializer.create() + : new dsSerializer(); + + let transforms; + let primaryKey = dsSerializer.primaryKey; + let attrs = dsSerializer.attrs; + if (primaryKey || attrs) { + let Serializer = + mirageSerializers[serializerName] || + mirageSerializers.application || + EmberDataSerializer; + + if (attrs) { + let serializer = Serializer.create + ? Serializer.create() + : new Serializer(); + + transforms = serializer.transforms || {}; + + Object.keys(attrs).forEach((key) => { + let transform = attrs[key]; + let serializerTransform = serializer.transforms + ? serializer.transforms[key] + : {}; + let resolvedTransform = + typeof attrs[key] === 'string' + ? { + key: attrs[key], + } + : { + key: attrs[key].key, + }; + + if (transform.serialize !== undefined) { + resolvedTransform.deserialize = transform.serialize; + } + + if (transform.deserialize !== undefined) { + resolvedTransform.serialize = transform.deserialize; + } + + transforms[key] = Object.assign( + resolvedTransform, + serializerTransform + ); + }); + } + + Serializers[serializerName] = Serializer.extend({ + primaryKey, + transforms, + }); + } + }); + + return Serializers; +} diff --git a/addon/factory.js b/addon/factory.js index 81ea1fa7f..6b9204154 100644 --- a/addon/factory.js +++ b/addon/factory.js @@ -1,142 +1,17 @@ -import _assign from 'lodash/assign'; -import _isFunction from 'lodash/isFunction'; -import _mapValues from 'lodash/mapValues'; -import referenceSort from './utils/reference-sort'; -import _isPlainObject from 'lodash/isPlainObject'; - -let Factory = function() { - this.build = function(sequence) { - let object = {}; - let topLevelAttrs = _assign({}, this.attrs); - delete topLevelAttrs.afterCreate; - Object.keys(topLevelAttrs).forEach((attr) => { - if (Factory.isTrait.call(this, attr)) { - delete topLevelAttrs[attr]; - } - }); - let keys = sortAttrs(topLevelAttrs, sequence); - - keys.forEach(function(key) { - let buildAttrs, buildSingleValue; - - buildAttrs = function(attrs) { - return _mapValues(attrs, buildSingleValue); - }; - - buildSingleValue = (value) => { - if (Array.isArray(value)) { - return value.map(buildSingleValue); - } else if (_isPlainObject(value)) { - return buildAttrs(value); - } else if (_isFunction(value)) { - return value.call(topLevelAttrs, sequence); - } else { - return value; - } - }; - - let value = topLevelAttrs[key]; - if (_isFunction(value)) { - object[key] = value.call(object, sequence); - } else { - object[key] = buildSingleValue(value); - } - - }); - - return object; - }; -}; - -Factory.extend = function(attrs) { - // Merge the new attributes with existing ones. If conflict, new ones win. - let newAttrs = _assign({}, this.attrs, attrs); - - let Subclass = function() { - this.attrs = newAttrs; - Factory.call(this); - }; - - // Copy extend - Subclass.extend = Factory.extend; - Subclass.extractAfterCreateCallbacks = Factory.extractAfterCreateCallbacks; - Subclass.isTrait = Factory.isTrait; - - // Store a reference on the class for future subclasses - Subclass.attrs = newAttrs; - - return Subclass; -}; - -Factory.extractAfterCreateCallbacks = function({ traits } = {}) { - let afterCreateCallbacks = []; - let attrs = this.attrs || {}; - let traitCandidates; - - if (attrs.afterCreate) { - afterCreateCallbacks.push(attrs.afterCreate); +import { Factory } from 'miragejs'; +import { deprecateNestedImport } from './deprecate-imports'; + +/** + @class DeprecatedFactory + @hide + */ +export default class DeprecatedFactory extends Factory { + constructor(...args) { + deprecateNestedImport( + `Importing 'Factory' from 'ember-cli-mirage/factory' is deprecated. ` + + `Install the \`miragejs\` package and use \`import { Factory } from 'miragejs';\` instead.` + ); + + super(...args); } - - if (Array.isArray(traits)) { - traitCandidates = traits; - } else { - traitCandidates = Object.keys(attrs); - } - - traitCandidates.filter((attr) => { - return this.isTrait(attr) && attrs[attr].extension.afterCreate; - }).forEach((attr) => { - afterCreateCallbacks.push(attrs[attr].extension.afterCreate); - }); - - return afterCreateCallbacks; -}; - -Factory.isTrait = function(attrName) { - let { attrs } = this; - return _isPlainObject(attrs[attrName]) && attrs[attrName].__isTrait__ === true; -}; - -function sortAttrs(attrs, sequence) { - let Temp = function() {}; - let obj = new Temp(); - let refs = []; - let property; - - Object.keys(attrs).forEach(function(key) { - let value; - Object.defineProperty(obj.constructor.prototype, key, { - get() { - refs.push([property, key]); - return value; - }, - set(newValue) { - value = newValue; - }, - enumerable: false, - configurable: true - }); - }); - - Object.keys(attrs).forEach(function(key) { - let value = attrs[key]; - if (typeof value !== 'function') { - obj[key] = value; - } - }); - - Object.keys(attrs).forEach(function(key) { - let value = attrs[key]; - property = key; - - if (typeof value === 'function') { - obj[key] = value.call(obj, sequence); - } - - refs.push([key]); - }); - - return referenceSort(refs); } - -export default Factory; diff --git a/addon/faker.js b/addon/faker.js deleted file mode 100644 index 321dc8fc5..000000000 --- a/addon/faker.js +++ /dev/null @@ -1,27 +0,0 @@ -let list = { - random() { - let items = arguments.length > 0 ? arguments : []; - - return function() { - return faker.random.arrayElement(items); - }; - }, - - cycle() { - let items = arguments.length > 0 ? arguments : []; - - return function(i) { - return items[i % items.length]; - }; - } -}; - -faker.list = list; - -faker.random.number.range = function(min, max) { - return function(/* i */) { - return Math.random() * (max - min) + min; - }; -}; - -export default faker; diff --git a/addon/get-rfc232-test-context.js b/addon/get-rfc232-test-context.js new file mode 100644 index 000000000..e7aaf43cc --- /dev/null +++ b/addon/get-rfc232-test-context.js @@ -0,0 +1,17 @@ +import { importSync, dependencySatisfies, isTesting } from '@embroider/macros'; + +/** + Helper to get our rfc232/rfc268 test context object, or null if we're not in + such a test. + + @hide +*/ +export default function getRfc232TestContext() { + // Support older versions of `ember-qunit` that don't have + // `@ember/test-helpers` (and therefore cannot possibly be running an + // rfc232/rfc268 test). + if (dependencySatisfies('@ember/test-helpers', '*') && isTesting()) { + let { getContext } = importSync('@ember/test-helpers'); + return getContext(); + } +} diff --git a/addon/identity-manager.js b/addon/identity-manager.js new file mode 100644 index 000000000..fab723234 --- /dev/null +++ b/addon/identity-manager.js @@ -0,0 +1,17 @@ +import { IdentityManager } from 'miragejs'; +import { deprecateNestedImport } from './deprecate-imports'; + +/** + @class DeprecatedIdentityManager + @hide + */ +export default class DeprecatedIdentityManager extends IdentityManager { + constructor(...args) { + deprecateNestedImport( + `Importing 'IdentityManager' from 'ember-cli-mirage/identity-manager' is deprecated. ` + + `Install the \`miragejs\` package and use \`import { IdentityManager } from 'miragejs';\` instead.` + ); + + super(...args); + } +} diff --git a/addon/index.js b/addon/index.js index 251964a15..3363f9400 100644 --- a/addon/index.js +++ b/addon/index.js @@ -1,43 +1,54 @@ -import Factory from './factory'; -import trait from './trait'; -import association from './association'; -import Response from './response'; -import faker from './faker'; -import Model from './orm/model'; -import Collection from './orm/collection'; -import Serializer from './serializer'; -import ActiveModelSerializer from './serializers/active-model-serializer'; -import JSONAPISerializer from './serializers/json-api-serializer'; -import RestSerializer from './serializers/rest-serializer'; -import HasMany from './orm/associations/has-many'; -import BelongsTo from './orm/associations/belongs-to'; +export { + discoverEmberDataModels, + applyEmberDataSerializers, +} from './ember-data'; +export { default as EmberDataSerializer } from 'ember-cli-mirage/serializers/ember-data-serializer'; + +import { deprecateImport } from './deprecate-imports'; + +import { initDeprecatedReExports } from './deprecate-reexports'; +initDeprecatedReExports(); + +import { Factory, Response, HasMany, BelongsTo } from 'miragejs'; + +const DeprecatedFactory = function (...args) { + deprecateImport('Factory'); + + return Factory.call(this, ...args); +}; + +// Copy extend +DeprecatedFactory.extend = Factory.extend; +DeprecatedFactory.extractAfterCreateCallbacks = + Factory.extractAfterCreateCallbacks; +DeprecatedFactory.isTrait = Factory.isTrait; + +// // Store a reference on the class for future subclasses +// DeprecatedFactory.attrs = newAttrs; + +class DeprecatedResponse extends Response { + constructor(...args) { + deprecateImport('Response'); + + super(...args); + } +} function hasMany(...args) { + deprecateImport('hasMany'); + return new HasMany(...args); } + function belongsTo(...args) { + deprecateImport('belongsTo'); + return new BelongsTo(...args); } -export { - Factory, - trait, - association, - Response, - faker, - Model, - Collection, - Serializer, - ActiveModelSerializer, - JSONAPISerializer, - RestSerializer, - hasMany, - belongsTo -}; - export default { - Factory, - Response, + Factory: DeprecatedFactory, + Response: DeprecatedResponse, hasMany, - belongsTo + belongsTo, }; diff --git a/addon/instance-initializers/ember-cli-mirage-autostart.js b/addon/instance-initializers/ember-cli-mirage-autostart.js new file mode 100644 index 000000000..0e18fa9a8 --- /dev/null +++ b/addon/instance-initializers/ember-cli-mirage-autostart.js @@ -0,0 +1,35 @@ +import { registerDestructor } from '@ember/destroyable'; +import getRfc232TestContext from '../get-rfc232-test-context'; +import startMirage from '../start-mirage'; + +/** + If we are running an rfc232/rfc268 test then we want to support the + `autostart` configuration option, which auto-starts mirage before the test + runs and shuts it down afterwards, and also sets `this.server` on the test + context so the tests don't need to use the global `server`. We do this in an + instance initializer because initializers only run once per test run, not + before and after each test. + + @hide +*/ +export function initialize(appInstance) { + let testContext = getRfc232TestContext(); + if (testContext) { + let { 'ember-cli-mirage': { autostart } = {} } = + appInstance.resolveRegistration('config:environment'); + + if (autostart) { + testContext.server = startMirage(appInstance); + + // Ensure that the server is shut down when the application is destroyed. + registerDestructor(appInstance, () => { + testContext.server.shutdown(); + delete testContext.server; + }); + } + } +} + +export default { + initialize, +}; diff --git a/addon/orm/associations/association.js b/addon/orm/associations/association.js index d1320b9e8..8176a753c 100644 --- a/addon/orm/associations/association.js +++ b/addon/orm/associations/association.js @@ -1,21 +1,18 @@ -export default class Association { +import { _ormAssociationsAssociation } from 'miragejs'; +import { deprecateNestedImport } from '../../deprecate-imports'; - constructor(modelName, opts) { - if (typeof modelName === 'object') { - // Received opts only - this.modelName = undefined; - this.opts = modelName; - } else { - // The modelName of the association - this.modelName = modelName; - this.opts = opts || {}; - } +/** + @class DeprecatedAssociation + @hide + */ +export default class DeprecatedAssociation extends _ormAssociationsAssociation { + constructor(...args) { + deprecateNestedImport( + `Importing 'Association' from 'ember-cli-mirage/orm/associations/association' is deprecated. ` + + `This wasn't intended to be a public API. If you absolute know what you are doing, ` + + `install the \`miragejs\` package and use \`import { _ormAssociationsAssociation } from 'miragejs';\` instead.` + ); - // The key pointing to the association - this.key = ''; - - // The modelName that owns this association - this.ownerModelName = ''; + super(...args); } - } diff --git a/addon/orm/associations/belongs-to.js b/addon/orm/associations/belongs-to.js index 94abaee0f..c4c1cbc7b 100644 --- a/addon/orm/associations/belongs-to.js +++ b/addon/orm/associations/belongs-to.js @@ -1,148 +1,18 @@ -import Association from './association'; -import _assign from 'lodash/assign'; -import { capitalize, camelize } from 'ember-cli-mirage/utils/inflector'; -import { toCollectionName } from 'ember-cli-mirage/utils/normalize-name'; -import assert from 'ember-cli-mirage/assert'; +import { _ormAssociationsBelongsTo } from 'miragejs'; +import { deprecateNestedImport } from '../../deprecate-imports'; /** - * @class BelongsTo - * @extends Association - * @constructor - * @public + @class DeprecatedBelongsTo + @hide */ -class BelongsTo extends Association { - - /* - The belongsTo association adds a fk to the owner of the association - */ - /** - * @method getForeignKeyArray - * @return {Array} Array of camelized name of the model owning the association - * and foreign key for the association - * @public - */ - getForeignKeyArray() { - return [camelize(this.ownerModelName), this.getForeignKey()]; - } - - /** - * @method getForeignKey - * @return {String} Foreign key for the association - * @public - */ - getForeignKey() { - return `${camelize(this.key)}Id`; +export default class DeprecatedBelongsTo extends _ormAssociationsBelongsTo { + constructor(...args) { + deprecateNestedImport( + `Importing 'BelongsTo' from 'ember-cli-mirage/orm/associations/belongs-to' is deprecated. ` + + `This wasn't intended to be a public API. If you absolute know what you are doing, ` + + `install the \`miragejs\` package and use \`import { _ormAssociationsBelongsTo } from 'miragejs';\` instead.` + ); + + super(...args); } - - /** - * registers belongs-to association defined by given key on given model, - * defines getters / setters for associated parent and associated parent's id, - * adds methods for creating unsaved parent record and creating a saved one - * - * @method addMethodsToModelClass - * @param {Function} ModelClass - * @param {String} key - * @param {Schema} schema - * @public - */ - addMethodsToModelClass(ModelClass, key, schema) { - let modelPrototype = ModelClass.prototype; - let association = this; - let foreignKey = this.getForeignKey(); - - let associationHash = {}; - associationHash[key] = this; - modelPrototype.belongsToAssociations = _assign(modelPrototype.belongsToAssociations, associationHash); - modelPrototype.associationKeys.push(key); - modelPrototype.associationIdKeys.push(foreignKey); - - Object.defineProperty(modelPrototype, this.getForeignKey(), { - - /* - object.parentId - - returns the associated parent's id - */ - get() { - return this.attrs[foreignKey]; - }, - - /* - object.parentId = (parentId) - - sets the associated parent (via id) - */ - set(id) { - assert( - !id || schema.db[toCollectionName(association.modelName)].find(id), - `Couldn\'t find ${association.modelName} with id = ${id}` - ); - - this.attrs[foreignKey] = id; - return this; - } - }); - - Object.defineProperty(modelPrototype, key, { - /* - object.parent - - returns the associated parent - */ - get() { - let foreignKeyId = this[foreignKey]; - if (foreignKeyId != null) { - association._tempParent = null; - return schema[toCollectionName(association.modelName)].find(foreignKeyId); - - } else if (association._tempParent) { - return association._tempParent; - } else { - return null; - } - }, - - /* - object.parent = (parentModel) - - sets the associated parent (via model) - */ - set(newModel) { - if (newModel && newModel.isNew()) { - this[foreignKey] = null; - association._tempParent = newModel; - } else if (newModel) { - association._tempParent = null; - this[foreignKey] = newModel.id; - } else { - association._tempParent = null; - this[foreignKey] = null; - } - } - }); - - /* - object.newParent - - creates a new unsaved associated parent - */ - modelPrototype[`new${capitalize(key)}`] = function(attrs) { - let parent = schema[toCollectionName(association.modelName)].new(attrs); - - this[key] = parent; - - return parent; - }; - - /* - object.createParent - - creates a new saved associated parent, and immediately persists both models - */ - modelPrototype[`create${capitalize(key)}`] = function(attrs) { - let parent = schema[toCollectionName(association.modelName)].create(attrs); - - this[key] = parent; - this.save(); - - return parent; - }; - } - } - -export default BelongsTo; diff --git a/addon/orm/associations/has-many.js b/addon/orm/associations/has-many.js index a32c80dac..96766fcc7 100644 --- a/addon/orm/associations/has-many.js +++ b/addon/orm/associations/has-many.js @@ -1,191 +1,18 @@ -import Association from './association'; -import Collection from '../collection'; -import _assign from 'lodash/assign'; -import _compact from 'lodash/compact'; -import { capitalize, camelize, singularize } from 'ember-cli-mirage/utils/inflector'; -import { toCollectionName } from 'ember-cli-mirage/utils/normalize-name'; -import assert from 'ember-cli-mirage/assert'; +import { _ormAssociationsHasMany } from 'miragejs'; +import { deprecateNestedImport } from '../../deprecate-imports'; /** - * @class HasMany - * @extends Association - * @constructor - * @public + @class DeprecatedHasMany + @hide */ -class HasMany extends Association { - - /** - * @method getForeignKeyArray - * @return {Array} Array of camelized model name of associated objects - * and foreign key for the object owning the association - * @public - */ - getForeignKeyArray() { - return [camelize(this.modelName), this.getForeignKey()]; - } - - /** - * @method getForeignKey - * @return {String} Foreign key for the object owning the association - * @public - */ - getForeignKey() { - return `${this.opts.inverse || camelize(this.ownerModelName)}Id`; - } - - /** - * Registers has-many association defined by given key on given model, - * defines getters / setters for associated records and associated records' ids, - * adds methods for creating unsaved child records and creating saved ones - * - * @method addMethodsToModelClass - * @param {Function} ModelClass - * @param {String} key - * @param {Schema} schema - * @public - */ - addMethodsToModelClass(ModelClass, key, schema) { - let modelPrototype = ModelClass.prototype; - this._model = modelPrototype; - this._key = key; - - let association = this; - let foreignKey = this.getForeignKey(); - let relationshipIdsKey = `${camelize(singularize(association.key))}Ids`; - let associationHash = { [key]: this }; - - modelPrototype.hasManyAssociations = _assign(modelPrototype.hasManyAssociations, associationHash); - modelPrototype.associationKeys.push(key); - modelPrototype.associationIdKeys.push(relationshipIdsKey); - - Object.defineProperty(modelPrototype, relationshipIdsKey, { - - /* - object.childrenIds - - returns an array of the associated children's ids - */ - get() { - let children = association._cachedChildren || new Collection(association.modelName); - - if (!this.isNew()) { - let query = { [foreignKey]: this.id }; - let savedChildren = schema[toCollectionName(association.modelName)].where(query); - - children.mergeCollection(savedChildren); - } - - return children.models.map((model) => model.id); - }, - - /* - object.childrenIds = ([childrenIds...]) - - sets the associated parent (via id) - */ - set(ids) { - ids = ids || []; - - if (this.isNew()) { - association._cachedChildren = schema[toCollectionName(association.modelName)].find(ids); - - } else { - // Set current children's fk to null - let query = { [foreignKey]: this.id }; - schema[toCollectionName(association.modelName)].where(query).update(foreignKey, null); - - // Associate the new childrens to this model - schema[toCollectionName(association.modelName)].find(ids).update(foreignKey, this.id); - - // Clear out any old cached children - association._cachedChildren = new Collection(association.modelName); - } - - return this; - } - }); - - Object.defineProperty(modelPrototype, key, { - - /* - object.children - - returns an array of associated children - */ - get() { - let temporaryChildren = association._cachedChildren || new Collection(association.modelName); - - if (this.isNew()) { - return temporaryChildren; - - } else { - let query = { [foreignKey]: this.id }; - let savedChildren = schema[toCollectionName(association.modelName)].where(query); - - return savedChildren.mergeCollection(temporaryChildren); - } - }, - - /* - object.children = [model1, model2, ...] - - sets the associated children (via array of models) - - note: this method will persist unsaved chidren - + (why? because rails does) - */ - set(models) { - models = models ? _compact(models) : []; - - if (this.isNew()) { - association._cachedChildren = models instanceof Collection ? models : new Collection(association.modelName, models); - - } else { - - // Set current children's fk to null - let query = { [foreignKey]: this.id }; - schema[toCollectionName(association.modelName)].where(query).update(foreignKey, null); - - // Save any children that are new - models.filter((model) => model.isNew()) - .forEach((model) => model.save()); - - // Associate the new children to this model - schema[toCollectionName(association.modelName)].find(models.map((m) => m.id)).update(foreignKey, this.id); - - // Clear out any old cached children - association._cachedChildren = new Collection(association.modelName); - } - } - }); - - /* - object.newChild - - creates a new unsaved associated child - */ - modelPrototype[`new${capitalize(camelize(singularize(association.key)))}`] = function(attrs = {}) { - if (!this.isNew()) { - attrs = _assign(attrs, { [foreignKey]: this.id }); - } - - let child = schema[toCollectionName(association.modelName)].new(attrs); - - association._cachedChildren = association._cachedChildren || new Collection(association.modelName); - association._cachedChildren.models.push(child); - - return child; - }; - - /* - object.createChild - - creates an associated child, persists directly to db, and - updates the association's foreign key - - parent must be saved - */ - modelPrototype[`create${capitalize(camelize(singularize(association.key)))}`] = function(attrs = {}) { - assert(!this.isNew(), 'You cannot call create unless the parent is saved'); - - let augmentedAttrs = _assign(attrs, { [foreignKey]: this.id }); - let child = schema[toCollectionName(association.modelName)].create(augmentedAttrs); - - return child; - }; +export default class DeprecatedHasMany extends _ormAssociationsHasMany { + constructor(...args) { + deprecateNestedImport( + `Importing 'HasMany' from 'ember-cli-mirage/orm/associations/has-many' is deprecated. ` + + `This wasn't intended to be a public API. If you absolute know what you are doing, ` + + `install the \`miragejs\` package and use \`import { _ormAssociationsHasMany } from 'miragejs';\` instead.` + ); + + super(...args); } } - -export default HasMany; diff --git a/addon/orm/collection.js b/addon/orm/collection.js index 7eb480d9d..f45096140 100644 --- a/addon/orm/collection.js +++ b/addon/orm/collection.js @@ -1,141 +1,17 @@ -import _invokeMap from 'lodash/invokeMap'; -import assert from '../assert'; +import { Collection } from 'miragejs'; +import { deprecateNestedImport } from '../deprecate-imports'; /** - * An array of models, returned from one of the schema query - * methods (all, find, where). Knows how to update and destroy its models. - * @class Collection - * @constructor - * @public + @class DeprecatedCollection + @hide */ -export default class Collection { - constructor(modelName, models = []) { - assert( - modelName && typeof modelName === 'string', - 'You must pass a `modelName` into a Collection' +export default class DeprecatedCollection extends Collection { + constructor(...args) { + deprecateNestedImport( + `Importing 'Collection' from 'ember-cli-mirage/orm/collection' is deprecated. ` + + `Install the \`miragejs\` package and use \`import { Collection } from 'miragejs';\` instead.` ); - this.modelName = modelName; - this.models = models; - } - - /** - * Number of models in the collection. - * - * @property length - * @type Number - * @public - */ - get length() { - return this.models.length; - } - - /** - * Updates each model in the collection (persisting immediately to the db). - * @method update - * @param key - * @param val - * @return this - * @public - */ - update(...args) { - _invokeMap(this.models, 'update', ...args); - - return this; - } - - /** - * Destroys the db record for all models in the collection. - * @method destroy - * @return this - * @public - */ - destroy() { - _invokeMap(this.models, 'destroy'); - - return this; - } - - /** - * Saves all models in the collection. - * @method save - * @return this - * @public - */ - save() { - _invokeMap(this.models, 'save'); - - return this; - } - - /** - * Reloads each model in the collection. - * @method reload - * @return this - * @public - */ - reload() { - _invokeMap(this.models, 'reload'); - - return this; - } - - /** - * @method filter - * @param f - * @return {Collection} - * @public - */ - filter(f) { - let filteredModels = this.models.filter(f); - - return new Collection(this.modelName, filteredModels); - } - - /** - * @method sort - * @param f - * @return {Collection} - * @public - */ - sort(f) { - let sortedModels = this.models.concat().sort(f); - - return new Collection(this.modelName, sortedModels); - } - - /** - * @method slice - * @param {Integer} begin - * @param {Integer} end - * @return {Collection} - * @public - */ - slice(...args) { - let slicedModels = this.models.slice(...args); - - return new Collection(this.modelName, slicedModels); - } - - /** - * @method mergeCollection - * @param collection - * @return this - * @public - */ - mergeCollection(collection) { - this.models = this.models.concat(collection.models); - - return this; - } - - /** - * Simple string representation of the collection and id. - * @method toString - * @return {String} - * @public - */ - toString() { - return `collection:${this.modelName}(${this.models.map((m) => m.id).join(',')})`; + super(...args); } } diff --git a/addon/orm/model.js b/addon/orm/model.js index cfdd5f373..135fb7b73 100644 --- a/addon/orm/model.js +++ b/addon/orm/model.js @@ -1,295 +1,17 @@ -import { toCollectionName } from 'ember-cli-mirage/utils/normalize-name'; -import extend from '../utils/extend'; -import assert from '../assert'; -import Collection from './collection'; - -/* - The Model class. Notes: - - - We need to pass in modelName, because models are created with - .extend and anonymous functions, so you cannot use - reflection to find the name of the constructor. -*/ - -/* - Constructor -*/ -class Model { - - constructor(schema, modelName, attrs, fks) { - assert(schema, 'A model requires a schema'); - assert(modelName, 'A model requires a modelName'); - - this._schema = schema; - this.modelName = modelName; - this.fks = fks || []; - attrs = attrs || {}; - - this._setupAttrs(attrs); - this._setupRelationships(attrs); - - return this; - } - - /** - * Creates or saves the model. - * @method save - * @return this - * @public - */ - save() { - let collection = toCollectionName(this.modelName); - - if (this.isNew()) { - // Update the attrs with the db response - this.attrs = this._schema.db[collection].insert(this.attrs); - - // Ensure the id getter/setter is set - this._definePlainAttribute('id'); - - } else { - this._schema.db[collection].update(this.attrs.id, this.attrs); - } - - // Update associated children - this._saveAssociations(); - - return this; - } - - /** - * Update the record in the db. - * @method update - * @param {String} key - * @param {String} val - * @return this - * @public - */ - update(key, val) { - let attrs; - if (key == null) { - return this; - } - - if (typeof key === 'object') { - attrs = key; - } else { - (attrs = {})[key] = val; - } - - Object.keys(attrs).forEach(function(attr) { - this._definePlainAttribute(attr); - this[attr] = attrs[attr]; - }, this); - - this.save(); - - return this; - } - - /** - * Destroys the db record - * @method destroy - * @public - */ - destroy() { - let collection = toCollectionName(this.modelName); - this._schema.db[collection].remove(this.attrs.id); - } - - /** - * Boolean, true if the model has not been persisted yet to the db. - * - * Originally this method simply checked if the model had an id; however, - * we let people create models with pre-specified ids. So, we have to - * check whether the record is in the actual databse or not. - * - * @method isNew - * @return {Boolean} - * @public - */ - isNew() { - let hasDbRecord = false; - let hasId = this.attrs.id !== undefined && this.attrs.id !== null; - - if (hasId) { - let collectionName = toCollectionName(this.modelName); - let record = this._schema.db[collectionName].find(this.attrs.id); - if (record) { - hasDbRecord = true; - } - } - - return !hasDbRecord; - } - - /** - * Boolean, opposite of `isNew` - * @method isSaved - * @return {Boolean} - * @public - */ - isSaved() { - return !this.isNew(); - } - - /** - * Reload a model’s data from the database. - * @method reload - * @return this - * @public - */ - reload() { - let collection = toCollectionName(this.modelName); - let attrs = this._schema.db[collection].find(this.id); - - Object.keys(attrs) - .filter(function(attr) { - return attr !== 'id'; - }) - .forEach(function(attr) { - this[attr] = attrs[attr]; - }, this); - - return this; - } - - toJSON() { - return this.attrs; - } - - // Private - - /** - * model.attrs represents the persistable attributes, i.e. your db - * table fields. - * @method _setupAttrs - * @param attrs - * @private - */ - _setupAttrs(attrs) { - // Verify no undefined associations are passed in - Object.keys(attrs) - .filter((key) => { - let value = attrs[key]; - return (value instanceof Model || value instanceof Collection); - }) - .forEach((key) => { - let modelOrCollection = attrs[key]; - - assert(this.associationKeys.indexOf(key) > -1, `You're trying to create a ${this.modelName} model and you passed in a ${modelOrCollection.toString()} under the ${key} key, but you haven't defined that key as an association on your model.`); - }); - - // Filter out association keys - let hash = Object.keys(attrs).reduce((memo, key) => { - if (this.associationKeys.indexOf(key) === -1 && this.associationIdKeys.indexOf(key) === -1) { - memo[key] = attrs[key]; - } - return memo; - }, {}); - - // Ensure fks are there - this.fks.map(function(fk) { - hash[fk] = attrs[fk] || null; - }); - - this.attrs = hash; - - // define plain getter/setters for non-association keys - Object.keys(hash).forEach(function(attr) { - if (this.associationKeys.indexOf(attr) === -1 && this.associationIdKeys.indexOf(attr) === -1) { - this._definePlainAttribute(attr); - } - }, this); - } - - /** - * Define getter/setter for a plain attribute - * @method _definePlainAttribute - * @param attr - * @private - */ - _definePlainAttribute(attr) { - - // Ensure the property hasn't already been defined - let existingProperty = Object.getOwnPropertyDescriptor(this, attr); - if (existingProperty && existingProperty.get) { - return; - } - - // Ensure the attribute is on the attrs hash - if (!this.attrs.hasOwnProperty(attr)) { - this.attrs[attr] = null; - } - - // Define the getter/setter - Object.defineProperty(this, attr, { - get() { - return this.attrs[attr]; - }, - set(val) { - this.attrs[attr] = val; - return this; - } - }); - } - - /** - * @method _setupRelationships - * @param attrs - * @private - */ - _setupRelationships(attrs) { - // Only want association keys and fks - let hash = Object.keys(attrs).reduce((memo, attr) => { - if (this.associationKeys.indexOf(attr) > -1 || this.associationIdKeys.indexOf(attr) > -1 || this.fks.indexOf(attr) > -1) { - memo[attr] = attrs[attr]; - } - return memo; - }, {}); - - Object.keys(hash).forEach(function(attr) { - this[attr] = hash[attr]; - }, this); - } - - /** - * Update associated children when saving a collection - * @method _saveAssociations - * @private - */ - _saveAssociations() { - Object.keys(this.belongsToAssociations).forEach((key) => { - let association = this.belongsToAssociations[key]; - let parent = this[key]; - if (parent && parent.isNew()) { - let fk = association.getForeignKey(); - parent.save(); - this.update(fk, parent.id); - } - }); - - Object.keys(this.hasManyAssociations).forEach((key) => { - let association = this.hasManyAssociations[key]; - let children = this[key]; - children.update(association.getForeignKey(), this.id); - }); - } - - /** - * Simple string representation of the model and id. - * @method toString - * @return {String} - * @public - */ - toString() { - return `model:${this.modelName}(${this.id})`; +import { Model } from 'miragejs'; +import { deprecateNestedImport } from '../deprecate-imports'; + +/** + @class DeprecatedModel + @hide + */ +export default class DeprecatedModel extends Model { + constructor(...args) { + deprecateNestedImport( + `Importing 'Model' from 'ember-cli-mirage/orm/model' is deprecated. ` + + `Install the \`miragejs\` package and use \`import { Model } from 'miragejs';\` instead.` + ); + + super(...args); } } - -Model.extend = extend; -Model.findBelongsToAssociation = function(associationType) { - return this.prototype.belongsToAssociations[associationType]; -}; - -export default Model; diff --git a/addon/orm/polymorphic-collection.js b/addon/orm/polymorphic-collection.js new file mode 100644 index 000000000..ad3f2fc1c --- /dev/null +++ b/addon/orm/polymorphic-collection.js @@ -0,0 +1,18 @@ +import { _ormPolymorphicCollection } from 'miragejs'; +import { deprecateNestedImport } from '../deprecate-imports'; + +/** + @class DeprecatedPolymorphicCollection + @hide + */ +export default class DeprecatedPolymorphicCollection extends _ormPolymorphicCollection { + constructor(...args) { + deprecateNestedImport( + `Importing 'PolymorphicCollection' from 'ember-cli-mirage/orm/polymorphic-collection' is deprecated. ` + + `This wasn't intended to be a public API. If you absolute know what you are doing, ` + + `install the \`miragejs\` package and use \`import { _ormPolymorphicCollection } from 'miragejs';\` instead.` + ); + + super(...args); + } +} diff --git a/addon/orm/schema.js b/addon/orm/schema.js index 5c1e47368..39a55ed36 100644 --- a/addon/orm/schema.js +++ b/addon/orm/schema.js @@ -1,290 +1,18 @@ -import { pluralize, camelize, dasherize } from '../utils/inflector'; -import { toCollectionName, toModelName } from 'ember-cli-mirage/utils/normalize-name'; -import Association from './associations/association'; -import Collection from './collection'; -import _forIn from 'lodash/forIn'; -import _includes from 'lodash/includes'; -import assert from '../assert'; +import { _ormSchema } from 'miragejs'; +import { deprecateNestedImport } from '../deprecate-imports'; /** - * @class Schema - * @constructor - * @public + @class DeprecatedSchema + @hide */ -export default class Schema { - - constructor(db, modelsMap = {}) { - assert(db, 'A schema requires a db'); - - this.db = db; - this._registry = {}; - this.registerModels(modelsMap); - } - - /** - * @method registerModels - * @param hash - * @public - */ - registerModels(hash = {}) { - _forIn(hash, (model, key) => { - this.registerModel(key, hash[key]); - }); - } - - /** - * @method registerModel - * @param type - * @param ModelClass - * @public - */ - registerModel(type, ModelClass) { - let camelizedModelName = camelize(type); - let modelName = dasherize(camelizedModelName); - - // Avoid mutating original class, because we may want to reuse it across many tests - ModelClass = ModelClass.extend(); - - // Store model & fks in registry - this._registry[camelizedModelName] = this._registry[camelizedModelName] || { class: null, foreignKeys: [] }; // we may have created this key before, if another model added fks to it - this._registry[camelizedModelName].class = ModelClass; - - // Set up associations - ModelClass.prototype.hasManyAssociations = {}; // a registry of the model's hasMany associations. Key is key from model definition, value is association instance itself - ModelClass.prototype.belongsToAssociations = {}; // a registry of the model's belongsTo associations. Key is key from model definition, value is association instance itself - ModelClass.prototype.associationKeys = []; // ex: address.user, user.addresses - ModelClass.prototype.associationIdKeys = []; // ex: address.user_id, user.address_ids. may or may not be a fk. - - let fksAddedFromThisModel = {}; - for (let associationProperty in ModelClass.prototype) { - if (ModelClass.prototype[associationProperty] instanceof Association) { - let association = ModelClass.prototype[associationProperty]; - association.key = associationProperty; - association.modelName = association.modelName || toModelName(associationProperty); - association.ownerModelName = modelName; - - // Update the registry with this association's foreign keys. This is - // essentially our "db migration", since we must know about the fks. - let [fkHolder, fk] = association.getForeignKeyArray(); - - fksAddedFromThisModel[fkHolder] = fksAddedFromThisModel[fkHolder] || []; - assert( - !_includes(fksAddedFromThisModel[fkHolder], fk), - `Your '${type}' model definition has multiple possible inverse relationships of type '${fkHolder}'. - - Please read the associations guide and specify explicit inverses: http://www.ember-cli-mirage.com/docs/v0.2.x/models/#associations` - ); - fksAddedFromThisModel[fkHolder].push(fk); - - this._addForeignKeyToRegistry(fkHolder, fk); - - // Augment the Model's class with any methods added by this association - association.addMethodsToModelClass(ModelClass, associationProperty, this); - } - } - - // Create a db collection for this model, if doesn't exist - let collection = toCollectionName(modelName); - if (!this.db[collection]) { - this.db.createCollection(collection); - } - - // Create the entity methods - this[collection] = { - camelizedModelName, - new: (attrs) => this.new(camelizedModelName, attrs), - create: (attrs) => this.create(camelizedModelName, attrs), - all: (attrs) => this.all(camelizedModelName, attrs), - find: (attrs) => this.find(camelizedModelName, attrs), - findBy: (attrs) => this.findBy(camelizedModelName, attrs), - where: (attrs) => this.where(camelizedModelName, attrs), - first: (attrs) => this.first(camelizedModelName, attrs) - }; - - return this; - } - - /** - * @method modelFor - * @param type - * @public - */ - modelFor(type) { - return this._registry[type]; - } - - /** - * @method new - * @param type - * @param attrs - * @public - */ - new(type, attrs) { - return this._instantiateModel(dasherize(type), attrs); - } - - /** - * @method create - * @param type - * @param attrs - * @public - */ - create(type, attrs) { - return this.new(type, attrs).save(); - } - - /** - * @method all - * @param type - * @public - */ - all(type) { - let collection = this._collectionForType(type); - - return this._hydrate(collection, dasherize(type)); - } - - /** - * @method find - * @param type - * @param ids - * @public - */ - find(type, ids) { - let collection = this._collectionForType(type); - let records = collection.find(ids); - - if (Array.isArray(ids)) { - assert( - records.length === ids.length, - `Couldn\'t find all ${pluralize(type)} with ids: (${ids.join(',')}) (found ${records.length} results, but was looking for ${ids.length})` - ); - } - - return this._hydrate(records, dasherize(type)); - } - - /** - * @method findBy - * @param type - * @param attributeName - * @public - */ - findBy(type, query) { - let collection = this._collectionForType(type); - let records = collection.findBy(query); - - return this._hydrate(records, dasherize(type)); - } - - /** - * @method where - * @param type - * @param query - * @public - */ - where(type, query) { - let collection = this._collectionForType(type); - let records = collection.where(query); - - return this._hydrate(records, dasherize(type)); - } - - /** - * @method first - * @param type - * @public - */ - first(type) { - let collection = this._collectionForType(type); - let [record] = collection; - - return this._hydrate(record, dasherize(type)); - } - - /* - Private methods - */ - - /** - * @method _collectionForType - * @param type - * @private - */ - _collectionForType(type) { - let collection = toCollectionName(type); - assert( - this.db[collection], - `You\'re trying to find model(s) of type ${type} but this collection doesn\'t exist in the database.` +export default class DeprecatedSchema extends _ormSchema { + constructor(...args) { + deprecateNestedImport( + `Importing 'Schema' from 'ember-cli-mirage/orm/schema' is deprecated. ` + + `This wasn't intended to be a public API. If you absolute know what you are doing, ` + + `install the \`miragejs\` package and use \`import { _ormSchema } from 'miragejs';\` instead.` ); - return this.db[collection]; - } - - /** - * @method _addForeignKeyToRegistry - * @param type - * @param fk - * @private - */ - _addForeignKeyToRegistry(type, fk) { - this._registry[type] = this._registry[type] || { class: null, foreignKeys: [] }; - - let fks = this._registry[type].foreignKeys; - if (!_includes(fks, fk)) { - fks.push(fk); - } - } - - /** - * @method _instantiateModel - * @param modelName - * @param attrs - * @private - */ - _instantiateModel(modelName, attrs) { - let ModelClass = this._modelFor(modelName); - let fks = this._foreignKeysFor(modelName); - - return new ModelClass(this, modelName, attrs, fks); - } - - /** - * @method _modelFor - * @param modelName - * @private - */ - _modelFor(modelName) { - return this._registry[camelize(modelName)].class; - } - - /** - * @method _foreignKeysFor - * @param modelName - * @private - */ - _foreignKeysFor(modelName) { - return this._registry[camelize(modelName)].foreignKeys; - } - - /** - * Takes a record and returns a model, or an array of records - * and returns a collection. - * @method _hydrate - * @param records - * @param modelName - * @private - */ - _hydrate(records, modelName) { - if (Array.isArray(records)) { - let models = records.map(function(record) { - return this._instantiateModel(modelName, record); - }, this); - return new Collection(modelName, models); - } else if (records) { - return this._instantiateModel(modelName, records); - } else { - return null; - } + super(...args); } } diff --git a/addon/response.js b/addon/response.js index 056efa050..6b99b08b0 100644 --- a/addon/response.js +++ b/addon/response.js @@ -1,18 +1,17 @@ -export default class Response { +import { Response } from 'miragejs'; +import { deprecateNestedImport } from './deprecate-imports'; - constructor(code, headers = {}, data = {}) { - this.code = code; - this.headers = headers; - this.data = data; - } - - toRackResponse() { - let { headers } = this; - if (!headers.hasOwnProperty('Content-Type')) { - headers['Content-Type'] = 'application/json'; - } +/** + @class DeprecatedResponse + @hide + */ +export default class DeprecatedResponse extends Response { + constructor(...args) { + deprecateNestedImport( + `Importing 'Response' from 'ember-cli-mirage/response' is deprecated. ` + + `Install the \`miragejs\` package and use \`import { Response } from 'miragejs';\` instead.` + ); - return [this.code, this.headers, this.data]; + super(...args); } - } diff --git a/addon/route-handler.js b/addon/route-handler.js index 9acdee0a7..3ec95aa35 100644 --- a/addon/route-handler.js +++ b/addon/route-handler.js @@ -1,126 +1,18 @@ -import Ember from 'ember'; -import { MirageError } from 'ember-cli-mirage/assert'; -import Response from './response'; -import FunctionHandler from './route-handlers/function'; -import ObjectHandler from './route-handlers/object'; -import GetShorthandHandler from './route-handlers/shorthands/get'; -import PostShorthandHandler from './route-handlers/shorthands/post'; -import PutShorthandHandler from './route-handlers/shorthands/put'; -import DeleteShorthandHandler from './route-handlers/shorthands/delete'; -import HeadShorthandHandler from './route-handlers/shorthands/head'; - -const { RSVP: { Promise }, isBlank, typeOf } = Ember; - -function isNotBlankResponse(response) { - return response - && !(typeOf(response) === 'object' && Object.keys(response).length === 0) - && (Array.isArray(response) || !isBlank(response)); -} - -const DEFAULT_CODES = { get: 200, put: 204, post: 201, 'delete': 204 }; - -function createHandler({ verb, schema, serializerOrRegistry, path, rawHandler, options }) { - let handler; - let args = [schema, serializerOrRegistry, rawHandler, path, options]; - let type = typeOf(rawHandler); - - if (type === 'function') { - handler = new FunctionHandler(...args); - } else if (type === 'object') { - handler = new ObjectHandler(...args); - } else if (verb === 'get') { - handler = new GetShorthandHandler(...args); - } else if (verb === 'post') { - handler = new PostShorthandHandler(...args); - } else if (verb === 'put' || verb === 'patch') { - handler = new PutShorthandHandler(...args); - } else if (verb === 'delete') { - handler = new DeleteShorthandHandler(...args); - } else if (verb === 'head') { - handler = new HeadShorthandHandler(...args); - } - return handler; -} - -export default class RouteHandler { - - constructor({ schema, verb, rawHandler, customizedCode, options, path, serializerOrRegistry }) { - this.verb = verb; - this.customizedCode = customizedCode; - this.serializerOrRegistry = serializerOrRegistry; - this.handler = createHandler({ verb, schema, path, serializerOrRegistry, rawHandler, options }); - } - - handle(request) { - return new Promise(resolve => { - this._getMirageResponseForRequest(request).then(mirageResponse => { - this.serialize(mirageResponse, request).then(serializedMirageResponse => { - resolve(serializedMirageResponse.toRackResponse()); - }); - }); - }); - } - - _getMirageResponseForRequest(request) { - let result; - try { - /* - We need to do this for the #serialize convenience method. Probably is - a better way. - */ - if (this.handler instanceof FunctionHandler) { - this.handler.setRequest(request); - } - - result = this.handler.handle(request); - } catch(e) { - if (e instanceof MirageError) { - throw e; - } else { - let message = (typeOf(e) === 'string') ? e : e.message; - throw new MirageError(`Your handler for the url ${request.url} threw an error: ${message}`); - } - } - - return this._toMirageResponse(result); - } - - _toMirageResponse(result) { - let mirageResponse; - - return new Promise(resolve => { - Promise.resolve(result).then(response => { - if (response instanceof Response) { - mirageResponse = result; - } else { - let code = this._getCodeForResponse(response); - mirageResponse = new Response(code, {}, response); - } - resolve(mirageResponse); - }); - - }); - } - - _getCodeForResponse(response) { - let code; - if (this.customizedCode) { - code = this.customizedCode; - } else { - code = DEFAULT_CODES[this.verb]; - if (code === 204 && isNotBlankResponse(response)) { - code = 200; - } - } - return code; - } - - serialize(mirageResponsePromise, request) { - return new Promise(resolve => { - Promise.resolve(mirageResponsePromise).then(mirageResponse => { - mirageResponse.data = this.serializerOrRegistry.serialize(mirageResponse.data, request); - resolve(mirageResponse); - }); - }); +import { _RouteHandler } from 'miragejs'; +import { deprecateNestedImport } from './deprecate-imports'; + +/** + @class DeprecatedRouteHandler + @hide + */ +export default class DeprecatedRouteHandler extends _RouteHandler { + constructor(...args) { + deprecateNestedImport( + `Importing 'RouteHandler' from 'ember-cli-mirage/route-handler' is deprecated. ` + + `This wasn't intended to be a public API. If you absolute know what you are doing, ` + + `install the \`miragejs\` package and use \`import { _RouteHandler } from 'miragejs';\` instead.` + ); + + super(...args); } } diff --git a/addon/route-handlers/base.js b/addon/route-handlers/base.js index 6f5b2f80d..8e1e4687c 100644 --- a/addon/route-handlers/base.js +++ b/addon/route-handlers/base.js @@ -1,93 +1,18 @@ -import assert from 'ember-cli-mirage/assert'; -import { camelize, singularize, dasherize } from 'ember-cli-mirage/utils/inflector'; - -export default class BaseRouteHandler { - - getModelClassFromPath(fullPath) { - if (!fullPath) { - return; - } - let path = fullPath.split('/'); - let lastPath; - while (path.length > 0) { - lastPath = path.splice(-1)[0]; - if (lastPath && lastPath !== ':id') { - break; - } - } - let modelName = dasherize(camelize(singularize(lastPath))); - return modelName; - } - - _getIdForRequest(request, jsonApiDoc) { - let id; - if (request && request.params && request.params.id) { - id = request.params.id; - } else if (jsonApiDoc && jsonApiDoc.data && jsonApiDoc.data.id) { - id = jsonApiDoc.data.id; - } - return id; - } - - _getJsonApiDocForRequest(request, modelName) { - let body; - if (request && request.requestBody) { - body = JSON.parse(request.requestBody); - } - return this.serializerOrRegistry.normalize(body, modelName); - } - - _getAttrsForRequest(request, modelName) { - let json = this._getJsonApiDocForRequest(request, modelName); - let id = this._getIdForRequest(request, json); - let attrs = {}; - - assert( - json.data && (json.data.attributes || json.data.type || json.data.relationships), - `You're using a shorthand or #normalizedRequestAttrs, but your serializer's normalize function did not return a valid JSON:API document. http://www.ember-cli-mirage.com/docs/v0.2.x/serializers/#normalizejson` - ); - - if (json.data.attributes) { - attrs = Object.keys(json.data.attributes).reduce((sum, key) => { - sum[camelize(key)] = json.data.attributes[key]; - return sum; - }, {}); - } - - if (json.data.relationships) { - Object.keys(json.data.relationships).forEach((key) => { - let relationship = json.data.relationships[key]; - - if (!Array.isArray(relationship.data)) { - attrs[`${camelize(key)}Id`] = relationship.data && relationship.data.id; - } - }, {}); - } - - if (id) { - attrs.id = id; - } - - return attrs; - } - - _getAttrsForFormRequest({ requestBody }) { - let attrs; - let urlEncodedParts = []; - - assert( - requestBody && typeof requestBody === 'string', - `You're using the helper method #normalizedFormData, but the request body is empty or not a valid url encoded string.` +import { _routeHandlersBase } from 'miragejs'; +import { deprecateNestedImport } from '../deprecate-imports'; + +/** + @class DeprecatedBaseRouteHandler + @hide + */ +export default class DeprecatedBaseRouteHandler extends _routeHandlersBase { + constructor(...args) { + deprecateNestedImport( + `Importing 'BaseRouteHandler' from 'ember-cli-mirage/route-handlers/base' is deprecated. ` + + `This wasn't intended to be a public API. If you absolute know what you are doing, ` + + `install the \`miragejs\` package and use \`import { _routeHandlersBase } from 'miragejs';\` instead.` ); - urlEncodedParts = requestBody.split('&'); - - attrs = urlEncodedParts.reduce((a, urlEncodedPart) => { - let [key, value] = urlEncodedPart.split('='); - a[key] = decodeURIComponent(value.replace(/\+/g, ' ')); - return a; - }, {}); - - return attrs; + super(...args); } } diff --git a/addon/route-handlers/function.js b/addon/route-handlers/function.js index adec306c5..d3d1fd3ec 100644 --- a/addon/route-handlers/function.js +++ b/addon/route-handlers/function.js @@ -1,48 +1,18 @@ -import BaseRouteHandler from './base'; - -export default class FunctionRouteHandler extends BaseRouteHandler { - - constructor(schema, serializerOrRegistry, userFunction, path) { - super(); - this.schema = schema; - this.serializerOrRegistry = serializerOrRegistry; - this.userFunction = userFunction; - this.path = path; - } - - handle(request) { - return this.userFunction(this.schema, request); - } - - setRequest(request) { - this.request = request; - } - - serialize(response, serializerType) { - let serializer; - - if (serializerType) { - serializer = this.serializerOrRegistry.serializerFor(serializerType, { explicit: true }); - } else { - serializer = this.serializerOrRegistry; - } - - return serializer.serialize(response, this.request); - } - - normalizedRequestAttrs() { - let { - path, - request, - request: { requestHeaders } - } = this; - - let modelName = this.getModelClassFromPath(path); - - if (/x-www-form-urlencoded/.test(requestHeaders['Content-Type'])) { - return this._getAttrsForFormRequest(request); - } else { - return this._getAttrsForRequest(request, modelName); - } +import { _routeHandlersFunction } from 'miragejs'; +import { deprecateNestedImport } from '../deprecate-imports'; + +/** + @class DeprecatedFunctionRouteHandler + @hide + */ +export default class DeprecatedFunctionRouteHandler extends _routeHandlersFunction { + constructor(...args) { + deprecateNestedImport( + `Importing 'FunctionRouteHandler' from 'ember-cli-mirage/route-handlers/function' is deprecated. ` + + `This wasn't intended to be a public API. If you absolute know what you are doing, ` + + `install the \`miragejs\` package and use \`import { _routeHandlersFunction } from 'miragejs';\` instead.` + ); + + super(...args); } } diff --git a/addon/route-handlers/object.js b/addon/route-handlers/object.js index 726179897..747b6abdd 100644 --- a/addon/route-handlers/object.js +++ b/addon/route-handlers/object.js @@ -1,13 +1,18 @@ -export default class ObjectRouteHandler { +import { _routeHandlersObject } from 'miragejs'; +import { deprecateNestedImport } from '../deprecate-imports'; - constructor(schema, serializerOrRegistry, object) { - this.schema = schema; - this.serializerOrRegistry = serializerOrRegistry; - this.object = object; - } +/** + @class DeprecatedObjectRouteHandler + @hide + */ +export default class DeprecatedObjectRouteHandler extends _routeHandlersObject { + constructor(...args) { + deprecateNestedImport( + `Importing 'ObjectRouteHandler' from 'ember-cli-mirage/route-handlers/object' is deprecated. ` + + `This wasn't intended to be a public API. If you absolute know what you are doing, ` + + `install the \`miragejs\` package and use \`import { _routeHandlersObject } from 'miragejs';\` instead.` + ); - handle(/* request */) { - return this.object; + super(...args); } - } diff --git a/addon/route-handlers/shorthands/base.js b/addon/route-handlers/shorthands/base.js index 99a35bd28..0bbcc1af8 100644 --- a/addon/route-handlers/shorthands/base.js +++ b/addon/route-handlers/shorthands/base.js @@ -1,36 +1,18 @@ -import { toCollectionName } from 'ember-cli-mirage/utils/normalize-name'; -import BaseRouteHandler from '../base'; +import { _routeHandlersShorthandsBase } from 'miragejs'; +import { deprecateNestedImport } from '../../deprecate-imports'; -export default class BaseShorthandRouteHandler extends BaseRouteHandler { +/** + @class DeprecatedBaseShorthandRouteHandler + @hide + */ +export default class DeprecatedBaseShorthandRouteHandler extends _routeHandlersShorthandsBase { + constructor(...args) { + deprecateNestedImport( + `Importing 'BaseShorthandRouteHandler' from 'ember-cli-mirage/route-handlers/shorthands/base' is deprecated. ` + + `This wasn't intended to be a public API. If you absolute know what you are doing, ` + + `install the \`miragejs\` package and use \`import { _routeHandlersShorthandsBase } from 'miragejs';\` instead.` + ); - constructor(schema, serializerOrRegistry, shorthand, path, options = {}) { - super(); - shorthand = shorthand || this.getModelClassFromPath(path); - this.schema = schema; - this.serializerOrRegistry = serializerOrRegistry; - this.shorthand = shorthand; - this.options = options; - - let type = Array.isArray(shorthand) ? 'array' : typeof shorthand; - if (type === 'string') { - let modelClass = this.schema[toCollectionName(shorthand)]; - this.handle = (request) => { - return this.handleStringShorthand(request, modelClass); - }; - } else if (type === 'array') { - let modelClasses = shorthand.map((modelName) => this.schema[toCollectionName(modelName)]); - this.handle = (request) => { - return this.handleArrayShorthand(request, modelClasses); - }; - } + super(...args); } - - // handleStringShorthand() { - // - // } - // - // handleArrayShorthand() { - // - // } - } diff --git a/addon/route-handlers/shorthands/delete.js b/addon/route-handlers/shorthands/delete.js index fba337b94..c4cfe804b 100644 --- a/addon/route-handlers/shorthands/delete.js +++ b/addon/route-handlers/shorthands/delete.js @@ -1,44 +1,18 @@ -import assert from 'ember-cli-mirage/assert'; -import BaseShorthandRouteHandler from './base'; -import { pluralize, camelize } from 'ember-cli-mirage/utils/inflector'; - -export default class DeleteShorthandRouteHandler extends BaseShorthandRouteHandler { - - /* - Remove the model from the db of type *camelizedModelName*. - - This would remove the user with id :id: - Ex: this.del('/contacts/:id', 'user'); - */ - handleStringShorthand(request, modelClass) { - let modelName = this.shorthand; - let camelizedModelName = camelize(modelName); - assert( - modelClass, - `The route handler for ${request.url} is trying to access the ${camelizedModelName} model, but that model doesn't exist. Create it using 'ember g mirage-model ${modelName}'.` +import { _routeHandlersShorthandsDelete } from 'miragejs'; +import { deprecateNestedImport } from '../../deprecate-imports'; + +/** + @class DeprecatedDeleteShorthandRouteHandler + @hide + */ +export default class DeprecatedDeleteShorthandRouteHandler extends _routeHandlersShorthandsDelete { + constructor(...args) { + deprecateNestedImport( + `Importing 'DeleteShorthandRouteHandler' from 'ember-cli-mirage/route-handlers/shorthands/delete' is deprecated. ` + + `This wasn't intended to be a public API. If you absolute know what you are doing, ` + + `install the \`miragejs\` package and use \`import { _routeHandlersShorthandsDelete } from 'miragejs';\` instead.` ); - let id = this._getIdForRequest(request); - return modelClass.find(id).destroy(); + super(...args); } - - /* - Remove the model and child related models from the db. - - This would remove the contact with id `:id`, and well - as this contact's addresses and phone numbers. - Ex: this.del('/contacts/:id', ['contact', 'addresses', 'numbers'); - */ - handleArrayShorthand(request, modelClasses) { - let id = this._getIdForRequest(request); - - let parent = modelClasses[0].find(id); - let childTypes = modelClasses.slice(1) - .map((modelClass) => pluralize(modelClass.camelizedModelName)); - - // Delete related children - childTypes.forEach((type) => parent[type].destroy()); - parent.destroy(); - } - } diff --git a/addon/route-handlers/shorthands/get.js b/addon/route-handlers/shorthands/get.js index b27ea1898..4cac4dbed 100644 --- a/addon/route-handlers/shorthands/get.js +++ b/addon/route-handlers/shorthands/get.js @@ -1,68 +1,18 @@ -import assert from 'ember-cli-mirage/assert'; -import BaseShorthandRouteHandler from './base'; -import { Response } from 'ember-cli-mirage'; -import { singularize, camelize } from 'ember-cli-mirage/utils/inflector'; - -export default class GetShorthandRouteHandler extends BaseShorthandRouteHandler { - - /* - Retrieve a model/collection from the db. - - Examples: - this.get('/contacts', 'contact'); - this.get('/contacts/:id', 'contact'); - */ - handleStringShorthand(request, modelClass) { - let modelName = this.shorthand; - let camelizedModelName = camelize(modelName); - - assert( - modelClass, - `The route handler for ${request.url} is trying to access the ${camelizedModelName} model, but that model doesn't exist. Create it using 'ember g mirage-model ${modelName}'.` +import { _routeHandlersShorthandsGet } from 'miragejs'; +import { deprecateNestedImport } from '../../deprecate-imports'; + +/** + @class DeprecatedGetShorthandRouteHandler + @hide + */ +export default class DeprecatedGetShorthandRouteHandler extends _routeHandlersShorthandsGet { + constructor(...args) { + deprecateNestedImport( + `Importing 'GetShorthandRouteHandler' from 'ember-cli-mirage/route-handlers/shorthands/get' is deprecated. ` + + `This wasn't intended to be a public API. If you absolute know what you are doing, ` + + `install the \`miragejs\` package and use \`import { _routeHandlersShorthandsGet } from 'miragejs';\` instead.` ); - let id = this._getIdForRequest(request); - if (id) { - let model = modelClass.find(id); - if (!model) { - return new Response(404); - } else { - return model; - } - } else if (this.options.coalesce && request.queryParams && request.queryParams.ids) { - return modelClass.find(request.queryParams.ids); - } else { - return modelClass.all(); - } + super(...args); } - - /* - Retrieve an array of collections from the db. - - Ex: this.get('/home', ['contacts', 'pictures']); - */ - handleArrayShorthand(request, modelClasses) { - let keys = this.shorthand; - let id = this._getIdForRequest(request); - - /* - If the first key is singular and we have an id param in - the request, we're dealing with the version of the shorthand - that has a parent model and several has-many relationships. - We throw an error, because the serializer is the appropriate - place for this now. - */ - assert( - !id || singularize(keys[0]) !== keys[0], - `It looks like you're using the "Single record with - related records" version of the array shorthand, in addition to opting - in to the model layer. This shorthand was made when there was no - serializer layer. Now that you're using models, please ensure your - relationships are defined, and create a serializer for the parent - model, adding the relationships there.` - ); - - return modelClasses.map((modelClass) => modelClass.all()); - } - } diff --git a/addon/route-handlers/shorthands/head.js b/addon/route-handlers/shorthands/head.js index 82724ba20..98f5bd146 100644 --- a/addon/route-handlers/shorthands/head.js +++ b/addon/route-handlers/shorthands/head.js @@ -1,44 +1,18 @@ -import assert from 'ember-cli-mirage/assert'; -import BaseShorthandRouteHandler from './base'; -import { Response } from 'ember-cli-mirage'; -import { camelize } from 'ember-cli-mirage/utils/inflector'; +import { _routeHandlersShorthandsHead } from 'miragejs'; +import { deprecateNestedImport } from '../../deprecate-imports'; -export default class HeadShorthandRouteHandler extends BaseShorthandRouteHandler { - - /* - Retrieve a model/collection from the db. - - Examples: - this.head('/contacts', 'contact'); - this.head('/contacts/:id', 'contact'); - */ - handleStringShorthand(request, modelClass) { - let modelName = this.shorthand; - let camelizedModelName = camelize(modelName); - - assert( - modelClass, - `The route handler for ${request.url} is trying to access the ${camelizedModelName} model, but that model doesn't exist. Create it using 'ember g mirage-model ${modelName}'.` +/** + @class DeprecatedHeadShorthandRouteHandler + @hide + */ +export default class DeprecatedHeadShorthandRouteHandler extends _routeHandlersShorthandsHead { + constructor(...args) { + deprecateNestedImport( + `Importing 'HeadShorthandRouteHandler' from 'ember-cli-mirage/route-handlers/shorthands/head' is deprecated. ` + + `This wasn't intended to be a public API. If you absolute know what you are doing, ` + + `install the \`miragejs\` package and use \`import { _routeHandlersShorthandsHead } from 'miragejs';\` instead.` ); - let id = this._getIdForRequest(request); - if (id) { - let model = modelClass.find(id); - if (!model) { - return new Response(404); - } else { - return new Response(204); - } - } else if (this.options.coalesce && request.queryParams && request.queryParams.ids) { - let model = modelClass.find(request.queryParams.ids); - - if (!model) { - return new Response(404); - } else { - return new Response(204); - } - } else { - return new Response(204); - } + super(...args); } } diff --git a/addon/route-handlers/shorthands/post.js b/addon/route-handlers/shorthands/post.js index 1ce91599d..ccaf1b49a 100644 --- a/addon/route-handlers/shorthands/post.js +++ b/addon/route-handlers/shorthands/post.js @@ -1,26 +1,18 @@ -import assert from 'ember-cli-mirage/assert'; -import BaseShorthandRouteHandler from './base'; -import { camelize } from 'ember-cli-mirage/utils/inflector'; +import { _routeHandlersShorthandsPost } from 'miragejs'; +import { deprecateNestedImport } from '../../deprecate-imports'; -export default class PostShorthandRouteHandler extends BaseShorthandRouteHandler { - - /* - Push a new model of type *camelizedModelName* to the db. - - For example, this will push a 'user': - this.post('/contacts', 'user'); - */ - - handleStringShorthand(request, modelClass) { - let modelName = this.shorthand; - let camelizedModelName = camelize(modelName); - assert( - modelClass, - `The route handler for ${request.url} is trying to access the ${camelizedModelName} model, but that model doesn't exist. Create it using 'ember g mirage-model ${modelName}'.` +/** + @class DeprecatedPostShorthandRouteHandler + @hide + */ +export default class DeprecatedPostShorthandRouteHandler extends _routeHandlersShorthandsPost { + constructor(...args) { + deprecateNestedImport( + `Importing 'PostShorthandRouteHandler' from 'ember-cli-mirage/route-handlers/shorthands/post' is deprecated. ` + + `This wasn't intended to be a public API. If you absolute know what you are doing, ` + + `install the \`miragejs\` package and use \`import { _routeHandlersShorthandsPost } from 'miragejs';\` instead.` ); - let attrs = this._getAttrsForRequest(request, modelClass.camelizedModelName); - return modelClass.create(attrs); + super(...args); } - } diff --git a/addon/route-handlers/shorthands/put.js b/addon/route-handlers/shorthands/put.js index ea0084fd0..d0e1399d5 100644 --- a/addon/route-handlers/shorthands/put.js +++ b/addon/route-handlers/shorthands/put.js @@ -1,27 +1,18 @@ -import assert from 'ember-cli-mirage/assert'; -import BaseShorthandRouteHandler from './base'; -import { camelize } from 'ember-cli-mirage/utils/inflector'; +import { _routeHandlersShorthandsPut } from 'miragejs'; +import { deprecateNestedImport } from '../../deprecate-imports'; -export default class PutShorthandRouteHandler extends BaseShorthandRouteHandler { - - /* - Update an object from the db, specifying the type. - - this.put('/contacts/:id', 'user'); - */ - handleStringShorthand(request, modelClass) { - let modelName = this.shorthand; - let camelizedModelName = camelize(modelName); - - assert( - modelClass, - `The route handler for ${request.url} is trying to access the ${camelizedModelName} model, but that model doesn't exist. Create it using 'ember g mirage-model ${modelName}'.` +/** + @class DeprecatedPutShorthandRouteHandler + @hide + */ +export default class DeprecatedPutShorthandRouteHandler extends _routeHandlersShorthandsPut { + constructor(...args) { + deprecateNestedImport( + `Importing 'PutShorthandRouteHandler' from 'ember-cli-mirage/route-handlers/shorthands/put' is deprecated. ` + + `This wasn't intended to be a public API. If you absolute know what you are doing, ` + + `install the \`miragejs\` package and use \`import { _routeHandlersShorthandsPut } from 'miragejs';\` instead.` ); - let id = this._getIdForRequest(request); - let attrs = this._getAttrsForRequest(request, modelClass.camelizedModelName); - - return modelClass.find(id).update(attrs); + super(...args); } - } diff --git a/addon/serializer-registry.js b/addon/serializer-registry.js index f6ff4227e..4d534f342 100644 --- a/addon/serializer-registry.js +++ b/addon/serializer-registry.js @@ -1,86 +1,18 @@ -import Model from 'ember-cli-mirage/orm/model'; -import Collection from 'ember-cli-mirage/orm/collection'; -import Serializer from 'ember-cli-mirage/serializer'; -import JsonApiSerializer from 'ember-cli-mirage/serializers/json-api-serializer'; -import { pluralize, camelize } from './utils/inflector'; -import assert from './assert'; - -import _assign from 'lodash/assign'; - -export default class SerializerRegistry { - - constructor(schema, serializerMap = {}) { - this.schema = schema; - this._serializerMap = serializerMap; - } - - normalize(payload, modelName) { - return this.serializerFor(modelName).normalize(payload); - } - - serialize(response, request) { - this.request = request; - - if (this._isModelOrCollection(response)) { - let serializer = this.serializerFor(response.modelName); - - return serializer.serialize(response, request); - } else if (Array.isArray(response) && response.filter(this._isCollection).length) { - return response.reduce((json, collection) => { - let serializer = this.serializerFor(collection.modelName); - - if (serializer.embed) { - json[pluralize(collection.modelName)] = serializer.serialize(collection, request); - } else { - json = _assign(json, serializer.serialize(collection, request)); - } - - return json; - }, {}); - - } else { - return response; - } - } - - serializerFor(type, { explicit = false } = {}) { - let SerializerForResponse = this._serializerMap && (this._serializerMap[camelize(type)]); - - if (explicit) { - assert(!!SerializerForResponse, `You passed in ${type} as an explicit serializer type but that serializer doesn't exist. Try running \`ember g mirage-serializer ${type}\`.`); - } else { - SerializerForResponse = SerializerForResponse || this._serializerMap.application || Serializer; - - assert( - !SerializerForResponse - || (SerializerForResponse.prototype.embed) - || (SerializerForResponse.prototype.root) - || (new SerializerForResponse() instanceof JsonApiSerializer), - 'You cannot have a serializer that sideloads (embed: false) and disables the root (root: false).' - ); - } - - return new SerializerForResponse(this, type, this.request); - } - - _isModel(object) { - return object instanceof Model; - } - - _isCollection(object) { - return object instanceof Collection; - } - - _isModelOrCollection(object) { - return this._isModel(object) || this._isCollection(object); - } - - registerSerializers(newSerializerMaps) { - let currentSerializerMap = this._serializerMap || {}; - this._serializerMap = _assign( - currentSerializerMap, - newSerializerMaps +import { _SerializerRegistry } from 'miragejs'; +import { deprecateNestedImport } from './deprecate-imports'; + +/** + @class DeprecatedSerializerRegistry + @hide + */ +export default class DeprecatedSerializerRegistry extends _SerializerRegistry { + constructor(...args) { + deprecateNestedImport( + `Importing 'SerializerRegistry' from 'ember-cli-mirage/serializer-registry' is deprecated. ` + + `This wasn't intended to be a public API. If you absolute know what you are doing, ` + + `install the \`miragejs\` package and use \`import { _SerializerRegistry } from 'miragejs';\` instead.` ); - } + super(...args); + } } diff --git a/addon/serializer.js b/addon/serializer.js index 9a296438d..937b58c2e 100644 --- a/addon/serializer.js +++ b/addon/serializer.js @@ -1,446 +1,17 @@ -import Model from './orm/model'; -import Collection from './orm/collection'; -import extend from './utils/extend'; -import { singularize, pluralize, camelize } from './utils/inflector'; - -import _isFunction from 'lodash/isFunction'; -import _isArray from 'lodash/isArray'; -import _isEmpty from 'lodash/isEmpty'; -import _includes from 'lodash/includes'; -import _assign from 'lodash/assign'; -import _get from 'lodash/get'; -import _ from 'lodash'; - -class Serializer { - - constructor(registry, type, request) { - this.registry = registry; - this.type = type; - this.request = request; - } - - /** - * Override this method to implement your own custom - * serialize function. `primaryResource` is whatever was returned - * from your route handler, and request is the Pretender - * request object. Returns a plain JavaScript object or - * array, which Mirage uses as the response data to your - * Ember app’s XHR request. You can also override this method, - * call super, and manipulate the data before Mirage responds - * with it. This is a great place to add metadata, or for - * one-off operations that don’t fit neatly into any of - * Mirage’s other abstractions. - * @method serialize - * @param response - * @param request - * @public - */ - serialize(primaryResource /* , request */) { - return this.buildPayload(primaryResource); - } - - buildPayload(primaryResource, toInclude, didSerialize, json) { - if (!primaryResource && _isEmpty(toInclude)) { - return json; - - } else if (primaryResource) { - let [resourceHash, newIncludes] = this.getHashForPrimaryResource(primaryResource); - let newDidSerialize = (this.isCollection(primaryResource) ? primaryResource.models : [primaryResource]); - - return this.buildPayload(undefined, newIncludes, newDidSerialize, resourceHash); - - } else { - let nextIncludedResource = toInclude.shift(); - let [resourceHash, newIncludes] = this.getHashForIncludedResource(nextIncludedResource); - - let newToInclude = newIncludes - .filter((resource) => { - return !_includes(didSerialize.map((m) => m.toString()), resource.toString()); - }) - .concat(toInclude); - let newDidSerialize = (this.isCollection(nextIncludedResource) ? nextIncludedResource.models : [nextIncludedResource]) - .concat(didSerialize); - let newJson = this.mergePayloads(json, resourceHash); - - return this.buildPayload(undefined, newToInclude, newDidSerialize, newJson); - } - } - - getHashForPrimaryResource(resource) { - let [hash, addToIncludes] = this.getHashForResource(resource); - let hashWithRoot; - - if (this.root) { - let serializer = this.serializerFor(resource.modelName); - let rootKey = serializer.keyForResource(resource); - hashWithRoot = { [rootKey]: hash }; - } else { - hashWithRoot = hash; - } - - return [hashWithRoot, addToIncludes]; - } - - getHashForIncludedResource(resource) { - let serializer = this.serializerFor(resource.modelName); - let [hash, addToIncludes] = serializer.getHashForResource(resource); - - // Included resources always have a root, and are always pushed to an array. - let rootKey = serializer.keyForRelationship(resource.modelName); - let hashWithRoot = _isArray(hash) ? { [rootKey]: hash } : { [rootKey]: [hash] }; - - return [hashWithRoot, addToIncludes]; - } - - getHashForResource(resource, removeForeignKeys = false, didSerialize = {}, lookupSerializer = false) { - let hash; - let serializer = lookupSerializer ? this.serializerFor(resource.modelName) : this; // this is used for embedded responses - - if (this.isModel(resource)) { - hash = serializer._hashForModel(resource, removeForeignKeys, didSerialize); - } else { - hash = resource.models.map((m) => serializer._hashForModel(m, removeForeignKeys, didSerialize)); - } - - if (this.embed) { - return [hash]; - - } else { - let addToIncludes = _(serializer.getKeysForIncluded()) - .map((key) => { - if (this.isCollection(resource)) { - return resource.models.map((m) => m[key]); - } else { - return resource[key]; - } - }) - .flatten() - .compact() - .uniqBy(m => m.toString()) - .value(); - - return [hash, addToIncludes]; - } - } - - /* - Merges new resource hash into json. If json already has root key, - pushes value of resourceHash onto that key. - - For example, - - json = { - post: { id: 1, title: 'Lorem Ipsum', comment_ids: [1, 3] }, - comments: [ - { id: 1, text: 'foo' } - ] - }; - - resourceHash = { - comments: [ - { id: 2, text: 'bar' } - ] - }; - - would yield - - { - post: { id: 1, title: 'Lorem Ipsum', comment_ids: [1, 3] }, - comments: [ - { id: 1, text: 'foo' }, - { id: 2, text: 'bar' } - ] - }; - - */ - mergePayloads(json, resourceHash) { - let newJson; - let [resourceHashKey] = Object.keys(resourceHash); - - if (json[resourceHashKey]) { - newJson = json; - newJson[resourceHashKey] = json[resourceHashKey].concat(resourceHash[resourceHashKey]); - } else { - newJson = _assign(json, resourceHash); - } - - return newJson; - } - - keyForResource(resource) { - let { modelName } = resource; - return this.isModel(resource) ? this.keyForModel(modelName) : this.keyForCollection(modelName); - } - - /** - * Used to define a custom key when serializing a - * primary model of modelName `modelName`. - * @method keyForModel - * @param modelName - * @public - */ - keyForModel(modelName) { - return camelize(modelName); - } - - /** - * Used to customize the key when serializing a primary - * collection. By default this pluralizes the return - * value of `keyForModel`. - * @method keyForCollection - * @param modelName - * @public - */ - keyForCollection(modelName) { - return pluralize(this.keyForModel(modelName)); - } - - _hashForModel(model, removeForeignKeys, didSerialize = {}) { - let attrs = this._attrsForModel(model); - - if (removeForeignKeys) { - model.fks.forEach((fk) => { - delete attrs[fk]; - }); - } - - if (this.embed) { - let newDidSerialize = _assign({}, didSerialize); - newDidSerialize[model.modelName] = newDidSerialize[model.modelName] || {}; - newDidSerialize[model.modelName][model.id] = true; - - this.getKeysForIncluded().forEach((key) => { - let associatedResource = model[key]; - if (!_get(newDidSerialize, `${associatedResource.modelName}.${associatedResource.id}`)) { - let [ associatedResourceHash ] = this.getHashForResource(associatedResource, true, newDidSerialize, true); - let formattedKey = this.keyForEmbeddedRelationship(key); - attrs[formattedKey] = associatedResourceHash; - - if (this.isModel(associatedResource)) { - let fk = `${camelize(key)}Id`; - delete attrs[fk]; - } - } - }); - - return attrs; - } else { - return this._maybeAddAssociationIds(model, attrs); - } - } - - /** - * @method _attrsForModel - * @param model - * @private - */ - _attrsForModel(model, removeForeignKeys = false) { - let attrs = {}; - - if (this.attrs) { - attrs = this.attrs.reduce((memo, attr) => { - memo[attr] = model[attr]; - return memo; - }, {}); - } else { - attrs = _assign(attrs, model.attrs); - } - - if (removeForeignKeys) { - model.fks.forEach((key) => delete attrs[key]); - } - - return this._formatAttributeKeys(attrs); - } - - /** - * @method _maybeAddAssociationIds - * @param model - * @param attrs - * @private - */ - _maybeAddAssociationIds(model, attrs) { - let newHash = _assign({}, attrs); - - if (this.serializeIds === 'always') { - model.associationKeys.forEach((key) => { - let association = model[key]; - if (this.isCollection(association)) { - let formattedKey = this.keyForRelationshipIds(key); - newHash[formattedKey] = model[key].models.map((m) => m.id); - } - }); - } else if (this.serializeIds === 'included') { - this.getKeysForIncluded().forEach((key) => { - let association = model[key]; - if (this.isCollection(association)) { - let formattedKey = this.keyForRelationshipIds(key); - newHash[formattedKey] = model[key].models.map((m) => m.id); - } - }); - } - - return newHash; - } - - /** - * Used to customize how a model’s attribute is - * formatted in your JSON payload. - * @method keyForAttribute - * @param attr - * @public - */ - keyForAttribute(attr) { - return attr; - } - - /** - * Use this hook to format the key for collections - * related to this model. - * - * For example, if you're serializing an author that - * side loads many `blogPosts`, you would get `blogPost` - * as an argument, and whatever you return would - * end up as the collection key in your JSON: - * - * keyForRelationship(type) { - * return dasherize(type); - * } - * - * { - * author: {...}, - * 'blog-posts': [...] - * } - * @method keyForRelationship - * @param modelName - * @public - */ - keyForRelationship(modelName) { - return camelize(pluralize(modelName)); - } - - /** - * @method keyForEmbeddedRelationship - * @param attributeName - * @public - */ - keyForEmbeddedRelationship(attributeName) { - return camelize(attributeName); - } - - /** - * Use this hook to format the key for relationship ids - * in this model's JSON representation. - * - * For example, if you're serializing an author that - * side loads many `blogPosts`, you would get `blogPost` - * as an argument, and whatever you return would - * end up as part of the `author` JSON: - * - * keyForRelationshipIds(type) { - * return dasherize(type) + '-ids'; - * } - * - * { - * author: { - * ..., - * 'blog-post-ids': [1, 2, 3] - * }, - * 'blog-posts': [...] - * } - * @method keyForRelationshipIds - * @param modelName - * @public - */ - keyForRelationshipIds(relationshipName) { - return `${singularize(camelize(relationshipName))}Ids`; - } - - /** - * This method is used by the POST and PUT shorthands. These shorthands - * expect a valid JSON:API document as part of the request, so that - * they know how to create or update the appropriate resouce. The normalize - * method allows you to transform your request body into a JSON:API - * document, which lets you take advantage of the shorthands when you - * otherwise may not be able to. - * - * Note that this method is a noop if you’re using JSON:API already, - * since request payloads sent along with POST and PUT requests will - * already be in the correct format. - * @method normalize - * @param json - * @public - */ - normalize(json) { - return json; - } - - /** - * @method isModel - * @param object - * @return {Boolean} - * @public - */ - isModel(object) { - return object instanceof Model; - } - - /** - * @method isCollection - * @param object - * @return {Boolean} - * @public - */ - isCollection(object) { - return object instanceof Collection; - } - - /** - * @method isModelOrCollection - * @param object - * @return {Boolean} - * @public - */ - isModelOrCollection(object) { - return this.isModel(object) || this.isCollection(object); - } - - /** - * @method serializerFor - * @param type - * @public - */ - serializerFor(type) { - return this.registry.serializerFor(type); - } - - getKeysForIncluded() { - return _isFunction(this.include) ? this.include(this.request) : this.include; - } - - /** - * @method _formatAttributeKeys - * @param attrs - * @private - */ - _formatAttributeKeys(attrs) { - let formattedAttrs = {}; - - for (let key in attrs) { - let formattedKey = this.keyForAttribute(key); - formattedAttrs[formattedKey] = attrs[key]; - } - - return formattedAttrs; +import { Serializer } from 'miragejs'; +import { deprecateNestedImport } from './deprecate-imports'; + +/** + @class DeprecatedSerializer + @hide + */ +export default class DeprecatedSerializer extends Serializer { + constructor(...args) { + deprecateNestedImport( + `Importing 'Serializer' from 'ember-cli-mirage/serializer' is deprecated. ` + + `Install the \`miragejs\` package and use \`import { Serializer } from 'miragejs';\` instead.` + ); + + super(...args); } } - -// Defaults -Serializer.prototype.include = []; -Serializer.prototype.root = true; -Serializer.prototype.embed = false; -Serializer.prototype.serializeIds = 'included'; // can be 'included', 'always', or 'never' - -Serializer.extend = extend; - -export default Serializer; diff --git a/addon/serializers/active-model-serializer.js b/addon/serializers/active-model-serializer.js index b1476634d..290b6ea19 100644 --- a/addon/serializers/active-model-serializer.js +++ b/addon/serializers/active-model-serializer.js @@ -1,48 +1,17 @@ -import Serializer from '../serializer'; -import { underscore, pluralize, dasherize, singularize } from '../utils/inflector'; - -export default Serializer.extend({ - - keyForModel(type) { - return underscore(type); - }, - - keyForAttribute(attr) { - return underscore(attr); - }, - - keyForRelationship(type) { - return pluralize(underscore(type)); - }, - - keyForEmbeddedRelationship(attributeName) { - return underscore(attributeName); - }, - - keyForRelationshipIds(type) { - return `${underscore(singularize(type))}_ids`; - }, - - normalize(payload) { - let type = Object.keys(payload)[0]; - let attrs = payload[type]; - - let jsonApiPayload = { - data: { - type: pluralize(type), - attributes: {} - } - }; - if (attrs.id) { - jsonApiPayload.data.id = attrs.id; - } - Object.keys(attrs).forEach((key) => { - if (key !== 'id') { - jsonApiPayload.data.attributes[dasherize(key)] = attrs[key]; - } - }); - - return jsonApiPayload; +import { ActiveModelSerializer } from 'miragejs'; +import { deprecateNestedImport } from '../deprecate-imports'; + +/** + @class DeprecatedActiveModelSerializer + @hide + */ +export default class DeprecatedActiveModelSerializer extends ActiveModelSerializer { + constructor(...args) { + deprecateNestedImport( + "Importing 'ActiveModelSerializer' from 'ember-cli-mirage/serializers/active-model-serializer' is deprecated. " + + "Add the `miragejs` package to devDependencies and use `import { ActiveModelSerializer } from 'miragejs';` instead." + ); + + super(...args); } - -}); +} diff --git a/addon/serializers/ember-data-serializer.js b/addon/serializers/ember-data-serializer.js new file mode 100644 index 000000000..ccf7756c3 --- /dev/null +++ b/addon/serializers/ember-data-serializer.js @@ -0,0 +1,309 @@ +import { + RestSerializer, + _utilsInflectorCamelize as camelize, + _utilsInflectorDasherize as dasherize, +} from 'miragejs'; +import { isFunction } from 'lodash-es'; +import { get } from '@ember/object'; + +/** + * This serializer does not use following mirage properties to control how things are serialized + * + * attrs - see `serialize` on the transform property + * embed - see `serialize` on the transform property + * serializeIds - see serialize on the transform property + * + * The above configuration was applied to every property on the serializer, whereas the transforms allows you + * to specify a value for each property or relation. + * + * This serializer uses a property `transforms` that follows the Ember Data serializer format of `attrs` to specify the + * serialization (`attrs` is already in use by mirageJs). + * + * The startMirage has been modified to also generate serializers from the Ember Data serializers supporting + * the key and the serialize/deserialize properties with the value of (true/ids/records). If a serializer is + * already present in the mirage directory, the transforms will be added to it. If that serializer is not + * a serializer of this type, there will be no effect. Ensure that your serializers and/or the application + * serializer in the mirage directory is a type of this serializer + * + * @class EmberDataSerializer + * @constructor + * @public + * + */ +let EmberDataSerializer = RestSerializer.extend({ + /** + * The property name for the primary key for mirage and ember data is normally `id`. This allows you + * to specify what that property name should be in the JSON. + */ + primaryKey: 'id', + + /** + * Transforms follow the format of ember data serializer attrs as follows + * + * { + * property: { // property would be the name of the property in the mirage store + * key: 'externalKey', // externalKey would be the name in the JSON + * serialize: 'ids', // how should this property be serialized and deserialized + * deserialize: 'ids' // the default is 'ids' that is the id of the releation + * // or 'records', that is, embed the full record instead of the id + * // or false, do not serialize or deserialize as applied + * } + * } + * + * These transforms will be created from the attrs on the corresponding serializer in ember data much like + * the models for mirage are created from the models in in ember date. If the transforms key is specified, it + * will overlay the definition created from the serializer key for key. That is you could override some + * of the transform definition. + */ + transforms: undefined, + // resolved transforms + _transforms: undefined, + + // These are the defaults + // include: [] + + keyForId() { + return this.primaryKey; + }, + + getKeysForIncluded() { + return isFunction(this.include) + ? this.include(this.request, this.primaryResource) + : this.include; + }, + + getTransforms() { + return this.transforms || {}; + }, + + getResolvedTransforms() { + if (!this._resolvedTransforms) { + this._resolvedTransforms = { + serialize: {}, + normalize: {}, + }; + } + + return this._resolvedTransforms; + }, + + getTransformForSerialize(key) { + let resolvedTransforms = this.getResolvedTransforms(); + let transforms = this.getTransforms(); + + if (!resolvedTransforms.serialize[key]) { + let transform = + typeof transforms[key] === 'string' + ? { key: transforms[key] } + : Object.assign({}, transforms[key]); + + resolvedTransforms.serialize[key] = Object.assign( + { key: key, serialize: 'ids', deserialize: 'ids' }, + transform + ); + } + + return resolvedTransforms.serialize[key]; + }, + + getTransformForNormalize(key) { + let resolvedTransforms = this.getResolvedTransforms(); + + if (!resolvedTransforms.normalize[key]) { + let transforms = this.getTransforms(); + let foundKey; + let foundTransform = Object.keys(transforms).find((item) => { + foundKey = item; + return transforms[item].key === key; + }); + let transform = foundTransform + ? Object.assign({}, transforms[foundKey], { key: foundKey }) + : { key: key, serialize: 'ids', deserialize: 'ids' }; + + resolvedTransforms.normalize[key] = transform; + } + + return resolvedTransforms.normalize[key]; + }, + + /** + * + * @param model + * @param removeForeignKeys + * @param didSerialize + * @returns {*} + * @private + */ + _hashForModel(model, removeForeignKeys, didSerialize = {}) { + let attrs = this._attrsForModel(model); + + let newDidSerialize = Object.assign({}, didSerialize); + newDidSerialize[model.modelName] = newDidSerialize[model.modelName] || {}; + newDidSerialize[model.modelName][model.id] = true; + + model.associationKeys.forEach((key) => { + let transform = this.getTransformForSerialize(key); + + if (transform.serialize) { + let associatedResource = model[key]; + + let serializeOption = transform.serialize; + + if ( + associatedResource && + get( + newDidSerialize, + `${associatedResource.modelName}.${associatedResource.id}` + ) + ) { + // force it to IDS if we already have serialized it to prevent recursion + // TODO: However is the end system wants records, we need to send records, so this really should be do records, dont resurse + serializeOption = 'ids'; + } + + if (serializeOption === 'records') { + let [associatedResourceHash] = this.getHashForResource( + associatedResource, + false, + newDidSerialize, + true + ); + let formattedKey = + this._keyForProperty(key) || this.isCollection(associatedResource) + ? this.keyForRelationship(key) + : this.keyForEmbeddedRelationship(key); + attrs[formattedKey] = associatedResourceHash; + } else { + let formattedKey = + this._keyForProperty(key) || this.keyForRelationshipIds(key); + + if (this.isCollection(associatedResource)) { + attrs[formattedKey] = + model[`${this._container.inflector.singularize(key)}Ids`]; + } else { + attrs[formattedKey] = + model[`${this._container.inflector.singularize(key)}Id`]; + } + } + } + }); + + return attrs; + }, + + _keyForProperty(attr) { + let transform = this.getTransformForSerialize(attr); + + return transform.key; + }, + + keyForAttribute(attr) { + if (attr === 'id') { + return this.keyForId(); + } + + return ( + this._keyForProperty(attr) || + RestSerializer.prototype.keyForAttribute.apply(this, arguments) + ); + }, + + keyForRelationship(type) { + return ( + this._keyForProperty(type) || + RestSerializer.prototype.keyForRelationship.apply(this, arguments) + ); + }, + + keyForEmbeddedRelationship(attributeName) { + return ( + this._keyForProperty(attributeName) || + RestSerializer.prototype.keyForEmbeddedRelationship.apply(this, arguments) + ); + }, + + keyForRelationshipIds(type) { + return ( + this._keyForProperty(type) || + RestSerializer.prototype.keyForRelationshipIds.apply(this, arguments) + ); + }, + + keyForForeignKey(relationshipName) { + return ( + this._keyForProperty(relationshipName) || + RestSerializer.prototype.keyForForeignKey.apply(this, arguments) + ); + }, + + normalize(payload) { + // was it not wrapped when serialized? + if (this.root === false) { + let p = {}; + p[this.type] = payload; + payload = p; + } + + let type = Object.keys(payload)[0]; + let attrs = payload[type]; + let modelName = camelize(type); + let modelClass = this.schema.modelClassFor(modelName); + let { belongsToAssociations, hasManyAssociations } = modelClass; + let belongsToKeys = Object.keys(belongsToAssociations); + let hasManyKeys = Object.keys(hasManyAssociations); + + let jsonApiPayload = { + data: { + type: this._container.inflector.pluralize(type), + attributes: {}, + }, + }; + + if (attrs[this.primaryKey]) { + jsonApiPayload.data.id = attrs[this.primaryKey]; + } + + let relationships = {}; + + Object.keys(attrs).forEach((attrKey) => { + if (attrKey !== this.primaryKey) { + let transform = this.getTransformForNormalize(attrKey); + let key = transform.key || attrKey; + if (this.normalizeIds) { + if (belongsToKeys.includes(key)) { + let association = belongsToAssociations[key]; + let associationModel = association.modelName; + relationships[dasherize(key)] = { + data: { + type: associationModel, + id: attrs[attrKey], + }, + }; + } else if (hasManyKeys.includes(key)) { + let association = hasManyAssociations[key]; + let associationModel = association.modelName; + let data = attrs[attrKey].map((id) => { + return { + type: associationModel, + id, + }; + }); + relationships[dasherize(key)] = { data }; + } else { + jsonApiPayload.data.attributes[dasherize(key)] = attrs[attrKey]; + } + } else { + jsonApiPayload.data.attributes[dasherize(key)] = attrs[attrKey]; + } + } + }); + + if (Object.keys(relationships).length) { + jsonApiPayload.data.relationships = relationships; + } + + return jsonApiPayload; + }, +}); + +export default EmberDataSerializer; diff --git a/addon/serializers/json-api-serializer.js b/addon/serializers/json-api-serializer.js index 75f6f9ee3..06d6ace46 100644 --- a/addon/serializers/json-api-serializer.js +++ b/addon/serializers/json-api-serializer.js @@ -1,196 +1,17 @@ -import Serializer from '../serializer'; -import { dasherize, pluralize, camelize } from '../utils/inflector'; - -import _get from 'lodash/get'; -import _ from 'lodash'; - -export default Serializer.extend({ - - keyForModel(modelName) { - return dasherize(modelName); - }, - - keyForCollection(modelName) { - return dasherize(modelName); - }, - - keyForAttribute(attr) { - return dasherize(attr); - }, - - keyForRelationship(key) { - return dasherize(key); - }, - - getHashForPrimaryResource(resource) { - let resourceHash = this.getHashForResource(resource); - let hashWithRoot = { data: resourceHash }; - let addToIncludes = this.getAddToIncludesForResource(resource); - - return [ hashWithRoot, addToIncludes ]; - }, - - getHashForIncludedResource(resource) { - let serializer = this.serializerFor(resource.modelName); - let hash = serializer.getHashForResource(resource); - let hashWithRoot = { included: (this.isModel(resource) ? [ hash ] : hash) }; - let addToIncludes = []; - - if (!this.hasQueryParamIncludes()) { - addToIncludes = this.getAddToIncludesForResource(resource); - } - - return [ hashWithRoot, addToIncludes ]; - }, - - getHashForResource(resource) { - let hash; - - if (this.isModel(resource)) { - hash = this._getResourceObjectForModel(resource); - } else { - hash = resource.models.map((m) => this._getResourceObjectForModel(m)); - } - - return hash; - }, - - /* - Returns a flat unique list of resources that need to be added to includes - */ - getAddToIncludesForResource(resource) { - let relationshipPaths; - - if (_get(this, 'request.queryParams.include')) { - relationshipPaths = this.request.queryParams.include.split(','); - } else { - let serializer = this.serializerFor(resource.modelName); - relationshipPaths = serializer.getKeysForIncluded(); - } - - return this.getAddToIncludesForResourceAndPaths(resource, relationshipPaths); - }, - - getAddToIncludesForResourceAndPaths(resource, relationshipPaths) { - let includes = []; - - relationshipPaths.forEach((path) => { - let relationshipNames = path.split('.'); - let newIncludes = this.getIncludesForResourceAndPath(resource, ...relationshipNames); - includes.push(newIncludes); - }); - - return _(includes) - .flatten() - .compact() - .uniqBy(m => m.toString()) - .value(); - }, - - getIncludesForResourceAndPath(resource, ...names) { - let nameForCurrentResource = camelize(names.shift()); - let includes = []; - let modelsToAdd = []; - - if (this.isModel(resource)) { - let relationship = resource[nameForCurrentResource]; - - if (this.isModel(relationship)) { - modelsToAdd = [ relationship ]; - } else if (this.isCollection(relationship)) { - modelsToAdd = relationship.models; - } - - } else { - resource.models.forEach((model) => { - let relationship = model[nameForCurrentResource]; - - if (this.isModel(relationship)) { - modelsToAdd.push(relationship); - } else if (this.isCollection(relationship)) { - modelsToAdd = modelsToAdd.concat(relationship.models); - } - }); - } - - includes = includes.concat(modelsToAdd); - - if (names.length) { - modelsToAdd.forEach((model) => { - includes = includes.concat(this.getIncludesForResourceAndPath(model, ...names)); - }); - } - - return includes; - }, - - _getResourceObjectForModel(model) { - let attrs = this._attrsForModel(model, true); - delete attrs.id; - - let hash = { - type: this.typeKeyForModel(model), - id: model.id, - attributes: attrs - }; - - model.associationKeys.forEach((key) => { - let relationship = model[key]; - let relationshipKey = this.keyForRelationship(key); - let relationshipHash; - hash.relationships = hash.relationships || {}; - - if (this.hasLinksForRelationship(model, key)) { - let serializer = this.serializerFor(model.modelName); - let links = serializer.links(model); - relationshipHash = { links: links[key] }; - - } else { - let data = null; - - if (this.isModel(relationship)) { - data = { - type: this.typeKeyForModel(relationship), - id: relationship.id - }; - } else if (this.isCollection(relationship)) { - data = relationship.models.map((model) => { - return { - type: this.typeKeyForModel(model), - id: model.id - }; - }); - } - - relationshipHash = { data }; - } - - hash.relationships[relationshipKey] = relationshipHash; - }); - - return hash; - }, - - hasLinksForRelationship(model, relationshipKey) { - let serializer = this.serializerFor(model.modelName); - let links; - if (serializer.links) { - links = serializer.links(model); - - return links[relationshipKey] != null; - } - }, - - getQueryParamIncludes() { - return (_get(this, 'request.queryParams.include')); - }, - - hasQueryParamIncludes() { - return !!this.getQueryParamIncludes(); - }, - - typeKeyForModel(model) { - return dasherize(pluralize(model.modelName)); +import { JSONAPISerializer } from 'miragejs'; +import { deprecateNestedImport } from '../deprecate-imports'; + +/** + @class DeprecatedJSONAPISerializer + @hide + */ +export default class DeprecatedJSONAPISerializer extends JSONAPISerializer { + constructor(...args) { + deprecateNestedImport( + "Importing 'JSONAPISerializer' from 'ember-cli-mirage/serializers/json-api-serializer' is deprecated. " + + "Add the `miragejs` package to devDependencies and use `import { JSONAPISerializer } from 'miragejs';` instead." + ); + + super(...args); } - -}); +} diff --git a/addon/serializers/rest-serializer.js b/addon/serializers/rest-serializer.js index 9b7361e9d..d8ed4eafd 100644 --- a/addon/serializers/rest-serializer.js +++ b/addon/serializers/rest-serializer.js @@ -1,25 +1,17 @@ -import ActiveModelSerializer from './active-model-serializer'; -import { camelize, singularize, pluralize } from '../utils/inflector'; +import { RestSerializer } from 'miragejs'; +import { deprecateNestedImport } from '../deprecate-imports'; -export default ActiveModelSerializer.extend({ +/** + @class DeprecatedRestSerializer + @hide + */ +export default class DeprecatedRestSerializer extends RestSerializer { + constructor(...args) { + deprecateNestedImport( + "Importing 'RestSerializer' from 'ember-cli-mirage/serializers/rest-serializer' is deprecated. " + + "Add the `miragejs` package to devDependencies and use `import { RestSerializer } from 'miragejs';` instead." + ); - keyForModel(type) { - return camelize(type); - }, - - keyForAttribute(attr) { - return camelize(attr); - }, - - keyForRelationship(type) { - return camelize(pluralize(type)); - }, - - keyForEmbeddedRelationship(attributeName) { - return camelize(attributeName); - }, - - keyForRelationshipIds(type) { - return `${camelize(singularize(type))}Ids`; + super(...args); } -}); +} diff --git a/addon/server.js b/addon/server.js index 942a549a9..958e6af9e 100644 --- a/addon/server.js +++ b/addon/server.js @@ -1,662 +1,30 @@ -/* eslint no-console: 0 */ +import { Server } from 'miragejs'; +import { discoverEmberDataModels } from './ember-data'; +import { hasEmberData } from './utils/ember-data'; -import { pluralize, camelize } from './utils/inflector'; -import { toCollectionName } from 'ember-cli-mirage/utils/normalize-name'; -import Ember from 'ember'; -import isAssociation from 'ember-cli-mirage/utils/is-association'; -import Pretender from 'pretender'; -import Db from './db'; -import Schema from './orm/schema'; -import assert from './assert'; -import SerializerRegistry from './serializer-registry'; -import RouteHandler from './route-handler'; - -import _pick from 'lodash/pick'; -import _assign from 'lodash/assign'; -import _find from 'lodash/find'; -import _isPlainObject from 'lodash/isPlainObject'; -import _isInteger from 'lodash/isInteger'; - -const { RSVP: { Promise } } = Ember; +export { defaultPassthroughs } from 'miragejs'; /** - * Creates a new Pretender instance. - * - * @method createPretender - * @param {Server} server - * @return {Object} A new Pretender instance. - * @public - */ -function createPretender(server) { - return new Pretender(function() { - this.passthroughRequest = function(verb, path, request) { - if (server.shouldLog()) { - console.log(`Passthrough request: ${verb.toUpperCase()} ${request.url}`); - } - }; - - this.handledRequest = function(verb, path, request) { - if (server.shouldLog()) { - console.log(`Mirage: [${request.status}] ${verb.toUpperCase()} ${request.url}`); - let { responseText } = request; - let loggedResponse; - - try { - loggedResponse = JSON.parse(responseText); - } catch(e) { - loggedResponse = responseText; - } - - console.log(loggedResponse); - } - }; - - this.unhandledRequest = function(verb, path) { - path = decodeURI(path); - assert( - `Your Ember app tried to ${verb} '${path}', - but there was no route defined to handle this request. - Define a route that matches this path in your - mirage/config.js file. Did you forget to add your namespace?` + @hide +*/ +export default class EmberServer extends Server { + constructor(options) { + // Merge models from autogenerated Ember Data models with user defined models + if (hasEmberData && options.discoverEmberDataModels) { + options.models = Object.assign( + {}, + discoverEmberDataModels(), + options.models ); - }; - }); -} - -const defaultRouteOptions = { - coalesce: false, - timing: undefined -}; - -const defaultPassthroughs = [ - 'http://localhost:0/chromecheckurl', // mobile chrome - 'http://localhost:30820/socket.io' // electron -]; -export { defaultPassthroughs }; - -/** - * Determine if the object contains a valid option. - * - * @method isOption - * @param {Object} option An object with one option value pair. - * @return {Boolean} True if option is a valid option, false otherwise. - * @private - */ -function isOption(option) { - if (!option || typeof option !== 'object') { - return false; - } - - let allOptions = Object.keys(defaultRouteOptions); - let optionKeys = Object.keys(option); - for (let i = 0; i < optionKeys.length; i++) { - let key = optionKeys[i]; - if (allOptions.indexOf(key) > -1) { - return true; - } - } - return false; -} - -/** - * Extract arguments for a route. - * - * @method extractRouteArguments - * @param {Array} args Of the form [options], [object, code], [function, code] - * [shorthand, options], [shorthand, code, options] - * @return {Array} [handler (i.e. the function, object or shorthand), code, - * options]. - * @private - */ -function extractRouteArguments(args) { - let [ lastArg ] = args.splice(-1); - if (isOption(lastArg)) { - lastArg = _assign({}, defaultRouteOptions, lastArg); - } else { - args.push(lastArg); - lastArg = defaultRouteOptions; - } - let t = 2 - args.length; - while (t-- > 0) { - args.push(undefined); - } - args.push(lastArg); - return args; -} - -/** - * - * - * @class Server - * @public - */ -export default class Server { - - /** - * Build the new server object. - * - * @constructor - * @public - */ - constructor(options = {}) { - this.config(options); - } - - config(config = {}) { - let didOverrideConfig = (config.environment && (this.environment && (this.environment !== config.environment))); - assert(!didOverrideConfig, - 'You cannot modify Mirage\'s environment once the server is created'); - this.environment = config.environment || 'development'; - - this.options = config; - - this.timing = this.timing || config.timing || 400; - this.namespace = this.namespace || config.namespace || ''; - this.urlPrefix = this.urlPrefix || config.urlPrefix || ''; - - this._defineRouteHandlerHelpers(); - - this.db = this.db || new Db(); - if (this.schema) { - this.schema.registerModels(config.models); - this.serializerOrRegistry.registerSerializers(config.serializers || {}); - } else { - this.schema = new Schema(this.db, config.models); - this.serializerOrRegistry = new SerializerRegistry(this.schema, config.serializers); - } - - let hasFactories = this._hasModulesOfType(config, 'factories'); - let hasDefaultScenario = config.scenarios && config.scenarios.hasOwnProperty('default'); - - this.pretender = this.pretender || createPretender(this); - - if (config.baseConfig) { - this.loadConfig(config.baseConfig); - } - - if (this.isTest()) { - if (config.testConfig) { - this.loadConfig(config.testConfig); - } - - window.server = this; // TODO: Better way to inject server into test env - } - - if (this.isTest() && hasFactories) { - this.loadFactories(config.factories); - } else if (!this.isTest() && hasDefaultScenario) { - this.loadFactories(config.factories); - config.scenarios.default(this); - } else { - this.loadFixtures(); - } - - if (config.useDefaultPassthroughs) { - this._configureDefaultPassthroughs(); - } - } - - /** - * Determines if the current environment is the testing environment. - * - * @method isTest - * @return {Boolean} True if the environment is 'test', false otherwise. - * @public - */ - isTest() { - return this.environment === 'test'; - } - - /** - * Determines if the server should log. - * - * @method shouldLog - * @return The value of this.logging if defined, or false if in the testing environment, - * true otherwise. - * @public - */ - shouldLog() { - return typeof this.logging !== 'undefined' ? this.logging : !this.isTest(); - } - - /** - * Load the configuration given, setting timing to 0 if in the test - * environment. - * - * @method loadConfig - * @param {Object} config The configuration to load. - * @public - */ - loadConfig(config) { - config.call(this); - this.timing = this.isTest() ? 0 : (this.timing || 0); - } - - /** - * Whitelist requests to the specified paths and allow them to pass through - * your Mirage server to the actual network layer. - * - * @method passthrough - * @param {String} [...paths] Any numer of paths to whitelist - * @param {Array} options Unused - * @public - */ - passthrough(...paths) { - let verbs = ['get', 'post', 'put', 'delete', 'patch']; - let lastArg = paths[paths.length - 1]; - - if (paths.length === 0) { - // paths = ['http://localhost:7357']; - paths = ['/**', '/']; - } else if (Array.isArray(lastArg)) { - verbs = paths.pop(); - } - - verbs.forEach((verb) => { - paths.forEach((path) => { - let fullPath = this._getFullPath(path); - this.pretender[verb](fullPath, this.pretender.passthrough); - }); - }); - } - - /** - * Load the all or only the specified fixtures into Mirage's database. - * - * @method loadFixtures - * @param {String} [...args] The name of the fixture to load. - * @public - */ - loadFixtures(...args) { - let { fixtures } = this.options; - if (args.length) { - let camelizedArgs = args.map(camelize); - fixtures = _pick(fixtures, ...camelizedArgs); - } - - this.db.loadData(fixtures); - } - - /* - Factory methods - */ - - /** - * Load factories into Mirage's database. - * - * @method loadFactories - * @param {Object} factoryMap - * @public - */ - loadFactories(factoryMap = {}) { - // Store a reference to the factories - let currentFactoryMap = this._factoryMap || {}; - this._factoryMap = _assign(currentFactoryMap, factoryMap); - - // Create a collection for each factory - Object.keys(factoryMap).forEach((type) => { - let collectionName = toCollectionName(type); - this.db.createCollection(collectionName); - }); - } - - /** - * Get the factory for a given type. - * - * @method factoryFor - * @param {String} type - * @private - */ - factoryFor(type) { - let camelizedType = camelize(type); - - if (this._factoryMap && this._factoryMap[camelizedType]) { - return this._factoryMap[camelizedType]; - } - } - - build(type, ...traitsAndOverrides) { - let traits = traitsAndOverrides.filter((arg) => arg && typeof arg === 'string'); - let overrides = _find(traitsAndOverrides, (arg) => _isPlainObject(arg)); - let camelizedType = camelize(type); - - // Store sequence for factory type as instance variable - this.factorySequences = this.factorySequences || {}; - this.factorySequences[camelizedType] = this.factorySequences[camelizedType] + 1 || 0; - - let OriginalFactory = this.factoryFor(type); - if (OriginalFactory) { - OriginalFactory = OriginalFactory.extend({}); - let attrs = OriginalFactory.attrs || {}; - this._validateTraits(traits, OriginalFactory, type); - let mergedExtensions = this._mergeExtensions(attrs, traits, overrides); - this._mapAssociationsFromAttributes(type, attrs); - this._mapAssociationsFromAttributes(type, mergedExtensions); - - let Factory = OriginalFactory.extend(mergedExtensions); - let factory = new Factory(); - - let sequence = this.factorySequences[camelizedType]; - return factory.build(sequence); - } else { - return overrides; - } - } - - buildList(type, amount, ...traitsAndOverrides) { - assert(_isInteger(amount), `second argument has to be an integer, you passed: ${typeof amount}`); - - let list = []; - - for (let i = 0; i < amount; i++) { - list.push(this.build(type, ...traitsAndOverrides)); - } - - return list; - } - - create(type, ...options) { - // When there is a Model defined, we should return an instance - // of it instead of returning the bare attributes. - let traits = options.filter((arg) => arg && typeof arg === 'string'); - let overrides = _find(options, (arg) => _isPlainObject(arg)); - let collectionFromCreateList = _find(options, (arg) => arg && Array.isArray(arg)); - - let attrs = this.build(type, ...traits, overrides); - let modelOrRecord; - - if (this.schema && this.schema[toCollectionName(type)]) { - let modelClass = this.schema[toCollectionName(type)]; - - modelOrRecord = modelClass.create(attrs); - - } else { - let collection, collectionName; - - if (collectionFromCreateList) { - collection = collectionFromCreateList; - } else { - collectionName = this.schema ? toCollectionName(type) : pluralize(type); - collection = this.db[collectionName]; - } - - assert(collection, `You called server.create(${type}) but no model or factory was found. Try \`ember g mirage-model ${type}\`.`); - modelOrRecord = collection.insert(attrs); - } - - let OriginalFactory = this.factoryFor(type); - if (OriginalFactory) { - OriginalFactory.extractAfterCreateCallbacks({ traits }).forEach((afterCreate) => { - afterCreate(modelOrRecord, this); - }); - } - - return modelOrRecord; - } - - createList(type, amount, ...traitsAndOverrides) { - assert(_isInteger(amount), `second argument has to be an integer, you passed: ${typeof amount}`); - - let list = []; - let collectionName = this.schema ? toCollectionName(type) : pluralize(type); - let collection = this.db[collectionName]; - - for (let i = 0; i < amount; i++) { - list.push(this.create(type, ...traitsAndOverrides, collection)); } - return list; - } - - shutdown() { - this.pretender.shutdown(); - if (this.environment === 'test') { - window.server = undefined; - } - } - - resource(resourceName, { only, except } = {}) { - only = only || []; - except = except || []; - - if (only.length > 0 && except.length > 0) { - throw 'cannot use both :only and :except options'; - } - - let actionsMethodsAndsPathsMappings = { - index: { methods: ['get'], path: `/${resourceName}` }, - show: { methods: ['get'], path: `/${resourceName}/:id` }, - create: { methods: ['post'], path: `/${resourceName}` }, - update: { methods: ['put', 'patch'], path: `/${resourceName}/:id` }, - delete: { methods: ['del'], path: `/${resourceName}/:id` } - }; - - let allActions = Object.keys(actionsMethodsAndsPathsMappings); - let actions = only.length > 0 && only - || except.length > 0 && allActions.filter((action) => (except.indexOf(action) === -1)) - || allActions; - - actions.forEach((action) => { - let methodsWithPath = actionsMethodsAndsPathsMappings[action]; - - methodsWithPath.methods.forEach((method) => this[method](methodsWithPath.path)); - }); - } - - /** - * - * @private - */ - _defineRouteHandlerHelpers() { - [['get'], ['post'], ['put'], ['delete', 'del'], ['patch'], ['head']].forEach(([verb, alias]) => { - this[verb] = (path, ...args) => { - let [ rawHandler, customizedCode, options ] = extractRouteArguments(args); - this._registerRouteHandler(verb, path, rawHandler, customizedCode, options); - }; - - if (alias) { - this[alias] = this[verb]; - } - }); - } - - _serialize(body) { - if (typeof body === 'string') { - return body; - } else if (body) { - return JSON.stringify(body); - } else { - return '{"error": "not found"}'; - } - } - - _registerRouteHandler(verb, path, rawHandler, customizedCode, options) { - - let routeHandler = new RouteHandler({ - schema: this.schema, - verb, rawHandler, customizedCode, options, path, - serializerOrRegistry: this.serializerOrRegistry - }); - - let fullPath = this._getFullPath(path); - let timing = options.timing !== undefined ? options.timing : (() => this.timing); - - this.pretender[verb]( - fullPath, - (request) => { - return new Promise(resolve => { - Promise.resolve(routeHandler.handle(request)).then(mirageResponse => { - let [ code, headers, response ] = mirageResponse; - resolve([ code, headers, this._serialize(response) ]); - }); - }); - }, - timing - ); - } - - /** - * - * @private - */ - _hasModulesOfType(modules, type) { - let modulesOfType = modules[type]; - return modulesOfType ? Object.keys(modulesOfType).length > 0 : false; - } - - /** - * Builds a full path for Pretender to monitor based on the `path` and - * configured options (`urlPrefix` and `namespace`). - * - * @private - */ - _getFullPath(path) { - path = path[0] === '/' ? path.slice(1) : path; - let fullPath = ''; - let urlPrefix = this.urlPrefix ? this.urlPrefix.trim() : ''; - let namespace = ''; - - // if there is a urlPrefix and a namespace - if (this.urlPrefix && this.namespace) { - if (this.namespace[0] === '/' && this.namespace[this.namespace.length - 1] === '/') { - namespace = this.namespace.substring(0, this.namespace.length - 1).substring(1); - } - - if (this.namespace[0] === '/' && this.namespace[this.namespace.length - 1] !== '/') { - namespace = this.namespace.substring(1); - } - - if (this.namespace[0] !== '/' && this.namespace[this.namespace.length - 1] === '/') { - namespace = this.namespace.substring(0, this.namespace.length - 1); - } - - if (this.namespace[0] !== '/' && this.namespace[this.namespace.length - 1] !== '/') { - namespace = this.namespace; - } - } - - // if there is a namespace and no urlPrefix - if (this.namespace && !this.urlPrefix) { - if (this.namespace[0] === '/' && this.namespace[this.namespace.length - 1] === '/') { - namespace = this.namespace.substring(0, this.namespace.length - 1); - } - - if (this.namespace[0] === '/' && this.namespace[this.namespace.length - 1] !== '/') { - namespace = this.namespace; - } - - if (this.namespace[0] !== '/' && this.namespace[this.namespace.length - 1] === '/') { - let namespaceSub = this.namespace.substring(0, this.namespace.length - 1); - namespace = `/${namespaceSub}`; - } - - if (this.namespace[0] !== '/' && this.namespace[this.namespace.length - 1] !== '/') { - namespace = `/${this.namespace}`; - } - } - - // if no namespace - if (!this.namespace) { - namespace = ''; - } - - // check to see if path is a FQDN. if so, ignore any urlPrefix/namespace that was set - if (/^https?:\/\//.test(path)) { - fullPath += path; - } else { - // otherwise, if there is a urlPrefix, use that as the beginning of the path - if (urlPrefix.length) { - fullPath += (urlPrefix[urlPrefix.length - 1] === '/') ? urlPrefix : `${urlPrefix}/`; - } - - // add the namespace to the path - fullPath += namespace; - - // add a trailing slash to the path if it doesn't already contain one - if (fullPath[fullPath.length - 1] !== '/') { - fullPath += '/'; - } - - // finally add the configured path - fullPath += path; - - // if we're making a same-origin request, ensure a / is prepended and - // dedup any double slashes - if (!/^https?:\/\//.test(fullPath)) { - fullPath = `/${fullPath}`; - fullPath = fullPath.replace(/\/+/g, '/'); - } - } - - return fullPath; - } - - /** - * - * @private - */ - _configureDefaultPassthroughs() { - defaultPassthroughs.forEach((passthroughUrl) => { - this.passthrough(passthroughUrl); - }); - } - - /** - * - * @private - */ - _validateTraits(traits, factory, type) { - traits.forEach((traitName) => { - if (!factory.isTrait(traitName)) { - throw new Error(`'${traitName}' trait is not registered in '${type}' factory`); - } - }); - } - - /** - * - * @private - */ - _mergeExtensions(attrs, traits, overrides) { - let allExtensions = traits.map((traitName) => { - return attrs[traitName].extension; - }); - allExtensions.push(overrides || {}); - return allExtensions.reduce((accum, extension) => { - return _assign(accum, extension); - }, {}); - } - - /** - * - * @private - */ - _mapAssociationsFromAttributes(modelType, attributes) { - Object.keys(attributes || {}).filter((attr) => { - return isAssociation(attributes[attr]); - }).forEach((attr) => { - let association = attributes[attr]; - let associationName = this._fetchAssociationNameFromModel(modelType, attr); - let foreignKey = `${camelize(attr)}Id`; - attributes[foreignKey] = this.create(associationName, ...association.traitsAndOverrides).id; - delete attributes[attr]; - }); - } - - /** - * - * @private - */ - _fetchAssociationNameFromModel(modelType, associationAttribute) { - let model = this.schema.modelFor(modelType); - if (!model) { - throw new Error(`Model not registered: ${modelType}`); - } + super(options); - let association = model.class.findBelongsToAssociation(associationAttribute); - if (!association) { - throw new Error(`You're using the \`association\` factory helper on the '${associationAttribute}' attribute of your ${modelType} factory, but that attribute is not a \`belongsTo\` association. Read the Factories docs for more information: http://www.ember-cli-mirage.com/docs/v0.2.x/factories/#factories-and-relationships`); + if ( + typeof location !== 'undefined' && + location.search.indexOf('mirageLogging') !== -1 + ) { + this.logging = true; } - return camelize(association.modelName); } } diff --git a/addon/start-mirage.js b/addon/start-mirage.js new file mode 100644 index 000000000..610d1e0a1 --- /dev/null +++ b/addon/start-mirage.js @@ -0,0 +1,104 @@ +import readModules from './utils/read-modules'; +import Server from './server'; +import { singularize, pluralize } from 'ember-inflector'; +import { deprecate } from '@ember/debug'; + +/** + Helper to start mirage. This should not be called directly. In rfc232/rfc268 + tests, use `setupMirage()` or the `autoboot` option in the addon config + in the environment. In legacy tests that call `startMirage` directly, this + should be called via the `startMirage` method exported from + `/initializers/ember-cli-mirage`. + + This is intended to be called with only the `owner` argument (which would be + `this.owner` in an rfc232/rfc268 test, or the application instance if called + from an instance initializer). However, to support the legacy initializer, it + can instead accept a hash of the environment and config objects. + + @hide +*/ +export default function startMirage( + owner, + { env, baseConfig, testConfig, makeServer } = {} +) { + if (!env || !baseConfig) { + if (!owner) { + throw new Error('You must pass `owner` to startMirage()'); + } + + env = env || resolveRegistration(owner, 'config:environment'); + // These are set from `/initializers/ember-cli-mirage` + baseConfig = baseConfig || resolveRegistration(owner, 'mirage:base-config'); + testConfig = testConfig || resolveRegistration(owner, 'mirage:test-config'); + makeServer = makeServer || resolveRegistration(owner, 'mirage:make-server'); + } + + // Deprecate exporting makeServer as NOT the default function + deprecate( + 'Do not export the makeServer function. Please make the makeServer function the default exported function', + makeServer === undefined, + { + id: 'ember-cli-mirage-config-makeserver-export', + for: 'ember-cli-mirage', + since: '2.3.0', + until: '3.0.0', + url: 'https://www.ember-cli-mirage.com/docs/advanced/server-configuration', + } + ); + + let routes; + + // Are they using the routes as the default export + if (baseConfig && baseConfig.length === 0) { + routes = baseConfig; + } + + // Is the default exported function the makeServer function + if (baseConfig && baseConfig.length > 0) { + makeServer = baseConfig; + } + + let environment = env.environment; + let mirageEnvironment = env['ember-cli-mirage'] || {}; + + let discoverEmberDataModels = mirageEnvironment.discoverEmberDataModels; + if (discoverEmberDataModels === undefined) { + discoverEmberDataModels = true; + } + let modules = readModules(env.modulePrefix); + + let options = Object.assign(modules, { + environment, + routes, + testConfig, + discoverEmberDataModels, + }); + options.trackRequests = mirageEnvironment.trackRequests; + options.inflector = { singularize, pluralize }; + + let server; + if (makeServer) { + server = makeServer(options); + if ( + typeof location !== 'undefined' && + location.search.indexOf('mirageLogging') !== -1 + ) { + server.logging = true; + } + } else { + server = new Server(options); + } + + return server; +} + +// Support Ember 1.13 +function resolveRegistration(owner, ...args) { + if (owner.resolveRegistration) { + return owner.resolveRegistration(...args); + } else if (owner.__container__) { + return owner.__container__.lookupFactory(...args); + } else { + return owner.container.lookupFactory(...args); + } +} diff --git a/addon/trait.js b/addon/trait.js index f45505ae8..191a8f285 100644 --- a/addon/trait.js +++ b/addon/trait.js @@ -1,9 +1,15 @@ -let trait = function(extension) { - let __isTrait__ = true; - return { - extension, - __isTrait__ - }; -}; +import { trait } from 'miragejs'; +import { deprecateNestedImport } from './deprecate-imports'; -export default trait; +/** + @function trait + @hide + */ +export default function (...args) { + deprecateNestedImport( + "Importing 'trait' from 'ember-cli-mirage/trait' is deprecated. " + + "Add the `miragejs` package to devDependencies and use `import { trait } from 'miragejs';` instead." + ); + + return trait(...args); +} diff --git a/addon/utils/ember-data.js b/addon/utils/ember-data.js new file mode 100644 index 000000000..fc6a7ce4a --- /dev/null +++ b/addon/utils/ember-data.js @@ -0,0 +1,13 @@ +import { dependencySatisfies } from '@embroider/macros'; + +/** + @hide +*/ +export const hasEmberData = dependencySatisfies('ember-data', '*'); + +/** + @hide +*/ +export function isDsModel(m) { + return m && typeof m.eachRelationship === 'function'; +} diff --git a/addon/utils/extend.js b/addon/utils/extend.js index d49d3488b..1ac7f679d 100644 --- a/addon/utils/extend.js +++ b/addon/utils/extend.js @@ -1,44 +1,18 @@ -import _assign from 'lodash/assign'; -import _has from 'lodash/has'; - -export default function(protoProps, staticProps) { - let parent = this; - let child; - - // The constructor function for the new subclass is either defined by you - // (the "constructor" property in your `extend` definition), or defaulted - // by us to simply call the parent's constructor. - if (protoProps && _has(protoProps, 'constructor')) { - child = protoProps.constructor; - } else { - child = function() { - return parent.apply(this, arguments); - }; - } - - // Add static properties to the constructor function, if supplied. - - _assign(child, parent, staticProps); - - // Set the prototype chain to inherit from `parent`, without calling - // `parent`'s constructor function. - let Surrogate = function() { - this.constructor = child; - }; - - Surrogate.prototype = parent.prototype; - child.prototype = new Surrogate(); - - // Add prototype properties (instance properties) to the subclass, - // if supplied. - if (protoProps) { - _assign(child.prototype, protoProps); - } - // if (protoProps) { _assign(child.prototype, protoProps); } - - // Set a convenience property in case the parent's prototype is needed - // later. - child.__super__ = parent.prototype; - - return child; +import { _utilsExtend } from 'miragejs'; +import { deprecateNestedImport } from '../deprecate-imports'; + +/** + @function extend + @hide + */ +export default function extend(...args) { + const message = + `Importing 'extend' from 'ember-cli-mirage/utils/extend' is deprecated. ` + + `This wasn't intended to be a public API and you should use Factory.extend, Model.extend, ` + + `etc. APIs described in https://miragejs.com/. If you absolute know what you are doing, ` + + `install the \`miragejs\` package and use \`import { _utilsExtend } from 'miragejs';\` instead.`; + + deprecateNestedImport(message); + + return _utilsExtend(...args); } diff --git a/addon/utils/inflector.js b/addon/utils/inflector.js index b69f3002e..ae481f143 100644 --- a/addon/utils/inflector.js +++ b/addon/utils/inflector.js @@ -1,7 +1,83 @@ -import Ember from 'ember'; -export { singularize, pluralize } from 'ember-inflector'; +import { + _utilsInflectorCamelize, + _utilsInflectorDasherize, + _utilsInflectorUnderscore, + _utilsInflectorCapitalize, +} from 'miragejs'; +import { + singularize as _singularize, + pluralize as _pluralize, +} from 'ember-inflector'; +import { deprecateNestedImport } from '../deprecate-imports'; -export var capitalize = Ember.String.capitalize; -export var camelize = Ember.String.camelize; -export var dasherize = Ember.String.dasherize; -export var underscore = Ember.String.underscore; +/** + @function getMessage + @hide + */ +function getMessage(importName) { + return ( + `Importing '${importName}' from 'ember-cli-mirage/utils/inflector' is deprecated. ` + + `Install the \`@ember/string\` package and use ` + + `\`import { ${importName} } from '@ember/string';\` instead.` + ); +} + +/** + @function camelize + @hide + */ +export function camelize(...args) { + deprecateNestedImport(getMessage('camelize')); + + return _utilsInflectorCamelize(...args); +} + +/** + @function dasherize + @hide + */ +export function dasherize(...args) { + deprecateNestedImport(getMessage('dasherize')); + + return _utilsInflectorDasherize(...args); +} + +/** + @function underscore + @hide + */ +export function underscore(...args) { + deprecateNestedImport(getMessage('underscore')); + + return _utilsInflectorUnderscore(...args); +} + +/** + @function capitalize + @hide + */ +export function capitalize(...args) { + deprecateNestedImport(getMessage('capitalize')); + + return _utilsInflectorCapitalize(...args); +} + +/** + @function singularize + @hide + */ +export function singularize(...args) { + deprecateNestedImport(getMessage('singularize')); + + return _singularize(...args); +} + +/** + @function pluralize + @hide + */ +export function pluralize(...args) { + deprecateNestedImport(getMessage('pluralize')); + + return _pluralize(...args); +} diff --git a/addon/utils/is-association.js b/addon/utils/is-association.js index 880a3855b..ff5c80f32 100644 --- a/addon/utils/is-association.js +++ b/addon/utils/is-association.js @@ -1,5 +1,17 @@ -import _isPlainObject from 'lodash/isPlainObject'; +import { _utilsIsAssociation } from 'miragejs'; +import { deprecateNestedImport } from '../deprecate-imports'; -export default function(object) { - return _isPlainObject(object) && object.__isAssociation__ === true; +/** + @function isAssociation + @hide + */ +export default function isAssociation(...args) { + const message = + `Importing 'isAssociation' from 'ember-cli-mirage/utils/is-association' is deprecated. ` + + `This wasn't intended to be a public API. If you absolute know what you are doing, ` + + `install the \`miragejs\` package and use \`import { _utilsIsAssociation } from 'miragejs';\` instead.`; + + deprecateNestedImport(message); + + return _utilsIsAssociation(...args); } diff --git a/addon/utils/normalize-name.js b/addon/utils/normalize-name.js deleted file mode 100644 index abefabc40..000000000 --- a/addon/utils/normalize-name.js +++ /dev/null @@ -1,16 +0,0 @@ -import { - camelize, - pluralize, - singularize, - dasherize -} from 'ember-cli-mirage/utils/inflector'; - -export function toCollectionName(type) { - let modelName = dasherize(type); - return camelize(pluralize(modelName)); -} - -export function toModelName(type) { - let modelName = dasherize(type); - return singularize(modelName); -} diff --git a/addon/utils/read-modules.js b/addon/utils/read-modules.js index 5abbd8c8d..706613ae5 100644 --- a/addon/utils/read-modules.js +++ b/addon/utils/read-modules.js @@ -1,60 +1,73 @@ -/* global requirejs, require */ +/* global requirejs */ /* eslint-env node */ 'use strict'; -import Ember from 'ember'; -import _camelCase from 'lodash/camelCase'; -import { pluralize } from 'ember-cli-mirage/utils/inflector'; +import assert from '../assert'; +import { _utilsInflectorCamelize as camelize } from 'miragejs'; +import { pluralize } from 'ember-inflector'; import require from 'require'; -const { assert } = Ember; - -/* +/** This function looks through all files that have been loaded by Ember CLI and finds the ones under /mirage/[factories, fixtures, scenarios, models]/, and exports a hash containing the names of the files as keys and the data as values. + + @hide */ -export default function(prefix) { - let modules = ['factories', 'fixtures', 'scenarios', 'models', 'serializers']; - let mirageModuleRegExp = new RegExp(`^${prefix}/mirage/(${modules.join('|')})`); +export default function (prefix) { + let modules = [ + 'factories', + 'fixtures', + 'scenarios', + 'models', + 'serializers', + 'identity-managers', + ]; + let mirageModuleRegExp = new RegExp( + `^${prefix}/mirage/(${modules.join('|')})` + ); let modulesMap = modules.reduce((memo, name) => { - memo[name] = {}; + memo[camelize(name)] = {}; return memo; }, {}); - Object.keys(requirejs.entries).filter(function(key) { - return mirageModuleRegExp.test(key); - }).forEach(function(moduleName) { - if (moduleName.match('.jshint')) { // ignore autogenerated .jshint files - return; - } - let moduleParts = moduleName.split('/'); - let moduleType = moduleParts[moduleParts.length - 2]; - let moduleKey = moduleParts[moduleParts.length - 1]; - assert(`Subdirectories under ${moduleType} are not supported`, - moduleParts[moduleParts.length - 3] === 'mirage'); - - if (moduleType === 'scenario') { - assert('Only scenario/default.js is supported at this time.', - moduleKey !== 'default'); - } - - /* + Object.keys(requirejs.entries) + .filter(function (key) { + return mirageModuleRegExp.test(key); + }) + .forEach(function (moduleName) { + if (moduleName.match('.jshint')) { + // ignore autogenerated .jshint files + return; + } + let moduleParts = moduleName.split('/'); + let moduleTypeIndex = moduleParts.indexOf('mirage') + 1; + let moduleType = camelize(moduleParts[moduleTypeIndex]); + let moduleKey = moduleParts.slice([moduleTypeIndex + 1]).join('/'); + + if (moduleType === 'scenario') { + assert( + 'Only scenario/default.js is supported at this time.', + moduleKey !== 'default' + ); + } + + /* Ensure fixture keys are pluralized */ - if (moduleType === 'fixtures') { - moduleKey = pluralize(moduleKey); - } + if (moduleType === 'fixtures') { + moduleKey = pluralize(moduleKey); + } - let module = require(moduleName, null, null, true); - if (!module) { - throw new Error(`${moduleName} must export a ${moduleType}`); - } + let module = require(moduleName, null, null, true); + if (!module) { + throw new Error(`${moduleName} must export a ${moduleType}`); + } - let data = module.default; + let data = module.default; - modulesMap[moduleType][_camelCase(moduleKey)] = data; - }); + modulesMap[moduleType][camelize(moduleKey)] = data; + }); return modulesMap; } diff --git a/addon/utils/reference-sort.js b/addon/utils/reference-sort.js index 00f45247f..a5b269709 100644 --- a/addon/utils/reference-sort.js +++ b/addon/utils/reference-sort.js @@ -1,50 +1,17 @@ -// jscs:disable disallowVar, requireArrayDestructuring -import _uniq from 'lodash/uniq'; -import _flatten from 'lodash/flatten'; - -export default function(edges) { - let nodes = _uniq(_flatten(edges)); - let cursor = nodes.length; - let sorted = new Array(cursor); - let visited = {}; - let i = cursor; - - let visit = function(node, i, predecessors) { - - if (predecessors.indexOf(node) >= 0) { - throw new Error(`Cyclic dependency in properties ${JSON.stringify(predecessors)}`); - } - - if (visited[i]) { - return; - } else { - visited[i] = true; - } - - let outgoing = edges.filter(function(edge) { - return edge && edge[0] === node; - }); - i = outgoing.length; - if (i) { - let preds = predecessors.concat(node); - do { - let pair = outgoing[--i]; - let child = pair[1]; - if (child) { - visit(child, nodes.indexOf(child), preds); - } - } while (i); - } - - sorted[--cursor] = node; - }; - - while (i--) { - if (!visited[i]) { - visit(nodes[i], i, []); - } - } - - return sorted.reverse(); - +import { _utilsReferenceSort } from 'miragejs'; +import { deprecateNestedImport } from '../deprecate-imports'; + +/** + @function referenceSort + @hide + */ +export default function referenceSort(...args) { + const message = + `Importing 'referenceSort' from 'ember-cli-mirage/utils/reference-sort' is deprecated. ` + + `This wasn't intended to be a public API. If you absolute know what you are doing, ` + + `install the \`miragejs\` package and use \`import { _utilsReferenceSort } from 'miragejs';\` instead.`; + + deprecateNestedImport(message); + + return _utilsReferenceSort(...args); } diff --git a/addon/utils/uuid.js b/addon/utils/uuid.js index a806f792f..7b62bb237 100644 --- a/addon/utils/uuid.js +++ b/addon/utils/uuid.js @@ -1,10 +1,17 @@ -/* - UUID generator -*/ -export default function() { - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { - var r = Math.random() * 16 | 0; - var v = c === 'x' ? r : (r & 0x3 | 0x8); - return v.toString(16); - }); +import { _utilsUuid } from 'miragejs'; +import { deprecateNestedImport } from '../deprecate-imports'; + +/** + @function uuid + @hide + */ +export default function uuid(...args) { + const message = + `Importing 'uuid' from 'ember-cli-mirage/utils/reference-sort' is deprecated. ` + + `This wasn't intended to be a public API. If you absolute know what you are doing, ` + + `install the \`miragejs\` package and use \`import { _utilsUuid } from 'miragejs';\` instead.`; + + deprecateNestedImport(message); + + return _utilsUuid(...args); } diff --git a/app/initializers/ember-cli-mirage.js b/app/initializers/ember-cli-mirage.js index 574b98dcb..2e6ff32e5 100644 --- a/app/initializers/ember-cli-mirage.js +++ b/app/initializers/ember-cli-mirage.js @@ -1,32 +1,55 @@ -import readModules from 'ember-cli-mirage/utils/read-modules'; import ENV from '../config/environment'; -import baseConfig, { testConfig } from '../mirage/config'; -import Server from 'ember-cli-mirage/server'; -import _assign from 'lodash/assign'; +import getRfc232TestContext from 'ember-cli-mirage/get-rfc232-test-context'; +import startMirageImpl from 'ember-cli-mirage/start-mirage'; +import * as config from '../mirage/config'; +const { default: baseConfig, testConfig, makeServer } = config; +// +// This initializer does two things: +// +// 1. Pulls the mirage config objects from the application's config and +// registers them in the container so `ember-cli-mirage/start-mirage` can +// find them (since it doesn't have access to the app's namespace). +// 2. Provides legacy support for auto-starting mirage in pre-rfc268 acceptance +// tests. +// export default { name: 'ember-cli-mirage', - initialize: function(application) { - if (arguments.length > 1) { // Ember < 2.1 - var container = arguments[0], - application = arguments[1]; + initialize(application) { + if (baseConfig) { + application.register('mirage:base-config', baseConfig, { + instantiate: false, + }); + } + if (testConfig) { + application.register('mirage:test-config', testConfig, { + instantiate: false, + }); + } + if (makeServer) { + application.register('mirage:make-server', makeServer, { + instantiate: false, + }); } + ENV['ember-cli-mirage'] = ENV['ember-cli-mirage'] || {}; if (_shouldUseMirage(ENV.environment, ENV['ember-cli-mirage'])) { startMirage(ENV); } - } + }, }; export function startMirage(env = ENV) { - let environment = env.environment; - let modules = readModules(env.modulePrefix); - let options = _assign(modules, {environment, baseConfig, testConfig}); - - return new Server(options); + return startMirageImpl(null, { env, baseConfig, testConfig, makeServer }); } function _shouldUseMirage(env, addonConfig) { + if (typeof FastBoot !== 'undefined') { + return false; + } + if (getRfc232TestContext()) { + return false; + } let userDeclaredEnabled = typeof addonConfig.enabled !== 'undefined'; let defaultEnabled = _defaultEnabled(env, addonConfig); diff --git a/app/instance-initializers/ember-cli-mirage-autostart.js b/app/instance-initializers/ember-cli-mirage-autostart.js new file mode 100644 index 000000000..6977ada09 --- /dev/null +++ b/app/instance-initializers/ember-cli-mirage-autostart.js @@ -0,0 +1 @@ +export { default } from 'ember-cli-mirage/instance-initializers/ember-cli-mirage-autostart'; diff --git a/blueprints/.jshintrc b/blueprints/.jshintrc deleted file mode 100644 index 33f4f6f4b..000000000 --- a/blueprints/.jshintrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "predef": [ - "console" - ], - "strict": false -} diff --git a/blueprints/ember-cli-mirage/files/__root__/config.js b/blueprints/ember-cli-mirage/files/__root__/config.js index 93a1c5192..c2cd26a9d 100644 --- a/blueprints/ember-cli-mirage/files/__root__/config.js +++ b/blueprints/ember-cli-mirage/files/__root__/config.js @@ -21,6 +21,6 @@ export default function() { this.put('/posts/:id'); // or this.patch this.del('/posts/:id'); - http://www.ember-cli-mirage.com/docs/v0.2.x/shorthands/ + https://www.ember-cli-mirage.com/docs/route-handlers/shorthands */ } diff --git a/blueprints/ember-cli-mirage/files/__root__/scenarios/default.js b/blueprints/ember-cli-mirage/files/__root__/scenarios/default.js index 0d2db8d3c..adb3af4c0 100644 --- a/blueprints/ember-cli-mirage/files/__root__/scenarios/default.js +++ b/blueprints/ember-cli-mirage/files/__root__/scenarios/default.js @@ -3,8 +3,6 @@ export default function(/* server */) { /* Seed your development database using your factories. This data will not be loaded in your tests. - - Make sure to define a factory for each model you want to create. */ // server.createList('post', 10); diff --git a/blueprints/ember-cli-mirage/files/__root__/serializers/application.js b/blueprints/ember-cli-mirage/files/__root__/serializers/application.js index 6d47a3669..ece160b27 100644 --- a/blueprints/ember-cli-mirage/files/__root__/serializers/application.js +++ b/blueprints/ember-cli-mirage/files/__root__/serializers/application.js @@ -1,4 +1,4 @@ -import { JSONAPISerializer } from 'ember-cli-mirage'; +import { JSONAPISerializer } from 'miragejs'; export default JSONAPISerializer.extend({ }); diff --git a/blueprints/ember-cli-mirage/index.js b/blueprints/ember-cli-mirage/index.js index ab5d1b12a..848351cac 100644 --- a/blueprints/ember-cli-mirage/index.js +++ b/blueprints/ember-cli-mirage/index.js @@ -3,57 +3,44 @@ 'use strict'; var path = require('path'); -var existsSync = require('exists-sync'); -var chalk = require('chalk'); -var EOL = require('os').EOL; +var fs = require('fs'); module.exports = { - normalizeEntityName: function() { + normalizeEntityName: function () { // this prevents an error when the entityName is // not specified (since that doesn't actually matter // to us }, - fileMapTokens: function() { + fileMapTokens: function () { var self = this; return { - __root__: function(options) { - if (!!self.project.config()['ember-cli-mirage'] && !!self.project.config()['ember-cli-mirage'].directory) { + __root__: function (options) { + if ( + !!self.project.config()['ember-cli-mirage'] && + !!self.project.config()['ember-cli-mirage'].directory + ) { return self.project.config()['ember-cli-mirage'].directory; } else if (options.inAddon) { return path.join('tests', 'dummy', 'mirage'); } else { return '/mirage'; } - } + }, }; }, - afterInstall: function() { - return this.insertIntoFile('.jshintrc', ' "server",', { - after: '"predef": [\n' - }).then(() => { - return this.insertIntoFile('tests/.jshintrc', ' "server",', { - after: '"predef": [\n' - }).then(() =>{ - if (existsSync('tests/helpers/destroy-app.js')) { - var shutdownText = ' if(window.server) {\n window.server.shutdown();\n }'; - return this.insertIntoFile('tests/helpers/destroy-app.js', shutdownText, { - after: "Ember.run(application, 'destroy');\n" - }); - } else { - this.ui.writeLine( - EOL + - chalk.yellow( - '******************************************************' + EOL + - 'destroy-app.js helper is not present. Please read this' + EOL + - 'https://gist.github.com/blimmer/35d3efbb64563029505a' + EOL + - 'to see how to fix the problem.' + EOL + - '******************************************************' + EOL - ) - ); - } + insertShutdownIntoDestroyApp: function () { + if (fs.existsSync('tests/helpers/destroy-app.js')) { + var shutdownText = + ' if (window.server) {\n window.server.shutdown();\n }'; + return this.insertIntoFile('tests/helpers/destroy-app.js', shutdownText, { + after: "run(application, 'destroy');\n", }); - }); - } + } + }, + + afterInstall: function () { + return this.insertShutdownIntoDestroyApp(); + }, }; diff --git a/blueprints/mirage-factory/files/__root__/factories/__name__.js b/blueprints/mirage-factory/files/__root__/factories/__name__.js index 85018979d..f7467166b 100644 --- a/blueprints/mirage-factory/files/__root__/factories/__name__.js +++ b/blueprints/mirage-factory/files/__root__/factories/__name__.js @@ -1,4 +1,4 @@ -import { Factory } from 'ember-cli-mirage'; +import { Factory } from 'miragejs'; export default Factory.extend({ }); diff --git a/blueprints/mirage-factory/index.js b/blueprints/mirage-factory/index.js index 5530221b3..68136ef74 100644 --- a/blueprints/mirage-factory/index.js +++ b/blueprints/mirage-factory/index.js @@ -6,18 +6,21 @@ var path = require('path'); module.exports = { description: 'Generates a Mirage factory.', - fileMapTokens: function() { + fileMapTokens: function () { var self = this; return { - __root__: function(options) { - if (!!self.project.config()['ember-cli-mirage'] && !!self.project.config()['ember-cli-mirage'].directory) { + __root__: function (options) { + if ( + !!self.project.config()['ember-cli-mirage'] && + !!self.project.config()['ember-cli-mirage'].directory + ) { return self.project.config()['ember-cli-mirage'].directory; } else if (options.inAddon) { return path.join('tests', 'dummy', 'mirage'); } else { return '/mirage'; } - } + }, }; - } + }, }; diff --git a/blueprints/mirage-fixture/index.js b/blueprints/mirage-fixture/index.js index 406639fb8..a62e0de2a 100644 --- a/blueprints/mirage-fixture/index.js +++ b/blueprints/mirage-fixture/index.js @@ -7,19 +7,21 @@ var path = require('path'); module.exports = { description: 'Generates a Mirage fixture.', - fileMapTokens: function() { + fileMapTokens: function () { var self = this; return { - __root__: function(options) { - if (!!self.project.config()['ember-cli-mirage'] && !!self.project.config()['ember-cli-mirage'].directory) { + __root__: function (options) { + if ( + !!self.project.config()['ember-cli-mirage'] && + !!self.project.config()['ember-cli-mirage'].directory + ) { return self.project.config()['ember-cli-mirage'].directory; } else if (options.inAddon) { return path.join('tests', 'dummy', 'mirage'); } else { return '/mirage'; } - } + }, }; - } - + }, }; diff --git a/blueprints/mirage-identity-manager/files/__root__/identity-managers/__name__.js b/blueprints/mirage-identity-manager/files/__root__/identity-managers/__name__.js new file mode 100644 index 000000000..8390e1057 --- /dev/null +++ b/blueprints/mirage-identity-manager/files/__root__/identity-managers/__name__.js @@ -0,0 +1,35 @@ +export default class { + /** + * Returns an unique identifier. + * + * @method fetch + * @param {Object} data Records attributes hash + * @return {String} Unique identifier + * @public + */ + fetch(data) { + + } + + /** + * Register an identifier. + * Must throw if identifier is already used. + * + * @method set + * @param {String|Number} id + * @public + */ + set(id) { + + } + + /** + * Reset identity manager. + * + * @method reset + * @public + */ + reset() { + + } +} diff --git a/blueprints/mirage-identity-manager/index.js b/blueprints/mirage-identity-manager/index.js new file mode 100644 index 000000000..173887d6c --- /dev/null +++ b/blueprints/mirage-identity-manager/index.js @@ -0,0 +1,23 @@ +const path = require('path'); + +module.exports = { + description: 'Generates a Mirage identity manager', + + fileMapTokens: function () { + var self = this; + return { + __root__: function (options) { + if ( + !!self.project.config()['ember-cli-mirage'] && + !!self.project.config()['ember-cli-mirage'].directory + ) { + return self.project.config()['ember-cli-mirage'].directory; + } else if (options.inAddon) { + return path.join('tests', 'dummy', 'mirage'); + } else { + return '/mirage'; + } + }, + }; + }, +}; diff --git a/blueprints/mirage-model/files/__root__/models/__name__.js b/blueprints/mirage-model/files/__root__/models/__name__.js index 1486a7240..88bbf3c2c 100644 --- a/blueprints/mirage-model/files/__root__/models/__name__.js +++ b/blueprints/mirage-model/files/__root__/models/__name__.js @@ -1,4 +1,4 @@ -import { Model } from 'ember-cli-mirage'; +import { Model } from 'miragejs'; export default Model.extend({ }); diff --git a/blueprints/mirage-model/index.js b/blueprints/mirage-model/index.js index fbd32bac4..28eb566b2 100644 --- a/blueprints/mirage-model/index.js +++ b/blueprints/mirage-model/index.js @@ -7,18 +7,21 @@ var path = require('path'); module.exports = { description: 'Generates a Mirage model.', - fileMapTokens: function() { + fileMapTokens: function () { var self = this; return { - __root__: function(options) { - if (!!self.project.config()['ember-cli-mirage'] && !!self.project.config()['ember-cli-mirage'].directory) { + __root__: function (options) { + if ( + !!self.project.config()['ember-cli-mirage'] && + !!self.project.config()['ember-cli-mirage'].directory + ) { return self.project.config()['ember-cli-mirage'].directory; } else if (options.inAddon) { return path.join('tests', 'dummy', 'mirage'); } else { return '/mirage'; } - } + }, }; }, }; diff --git a/blueprints/mirage-serializer/files/__root__/serializers/__name__.js b/blueprints/mirage-serializer/files/__root__/serializers/__name__.js index 6d47a3669..9678f197b 100644 --- a/blueprints/mirage-serializer/files/__root__/serializers/__name__.js +++ b/blueprints/mirage-serializer/files/__root__/serializers/__name__.js @@ -1,4 +1,4 @@ -import { JSONAPISerializer } from 'ember-cli-mirage'; +import ApplicationSerializer from './application'; -export default JSONAPISerializer.extend({ +export default ApplicationSerializer.extend({ }); diff --git a/blueprints/mirage-serializer/index.js b/blueprints/mirage-serializer/index.js index 1728e57a9..93de68195 100644 --- a/blueprints/mirage-serializer/index.js +++ b/blueprints/mirage-serializer/index.js @@ -7,18 +7,21 @@ var path = require('path'); module.exports = { description: 'Generates a Mirage serializer.', - fileMapTokens: function() { + fileMapTokens: function () { var self = this; return { - __root__: function(options) { - if (!!self.project.config()['ember-cli-mirage'] && !!self.project.config()['ember-cli-mirage'].directory) { + __root__: function (options) { + if ( + !!self.project.config()['ember-cli-mirage'] && + !!self.project.config()['ember-cli-mirage'].directory + ) { return self.project.config()['ember-cli-mirage'].directory; } else if (options.inAddon) { return path.join('tests', 'dummy', 'mirage'); } else { return '/mirage'; } - } + }, }; }, }; diff --git a/bower.json b/bower.json deleted file mode 100644 index 9d3780f6e..000000000 --- a/bower.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "ember-cli-mirage", - "dependencies": { - "jquery": "2.1.4", - "ember": "2.10.0", - "ember-cli-shims": "0.1.3", - "ember-cli-test-loader": "0.2.2", - "ember-qunit-notifications": "0.1.0", - "sinonjs": "~1.17.1" - } -} diff --git a/config/addon-docs.js b/config/addon-docs.js new file mode 100644 index 000000000..fffeb22c5 --- /dev/null +++ b/config/addon-docs.js @@ -0,0 +1,13 @@ +'use strict'; + +// eslint-disable-next-line node/no-unpublished-require +const AddonDocsConfig = require('ember-cli-addon-docs/lib/config'); + +module.exports = class extends AddonDocsConfig { + // See https://ember-learn.github.io/ember-cli-addon-docs/docs/deploying + // for details on configuration you can override here. + + getRootURL() { + return ''; + } +}; diff --git a/config/deploy.js b/config/deploy.js new file mode 100644 index 000000000..c93a1ebff --- /dev/null +++ b/config/deploy.js @@ -0,0 +1,31 @@ +/* eslint-env node */ +'use strict'; + +module.exports = function (deployTarget) { + let ENV = { + build: {}, + git: { + repo: 'git@github.com:miragejs/ember-cli-mirage.git', + }, + }; + + if (deployTarget === 'development') { + ENV.build.environment = 'development'; + // configure other plugins for development deploy target here + } + + if (deployTarget === 'staging') { + ENV.build.environment = 'production'; + // configure other plugins for staging deploy target here + } + + if (deployTarget === 'production') { + ENV.build.environment = 'production'; + // configure other plugins for production deploy target here + } + + // Note: if you need to build some configuration asynchronously, you can return + // a promise that resolves with the ENV object instead of returning the + // ENV object synchronously. + return ENV; +}; diff --git a/config/ember-try.js b/config/ember-try.js index f6f8205a6..311359f14 100644 --- a/config/ember-try.js +++ b/config/ember-try.js @@ -1,60 +1,125 @@ -/* eslint-env node */ -module.exports = { - scenarios: [ - { - name: 'ember-1.13', - bower: { - dependencies: { - 'ember': '~1.13.0' - }, - resolutions: { - 'ember': '~1.13.0' - } - } - }, - { - name: 'ember-lts-2.4', - bower: { - dependencies: { - 'ember': 'components/ember#lts-2-4' - }, - resolutions: { - 'ember': 'lts-2-4' - } - } - }, - { - name: 'ember-release', - bower: { - dependencies: { - 'ember': 'components/ember#release' - }, - resolutions: { - 'ember': 'release' - } - } - }, - { - name: 'ember-beta', - bower: { - dependencies: { - 'ember': 'components/ember#beta' - }, - resolutions: { - 'ember': 'beta' - } - } - }, - { - name: 'ember-canary', - bower: { - dependencies: { - 'ember': 'components/ember#canary' - }, - resolutions: { - 'ember': 'canary' - } - } - } - ] +'use strict'; + +const getChannelURL = require('ember-source-channel-url'); +// const { embroiderSafe, embroiderOptimized } = require('@embroider/test-setup'); + +module.exports = async function () { + return { + useYarn: true, + scenarios: [ + { + name: 'ember-lts-3.12', + npm: { + devDependencies: { + 'ember-cli': '~3.12.1', + 'ember-data': '~3.12.6', + 'ember-source': '~3.12.4', + }, + }, + }, + { + name: 'ember-lts-3.16', + npm: { + devDependencies: { + 'ember-cli': '~3.16.2', + 'ember-source': '~3.16.10', + }, + }, + }, + { + name: 'ember-lts-3.20', + npm: { + devDependencies: { + 'ember-cli': '~3.20.2', + 'ember-source': '~3.20.5', + }, + }, + }, + { + name: 'ember-lts-3.24', + npm: { + devDependencies: { + 'ember-source': '~3.24.3', + }, + }, + }, + { + name: 'ember-lts-3.28', + npm: { + devDependencies: { + 'ember-source': '~3.28.8', + }, + }, + }, + { + name: 'ember-release', + npm: { + devDependencies: { + 'ember-source': await getChannelURL('release'), + }, + dependencies: { + 'ember-auto-import': '^2.2.4', + webpack: '^5.64.4', + }, + }, + }, + { + name: 'ember-beta', + npm: { + devDependencies: { + 'ember-source': await getChannelURL('beta'), + }, + dependencies: { + 'ember-auto-import': '^2.2.4', + webpack: '^5.64.4', + }, + }, + }, + { + name: 'ember-canary', + npm: { + devDependencies: { + 'ember-source': await getChannelURL('canary'), + }, + dependencies: { + 'ember-auto-import': '^2.2.4', + webpack: '^5.64.4', + }, + }, + }, + { + name: 'ember-default-with-jquery', + env: { + EMBER_OPTIONAL_FEATURES: JSON.stringify({ + 'jquery-integration': true, + }), + }, + npm: { + devDependencies: { + '@ember/jquery': '^1.1.0', + }, + }, + }, + { + name: 'ember-classic', + env: { + EMBER_OPTIONAL_FEATURES: JSON.stringify({ + 'application-template-wrapper': true, + 'default-async-observers': false, + 'template-only-glimmer-components': false, + }), + }, + npm: { + devDependencies: { + 'ember-source': '~3.28.8', + }, + ember: { + edition: 'classic', + }, + }, + }, + // embroiderSafe(), + // embroiderOptimized(), + ], + }; }; diff --git a/config/environment.js b/config/environment.js index f0d875e1a..cef3b653d 100644 --- a/config/environment.js +++ b/config/environment.js @@ -1,26 +1,31 @@ -/* eslint-env node */ 'use strict'; var fs = require('fs'); function usingProxy() { var usingProxyArg = !!process.argv.filter(function (arg) { - return arg.indexOf('--proxy') === 0 || arg.indexOf('-pr') === 0 || arg.indexOf('-pxy') === 0; + return ( + arg.indexOf('--proxy') === 0 || + arg.indexOf('-pr') === 0 || + arg.indexOf('-pxy') === 0 + ); }).length; var hasGeneratedProxies = false; - var proxiesDir = process.env.PWD + '/server/proxies'; + var proxiesDir = `${process.env.PWD}/server/proxies`; try { fs.lstatSync(proxiesDir); hasGeneratedProxies = true; - } catch (e) {} + } catch (e) { + // ignore + } return usingProxyArg || hasGeneratedProxies; } -module.exports = function(environment, appConfig) { +module.exports = function (environment, appConfig) { appConfig['ember-cli-mirage'] = appConfig['ember-cli-mirage'] || {}; - appConfig['ember-cli-mirage']['usingProxy'] = usingProxy(); - appConfig['ember-cli-mirage']['useDefaultPassthroughs'] = true; + appConfig['ember-cli-mirage'].usingProxy = usingProxy(); + appConfig['ember-cli-mirage'].useDefaultPassthroughs = true; return {}; -}; \ No newline at end of file +}; diff --git a/ember-cli-build.js b/ember-cli-build.js index 94fec27b6..b8c44a756 100644 --- a/ember-cli-build.js +++ b/ember-cli-build.js @@ -1,20 +1,39 @@ -/* eslint-env node */ -/* global require, module */ -var EmberAddon = require('ember-cli/lib/broccoli/ember-addon'); +'use strict'; -module.exports = function(defaults) { - var app = new EmberAddon(defaults, { - babel: { - includePolyfill: true +const EmberAddon = require('ember-cli/lib/broccoli/ember-addon'); + +module.exports = function (defaults) { + let app = new EmberAddon(defaults, { + 'ember-cli-babel': { + includePolyfill: true, + }, + 'ember-cli-addon-docs-esdoc': { + packages: [ + 'ember-cli-mirage', + { name: 'miragejs', sourceDirectory: 'lib' }, + ], + }, + 'ember-composable-helpers': { + only: ['sort-by'], + }, + addons: { + blacklist: ['ember-cli-fastboot'], }, }); /* - This build file specifies the options for the dummy test app of this - addon, located in `/tests/dummy` - This build file does *not* influence how the addon or the app using it - behave. You most likely want to be modifying `./index.js` or app's build file + This build file specifies the options for the dummy test app of this addon, + located in `/tests/dummy`. This build file does *not* influence how the addon + or the app using it behave. You most likely want to be modifying `./index.js` + or app's build file. */ - return app.toTree(); + const { maybeEmbroider } = require('@embroider/test-setup'); + return maybeEmbroider(app, { + skipBabel: [ + { + package: 'qunit', + }, + ], + }); }; diff --git a/index.js b/index.js index e1d3813f3..33abecc64 100644 --- a/index.js +++ b/index.js @@ -1,26 +1,18 @@ -/* eslint-env node */ 'use strict'; -var path = require('path'); -var mergeTrees = require('broccoli-merge-trees'); -var Funnel = require('broccoli-funnel'); +const path = require('path'); +const mergeTrees = require('broccoli-merge-trees'); +const Funnel = require('broccoli-funnel'); +const writeFile = require('broccoli-file-creator'); module.exports = { - name: 'ember-cli-mirage', - - options: { - nodeAssets: { - 'route-recognizer': npmAsset({ - path: 'dist/route-recognizer.js', - sourceMap: 'dist/route-recognizer.js.map' - }), - 'fake-xml-http-request': npmAsset('fake_xml_http_request.js'), - 'pretender': npmAsset('pretender.js'), - 'faker': npmAsset('build/build/faker.js') - } - }, + name: require('./package').name, - included: function included() { - var app; + // isDevelopingAddon: function () { + // return true; + // }, + + included() { + let app; // If the addon has the _findHost() method (in ember-cli >= 2.7.0), we'll just // use that. @@ -29,14 +21,15 @@ module.exports = { } else { // Otherwise, we'll use this implementation borrowed from the _findHost() // method in ember-cli. - var current = this; + let current = this; do { app = current.app || app; } while (current.parent.parent && (current = current.parent)); } this.app = app; - this.addonConfig = this.app.project.config(app.env)['ember-cli-mirage'] || {}; + this.addonConfig = + this.app.project.config(app.env)['ember-cli-mirage'] || {}; this.addonBuildConfig = this.app.options['ember-cli-mirage'] || {}; // Call super after initializing config so we can use _shouldIncludeFiles for the node assets @@ -46,61 +39,77 @@ module.exports = { this.mirageDirectory = this.addonBuildConfig.directory; } else if (this.addonConfig.directory) { this.mirageDirectory = this.addonConfig.directory; - } else if (app.project.pkg['ember-addon'] && !app.project.pkg['ember-addon'].paths) { - this.mirageDirectory = path.resolve(app.project.root, path.join('tests', 'dummy', 'mirage')); + } else if ( + app.project.pkg['ember-addon'] && + app.project.pkg['ember-addon'].configPath + ) { + this.mirageDirectory = path.resolve( + app.project.root, + path.join('tests', 'dummy', 'mirage') + ); } else { this.mirageDirectory = path.join(this.app.project.root, '/mirage'); } - - if (this._shouldIncludeFiles()) { - app.import('vendor/ember-cli-mirage/pretender-shim.js', { - type: 'vendor', - exports: { 'pretender': ['default'] } - }); - } }, - blueprintsPath: function() { + blueprintsPath() { return path.join(__dirname, 'blueprints'); }, - treeFor: function(name) { - if (!this._shouldIncludeFiles()) { - return; + treeFor(name) { + let shouldIncludeFiles = this._shouldIncludeFiles(); + if (shouldIncludeFiles || name === 'vendor') { + return this._super.treeFor.apply(this, arguments); } - return this._super.treeFor.apply(this, arguments); + if (name === 'app') { + // Include a noop initializer, even if Mirage is excluded from the build + return writeFile( + 'initializers/ember-cli-mirage.js', + ` + export default { + name: 'ember-cli-mirage', + initialize() {} + }; + ` + ); + } }, - _lintMirageTree: function(mirageTree) { - var lintedMirageTrees; + _lintMirageTree(mirageTree) { + let lintedMirageTrees; // _eachProjectAddonInvoke was added in ember-cli@2.5.0 // this conditional can be removed when we no longer support // versions older than 2.5.0 if (this._eachProjectAddonInvoke) { - lintedMirageTrees = this._eachProjectAddonInvoke('lintTree', ['mirage', mirageTree]); + lintedMirageTrees = this._eachProjectAddonInvoke('lintTree', [ + 'mirage', + mirageTree, + ]); } else { - lintedMirageTrees = this.project.addons.map(function(addon) { - if (addon.lintTree) { - return addon.lintTree('mirage', mirageTree); - } - }).filter(Boolean); + lintedMirageTrees = this.project.addons + .map(function (addon) { + if (addon.lintTree) { + return addon.lintTree('mirage', mirageTree); + } + }) + .filter(Boolean); } - var lintedMirage = mergeTrees(lintedMirageTrees, { + let lintedMirage = mergeTrees(lintedMirageTrees, { overwrite: true, - annotation: 'TreeMerger (mirage-lint)' + annotation: 'TreeMerger (mirage-lint)', }); return new Funnel(lintedMirage, { - destDir: 'tests/mirage/' + destDir: 'tests/mirage/', }); }, - treeForApp: function(appTree) { - var trees = [ appTree ]; - var mirageFilesTree = new Funnel(this.mirageDirectory, { - destDir: 'mirage' + treeForApp(appTree) { + let trees = [appTree]; + let mirageFilesTree = new Funnel(this.mirageDirectory, { + destDir: 'mirage', }); trees.push(mirageFilesTree); @@ -111,28 +120,27 @@ module.exports = { return mergeTrees(trees); }, - _shouldIncludeFiles: function() { + _shouldIncludeFiles() { if (process.env.EMBER_CLI_FASTBOOT) { return false; } - var environment = this.app.env; - var enabledInProd = environment === 'production' && this.addonConfig.enabled; - var explicitExcludeFiles = this.addonConfig.excludeFilesFromBuild; + let environment = this.app.env; + let enabledInProd = + environment === 'production' && this.addonConfig.enabled; + let explicitExcludeFiles = this.addonConfig.excludeFilesFromBuild; if (enabledInProd && explicitExcludeFiles) { - throw new Error('Mirage was explicitly enabled in production, but its files were excluded ' - + 'from the build. Please, use only ENV[\'ember-cli-mirage\'].enabled in ' - + 'production environment.'); + throw new Error( + 'Mirage was explicitly enabled in production, but its files were excluded ' + + "from the build. Please, use only ENV['ember-cli-mirage'].enabled in " + + 'production environment.' + ); } - return enabledInProd || (environment && environment !== 'production' && explicitExcludeFiles !== true); - } + return ( + enabledInProd || + (environment && + environment !== 'production' && + explicitExcludeFiles !== true) + ); + }, }; - -function npmAsset(filePath) { - return function() { - return { - enabled: this._shouldIncludeFiles(), - import: [filePath] - }; - }; -} diff --git a/package.json b/package.json index 6270efe27..ea9d2c815 100644 --- a/package.json +++ b/package.json @@ -1,82 +1,156 @@ { "name": "ember-cli-mirage", - "version": "0.2.9", - "description": "A client-side HTTP server to develop, test and demo your Ember app", + "version": "2.3.0", + "description": "A client-side server to help you build, test and demo your Ember app", + "keywords": [ + "ember-addon", + "pretender", + "prototype", + "server", + "testing" + ], + "repository": { + "type": "git", + "url": "https://github.com/miragejs/ember-cli-mirage.git" + }, + "license": "MIT", + "author": "Sam Selikoff", "directories": { "doc": "doc", "test": "tests" }, + "homepage": "https://github.com/miragejs/ember-cli-mirage", + "bugs": { + "url": "https://github.com/miragejs/ember-cli-mirage/issues" + }, "scripts": { - "build": "ember build", - "start": "ember server", - "test": "ember try:each && mocha tests/**/*-test-node.js" + "build": "ember build --environment=production", + "lint": "npm-run-all --aggregate-output --continue-on-error --parallel \"lint:!(fix)\"", + "lint:fix": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*:fix", + "lint:hbs": "ember-template-lint .", + "lint:hbs:fix": "ember-template-lint . --fix", + "lint:js": "eslint . --cache", + "lint:js:fix": "eslint . --fix", + "start": "ember serve", + "test": "npm-run-all lint test:*", + "test:ember": "ember test", + "test:ember-compatibility": "ember try:each", + "test:test-projects": "./scripts/test.sh", + "prepare": "./scripts/link.sh" }, - "repository": { - "type": "git", - "url": "https://github.com/samselikoff/ember-cli-mirage.git" + "dependencies": { + "@embroider/macros": "^0.50.1", + "broccoli-file-creator": "^2.1.1", + "broccoli-funnel": "^3.0.3", + "broccoli-merge-trees": "^4.2.0", + "ember-auto-import": "^1.12.0", + "ember-cli-babel": "^7.26.6", + "ember-destroyable-polyfill": "^2.0.3", + "ember-get-config": "0.2.4 - 0.5.0", + "ember-inflector": "^2.0.0 || ^3.0.0 || ^4.0.2", + "lodash-es": "^4.17.11", + "miragejs": "^0.1.43" }, - "bugs": { - "url": "https://github.com/samselikoff/ember-cli-mirage/issues" + "peerDependencies": { + "@ember/test-helpers": "*", + "ember-data": "*", + "ember-qunit": "*" }, - "homepage": "https://github.com/samselikoff/ember-cli-mirage", - "engines": { - "node": ">= 0.12.0" + "peerDependenciesMeta": { + "@ember/test-helpers": { + "optional": true + }, + "ember-data": { + "optional": true + }, + "ember-qunit": { + "optional": true + } }, - "author": "Sam Selikoff", - "license": "MIT", "devDependencies": { - "active-model-adapter": "^2.0.3", - "broccoli-asset-rev": "^2.4.5", - "chai": "2.0.0", - "ember-ajax": "^2.4.1", - "ember-cli": "^2.9.1", - "ember-cli-app-version": "^2.0.0", - "ember-cli-content-security-policy": "0.4.0", - "ember-cli-dependency-checker": "^1.3.0", - "ember-cli-eslint": "3.0.0", - "ember-cli-htmlbars": "^1.0.10", - "ember-cli-htmlbars-inline-precompile": "^0.3.3", - "ember-cli-inject-live-reload": "^1.4.1", - "ember-cli-qunit": "^3.0.1", - "ember-cli-release": "^0.2.9", - "ember-cli-sri": "^2.1.0", - "ember-cli-test-loader": "^1.1.0", - "ember-cli-uglify": "^1.2.0", - "ember-data": "^2.10.0", - "ember-disable-proxy-controllers": "^1.0.1", - "ember-disable-prototype-extensions": "^1.1.0", - "ember-export-application-global": "^1.0.5", - "ember-load-initializers": "^0.5.1", - "ember-resolver": "^2.0.3", - "ember-sinon": "0.5.1", - "eslint-plugin-ember-suave": "^1.0.0", - "loader.js": "^4.0.10", - "lodash": "3.10.1", - "mocha": "^2.1.0" + "@ember/jquery": "^2.0.0", + "@ember/optional-features": "^2.0.0", + "@ember/test-helpers": "^2.6.0", + "@embroider/test-setup": "^0.41.0", + "@glimmer/component": "^1.0.4", + "@glimmer/tracking": "^1.0.4", + "babel-eslint": "^10.1.0", + "broccoli-asset-rev": "^3.0.0", + "ember-cli": "~3.28.4", + "ember-cli-addon-docs": "^3.0.0", + "ember-cli-addon-docs-esdoc": "^0.4.0", + "ember-cli-dependency-checker": "^3.2.0", + "ember-cli-deploy": "^1.0.2", + "ember-cli-deploy-build": "^2.0.0", + "ember-cli-deploy-git": "^1.3.3", + "ember-cli-deploy-git-ci": "^1.0.1", + "ember-cli-fastboot": "^3.2.0-beta.5", + "ember-cli-favicon": "^3.0.0", + "ember-cli-htmlbars": "^6.0.1", + "ember-cli-inject-live-reload": "^2.1.0", + "ember-cli-moment-shim": "^3.8.0", + "ember-cli-sri": "^2.1.1", + "ember-cli-terser": "^4.0.2", + "ember-composable-helpers": "^5.0.0", + "ember-data": "~3.28.5", + "ember-disable-prototype-extensions": "^1.1.3", + "ember-export-application-global": "^2.0.1", + "ember-fetch": "^8.1.1", + "ember-load-initializers": "^2.1.2", + "ember-maybe-import-regenerator": "^1.0.0", + "ember-moment": "^9.0.1", + "ember-qunit": "^5.1.5", + "ember-resolver": "^8.0.3", + "ember-source": "~3.28.8", + "ember-source-channel-url": "^3.0.0", + "ember-template-lint": "^3.14.0", + "ember-try": "^2.0.0", + "eslint": "^7.32.0", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-ember": "^10.5.8", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^4.0.0", + "eslint-plugin-qunit": "^7.1.0", + "faker": "^5.1.0", + "fastboot": "^3.2.0-beta.5", + "js-yaml": "^4.0.0", + "jsdom": "^19.0.0", + "loader.js": "^4.7.0", + "npm-run-all": "^4.1.5", + "prettier": "^2.5.1", + "qunit": "^2.17.2", + "qunit-dom": "^2.0.0" }, - "keywords": [ - "ember-addon", - "pretender", - "testing", - "prototype", - "server" - ], - "ember-addon": { - "configPath": "tests/dummy/config" + "resolutions": { + "favicons": "5.3.0", + "colors": "1.4.0" }, - "dependencies": { - "broccoli-funnel": "^1.0.2", - "broccoli-merge-trees": "^1.1.0", - "broccoli-unwatched-tree": "^0.1.1", - "chalk": "^1.1.1", - "ember-cli-babel": "^5.1.7", - "ember-cli-node-assets": "^0.1.4", - "ember-inflector": "^1.9.2", - "ember-lodash": "^4.0", - "exists-sync": "0.0.3", - "fake-xml-http-request": "^1.4.0", - "faker": "^3.0.0", - "pretender": "^1.4.2", - "route-recognizer": "^0.2.3" + "engines": { + "node": ">= 10.*" + }, + "volta": { + "node": "12.22.7", + "yarn": "1.22.17" + }, + "changelog": { + "labels": { + "Breaking": "💥 Breaking Change", + "Feature / Enhancement": "🚀 Enhancement", + "Bug": "🐛 Bug Fix", + "documentation": "📝 Documentation", + "internal": "🏠 Internal" + } + }, + "ember": { + "edition": "octane" + }, + "ember-addon": { + "configPath": "tests/dummy/config", + "before": [ + "ember-cli-babel" + ], + "after": [ + "ember-qunit" + ] } } diff --git a/scripts/link.sh b/scripts/link.sh new file mode 100755 index 000000000..4f81212e8 --- /dev/null +++ b/scripts/link.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +set -e + +# Copied from https://github.com/ef4/ember-auto-import/blob/9e48e9ec9639ce05ca2a2688581ea41fdd627c5c/scripts/link-them.sh + +# All packages get a node_modules directory and a .bin link +for package in "01-basic-app" "02-app-that-excludes-mirage"; do + mkdir -p ./test-projects/$package/node_modules + pushd ./test-projects/$package/node_modules > /dev/null + rm -rf .bin + ln -s ../../../node_modules/.bin .bin + popd > /dev/null +done + +# These packages get to depend on ember-cli-mirage +for package in "01-basic-app" "02-app-that-excludes-mirage"; do + pushd ./test-projects/$package/node_modules > /dev/null + rm -rf ./ember-cli-mirage + ln -s ../../.. ./ember-cli-mirage + popd > /dev/null +done diff --git a/scripts/parallel b/scripts/parallel new file mode 100755 index 000000000..955b4dc38 --- /dev/null +++ b/scripts/parallel @@ -0,0 +1,11892 @@ +#!/usr/bin/env perl + +# Copyright (C) 2007,2008,2009,2010,2011,2012,2013,2014,2015,2016, +# 2017,2018 Ole Tange and Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# or write to the Free Software Foundation, Inc., 51 Franklin St, +# Fifth Floor, Boston, MA 02110-1301 USA + +# open3 used in Job::start +use IPC::Open3; +# &WNOHANG used in reaper +use POSIX qw(:sys_wait_h setsid ceil :errno_h); +# gensym used in Job::start +use Symbol qw(gensym); +# tempfile used in Job::start +use File::Temp qw(tempfile tempdir); +# mkpath used in openresultsfile +use File::Path; +# GetOptions used in get_options_from_array +use Getopt::Long; +# Used to ensure code quality +use strict; +use File::Basename; + +save_stdin_stdout_stderr(); +save_original_signal_handler(); +parse_options(); +::debug("init", "Open file descriptors: ", join(" ",keys %Global::fd), "\n"); +my $number_of_args; +if($Global::max_number_of_args) { + $number_of_args = $Global::max_number_of_args; +} elsif ($opt::X or $opt::m or $opt::xargs) { + $number_of_args = undef; +} else { + $number_of_args = 1; +} + +my @command = @ARGV; +my @input_source_fh; +if($opt::pipepart) { + if($opt::tee) { + @input_source_fh = map { open_or_exit($_) } @opt::a; + # Remove the first: It will be the file piped. + shift @input_source_fh; + if(not @input_source_fh and not $opt::pipe) { + @input_source_fh = (*STDIN); + } + } else { + # -a is used for data - not for command line args + @input_source_fh = map { open_or_exit($_) } "/dev/null"; + } +} else { + @input_source_fh = map { open_or_exit($_) } @opt::a; + if(not @input_source_fh and not $opt::pipe) { + @input_source_fh = (*STDIN); + } +} +if($opt::sqlmaster) { + # Create SQL table to hold joblog + output + $Global::sql->create_table($#input_source_fh+1); + if($opt::sqlworker) { + # Start a real --sqlworker in the background later + $Global::start_sqlworker = 1; + $opt::sqlworker = undef; + } +} + +if($opt::skip_first_line) { + # Skip the first line for the first file handle + my $fh = $input_source_fh[0]; + <$fh>; +} + +set_input_source_header(); + +if($opt::filter_hosts and (@opt::sshlogin or @opt::sshloginfile)) { + # Parallel check all hosts are up. Remove hosts that are down + filter_hosts(); +} + +if($opt::nonall or $opt::onall) { + onall(\@input_source_fh,@command); + wait_and_exit(min(undef_as_zero($Global::exitstatus),254)); +} + +$Global::JobQueue = JobQueue->new( + \@command,\@input_source_fh,$Global::ContextReplace, + $number_of_args,\@Global::transfer_files,\@Global::ret_files); + +if($opt::pipepart) { + pipepart_setup(); +} elsif($opt::pipe and $opt::tee) { + pipe_tee_setup(); +} + +if($opt::eta or $opt::bar or $opt::shuf or $Global::halt_pct) { + # Count the number of jobs or shuffle all jobs + # before starting any. + # Must be done after ungetting any --pipepart jobs. + $Global::JobQueue->total_jobs(); +} +# Compute $Global::max_jobs_running +# Must be done after ungetting any --pipepart jobs. +max_jobs_running(); + +init_run_jobs(); +my $sem; +if($Global::semaphore) { + $sem = acquire_semaphore(); +} +$SIG{TERM} = \&start_no_new_jobs; +start_more_jobs(); +if($opt::tee) { + # All jobs must be running in parallel for --tee + $Global::start_no_new_jobs = 1; +} elsif($opt::pipe and not $opt::pipepart) { + spreadstdin(); +} +::debug("init", "Start draining\n"); +drain_job_queue(); +::debug("init", "Done draining\n"); +reaper(); +::debug("init", "Done reaping\n"); +if($Global::semaphore) { + $sem->release(); +} +cleanup(); +::debug("init", "Halt\n"); +halt(); + +sub set_input_source_header { + if($opt::header and not $opt::pipe) { + # split with colsep or \t + # $header force $colsep = \t if undef? + my $delimiter = defined $opt::colsep ? $opt::colsep : "\t"; + # regexp for {= + my $left = "\Q$Global::parensleft\E"; + my $l = $Global::parensleft; + # regexp for =} + my $right = "\Q$Global::parensright\E"; + my $r = $Global::parensright; + my $id = 1; + for my $fh (@input_source_fh) { + my $line = <$fh>; + chomp($line); + ::debug("init", "Delimiter: '$delimiter'"); + for my $s (split /$delimiter/o, $line) { + ::debug("init", "Colname: '$s'"); + # Replace {colname} with {2} + for(@command,@Global::ret_files,@Global::transfer_files, + $opt::tagstring, $opt::workdir, $opt::results, $opt::retries) { + # Skip if undefined + $_ or next; + s:\{$s(|/|//|\.|/\.)\}:\{$id$1\}:g; + # {=header1 ... =} => {=1 ... =} + s:$left $s (.*?) $right:$l$id$1$r:gx; + } + $Global::input_source_header{$id} = $s; + $id++; + } + } + } else { + my $id = 1; + for my $fh (@input_source_fh) { + $Global::input_source_header{$id} = $id; + $id++; + } + } +} + +sub max_jobs_running { + # Compute $Global::max_jobs_running as the max number of jobs + # running on each sshlogin. + # Returns: + # $Global::max_jobs_running + if(not $Global::max_jobs_running) { + + for my $sshlogin (values %Global::host) { + $sshlogin->max_jobs_running(); + } + } + return $Global::max_jobs_running; +} + +sub halt { + # Compute exit value, + # wait for children to complete + # and exit + if($opt::halt and $Global::halt_when ne "never") { + if(not defined $Global::halt_exitstatus) { + if($Global::halt_pct) { + $Global::halt_exitstatus = + ::ceil($Global::total_failed / $Global::total_started * 100); + } elsif($Global::halt_count) { + $Global::halt_exitstatus = + ::min(undef_as_zero($Global::total_failed),101); + } + } + wait_and_exit($Global::halt_exitstatus); + } else { + wait_and_exit(min(undef_as_zero($Global::exitstatus),101)); + } +} + +sub __PIPE_MODE__ {} + +sub pipepart_setup { + # Compute the blocksize + # Generate the commands to extract the blocks + # Push the commands on queue + # Changes: + # @Global::cat_prepends + # $Global::JobQueue + if($opt::tee) { + # Prepend each command with + # < file + my $cat_string = "< ".::shell_quote_scalar($opt::a[0]); + for(1..$Global::JobQueue->total_jobs()) { + push @Global::cat_appends, $cat_string; + push @Global::cat_prepends, ""; + } + } else { + if(not $opt::blocksize) { + # --blocksize with 10 jobs per jobslot + $opt::blocksize = -10; + } + if($opt::roundrobin) { + # --blocksize with 1 job per jobslot + $opt::blocksize = -1; + } + if($opt::blocksize < 0) { + my $size = 0; + # Compute size of -a + for(@opt::a) { + if(-f $_) { + $size += -s $_; + } elsif(-b $_) { + $size += size_of_block_dev($_); + } else { + ::error("$_ is neither a file nor a block device"); + wait_and_exit(255); + } + } + # Run in total $job_slots*(- $blocksize) jobs + # Set --blocksize = size / no of proc / (- $blocksize) + $Global::dummy_jobs = 1; + $Global::blocksize = 1 + + int($size / max_jobs_running() / -$opt::blocksize); + } + @Global::cat_prepends = map { pipe_part_files($_) } @opt::a; + # Unget the empty arg as many times as there are parts + $Global::JobQueue->{'commandlinequeue'}{'arg_queue'}->unget( + map { [Arg->new("\0")] } @Global::cat_prepends + ); + } +} + +sub pipe_tee_setup { + # Create temporary fifos + # Run 'tee fifo1 fifo2 fifo3 ... fifoN' in the background + # This will spread the input to fifos + # Generate commands that reads from fifo1..N: + # cat fifo | user_command + # Changes: + # @Global::cat_prepends + my @fifos; + for(1..$Global::JobQueue->total_jobs()) { + push @fifos, tmpfifo(); + } + # cat foo | tee fifo1 fifo2 fifo3 fifo4 fifo5 > /dev/null + if(not fork()){ + # Let tee inherit our stdin + # and redirect stdout to null + open STDOUT, ">","/dev/null"; + exec "tee",@fifos; + } + # For each fifo + # (rm fifo1; grep 1) < fifo1 + # (rm fifo2; grep 2) < fifo2 + # (rm fifo3; grep 3) < fifo3 + # Remove the tmpfifo as soon as it is open + @Global::cat_prepends = map { "(rm $_;" } @fifos; + @Global::cat_appends = map { ") < $_" } @fifos; +} + +sub pipe_part_files { + # Given the bigfile + # find header and split positions + # make commands that 'cat's the partial file + # Input: + # $file = the file to read + # Returns: + # @commands that will cat_partial each part + my ($file) = @_; + my $buf = ""; + if(not -f $file and not -b $file) { + ::error("$file is not a seekable file."); + ::wait_and_exit(255); + } + my $header = find_header(\$buf,open_or_exit($file)); + # find positions + my @pos = find_split_positions($file,$Global::blocksize,length $header); + # Make @cat_prepends + my @cat_prepends = (); + for(my $i=0; $i<$#pos; $i++) { + push(@cat_prepends, + cat_partial($file, 0, length($header), $pos[$i], $pos[$i+1])); + } + return @cat_prepends; +} + +sub find_header { + # Compute the header based on $opt::header + # Input: + # $buf_ref = reference to read-in buffer + # $fh = filehandle to read from + # Uses: + # $opt::header + # $Global::blocksize + # Returns: + # $header string + my ($buf_ref, $fh) = @_; + my $header = ""; + if($opt::header) { + if($opt::header eq ":") { $opt::header = "(.*\n)"; } + # Number = number of lines + $opt::header =~ s/^(\d+)$/"(.*\n)"x$1/e; + while(read($fh,substr($$buf_ref,length $$buf_ref,0),$Global::blocksize)) { + if($$buf_ref=~s/^($opt::header)//) { + $header = $1; + last; + } + } + } + return $header; +} + +sub find_split_positions { + # Find positions in bigfile where recend is followed by recstart + # Input: + # $file = the file to read + # $block = (minimal) --block-size of each chunk + # $headerlen = length of header to be skipped + # Uses: + # $opt::recstart + # $opt::recend + # Returns: + # @positions of block start/end + my($file, $block, $headerlen) = @_; + my $size = -s $file; + if(-b $file) { + # $file is a blockdevice + $size = size_of_block_dev($file); + } + $block = int $block; + # The optimal dd blocksize for mint, redhat, solaris, openbsd = 2^17..2^20 + # The optimal dd blocksize for freebsd = 2^15..2^17 + my $dd_block_size = 131072; # 2^17 + my @pos; + my ($recstart,$recend) = recstartrecend(); + my $recendrecstart = $recend.$recstart; + my $fh = ::open_or_exit($file); + push(@pos,$headerlen); + for(my $pos = $block+$headerlen; $pos < $size; $pos += $block) { + my $buf; + if($recendrecstart eq "") { + # records ends anywhere + push(@pos,$pos); + } else { + # Seek the the block start + seek($fh, $pos, 0) || die; + while(read($fh,substr($buf,length $buf,0),$dd_block_size)) { + if($opt::regexp) { + # If match /$recend$recstart/ => Record position + if($buf =~ /^(.*$recend)$recstart/os) { + # Start looking for next record _after_ this match + $pos += length($1); + push(@pos,$pos); + last; + } + } else { + # If match $recend$recstart => Record position + # TODO optimize to only look at the appended + # $dd_block_size + len $recendrecstart + # TODO increase $dd_block_size to optimize for longer records + my $i = index64(\$buf,$recendrecstart); + if($i != -1) { + # Start looking for next record _after_ this match + $pos += $i + length($recend); + push(@pos,$pos); + last; + } + } + } + } + } + if($pos[$#pos] != $size) { + # Last splitpoint was not at end of the file: add it + push(@pos,$size); + } + close $fh; + return @pos; +} + +sub cat_partial { + # Efficient command to copy from byte X to byte Y + # Input: + # $file = the file to read + # ($start, $end, [$start2, $end2, ...]) = start byte, end byte + # Returns: + # Efficient command to copy $start..$end, $start2..$end2, ... to stdout + my($file, @start_end) = @_; + my($start, $i); + # Convert (start,end) to (start,len) + my @start_len = map { + if(++$i % 2) { $start = $_; } else { $_-$start } + } @start_end; + # This can read 7 GB/s using a single core + my $script = spacefree + (0, + q{ + while(@ARGV) { + sysseek(STDIN,shift,0) || die; + $left = shift; + while($read = + sysread(STDIN,$buf, $left > 131072 ? 131072 : $left)){ + $left -= $read; + syswrite(STDOUT,$buf); + } + } + }); + return "<". shell_quote_scalar($file) . + " perl -e '$script' @start_len |"; +} + +sub spreadstdin { + # read a record + # Spawn a job and print the record to it. + # Uses: + # $Global::blocksize + # STDIN + # $opt::r + # $Global::max_lines + # $Global::max_number_of_args + # $opt::regexp + # $Global::start_no_new_jobs + # $opt::roundrobin + # %Global::running + # Returns: N/A + + if($opt::tee) { + # Spawn all jobs + # read a record + # Write record to all jobs + if(not $Global::JobQueue->empty()) { + ::error("--tee requres --jobs to be higher. Try --jobs 0."); + } + } + + my $buf = ""; + my ($recstart,$recend) = recstartrecend(); + my $recendrecstart = $recend.$recstart; + my $chunk_number = 1; + my $one_time_through; + my $two_gb = 2**31-1; + my $blocksize = $Global::blocksize; + my $in = *STDIN; + my $header = find_header(\$buf,$in); + while(1) { + my $anything_written = 0; + my $buflen = length $buf; + my $readsize = ($buflen < $blocksize) ? $blocksize-$buflen : $blocksize; + # If $buf < $blocksize, append so it is $blocksize long after reading. + # Otherwise append a full $blocksize + if(not read($in,substr($buf,$buflen,0),$readsize)) { + # End-of-file + $chunk_number != 1 and last; + # Force the while-loop once if everything was read by header reading + $one_time_through++ and last; + } + if($opt::r) { + # Remove empty lines + $buf =~ s/^\s*\n//gm; + if(length $buf == 0) { + next; + } + } + if($Global::max_lines and not $Global::max_number_of_args) { + # Read n-line records + my $n_lines = $buf =~ tr/\n/\n/; + my $last_newline_pos = rindex64(\$buf,"\n"); + # Go backwards until there are full n-line records + while($n_lines % $Global::max_lines) { + $n_lines--; + $last_newline_pos = rindex64(\$buf,"\n",$last_newline_pos-1); + } + # Chop at $last_newline_pos as that is where n-line record ends + $anything_written += + write_record_to_pipe($chunk_number++,\$header,\$buf, + $recstart,$recend,$last_newline_pos+1); + shorten(\$buf,$last_newline_pos+1); + } elsif($opt::regexp) { + if($Global::max_number_of_args) { + # -N => (start..*?end){n} + # -L -N => (start..*?end){n*l} + my $read_n_lines = -1+ + $Global::max_number_of_args * ($Global::max_lines || 1); + # (?!negative lookahead) is needed to avoid backtracking + # See: https://unix.stackexchange.com/questions/439356/ + while($buf =~ /# From start up till recend + ^((?:(?!$recend$recstart).)*?$recend + # Then n-1 times recstart.*recend + (?:$recstart(?:(?!$recend$recstart).)*?$recend){$read_n_lines}) + # Followed by recstart + (?=$recstart)/osx) { + $anything_written += + write_record_to_pipe($chunk_number++,\$header,\$buf, + $recstart,$recend,length $1); + shorten(\$buf,length $1); + } + } else { + eof($in) and last; + # Find the last recend-recstart in $buf + if($buf =~ /^(.*$recend)$recstart.*?$/os) { + $anything_written += + write_record_to_pipe($chunk_number++,\$header,\$buf, + $recstart,$recend,length $1); + shorten(\$buf,length $1); + } + } + } elsif($opt::csv) { + # Read a full CSV record + # even number of " + end of line + my $last_newline_pos = length $buf; + do { + # find last EOL + $last_newline_pos = rindex64(\$buf,"\n",$last_newline_pos-1); + # While uneven " + } while((substr($buf,0,$last_newline_pos) =~ y/"/"/)%2 + and $last_newline_pos >= 0); + # Chop at $last_newline_pos as that is where CSV record ends + $anything_written += + write_record_to_pipe($chunk_number++,\$header,\$buf, + $recstart,$recend,$last_newline_pos+1); + shorten(\$buf,$last_newline_pos+1); + } else { + if($Global::max_number_of_args) { + # -N => (start..*?end){n} + my $i = 0; + my $read_n_lines = + $Global::max_number_of_args * ($Global::max_lines || 1); + while(($i = nindex(\$buf,$recendrecstart,$read_n_lines)) != -1) { + $i += length $recend; # find the actual splitting location + $anything_written += + write_record_to_pipe($chunk_number++,\$header,\$buf, + $recstart,$recend,$i); + shorten(\$buf,$i); + } + } else { + eof($in) and last; + # Find the last recend+recstart in $buf + my $i = rindex64(\$buf,$recendrecstart); + if($i != -1) { + $i += length $recend; # find the actual splitting location + $anything_written += + write_record_to_pipe($chunk_number++,\$header,\$buf, + $recstart,$recend,$i); + shorten(\$buf,$i); + } + } + } + if(not $anything_written + and not eof($in) + and not $Global::no_autoexpand_block) { + # Nothing was written - maybe the block size < record size? + # Increase blocksize exponentially up to 2GB-1 (2GB causes problems) + if($blocksize < $two_gb) { + my $old_blocksize = $blocksize; + $blocksize = ::min(ceil($blocksize * 1.3 + 1), $two_gb); + ::warning("A record was longer than $old_blocksize. " . + "Increasing to --blocksize $blocksize."); + } + } + } + ::debug("init", "Done reading input\n"); + + # If there is anything left in the buffer write it + write_record_to_pipe($chunk_number++, \$header, \$buf, $recstart, + $recend, length $buf); + + if($opt::retries) { + $Global::no_more_input = 1; + # We need to start no more jobs: At most we need to retry some + # of the already running. + my @running = values %Global::running; + # Stop any virgins. + for my $job (@running) { + if(defined $job and $job->virgin()) { + close $job->fh(0,"w"); + } + } + # Wait for running jobs to be done + my $sleep =1; + while($Global::total_running > 0) { + $sleep = ::reap_usleep($sleep); + } + } + $Global::start_no_new_jobs ||= 1; + if($opt::roundrobin) { + # Flush blocks to roundrobin procs + my $sleep = 1; + while(%Global::running) { + my $something_written = 0; + for my $job (values %Global::running) { + if($job->block_length()) { + $something_written += $job->non_blocking_write(); + } else { + close $job->fh(0,"w"); + } + } + if($something_written) { + $sleep = $sleep/2+0.001; + } + $sleep = ::reap_usleep($sleep); + } + } +} + +sub recstartrecend { + # Uses: + # $opt::recstart + # $opt::recend + # Returns: + # $recstart,$recend with default values and regexp conversion + my($recstart,$recend); + if(defined($opt::recstart) and defined($opt::recend)) { + # If both --recstart and --recend is given then both must match + $recstart = $opt::recstart; + $recend = $opt::recend; + } elsif(defined($opt::recstart)) { + # If --recstart is given it must match start of record + $recstart = $opt::recstart; + $recend = ""; + } elsif(defined($opt::recend)) { + # If --recend is given then it must match end of record + $recstart = ""; + $recend = $opt::recend; + } + + if($opt::regexp) { + # If $recstart/$recend contains '|' this should only apply to the regexp + $recstart = "(?:".$recstart.")"; + $recend = "(?:".$recend.")"; + } else { + # $recstart/$recend = printf strings (\n) + $recstart =~ s/\\([0rnt\'\"\\])/"qq|\\$1|"/gee; + $recend =~ s/\\([0rnt\'\"\\])/"qq|\\$1|"/gee; + } + return ($recstart,$recend); +} + +sub nindex { + # See if string is in buffer N times + # Returns: + # the position where the Nth copy is found + my ($buf_ref, $str, $n) = @_; + my $i = 0; + for(1..$n) { + $i = index64($buf_ref,$str,$i+1); + if($i == -1) { last } + } + return $i; +} + +{ + my @robin_queue; + my $sleep = 1; + + sub round_robin_write { + # Input: + # $header_ref = ref to $header string + # $block_ref = ref to $block to be written + # $recstart = record start string + # $recend = record end string + # $endpos = end position of $block + # Uses: + # %Global::running + # Returns: + # $something_written = amount of bytes written + my ($header_ref,$buffer_ref,$recstart,$recend,$endpos) = @_; + my $written = 0; + my $block_passed = 0; + while(not $block_passed) { + # Continue flushing existing buffers + # until one is empty and a new block is passed + if(@robin_queue) { + # Rotate queue once so new blocks get a fair chance + # to be given to another block + push @robin_queue, shift @robin_queue; + } else { + # Make a queue to spread the blocks evenly + push @robin_queue, (sort { $a->seq() <=> $b->seq() } + values %Global::running); + } + if($opt::keeporder) { + for my $job (@robin_queue) { + if($job->block_length() > 0) { + $written += $job->non_blocking_write(); + } else { + $job->set_block($header_ref,$buffer_ref,$endpos,$recstart,$recend); + $block_passed = 1; + $job->set_virgin(0); + $written += $job->non_blocking_write(); + last; + } + } + } else { + do { + $written = 0; + for my $job (@robin_queue) { + if($job->block_length() > 0) { + $written += $job->non_blocking_write(); + } else { + $job->set_block($header_ref,$buffer_ref, + $endpos,$recstart,$recend); + $block_passed = 1; + $job->set_virgin(0); + $written += $job->non_blocking_write(); + last; + } + } + if($written) { + $sleep = $sleep/1.5+0.001; + } + } while($written and not $block_passed); + } + $sleep = ::reap_usleep($sleep); + } + return $written; + } +} + +sub index64 { + # Do index on strings > 2GB. + # index in Perl < v5.22 does not work for > 2GB + # Input: + # as index except STR which must be passed as a reference + # Output: + # as index + my $ref = shift; + my $match = shift; + my $pos = shift || 0; + my $block_size = 2**31-1; + my $strlen = length($$ref); + # No point in doing extra work if we don't need to. + if($strlen < $block_size or $] > 5.022) { + return index($$ref, $match, $pos); + } + + my $matchlen = length($match); + my $ret; + my $offset = $pos; + while($offset < $strlen) { + $ret = index( + substr($$ref, $offset, $block_size), + $match, $pos-$offset); + if($ret != -1) { + return $ret + $offset; + } + $offset += ($block_size - $matchlen - 1); + } + return -1; +} + +sub rindex64 { + # Do rindex on strings > 2GB. + # rindex in Perl < v5.22 does not work for > 2GB + # Input: + # as rindex except STR which must be passed as a reference + # Output: + # as rindex + my $ref = shift; + my $match = shift; + my $pos = shift; + my $block_size = 2**31-1; + my $strlen = length($$ref); + # Default: search from end + $pos = defined $pos ? $pos : $strlen; + # No point in doing extra work if we don't need to. + if($strlen < $block_size) { + return rindex($$ref, $match, $pos); + } + + my $matchlen = length($match); + my $ret; + my $offset = $pos - $block_size + $matchlen; + if($offset < 0) { + # The offset is less than a $block_size + # Set the $offset to 0 and + # Adjust block_size accordingly + $block_size = $block_size + $offset; + $offset = 0; + } + while($offset >= 0) { + $ret = rindex( + substr($$ref, $offset, $block_size), + $match); + if($ret != -1) { + return $ret + $offset; + } + $offset -= ($block_size - $matchlen - 1); + } + return -1; +} + +sub shorten { + # Do: substr($buf,0,$i) = ""; + # Some Perl versions do not support $i > 2GB, so do this in 2GB chunks + # Input: + # $buf_ref = \$buf + # $i = position to shorten to + # Returns: N/A + my ($buf_ref, $i) = @_; + my $two_gb = 2**31-1; + while($i > $two_gb) { + substr($$buf_ref,0,$two_gb) = ""; + $i -= $two_gb; + } + substr($$buf_ref,0,$i) = ""; +} + +sub write_record_to_pipe { + # Fork then + # Write record from pos 0 .. $endpos to pipe + # Input: + # $chunk_number = sequence number - to see if already run + # $header_ref = reference to header string to prepend + # $buffer_ref = reference to record to write + # $recstart = start string of record + # $recend = end string of record + # $endpos = position in $buffer_ref where record ends + # Uses: + # $Global::job_already_run + # $opt::roundrobin + # @Global::virgin_jobs + # Returns: + # Number of chunks written (0 or 1) + my ($chunk_number,$header_ref,$buffer_ref,$recstart,$recend,$endpos) = @_; + if($endpos == 0) { return 0; } + if(vec($Global::job_already_run,$chunk_number,1)) { return 1; } + if($opt::roundrobin) { + # Write the block to one of the already running jobs + return round_robin_write($header_ref,$buffer_ref,$recstart,$recend,$endpos); + } + # If no virgin found, backoff + my $sleep = 0.0001; # 0.01 ms - better performance on highend + while(not @Global::virgin_jobs) { + ::debug("pipe", "No virgin jobs"); + $sleep = ::reap_usleep($sleep); + # Jobs may not be started because of loadavg + # or too little time between each ssh login + # or retrying failed jobs. + start_more_jobs(); + } + my $job = shift @Global::virgin_jobs; + # Job is no longer virgin + $job->set_virgin(0); + + if($opt::retries) { + # Copy $buffer[0..$endpos] to $job->{'block'} + # Remove rec_sep + # Run $job->add_transfersize + $job->set_block($header_ref,$buffer_ref,$endpos,$recstart,$recend); + if(fork()) { + # Skip + } else { + $job->write($job->block_ref()); + close $job->fh(0,"w"); + exit(0); + } + } else { + # We ignore the removed rec_sep which is technically wrong. + $job->add_transfersize($endpos + length $$header_ref); + if(fork()) { + # Skip + } else { + # Chop of at $endpos as we do not know how many rec_sep will + # be removed. + substr($$buffer_ref,$endpos,length $$buffer_ref) = ""; + # Remove rec_sep + if($opt::remove_rec_sep) { + Job::remove_rec_sep($buffer_ref,$recstart,$recend); + } + $job->write($header_ref); + $job->write($buffer_ref); + close $job->fh(0,"w"); + exit(0); + } + } + close $job->fh(0,"w"); + return 1; +} + + +sub __SEM_MODE__ {} + + +sub acquire_semaphore { + # Acquires semaphore. If needed: spawns to the background + # Uses: + # @Global::host + # Returns: + # The semaphore to be released when jobs is complete + $Global::host{':'} = SSHLogin->new(":"); + my $sem = Semaphore->new($Semaphore::name,$Global::host{':'}->max_jobs_running()); + $sem->acquire(); + if($Semaphore::fg) { + # skip + } else { + if(fork()) { + exit(0); + } else { + # If run in the background, the PID will change + $sem->pid_change(); + } + } + return $sem; +} + + +sub __PARSE_OPTIONS__ {} + + +sub options_hash { + # Returns: + # %hash = the GetOptions config + return + ("debug|D=s" => \$opt::D, + "xargs" => \$opt::xargs, + "m" => \$opt::m, + "X" => \$opt::X, + "v" => \@opt::v, + "sql=s" => \$opt::retired, + "sqlmaster=s" => \$opt::sqlmaster, + "sqlworker=s" => \$opt::sqlworker, + "sqlandworker=s" => \$opt::sqlandworker, + "joblog|jl=s" => \$opt::joblog, + "results|result|res=s" => \$opt::results, + "resume" => \$opt::resume, + "resume-failed|resumefailed" => \$opt::resume_failed, + "retry-failed|retryfailed" => \$opt::retry_failed, + "silent" => \$opt::silent, + "keep-order|keeporder|k" => \$opt::keeporder, + "no-keep-order|nokeeporder|nok|no-k" => \$opt::nokeeporder, + "group" => \$opt::group, + "g" => \$opt::retired, + "ungroup|u" => \$opt::ungroup, + "linebuffer|linebuffered|line-buffer|line-buffered|lb" => \$opt::linebuffer, + "tmux" => \$opt::tmux, + "tmuxpane" => \$opt::tmuxpane, + "null|0" => \$opt::null, + "quote|q" => \$opt::q, + # Replacement strings + "parens=s" => \$opt::parens, + "rpl=s" => \@opt::rpl, + "plus" => \$opt::plus, + "I=s" => \$opt::I, + "extensionreplace|er=s" => \$opt::U, + "U=s" => \$opt::retired, + "basenamereplace|bnr=s" => \$opt::basenamereplace, + "dirnamereplace|dnr=s" => \$opt::dirnamereplace, + "basenameextensionreplace|bner=s" => \$opt::basenameextensionreplace, + "seqreplace=s" => \$opt::seqreplace, + "slotreplace=s" => \$opt::slotreplace, + "jobs|j=s" => \$opt::jobs, + "delay=s" => \$opt::delay, + "sshdelay=f" => \$opt::sshdelay, + "load=s" => \$opt::load, + "noswap" => \$opt::noswap, + "max-line-length-allowed" => \$opt::max_line_length_allowed, + "number-of-cpus" => \$opt::number_of_cpus, + "number-of-cores" => \$opt::number_of_cores, + "use-cpus-instead-of-cores" => \$opt::use_cpus_instead_of_cores, + "shellquote|shell_quote|shell-quote" => \$opt::shellquote, + "nice=i" => \$opt::nice, + "tag" => \$opt::tag, + "tagstring|tag-string=s" => \$opt::tagstring, + "onall" => \$opt::onall, + "nonall" => \$opt::nonall, + "filter-hosts|filterhosts|filter-host" => \$opt::filter_hosts, + "sshlogin|S=s" => \@opt::sshlogin, + "sshloginfile|slf=s" => \@opt::sshloginfile, + "controlmaster|M" => \$opt::controlmaster, + "ssh=s" => \$opt::ssh, + "transfer-file|transferfile|transfer-files|transferfiles|tf=s" + => \@opt::transfer_files, + "return=s" => \@opt::return, + "trc=s" => \@opt::trc, + "transfer" => \$opt::transfer, + "cleanup" => \$opt::cleanup, + "basefile|bf=s" => \@opt::basefile, + "B=s" => \$opt::retired, + "ctrlc|ctrl-c" => \$opt::retired, + "noctrlc|no-ctrlc|no-ctrl-c" => \$opt::retired, + "workdir|work-dir|wd=s" => \$opt::workdir, + "W=s" => \$opt::retired, + "rsync-opts|rsyncopts=s" => \$opt::rsync_opts, + "tmpdir|tempdir=s" => \$opt::tmpdir, + "use-compress-program|compress-program=s" => \$opt::compress_program, + "use-decompress-program|decompress-program=s" => \$opt::decompress_program, + "compress" => \$opt::compress, + "tty" => \$opt::tty, + "T" => \$opt::retired, + "H=i" => \$opt::retired, + "dry-run|dryrun|dr" => \$opt::dryrun, + "progress" => \$opt::progress, + "eta" => \$opt::eta, + "bar" => \$opt::bar, + "shuf" => \$opt::shuf, + "arg-sep|argsep=s" => \$opt::arg_sep, + "arg-file-sep|argfilesep=s" => \$opt::arg_file_sep, + "trim=s" => \$opt::trim, + "env=s" => \@opt::env, + "recordenv|record-env" => \$opt::record_env, + "session" => \$opt::session, + "plain" => \$opt::plain, + "profile|J=s" => \@opt::profile, + "pipe|spreadstdin" => \$opt::pipe, + "robin|round-robin|roundrobin" => \$opt::roundrobin, + "recstart=s" => \$opt::recstart, + "recend=s" => \$opt::recend, + "regexp|regex" => \$opt::regexp, + "remove-rec-sep|removerecsep|rrs" => \$opt::remove_rec_sep, + "files|output-as-files|outputasfiles" => \$opt::files, + "block|block-size|blocksize=s" => \$opt::blocksize, + "tollef" => \$opt::tollef, + "gnu" => \$opt::gnu, + "link|xapply" => \$opt::link, + "linkinputsource|xapplyinputsource=i" => \@opt::linkinputsource, + "bibtex|citation" => \$opt::citation, + "wc|willcite|will-cite|nn|nonotice|no-notice" => \$opt::willcite, + # Termination and retries + "halt-on-error|halt=s" => \$opt::halt, + "limit=s" => \$opt::limit, + "memfree=s" => \$opt::memfree, + "retries=s" => \$opt::retries, + "timeout=s" => \$opt::timeout, + "termseq|term-seq=s" => \$opt::termseq, + # xargs-compatibility - implemented, man, testsuite + "max-procs|P=s" => \$opt::jobs, + "delimiter|d=s" => \$opt::d, + "max-chars|s=i" => \$opt::max_chars, + "arg-file|a=s" => \@opt::a, + "no-run-if-empty|r" => \$opt::r, + "replace|i:s" => \$opt::i, + "E=s" => \$opt::eof, + "eof|e:s" => \$opt::eof, + "max-args|maxargs|n=i" => \$opt::max_args, + "max-replace-args|N=i" => \$opt::max_replace_args, + "colsep|col-sep|C=s" => \$opt::colsep, + "csv"=> \$opt::csv, + "help|h" => \$opt::help, + "L=f" => \$opt::L, + "max-lines|l:f" => \$opt::max_lines, + "interactive|p" => \$opt::interactive, + "verbose|t" => \$opt::verbose, + "version|V" => \$opt::version, + "minversion|min-version=i" => \$opt::minversion, + "show-limits|showlimits" => \$opt::show_limits, + "exit|x" => \$opt::x, + # Semaphore + "semaphore" => \$opt::semaphore, + "semaphoretimeout|st=i" => \$opt::semaphoretimeout, + "semaphorename|id=s" => \$opt::semaphorename, + "fg" => \$opt::fg, + "bg" => \$opt::bg, + "wait" => \$opt::wait, + # Shebang #!/usr/bin/parallel --shebang + "shebang|hashbang" => \$opt::shebang, + "internal-pipe-means-argfiles" => \$opt::internal_pipe_means_argfiles, + "Y" => \$opt::retired, + "skip-first-line" => \$opt::skip_first_line, + "bug" => \$opt::bug, + "header=s" => \$opt::header, + "cat" => \$opt::cat, + "fifo" => \$opt::fifo, + "pipepart|pipe-part" => \$opt::pipepart, + "tee" => \$opt::tee, + "hgrp|hostgrp|hostgroup|hostgroups" => \$opt::hostgroups, + "embed" => \$opt::embed, + ); +} + +sub get_options_from_array { + # Run GetOptions on @array + # Input: + # $array_ref = ref to @ARGV to parse + # @keep_only = Keep only these options + # Uses: + # @ARGV + # Returns: + # true if parsing worked + # false if parsing failed + # @$array_ref is changed + my ($array_ref, @keep_only) = @_; + if(not @$array_ref) { + # Empty array: No need to look more at that + return 1; + } + # A bit of shuffling of @ARGV needed as GetOptionsFromArray is not + # supported everywhere + my @save_argv; + my $this_is_ARGV = (\@::ARGV == $array_ref); + if(not $this_is_ARGV) { + @save_argv = @::ARGV; + @::ARGV = @{$array_ref}; + } + # If @keep_only set: Ignore all values except @keep_only + my %options = options_hash(); + if(@keep_only) { + my (%keep,@dummy); + @keep{@keep_only} = @keep_only; + for my $k (grep { not $keep{$_} } keys %options) { + # Store the value of the option in @dummy + $options{$k} = \@dummy; + } + } + my $retval = GetOptions(%options); + if(not $this_is_ARGV) { + @{$array_ref} = @::ARGV; + @::ARGV = @save_argv; + } + return $retval; +} + +sub parse_options { + # Returns: N/A + init_globals(); + my @argv_before = @ARGV; + @ARGV = read_options(); + + if(defined $opt::citation) { + citation(\@argv_before,\@ARGV); + wait_and_exit(0); + } + # no-* overrides * + if($opt::nokeeporder) { $opt::keeporder = undef; } + + if(@opt::v) { $Global::verbose = $#opt::v+1; } # Convert -v -v to v=2 + if($opt::bug) { ::die_bug("test-bug"); } + $Global::debug = $opt::D; + $Global::shell = $ENV{'PARALLEL_SHELL'} || parent_shell($$) + || $ENV{'SHELL'} || "/bin/sh"; + if(not -x $Global::shell and not which($Global::shell)) { + ::error("Shell '$Global::shell' not found."); + wait_and_exit(255); + } + ::debug("init","Global::shell $Global::shell\n"); + $Global::cshell = $Global::shell =~ m:(/[-a-z]*)?csh:; + if(defined $opt::X) { $Global::ContextReplace = 1; } + if(defined $opt::silent) { $Global::verbose = 0; } + if(defined $opt::null) { $/ = "\0"; } + if(defined $opt::d) { $/ = unquote_printf($opt::d) } + if(defined $opt::tagstring) { + $opt::tagstring = unquote_printf($opt::tagstring); + } + if(defined $opt::interactive) { $Global::interactive = $opt::interactive; } + if(defined $opt::q) { $Global::quoting = 1; } + if(defined $opt::r) { $Global::ignore_empty = 1; } + if(defined $opt::verbose) { $Global::stderr_verbose = 1; } + parse_replacement_string_options(); + if(defined $opt::eof) { $Global::end_of_file_string = $opt::eof; } + if(defined $opt::max_args) { + $Global::max_number_of_args = $opt::max_args; + } + if(defined $opt::timeout) { + $Global::timeoutq = TimeoutQueue->new($opt::timeout); + } + if(defined $opt::tmpdir) { $ENV{'TMPDIR'} = $opt::tmpdir; } + $ENV{'PARALLEL_RSYNC_OPTS'} = $opt::rsync_opts || + $ENV{'PARALLEL_RSYNC_OPTS'} || '-rlDzR'; + $opt::nice ||= 0; + if(defined $opt::help) { usage(); exit(0); } + if(defined $opt::embed) { embed(); exit(0); } + if(defined $opt::sqlandworker) { + $opt::sqlmaster = $opt::sqlworker = $opt::sqlandworker; + } + if(defined $opt::tmuxpane) { $opt::tmux = $opt::tmuxpane; } + if(defined $opt::colsep) { $Global::trim = 'lr'; } + if(defined $opt::csv) { + $Global::use{"Text::CSV"} ||= eval "use Text::CSV; 1;"; + $opt::colsep = defined $opt::colsep ? $opt::colsep : ","; + my $csv_setting = { binary => 1, sep_char => $opt::colsep }; + my $sep = $csv_setting->{sep_char}; + $Global::csv = Text::CSV->new($csv_setting) + or die "Cannot use CSV: ".Text::CSV->error_diag (); + } + if(defined $opt::header) { + $opt::colsep = defined $opt::colsep ? $opt::colsep : "\t"; + } + if(defined $opt::trim) { $Global::trim = $opt::trim; } + if(defined $opt::arg_sep) { $Global::arg_sep = $opt::arg_sep; } + if(defined $opt::arg_file_sep) { + $Global::arg_file_sep = $opt::arg_file_sep; + } + if(defined $opt::number_of_cpus) { + print SSHLogin::no_of_cpus(),"\n"; wait_and_exit(0); + } + if(defined $opt::number_of_cores) { + print SSHLogin::no_of_cores(),"\n"; wait_and_exit(0); + } + if(defined $opt::max_line_length_allowed) { + print Limits::Command::real_max_length(),"\n"; wait_and_exit(0); + } + if(defined $opt::version) { version(); wait_and_exit(0); } + if(defined $opt::record_env) { record_env(); wait_and_exit(0); } + if(defined $opt::show_limits) { show_limits(); } + if(@opt::sshlogin) { @Global::sshlogin = @opt::sshlogin; } + if(@opt::sshloginfile) { read_sshloginfiles(@opt::sshloginfile); } + if(@opt::return) { push @Global::ret_files, @opt::return; } + if($opt::transfer) { + push @Global::transfer_files, $opt::i || $opt::I || "{}"; + } + push @Global::transfer_files, @opt::transfer_files; + if(not defined $opt::recstart and + not defined $opt::recend) { $opt::recend = "\n"; } + $Global::blocksize = multiply_binary_prefix($opt::blocksize || "1M"); + if($Global::blocksize > 2**31-1 and not $opt::pipepart) { + warning("--blocksize >= 2G causes problems. Using 2G-1."); + $Global::blocksize = 2**31-1; + } + if($^O eq "cygwin" and + ($opt::pipe or $opt::pipepart or $opt::roundrobin) + and $Global::blocksize > 65535) { + warning("--blocksize >= 64K causes problems on Cygwin."); + } + $opt::memfree = multiply_binary_prefix($opt::memfree); + check_invalid_option_combinations(); + if((defined $opt::fifo or defined $opt::cat) + and not $opt::pipepart) { + $opt::pipe = 1; + } + if(defined $opt::minversion) { + print $Global::version,"\n"; + if($Global::version < $opt::minversion) { + wait_and_exit(255); + } else { + wait_and_exit(0); + } + } + if(not defined $opt::delay) { + # Set --delay to --sshdelay if not set + $opt::delay = $opt::sshdelay; + } + $opt::delay = multiply_time_units($opt::delay); + if($opt::compress_program) { + $opt::compress = 1; + $opt::decompress_program ||= $opt::compress_program." -dc"; + } + + if(defined $opt::results) { + # Is the output a dir or CSV-file? + if($opt::results =~ /\.csv$/i) { + # CSV with , as separator + $Global::csvsep = ","; + $Global::membuffer ||= 1; + } elsif($opt::results =~ /\.tsv$/i) { + # CSV with TAB as separator + $Global::csvsep = "\t"; + $Global::membuffer ||= 1; + } + } + if($opt::compress) { + my ($compress, $decompress) = find_compression_program(); + $opt::compress_program ||= $compress; + $opt::decompress_program ||= $decompress; + if(($opt::results and not $Global::csvsep) or $opt::files) { + # No need for decompressing + $opt::decompress_program = "cat >/dev/null"; + } + } + if(defined $opt::dryrun) { + # Force grouping due to bug #51039: --dry-run --timeout 3600 -u breaks + $opt::ungroup = 0; + $opt::group = 1; + } + if(defined $opt::nonall) { + # Append a dummy empty argument if there are no arguments + # on the command line to avoid reading from STDIN. + # arg_sep = random 50 char + # \0 => nothing (not the empty string) + $Global::arg_sep = join "", + map { (0..9,"a".."z","A".."Z")[rand(62)] } (1..50); + push @ARGV, $Global::arg_sep, "\0"; + } + if(defined $opt::tee) { + if(not defined $opt::jobs) { + $opt::jobs = 0; + } + } + if(defined $opt::tty) { + # Defaults for --tty: -j1 -u + # Can be overridden with -jXXX -g + if(not defined $opt::jobs) { + $opt::jobs = 1; + } + if(not defined $opt::group) { + $opt::ungroup = 1; + } + } + if(@opt::trc) { + push @Global::ret_files, @opt::trc; + if(not @Global::transfer_files) { + # Defaults to --transferfile {} + push @Global::transfer_files, $opt::i || $opt::I || "{}"; + } + $opt::cleanup = 1; + } + if(defined $opt::max_lines) { + if($opt::max_lines eq "-0") { + # -l -0 (swallowed -0) + $opt::max_lines = 1; + $opt::null = 1; + $/ = "\0"; + } elsif ($opt::max_lines == 0) { + # If not given (or if 0 is given) => 1 + $opt::max_lines = 1; + } + $Global::max_lines = $opt::max_lines; + if(not $opt::pipe) { + # --pipe -L means length of record - not max_number_of_args + $Global::max_number_of_args ||= $Global::max_lines; + } + } + + # Read more than one arg at a time (-L, -N) + if(defined $opt::L) { + $Global::max_lines = $opt::L; + if(not $opt::pipe) { + # --pipe -L means length of record - not max_number_of_args + $Global::max_number_of_args ||= $Global::max_lines; + } + } + if(defined $opt::max_replace_args) { + $Global::max_number_of_args = $opt::max_replace_args; + $Global::ContextReplace = 1; + } + if((defined $opt::L or defined $opt::max_replace_args) + and + not ($opt::xargs or $opt::m)) { + $Global::ContextReplace = 1; + } + if(defined $opt::tag and not defined $opt::tagstring) { + # Default = {} + $opt::tagstring = $Global::parensleft.$Global::parensright; + } + if(grep /^$Global::arg_sep\+?$|^$Global::arg_file_sep\+?$/o, @ARGV) { + # Deal with ::: :::+ :::: and ::::+ + @ARGV = read_args_from_command_line(); + } + parse_semaphore(); + + if(defined $opt::eta) { $opt::progress = $opt::eta; } + if(defined $opt::bar) { $opt::progress = $opt::bar; } + citation_notice(); + + parse_halt(); + parse_sshlogin(); + + if(remote_hosts() and ($opt::X or $opt::m or $opt::xargs)) { + # As we do not know the max line length on the remote machine + # long commands generated by xargs may fail + # If $opt::max_replace_args is set, it is probably safe + ::warning("Using -X or -m with --sshlogin may fail."); + } + + if(not defined $opt::jobs) { $opt::jobs = "100%"; } + open_joblog(); + open_csv(); + if($opt::sqlmaster or $opt::sqlworker) { + $Global::sql = SQL->new($opt::sqlmaster || $opt::sqlworker); + } + if($opt::sqlworker) { $Global::membuffer ||= 1; } +} + +sub check_invalid_option_combinations { + if(defined $opt::timeout and + $opt::timeout !~ /^\d+(\.\d+)?%?$|^(\d+(\.\d+)?[dhms])+$/i) { + ::error("--timeout must be seconds or percentage."); + wait_and_exit(255); + } + if(defined $opt::fifo and defined $opt::cat) { + ::error("--fifo cannot be combined with --cat."); + ::wait_and_exit(255); + } + if(defined $opt::retries and defined $opt::roundrobin) { + ::error("--retries cannot be combined with --roundrobin."); + ::wait_and_exit(255); + } + if(defined $opt::pipepart and + (defined $opt::L or defined $opt::max_lines + or defined $opt::max_replace_args)) { + ::error("--pipepart is incompatible with --max-replace-args, ". + "--max-lines, and -L."); + wait_and_exit(255); + } + if(defined $opt::group and $opt::ungroup) { + ::error("--group cannot be combined with --ungroup."); + ::wait_and_exit(255); + } + if(defined $opt::group and $opt::linebuffer) { + ::error("--group cannot be combined with --line-buffer."); + ::wait_and_exit(255); + } + if(defined $opt::ungroup and $opt::linebuffer) { + ::error("--ungroup cannot be combined with --line-buffer."); + ::wait_and_exit(255); + } + if(defined $opt::tollef and not $opt::gnu) { + ::error("--tollef has been retired.", + "Remove --tollef or use --gnu to override --tollef."); + ::wait_and_exit(255); + } + if(defined $opt::retired) { + ::error("-g has been retired. Use --group.", + "-B has been retired. Use --bf.", + "-T has been retired. Use --tty.", + "-U has been retired. Use --er.", + "-W has been retired. Use --wd.", + "-Y has been retired. Use --shebang.", + "-H has been retired. Use --halt.", + "--sql has been retired. Use --sqlmaster.", + "--ctrlc has been retired.", + "--noctrlc has been retired."); + ::wait_and_exit(255); + } +} + +sub init_globals { + # Defaults: + $Global::version = 20180622; + $Global::progname = 'parallel'; + $Global::infinity = 2**31; + $Global::debug = 0; + $Global::verbose = 0; + $Global::quoting = 0; + $Global::total_completed = 0; + # Read only table with default --rpl values + %Global::replace = + ( + '{}' => '', + '{#}' => '1 $_=$job->seq()', + '{%}' => '1 $_=$job->slot()', + '{/}' => 's:.*/::', + '{//}' => + ('$Global::use{"File::Basename"} ||= eval "use File::Basename; 1;"; '. + '$_ = dirname($_);'), + '{/.}' => 's:.*/::; s:\.[^/.]+$::;', + '{.}' => 's:\.[^/.]+$::', + ); + %Global::plus = + ( + # {} = {+/}/{/} + # = {.}.{+.} = {+/}/{/.}.{+.} + # = {..}.{+..} = {+/}/{/..}.{+..} + # = {...}.{+...} = {+/}/{/...}.{+...} + '{+/}' => 's:/[^/]*$::', + '{+.}' => 's:.*\.::', + '{+..}' => 's:.*\.([^.]*\.):$1:', + '{+...}' => 's:.*\.([^.]*\.[^.]*\.):$1:', + '{..}' => 's:\.[^/.]+$::; s:\.[^/.]+$::', + '{...}' => 's:\.[^/.]+$::; s:\.[^/.]+$::; s:\.[^/.]+$::', + '{/..}' => 's:.*/::; s:\.[^/.]+$::; s:\.[^/.]+$::', + '{/...}' => 's:.*/::; s:\.[^/.]+$::; s:\.[^/.]+$::; s:\.[^/.]+$::', + '{choose_k}' => 'for $t (2..$#arg){ if($arg[$t-1] ge $arg[$t]) { skip() } }', + # {##} = number of jobs + '{##}' => '$_=total_jobs()', + # Bash ${a:-myval} + '{:-([^}]+?)}' => '$_ ||= $$1', + # Bash ${a:2} + '{:(\d+?)}' => 'substr($_,0,$$1) = ""', + # Bash ${a:2:3} + '{:(\d+?):(\d+?)}' => '$_ = substr($_,$$1,$$2);', + # Bash ${a#bc} + '{#([^#}][^}]*?)}' => 's/^$$1//;', + # Bash ${a%def} + '{%([^}]+?)}' => 's/$$1$//;', + # Bash ${a/def/ghi} ${a/def/} + '{/([^}]+?)/([^}]*?)}' => 's/$$1/$$2/;', + # Bash ${a^a} + '{^([^}]+?)}' => 's/^($$1)/uc($1)/e;', + # Bash ${a^^a} + '{^^([^}]+?)}' => 's/($$1)/uc($1)/eg;', + # Bash ${a,A} + '{,([^}]+?)}' => 's/^($$1)/lc($1)/e;', + # Bash ${a,,A} + '{,,([^}]+?)}' => 's/($$1)/lc($1)/eg;', + ); + # Modifiable copy of %Global::replace + %Global::rpl = %Global::replace; + $/ = "\n"; + $Global::ignore_empty = 0; + $Global::interactive = 0; + $Global::stderr_verbose = 0; + $Global::default_simultaneous_sshlogins = 9; + $Global::exitstatus = 0; + $Global::arg_sep = ":::"; + $Global::arg_file_sep = "::::"; + $Global::trim = 'n'; + $Global::max_jobs_running = 0; + $Global::job_already_run = ''; + # LC_ALL workaround for multibyte chars containing special shell chars + $ENV{'LC_ALL'} = 'C'; + $ENV{'TMPDIR'} ||= "/tmp"; + if(not $ENV{HOME}) { + # $ENV{HOME} is sometimes not set if called from PHP + ::warning("\$HOME not set. Using /tmp."); + $ENV{HOME} = "/tmp"; + } + # no warnings to allow for undefined $XDG_* + no warnings 'uninitialized'; + # $xdg_config_home is needed to make env_parallel.fish stop complaining + my $xdg_config_home = $ENV{'XDG_CONFIG_HOME'}; + # config_dirs = $PARALLEL_HOME, $XDG_CONFIG_HOME/parallel, + # $(each XDG_CONFIG_DIRS)/parallel, $HOME/.parallel + # Keep only dirs that exist + @Global::config_dirs = + (grep { -d $_ } + $ENV{'PARALLEL_HOME'}, + (map { "$_/parallel" } + $xdg_config_home, + split /:/, $ENV{'XDG_CONFIG_DIRS'}), + $ENV{'HOME'} . "/.parallel"); + # Use first dir as config dir + $Global::config_dir = $Global::config_dirs[0] || + $ENV{'HOME'} . "/.parallel"; + # cache_dirs = $PARALLEL_HOME, $XDG_CACHE_HOME/parallel, + # Keep only dirs that exist + @Global::cache_dirs = + (grep { -d $_ } + $ENV{'PARALLEL_HOME'}, $ENV{'XDG_CACHE_HOME'}."/parallel"); + $Global::cache_dir = $Global::cache_dirs[0] || + $ENV{'HOME'} . "/.parallel"; +} + +sub parse_halt { + # $opt::halt flavours + # Uses: + # $opt::halt + # $Global::halt_when + # $Global::halt_fail + # $Global::halt_success + # $Global::halt_pct + # $Global::halt_count + if(defined $opt::halt) { + my %halt_expansion = ( + "0" => "never", + "1" => "soon,fail=1", + "2" => "now,fail=1", + "-1" => "soon,success=1", + "-2" => "now,success=1", + ); + # Expand -2,-1,0,1,2 into long form + $opt::halt = $halt_expansion{$opt::halt} || $opt::halt; + # --halt 5% == --halt soon,fail=5% + $opt::halt =~ s/^(\d+)%$/soon,fail=$1%/; + # Split: soon,fail=5% + my ($when,$fail_success,$pct_count) = split /[,=]/, $opt::halt; + if(not grep { $when eq $_ } qw(never soon now)) { + ::error("--halt must have 'never', 'soon', or 'now'."); + ::wait_and_exit(255); + } + $Global::halt_when = $when; + if($when ne "never") { + if($fail_success eq "fail") { + $Global::halt_fail = 1; + } elsif($fail_success eq "success") { + $Global::halt_success = 1; + } elsif($fail_success eq "done") { + $Global::halt_done = 1; + } else { + ::error("--halt $when must be followed by ,success or ,fail."); + ::wait_and_exit(255); + } + if($pct_count =~ /^(\d+)%$/) { + $Global::halt_pct = $1/100; + } elsif($pct_count =~ /^(\d+)$/) { + $Global::halt_count = $1; + } else { + ::error("--halt $when,$fail_success ". + "must be followed by ,number or ,percent%."); + ::wait_and_exit(255); + } + } + } +} + +sub parse_replacement_string_options { + # Deal with --rpl + # Uses: + # %Global::rpl + # $Global::parensleft + # $Global::parensright + # $opt::parens + # $Global::parensleft + # $Global::parensright + # $opt::plus + # %Global::plus + # $opt::I + # $opt::U + # $opt::i + # $opt::basenamereplace + # $opt::dirnamereplace + # $opt::seqreplace + # $opt::slotreplace + # $opt::basenameextensionreplace + + sub rpl { + # Modify %Global::rpl + # Replace $old with $new + my ($old,$new) = @_; + if($old ne $new) { + $Global::rpl{$new} = $Global::rpl{$old}; + delete $Global::rpl{$old}; + } + } + my $parens = "{==}"; + if(defined $opt::parens) { $parens = $opt::parens; } + my $parenslen = 0.5*length $parens; + $Global::parensleft = substr($parens,0,$parenslen); + $Global::parensright = substr($parens,$parenslen); + if(defined $opt::plus) { %Global::rpl = (%Global::plus,%Global::rpl); } + if(defined $opt::I) { rpl('{}',$opt::I); } + if(defined $opt::i and $opt::i) { rpl('{}',$opt::i); } + if(defined $opt::U) { rpl('{.}',$opt::U); } + if(defined $opt::basenamereplace) { rpl('{/}',$opt::basenamereplace); } + if(defined $opt::dirnamereplace) { rpl('{//}',$opt::dirnamereplace); } + if(defined $opt::seqreplace) { rpl('{#}',$opt::seqreplace); } + if(defined $opt::slotreplace) { rpl('{%}',$opt::slotreplace); } + if(defined $opt::basenameextensionreplace) { + rpl('{/.}',$opt::basenameextensionreplace); + } + for(@opt::rpl) { + # Create $Global::rpl entries for --rpl options + # E.g: "{..} s:\.[^.]+$:;s:\.[^.]+$:;" + my ($shorthand,$long) = split/ /,$_,2; + $Global::rpl{$shorthand} = $long; + } +} + +sub parse_semaphore { + # Semaphore defaults + # Must be done before computing number of processes and max_line_length + # because when running as a semaphore GNU Parallel does not read args + # Uses: + # $opt::semaphore + # $Global::semaphore + # $opt::semaphoretimeout + # $Semaphore::timeout + # $opt::semaphorename + # $Semaphore::name + # $opt::fg + # $Semaphore::fg + # $opt::wait + # $Semaphore::wait + # $opt::bg + # @opt::a + # @Global::unget_argv + # $Global::default_simultaneous_sshlogins + # $opt::jobs + # $Global::interactive + $Global::semaphore ||= ($0 =~ m:(^|/)sem$:); # called as 'sem' + if(defined $opt::semaphore) { $Global::semaphore = 1; } + if(defined $opt::semaphoretimeout) { $Global::semaphore = 1; } + if(defined $opt::semaphorename) { $Global::semaphore = 1; } + if(defined $opt::fg and not $opt::tmux and not $opt::tmuxpane) { + $Global::semaphore = 1; + } + if(defined $opt::bg) { $Global::semaphore = 1; } + if(defined $opt::wait and not $opt::sqlmaster) { + $Global::semaphore = 1; @ARGV = "true"; + } + if($Global::semaphore) { + if(@opt::a) { + # A semaphore does not take input from neither stdin nor file + ::error("A semaphore does not take input from neither stdin nor a file\n"); + ::wait_and_exit(255); + } + @opt::a = ("/dev/null"); + # Append a dummy empty argument + # \0 => nothing (not the empty string) + push(@Global::unget_argv, [Arg->new("\0")]); + $Semaphore::timeout = $opt::semaphoretimeout || 0; + if(defined $opt::semaphorename) { + $Semaphore::name = $opt::semaphorename; + } else { + local $/ = "\n"; + $Semaphore::name = `tty`; + chomp $Semaphore::name; + } + $Semaphore::fg = $opt::fg; + $Semaphore::wait = $opt::wait; + $Global::default_simultaneous_sshlogins = 1; + if(not defined $opt::jobs) { + $opt::jobs = 1; + } + if($Global::interactive and $opt::bg) { + ::error("Jobs running in the ". + "background cannot be interactive."); + ::wait_and_exit(255); + } + } +} + +sub record_env { + # Record current %ENV-keys in $PARALLEL_HOME/ignored_vars + # Returns: N/A + my $ignore_filename = $Global::config_dir . "/ignored_vars"; + if(open(my $vars_fh, ">", $ignore_filename)) { + print $vars_fh map { $_,"\n" } keys %ENV; + } else { + ::error("Cannot write to $ignore_filename."); + ::wait_and_exit(255); + } +} + +sub open_joblog { + # Open joblog as specified by --joblog + # Uses: + # $opt::resume + # $opt::resume_failed + # $opt::joblog + # $opt::results + # $Global::job_already_run + # %Global::fd + my $append = 0; + if(($opt::resume or $opt::resume_failed) + and + not ($opt::joblog or $opt::results)) { + ::error("--resume and --resume-failed require --joblog or --results."); + ::wait_and_exit(255); + } + if(defined $opt::joblog and $opt::joblog =~ s/^\+//) { + # --joblog +filename = append to filename + $append = 1; + } + if($opt::joblog + and + ($opt::sqlmaster + or + not $opt::sqlworker)) { + # Do not log if --sqlworker + if($opt::resume || $opt::resume_failed || $opt::retry_failed) { + if(open(my $joblog_fh, "<", $opt::joblog)) { + # Read the joblog + # If there is a header: Open as append later + $append = <$joblog_fh>; + my $joblog_regexp; + if($opt::retry_failed) { + # Make a regexp that only matches commands with exit+signal=0 + # 4 host 1360490623.067 3.445 1023 1222 0 0 command + $joblog_regexp='^(\d+)(?:\t[^\t]+){5}\t0\t0\t'; + my @group; + { + local $/ = "\n"; + while(<$joblog_fh>) { + if(/$joblog_regexp/o) { + # This is 30% faster than set_job_already_run($1); + vec($Global::job_already_run,($1||0),1) = 1; + $Global::total_completed++; + $group[$1-1] = "true"; + } elsif(/(\d+)\s+\S+(\s+[-0-9.]+){6}\s+(.*)$/) { + # Grab out the command + $group[$1-1] = $3; + } else { + chomp; + ::error("Format of '$opt::joblog' is wrong: $_"); + ::wait_and_exit(255); + } + } + } + if(@group) { + my ($outfh,$name) = ::tmpfile(SUFFIX => ".arg"); + unlink($name); + # Put args into argfile + if(grep /\0/, @group) { + # force --null to deal with \n in commandlines + ::warning("Command lines contain newline. Forcing --null."); + $opt::null = 1; + $/ = "\0"; + } + # Replace \0 with '\n' as used in print_joblog() + print $outfh map { s/\0/\n/g; $_,$/ } @group; + seek $outfh, 0, 0; + exit_if_disk_full(); + # Set filehandle to -a + @opt::a = ($outfh); + } + # Remove $command (so -a is run) + @ARGV = (); + } + if($opt::resume || $opt::resume_failed) { + if($opt::resume_failed) { + # Make a regexp that only matches commands with exit+signal=0 + # 4 host 1360490623.067 3.445 1023 1222 0 0 command + $joblog_regexp='^(\d+)(?:\t[^\t]+){5}\t0\t0\t'; + } else { + # Just match the job number + $joblog_regexp='^(\d+)'; + } + while(<$joblog_fh>) { + if(/$joblog_regexp/o) { + # This is 30% faster than set_job_already_run($1); + vec($Global::job_already_run,($1||0),1) = 1; + $Global::total_completed++; + } elsif(not /\d+\s+[^\s]+\s+([-0-9.]+\s+){6}/) { + ::error("Format of '$opt::joblog' is wrong: $_"); + ::wait_and_exit(255); + } + } + } + close $joblog_fh; + } + } + if($opt::dryrun) { + # Do not write to joblog in a dry-run + if(not open($Global::joblog, ">", "/dev/null")) { + ::error("Cannot write to --joblog $opt::joblog."); + ::wait_and_exit(255); + } + } elsif($append) { + # Append to joblog + if(not open($Global::joblog, ">>", $opt::joblog)) { + ::error("Cannot append to --joblog $opt::joblog."); + ::wait_and_exit(255); + } + } else { + if($opt::joblog eq "-") { + # Use STDOUT as joblog + $Global::joblog = $Global::fd{1}; + } elsif(not open($Global::joblog, ">", $opt::joblog)) { + # Overwrite the joblog + ::error("Cannot write to --joblog $opt::joblog."); + ::wait_and_exit(255); + } + print $Global::joblog + join("\t", "Seq", "Host", "Starttime", "JobRuntime", + "Send", "Receive", "Exitval", "Signal", "Command" + ). "\n"; + } + } +} + +sub open_csv { + if($opt::results) { + # Output as CSV/TSV + if($opt::results eq "-.csv" + or + $opt::results eq "-.tsv") { + # Output as CSV/TSV on stdout + open $Global::csv_fh, ">&", "STDOUT" or + ::die_bug("Can't dup STDOUT in csv: $!"); + # Do not print any other output to STDOUT + # by forcing all other output to /dev/null + open my $fd, ">", "/dev/null" or + ::die_bug("Can't >/dev/null in csv: $!"); + $Global::fd{1} = $fd; + $Global::fd{2} = $fd; + } elsif($Global::csvsep) { + if(not open($Global::csv_fh,">",$opt::results)) { + ::error("Cannot open results file `$opt::results': ". + "$!."); + wait_and_exit(255); + } + } + } +} + +sub find_compression_program { + # Find a fast compression program + # Returns: + # $compress_program = compress program with options + # $decompress_program = decompress program with options + + # Search for these. Sorted by speed on 128 core + + # seq 120000000|shuf > 1gb & + # apt-get update + # apt install make g++ htop + # wget -O - pi.dk/3 | bash + # apt install zstd clzip liblz4-tool lzop pigz pxz gzip plzip pbzip2 lzma xz-utils lzip bzip2 lbzip2 lrzip pixz + # git clone https://github.com/facebook/zstd.git + # (cd zstd/contrib/pzstd; make -j; cp pzstd /usr/local/bin) + # echo 'lrzip -L $((-$1))' >/usr/local/bin/lrz + # chmod +x /usr/local/bin/lrz + # wait + # onethread="zstd clzip lz4 lzop gzip lzma xz bzip2" + # multithread="pzstd pigz pxz plzip pbzip2 lzip lbzip2 lrz pixz" + # parallel --shuf -j1 --joblog jl-m --arg-sep , parallel --compress-program \'{3}" "-{2}\' cat ::: 1gb '>'/dev/null , 1 2 3 , {1..3} , $multithread + # parallel --shuf -j50% --delay 1 --joblog jl-s --arg-sep , parallel --compress-program \'{3}" "-{2}\' cat ::: 1gb '>'/dev/null , 1 2 3 , {1..3} , $onethread + # sort -nk4 jl-? + + # 1-core: + # 2-cores: pzstd zstd lz4 lzop pigz gzip lbzip2 pbzip2 lrz bzip2 lzma pxz plzip xz lzip clzip + # 4-cores: + # 8-cores: pzstd lz4 zstd pigz lzop lbzip2 pbzip2 gzip lzip lrz plzip pxz bzip2 lzma xz clzip + # 16-cores: pzstd lz4 pigz lzop lbzip2 pbzip2 plzip lzip lrz pxz gzip lzma xz bzip2 + # 32-cores: pzstd lbzip2 pbzip2 zstd pigz lz4 lzop plzip lzip lrz gzip pxz lzma bzip2 xz clzip + # 64-cores: pzstd lbzip2 pbzip2 pigz zstd pixz lz4 plzip lzop lzip lrz gzip pxz lzma bzip2 xz clzip + # 128-core: pzstd lbzip2 pbzip2 zstd pixz lz4 pigz lzop plzip lzip gzip lrz pxz bzip2 lzma xz clzip + + my @prg = qw(pzstd lbzip2 pbzip2 zstd pixz lz4 pigz lzop plzip lzip gzip + lrz pxz bzip2 lzma xz clzip); + for my $p (@prg) { + if(which($p)) { + return ("$p -c -1","$p -dc"); + } + } + # Fall back to cat + return ("cat","cat"); +} + +sub read_options { + # Read options from command line, profile and $PARALLEL + # Uses: + # $opt::shebang_wrap + # $opt::shebang + # @ARGV + # $opt::plain + # @opt::profile + # $ENV{'HOME'} + # $ENV{'PARALLEL'} + # Returns: + # @ARGV_no_opt = @ARGV without --options + + # This must be done first as this may exec myself + if(defined $ARGV[0] and ($ARGV[0] =~ /^--shebang/ or + $ARGV[0] =~ /^--shebang-?wrap/ or + $ARGV[0] =~ /^--hashbang/)) { + # Program is called from #! line in script + # remove --shebang-wrap if it is set + $opt::shebang_wrap = ($ARGV[0] =~ s/^--shebang-?wrap *//); + # remove --shebang if it is set + $opt::shebang = ($ARGV[0] =~ s/^--shebang *//); + # remove --hashbang if it is set + $opt::shebang .= ($ARGV[0] =~ s/^--hashbang *//); + if($opt::shebang) { + my $argfile = shell_quote_scalar(pop @ARGV); + # exec myself to split $ARGV[0] into separate fields + exec "$0 --skip-first-line -a $argfile @ARGV"; + } + if($opt::shebang_wrap) { + my @options; + my @parser; + if ($^O eq 'freebsd') { + # FreeBSD's #! puts different values in @ARGV than Linux' does. + my @nooptions = @ARGV; + get_options_from_array(\@nooptions); + while($#ARGV > $#nooptions) { + push @options, shift @ARGV; + } + while(@ARGV and $ARGV[0] ne ":::") { + push @parser, shift @ARGV; + } + if(@ARGV and $ARGV[0] eq ":::") { + shift @ARGV; + } + } else { + @options = shift @ARGV; + } + my $script = shell_quote_scalar(shift @ARGV); + # exec myself to split $ARGV[0] into separate fields + exec "$0 --internal-pipe-means-argfiles @options @parser $script ". + "::: @ARGV"; + } + } + if($ARGV[0] =~ / --shebang(-?wrap)? /) { + ::warning("--shebang and --shebang-wrap must be the first argument.\n"); + } + + Getopt::Long::Configure("bundling","require_order"); + my @ARGV_copy = @ARGV; + my @ARGV_orig = @ARGV; + # Check if there is a --profile to set @opt::profile + get_options_from_array(\@ARGV_copy,"profile|J=s","plain") || die_usage(); + my @ARGV_profile = (); + my @ARGV_env = (); + if(not $opt::plain) { + # Add options from $PARALLEL_HOME/config and other profiles + my @config_profiles = ( + "/etc/parallel/config", + (map { "$_/config" } @Global::config_dirs), + $ENV{'HOME'}."/.parallelrc"); + my @profiles = @config_profiles; + if(@opt::profile) { + # --profile overrides default profiles + @profiles = (); + for my $profile (@opt::profile) { + # Look for the $profile in . and @Global::config_dirs + push @profiles, grep { -r $_ } + map { "$_/$profile" } ".", @Global::config_dirs; + } + } + for my $profile (@profiles) { + if(-r $profile) { + local $/ = "\n"; + open (my $in_fh, "<", $profile) || + ::die_bug("read-profile: $profile"); + while(<$in_fh>) { + /^\s*\#/ and next; + chomp; + push @ARGV_profile, shell_words($_); + } + close $in_fh; + } else { + if(grep /^$profile$/, @config_profiles) { + # config file is not required to exist + } else { + ::error("$profile not readable."); + wait_and_exit(255); + } + } + } + # Add options from shell variable $PARALLEL + if($ENV{'PARALLEL'}) { + @ARGV_env = shell_words($ENV{'PARALLEL'}); + } + } + Getopt::Long::Configure("bundling","require_order"); + get_options_from_array(\@ARGV_profile) || die_usage(); + get_options_from_array(\@ARGV_env) || die_usage(); + get_options_from_array(\@ARGV) || die_usage(); + # What were the options given on the command line? + # Used to start --sqlworker + my $ai = arrayindex(\@ARGV_orig, \@ARGV); + @Global::options_in_argv = @ARGV_orig[0..$ai-1]; + # Prepend non-options to @ARGV (such as commands like 'nice') + unshift @ARGV, @ARGV_profile, @ARGV_env; + return @ARGV; +} + +sub arrayindex { + # Similar to Perl's index function, but for arrays + # Input: + # $arr_ref1 = ref to @array1 to search in + # $arr_ref2 = ref to @array2 to search for + my ($arr_ref1,$arr_ref2) = @_; + my $array1_as_string = join "", map { "\0".$_ } @$arr_ref1; + my $array2_as_string = join "", map { "\0".$_ } @$arr_ref2; + my $i = index($array1_as_string,$array2_as_string,0); + if($i == -1) { return -1 } + my @before = split /\0/, substr($array1_as_string,0,$i); + return $#before; +} + +sub read_args_from_command_line { + # Arguments given on the command line after: + # ::: ($Global::arg_sep) + # :::: ($Global::arg_file_sep) + # :::+ ($Global::arg_sep with --link) + # ::::+ ($Global::arg_file_sep with --link) + # Removes the arguments from @ARGV and: + # - puts filenames into -a + # - puts arguments into files and add the files to -a + # - adds --linkinputsource with 0/1 for each -a depending on :::+/::::+ + # Input: + # @::ARGV = command option ::: arg arg arg :::: argfiles + # Uses: + # $Global::arg_sep + # $Global::arg_file_sep + # $opt::internal_pipe_means_argfiles + # $opt::pipe + # @opt::a + # Returns: + # @argv_no_argsep = @::ARGV without ::: and :::: and following args + my @new_argv = (); + for(my $arg = shift @ARGV; @ARGV; $arg = shift @ARGV) { + if($arg eq $Global::arg_sep + or + $arg eq $Global::arg_sep."+" + or + $arg eq $Global::arg_file_sep + or + $arg eq $Global::arg_file_sep."+") { + my $group_sep = $arg; # This group of arguments is args or argfiles + my @group; + while(defined ($arg = shift @ARGV)) { + if($arg eq $Global::arg_sep + or + $arg eq $Global::arg_sep."+" + or + $arg eq $Global::arg_file_sep + or + $arg eq $Global::arg_file_sep."+") { + # exit while loop if finding new separator + last; + } else { + # If not hitting ::: :::+ :::: or ::::+ + # Append it to the group + push @group, $arg; + } + } + my $is_linked = ($group_sep =~ /\+$/) ? 1 : 0; + my $is_file = ($group_sep eq $Global::arg_file_sep + or + $group_sep eq $Global::arg_file_sep."+"); + if($is_file) { + # :::: / ::::+ + push @opt::linkinputsource, map { $is_linked } @group; + } else { + # ::: / :::+ + push @opt::linkinputsource, $is_linked; + } + if($is_file + or ($opt::internal_pipe_means_argfiles and $opt::pipe) + ) { + # Group of file names on the command line. + # Append args into -a + push @opt::a, @group; + } else { + # Group of arguments on the command line. + # Put them into a file. + # Create argfile + my ($outfh,$name) = ::tmpfile(SUFFIX => ".arg"); + unlink($name); + # Put args into argfile + print $outfh map { $_,$/ } @group; + seek $outfh, 0, 0; + exit_if_disk_full(); + # Append filehandle to -a + push @opt::a, $outfh; + } + if(defined($arg)) { + # $arg is ::: :::+ :::: or ::::+ + # so there is another group + redo; + } else { + # $arg is undef -> @ARGV empty + last; + } + } + push @new_argv, $arg; + } + # Output: @ARGV = command to run with options + return @new_argv; +} + +sub cleanup { + # Returns: N/A + unlink keys %Global::unlink; + map { rmdir $_ } keys %Global::unlink; + if(@opt::basefile and $opt::cleanup) { cleanup_basefile(); } + for(keys %Global::sshmaster) { + # If 'ssh -M's are running: kill them + kill "TERM", $_; + } +} + + +sub __QUOTING_ARGUMENTS_FOR_SHELL__ {} + + +sub shell_quote { + # Input: + # @strings = strings to be quoted + # Output: + # @shell_quoted_strings = string quoted with \ as needed by the shell + return wantarray ? + (map { shell_quote_scalar($_) } @_) + : (join" ",map { shell_quote_scalar($_) } @_); +} + +sub shell_quote_scalar_rc { + # Quote for the rc-shell + my $a = $_[0]; + if(defined $a) { + if(($a =~ s/'/''/g) + + + ($a =~ s/[\n\002-\011\013-\032\\\#\?\`\(\)\{\}\[\]\^\*\<\=\>\~\|\; \"\!\$\&\'\202-\377]+/'$&'/go)) { + # A string was replaced + # No need to test for "" or \0 + } elsif($a eq "") { + $a = "''"; + } elsif($a eq "\0") { + $a = ""; + } + } + return $a; +} + +sub shell_quote_scalar_csh { + # Quote for (t)csh + my $a = $_[0]; + if(defined $a) { + # $a =~ s/([\002-\011\013-\032\\\#\?\`\(\)\{\}\[\]\^\*\>\<\~\|\; \"\!\$\&\'\202-\377])/\\$1/g; + # This is 1% faster than the above + if(($a =~ s/[\002-\011\013-\032\\\#\?\`\(\)\{\}\[\]\^\*\<\=\>\~\|\; \"\!\$\&\'\202-\377]/\\$&/go) + + + # quote newline in csh as \\\n + ($a =~ s/[\n]/"\\\n"/go)) { + # A string was replaced + # No need to test for "" or \0 + } elsif($a eq "") { + $a = "''"; + } elsif($a eq "\0") { + $a = ""; + } + } + return $a; +} + +sub shell_quote_scalar_default { + # Quote for other shells + my $a = $_[0]; + if(defined $a) { + # zsh wants '=' quoted + # Solaris sh wants ^ quoted. + # $a =~ s/([\002-\011\013-\032\\\#\?\`\(\)\{\}\[\]\^\*\>\<\~\|\; \"\!\$\&\'\202-\377])/\\$1/g; + # This is 1% faster than the above + if(($a =~ s/[\002-\011\013-\032\\\#\?\`\(\)\{\}\[\]\^\*\<\=\>\~\|\; \"\!\$\&\'\202-\377]/\\$&/go) + + + # quote newline as '\n' + ($a =~ s/[\n]/'\n'/go)) { + # A string was replaced + # No need to test for "" or \0 + } elsif($a eq "") { + $a = "''"; + } elsif($a eq "\0") { + $a = ""; + } + } + return $a; +} + +sub shell_quote_scalar { + # Quote the string so the shell will not expand any special chars + # Inputs: + # $string = string to be quoted + # Returns: + # $shell_quoted = string quoted as needed by the shell + + # Speed optimization: Choose the correct shell_quote_scalar_* + # and call that directly from now on + no warnings 'redefine'; + if($Global::cshell) { + # (t)csh + *shell_quote_scalar = \&shell_quote_scalar_csh; + } elsif($Global::shell =~ m:(^|/)rc$:) { + # rc-shell + *shell_quote_scalar = \&shell_quote_scalar_rc; + } else { + # other shells + *shell_quote_scalar = \&shell_quote_scalar_default; + } + # The sub is now redefined. Call it + return shell_quote_scalar(@_); +} + +sub shell_quote_file { + # Quote the string so shell will not expand any special chars + # and prepend ./ if needed + # Input: + # $filename = filename to be shell quoted + # Returns: + # $quoted_filename = filename quoted with \ and ./ if needed + my $a = shell_quote_scalar(shift); + if(defined $a) { + if($a =~ m:^/: or $a =~ m:^\./:) { + # /abs/path or ./rel/path => skip + } else { + # rel/path => ./rel/path + $a = "./".$a; + } + } + return $a; +} + +sub shell_words { + # Input: + # $string = shell line + # Returns: + # @shell_words = $string split into words as shell would do + $Global::use{"Text::ParseWords"} ||= eval "use Text::ParseWords; 1;"; + return Text::ParseWords::shellwords(@_); +} + +sub perl_quote_scalar { + # Quote the string so perl's eval will not expand any special chars + # Inputs: + # $string = string to be quoted + # Returns: + # $perl_quoted = string quoted with \ as needed by perl's eval + my $a = $_[0]; + if(defined $a) { + $a =~ s/[\\\"\$\@]/\\$&/go; + } + return $a; +} + +sub unquote_printf { + # Convert \t \n \r \000 \0 + $_ = shift; + s/\\t/\t/g; + s/\\n/\n/g; + s/\\r/\r/g; + s/\\(\d\d\d)/eval 'sprintf "\\'.$1.'"'/ge; + s/\\(\d)/eval 'sprintf "\\'.$1.'"'/ge; + return $_; +} + + +sub __FILEHANDLES__ {} + + +sub save_stdin_stdout_stderr { + # Remember the original STDIN, STDOUT and STDERR + # and file descriptors opened by the shell (e.g. 3>/tmp/foo) + # Uses: + # %Global::fd + # $Global::original_stderr + # $Global::original_stdin + # Returns: N/A + + # TODO Disabled until we have an open3 that will take n filehandles + # for my $fdno (1..61) { + # # /dev/fd/62 and above are used by bash for <(cmd) + # # Find file descriptors that are already opened (by the shell) + # Only focus on stdout+stderr for now + for my $fdno (1..2) { + my $fh; + # 2-argument-open is used to be compatible with old perl 5.8.0 + # bug #43570: Perl 5.8.0 creates 61 files + if(open($fh,">&=$fdno")) { + $Global::fd{$fdno}=$fh; + } + } + open $Global::original_stderr, ">&", "STDERR" or + ::die_bug("Can't dup STDERR: $!"); + open $Global::status_fd, ">&", "STDERR" or + ::die_bug("Can't dup STDERR: $!"); + open $Global::original_stdin, "<&", "STDIN" or + ::die_bug("Can't dup STDIN: $!"); +} + +sub enough_file_handles { + # Check that we have enough filehandles available for starting + # another job + # Uses: + # $opt::ungroup + # %Global::fd + # Returns: + # 1 if ungrouped (thus not needing extra filehandles) + # 0 if too few filehandles + # 1 if enough filehandles + if(not $opt::ungroup) { + my %fh; + my $enough_filehandles = 1; + # perl uses 7 filehandles for something? + # open3 uses 2 extra filehandles temporarily + # We need a filehandle for each redirected file descriptor + # (normally just STDOUT and STDERR) + for my $i (1..(7+2+keys %Global::fd)) { + $enough_filehandles &&= open($fh{$i}, "<", "/dev/null"); + } + for (values %fh) { close $_; } + return $enough_filehandles; + } else { + # Ungrouped does not need extra file handles + return 1; + } +} + +sub open_or_exit { + # Open a file name or exit if the file cannot be opened + # Inputs: + # $file = filehandle or filename to open + # Uses: + # $Global::original_stdin + # Returns: + # $fh = file handle to read-opened file + my $file = shift; + if($file eq "-") { + return ($Global::original_stdin || *STDIN); + } + if(ref $file eq "GLOB") { + # This is an open filehandle + return $file; + } + my $fh = gensym; + if(not open($fh, "<", $file)) { + ::error("Cannot open input file `$file': No such file or directory."); + wait_and_exit(255); + } + return $fh; +} + +sub set_fh_blocking { + # Set filehandle as blocking + # Inputs: + # $fh = filehandle to be blocking + # Returns: + # N/A + my $fh = shift; + $Global::use{"Fcntl"} ||= eval "use Fcntl qw(:DEFAULT :flock); 1;"; + my $flags; + # Get the current flags on the filehandle + fcntl($fh, &F_GETFL, $flags) || die $!; + # Remove non-blocking from the flags + $flags &= ~&O_NONBLOCK; + # Set the flags on the filehandle + fcntl($fh, &F_SETFL, $flags) || die $!; +} + +sub set_fh_non_blocking { + # Set filehandle as non-blocking + # Inputs: + # $fh = filehandle to be blocking + # Returns: + # N/A + my $fh = shift; + $Global::use{"Fcntl"} ||= eval "use Fcntl qw(:DEFAULT :flock); 1;"; + my $flags; + # Get the current flags on the filehandle + fcntl($fh, &F_GETFL, $flags) || die $!; + # Add non-blocking to the flags + $flags |= &O_NONBLOCK; + # Set the flags on the filehandle + fcntl($fh, &F_SETFL, $flags) || die $!; +} + + +sub __RUNNING_THE_JOBS_AND_PRINTING_PROGRESS__ {} + + +# Variable structure: +# +# $Global::running{$pid} = Pointer to Job-object +# @Global::virgin_jobs = Pointer to Job-object that have received no input +# $Global::host{$sshlogin} = Pointer to SSHLogin-object +# $Global::total_running = total number of running jobs +# $Global::total_started = total jobs started +# $Global::max_procs_file = filename if --jobs is given a filename +# $Global::JobQueue = JobQueue object for the queue of jobs +# $Global::timeoutq = queue of times where jobs timeout +# $Global::newest_job = Job object of the most recent job started +# $Global::newest_starttime = timestamp of $Global::newest_job +# @Global::sshlogin +# $Global::minimal_command_line_length = minimum length supported by all sshlogins +# $Global::start_no_new_jobs = should more jobs be started? +# $Global::original_stderr = file handle for STDERR when the program started +# $Global::total_started = total number of jobs started +# $Global::joblog = filehandle of joblog +# $Global::debug = Is debugging on? +# $Global::exitstatus = status code of GNU Parallel +# $Global::quoting = quote the command to run + +sub init_run_jobs { + # Set Global variables and progress signal handlers + # Do the copying of basefiles + # Returns: N/A + $Global::total_running = 0; + $Global::total_started = 0; + $SIG{USR1} = \&list_running_jobs; + $SIG{USR2} = \&toggle_progress; + if(@opt::basefile) { setup_basefile(); } +} + +{ + my $last_time; + my %last_mtime; + my $max_procs_file_last_mod; + + sub changed_procs_file { + # If --jobs is a file and it is modfied: + # Force recomputing of max_jobs_running for each $sshlogin + # Uses: + # $Global::max_procs_file + # %Global::host + # Returns: N/A + if($Global::max_procs_file) { + # --jobs filename + my $mtime = (stat($Global::max_procs_file))[9]; + $max_procs_file_last_mod ||= 0; + if($mtime > $max_procs_file_last_mod) { + # file changed: Force re-computing max_jobs_running + $max_procs_file_last_mod = $mtime; + for my $sshlogin (values %Global::host) { + $sshlogin->set_max_jobs_running(undef); + } + } + } + } + + sub changed_sshloginfile { + # If --slf is changed: + # reload --slf + # filter_hosts + # setup_basefile + # Uses: + # @opt::sshloginfile + # @Global::sshlogin + # %Global::host + # $opt::filter_hosts + # Returns: N/A + if(@opt::sshloginfile) { + # Is --sshloginfile changed? + for my $slf (@opt::sshloginfile) { + my $actual_file = expand_slf_shorthand($slf); + my $mtime = (stat($actual_file))[9]; + $last_mtime{$actual_file} ||= $mtime; + if($mtime - $last_mtime{$actual_file} > 1) { + ::debug("run","--sshloginfile $actual_file changed. reload\n"); + $last_mtime{$actual_file} = $mtime; + # Reload $slf + # Empty sshlogins + @Global::sshlogin = (); + for (values %Global::host) { + # Don't start new jobs on any host + # except the ones added back later + $_->set_max_jobs_running(0); + } + # This will set max_jobs_running on the SSHlogins + read_sshloginfile($actual_file); + parse_sshlogin(); + $opt::filter_hosts and filter_hosts(); + setup_basefile(); + } + } + } + } + + sub start_more_jobs { + # Run start_another_job() but only if: + # * not $Global::start_no_new_jobs set + # * not JobQueue is empty + # * not load on server is too high + # * not server swapping + # * not too short time since last remote login + # Uses: + # %Global::host + # $Global::start_no_new_jobs + # $Global::JobQueue + # $opt::pipe + # $opt::load + # $opt::noswap + # $opt::delay + # $Global::newest_starttime + # Returns: + # $jobs_started = number of jobs started + my $jobs_started = 0; + my $jobs_started_this_round = 0; + if($Global::start_no_new_jobs) { + return $jobs_started; + } + if(time - ($last_time||0) > 1) { + # At most do this every second + $last_time = time; + changed_procs_file(); + changed_sshloginfile(); + } + do { + $jobs_started_this_round = 0; + # This will start 1 job on each --sshlogin (if possible) + # thus distribute the jobs on the --sshlogins round robin + for my $sshlogin (values %Global::host) { + if($Global::JobQueue->empty() and not $opt::pipe) { + # No more jobs in the queue + last; + } + debug("run", "Running jobs before on ", $sshlogin->string(), ": ", + $sshlogin->jobs_running(), "\n"); + if ($sshlogin->jobs_running() < $sshlogin->max_jobs_running()) { + if($opt::delay + and + $opt::delay > ::now() - $Global::newest_starttime) { + # It has been too short since last start + next; + } + if($opt::load and $sshlogin->loadavg_too_high()) { + # The load is too high or unknown + next; + } + if($opt::noswap and $sshlogin->swapping()) { + # The server is swapping + next; + } + if($opt::limit and $sshlogin->limit()) { + # Over limit + next; + } + if($opt::memfree and $sshlogin->memfree() < $opt::memfree) { + # The server has not enough mem free + ::debug("mem", "Not starting job: not enough mem\n"); + next; + } + if($sshlogin->too_fast_remote_login()) { + # It has been too short since + next; + } + debug("run", $sshlogin->string(), + " has ", $sshlogin->jobs_running(), + " out of ", $sshlogin->max_jobs_running(), + " jobs running. Start another.\n"); + if(start_another_job($sshlogin) == 0) { + # No more jobs to start on this $sshlogin + debug("run","No jobs started on ", + $sshlogin->string(), "\n"); + next; + } + $sshlogin->inc_jobs_running(); + $sshlogin->set_last_login_at(::now()); + $jobs_started++; + $jobs_started_this_round++; + } + debug("run","Running jobs after on ", $sshlogin->string(), ": ", + $sshlogin->jobs_running(), " of ", + $sshlogin->max_jobs_running(), "\n"); + } + } while($jobs_started_this_round); + + return $jobs_started; + } +} + +{ + my $no_more_file_handles_warned; + + sub start_another_job { + # If there are enough filehandles + # and JobQueue not empty + # and not $job is in joblog + # Then grab a job from Global::JobQueue, + # start it at sshlogin + # mark it as virgin_job + # Inputs: + # $sshlogin = the SSHLogin to start the job on + # Uses: + # $Global::JobQueue + # $opt::pipe + # $opt::results + # $opt::resume + # @Global::virgin_jobs + # Returns: + # 1 if another jobs was started + # 0 otherwise + my $sshlogin = shift; + # Do we have enough file handles to start another job? + if(enough_file_handles()) { + if($Global::JobQueue->empty() and not $opt::pipe) { + # No more commands to run + debug("start", "Not starting: JobQueue empty\n"); + return 0; + } else { + my $job; + # Skip jobs already in job log + # Skip jobs already in results + do { + $job = get_job_with_sshlogin($sshlogin); + if(not defined $job) { + # No command available for that sshlogin + debug("start", "Not starting: no jobs available for ", + $sshlogin->string(), "\n"); + return 0; + } + if($job->is_already_in_joblog()) { + $job->free_slot(); + } + } while ($job->is_already_in_joblog() + or + ($opt::results and $opt::resume and $job->is_already_in_results())); + debug("start", "Command to run on '", $job->sshlogin()->string(), "': '", + $job->replaced(),"'\n"); + if($job->start()) { + if($opt::pipe) { + if($job->virgin()) { + push(@Global::virgin_jobs,$job); + } else { + # Block already set: This is a retry + if(fork()) { + ::debug("pipe","\n\nWriting ",length ${$job->block_ref()}, + " to ", $job->seq(),"\n"); + close $job->fh(0,"w"); + } else { + $job->write($job->block_ref()); + close $job->fh(0,"w"); + exit(0); + } + } + } + debug("start", "Started as seq ", $job->seq(), + " pid:", $job->pid(), "\n"); + return 1; + } else { + # Not enough processes to run the job. + # Put it back on the queue. + $Global::JobQueue->unget($job); + # Count down the number of jobs to run for this SSHLogin. + my $max = $sshlogin->max_jobs_running(); + if($max > 1) { $max--; } else { + my @arg; + for my $record (@{$job->{'commandline'}->{'arg_list'}}) { + push @arg, map { $_->orig() } @$record; + } + ::error("No more processes: cannot run a single job. Something is wrong at @arg."); + ::wait_and_exit(255); + } + $sshlogin->set_max_jobs_running($max); + # Sleep up to 300 ms to give other processes time to die + ::usleep(rand()*300); + ::warning("No more processes: ". + "Decreasing number of running jobs to $max.", + "Raising ulimit -u or /etc/security/limits.conf may help."); + return 0; + } + } + } else { + # No more file handles + $no_more_file_handles_warned++ or + ::warning("No more file handles. ", + "Raising ulimit -n or /etc/security/limits.conf may help."); + debug("start", "No more file handles. "); + return 0; + } + } +} + +sub init_progress { + # Uses: + # $opt::bar + # Returns: + # list of computers for progress output + $|=1; + if($opt::bar) { + return("",""); + } + my %progress = progress(); + return ("\nComputers / CPU cores / Max jobs to run\n", + $progress{'workerlist'}); +} + +sub drain_job_queue { + # Uses: + # $opt::progress + # $Global::total_running + # $Global::max_jobs_running + # %Global::running + # $Global::JobQueue + # %Global::host + # $Global::start_no_new_jobs + # Returns: N/A + if($opt::progress) { + ::status_no_nl(init_progress()); + } + my $last_header = ""; + my $sleep = 0.2; + do { + while($Global::total_running > 0) { + debug($Global::total_running, "==", scalar + keys %Global::running," slots: ", $Global::max_jobs_running); + if($opt::pipe) { + # When using --pipe sometimes file handles are not closed properly + for my $job (values %Global::running) { + close $job->fh(0,"w"); + } + } + if($opt::progress) { + my %progress = progress(); + if($last_header ne $progress{'header'}) { + ::status("", $progress{'header'}); + $last_header = $progress{'header'}; + } + ::status_no_nl("\r",$progress{'status'}); + } + if($Global::total_running < $Global::max_jobs_running + and not $Global::JobQueue->empty()) { + # These jobs may not be started because of loadavg + # or too little time between each ssh login. + if(start_more_jobs() > 0) { + # Exponential back-on if jobs were started + $sleep = $sleep/2+0.001; + } + } + # Exponential back-off sleeping + $sleep = ::reap_usleep($sleep); + } + if(not $Global::JobQueue->empty()) { + # These jobs may not be started: + # * because there the --filter-hosts has removed all + if(not %Global::host) { + ::error("There are no hosts left to run on."); + ::wait_and_exit(255); + } + # * because of loadavg + # * because of too little time between each ssh login. + start_more_jobs(); + $sleep = ::reap_usleep($sleep); + if($Global::max_jobs_running == 0) { + ::warning("There are no job slots available. Increase --jobs."); + } + } + while($opt::sqlmaster and not $Global::sql->finished()) { + # SQL master + $sleep = ::reap_usleep($sleep); + if($Global::start_sqlworker) { + # Start an SQL worker as we are now sure there is work to do + $Global::start_sqlworker = 0; + if(my $pid = fork()) { + $Global::unkilled_sqlworker = $pid; + } else { + # Replace --sql/--sqlandworker with --sqlworker + my @ARGV = map { s/^--sql(andworker)?$/--sqlworker/; $_ } @Global::options_in_argv; + # exec the --sqlworker + exec($0,::shell_quote(@ARGV),@command); + } + } + } + } while ($Global::total_running > 0 + or + not $Global::start_no_new_jobs and not $Global::JobQueue->empty() + or + $opt::sqlmaster and not $Global::sql->finished()); + if($opt::progress) { + my %progress = progress(); + ::status("\r".$progress{'status'}); + } +} + +sub toggle_progress { + # Turn on/off progress view + # Uses: + # $opt::progress + # Returns: N/A + $opt::progress = not $opt::progress; + if($opt::progress) { + ::status_no_nl(init_progress()); + } +} + +sub progress { + # Uses: + # $opt::bar + # $opt::eta + # %Global::host + # $Global::total_started + # Returns: + # $workerlist = list of workers + # $header = that will fit on the screen + # $status = message that will fit on the screen + if($opt::bar) { + return ("workerlist" => "", "header" => "", "status" => bar()); + } + my $eta = ""; + my ($status,$header)=("",""); + if($opt::eta) { + my($total, $completed, $left, $pctcomplete, $avgtime, $this_eta) = + compute_eta(); + $eta = sprintf("ETA: %ds Left: %d AVG: %.2fs ", + $this_eta, $left, $avgtime); + } + my $termcols = terminal_columns(); + my @workers = sort keys %Global::host; + my %sshlogin = map { $_ eq ":" ? ($_ => "local") : ($_ => $_) } @workers; + my $workerno = 1; + my %workerno = map { ($_=>$workerno++) } @workers; + my $workerlist = ""; + for my $w (@workers) { + $workerlist .= + $workerno{$w}.":".$sshlogin{$w} ." / ". + ($Global::host{$w}->ncpus() || "-")." / ". + $Global::host{$w}->max_jobs_running()."\n"; + } + $status = "x"x($termcols+1); + # Select an output format that will fit on a single line + if(length $status > $termcols) { + # sshlogin1:XX/XX/XX%/XX.Xs sshlogin2:XX/XX/XX%/XX.Xs sshlogin3:XX/XX/XX%/XX.Xs + $header = "Computer:jobs running/jobs completed/%of started jobs/Average seconds to complete"; + $status = $eta . + join(" ",map + { + if($Global::total_started) { + my $completed = ($Global::host{$_}->jobs_completed()||0); + my $running = $Global::host{$_}->jobs_running(); + my $time = $completed ? (time-$^T)/($completed) : "0"; + sprintf("%s:%d/%d/%d%%/%.1fs ", + $sshlogin{$_}, $running, $completed, + ($running+$completed)*100 + / $Global::total_started, $time); + } + } @workers); + } + if(length $status > $termcols) { + # 1:XX/XX/XX%/XX.Xs 2:XX/XX/XX%/XX.Xs 3:XX/XX/XX%/XX.Xs 4:XX/XX/XX%/XX.Xs + $header = "Computer:jobs running/jobs completed/%of started jobs"; + $status = $eta . + join(" ",map + { + if($Global::total_started) { + my $completed = ($Global::host{$_}->jobs_completed()||0); + my $running = $Global::host{$_}->jobs_running(); + my $time = $completed ? (time-$^T)/($completed) : "0"; + sprintf("%s:%d/%d/%d%%/%.1fs ", + $workerno{$_}, $running, $completed, + ($running+$completed)*100 + / $Global::total_started, $time); + } + } @workers); + } + if(length $status > $termcols) { + # sshlogin1:XX/XX/XX% sshlogin2:XX/XX/XX% sshlogin3:XX/XX/XX% + $header = "Computer:jobs running/jobs completed/%of started jobs"; + $status = $eta . + join(" ",map + { + if($Global::total_started) { + sprintf("%s:%d/%d/%d%%", + $sshlogin{$_}, + $Global::host{$_}->jobs_running(), + ($Global::host{$_}->jobs_completed()||0), + ($Global::host{$_}->jobs_running()+ + ($Global::host{$_}->jobs_completed()||0))*100 + / $Global::total_started) + } + } + @workers); + } + if(length $status > $termcols) { + # 1:XX/XX/XX% 2:XX/XX/XX% 3:XX/XX/XX% 4:XX/XX/XX% 5:XX/XX/XX% 6:XX/XX/XX% + $header = "Computer:jobs running/jobs completed/%of started jobs"; + $status = $eta . + join(" ",map + { + if($Global::total_started) { + sprintf("%s:%d/%d/%d%%", + $workerno{$_}, + $Global::host{$_}->jobs_running(), + ($Global::host{$_}->jobs_completed()||0), + ($Global::host{$_}->jobs_running()+ + ($Global::host{$_}->jobs_completed()||0))*100 + / $Global::total_started) + } + } + @workers); + } + if(length $status > $termcols) { + # sshlogin1:XX/XX/XX% sshlogin2:XX/XX/XX% sshlogin3:XX/XX sshlogin4:XX/XX + $header = "Computer:jobs running/jobs completed"; + $status = $eta . + join(" ",map + { sprintf("%s:%d/%d", + $sshlogin{$_}, $Global::host{$_}->jobs_running(), + ($Global::host{$_}->jobs_completed()||0)) } + @workers); + } + if(length $status > $termcols) { + # sshlogin1:XX/XX sshlogin2:XX/XX sshlogin3:XX/XX sshlogin4:XX/XX + $header = "Computer:jobs running/jobs completed"; + $status = $eta . + join(" ",map + { sprintf("%s:%d/%d", + $sshlogin{$_}, $Global::host{$_}->jobs_running(), + ($Global::host{$_}->jobs_completed()||0)) } + @workers); + } + if(length $status > $termcols) { + # 1:XX/XX 2:XX/XX 3:XX/XX 4:XX/XX 5:XX/XX 6:XX/XX + $header = "Computer:jobs running/jobs completed"; + $status = $eta . + join(" ",map + { sprintf("%s:%d/%d", + $workerno{$_}, $Global::host{$_}->jobs_running(), + ($Global::host{$_}->jobs_completed()||0)) } + @workers); + } + if(length $status > $termcols) { + # sshlogin1:XX sshlogin2:XX sshlogin3:XX sshlogin4:XX sshlogin5:XX + $header = "Computer:jobs completed"; + $status = $eta . + join(" ",map + { sprintf("%s:%d", + $sshlogin{$_}, + ($Global::host{$_}->jobs_completed()||0)) } + @workers); + } + if(length $status > $termcols) { + # 1:XX 2:XX 3:XX 4:XX 5:XX 6:XX + $header = "Computer:jobs completed"; + $status = $eta . + join(" ",map + { sprintf("%s:%d", + $workerno{$_}, + ($Global::host{$_}->jobs_completed()||0)) } + @workers); + } + return ("workerlist" => $workerlist, "header" => $header, "status" => $status); +} + +{ + + my ($total, $first_completed, $smoothed_avg_time, $last_eta); + + sub compute_eta { + # Calculate important numbers for ETA + # Returns: + # $total = number of jobs in total + # $completed = number of jobs completed + # $left = number of jobs left + # $pctcomplete = percent of jobs completed + # $avgtime = averaged time + # $eta = smoothed eta + $total = $Global::JobQueue->total_jobs(); + my $completed = $Global::total_completed; + my $left = $total - $completed; + if(not $completed) { + return($total, $completed, $left, 0, 0, 0); + } + my $pctcomplete = $completed / $total; + $first_completed ||= time; + my $timepassed = (time - $first_completed); + my $avgtime = $timepassed / $completed; + $smoothed_avg_time ||= $avgtime; + # Smooth the eta so it does not jump wildly + $smoothed_avg_time = (1 - $pctcomplete) * $smoothed_avg_time + + $pctcomplete * $avgtime; + my $eta = int($left * $smoothed_avg_time); + if($eta*0.90 < $last_eta and $last_eta < $eta) { + # Eta jumped less that 10% up: Keep the last eta instead + $eta = $last_eta; + } else { + $last_eta = $eta; + } + return($total, $completed, $left, $pctcomplete, $avgtime, $eta); + } +} + +{ + my ($rev,$reset); + + sub bar { + # Return: + # $status = bar with eta, completed jobs, arg and pct + $rev ||= "\033[7m"; + $reset ||= "\033[0m"; + my($total, $completed, $left, $pctcomplete, $avgtime, $eta) = + compute_eta(); + my $arg = $Global::newest_job ? + $Global::newest_job->{'commandline'}-> + replace_placeholders(["\257<\257>"],0,0) : ""; + # These chars mess up display in the terminal + $arg =~ tr/[\011-\016\033\302-\365]//d; + my $eta_dhms = ::seconds_to_time_units($eta); + my $bar_text = + sprintf("%d%% %d:%d=%s %s", + $pctcomplete*100, $completed, $left, $eta_dhms, $arg); + my $terminal_width = terminal_columns(); + my $s = sprintf("%-${terminal_width}s", + substr($bar_text." "x$terminal_width, + 0,$terminal_width)); + my $width = int($terminal_width * $pctcomplete); + substr($s,$width,0) = $reset; + my $zenity = sprintf("%-${terminal_width}s", + substr("# $eta sec $arg", + 0,$terminal_width)); + $s = "\r" . $zenity . "\r" . $pctcomplete*100 . # Prefix with zenity header + "\r" . $rev . $s . $reset; + return $s; + } +} + +{ + my ($columns,$last_column_time); + + sub terminal_columns { + # Get the number of columns of the terminal. + # Only update once per second. + # Returns: + # number of columns of the screen + if(not $columns or $last_column_time < time) { + $last_column_time = time; + $columns = $ENV{'COLUMNS'}; + if(not $columns) { + my $stty = ::qqx("stty -a get()) { + if($sshlogin->in_hostgroups($job->hostgroups())) { + # Found a job to be run on a hostgroup of this + # $sshlogin + last; + } else { + # This job was not in the hostgroups of $sshlogin + push @other_hostgroup_jobs, $job; + } + } + $Global::JobQueue->unget(@other_hostgroup_jobs); + if(not defined $job) { + # No more jobs + return undef; + } + } else { + $job = $Global::JobQueue->get(); + if(not defined $job) { + # No more jobs + ::debug("start", "No more jobs: JobQueue empty\n"); + return undef; + } + } + + my $clean_command = $job->replaced(); + if($clean_command =~ /^\s*$/) { + # Do not run empty lines + if(not $Global::JobQueue->empty()) { + return get_job_with_sshlogin($sshlogin); + } else { + return undef; + } + } + $job->set_sshlogin($sshlogin); + if($opt::retries and $clean_command and + $job->failed_here()) { + # This command with these args failed for this sshlogin + my ($no_of_failed_sshlogins,$min_failures) = $job->min_failed(); + # Only look at the Global::host that have > 0 jobslots + if($no_of_failed_sshlogins == + grep { $_->max_jobs_running() > 0 } values %Global::host + and $job->failed_here() == $min_failures) { + # It failed the same or more times on another host: + # run it on this host + } else { + # If it failed fewer times on another host: + # Find another job to run + my $nextjob; + if(not $Global::JobQueue->empty()) { + # This can potentially recurse for all args + no warnings 'recursion'; + $nextjob = get_job_with_sshlogin($sshlogin); + } + # Push the command back on the queue + $Global::JobQueue->unget($job); + return $nextjob; + } + } + return $job; +} + + +sub __REMOTE_SSH__ {} + + +sub read_sshloginfiles { + # Read a list of --slf's + # Input: + # @files = files or symbolic file names to read + # Returns: N/A + for my $s (@_) { + read_sshloginfile(expand_slf_shorthand($s)); + } +} + +sub expand_slf_shorthand { + # Expand --slf shorthand into a read file name + # Input: + # $file = file or symbolic file name to read + # Returns: + # $file = actual file name to read + my $file = shift; + if($file eq "-") { + # skip: It is stdin + } elsif($file eq "..") { + $file = $Global::config_dir."/sshloginfile"; + } elsif($file eq ".") { + $file = "/etc/parallel/sshloginfile"; + } elsif(not -r $file) { + for(@Global::config_dirs) { + if(not -r $_."/".$file) { + # Try prepending $PARALLEL_HOME + ::error("Cannot open $file."); + ::wait_and_exit(255); + } else { + $file = $_."/".$file; + last; + } + } + } + return $file; +} + +sub read_sshloginfile { + # Read sshloginfile into @Global::sshlogin + # Input: + # $file = file to read + # Uses: + # @Global::sshlogin + # Returns: N/A + local $/ = "\n"; + my $file = shift; + my $close = 1; + my $in_fh; + ::debug("init","--slf ",$file); + if($file eq "-") { + $in_fh = *STDIN; + $close = 0; + } else { + if(not open($in_fh, "<", $file)) { + # Try the filename + ::error("Cannot open $file."); + ::wait_and_exit(255); + } + } + while(<$in_fh>) { + chomp; + /^\s*#/ and next; + /^\s*$/ and next; + push @Global::sshlogin, $_; + } + if($close) { + close $in_fh; + } +} + +sub parse_sshlogin { + # Parse @Global::sshlogin into %Global::host. + # Keep only hosts that are in one of the given ssh hostgroups. + # Uses: + # @Global::sshlogin + # $Global::minimal_command_line_length + # %Global::host + # $opt::transfer + # @opt::return + # $opt::cleanup + # @opt::basefile + # @opt::trc + # Returns: N/A + my @login; + if(not @Global::sshlogin) { @Global::sshlogin = (":"); } + for my $sshlogin (@Global::sshlogin) { + # Split up -S sshlogin,sshlogin + for my $s (split /,|\n/, $sshlogin) { + if ($s eq ".." or $s eq "-") { + # This may add to @Global::sshlogin - possibly bug + read_sshloginfile(expand_slf_shorthand($s)); + } else { + $s =~ s/\s*$//; + push (@login, $s); + } + } + } + $Global::minimal_command_line_length = 8_000_000; + my @allowed_hostgroups; + for my $ncpu_sshlogin_string (::uniq(@login)) { + my $sshlogin = SSHLogin->new($ncpu_sshlogin_string); + my $sshlogin_string = $sshlogin->string(); + if($sshlogin_string eq "") { + # This is an ssh group: -S @webservers + push @allowed_hostgroups, $sshlogin->hostgroups(); + next; + } + if($Global::host{$sshlogin_string}) { + # This sshlogin has already been added: + # It is probably a host that has come back + # Set the max_jobs_running back to the original + debug("run","Already seen $sshlogin_string\n"); + if($sshlogin->{'ncpus'}) { + # If ncpus set by '#/' of the sshlogin, overwrite it: + $Global::host{$sshlogin_string}->set_ncpus($sshlogin->ncpus()); + } + $Global::host{$sshlogin_string}->set_max_jobs_running(undef); + next; + } + $sshlogin->set_maxlength(Limits::Command::max_length()); + + $Global::minimal_command_line_length = + ::min($Global::minimal_command_line_length, $sshlogin->maxlength()); + $Global::host{$sshlogin_string} = $sshlogin; + } + if(@allowed_hostgroups) { + # Remove hosts that are not in these groups + while (my ($string, $sshlogin) = each %Global::host) { + if(not $sshlogin->in_hostgroups(@allowed_hostgroups)) { + delete $Global::host{$string}; + } + } + } + + # debug("start", "sshlogin: ", my_dump(%Global::host),"\n"); + if(@Global::transfer_files or @opt::return or $opt::cleanup or @opt::basefile) { + if(not remote_hosts()) { + # There are no remote hosts + if(@opt::trc) { + ::warning("--trc ignored as there are no remote --sshlogin."); + } elsif (defined $opt::transfer) { + ::warning("--transfer ignored as there are no remote --sshlogin."); + } elsif (@opt::transfer_files) { + ::warning("--transferfile ignored as there are no remote --sshlogin."); + } elsif (@opt::return) { + ::warning("--return ignored as there are no remote --sshlogin."); + } elsif (defined $opt::cleanup) { + ::warning("--cleanup ignored as there are no remote --sshlogin."); + } elsif (@opt::basefile) { + ::warning("--basefile ignored as there are no remote --sshlogin."); + } + } + } +} + +sub remote_hosts { + # Return sshlogins that are not ':' + # Uses: + # %Global::host + # Returns: + # list of sshlogins with ':' removed + return grep !/^:$/, keys %Global::host; +} + +sub setup_basefile { + # Transfer basefiles to each $sshlogin + # This needs to be done before first jobs on $sshlogin is run + # Uses: + # %Global::host + # @opt::basefile + # Returns: N/A + my @cmd; + my $rsync_destdir; + my $workdir; + for my $sshlogin (values %Global::host) { + if($sshlogin->string() eq ":") { next } + for my $file (@opt::basefile) { + if($file !~ m:^/: and $opt::workdir eq "...") { + ::error("Work dir '...' will not work with relative basefiles."); + ::wait_and_exit(255); + } + if(not $workdir) { + my $dummycmdline = CommandLine->new(1,["true"],{},0,0,[],[],{},{},{}); + my $dummyjob = Job->new($dummycmdline); + $workdir = $dummyjob->workdir(); + } + push @cmd, $sshlogin->rsync_transfer_cmd($file,$workdir); + } + } + debug("init", "basesetup: @cmd\n"); + my ($exitstatus,$stdout_ref,$stderr_ref) = + run_parallel((join "\n",@cmd),"-j0","--retries",5); + if($exitstatus) { + my @stdout = @$stdout_ref; + my @stderr = @$stderr_ref; + ::error("Copying of --basefile failed: @stdout@stderr"); + ::wait_and_exit(255); + } +} + +sub cleanup_basefile { + # Remove the basefiles transferred + # Uses: + # %Global::host + # @opt::basefile + # Returns: N/A + my @cmd; + my $workdir; + if(not $workdir) { + my $dummycmdline = CommandLine->new(1,"true",0,0,0,0,0,{},{},{}); + my $dummyjob = Job->new($dummycmdline); + $workdir = $dummyjob->workdir(); + } + for my $sshlogin (values %Global::host) { + if($sshlogin->string() eq ":") { next } + for my $file (@opt::basefile) { + push @cmd, $sshlogin->cleanup_cmd($file,$workdir); + } + } + debug("init", "basecleanup: @cmd\n"); + my ($exitstatus,$stdout_ref,$stderr_ref) = + run_parallel(join("\n",@cmd),"-j0","--retries",5); + if($exitstatus) { + my @stdout = @$stdout_ref; + my @stderr = @$stderr_ref; + ::error("Cleanup of --basefile failed: @stdout@stderr"); + ::wait_and_exit(255); + } +} + +sub run_parallel { + my ($stdin,@args) = @_; + my $cmd = join "",map { " $_ & " } split /\n/, $stdin; + print $Global::original_stderr ` $cmd wait` ; + return 0 +} + +sub _run_parallel { + # Run GNU Parallel + # This should ideally just fork an internal copy + # and not start it through a shell + # Input: + # $stdin = data to provide on stdin for GNU Parallel + # @args = command line arguments + # Returns: + # $exitstatus = exitcode of GNU Parallel run + # \@stdout = standard output + # \@stderr = standard error + my ($stdin,@args) = @_; + my ($exitstatus,@stdout,@stderr); + my ($stdin_fh,$stdout_fh)=(gensym(),gensym()); + my ($stderr_fh, $stderrname) = ::tmpfile(SUFFIX => ".par"); + unlink $stderrname; + + my $pid = ::open3($stdin_fh,$stdout_fh,$stderr_fh, + $0,qw(--plain --shell /bin/sh --will-cite), @args); + if(my $writerpid = fork()) { + close $stdin_fh; + @stdout = <$stdout_fh>; + # Now stdout is closed: + # These pids should be dead or die very soon + while(kill 0, $writerpid) { ::usleep(1); } + die; +# reap $writerpid; +# while(kill 0, $pid) { ::usleep(1); } +# reap $writerpid; + $exitstatus = $?; + seek $stderr_fh, 0, 0; + @stderr = <$stderr_fh>; + close $stdout_fh; + close $stderr_fh; + } else { + close $stdout_fh; + close $stderr_fh; + print $stdin_fh $stdin; + close $stdin_fh; + exit(0); + } + return ($exitstatus,\@stdout,\@stderr); +} + +sub filter_hosts { + # Remove down --sshlogins from active duty. + # Find ncpus, ncores, maxlen, time-to-login for each host. + # Uses: + # %Global::host + # $Global::minimal_command_line_length + # $opt::use_cpus_instead_of_cores + # Returns: N/A + + my ($ncores_ref, $ncpus_ref, $time_to_login_ref, $maxlen_ref, + $echo_ref, $down_hosts_ref) = + parse_host_filtering(parallelized_host_filtering()); + + delete @Global::host{@$down_hosts_ref}; + @$down_hosts_ref and ::warning("Removed @$down_hosts_ref."); + + $Global::minimal_command_line_length = 8_000_000; + while (my ($sshlogin, $obj) = each %Global::host) { + if($sshlogin eq ":") { next } + $ncpus_ref->{$sshlogin} or + ::die_bug("ncpus missing: ".$obj->serverlogin()); + $ncores_ref->{$sshlogin} or + ::die_bug("ncores missing: ".$obj->serverlogin()); + $time_to_login_ref->{$sshlogin} or + ::die_bug("time_to_login missing: ".$obj->serverlogin()); + $maxlen_ref->{$sshlogin} or + ::die_bug("maxlen missing: ".$obj->serverlogin()); + if($opt::use_cpus_instead_of_cores) { + $obj->set_ncpus($ncpus_ref->{$sshlogin}); + } else { + $obj->set_ncpus($ncores_ref->{$sshlogin}); + } + $obj->set_time_to_login($time_to_login_ref->{$sshlogin}); + $obj->set_maxlength($maxlen_ref->{$sshlogin}); + $Global::minimal_command_line_length = + ::min($Global::minimal_command_line_length, + int($maxlen_ref->{$sshlogin}/2)); + ::debug("init", "Timing from -S:$sshlogin ", + " ncpus:",$ncpus_ref->{$sshlogin}, + " ncores:", $ncores_ref->{$sshlogin}, + " time_to_login:", $time_to_login_ref->{$sshlogin}, + " maxlen:", $maxlen_ref->{$sshlogin}, + " min_max_len:", $Global::minimal_command_line_length,"\n"); + } +} + +sub parse_host_filtering { + # Input: + # @lines = output from parallelized_host_filtering() + # Returns: + # \%ncores = number of cores of {host} + # \%ncpus = number of cpus of {host} + # \%time_to_login = time_to_login on {host} + # \%maxlen = max command len on {host} + # \%echo = echo received from {host} + # \@down_hosts = list of hosts with no answer + local $/ = "\n"; + my (%ncores, %ncpus, %time_to_login, %maxlen, %echo, @down_hosts); + for (@_) { + ::debug("init",$_); + chomp; + my @col = split /\t/, $_; + if($col[0] =~ /^parallel: Warning:/) { + # Timed out job: Ignore it + next; + } elsif(defined $col[6]) { + # This is a line from --joblog + # seq host time spent sent received exit signal command + # 2 : 1372607672.654 0.675 0 0 0 0 eval true\ m\;ssh\ m\ parallel\ --number-of-cores + if($col[0] eq "Seq" and $col[1] eq "Host" and + $col[2] eq "Starttime") { + # Header => skip + next; + } + # Get server from: eval true server\; + $col[8] =~ /eval true..([^;]+).;/ or + ::die_bug("col8 does not contain host: $col[8]"); + my $host = $1; + $host =~ tr/\\//d; + $Global::host{$host} or next; + if($col[6] eq "255" or $col[6] eq "-1" or $col[6] eq "1") { + # exit == 255 or exit == timeout (-1): ssh failed/timedout + # exit == 1: lsh failed + # Remove sshlogin + ::debug("init", "--filtered $host\n"); + push(@down_hosts, $host); + } elsif($col[6] eq "127") { + # signal == 127: parallel not installed remote + # Set ncpus and ncores = 1 + ::warning("Could not figure out ". + "number of cpus on $host. Using 1."); + $ncores{$host} = 1; + $ncpus{$host} = 1; + $maxlen{$host} = Limits::Command::max_length(); + } elsif($col[0] =~ /^\d+$/ and $Global::host{$host}) { + # Remember how log it took to log in + # 2 : 1372607672.654 0.675 0 0 0 0 eval true\ m\;ssh\ m\ echo + $time_to_login{$host} = ::min($time_to_login{$host},$col[3]); + } else { + ::die_bug("host check unmatched long jobline: $_"); + } + } elsif($Global::host{$col[0]}) { + # This output from --number-of-cores, --number-of-cpus, + # --max-line-length-allowed + # ncores: server 8 + # ncpus: server 2 + # maxlen: server 131071 + if(/parallel: Warning: Cannot figure out number of/) { + next; + } + if(not $ncores{$col[0]}) { + $ncores{$col[0]} = $col[1]; + } elsif(not $ncpus{$col[0]}) { + $ncpus{$col[0]} = $col[1]; + } elsif(not $maxlen{$col[0]}) { + $maxlen{$col[0]} = $col[1]; + } elsif(not $echo{$col[0]}) { + $echo{$col[0]} = $col[1]; + } elsif(m/perl: warning:|LANGUAGE =|LC_ALL =|LANG =|are supported and installed/) { + # Skip these: + # perl: warning: Setting locale failed. + # perl: warning: Please check that your locale settings: + # LANGUAGE = (unset), + # LC_ALL = (unset), + # LANG = "en_US.UTF-8" + # are supported and installed on your system. + # perl: warning: Falling back to the standard locale ("C"). + } else { + ::die_bug("host check too many col0: $_"); + } + } else { + ::die_bug("host check unmatched short jobline ($col[0]): $_"); + } + } + @down_hosts = uniq(@down_hosts); + return(\%ncores, \%ncpus, \%time_to_login, \%maxlen, \%echo, \@down_hosts); +} + +sub parallelized_host_filtering { + # Uses: + # %Global::host + # Returns: + # text entries with: + # * joblog line + # * hostname \t number of cores + # * hostname \t number of cpus + # * hostname \t max-line-length-allowed + # * hostname \t empty + + sub sshwrapped { + # Wrap with ssh and --env + my $sshlogin = shift; + my $command = shift; + my $commandline = CommandLine->new(1,[$command],{},0,0,[],[],{},{},{}); + my $job = Job->new($commandline); + $job->set_sshlogin($sshlogin); + $job->wrapped(); + return($job->{'wrapped'}); + } + + my(@cores, @cpus, @maxline, @echo); + while (my ($host, $sshlogin) = each %Global::host) { + if($host eq ":") { next } + # The 'true' is used to get the $host out later + push(@cores, $host."\t"."true $host; ". + sshwrapped($sshlogin,"parallel --number-of-cores")."\n\0"); + push(@cpus, $host."\t"."true $host; ". + sshwrapped($sshlogin,"parallel --number-of-cpus")."\n\0"); + push(@maxline, $host."\t"."true $host; ". + sshwrapped($sshlogin,"parallel --max-line-length-allowed")."\n\0"); + # 'echo' is used to get the fastest possible ssh login time + my $sshcmd = "true $host; exec " .$sshlogin->sshcommand()." ". + $sshlogin->serverlogin(); + push(@echo, $host."\t".$sshcmd." -- echo\n\0"); + } + + # --timeout 10: Setting up an SSH connection and running a simple + # command should never take > 10 sec. + # --delay 0.1: If multiple sshlogins use the same proxy the delay + # will make it less likely to overload the ssh daemon. + # --retries 3: If the ssh daemon is overloaded, try 3 times + my $cmd = + "$0 -j0 --timeout 10 --joblog - --plain --delay 0.1 --retries 3 ". + "--tag --tagstring '{1}' -0 --colsep '\t' -k eval '{2}' && true "; + $cmd = $Global::shell." -c ".::shell_quote_scalar($cmd); + ::debug("init", $cmd, "\n"); + my @out; + my $prepend = ""; + + my ($host_fh,$in,$err); + open3($in, $host_fh, $err, $cmd) || ::die_bug("parallel host check: $cmd"); + if(not fork()) { + # Give the commands to run to the $cmd + close $host_fh; + print $in @cores, @cpus, @maxline, @echo; + close $in; + exit(); + } + close $in; + for(<$host_fh>) { + if(/\'$/) { + # if last char = ' then append next line + # This may be due to quoting of \n in environment var + $prepend .= $_; + next; + } + $_ = $prepend . $_; + $prepend = ""; + push @out, $_; + } + close $host_fh; + return @out; +} + +sub onall { + # Runs @command on all hosts. + # Uses parallel to run @command on each host. + # --jobs = number of hosts to run on simultaneously. + # For each host a parallel command with the args will be running. + # Uses: + # $Global::quoting + # @opt::basefile + # $opt::jobs + # $opt::linebuffer + # $opt::ungroup + # $opt::group + # $opt::keeporder + # $opt::D + # $opt::plain + # $opt::max_chars + # $opt::linebuffer + # $opt::files + # $opt::colsep + # $opt::timeout + # $opt::plain + # $opt::retries + # $opt::max_chars + # $opt::arg_sep + # $opt::arg_file_sep + # @opt::v + # @opt::env + # %Global::host + # $Global::exitstatus + # $Global::debug + # $Global::joblog + # $opt::joblog + # $opt::tag + # $opt::tee + # Input: + # @command = command to run on all hosts + # Returns: N/A + sub tmp_joblog { + # Input: + # $joblog = filename of joblog - undef if none + # Returns: + # $tmpfile = temp file for joblog - undef if none + my $joblog = shift; + if(not defined $joblog) { + return undef; + } + my ($fh, $tmpfile) = ::tmpfile(SUFFIX => ".log"); + close $fh; + return $tmpfile; + } + my ($input_source_fh_ref,@command) = @_; + if($Global::quoting) { + @command = shell_quote(@command); + } + + # Copy all @input_source_fh (-a and :::) into tempfiles + my @argfiles = (); + for my $fh (@$input_source_fh_ref) { + my ($outfh, $name) = ::tmpfile(SUFFIX => ".all", UNLINK => not $opt::D); + print $outfh (<$fh>); + close $outfh; + push @argfiles, $name; + } + if(@opt::basefile) { setup_basefile(); } + # for each sshlogin do: + # parallel -S $sshlogin $command :::: @argfiles + # + # Pass some of the options to the sub-parallels, not all of them as + # -P should only go to the first, and -S should not be copied at all. + my $options = + join(" ", + ((defined $opt::D) ? "-D $opt::D" : ""), + ((defined $opt::group) ? "-g" : ""), + ((defined $opt::jobs) ? "-P $opt::jobs" : ""), + ((defined $opt::keeporder) ? "--keeporder" : ""), + ((defined $opt::linebuffer) ? "--linebuffer" : ""), + ((defined $opt::max_chars) ? "--max-chars ".$opt::max_chars : ""), + ((defined $opt::plain) ? "--plain" : ""), + ((defined $opt::ungroup) ? "-u" : ""), + ((defined $opt::tee) ? "--tee" : ""), + ); + my $suboptions = + join(" ", + ((defined $opt::D) ? "-D $opt::D" : ""), + ((defined $opt::arg_file_sep) ? "--arg-file-sep ".$opt::arg_file_sep : ""), + ((defined $opt::arg_sep) ? "--arg-sep ".$opt::arg_sep : ""), + ((defined $opt::colsep) ? "--colsep ".shell_quote($opt::colsep) : ""), + ((defined $opt::files) ? "--files" : ""), + ((defined $opt::group) ? "-g" : ""), + ((defined $opt::cleanup) ? "--cleanup" : ""), + ((defined $opt::keeporder) ? "--keeporder" : ""), + ((defined $opt::linebuffer) ? "--linebuffer" : ""), + ((defined $opt::max_chars) ? "--max-chars ".$opt::max_chars : ""), + ((defined $opt::plain) ? "--plain" : ""), + ((defined $opt::retries) ? "--retries ".$opt::retries : ""), + ((defined $opt::timeout) ? "--timeout ".$opt::timeout : ""), + ((defined $opt::ungroup) ? "-u" : ""), + ((defined $opt::tee) ? "--tee" : ""), + ((defined $opt::workdir) ? "--wd ".::shell_quote_scalar($opt::workdir) : ""), + (@Global::transfer_files ? map { "--tf ".::shell_quote_scalar($_) } + @Global::transfer_files : ""), + (@Global::ret_files ? map { "--return ".::shell_quote_scalar($_) } + @Global::ret_files : ""), + (@opt::env ? map { "--env ".::shell_quote_scalar($_) } @opt::env : ""), + (map { "-v" } @opt::v), + ); + ::debug("init", "| $0 $options\n"); + open(my $parallel_fh, "|-", "$0 --will-cite -j0 $options") || + ::die_bug("This does not run GNU Parallel: $0 $options"); + my @joblogs; + for my $host (sort keys %Global::host) { + my $sshlogin = $Global::host{$host}; + my $joblog = tmp_joblog($opt::joblog); + if($joblog) { + push @joblogs, $joblog; + $joblog = "--joblog $joblog"; + } + my $quad = $opt::arg_file_sep || "::::"; + ::debug("init", "$0 $suboptions -j1 $joblog ", + ((defined $opt::tag) ? + "--tagstring ".shell_quote_scalar($sshlogin->string()) : ""), + " -S ", shell_quote_scalar($sshlogin->string())," ", + join(" ",shell_quote(@command))," $quad @argfiles\n"); + print $parallel_fh "$0 $suboptions -j1 $joblog ", + ((defined $opt::tag) ? + "--tagstring ".shell_quote_scalar($sshlogin->string()) : ""), + " -S ", shell_quote_scalar($sshlogin->string())," ", + join(" ",shell_quote(@command))," $quad @argfiles\n"; + } + close $parallel_fh; + $Global::exitstatus = $? >> 8; + debug("init", "--onall exitvalue ", $?); + if(@opt::basefile and $opt::cleanup) { cleanup_basefile(); } + $Global::debug or unlink(@argfiles); + my %seen; + for my $joblog (@joblogs) { + # Append to $joblog + open(my $fh, "<", $joblog) || ::die_bug("Cannot open tmp joblog $joblog"); + # Skip first line (header); + <$fh>; + print $Global::joblog (<$fh>); + close $fh; + unlink($joblog); + } +} + + +sub __SIGNAL_HANDLING__ {} + + +sub sigtstp { + # Send TSTP signal (Ctrl-Z) to all children process groups + # Uses: + # %SIG + # Returns: N/A + signal_children("TSTP"); +} + +sub sigpipe { + # Send SIGPIPE signal to all children process groups + # Uses: + # %SIG + # Returns: N/A + signal_children("PIPE"); +} + +sub signal_children { + # Send signal to all children process groups + # and GNU Parallel itself + # Uses: + # %SIG + # Returns: N/A + my $signal = shift; + debug("run", "Sending $signal "); + kill $signal, map { -$_ } keys %Global::running; + # Use default signal handler for GNU Parallel itself + $SIG{$signal} = undef; + kill $signal, $$; +} + +sub save_original_signal_handler { + # Remember the original signal handler + # Uses: + # %Global::original_sig + # Returns: N/A + $SIG{INT} = sub { + if($opt::tmux) { ::qqx("tmux kill-session -t p$$"); } + wait_and_exit(255); + }; + $SIG{TERM} = sub { + if($opt::tmux) { ::qqx("tmux kill-session -t p$$"); } + wait_and_exit(255); + }; + %Global::original_sig = %SIG; + $SIG{TERM} = sub {}; # Dummy until jobs really start + $SIG{ALRM} = 'IGNORE'; + # Allow Ctrl-Z to suspend and `fg` to continue + $SIG{TSTP} = \&sigtstp; + $SIG{PIPE} = \&sigpipe; + $SIG{CONT} = sub { + # Set $SIG{TSTP} again (it is undef'ed in sigtstp() ) + $SIG{TSTP} = \&sigtstp; + # Send continue signal to all children process groups + kill "CONT", map { -$_ } keys %Global::running; + }; +} + +sub list_running_jobs { + # Print running jobs on tty + # Uses: + # %Global::running + # Returns: N/A + for my $job (values %Global::running) { + ::status("$Global::progname: ".$job->replaced()); + } +} + +sub start_no_new_jobs { + # Start no more jobs + # Uses: + # %Global::original_sig + # %Global::unlink + # $Global::start_no_new_jobs + # Returns: N/A + $SIG{TERM} = $Global::original_sig{TERM}; + unlink keys %Global::unlink; + ::status + ("$Global::progname: SIGTERM received. No new jobs will be started.", + "$Global::progname: Waiting for these ".(keys %Global::running). + " jobs to finish. Send SIGTERM again to stop now."); + list_running_jobs(); + $Global::start_no_new_jobs ||= 1; +} + +sub reaper { + # A job finished. + # Print the output. + # Start another job + # Uses: + # %Global::sshmaster + # %Global::running + # $opt::timeout + # $Global::timeoutq + # $opt::halt + # $opt::keeporder + # $Global::total_running + # Returns: + # @pids_reaped = PIDs of children finished + my $stiff; + my @pids_reaped; + my $children_reaped = 0; + debug("run", "Reaper "); + # For efficiency surround with BEGIN/COMMIT when using $opt::sqlmaster + $opt::sqlmaster and $Global::sql->run("BEGIN;"); + while (($stiff = waitpid(-1, &WNOHANG)) > 0) { + # $stiff = pid of dead process + if(wantarray) { + push(@pids_reaped,$stiff); + } else { + $children_reaped++; + } + if($Global::sshmaster{$stiff}) { + # This is one of the ssh -M: ignore + next; + } + my $job = $Global::running{$stiff}; + + # '-a <(seq 10)' will give us a pid not in %Global::running + $job or next; + delete $Global::running{$stiff}; + $Global::total_running--; + if($job->{'commandline'}{'skip'}) { + # $job->skip() was called + $job->set_exitstatus(-2); + $job->set_exitsignal(0); + } else { + $job->set_exitstatus($? >> 8); + $job->set_exitsignal($? & 127); + } + + debug("run", "seq ",$job->seq()," died (", $job->exitstatus(), ")"); + $job->set_endtime(::now()); + my $sshlogin = $job->sshlogin(); + $sshlogin->dec_jobs_running(); + if($job->should_be_retried()) { + $job->free_ressources(); + } else { + # The job is done + $sshlogin->inc_jobs_completed(); + # Free the jobslot + $job->free_slot(); + if($opt::timeout and not $job->exitstatus()) { + # Update average runtime for timeout only for successful jobs + $Global::timeoutq->update_median_runtime($job->runtime()); + } + if($opt::keeporder) { + $job->print_earlier_jobs(); + } else { + $job->print(); + } + if($job->should_we_halt() eq "now") { + # Kill children + ::kill_sleep_seq($job->pid()); + ::killall(); + ::wait_and_exit($Global::halt_exitstatus); + } + } + $job->cleanup(); + start_more_jobs(); + if($opt::progress) { + my %progress = progress(); + ::status_no_nl("\r",$progress{'status'}); + } + } + $opt::sqlmaster and $Global::sql->run("COMMIT;"); + debug("run", "done "); + return wantarray ? @pids_reaped : $children_reaped; +} + + +sub __USAGE__ {} + + +sub killall { + # Kill all jobs by killing their process groups + + $Global::start_no_new_jobs ||= 1; + $Global::killall ||= 1; + kill_sleep_seq(keys %Global::running); +} + +sub kill_sleep_seq { + # Send jobs TERM,TERM,KILL to processgroups + # Input: + # @pids = list of pids that are also processgroups + # Convert pids to process groups ($processgroup = -$pid) + my @pgrps = map { -$_ } @_; + my @term_seq = split/,/,$opt::termseq; + if(not @term_seq) { + @term_seq = ("TERM",200,"TERM",100,"TERM",50,"KILL",25); + } + while(@term_seq) { + @pgrps = kill_sleep(shift @term_seq, shift @term_seq, @pgrps); + } +} + +sub kill_sleep { + my ($signal, $sleep_max, @pids) = @_; + ::debug("kill","kill_sleep $signal ",(join " ",sort @pids),"\n"); + kill $signal, @pids; + my $sleepsum = 0; + my $sleep = 0.001; + my @dead; + + while(@pids and $sleepsum < $sleep_max) { + if($Global::killall) { + # Killall => don't run reaper + my $stiff; + while (($stiff = waitpid(-1, &WNOHANG)) > 0) { + # remove $stiff from @pids + @pids = grep { $_ != $stiff } @pids; + $sleep = $sleep/2+0.001; + } + } elsif(@dead = reaper()) { + # Remove reaped pids + for my $stiff (@dead) { + @pids = grep { $_ != $stiff } @pids; + } + $sleep = $sleep/2+0.001; + } + @pids = grep { kill( 0, $_) } @pids; + $sleep *= 1.1; + ::usleep($sleep); + $sleepsum += $sleep; + # Remove dead children + @pids = grep { kill( 0, $_) } @pids; + } + return @pids; +} + +sub wait_and_exit { + # If we do not wait, we sometimes get segfault + # Returns: N/A + my $error = shift; + unlink keys %Global::unlink; + if($error) { + # Kill all jobs without printing + killall(); + } + for (keys %Global::unkilled_children) { + # Kill any (non-jobs) children + kill 9, $_; + waitpid($_,0); + delete $Global::unkilled_children{$_}; + } + if($Global::unkilled_sqlworker) { + waitpid($Global::unkilled_sqlworker,0); + } + exit($error); +} + +sub die_usage { + # Returns: N/A + usage(); + wait_and_exit(255); +} + +sub usage { + # Returns: N/A + print join + ("\n", + "Usage:", + "", + "$Global::progname [options] [command [arguments]] < list_of_arguments", + "$Global::progname [options] [command [arguments]] (::: arguments|:::: argfile(s))...", + "cat ... | $Global::progname --pipe [options] [command [arguments]]", + "", + "-j n Run n jobs in parallel", + "-k Keep same order", + "-X Multiple arguments with context replace", + "--colsep regexp Split input on regexp for positional replacements", + "{} {.} {/} {/.} {#} {%} {= perl code =} Replacement strings", + "{3} {3.} {3/} {3/.} {=3 perl code =} Positional replacement strings", + "With --plus: {} = {+/}/{/} = {.}.{+.} = {+/}/{/.}.{+.} = {..}.{+..} =", + " {+/}/{/..}.{+..} = {...}.{+...} = {+/}/{/...}.{+...}", + "", + "-S sshlogin Example: foo\@server.example.com", + "--slf .. Use ~/.parallel/sshloginfile as the list of sshlogins", + "--trc {}.bar Shorthand for --transfer --return {}.bar --cleanup", + "--onall Run the given command with argument on all sshlogins", + "--nonall Run the given command with no arguments on all sshlogins", + "", + "--pipe Split stdin (standard input) to multiple jobs.", + "--recend str Record end separator for --pipe.", + "--recstart str Record start separator for --pipe.", + "", + "See 'man $Global::progname' for details", + "", + "Academic tradition requires you to cite works you base your article on.", + "If you use programs that use GNU Parallel to process data for an article in a", + "scientific publication, please cite:", + "", + " O. Tange (2018): GNU Parallel 2018, Mar 2018, ISBN 9781387509881,", + " DOI https://doi.org/10.5281/zenodo.1146014", + "", + "This helps funding further development; AND IT WON'T COST YOU A CENT.", + "If you pay 10000 EUR you should feel free to use GNU Parallel without citing.", + "", + "",); +} + +sub citation_notice { + # if --will-cite or --plain: do nothing + # if stderr redirected: do nothing + # if $PARALLEL_HOME/will-cite: do nothing + # else: print citation notice to stderr + if($opt::willcite + or + $opt::plain + or + not -t $Global::original_stderr + or + grep { -e "$_/will-cite" } @Global::config_dirs) { + # skip + } else { + ::status + ("Academic tradition requires you to cite works you base your article on.", + "If you use programs that use GNU Parallel to process data for an article in a", + "scientific publication, please cite:", + "", + " O. Tange (2018): GNU Parallel 2018, Mar 2018, ISBN 9781387509881,", + " DOI https://doi.org/10.5281/zenodo.1146014", + "", + "This helps funding further development; AND IT WON'T COST YOU A CENT.", + "If you pay 10000 EUR you should feel free to use GNU Parallel without citing.", + "", + "More about funding GNU Parallel and the citation notice:", + "https://www.gnu.org/software/parallel/parallel_design.html#Citation-notice", + "", + "To silence this citation notice: run 'parallel --citation' once.", + "" + ); + } +} + +sub status { + my @w = @_; + my $fh = $Global::status_fd || *STDERR; + print $fh map { ($_, "\n") } @w; + flush $fh; +} + +sub status_no_nl { + my @w = @_; + my $fh = $Global::status_fd || *STDERR; + print $fh @w; + flush $fh; +} + +sub warning { + my @w = @_; + my $prog = $Global::progname || "parallel"; + status_no_nl(map { ($prog, ": Warning: ", $_, "\n"); } @w); +} + +sub error { + my @w = @_; + my $prog = $Global::progname || "parallel"; + status(map { ($prog.": Error: ". $_); } @w); +} + +sub die_bug { + my $bugid = shift; + print STDERR + ("$Global::progname: This should not happen. You have found a bug.\n", + "Please contact and follow\n", + "https://www.gnu.org/software/parallel/man.html#REPORTING-BUGS\n", + "\n", + "Include this in the report:\n", + "* The version number: $Global::version\n", + "* The bugid: $bugid\n", + "* The command line being run\n", + "* The files being read (put the files on a webserver if they are big)\n", + "\n", + "If you get the error on smaller/fewer files, please include those instead.\n"); + ::wait_and_exit(255); +} + +sub version { + # Returns: N/A + print join("\n", + "GNU $Global::progname $Global::version", + "Copyright (C) 2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018", + "Ole Tange and Free Software Foundation, Inc.", + "License GPLv3+: GNU GPL version 3 or later ", + "This is free software: you are free to change and redistribute it.", + "GNU $Global::progname comes with no warranty.", + "", + "Web site: http://www.gnu.org/software/${Global::progname}\n", + "When using programs that use GNU Parallel to process data for publication", + "please cite as described in 'parallel --citation'.\n", + ); +} + +sub citation { + # Returns: N/A + my ($all_argv_ref,$argv_options_removed_ref) = @_; + my $all_argv = "@$all_argv_ref"; + my $no_opts = "@$argv_options_removed_ref"; + $all_argv=~s/--citation//; + if($all_argv ne $no_opts) { + ::warning("--citation ignores all other options and arguments."); + ::status(""); + } + + ::status( + "Academic tradition requires you to cite works you base your article on.", + "If you use programs that use GNU Parallel to process data for an article in a", + "scientific publication, please cite:", + "", + "\@book{tange_ole_2018_1146014,", + " author = {Tange, Ole},", + " title = {GNU Parallel 2018},", + " publisher = {Ole Tange},", + " month = Mar,", + " year = 2018,", + " ISBN = {9781387509881},", + " doi = {10.5281/zenodo.1146014},", + " url = {https://doi.org/10.5281/zenodo.1146014}", + "}", + "", + "(Feel free to use \\nocite{tange_ole_2018_1146014})", + "", + "This helps funding further development; AND IT WON'T COST YOU A CENT.", + "If you pay 10000 EUR you should feel free to use GNU Parallel without citing.", + "", + "More about funding GNU Parallel and the citation notice:", + "https://www.gnu.org/software/parallel/parallel_design.html#Citation-notice", + "", + "If you send a copy of your published article to tange\@gnu.org, it will be", + "mentioned in the release notes of next version of GNU Parallel.", + "" + ); + while(not grep { -e "$_/will-cite" } @Global::config_dirs) { + print "\nType: 'will cite' and press enter.\n> "; + my $input = ; + if(not defined $input) { + exit(255); + } + if($input =~ /will cite/i) { + mkdir $Global::config_dir; + if(open (my $fh, ">", $Global::config_dir."/will-cite")) { + close $fh; + ::status( + "", + "Thank you for your support. It is much appreciated. The citation", + "notice is now silenced.", + ""); + } else { + ::status( + "", + "Thank you for your support. It is much appreciated. The citation", + "cannot permanently be silenced. Use '--will-cite' instead.", + "", + "If you use '--will-cite' in scripts to be run by others you are making", + "it harder for others to see the citation notice. The development of", + "GNU parallel is indirectly financed through citations, so if users", + "do not know they should cite then you are making it harder to finance", + "development. However, if you pay 10000 EUR, you should feel free to", + "use '--will-cite' in scripts.", + ""); + last; + } + } + } +} + +sub show_limits { + # Returns: N/A + print("Maximal size of command: ",Limits::Command::real_max_length(),"\n", + "Maximal used size of command: ",Limits::Command::max_length(),"\n", + "\n", + "Execution of will continue now, and it will try to read its input\n", + "and run commands; if this is not what you wanted to happen, please\n", + "press CTRL-D or CTRL-C\n"); +} + +sub embed { + # Give an embeddable version of GNU Parallel + # Tested with: bash, zsh, ksh, ash, dash, sh + my $randomstring = "cut-here-".join"", + map { (0..9,"a".."z","A".."Z")[rand(62)] } (1..20); + if(not -f $0 or not -r $0) { + ::error("--embed only works if parallel is a readable file"); + exit(255); + } + if(open(my $fh, "<", $0)) { + # Read the source from $0 + my @source = <$fh>; + my $user = $ENV{LOGNAME} || $ENV{USERNAME} || $ENV{USER}; + my @env_parallel_source = (); + my $shell = $Global::shell; + $shell =~ s:.*/::; + for(which("env_parallel.$shell")) { + -r $_ or next; + # Read the source of env_parallel.shellname + open(my $env_parallel_source_fh, $_) || die; + @env_parallel_source = <$env_parallel_source_fh>; + close $env_parallel_source_fh; + last; + } + print "#!$Global::shell + +# Copyright (C) 2007,2008,2009,2010,2011,2012,2013,2014,2015,2016, +# 2017,2018 $user, Ole Tange and Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# or write to the Free Software Foundation, Inc., 51 Franklin St, +# Fifth Floor, Boston, MA 02110-1301 USA +"; + + print q! +# Embedded GNU Parallel created with --embed +parallel() { + # Start GNU Parallel without leaving temporary files + # + # Not all shells support 'perl <(cat ...)' + # This is a complex way of doing: + # perl <(cat <<'cut-here' + # [...] + # ) "$@" + # and also avoiding: + # [1]+ Done cat + + # Make a temporary fifo that perl can read from + _fifo_with_parallel_source=`perl -e 'use POSIX qw(mkfifo); + do { + $f = "/tmp/parallel-".join"", + map { (0..9,"a".."z","A".."Z")[rand(62)] } (1..5); + } while(-e $f); + mkfifo($f,0600); + print $f;'` + # Put source code into temporary file + # so it is easy to copy to the fifo + _file_with_parallel_source=`mktemp`; +!, + "cat <<'$randomstring' > \$_file_with_parallel_source\n", + @source, + $randomstring,"\n", + q! + # Copy the source code from the file to the fifo + # and remove the file and fifo ASAP + # 'sh -c' is needed to avoid + # [1]+ Done cat + sh -c "(rm $_file_with_parallel_source; cat >$_fifo_with_parallel_source; rm $_fifo_with_parallel_source) < $_file_with_parallel_source &" + + # Read the source from the fifo + perl $_fifo_with_parallel_source "$@" +} +!, + @env_parallel_source, + q! + +# This will call the functions above +parallel -k echo ::: Put your code here +env_parallel --session +env_parallel -k echo ::: Put your code here +parset p,y,c,h -k echo ::: Put your code here +echo $p $y $c $h +!; + } else { + ::error("Cannot open $0"); + exit(255); + } + ::status("Redirect the output to a file and add your changes at the end:", + " $0 --embed > new_script"); +} + +sub __GENERIC_COMMON_FUNCTION__ {} + + +sub mkdir_or_die { + # If dir is not executable: die + my $dir = shift; + # The eval is needed to catch exception from mkdir + eval { File::Path::mkpath($dir); }; + if(not -x $dir) { + ::error("Cannot change into non-executable dir $dir: $!"); + ::wait_and_exit(255); + } +} + +sub tmpfile { + # Create tempfile as $TMPDIR/parXXXXX + # Returns: + # $filehandle = opened file handle + # $filename = file name created + my($filehandle,$filename) = + ::tempfile(DIR=>$ENV{'TMPDIR'}, TEMPLATE => 'parXXXXX', @_); + if(wantarray) { + return($filehandle,$filename); + } else { + # Separate unlink due to NFS dealing badly with File::Temp + unlink $filename; + return $filehandle; + } +} + +sub tmpname { + # Select a name that does not exist + # Do not create the file as it may be used for creating a socket (by tmux) + # Remember the name in $Global::unlink to avoid hitting the same name twice + my $name = shift; + my($tmpname); + if(not -w $ENV{'TMPDIR'}) { + if(not -e $ENV{'TMPDIR'}) { + ::error("Tmpdir '$ENV{'TMPDIR'}' does not exist.","Try 'mkdir $ENV{'TMPDIR'}'"); + } else { + ::error("Tmpdir '$ENV{'TMPDIR'}' is not writable.","Try 'chmod +w $ENV{'TMPDIR'}'"); + } + ::wait_and_exit(255); + } + do { + $tmpname = $ENV{'TMPDIR'}."/".$name. + join"", map { (0..9,"a".."z","A".."Z")[rand(62)] } (1..5); + } while(-e $tmpname or $Global::unlink{$tmpname}++); + return $tmpname; +} + +sub tmpfifo { + # Find an unused name and mkfifo on it + use POSIX qw(mkfifo); + my $tmpfifo = tmpname("fif",@_); + mkfifo($tmpfifo,0600); + return $tmpfifo; +} + +sub rm { + # Remove file and remove it from %Global::unlink + # Uses: + # %Global::unlink + delete @Global::unlink{@_}; + unlink @_; +} + +sub size_of_block_dev { + # Like -s but for block devices + # Input: + # $blockdev = file name of block device + # Returns: + # $size = in bytes, undef if error + my $blockdev = shift; + if(open(my $fh, "<", $blockdev)) { + seek($fh,0,2) || ::die_bug("cannot seek $blockdev"); + my $size = tell($fh); + close $fh; + return $size; + } else { + ::error("cannot open $blockdev"); + wait_and_exit(255); + } +} + +sub qqx { + # Like qx but with clean environment (except for @keep) + # and STDERR ignored + # This is needed if the environment contains functions + # that /bin/sh does not understand + my $PATH = $ENV{'PATH'}; + my %env; + # ssh with ssh-agent needs PATH SSH_AUTH_SOCK SSH_AGENT_PID + # ssh with Kerberos needs KRB5CCNAME + # tmux needs LC_CTYPE + my @keep = qw(PATH SSH_AUTH_SOCK SSH_AGENT_PID KRB5CCNAME LC_CTYPE); + @env{@keep} = @ENV{@keep}; + local %ENV; + %ENV = %env; + if($Global::debug) { + return qx{ @_ && true }; + } else { + return qx{ ( @_ ) 2>/dev/null }; + } +} + +sub uniq { + # Remove duplicates and return unique values + return keys %{{ map { $_ => 1 } @_ }}; +} + +sub min { + # Returns: + # Minimum value of array + my $min; + for (@_) { + # Skip undefs + defined $_ or next; + defined $min or do { $min = $_; next; }; # Set $_ to the first non-undef + $min = ($min < $_) ? $min : $_; + } + return $min; +} + +sub max { + # Returns: + # Maximum value of array + my $max; + for (@_) { + # Skip undefs + defined $_ or next; + defined $max or do { $max = $_; next; }; # Set $_ to the first non-undef + $max = ($max > $_) ? $max : $_; + } + return $max; +} + +sub sum { + # Returns: + # Sum of values of array + my @args = @_; + my $sum = 0; + for (@args) { + # Skip undefs + $_ and do { $sum += $_; } + } + return $sum; +} + +sub undef_as_zero { + my $a = shift; + return $a ? $a : 0; +} + +sub undef_as_empty { + my $a = shift; + return $a ? $a : ""; +} + +sub undef_if_empty { + if(defined($_[0]) and $_[0] eq "") { + return undef; + } + return $_[0]; +} + +sub multiply_binary_prefix { + # Evalualte numbers with binary prefix + # Ki=2^10, Mi=2^20, Gi=2^30, Ti=2^40, Pi=2^50, Ei=2^70, Zi=2^80, Yi=2^80 + # ki=2^10, mi=2^20, gi=2^30, ti=2^40, pi=2^50, ei=2^70, zi=2^80, yi=2^80 + # K =2^10, M =2^20, G =2^30, T =2^40, P =2^50, E =2^70, Z =2^80, Y =2^80 + # k =10^3, m =10^6, g =10^9, t=10^12, p=10^15, e=10^18, z=10^21, y=10^24 + # 13G = 13*1024*1024*1024 = 13958643712 + # Input: + # $s = string with prefixes + # Returns: + # $value = int with prefixes multiplied + my @v = @_; + for(@v) { + defined $_ or next; + s/ki/*1024/gi; + s/mi/*1024*1024/gi; + s/gi/*1024*1024*1024/gi; + s/ti/*1024*1024*1024*1024/gi; + s/pi/*1024*1024*1024*1024*1024/gi; + s/ei/*1024*1024*1024*1024*1024*1024/gi; + s/zi/*1024*1024*1024*1024*1024*1024*1024/gi; + s/yi/*1024*1024*1024*1024*1024*1024*1024*1024/gi; + s/xi/*1024*1024*1024*1024*1024*1024*1024*1024*1024/gi; + + s/K/*1024/g; + s/M/*1024*1024/g; + s/G/*1024*1024*1024/g; + s/T/*1024*1024*1024*1024/g; + s/P/*1024*1024*1024*1024*1024/g; + s/E/*1024*1024*1024*1024*1024*1024/g; + s/Z/*1024*1024*1024*1024*1024*1024*1024/g; + s/Y/*1024*1024*1024*1024*1024*1024*1024*1024/g; + s/X/*1024*1024*1024*1024*1024*1024*1024*1024*1024/g; + + s/k/*1000/g; + s/m/*1000*1000/g; + s/g/*1000*1000*1000/g; + s/t/*1000*1000*1000*1000/g; + s/p/*1000*1000*1000*1000*1000/g; + s/e/*1000*1000*1000*1000*1000*1000/g; + s/z/*1000*1000*1000*1000*1000*1000*1000/g; + s/y/*1000*1000*1000*1000*1000*1000*1000*1000/g; + s/x/*1000*1000*1000*1000*1000*1000*1000*1000*1000/g; + + $_ = eval $_; + } + return wantarray ? @v : $v[0]; +} + +sub multiply_time_units { + # Evalualte numbers with time units + # s=1, m=60, h=3600, d=86400 + # Input: + # $s = string time units + # Returns: + # $value = int in seconds + my @v = @_; + for(@v) { + defined $_ or next; + if(/[dhms]/i) { + s/s/*1+/gi; + s/m/*60+/gi; + s/h/*3600+/gi; + s/d/*86400+/gi; + $_ = eval $_."0"; + } + } + return wantarray ? @v : $v[0]; +} + +sub seconds_to_time_units { + # Convert seconds into ??d??h??m??s + # s=1, m=60, h=3600, d=86400 + # Input: + # $s = int in seconds + # Returns: + # $str = string time units + my $s = shift; + my $str; + my $d = int($s/86400); + $s -= $d * 86400; + my $h = int($s/3600); + $s -= $h * 3600; + my $m = int($s/60); + $s -= $m * 60; + if($d) { + $str = sprintf("%dd%02dh%02dm%02ds",$d,$h,$m,$s); + } elsif($h) { + $str = sprintf("%dh%02dm%02ds",$h,$m,$s); + } elsif($m) { + $str = sprintf("%dm%02ds",$m,$s); + } else { + $str = sprintf("%ds",$s); + } + return $str; +} + +{ + my ($disk_full_fh, $b8193, $error_printed); + sub exit_if_disk_full { + # Checks if $TMPDIR is full by writing 8kb to a tmpfile + # If the disk is full: Exit immediately. + # Returns: + # N/A + if(not $disk_full_fh) { + $disk_full_fh = ::tmpfile(SUFFIX => ".df"); + $b8193 = "x"x8193; + } + # Linux does not discover if a disk is full if writing <= 8192 + # Tested on: + # bfs btrfs cramfs ext2 ext3 ext4 ext4dev jffs2 jfs minix msdos + # ntfs reiserfs tmpfs ubifs vfat xfs + # TODO this should be tested on different OS similar to this: + # + # doit() { + # sudo mount /dev/ram0 /mnt/loop; sudo chmod 1777 /mnt/loop + # seq 100000 | parallel --tmpdir /mnt/loop/ true & + # seq 6900000 > /mnt/loop/i && echo seq OK + # seq 6980868 > /mnt/loop/i + # seq 10000 > /mnt/loop/ii + # sleep 3 + # sudo umount /mnt/loop/ || sudo umount -l /mnt/loop/ + # echo >&2 + # } + print $disk_full_fh $b8193; + if(not $disk_full_fh + or + tell $disk_full_fh != 8193) { + # On raspbian the disk can be full except for 10 chars. + if(not $error_printed) { + ::error("Output is incomplete.", + "Cannot append to buffer file in $ENV{'TMPDIR'}.", + "Is the disk full?", + "Change \$TMPDIR with --tmpdir or use --compress."); + $error_printed = 1; + } + ::wait_and_exit(255); + } + truncate $disk_full_fh, 0; + seek($disk_full_fh, 0, 0) || die; + } +} + +sub spacefree { + # Remove comments and spaces + # Inputs: + # $spaces = keep 1 space? + # $s = string to remove spaces from + # Returns: + # $s = with spaces removed + my $spaces = shift; + my $s = shift; + $s =~ s/#.*//mg; + if(1 == $spaces) { + $s =~ s/\s+/ /mg; + } elsif(2 == $spaces) { + # Keep newlines + $s =~ s/\n\n+/\n/sg; + $s =~ s/[ \t]+/ /mg; + } else { + $s =~ s/\s//mg; + } + return $s; +} + +{ + my $hostname; + sub hostname { + local $/ = "\n"; + if(not $hostname) { + $hostname = `hostname`; + chomp($hostname); + $hostname ||= "nohostname"; + } + return $hostname; + } +} + +sub which { + # Input: + # @programs = programs to find the path to + # Returns: + # @full_path = full paths to @programs. Nothing if not found + my @which; + ::debug("which", "@_ in $ENV{'PATH'}\n"); + for my $prg (@_) { + push(@which, grep { not -d $_ and -x $_ } + map { $_."/".$prg } split(":",$ENV{'PATH'})); + if($prg =~ m:/:) { + # Including path + push(@which, grep { not -d $_ and -x $_ } $prg); + } + } + return @which; +} + +{ + my ($regexp,$shell,%fakename); + + sub parent_shell { + # Input: + # $pid = pid to see if (grand)*parent is a shell + # Returns: + # $shellpath = path to shell - undef if no shell found + my $pid = shift; + ::debug("init","Parent of $pid\n"); + if(not $regexp) { + # All shells known to mankind + # + # ash bash csh dash fdsh fish fizsh ksh ksh93 mksh pdksh + # posh rbash rc rush rzsh sash sh static-sh tcsh yash zsh + + my @shells = (qw(ash bash bsd-csh csh dash fdsh fish fizsh + ksh ksh93 lksh mksh pdksh posh rbash rc rush rzsh sash sh + static-sh tcsh yash zsh -sh -csh -bash), + '-sh (sh)' # sh on FreeBSD + ); + # Can be formatted as: + # [sh] -sh sh busybox sh -sh (sh) + # /bin/sh /sbin/sh /opt/csw/sh + # But not: foo.sh sshd crash flush pdflush scosh fsflush ssh + $shell = "(?:".join("|",map { "\Q$_\E" } @shells).")"; + $regexp = '^((\[)(-?)('. $shell. ')(\])|(|\S+/|busybox )'. + '(-?)('. $shell. '))( *$| [^(])'; + %fakename = ( + # sh disguises itself as -sh (sh) on FreeBSD + "-sh (sh)" => ["sh"], + # csh and tcsh disguise themselves as -sh/-csh + # E.g.: ssh -tt csh@lo 'ps aux;true' |egrep ^csh + # but sh also disguise itself as -sh + # (When?) + "-sh" => ["sh"], + "-csh" => ["tcsh", "csh"], + # ash disguises itself as -ash + "-ash" => ["ash", "dash", "sh"], + # dash disguises itself as -dash + "-dash" => ["dash", "ash", "sh"], + # bash disguises itself as -bash + "-bash" => ["bash", "sh"], + # ksh disguises itself as -ash + "-ksh" => ["ksh", "sh"], + # zsh disguises itself as -zsh + "-zsh" => ["zsh", "sh"], + ); + } + # if -sh or -csh try readlink /proc/$$/exe + my ($children_of_ref, $parent_of_ref, $name_of_ref) = pid_table(); + my $shellpath; + my $testpid = $pid; + while($testpid) { + if($name_of_ref->{$testpid} =~ /$regexp/o) { + my $shellname = $4 || $8; + my $dash = $3 || $7; + if($shellname eq "sh" and $dash) { + # -sh => csh or sh + if($shellpath = readlink "/proc/$testpid/exe") { + ::debug("init","procpath $shellpath\n"); + if($shellpath =~ m:/$shell$:o) { + ::debug("init", "proc which ".$shellpath." => "); + return $shellpath; + } + } + } + ::debug("init", "which ".$shellname." => "); + $shellpath = (which($shellname,@{$fakename{$shellname}}))[0]; + ::debug("init", "shell path $shellpath\n"); + $shellpath and last; + } + if($testpid == $parent_of_ref->{$testpid}) { + # In Solaris zones, the PPID of the zsched process is itself + last; + } + $testpid = $parent_of_ref->{$testpid}; + } + return $shellpath; + } +} + +{ + my %pid_parentpid_cmd; + + sub pid_table { + # Returns: + # %children_of = { pid -> children of pid } + # %parent_of = { pid -> pid of parent } + # %name_of = { pid -> commandname } + + if(not %pid_parentpid_cmd) { + # Filter for SysV-style `ps` + my $sysv = q( ps -ef | perl -ane '1..1 and /^(.*)CO?MM?A?N?D/ and $s=length $1;). + q(s/^.{$s}//; print "@F[1,2] $_"' ); + # Crazy msys: ' is not accepted on the cmd line, but " are treated as ' + my $msys = q( ps -ef | perl -ane "1..1 and /^(.*)CO?MM?A?N?D/ and $s=length $1;). + q(s/^.{$s}//; print qq{@F[1,2] $_}" ); + # BSD-style `ps` + my $bsd = q(ps -o pid,ppid,command -ax); + %pid_parentpid_cmd = + ( + 'aix' => $sysv, + 'android' => $sysv, + 'cygwin' => $sysv, + 'darwin' => $bsd, + 'dec_osf' => $sysv, + 'dragonfly' => $bsd, + 'freebsd' => $bsd, + 'gnu' => $sysv, + 'hpux' => $sysv, + 'linux' => $sysv, + 'mirbsd' => $bsd, + 'msys' => $msys, + 'MSWin32' => $sysv, + 'netbsd' => $bsd, + 'nto' => $sysv, + 'openbsd' => $bsd, + 'solaris' => $sysv, + 'svr5' => $sysv, + 'syllable' => "echo ps not supported", + ); + } + $pid_parentpid_cmd{$^O} or ::die_bug("pid_parentpid_cmd for $^O missing"); + + my (@pidtable,%parent_of,%children_of,%name_of); + # Table with pid -> children of pid + @pidtable = `$pid_parentpid_cmd{$^O}`; + my $p=$$; + for (@pidtable) { + # must match: 24436 21224 busybox ash + # must match: 24436 21224 <> + # must match: 24436 21224 <> + # or: perl -e 'while($0=" "){}' + if(/^\s*(\S+)\s+(\S+)\s+(\S+.*)/ + or + /^\s*(\S+)\s+(\S+)\s+()$/) { + $parent_of{$1} = $2; + push @{$children_of{$2}}, $1; + $name_of{$1} = $3; + } else { + ::die_bug("pidtable format: $_"); + } + } + return(\%children_of, \%parent_of, \%name_of); + } +} + +sub now { + # Returns time since epoch as in seconds with 3 decimals + # Uses: + # @Global::use + # Returns: + # $time = time now with millisecond accuracy + if(not $Global::use{"Time::HiRes"}) { + if(eval "use Time::HiRes qw ( time );") { + eval "sub TimeHiRestime { return Time::HiRes::time };"; + } else { + eval "sub TimeHiRestime { return time() };"; + } + $Global::use{"Time::HiRes"} = 1; + } + + return (int(TimeHiRestime()*1000))/1000; +} + +sub usleep { + # Sleep this many milliseconds. + # Input: + # $ms = milliseconds to sleep + my $ms = shift; + ::debug("timing",int($ms),"ms "); + select(undef, undef, undef, $ms/1000); +} + +sub reap_usleep { + # Reap dead children. + # If no dead children: Sleep specified amount with exponential backoff + # Input: + # $ms = milliseconds to sleep + # Returns: + # $ms/2+0.001 if children reaped + # $ms*1.1 if no children reaped + my $ms = shift; + if(reaper()) { + if(not $Global::total_completed % 100) { + if($opt::timeout) { + # Force cleaning the timeout queue for every 1000 jobs + # Fixes potential memleak + $Global::timeoutq->process_timeouts(); + } + } + # Sleep exponentially shorter (1/2^n) if a job finished + return $ms/2+0.001; + } else { + if($opt::timeout) { + $Global::timeoutq->process_timeouts(); + } + if($opt::memfree) { + kill_youngster_if_not_enough_mem(); + } + if($opt::limit) { + kill_youngest_if_over_limit(); + } + if($ms > 0.002) { + # When a child dies, wake up from sleep (or select(,,,)) + $SIG{CHLD} = sub { kill "ALRM", $$ }; + usleep($ms); + # --compress needs $SIG{CHLD} unset + $SIG{CHLD} = 'DEFAULT'; + } + exit_if_disk_full(); + if($opt::linebuffer) { + my $something_printed = 0; + if($opt::keeporder) { + for my $job (values %Global::running) { + $something_printed += $job->print_earlier_jobs(); + } + } else { + for my $job (values %Global::running) { + $something_printed += $job->print(); + } + } + if($something_printed) { + $ms = $ms/2+0.001; + } + } + # Sleep exponentially longer (1.1^n) if a job did not finish, + # though at most 1000 ms. + return (($ms < 1000) ? ($ms * 1.1) : ($ms)); + } +} + +sub kill_youngest_if_over_limit { + # Check each $sshlogin we are over limit + # If over limit: kill off the youngest child + # Put the child back in the queue. + # Uses: + # %Global::running + my %jobs_of; + my @sshlogins; + + for my $job (values %Global::running) { + if(not $jobs_of{$job->sshlogin()}) { + push @sshlogins, $job->sshlogin(); + } + push @{$jobs_of{$job->sshlogin()}}, $job; + } + for my $sshlogin (@sshlogins) { + for my $job (sort { $b->seq() <=> $a->seq() } @{$jobs_of{$sshlogin}}) { + if($sshlogin->limit() == 2) { + $job->kill(); + last; + } + } + } +} + +sub kill_youngster_if_not_enough_mem { + # Check each $sshlogin if there is enough mem. + # If less than 50% enough free mem: kill off the youngest child + # Put the child back in the queue. + # Uses: + # %Global::running + my %jobs_of; + my @sshlogins; + + for my $job (values %Global::running) { + if(not $jobs_of{$job->sshlogin()}) { + push @sshlogins, $job->sshlogin(); + } + push @{$jobs_of{$job->sshlogin()}}, $job; + } + for my $sshlogin (@sshlogins) { + for my $job (sort { $b->seq() <=> $a->seq() } @{$jobs_of{$sshlogin}}) { + if($sshlogin->memfree() < $opt::memfree * 0.5) { + ::debug("mem","\n",map { $_->seq()." " } + (sort { $b->seq() <=> $a->seq() } + @{$jobs_of{$sshlogin}})); + ::debug("mem","\n", $job->seq(), "killed ", + $sshlogin->memfree()," < ",$opt::memfree * 0.5); + $job->kill(); + $sshlogin->memfree_recompute(); + } else { + last; + } + } + ::debug("mem","Free mem OK ", + $sshlogin->memfree()," > ",$opt::memfree * 0.5); + } +} + + +sub __DEBUGGING__ {} + + +sub debug { + # Uses: + # $Global::debug + # %Global::fd + # Returns: N/A + $Global::debug or return; + @_ = grep { defined $_ ? $_ : "" } @_; + if($Global::debug eq "all" or $Global::debug eq $_[0]) { + if($Global::fd{1}) { + # Original stdout was saved + my $stdout = $Global::fd{1}; + print $stdout @_[1..$#_]; + } else { + print @_[1..$#_]; + } + } +} + +sub my_memory_usage { + # Returns: + # memory usage if found + # 0 otherwise + use strict; + use FileHandle; + + local $/ = "\n"; + my $pid = $$; + if(-e "/proc/$pid/stat") { + my $fh = FileHandle->new("; + chomp $data; + $fh->close; + + my @procinfo = split(/\s+/,$data); + + return undef_as_zero($procinfo[22]); + } else { + return 0; + } +} + +sub my_size { + # Returns: + # $size = size of object if Devel::Size is installed + # -1 otherwise + my @size_this = (@_); + eval "use Devel::Size qw(size total_size)"; + if ($@) { + return -1; + } else { + return total_size(@_); + } +} + +sub my_dump { + # Returns: + # ascii expression of object if Data::Dump(er) is installed + # error code otherwise + my @dump_this = (@_); + eval "use Data::Dump qw(dump);"; + if ($@) { + # Data::Dump not installed + eval "use Data::Dumper;"; + if ($@) { + my $err = "Neither Data::Dump nor Data::Dumper is installed\n". + "Not dumping output\n"; + ::status($err); + return $err; + } else { + return Dumper(@dump_this); + } + } else { + # Create a dummy Data::Dump:dump as Hans Schou sometimes has + # it undefined + eval "sub Data::Dump:dump {}"; + eval "use Data::Dump qw(dump);"; + return (Data::Dump::dump(@dump_this)); + } +} + +sub my_croak { + eval "use Carp; 1"; + $Carp::Verbose = 1; + croak(@_); +} + +sub my_carp { + eval "use Carp; 1"; + $Carp::Verbose = 1; + carp(@_); +} + + +sub __OBJECT_ORIENTED_PARTS__ {} + + +package SSHLogin; + +sub new { + my $class = shift; + my $sshlogin_string = shift; + my $ncpus; + my %hostgroups; + # SSHLogins can have these formats: + # @grp+grp/ncpu//usr/bin/ssh user@server + # ncpu//usr/bin/ssh user@server + # /usr/bin/ssh user@server + # user@server + # ncpu/user@server + # @grp+grp/user@server + if($sshlogin_string =~ s:^\@([^/]+)/?::) { + # Look for SSHLogin hostgroups + %hostgroups = map { $_ => 1 } split(/\+/, $1); + } + # An SSHLogin is always in the hostgroup of its "numcpu/host" + $hostgroups{$sshlogin_string} = 1; + if ($sshlogin_string =~ s:^(\d+)/::) { + # Override default autodetected ncpus unless missing + $ncpus = $1; + } + my $string = $sshlogin_string; + # An SSHLogin is always in the hostgroup of its $string-name + $hostgroups{$string} = 1; + @Global::hostgroups{keys %hostgroups} = values %hostgroups; + my @unget = (); + my $no_slash_string = $string; + $no_slash_string =~ s/[^-a-z0-9:]/_/gi; + return bless { + 'string' => $string, + 'jobs_running' => 0, + 'jobs_completed' => 0, + 'maxlength' => undef, + 'max_jobs_running' => undef, + 'orig_max_jobs_running' => undef, + 'ncpus' => $ncpus, + 'hostgroups' => \%hostgroups, + 'sshcommand' => undef, + 'serverlogin' => undef, + 'control_path_dir' => undef, + 'control_path' => undef, + 'time_to_login' => undef, + 'last_login_at' => undef, + 'loadavg_file' => $Global::cache_dir . "/tmp/sshlogin/" . + $no_slash_string . "/loadavg", + 'loadavg' => undef, + 'last_loadavg_update' => 0, + 'swap_activity_file' => $Global::cache_dir . "/tmp/sshlogin/" . + $no_slash_string . "/swap_activity", + 'swap_activity' => undef, + }, ref($class) || $class; +} + +sub DESTROY { + my $self = shift; + # Remove temporary files if they are created. + ::rm($self->{'loadavg_file'}); + ::rm($self->{'swap_activity_file'}); +} + +sub string { + my $self = shift; + return $self->{'string'}; +} + +sub jobs_running { + my $self = shift; + return ($self->{'jobs_running'} || "0"); +} + +sub inc_jobs_running { + my $self = shift; + $self->{'jobs_running'}++; +} + +sub dec_jobs_running { + my $self = shift; + $self->{'jobs_running'}--; +} + +sub set_maxlength { + my $self = shift; + $self->{'maxlength'} = shift; +} + +sub maxlength { + my $self = shift; + return $self->{'maxlength'}; +} + +sub jobs_completed { + my $self = shift; + return $self->{'jobs_completed'}; +} + +sub in_hostgroups { + # Input: + # @hostgroups = the hostgroups to look for + # Returns: + # true if intersection of @hostgroups and the hostgroups of this + # SSHLogin is non-empty + my $self = shift; + return grep { defined $self->{'hostgroups'}{$_} } @_; +} + +sub hostgroups { + my $self = shift; + return keys %{$self->{'hostgroups'}}; +} + +sub inc_jobs_completed { + my $self = shift; + $self->{'jobs_completed'}++; + $Global::total_completed++; +} + +sub set_max_jobs_running { + my $self = shift; + if(defined $self->{'max_jobs_running'}) { + $Global::max_jobs_running -= $self->{'max_jobs_running'}; + } + $self->{'max_jobs_running'} = shift; + if(defined $self->{'max_jobs_running'}) { + # max_jobs_running could be resat if -j is a changed file + $Global::max_jobs_running += $self->{'max_jobs_running'}; + } + # Initialize orig to the first non-zero value that comes around + $self->{'orig_max_jobs_running'} ||= $self->{'max_jobs_running'}; +} + +sub memfree { + # Returns: + # $memfree in bytes + my $self = shift; + $self->memfree_recompute(); + return (not defined $self->{'memfree'} or $self->{'memfree'}) +} + +sub memfree_recompute { + my $self = shift; + my $script = memfreescript(); + + # TODO add sshlogin and backgrounding + # Run the script twice if it gives 0 (typically intermittent error) + $self->{'memfree'} = ::qqx($script) || ::qqx($script); + if(not $self->{'memfree'}) { + ::die_bug("Less than 1 byte free"); + } + #::debug("mem","New free:",$self->{'memfree'}," "); +} + +{ + my $script; + + sub memfreescript { + # Returns: + # shellscript for giving available memory in bytes + if(not $script) { + my %script_of = ( + # /proc/meminfo + # MemFree: 7012 kB + # Buffers: 19876 kB + # Cached: 431192 kB + # SwapCached: 0 kB + "linux" => + q[ print 1024 * qx{ ]. + q[ awk '/^((Swap)?Cached|MemFree|Buffers):/ ]. + q[ { sum += \$2} END { print sum }' ]. + q[ /proc/meminfo } ], + # $ vmstat 1 1 + # procs memory page faults cpu + # r b w avm free re at pi po fr de sr in sy cs us sy id + # 1 0 0 242793 389737 5 1 0 0 0 0 0 107 978 60 1 1 99 + "hpux" => + q[ print (((reverse `vmstat 1 1`)[0] ]. + q[ =~ /(?:\d+\D+){4}(\d+)/)[0]*1024) ], + # $ vmstat 1 2 + # kthr memory page disk faults cpu + # r b w swap free re mf pi po fr de sr s3 s4 -- -- in sy cs us sy id + # 0 0 0 6496720 5170320 68 260 8 2 1 0 0 -0 3 0 0 309 1371 255 1 2 97 + # 0 0 0 6434088 5072656 7 15 8 0 0 0 0 0 261 0 0 1889 1899 3222 0 8 92 + # + # The second free value is correct + "solaris" => + q[ print (((reverse `vmstat 1 2`)[0] ]. + q[ =~ /(?:\d+\D+){4}(\d+)/)[0]*1024) ], + "freebsd" => q{ + for(qx{/sbin/sysctl -a}) { + if (/^([^:]+):\s+(.+)\s*$/s) { + $sysctl->{$1} = $2; + } + } + print $sysctl->{"hw.pagesize"} * + ($sysctl->{"vm.stats.vm.v_cache_count"} + + $sysctl->{"vm.stats.vm.v_inactive_count"} + + $sysctl->{"vm.stats.vm.v_free_count"}); + }, + # Mach Virtual Memory Statistics: (page size of 4096 bytes) + # Pages free: 198061. + # Pages active: 159701. + # Pages inactive: 47378. + # Pages speculative: 29707. + # Pages wired down: 89231. + # "Translation faults": 928901425. + # Pages copy-on-write: 156988239. + # Pages zero filled: 271267894. + # Pages reactivated: 48895. + # Pageins: 1798068. + # Pageouts: 257. + # Object cache: 6603 hits of 1713223 lookups (0% hit rate) + 'darwin' => + q[ $vm = `vm_stat`; + print (($vm =~ /page size of (\d+)/)[0] * + (($vm =~ /Pages free:\s+(\d+)/)[0] + + ($vm =~ /Pages inactive:\s+(\d+)/)[0])); + ], + ); + my $perlscript = ""; + # Make a perl script that detects the OS ($^O) and runs + # the appropriate command + for my $os (keys %script_of) { + $perlscript .= 'if($^O eq "'.$os.'") { '.$script_of{$os}.'}'; + } + $perlscript =~ s/[\t\n ]+/ /g; + $script = "perl -e " . ::shell_quote_scalar($perlscript); + } + return $script; + } +} + +sub limit { + # Returns: + # 0 = Below limit. Start another job. + # 1 = Over limit. Start no jobs. + # 2 = Kill youngest job + my $self = shift; + + if(not defined $self->{'limitscript'}) { + my %limitscripts = + ("io" => q! + io() { + limit=$1; + io_file=$2; + # Do the measurement in the background + (tmp=$(tempfile); + LANG=C iostat -x 1 2 > $tmp; + mv $tmp $io_file) & + perl -e '-e $ARGV[0] or exit(1); + for(reverse <>) { + /Device:/ and last; + /(\S+)$/ and $max = $max > $1 ? $max : $1; } + exit ($max < '$limit')' $io_file; + }; + export -f io; + io %s %s + !, + "mem" => q! + mem() { + limit=$1; + awk '/^((Swap)?Cached|MemFree|Buffers):/{ sum += $2} + END { + if (sum*1024 < '$limit'/2) { exit 2; } + else { exit (sum*1024 < '$limit') } + }' /proc/meminfo; + }; + export -f mem; + mem %s; + !, + "load" => q! + load() { + limit=$1; + ps ax -o state,command | + grep -E '^[DOR].[^[]' | + wc -l | + perl -ne 'exit ('$limit' < $_)'; + }; + export -f load; + load %s; + !, + ); + my ($cmd,@args) = split /\s+/,$opt::limit; + if($limitscripts{$cmd}) { + my $tmpfile = ::tmpname("parlmt"); + ++$Global::unlink{$tmpfile}; + $self->{'limitscript'} = + ::spacefree(1, sprintf($limitscripts{$cmd}, + ::multiply_binary_prefix(@args),$tmpfile)); + } else { + $self->{'limitscript'} = $opt::limit; + } + } + + my %env = %ENV; + local %ENV = %env; + $ENV{'SSHLOGIN'} = $self->string(); + system($Global::shell,"-c",$self->{'limitscript'}); + ::debug("limit","limit `".$self->{'limitscript'}."` result ".($?>>8)."\n"); + return $?>>8; +} + + +sub swapping { + my $self = shift; + my $swapping = $self->swap_activity(); + return (not defined $swapping or $swapping) +} + +sub swap_activity { + # If the currently known swap activity is too old: + # Recompute a new one in the background + # Returns: + # last swap activity computed + my $self = shift; + # Should we update the swap_activity file? + my $update_swap_activity_file = 0; + if(-r $self->{'swap_activity_file'}) { + open(my $swap_fh, "<", $self->{'swap_activity_file'}) || ::die_bug("swap_activity_file-r"); + my $swap_out = <$swap_fh>; + close $swap_fh; + if($swap_out =~ /^(\d+)$/) { + $self->{'swap_activity'} = $1; + ::debug("swap", "New swap_activity: ", $self->{'swap_activity'}); + } + ::debug("swap", "Last update: ", $self->{'last_swap_activity_update'}); + if(time - $self->{'last_swap_activity_update'} > 10) { + # last swap activity update was started 10 seconds ago + ::debug("swap", "Older than 10 sec: ", $self->{'swap_activity_file'}); + $update_swap_activity_file = 1; + } + } else { + ::debug("swap", "No swap_activity file: ", $self->{'swap_activity_file'}); + $self->{'swap_activity'} = undef; + $update_swap_activity_file = 1; + } + if($update_swap_activity_file) { + ::debug("swap", "Updating swap_activity file ", $self->{'swap_activity_file'}); + $self->{'last_swap_activity_update'} = time; + my $dir = ::dirname($self->{'swap_activity_file'}); + -d $dir or eval { File::Path::mkpath($dir); }; + my $swap_activity; + $swap_activity = swapactivityscript(); + if($self->{'string'} ne ":") { + $swap_activity = $self->sshcommand() . " " . $self->serverlogin() . " " . + ::shell_quote_scalar($swap_activity); + } + # Run swap_activity measuring. + # As the command can take long to run if run remote + # save it to a tmp file before moving it to the correct file + my $file = $self->{'swap_activity_file'}; + my ($dummy_fh, $tmpfile) = ::tmpfile(SUFFIX => ".swp"); + ::debug("swap", "\n", $swap_activity, "\n"); + ::qqx("($swap_activity > $tmpfile && mv $tmpfile $file || rm $tmpfile &)"); + } + return $self->{'swap_activity'}; +} + +{ + my $script; + + sub swapactivityscript { + # Returns: + # shellscript for detecting swap activity + # + # arguments for vmstat are OS dependant + # swap_in and swap_out are in different columns depending on OS + # + if(not $script) { + my %vmstat = ( + # linux: $7*$8 + # $ vmstat 1 2 + # procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu---- + # r b swpd free buff cache si so bi bo in cs us sy id wa + # 5 0 51208 1701096 198012 18857888 0 0 37 153 28 19 56 11 33 1 + # 3 0 51208 1701288 198012 18857972 0 0 0 0 3638 10412 15 3 82 0 + 'linux' => ['vmstat 1 2 | tail -n1', '$7*$8'], + + # solaris: $6*$7 + # $ vmstat -S 1 2 + # kthr memory page disk faults cpu + # r b w swap free si so pi po fr de sr s3 s4 -- -- in sy cs us sy id + # 0 0 0 4628952 3208408 0 0 3 1 1 0 0 -0 2 0 0 263 613 246 1 2 97 + # 0 0 0 4552504 3166360 0 0 0 0 0 0 0 0 0 0 0 246 213 240 1 1 98 + 'solaris' => ['vmstat -S 1 2 | tail -1', '$6*$7'], + + # darwin (macosx): $21*$22 + # $ vm_stat -c 2 1 + # Mach Virtual Memory Statistics: (page size of 4096 bytes) + # free active specul inactive throttle wired prgable faults copy 0fill reactive purged file-backed anonymous cmprssed cmprssor dcomprs comprs pageins pageout swapins swapouts + # 346306 829050 74871 606027 0 240231 90367 544858K 62343596 270837K 14178 415070 570102 939846 356 370 116 922 4019813 4 0 0 + # 345740 830383 74875 606031 0 239234 90369 2696 359 553 0 0 570110 941179 356 370 0 0 0 0 0 0 + 'darwin' => ['vm_stat -c 2 1 | tail -n1', '$21*$22'], + + # ultrix: $12*$13 + # $ vmstat -S 1 2 + # procs faults cpu memory page disk + # r b w in sy cs us sy id avm fre si so pi po fr de sr s0 + # 1 0 0 4 23 2 3 0 97 7743 217k 0 0 0 0 0 0 0 0 + # 1 0 0 6 40 8 0 1 99 7743 217k 0 0 3 0 0 0 0 0 + 'ultrix' => ['vmstat -S 1 2 | tail -1', '$12*$13'], + + # aix: $6*$7 + # $ vmstat 1 2 + # System configuration: lcpu=1 mem=2048MB + # + # kthr memory page faults cpu + # ----- ----------- ------------------------ ------------ ----------- + # r b avm fre re pi po fr sr cy in sy cs us sy id wa + # 0 0 333933 241803 0 0 0 0 0 0 10 143 90 0 0 99 0 + # 0 0 334125 241569 0 0 0 0 0 0 37 5368 184 0 9 86 5 + 'aix' => ['vmstat 1 2 | tail -n1', '$6*$7'], + + # freebsd: $8*$9 + # $ vmstat -H 1 2 + # procs memory page disks faults cpu + # r b w avm fre flt re pi po fr sr ad0 ad1 in sy cs us sy id + # 1 0 0 596716 19560 32 0 0 0 33 8 0 0 11 220 277 0 0 99 + # 0 0 0 596716 19560 2 0 0 0 0 0 0 0 11 144 263 0 1 99 + 'freebsd' => ['vmstat -H 1 2 | tail -n1', '$8*$9'], + + # mirbsd: $8*$9 + # $ vmstat 1 2 + # procs memory page disks traps cpu + # r b w avm fre flt re pi po fr sr wd0 cd0 int sys cs us sy id + # 0 0 0 25776 164968 34 0 0 0 0 0 0 0 230 259 38 4 0 96 + # 0 0 0 25776 164968 24 0 0 0 0 0 0 0 237 275 37 0 0 100 + 'mirbsd' => ['vmstat 1 2 | tail -n1', '$8*$9'], + + # netbsd: $7*$8 + # $ vmstat 1 2 + # procs memory page disks faults cpu + # r b avm fre flt re pi po fr sr w0 w1 in sy cs us sy id + # 0 0 138452 6012 54 0 0 0 1 2 3 0 4 100 23 0 0 100 + # 0 0 138456 6008 1 0 0 0 0 0 0 0 7 26 19 0 0 100 + 'netbsd' => ['vmstat 1 2 | tail -n1', '$7*$8'], + + # openbsd: $8*$9 + # $ vmstat 1 2 + # procs memory page disks traps cpu + # r b w avm fre flt re pi po fr sr wd0 wd1 int sys cs us sy id + # 0 0 0 76596 109944 73 0 0 0 0 0 0 1 5 259 22 0 1 99 + # 0 0 0 76604 109936 24 0 0 0 0 0 0 0 7 114 20 0 1 99 + 'openbsd' => ['vmstat 1 2 | tail -n1', '$8*$9'], + + # hpux: $8*$9 + # $ vmstat 1 2 + # procs memory page faults cpu + # r b w avm free re at pi po fr de sr in sy cs us sy id + # 1 0 0 247211 216476 4 1 0 0 0 0 0 102 73005 54 6 11 83 + # 1 0 0 247211 216421 43 9 0 0 0 0 0 144 1675 96 25269512791222387000 25269512791222387000 105 + 'hpux' => ['vmstat 1 2 | tail -n1', '$8*$9'], + + # dec_osf (tru64): $11*$12 + # $ vmstat 1 2 + # Virtual Memory Statistics: (pagesize = 8192) + # procs memory pages intr cpu + # r w u act free wire fault cow zero react pin pout in sy cs us sy id + # 3 181 36 51K 1895 8696 348M 59M 122M 259 79M 0 5 218 302 4 1 94 + # 3 181 36 51K 1893 8696 3 15 21 0 28 0 4 81 321 1 1 98 + 'dec_osf' => ['vmstat 1 2 | tail -n1', '$11*$12'], + + # gnu (hurd): $7*$8 + # $ vmstat -k 1 2 + # (pagesize: 4, size: 512288, swap size: 894972) + # free actv inact wired zeroed react pgins pgouts pfaults cowpfs hrat caobj cache swfree + # 371940 30844 89228 20276 298348 0 48192 19016 756105 99808 98% 876 20628 894972 + # 371940 30844 89228 20276 +0 +0 +0 +0 +42 +2 98% 876 20628 894972 + 'gnu' => ['vmstat -k 1 2 | tail -n1', '$7*$8'], + + # -nto (qnx has no swap) + #-irix + #-svr5 (scosysv) + ); + my $perlscript = ""; + # Make a perl script that detects the OS ($^O) and runs + # the appropriate vmstat command + for my $os (keys %vmstat) { + $vmstat{$os}[1] =~ s/\$/\\\\\\\$/g; # $ => \\\$ + $perlscript .= 'if($^O eq "'.$os.'") { print `'.$vmstat{$os}[0].' | awk "{print ' . + $vmstat{$os}[1] . '}"` }'; + } + $script = "perl -e " . ::shell_quote_scalar($perlscript); + } + return $script; + } +} + +sub too_fast_remote_login { + my $self = shift; + if($self->{'last_login_at'} and $self->{'time_to_login'}) { + # sshd normally allows 10 simultaneous logins + # A login takes time_to_login + # So time_to_login/5 should be safe + # If now <= last_login + time_to_login/5: Then it is too soon. + my $too_fast = (::now() <= $self->{'last_login_at'} + + $self->{'time_to_login'}/5); + ::debug("run", "Too fast? $too_fast "); + return $too_fast; + } else { + # No logins so far (or time_to_login not computed): it is not too fast + return 0; + } +} + +sub last_login_at { + my $self = shift; + return $self->{'last_login_at'}; +} + +sub set_last_login_at { + my $self = shift; + $self->{'last_login_at'} = shift; +} + +sub loadavg_too_high { + my $self = shift; + my $loadavg = $self->loadavg(); + return (not defined $loadavg or + $loadavg > $self->max_loadavg()); +} + +{ + my $cmd; + sub loadavg_cmd { + if(not $cmd) { + # aix => "ps -ae -o state,command" # state wrong + # bsd => "ps ax -o state,command" + # sysv => "ps -ef -o s -o comm" + # cygwin => perl -ne 'close STDERR; /Name/ and print"\n"; \ + # /(Name|Pid|Ppid|State):\s+(\S+)/ and print "$2\t";' /proc/*/status | + # awk '{print $2,$1}' + # dec_osf => bsd + # dragonfly => bsd + # freebsd => bsd + # gnu => bsd + # hpux => ps -el|awk '{print $2,$14,$15}' + # irix => ps -ef -o state -o comm + # linux => bsd + # minix => ps el|awk '{print \$1,\$11}' + # mirbsd => bsd + # netbsd => bsd + # openbsd => bsd + # solaris => sysv + # svr5 => sysv + # ultrix => ps -ax | awk '{print $3,$5}' + # unixware => ps -el|awk '{print $2,$14,$15}' + my $ps = ::spacefree(1,q{ + $sysv="ps -ef -o s -o comm"; + $sysv2="ps -ef -o state -o comm"; + $bsd="ps ax -o state,command"; + # Treat threads as processes + $bsd2="ps axH -o state,command"; + $psel="ps -el|awk '{ print \$2,\$14,\$15 }'"; + $cygwin=q{ perl -ne 'close STDERR; /Name/ and print"\n"; + /(Name|Pid|Ppid|State):\s+(\S+)/ and print "$2\t";' /proc/*/status | + awk '{print $2,$1}' }; + $dummy="echo S COMMAND;echo R dummy"; + %ps=( + # TODO Find better code for AIX + 'aix' => "uptime", + 'cygwin' => $cygwin, + 'darwin' => $bsd, + 'dec_osf' => $sysv2, + 'dragonfly' => $bsd, + 'freebsd' => $bsd2, + 'gnu' => $bsd, + 'hpux' => $psel, + 'irix' => $sysv2, + 'linux' => $bsd2, + 'minix' => "ps el|awk '{print \$1,\$11}'", + 'mirbsd' => $bsd, + 'msys' => $cygwin, + 'MSWin32' => $sysv, + 'netbsd' => $bsd, + 'nto' => $dummy, + 'openbsd' => $bsd, + 'solaris' => $sysv, + 'svr5' => $psel, + 'ultrix' => "ps -ax | awk '{print \$3,\$5}'", + ); + print `$ps{$^O}`; + }); + # The command is too long for csh, so base64_wrap the command + $cmd = Job::base64_wrap($ps); + } + return $cmd; + } +} + + +sub loadavg { + # If the currently know loadavg is too old: + # Recompute a new one in the background + # The load average is computed as the number of processes waiting for disk + # or CPU right now. So it is the server load this instant and not averaged over + # several minutes. This is needed so GNU Parallel will at most start one job + # that will push the load over the limit. + # + # Returns: + # $last_loadavg = last load average computed (undef if none) + my $self = shift; + # Should we update the loadavg file? + my $update_loadavg_file = 0; + if(open(my $load_fh, "<", $self->{'loadavg_file'})) { + local $/; # $/ = undef => slurp whole file + my $load_out = <$load_fh>; + close $load_fh; + if($load_out =~ /\S/) { + # Content can be empty if ~/ is on NFS + # due to reading being non-atomic. + # + # Count lines starting with D,O,R but command does not start with [ + my $load =()= ($load_out=~/(^\s?[DOR]\S* +(?=[^\[])\S)/gm); + if($load > 0) { + # load is overestimated by 1 + $self->{'loadavg'} = $load - 1; + ::debug("load", "New loadavg: ", $self->{'loadavg'},"\n"); + } elsif ($load_out=~/average: (\d+.\d+)/) { + # AIX does not support instant load average + # 04:11AM up 21 days, 12:55, 1 user, load average: 1.85, 1.57, 1.55 + $self->{'loadavg'} = $1; + } else { + ::die_bug("loadavg_invalid_content: " . + $self->{'loadavg_file'} . "\n$load_out"); + } + } + $update_loadavg_file = 1; + } else { + ::debug("load", "No loadavg file: ", $self->{'loadavg_file'}); + $self->{'loadavg'} = undef; + $update_loadavg_file = 1; + } + if($update_loadavg_file) { + ::debug("load", "Updating loadavg file", $self->{'loadavg_file'}, "\n"); + $self->{'last_loadavg_update'} = time; + my $dir = ::dirname($self->{'swap_activity_file'}); + -d $dir or eval { File::Path::mkpath($dir); }; + -w $dir or ::die_bug("Cannot write to $dir"); + my $cmd = ""; + if($self->{'string'} ne ":") { + $cmd = $self->sshcommand() . " " . $self->serverlogin() . " " . + ::shell_quote_scalar(loadavg_cmd()); + } else { + $cmd .= loadavg_cmd(); + } + # As the command can take long to run if run remote + # save it to a tmp file before moving it to the correct file + ::debug("load", "Cmd: ", $cmd,"\n"); + my $file = $self->{'loadavg_file'}; + # tmpfile on same filesystem as $file + my $tmpfile = $file.$$; + ::qqx("($cmd > $tmpfile && mv $tmpfile $file || rm $tmpfile & )"); + } + return $self->{'loadavg'}; +} + +sub max_loadavg { + my $self = shift; + # If --load is a file it might be changed + if($Global::max_load_file) { + my $mtime = (stat($Global::max_load_file))[9]; + if($mtime > $Global::max_load_file_last_mod) { + $Global::max_load_file_last_mod = $mtime; + for my $sshlogin (values %Global::host) { + $sshlogin->set_max_loadavg(undef); + } + } + } + if(not defined $self->{'max_loadavg'}) { + $self->{'max_loadavg'} = + $self->compute_max_loadavg($opt::load); + } + ::debug("load", "max_loadavg: ", $self->string(), " ", $self->{'max_loadavg'}); + return $self->{'max_loadavg'}; +} + +sub set_max_loadavg { + my $self = shift; + $self->{'max_loadavg'} = shift; +} + +sub compute_max_loadavg { + # Parse the max loadaverage that the user asked for using --load + # Returns: + # max loadaverage + my $self = shift; + my $loadspec = shift; + my $load; + if(defined $loadspec) { + if($loadspec =~ /^\+(\d+)$/) { + # E.g. --load +2 + my $j = $1; + $load = + $self->ncpus() + $j; + } elsif ($loadspec =~ /^-(\d+)$/) { + # E.g. --load -2 + my $j = $1; + $load = + $self->ncpus() - $j; + } elsif ($loadspec =~ /^(\d+)\%$/) { + my $j = $1; + $load = + $self->ncpus() * $j / 100; + } elsif ($loadspec =~ /^(\d+(\.\d+)?)$/) { + $load = $1; + } elsif (-f $loadspec) { + $Global::max_load_file = $loadspec; + $Global::max_load_file_last_mod = (stat($Global::max_load_file))[9]; + if(open(my $in_fh, "<", $Global::max_load_file)) { + my $opt_load_file = join("",<$in_fh>); + close $in_fh; + $load = $self->compute_max_loadavg($opt_load_file); + } else { + ::error("Cannot open $loadspec."); + ::wait_and_exit(255); + } + } else { + ::error("Parsing of --load failed."); + ::die_usage(); + } + if($load < 0.01) { + $load = 0.01; + } + } + return $load; +} + +sub time_to_login { + my $self = shift; + return $self->{'time_to_login'}; +} + +sub set_time_to_login { + my $self = shift; + $self->{'time_to_login'} = shift; +} + +sub max_jobs_running { + my $self = shift; + if(not defined $self->{'max_jobs_running'}) { + my $nproc = $self->compute_number_of_processes($opt::jobs); + $self->set_max_jobs_running($nproc); + } + return $self->{'max_jobs_running'}; +} + +sub orig_max_jobs_running { + my $self = shift; + return $self->{'orig_max_jobs_running'}; +} + +sub compute_number_of_processes { + # Number of processes wanted and limited by system resources + # Returns: + # Number of processes + my $self = shift; + my $opt_P = shift; + my $wanted_processes = $self->user_requested_processes($opt_P); + if(not defined $wanted_processes) { + $wanted_processes = $Global::default_simultaneous_sshlogins; + } + ::debug("load", "Wanted procs: $wanted_processes\n"); + my $system_limit = + $self->processes_available_by_system_limit($wanted_processes); + ::debug("load", "Limited to procs: $system_limit\n"); + return $system_limit; +} + +{ + my @children; + my $max_system_proc_reached; + my $more_filehandles; + my %fh; + my $tmpfhname; + my $count_jobs_already_read; + my @jobs; + my $job; + my @args; + my $arg; + + sub reserve_filehandles { + # Reserves filehandle + my $n = shift; + for (1..$n) { + $more_filehandles &&= open($fh{$tmpfhname++}, "<", "/dev/null"); + } + } + + sub reserve_process { + # Spawn a dummy process + my $child; + if($child = fork()) { + push @children, $child; + $Global::unkilled_children{$child} = 1; + } elsif(defined $child) { + # This is the child + # The child takes one process slot + # It will be killed later + $SIG{'TERM'} = $Global::original_sig{'TERM'}; + if($^O eq "cygwin" or $^O eq "msys") { + # The exec does not work on Cygwin + sleep 10101010; + } else { + # 'exec sleep' takes less RAM than sleeping in perl + exec 'sleep', 10101; + } + exit(0); + } else { + # Failed to spawn + $max_system_proc_reached = 1; + } + } + + sub get_args_or_jobs { + # Get an arg or a job (depending on mode) + if($Global::semaphore or ($opt::pipe and not $opt::tee)) { + # Skip: No need to get args + return 1; + } elsif(defined $opt::retries and $count_jobs_already_read) { + # For retries we may need to run all jobs on this sshlogin + # so include the already read jobs for this sshlogin + $count_jobs_already_read--; + return 1; + } else { + if($opt::X or $opt::m) { + # The arguments may have to be re-spread over several jobslots + # So pessimistically only read one arg per jobslot + # instead of a full commandline + if($Global::JobQueue->{'commandlinequeue'}->{'arg_queue'}->empty()) { + if($Global::JobQueue->empty()) { + return 0; + } else { + $job = $Global::JobQueue->get(); + push(@jobs, $job); + return 1; + } + } else { + $arg = $Global::JobQueue->{'commandlinequeue'}->{'arg_queue'}->get(); + push(@args, $arg); + return 1; + } + } else { + # If there are no more command lines, then we have a process + # per command line, so no need to go further + if($Global::JobQueue->empty()) { + return 0; + } else { + $job = $Global::JobQueue->get(); + push(@jobs, $job); + return 1; + } + } + } + } + + sub cleanup { + # Cleanup: Close the files + for (values %fh) { close $_ } + # Cleanup: Kill the children + for my $pid (@children) { + kill 9, $pid; + waitpid($pid,0); + delete $Global::unkilled_children{$pid}; + } + # Cleanup: Unget the command_lines or the @args + $Global::JobQueue->{'commandlinequeue'}->{'arg_queue'}->unget(@args); + @args = (); + $Global::JobQueue->unget(@jobs); + @jobs = (); + } + + sub processes_available_by_system_limit { + # If the wanted number of processes is bigger than the system limits: + # Limit them to the system limits + # Limits are: File handles, number of input lines, processes, + # and taking > 1 second to spawn 10 extra processes + # Returns: + # Number of processes + my $self = shift; + my $wanted_processes = shift; + my $system_limit = 0; + my $slow_spawning_warning_printed = 0; + my $time = time; + $more_filehandles = 1; + $tmpfhname = "TmpFhNamE"; + + # perl uses 7 filehandles for something? + # parallel uses 1 for memory_usage + # parallel uses 4 for ? + reserve_filehandles(12); + # Two processes for load avg and ? + reserve_process(); + reserve_process(); + + # For --retries count also jobs already run + $count_jobs_already_read = $Global::JobQueue->next_seq(); + my $wait_time_for_getting_args = 0; + my $start_time = time; + while(1) { + $system_limit >= $wanted_processes and last; + not $more_filehandles and last; + $max_system_proc_reached and last; + + my $before_getting_arg = time; + if(!$Global::dummy_jobs) { + get_args_or_jobs() or last; + } + $wait_time_for_getting_args += time - $before_getting_arg; + $system_limit++; + + # Every simultaneous process uses 2 filehandles to write to + # and 2 filehandles to read from + reserve_filehandles(4); + + # System process limit + reserve_process(); + + my $forktime = time - $time - $wait_time_for_getting_args; + ::debug("run", "Time to fork $system_limit procs: $wait_time_for_getting_args ", + $forktime, + " (processes so far: ", $system_limit,")\n"); + if($system_limit > 10 and + $forktime > 1 and + $forktime > $system_limit * 0.01 + and not $slow_spawning_warning_printed) { + # It took more than 0.01 second to fork a processes on avg. + # Give the user a warning. He can press Ctrl-C if this + # sucks. + ::warning("Starting $system_limit processes took > $forktime sec.", + "Consider adjusting -j. Press CTRL-C to stop."); + $slow_spawning_warning_printed = 1; + } + } + cleanup(); + + if($system_limit < $wanted_processes) { + # The system_limit is less than the wanted_processes + if($system_limit < 1 and not $Global::JobQueue->empty()) { + ::warning("Cannot spawn any jobs. ". + "Raising ulimit -u or 'nproc' in /etc/security/limits.conf", + "or /proc/sys/kernel/pid_max may help."); + ::wait_and_exit(255); + } + if(not $more_filehandles) { + ::warning("Only enough file handles to run ". + $system_limit. " jobs in parallel.", + "Running 'parallel -j0 -N $system_limit --pipe parallel -j0' or", + "raising 'ulimit -n' or 'nofile' in /etc/security/limits.conf", + "or /proc/sys/fs/file-max may help."); + } + if($max_system_proc_reached) { + ::warning("Only enough available processes to run ". + $system_limit. " jobs in parallel.", + "Raising ulimit -u or /etc/security/limits.conf ", + "or /proc/sys/kernel/pid_max may help."); + } + } + if($] == 5.008008 and $system_limit > 1000) { + # https://savannah.gnu.org/bugs/?36942 + $system_limit = 1000; + } + if($Global::JobQueue->empty()) { + $system_limit ||= 1; + } + if($self->string() ne ":" and + $system_limit > $Global::default_simultaneous_sshlogins) { + $system_limit = + $self->simultaneous_sshlogin_limit($system_limit); + } + return $system_limit; + } +} + +sub simultaneous_sshlogin_limit { + # Test by logging in wanted number of times simultaneously + # Returns: + # min($wanted_processes,$working_simultaneous_ssh_logins-1) + my $self = shift; + my $wanted_processes = shift; + if($self->{'time_to_login'}) { + return $wanted_processes; + } + + # Try twice because it guesses wrong sometimes + # Choose the minimal + my $ssh_limit = + ::min($self->simultaneous_sshlogin($wanted_processes), + $self->simultaneous_sshlogin($wanted_processes)); + if($ssh_limit < $wanted_processes) { + my $serverlogin = $self->serverlogin(); + ::warning("ssh to $serverlogin only allows ". + "for $ssh_limit simultaneous logins.", + "You may raise this by changing ". + "/etc/ssh/sshd_config:MaxStartups and MaxSessions on $serverlogin.", + "You can also try --sshdelay 0.1", + "Using only ".($ssh_limit-1)." connections ". + "to avoid race conditions."); + # Race condition can cause problem if using all sshs. + if($ssh_limit > 1) { $ssh_limit -= 1; } + } + return $ssh_limit; +} + +sub simultaneous_sshlogin { + # Using $sshlogin try to see if we can do $wanted_processes + # simultaneous logins + # (ssh host echo simultaneouslogin & ssh host echo simultaneouslogin & ...)|grep simul|wc -l + # Returns: + # Number of succesful logins + local $/ = "\n"; + my $self = shift; + my $wanted_processes = shift; + my $sshcmd = $self->sshcommand(); + my $serverlogin = $self->serverlogin(); + my $sshdelay = $opt::sshdelay ? "sleep $opt::sshdelay;" : ""; + # TODO sh -c wrapper to work for csh + my $cmd = "$sshdelay$sshcmd $serverlogin -- echo simultaneouslogin &1 &"x$wanted_processes; + ::debug("init", "Trying $wanted_processes logins at $serverlogin\n"); + open (my $simul_fh, "-|", "($cmd)|grep simultaneouslogin | wc -l") or + ::die_bug("simultaneouslogin"); + my $ssh_limit = <$simul_fh>; + close $simul_fh; + chomp $ssh_limit; + return $ssh_limit; +} + +sub set_ncpus { + my $self = shift; + $self->{'ncpus'} = shift; +} + +sub user_requested_processes { + # Parse the number of processes that the user asked for using -j + # Returns: + # the number of processes to run on this sshlogin + my $self = shift; + my $opt_P = shift; + my $processes; + if(defined $opt_P) { + if($opt_P =~ /^\+(\d+)$/) { + # E.g. -P +2 + my $j = $1; + $processes = + $self->ncpus() + $j; + } elsif ($opt_P =~ /^-(\d+)$/) { + # E.g. -P -2 + my $j = $1; + $processes = + $self->ncpus() - $j; + } elsif ($opt_P =~ /^(\d+(\.\d+)?)\%$/) { + # E.g. -P 10.5% + my $j = $1; + $processes = + $self->ncpus() * $j / 100; + } elsif ($opt_P =~ /^(\d+)$/) { + $processes = $1; + if($processes == 0) { + # -P 0 = infinity (or at least close) + $processes = $Global::infinity; + } + } elsif (-f $opt_P) { + $Global::max_procs_file = $opt_P; + if(open(my $in_fh, "<", $Global::max_procs_file)) { + my $opt_P_file = join("",<$in_fh>); + close $in_fh; + $processes = $self->user_requested_processes($opt_P_file); + } else { + ::error("Cannot open $opt_P."); + ::wait_and_exit(255); + } + } else { + ::error("Parsing of --jobs/-j/--max-procs/-P failed."); + ::die_usage(); + } + $processes = ::ceil($processes); + } + return $processes; +} + +sub ncpus { + local $/ = "\n"; + my $self = shift; + if(not defined $self->{'ncpus'}) { + my $sshcmd = $self->sshcommand(); + my $serverlogin = $self->serverlogin(); + if($serverlogin eq ":") { + if($opt::use_cpus_instead_of_cores) { + $self->{'ncpus'} = no_of_cpus(); + } else { + $self->{'ncpus'} = no_of_cores(); + } + } else { + my $ncpu; + if($opt::use_cpus_instead_of_cores) { + $ncpu = ::qqx("echo|$sshcmd $serverlogin -- parallel --number-of-cpus"); + } else { + ::debug("init",qq(echo|$sshcmd $serverlogin -- parallel --number-of-cores\n)); + $ncpu = ::qqx("echo|$sshcmd $serverlogin -- parallel --number-of-cores"); + } + chomp $ncpu; + if($ncpu =~ /^\s*[0-9]+\s*$/s) { + $self->{'ncpus'} = $ncpu; + } else { + ::warning("Could not figure out ". + "number of cpus on $serverlogin ($ncpu). Using 1."); + $self->{'ncpus'} = 1; + } + } + } + return $self->{'ncpus'}; +} + +sub no_of_cpus { + # Returns: + # Number of physical CPUs + local $/ = "\n"; # If delimiter is set, then $/ will be wrong + my $no_of_cpus; + if ($^O eq 'linux') { + $no_of_cpus = no_of_cpus_gnu_linux() || no_of_cores_gnu_linux(); + } elsif ($^O eq 'freebsd') { + $no_of_cpus = no_of_cpus_freebsd(); + } elsif ($^O eq 'netbsd') { + $no_of_cpus = no_of_cpus_netbsd(); + } elsif ($^O eq 'openbsd') { + $no_of_cpus = no_of_cpus_openbsd(); + } elsif ($^O eq 'gnu') { + $no_of_cpus = no_of_cpus_hurd(); + } elsif ($^O eq 'darwin') { + $no_of_cpus = no_of_cpus_darwin(); + } elsif ($^O eq 'solaris') { + $no_of_cpus = no_of_cpus_solaris() || nproc(); + } elsif ($^O eq 'aix') { + $no_of_cpus = no_of_cpus_aix(); + } elsif ($^O eq 'hpux') { + $no_of_cpus = no_of_cpus_hpux(); + } elsif ($^O eq 'nto') { + $no_of_cpus = no_of_cpus_qnx(); + } elsif ($^O eq 'svr5') { + $no_of_cpus = no_of_cpus_openserver(); + } elsif ($^O eq 'irix') { + $no_of_cpus = no_of_cpus_irix(); + } elsif ($^O eq 'dec_osf') { + $no_of_cpus = no_of_cpus_tru64(); + } else { + $no_of_cpus = (no_of_cpus_gnu_linux() + || no_of_cpus_freebsd() + || no_of_cpus_netbsd() + || no_of_cpus_openbsd() + || no_of_cpus_hurd() + || no_of_cpus_darwin() + || no_of_cpus_solaris() + || no_of_cpus_aix() + || no_of_cpus_hpux() + || no_of_cpus_qnx() + || no_of_cpus_openserver() + || no_of_cpus_irix() + || no_of_cpus_tru64() + # Number of cores is better than no guess for #CPUs + || nproc() + ); + } + if($no_of_cpus) { + chomp $no_of_cpus; + return $no_of_cpus; + } else { + ::warning("Cannot figure out number of cpus. Using 1."); + return 1; + } +} + +sub no_of_cores { + # Returns: + # Number of CPU cores + local $/ = "\n"; # If delimiter is set, then $/ will be wrong + my $no_of_cores; + if ($^O eq 'linux') { + $no_of_cores = no_of_cores_gnu_linux(); + } elsif ($^O eq 'freebsd') { + $no_of_cores = no_of_cores_freebsd(); + } elsif ($^O eq 'netbsd') { + $no_of_cores = no_of_cores_netbsd(); + } elsif ($^O eq 'openbsd') { + $no_of_cores = no_of_cores_openbsd(); + } elsif ($^O eq 'gnu') { + $no_of_cores = no_of_cores_hurd(); + } elsif ($^O eq 'darwin') { + $no_of_cores = no_of_cores_darwin(); + } elsif ($^O eq 'solaris') { + $no_of_cores = no_of_cores_solaris() || nproc(); + } elsif ($^O eq 'aix') { + $no_of_cores = no_of_cores_aix(); + } elsif ($^O eq 'hpux') { + $no_of_cores = no_of_cores_hpux(); + } elsif ($^O eq 'nto') { + $no_of_cores = no_of_cores_qnx(); + } elsif ($^O eq 'svr5') { + $no_of_cores = no_of_cores_openserver(); + } elsif ($^O eq 'irix') { + $no_of_cores = no_of_cores_irix(); + } elsif ($^O eq 'dec_osf') { + $no_of_cores = no_of_cores_tru64(); + } else { + $no_of_cores = (no_of_cores_gnu_linux() + || no_of_cores_freebsd() + || no_of_cores_netbsd() + || no_of_cores_openbsd() + || no_of_cores_hurd() + || no_of_cores_darwin() + || no_of_cores_solaris() + || no_of_cores_aix() + || no_of_cores_hpux() + || no_of_cores_qnx() + || no_of_cores_openserver() + || no_of_cores_irix() + || no_of_cores_tru64() + || nproc() + ); + } + if($no_of_cores) { + chomp $no_of_cores; + return $no_of_cores; + } else { + ::warning("Cannot figure out number of CPU cores. Using 1."); + return 1; + } +} + +sub nproc { + # Returns: + # Number of cores using `nproc` + my $no_of_cores = ::qqx("nproc"); + return $no_of_cores; +} + +sub no_of_cpus_gnu_linux { + # Returns: + # Number of physical CPUs on GNU/Linux + # undef if not GNU/Linux + my $no_of_cpus; + my $no_of_cores; + my $no_of_active_cores; + if(-e "/proc/cpuinfo") { + $no_of_cpus = 0; + $no_of_cores = 0; + my %seen; + if(open(my $in_fh, "<", "/proc/cpuinfo")) { + while(<$in_fh>) { + if(/^physical id.*[:](.*)/ and not $seen{$1}++) { + $no_of_cpus++; + } + /^processor.*[:]/i and $no_of_cores++; + } + close $in_fh; + } + } + if(-e "/proc/self/status") { + # if 'taskset' is used to limit number of cores + if(open(my $in_fh, "<", "/proc/self/status")) { + while(<$in_fh>) { + if(/^Cpus_allowed:\s*(\S+)/) { + my $a = $1; + $a =~ tr/,//d; + $no_of_active_cores = unpack ("%32b*", pack ("H*",$a)); + } + } + close $in_fh; + } + } + return (::min($no_of_cpus || $no_of_cores,$no_of_active_cores)); +} + +sub no_of_cores_gnu_linux { + # Returns: + # Number of CPU cores on GNU/Linux + # undef if not GNU/Linux + my $no_of_cores; + my $no_of_active_cores; + if(-e "/proc/cpuinfo") { + $no_of_cores = 0; + open(my $in_fh, "<", "/proc/cpuinfo") || return undef; + while(<$in_fh>) { + /^processor.*[:]/i and $no_of_cores++; + } + close $in_fh; + } + if(-e "/proc/self/status") { + # if 'taskset' is used to limit number of cores + if(open(my $in_fh, "<", "/proc/self/status")) { + while(<$in_fh>) { + if(/^Cpus_allowed:\s*(\S+)/) { + my $a = $1; + $a =~ tr/,//d; + $no_of_active_cores = unpack ("%32b*", pack ("H*",$a)); + } + } + close $in_fh; + } + } + return (::min($no_of_cores,$no_of_active_cores)); +} + +sub no_of_cpus_freebsd { + # Returns: + # Number of physical CPUs on FreeBSD + # undef if not FreeBSD + local $/ = "\n"; + my $no_of_cpus = + (::qqx(qq{ sysctl -a dev.cpu | grep \%parent | awk '{ print \$2 }' | uniq | wc -l | awk '{ print \$1 }' }) + or + ::qqx(qq{ sysctl hw.ncpu | awk '{ print \$2 }' })); + chomp $no_of_cpus; + return $no_of_cpus; +} + +sub no_of_cores_freebsd { + # Returns: + # Number of CPU cores on FreeBSD + # undef if not FreeBSD + local $/ = "\n"; + my $no_of_cores = + (::qqx(qq{ sysctl hw.ncpu | awk '{ print \$2 }' }) + or + ::qqx(qq{ sysctl -a dev.cpu | grep \%parent | awk '{ print \$2 }' | uniq | wc -l | awk '{ print \$1 }' })); + chomp $no_of_cores; + return $no_of_cores; +} + +sub no_of_cpus_netbsd { + # Returns: + # Number of physical CPUs on NetBSD + # undef if not NetBSD + local $/ = "\n"; + my $no_of_cpus = ::qqx("sysctl -n hw.ncpu"); + chomp $no_of_cpus; + return $no_of_cpus; +} + +sub no_of_cores_netbsd { + # Returns: + # Number of CPU cores on NetBSD + # undef if not NetBSD + local $/ = "\n"; + my $no_of_cores = ::qqx("sysctl -n hw.ncpu"); + chomp $no_of_cores; + return $no_of_cores; +} + +sub no_of_cpus_openbsd { + # Returns: + # Number of physical CPUs on OpenBSD + # undef if not OpenBSD + local $/ = "\n"; + my $no_of_cpus = ::qqx('sysctl -n hw.ncpu'); + chomp $no_of_cpus; + return $no_of_cpus; +} + +sub no_of_cores_openbsd { + # Returns: + # Number of CPU cores on OpenBSD + # undef if not OpenBSD + local $/ = "\n"; + my $no_of_cores = ::qqx('sysctl -n hw.ncpu'); + chomp $no_of_cores; + return $no_of_cores; +} + +sub no_of_cpus_hurd { + # Returns: + # Number of physical CPUs on HURD + # undef if not HURD + local $/ = "\n"; + my $no_of_cpus = ::qqx("nproc"); + chomp $no_of_cpus; + return $no_of_cpus; +} + +sub no_of_cores_hurd { + # Returns: + # Number of physical CPUs on HURD + # undef if not HURD + local $/ = "\n"; + my $no_of_cores = ::qqx("nproc"); + chomp $no_of_cores; + return $no_of_cores; +} + +sub no_of_cpus_darwin { + # Returns: + # Number of physical CPUs on MacOSX Darwin + # undef if not MacOSX Darwin + my $no_of_cpus = + (::qqx('sysctl -n hw.physicalcpu') + or + ::qqx(qq{ sysctl -a hw | grep [^a-z]physicalcpu[^a-z] | awk '{ print \$2 }' })); + return $no_of_cpus; +} + +sub no_of_cores_darwin { + # Returns: + # Number of CPU cores on Mac Darwin + # undef if not Mac Darwin + my $no_of_cores = + (::qqx('sysctl -n hw.logicalcpu') + or + ::qqx(qq{ sysctl -a hw | grep [^a-z]logicalcpu[^a-z] | awk '{ print \$2 }' })); + return $no_of_cores; +} + +sub no_of_cpus_solaris { + # Returns: + # Number of physical CPUs on Solaris + # undef if not Solaris + if(-x "/usr/sbin/psrinfo") { + my @psrinfo = ::qqx("/usr/sbin/psrinfo"); + if($#psrinfo >= 0) { + return $#psrinfo +1; + } + } + if(-x "/usr/sbin/prtconf") { + my @prtconf = ::qqx("/usr/sbin/prtconf | grep cpu..instance"); + if($#prtconf >= 0) { + return $#prtconf +1; + } + } + if(-x "/usr/sbin/prtconf") { + my @prtconf = ::qqx("/usr/sbin/prtconf | grep cpu..instance"); + if($#prtconf >= 0) { + return $#prtconf +1; + } + } + return undef; +} + +sub no_of_cores_solaris { + # Returns: + # Number of CPU cores on Solaris + # undef if not Solaris + if(-x "/usr/sbin/psrinfo") { + my @psrinfo = ::qqx("/usr/sbin/psrinfo"); + if($#psrinfo >= 0) { + return $#psrinfo +1; + } + } + if(-x "/usr/sbin/prtconf") { + my @prtconf = ::qqx("/usr/sbin/prtconf | grep cpu..instance"); + if($#prtconf >= 0) { + return $#prtconf +1; + } + } + return undef; +} + +sub no_of_cpus_aix { + # Returns: + # Number of physical CPUs on AIX + # undef if not AIX + local $/ = "\n"; + my $no_of_cpus = 0; + if(-x "/usr/sbin/lscfg") { + open(my $in_fh, "-|", "/usr/sbin/lscfg -vs |grep proc | wc -l|tr -d ' '") + || return undef; + $no_of_cpus = <$in_fh>; + chomp ($no_of_cpus); + close $in_fh; + } + return $no_of_cpus; +} + +sub no_of_cores_aix { + # Returns: + # Number of CPU cores on AIX + # undef if not AIX + my $no_of_cores; + if(-x "/usr/bin/vmstat") { + open(my $in_fh, "-|", "/usr/bin/vmstat 1 1") || return undef; + while(<$in_fh>) { + /lcpu=([0-9]*) / and $no_of_cores = $1; + } + close $in_fh; + } + return $no_of_cores; +} + +sub no_of_cpus_hpux { + # Returns: + # Number of physical CPUs on HP-UX + # undef if not HP-UX + my $no_of_cpus = + ::qqx(qq{ /usr/bin/mpsched -s 2>&1 | grep 'Locality Domain Count' | awk '{ print \$4 }'}); + return $no_of_cpus; +} + +sub no_of_cores_hpux { + # Returns: + # Number of CPU cores on HP-UX + # undef if not HP-UX + my $no_of_cores = + ::qqx(qq{ /usr/bin/mpsched -s 2>&1 | perl -ne '/Processor Count\\D+(\\d+)/ and print "\$1\n"'}); + return $no_of_cores; +} + +sub no_of_cpus_qnx { + # Returns: + # Number of physical CPUs on QNX + # undef if not QNX + # BUG: It is not known how to calculate this. + my $no_of_cpus = 0; + return $no_of_cpus; +} + +sub no_of_cores_qnx { + # Returns: + # Number of CPU cores on QNX + # undef if not QNX + # BUG: It is not known how to calculate this. + my $no_of_cores = 0; + return $no_of_cores; +} + +sub no_of_cpus_openserver { + # Returns: + # Number of physical CPUs on SCO OpenServer + # undef if not SCO OpenServer + my $no_of_cpus = 0; + if(-x "/usr/sbin/psrinfo") { + my @psrinfo = ::qqx("/usr/sbin/psrinfo"); + if($#psrinfo >= 0) { + return $#psrinfo +1; + } + } + return $no_of_cpus; +} + +sub no_of_cores_openserver { + # Returns: + # Number of CPU cores on SCO OpenServer + # undef if not SCO OpenServer + my $no_of_cores = 0; + if(-x "/usr/sbin/psrinfo") { + my @psrinfo = ::qqx("/usr/sbin/psrinfo"); + if($#psrinfo >= 0) { + return $#psrinfo +1; + } + } + return $no_of_cores; +} + +sub no_of_cpus_irix { + # Returns: + # Number of physical CPUs on IRIX + # undef if not IRIX + my $no_of_cpus = ::qqx(qq{ hinv | grep HZ | grep Processor | awk '{print \$1}' }); + return $no_of_cpus; +} + +sub no_of_cores_irix { + # Returns: + # Number of CPU cores on IRIX + # undef if not IRIX + my $no_of_cores = ::qqx(qq{ hinv | grep HZ | grep Processor | awk '{print \$1}' }); + return $no_of_cores; +} + +sub no_of_cpus_tru64 { + # Returns: + # Number of physical CPUs on Tru64 + # undef if not Tru64 + my $no_of_cpus = ::qqx("sizer -pr"); + return $no_of_cpus; +} + +sub no_of_cores_tru64 { + # Returns: + # Number of CPU cores on Tru64 + # undef if not Tru64 + my $no_of_cores = ::qqx("sizer -pr"); + return $no_of_cores; +} + +sub sshcommand { + my $self = shift; + if (not defined $self->{'sshcommand'}) { + $self->sshcommand_of_sshlogin(); + } + return $self->{'sshcommand'}; +} + +sub serverlogin { + my $self = shift; + if (not defined $self->{'serverlogin'}) { + $self->sshcommand_of_sshlogin(); + } + return $self->{'serverlogin'}; +} + +sub sshcommand_of_sshlogin { + # 'server' -> ('ssh -S /tmp/parallel-ssh-RANDOM/host-','server') + # 'user@server' -> ('ssh','user@server') + # 'myssh user@server' -> ('myssh','user@server') + # 'myssh -l user server' -> ('myssh -l user','server') + # '/usr/bin/myssh -l user server' -> ('/usr/bin/myssh -l user','server') + # Returns: + # sshcommand - defaults to 'ssh' + # login@host + my $self = shift; + my ($sshcmd, $serverlogin); + # If $opt::ssh is unset, use $PARALLEL_SSH or 'ssh' + $opt::ssh ||= $ENV{'PARALLEL_SSH'} || "ssh"; + if($self->{'string'} =~ /(.+) (\S+)$/) { + # Own ssh command + $sshcmd = $1; $serverlogin = $2; + } else { + # Normal ssh + if($opt::controlmaster) { + # Use control_path to make ssh faster + my $control_path = $self->control_path_dir()."/ssh-%r@%h:%p"; + $sshcmd = $opt::ssh." -S ".$control_path; + $serverlogin = $self->{'string'}; + if(not $self->{'control_path'}{$control_path}++) { + # Master is not running for this control_path + # Start it + my $pid = fork(); + if($pid) { + $Global::sshmaster{$pid} ||= 1; + } else { + $SIG{'TERM'} = undef; + # Ignore the 'foo' being printed + open(STDOUT,">","/dev/null"); + # STDERR >/dev/null to ignore + open(STDERR,">","/dev/null"); + open(STDIN,"<","/dev/null"); + # Run a sleep that outputs data, so it will discover + # if the ssh connection closes. + my $sleep = ::shell_quote_scalar + ('$|=1;while(1){sleep 1;print "foo\n"}'); + my @master = ($opt::ssh, "-MTS", + $control_path, $serverlogin, "--", "perl", "-e", + $sleep); + exec(@master); + } + } + } else { + $sshcmd = $opt::ssh; $serverlogin = $self->{'string'}; + } + } + + if($serverlogin =~ s/(\S+)\@(\S+)/$2/) { + # convert user@server to '-l user server' + # because lsh does not support user@server + $sshcmd = $sshcmd." -l ".$1; + } + + $self->{'sshcommand'} = $sshcmd; + $self->{'serverlogin'} = $serverlogin; +} + +sub control_path_dir { + # Returns: + # path to directory + my $self = shift; + if(not defined $self->{'control_path_dir'}) { + $self->{'control_path_dir'} = + # Use $ENV{'TMPDIR'} as that is typically not + # NFS mounted + File::Temp::tempdir($ENV{'TMPDIR'} + . "/control_path_dir-XXXX", + CLEANUP => 1); + } + return $self->{'control_path_dir'}; +} + +sub rsync_transfer_cmd { + # Command to run to transfer a file + # Input: + # $file = filename of file to transfer + # $workdir = destination dir + # Returns: + # $cmd = rsync command to run to transfer $file ("" if unreadable) + my $self = shift; + my $file = shift; + my $workdir = shift; + if(not -r $file) { + ::warning($file. " is not readable and will not be transferred."); + return "true"; + } + my $rsync_destdir; + my $relpath = ($file !~ m:^/:) || ($file =~ m:/\./:); # Is the path relative or /./? + if($relpath) { + $rsync_destdir = ::shell_quote_file($workdir); + } else { + # rsync /foo/bar / + $rsync_destdir = "/"; + } + $file = ::shell_quote_file($file); + my $sshcmd = $self->sshcommand(); + my $rsync_opts = $ENV{'PARALLEL_RSYNC_OPTS'}. + " -e".::shell_quote_scalar($sshcmd); + my $serverlogin = $self->serverlogin(); + # Make dir if it does not exist + return "$sshcmd $serverlogin -- mkdir -p $rsync_destdir && " . + rsync()." $rsync_opts $file $serverlogin:$rsync_destdir"; +} + +sub cleanup_cmd { + # Command to run to remove the remote file + # Input: + # $file = filename to remove + # $workdir = destination dir + # Returns: + # $cmd = ssh command to run to remove $file and empty parent dirs + my $self = shift; + my $file = shift; + my $workdir = shift; + my $f = $file; + if($f =~ m:/\./:) { + # foo/bar/./baz/quux => workdir/baz/quux + # /foo/bar/./baz/quux => workdir/baz/quux + $f =~ s:.*/\./:$workdir/:; + } elsif($f =~ m:^[^/]:) { + # foo/bar => workdir/foo/bar + $f = $workdir."/".$f; + } + my @subdirs = split m:/:, ::dirname($f); + my @rmdir; + my $dir = ""; + for(@subdirs) { + $dir .= $_."/"; + unshift @rmdir, ::shell_quote_file($dir); + } + my $rmdir = @rmdir ? "sh -c ".::shell_quote_scalar("rmdir @rmdir 2>/dev/null;") : ""; + if(defined $opt::workdir and $opt::workdir eq "...") { + $rmdir .= ::shell_quote_scalar("rm -rf " . ::shell_quote_file($workdir).';'); + } + + $f = ::shell_quote_file($f); + my $sshcmd = $self->sshcommand(); + my $serverlogin = $self->serverlogin(); + return "$sshcmd $serverlogin -- ".::shell_quote_scalar("rm -f $f; $rmdir"); +} + +{ + my $rsync; + + sub rsync { + # rsync 3.1.x uses protocol 31 which is unsupported by 2.5.7. + # If the version >= 3.1.0: downgrade to protocol 30 + if(not $rsync) { + my @out = `rsync --version`; + for (@out) { + if(/version (\d+.\d+)(.\d+)?/) { + if($1 >= 3.1) { + # Version 3.1.0 or later: Downgrade to protocol 30 + $rsync = "rsync --protocol 30"; + } else { + $rsync = "rsync"; + } + } + } + $rsync or ::die_bug("Cannot figure out version of rsync: @out"); + } + return $rsync; + } +} + + +package JobQueue; + +sub new { + my $class = shift; + my $commandref = shift; + my $read_from = shift; + my $context_replace = shift; + my $max_number_of_args = shift; + my $transfer_files = shift; + my $return_files = shift; + my $commandlinequeue = CommandLineQueue->new + ($commandref, $read_from, $context_replace, $max_number_of_args, + $transfer_files, $return_files); + my @unget = (); + return bless { + 'unget' => \@unget, + 'commandlinequeue' => $commandlinequeue, + 'this_job_no' => 0, + 'total_jobs' => undef, + }, ref($class) || $class; +} + +sub get { + my $self = shift; + + $self->{'this_job_no'}++; + if(@{$self->{'unget'}}) { + return shift @{$self->{'unget'}}; + } else { + my $commandline = $self->{'commandlinequeue'}->get(); + if(defined $commandline) { + return Job->new($commandline); + } else { + $self->{'this_job_no'}--; + return undef; + } + } +} + +sub unget { + my $self = shift; + unshift @{$self->{'unget'}}, @_; + $self->{'this_job_no'} -= @_; +} + +sub empty { + my $self = shift; + my $empty = (not @{$self->{'unget'}}) + && $self->{'commandlinequeue'}->empty(); + ::debug("run", "JobQueue->empty $empty "); + return $empty; +} + +sub total_jobs { + my $self = shift; + if(not defined $self->{'total_jobs'}) { + if($opt::pipe and not $opt::tee) { + ::error("--pipe is incompatible with --eta/--bar/--shuf"); + ::wait_and_exit(255); + } + if($opt::sqlworker) { + $self->{'total_jobs'} = $Global::sql->total_jobs(); + } else { + my $record; + my @arg_records; + my $record_queue = $self->{'commandlinequeue'}{'arg_queue'}; + my $start = time; + while($record = $record_queue->get()) { + push @arg_records, $record; + if(time - $start > 10) { + ::warning("Reading ".scalar(@arg_records). + " arguments took longer than 10 seconds."); + $opt::eta && ::warning("Consider removing --eta."); + $opt::bar && ::warning("Consider removing --bar."); + $opt::shuf && ::warning("Consider removing --shuf."); + last; + } + } + while($record = $record_queue->get()) { + push @arg_records, $record; + } + if($opt::shuf) { + my $i = @arg_records; + while (--$i) { + my $j = int rand($i+1); + @arg_records[$i,$j] = @arg_records[$j,$i]; + } + } + $record_queue->unget(@arg_records); + $self->{'total_jobs'} = + ::ceil((1+$#arg_records+$self->{'this_job_no'}) + / ::max($Global::max_number_of_args,1)); + ::debug("init","Total jobs: ".$self->{'total_jobs'}. + " (".(1+$#arg_records)."+".$self->{'this_job_no'}.")\n"); + } + } + return $self->{'total_jobs'}; +} + +sub flush_total_jobs { + # Unset total_jobs to force recomputing + my $self = shift; + $self->{'total_jobs'} = undef; +} + +sub next_seq { + my $self = shift; + + return $self->{'commandlinequeue'}->seq(); +} + +sub quote_args { + my $self = shift; + return $self->{'commandlinequeue'}->quote_args(); +} + + +package Job; + +sub new { + my $class = shift; + my $commandlineref = shift; + return bless { + 'commandline' => $commandlineref, # CommandLine object + 'workdir' => undef, # --workdir + # filehandle for stdin (used for --pipe) + # filename for writing stdout to (used for --files) + # remaining data not sent to stdin (used for --pipe) + # tmpfiles to cleanup when job is done + 'unlink' => [], + # amount of data sent via stdin (used for --pipe) + 'transfersize' => 0, # size of files using --transfer + 'returnsize' => 0, # size of files using --return + 'pid' => undef, + # hash of { SSHLogins => number of times the command failed there } + 'failed' => undef, + 'sshlogin' => undef, + # The commandline wrapped with rsync and ssh + 'sshlogin_wrap' => undef, + 'exitstatus' => undef, + 'exitsignal' => undef, + # Timestamp for timeout if any + 'timeout' => undef, + 'virgin' => 1, + # Output used for SQL and CSV-output + 'output' => { 1 => [], 2 => [] }, + 'halfline' => { 1 => [], 2 => [] }, + }, ref($class) || $class; +} + +sub replaced { + my $self = shift; + $self->{'commandline'} or ::die_bug("commandline empty"); + return $self->{'commandline'}->replaced(); +} + +sub seq { + my $self = shift; + return $self->{'commandline'}->seq(); +} + +sub set_seq { + my $self = shift; + return $self->{'commandline'}->set_seq(shift); +} + +sub slot { + my $self = shift; + return $self->{'commandline'}->slot(); +} + +sub free_slot { + my $self = shift; + push @Global::slots, $self->slot(); +} + +{ + my($cattail); + + sub cattail { + # Returns: + # $cattail = perl program for: + # cattail "decompress program" writerpid [file_to_decompress or stdin] [file_to_unlink] + if(not $cattail) { + $cattail = q{ + # cat followed by tail (possibly with rm as soon at the file is opened) + # If $writerpid dead: finish after this round + use Fcntl; + $|=1; + + my ($comfile, $cmd, $writerpid, $read_file, $unlink_file) = @ARGV; + if($read_file) { + open(IN,"<",$read_file) || die("cattail: Cannot open $read_file"); + } else { + *IN = *STDIN; + } + while(! -s $comfile) { + # Writer has not opened the buffer file, so we cannot remove it yet + $sleep = ($sleep < 30) ? ($sleep * 1.001 + 0.01) : ($sleep); + usleep($sleep); + } + # The writer and we have both opened the file, so it is safe to unlink it + unlink $unlink_file; + unlink $comfile; + + my $first_round = 1; + my $flags; + fcntl(IN, F_GETFL, $flags) || die $!; # Get the current flags on the filehandle + $flags |= O_NONBLOCK; # Add non-blocking to the flags + fcntl(IN, F_SETFL, $flags) || die $!; # Set the flags on the filehandle + + while(1) { + # clear EOF + seek(IN,0,1); + my $writer_running = kill 0, $writerpid; + $read = sysread(IN,$buf,131072); + if($read) { + if($first_round) { + # Only start the command if there any input to process + $first_round = 0; + open(OUT,"|-",$cmd) || die("cattail: Cannot run $cmd"); + } + + # Blocking print + while($buf) { + my $bytes_written = syswrite(OUT,$buf); + # syswrite may be interrupted by SIGHUP + substr($buf,0,$bytes_written) = ""; + } + # Something printed: Wait less next time + $sleep /= 2; + } else { + if(eof(IN) and not $writer_running) { + # Writer dead: There will never be sent more to the decompressor + close OUT; + exit; + } + # TODO This could probably be done more efficiently using select(2) + # Nothing read: Wait longer before next read + # Up to 100 milliseconds + $sleep = ($sleep < 100) ? ($sleep * 1.001 + 0.01) : ($sleep); + usleep($sleep); + } + } + + sub usleep { + # Sleep this many milliseconds. + my $secs = shift; + select(undef, undef, undef, $secs/1000); + } + }; + $cattail =~ s/#.*//mg; + $cattail =~ s/\s+/ /g; + } + return $cattail; + } +} + +sub openoutputfiles { + # Open files for STDOUT and STDERR + # Set file handles in $self->fh + my $self = shift; + my ($outfhw, $errfhw, $outname, $errname); + + if($opt::linebuffer and not + ($opt::keeporder or $opt::files or $opt::results or + $opt::compress or $opt::compress_program or + $opt::decompress_program)) { + # Do not save to files: Use non-blocking pipe + my ($outfhr, $errfhr); + pipe($outfhr, $outfhw) || die; + pipe($errfhr, $errfhw) || die; + $self->set_fh(1,'w',$outfhw); + $self->set_fh(2,'w',$errfhw); + $self->set_fh(1,'r',$outfhr); + $self->set_fh(2,'r',$errfhr); + # Make it possible to read non-blocking from the pipe + for my $fdno (1,2) { + ::set_fh_non_blocking($self->fh($fdno,'r')); + } + # Return immediately because we do not need setting filenames + return; + } elsif($opt::results and not $Global::csvsep) { + my $out = $self->{'commandline'}->results_out(); + my $seqname; + if($out eq $opt::results or $out =~ m:/$:) { + # $opt::results = simple string or ending in / + # => $out is a dir/ + # prefix/name1/val1/name2/val2/seq + $seqname = $out."seq"; + # prefix/name1/val1/name2/val2/stdout + $outname = $out."stdout"; + # prefix/name1/val1/name2/val2/stderr + $errname = $out."stderr"; + } else { + # $opt::results = replacement string not ending in / + # => $out is a file + $outname = $out; + $errname = "$out.err"; + $seqname = "$out.seq"; + } + my $seqfhw; + if(not open($seqfhw, "+>", $seqname)) { + ::error("Cannot write to `$seqname'."); + ::wait_and_exit(255); + } + print $seqfhw $self->seq(); + close $seqfhw; + if(not open($outfhw, "+>", $outname)) { + ::error("Cannot write to `$outname'."); + ::wait_and_exit(255); + } + if(not open($errfhw, "+>", $errname)) { + ::error("Cannot write to `$errname'."); + ::wait_and_exit(255); + } + $self->set_fh(1,"unlink",""); + $self->set_fh(2,"unlink",""); + if($opt::sqlworker) { + # Save the filenames in SQL table + $Global::sql->update("SET Stdout = ?, Stderr = ? ". + "WHERE Seq = ". $self->seq(), + $outname, $errname); + } + } elsif(not $opt::ungroup) { + # To group we create temporary files for STDOUT and STDERR + # To avoid the cleanup unlink the files immediately (but keep them open) + if($opt::files) { + ($outfhw, $outname) = ::tmpfile(SUFFIX => ".par"); + ($errfhw, $errname) = ::tmpfile(SUFFIX => ".par"); + # --files => only remove stderr + $self->set_fh(1,"unlink",""); + $self->set_fh(2,"unlink",$errname); + } else { + ($outfhw, $outname) = ::tmpfile(SUFFIX => ".par"); + ($errfhw, $errname) = ::tmpfile(SUFFIX => ".par"); + $self->set_fh(1,"unlink",$outname); + $self->set_fh(2,"unlink",$errname); + } + } else { + # --ungroup + open($outfhw,">&",$Global::fd{1}) || die; + open($errfhw,">&",$Global::fd{2}) || die; + # File name must be empty as it will otherwise be printed + $outname = ""; + $errname = ""; + $self->set_fh(1,"unlink",$outname); + $self->set_fh(2,"unlink",$errname); + } + # Set writing FD + $self->set_fh(1,'w',$outfhw); + $self->set_fh(2,'w',$errfhw); + $self->set_fh(1,'name',$outname); + $self->set_fh(2,'name',$errname); + if($opt::compress) { + $self->filter_through_compress(); + } elsif(not $opt::ungroup) { + $self->grouped(); + } + if($opt::linebuffer) { + # Make it possible to read non-blocking from + # the buffer files + # Used for --linebuffer with -k, --files, --res, --compress* + for my $fdno (1,2) { + ::set_fh_non_blocking($self->fh($fdno,'r')); + } + } +} + +sub print_verbose_dryrun { + # If -v set: print command to stdout (possibly buffered) + # This must be done before starting the command + my $self = shift; + if($Global::verbose or $opt::dryrun) { + my $fh = $self->fh(1,"w"); + if($Global::verbose <= 1) { + print $fh $self->replaced(),"\n"; + } else { + # Verbose level > 1: Print the rsync and stuff + print $fh $self->wrapped(),"\n"; + } + } + if($opt::sqlworker) { + $Global::sql->update("SET Command = ? WHERE Seq = ".$self->seq(), + $self->replaced()); + } +} + +sub add_rm { + # Files to remove when job is done + my $self = shift; + push @{$self->{'unlink'}}, @_; +} + +sub get_rm { + # Files to remove when job is done + my $self = shift; + return @{$self->{'unlink'}}; +} + +sub cleanup { + # Remove files when job is done + my $self = shift; + unlink $self->get_rm(); + delete @Global::unlink{$self->get_rm()}; +} + +sub grouped { + my $self = shift; + # Set reading FD if using --group (--ungroup does not need) + for my $fdno (1,2) { + # Re-open the file for reading + # so fdw can be closed seperately + # and fdr can be seeked seperately (for --line-buffer) + open(my $fdr,"<", $self->fh($fdno,'name')) || + ::die_bug("fdr: Cannot open ".$self->fh($fdno,'name')); + $self->set_fh($fdno,'r',$fdr); + # Unlink if required + $Global::debug or ::rm($self->fh($fdno,"unlink")); + } +} + +sub empty_input_wrapper { + # If no input: exit(0) + # If some input: Pass input as input to command on STDIN + # This avoids starting the command if there is no input. + # Input: + # $command = command to pipe data to + # Returns: + # $wrapped_command = the wrapped command + my $command = shift; + my $script = + ::spacefree(0,q{ + if(sysread(STDIN, $buf, 1)) { + open($fh, "|-", @ARGV) || die; + syswrite($fh, $buf); + # Align up to 128k block + if($read = sysread(STDIN, $buf, 131071)) { + syswrite($fh, $buf); + } + while($read = sysread(STDIN, $buf, 131072)) { + syswrite($fh, $buf); + } + close $fh; + exit ($?&127 ? 128+($?&127) : 1+$?>>8) + } + }); + ::debug("run",'Empty wrap: perl -e '.::shell_quote_scalar($script)."\n"); + if($Global::cshell + and + length $command > 499) { + # csh does not like words longer than 1000 (499 quoted) + # $command = "perl -e '".base64_zip_eval()."' ". + # join" ",string_zip_base64( + # 'exec "'.::perl_quote_scalar($command).'"'); + return 'perl -e '.::shell_quote_scalar($script)." ". + base64_wrap("exec \"$Global::shell\",'-c',\"". + ::perl_quote_scalar($command).'"'); + } else { + return 'perl -e '.::shell_quote_scalar($script)." ". + $Global::shell." -c ".::shell_quote_scalar($command); + } +} + +sub filter_through_compress { + my $self = shift; + # Send stdout to stdin for $opt::compress_program(1) + # Send stderr to stdin for $opt::compress_program(2) + # cattail get pid: $pid = $self->fh($fdno,'rpid'); + my $cattail = cattail(); + + for my $fdno (1,2) { + # Make a communication file. + my ($fh, $comfile) = ::tmpfile(SUFFIX => ".pac"); + close $fh; + # Compressor: (echo > $comfile; compress pipe) > output + # When the echo is written to $comfile, + # it is known that output file is opened, + # thus output file can then be removed by the decompressor. + my $wpid = open(my $fdw,"|-", "(echo > $comfile; ". + empty_input_wrapper($opt::compress_program).") >". + $self->fh($fdno,'name')) || die $?; + $self->set_fh($fdno,'w',$fdw); + $self->set_fh($fdno,'wpid',$wpid); + # Decompressor: open output; -s $comfile > 0: rm $comfile output; + # decompress output > stdout + my $rpid = open(my $fdr, "-|", "perl", "-e", $cattail, $comfile, + $opt::decompress_program, $wpid, + $self->fh($fdno,'name'),$self->fh($fdno,'unlink')) + || die $?; + $self->set_fh($fdno,'r',$fdr); + $self->set_fh($fdno,'rpid',$rpid); + } +} + + + +sub set_fh { + # Set file handle + my ($self, $fd_no, $key, $fh) = @_; + $self->{'fd'}{$fd_no,$key} = $fh; +} + +sub fh { + # Get file handle + my ($self, $fd_no, $key) = @_; + return $self->{'fd'}{$fd_no,$key}; +} + +sub write { + my $self = shift; + my $remaining_ref = shift; + my $stdin_fh = $self->fh(0,"w"); + + my $len = length $$remaining_ref; + # syswrite may not write all in one go, + # so make sure everything is written. + my $written; + + # If writing is to a closed pipe: + # Do not call signal handler, but let nothing be written + local $SIG{PIPE} = undef; + while($written = syswrite($stdin_fh,$$remaining_ref)){ + substr($$remaining_ref,0,$written) = ""; + } +} + +sub set_block { + # Copy stdin buffer from $block_ref up to $endpos + # Prepend with $header_ref if virgin (i.e. not --roundrobin) + # Remove $recstart and $recend if needed + # Input: + # $header_ref = ref to $header to prepend + # $buffer_ref = ref to $buffer containing the block + # $endpos = length of $block to pass on + # $recstart = --recstart regexp + # $recend = --recend regexp + # Returns: + # N/A + my $self = shift; + my ($header_ref,$buffer_ref,$endpos,$recstart,$recend) = @_; + $self->{'block'} = ($self->virgin() ? $$header_ref : ""). + substr($$buffer_ref,0,$endpos); + if($opt::remove_rec_sep) { + remove_rec_sep(\$self->{'block'},$recstart,$recend); + } + $self->{'block_length'} = length $self->{'block'}; + $self->{'block_pos'} = 0; + $self->add_transfersize($self->{'block_length'}); +} + +sub block_ref { + my $self = shift; + return \$self->{'block'}; +} + + +sub block_length { + my $self = shift; + return $self->{'block_length'}; +} + +sub remove_rec_sep { + my ($block_ref,$recstart,$recend) = @_; + # Remove record separator + $$block_ref =~ s/$recend$recstart//gos; + $$block_ref =~ s/^$recstart//os; + $$block_ref =~ s/$recend$//os; +} + +sub non_blocking_write { + my $self = shift; + my $something_written = 0; + use POSIX qw(:errno_h); + + my $in = $self->fh(0,"w"); + my $rv = syswrite($in, + substr($self->{'block'},$self->{'block_pos'})); + if (!defined($rv) && $! == EAGAIN) { + # would block - but would have written + $something_written = 0; + # avoid triggering auto expanding block + $Global::no_autoexpand_block ||= 1; + } elsif ($self->{'block_pos'}+$rv != $self->{'block_length'}) { + # incomplete write + # Remove the written part + $self->{'block_pos'} += $rv; + $something_written = $rv; + } else { + # successfully wrote everything + # Empty block to free memory + my $a = ""; + $self->set_block(\$a,\$a,0,"",""); + $something_written = $rv; + } + ::debug("pipe", "Non-block: ", $something_written); + return $something_written; +} + + +sub virgin { + my $self = shift; + return $self->{'virgin'}; +} + +sub set_virgin { + my $self = shift; + $self->{'virgin'} = shift; +} + +sub pid { + my $self = shift; + return $self->{'pid'}; +} + +sub set_pid { + my $self = shift; + $self->{'pid'} = shift; +} + +sub starttime { + # Returns: + # UNIX-timestamp this job started + my $self = shift; + return sprintf("%.3f",$self->{'starttime'}); +} + +sub set_starttime { + my $self = shift; + my $starttime = shift || ::now(); + $self->{'starttime'} = $starttime; + $opt::sqlworker and + $Global::sql->update("SET Starttime = ? WHERE Seq = ".$self->seq(), + $starttime); +} + +sub runtime { + # Returns: + # Run time in seconds with 3 decimals + my $self = shift; + return sprintf("%.3f", + int(($self->endtime() - $self->starttime())*1000)/1000); +} + +sub endtime { + # Returns: + # UNIX-timestamp this job ended + # 0 if not ended yet + my $self = shift; + return ($self->{'endtime'} || 0); +} + +sub set_endtime { + my $self = shift; + my $endtime = shift; + $self->{'endtime'} = $endtime; + $opt::sqlworker and + $Global::sql->update("SET JobRuntime = ? WHERE Seq = ".$self->seq(), + $self->runtime()); +} + +sub is_timedout { + # Is the job timedout? + # Input: + # $delta_time = time that the job may run + # Returns: + # True or false + my $self = shift; + my $delta_time = shift; + return time > $self->{'starttime'} + $delta_time; +} + +sub kill { + my $self = shift; + $self->set_exitstatus(-1); + ::kill_sleep_seq($self->pid()); +} + +sub failed { + # return number of times failed for this $sshlogin + # Input: + # $sshlogin + # Returns: + # Number of times failed for $sshlogin + my $self = shift; + my $sshlogin = shift; + return $self->{'failed'}{$sshlogin}; +} + +sub failed_here { + # return number of times failed for the current $sshlogin + # Returns: + # Number of times failed for this sshlogin + my $self = shift; + return $self->{'failed'}{$self->sshlogin()}; +} + +sub add_failed { + # increase the number of times failed for this $sshlogin + my $self = shift; + my $sshlogin = shift; + $self->{'failed'}{$sshlogin}++; +} + +sub add_failed_here { + # increase the number of times failed for the current $sshlogin + my $self = shift; + $self->{'failed'}{$self->sshlogin()}++; +} + +sub reset_failed { + # increase the number of times failed for this $sshlogin + my $self = shift; + my $sshlogin = shift; + delete $self->{'failed'}{$sshlogin}; +} + +sub reset_failed_here { + # increase the number of times failed for this $sshlogin + my $self = shift; + delete $self->{'failed'}{$self->sshlogin()}; +} + +sub min_failed { + # Returns: + # the number of sshlogins this command has failed on + # the minimal number of times this command has failed + my $self = shift; + my $min_failures = + ::min(map { $self->{'failed'}{$_} } keys %{$self->{'failed'}}); + my $number_of_sshlogins_failed_on = scalar keys %{$self->{'failed'}}; + return ($number_of_sshlogins_failed_on,$min_failures); +} + +sub total_failed { + # Returns: + # $total_failures = the number of times this command has failed + my $self = shift; + my $total_failures = 0; + for (values %{$self->{'failed'}}) { + $total_failures += $_; + } + return $total_failures; +} + +{ + my $script; + + sub postpone_exit_and_cleanup { + # Command to remove files and dirs (given as args) without + # affecting the exit value in $?/$status. + if(not $script) { + $script = "perl -e '". + ::spacefree(0,q{ + $bash=shift; + $csh=shift; + for(@ARGV){ + unlink; + rmdir; + } + if($bash=~s/h//) { + exit $bash; + } + exit $csh; + }). + "' ".'"$?h" "$status" '; + } + return $script + } +} + +{ + my $script; + + sub fifo_wrap { + # Script to create a fifo, run a command on the fifo + # while copying STDIN to the fifo, and finally + # remove the fifo and return the exit code of the command. + if(not $script) { + # {} == $PARALLEL_TMP for --fifo + # To make it csh compatible a wrapper needs to: + # * mkfifo + # * spawn $command & + # * cat > fifo + # * waitpid to get the exit code from $command + # * be less than 1000 chars long + $script = "perl -e '". + (::spacefree + (0, q{ + ($s,$c,$f) = @ARGV; + # mkfifo $PARALLEL_TMP + system "mkfifo", $f; + # spawn $shell -c $command & + $pid = fork || exec $s, "-c", $c; + open($o,">",$f) || die $!; + # cat > $PARALLEL_TMP + while(sysread(STDIN,$buf,131072)){ + syswrite $o, $buf; + } + close $o; + # waitpid to get the exit code from $command + waitpid $pid,0; + # Cleanup + unlink $f; + exit $?/256; + }))."'"; + } + return $script; + } +} + +sub wrapped { + # Wrap command with: + # * --shellquote + # * --nice + # * --cat + # * --fifo + # * --sshlogin + # * --pipepart (@Global::cat_prepends) + # * --tee (@Global::cat_prepends) + # * --pipe + # * --tmux + # The ordering of the wrapping is important: + # * --nice/--cat/--fifo should be done on the remote machine + # * --pipepart/--pipe should be done on the local machine inside --tmux + # Uses: + # $opt::shellquote + # $opt::nice + # $Global::shell + # $opt::cat + # $opt::fifo + # @Global::cat_prepends + # $opt::pipe + # $opt::tmux + # Returns: + # $self->{'wrapped'} = the command wrapped with the above + my $self = shift; + if(not defined $self->{'wrapped'}) { + my $command = $self->replaced(); + # Bug in Bash and Ksh when running multiline aliases + # This will force them to run correctly, but will fail in + # tcsh so we do not do it. + # $command .= "\n\n"; + if($opt::shellquote) { + # Prepend /bin/echo (echo no-/bin is wrong in csh) + # and quote twice + $command = "/bin/echo " . + ::shell_quote_scalar(::shell_quote_scalar($command)); + } + if($ENV{'PARALLEL_ENV'}) { + if(-e $ENV{'PARALLEL_ENV'}) { + # This is a file/fifo: Replace envvar with content of file + open(my $parallel_env, "<", $ENV{'PARALLEL_ENV'}) || + ::die_bug("Cannot read parallel_env from $ENV{'PARALLEL_ENV'}"); + local $/; + $ENV{'PARALLEL_ENV'} = <$parallel_env>; + close $parallel_env; + } + # If $PARALLEL_ENV set, put that in front of the command + # Used for env_parallel.* + # Map \001 to \n to make it easer to quote \n in $PARALLEL_ENV + $ENV{'PARALLEL_ENV'} =~ s/\001/\n/g; + if($Global::shell =~ /zsh/) { + # The extra 'eval' will make aliases work, too + $command = $ENV{'PARALLEL_ENV'}."\n". + "eval ".::shell_quote_scalar($command); + } else { + $command = $ENV{'PARALLEL_ENV'}."\n".$command; + } + } + if($opt::cat) { + # In '--cat' and '--fifo' {} == $PARALLEL_TMP. + # This is to make it possible to compute $PARALLEL_TMP on + # the fly when running remotely. + # $ENV{PARALLEL_TMP} is set in the remote wrapper before + # the command is run. + # + # Prepend 'cat > $PARALLEL_TMP;' + # Append 'unlink $PARALLEL_TMP without affecting $?' + $command = + 'cat > $PARALLEL_TMP;'. + $command.";". postpone_exit_and_cleanup(). + '$PARALLEL_TMP'; + } elsif($opt::fifo) { + # Prepend fifo-wrapper. In essence: + # mkfifo {} + # ( $command ) & + # # $command must read {}, otherwise this 'cat' will block + # cat > {}; + # wait; rm {} + # without affecting $? + $command = fifo_wrap(). " ". + $Global::shell. " ". + ::shell_quote_scalar($command). + ' $PARALLEL_TMP'. + ';'; + } + # Wrap with ssh + tranferring of files + $command = $self->sshlogin_wrap($command); + if(@Global::cat_prepends) { + # --pipepart: prepend: + # < /tmp/foo perl -e 'while(@ARGV) { + # sysseek(STDIN,shift,0) || die; $left = shift; + # while($read = sysread(STDIN,$buf, ($left > 131072 ? 131072 : $left))){ + # $left -= $read; syswrite(STDOUT,$buf); + # } + # }' 0 0 0 11 | + # + # --pipepart --tee: prepend: + # < dash-a-file + # + # --pipe --tee: wrap: + # (rm fifo; ... ) < fifo + $command = (shift @Global::cat_prepends). "($command)". + (shift @Global::cat_appends); + } elsif($opt::pipe) { + # Wrap with EOF-detector to avoid starting $command if EOF. + $command = empty_input_wrapper($command); + } + if($opt::tmux) { + # Wrap command with 'tmux' + $command = $self->tmux_wrap($command); + } + if($Global::cshell + and + length $command > 499) { + # csh does not like words longer than 1000 (499 quoted) + # $command = "perl -e '".base64_zip_eval()."' ". + # join" ",string_zip_base64( + # 'exec "'.::perl_quote_scalar($command).'"'); + $command = base64_wrap("exec \"$Global::shell\",'-c',\"". + ::perl_quote_scalar($command).'"'); + } + $self->{'wrapped'} = $command; + } + return $self->{'wrapped'}; +} + +sub set_sshlogin { + my $self = shift; + my $sshlogin = shift; + $self->{'sshlogin'} = $sshlogin; + delete $self->{'sshlogin_wrap'}; # If sshlogin is changed the wrap is wrong + delete $self->{'wrapped'}; + + if($opt::sqlworker) { + # Identify worker as --sqlworker often runs on different machines + my $host = $sshlogin->string(); + if($host eq ":") { + $host = ::hostname(); + } + $Global::sql->update("SET Host = ? WHERE Seq = ".$self->seq(), $host); + } +} + +sub sshlogin { + my $self = shift; + return $self->{'sshlogin'}; +} + +sub string_base64 { + # Base64 encode strings into 1000 byte blocks. + # 1000 bytes is the largest word size csh supports + # Input: + # @strings = to be encoded + # Returns: + # @base64 = 1000 byte block + $Global::use{"MIME::Base64"} ||= eval "use MIME::Base64; 1;"; + my @base64 = unpack("(A1000)*",encode_base64((join"",@_),"")); + return @base64; +} + +sub string_zip_base64 { + # Pipe string through 'bzip2 -9' and base64 encode it into 1000 + # byte blocks. + # 1000 bytes is the largest word size csh supports + # Zipping will make exporting big environments work, too + # Input: + # @strings = to be encoded + # Returns: + # @base64 = 1000 byte block + my($zipin_fh, $zipout_fh,@base64); + ::open3($zipin_fh,$zipout_fh,">&STDERR","bzip2 -9"); + if(fork) { + close $zipin_fh; + $Global::use{"MIME::Base64"} ||= eval "use MIME::Base64; 1;"; + # Split base64 encoded into 1000 byte blocks + @base64 = unpack("(A1000)*",encode_base64((join"",<$zipout_fh>),"")); + close $zipout_fh; + } else { + close $zipout_fh; + print $zipin_fh @_; + close $zipin_fh; + exit; + } + ::debug("base64","Orig:@_\nAs bzip2 base64:@base64\n"); + return @base64; +} + +sub base64_zip_eval { + # Script that: + # * reads base64 strings from @ARGV + # * decodes them + # * pipes through 'bzip2 -dc' + # * evals the result + # Reverse of string_zip_base64 + eval + # Will be wrapped in ' so single quote is forbidden + # Returns: + # $script = 1-liner for perl -e + my $script = ::spacefree(0,q{ + @GNU_Parallel = split /_/, "use_IPC::Open3;_use_MIME::Base64"; + eval"@GNU_Parallel"; + $chld = $SIG{CHLD}; + $SIG{CHLD} = "IGNORE"; + # Search for bzip2. Not found => use default path + my $zip = (grep { -x $_ } "/usr/local/bin/bzip2")[0] || "bzip2"; + # $in = stdin on $zip, $out = stdout from $zip + # Forget my() to save chars for csh + # my($in, $out,$eval); + open3($in,$out,">&STDERR",$zip,"-dc"); + if(my $perlpid = fork) { + close $in; + $eval = join "", <$out>; + close $out; + } else { + close $out; + # Pipe decoded base64 into 'bzip2 -dc' + print $in (decode_base64(join"",@ARGV)); + close $in; + exit; + } + wait; + $SIG{CHLD} = $chld; + eval $eval; + }); + ::debug("base64",$script,"\n"); + return $script; +} + +sub base64_wrap { + # base64 encode Perl code + # Split it into chunks of < 1000 bytes + # Prepend it with a decoder that eval's it + # Input: + # $eval_string = Perl code to run + # Returns: + # $shell_command = shell command that runs $eval_string + my $eval_string = shift; + return + "perl -e ". + ::shell_quote_scalar(base64_zip_eval())." ". + join" ",::shell_quote(string_zip_base64($eval_string)); +} + +sub base64_eval { + # Script that: + # * reads base64 strings from @ARGV + # * decodes them + # * evals the result + # Reverse of string_base64 + eval + # Will be wrapped in ' so single quote is forbidden. + # Spaces are stripped so spaces cannot be significant. + # The funny 'use IPC::Open3'-syntax is to avoid spaces and + # to make it clear that this is a GNU Parallel command + # when looking at the process table. + # Returns: + # $script = 1-liner for perl -e + my $script = ::spacefree(0,q{ + @GNU_Parallel=("use","IPC::Open3;","use","MIME::Base64"); + eval "@GNU_Parallel"; + my $eval = decode_base64(join"",@ARGV); + eval $eval; + }); + ::debug("base64",$script,"\n"); + return $script; +} + +sub sshlogin_wrap { + # Wrap the command with the commands needed to run remotely + # Input: + # $command = command to run + # Returns: + # $self->{'sshlogin_wrap'} = command wrapped with ssh+transfer commands + sub monitor_parent_sshd_script { + # This script is to solve the problem of + # * not mixing STDERR and STDOUT + # * terminating with ctrl-c + # If its parent is ssh: all good + # If its parent is init(1): ssh died, so kill children + my $monitor_parent_sshd_script; + + if(not $monitor_parent_sshd_script) { + $monitor_parent_sshd_script = + # This will be packed in ', so only use " + ::spacefree(0,'$shell = "'.($ENV{'PARALLEL_SHELL'} || '$ENV{SHELL}').'";'. + '$tmpdir = "'.::perl_quote_scalar($ENV{'TMPDIR'}).'";'. + '$nice = '.$opt::nice.';'. + q{ + # Set $PARALLEL_TMP to a non-existent file name in $TMPDIR + do { + $ENV{PARALLEL_TMP} = $tmpdir."/par". + join"", map { (0..9,"a".."z","A".."Z")[rand(62)] } (1..5); + } while(-e $ENV{PARALLEL_TMP}); + $SIG{CHLD} = sub { $done = 1; }; + $pid = fork; + unless($pid) { + # Make own process group to be able to kill HUP it later + eval { setpgrp }; + eval { setpriority(0,0,$nice) }; + exec $shell, "-c", ($bashfunc."@ARGV"); + die "exec: $!\n"; + } + do { + # Parent is not init (ppid=1), so sshd is alive + # Exponential sleep up to 1 sec + $s = $s < 1 ? 0.001 + $s * 1.03 : $s; + select(undef, undef, undef, $s); + } until ($done || getppid == 1); + # Kill HUP the process group if job not done + kill(SIGHUP, -${pid}) unless $done; + wait; + exit ($?&127 ? 128+($?&127) : 1+$?>>8) + }); + } + return $monitor_parent_sshd_script; + } + + sub vars_to_export { + # Uses: + # @opt::env + my @vars = ("parallel_bash_environment"); + for my $varstring (@opt::env) { + # Split up --env VAR1,VAR2 + push @vars, split /,/, $varstring; + } + for (@vars) { + if(-r $_ and not -d) { + # Read as environment definition bug #44041 + # TODO parse this + my $fh = ::open_or_exit($_); + $Global::envdef = join("",<$fh>); + close $fh; + } + } + if(grep { /^_$/ } @vars) { + local $/ = "\n"; + # --env _ + # Include all vars that are not in a clean environment + if(open(my $vars_fh, "<", $Global::config_dir . "/ignored_vars")) { + my @ignore = <$vars_fh>; + chomp @ignore; + my %ignore; + @ignore{@ignore} = @ignore; + close $vars_fh; + push @vars, grep { not defined $ignore{$_} } keys %ENV; + @vars = grep { not /^_$/ } @vars; + } else { + ::error("Run '$Global::progname --record-env' ". + "in a clean environment first."); + ::wait_and_exit(255); + } + } + # Duplicate vars as BASH functions to include post-shellshock functions (v1+v2) + # So --env myfunc should look for BASH_FUNC_myfunc() and BASH_FUNC_myfunc%% + push(@vars, "PARALLEL_PID", "PARALLEL_SEQ", + map { ("BASH_FUNC_$_()", "BASH_FUNC_$_%%") } @vars); + # Keep only defined variables + return grep { defined($ENV{$_}) } @vars; + } + + sub env_as_eval { + # Returns: + # $eval = '$ENV{"..."}=...; ...' + my @vars = vars_to_export(); + my $csh_friendly = not grep { /\n/ } @ENV{@vars}; + my @bash_functions = grep { substr($ENV{$_},0,4) eq "() {" } @vars; + my @non_functions = (grep { !/PARALLEL_ENV/ } + grep { substr($ENV{$_},0,4) ne "() {" } @vars); + + # eval of @envset will set %ENV + my $envset = join"", map { + '$ENV{"'.::perl_quote_scalar($_).'"}="'. + ::perl_quote_scalar($ENV{$_}).'";'; } @non_functions; + + # running @bashfunc on the command line, will set the functions + my @bashfunc = map { + my $v=$_; + s/BASH_FUNC_(.*)(\(\)|%%)/$1/; + "$_$ENV{$v};export -f $_ >/dev/null;" } @bash_functions; + # eval $bashfuncset will set $bashfunc + my $bashfuncset; + if(@bashfunc) { + # Functions are not supported for all shells + if($Global::shell !~ m:(bash|rbash|zsh|rzsh|dash|ksh):) { + ::warning("Shell functions may not be supported in $Global::shell."); + } + $bashfuncset = + '@bash_functions=qw('."@bash_functions".");". + ::spacefree(1,'$shell="'.($ENV{'PARALLEL_SHELL'} || '$ENV{SHELL}').'";'.q{ + if($shell=~/csh/) { + print STDERR "CSH/TCSH DO NOT SUPPORT newlines IN VARIABLES/FUNCTIONS. Unset @bash_functions\n"; + exec "false"; + } + }). + "\n".'$bashfunc = "'.::perl_quote_scalar("@bashfunc").'";'; + } else { + $bashfuncset = '$bashfunc = "";' + } + if($ENV{"parallel_bash_environment"}) { + $bashfuncset .= '$bashfunc .= "eval\ \"\$parallel_bash_environment\"\;";'; + } + ::debug("base64",$envset,$bashfuncset,"\n"); + return $csh_friendly,$envset,$bashfuncset; + } + + my $self = shift; + my $command = shift; + # TODO test that *sh -c 'parallel --env' use *sh + if(not defined $self->{'sshlogin_wrap'}) { + my $sshlogin = $self->sshlogin(); + my $serverlogin = $sshlogin->serverlogin(); + my $quoted_remote_command; + $ENV{'PARALLEL_SEQ'} = $self->seq(); + $ENV{'PARALLEL_PID'} = $$; + if($serverlogin eq ":") { + if($opt::workdir) { + # Create workdir if needed. Then cd to it. + my $wd = $self->workdir(); + if($opt::workdir eq "." or $opt::workdir eq "...") { + # If $wd does not start with '/': Prepend $HOME + $wd =~ s:^([^/]):$ENV{'HOME'}/$1:; + } + ::mkdir_or_die($wd); + $command = "cd ".::shell_quote_scalar($wd)." || exit 255; ".$command; + } + if(@opt::env) { + # Prepend with environment setter, which sets functions in zsh + my ($csh_friendly,$envset,$bashfuncset) = env_as_eval(); + my $perl_code = $envset.$bashfuncset. + '@ARGV="'.::perl_quote_scalar($command).'";'. + "exec\"$Global::shell\",\"-c\",\(\$bashfunc.\"\@ARGV\"\)\;die\"exec:\$\!\\n\"\;"; + if(length $perl_code > 999 + or + not $csh_friendly + or + $command =~ /\n/) { + # csh does not deal well with > 1000 chars in one word + # csh does not deal well with $ENV with \n + $self->{'sshlogin_wrap'} = base64_wrap($perl_code); + } else { + $self->{'sshlogin_wrap'} = "perl -e ".::shell_quote_scalar($perl_code); + } + } else { + $self->{'sshlogin_wrap'} = $command; + } + } else { + my $pwd = ""; + if($opt::workdir) { + # Create remote workdir if needed. Then cd to it. + my $wd = $self->workdir(); + $pwd = qq{system("mkdir","-p","--","$wd"); chdir "$wd" ||}. + qq{print(STDERR "parallel: Cannot chdir to $wd\\n") && exit 255;}; + } + my ($csh_friendly,$envset,$bashfuncset) = env_as_eval(); + my $remote_command = $pwd.$envset.$bashfuncset. + '@ARGV="'.::perl_quote_scalar($command).'";'. + monitor_parent_sshd_script(); + $quoted_remote_command = "perl -e ". + ::shell_quote_scalar($remote_command); + my $dq_remote_command = + ::shell_quote_scalar($quoted_remote_command); + if(length $dq_remote_command > 999 + or + not $csh_friendly + or + $command =~ /\n/) { + # csh does not deal well with > 1000 chars in one word + # csh does not deal well with $ENV with \n + $quoted_remote_command = + "perl -e ". + ::shell_quote_scalar(::shell_quote_scalar(base64_zip_eval()))." ". + join" ",::shell_quote(::shell_quote(string_zip_base64($remote_command))); + } else { + $quoted_remote_command = $dq_remote_command; + } + + my $sshcmd = $sshlogin->sshcommand(); + my ($pre,$post,$cleanup)=("","",""); + # --transfer + $pre .= $self->sshtransfer(); + # --return + $post .= $self->sshreturn(); + # --cleanup + $post .= $self->sshcleanup(); + if($post) { + # We need to save the exit status of the job + $post = '_EXIT_status=$?; ' . $post . ' exit $_EXIT_status;'; + } + $self->{'sshlogin_wrap'} = + ($pre + . "$sshcmd $serverlogin -- exec " + . $quoted_remote_command + . ";" + . $post); + } + } + return $self->{'sshlogin_wrap'}; +} + +sub transfer { + # Files to transfer + # Non-quoted and with {...} substituted + # Returns: + # @transfer - File names of files to transfer + my $self = shift; + + my $transfersize = 0; + my @transfer = $self->{'commandline'}-> + replace_placeholders($self->{'commandline'}{'transfer_files'},0,0); + for(@transfer) { + # filesize + if(-e $_) { + $transfersize += (stat($_))[7]; + } + } + $self->add_transfersize($transfersize); + return @transfer; +} + +sub transfersize { + my $self = shift; + return $self->{'transfersize'}; +} + +sub add_transfersize { + my $self = shift; + my $transfersize = shift; + $self->{'transfersize'} += $transfersize; + $opt::sqlworker and + $Global::sql->update("SET Send = ? WHERE Seq = ".$self->seq(), + $self->{'transfersize'}); +} + +sub sshtransfer { + # Returns for each transfer file: + # rsync $file remote:$workdir + my $self = shift; + my @pre; + my $sshlogin = $self->sshlogin(); + my $workdir = $self->workdir(); + for my $file ($self->transfer()) { + push @pre, $sshlogin->rsync_transfer_cmd($file,$workdir).";"; + } + return join("",@pre); +} + +sub return { + # Files to return + # Non-quoted and with {...} substituted + # Returns: + # @non_quoted_filenames + my $self = shift; + return $self->{'commandline'}-> + replace_placeholders($self->{'commandline'}{'return_files'},0,0); +} + +sub returnsize { + # This is called after the job has finished + # Returns: + # $number_of_bytes transferred in return + my $self = shift; + for my $file ($self->return()) { + if(-e $file) { + $self->{'returnsize'} += (stat($file))[7]; + } + } + return $self->{'returnsize'}; +} + +sub add_returnsize { + my $self = shift; + my $returnsize = shift; + $self->{'returnsize'} += $returnsize; + $opt::sqlworker and + $Global::sql->update("SET Receive = ? WHERE Seq = ".$self->seq(), + $self->{'returnsize'}); +} + +sub sshreturn { + # Returns for each return-file: + # rsync remote:$workdir/$file . + my $self = shift; + my $sshlogin = $self->sshlogin(); + my $sshcmd = $sshlogin->sshcommand(); + my $serverlogin = $sshlogin->serverlogin(); + my $rsync_opts = $ENV{'PARALLEL_RSYNC_OPTS'}. + " -e".::shell_quote_scalar($sshcmd); + my $pre = ""; + for my $file ($self->return()) { + $file =~ s:^\./::g; # Remove ./ if any + my $relpath = ($file !~ m:^/:) || ($file =~ m:/\./:); # Is the path relative or /./? + my $cd = ""; + my $wd = ""; + if($relpath) { + # rsync -avR /foo/./bar/baz.c remote:/tmp/ + # == (on old systems) + # rsync -avR --rsync-path="cd /foo; rsync" remote:bar/baz.c /tmp/ + $wd = ::shell_quote_file($self->workdir()."/"); + } + # Only load File::Basename if actually needed + $Global::use{"File::Basename"} ||= eval "use File::Basename; 1;"; + # dir/./file means relative to dir, so remove dir on remote + $file =~ m:(.*)/\./:; + my $basedir = $1 ? ::shell_quote_file($1."/") : ""; + my $nobasedir = $file; + $nobasedir =~ s:.*/\./::; + $cd = ::shell_quote_file(::dirname($nobasedir)); + my $rsync_cd = '--rsync-path='.::shell_quote_scalar("cd $wd$cd; rsync"); + my $basename = + ::shell_quote_scalar(::shell_quote_file(::basename($file))); + # --return + # mkdir -p /home/tange/dir/subdir/; + # rsync (--protocol 30) -rlDzR + # --rsync-path="cd /home/tange/dir/subdir/; rsync" + # server:file.gz /home/tange/dir/subdir/ + $pre .= "mkdir -p $basedir$cd && ". $sshlogin->rsync(). + " $rsync_cd $rsync_opts $serverlogin:". + $basename . " ".$basedir.$cd.";"; + } + return $pre; +} + +sub sshcleanup { + # Return the sshcommand needed to remove the file + # Returns: + # ssh command needed to remove files from sshlogin + my $self = shift; + my $sshlogin = $self->sshlogin(); + my $sshcmd = $sshlogin->sshcommand(); + my $serverlogin = $sshlogin->serverlogin(); + my $workdir = $self->workdir(); + my $cleancmd = ""; + + for my $file ($self->remote_cleanup()) { + my @subworkdirs = parentdirs_of($file); + $cleancmd .= $sshlogin->cleanup_cmd($file,$workdir).";"; + } + if(defined $opt::workdir and $opt::workdir eq "...") { + $cleancmd .= "$sshcmd $serverlogin -- rm -rf " . ::shell_quote_scalar($workdir).';'; + } + return $cleancmd; +} + +sub remote_cleanup { + # Returns: + # Files to remove at cleanup + my $self = shift; + if($opt::cleanup) { + my @transfer = $self->transfer(); + my @return = $self->return(); + return (@transfer,@return); + } else { + return (); + } +} + +sub workdir { + # Returns: + # the workdir on a remote machine + my $self = shift; + if(not defined $self->{'workdir'}) { + my $workdir; + if(defined $opt::workdir) { + if($opt::workdir eq ".") { + # . means current dir + my $home = $ENV{'HOME'}; + eval 'use Cwd'; + my $cwd = cwd(); + $workdir = $cwd; + if($home) { + # If homedir exists: remove the homedir from + # workdir if cwd starts with homedir + # E.g. /home/foo/my/dir => my/dir + # E.g. /tmp/my/dir => /tmp/my/dir + my ($home_dev, $home_ino) = (stat($home))[0,1]; + my $parent = ""; + my @dir_parts = split(m:/:,$cwd); + my $part; + while(defined ($part = shift @dir_parts)) { + $part eq "" and next; + $parent .= "/".$part; + my ($parent_dev, $parent_ino) = (stat($parent))[0,1]; + if($parent_dev == $home_dev and $parent_ino == $home_ino) { + # dev and ino is the same: We found the homedir. + $workdir = join("/",@dir_parts); + last; + } + } + } + if($workdir eq "") { + $workdir = "."; + } + } elsif($opt::workdir eq "...") { + $workdir = ".parallel/tmp/" . ::hostname() . "-" . $$ + . "-" . $self->seq(); + } else { + $workdir = $self->{'commandline'}-> + replace_placeholders([$opt::workdir],0,0); + #$workdir = $opt::workdir; + # Rsync treats /./ special. We dont want that + $workdir =~ s:/\./:/:g; # Remove /./ + $workdir =~ s:(.)/+$:$1:; # Remove ending / if any + $workdir =~ s:^\./::g; # Remove starting ./ if any + } + } else { + $workdir = "."; + } + $self->{'workdir'} = ::shell_quote_scalar($workdir); + } + return $self->{'workdir'}; +} + +sub parentdirs_of { + # Return: + # all parentdirs except . of this dir or file - sorted desc by length + my $d = shift; + my @parents = (); + while($d =~ s:/[^/]+$::) { + if($d ne ".") { + push @parents, $d; + } + } + return @parents; +} + +sub start { + # Setup STDOUT and STDERR for a job and start it. + # Returns: + # job-object or undef if job not to run + + sub open3_setpgrp_internal { + # Run open3+setpgrp followed by the command + # Input: + # $stdin_fh = Filehandle to use as STDIN + # $stdout_fh = Filehandle to use as STDOUT + # $stderr_fh = Filehandle to use as STDERR + # $command = Command to run + # Returns: + # $pid = Process group of job started + my ($stdin_fh,$stdout_fh,$stderr_fh,$command) = @_; + my $pid; + local (*OUT,*ERR); + open OUT, '>&', $stdout_fh or ::die_bug("Can't dup STDOUT: $!"); + open ERR, '>&', $stderr_fh or ::die_bug("Can't dup STDERR: $!"); + # The eval is needed to catch exception from open3 + eval { + if(not $pid = ::open3($stdin_fh, ">&OUT", ">&ERR", "-")) { + # Each child gets its own process group to make it safe to killall + eval{ setpgrp(0,0) }; + eval{ setpriority(0,0,$opt::nice) }; + exec($Global::shell,"-c",$command) + || ::die_bug("open3-$stdin_fh $command"); + } + }; + return $pid; + } + + sub open3_setpgrp_external { + # Run open3 on $command wrapped with a perl script doing setpgrp + # Works on systems that do not support open3(,,,"-") + # Input: + # $stdin_fh = Filehandle to use as STDIN + # $stdout_fh = Filehandle to use as STDOUT + # $stderr_fh = Filehandle to use as STDERR + # $command = Command to run + # Returns: + # $pid = Process group of job started + my ($stdin_fh,$stdout_fh,$stderr_fh,$command) = @_; + local (*OUT,*ERR); + open OUT, '>&', $stdout_fh or ::die_bug("Can't dup STDOUT: $!"); + open ERR, '>&', $stderr_fh or ::die_bug("Can't dup STDERR: $!"); + + my $pid; + my @setpgrp_wrap = + ('perl','-e', + "eval\{setpgrp\}\;eval\{setpriority\(0,0,$opt::nice\)\}\;". + "exec '$Global::shell', '-c', \@ARGV"); + # The eval is needed to catch exception from open3 + eval { + $pid = ::open3($stdin_fh, ">&OUT", ">&ERR", @setpgrp_wrap, $command) + || ::die_bug("open3-$stdin_fh"); + 1; + }; + return $pid; + } + + sub open3_setpgrp { + # Select and run open3_setpgrp_internal/open3_setpgrp_external + no warnings 'redefine'; + my ($outfh,$name) = ::tmpfile(SUFFIX => ".tst"); + # Test to see if open3(x,x,x,"-") is fully supported + # Can an exported bash function be called via open3? + my $script = 'if($pid=::open3($i,$o,$e,"-")) { wait; } '. + 'else { exec("bash","-c","testfun && true"); }'; + my $bash = + ::shell_quote_scalar_default( + "testfun() { rm $name; }; export -f testfun; ". + "perl -MIPC::Open3 -e ". + ::shell_quote_scalar_default($script) + ); + # Redirect STDERR temporarily, + # so errors on MacOS X are ignored. + open my $saveerr, ">&STDERR"; + open STDERR, '>', "/dev/null"; + # Run the test + ::debug("init",qq{bash -c $bash 2>/dev/null}); + qx{ bash -c $bash 2>/dev/null }; + open STDERR, ">&", $saveerr; + + if(-e $name) { + # Does not support open3(x,x,x,"-") + # or does not have bash: + # Use (slow) external version + unlink($name); + *open3_setpgrp = \&open3_setpgrp_external; + ::debug("init","open3_setpgrp_external chosen\n"); + } else { + # Supports open3(x,x,x,"-") + # This is 0.5 ms faster to run + *open3_setpgrp = \&open3_setpgrp_internal; + ::debug("init","open3_setpgrp_internal chosen\n"); + } + # The sub is now redefined. Call it + return open3_setpgrp(@_); + } + + my $job = shift; + # Get the shell command to be executed (possibly with ssh infront). + my $command = $job->wrapped(); + my $pid; + + if($Global::interactive or $Global::stderr_verbose) { + $job->interactive_start(); + } + # Must be run after $job->interactive_start(): + # $job->interactive_start() may call $job->skip() + if($job->{'commandline'}{'skip'}) { + # $job->skip() was called + $command = "true"; + } + $job->openoutputfiles(); + $job->print_verbose_dryrun(); + # Call slot to store the slot value + $job->slot(); + my($stdout_fh,$stderr_fh) = ($job->fh(1,"w"),$job->fh(2,"w")); + if($opt::dryrun or $opt::sqlmaster) { $command = "true"; } + $ENV{'PARALLEL_SEQ'} = $job->seq(); + $ENV{'PARALLEL_PID'} = $$; + $ENV{'PARALLEL_TMP'} = ::tmpname("par"); + $job->add_rm($ENV{'PARALLEL_TMP'}); + ::debug("run", $Global::total_running, " processes . Starting (", + $job->seq(), "): $command\n"); + if($opt::pipe) { + my ($stdin_fh) = ::gensym(); + $pid = open3_setpgrp($stdin_fh,$stdout_fh,$stderr_fh,$command); + if($opt::roundrobin and not $opt::keeporder) { + # --keep-order will make sure the order will be reproducible + ::set_fh_non_blocking($stdin_fh); + } + $job->set_fh(0,"w",$stdin_fh); + if($opt::tee) { $job->set_virgin(0); } + } elsif ($opt::tty and -c "/dev/tty" and + open(my $devtty_fh, "<", "/dev/tty")) { + # Give /dev/tty to the command if no one else is using it + # The eval is needed to catch exception from open3 + local (*IN,*OUT,*ERR); + open OUT, '>&', $stdout_fh or ::die_bug("Can't dup STDOUT: $!"); + open ERR, '>&', $stderr_fh or ::die_bug("Can't dup STDERR: $!"); + *IN = $devtty_fh; + # The eval is needed to catch exception from open3 + my @wrap = ('perl','-e', + "eval\{setpriority\(0,0,$opt::nice\)\}\;". + "exec '$Global::shell', '-c', \@ARGV"); + eval { + $pid = ::open3("<&IN", ">&OUT", ">&ERR", @wrap, $command) + || ::die_bug("open3-/dev/tty"); + 1; + }; + close $devtty_fh; + $job->set_virgin(0); + } else { + $pid = open3_setpgrp(::gensym(),$stdout_fh,$stderr_fh,$command); + $job->set_virgin(0); + } + if($pid) { + # A job was started + $Global::total_running++; + $Global::total_started++; + $job->set_pid($pid); + $job->set_starttime(); + $Global::running{$job->pid()} = $job; + if($opt::timeout) { + $Global::timeoutq->insert($job); + } + $Global::newest_job = $job; + $Global::newest_starttime = ::now(); + return $job; + } else { + # No more processes + ::debug("run", "Cannot spawn more jobs.\n"); + return undef; + } +} + +sub interactive_start { + my $self = shift; + my $command = $self->wrapped(); + if($Global::interactive) { + ::status_no_nl("$command ?..."); + open(my $tty_fh, "<", "/dev/tty") || ::die_bug("interactive-tty"); + my $answer = <$tty_fh>; + close $tty_fh; + my $run_yes = ($answer =~ /^\s*y/i); + if (not $run_yes) { + $self->{'commandline'}->skip(); + } + } else { + print $Global::original_stderr "$command\n"; + } +} + +{ + my $tmuxsocket; + + sub tmux_wrap { + # Wrap command with tmux for session pPID + # Input: + # $actual_command = the actual command being run (incl ssh wrap) + my $self = shift; + my $actual_command = shift; + # Temporary file name. Used for fifo to communicate exit val + my $tmpfifo = ::tmpname("tmx"); + $self->add_rm($tmpfifo); + + if(length($tmpfifo) >=100) { + ::error("tmux does not support sockets with path > 100."); + ::wait_and_exit(255); + } + if($opt::tmuxpane) { + # Move the command into a pane in window 0 + $actual_command = $ENV{'PARALLEL_TMUX'}.' joinp -t :0 ; '. + $ENV{'PARALLEL_TMUX'}.' select-layout -t :0 tiled ; '. + $actual_command; + } + my $visual_command = $self->replaced(); + my $title = $visual_command; + if($visual_command =~ /\0/) { + ::error("Command line contains NUL. tmux is confused by NUL."); + ::wait_and_exit(255); + } + # ; causes problems + # ascii 194-245 annoys tmux + $title =~ tr/[\011-\016;\302-\365]/ /s; + $title = ::shell_quote_scalar($title); + + my $l_act = length($actual_command); + my $l_tit = length($title); + my $l_fifo = length($tmpfifo); + # The line to run contains a 118 chars extra code + the title 2x + my $l_tot = 2 * $l_tit + $l_act + $l_fifo; + + my $quoted_space75 = ::shell_quote_scalar(" ")x75; + while($l_tit < 1000 and + ( + (890 < $l_tot and $l_tot < 1350) + or + (9250 < $l_tot and $l_tot < 9800) + )) { + # tmux blocks for certain lengths: + # 900 < title + command < 1200 + # 9250 < title + command < 9800 + # but only if title < 1000, so expand the title with 75 spaces + # The measured lengths are: + # 996 < (title + whole command) < 1127 + # 9331 < (title + whole command) < 9636 + $title .= $quoted_space75; + $l_tit = length($title); + $l_tot = 2 * $l_tit + $l_act + $l_fifo; + } + + my $tmux; + $ENV{'PARALLEL_TMUX'} ||= "tmux"; + if(not $tmuxsocket) { + $tmuxsocket = ::tmpname("tms"); + if($opt::fg) { + if(not fork) { + # Run tmux in the foreground + # Wait for the socket to appear + while (not -e $tmuxsocket) { } + `$ENV{'PARALLEL_TMUX'} -S $tmuxsocket attach`; + exit; + } + } + ::status("See output with: $ENV{'PARALLEL_TMUX'} -S $tmuxsocket attach"); + } + $tmux = "sh -c '". + $ENV{'PARALLEL_TMUX'}." -S $tmuxsocket new-session -s p$$ -d \"sleep .2\" >/dev/null 2>&1';" . + $ENV{'PARALLEL_TMUX'}." -S $tmuxsocket new-window -t p$$ -n $title"; + + ::debug("tmux", "title len:", $l_tit, " act ", $l_act, " max ", + $Limits::Command::line_max_len, " tot ", + $l_tot, "\n"); + + return "mkfifo $tmpfifo && $tmux ". + # Run in tmux + ::shell_quote_scalar + ( + "(".$actual_command.');'. + # The triple print is needed - otherwise the testsuite fails + q[ perl -e 'while($t++<3){ print $ARGV[0],"\n" }' $?h/$status >> ].$tmpfifo."&". + "echo $title; echo \007Job finished at: `date`;sleep 10" + ). + # Run outside tmux + # Read a / separated line: 0h/2 for csh, 2/0 for bash. + # If csh the first will be 0h, so use the second as exit value. + # Otherwise just use the first value as exit value. + q{; exec perl -e '$/="/";$_=<>;$c=<>;unlink $ARGV; /(\d+)h/ and exit($1);exit$c' }.$tmpfifo; + } +} + +sub is_already_in_results { + # Do we already have results for this job? + # Returns: + # $job_already_run = bool whether there is output for this or not + my $job = $_[0]; + my $out = $job->{'commandline'}->results_out(); + ::debug("run", "Test ${out}stdout", -e "${out}stdout", "\n"); + return(-e $out."stdout" or -f $out); +} + +sub is_already_in_joblog { + my $job = shift; + return vec($Global::job_already_run,$job->seq(),1); +} + +sub set_job_in_joblog { + my $job = shift; + vec($Global::job_already_run,$job->seq(),1) = 1; +} + +sub should_be_retried { + # Should this job be retried? + # Returns + # 0 - do not retry + # 1 - job queued for retry + my $self = shift; + if (not $opt::retries) { + return 0; + } + if(not $self->exitstatus() and not $self->exitsignal()) { + # Completed with success. If there is a recorded failure: forget it + $self->reset_failed_here(); + return 0; + } else { + # The job failed. Should it be retried? + $self->add_failed_here(); + my $retries = $self->{'commandline'}-> + replace_placeholders([$opt::retries],0,0); + if($self->total_failed() == $retries) { + # This has been retried enough + return 0; + } else { + # This command should be retried + $self->set_endtime(undef); + $self->reset_exitstatus(); + $Global::JobQueue->unget($self); + ::debug("run", "Retry ", $self->seq(), "\n"); + return 1; + } + } +} + +{ + my (%print_later,$job_seq_to_print); + + sub print_earlier_jobs { + # Print jobs whose output is postponed due to --keep-order + # Returns: N/A + my $job = shift; + $print_later{$job->seq()} = $job; + $job_seq_to_print ||= 1; + my $returnsize = 0; + ::debug("run", "Looking for: $job_seq_to_print ", + "This: ", $job->seq(), "\n"); + for(;vec($Global::job_already_run,$job_seq_to_print,1); + $job_seq_to_print++) {} + while(my $j = $print_later{$job_seq_to_print}) { + $returnsize += $j->print(); + if($j->endtime()) { + # Job finished - look at the next + delete $print_later{$job_seq_to_print}; + $job_seq_to_print++; + next; + } else { + # Job not finished yet - look at it again next round + last; + } + } + return $returnsize; + } +} + +sub print { + # Print the output of the jobs + # Returns: N/A + + my $self = shift; + ::debug("print", ">>joboutput ", $self->replaced(), "\n"); + if($opt::dryrun) { + # Nothing was printed to this job: + # cleanup tmp files if --files was set + ::rm($self->fh(1,"name")); + } + if($opt::pipe and $self->virgin() and not $opt::tee) { + # Skip --joblog, --dryrun, --verbose + } else { + if($opt::ungroup) { + # NULL returnsize = 0 returnsize + $self->returnsize() or $self->add_returnsize(0); + if($Global::joblog and defined $self->{'exitstatus'}) { + # Add to joblog when finished + $self->print_joblog(); + # Printing is only relevant for grouped/--line-buffer output. + $opt::ungroup and return; + } + } + + # Check for disk full + ::exit_if_disk_full(); + } + + my $returnsize = $self->returnsize(); + for my $fdno (sort { $a <=> $b } keys %Global::fd) { + # Sort by file descriptor numerically: 1,2,3,..,9,10,11 + $fdno == 0 and next; + my $out_fd = $Global::fd{$fdno}; + my $in_fh = $self->fh($fdno,"r"); + if(not $in_fh) { + if(not $Job::file_descriptor_warning_printed{$fdno}++) { + # ::warning("File descriptor $fdno not defined\n"); + } + next; + } + ::debug("print", "File descriptor $fdno (", $self->fh($fdno,"name"), "):\n"); + if($opt::linebuffer) { + # Line buffered print out + $self->print_linebuffer($fdno,$in_fh,$out_fd); + } elsif($opt::files) { + $self->print_files($fdno,$in_fh,$out_fd); + } elsif($opt::tag or defined $opt::tagstring) { + $self->print_tag($fdno,$in_fh,$out_fd); + } else { + $self->print_normal($fdno,$in_fh,$out_fd); + } + flush $out_fd; + } + ::debug("print", "<{'exitstatus'} + and not ($self->virgin() and $opt::pipe)) { + if($Global::joblog and not $opt::sqlworker) { + # Add to joblog when finished + $self->print_joblog(); + } + if($opt::sqlworker and not $opt::results) { + $Global::sql->output($self); + } + if($Global::csvsep) { + # Add output to CSV when finished + $self->print_csv(); + } + } + return $returnsize - $self->returnsize(); +} + +{ + my $header_printed; + + sub print_csv { + my $self = shift; + my $cmd; + if($Global::verbose <= 1) { + $cmd = $self->replaced(); + } else { + # Verbose level > 1: Print the rsync and stuff + $cmd = "@command"; + } + my $record_ref = $self->{'commandline'}{'arg_list_flat_orig'}; + + if(not $header_printed) { + # Variable headers + # Normal => V1..Vn + # --header : => first value from column + my @V; + if($opt::header) { + my $i = 1; + @V = (map { $Global::input_source_header{$i++} } + @$record_ref[1..$#$record_ref]); + } else { + my $V = "V1"; + @V = (map { $V++ } @$record_ref[1..$#$record_ref]); + } + print $Global::csv_fh + (map { $$_ } + combine_ref("Seq", "Host", "Starttime", "JobRuntime", + "Send", "Receive", "Exitval", "Signal", "Command", + @V, + "Stdout","Stderr" + )),"\n"; + $header_printed++; + } + # Memory optimization: Overwrite with the joined output + $self->{'output'}{1} = join("", @{$self->{'output'}{1}}); + $self->{'output'}{2} = join("", @{$self->{'output'}{2}}); + print $Global::csv_fh + (map { $$_ } + combine_ref + ($self->seq(), + $self->sshlogin()->string(), + $self->starttime(), sprintf("%0.3f",$self->runtime()), + $self->transfersize(), $self->returnsize(), + $self->exitstatus(), $self->exitsignal(), \$cmd, + \@$record_ref[1..$#$record_ref], + \$self->{'output'}{1}, + \$self->{'output'}{2})),"\n"; + } +} + +sub combine_ref { + # Inspired by Text::CSV_PP::_combine (by Makamaka Hannyaharamitu) + my @part = @_; + my $sep = $Global::csvsep; + my $quot = '"'; + my @out = (); + + my $must_be_quoted; + for my $column (@part) { + # Memory optimization: Content transferred as reference + if(ref $column ne "SCALAR") { + # Convert all columns to scalar references + my $v = $column; + $column = \$v; + } + if(not defined $$column) { + $$column = ''; + next; + } + + $must_be_quoted = 0; + + if($$column =~ s/$quot/$quot$quot/go){ + # Replace " => "" + $must_be_quoted ||=1; + } + if($$column =~ /[\s\Q$sep\E]/o){ + # Put quotes around if the column contains , + $must_be_quoted ||=1; + } + + $Global::use{"bytes"} ||= eval "use bytes; 1;"; + if ($$column =~ /\0/) { + # Contains \0 => put quotes around + $must_be_quoted ||=1; + } + if($must_be_quoted){ + push @out, \$sep, \$quot, $column, \$quot; + } else { + push @out, \$sep, $column; + } + } + # Pop off a $sep + shift @out; + return @out; +} + +sub print_files { + # Print the name of the file containing stdout on stdout + # Uses: + # $opt::pipe + # $opt::group = Print when job is done + # $opt::linebuffer = Print ASAP + # Returns: N/A + my $self = shift; + my ($fdno,$in_fh,$out_fd) = @_; + + # If the job is dead: close printing fh. Needed for --compress + close $self->fh($fdno,"w"); + if($? and $opt::compress) { + ::error($opt::compress_program." failed."); + $self->set_exitstatus(255); + } + if($opt::compress) { + # Kill the decompressor which will not be needed + CORE::kill "TERM", $self->fh($fdno,"rpid"); + } + close $in_fh; + + if($opt::pipe and $self->virgin()) { + # Nothing was printed to this job: + # cleanup unused tmp files because --files was set + for my $fdno (1,2) { + ::rm($self->fh($fdno,"name")); + ::rm($self->fh($fdno,"unlink")); + } + } elsif($fdno == 1 and $self->fh($fdno,"name")) { + print $out_fd $self->tag(),$self->fh($fdno,"name"),"\n"; + if($Global::membuffer) { + push @{$self->{'output'}{$fdno}}, + $self->tag(), $self->fh($fdno,"name"); + } + $self->add_returnsize(-s $self->fh($fdno,"name")); + # Mark as printed - do not print again + $self->set_fh($fdno,"name",undef); + } +} + +sub print_linebuffer { + my $self = shift; + my ($fdno,$in_fh,$out_fd) = @_; + if(defined $self->{'exitstatus'}) { + # If the job is dead: close printing fh. Needed for --compress + close $self->fh($fdno,"w"); + if($? and $opt::compress) { + ::error($opt::compress_program." failed."); + $self->set_exitstatus(255); + } + if($opt::compress) { + # Blocked reading in final round + for my $fdno (1,2) { + ::set_fh_blocking($self->fh($fdno,'r')); + } + } + } + if(not $self->virgin()) { + if($opt::files or ($opt::results and not $Global::csvsep)) { + # Print filename + if($fdno == 1 and not $self->fh($fdno,"printed")) { + print $out_fd $self->tag(),$self->fh($fdno,"name"),"\n"; + if($Global::membuffer) { + push(@{$self->{'output'}{$fdno}}, $self->tag(), + $self->fh($fdno,"name")); + } + $self->set_fh($fdno,"printed",1); + } + # No need for reading $in_fh, as it is from "cat >/dev/null" + } else { + # Read halflines and print full lines + my $outputlength = 0; + my $halfline_ref = $self->{'halfline'}{$fdno}; + my ($buf,$i,$rv); + while($rv = sysread($in_fh, $buf, 131072)) { + $outputlength += $rv; + # Treat both \n and \r as line end + $i = (rindex($buf,"\n")+1) || (rindex($buf,"\r")+1); + if($i) { + # One or more complete lines were found + if($opt::tag or defined $opt::tagstring) { + # Replace ^ with $tag within the full line + my $tag = $self->tag(); + substr($buf,0,$i-1) =~ s/(?<=[\n\r])/$tag/gm; + # The length changed, so find the new ending pos + $i = (rindex($buf,"\n")+1) || (rindex($buf,"\r")+1); + unshift @$halfline_ref, $tag; + } + # Print the partial line (halfline) and the last half + print $out_fd @$halfline_ref, substr($buf,0,$i); + # Buffer in memory for SQL and CSV-output + if($Global::membuffer) { + push(@{$self->{'output'}{$fdno}}, + @$halfline_ref, substr($buf,0,$i)); + } + # Remove the printed part by keeping the unprinted part + @$halfline_ref = (substr($buf,$i)); + } else { + # No newline, so append to the halfline + push @$halfline_ref, $buf; + } + } + $self->add_returnsize($outputlength); + } + if(defined $self->{'exitstatus'}) { + if($opt::files or ($opt::results and not $Global::csvsep)) { + $self->add_returnsize(-s $self->fh($fdno,"name")); + } else { + # If the job is dead: print the remaining partial line + # read remaining + my $halfline_ref = $self->{'halfline'}{$fdno}; + if(grep /./, @$halfline_ref) { + $self->add_returnsize(length join("",@$halfline_ref)); + if($opt::tag or defined $opt::tagstring) { + # Prepend $tag the the remaining half line + unshift @$halfline_ref, $self->tag(); + } + # Print the partial line (halfline) + print $out_fd @{$self->{'halfline'}{$fdno}}; + # Buffer in memory for SQL and CSV-output + if($Global::membuffer) { + push(@{$self->{'output'}{$fdno}}, @$halfline_ref); + } + @$halfline_ref = (); + } + } + if($self->fh($fdno,"rpid") and + CORE::kill 0, $self->fh($fdno,"rpid")) { + # decompress still running + } else { + # decompress done: close fh + close $in_fh; + if($? and $opt::compress) { + ::error($opt::decompress_program." failed."); + $self->set_exitstatus(255); + } + } + } + } +} + +sub print_tag { + return print_normal(@_); +} + +sub free_ressources() { + my $self = shift; + if(not $opt::ungroup) { + for my $fdno (sort { $a <=> $b } keys %Global::fd) { + close $self->fh($fdno,"w"); + close $self->fh($fdno,"r"); + } + } +} + +sub print_normal { + my $self = shift; + my ($fdno,$in_fh,$out_fd) = @_; + my $buf; + close $self->fh($fdno,"w"); + if($? and $opt::compress) { + ::error($opt::compress_program." failed."); + $self->set_exitstatus(255); + } + if(not $self->virgin()) { + seek $in_fh, 0, 0; + # $in_fh is now ready for reading at position 0 + my $outputlength = 0; + my @output; + + if($opt::tag or $opt::tagstring) { + # Read line by line + local $/ = "\n"; + my $tag = $self->tag(); + while(<$in_fh>) { + print $out_fd $tag,$_; + $outputlength += length $_; + if($Global::membuffer) { + push @{$self->{'output'}{$fdno}}, $tag, $_; + } + } + } else { + while(sysread($in_fh,$buf,131072)) { + print $out_fd $buf; + $outputlength += length $buf; + if($Global::membuffer) { + push @{$self->{'output'}{$fdno}}, $buf; + } + } + } + if($fdno == 1) { + $self->add_returnsize($outputlength); + } + close $in_fh; + if($? and $opt::compress) { + ::error($opt::decompress_program." failed."); + $self->set_exitstatus(255); + } + } +} + +sub print_joblog { + my $self = shift; + my $cmd; + if($Global::verbose <= 1) { + $cmd = $self->replaced(); + } else { + # Verbose level > 1: Print the rsync and stuff + $cmd = "@command"; + } + # Newlines make it hard to parse the joblog + $cmd =~ s/\n/\0/g; + print $Global::joblog + join("\t", $self->seq(), $self->sshlogin()->string(), + $self->starttime(), sprintf("%10.3f",$self->runtime()), + $self->transfersize(), $self->returnsize(), + $self->exitstatus(), $self->exitsignal(), $cmd + ). "\n"; + flush $Global::joblog; + $self->set_job_in_joblog(); +} + +sub tag { + my $self = shift; + if(not defined $self->{'tag'}) { + if($opt::tag or defined $opt::tagstring) { + $self->{'tag'} = $self->{'commandline'}-> + replace_placeholders([$opt::tagstring],0,0)."\t"; + } else { + $self->{'tag'} = ""; + } + } + return $self->{'tag'}; +} + +sub hostgroups { + my $self = shift; + if(not defined $self->{'hostgroups'}) { + $self->{'hostgroups'} = + $self->{'commandline'}->{'arg_list'}[0][0]->{'hostgroups'}; + } + return @{$self->{'hostgroups'}}; +} + +sub exitstatus { + my $self = shift; + return $self->{'exitstatus'}; +} + +sub set_exitstatus { + my $self = shift; + my $exitstatus = shift; + if($exitstatus) { + # Overwrite status if non-zero + $self->{'exitstatus'} = $exitstatus; + } else { + # Set status but do not overwrite + # Status may have been set by --timeout + $self->{'exitstatus'} ||= $exitstatus; + } + $opt::sqlworker and + $Global::sql->update("SET Exitval = ? WHERE Seq = ".$self->seq(), + $exitstatus); +} + +sub reset_exitstatus { + my $self = shift; + undef $self->{'exitstatus'}; +} + +sub exitsignal { + my $self = shift; + return $self->{'exitsignal'}; +} + +sub set_exitsignal { + my $self = shift; + my $exitsignal = shift; + $self->{'exitsignal'} = $exitsignal; + $opt::sqlworker and + $Global::sql->update("SET _Signal = ? WHERE Seq = ".$self->seq(), + $exitsignal); +} + +{ + my $status_printed; + my $total_jobs; + + sub should_we_halt { + # Should we halt? Immediately? Gracefully? + # Returns: N/A + my $job = shift; + my $limit; + if($job->exitstatus() or $job->exitsignal()) { + # Job failed + $Global::exitstatus++; + $Global::total_failed++; + if($Global::halt_fail) { + ::status("$Global::progname: This job failed:", + $job->replaced()); + $limit = $Global::total_failed; + } + } elsif($Global::halt_success) { + ::status("$Global::progname: This job succeeded:", + $job->replaced()); + $limit = $Global::total_completed - $Global::total_failed; + } + if($Global::halt_done) { + ::status("$Global::progname: This job finished:", + $job->replaced()); + $limit = $Global::total_completed; + } + if(not defined $limit) { + return "" + } + # --halt # => 1..100 (number of jobs failed, 101 means > 100) + # --halt % => 1..100 (pct of jobs failed) + if($Global::halt_pct and not $Global::halt_count) { + $total_jobs ||= $Global::JobQueue->total_jobs(); + # From the pct compute the number of jobs that must fail/succeed + $Global::halt_count = $total_jobs * $Global::halt_pct; + } + if($limit >= $Global::halt_count) { + # At least N jobs have failed/succeded/completed + # or at least N% have failed/succeded/completed + # So we should prepare for exit + if($Global::halt_fail or $Global::halt_done) { + # Set exit status + if(not defined $Global::halt_exitstatus) { + if($Global::halt_pct) { + # --halt now,fail=X% or soon,fail=X% + # --halt now,done=X% or soon,done=X% + $Global::halt_exitstatus = + ::ceil($Global::total_failed / $total_jobs * 100); + } elsif($Global::halt_count) { + # --halt now,fail=X or soon,fail=X + # --halt now,done=X or soon,done=X + $Global::halt_exitstatus = + ::min($Global::total_failed,101); + } + if($Global::halt_count and $Global::halt_count == 1) { + # --halt now,fail=1 or soon,fail=1 + # --halt now,done=1 or soon,done=1 + # Emulate Bash's +128 if there is a signal + $Global::halt_exitstatus = + ($job->exitstatus() + or + $job->exitsignal() ? $job->exitsignal() + 128 : 0); + } + } + ::debug("halt","Pct: ",$Global::halt_pct, + " count: ",$Global::halt_count, + " status: ",$Global::halt_exitstatus,"\n"); + } elsif($Global::halt_success) { + $Global::halt_exitstatus = 0; + } + if($Global::halt_when eq "soon" + and + (scalar(keys %Global::running) > 0 + or + $Global::max_jobs_running == 1)) { + ::status + ("$Global::progname: Starting no more jobs. ". + "Waiting for ". (keys %Global::running). + " jobs to finish."); + $Global::start_no_new_jobs ||= 1; + } + return($Global::halt_when); + } + return ""; + } +} + + +package CommandLine; + +sub new { + my $class = shift; + my $seq = shift; + my $commandref = shift; + $commandref || die; + my $arg_queue = shift; + my $context_replace = shift; + my $max_number_of_args = shift; # for -N and normal (-n1) + my $transfer_files = shift; + my $return_files = shift; + my $replacecount_ref = shift; + my $len_ref = shift; + my %replacecount = %$replacecount_ref; + my %len = %$len_ref; + for (keys %$replacecount_ref) { + # Total length of this replacement string {} replaced with all args + $len{$_} = 0; + } + return bless { + 'command' => $commandref, + 'seq' => $seq, + 'len' => \%len, + 'arg_list' => [], + 'arg_list_flat' => [], + 'arg_list_flat_orig' => [undef], + 'arg_queue' => $arg_queue, + 'max_number_of_args' => $max_number_of_args, + 'replacecount' => \%replacecount, + 'context_replace' => $context_replace, + 'transfer_files' => $transfer_files, + 'return_files' => $return_files, + 'replaced' => undef, + }, ref($class) || $class; +} + +sub seq { + my $self = shift; + return $self->{'seq'}; +} + +sub set_seq { + my $self = shift; + $self->{'seq'} = shift; +} + +sub slot { + # Find the number of a free job slot and return it + # Uses: + # @Global::slots - list with free jobslots + # Returns: + # $jobslot = number of jobslot + my $self = shift; + if(not $self->{'slot'}) { + if(not @Global::slots) { + # $max_slot_number will typically be $Global::max_jobs_running + push @Global::slots, ++$Global::max_slot_number; + } + $self->{'slot'} = shift @Global::slots; + } + return $self->{'slot'}; +} + +{ + my $already_spread; + + sub populate { + # Add arguments from arg_queue until the number of arguments or + # max line length is reached + # Uses: + # $Global::minimal_command_line_length + # $opt::cat + # $opt::fifo + # $Global::JobQueue + # $opt::m + # $opt::X + # $Global::max_jobs_running + # Returns: N/A + my $self = shift; + my $next_arg; + my $max_len = $Global::minimal_command_line_length + || Limits::Command::max_length(); + + if($opt::cat or $opt::fifo) { + # Get the empty arg added by --pipepart (if any) + $Global::JobQueue->{'commandlinequeue'}->{'arg_queue'}->get(); + # $PARALLEL_TMP will point to a tempfile that will be used as {} + $Global::JobQueue->{'commandlinequeue'}->{'arg_queue'}-> + unget([Arg->new('$PARALLEL_TMP')]); + } + while (not $self->{'arg_queue'}->empty()) { + $next_arg = $self->{'arg_queue'}->get(); + if(not defined $next_arg) { + next; + } + $self->push($next_arg); + if($self->len() >= $max_len) { + # Command length is now > max_length + # If there are arguments: remove the last + # If there are no arguments: Error + # TODO stuff about -x opt_x + if($self->number_of_args() > 1) { + # There is something to work on + $self->{'arg_queue'}->unget($self->pop()); + last; + } else { + my $args = join(" ", map { $_->orig() } @$next_arg); + ::error("Command line too long (". + $self->len(). " >= ". + $max_len. + ") at input ". + $self->{'arg_queue'}->arg_number(). + ": ". + ((length $args > 50) ? + (substr($args,0,50))."..." : + $args)); + $self->{'arg_queue'}->unget($self->pop()); + ::wait_and_exit(255); + } + } + + if(defined $self->{'max_number_of_args'}) { + if($self->number_of_args() >= $self->{'max_number_of_args'}) { + last; + } + } + } + if(($opt::m or $opt::X) and not $already_spread + and $self->{'arg_queue'}->empty() and $Global::max_jobs_running) { + # -m or -X and EOF => Spread the arguments over all jobslots + # (unless they are already spread) + $already_spread ||= 1; + if($self->number_of_args() > 1) { + $self->{'max_number_of_args'} = + ::ceil($self->number_of_args()/$Global::max_jobs_running); + $Global::JobQueue->{'commandlinequeue'}->{'max_number_of_args'} = + $self->{'max_number_of_args'}; + $self->{'arg_queue'}->unget($self->pop_all()); + while($self->number_of_args() < $self->{'max_number_of_args'}) { + $self->push($self->{'arg_queue'}->get()); + } + } + $Global::JobQueue->flush_total_jobs(); + } + + if($opt::sqlmaster) { + # Insert the V1..Vn for this $seq in SQL table instead of generating one + $Global::sql->insert_records($self->seq(), $self->{'command'}, + $self->{'arg_list_flat_orig'}); + } + } +} + +sub push { + # Add one or more records as arguments + # Returns: N/A + my $self = shift; + my $record = shift; + push @{$self->{'arg_list_flat_orig'}}, map { $_->orig() } @$record; + push @{$self->{'arg_list_flat'}}, @$record; + push @{$self->{'arg_list'}}, $record; + # Make @arg available for {= =} + *Arg::arg = $self->{'arg_list_flat_orig'}; + + my $quote_arg = $Global::noquote ? 0 : not $Global::quoting; + for my $perlexpr (keys %{$self->{'replacecount'}}) { + if($perlexpr =~ /^(\d+) /) { + # Positional + defined($record->[$1-1]) or next; + $self->{'len'}{$perlexpr} += + length $record->[$1-1]->replace($perlexpr,$quote_arg,$self); + } else { + for my $arg (@$record) { + if(defined $arg) { + $self->{'len'}{$perlexpr} += + length $arg->replace($perlexpr,$quote_arg,$self); + } + } + } + } +} + +sub pop { + # Remove last argument + # Returns: + # the last record + my $self = shift; + my $record = pop @{$self->{'arg_list'}}; + # pop off arguments from @$record + splice @{$self->{'arg_list_flat_orig'}}, -($#$record+1), $#$record+1; + splice @{$self->{'arg_list_flat'}}, -($#$record+1), $#$record+1; + my $quote_arg = $Global::noquote ? 0 : not $Global::quoting; + for my $perlexpr (keys %{$self->{'replacecount'}}) { + if($perlexpr =~ /^(\d+) /) { + # Positional + defined($record->[$1-1]) or next; + $self->{'len'}{$perlexpr} -= + length $record->[$1-1]->replace($perlexpr,$quote_arg,$self); + } else { + for my $arg (@$record) { + if(defined $arg) { + $self->{'len'}{$perlexpr} -= + length $arg->replace($perlexpr,$quote_arg,$self); + } + } + } + } + return $record; +} + +sub pop_all { + # Remove all arguments and zeros the length of replacement perlexpr + # Returns: + # all records + my $self = shift; + my @popped = @{$self->{'arg_list'}}; + for my $perlexpr (keys %{$self->{'replacecount'}}) { + $self->{'len'}{$perlexpr} = 0; + } + $self->{'arg_list'} = []; + $self->{'arg_list_flat_orig'} = [undef]; + $self->{'arg_list_flat'} = []; + return @popped; +} + +sub number_of_args { + # The number of records + # Returns: + # number of records + my $self = shift; + # This is really the number of records + return $#{$self->{'arg_list'}}+1; +} + +sub number_of_recargs { + # The number of args in records + # Returns: + # number of args records + my $self = shift; + my $sum = 0; + my $nrec = scalar @{$self->{'arg_list'}}; + if($nrec) { + $sum = $nrec * (scalar @{$self->{'arg_list'}[0]}); + } + return $sum; +} + +sub args_as_string { + # Returns: + # all unmodified arguments joined with ' ' (similar to {}) + my $self = shift; + return (join " ", map { $_->orig() } + map { @$_ } @{$self->{'arg_list'}}); +} + +sub results_out { + sub max_file_name_length { + # Figure out the max length of a subdir + # TODO and the max total length + # Ext4 = 255,130816 + # Uses: + # $Global::max_file_length is set + # Returns: + # $Global::max_file_length + my $testdir = shift; + + my $upper = 8_000_000; + # Dir length of 8 chars is supported everywhere + my $len = 8; + my $dir = "x"x$len; + do { + rmdir($testdir."/".$dir); + $len *= 16; + $dir = "x"x$len; + } while ($len < $upper and mkdir $testdir."/".$dir); + # Then search for the actual max length between $len/16 and $len + my $min = $len/16; + my $max = $len; + while($max-$min > 5) { + # If we are within 5 chars of the exact value: + # it is not worth the extra time to find the exact value + my $test = int(($min+$max)/2); + $dir = "x"x$test; + if(mkdir $testdir."/".$dir) { + rmdir($testdir."/".$dir); + $min = $test; + } else { + $max = $test; + } + } + $Global::max_file_length = $min; + return $min; + } + + my $self = shift; + my $out = $self->replace_placeholders([$opt::results],0,0); + if($out eq $opt::results) { + # $opt::results simple string: Append args_as_dirname + my $args_as_dirname = $self->args_as_dirname(); + # Output in: prefix/name1/val1/name2/val2/stdout + $out = $opt::results."/".$args_as_dirname; + if(-d $out or eval{ File::Path::mkpath($out); }) { + # OK + } else { + # mkpath failed: Argument probably too long. + # Set $Global::max_file_length, which will keep the individual + # dir names shorter than the max length + max_file_name_length($opt::results); + $args_as_dirname = $self->args_as_dirname(); + # prefix/name1/val1/name2/val2/ + $out = $opt::results."/".$args_as_dirname; + File::Path::mkpath($out); + } + $out .="/"; + } else { + if($out =~ m:/$:) { + # / = dir + if(-d $out or eval{ File::Path::mkpath($out); }) { + # OK + } else { + ::error("Cannot make dir '$out'."); + ::wait_and_exit(255); + } + } else { + $out =~ m:(.*)/:; + File::Path::mkpath($1); + } + } + return $out; +} + +sub args_as_dirname { + # Returns: + # all unmodified arguments joined with '/' (similar to {}) + # \t \0 \\ and / are quoted as: \t \0 \\ \_ + # If $Global::max_file_length: Keep subdirs < $Global::max_file_length + my $self = shift; + my @res = (); + + for my $rec_ref (@{$self->{'arg_list'}}) { + # If headers are used, sort by them. + # Otherwise keep the order from the command line. + my @header_indexes_sorted = header_indexes_sorted($#$rec_ref+1); + for my $n (@header_indexes_sorted) { + CORE::push(@res, + $Global::input_source_header{$n}, + map { my $s = $_; + # \t \0 \\ and / are quoted as: \t \0 \\ \_ + $s =~ s/\\/\\\\/g; + $s =~ s/\t/\\t/g; + $s =~ s/\0/\\0/g; + $s =~ s:/:\\_:g; + if($Global::max_file_length) { + # Keep each subdir shorter than the longest + # allowed file name + $s = substr($s,0,$Global::max_file_length); + } + $s; } + $rec_ref->[$n-1]->orig()); + } + } + return join "/", @res; +} + +sub header_indexes_sorted { + # Sort headers first by number then by name. + # E.g.: 1a 1b 11a 11b + # Returns: + # Indexes of %Global::input_source_header sorted + my $max_col = shift; + + no warnings 'numeric'; + for my $col (1 .. $max_col) { + # Make sure the header is defined. If it is not: use column number + if(not defined $Global::input_source_header{$col}) { + $Global::input_source_header{$col} = $col; + } + } + my @header_indexes_sorted = sort { + # Sort headers numerically then asciibetically + $Global::input_source_header{$a} <=> $Global::input_source_header{$b} + or + $Global::input_source_header{$a} cmp $Global::input_source_header{$b} + } 1 .. $max_col; + return @header_indexes_sorted; +} + +sub len { + # Uses: + # $opt::shellquote + # The length of the command line with args substituted + my $self = shift; + my $len = 0; + # Add length of the original command with no args + # Length of command w/ all replacement args removed + $len += $self->{'len'}{'noncontext'} + @{$self->{'command'}} -1; + ::debug("length", "noncontext + command: $len\n"); + my $recargs = $self->number_of_recargs(); + if($self->{'context_replace'}) { + # Context is duplicated for each arg + $len += $recargs * $self->{'len'}{'context'}; + for my $replstring (keys %{$self->{'replacecount'}}) { + # If the replacements string is more than once: mulitply its length + $len += $self->{'len'}{$replstring} * + $self->{'replacecount'}{$replstring}; + ::debug("length", $replstring, " ", $self->{'len'}{$replstring}, "*", + $self->{'replacecount'}{$replstring}, "\n"); + } + # echo 11 22 33 44 55 66 77 88 99 1010 + # echo 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 + # 5 + ctxgrp*arg + ::debug("length", "Ctxgrp: ", $self->{'len'}{'contextgroups'}, + " Groups: ", $self->{'len'}{'noncontextgroups'}, "\n"); + # Add space between context groups + $len += ($recargs-1) * ($self->{'len'}{'contextgroups'}); + } else { + # Each replacement string may occur several times + # Add the length for each time + $len += 1*$self->{'len'}{'context'}; + ::debug("length", "context+noncontext + command: $len\n"); + for my $replstring (keys %{$self->{'replacecount'}}) { + # (space between regargs + length of replacement) + # * number this replacement is used + $len += ($recargs -1 + $self->{'len'}{$replstring}) * + $self->{'replacecount'}{$replstring}; + } + } + if($Global::quoting) { + # Pessimistic length if -q is set + # Worse than worst case: every char needs to be quoted with \ + $len *= 2; + } + if($opt::shellquote) { + # Pessimistic length if --shellquote is set + # Worse than worst case: every char needs to be quoted with \ twice + $len *= 4; + } + # If we are using --env, add the prefix for that, too. + $len += 0; + return $len; +} + +sub replaced { + # Uses: + # $Global::noquote + # $Global::quoting + # Returns: + # $replaced = command with place holders replaced and prepended + my $self = shift; + if(not defined $self->{'replaced'}) { + # Don't quote arguments if the input is the full command line + my $quote_arg = $Global::noquote ? 0 : not $Global::quoting; + # or if ($opt::cat or $opt::pipe) as they use $PARALLEL_TMP + $quote_arg = ($opt::cat || $opt::fifo) ? 0 : $quote_arg; + $self->{'replaced'} = $self-> + replace_placeholders($self->{'command'},$Global::quoting, + $quote_arg); + my $len = length $self->{'replaced'}; + if ($len != $self->len()) { + ::debug("length", $len, " != ", $self->len(), + " ", $self->{'replaced'}, "\n"); + } else { + ::debug("length", $len, " == ", $self->len(), + " ", $self->{'replaced'}, "\n"); + } + } + return $self->{'replaced'}; +} + +{ + my @target; + my $context_replace; + my $perl_expressions_as_re; + my @arg; + my %words_with_rpl_strings; + + sub fish_out_words_with_rpl_strings { + if(not $words_with_rpl_strings{$context_replace,@target}) { + my %word; + for (@target) { + my $tt = $_; + ::debug("replace", "Target: $tt"); + # Command line template: + # a{1}b{}c{}d + # becomes: + # a{=1 $_=$_ =}b{= $_=$_ =}c{= $_=$_ =}d + # becomes: + # a\257<1 $_=$_ \257>b\257< $_=$_ \257>c\257< $_=$_ \257>d + # Input A B C (no context) becomes: + # A B C => aAbA B CcA B Cd + # Input A B C (context -X) becomes: + # A B C => aAbAcAd aAbBcBd aAbCcCd + if($context_replace) { + while($tt =~ s/([^\s\257]* # before {= + (?: + \257< # {= + (?: (?! \257[<>]). )* # The perl expression + \257> # =} + [^\s\257]* # after =} + )+)/ /xs) { + # $1 = pre \257< perlexpr \257> post + $word{"$1"} ||= 1; + } + } else { + while($tt =~ s/( \257<(?: (?! \257[<>]). )*\257> )//xs) { + # $1 = \257< perlexpr \257> + $word{$1} ||= 1; + } + } + } + @{$words_with_rpl_strings{$context_replace,@target}} = keys %word + } + return @{$words_with_rpl_strings{$context_replace,@target}}; + } + + sub replace_placeholders { + # Replace foo{}bar with fooargbar + # Uses: + # @Arg::arg = arguments as strings to be use in {= =} + # Input: + # $targetref = command as shell words + # $quote = should everything be quoted? + # $quote_arg = should replaced arguments be quoted? + # Returns: + # @target with placeholders replaced + my $self = shift; + my $targetref = shift; + my $quote = shift; + my $quote_arg = shift; + my %replace; + # -X = context replace (fish_out_words_with_rpl_strings) + $context_replace = $self->{'context_replace'}; + @target = @$targetref; + ::debug("replace", "Replace @target\n"); + if(not @target) { + # @target is empty: Return empty array + return @target; + } + # Make it possible to use $arg[2] in {= =} + *Arg::arg = $self->{'arg_list_flat_orig'}; + # Flat list: + # $self->{'arg_list'} = [ [Arg11, Arg12], [Arg21, Arg22], [Arg31, Arg32] ] + # $self->{'arg_list_flat'} = [ Arg11, Arg12, Arg21, Arg22, Arg31, Arg32 ] + if(not @{$self->{'arg_list_flat'}}) { + @{$self->{'arg_list_flat'}} = Arg->new(""); + } + my $argref = $self->{'arg_list_flat'}; + # Number of arguments - used for positional arguments + my $n = $#$argref+1; + + # $self is actually a CommandLine-object, + # but it looks nice to be able to say {= $job->slot() =} + my $job = $self; + $perl_expressions_as_re = + join("|", map {s/^-?\d+//; "\Q$_\E"} keys %{$self->{'replacecount'}}); + # Fish out the words that have replacement strings in them + for my $word (fish_out_words_with_rpl_strings()) { + # word = AB \257< perlexpr \257> CD \257< perlexpr \257> EF + ::debug("replace", "Replacing in $word\n"); + my $normal_replace; + + # for each arg: + # replace replacement strings with replacement in the word value + # push to replace word value + for my $arg (@$argref) { + my $val = $word; + # Replace {= perl expr =} with value for each arg + $val =~ s{\257<(-?\d+)?($perl_expressions_as_re)\257>} + { + if($1) { + # Positional replace + # Find the relevant arg and replace it + ($argref->[$1 > 0 ? $1-1 : $n+$1] ? # If defined: replace + $argref->[$1 > 0 ? $1-1 : $n+$1]-> + replace($2,$quote_arg,$self) + : ""); + } else { + # Normal replace + $normal_replace ||= 1; + ($arg ? $arg->replace($2,$quote_arg,$self) : ""); + } + }gxe; + if($quote) { + CORE::push(@{$replace{::shell_quote_scalar($word)}}, + ::shell_quote_scalar($val)); + } else { + CORE::push(@{$replace{$word}}, $val); + } + # No normal replacements => only run once + $normal_replace or last; + } + } + *Arg::arg = []; + if($quote) { + @target = ::shell_quote(@target); + } + if(%replace) { + # Substitute the replace strings with the replacement values + # Must be sorted by length if a short word is a substring of a long word + my $regexp = join('|', map { my $s = $_; $s =~ s/(\W)/\\$1/g; $s } + sort { length $b <=> length $a } keys %replace); + for(@target) { + s/($regexp)/join(" ",@{$replace{$1}})/ge; + } + } + if($Global::escape_string_present) { + # Command line contains \257: Unescape it \257\256 => \257 + # If a replacement resulted in \257\256 + # it will have been escaped into \\\257\\\\256 + # and will not be matched below + for(@target) { + s/\257\256/\257/g; + } + if($opt::q) { + # \257 will be quoted too much + for(@target) { + s/\\\257\\\256/\\\257/g; + } + } + } + ::debug("replace", "Return @target\n"); + return wantarray ? @target : "@target"; + } +} + +sub skip { + # Skip this job + my $self = shift; + $self->{'skip'} = 1; +} + + +package CommandLineQueue; + +sub new { + my $class = shift; + my $commandref = shift; + my $read_from = shift; + my $context_replace = shift || 0; + my $max_number_of_args = shift; + my $transfer_files = shift; + my $return_files = shift; + my @unget = (); + my ($count,$posrpl,$perlexpr); + my ($replacecount_ref, $len_ref); + my @command = @$commandref; + my $dummy = ''; + my $seq = 1; + # Replace replacement strings with {= perl expr =} + # '{=' 'perlexpr' '=}' => '{= perlexpr =}' + @command = merge_rpl_parts(@command); + + # Protect matching inside {= perl expr =} + # by replacing {= and =} with \257< and \257> + # in options that can contain replacement strings: + # @command, --transferfile, --return, + # --tagstring, --workdir, --results + for(@command, @$transfer_files, @$return_files, + $opt::tagstring, $opt::workdir, $opt::results, $opt::retries) { + # Skip if undefined + $_ or next; + # Escape \257 => \257\256 + $Global::escape_string_present += s/\257/\257\256/g; + # Needs to match rightmost left parens (Perl defaults to leftmost) + # to deal with: {={==} and {={==}=} + # Replace {= -> \257< and =} -> \257> + # + # Complex way to do: + # s/{=(.*)=}/\257<$1\257>/g + # which would not work + s[\Q$Global::parensleft\E # Match {= + # Match . unless the next string is {= or =} + # needed to force matching the shortest {= =} + ((?:(?! \Q$Global::parensleft\E|\Q$Global::parensright\E ).)*?) + \Q$Global::parensright\E ] # Match =} + {\257<$1\257>}gx; + for my $rpl (sort { length $b <=> length $a } keys %Global::rpl) { + # Replace long --rpl's before short ones, as a short may be a + # substring of a long: + # --rpl '% s/a/b/' --rpl '%% s/b/a/' + # + # Replace the shorthand string (--rpl) + # with the {= perl expr =} + # + # Avoid searching for shorthand strings inside existing {= perl expr =} + # + # Replace $$1 in {= perl expr =} with groupings in shorthand string + # + # --rpl '{/(\.\S+)/(\.\S+)} s/$$1/$$2/g;' + # echo {/.tar/.gz} ::: UU.tar.gz + my ($prefix,$grp_regexp,$postfix) = + $rpl =~ /^( [^(]* ) # Prefix - e.g. {%% + ( \(.*\) )? # Group capture regexp - e.g (.*) + ( [^)]* )$ # Postfix - e.g } + /xs; + $grp_regexp ||= ''; + my $rplval = $Global::rpl{$rpl}; + while(s{( (?: ^|\257> ) (?: (?! \257[<>])(?:.|\n) )*? ) + # Don't replace after \257 unless \257> + \Q$prefix\E $grp_regexp \Q$postfix\E} + { + # The start remains the same + my $unchanged = $1; + # Dummy entry to start at 1. + my @grp = (1); + # $2 = first ()-group in $grp_regexp + # Put $2 in $grp[1], Put $3 in $grp[2] + # so first ()-group in $grp_regexp is $grp[1]; + for(my $i = 2; defined $grp[$#grp]; $i++) { + push @grp, eval '$'.$i; + } + my $rv = $rplval; + # replace $$1 with $_pAr_gRp1, $$2 with $_pAr_gRp2 + # in the code to be executed + $rv =~ s/\$\$ (\d+)/\$_pAr_gRp$1/gx; + # prepend with $_pAr_gRp1 = perlquote($1), + my $set_args = ""; + for(my $i = 1;defined $grp[$i]; $i++) { + $set_args .= "\$_pAr_gRp$i = \"" . + ::perl_quote_scalar($grp[$i]) . "\";"; + } + $unchanged . "\257<" . $set_args . $rv . "\257>" + }gxes) { + } + # Do the same for the positional replacement strings + $posrpl = $rpl; + if($posrpl =~ s/^\{//) { + # Only do this if the shorthand start with { + $prefix=~s/^\{//; + # Don't replace after \257 unless \257> + while(s{( (?: ^|\257> ) (?: (?! \257[<>]). )*? ) + \{(-?\d+) \s* \Q$prefix\E $grp_regexp \Q$postfix\E} + { + # The start remains the same + my $unchanged = $1; + my $position = $2; + # Dummy entry to start at 1. + my @grp = (1); + # $3 = first ()-group in $grp_regexp + # Put $3 in $grp[1], Put $4 in $grp[2] + # so first ()-group in $grp_regexp is $grp[1]; + for(my $i = 3; defined $grp[$#grp]; $i++) { + push @grp, eval '$'.$i; + } + my $rv = $rplval; + # replace $$1 with $_pAr_gRp1, $$2 with $_pAr_gRp2 + # in the code to be executed + $rv =~ s/\$\$ (\d+)/\$_pAr_gRp$1/gx; + # prepend with $_pAr_gRp1 = perlquote($1), + my $set_args = ""; + for(my $i = 1;defined $grp[$i]; $i++) { + $set_args .= "\$_pAr_gRp$i = \"" . + ::perl_quote_scalar($grp[$i]) . "\";"; + } + $unchanged . "\257<" . $position . $set_args . $rv . "\257>" + }gxes) { + } + } + } + } + + # Add {} if no replacement strings in @command + ($replacecount_ref, $len_ref, @command) = + replacement_counts_and_lengths($transfer_files,$return_files,@command); + if("@command" =~ /^[^ \t\n=]*\257append()) { + $seq = $Global::sql->max_seq() + 1; + } + + return bless { + 'unget' => \@unget, + 'command' => \@command, + 'replacecount' => $replacecount_ref, + 'arg_queue' => RecordQueue->new($read_from,$opt::colsep), + 'context_replace' => $context_replace, + 'len' => $len_ref, + 'max_number_of_args' => $max_number_of_args, + 'size' => undef, + 'transfer_files' => $transfer_files, + 'return_files' => $return_files, + 'seq' => $seq, + }, ref($class) || $class; +} + +sub merge_rpl_parts { + # '{=' 'perlexpr' '=}' => '{= perlexpr =}' + # Input: + # @in = the @command as given by the user + # Uses: + # $Global::parensleft + # $Global::parensright + # Returns: + # @command with parts merged to keep {= and =} as one + my @in = @_; + my @out; + my $l = quotemeta($Global::parensleft); + my $r = quotemeta($Global::parensright); + + while(@in) { + my $s = shift @in; + $_ = $s; + # Remove matching (right most) parens + while(s/(.*)$l.*?$r/$1/o) {} + if(/$l/o) { + # Missing right parens + while(@in) { + $s .= " ".shift @in; + $_ = $s; + while(s/(.*)$l.*?$r/$1/o) {} + if(not /$l/o) { + last; + } + } + } + push @out, $s; + } + return @out; +} + +sub replacement_counts_and_lengths { + # Count the number of different replacement strings. + # Find the lengths of context for context groups and non-context + # groups. + # If no {} found in @command: add it to @command + # + # Input: + # \@transfer_files = array of filenames to transfer + # \@return_files = array of filenames to return + # @command = command template + # Output: + # \%replacecount, \%len, @command + my $transfer_files = shift; + my $return_files = shift; + my @command = @_; + my (%replacecount,%len); + my $sum = 0; + while($sum == 0) { + # Count how many times each replacement string is used + my @cmd = @command; + my $contextlen = 0; + my $noncontextlen = 0; + my $contextgroups = 0; + for my $c (@cmd) { + while($c =~ s/ \257<( (?: (?! \257[<>]). )*?)\257> /\000/xs) { + # %replacecount = { "perlexpr" => number of times seen } + # e.g { "s/a/b/" => 2 } + $replacecount{$1}++; + $sum++; + } + # Measure the length of the context around the {= perl expr =} + # Use that {=...=} has been replaced with \000 above + # So there is no need to deal with \257< + while($c =~ s/ (\S*\000\S*) //xs) { + my $w = $1; + $w =~ tr/\000//d; # Remove all \000's + $contextlen += length($w); + $contextgroups++; + } + # All {= perl expr =} have been removed: The rest is non-context + $noncontextlen += length $c; + } + for(@$transfer_files, @$return_files, + $opt::tagstring, $opt::workdir, $opt::results, $opt::retries) { + # Options that can contain replacement strings + $_ or next; + my $t = $_; + while($t =~ s/ \257<( (?: (?! \257[<>]). )* )\257> //xs) { + # %replacecount = { "perlexpr" => number of times seen } + # e.g { "$_++" => 2 } + # But for tagstring we just need to mark it as seen + $replacecount{$1} ||= 1; + } + } + if($opt::bar) { + # If the command does not contain {} force it to be computed + # as it is being used by --bar + $replacecount{""} ||= 1; + } + + $len{'context'} = 0+$contextlen; + $len{'noncontext'} = $noncontextlen; + $len{'contextgroups'} = $contextgroups; + $len{'noncontextgroups'} = @cmd-$contextgroups; + ::debug("length", "@command Context: ", $len{'context'}, + " Non: ", $len{'noncontext'}, " Ctxgrp: ", $len{'contextgroups'}, + " NonCtxGrp: ", $len{'noncontextgroups'}, "\n"); + if($sum == 0) { + if(not @command) { + # Default command = {} + @command = ("\257<\257>"); + } elsif(($opt::pipe or $opt::pipepart) + and not $opt::fifo and not $opt::cat) { + # With --pipe / --pipe-part you can have no replacement + last; + } else { + # Append {} to the command if there are no {...}'s and no {=...=} + push @command, ("\257<\257>"); + } + } + } + return(\%replacecount,\%len,@command); +} + +sub get { + my $self = shift; + if(@{$self->{'unget'}}) { + my $cmd_line = shift @{$self->{'unget'}}; + return ($cmd_line); + } else { + if($opt::sqlworker) { + # Get the sequence number from the SQL table + $self->set_seq($SQL::next_seq); + # Get the command from the SQL table + $self->{'command'} = $SQL::command_ref; + my @command; + # Recompute replace counts based on the read command + ($self->{'replacecount'}, + $self->{'len'}, @command) = + replacement_counts_and_lengths($self->{'transfer_files'}, + $self->{'return_files'}, + @$SQL::command_ref); + if("@command" =~ /^[^ \t\n=]*\257new($self->seq(), + $self->{'command'}, + $self->{'arg_queue'}, + $self->{'context_replace'}, + $self->{'max_number_of_args'}, + $self->{'transfer_files'}, + $self->{'return_files'}, + $self->{'replacecount'}, + $self->{'len'}, + ); + $cmd_line->populate(); + ::debug("init","cmd_line->number_of_args ", + $cmd_line->number_of_args(), "\n"); + if(not $Global::no_more_input and ($opt::pipe or $opt::pipepart)) { + if($cmd_line->replaced() eq "") { + # Empty command - pipe requires a command + ::error("--pipe/--pipepart must have a command to pipe into ". + "(e.g. 'cat')."); + ::wait_and_exit(255); + } + } else { + if($cmd_line->number_of_args() == 0) { + # We did not get more args - maybe at EOF string? + return undef; + } elsif($cmd_line->replaced() eq "") { + # Empty command - get the next instead + return $self->get(); + } + } + $self->set_seq($self->seq()+1); + return $cmd_line; + } +} + +sub unget { + my $self = shift; + unshift @{$self->{'unget'}}, @_; +} + +sub empty { + my $self = shift; + my $empty = (not @{$self->{'unget'}}) && $self->{'arg_queue'}->empty(); + ::debug("run", "CommandLineQueue->empty $empty"); + return $empty; +} + +sub seq { + my $self = shift; + return $self->{'seq'}; +} + +sub set_seq { + my $self = shift; + $self->{'seq'} = shift; +} + +sub quote_args { + my $self = shift; + # If there is not command emulate |bash + return $self->{'command'}; +} + + +package Limits::Command; + +# Maximal command line length (for -m and -X) +sub max_length { + # Find the max_length of a command line and cache it + # Returns: + # number of chars on the longest command line allowed + if(not $Limits::Command::line_max_len) { + # Disk cache of max command line length + my $len_cache = $Global::cache_dir . "/tmp/sshlogin/" . ::hostname() . + "/linelen"; + my $cached_limit; + if(-e $len_cache) { + open(my $fh, "<", $len_cache) || ::die_bug("Cannot read $len_cache"); + $cached_limit = <$fh>; + close $fh; + } else { + $cached_limit = real_max_length(); + # If $HOME is write protected: Do not fail + my $dir = ::dirname($len_cache); + -d $dir or eval { File::Path::mkpath($dir); }; + open(my $fh, ">", $len_cache); + print $fh $cached_limit; + close $fh; + } + $Limits::Command::line_max_len = tmux_length($cached_limit); + if($opt::max_chars) { + if($opt::max_chars <= $cached_limit) { + $Limits::Command::line_max_len = $opt::max_chars; + } else { + ::warning("Value for -s option should be < $cached_limit."); + } + } + } + return int($Limits::Command::line_max_len); +} + +sub real_max_length { + # Find the max_length of a command line + # Returns: + # The maximal command line length + # Use an upper bound of 8 MB if the shell allows for infinite long lengths + my $upper = 8_000_000; + my $len = 8; + do { + if($len > $upper) { return $len }; + $len *= 16; + } while (is_acceptable_command_line_length($len)); + # Then search for the actual max length between 0 and upper bound + return binary_find_max_length(int($len/16),$len); +} + +sub binary_find_max_length { + # Given a lower and upper bound find the max_length of a command line + # Returns: + # number of chars on the longest command line allowed + my ($lower, $upper) = (@_); + if($lower == $upper or $lower == $upper-1) { return $lower; } + my $middle = int (($upper-$lower)/2 + $lower); + ::debug("init", "Maxlen: $lower,$upper,$middle : "); + if (is_acceptable_command_line_length($middle)) { + return binary_find_max_length($middle,$upper); + } else { + return binary_find_max_length($lower,$middle); + } +} + +sub is_acceptable_command_line_length { + # Test if a command line of this length can run + # in the current environment + # Returns: + # 0 if the command line length is too long + # 1 otherwise + my $len = shift; + if($ENV{PARALLEL_ENV}) { + $len += length $ENV{PARALLEL_ENV} + (-s $ENV{PARALLEL_ENV})*2; + } + ::qqx("true "."x"x$len); + ::debug("init", "$len=$? "); + return not $?; +} + +sub tmux_length { + # If $opt::tmux set, find the limit for tmux + # tmux 1.8 has a 2kB limit + # tmux 1.9 has a 16kB limit + # tmux 2.0 has a 16kB limit + # tmux 2.1 has a 16kB limit + # tmux 2.2 has a 16kB limit + # Input: + # $len = maximal command line length + # Returns: + # $tmux_len = maximal length runable in tmux + local $/ = "\n"; + my $len = shift; + if($opt::tmux) { + $ENV{'PARALLEL_TMUX'} ||= "tmux"; + if(not ::which($ENV{'PARALLEL_TMUX'})) { + ::error($ENV{'PARALLEL_TMUX'}." not found in \$PATH."); + ::wait_and_exit(255); + } + my @out; + for my $l (1, 2020, 16320, 100000, $len) { + my $tmpfile = ::tmpname("tms"); + my $tmuxcmd = $ENV{'PARALLEL_TMUX'}. + " -S $tmpfile new-session -d -n echo $l". + ("x"x$l). " && echo $l; rm -f $tmpfile"; + push @out, ::qqx($tmuxcmd); + ::rm($tmpfile); + } + ::debug("tmux","tmux-out ",@out); + chomp @out; + # The arguments is given 3 times on the command line + # and the wrapping is around 30 chars + # (29 for tmux1.9, 33 for tmux1.8) + my $tmux_len = ::max(@out); + $len = ::min($len,int($tmux_len/4-33)); + ::debug("tmux","tmux-length ",$len); + } + return $len; +} + + +package RecordQueue; + +sub new { + my $class = shift; + my $fhs = shift; + my $colsep = shift; + my @unget = (); + my $arg_sub_queue; + if($opt::sqlworker) { + # Open SQL table + $arg_sub_queue = SQLRecordQueue->new(); + } elsif(defined $colsep) { + # Open one file with colsep or CSV + $arg_sub_queue = RecordColQueue->new($fhs); + } else { + # Open one or more files if multiple -a + $arg_sub_queue = MultifileQueue->new($fhs); + } + return bless { + 'unget' => \@unget, + 'arg_number' => 0, + 'arg_sub_queue' => $arg_sub_queue, + }, ref($class) || $class; +} + +sub get { + # Returns: + # reference to array of Arg-objects + my $self = shift; + if(@{$self->{'unget'}}) { + $self->{'arg_number'}++; + # Flush cached computed replacements in Arg-objects + # To fix: parallel --bar echo {%} ::: a b c ::: d e f + my $ret = shift @{$self->{'unget'}}; + if($ret) { + map { $_->flush_cache() } @$ret; + } + return $ret; + } + my $ret = $self->{'arg_sub_queue'}->get(); + if($ret) { + if(grep { index($_->orig(),"\0") > 0 } @$ret) { + # Allow for \0 in position 0 because GNU Parallel uses "\0" + # to mean no-string + ::warning("a NUL character occurred in the input.", + "It cannot be passed through in the argument list.", + "Did you mean to use the --null option?"); + } + if(defined $Global::max_number_of_args + and $Global::max_number_of_args == 0) { + ::debug("run", "Read 1 but return 0 args\n"); + # \0 => nothing (not the empty string) + map { $_->set_orig("\0"); } @$ret; + } + # Flush cached computed replacements in Arg-objects + # To fix: parallel --bar echo {%} ::: a b c ::: d e f + map { $_->flush_cache() } @$ret; + } + return $ret; +} + +sub unget { + my $self = shift; + ::debug("run", "RecordQueue-unget '@_'\n"); + $self->{'arg_number'} -= @_; + unshift @{$self->{'unget'}}, @_; +} + +sub empty { + my $self = shift; + my $empty = not @{$self->{'unget'}}; + $empty &&= $self->{'arg_sub_queue'}->empty(); + ::debug("run", "RecordQueue->empty $empty"); + return $empty; +} + +sub arg_number { + my $self = shift; + return $self->{'arg_number'}; +} + + +package RecordColQueue; + +sub new { + my $class = shift; + my $fhs = shift; + my @unget = (); + my $arg_sub_queue = MultifileQueue->new($fhs); + return bless { + 'unget' => \@unget, + 'arg_sub_queue' => $arg_sub_queue, + }, ref($class) || $class; +} + +sub get { + # Returns: + # reference to array of Arg-objects + my $self = shift; + if(@{$self->{'unget'}}) { + return shift @{$self->{'unget'}}; + } + my $unget_ref = $self->{'unget'}; + if($self->{'arg_sub_queue'}->empty()) { + return undef; + } + my $in_record = $self->{'arg_sub_queue'}->get(); + if(defined $in_record) { + my @out_record = (); + for my $arg (@$in_record) { + ::debug("run", "RecordColQueue::arg $arg\n"); + my $line = $arg->orig(); + ::debug("run", "line='$line'\n"); + if($line ne "") { + if($opt::csv) { + # Parse CSV + chomp $line; + if(not $Global::csv->parse($line)) { + die "CSV has unexpected format: ^$line^"; + } + for($Global::csv->fields()) { + push @out_record, Arg->new($_); + } + } else { + for my $s (split /$opt::colsep/o, $line, -1) { + push @out_record, Arg->new($s); + } + } + } else { + push @out_record, Arg->new(""); + } + } + return \@out_record; + } else { + return undef; + } +} + +sub unget { + my $self = shift; + ::debug("run", "RecordColQueue-unget '@_'\n"); + unshift @{$self->{'unget'}}, @_; +} + +sub empty { + my $self = shift; + my $empty = (not @{$self->{'unget'}} and + $self->{'arg_sub_queue'}->empty()); + ::debug("run", "RecordColQueue->empty $empty"); + return $empty; +} + + +package SQLRecordQueue; + +sub new { + my $class = shift; + my @unget = (); + return bless { + 'unget' => \@unget, + }, ref($class) || $class; +} + +sub get { + # Returns: + # reference to array of Arg-objects + my $self = shift; + if(@{$self->{'unget'}}) { + return shift @{$self->{'unget'}}; + } + return $Global::sql->get_record(); +} + +sub unget { + my $self = shift; + ::debug("run", "SQLRecordQueue-unget '@_'\n"); + unshift @{$self->{'unget'}}, @_; +} + +sub empty { + my $self = shift; + if(@{$self->{'unget'}}) { return 0; } + my $get = $self->get(); + if(defined $get) { + $self->unget($get); + } + my $empty = not $get; + ::debug("run", "SQLRecordQueue->empty $empty"); + return $empty; +} + + +package MultifileQueue; + +@Global::unget_argv=(); + +sub new { + my $class = shift; + my $fhs = shift; + for my $fh (@$fhs) { + if(-t $fh and -t ($Global::status_fd || *STDERR)) { + ::warning("Input is read from the terminal. You either know what you", + "are doing (in which case: YOU ARE AWESOME!) or you forgot", + "::: or :::: or to pipe data into parallel. If so", + "consider going through the tutorial: man parallel_tutorial", + "Press CTRL-D to exit."); + } + } + return bless { + 'unget' => \@Global::unget_argv, + 'fhs' => $fhs, + 'arg_matrix' => undef, + }, ref($class) || $class; +} + +sub get { + my $self = shift; + if($opt::link) { + return $self->link_get(); + } else { + return $self->nest_get(); + } +} + +sub unget { + my $self = shift; + ::debug("run", "MultifileQueue-unget '@_'\n"); + unshift @{$self->{'unget'}}, @_; +} + +sub empty { + my $self = shift; + my $empty = (not @Global::unget_argv + and not @{$self->{'unget'}}); + for my $fh (@{$self->{'fhs'}}) { + $empty &&= eof($fh); + } + ::debug("run", "MultifileQueue->empty $empty "); + return $empty; +} + +sub link_get { + my $self = shift; + if(@{$self->{'unget'}}) { + return shift @{$self->{'unget'}}; + } + my @record = (); + my $prepend; + my $empty = 1; + for my $fh (@{$self->{'fhs'}}) { + my $arg = read_arg_from_fh($fh); + if(defined $arg) { + # Record $arg for recycling at end of file + push @{$self->{'arg_matrix'}{$fh}}, $arg; + push @record, $arg; + $empty = 0; + } else { + ::debug("run", "EOA "); + # End of file: Recycle arguments + push @{$self->{'arg_matrix'}{$fh}}, shift @{$self->{'arg_matrix'}{$fh}}; + # return last @{$args->{'args'}{$fh}}; + push @record, @{$self->{'arg_matrix'}{$fh}}[-1]; + } + } + if($empty) { + return undef; + } else { + return \@record; + } +} + +sub nest_get { + my $self = shift; + if(@{$self->{'unget'}}) { + return shift @{$self->{'unget'}}; + } + my @record = (); + my $prepend; + my $empty = 1; + my $no_of_inputsources = $#{$self->{'fhs'}} + 1; + if(not $self->{'arg_matrix'}) { + # Initialize @arg_matrix with one arg from each file + # read one line from each file + my @first_arg_set; + my $all_empty = 1; + for (my $fhno = 0; $fhno < $no_of_inputsources ; $fhno++) { + my $arg = read_arg_from_fh($self->{'fhs'}[$fhno]); + if(defined $arg) { + $all_empty = 0; + } + $self->{'arg_matrix'}[$fhno][0] = $arg || Arg->new(""); + push @first_arg_set, $self->{'arg_matrix'}[$fhno][0]; + } + if($all_empty) { + # All filehandles were at eof or eof-string + return undef; + } + return [@first_arg_set]; + } + + # Treat the case with one input source special. For multiple + # input sources we need to remember all previously read values to + # generate all combinations. But for one input source we can + # forget the value after first use. + if($no_of_inputsources == 1) { + my $arg = read_arg_from_fh($self->{'fhs'}[0]); + if(defined($arg)) { + return [$arg]; + } + return undef; + } + for (my $fhno = $no_of_inputsources - 1; $fhno >= 0; $fhno--) { + if(eof($self->{'fhs'}[$fhno])) { + next; + } else { + # read one + my $arg = read_arg_from_fh($self->{'fhs'}[$fhno]); + defined($arg) || next; # If we just read an EOF string: Treat this as EOF + my $len = $#{$self->{'arg_matrix'}[$fhno]} + 1; + $self->{'arg_matrix'}[$fhno][$len] = $arg; + # make all new combinations + my @combarg = (); + for (my $fhn = 0; $fhn < $no_of_inputsources; $fhn++) { + push(@combarg, [0, $#{$self->{'arg_matrix'}[$fhn]}], + # Is input source --link'ed to the next? + $opt::linkinputsource[$fhn+1]); + } + # Find only combinations with this new entry + $combarg[2*$fhno] = [$len,$len]; + # map combinations + # [ 1, 3, 7 ], [ 2, 4, 1 ] + # => + # [ m[0][1], m[1][3], m[2][7] ], [ m[0][2], m[1][4], m[2][1] ] + my @mapped; + for my $c (expand_combinations(@combarg)) { + my @a; + for my $n (0 .. $no_of_inputsources - 1 ) { + push @a, $self->{'arg_matrix'}[$n][$$c[$n]]; + } + push @mapped, \@a; + } + # append the mapped to the ungotten arguments + push @{$self->{'unget'}}, @mapped; + # get the first + if(@mapped) { + return shift @{$self->{'unget'}}; + } + } + } + # all are eof or at EOF string; return from the unget queue + return shift @{$self->{'unget'}}; +} + +sub read_arg_from_fh { + # Read one Arg from filehandle + # Returns: + # Arg-object with one read line + # undef if end of file + my $fh = shift; + my $prepend; + my $arg; + my $half_record = 0; + do {{ + # This makes 10% faster + if(not defined ($arg = <$fh>)) { + if(defined $prepend) { + return Arg->new($prepend); + } else { + return undef; + } + } + if($opt::csv) { + # We need to read a full CSV line. + if(($arg =~ y/"/"/) % 2 ) { + # The number of " on the line is uneven: + # If we were in a half_record => we have a full record now + # If we were ouside a half_record => we are in a half record now + $half_record = not $half_record; + } + if($half_record) { + # CSV half-record with quoting: + # col1,"col2 2""x3"" board newline <-this one + # cont",col3 + $prepend .= $arg; + redo; + } else { + # Now we have a full CSV record + } + } + # Remove delimiter + chomp $arg; + if($Global::end_of_file_string and + $arg eq $Global::end_of_file_string) { + # Ignore the rest of input file + close $fh; + ::debug("run", "EOF-string ($arg) met\n"); + if(defined $prepend) { + return Arg->new($prepend); + } else { + return undef; + } + } + if(defined $prepend) { + $arg = $prepend.$arg; # For line continuation + undef $prepend; + } + if($Global::ignore_empty) { + if($arg =~ /^\s*$/) { + redo; # Try the next line + } + } + if($Global::max_lines) { + if($arg =~ /\s$/) { + # Trailing space => continued on next line + $prepend = $arg; + redo; + } + } + }} while (1 == 0); # Dummy loop {{}} for redo + if(defined $arg) { + return Arg->new($arg); + } else { + ::die_bug("multiread arg undefined"); + } +} + +sub expand_combinations { + # Input: + # ([xmin,xmax], [ymin,ymax], ...) + # Returns: ([x,y,...],[x,y,...]) + # where xmin <= x <= xmax and ymin <= y <= ymax + my $minmax_ref = shift; + my $link = shift; # This is linked to the next input source + my $xmin = $$minmax_ref[0]; + my $xmax = $$minmax_ref[1]; + my @p; + if(@_) { + my @rest = expand_combinations(@_); + if($link) { + # Linked to next col with --link/:::+/::::+ + # TODO BUG does not wrap values if not same number of vals + push(@p, map { [$$_[0], @$_] } + grep { $xmin <= $$_[0] and $$_[0] <= $xmax } @rest); + } else { + # If there are more columns: Compute those recursively + for(my $x = $xmin; $x <= $xmax; $x++) { + push @p, map { [$x, @$_] } @rest; + } + } + } else { + for(my $x = $xmin; $x <= $xmax; $x++) { + push @p, [$x]; + } + } + return @p; +} + + +package Arg; + +sub new { + my $class = shift; + my $orig = shift; + my @hostgroups; + if($opt::hostgroups) { + if($orig =~ s:@(.+)::) { + # We found hostgroups on the arg + @hostgroups = split(/\+/, $1); + if(not grep { defined $Global::hostgroups{$_} } @hostgroups) { + # This hostgroup is not defined using -S + # Add it + ::warning("Adding hostgroups: @hostgroups"); + # Add sshlogin + for(grep { not defined $Global::hostgroups{$_} } @hostgroups) { + my $sshlogin = SSHLogin->new($_); + my $sshlogin_string = $sshlogin->string(); + $Global::host{$sshlogin_string} = $sshlogin; + $Global::hostgroups{$sshlogin_string} = 1; + } + } + } else { + # No hostgroup on the arg => any hostgroup + @hostgroups = (keys %Global::hostgroups); + } + } + return bless { + 'orig' => $orig, + 'hostgroups' => \@hostgroups, + }, ref($class) || $class; +} + +sub Q { + # Q alias for ::shell_quote_scalar + # Run shell_quote_scalar once to set the reference to the sub + my $a = ::shell_quote_scalar(@_); + *Q = \&::shell_quote_scalar; + return $a; +} + +sub pQ { + # pQ alias for ::perl_quote_scalar + *pQ = \&::perl_quote_scalar; + return pQ(@_); +} + +sub total_jobs { + return $Global::JobQueue->total_jobs(); +} + +{ + my %perleval; + my $job; + sub skip { + # shorthand for $job->skip(); + $job->skip(); + } + sub slot { + # shorthand for $job->slot(); + $job->slot(); + } + sub seq { + # shorthand for $job->seq(); + $job->seq(); + } + + sub replace { + # Calculates the corresponding value for a given perl expression + # Returns: + # The calculated string (quoted if asked for) + my $self = shift; + my $perlexpr = shift; # E.g. $_=$_ or s/.gz// + my $quote = (shift) ? 1 : 0; # should the string be quoted? + # This is actually a CommandLine-object, + # but it looks nice to be able to say {= $job->slot() =} + $job = shift; + $perlexpr =~ s/^(-?\d+)? *//; # Positional replace treated as normal replace + if(not $self->{'cache'}{$perlexpr}) { + # Only compute the value once + # Use $_ as the variable to change + local $_; + if($Global::trim eq "n") { + $_ = $self->{'orig'}; + } else { + # Trim the input + $_ = trim_of($self->{'orig'}); + } + ::debug("replace", "eval ", $perlexpr, " ", $_, "\n"); + if(not $perleval{$perlexpr}) { + # Make an anonymous function of the $perlexpr + # And more importantly: Compile it only once + if($perleval{$perlexpr} = + eval('sub { no strict; no warnings; my $job = shift; '. + $perlexpr.' }')) { + # All is good + } else { + # The eval failed. Maybe $perlexpr is invalid perl? + ::error("Cannot use $perlexpr: $@"); + ::wait_and_exit(255); + } + } + # Execute the function + $perleval{$perlexpr}->($job); + $self->{'cache'}{$perlexpr} = $_; + } + # Return the value quoted if needed + return($quote ? ::shell_quote_scalar($self->{'cache'}{$perlexpr}) + : $self->{'cache'}{$perlexpr}); + } +} + +sub flush_cache { + # Flush cache of computed values + my $self = shift; + $self->{'cache'} = undef; +} + +sub orig { + my $self = shift; + return $self->{'orig'}; +} + +sub set_orig { + my $self = shift; + $self->{'orig'} = shift; +} + +sub trim_of { + # Removes white space as specifed by --trim: + # n = nothing + # l = start + # r = end + # lr|rl = both + # Returns: + # string with white space removed as needed + my @strings = map { defined $_ ? $_ : "" } (@_); + my $arg; + if($Global::trim eq "n") { + # skip + } elsif($Global::trim eq "l") { + for my $arg (@strings) { $arg =~ s/^\s+//; } + } elsif($Global::trim eq "r") { + for my $arg (@strings) { $arg =~ s/\s+$//; } + } elsif($Global::trim eq "rl" or $Global::trim eq "lr") { + for my $arg (@strings) { $arg =~ s/^\s+//; $arg =~ s/\s+$//; } + } else { + ::error("--trim must be one of: r l rl lr."); + ::wait_and_exit(255); + } + return wantarray ? @strings : "@strings"; +} + + +package TimeoutQueue; + +sub new { + my $class = shift; + my $delta_time = shift; + my ($pct); + if($delta_time =~ /(\d+(\.\d+)?)%/) { + # Timeout in percent + $pct = $1/100; + $delta_time = 1_000_000; + } + $delta_time = ::multiply_time_units($delta_time); + + return bless { + 'queue' => [], + 'delta_time' => $delta_time, + 'pct' => $pct, + 'remedian_idx' => 0, + 'remedian_arr' => [], + 'remedian' => undef, + }, ref($class) || $class; +} + +sub delta_time { + my $self = shift; + return $self->{'delta_time'}; +} + +sub set_delta_time { + my $self = shift; + $self->{'delta_time'} = shift; +} + +sub remedian { + my $self = shift; + return $self->{'remedian'}; +} + +sub set_remedian { + # Set median of the last 999^3 (=997002999) values using Remedian + # + # Rousseeuw, Peter J., and Gilbert W. Bassett Jr. "The remedian: A + # robust averaging method for large data sets." Journal of the + # American Statistical Association 85.409 (1990): 97-104. + my $self = shift; + my $val = shift; + my $i = $self->{'remedian_idx'}++; + my $rref = $self->{'remedian_arr'}; + $rref->[0][$i%999] = $val; + $rref->[1][$i/999%999] = (sort @{$rref->[0]})[$#{$rref->[0]}/2]; + $rref->[2][$i/999/999%999] = (sort @{$rref->[1]})[$#{$rref->[1]}/2]; + $self->{'remedian'} = (sort @{$rref->[2]})[$#{$rref->[2]}/2]; +} + +sub update_median_runtime { + # Update delta_time based on runtime of finished job if timeout is + # a percentage + my $self = shift; + my $runtime = shift; + if($self->{'pct'}) { + $self->set_remedian($runtime); + $self->{'delta_time'} = $self->{'pct'} * $self->remedian(); + ::debug("run", "Timeout: $self->{'delta_time'}s "); + } +} + +sub process_timeouts { + # Check if there was a timeout + my $self = shift; + # $self->{'queue'} is sorted by start time + while (@{$self->{'queue'}}) { + my $job = $self->{'queue'}[0]; + if($job->endtime()) { + # Job already finished. No need to timeout the job + # This could be because of --keep-order + shift @{$self->{'queue'}}; + } elsif($job->is_timedout($self->{'delta_time'})) { + # Need to shift off queue before kill + # because kill calls usleep that calls process_timeouts + shift @{$self->{'queue'}}; + ::warning("This job was killed because it timed out:", + $job->replaced()); + $job->kill(); + } else { + # Because they are sorted by start time the rest are later + last; + } + } +} + +sub insert { + my $self = shift; + my $in = shift; + push @{$self->{'queue'}}, $in; +} + + +package SQL; + +sub new { + my $class = shift; + my $dburl = shift; + $Global::use{"DBI"} ||= eval "use DBI; 1;"; + # +DBURL = append to this DBURL + my $append = $dburl=~s/^\+//; + my %options = parse_dburl(get_alias($dburl)); + my %driveralias = ("sqlite" => "SQLite", + "sqlite3" => "SQLite", + "pg" => "Pg", + "postgres" => "Pg", + "postgresql" => "Pg", + "csv" => "CSV", + "oracle" => "Oracle", + "ora" => "Oracle"); + my $driver = $driveralias{$options{'databasedriver'}} || + $options{'databasedriver'}; + my $database = $options{'database'}; + my $host = $options{'host'} ? ";host=".$options{'host'} : ""; + my $port = $options{'port'} ? ";port=".$options{'port'} : ""; + my $dsn = "DBI:$driver:dbname=$database$host$port"; + my $userid = $options{'user'}; + my $password = $options{'password'};; + my $dbh = DBI->connect($dsn, $userid, $password, + { RaiseError => 1, AutoInactiveDestroy => 1 }) + or die $DBI::errstr; + $dbh->{'PrintWarn'} = $Global::debug || 0; + $dbh->{'PrintError'} = $Global::debug || 0; + $dbh->{'RaiseError'} = 1; + $dbh->{'ShowErrorStatement'} = 1; + $dbh->{'HandleError'} = sub {}; + + if(not defined $options{'table'}) { + ::error("The DBURL ($dburl) must contain a table."); + ::wait_and_exit(255); + } + + return bless { + 'dbh' => $dbh, + 'driver' => $driver, + 'max_number_of_args' => undef, + 'table' => $options{'table'}, + 'append' => $append, + }, ref($class) || $class; +} + +sub get_alias { + my $alias = shift; + $alias =~ s/^(sql:)*//; # Accept aliases prepended with sql: + if ($alias !~ /^:/) { + return $alias; + } + + # Find the alias + my $path; + if (-l $0) { + ($path) = readlink($0) =~ m|^(.*)/|; + } else { + ($path) = $0 =~ m|^(.*)/|; + } + + my @deprecated = ("$ENV{HOME}/.dburl.aliases", + "$path/dburl.aliases", "$path/dburl.aliases.dist"); + for (@deprecated) { + if(-r $_) { + ::warning("$_ is deprecated. ". + "Use .sql/aliases instead (read man sql)."); + } + } + my @urlalias=(); + check_permissions("$ENV{HOME}/.sql/aliases"); + check_permissions("$ENV{HOME}/.dburl.aliases"); + my @search = ("$ENV{HOME}/.sql/aliases", + "$ENV{HOME}/.dburl.aliases", "/etc/sql/aliases", + "$path/dburl.aliases", "$path/dburl.aliases.dist"); + for my $alias_file (@search) { + # local $/ needed if -0 set + local $/ = "\n"; + if(-r $alias_file) { + open(my $in, "<", $alias_file) || die; + push @urlalias, <$in>; + close $in; + } + } + my ($alias_part,$rest) = $alias=~/(:\w*)(.*)/; + # If we saw this before: we have an alias loop + if(grep {$_ eq $alias_part } @Private::seen_aliases) { + ::error("$alias_part is a cyclic alias."); + exit -1; + } else { + push @Private::seen_aliases, $alias_part; + } + + my $dburl; + for (@urlalias) { + /^$alias_part\s+(\S+.*)/ and do { $dburl = $1; last; } + } + + if($dburl) { + return get_alias($dburl.$rest); + } else { + ::error("$alias is not defined in @search"); + exit(-1); + } +} + +sub check_permissions { + my $file = shift; + + if(-e $file) { + if(not -o $file) { + my $username = (getpwuid($<))[0]; + ::warning("$file should be owned by $username: ". + "chown $username $file"); + } + my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, + $atime,$mtime,$ctime,$blksize,$blocks) = stat($file); + if($mode & 077) { + my $username = (getpwuid($<))[0]; + ::warning("$file should be only be readable by $username: ". + "chmod 600 $file"); + } + } +} + +sub parse_dburl { + my $url = shift; + my %options = (); + # sql:mysql://[[user][:password]@][host][:port]/[database[/table][?query]] + + if($url=~m!(?:sql:)? # You can prefix with 'sql:' + ((?:oracle|ora|mysql|pg|postgres|postgresql)(?:s|ssl|)| + (?:sqlite|sqlite2|sqlite3|csv)):// # Databasedriver ($1) + (?: + ([^:@/][^:@]*|) # Username ($2) + (?: + :([^@]*) # Password ($3) + )? + @)? + ([^:/]*)? # Hostname ($4) + (?: + : + ([^/]*)? # Port ($5) + )? + (?: + / + ([^/?]*)? # Database ($6) + )? + (?: + / + ([^?]*)? # Table ($7) + )? + (?: + \? + (.*)? # Query ($8) + )? + !ix) { + $options{databasedriver} = ::undef_if_empty(lc(uri_unescape($1))); + $options{user} = ::undef_if_empty(uri_unescape($2)); + $options{password} = ::undef_if_empty(uri_unescape($3)); + $options{host} = ::undef_if_empty(uri_unescape($4)); + $options{port} = ::undef_if_empty(uri_unescape($5)); + $options{database} = ::undef_if_empty(uri_unescape($6)); + $options{table} = ::undef_if_empty(uri_unescape($7)); + $options{query} = ::undef_if_empty(uri_unescape($8)); + ::debug("sql", "dburl $url\n"); + ::debug("sql", "databasedriver ", $options{databasedriver}, + " user ", $options{user}, + " password ", $options{password}, " host ", $options{host}, + " port ", $options{port}, " database ", $options{database}, + " table ", $options{table}, " query ", $options{query}, "\n"); + } else { + ::error("$url is not a valid DBURL"); + exit 255; + } + return %options; +} + +sub uri_unescape { + # Copied from http://cpansearch.perl.org/src/GAAS/URI-1.55/URI/Escape.pm + # to avoid depending on URI::Escape + # This section is (C) Gisle Aas. + # Note from RFC1630: "Sequences which start with a percent sign + # but are not followed by two hexadecimal characters are reserved + # for future extension" + my $str = shift; + if (@_ && wantarray) { + # not executed for the common case of a single argument + my @str = ($str, @_); # need to copy + foreach (@str) { + s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg; + } + return @str; + } + $str =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg if defined $str; + $str; +} + +sub run { + my $self = shift; + my $stmt = shift; + if($self->{'driver'} eq "CSV") { + $stmt=~ s/;$//; + if($stmt eq "BEGIN" or + $stmt eq "COMMIT") { + return undef; + } + } + my @retval; + my $dbh = $self->{'dbh'}; + ::debug("sql","$opt::sqlmaster$opt::sqlworker run $stmt\n"); + # Execute with the rest of the args - if any + my $rv; + my $sth; + my $lockretry = 0; + while($lockretry < 10) { + $sth = $dbh->prepare($stmt); + if($sth + and + eval { $rv = $sth->execute(@_) }) { + last; + } else { + if($@ =~ /no such table|Table .* doesn.t exist|relation ".*" does not exist/ + or + $DBI::errstr =~ /no such table|Table .* doesn.t exist|relation ".*" does not exist/) { + # This is fine: + # It is just a worker that reported back too late - + # another worker had finished the job first + # and the table was then dropped + $rv = $sth = 0; + last; + } + if($DBI::errstr =~ /locked/) { + ::debug("sql", "Lock retry: $lockretry"); + $lockretry++; + ::usleep(rand()*300); + } elsif(not $sth) { + # Try again + $lockretry++; + } else { + ::error($DBI::errstr); + ::wait_and_exit(255); + } + } + } + if($lockretry >= 10) { + ::die_bug("retry > 10: $DBI::errstr"); + } + if($rv < 0 and $DBI::errstr){ + ::error($DBI::errstr); + ::wait_and_exit(255); + } + return $sth; +} + +sub get { + my $self = shift; + my $sth = $self->run(@_); + my @retval; + # If $sth = 0 it means the table was dropped by another process + while($sth) { + my @row = $sth->fetchrow_array(); + @row or last; + push @retval, \@row; + } + return \@retval; +} + +sub table { + my $self = shift; + return $self->{'table'}; +} + +sub append { + my $self = shift; + return $self->{'append'}; +} + +sub update { + my $self = shift; + my $stmt = shift; + my $table = $self->table(); + $self->run("UPDATE $table $stmt",@_); +} + +sub output { + my $self = shift; + my $commandline = shift; + + $self->update("SET Stdout = ?, Stderr = ? WHERE Seq = ". + $commandline->seq(), + join("",@{$commandline->{'output'}{1}}), + join("",@{$commandline->{'output'}{2}})); +} + +sub max_number_of_args { + # Maximal number of args for this table + my $self = shift; + if(not $self->{'max_number_of_args'}) { + # Read the number of args from the SQL table + my $table = $self->table(); + my $v = $self->get("SELECT * FROM $table LIMIT 1;"); + my @reserved_columns = qw(Seq Host Starttime JobRuntime Send + Receive Exitval _Signal Command Stdout Stderr); + if(not $v) { + ::error("$table contains no records"); + } + # Count the number of Vx columns + $self->{'max_number_of_args'} = $#{$v->[0]} - $#reserved_columns; + } + return $self->{'max_number_of_args'}; +} + +sub set_max_number_of_args { + my $self = shift; + $self->{'max_number_of_args'} = shift; +} + +sub create_table { + my $self = shift; + if($self->append()) { return; } + my $max_number_of_args = shift; + $self->set_max_number_of_args($max_number_of_args); + my $table = $self->table(); + $self->run(qq(DROP TABLE IF EXISTS $table;)); + # BIGINT and TEXT are not supported in these databases or are too small + my %vartype = ( + "Oracle" => { "BIGINT" => "NUMBER(19,0)", + "TEXT" => "CLOB", }, + "mysql" => { "TEXT" => "LONGTEXT", }, + "CSV" => { "BIGINT" => "INT", + "FLOAT" => "REAL", }, + ); + my $BIGINT = $vartype{$self->{'driver'}}{"BIGINT"} || "BIGINT"; + my $TEXT = $vartype{$self->{'driver'}}{"TEXT"} || "TEXT"; + my $FLOAT = $vartype{$self->{'driver'}}{"FLOAT"} || "FLOAT(44)"; + my $v_def = join "", map { "V$_ $TEXT," } (1..$self->max_number_of_args()); + $self->run(qq{CREATE TABLE $table + (Seq $BIGINT, + Host $TEXT, + Starttime $FLOAT, + JobRuntime $FLOAT, + Send $BIGINT, + Receive $BIGINT, + Exitval $BIGINT, + _Signal $BIGINT, + Command $TEXT,}. + $v_def. + qq{Stdout $TEXT, + Stderr $TEXT);}); +} + +sub insert_records { + my $self = shift; + my $seq = shift; + my $command_ref = shift; + my $record_ref = shift; + my $table = $self->table(); + # For SQL encode the command with \257 space as split points + my $command = join("\257 ",@$command_ref); + my $v_cols = join ",", map { "V$_" } (1..$self->max_number_of_args()); + # Two extra value due to $seq, Exitval, Send + my $v_vals = join ",", map { "?" } (1..$self->max_number_of_args()+4); + $self->run("INSERT INTO $table (Seq,Command,Exitval,Send,$v_cols) ". + "VALUES ($v_vals);", $seq, $command, -1000, + 0, @$record_ref[1..$#$record_ref]); +} + +sub get_record { + my $self = shift; + my @retval; + my $table = $self->table(); + my $v_cols = join ",", map { "V$_" } (1..$self->max_number_of_args()); + my $v = $self->get("SELECT Seq, Command, $v_cols FROM $table ". + "WHERE Exitval = -1000 ORDER BY Seq LIMIT 1;"); + if($v->[0]) { + my $val_ref = $v->[0]; + # Mark record as taken + my $seq = shift @$val_ref; + # Save the sequence number to use when running the job + $SQL::next_seq = $seq; + $self->update("SET Exitval = ? WHERE Seq = ".$seq, -1220); + my @command = split /\257 /, shift @$val_ref; + $SQL::command_ref = \@command; + for (@$val_ref) { + push @retval, Arg->new($_); + } + } + if(@retval) { + return \@retval; + } else { + return undef; + } +} + +sub total_jobs { + my $self = shift; + my $table = $self->table(); + my $v = $self->get("SELECT count(*) FROM $table;"); + if($v->[0]) { + return $v->[0]->[0]; + } else { + ::die_bug("SQL::total_jobs"); + } +} + +sub max_seq { + my $self = shift; + my $table = $self->table(); + my $v = $self->get("SELECT max(Seq) FROM $table;"); + if($v->[0]) { + return $v->[0]->[0]; + } else { + ::die_bug("SQL::max_seq"); + } +} + +sub finished { + # Check if there are any jobs left in the SQL table that do not + # have a "real" exitval + my $self = shift; + if($opt::wait or $Global::start_sqlworker) { + my $table = $self->table(); + my $rv = $self->get("select Seq,Exitval from $table ". + "where Exitval <= -1000 limit 1"); + return not $rv->[0]; + } else { + return 1; + } +} + +package Semaphore; + +# This package provides a counting semaphore +# +# If a process dies without releasing the semaphore the next process +# that needs that entry will clean up dead semaphores +# +# The semaphores are stored in $PARALLEL_HOME/semaphores/id- Each +# file in $PARALLEL_HOME/semaphores/id-/ is the process ID of the +# process holding the entry. If the process dies, the entry can be +# taken by another process. + +sub new { + my $class = shift; + my $id = shift; + my $count = shift; + $id =~ s/([^-_a-z0-9])/unpack("H*",$1)/ige; # Convert non-word chars to hex + $id = "id-".$id; # To distinguish it from a process id + my $parallel_locks = $Global::cache_dir . "/semaphores"; + -d $parallel_locks or ::mkdir_or_die($parallel_locks); + my $lockdir = "$parallel_locks/$id"; + + my $lockfile = $lockdir.".lock"; + if($count < 1) { ::die_bug("semaphore-count: $count"); } + return bless { + 'lockfile' => $lockfile, + 'lockfh' => Symbol::gensym(), + 'lockdir' => $lockdir, + 'id' => $id, + 'idfile' => $lockdir."/".$id, + 'pid' => $$, + 'pidfile' => $lockdir."/".$$.'@'.::hostname(), + 'count' => $count + 1 # nlinks returns a link for the 'id-' as well + }, ref($class) || $class; +} + +sub remove_dead_locks { + my $self = shift; + my $lockdir = $self->{'lockdir'}; + + for my $d (glob "$lockdir/*") { + $d =~ m:$lockdir/([0-9]+)\@([-\._a-z0-9]+)$:o or next; + my ($pid, $host) = ($1, $2); + if($host eq ::hostname()) { + if(kill 0, $pid) { + ::debug("sem", "Alive: $pid $d\n"); + } else { + ::debug("sem", "Dead: $d\n"); + ::rm($d); + } + } + } +} + +sub acquire { + my $self = shift; + my $sleep = 1; # 1 ms + my $start_time = time; + while(1) { + # Can we get a lock? + $self->atomic_link_if_count_less_than() and last; + $self->remove_dead_locks(); + # Retry slower and slower up to 1 second + $sleep = ($sleep < 1000) ? ($sleep * 1.1) : ($sleep); + # Random to avoid every sleeping job waking up at the same time + ::usleep(rand()*$sleep); + if($opt::semaphoretimeout) { + if($opt::semaphoretimeout > 0 + and + time - $start_time > $opt::semaphoretimeout) { + # Timeout: Take the semaphore anyway + ::warning("Semaphore timed out. Stealing the semaphore."); + if(not -e $self->{'idfile'}) { + open (my $fh, ">", $self->{'idfile'}) or + ::die_bug("timeout_write_idfile: $self->{'idfile'}"); + close $fh; + } + link $self->{'idfile'}, $self->{'pidfile'}; + last; + } + if($opt::semaphoretimeout < 0 + and + time - $start_time > -$opt::semaphoretimeout) { + # Timeout: Exit + ::warning("Semaphore timed out. Exiting."); + exit(1); + last; + } + } + } + ::debug("sem", "acquired $self->{'pid'}\n"); +} + +sub release { + my $self = shift; + ::rm($self->{'pidfile'}); + if($self->nlinks() == 1) { + # This is the last link, so atomic cleanup + $self->lock(); + if($self->nlinks() == 1) { + ::rm($self->{'idfile'}); + rmdir $self->{'lockdir'}; + } + $self->unlock(); + } + ::debug("run", "released $self->{'pid'}\n"); +} + +sub pid_change { + # This should do what release()+acquire() would do without having + # to re-acquire the semaphore + my $self = shift; + + my $old_pidfile = $self->{'pidfile'}; + $self->{'pid'} = $$; + $self->{'pidfile'} = $self->{'lockdir'}."/".$$.'@'.::hostname(); + my $retval = link $self->{'idfile'}, $self->{'pidfile'}; + ::debug("sem","link($self->{'idfile'},$self->{'pidfile'})=$retval\n"); + ::rm($old_pidfile); +} + +sub atomic_link_if_count_less_than { + # Link $file1 to $file2 if nlinks to $file1 < $count + my $self = shift; + my $retval = 0; + $self->lock(); + my $nlinks = $self->nlinks(); + ::debug("sem","$nlinks<$self->{'count'} "); + if($nlinks < $self->{'count'}) { + -d $self->{'lockdir'} or ::mkdir_or_die($self->{'lockdir'}); + if(not -e $self->{'idfile'}) { + open (my $fh, ">", $self->{'idfile'}) or + ::die_bug("write_idfile: $self->{'idfile'}"); + close $fh; + } + $retval = link $self->{'idfile'}, $self->{'pidfile'}; + ::debug("sem","link($self->{'idfile'},$self->{'pidfile'})=$retval\n"); + } + $self->unlock(); + ::debug("sem", "atomic $retval"); + return $retval; +} + +sub nlinks { + my $self = shift; + if(-e $self->{'idfile'}) { + return (stat(_))[3]; + } else { + return 0; + } +} + +sub lock { + my $self = shift; + my $sleep = 100; # 100 ms + my $total_sleep = 0; + $Global::use{"Fcntl"} ||= eval "use Fcntl qw(:DEFAULT :flock); 1;"; + my $locked = 0; + while(not $locked) { + if(tell($self->{'lockfh'}) == -1) { + # File not open + open($self->{'lockfh'}, ">", $self->{'lockfile'}) + or ::debug("run", "Cannot open $self->{'lockfile'}"); + } + if($self->{'lockfh'}) { + # File is open + chmod 0666, $self->{'lockfile'}; # assuming you want it a+rw + if(flock($self->{'lockfh'}, LOCK_EX()|LOCK_NB())) { + # The file is locked: No need to retry + $locked = 1; + last; + } else { + if ($! =~ m/Function not implemented/) { + ::warning("flock: $!", + "Will wait for a random while."); + ::usleep(rand(5000)); + # File cannot be locked: No need to retry + $locked = 2; + last; + } + } + } + # Locking failed in first round + # Sleep and try again + $sleep = ($sleep < 1000) ? ($sleep * 1.1) : ($sleep); + # Random to avoid every sleeping job waking up at the same time + ::usleep(rand()*$sleep); + $total_sleep += $sleep; + if($opt::semaphoretimeout) { + if($opt::semaphoretimeout > 0 + and + $total_sleep/1000 > $opt::semaphoretimeout) { + # Timeout: Take the semaphore anyway + ::warning("Semaphore timed out. Taking the semaphore."); + $locked = 3; + last; + } + if($opt::semaphoretimeout < 0 + and + $total_sleep/1000 > -$opt::semaphoretimeout) { + # Timeout: Exit + ::warning("Semaphore timed out. Exiting."); + $locked = 4; + last; + } + } else { + if($total_sleep/1000 > 30) { + ::warning("Semaphore stuck for 30 seconds. ". + "Consider using --semaphoretimeout."); + } + } + } + ::debug("run", "locked $self->{'lockfile'}"); +} + +sub unlock { + my $self = shift; + ::rm($self->{'lockfile'}); + close $self->{'lockfh'}; + ::debug("run", "unlocked\n"); +} + +# Keep perl -w happy + +$opt::x = $Semaphore::timeout = $Semaphore::wait = +$Job::file_descriptor_warning_printed = $Global::envdef = @Arg::arg = +$Global::max_slot_number = $opt::session; diff --git a/scripts/test.sh b/scripts/test.sh new file mode 100755 index 000000000..b3675da7a --- /dev/null +++ b/scripts/test.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +./scripts/parallel --tag <` this repository +* `cd basic-app` +* `yarn install` + +## Running / Development + +* `ember serve` +* Visit your app at [http://localhost:4200](http://localhost:4200). +* Visit your tests at [http://localhost:4200/tests](http://localhost:4200/tests). + +### Code Generators + +Make use of the many generators for code, try `ember help generate` for more details + +### Running Tests + +* `ember test` +* `ember test --server` + +### Linting + +* `yarn lint` +* `yarn lint:fix` + +### Building + +* `ember build` (development) +* `ember build --environment production` (production) + +### Deploying + +Specify what it takes to deploy your app. + +## Further Reading / Useful Links + +* [ember.js](https://emberjs.com/) +* [ember-cli](https://ember-cli.com/) +* Development Browser Extensions + * [ember inspector for chrome](https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi) + * [ember inspector for firefox](https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/) diff --git a/test-projects/01-basic-app/app/app.js b/test-projects/01-basic-app/app/app.js new file mode 100644 index 000000000..e9953bf80 --- /dev/null +++ b/test-projects/01-basic-app/app/app.js @@ -0,0 +1,12 @@ +import Application from '@ember/application'; +import Resolver from 'ember-resolver'; +import loadInitializers from 'ember-load-initializers'; +import config from 'basic-app/config/environment'; + +export default class App extends Application { + modulePrefix = config.modulePrefix; + podModulePrefix = config.podModulePrefix; + Resolver = Resolver; +} + +loadInitializers(App, config.modulePrefix); diff --git a/tests/dummy/app/components/.gitkeep b/test-projects/01-basic-app/app/components/.gitkeep similarity index 100% rename from tests/dummy/app/components/.gitkeep rename to test-projects/01-basic-app/app/components/.gitkeep diff --git a/tests/dummy/app/controllers/.gitkeep b/test-projects/01-basic-app/app/controllers/.gitkeep similarity index 100% rename from tests/dummy/app/controllers/.gitkeep rename to test-projects/01-basic-app/app/controllers/.gitkeep diff --git a/test-projects/01-basic-app/app/controllers/application.js b/test-projects/01-basic-app/app/controllers/application.js new file mode 100644 index 000000000..09c6806ef --- /dev/null +++ b/test-projects/01-basic-app/app/controllers/application.js @@ -0,0 +1,23 @@ +/* global requirejs */ +import Controller from '@ember/controller'; +import ENV from 'basic-app/config/environment'; + +export default class extends Controller { + environment = ENV.environment; + + get mirageModules() { + return Object.keys(requirejs.entries).filter((key) => + key.match('^ember-cli-mirage') + ); + } + + get otherIncludedModules() { + return Object.keys(requirejs.entries).filter((key) => { + return ( + key.match('^pretender') || + key.match('^lodash') || + key.match('initializers/ember-cli-mirage') + ); + }); + } +} diff --git a/tests/dummy/app/helpers/.gitkeep b/test-projects/01-basic-app/app/helpers/.gitkeep similarity index 100% rename from tests/dummy/app/helpers/.gitkeep rename to test-projects/01-basic-app/app/helpers/.gitkeep diff --git a/test-projects/01-basic-app/app/index.html b/test-projects/01-basic-app/app/index.html new file mode 100644 index 000000000..326f147b5 --- /dev/null +++ b/test-projects/01-basic-app/app/index.html @@ -0,0 +1,25 @@ + + + + + + BasicApp + + + + {{content-for "head"}} + + + + + {{content-for "head-footer"}} + + + {{content-for "body"}} + + + + + {{content-for "body-footer"}} + + diff --git a/tests/dummy/app/templates/components/.gitkeep b/test-projects/01-basic-app/app/models/.gitkeep similarity index 100% rename from tests/dummy/app/templates/components/.gitkeep rename to test-projects/01-basic-app/app/models/.gitkeep diff --git a/test-projects/01-basic-app/app/models/book.js b/test-projects/01-basic-app/app/models/book.js new file mode 100644 index 000000000..6c8e5117f --- /dev/null +++ b/test-projects/01-basic-app/app/models/book.js @@ -0,0 +1,5 @@ +import Model, { belongsTo } from '@ember-data/model'; + +export default class Book extends Model { + @belongsTo() user; +} diff --git a/test-projects/01-basic-app/app/models/tag.js b/test-projects/01-basic-app/app/models/tag.js new file mode 100644 index 000000000..a765f525b --- /dev/null +++ b/test-projects/01-basic-app/app/models/tag.js @@ -0,0 +1,3 @@ +import Model from '@ember-data/model'; + +export default class Tag extends Model {} diff --git a/test-projects/01-basic-app/app/models/things/watch.js b/test-projects/01-basic-app/app/models/things/watch.js new file mode 100644 index 000000000..1999b84c1 --- /dev/null +++ b/test-projects/01-basic-app/app/models/things/watch.js @@ -0,0 +1,3 @@ +import Model from '@ember-data/model'; + +export default class ThingsWatch extends Model {} diff --git a/test-projects/01-basic-app/app/models/user.js b/test-projects/01-basic-app/app/models/user.js new file mode 100644 index 000000000..fc879bf3a --- /dev/null +++ b/test-projects/01-basic-app/app/models/user.js @@ -0,0 +1,9 @@ +import Model, { attr, hasMany } from '@ember-data/model'; + +export default class User extends Model { + @attr('string') name; + @attr('number') age; + @attr('string') email; + + @hasMany() books; +} diff --git a/test-projects/01-basic-app/app/pods/application/template.hbs b/test-projects/01-basic-app/app/pods/application/template.hbs new file mode 100644 index 000000000..b6a8aa972 --- /dev/null +++ b/test-projects/01-basic-app/app/pods/application/template.hbs @@ -0,0 +1,3 @@ +

Mirage - test app

+ +{{outlet}} diff --git a/test-projects/01-basic-app/app/pods/crud-demo-error/template.hbs b/test-projects/01-basic-app/app/pods/crud-demo-error/template.hbs new file mode 100644 index 000000000..d0f5e0a94 --- /dev/null +++ b/test-projects/01-basic-app/app/pods/crud-demo-error/template.hbs @@ -0,0 +1,5 @@ +

WHOOPS

+ +

+ {{this.model.errors.firstObject}} +

diff --git a/test-projects/01-basic-app/app/pods/crud-demo/controller.js b/test-projects/01-basic-app/app/pods/crud-demo/controller.js new file mode 100644 index 000000000..4acd8334a --- /dev/null +++ b/test-projects/01-basic-app/app/pods/crud-demo/controller.js @@ -0,0 +1,35 @@ +import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; +import { tracked } from '@glimmer/tracking'; + +export default class extends Controller { + @service store; + + @tracked newName; + + @action createUser(event) { + event.preventDefault(); + + let name = this.newName; + + this.store + .createRecord('user', { name }) + .save() + .then(() => { + this.newName = ''; + }); + } + + @action updateUser(user, event) { + event.preventDefault(); + + user.save(); + } + + @action deleteUser(user, event) { + event.preventDefault(); + + user.destroyRecord(); + } +} diff --git a/test-projects/01-basic-app/app/pods/crud-demo/route.js b/test-projects/01-basic-app/app/pods/crud-demo/route.js new file mode 100644 index 000000000..e4f198d40 --- /dev/null +++ b/test-projects/01-basic-app/app/pods/crud-demo/route.js @@ -0,0 +1,10 @@ +import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; + +export default class extends Route { + @service store; + + model() { + return this.store.findAll('user'); + } +} diff --git a/test-projects/01-basic-app/app/pods/crud-demo/template.hbs b/test-projects/01-basic-app/app/pods/crud-demo/template.hbs new file mode 100644 index 000000000..d074dca68 --- /dev/null +++ b/test-projects/01-basic-app/app/pods/crud-demo/template.hbs @@ -0,0 +1,48 @@ +{{#if this.error}} + +

+ There was an error: {{this.error}} +

+ +{{else}} + + {{#each this.model as |user|}} +
+
+ + + + + {{#if user.isSaving}} + Saving... + {{else if user.id}} + Saved + {{/if}} + +
+
+ {{/each}} + +{{/if}} + +
+ +
+
+
+ +
+ +
+ +
+
+
diff --git a/test-projects/01-basic-app/app/pods/module-count/controller.js b/test-projects/01-basic-app/app/pods/module-count/controller.js new file mode 100644 index 000000000..09c6806ef --- /dev/null +++ b/test-projects/01-basic-app/app/pods/module-count/controller.js @@ -0,0 +1,23 @@ +/* global requirejs */ +import Controller from '@ember/controller'; +import ENV from 'basic-app/config/environment'; + +export default class extends Controller { + environment = ENV.environment; + + get mirageModules() { + return Object.keys(requirejs.entries).filter((key) => + key.match('^ember-cli-mirage') + ); + } + + get otherIncludedModules() { + return Object.keys(requirejs.entries).filter((key) => { + return ( + key.match('^pretender') || + key.match('^lodash') || + key.match('initializers/ember-cli-mirage') + ); + }); + } +} diff --git a/test-projects/01-basic-app/app/pods/module-count/template.hbs b/test-projects/01-basic-app/app/pods/module-count/template.hbs new file mode 100644 index 000000000..ae84b795e --- /dev/null +++ b/test-projects/01-basic-app/app/pods/module-count/template.hbs @@ -0,0 +1,20 @@ +

+ Environment: + + {{this.environment}} + +

+ +

+ Mirage modules in project: + + {{this.mirageModules.length}} + +

+ +

+ Other modules in project: + + {{this.otherIncludedModules.length}} + +

diff --git a/test-projects/01-basic-app/app/router.js b/test-projects/01-basic-app/app/router.js new file mode 100644 index 000000000..797295e13 --- /dev/null +++ b/test-projects/01-basic-app/app/router.js @@ -0,0 +1,12 @@ +import EmberRouter from '@ember/routing/router'; +import config from 'basic-app/config/environment'; + +export default class Router extends EmberRouter { + location = config.locationType; + rootURL = config.rootURL; +} + +Router.map(function () { + this.route('module-count'); + this.route('crud-demo'); +}); diff --git a/test-projects/01-basic-app/app/routes/.gitkeep b/test-projects/01-basic-app/app/routes/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test-projects/01-basic-app/app/serializers/application.js b/test-projects/01-basic-app/app/serializers/application.js new file mode 100644 index 000000000..33d31a206 --- /dev/null +++ b/test-projects/01-basic-app/app/serializers/application.js @@ -0,0 +1,3 @@ +import JSONAPISerializer from '@ember-data/serializer/json-api'; + +export default class extends JSONAPISerializer {} diff --git a/test-projects/01-basic-app/app/styles/app.css b/test-projects/01-basic-app/app/styles/app.css new file mode 100644 index 000000000..e69de29bb diff --git a/test-projects/01-basic-app/app/templates/application.hbs b/test-projects/01-basic-app/app/templates/application.hbs new file mode 100644 index 000000000..aa16a3ead --- /dev/null +++ b/test-projects/01-basic-app/app/templates/application.hbs @@ -0,0 +1,22 @@ +

Welcome to Ember

+ +

+ Environment: + + {{this.environment}} + +

+ +

+ Mirage modules in project: + + {{this.mirageModules.length}} + +

+ +

+ Other modules in project: + + {{this.otherIncludedModules.length}} + +

diff --git a/test-projects/01-basic-app/config/ember-cli-update.json b/test-projects/01-basic-app/config/ember-cli-update.json new file mode 100644 index 000000000..4d3d25b5a --- /dev/null +++ b/test-projects/01-basic-app/config/ember-cli-update.json @@ -0,0 +1,21 @@ +{ + "schemaVersion": "1.0.0", + "packages": [ + { + "name": "ember-cli", + "version": "3.28.4", + "blueprints": [ + { + "name": "app", + "outputRepo": "https://github.com/ember-cli/ember-new-output", + "codemodsSource": "ember-app-codemods-manifest@1", + "isBaseBlueprint": true, + "options": [ + "--yarn", + "--no-welcome" + ] + } + ] + } + ] +} diff --git a/test-projects/01-basic-app/config/environment.js b/test-projects/01-basic-app/config/environment.js new file mode 100644 index 000000000..1af33a9ba --- /dev/null +++ b/test-projects/01-basic-app/config/environment.js @@ -0,0 +1,58 @@ +'use strict'; + +module.exports = function (environment) { + let ENV = { + modulePrefix: 'basic-app', + podModulePrefix: 'basic-app/pods', + environment, + rootURL: '/', + locationType: 'auto', + EmberENV: { + FEATURES: { + // Here you can enable experimental features on an ember canary build + // e.g. EMBER_NATIVE_DECORATOR_SUPPORT: true + }, + EXTEND_PROTOTYPES: { + // Prevent Ember Data from overriding Date.parse. + Date: false, + }, + }, + + APP: { + // Here you can pass flags/options to your application instance + // when it is created + }, + }; + + if (process.env.MIRAGE_ENABLED) { + ENV['ember-cli-mirage'] = { + enabled: true, + }; + } + + if (environment === 'development') { + // ENV.APP.LOG_RESOLVER = true; + // ENV.APP.LOG_ACTIVE_GENERATION = true; + // ENV.APP.LOG_TRANSITIONS = true; + // ENV.APP.LOG_TRANSITIONS_INTERNAL = true; + // ENV.APP.LOG_VIEW_LOOKUPS = true; + } + + if (environment === 'test') { + // Testem prefers this... + ENV.locationType = 'none'; + + // keep test console output quieter + ENV.APP.LOG_ACTIVE_GENERATION = false; + ENV.APP.LOG_VIEW_LOOKUPS = false; + + ENV.APP.rootElement = '#ember-testing'; + ENV.APP.autoboot = false; + } + + if (environment === 'production') { + // here you can enable a production-specific feature + } + + return ENV; +}; diff --git a/test-projects/01-basic-app/config/optional-features.json b/test-projects/01-basic-app/config/optional-features.json new file mode 100644 index 000000000..b26286e2e --- /dev/null +++ b/test-projects/01-basic-app/config/optional-features.json @@ -0,0 +1,6 @@ +{ + "application-template-wrapper": false, + "default-async-observers": true, + "jquery-integration": false, + "template-only-glimmer-components": true +} diff --git a/test-projects/01-basic-app/config/targets.js b/test-projects/01-basic-app/config/targets.js new file mode 100644 index 000000000..0b433b73c --- /dev/null +++ b/test-projects/01-basic-app/config/targets.js @@ -0,0 +1,27 @@ +'use strict'; + +const browsers = [ + 'last 1 Chrome versions', + 'last 1 Firefox versions', + 'last 1 Safari versions', +]; + +// Ember's browser support policy is changing, and IE11 support will end in +// v4.0 onwards. +// +// See https://deprecations.emberjs.com/v3.x#toc_3-0-browser-support-policy +// +// If you need IE11 support on a version of Ember that still offers support +// for it, uncomment the code block below. +// +// const isCI = Boolean(process.env.CI); +// const isProduction = process.env.EMBER_ENV === 'production'; +// +// if (isCI || isProduction) { +// browsers.push('ie 11'); +// } + +module.exports = { + browsers, + node: 'current', +}; diff --git a/test-projects/01-basic-app/ember-cli-build.js b/test-projects/01-basic-app/ember-cli-build.js new file mode 100644 index 000000000..633f74278 --- /dev/null +++ b/test-projects/01-basic-app/ember-cli-build.js @@ -0,0 +1,26 @@ +'use strict'; + +const EmberApp = require('ember-cli/lib/broccoli/ember-app'); + +module.exports = function (defaults) { + let app = new EmberApp(defaults, { + autoImport: { + exclude: ['qunit'], + }, + }); + + // Use `app.import` to add additional libraries to the generated + // output files. + // + // If you need to use different assets in different + // environments, specify an object as the first parameter. That + // object's keys should be the environment name and the values + // should be the asset to use in that environment. + // + // If the library that you are including contains AMD or ES6 + // modules that you would like to import into your application + // please specify an object with the list of modules as keys + // along with the exports of each module as its value. + + return app.toTree(); +}; diff --git a/test-projects/01-basic-app/fastboot-tests/included-files-test.js b/test-projects/01-basic-app/fastboot-tests/included-files-test.js new file mode 100644 index 000000000..ae6d5cd34 --- /dev/null +++ b/test-projects/01-basic-app/fastboot-tests/included-files-test.js @@ -0,0 +1,141 @@ +const FastBoot = require('fastboot'); +const { execFileSync } = require('child_process'); +const { module: qModule, test } = require('qunit'); +const jsdom = require('jsdom'); +const { JSDOM } = jsdom; + +const findTextFromHtml = (html, selector) => { + let document = new JSDOM(html).window.document; + return document.querySelector(selector).textContent.trim(); +}; + +qModule('basic-app | fastboot | included files', function () { + test('it includes all modules in development by default', async function (assert) { + execFileSync('node', [require.resolve('ember-cli/bin/ember'), 'build']); + let fastboot = new FastBoot({ + distPath: 'dist', + resilient: false, + }); + + let page = await fastboot.visit('/module-count', { + request: { + url: '/module-count', + protocol: 'https:', + headers: {}, + }, + response: {}, + }); + let html = await page.html(); + + assert.equal( + findTextFromHtml(html, '[data-test-id="environment"]'), + 'development' + ); + assert.ok( + +findTextFromHtml(html, '[data-test-id="mirage-module-count"]') > 1 + ); + assert.ok( + +findTextFromHtml(html, '[data-test-id="other-module-count"]') > 1 + ); + }); + + test('it includes all modules in test by default', async function (assert) { + execFileSync('node', [ + require.resolve('ember-cli/bin/ember'), + 'build', + '--environment=test', + ]); + let fastboot = new FastBoot({ + distPath: 'dist', + resilient: false, + }); + + let page = await fastboot.visit('/module-count', { + request: { + url: '/module-count', + protocol: 'https:', + headers: {}, + }, + response: {}, + }); + let html = await page.html(); + + assert.equal( + findTextFromHtml(html, '[data-test-id="environment"]'), + 'test' + ); + assert.ok( + +findTextFromHtml(html, '[data-test-id="mirage-module-count"]') > 1 + ); + assert.ok( + +findTextFromHtml(html, '[data-test-id="other-module-count"]') > 1 + ); + }); + + test('it only includes an initializer in production by default', async function (assert) { + execFileSync('node', [ + require.resolve('ember-cli/bin/ember'), + 'build', + '-prod', + ]); + let fastboot = new FastBoot({ + distPath: 'dist', + resilient: false, + }); + let page = await fastboot.visit('/module-count', { + request: { + url: '/module-count', + protocol: 'https:', + headers: {}, + }, + response: {}, + }); + let html = await page.html(); + + assert.equal( + findTextFromHtml(html, '[data-test-id="environment"]'), + 'production' + ); + assert.equal( + findTextFromHtml(html, '[data-test-id="mirage-module-count"]'), + '0' + ); + assert.equal( + findTextFromHtml(html, '[data-test-id="other-module-count"]'), + '1' + ); + }); + + test('all files can be included in production by explicitly setting enabled to true', async function (assert) { + process.env.MIRAGE_ENABLED = 'true'; + execFileSync('node', [ + require.resolve('ember-cli/bin/ember'), + 'build', + '-prod', + ]); + let fastboot = new FastBoot({ + distPath: 'dist', + resilient: false, + }); + let page = await fastboot.visit('/module-count', { + request: { + url: '/module-count', + protocol: 'https:', + headers: {}, + }, + response: {}, + }); + let html = await page.html(); + + assert.equal( + findTextFromHtml(html, '[data-test-id="environment"]'), + 'production' + ); + assert.ok( + +findTextFromHtml(html, '[data-test-id="mirage-module-count"]') > 1 + ); + assert.ok( + +findTextFromHtml(html, '[data-test-id="other-module-count"]') > 1 + ); + }); +}); diff --git a/test-projects/01-basic-app/mirage/config.js b/test-projects/01-basic-app/mirage/config.js new file mode 100644 index 000000000..bb5285750 --- /dev/null +++ b/test-projects/01-basic-app/mirage/config.js @@ -0,0 +1,3 @@ +export default function () { + this.resource('user'); +} diff --git a/test-projects/01-basic-app/mirage/factories/nested/thing.js b/test-projects/01-basic-app/mirage/factories/nested/thing.js new file mode 100644 index 000000000..c2692a773 --- /dev/null +++ b/test-projects/01-basic-app/mirage/factories/nested/thing.js @@ -0,0 +1,5 @@ +import { Factory } from 'miragejs'; + +export default Factory.extend({ + name: 'nested factory works!', +}); diff --git a/test-projects/01-basic-app/mirage/factories/user.js b/test-projects/01-basic-app/mirage/factories/user.js new file mode 100644 index 000000000..797df9909 --- /dev/null +++ b/test-projects/01-basic-app/mirage/factories/user.js @@ -0,0 +1,8 @@ +import { Factory } from 'miragejs'; +import faker from 'faker'; + +export default Factory.extend({ + age() { + return faker.datatype.number({ min: 32, max: 32 }); + }, +}); diff --git a/test-projects/01-basic-app/mirage/fixtures/countries.js b/test-projects/01-basic-app/mirage/fixtures/countries.js new file mode 100644 index 000000000..129fc618c --- /dev/null +++ b/test-projects/01-basic-app/mirage/fixtures/countries.js @@ -0,0 +1 @@ +export default [{ name: 'United State' }]; diff --git a/test-projects/01-basic-app/mirage/fixtures/nested/things.js b/test-projects/01-basic-app/mirage/fixtures/nested/things.js new file mode 100644 index 000000000..bfd4cb47d --- /dev/null +++ b/test-projects/01-basic-app/mirage/fixtures/nested/things.js @@ -0,0 +1 @@ +export default [{ fixtureField: 'nested fixture works!' }]; diff --git a/test-projects/01-basic-app/mirage/fixtures/users.js b/test-projects/01-basic-app/mirage/fixtures/users.js new file mode 100644 index 000000000..42dd95037 --- /dev/null +++ b/test-projects/01-basic-app/mirage/fixtures/users.js @@ -0,0 +1 @@ +export default [{ id: 1, name: 'Sam' }]; diff --git a/test-projects/01-basic-app/mirage/identity-managers/book.js b/test-projects/01-basic-app/mirage/identity-managers/book.js new file mode 100644 index 000000000..4ba1e894f --- /dev/null +++ b/test-projects/01-basic-app/mirage/identity-managers/book.js @@ -0,0 +1,59 @@ +export default class { + constructor() { + this.reset(); + } + + /** + * Returns an unique identifier. + * + * @method fetch + * @return {String} Unique identifier + * @public + */ + fetch() { + let alphabet = 'abcdefghijklmnopqrstuvwxyz'; + let id; + + if (this._nextId >= alphabet.length) { + throw new Error( + `IdentityManager used for testing only supports ${alphabet.length} ids.` + ); + } + id = alphabet[this._nextId % alphabet.length]; + this._ids[id] = true; + this._nextId = this._nextid + 1; + return id; + } + + /** + * Register an identifier. + * Must throw if identifier is already used. + * + * @method set + * @param {String|Number} id + * @public + */ + set(id) { + if (typeof this._ids[id] !== 'undefined') { + throw new Error(`Id {id} is already used.`); + } + + this._ids[id] = true; + + let int = parseInt(id, 16); + if (!isNaN(int) && int > this._nextid) { + this._nextId = int; + } + } + + /** + * Reset identity manager. + * + * @method reset + * @public + */ + reset() { + this._nextId = 0; + this._ids = {}; + } +} diff --git a/test-projects/01-basic-app/mirage/identity-managers/nested/thing.js b/test-projects/01-basic-app/mirage/identity-managers/nested/thing.js new file mode 100644 index 000000000..e7fc3b4e2 --- /dev/null +++ b/test-projects/01-basic-app/mirage/identity-managers/nested/thing.js @@ -0,0 +1,58 @@ +export default class { + constructor() { + this.reset(); + } + + /** + * Returns an unique identifier. + * + * @method fetch + * @return {String} Unique identifier + * @public + */ + fetch() { + let id; + + if (this._nextId >= 1) { + throw new Error( + `IdentityManager used for testing only supports single id.` + ); + } + id = 'nested identity manager works!'; + this._ids[id] = true; + this._nextId = this._nextid + 1; + return id; + } + + /** + * Register an identifier. + * Must throw if identifier is already used. + * + * @method set + * @param {String|Number} id + * @public + */ + set(id) { + if (typeof this._ids[id] !== 'undefined') { + throw new Error(`Id {id} is already used.`); + } + + this._ids[id] = true; + + let int = parseInt(id, 16); + if (!isNaN(int) && int > this._nextid) { + this._nextId = int; + } + } + + /** + * Reset identity manager. + * + * @method reset + * @public + */ + reset() { + this._nextId = 0; + this._ids = {}; + } +} diff --git a/test-projects/01-basic-app/mirage/models/nested/thing.js b/test-projects/01-basic-app/mirage/models/nested/thing.js new file mode 100644 index 000000000..db502f142 --- /dev/null +++ b/test-projects/01-basic-app/mirage/models/nested/thing.js @@ -0,0 +1,3 @@ +import { Model } from 'miragejs'; + +export default Model.extend({}); diff --git a/test-projects/01-basic-app/mirage/scenarios/default.js b/test-projects/01-basic-app/mirage/scenarios/default.js new file mode 100644 index 000000000..bc83f83ce --- /dev/null +++ b/test-projects/01-basic-app/mirage/scenarios/default.js @@ -0,0 +1,5 @@ +export default function (server) { + server.create('user', { name: 'Yehuda' }); + server.create('user', { name: 'Tom' }); + server.create('user', { name: 'Leah' }); +} diff --git a/test-projects/01-basic-app/mirage/serializers/application.js b/test-projects/01-basic-app/mirage/serializers/application.js new file mode 100644 index 000000000..6753a45f3 --- /dev/null +++ b/test-projects/01-basic-app/mirage/serializers/application.js @@ -0,0 +1,3 @@ +import { JSONAPISerializer } from 'miragejs'; + +export default JSONAPISerializer; diff --git a/test-projects/01-basic-app/mirage/serializers/nested/thing.js b/test-projects/01-basic-app/mirage/serializers/nested/thing.js new file mode 100644 index 000000000..103273872 --- /dev/null +++ b/test-projects/01-basic-app/mirage/serializers/nested/thing.js @@ -0,0 +1,12 @@ +import ApplicationSerizlizer from '../application'; + +export default ApplicationSerizlizer.extend({ + keyForAttribute(attr) { + const key = ApplicationSerizlizer.prototype.keyForAttribute.call( + this, + attr + ); + + return `nested_thing_${key}`; + }, +}); diff --git a/test-projects/01-basic-app/package.json b/test-projects/01-basic-app/package.json new file mode 100644 index 000000000..acc03f67e --- /dev/null +++ b/test-projects/01-basic-app/package.json @@ -0,0 +1,64 @@ +{ + "name": "basic-app", + "version": "0.0.0", + "private": true, + "description": "Small description for basic-app goes here", + "license": "MIT", + "author": "", + "directories": { + "doc": "doc", + "test": "tests" + }, + "repository": "", + "scripts": { + "build": "ember build --environment=production", + "start": "ember serve", + "test": "npm-run-all lint test:*", + "test:ember": "ember test --test-port=0", + "test:fastboot": "qunit fastboot-tests/**/*.js" + }, + "devDependencies": { + "@ember/jquery": "*", + "@ember/optional-features": "*", + "@ember/test-helpers": "*", + "@embroider/test-setup": "*", + "@glimmer/component": "*", + "@glimmer/tracking": "*", + "broccoli-asset-rev": "*", + "ember-auto-import": "*", + "ember-cli": "*", + "ember-cli-babel": "*", + "ember-cli-dependency-checker": "*", + "ember-cli-fastboot": "*", + "ember-cli-htmlbars": "*", + "ember-cli-inject-live-reload": "*", + "ember-cli-mirage": "*", + "ember-cli-sri": "*", + "ember-cli-terser": "*", + "ember-data": "*", + "ember-export-application-global": "*", + "ember-fetch": "*", + "ember-load-initializers": "*", + "ember-maybe-import-regenerator": "*", + "ember-qunit": "*", + "ember-resolver": "*", + "ember-source": "*", + "faker": "*", + "fastboot": "*", + "jsdom": "*", + "loader.js": "*", + "miragejs": "*", + "npm-run-all": "*", + "qunit": "*", + "qunit-dom": "*" + }, + "engines": { + "node": ">= 10.*" + }, + "ember": { + "edition": "octane" + }, + "volta": { + "extends": "../../package.json" + } +} diff --git a/test-projects/01-basic-app/public/robots.txt b/test-projects/01-basic-app/public/robots.txt new file mode 100644 index 000000000..f5916452e --- /dev/null +++ b/test-projects/01-basic-app/public/robots.txt @@ -0,0 +1,3 @@ +# http://www.robotstxt.org +User-agent: * +Disallow: diff --git a/test-projects/01-basic-app/testem.js b/test-projects/01-basic-app/testem.js new file mode 100644 index 000000000..1f6c614e5 --- /dev/null +++ b/test-projects/01-basic-app/testem.js @@ -0,0 +1,24 @@ +'use strict'; + +module.exports = { + test_page: 'tests/index.html?hidepassed', + disable_watching: true, + launch_in_ci: ['Chrome'], + launch_in_dev: ['Chrome'], + browser_start_timeout: 120, + browser_args: { + Chrome: { + mode: 'ci', + args: [ + // --no-sandbox is needed when running Chrome inside a container + process.env.CI ? '--no-sandbox' : null, + '--headless', + '--disable-dev-shm-usage', + '--disable-software-rasterizer', + '--mute-audio', + '--remote-debugging-port=0', + '--window-size=1440,900', + ].filter(Boolean), + }, + }, +}; diff --git a/test-projects/01-basic-app/tests/acceptance/crud-demo-test.js b/test-projects/01-basic-app/tests/acceptance/crud-demo-test.js new file mode 100644 index 000000000..b1c5b6697 --- /dev/null +++ b/test-projects/01-basic-app/tests/acceptance/crud-demo-test.js @@ -0,0 +1,72 @@ +import { module, test } from 'qunit'; +import { + visit, + currentRouteName, + findAll, + fillIn, + click, +} from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import { setupMirage } from 'ember-cli-mirage/test-support'; + +module('Acceptance | Crud demo', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + test('I can view the users', async function (assert) { + this.server.createList('user', 3); + + await visit('/crud-demo'); + + assert.equal(findAll('[data-test-id="user"]').length, 3); + }); + + test('I can create a new user', async function (assert) { + this.server.create('user', 1); + + await visit('/crud-demo'); + await fillIn('input', 'Ganon'); + await click('[data-test-id="create-user"]'); + + assert.equal(findAll('[data-test-id="user"]').length, 2); + assert.ok(this.server.db.users.length, 2); + }); + + test('I can update a user', async function (assert) { + let user = this.server.create('user', { name: 'Yehuda' }); + + await visit('/crud-demo'); + await fillIn('[data-test-id="user"] input', 'Katz'); + await click('[data-test-id="update-user"]'); + + user.reload(); + + assert.dom('[data-test-id="user"] input').hasValue('Katz'); + assert.ok(user.name, 'Katz'); + }); + + test('I can delete a user', async function (assert) { + this.server.create('user', { name: 'Yehuda' }); + + await visit('/crud-demo'); + await click('[data-test-id="delete-user"]'); + + assert.equal(findAll('[data-test-id="user"]').length, 0); + assert.equal(this.server.db.users.length, 0); + }); + + test('If the server errors on GET /users, the error template shows', async function (assert) { + this.server.get( + '/users', + { + errors: ['improper auth'], + }, + 404 + ); + + await visit('/crud-demo'); + + assert.dom('[data-test-id="error"]').hasText('improper auth'); + assert.equal(currentRouteName(), 'crud-demo_error'); + }); +}); diff --git a/test-projects/01-basic-app/tests/acceptance/ember-data-test.js b/test-projects/01-basic-app/tests/acceptance/ember-data-test.js new file mode 100644 index 000000000..5200c5ba9 --- /dev/null +++ b/test-projects/01-basic-app/tests/acceptance/ember-data-test.js @@ -0,0 +1,105 @@ +import { module, test } from 'qunit'; +import Server from 'ember-cli-mirage/server'; +import { Model } from 'ember-cli-mirage'; +import { modelFor } from 'ember-cli-mirage/ember-data'; + +const CustomTag = Model.extend(); +CustomTag.__isCustom__ = true; + +module('Acceptance | Ember Data', function (hooks) { + hooks.beforeEach(function () { + this.server = new Server({ + environment: 'development', + discoverEmberDataModels: true, + scenarios: { + default() {}, + }, + models: { + // Friend exists in dummy/app/models. We want to make sure pre-defined + // models take precedence + tag: CustomTag, + foo: Model.extend(), + }, + factories: {}, + }); + }); + + hooks.afterEach(function () { + this.server.shutdown(); + }); + + test(`Ember data models were generated and loaded`, function (assert) { + let { schema } = this.server; + let registry = schema._registry; + + assert.ok(registry.foo, 'Mirage model Foo has been registered'); + assert.ok(registry.book, 'EmberData model Book has been registered'); + assert.ok(registry.user, 'EmberData model User has been registered'); + assert.equal( + registry.user.foreignKeys.length, + 1, + 'EmberData model User has the correct relationships' + ); + assert.equal( + registry.book.foreignKeys.length, + 1, + 'EmberData model User has the correct relationships' + ); + assert.equal( + registry.user.foreignKeys[0], + 'bookIds', + 'EmberData model User has the correct relationships' + ); + assert.equal( + registry.book.foreignKeys[0], + 'userId', + 'EmberData model Book has the correct relationships' + ); + }); + + test(`It works with nested models`, function (assert) { + let { schema } = this.server; + let registry = schema._registry; + + assert.ok( + registry['things/watch'], + 'Model things/watch has been registered' + ); + }); + + test(`Defined Mirage models take precedence over autogenerated ones`, function (assert) { + let { schema } = this.server; + let registry = schema._registry; + + assert.ok(registry.tag, 'Model Tag has been registered'); + assert.ok( + registry.tag.class.__isCustom__, + 'Model Tag is not the autogenerated one' + ); + }); + + test(`Auto generated models can be extended via modelFor`, function (assert) { + let { schema } = this.server; + let registry = schema._registry; + + assert.ok(registry.book, 'Ember data model Book has been registered'); + assert.ok(modelFor('book'), 'Ember data model Book is found'); + assert.equal( + typeof modelFor('book').extend, + 'function', + 'Ember data model Book can be extended' + ); + }); + + test(`modelFor is only for auto generated models`, function (assert) { + assert.notOk( + modelFor('tag').__isCustom__, + 'Tag model is not the pre defined one' + ); + assert.throws( + () => modelFor('foo'), + /Model of type 'foo' does not exist/, + 'Pre defined mirage models cannot be found via modelFor' + ); + }); +}); diff --git a/test-projects/01-basic-app/tests/acceptance/faker-test.js b/test-projects/01-basic-app/tests/acceptance/faker-test.js new file mode 100644 index 000000000..d6dcad019 --- /dev/null +++ b/test-projects/01-basic-app/tests/acceptance/faker-test.js @@ -0,0 +1,14 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; +import { setupMirage } from 'ember-cli-mirage/test-support'; + +module('Acceptance | Faker', function (hooks) { + setupTest(hooks); + setupMirage(hooks); + + test('it works', function (assert) { + let user = this.server.create('user'); + + assert.equal(user.age, 32); + }); +}); diff --git a/test-projects/01-basic-app/tests/acceptance/fixtures-test.js b/test-projects/01-basic-app/tests/acceptance/fixtures-test.js new file mode 100644 index 000000000..ff3e286a1 --- /dev/null +++ b/test-projects/01-basic-app/tests/acceptance/fixtures-test.js @@ -0,0 +1,25 @@ +import { module, test } from 'qunit'; +import { visit } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import { setupMirage } from 'ember-cli-mirage/test-support'; + +module('Acceptance | Fixtures', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + test('I can use fixtures', async function (assert) { + this.server.loadFixtures(); + + await visit('/crud-demo'); + + assert.dom('[data-test-id="user"]').exists({ count: 1 }); + }); + + test('I can use fixtures with the filename api', async function (assert) { + this.server.loadFixtures('countries'); + + await visit('/crud-demo'); + + assert.dom('[data-test-id="user"]').doesNotExist(); + }); +}); diff --git a/test-projects/01-basic-app/tests/acceptance/identity-manager-test.js b/test-projects/01-basic-app/tests/acceptance/identity-manager-test.js new file mode 100644 index 000000000..ff654e79c --- /dev/null +++ b/test-projects/01-basic-app/tests/acceptance/identity-manager-test.js @@ -0,0 +1,14 @@ +import { module, test } from 'qunit'; +import { setupApplicationTest } from 'ember-qunit'; +import { setupMirage } from 'ember-cli-mirage/test-support'; + +module('Acceptance | Identity manager', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + test('custom identity managers work', function (assert) { + let book = this.server.create('book'); + + assert.equal(book.id, 'a'); + }); +}); diff --git a/test-projects/01-basic-app/tests/acceptance/legacy-start-mirage-test.js b/test-projects/01-basic-app/tests/acceptance/legacy-start-mirage-test.js new file mode 100644 index 000000000..728b0820b --- /dev/null +++ b/test-projects/01-basic-app/tests/acceptance/legacy-start-mirage-test.js @@ -0,0 +1,59 @@ +import { module, test } from 'qunit'; +import startApp from '../helpers/start-app'; +import destroyApp from '../helpers/destroy-app'; +import { startMirage } from 'basic-app/initializers/ember-cli-mirage'; +import ENV from 'basic-app/config/environment'; + +module('Acceptance | Starting mirage (legacy)', function (hooks) { + let app, oldEnv, addonConfig; + + hooks.beforeEach(function () { + oldEnv = ENV['ember-cli-mirage']; + ENV['ember-cli-mirage'] = addonConfig = {}; + }); + + hooks.afterEach(function () { + destroyApp(app); + ENV['ember-cli-mirage'] = oldEnv; + }); + + test('The server starts automatically when configured with enabled undefined', async function (assert) { + app = startApp(); + + assert.ok(window.server, 'There is a server after starting'); + + window.server.create('user'); + await window.visit('/crud-demo'); + + assert.equal(window.currentRouteName(), 'crud-demo'); + assert.dom('[data-test-id="user"]').exists(); + }); + + test('The server starts automatically when configured with { enabled: true }', async function (assert) { + addonConfig.enabled = true; + app = startApp(); + + assert.ok(window.server, 'There is a server after starting'); + + window.server.create('user'); + await window.visit('/crud-demo'); + + assert.equal(window.currentRouteName(), 'crud-demo'); + assert.dom('[data-test-id="user"]').exists(); + }); + + test('The server can be started manually when configured with { enabled: false }', async function (assert) { + addonConfig.enabled = false; + app = startApp(); + + assert.equal(window.server, undefined, 'There is no server at first'); + startMirage(); + assert.ok(window.server, 'There is a server after starting'); + + window.server.create('user'); + await window.visit('/crud-demo'); + + assert.equal(window.currentRouteName(), 'crud-demo'); + assert.dom('[data-test-id="user"]').exists(); + }); +}); diff --git a/test-projects/01-basic-app/tests/acceptance/request-tracking-test.js b/test-projects/01-basic-app/tests/acceptance/request-tracking-test.js new file mode 100644 index 000000000..bd5fd32c2 --- /dev/null +++ b/test-projects/01-basic-app/tests/acceptance/request-tracking-test.js @@ -0,0 +1,67 @@ +import { run } from '@ember/runloop'; +import { module, test } from 'qunit'; +import startApp from '../helpers/start-app'; +import ENV from 'basic-app/config/environment'; +import promiseAjax from '../helpers/promise-ajax'; + +let App; + +module('Acceptance | Enabling request tracking', function (hooks) { + hooks.afterEach(function () { + window.server.shutdown(); + run(App, 'destroy'); + ENV['ember-cli-mirage'].enabled = undefined; + }); + + test('Request tracking defaults to false', async function (assert) { + App = startApp(); + + await promiseAjax({ + method: 'GET', + url: '/users', + }); + + assert.equal( + window.server.pretender.handledRequests.length, + 0, + 'request tracking should be false by default' + ); + }); + + test('Request tracking treats undefined config as false', async function (assert) { + ENV['ember-cli-mirage'] = { trackRequests: undefined }; + App = startApp(); + + await promiseAjax({ + method: 'GET', + url: '/users', + }); + + assert.equal( + window.server.pretender.handledRequests.length, + 0, + 'request tracking should be false when undefined in config' + ); + }); + + test('Request tracking can be set to true in config', async function (assert) { + ENV['ember-cli-mirage'] = { trackRequests: true }; + App = startApp(); + + await promiseAjax({ + method: 'GET', + url: '/users', + }); + + assert.equal( + window.server.pretender.handledRequests.length, + 1, + 'request tracking can be turned on in config and track requests' + ); + assert.equal( + window.server.pretender.handledRequests[0].method, + 'GET', + 'tracked request method should match the requests method' + ); + }); +}); diff --git a/test-projects/01-basic-app/tests/acceptance/start-mirage-test.js b/test-projects/01-basic-app/tests/acceptance/start-mirage-test.js new file mode 100644 index 000000000..204e8a32b --- /dev/null +++ b/test-projects/01-basic-app/tests/acceptance/start-mirage-test.js @@ -0,0 +1,131 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; +import { visit, currentRouteName } from '@ember/test-helpers'; +import startMirage from 'ember-cli-mirage/start-mirage'; +import { setupMirage } from 'ember-cli-mirage/test-support'; +import ENV from 'basic-app/config/environment'; +import NestedThingModel from 'basic-app/mirage/models/nested/thing'; + +module('Acceptance | Starting mirage', function (hooks) { + let oldEnv, addonConfig, dynamicAfterEach; + + hooks.beforeEach(function () { + oldEnv = ENV['ember-cli-mirage']; + ENV['ember-cli-mirage'] = addonConfig = {}; + // When running in non-legacy mode we shoud ignore this, so we set it so we + // can make sure that tests that it doesn't cause the server to start when + // it shouldn't in the cases that test that + addonConfig.enabled = true; + + dynamicAfterEach = () => undefined; + }); + + hooks.afterEach(function () { + dynamicAfterEach(); + }); + + hooks.afterEach(function () { + ENV['ember-cli-mirage'] = oldEnv; + }); + + module('without autostart', function (hooks) { + setupTest(hooks); + + test('it does not autostart but can be started manually', async function (assert) { + assert.equal( + window.server, + undefined, + 'There is no global server at first' + ); + let server = startMirage(this.owner); + assert.ok(server, 'There is a server after starting'); + assert.ok(window.server, 'There is a global server after starting'); + dynamicAfterEach = () => server.shutdown(); + + server.create('user'); + await visit('/crud-demo'); + + assert.equal(currentRouteName(), 'crud-demo'); + assert.dom('[data-test-id="user"]').exists(); + }); + + module('nested mirage modules', function () { + test('it works', async function (assert) { + const server = startMirage(this.owner); + const model = server.create('nested/thing'); + dynamicAfterEach = () => server.shutdown(); + + assert.ok(model instanceof NestedThingModel, 'models'); + assert.equal( + model.id, + 'nested identity manager works!', + 'identity managers' + ); + assert.equal(model.name, 'nested factory works!', 'factories'); + + const { attributes } = + server.serializerOrRegistry.serialize(model).data; + assert.ok('nested_thing_name' in attributes, 'serializer'); + }); + + // factories and fixtures have to be tested separately + test('fixtures support', async function (assert) { + const server = startMirage(this.owner); + dynamicAfterEach = () => server.shutdown(); + + server.loadFixtures('nested/things'); + const model = server.schema.first('nested/thing'); + + assert.ok(model instanceof NestedThingModel, 'models'); + assert.equal( + model.id, + 'nested identity manager works!', + 'identity managers' + ); + assert.equal(model.fixtureField, 'nested fixture works!', 'fixtures'); + }); + }); + + module('setupMirage()', function (hooks) { + setupMirage(hooks); + + test('it works', async function (assert) { + assert.ok(this.server, 'There is a server'); + assert.ok(window.server, 'There is a global server'); + dynamicAfterEach = () => { + assert.notOk(this.server, 'The server was shut down'); + assert.notOk(window.server, 'The global server is gone'); + }; + + this.server.create('user'); + await visit('/crud-demo'); + + assert.equal(currentRouteName(), 'crud-demo'); + assert.dom('[data-test-id="user"]').exists(); + }); + }); + }); + + module('with autostart', function (hooks) { + hooks.beforeEach(function () { + addonConfig.autostart = true; + }); + + setupTest(hooks); + + test('it autostarts', async function (assert) { + assert.ok(this.server, 'There is a server'); + assert.ok(window.server, 'There is a global server'); + dynamicAfterEach = () => { + assert.notOk(this.server, 'The server was shut down'); + assert.notOk(window.server, 'The global server is gone'); + }; + + this.server.create('user'); + await visit('/crud-demo'); + + assert.equal(currentRouteName(), 'crud-demo'); + assert.dom('[data-test-id="user"]').exists(); + }); + }); +}); diff --git a/test-projects/01-basic-app/tests/helpers/destroy-app.js b/test-projects/01-basic-app/tests/helpers/destroy-app.js new file mode 100644 index 000000000..a935b7e33 --- /dev/null +++ b/test-projects/01-basic-app/tests/helpers/destroy-app.js @@ -0,0 +1,9 @@ +import { run } from '@ember/runloop'; + +export default function destroyApp(application) { + run(function () { + application.destroy(); + + window.server.shutdown(); + }); +} diff --git a/test-projects/01-basic-app/tests/helpers/module-for-acceptance.js b/test-projects/01-basic-app/tests/helpers/module-for-acceptance.js new file mode 100644 index 000000000..68cbbdeb8 --- /dev/null +++ b/test-projects/01-basic-app/tests/helpers/module-for-acceptance.js @@ -0,0 +1,22 @@ +import { module } from 'qunit'; +import { resolve } from 'rsvp'; +import startApp from '../helpers/start-app'; +import destroyApp from '../helpers/destroy-app'; + +export default function (name, options = {}) { + module(name, { + beforeEach() { + this.application = startApp(); + + if (options.beforeEach) { + return options.beforeEach.apply(this, arguments); + } + }, + + afterEach() { + let afterEach = + options.afterEach && options.afterEach.apply(this, arguments); + return resolve(afterEach).then(() => destroyApp(this.application)); + }, + }); +} diff --git a/test-projects/01-basic-app/tests/helpers/promise-ajax.js b/test-projects/01-basic-app/tests/helpers/promise-ajax.js new file mode 100644 index 000000000..6b746ce18 --- /dev/null +++ b/test-projects/01-basic-app/tests/helpers/promise-ajax.js @@ -0,0 +1,11 @@ +/* eslint-disable ember/no-jquery */ +import { Promise } from 'rsvp'; +import $ from 'jquery'; + +export default (options) => { + return new Promise((resolve, reject) => { + $.ajax(options) + .done((data, status, xhr) => resolve({ data, status, xhr })) + .fail((xhr, status, error) => reject({ xhr, status, error })); + }); +}; diff --git a/test-projects/01-basic-app/tests/helpers/resolver.js b/test-projects/01-basic-app/tests/helpers/resolver.js new file mode 100644 index 000000000..319b45fc1 --- /dev/null +++ b/test-projects/01-basic-app/tests/helpers/resolver.js @@ -0,0 +1,11 @@ +import Resolver from '../../resolver'; +import config from '../../config/environment'; + +const resolver = Resolver.create(); + +resolver.namespace = { + modulePrefix: config.modulePrefix, + podModulePrefix: config.podModulePrefix, +}; + +export default resolver; diff --git a/test-projects/01-basic-app/tests/helpers/start-app.js b/test-projects/01-basic-app/tests/helpers/start-app.js new file mode 100644 index 000000000..9f6aee596 --- /dev/null +++ b/test-projects/01-basic-app/tests/helpers/start-app.js @@ -0,0 +1,17 @@ +import Application from '../../app'; +import config from '../../config/environment'; +import { assign } from '@ember/polyfills'; +import { run } from '@ember/runloop'; + +export default function startApp(attrs) { + let attributes = assign({}, config.APP); + attributes.autoboot = true; + attributes = assign(attributes, attrs); // use defaults, but you can override; + + return run(() => { + let application = Application.create(attributes); + application.setupForTesting(); + application.injectTestHelpers(); + return application; + }); +} diff --git a/test-projects/01-basic-app/tests/index.html b/test-projects/01-basic-app/tests/index.html new file mode 100644 index 000000000..25cdfb5cd --- /dev/null +++ b/test-projects/01-basic-app/tests/index.html @@ -0,0 +1,40 @@ + + + + + + BasicApp Tests + + + + {{content-for "head"}} + {{content-for "test-head"}} + + + + + + {{content-for "head-footer"}} + {{content-for "test-head-footer"}} + + + {{content-for "body"}} + {{content-for "test-body"}} + +
+
+
+
+
+
+ + + + + + + + {{content-for "body-footer"}} + {{content-for "test-body-footer"}} + + diff --git a/test-projects/01-basic-app/tests/test-helper.js b/test-projects/01-basic-app/tests/test-helper.js new file mode 100644 index 000000000..0cd91d37f --- /dev/null +++ b/test-projects/01-basic-app/tests/test-helper.js @@ -0,0 +1,12 @@ +import Application from 'basic-app/app'; +import config from 'basic-app/config/environment'; +import * as QUnit from 'qunit'; +import { setApplication } from '@ember/test-helpers'; +import { setup } from 'qunit-dom'; +import { start } from 'ember-qunit'; + +setApplication(Application.create(config.APP)); + +setup(QUnit.assert); + +start(); diff --git a/test-projects/01-basic-app/vendor/.gitkeep b/test-projects/01-basic-app/vendor/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test-projects/02-app-that-excludes-mirage/.editorconfig b/test-projects/02-app-that-excludes-mirage/.editorconfig new file mode 100644 index 000000000..c35a00240 --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/.editorconfig @@ -0,0 +1,19 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# editorconfig.org + +root = true + +[*] +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space +indent_size = 2 + +[*.hbs] +insert_final_newline = false + +[*.{diff,md}] +trim_trailing_whitespace = false diff --git a/test-projects/02-app-that-excludes-mirage/.ember-cli b/test-projects/02-app-that-excludes-mirage/.ember-cli new file mode 100644 index 000000000..ee64cfed2 --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/.ember-cli @@ -0,0 +1,9 @@ +{ + /** + Ember CLI sends analytics information by default. The data is completely + anonymous, but there are times when you might want to disable this behavior. + + Setting `disableAnalytics` to true will prevent any data from being sent. + */ + "disableAnalytics": false +} diff --git a/test-projects/02-app-that-excludes-mirage/.gitignore b/test-projects/02-app-that-excludes-mirage/.gitignore new file mode 100644 index 000000000..4156d2e30 --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/.gitignore @@ -0,0 +1,26 @@ +# See https://help.github.com/ignore-files/ for more about ignoring files. + +# compiled output +/dist/ +/tmp/ + +# dependencies +/bower_components/ +/node_modules/ + +# misc +/.env* +/.pnp* +/.sass-cache +/.eslintcache +/connect.lock +/coverage/ +/libpeerconnection.log +/npm-debug.log* +/testem.log +/yarn-error.log + +# ember-try +.node_modules.ember-try/ +bower.json.ember-try +package.json.ember-try diff --git a/test-projects/02-app-that-excludes-mirage/.npmignore b/test-projects/02-app-that-excludes-mirage/.npmignore new file mode 100644 index 000000000..72e8ffc0d --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/.npmignore @@ -0,0 +1 @@ +* diff --git a/test-projects/02-app-that-excludes-mirage/.watchmanconfig b/test-projects/02-app-that-excludes-mirage/.watchmanconfig new file mode 100644 index 000000000..e7834e3e4 --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/.watchmanconfig @@ -0,0 +1,3 @@ +{ + "ignore_dirs": ["tmp", "dist"] +} diff --git a/test-projects/02-app-that-excludes-mirage/README.md b/test-projects/02-app-that-excludes-mirage/README.md new file mode 100644 index 000000000..7078509d6 --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/README.md @@ -0,0 +1,57 @@ +# basic-app + +This README outlines the details of collaborating on this Ember application. +A short introduction of this app could easily go here. + +## Prerequisites + +You will need the following things properly installed on your computer. + +* [Git](https://git-scm.com/) +* [Node.js](https://nodejs.org/) +* [Yarn](https://yarnpkg.com/) +* [Ember CLI](https://ember-cli.com/) +* [Google Chrome](https://google.com/chrome/) + +## Installation + +* `git clone ` this repository +* `cd basic-app` +* `yarn install` + +## Running / Development + +* `ember serve` +* Visit your app at [http://localhost:4200](http://localhost:4200). +* Visit your tests at [http://localhost:4200/tests](http://localhost:4200/tests). + +### Code Generators + +Make use of the many generators for code, try `ember help generate` for more details + +### Running Tests + +* `ember test` +* `ember test --server` + +### Linting + +* `npm run lint` +* `npm run lint:fix` + +### Building + +* `ember build` (development) +* `ember build --environment production` (production) + +### Deploying + +Specify what it takes to deploy your app. + +## Further Reading / Useful Links + +* [ember.js](https://emberjs.com/) +* [ember-cli](https://ember-cli.com/) +* Development Browser Extensions + * [ember inspector for chrome](https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi) + * [ember inspector for firefox](https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/) diff --git a/test-projects/02-app-that-excludes-mirage/app/app.js b/test-projects/02-app-that-excludes-mirage/app/app.js new file mode 100644 index 000000000..e9953bf80 --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/app/app.js @@ -0,0 +1,12 @@ +import Application from '@ember/application'; +import Resolver from 'ember-resolver'; +import loadInitializers from 'ember-load-initializers'; +import config from 'basic-app/config/environment'; + +export default class App extends Application { + modulePrefix = config.modulePrefix; + podModulePrefix = config.podModulePrefix; + Resolver = Resolver; +} + +loadInitializers(App, config.modulePrefix); diff --git a/test-projects/02-app-that-excludes-mirage/app/components/.gitkeep b/test-projects/02-app-that-excludes-mirage/app/components/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test-projects/02-app-that-excludes-mirage/app/controllers/.gitkeep b/test-projects/02-app-that-excludes-mirage/app/controllers/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test-projects/02-app-that-excludes-mirage/app/controllers/application.js b/test-projects/02-app-that-excludes-mirage/app/controllers/application.js new file mode 100644 index 000000000..9605e0f1d --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/app/controllers/application.js @@ -0,0 +1,26 @@ +/* global requirejs */ +import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; +import ENV from 'basic-app/config/environment'; + +export default class extends Controller { + @service wifi; + + environment = ENV.environment; + + get mirageModules() { + return Object.keys(requirejs.entries).filter((key) => + key.match('^ember-cli-mirage') + ); + } + + get otherIncludedModules() { + return Object.keys(requirejs.entries).filter((key) => { + return ( + key.match('^pretender') || + key.match('^lodash') || + key.match('initializers/ember-cli-mirage') + ); + }); + } +} diff --git a/test-projects/02-app-that-excludes-mirage/app/helpers/.gitkeep b/test-projects/02-app-that-excludes-mirage/app/helpers/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test-projects/02-app-that-excludes-mirage/app/index.html b/test-projects/02-app-that-excludes-mirage/app/index.html new file mode 100644 index 000000000..326f147b5 --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/app/index.html @@ -0,0 +1,25 @@ + + + + + + BasicApp + + + + {{content-for "head"}} + + + + + {{content-for "head-footer"}} + + + {{content-for "body"}} + + + + + {{content-for "body-footer"}} + + diff --git a/test-projects/02-app-that-excludes-mirage/app/models/.gitkeep b/test-projects/02-app-that-excludes-mirage/app/models/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test-projects/02-app-that-excludes-mirage/app/router.js b/test-projects/02-app-that-excludes-mirage/app/router.js new file mode 100644 index 000000000..90091dca2 --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/app/router.js @@ -0,0 +1,9 @@ +import EmberRouter from '@ember/routing/router'; +import config from 'basic-app/config/environment'; + +export default class Router extends EmberRouter { + location = config.locationType; + rootURL = config.rootURL; +} + +Router.map(function () {}); diff --git a/test-projects/02-app-that-excludes-mirage/app/routes/.gitkeep b/test-projects/02-app-that-excludes-mirage/app/routes/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test-projects/02-app-that-excludes-mirage/app/services/wifi.js b/test-projects/02-app-that-excludes-mirage/app/services/wifi.js new file mode 100644 index 000000000..b12952cf9 --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/app/services/wifi.js @@ -0,0 +1,5 @@ +import Service from '@ember/service'; + +export default class extends Service { + isConnected = true; +} diff --git a/test-projects/02-app-that-excludes-mirage/app/styles/app.css b/test-projects/02-app-that-excludes-mirage/app/styles/app.css new file mode 100644 index 000000000..e69de29bb diff --git a/test-projects/02-app-that-excludes-mirage/app/templates/application.hbs b/test-projects/02-app-that-excludes-mirage/app/templates/application.hbs new file mode 100644 index 000000000..de2c24227 --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/app/templates/application.hbs @@ -0,0 +1,19 @@ +

Welcome to Ember

+ +{{#if this.wifi.isConnected}} +

We ran the initializer

+{{/if}} + +

+ Mirage modules in project: + + {{this.mirageModules.length}} + +

+ +

+ Other modules in project: + + {{this.otherIncludedModules.length}} + +

diff --git a/test-projects/02-app-that-excludes-mirage/config/ember-cli-update.json b/test-projects/02-app-that-excludes-mirage/config/ember-cli-update.json new file mode 100644 index 000000000..192c7719f --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/config/ember-cli-update.json @@ -0,0 +1,20 @@ +{ + "schemaVersion": "1.0.0", + "packages": [ + { + "name": "ember-cli", + "version": "3.28.4", + "blueprints": [ + { + "name": "app", + "outputRepo": "https://github.com/ember-cli/ember-new-output", + "codemodsSource": "ember-app-codemods-manifest@1", + "isBaseBlueprint": true, + "options": [ + "--no-welcome" + ] + } + ] + } + ] +} diff --git a/test-projects/02-app-that-excludes-mirage/config/environment.js b/test-projects/02-app-that-excludes-mirage/config/environment.js new file mode 100644 index 000000000..688fd2276 --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/config/environment.js @@ -0,0 +1,54 @@ +'use strict'; + +module.exports = function (environment) { + let ENV = { + modulePrefix: 'basic-app', + environment, + rootURL: '/', + locationType: 'auto', + EmberENV: { + FEATURES: { + // Here you can enable experimental features on an ember canary build + // e.g. EMBER_NATIVE_DECORATOR_SUPPORT: true + }, + EXTEND_PROTOTYPES: { + // Prevent Ember Data from overriding Date.parse. + Date: false, + }, + }, + + APP: { + // Here you can pass flags/options to your application instance + // when it is created + }, + 'ember-cli-mirage': { + excludeFilesFromBuild: true, + }, + }; + + if (environment === 'development') { + // ENV.APP.LOG_RESOLVER = true; + // ENV.APP.LOG_ACTIVE_GENERATION = true; + // ENV.APP.LOG_TRANSITIONS = true; + // ENV.APP.LOG_TRANSITIONS_INTERNAL = true; + // ENV.APP.LOG_VIEW_LOOKUPS = true; + } + + if (environment === 'test') { + // Testem prefers this... + ENV.locationType = 'none'; + + // keep test console output quieter + ENV.APP.LOG_ACTIVE_GENERATION = false; + ENV.APP.LOG_VIEW_LOOKUPS = false; + + ENV.APP.rootElement = '#ember-testing'; + ENV.APP.autoboot = false; + } + + if (environment === 'production') { + // here you can enable a production-specific feature + } + + return ENV; +}; diff --git a/test-projects/02-app-that-excludes-mirage/config/optional-features.json b/test-projects/02-app-that-excludes-mirage/config/optional-features.json new file mode 100644 index 000000000..b26286e2e --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/config/optional-features.json @@ -0,0 +1,6 @@ +{ + "application-template-wrapper": false, + "default-async-observers": true, + "jquery-integration": false, + "template-only-glimmer-components": true +} diff --git a/test-projects/02-app-that-excludes-mirage/config/targets.js b/test-projects/02-app-that-excludes-mirage/config/targets.js new file mode 100644 index 000000000..0b433b73c --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/config/targets.js @@ -0,0 +1,27 @@ +'use strict'; + +const browsers = [ + 'last 1 Chrome versions', + 'last 1 Firefox versions', + 'last 1 Safari versions', +]; + +// Ember's browser support policy is changing, and IE11 support will end in +// v4.0 onwards. +// +// See https://deprecations.emberjs.com/v3.x#toc_3-0-browser-support-policy +// +// If you need IE11 support on a version of Ember that still offers support +// for it, uncomment the code block below. +// +// const isCI = Boolean(process.env.CI); +// const isProduction = process.env.EMBER_ENV === 'production'; +// +// if (isCI || isProduction) { +// browsers.push('ie 11'); +// } + +module.exports = { + browsers, + node: 'current', +}; diff --git a/test-projects/02-app-that-excludes-mirage/ember-cli-build.js b/test-projects/02-app-that-excludes-mirage/ember-cli-build.js new file mode 100644 index 000000000..48e94e9e4 --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/ember-cli-build.js @@ -0,0 +1,24 @@ +'use strict'; + +const EmberApp = require('ember-cli/lib/broccoli/ember-app'); + +module.exports = function (defaults) { + let app = new EmberApp(defaults, { + // Add options here + }); + + // Use `app.import` to add additional libraries to the generated + // output files. + // + // If you need to use different assets in different + // environments, specify an object as the first parameter. That + // object's keys should be the environment name and the values + // should be the asset to use in that environment. + // + // If the library that you are including contains AMD or ES6 + // modules that you would like to import into your application + // please specify an object with the list of modules as keys + // along with the exports of each module as its value. + + return app.toTree(); +}; diff --git a/test-projects/02-app-that-excludes-mirage/mirage/config.js b/test-projects/02-app-that-excludes-mirage/mirage/config.js new file mode 100644 index 000000000..ea9b101e1 --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/mirage/config.js @@ -0,0 +1 @@ +export default function () {} diff --git a/test-projects/02-app-that-excludes-mirage/package.json b/test-projects/02-app-that-excludes-mirage/package.json new file mode 100644 index 000000000..acc03f67e --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/package.json @@ -0,0 +1,64 @@ +{ + "name": "basic-app", + "version": "0.0.0", + "private": true, + "description": "Small description for basic-app goes here", + "license": "MIT", + "author": "", + "directories": { + "doc": "doc", + "test": "tests" + }, + "repository": "", + "scripts": { + "build": "ember build --environment=production", + "start": "ember serve", + "test": "npm-run-all lint test:*", + "test:ember": "ember test --test-port=0", + "test:fastboot": "qunit fastboot-tests/**/*.js" + }, + "devDependencies": { + "@ember/jquery": "*", + "@ember/optional-features": "*", + "@ember/test-helpers": "*", + "@embroider/test-setup": "*", + "@glimmer/component": "*", + "@glimmer/tracking": "*", + "broccoli-asset-rev": "*", + "ember-auto-import": "*", + "ember-cli": "*", + "ember-cli-babel": "*", + "ember-cli-dependency-checker": "*", + "ember-cli-fastboot": "*", + "ember-cli-htmlbars": "*", + "ember-cli-inject-live-reload": "*", + "ember-cli-mirage": "*", + "ember-cli-sri": "*", + "ember-cli-terser": "*", + "ember-data": "*", + "ember-export-application-global": "*", + "ember-fetch": "*", + "ember-load-initializers": "*", + "ember-maybe-import-regenerator": "*", + "ember-qunit": "*", + "ember-resolver": "*", + "ember-source": "*", + "faker": "*", + "fastboot": "*", + "jsdom": "*", + "loader.js": "*", + "miragejs": "*", + "npm-run-all": "*", + "qunit": "*", + "qunit-dom": "*" + }, + "engines": { + "node": ">= 10.*" + }, + "ember": { + "edition": "octane" + }, + "volta": { + "extends": "../../package.json" + } +} diff --git a/test-projects/02-app-that-excludes-mirage/public/robots.txt b/test-projects/02-app-that-excludes-mirage/public/robots.txt new file mode 100644 index 000000000..f5916452e --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/public/robots.txt @@ -0,0 +1,3 @@ +# http://www.robotstxt.org +User-agent: * +Disallow: diff --git a/test-projects/02-app-that-excludes-mirage/testem.js b/test-projects/02-app-that-excludes-mirage/testem.js new file mode 100644 index 000000000..1f6c614e5 --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/testem.js @@ -0,0 +1,24 @@ +'use strict'; + +module.exports = { + test_page: 'tests/index.html?hidepassed', + disable_watching: true, + launch_in_ci: ['Chrome'], + launch_in_dev: ['Chrome'], + browser_start_timeout: 120, + browser_args: { + Chrome: { + mode: 'ci', + args: [ + // --no-sandbox is needed when running Chrome inside a container + process.env.CI ? '--no-sandbox' : null, + '--headless', + '--disable-dev-shm-usage', + '--disable-software-rasterizer', + '--mute-audio', + '--remote-debugging-port=0', + '--window-size=1440,900', + ].filter(Boolean), + }, + }, +}; diff --git a/test-projects/02-app-that-excludes-mirage/tests/acceptance/modules-test.js b/test-projects/02-app-that-excludes-mirage/tests/acceptance/modules-test.js new file mode 100644 index 000000000..8aa58e9b5 --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/tests/acceptance/modules-test.js @@ -0,0 +1,14 @@ +import { module, test } from 'qunit'; +import { visit } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; + +module('Acceptance | modules', function (hooks) { + setupApplicationTest(hooks); + + test('only 1 module (the no-op initializer) is included in the build', async function (assert) { + await visit('/'); + + assert.dom('[data-test-id="mirage-module-count"]').hasText('0'); + assert.dom('[data-test-id="other-module-count"]').hasText('1'); + }); +}); diff --git a/test-projects/02-app-that-excludes-mirage/tests/acceptance/pre-mirage-initializer-test.js b/test-projects/02-app-that-excludes-mirage/tests/acceptance/pre-mirage-initializer-test.js new file mode 100644 index 000000000..54c39b6de --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/tests/acceptance/pre-mirage-initializer-test.js @@ -0,0 +1,13 @@ +import { module, test } from 'qunit'; +import { visit } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; + +module('Acceptance | noop initializer test', function (hooks) { + setupApplicationTest(hooks); + + test('visiting /noop-initializer-test', async function (assert) { + await visit('/'); + + assert.dom('[data-test-id="wifi-connected"]').exists({ count: 1 }); + }); +}); diff --git a/test-projects/02-app-that-excludes-mirage/tests/helpers/destroy-app.js b/test-projects/02-app-that-excludes-mirage/tests/helpers/destroy-app.js new file mode 100644 index 000000000..07753ba46 --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/tests/helpers/destroy-app.js @@ -0,0 +1,11 @@ +import { run } from '@ember/runloop'; + +export default function destroyApp(application) { + run(function () { + application.destroy(); + + if (window.server) { + window.server.shutdown(); + } + }); +} diff --git a/test-projects/02-app-that-excludes-mirage/tests/helpers/module-for-acceptance.js b/test-projects/02-app-that-excludes-mirage/tests/helpers/module-for-acceptance.js new file mode 100644 index 000000000..68cbbdeb8 --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/tests/helpers/module-for-acceptance.js @@ -0,0 +1,22 @@ +import { module } from 'qunit'; +import { resolve } from 'rsvp'; +import startApp from '../helpers/start-app'; +import destroyApp from '../helpers/destroy-app'; + +export default function (name, options = {}) { + module(name, { + beforeEach() { + this.application = startApp(); + + if (options.beforeEach) { + return options.beforeEach.apply(this, arguments); + } + }, + + afterEach() { + let afterEach = + options.afterEach && options.afterEach.apply(this, arguments); + return resolve(afterEach).then(() => destroyApp(this.application)); + }, + }); +} diff --git a/test-projects/02-app-that-excludes-mirage/tests/helpers/promise-ajax.js b/test-projects/02-app-that-excludes-mirage/tests/helpers/promise-ajax.js new file mode 100644 index 000000000..6b746ce18 --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/tests/helpers/promise-ajax.js @@ -0,0 +1,11 @@ +/* eslint-disable ember/no-jquery */ +import { Promise } from 'rsvp'; +import $ from 'jquery'; + +export default (options) => { + return new Promise((resolve, reject) => { + $.ajax(options) + .done((data, status, xhr) => resolve({ data, status, xhr })) + .fail((xhr, status, error) => reject({ xhr, status, error })); + }); +}; diff --git a/test-projects/02-app-that-excludes-mirage/tests/helpers/resolver.js b/test-projects/02-app-that-excludes-mirage/tests/helpers/resolver.js new file mode 100644 index 000000000..319b45fc1 --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/tests/helpers/resolver.js @@ -0,0 +1,11 @@ +import Resolver from '../../resolver'; +import config from '../../config/environment'; + +const resolver = Resolver.create(); + +resolver.namespace = { + modulePrefix: config.modulePrefix, + podModulePrefix: config.podModulePrefix, +}; + +export default resolver; diff --git a/test-projects/02-app-that-excludes-mirage/tests/helpers/start-app.js b/test-projects/02-app-that-excludes-mirage/tests/helpers/start-app.js new file mode 100644 index 000000000..9f6aee596 --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/tests/helpers/start-app.js @@ -0,0 +1,17 @@ +import Application from '../../app'; +import config from '../../config/environment'; +import { assign } from '@ember/polyfills'; +import { run } from '@ember/runloop'; + +export default function startApp(attrs) { + let attributes = assign({}, config.APP); + attributes.autoboot = true; + attributes = assign(attributes, attrs); // use defaults, but you can override; + + return run(() => { + let application = Application.create(attributes); + application.setupForTesting(); + application.injectTestHelpers(); + return application; + }); +} diff --git a/test-projects/02-app-that-excludes-mirage/tests/index.html b/test-projects/02-app-that-excludes-mirage/tests/index.html new file mode 100644 index 000000000..25cdfb5cd --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/tests/index.html @@ -0,0 +1,40 @@ + + + + + + BasicApp Tests + + + + {{content-for "head"}} + {{content-for "test-head"}} + + + + + + {{content-for "head-footer"}} + {{content-for "test-head-footer"}} + + + {{content-for "body"}} + {{content-for "test-body"}} + +
+
+
+
+
+
+ + + + + + + + {{content-for "body-footer"}} + {{content-for "test-body-footer"}} + + diff --git a/test-projects/02-app-that-excludes-mirage/tests/test-helper.js b/test-projects/02-app-that-excludes-mirage/tests/test-helper.js new file mode 100644 index 000000000..0cd91d37f --- /dev/null +++ b/test-projects/02-app-that-excludes-mirage/tests/test-helper.js @@ -0,0 +1,12 @@ +import Application from 'basic-app/app'; +import config from 'basic-app/config/environment'; +import * as QUnit from 'qunit'; +import { setApplication } from '@ember/test-helpers'; +import { setup } from 'qunit-dom'; +import { start } from 'ember-qunit'; + +setApplication(Application.create(config.APP)); + +setup(QUnit.assert); + +start(); diff --git a/test-projects/02-app-that-excludes-mirage/vendor/.gitkeep b/test-projects/02-app-that-excludes-mirage/vendor/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/testem.js b/testem.js index 7586db34e..ed2f37124 100644 --- a/testem.js +++ b/testem.js @@ -1,12 +1,23 @@ -/* eslint-env node */ +'use strict'; + module.exports = { - "framework": "qunit", - "test_page": "tests/index.html?hidepassed", - "disable_watching": true, - "launch_in_ci": [ - "PhantomJS" - ], - "launch_in_dev": [ - "PhantomJS" - ] + test_page: 'tests/index.html?hidepassed', + disable_watching: true, + launch_in_ci: ['Chrome'], + launch_in_dev: ['Chrome'], + browser_start_timeout: 120, + browser_args: { + Chrome: { + ci: [ + // --no-sandbox is needed when running Chrome inside a container + process.env.CI ? '--no-sandbox' : null, + '--headless', + '--disable-dev-shm-usage', + '--disable-software-rasterizer', + '--mute-audio', + '--remote-debugging-port=0', + '--window-size=1440,900', + ].filter(Boolean), + }, + }, }; diff --git a/tests/.eslintrc.js b/tests/.eslintrc.js deleted file mode 100644 index 377bbd962..000000000 --- a/tests/.eslintrc.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - env: { - 'embertest': true - }, - rules: { - 'prefer-template': 0 - }, - globals: { - require: true, - describe: true, - afterEach: true, - it: true - } -}; diff --git a/tests/acceptance/contact-test.js b/tests/acceptance/contact-test.js deleted file mode 100644 index 673d05a10..000000000 --- a/tests/acceptance/contact-test.js +++ /dev/null @@ -1,29 +0,0 @@ -import {test} from 'qunit'; -import moduleForAcceptance from '../helpers/module-for-acceptance'; - -let contact; - -moduleForAcceptance('Acceptance | Contact', { - beforeEach() { - contact = server.create('contact'); - } -}); - -test('I can view a contact', function(assert) { - visit('/1'); - - andThen(function() { - assert.equal(currentRouteName(), 'contact'); - assert.equal(find('p:first').text(), `The contact is ${contact.name}`); - }); -}); - -test('I can delete a contact', function(assert) { - visit('/1'); - click('button:contains(Delete)'); - - andThen(function() { - assert.equal(currentRouteName(), 'contacts'); - assert.equal(find('p').length, 0); - }); -}); diff --git a/tests/acceptance/contacts-test.js b/tests/acceptance/contacts-test.js deleted file mode 100644 index abf303288..000000000 --- a/tests/acceptance/contacts-test.js +++ /dev/null @@ -1,44 +0,0 @@ -import {test} from 'qunit'; -import moduleForAcceptance from '../helpers/module-for-acceptance'; - -let contacts; - -moduleForAcceptance('Acceptance | Contacts', { - beforeEach() { - contacts = server.createList('contact', 2); - } -}); - -test('I can view the contacts', function(assert) { - visit('/'); - - andThen(function() { - assert.equal(currentRouteName(), 'contacts'); - assert.equal(find('p').length, 2); - assert.equal(find('p:first').text(), contacts[0].name); - }); -}); - -test('I can create a new contact', function(assert) { - visit('/'); - fillIn('input', 'Ganon'); - click('button:contains(Create)'); - - andThen(function() { - assert.equal(currentRouteName(), 'contacts'); - assert.equal(find('p').length, 3); - assert.equal(find('p:last').text(), 'Ganon'); - }); -}); - -test('If the server errors on /contacts, the first error message should show', function(assert) { - server.get('/contacts', { - errors: ['improper auth'] - }, 404); - - visit('/'); - - andThen(function() { - assert.equal(find('.error span').text(), 'improper auth'); - }); -}); diff --git a/tests/acceptance/custom-handlers-test.js b/tests/acceptance/custom-handlers-test.js deleted file mode 100644 index 4b0e0ee36..000000000 --- a/tests/acceptance/custom-handlers-test.js +++ /dev/null @@ -1,68 +0,0 @@ -import Ember from 'ember'; -import moduleForAcceptance from '../helpers/module-for-acceptance'; -import { test } from 'qunit'; - -const { ajax } = Ember.$; - -let appStore, rex; - -moduleForAcceptance('Acceptance | Custom handlers', { - beforeEach() { - appStore = this.application.__container__.lookup('service:store'); - rex = server.create('pet', { name: 'Rex', alive: true }); - server.create('pet', { name: 'Toby', alive: false }); - server.create('pet', { name: 'Sam', alive: false }); - server.create('pet', { name: 'Andy', alive: true }); - } -}); - -test('You can customize the response by passing a handler function that returns the desired body', function(assert) { - let done = assert.async(); - appStore.findAll('pet').then(function(pets) { - assert.deepEqual(pets.mapBy('name'), ['Rex', 'Andy']); - }).finally(done); -}); - -test('You can customize the response code of a custom handler passing the code as 3rd argument', function(assert) { - let done = assert.async(); - let request = ajax({ - url: '/pets/${rex.id}', - method: 'delete' - }); - - request.then(function(response, statusText, jqXHR) { - assert.equal(jqXHR.status, 200, 'The status code is 200 instead od 204'); - done(); - }); -}); - -test('You can can programatically returns a tailored response by returning a Mirage.Response', function(assert) { - let done = assert.async(); - let request = ajax({ - url: '/pets', - method: 'post', - data: JSON.stringify({ pet: { alive: true } }) - }); - - request.then(function() { /* noop */ }, function(response) { - assert.equal(response.status, 422, 'The status code is 422'); - assert.equal(response.responseText, '{"errors":{"name":["can\'t be blank"]}}', 'The response body is correct'); - assert.equal(response.getResponseHeader('some'), 'header', 'The response contains the custom header'); - done(); - }); -}); - -test('returning a non-blank response from a custom handler whose default status is 204 changes the status to 200', function(assert) { - let done = assert.async(); - let request = ajax({ - url: '/pets/${rex.id}', - method: 'put', - data: JSON.stringify({ pet: { id: rex.id, name: 'The Rex', alive: true } }) - }); - - request.then(function(response, statusText, jqXHR) { - assert.equal(jqXHR.status, 200, 'The status code is 200 instead of 204'); - assert.deepEqual(response, { id: '1', name: 'The Rex', alive: true }, 'The response is correct'); - done(); - }); -}); diff --git a/tests/acceptance/edit-test.js b/tests/acceptance/edit-test.js deleted file mode 100644 index c953c2328..000000000 --- a/tests/acceptance/edit-test.js +++ /dev/null @@ -1,19 +0,0 @@ -import {test} from 'qunit'; -import moduleForAcceptance from '../helpers/module-for-acceptance'; - -moduleForAcceptance('Acceptance | Edit'); - -test('I can edit a contact', function(assert) { - server.create('contact'); - - visit('/1'); - click('button:contains(Edit)'); - fillIn('input', 'Shiek'); - click('button:contains(Save)'); - - andThen(function() { - assert.equal(currentRouteName(), 'contact'); - assert.equal(find('p:first').text(), 'The contact is Shiek'); - }); -}); - diff --git a/tests/acceptance/fixtures-test.js b/tests/acceptance/fixtures-test.js deleted file mode 100644 index a5be14c68..000000000 --- a/tests/acceptance/fixtures-test.js +++ /dev/null @@ -1,37 +0,0 @@ -import moduleForAcceptance from '../helpers/module-for-acceptance'; -import { test } from 'qunit'; - -moduleForAcceptance('Acceptance | Fixtures', { - beforeEach() { - this.store = this.application.__container__.lookup('service:store'); - } -}); - -test('I can use fixtures', function(assert) { - server.loadFixtures(); - - visit(`/word-smiths/1`); - - andThen(() => { - let wordSmithsInStore = this.store.peekAll('word-smith'); - let blogPostsInStore = this.store.peekAll('blog-post'); - - assert.equal(wordSmithsInStore.get('length'), 1); - assert.equal(blogPostsInStore.get('length'), 3); - }); -}); - -test('I can use fixtures with the filename api', function(assert) { - server.loadFixtures('word-smiths', 'blog-posts'); - - visit(`/word-smiths/1`); - - andThen(() => { - let wordSmithsInStore = this.store.peekAll('word-smith'); - let blogPostsInStore = this.store.peekAll('blog-post'); - - assert.equal(wordSmithsInStore.get('length'), 1); - assert.equal(blogPostsInStore.get('length'), 3); - }); -}); - diff --git a/tests/acceptance/friends-test.js b/tests/acceptance/friends-test.js deleted file mode 100644 index a7080c69c..000000000 --- a/tests/acceptance/friends-test.js +++ /dev/null @@ -1,52 +0,0 @@ -import {test} from 'qunit'; -import moduleForAcceptance from '../helpers/module-for-acceptance'; - -moduleForAcceptance('Acceptance | Friends'); - -test('I can view the friends', function(assert) { - let friend = server.create('friend'); - let youngFriend = server.create('friend', { name: 'Tommy', age: 10 }); - - visit('/friends'); - - andThen(function() { - assert.equal(currentRouteName(), 'friends'); - assert.equal(find('p').length, 2); - assert.equal(friend.isYoung, false); - assert.equal(youngFriend.isYoung, true); - - assert.ok(find('p:first').text().match(friend.name)); - assert.ok(find('p:first').text().match(friend.age)); - assert.ok(find('p:last').text().match('Tommy')); - assert.ok(find('p:last').text().match(10)); - }); -}); - -test('I can view the selected friends', function(assert) { - server.create('friend', { name: 'Jane', age: 30 }); - server.create('friend', { name: 'Tommy', age: 10 }); - server.create('friend', { name: 'Bob', age: 28 }); - - visit('/close-friends'); - - andThen(function() { - assert.equal(currentRouteName(), 'close-friends'); - assert.equal(find('p').length, 2); - - assert.ok(find('p:first').text().match('Jane')); - assert.ok(find('p:first').text().match(30)); - assert.ok(find('p:last').text().match('Bob')); - assert.ok(find('p:last').text().match(28)); - }); -}); - -test('I can view a friend that was configured only for test mode', function(assert) { - let friend = server.create('friend', { name: 'The Dude' }); - - visit(`/friends/${friend.id}`); - - andThen(function() { - assert.equal(currentRouteName(), 'friend'); - assert.ok(find('h2.friend-name').text().match('The Dude')); - }); -}); diff --git a/tests/acceptance/home-test.js b/tests/acceptance/home-test.js new file mode 100644 index 000000000..71f984cc7 --- /dev/null +++ b/tests/acceptance/home-test.js @@ -0,0 +1,17 @@ +import { module, test } from 'qunit'; +import { visit, currentURL } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import { dependencySatisfies } from '@embroider/macros'; + +module('Acceptance | home', function (hooks) { + setupApplicationTest(hooks); + + // Ember Addon docs will fail for sources less then 3.16.0 + if (dependencySatisfies('ember-source', '^3.16.0')) { + test('the homepage renders without error', async function (assert) { + await visit('/'); + + assert.strictEqual(currentURL(), '/', 'Correct URL is shown'); + }); + } +}); diff --git a/tests/acceptance/manually-starting-test.js b/tests/acceptance/manually-starting-test.js deleted file mode 100644 index 8fa2bf656..000000000 --- a/tests/acceptance/manually-starting-test.js +++ /dev/null @@ -1,36 +0,0 @@ -import Ember from 'ember'; -import {module, test} from 'qunit'; -import startApp from '../helpers/start-app'; -import { startMirage } from 'dummy/initializers/ember-cli-mirage'; -import ENV from 'dummy/config/environment'; - -const { run } = Ember; - -let App; - -module('Acceptance: Manually starting Mirage', { - beforeEach() { - ENV['ember-cli-mirage'] = { enabled: false }; - App = startApp(); - }, - - afterEach() { - server.shutdown(); - run(App, 'destroy'); - ENV['ember-cli-mirage'].enabled = undefined; - } -}); - -test('The server can be started manually when configured with { enabled: false }', function(assert) { - assert.equal(window.server, undefined, 'There is no server at first'); - startMirage(); - assert.ok(window.server, 'There is a server after starting'); - - let contact = server.create('contact'); - visit('/1'); - - andThen(function() { - assert.equal(currentRouteName(), 'contact'); - assert.equal(find('p:first').text(), `The contact is ${contact.name}`, 'The manually started server works'); - }); -}); diff --git a/tests/acceptance/pets-test.js b/tests/acceptance/pets-test.js deleted file mode 100644 index 930549a93..000000000 --- a/tests/acceptance/pets-test.js +++ /dev/null @@ -1,33 +0,0 @@ -import {test} from 'qunit'; -import moduleForAcceptance from '../helpers/module-for-acceptance'; - -let pets; - -moduleForAcceptance('Acceptance | Pets', { - beforeEach() { - pets = server.createList('pet', 3); - } -}); - -test('I can view the pets', function(assert) { - visit('/pets'); - - andThen(function() { - assert.equal(currentRouteName(), 'pets'); - assert.equal(find('li').length, 3); - assert.equal(find('li:first .name').text().trim(), pets[0].name); - }); -}); - -test('I can create a new pet', function(assert) { - visit('/pets'); - - fillIn('input', 'Brownie'); - click('button:contains(create)'); - - andThen(function() { - assert.equal(currentRouteName(), 'pets'); - assert.equal(find('li').length, 4); - assert.equal(find('li:last .name').text(), 'Brownie'); - }); -}); diff --git a/tests/acceptance/serializers-test.js b/tests/acceptance/serializers-test.js deleted file mode 100644 index eff44e0b0..000000000 --- a/tests/acceptance/serializers-test.js +++ /dev/null @@ -1,24 +0,0 @@ -import moduleForAcceptance from '../helpers/module-for-acceptance'; -import { test } from 'qunit'; - -moduleForAcceptance('Acceptance | Serializers', { - beforeEach() { - this.store = this.application.__container__.lookup('service:store'); - } -}); - -test('Serializers can provide default includes', function(assert) { - let wordSmith = server.create('word-smith'); - server.createList('blog-post', 3, { wordSmithId: wordSmith.id }); - - visit(`/word-smiths/${wordSmith.id}`); - - andThen(() => { - let wordSmithsInStore = this.store.peekAll('word-smith'); - let blogPostsInStore = this.store.peekAll('blog-post'); - - assert.equal(wordSmithsInStore.get('length'), 1); - assert.equal(blogPostsInStore.get('length'), 3); - }); -}); - diff --git a/tests/dummy/app/adapters/application.js b/tests/dummy/app/adapters/application.js deleted file mode 100644 index 0aa14480c..000000000 --- a/tests/dummy/app/adapters/application.js +++ /dev/null @@ -1,3 +0,0 @@ -import ActiveModelAdapter from 'active-model-adapter'; - -export default ActiveModelAdapter; diff --git a/tests/dummy/app/adapters/post.js b/tests/dummy/app/adapters/post.js new file mode 100644 index 000000000..7b59fea59 --- /dev/null +++ b/tests/dummy/app/adapters/post.js @@ -0,0 +1,126 @@ +/* eslint-disable ember/no-jquery */ +import { run } from '@ember/runloop'; +import JSONAPIAdapter from '@ember-data/adapter/json-api'; +import $ from 'jquery'; +import { Promise } from 'rsvp'; + +const BASE_URL = 'https://api.github.com/repos/miragejs/ember-cli-mirage'; + +export default class extends JSONAPIAdapter { + findRecord(store, type, id /*, snapshot*/) { + let url = `${BASE_URL}/issues/${id}`; + + return new Promise((resolve, reject) => { + $.getJSON(url).then( + (json) => { + let jsonApiDocument = { + data: { + id, + type: 'posts', + attributes: { + title: json.title, + body: json.body, + 'issue-url': json.html_url, + }, + relationships: { + comments: { + links: { + related: json.comments_url, + }, + }, + }, + }, + }; + + resolve(jsonApiDocument); + }, + (jqXHR) => { + reject(jqXHR); + } + ); + }); + } + + findAll(/*store, type*/) { + let url = `${BASE_URL}/issues?state=closed&labels=Blog%20post`; + + return new Promise((resolve, reject) => { + $.getJSON(url).then( + (json) => { + this.hasLoadedAllPosts = true; + + let jsonApiDocument = { + data: json.map((obj) => ({ + id: obj.number, + type: 'posts', + attributes: { + title: obj.title, + body: obj.body, + 'issue-url': obj.html_url, + }, + })), + }; + + resolve(jsonApiDocument); + }, + (jqXHR) => { + reject(jqXHR); + } + ); + }); + } + + shouldReloadAll(/*store, snapshotArray*/) { + return !this.hasLoadedAllPosts; + } + + findHasMany(store, snapshot, url /*, relationship*/) { + return new Promise((resolve, reject) => { + $.getJSON(url).then( + (json) => { + run(() => { + let jsonApiDocument = { data: [], included: [] }; + let includedUserHash = {}; + + json.forEach((obj) => { + jsonApiDocument.data.push({ + id: obj.id, + type: 'comments', + attributes: { + body: obj.body, + permalink: obj.html_url, + 'created-at': obj.created_at, + }, + relationships: { + user: { + data: { type: 'users', id: obj.user.id }, + }, + }, + }); + + includedUserHash[obj.user.id] = obj.user; + }); + + Object.keys(includedUserHash).forEach((key) => { + let user = includedUserHash[key]; + jsonApiDocument.included.push({ + type: 'users', + id: user.id, + attributes: { + 'avatar-url': user.avatar_url, + 'profile-url': user.html_url, + username: user.login, + }, + }); + }); + + resolve(jsonApiDocument); + }); + }, + (jqXHR) => { + run(() => reject(jqXHR)); + } + ); + }); + } +} diff --git a/tests/dummy/app/adapters/word-smith.js b/tests/dummy/app/adapters/word-smith.js deleted file mode 100644 index 9c2d2e317..000000000 --- a/tests/dummy/app/adapters/word-smith.js +++ /dev/null @@ -1,5 +0,0 @@ -import DS from 'ember-data'; - -const { JSONAPIAdapter } = DS; - -export default JSONAPIAdapter; diff --git a/tests/dummy/app/app.js b/tests/dummy/app/app.js index 23b9ad028..523bad60c 100644 --- a/tests/dummy/app/app.js +++ b/tests/dummy/app/app.js @@ -1,18 +1,12 @@ -import Ember from 'ember'; -import Resolver from './resolver'; +import Application from '@ember/application'; +import Resolver from 'ember-resolver'; import loadInitializers from 'ember-load-initializers'; -import config from './config/environment'; +import config from 'dummy/config/environment'; -const { Application } = Ember; - -Ember.MODEL_FACTORY_INJECTIONS = true; - -const App = Application.extend({ - modulePrefix: config.modulePrefix, - podModulePrefix: config.podModulePrefix, - Resolver -}); +export default class App extends Application { + modulePrefix = config.modulePrefix; + podModulePrefix = config.podModulePrefix; + Resolver = Resolver; +} loadInitializers(App, config.modulePrefix); - -export default App; diff --git a/tests/dummy/app/controllers/application.js b/tests/dummy/app/controllers/application.js deleted file mode 100644 index 46ced9151..000000000 --- a/tests/dummy/app/controllers/application.js +++ /dev/null @@ -1,5 +0,0 @@ -import Ember from 'ember'; - -const { Controller } = Ember; - -export default Controller.extend(); diff --git a/tests/dummy/app/index.html b/tests/dummy/app/index.html index 5120bd73f..c76347a77 100644 --- a/tests/dummy/app/index.html +++ b/tests/dummy/app/index.html @@ -3,18 +3,18 @@ - Dummy + EmberCLI Mirage {{content-for "head"}} - - + + {{content-for "head-footer"}} - + {{content-for "body"}} diff --git a/tests/dummy/app/initializers/es2015-polyfills.js b/tests/dummy/app/initializers/es2015-polyfills.js index 274eefc05..ddcc1b26a 100644 --- a/tests/dummy/app/initializers/es2015-polyfills.js +++ b/tests/dummy/app/initializers/es2015-polyfills.js @@ -2,12 +2,14 @@ export function initialize(/* container, application */) { // Production steps of ECMA-262, Edition 6, 22.1.2.1 // Reference: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.from if (!Array.from) { - Array.from = (function() { + Array.from = (function () { let toStr = Object.prototype.toString; - let isCallable = function(fn) { - return typeof fn === 'function' || toStr.call(fn) === '[object Function]'; + let isCallable = function (fn) { + return ( + typeof fn === 'function' || toStr.call(fn) === '[object Function]' + ); }; - let toInteger = function(value) { + let toInteger = function (value) { let number = Number(value); if (isNaN(number)) { return 0; @@ -18,13 +20,13 @@ export function initialize(/* container, application */) { return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number)); }; let maxSafeInteger = Math.pow(2, 53) - 1; - let toLength = function(value) { + let toLength = function (value) { let len = toInteger(value); return Math.min(Math.max(len, 0), maxSafeInteger); }; // The length property of the from method is 1. - return function from(arrayLike/* , mapFn, thisArg */) { + return function from(arrayLike /* , mapFn, thisArg */) { // 1. Let C be the this value. let C = this; let T, kValue; @@ -34,7 +36,9 @@ export function initialize(/* container, application */) { // 3. ReturnIfAbrupt(items). if (arrayLike == null) { - throw new TypeError('Array.from requires an array-like object - not null or undefined'); + throw new TypeError( + 'Array.from requires an array-like object - not null or undefined' + ); } // 4. If mapfn is undefined, then let mapping be false. @@ -43,7 +47,9 @@ export function initialize(/* container, application */) { // 5. else // 5. a If IsCallable(mapfn) is false, throw a TypeError exception. if (!isCallable(mapFn)) { - throw new TypeError('Array.from: when provided, the second argument must be a function'); + throw new TypeError( + 'Array.from: when provided, the second argument must be a function' + ); } // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined. @@ -67,7 +73,10 @@ export function initialize(/* container, application */) { while (k < len) { kValue = items[k]; if (mapFn) { - A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k); + A[k] = + typeof T === 'undefined' + ? mapFn(kValue, k) + : mapFn.call(T, kValue, k); } else { A[k] = kValue; } @@ -78,11 +87,11 @@ export function initialize(/* container, application */) { // 20. Return A. return A; }; - }()); + })(); } } export default { name: 'es2015-polyfills', - initialize + initialize, }; diff --git a/tests/dummy/app/models/address.js b/tests/dummy/app/models/address.js index 31fb290d5..df7e70f8c 100644 --- a/tests/dummy/app/models/address.js +++ b/tests/dummy/app/models/address.js @@ -1,9 +1,3 @@ -import DS from 'ember-data'; +import Model from '@ember-data/model'; -const { Model, attr, belongsTo } = DS; - -export default Model.extend({ - street: attr('string'), - - contact: belongsTo('contact') -}); +export default class extends Model {} diff --git a/tests/dummy/app/models/blog-post.js b/tests/dummy/app/models/blog-post.js deleted file mode 100644 index 4e619aea4..000000000 --- a/tests/dummy/app/models/blog-post.js +++ /dev/null @@ -1,11 +0,0 @@ -import DS from 'ember-data'; - -const { Model, attr, belongsTo } = DS; - -export default Model.extend({ - - title: attr(), - - wordSmith: belongsTo() - -}); diff --git a/tests/dummy/app/models/comment.js b/tests/dummy/app/models/comment.js new file mode 100644 index 000000000..a0f3b2a6f --- /dev/null +++ b/tests/dummy/app/models/comment.js @@ -0,0 +1,15 @@ +import Model, { attr, belongsTo } from '@ember-data/model'; +import compileMarkdown from 'ember-cli-addon-docs/utils/compile-markdown'; +import { htmlSafe } from '@ember/string'; + +export default class Comment extends Model { + @belongsTo() user; + + @attr body; + @attr permalink; + @attr createdAt; + + get htmlBody() { + return htmlSafe(compileMarkdown(this.body)); + } +} diff --git a/tests/dummy/app/models/contact.js b/tests/dummy/app/models/contact.js deleted file mode 100644 index 8eaa01c07..000000000 --- a/tests/dummy/app/models/contact.js +++ /dev/null @@ -1,11 +0,0 @@ -import DS from 'ember-data'; - -const { Model, attr, belongsTo } = DS; - -export default Model.extend({ - name: attr('string'), - age: attr('number'), - email: attr('string'), - - address: belongsTo('address') -}); diff --git a/tests/dummy/app/models/friend.js b/tests/dummy/app/models/friend.js deleted file mode 100644 index 1294cbdbf..000000000 --- a/tests/dummy/app/models/friend.js +++ /dev/null @@ -1,8 +0,0 @@ -import DS from 'ember-data'; -import Contact from './contact'; - -const { attr } = DS; - -export default Contact.extend({ - isYoung: attr('boolean') -}); diff --git a/tests/dummy/app/models/pet.js b/tests/dummy/app/models/pet.js deleted file mode 100644 index b0fbb379b..000000000 --- a/tests/dummy/app/models/pet.js +++ /dev/null @@ -1,8 +0,0 @@ -import DS from 'ember-data'; - -const { Model, attr } = DS; - -export default Model.extend({ - name: attr('string'), - alive: attr('boolean') -}); diff --git a/tests/dummy/app/models/post.js b/tests/dummy/app/models/post.js new file mode 100644 index 000000000..587d693b9 --- /dev/null +++ b/tests/dummy/app/models/post.js @@ -0,0 +1,35 @@ +import Model, { attr, hasMany } from '@ember-data/model'; +import yaml from 'js-yaml'; +import compileMarkdown from 'ember-cli-addon-docs/utils/compile-markdown'; +import { htmlSafe } from '@ember/string'; + +export default class Post extends Model { + @hasMany() comments; + + @attr title; + @attr body; + @attr issueUrl; + + get htmlBody() { + return htmlSafe(compileMarkdown(this.body)); + } + + get meta() { + let lines = this.body.split('\n').map((line) => line.trim()); + let firstLine = lines[0]; + + if (firstLine === ''); + let metaLines = lines.slice(1, lastIndex); + let meta = yaml.safeLoad(`${metaLines.join('\n')}`); + + return meta; + } else { + return {}; + } + } + + get slugAndId() { + return `${this.meta.slug}-${this.id}`; + } +} diff --git a/tests/dummy/app/models/user.js b/tests/dummy/app/models/user.js new file mode 100644 index 000000000..06b9e3e3a --- /dev/null +++ b/tests/dummy/app/models/user.js @@ -0,0 +1,7 @@ +import Model, { attr } from '@ember-data/model'; + +export default class User extends Model { + @attr avatarUrl; + @attr profileUrl; + @attr username; +} diff --git a/tests/dummy/app/models/word-smith.js b/tests/dummy/app/models/word-smith.js index 228563fb0..4aa646ece 100644 --- a/tests/dummy/app/models/word-smith.js +++ b/tests/dummy/app/models/word-smith.js @@ -1,11 +1,8 @@ -import DS from 'ember-data'; - -const { Model, attr, hasMany } = DS; - -export default Model.extend({ - - name: attr(), - - blogPosts: hasMany() - -}); +import Model, { attr, belongsTo, hasMany } from '@ember-data/model'; + +export default class extends Model { + @attr name; + @attr age; + @hasMany('comments') comments; + @belongsTo('address') address; +} diff --git a/tests/dummy/app/pods/application/route.js b/tests/dummy/app/pods/application/route.js new file mode 100644 index 000000000..cd5cf6058 --- /dev/null +++ b/tests/dummy/app/pods/application/route.js @@ -0,0 +1,23 @@ +import Route from '@ember/routing/route'; + +export default class extends Route { + beforeModel() { + let pathname = window.location.pathname; + [ + 'v0.0.27', + 'v0.0.28', + 'v0.0.29', + 'v0.1.x', + 'v0.2.x', + 'v0.3.x', + 'v0.4.x', + ].forEach((version) => { + if (pathname.match(`/docs/${version}`)) { + window.location = pathname.replace( + `/docs/${version}`, + `/versions/${version}` + ); + } + }); + } +} diff --git a/tests/dummy/app/pods/application/template.hbs b/tests/dummy/app/pods/application/template.hbs new file mode 100644 index 000000000..445adab58 --- /dev/null +++ b/tests/dummy/app/pods/application/template.hbs @@ -0,0 +1,9 @@ + + {{#header.link "blog"}} + Blog + {{/header.link}} + + +{{outlet}} + + diff --git a/tests/dummy/app/pods/blog/detail/route.js b/tests/dummy/app/pods/blog/detail/route.js new file mode 100644 index 000000000..051773a7e --- /dev/null +++ b/tests/dummy/app/pods/blog/detail/route.js @@ -0,0 +1,15 @@ +import Route from '@ember/routing/route'; + +export default class extends Route { + model({ post_slug_and_id }) { + let matches = post_slug_and_id.match(/\d+$/); + if (!matches) { + let path = document.location.pathname.replace(/^\/|\/$/g, ''); + this.transitionTo('not-found', path); + } + + let postId = matches[0]; + + return this.store.findRecord('post', postId); + } +} diff --git a/tests/dummy/app/pods/blog/detail/template.hbs b/tests/dummy/app/pods/blog/detail/template.hbs new file mode 100644 index 000000000..ba8d6bb4a --- /dev/null +++ b/tests/dummy/app/pods/blog/detail/template.hbs @@ -0,0 +1,52 @@ +{{!-- docs-md is a private class. Can switch once we expose AddonDocs styles publicly. --}} +
+ + ← All posts + + +
+ + +

+ {{this.model.title}} +

+ + {{this.model.htmlBody}} +
+ +
+ +
+

Comments

+ + {{#each this.model.comments as |comment|}} +
+ + profile + + + +
+ {{/each}} + + +
+
diff --git a/tests/dummy/app/pods/blog/error/template.hbs b/tests/dummy/app/pods/blog/error/template.hbs new file mode 100644 index 000000000..41a6ac37c --- /dev/null +++ b/tests/dummy/app/pods/blog/error/template.hbs @@ -0,0 +1,5 @@ +

We're sorry...

+ +

+ {{this.model.responseJSON.message}} +

diff --git a/tests/dummy/app/pods/blog/index/route.js b/tests/dummy/app/pods/blog/index/route.js new file mode 100644 index 000000000..2099c3b01 --- /dev/null +++ b/tests/dummy/app/pods/blog/index/route.js @@ -0,0 +1,7 @@ +import Route from '@ember/routing/route'; + +export default class extends Route { + model() { + return this.store.findAll('post'); + } +} diff --git a/tests/dummy/app/pods/blog/index/template.hbs b/tests/dummy/app/pods/blog/index/template.hbs new file mode 100644 index 000000000..ab25bf282 --- /dev/null +++ b/tests/dummy/app/pods/blog/index/template.hbs @@ -0,0 +1,16 @@ +
+

Blog

+ + {{#each (sort-by "meta.publishedAt:desc" this.model) as |post|}} +
+ +

+ + {{post.title}} + +

+
+ {{/each}} +
diff --git a/tests/dummy/app/pods/blog/template.hbs b/tests/dummy/app/pods/blog/template.hbs new file mode 100644 index 000000000..9e19668ae --- /dev/null +++ b/tests/dummy/app/pods/blog/template.hbs @@ -0,0 +1,7 @@ +
+
+
+
+ {{outlet}} +
+
diff --git a/tests/dummy/app/pods/docs/advanced/customizing-the-inflector/template.md b/tests/dummy/app/pods/docs/advanced/customizing-the-inflector/template.md new file mode 100644 index 000000000..945f069fb --- /dev/null +++ b/tests/dummy/app/pods/docs/advanced/customizing-the-inflector/template.md @@ -0,0 +1,67 @@ +# Customizing the inflector + +When using Ember Data, you'll sometimes find yourself needing to customize the inflection rules used by your models. + +For example, say you had an `Advice` model. By default, Ember's inflector pluralizes this as "advices" + +```js +import { pluralize } from 'ember-inflector'; + +pluralize("advice"); // advices +``` + +Ember Data uses these inflection rules for things like building its conventional URLs. For example, + +```Js +this.store.findAll('advice'); +``` + +would result in a GET request to `/api/advices`. + +Mirage also relies on the inflector for its conventions. For example, the resource Shorthand + +```js +// mirage/config.js +this.resource('advice'); +``` + +might use inflection rules to try to look up the "advices" collection or database table. + +[The guides](https://guides.emberjs.com/release/models/customizing-adapters/#toc_pluralization-customization) document the best way to configure these inflection rules. At the time of this writing, here's how you'd configure the inflector to treat "advice" as an uncountable word (i.e. a word with no plural form): + +```js +// app/initializers/custom-inflector-rules.js +import Inflector from 'ember-inflector'; + +export function initialize(/* application */) { + const inflector = Inflector.inflector; + + // Tell the inflector that the plural of "advice" is "advice" + inflector.uncountable('advice'); +} + +export default { + name: 'custom-inflector-rules', + before: 'ember-cli-mirage', + initialize +}; +``` + +Make sure to use `before: "ember-cli-mirage"` so this runs before Mirage initializes itself. + +As long as you follow this approach, Mirage should respect your custom inflector rules. + +With the above rule, + +```Js +this.store.findAll('advice'); +``` + +would now result in a `GET` request to `/api/advice`, and + +```js +// mirage/config.js +this.resource('advice'); +``` + +would respond correctly to that request, as well as correctly handle all other operations to the `Advice` resource. diff --git a/tests/dummy/app/pods/docs/advanced/environment-options/template.md b/tests/dummy/app/pods/docs/advanced/environment-options/template.md new file mode 100644 index 000000000..bfa550d11 --- /dev/null +++ b/tests/dummy/app/pods/docs/advanced/environment-options/template.md @@ -0,0 +1,111 @@ +# Environment options + +Set these options via the `ENV['ember-cli-mirage']` variable in your `config/environment.js` file: + +```js +// config/environment.js +... +if (environment === 'production') { + ENV['ember-cli-mirage'] = { + enabled: true + }; +} +``` + +## enabled + +By default, your Mirage server will run in test mode, and in development mode as long as the `--proxy` option isn't passed. To change this default behavior, set `enabled` to either true or false in your ENV config. + +For example, to enable in production (e.g. to share a working prototype before your server is ready): + +```js +// config/environment.js +... +if (environment === 'production') { + ENV['ember-cli-mirage'] = { + enabled: true + }; +} +``` + +To disable in development, + +```js +// config/environment.js +... +if (environment === 'development') { + ENV['ember-cli-mirage'] = { + enabled: false + }; +} +``` + +## trackRequests + +Defaults to `false`. + +A boolean that controls whether [Pretender's `trackedRequests` feature](https://github.com/pretenderjs/pretender#tracking-requests) is enabled. By default it is disabled to avoid memory issues during long development sessions. + +To enable, set to `true`, for example in testing environments: + +```js +// config/environment.js +module.exports = function(environment) { + if (environment === 'test') { + ENV['ember-cli-mirage'] = { + trackRequests: true + }; + } +} +``` + +This feature is useful for asserting against HTTP requests and responses during tests. See the "Asserting against handled requests and responses" section of the {{docs-link 'Assertions guide' 'docs.testing.assertions'}} to learn more. + + +## excludeFilesFromBuild + +Defaults to `false`. + +By default, Mirage's files are included in your Ember app's build in non-production environments. This is in case you want to use Mirage via `ember serve` by visiting `/tests`, since that's an app with a build-time environment of `development` but a run-time environment of `test`. + +You can explicilty exclude Mirage's files from your Ember app's build by setting `excludeFilesFromBuild` to `true`. + +## useDefaultPassthroughs + +Defaults to `true`. + +If true, Mirage will add some default passthrough routes to your server. Currently we add a single route + +- http://localhost:0/chromecheckurl + +which is used by iOS for URL verification. + +## directory + +Configure which directory contains your Mirage server definition. The default directory is `/mirage` (from the root of your project). + +For example, to have your server definition under `/app/mirage`, + +```js +// config/environment.js +... +ENV['ember-cli-mirage'] = { + directory: 'app/mirage' +}; +``` + +## discoverEmberDataModels + +Tells Mirage whether to automatically infer its schema from the host application's Ember Data models and relationships. + +Defaults to true. If Ember Data models are present, predefines Mirage's models and relationships. If Ember Data models are not present, has no effect. + +You can disable by setting to `false`. You might want to do this if you run into an edge case/issue where the autodiscovery code causes issues in your app's environment (for example, if you have a complex engines setup). + +```js +// config/environment.js +... +ENV['ember-cli-mirage'] = { + discoverEmberDataModels: false +}; +``` diff --git a/tests/dummy/app/pods/docs/advanced/mocking-guids/template.md b/tests/dummy/app/pods/docs/advanced/mocking-guids/template.md new file mode 100644 index 000000000..0618fcb2a --- /dev/null +++ b/tests/dummy/app/pods/docs/advanced/mocking-guids/template.md @@ -0,0 +1,55 @@ +# Mocking GUIDs + +Some applications use GUIDs (or UUIDs) instead of auto-incrementing integers as identifiers for their models. + +Mirage supports the ability to overwrite how its database assigns IDs to new records via the `IdentityManager` class. You can generate model-specific managers or an application-wide manager to customize how your database behaves. + +To generate a new identity manager, use the blueprint: + +``` +ember generate mirage-identity-manager +``` + +A custom identity manager must implement these methods: + +- `fetch`, which must return an identifier not used yet. +- `set`, which is called with an `id` of a record being insert in mirage's database. +- `reset`, which should reset database to initial state. + +Here's an example implementation for an identity manager that mocks GUIDs: + +```js +import { v4 as getUuid } from "ember-uuid"; + +export default class { + constructor() { + this.ids = new Set(); + } + + // Returns a new unused unique identifier. + fetch() { + let uuid = getUuid(); + while (this.ids.has(uuid)) { + uuid = getUuid(); + } + + this.ids.add(uuid); + + return uuid; + } + + // Registers an identifier as used. Must throw if identifier is already used. + set(id) { + if (this.ids.has(id)) { + throw new Error(`ID ${id} has already been used.`); + } + + this.ids.add(id); + } + + // Resets all used identifiers to unused. + reset() { + this.ids.clear(); + } +} +``` diff --git a/tests/dummy/app/pods/docs/advanced/server-configuration/template.md b/tests/dummy/app/pods/docs/advanced/server-configuration/template.md new file mode 100644 index 000000000..047fd992e --- /dev/null +++ b/tests/dummy/app/pods/docs/advanced/server-configuration/template.md @@ -0,0 +1,132 @@ +# Server configuration + +The MirageJS server is configured for you by ember-cli-mirage. However, if you +need to customize the server you can by creating a makeServer function in the +config.js. + +Typically, the `/mirage/config.js` file contains a single default export which +is a function defining all your Mirage route handlers. Ember CLI Mirage then +uses this function, along with all the other modules you've defined in +`mirage/models`, `mirage/fixtures`, `mirage/factories`, and +`mirage/serializers`, to create your Mirage JS server when your app boots up +in development and testing. + +You can now opt in to having more control over exactly how your Mirage server +is instantiated using the same code as the mirageJS examples of creating a server +by changing your current default export that represents the routes to a normal function, +then creating a new default export function that creates the mirageJS server. + +This new default export function receives a single argument named `config`, +which contains all the factory/fixture/serializer/model modules that exist +in your project's `/mirage` directory. This saves you from having to import +each module explicitly and then pass it into your Mirage server, just like +you're used to with the default setup. + +The `config` argument maps exactly to everything inside of your `/mirage` +directory - notably, it does not contain the autogenerated Mirage model +definitions derived from your Ember Data models, which is an important feature +of Ember CLI Mirage that is enabled by default. To replicate this behavior, a helper +has been provided named `discoverEmberDataModels` from the `ember-cli-mirage` +package that you can use to augment your config with these models so that your Mirage schema is +automatically inferred from your host application's Ember Data models and +relationships. The snippet below shows how to do this. Note that the order +here matters if you also have models defined in your `/mirage/models` +directory, as those model definitions would "win" in the event of a conflict +with the ones autodiscovered from Ember Data. (However, most of time if you +are inferring your Mirage schema from Ember Data, you shouldn't need to define +additional models.) + +Finally, your route handlers just need to be passed to the `routes()` key in +your Mirage config. You can do this inline, or you can make them a separate +function, and organize that function however you choose. + +You should also add `miragejs` to your project's dependencies in +your `package.json` file, since you are now importing directly from it. Note +that this gives you the added benefit of being able to upgrade `miragejs` +independently of `ember-cli-mirage`. + +All the objects from `miragejs` are re-exported in `ember-cli-mirage` such as +`Model`, `belongsTo`, `hasMany` as well as `Fixtures`, `Traits` for example. +These should in the future also be imported directly from `miragejs` as +eventually these re-exports will be removed. This will help align the +`ember-cli-mirage` users with the rest of the Mirage JS community. + +```javascript +// Example with inline routes +import { discoverEmberDataModels } from "ember-cli-mirage"; +import { createServer } from 'miragejs'; + +export default function(config) { + let finalConfig = { + ...config, + models: { ...discoverEmberDataModels(), ...config.models }, + routes() { + // this.namespace = '/api' + + // this.resource('user') + }, + }; + + return createServer(finalConfig); +} + +// Example with routes in an external function +import { discoverEmberDataModels } from "ember-cli-mirage"; +import { createServer } from 'miragejs'; + +export default function(config) { + let finalConfig = { + ...config, + models: { ...discoverEmberDataModels(), ...config.models }, + routes, + }; + + return createServer(finalConfig); +} + +function routes() { + // this.namespace = '/api' + + // this.resource('user') +} +``` + +## Serializers + +If you would like to have Mirage adjust or create your serializers for you from your ember data serializers adjust your +server configuration to have mirage perform this for you. + +When Mirage auto discovers your ember data models, should you also have the same model defined in mirage, it will use the mirage +version of the model. With serializers, you may have created a mirage serializer to override some methods, but would still +like Mirage to apply the primaryKey and transforms. For that reason the method to apply these properties is different than +the way you merge the models. + +`applyEmberDataSerializers` will apply the `primaryKey` and `attrs` from your ember data serializers to your mirage serializers. +If you have not created a mirage serializer it will create one and extend it from your mirage application serializer. +Ensure your application serializer extends from EmberDataSerializer as the default JSONApiSerializer will not understand +how to use `primaryKey` and `transforms`. If you have not created a mirage serializer named application, the created serializer +will extend EmberDataSerializer directly. + +```javascript +// Example of having Mirage adjust/create your serializers similiar to ember data models + +import { discoverEmberDataModels, applyEmberDataSerializers } from "ember-cli-mirage"; +import { createServer } from 'miragejs'; + +export function makeServer(config) { + let finalConfig = { + ...config, + models: { ...discoverEmberDataModels(), ...config.models }, + serializers: applyEmberDataSerializers(config.serializers), + routes, + }; + + return createServer(finalConfig); +} + +function routes() { + // this.namespace = '/api' + + // this.resource('user') +} +``` diff --git a/tests/dummy/app/pods/docs/advanced/simulating-cookie-responses/template.md b/tests/dummy/app/pods/docs/advanced/simulating-cookie-responses/template.md new file mode 100644 index 000000000..a4687381b --- /dev/null +++ b/tests/dummy/app/pods/docs/advanced/simulating-cookie-responses/template.md @@ -0,0 +1,25 @@ +# Simulating cookie responses + +Although Mirage allows setting headers in a response, the +XMLHttpRequest spec explicitly +[forbids access](http://www.w3.org/TR/XMLHttpRequest/#the-getresponseheader()-method) +to `Set-Cookie` and `Set-Cookie2` headers. As a result Mirage +responses cannot set cookies via headers. + +However, you can simulate receiving cookies from an ajax +call at the browser level by setting them in a route +function handler: + +```js +this.post('/users/login', schema => { + // log in for 24 hours + let now = new Date(); + let cookieExpiration = new Date(now.getTime() + (24 * 3600 * 1000)); + document.cookie=`remember_me=cookie-content-here; domain=.dev-domain; path=/; expires=${cookieExpiration.toUTCString()};`; + + return schema.users.find(1); +}); +``` + +Your Ember client code will now have access to any cookies set +using `document.cookie`. diff --git a/tests/dummy/app/pods/docs/advanced/switching-between-scenarios/template.md b/tests/dummy/app/pods/docs/advanced/switching-between-scenarios/template.md new file mode 100644 index 000000000..40e4021a0 --- /dev/null +++ b/tests/dummy/app/pods/docs/advanced/switching-between-scenarios/template.md @@ -0,0 +1,77 @@ +# Switching between scenarios + +Mirage adds a `/scenarios` directory to your project, where you'll find a `default.js` file. +The function in this file will run in development mode and act as your "development seeds". +In testing it's ignored, so that your Mirage server starts out with a clean database. You +can then use each test to seed Mirage as needed for that test. In this way, each test acts +as its own Mirage scenario. + +Originally Mirage was going to add first-class support for development-time scenario switching, +but currently only the `scenarios/default.js` file is used by Mirage. However, you can use various +strategies to configure the behavior of your default scenario, to support multiple development +server states or to facilitate things like running [user acceptance testing](https://en.wikipedia.org/wiki/Acceptance_testing#User_acceptance_testing). +For example, you might want to test whether a user can complete a set of tasks specific to unique circumstances defined in a scenario. + +One strategy you could take is to configure your default scenario file to honor options passed +to the runtime environment. For example, say you wanted to be able to run a scenario file like this: + +```bash +MIRAGE_SCENARIO=some-scenario ember s +``` + +To affect the behavior of `scenarios/default.js`, add the `MIRAGE_SCENARIO` ENV variable to your `environment/config.js`: + +```js +const { MIRAGE_SCENARIO } = process.env; + +module.exports = function(environment) { + const ENV = { + // ...other stuff + + MIRAGE_SCENARIO, + + // ...other stuff + }; + + return ENV; +} +``` + +Then access this new config variable in your `scenarios/default.js` file: + +```js +// scenarios/default.js +import ENV from '../../config/environment'; +import visitor from './visitor'; +import subscriber from './subscriber'; +import administrator from './administrator'; + +const scenarios = { + visitor, + subscriber, + administrator +} + +const activeScenario = ENV.MIRAGE_SCENARIO || 'visitor'; + +export default function(server) { + const scenario = scenarios[activeScenario]; + + if (scenario) { + scenario(server); + } + + // plus whatever default scenario code you want +} +``` + +Like other Mirage objects, all scenario files must export a function like so: + +```js +export default function(server) { + // server.createList('post', 15); +} +``` + +Note that the `server` parameter is not provided by default. + diff --git a/tests/dummy/app/pods/docs/data-layer/database/template.md b/tests/dummy/app/pods/docs/data-layer/database/template.md new file mode 100644 index 000000000..0dc9f7bc2 --- /dev/null +++ b/tests/dummy/app/pods/docs/data-layer/database/template.md @@ -0,0 +1,62 @@ +# The Database + +At the core of Mirage's data layer is a simple in-memory database. This database stores all of Mirage's initial state, and then your route handlers access and modify that state as you use your application. + +The database is what allows Mirage to mimic a production server, giving you the ability to write complete dynamic features in your Ember app. + +Most of your Mirage code will not access the database directly, but rather will interact with it through Mirage's ORM. We'll cover the ORM in the next section of these guides. + +However, it's good to know that whether or not you use the ORM, you can always interact with the database directly. + +For example, you could seed it with some data in `scenarios/default.js` + +```js +// scenarios/default.js +export default function(server) { + server.db.loadData({ + movies: [ + { title: 'Interstellar' }, + { title: 'Inception' }, + { title: 'Dunkirk' }, + ] + }); +} +``` + +and then can access it in your route handlers using the `schema` argument: + +```js +this.get('/movies', (schema, request) => { + return schema.db.movies; +}); +``` + +This route handler would then respond with the data you loaded: + +```js +[ + { id: '1', title: 'Interstellar' }, + { id: '2', title: 'Inception' }, + { id: '3', title: 'Dunkirk' } +] +``` + +Note that each record has an `id` field, since the database assigns all new records an auto-incrementing ID. + +The most common place you'll use the database directly is in your tests, where you can access it via `this.server.db`. It can be useful to assert against the state of Mirage's database to verify that your Ember app's network requests are sending over the correct data. + +```js +// tests/movie-test.js +test('I can create a movie', async function(assert) { + await visit('/movies/new'); + await fillIn('.title', 'The Dark Knight'); + await click('.submit'); + + assert.dom('h2').includesText('New movie saved!'); + assert.equal(this.server.db.movies[0].title, 'The Dark Knight'); +}); +``` + +You can view the rest of the Database APIs in the {{docs-link 'Db' 'docs.api.item' 'modules/db~Db'}} and {{docs-link 'DbCollection' 'docs.api.item' 'modules/db-collection~DbCollection'}} API reference. + +Next, we'll learn about Mirage's ORM. diff --git a/tests/dummy/app/pods/docs/data-layer/factories/template.md b/tests/dummy/app/pods/docs/data-layer/factories/template.md new file mode 100644 index 000000000..8cf6dbd28 --- /dev/null +++ b/tests/dummy/app/pods/docs/data-layer/factories/template.md @@ -0,0 +1,700 @@ +# Factories + +One of the main benefits of using Mirage is the ability to quickly put your server into different states. + +For example, you might be developing a feature and want to see how the UI renders for both a logged-in user and an anonymous user. This is the kind of thing that's a pain when using a real backend server, but with Mirage it's as simple as flipping a JavaScript variable and live-reloading your Ember app. + +**Factories** are classes that help you organize your data-creation logic, making it easier to define different server states during development or within tests. + +Let's see how they work. + +## Defining factories + +### Your first factory + +Say we have a `Movie` model defined in Mirage. (Remember, if you're using Ember Data you won't have this file on disk. The Model definition will be automatically generated for you.) + +```js +// mirage/models/movie.js +import { Model } from 'miragejs'; + +export default Model.extend({ +}); +``` + +To seed Mirage's database with some movies so you can start developing your app, use the `server.create` method in the `scenarios/default.js` file: + +```js +// mirage/scenarios/default.js +export default function(server) { + + server.create('movie'); + +} +``` + +`server.create` takes the singular hyphenated form of your model's class name as its first argument. + +Because we have no Factory defined for a `Movie`, `server.create('movie')` will just create an empty record and insert it into the database: + +```js +// server.db.dump(); +{ + movies: [ + { id: '1' } + ] +} +``` + +Not a very interesting record. + +However, we can pass attributes of our own as the second argument to `server.create`: + +```js +// mirage/scenarios/default.js +export default function(server) { + + server.create('movie', { + title: 'Interstellar', + releaseDate: '10/26/2014', + genre: 'Sci-Fi' + }); + +} +``` + +Now our database looks like this + +```js +{ + movies: [ + { + id: '1', + title: 'Interstellar', + releaseDate: '10/26/2014', + genre: 'Sci-Fi' + } + ] +} +``` + +and we'll actually be able to develop our UI against realistic data. + +This is a great way to start, but it can be cumbersome to manually define every attribute (and relationship) when working on data-driven applications. It would be nice if we had a way to dynamically generate some of these attributes. + +Fortunately, that's exactly what Factories let us do! + +Let's generate a Factory for our movie using + +``` +ember g mirage-factory movie +``` + +which creates this file: + +```js +// mirage/factories/movie.js +import { Factory } from 'miragejs'; + +export default Factory.extend({ +}); +``` + +Right now the Factory is empty. Let's define a property on it: + +```js +// mirage/factories/movie.js +import { Factory } from 'miragejs'; + +export default Factory.extend({ + + title: 'Movie title' + +}); +``` + +Now `server.create('movie')` will use the properties from this factory. The inserted record will look like this: + +```js +{ + movies: [ + { id: '1', title: 'Movie title' } + ] +} +``` + +We can also make this property a function. + +```js +// mirage/factories/movie.js +import { Factory } from 'miragejs'; + +export default Factory.extend({ + + title(i) { + return `Movie ${i}`; + } + +}); +``` + +`i` is an incrementing index that lets us make our factory attributes more dynamic. + +If we use the `server.createList` method, we can quickly generate five movies + +```js +server.createList('movie', 5); +``` + +and with the above factory definition, our database will look like this: + +```js +{ + movies: [ + { id: '1', title: 'Movie 1' }, + { id: '2', title: 'Movie 2' }, + { id: '3', title: 'Movie 3' }, + { id: '4', title: 'Movie 4' }, + { id: '5', title: 'Movie 5' } + ] +} +``` + +Let's add some more properties to our factory: + +```js +// mirage/factories/movie.js +import { Factory } from 'miragejs'; +import faker from 'faker'; + +export default Factory.extend({ + + title(i) { + return `Movie ${i}`; + }, + + releaseDate() { + return faker.date.past().toLocaleDateString(); + }, + + genre(i) { + let genres = [ 'Sci-Fi', 'Drama', 'Comedy' ]; + + return genres[i % genres.length]; + } + +}); +``` + +Here we've installed the [Faker.js](https://github.com/marak/Faker.js/) library to help us generate random dates. + +Now `server.createList('movie', 5)` gives us this data: + +```js +{ + movies: [ + { id: '1', title: 'Movie 1', releaseDate: '5/14/2018', genre: 'Sci-Fi' }, + { id: '2', title: 'Movie 2', releaseDate: '2/22/2019', genre: 'Drama' }, + { id: '3', title: 'Movie 3', releaseDate: '6/2/2018', genre: 'Comedy' }, + { id: '4', title: 'Movie 4', releaseDate: '7/29/2018', genre: 'Sci-Fi' }, + { id: '5', title: 'Movie 5', releaseDate: '6/30/2018', genre: 'Drama' }, + ] +} +``` + +As you can see, Factories let us rapidly generate different scenarios for our dynamic server data. + + +### Attribute overrides + +Factories are great for defining the "base case" of your models, but there's plenty of times where you'll want to override attributes from your factory with specific values. + +The last argument to `create` and `createList` accepts a POJO of attributes that will override anything from your factory. + +```js +// Using only the base factory +server.create('movie'); +// gives us this object: +{ id: '1', title: 'Movie 1', releaseDate: '01/01/2000' } + +// Passing in specific values to override certain attributes +server.create('movie', { title: 'Interstellar' }); +// gives us this object: +{ id: '2', title: 'Interstellar', releaseDate: '01/01/2000' } +``` + +Think of your factory attributes as a reasonable "base case" for your models, and then override them in development and testing scenarios as you have need for specific values. + + +### Dependent attributes + +Attributes can depend on other attributes via `this` from within a function. This can be useful for quickly generating things like usernames from names: + +```js +// mirage/factories/user.js +import { Factory } from 'miragejs'; +import faker from 'faker'; + +export default Factory.extend({ + + name() { + return faker.name.findName(); + }, + + username() { + return this.name.replace(' ', '').toLowerCase(); + } + +}); +``` + +Calling `server.createList('user', 3)` with this factory would generate this data: + +```js +[ + { id: '1', name: 'Retha Donnelly', username: 'rethadonnelly' } + { id: '2', name: 'Crystal Schaefer', username: 'crystalschaefer' } + { id: '3', name: 'Jerome Schoen', username: 'jeromeschoen' } +] +``` + + +### Relationships + +In the same way that you use the ORM to create relational data, as this example from the _Creating and editing related data_ section of the {{docs-link 'ORM guide' 'docs.data-layer.orm'}} illustrates + +```js +let nolan = schema.people.create({ name: 'Christopher Nolan' }); + +schema.movies.create({ + director: nolan, + title: 'Interstellar', +}); +``` + +you can also create relational data with your factories: + +```js +let nolan = server.create('director', { name: 'Christopher Nolan' }); + +server.create('movie', { + director: nolan, + title: 'Interstellar' +}); +``` + +`nolan` is a model instance, which is why we can just pass it in as an attribute override when creating the Interstellar movie. + +This also works when using `createList`: + +```js +server.create('actor', { + movies: server.createList('movie', 3) +}); +``` + +In this way you use factories to help you quickly create graphs of relational data: + +```js +server.createList('user', 5).forEach(user => { + server.createList('post', 10, { user }).forEach(post => { + server.createList('comment', 5, { post }); + }); +}); +``` + +This code generates 5 users, each of which has 10 posts with each post having 5 comments. Assuming these relationships are defined in your models, all the foreign keys would be set correctly in Mirage's database. + + +### The afterCreate hook + +In many cases, setting up relationships manually (as shown in the previous section) is perfectly fine. However there are times where it makes more sense to have base case relationships set up for you automatically. + +Enter `afterCreate`. It's a hook that's called after a model has been created using the factory's base attributes. This hook lets you perform additional logic on your newly-created models before they're returned from `create` and `createList`. + +Let's see how it works. + +Say you have these two models in your app: + +```js +// mirage/models/user.js +export default Model.extend({ +}); + +// mirage/models/post.js +export default Model.extend({ + post: belongsTo() +}); +``` + +Let's further suppose that in your app, it is never valid to create a post without an associated user. + +You can use `afterCreate` to enforce this behavior: + +```js +// mirage/factories/post.js +export default Factory.extend({ + + afterCreate(post, server) { + post.update({ + user: server.create('user') + }); + } + +}); +``` + +The first argument to `afterCreate` is the object that was just created (in this case the `post`), and the second is a reference to the Mirage server instance, so that you can invoke other factories or inspect any other server state needed to customize your newly-created object. + +In this example we're immediately creating a user for this post. That way elsewhere in your app (say a test), you could just create a post + +```js +server.create('post'); +``` + +and you'd be working with a valid record, since that post would have an associated user. + +Now, there's one problem with the way we've implemented this so far. Our `afterCreate` hook updates the post's user _regardless if that post already had a user associated with it_. + +That means that this code + +```js +let tomster = server.create('user', 'Tomster'); +server.createList('post', 10, { user: tomster }); +``` + +would not work as we expect, since the attribute overrides while the object is being created, but the logic in `afterCreate` runs _after_ the post has been created. Thus, this post would be associated with the newly created post from the hook, rather than Tomster. + +To fix this, we can update our `afterCreate` hook to first check if the newly created post already has a user associated with it. Only if it doesn't will we create a new one and update the relationship. + +```js +// mirage/factories/post.js +export default Factory.extend({ + + afterCreate(post, server) { + if (!post.user) { + post.update({ + user: server.create('user') + }); + } + } + +}); +``` + +Now callers can pass in specific users + +```js +server.createList('post', 10, { user: tomster }); +``` + +or omit specifying a user if the details of that user aren't important + +```js +server.create('post'); +``` + +and in both cases they'll end up with a valid record. + +`afterCreate` can also be used to create `hasMany` associations, as well as apply any other relevant creation logic. + + +### Traits + +Traits are an important feature of factories that make it easy to group related attributes. Define them by importing `trait` and adding a new key to your factory. + +For example, here we define a trait named `published` on our post factory: + +```js +// mirage/factories/post.js +import { Factory, trait } from 'miragejs'; + +export default Factory.extend({ + title: 'Lorem ipsum', + + published: trait({ + isPublished: true, + publishedAt: '2010-01-01 10:00:00' + }) +}); +``` + +You can pass anything into `trait` that you can into the base factory. + +We can use our new trait by passing in the name of the trait as a string argument to `create` or `createList`: + +```js +server.create('post', 'published'); +server.createList('post', 3, 'published'); +``` + +The created posts will have all the base attributes, as well as everything under the `published` trait. + +You can also compose multiple traits together: + +```js +// mirage/factories/post.js +import { Factory, trait } from 'miragejs'; + +export default Factory.extend({ + title: 'Lorem ipsum', + + published: trait({ + isPublished: true, + publishedAt: '2010-01-01 10:00:00' + }), + + official: trait({ + isOfficial: true + }) +}); +``` + +We can pass our new traits into `create` or `createList` in any order: + +```js +let officialPost = server.create('post', 'official'); +let officialPublishedPost = server.create('post', 'official', 'published'); +``` + +If multiple traits set the same attribute, the last trait wins. + +As always, you can pass in an object of attribute overrides as the last argument: + +```js +server.create('post', 'published', { title: 'My first post' }); +``` + +When combined with the `afterCreate()` hook, traits simplify the process of setting up related object graphs. + +Here we define a `withComments` trait that creates 3 comments for a newly created post: + +``` js +// mirage/factories/post.js +import { Factory, trait } from 'miragejs'; + +export default Factory.extend({ + title: 'Lorem ipsum', + + withComments: trait({ + afterCreate(post, server) { + server.createList('comment', 3, { post }); + } + }) +}); +``` + +We can use this trait to quickly make 10 posts with 3 comments each: + +```js +server.createList('post', 10, 'withComments'); +``` + +Combining traits with the `afterCreate` hook is one of the most powerful features of Mirage factories. Effective use of this technique will dramatically simplify the process of creating different graphs of relational data for your app. + + +### The association helper + +The `association()` helper provides some sugar for creating `belongsTo` relationships. + +As we saw earlier, given a `Post` that `belongsTo` a `User`, we were able to use the `afterCreate` hook to pre-wire that relationship: + +```js +// mirage/factories/post.js +import { Factory } from 'miragejs'; + +export default Factory.extend({ + + afterCreate(post, server) { + if (!post.user) { + post.update({ + user: server.create('user') + }); + } + } + +}); +``` + +The `association()` helper effectively replaces this code: + +```js +// mirage/factories/post.js +import { Factory, association } from 'miragejs'; + +export default Factory.extend({ + + user: association() + +}); +``` + +This should help reduce some of the boilerplate in your factory definitions. + +You can also use `association()` within traits + +```js +// mirage/factories/post.js +import { Factory, association, trait } from 'miragejs'; + +export default Factory.extend({ + + withUser: trait({ + user: association() + }) + +}); +``` + +and it also accepts additional traits and overrides for the related model's factory: + +```js +// mirage/factories/post.js +import { Factory, association, trait } from 'miragejs'; + +export default Factory.extend({ + + withUser: trait({ + user: association('admin', { role: 'editor' }) + }) + +}); +``` + +There is no equivalent helper for `hasMany` relationships, so you can continue to use the `afterCreate` hook to seed those relationships. + + +## Using factories + +### In development + +To use your factories to seed your development database, call `server.create` and `server.createList` in your `scenarios/default.js` file: + +```js +// mirage/scenarios/default.js +export default function(server) { + server.createList('movie', 10); +} +``` + +There's no explicit API for switching scenarios in development, but you can just use JavaScript modules to split things up. + +For example, you could create a new file for each scenario that contains some seeding logic + +```js +// mirage/scenarios/admin.js +export default function(server) { + server.create('user', { isAdmin: true }); +} +``` + +...export all scenarios as an object from an `index.js` file + +```js +// mirage/scenarios/index.js +import anonymous from './anonymous'; +import subscriber from './subscriber'; +import admin from './admin'; + +export default scenarios = { + anonymous, + subscriber, + admin +} +``` + +...and then import that object into `default.js`. + +Now you can quickly switch your development state by changing a single variable: + +```js +// mirage/scenarios/default.js +import scenarios from './index'; + +// Choose one +const state = + // 'anonymous' + // 'subscriber' + 'admin' +; +export default function(server) { + scenarios[state](server); +} +``` + +This can be handy while developing your app or sharing the different states of a new feature with your team. + + +### In testing + +When running your app in the `test` environment, your entire Mirage server is loaded, _except_ for your `scenarios/default.js` file. + +That means each test starts out with a clean database, giving you the opportunity to set up only the state needed for that test. It also keeps your development scenarios isolated from your tests, so that you don't inadvertently break your test suite while tweaking your development scenario. + +To seed Mirage's database within a test, use `this.server` to access the `create` and `createList` methods: + +```js +test('I can see the movies on the homepage', async function(assert) { + this.server.createList('movie', 5); + + await visit('/'); + + assert.dom('li.movie').exists({ length: 5 }); +}); +``` + +In this test, we start our Mirage server out with 5 movies. Then we boot up the Ember app and visit the `/` route, and finally assert that those movies show up in our UI. + +When we write another test, the database will start out empty so that none of Mirage's state leaks across tests. + +You can read more about testing with Mirage in the {{docs-link 'Testing' 'docs.testing.acceptance-tests'}} section of these guides. + + +## Factory best practices + +In general, it's best to define a model's base factory using only the attributes and relationships that comprise the minimal valid state for that model. You can then use `afterCreate` and traits to define other common states that contain valid, related changes on top of the base case. + +This advice goes a long way towards keeping your test suite maintainable. + +If you don't use traits and `afterCreate`, your tests will become bogged down in irrelevant details related to setting up the data needed for that test. + +```js +test('I can see the title of a post', async function(assert) { + let session = server.create('session'); + let user = server.create('user', { session }); + server.create('post', { + user, + title: 'My first post', + slug: 'my-first-post' + }); + + await visit('/post/my-first-post'); + + assert.dom('h1').hasText('My first post'); +}); +``` + +This test is only concerned with asserting the title of a post gets rendered to the screen, but it has lots of boilerplate code that's only there to get the post in a valid state. + +If we used `afterCreate` instead, the developer writing this test could simply create a post with a specified `title` and `slug`, since those are the only details relevant to the test: + +```js +test('I can see the title of a post', async function(assert) { + server.create('post', { + title: 'My first post', + slug: 'my-first-post' + }); + + await visit('/post/my-first-post'); + + assert.dom('h1').hasText('My first post'); +}); +``` + +`afterCreate` could take care of setting up the session and user in valid states, and associating the user with the post, so that the test can stay concise and focused on what it's actually testing. + +Effective use of traits and `afterCreate` keeps your test suite less brittle and more robust to changes in your data layer, since tests only declare the bare minimum setup logic needed to verify their assertions. + +--- + +Up next, we'll take a look at how to use Fixtures as an alternative way to seed your database. diff --git a/tests/dummy/app/pods/docs/data-layer/fixtures/template.md b/tests/dummy/app/pods/docs/data-layer/fixtures/template.md new file mode 100644 index 000000000..485021f71 --- /dev/null +++ b/tests/dummy/app/pods/docs/data-layer/fixtures/template.md @@ -0,0 +1,193 @@ +# Fixtures + +Mirage also lets you use flat fixture files to seed your database with data. + +In general, we recommend using factories for most situations, since they tend to keep your mock data more maintainable. But there are certainly times where fixture data makes sense. + +Fixtures are nothing more than a conventional file-based way to accomplish the following: + +```js +// mirage/scenarios/default.js +export default function(server) { + server.db.loadData({ + countries: [ + { id: 1, name: 'China' }, + { id: 2, name: 'India' }, + { id: 3, name: 'United States' } + ] + }); +} +``` + +Let's see how we can do the same thing using fixtures. + + +## Basic usage + +We'll start by generating a fixture file for our `Country` model: + +``` +ember g mirage-fixture countries +``` + +Fixture filenames should be the dasherized plural form of the model class. + +We can now add some data to our fixture file: + +```js +// mirage/fixtures/countries.js +export default [ + { id: 1, name: 'China', largestCity: 'Shanghai' }, + { id: 2, name: 'India', largestCity: 'Mumbai' }, + { id: 3, name: 'United States', largestCity: 'New York City' }, + { id: 4, name: 'Indonesia', largestCity: 'Jakarta' }, + { id: 5, name: 'Pakistan', largestCity: 'Karachi' }, + { id: 6, name: 'Brazil', largestCity: 'São Paulo' }, + { id: 7, name: 'Nigeria', largestCity: 'Lagos' }, + { id: 8, name: 'Bangladesh', largestCity: 'Dhaka' }, + { id: 9, name: 'Russia', largestCity: 'Moscow' }, + { id: 10, name: 'Mexico', largestCity: 'Mexico City' }, +]; +``` + +Because this data will be read directly into Mirage's database, we want to use camelCase for all multi-word attributes. (Mirage uses the camelCasing convention to avoid configuration for things like identifying foreign keys.) + +Don't worry if your production API format doesn't use camelCase. We'll be able to customize Mirage's API format in the Serializer layer. + +To load our new fixture file into the database during development, we can call `server.loadFixtures` in our `scenarios/default.js` file: + +```js +// mirage/scenarios/default.js +export default function(server) { + server.loadFixtures(); +} +``` + +If we have multiple fixtures defined, `server.loadFixtures()` will load every file. You can load files selectively by passing in an argument list of fixture names to `loadFixtures`: + +```js +// mirage/scenarios/default.js +export default function(server) { + server.loadFixtures('countries', 'cities'); // only load the countries and cities fixtures +} +``` + +Just like with factories, fixtures will be ignored during tests. If you want to load fixture data in a test, you can call `this.server.loadFixtures`: + +```js +test('I can see the countries', async function(assert) { + this.server.loadFixtures('countries'); + + await visit('/'); + + assert.dom('option.country').exists({ length: 100 }); +}); +``` + +## Relationships + +There's no special API for creating relationships using fixtures – you just need to understand how Mirage uses foreign keys to wire up relationships. + +Let's say we had these models: + +```js +// mirage/models/user.js +export default Model.extend({ +}); + +// mirage/models/post.js +export default Model.extend({ + author: belongsTo('user') +}); +``` + +Using the ORM we can create two related models: + +```js +let chris = schema.users.create({ name: 'Chris Garrett' }); + +schema.posts.create({ + author: chris, + title: 'Coming Soon in Ember Octane' +}); +``` + +If we take a look at Mirage's database after this, we'll see this data: + +```js +// server.db.dump() +{ + users: [ + { id: '1', name: 'Chris Garrett' } + ], + posts: [ + { id: '1', authorId: '1', title: 'Coming Soon in Ember Octane' } + ] +} +``` + +As you can see, Mirage added an `authorId` foreign key to the post. The convention for belongsTo foreign keys is + +```js +`${relationshipName}Id` +``` + +In this case, a post gets an `authorId`, even though that relationship points to a `User` model. The relationship name is always used rather than the model name, because models can have multiple relationships that point to the same type of model. + +Looking at the database dump above, if you wanted to recreate the same relationship graph using only fixture files, your files would look something like this: + +```js +// mirage/fixtures/users.js +export default [ + { id: '1', name: 'Chris Garrett' } +]; + +// mirage/fixtures/posts.js +export default [ + { id: '1', authorId: '1', title: 'Coming Soon in Ember Octane' } +]; +``` + +Once these fixtures are loaded into Mirage, all the ORM methods, Shorthands and Serializers would work as expected. + +If this happens to be a bi-directional relationship + +```diff + // mirage/models/user.js + export default Model.extend({ ++ posts: hasMany() + }); + + // mirage/models/post.js + export default Model.extend({ + author: belongsTo('user') + }); +``` + +then Mirage will add an array of foreign keys on the new hasMany association: + +```js +// mirage/fixtures/users.js +export default [ + { id: '1', postIds: [ '1' ], name: 'Chris Garrett' } +]; + +// mirage/fixtures/posts.js +export default [ + { id: '1', authorId: '1', title: 'Coming Soon in Ember Octane' } +]; +``` + +The convention for hasMany relationship foreign keys is + +```js +`${singularize(relationshipName)}Ids` +``` + +All associations have their own keys, because Mirage supports arbitrary one-way relationships. If two associations are inverses of each other, as in the above case, Mirage will keep the keys on each model in sync provided you use the ORM methods. + +As you can see, maintaining foreign keys and keeping them in sync across fixture files can get a little messy, which is why Mirage recommends using factories for most of your data creation. + +Still, fixtures can be quite useful in certain situations, so they're a good tool to have in your toolbox. + +--- diff --git a/tests/dummy/app/pods/docs/data-layer/models/template.md b/tests/dummy/app/pods/docs/data-layer/models/template.md new file mode 100644 index 000000000..c05d3f57e --- /dev/null +++ b/tests/dummy/app/pods/docs/data-layer/models/template.md @@ -0,0 +1,111 @@ +# Models + +To take advantage of the ORM, Mirage needs to know about your application's models and their relationships. This section will teach you how to define and work with your models, and the next will discuss relationships. + +**Note that if your Ember application uses Ember Data, Mirage will automatically discover your models and their relationships**, so you don’t need to define any files within Mirage yourself. + +As a clarifying point, Mirage model instances only exist within Mirage's server, and are never shared directly with your Ember app or rendered directly in components. They exist solely to help you manage the data and relationships in your fake backend, but are serialized as a JSON string before they are sent over to your Ember app. + +## Defining models + +To define a model, you can use the generator: + +```sh +ember g mirage-model blog-post +``` + +This creates a file under `/mirage/models`: + +```js +// mirage/models/blog-post.js +import { Model } from 'miragejs'; + +export default Model; +``` + +## Creating models + +To create models, access the model's collection via the `schema` object, which is available in your route handlers: + +```js +this.post('/blog-posts', function(schema) { + let attrs = this.normalizedRequestAttrs(); + + schema.blogPosts.create(attrs); +}); +``` + +or as `server.schema` directly off of your Mirage server instance: + +```js +// scenarios/default.js +export default function(server) { + server.schema.blogPosts.create({ title: 'Lorem ipsum' }); +} +``` + +Note that the collection is the pluralized form of the model's model name (the `models/blog-post.js` definition from above creates a `schema.blogPosts` collection). + +Outside of route handlers, you'll typically create models using Factories via `server.create` + +```js +// scenarios/default.js +export default function(server) { + server.create('blog-post'); +} +``` + +which delegates to the collection's `create` method under the hood. We'll talk more about creating data using Factories later in these guides. + + +## Accessing models + +To access your models, use the various query methods from the model's collection. + +For example, use `all()` to return all known models: + +```js +this.get('/blog-posts', (schema, request) => { + return schema.blogPosts.all(); +}); +``` + +Here are some other common query methods: + +```js +schema.blogPosts.find(1); +schema.blogPosts.first(); +schema.blogPosts.where({ isPublished: true }); +schema.blogPosts.findBy({ title: 'Introduction' }); +``` + +Check out the {{docs-link 'Schema API docs' 'docs.api.item' 'modules/orm/schema~Schema'}} to see all available query methods. + + +## Updating and deleting models + +Once you're working with an instance of a model, there are other properties and methods you'll have access to. + +For example, you can update a model: + +```js +let post = schema.blogPosts.find(1); + +post.update({ author: 'Obi-Wan' }); +``` + +or delete one: + +```js +let post = schema.blogPosts.find(2); + +post.destroy(); +``` + +View the {{docs-link 'Model API docs' 'docs.api.item' 'modules/orm/model~Model'}} to see all the available fields and methods for model instances. + +--- + +Once your Models have been defined, the next step is to define the relationships between them, so you can really start to leverage the power of Mirage's ORM. + +Let's talk about how to do that next. diff --git a/tests/dummy/app/pods/docs/data-layer/orm/template.md b/tests/dummy/app/pods/docs/data-layer/orm/template.md new file mode 100644 index 000000000..a4212963c --- /dev/null +++ b/tests/dummy/app/pods/docs/data-layer/orm/template.md @@ -0,0 +1,399 @@ +# Why an ORM? + +Mirage originally shipped with just a database as its data layer. While helpful, users still had to write a lot of code to reproduce their modern, complex backends. In particular, dealing with relationships was a big pain point. + +The solution was to add an Object Relational Mapper, or ORM, to Mirage. + +Let's see how an ORM allows Mirage to do more of the heavy lifting for you. + + +## Motivation + +Consider a database that looks like this: + +```js +db.dump(); + +// Result +{ + movies: [ + { id: '1', title: 'Interstellar' }, + { id: '2', title: 'Inception' }, + { id: '3', title: 'Dunkirk' } + ] +} +``` + +The first problem you'll encounter when writing a route handler is how to transform this raw data into the format your Ember app expects – that is, how to match the format of your production API. + +Let's say your backend uses [the JSON:API spec](https://jsonapi.org/). Your response to a GET request for `/api/movies/1` should look something like this: + +```js +// GET /api/movies/1 +{ + data: { + id: '1', + type: 'movies', + attributes: { + title: 'Interstellar' + } + } +} +``` + +Not a huge deal – we could just write this formatting logic directly in our route handler: + +```js +this.get('/movies/:id', (schema, request) => { + let movie = schema.db.movies.find(request.params.id); + + return { + data: { + id: movie.id, + type: 'movies', + attributes: { + title: movie.title + } + } + }; +}); +``` + +This works. But let's say our `Movie` model had a few more attributes: + +```js +{ + id: '1', + title: 'Interstellar', + releaseDate: 'October 26, 2014', + genre: 'Sci-Fi' +} +``` + +Now our route handler needs to be more clever, and make sure all properties other than `id` end up in the `attributes` hash: + +```js +this.get('/movies/:id', (schema, request) => { + let movie = schema.db.movies.find(request.params.id); + let movieJSON = { + data: { + id: movie.id, + type: 'movies', + attributes: { } + } + }; + Object.keys(movie) + .filter(key => key !=== 'id') + .forEach(key => { + movieJSON[key] = movie[key]; + }); + + return movieJSON; +}); +``` + +As you can see, things get complicated pretty fast. + +What if we add relationships to the mix? Let's say a `Movie` has a relationship to a `director`, and it stores that relationship using a `directorId` foreign key: + +```js +{ + id: '1', + title: 'Interstellar', + releaseDate: 'October 26, 2014', + genre: 'Sci-Fi', + directorId: '23' +} +``` + +The expected HTTP response for this model now looks like this + +```js +{ + data: { + id: '1', + type: 'movies', + attributes: { + title: 'Interstellar' + }, + relationships: { + directors: { + data: { type: 'people', id: '23' } + } + } + } +} +``` + +meaning our route handlers need to get even more complex. In particular, they need a robust way to differentiate between a model's attributes (like `title`) and its relationship keys (like `directorId`). + +These sorts of problems turn out to be common enough that we can solve them generally, provided Mirage is aware of your application's models and their relationships. + + +## Problems solved by the ORM + +When Mirage knows about your application's domain, it can shoulder the responsibility for the low-level bookkeeping work needed to properly implement your mock server. + +Let's take a look at some examples of how it does this. + + +### Separation of formatting logic + +To start, we can tell Mirage about our application's schema by defining Mirage models. These models get registered with the ORM and tell Mirage about the shape of your data. + +Let's define a `Movie` model. + +```js +// mirage/models/movie.js +import { Model } from 'miragejs'; + +export default Model.extend({ +}); +``` + +Mirage models are _schemaless in attributes_, in that they don't require you to define plain attributes like `title` and `releaseDate`. So, the above model definition works regardless of what attributes your `Movie` model has. + +If you're using Ember Data, Mirage's ORM will automatically register your Ember Data models for you at run time, so you don't have to duplicate your domain information in two places. + +With the `Movie` model defined, we can update our route handler to use the ORM to respond with a Mirage model instance: + +```js +this.get('/movies/:id', (schema, request) => { + let id = request.params.id; + + return schema.movies.find(id); +}); +``` + +The `schema` argument is how you interact with the ORM. + +By returning an instance of a Mirage model from a route handler instead of a plain JavaScript object, we can now take advantage of Mirage's Serializer layer. Serializers work by turning Models and Collections into formatted JSON responses. + +Mirage ships with a JSONAPISerializer out of the box, so assuming it's defined as your Application serializer + +```js +// mirage/serializers/application.js +import { JSONAPISerializer } from 'miragejs'; + +export default JSONAPISerializer.extend({ +}); +``` + +this route handler will now respond with the payload we expect: + +```js +{ + data: { + id: '1', + type: 'movies', + attributes: { + title: 'Interstellar', + releaseDate: 'October 26, 2014', + genre: 'Sci-Fi' + } + } +} +``` + +The ORM is already helping us keep our route handlers tidy by delegating the work of transforming our models into JSON to the Serializer layer. + +But it gets even more powerful when we add relationships to the mix. + + +### Fetching related data + +Let's say our `Movie` has a belongs-to relationship with a `director`: + +```js +// mirage/models/movie.js +import { Model, belongsTo } from 'miragejs'; + +export default Model.extend({ + + director: belongsTo('person') + +}); +``` + +The `director` is an instance of a `Person` model: + +```js +// mirage/models/person.js +import { Model } from 'miragejs'; + +export default Model.extend({ +}); +``` + +Again, if you're using Ember Data, both the models and relationships will be automatically generated for you. No need to create this file. + +Without changing anything about our route handler or serializer, we can now fetch a graph of data by using JSON:API includes. + +The following request + +``` +GET /api/movies/1?include=director +``` + +will now generate this response: + +```js +{ + data: { + id: '1', + type: 'movies', + attributes: { + title: 'Interstellar', + releaseDate: 'October 26, 2014', + genre: 'Sci-Fi' + }, + relationships: { + director: { + data: { type: 'people', id: '1' } + } + } + }, + included: [ + { + id: '1', + type: 'people', + attributes: { + name: 'Christopher Nolan' + } + } + ] +} +``` + +The JSONAPISerializer is able to inspect the ORM so that it can put all models, attributes and relationships in the right place. Our route handler doesn't need to change at all. + +In fact, the route handler we wrote is the same as the default behavior of the Shorthand, meaning we can just switch to using that: + +```diff +- this.get('/movies/:id', (schema, request) => { +- let id = request.params.id; + +- return schema.movies.find(id); +- }); ++ this.get('/movies/:id'); +``` + +This is another example of how the ORM helps various parts of Mirage, like Shorthands and Serializers, work together to simplify your server definition. + + +### Creating and editing related data + +The ORM also makes creating and editing related data easier than if you only worked with the raw database records. + +For instance, to create a `Movie` and `Person` with a relationship using only the database, you'd need to do something like this: + +```js +server.db.loadData({ + people: [ + { + id: '1', + name: 'Christopher Nolan' + } + ], + movies: [ + { + id: '1', + title: 'Interstellar', + releaseDate: 'October 26, 2014', + genre: 'Sci-Fi', + directorId: '1' + } + ] +}); +``` + +Note the `directorId` foreign key on the `Movies` record must match the `id` on the associated `People` record. + +Managing raw database data like this quickly gets unwieldy, especially as relationships change over time. + +Using the ORM via `server.schema`, we can create this graph without managing any IDs: + +```js +let nolan = schema.people.create({ name: 'Christopher Nolan' }); + +schema.movies.create({ + director: nolan, + title: 'Interstellar', + releaseDate: 'October 26, 2014', + genre: 'Sci-Fi' +}); +``` + +Passing in the model instance `nolan` as the `director` attribute when creating the movie is enough for all the keys to be properly set up. + +The ORM also keeps foreign keys in sync as relationships are edited. Given the database + +```js +{ + movies: [ + { + id: '1', + title: 'Star Wars: The Rise of Skywalker', + directorId: '2' + } + ], + people: [ + { + id: '2', + name: 'Rian Johnson' + }, + { + id: '3', + name: 'J.J. Abrams' + } + ] +} +``` + +we could update the movie's director like this: + +```js +let episode9 = schema.movies.findBy({ + title: 'Star Wars: The Rise of Skywalker' +}); + +episode9.update({ + director: schema.people.findBy({ name: 'J.J. Abrams' }); +}); +``` + +The new database would look like this: + +```js +{ + movies: [ + { + id: '1', + title: 'Star Wars: The Rise of Skywalker', + directorId: '3' + } + ], + people: [ + { + id: '2', + name: 'Rian Johnson' + }, + { + id: '3', + name: 'J.J. Abrams' + } + ] +} +``` + +Note how the `directorId` was changed in the database, even though we only ever worked with model instances. + +Importantly, this also holds true for more complex relationships, like one-to-many or many-to-many relationships that have an inverse. + +The ORM allows Mirage to abstract all this bookkeeping away from your code, and even gives Shorthands enough power to respect arbitrary updates to complex relationship graphs. + +--- + +These are some of the main problems addressed by Mirage's ORM. Generally, when Mirage knows about your application's schema, it can take on more of the responsibility of configuring your mock server. + +Next, we'll take a look at how to actually define your models and their relationships in Mirage. diff --git a/tests/dummy/app/pods/docs/data-layer/relationships/template.md b/tests/dummy/app/pods/docs/data-layer/relationships/template.md new file mode 100644 index 000000000..fe3d6c99d --- /dev/null +++ b/tests/dummy/app/pods/docs/data-layer/relationships/template.md @@ -0,0 +1,213 @@ +# Relationships + +Once you've defined your models, you can define relationships between them using the `belongsTo` and `hasMany` helpers. Each helper adds some dynamic methods to your model. + +Just as another reminder, if you use Ember Data and have models and relationships defined there, you don't need to define any relationships within your Mirage folder, as those will be automatically discovered and set up for you. + +## belongsTo + +To define a to-one relationship, import the `belongsTo` helper and define a new property on a model that points to another model: + +```js +// mirage/models/blog-post.js +import { Model, belongsTo } from "ember-cli-mirage"; + +export default Model.extend({ + author: belongsTo() +}); +``` + +This defines a `belongsTo` relationship to an `Author` model. + +The `belongsTo` helper adds several new properties and methods to your models. + +In this case, our `blog-post` model would now have an `authorId` property, as well as some methods for working with the associated `author` model: + +```js +blogPost.authorId; // 1 +blogPost.authorId = 2; // updates the relationship +blogPost.author; // Author instance +blogPost.author = anotherAuthor; +blogPost.newAuthor(attrs); // new unsaved author +blogPost.createAuthor(attrs); // new saved author (updates blogPost.authorId in memory only) +``` + +Note that when a child calls `child.createParent`, the new parent is immediately saved to the `db`, but the child's foreign key is updated _on this instance only_, and is not immediately persisted to the database. + +In other words, `blogPost.createAuthor` will create a new `author` record, insert it into the `db`, and update the `blogPost.authorId` in memory, but if you were to fetch the `blogPost` from the `db` again, the relationship would not be persisted. + +To persist the new foreign key, you would call `blogPost.save()` after creating the new author. + +## hasMany + +To define a to-many relationship, use the `hasMany` helper: + +```js +// mirage/models/blog-post.js +import { Model, hasMany } from "ember-cli-mirage"; + +export default Model.extend({ + comments: hasMany() +}); +``` + +This helper adds a `commentIds` property to the `blogPost` model, as well as some methods for working with the associated `comments` collection: + +```js +blogPost.commentIds; // [1, 2, 3] +blogPost.commentIds = [2, 3]; // updates the relationship +blogPost.comments; // array of related comments +blogPost.comments = [comment1, comment2]; // updates the relationship +blogPost.newComment(attrs); // new unsaved comment +blogPost.createComment(attrs); // new saved comment (comment.blogPostId is set) +``` + +## Association options + +### modelName + +If your associations model has a different name than the association itself, you can specify the `modelName` on the association. + +For example, + +```js +// mirage/models/blog-post.js +import { Model, belongsTo, hasMany } from "ember-cli-mirage"; + +export default Model.extend({ + author: belongsTo("user"), + comments: hasMany("annotation") +}); +``` + +would add all the named `author` and `comment` methods as listed above, but use `user` and `annotation` models for the actual relationships. + +### inverse + +Often, relationships can be inverses of each other. + +For example, say we had the following two models: + +```js +// blog-post.js +export default Model.extend({ + comments: hasMany() +}); + +// comment.js +export default Model.extend({ + blogPost: belongsTo() +}); +``` + +In this case, `blogPost.comments` would point to a collection of Comment models, and each one of those Comment models would have a `comment.blogPost` relationship that pointed back to the original post. + +Mirage will often be able to infer that two relationships on two different models are inverses of each other, but sometimes you'll need to be explicit. This typically happens if a model has two relationships that point to the same model type. + +For example, suppose we had the following schema: + +```js +// user.js +export default Model.extend({ + blogPosts: hasMany() +}); + +// blog-post.js +export default Model.extend({ + author: belongsTo("user"), + reviewer: belongsTo("user") +}); +``` + +In this case, Mirage doesn't know which relationship (`blogPost.author` or `blogPost.reviewer`) should by synchronized with the parent's `user.blogPosts` collection. So, you can specify which one by using the `inverse` option: + +```js +// user.js +export default Model.extend({ + blogPosts: hasMany() +}); + +// blog-post.js +export default Model.extend({ + author: belongsTo("user", { inverse: "blogPosts" }), + reviewer: belongsTo("user", { inverse: null }) +}); +``` + +Now, if a blog post is added to `user.blogPosts`, that post's `author` will be correctly set. + +### polymorphic + +You can specify whether an association is a polymorphic association by passing `{ polymorphic: true }` as an option. + +For example, say you have a `Comment` that can belong to a `BlogPost` or a `Picture`. Here's how the model definitions would look: + +```js +// app/models/comment.js +export default Model.extend({ + commentable: belongsTo({ polymorphic: true }) +}); + +// app/models/blog-post.js +export default Model.extend({ + comments: hasMany() +}); + +// app/models/picture.js +export default Model.extend({ + comments: hasMany() +}); +``` + +Note that `commentable` doesn't need a type (there's no validation done on which types of models can exist on that association). + +Polymorphic associations have slightly different method signatures for their foreign keys and build/create methods. + +```js +let comment = schema.comments.create({ text: "foo" }); + +comment.buildCommentable("post", { title: "Lorem Ipsum" }); +comment.createCommentable("post", { title: "Lorem Ipsum" }); + +// getter +comment.commentableId; // { id: 1, type: 'blog-post' } + +// setter +comment.commentableId = { id: 2, type: "picture" }; +``` + +Has-many asssociations can also be polymorphic: + +```js +// app/models/user.js +export default Model.extend({ + things: hasMany({ polymorphic: true }) +}); + +// app/models/car.js +export default Model.extend({ +}); + +// app/models/watch.js +export default Model.extend({ +}); + +let user = schema.users.create({ name: "Sam" }); + +user.buildThing('car', { attrs }); +user.createThing('watch', { attrs }); + +// getter +user.thingIds; // [ { id: 1, type: 'car' }, { id: 3, type: 'watch' }, ... ] + +// setter +user.thingIds = [ { id: 2, type: 'watch' }, ... ]; +``` + +--- + +Be sure to check out the {{docs-link 'Schema' 'docs.api.item' 'modules/orm/schema~Schema'}}, {{docs-link 'Model' 'docs.api.item' 'modules/orm/model~Model'}} and {{docs-link 'Collection' 'docs.api.item' 'modules/orm/collection~Collection'}} API docs to learn about all the available ORM methods. + +We'll also cover Serializers in these guides, where you'll learn how to customize the serialized forms of your models and collections to match your production API. + +Next, let's take a look at Factories, which leverage your new Model and Relationship definitions to make it easy to create graphs of relational data. diff --git a/tests/dummy/app/pods/docs/data-layer/serializers/ember-data-serializer/template.md b/tests/dummy/app/pods/docs/data-layer/serializers/ember-data-serializer/template.md new file mode 100644 index 000000000..13b3f2b9d --- /dev/null +++ b/tests/dummy/app/pods/docs/data-layer/serializers/ember-data-serializer/template.md @@ -0,0 +1,46 @@ +The `EmberDataSerializer` extends the `RestSerializer` with the added functionality of`primaryKey` and `attrs` +(renamed `transforms` as `attrs` was already in use by Mirage) properties. +These properties work the same as the properties provided. + +## Primary Key +This serializer provides for a property `primaryKey` that works the same as the `primaryKey` property on an ember data serializer. +By default this property will be `id` but if you assign a different value, that value will be used in the JSON instead of `id`. +This means that if you are using the `primaryKey` property on your ember data serializer, using the same property on the mirage serializer +will perform the same function. +If you were using the `RestSerializer` you would need to override the `serialize` and `normalize` functions to do the transform yourself. + +Using `EmberDataSerializer` you can let the serializer perform this transformation for you. To be clear, when data is received by Mirage, this will take the +value of `addressId` from the JSON and use it as the `id` for the Mirage model. When Mirage serializers it's model into JSON, it will +use the value for the `id` property and assign it to the property `addressId`. + +```js +import { EmberDataSerializer } from "ember-cli-mirage"; + +export default EmberDataSerializer.extend({ + primaryKey: "addressId" +}); +``` + +## Transforms + +Transforms provides the same function as `attrs` for the ember data serializers however this transformation is happening +on the server side for Mirage. This allows your mirage models to look more like your actual server models. + +Example of a Mirage serializer extending from EmberDataSerializer +```js +import { EmberDataSerializer } from "ember-cli-mirage"; + +export default EmberDataSerializer.extend({ + transforms: { + name: "externalName", + address: {key: "addressId", serialize: "ids"}, + age: {key: "externalAge"}, + blogPosts: {key: "blogPostIds"} + } +}); +``` + +If you would like Mirage to apply the transforms from your ember data serializers for you see +{{docs-link 'Advanced Configuration of Serializers' 'docs.advanced.server-configuration'}}. + + diff --git a/tests/dummy/app/pods/docs/data-layer/serializers/index/template.md b/tests/dummy/app/pods/docs/data-layer/serializers/index/template.md new file mode 100644 index 000000000..752628677 --- /dev/null +++ b/tests/dummy/app/pods/docs/data-layer/serializers/index/template.md @@ -0,0 +1,255 @@ +# Serializers + +A serializer is an object responsible for transforming a Model or Collection that's returned from your route handlers + +```js +this.get('movies/:id', (schema, request) => { + return schema.movies.find(request.params.id); +}); +``` + +into a formatted JSON payload + +```js +// GET /movies/1 + +{ + data: { + id: '1', + type: 'movies';, + attributes: { + title: 'Interstellar' + } + } +} +``` + +suitable for consumption by your Ember app. + +Serializers are the last main part of Mirage's architecture that interacts with the Data Layer, because producing a well-formatted JSON response often involves traversing the relationship graph of your models. + +Let's see how they work. + + +## Choosing which serializer to use + +The first step in working with Mirage's serializers is to choose which included serializer to start with, which in turn depends on what JSON format your backend uses to serve data to your Ember app. + +The JSON payload above is an example of an API that follows [the JSON:API spec](https://jsonapi.org/). You'll see it used a lot in the Ember ecosystem, because it's the default API format expected by Ember Data. It also solves a lot of problems that exist in other formats that are less well-defined. + +If you are starting a new app, it's recommended that you choose a JSON:API implementation for your backend, as that format will give you the smoothest experience with the rest of the Ember ecosystem. However, plenty of Ember apps are built that don't use JSON:API. + +If your app does use JSON:API, Mirage ships with a `JSONAPISerializer` that will do the heavy lifting for you. + +Mirage also ships with two other named serializers, `ActiveModelSerializer` and `RestSerializer`, that match two other popular backend formats. `EmberDataSerializer` is also provided as a variation to the `RestSerializer` that uses the `primaryKey` and `attrs` defined in your applications ember data serializers, similar to how models are auto discovered. See the section on {{docs-link 'Ember Data Serializer' 'docs.data-layer.serializers.ember-data-serializer'}} for more information. + +If your backend uses a different format, you'll need to choose the closest one and customize it to match your production format. We'll talk about that later in this guide. + + +## Defining serializers + +Once you've selected the appropriate serializer, define your default application-wide serializer by exporting it from `/mirage/serializers/application.js`: + +```js +// mirage/serializers/application.js +import { JSONAPISerializer } from 'miragejs'; + +export default JSONAPISerializer.extend({ +}); +``` + +This specifies the serializer to use for each Model and Collection in your system. + +If you need to customize a serializer for a particular model type, you can define model-specific serializers that take precedence over your application serializer. + +Let's use Mirage's generator to create a `Movie` serializer: + +``` +ember g mirage-serializer movie +``` + +This creates the file + +```js +import ApplicationSerializer from './application'; + +export default ApplicationSerializer.extend({ +}); +``` + +which follows the best practice of model-specific serializers extending from your Application serializer. + +You can now customize the behavior of how `Movie` models and collections are serialized into JSON. + + +## Customizing serializers + +When it comes to customizing your application's serializers, you'll mostly be tweaking Mirage's defaults. + +For example, if your Ember app expects attribute names to be PascalCase + +```js +// GET /movies/1 + +{ + Id: '1', + ReleaseDate: 'Interstellar' +} +``` + +you might override the Serializer's `keyForAttribute` method: + +```js +import { Serializer } from 'miragejs'; +import { classify } from '@ember/string'; + +export default Serializer.extend({ + + keyForAttribute(attr) { + return classify(attr); + } + +}); +``` + +See the API docs for each serializer to learn more about all the customization hooks available. + + +## Relationships + +Relationships are another important aspect of Serializers, as backends have many different ways of dealing with relationships. + +For example, the `JSONAPISerializer` respects query param includes + +``` +GET /movies/1?include=cast-members +``` + +out of the box. But sometimes Ember apps expect a resource payload to have all their relationship IDs defined, regardless if the request used query param includes. + +There's an option on `JSONAPISerializer` that enables this: + +```js +import { JSONAPISerializer } from 'miragejs'; + +export default JSONAPISerializer.extend({ + + alwaysIncludeLinkageData: true + +}); +``` + +Now, a GET request to `/movies/1` would respond with this payload: + +```js +{ + data: { + id: '1', + type: 'movies';, + attributes: { + title: 'Interstellar' + }, + relationships: { + 'cast-members': { + data: [ + { type: 'people', id: '1' }, + { type: 'people', id: '2' }, + { type: 'people', id: '3' }, + ] + } + } + } +} +``` + +The Ember app could now use these ids to subsequently fetch the related cast members. + +Other times, an Ember app expects to get a link to fetch related data. The `JSONAPISerializer` also has a hook for this: + +```js +// mirage/serializers/movie.js +import ApplicationSerializer from './application'; + +export default ApplicationSerializer.extend({ + + links(movie) { + return { + 'cast-members': { + related: `/api/movies/${movie.id}/cast-members` + } + }; + } + +}); +``` + +Now a GET request to `/movies/1` would respond with this payload: + +```js +{ + data: { + id: '1', + type: 'movies';, + attributes: { + title: 'Interstellar' + }, + relationships: { + 'cast-members': { + links: { + related: `/api/movies/1/cast-members` + } + } + } + } +} +``` + +The other serializers also have mechanisms controlling how related data can be loaded. Be sure to check out the API docs for all the details. + + +## Working with serialized JSON + +While most route handlers should return a Model or Collection instance, and leave the serialization logic up to the Serializer, sometimes it can be convenient to perform some final serialization logic directly in your route handler. + +You can use the `this.serialize` helper method to do this - make sure to use a `function` instead of a fat arrow so you have access to the correct `this`: + +```js +// mirage/config.js +this.get('/movies', function(schema, request) { + let movies = schema.movies.all(); + let json = this.serialize(movies); + + json.meta.size = movies.length; + + return json; +}); +``` + +The `serialize` helper will use the typical lookup logic to first check for a model-specific serializer, and then fall back to the default Application serializer. + +You can also use a specific serializer if you have a special case by passing in the name of the serialize as a second argument: + +```js +// mirage/config.js +this.get('/movies', function(schema, request) { + let movies = schema.movies.all(); + let json = this.serialize(movies, 'movie-with-relationship'); + + json.meta.size = movies.length; + + return json; +}); +``` + +This route handler would use the `mirage/serializers/movie-with-relationship.js` serializer to transform the collection of movies into a `json` payload, which is then modified and then finally returned from the route handler. + + +--- + +In general, you should not need to write much code dealing with Mirage serializers. Even if your backend doesn't adhere to one of the predefined formats, you should be able to use the provided hooks to implement an ApplicationSerializer that works for the majority of your models. + +The more conventional your backend API is, the less code you'll need to write – not only in Mirage, but also in other parts of your Ember application! + +Be sure to check out the {{docs-link 'Serializer' 'docs.api.item' 'modules/serializer~Serializer#keyForAttribute'}} and {{docs-link 'JSONAPISerializer' 'docs.api.item' 'modules/serializers/json-api-serializer~JSONAPISerializer'}} docs to learn about all the hooks available to customize your serializer layer. + +Now that we've covered the ins and outs of Mirage's data layer, we're ready to see how we can use Mirage to effectively test our Ember application. diff --git a/tests/dummy/app/pods/docs/getting-started/installation/template.md b/tests/dummy/app/pods/docs/getting-started/installation/template.md new file mode 100644 index 000000000..6d016264b --- /dev/null +++ b/tests/dummy/app/pods/docs/getting-started/installation/template.md @@ -0,0 +1,36 @@ +# Installation + +To install Mirage, run + +``` +ember install ember-cli-mirage +``` + +Ember should install the addon and add a `/mirage` directory to the root of your project. + +Check out the {{docs-link 'upgrade guide' 'docs.getting-started.upgrade-guide'}} if you're coming from a previous version of Mirage. + +## Note for Prettier users + +There's an Ember CLI bug that exposes itself when using Prettier + Mirage. A longer-term fix is in the works, but for now, if you're using Prettier and install Mirage, you can either + +- pin `eslint-plugin-prettier` to 2.6.0, or +- add the following to `.eslintignore`: + + ```sh + /mirage/mirage + ``` + +## Note for FastBoot users + +You might expect Mirage to serve network requests made by your FastBoot app, but because Mirage runs only in the browser, it currently disables itself if your app is being served by FastBoot. + +[FastBoot support](https://github.com/miragejs/ember-cli-mirage/issues/1411) is a highly requested feature we are working on. In the meantime, you'll need to develop your FastBoot pages against a local server. + +You can always bypass FastBoot page generation locally by running + +```sh +FASTBOOT_DISABLED=true ember serve +``` + +Mirage will then run in the browser as expected, and you can develop your client app as normal. diff --git a/tests/dummy/app/pods/docs/getting-started/overview/template.md b/tests/dummy/app/pods/docs/getting-started/overview/template.md new file mode 100644 index 000000000..35807d97d --- /dev/null +++ b/tests/dummy/app/pods/docs/getting-started/overview/template.md @@ -0,0 +1,426 @@ +# Overview + +Mirage lets you simulate API responses by writing **route handlers**. + +The simplest example of a route handler is a function that returns an object: + +```js +// mirage/config.js +export default function() { + this.namespace = 'api'; + + this.get('/movies', () => { + return { + data: [ + { id: 1, type: 'movies', attributes: { name: 'Interstellar' } }, + { id: 2, type: 'movies', attributes: { name: 'Inception' } }, + { id: 3, type: 'movies', attributes: { name: 'Dunkirk' } }, + ] + }; + }); + +} +``` + +Now whenever your Ember app makes a GET request to `/api/movies`, Mirage will respond with this data. + +## Dynamic data + +This works, and is a common way to simulate HTTP responses - but hard-coded responses like this have a few problems: + + - *They're inflexible*. What if you want to change the data for this route in your tests? + - *They contain formatting logic*. Logic that's concerned with the shape of your JSON payload (e.g. the `data` and `attributes` keys) is now duplicated across all your route handlers. + - *They're too basic.* Inevitably, when your Mirage server needs to deal with more complex things like relationships, these simple ad hoc responses start to break down. + +Mirage provides a **data layer** that lets you write more powerful server implementations. Let's see how it works by replacing our basic stub data above. + +### Creating a model + +First, we'll need to tell Mirage that we have a dynamic `Movie` model. + +If you're using Ember Data and you already have a `Movie` model defined, you can skip this step! Mirage will automatically generate its models from your Ember Data definitions, so you won't have any files in the `mirage/models` directory. + +If you're not using Ember Data, you can use the `mirage-model` generator to create a model from the command line: + +```bash +$ ember g mirage-model movie +``` + +This generates the following file: + +```js +// mirage/models/movie.js +import { Model } from 'miragejs'; + +export default Model.extend({ +}); +``` + +### Writing a dynamic route handler + +Models let our route handlers take advantage of Mirage's _in-memory database_. The database makes our route handlers dynamic, so we can change the data that's returned without having to rewrite the handler. + +Let's update our route handler to be dynamic: + +```js +this.get('/movies', (schema, request) => { + return schema.movies.all(); +}); +``` + +The `schema` argument lets us access our new `Movie` model. This route will now respond with all the authors in Mirage's database at the time of the request. We can therefore change the data this route responds with by only changing what records are in Mirage's database, instead of having to write a different version of the handler for each scenario we want to simulate. + + +### Seeding the database + +Right now, if we sent a request to our new handler above, the response would look something like this: + +```js +// GET /api/movies +data: [ +] +``` + +That's because Mirage's database is empty. + +To actually seed our database with fake data, we'll use *factories*. Factories are objects that make it easy to generate realistic-looking data for your Mirage server. Think of them as blueprints for your models. + +Let's create a factory for our author with + +```sh +$ ember g mirage-factory movie +``` + +We can then define some properties on our Factory. They can be simple types like Booleans, Strings or Numbers, or functions that return dynamic data: + +```js +// mirage/factories/movie.js +import { Factory } from 'miragejs'; + +export default Factory.extend({ + + title(i) { + return `Movie ${i}`; // Movie 1, Movie 2, etc. + }, + + year() { + let min = 1950; + let max = 2019; + + return Math.floor(Math.random() * (max - min + 1)) + min; + }, + + rating: "PG-13" + +}); +``` + +This factory creates objects like + +```js +[ + { + title: 'Movie 1', + year: 1992, + rating: "PG-13" + }, + { + title: 'Movie 2', + year: 2008, + rating: "PG-13" + }, + // ... +] +``` + +and so on, which will automatically be inserted into the `movies` database table. The database will assign each record an `id`, and now we can interact with this data in our route handlers. + +To actually use our new factory definition, we can call the `server.create` and `server.createList` methods. + +To seed our development database, use the function in the `scenarios/default.js` file: + +```js +// mirage/scenarios/default.js +export default function(server) { + + server.createList('movie', 10); + +}; +``` + +Now when our Ember app makes a GET request to `/api/movies` using the route handler above, we'll see something that looks like this: + +```js +// GET /api/movies +data: [ + { + id: 1, + type: "movies", + attributes: { + title: "Movie 1", + year: 1992, + rating: "PG-13" + } + }, + { + id: 2, + type: "movies", + attributes: { + title: "Movie 2", + year: 2008, + rating: "PG-13" + } + }, + // ... +] +``` + +As we can see, this response is now influenced by the run-time state of our database. + +In acceptance tests, `scenarios/default.js` is ignored, and instead you can use `this.server` to setup your database in the state needed for the test: + +```js +// tests/acceptance/movies-test.js +import { setupApplicationTest } from 'ember-qunit'; +import { setupMirage } from 'ember-cli-mirage/test-support'; + +module('Acceptance | Homepage test', function(hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + test("I can view the movies", async function(assert) { + this.server.createList("movie", 3); + + await visit("/home"); + + assert.dom("[data-test-id='movie-row']").exists({ count: 3 }); + }); +}); +``` + +You can also pass attribute overrides directly to `create` or `createList`: + +```js +test("I can view the movie title", async function(assert) { + let movie = this.server.create('movie', { title: "Interstellar" }); + + await visit(`/movies/${movie.id}`); + + assert.dom('h1').includesText("Interstellar"); +}); +``` + +You now have a simple way to set up your Mirage server's initial data, both during development and on a per-test basis. + +## Associations + +Dealing with associations is always tricky, and faking endpoints that deal with associations is no exception. Fortunately, Mirage ships with an ORM to help keep your route handlers clean. + +Let's say your movie has many cast-members. You can declare this relationship in your model: + +```js +// mirage/models/movie.js +import { Model, hasMany } from 'miragejs'; + +export default Model.extend({ + castMembers: hasMany() +}); + +// mirage/models/cast-member.js +import { Model, belongsTo } from 'miragejs'; + +export default Model.extend({ + movie: belongsTo() +}); +``` + +Now Mirage knows about the relationship between these two models, which can be useful when writing route handlers: + +```js +this.get('/movies/:id/cast-members', (schema, request) => { + let movie = schema.movies.find(request.params.id); + + return movie.castMembers; +}); +``` + +and when creating graphs of related data: + +```js +test("I can see a movie's cast members", async function(assert) { + server.create('movie', { + title: 'Interstellar', + castMembers: [ + server.create('cast-member', { name: 'Matthew McConaughey' }), + server.create('cast-member', { name: 'Anne Hathaway' }), + server.create('cast-member', { name: 'Jessica Chastain' }) + ] + }); + + await visit('/'); + + assert.dom('li.cast-member').exists({ count: 3 }); +}); +``` + +Mirage uses foreign keys to keep track of these related models for you, so you don't have to worry about any messy bookkeeping details while your Ember app reads and writes new relationships to Mirage's database. + + +## Serializers + +Mirage is designed for you to be able to completely replicate your production server. + +So far, we've seen that Mirage's default payloads are formatted using the [JSON:API](https://jsonapi.org) spec. This spec produces payloads that look like this: + +```js +// GET /movies/1 +{ + data: { + id: 1, + type: 'movies', + attributes: { + title: 'Interstellar' + } + } +} +``` + +New Ember apps using Ember Data work well with the JSON:API format, but of course, not every backend uses JSON:API. + +For example, your API responses might look more like this: + +```js +// GET /movies/1 +{ + movies: { + id: 1, + title: 'Interstellar' + } +} +``` + +This is why Mirage _serializers_ exist. Serializers let you customize the formatting logic of your responses, without having to change your route handlers, models, relationships, or any other part of your Mirage setup. + +Mirage ships with a few named serializers that match popular backend formats. You can also extend from the base class and use formatting hooks to match your own backend: + +```js +// mirage/serializers/application.js +import { Serializer } from 'miragejs'; + +export default Serializer.extend({ + keyForAttribute(attr) { + return dasherize(attr); + }, + + keyForRelationship(attr) { + return dasherize(attr); + } +}); +``` + +Mirage's serializer layer is also aware of your relationships, which helps when faking endpoints that sideload or embed related data: + +```js +// mirage/serializers/movie.js +import { Serializer } from 'miragejs'; + +export default Serializer.extend({ + include: [ 'crewMembers' ] +}); + +// mirage/config.js +export default function() { + this.get('/movies/:id', (schema, request) => { + return schema.movies.find(request.params.id); + }); +} +``` + +With the above config, a GET to `/movies/1` would return automatically include related crew members: + +```js +{ + movie: { + id: 1, + title: 'Interstellar' + }, + 'crew-members': [ + { + id: 1, + 'movie-id': 1, + name: 'Matthew McConaughey' + }, + { + id: 1, + 'movie-id': 1, + name: 'Anne Hathaway' + }, + ... + ] +} +``` + +Mirage ships with two named serializers, JSONAPISerializer and ActiveModelSerializer, to save you the trouble of writing this custom code yourself. See the [serializer guide](../api/modules/serializer~Serializer) to learn more. + +## Shorthands + +Mirage has *shorthands* to reduce the code needed for conventional API routes. For example, the route handler + +```js +this.get('/authors', (schema, request) => { + return schema.authors.all(); +}); +``` + +can be written as + +```js +this.get('/authors'); +``` + +There are also shorthands for `post`, `patch` (or `put`), and `del` methods. Here's a full set of resourceful routes for an `author` resource: + +```js +this.get('/authors'); +this.get('/authors/:id'); +this.post('/authors'); +this.patch('/authors/:id'); +this.del('/authors/:id'); +``` + +Shorthands make writing your server definition concise, so use them whenever possible. When mocking a new route, you should always start with a Shorthand, and then drop down to a function route handler when you need more control. + + +## Passthrough + +Mirage is a great tool to use even if you're working on an existing app, or if you don't want to fake your entire API. By default, Mirage throws an error if your Ember app makes a request that doesn't have a corresponding route handler defined. To avoid this, tell Mirage to let unhandled requests pass through: + +```js +// mirage/config.js +this.passthrough(); +``` + +Now you can develop as you normally would, for example against an existing API. + +When it comes time to build a new feature, you don't have to wait for the API to be updated. Just define the new route that you need + +```js +// mirage/config.js +this.get('/comments'); + +this.passthrough(); +``` + +and you can fully develop and test the feature. In this way you can build up your fake server piece by piece - adding some solid acceptance tests along the way. + +--- + +That should be enough to get you started! + +The rest of the docs are organized by Mirage's higher-level concepts: + + - **Route handlers** contain the logic around what run-time data Mirage uses to respond to requests. + + - The **Data layer** is how Mirage stores and tracks changes to your data over time. + +Keep reading to learn more! diff --git a/tests/dummy/app/pods/docs/getting-started/upgrade-guide/index/template.md b/tests/dummy/app/pods/docs/getting-started/upgrade-guide/index/template.md new file mode 100644 index 000000000..4ab912121 --- /dev/null +++ b/tests/dummy/app/pods/docs/getting-started/upgrade-guide/index/template.md @@ -0,0 +1,425 @@ +# Upgrade guide + +If you're upgrading from an existing version of Mirage, you can run the following: + +```sh +# Using npm +npm install -D ember-cli-mirage@X.X.X + +# Using yarn +yarn add -D ember-cli-mirage@X.X.X +``` + +## Full Changelog + +You can view all of Mirage's release notes on [our Releases page](https://github.com/miragejs/ember-cli-mirage/releases). + +## 2.0 Upgrade guide + +There were a few breaking changes made in the 1.0 release. + +### 1. Update import paths for miragejs imports + +## 1.0 Upgrade guide + +There were a few breaking changes made in the 1.0 release. + +### 1. Remove Faker.js + +When Mirage was first released, including npm libraries into Ember CLI apps was difficult. You needed to generate a vendor shim and call `app.import` in order to use the library in your application code. + +Because of all this ceremony, it was common for addons to do that work for you, and bundle related packages. This is exactly what Mirage did for [Faker.js](https://github.com/Marak/faker.js), a useful library to have alongside your Mirage factory definitions. + +There's a few problems with this, most notably that users _had_ to use the version of Faker that was bundled with Mirage. It was frustrating not being able to take advantage of new Faker features until Mirage upgraded its bundled version. + +Now, thanks to [Ember Auto Import](https://github.com/ef4/ember-auto-import), this is no longer the case. Using dependencies directly from npm is painless – just `yarn/npm install` them and `import` them directly from your ES6 classes. Thanks to Auto Import, all that ceremony is taken care of for you. + +This also means that users can easily manage their project's version of Faker (and other similar dependencies) independently of the version of Mirage they're using. + +For this reason, in 1.0 we are no longer bundling Faker.js with Mirage. This is a breaking change. + +Here are the steps you'll need to take to fix this: + +1. Install Ember Auto Import (if it's not already installed) + +```sh +ember install ember-auto-import +``` + +2. Install Faker.js directly from npm: + +```sh +yarn add -D faker + +# or npm install --save-dev faker +``` + +3. Change all imports of `faker` from the `ember-cli-packge` to import directly from `faker`: + +```diff +- import { Factory, faker } from 'miragejs'; ++ import { Factory } from 'miragejs'; ++ import faker from 'faker'; +``` + +[There is a codemod](https://github.com/miragejs/ember-cli-mirage-faker-codemod) that will do this for you, thanks to the gracious work of [Casey Watts](https://github.com/caseywatts). + +Additionally, when I originally bundled Faker, I monkey-patched it with some methods that I thought would be "useful" additions. I thought this was a good idea at the time... it wasn't. 🙈 + +You can look at [the module from v0.4.15](https://github.com/miragejs/ember-cli-mirage/blob/v0.4.15/addon/faker.js) to see that we added the `faker.list.random`, `faker.list.cycle` and `faker.random.number.range` methods, so if you use these methods too, you'll need to refactor them. + +Fortunately, two of them have been added to recent versions of Faker, and one can be replaced with some simple JS: + +For `faker.list.random`, use `faker.random.arrayElement`: + +```diff + countries() { +- return faker.list.random([ 'United States of America', 'Canada', 'Mexico' ]); ++ return faker.random.arrayElement([ 'United States of America', 'Canada', 'Mexico' ]); + } +``` + +For `faker.list.cycle`, use the remainder (modulo) operator: + +```diff + countries(i) { +- return faker.list.cycle([ 'United States of America', 'Canada', 'Mexico' ]); + ++ let countries = [ 'United States of America', 'Canada', 'Mexico' ]; ++ ++ return countries[i % countries.length]; + } +``` + +For `faker.random.number.range`, use `faker.random.number` with min and max options: + +```diff + age() { +- return faker.random.number.range(18, 65); ++ return faker.random.number({ min: 18, max: 65 }); + } +``` + +After that, you should be on your own with respect to Faker! Thanks to Auto Import, you can change versions, or even try out other libraries like [Chance.js](https://chancejs.com/), and rest easy knowing Mirage is a bit slimmer and one less thing is beyond your control. + +### 2. New import for setupMirage + +Please use the new named import for the setupMirage test helper. The old one still works for now but is not robust to us refactoring the internal file location. The named export is also more aligned with the rest of the ecosystem. + +```js +// Before +import setupMirage from "ember-cli-mirage/test-support/setup-mirage"; + +// After +import { setupMirage } from "ember-cli-mirage/test-support"; +``` + +### 3. Remove deprecated forms of `create`, `createList` and `normalizedRequestAttrs` + +There are several places in Mirage's APIs that were intended to be used with singularized versions of model names, but just so happened to work if a non-singularized version was passed in. + +This behavior was discovered during a refactor, and the non-singularized versions were maintained to avoid breaking apps. Now that we're moving to 1.0, we're removing this deprecated/unintentional behavior. + +- `server.create` and `server.createList` were coded to take a singularized model name, e.g. `server.create('user')`. It just so happens that `server.create('users')` also works. That pluralized version is now removed from Mirage. + + If you're running the latest 0.x version you should see a deprecation message letting you know where to change it. Otherwise, it should be a pretty mechanic change from things like `server.create('users')` to `server.create('user')`. + + Note this also applies to `server.createList` – the correct form is `server.createList('user', 3)`, and the pluralized form `server.createList('users', 3)` is now unsupported. + +- `this.normalizedRequestAttrs` in a route handler optionally takes a modelName as an argument. This is if your URLs are non-standard and Mirage cannot guess the modelName from the URL path. + + In this case, you can call `this.normalizedRequestAttrs('blog-post')` to tell Mirage to expect the payload to be for a `blog-post` model. + + This API was intended to be used with dasherized names, because that's how compound model names are specified throughout Mirage when they are represented as strings. + + It just so happened that `this.normalizedRequestAttrs('blogPost')` also worked, by chance, until a refactor. So, that behavior was kept but now is being removed. + + The correct usage is `this.normalizedRequestAttrs('blog-post')`. Using the camelized version of the model name is no longer supported. + +If either of these changes cause a ton of refactoring pain, we can try to marshal some resources to help write a codemod. Please open an issue if that's the case! + +### 4. The `normalizeIds` serializer property now defaults to true + +This applies to the ActiveModelSerializer and RestSerializer. + +The `normalize` property on serializers helps Mirage's shorthands work by transforming differently formatted payloads into JSON:API documents. These documents are then used by Mirage to update the database accordingly. + +There was a gap in the default `normalize` method for a long time, in that it didn't take REST payloads that included foreign keys and looked like + +```js +let payload = { + contact: { + id: 1, + name: "Link", + address: 1 + } +}; +``` + +and turn that `address` key into a proper JSON:API relationship: + +```js +data: { + type: 'contacts', + id: 1, + attributes: { + name: 'Link' + }, + relationships: { + address: { + data: { + type: 'address', + id: 1 + } + } + } +} +``` + +We added this feature a while ago, and it's controlled with the `normalizeIds` property on the ActiveModelSerializer and RESTSerializer. (We did this so the feature wouldn't be a breaking change.) + +We're now making `true` the default, which should be the behavior everyone desires (assuming they're using shorthands). This is technically a breaking change, though it's unlikely to affect most people. + +## 0.3.x → 0.4 Upgrade guide + +There is one primary change in 0.4 that could break your 0.3 app. + +In 0.3.x, Mirage's JSONAPISerializer included all related foreign keys whenever serializing a model or collection, even if those relationships were not being `included` in the payload. + +This actually goes against JSON:API's design. Foreign keys in the payload are known as [Resource Linkage](http://jsonapi.org/format/#document-resource-object-linkage) and are intended to be used by API clients to link together all resources in a JSON:API compound document. In fact, most server-side JSON:API libraries do not automatically serialize all related foreign keys, and only return linkage data for related resources when they are being included in the current document. + +By including linkage data for every relationship in 0.3, it was easy to develop Ember apps that would work with Mirage but would behave differently when hooked up to a standard JSON:API server. Since Mirage always included linkage data, an Ember app might automatically be able to fetch related resources using the ids from that linkage data plus its knowledge about the API. For example, if a `post` came back like this: + +```js +// GET /posts/1 +{ + data: { + type: 'posts', + id: '1', + attributes: { ... }, + relationships: { + author: { + data: { + type: 'users', + id: '1' + } + } + } + } +} +``` + +and you forgot to `?include=author` in your GET request, Ember Data would potentially use the `user:1` foreign key and lazily fetch the `author` by making a request to `GET /authors/1`. This is problematic because + +1. This is not how foreign keys are intended to be used +2. It'd be better to see no data and fix the problem by going back up to your data-loading code and add `?include=author` to your GET request, or +3. If you do want your interface to lazily load the author, use resource `links` instead of the resource linkage `data`: + +```js +// GET /posts/1 +{ + data: { + type: 'posts', + id: '1', + attributes: { ... }, + relationships: { + author: { + links: { + related: '/api/users/1' + } + } + } + } +} +``` + +Resource links can be defined on Mirage serializers using the [links](http://www.ember-cli-mirage.com/docs/v0.3.x/serializers/#linksmodel) method (though `including` is likely the far more simpler and common approach to fetching related data). + +So, Mirage 0.4 changed this behavior and by default, the JSONAPISerializer only includes linkage data for relationships that are being included in the current payload (i.e. within the same compound document). + +This behavior is configurable via the `alwaysIncludeLinkageData` key on your JSONAPISerializers. It is set to `false` by default, but if you want to opt-in to 0.3 behavior and always include linkage data, set it to `true`: + +```js +// mirage/serializers/application.js +import { JSONAPISerializer } from "ember-cli-mirage"; + +export default JSONAPISerializer.extend({ + alwaysIncludeLinkageData: true +}); +``` + +If you do this, I would recommend looking closely at how your real server behaves when serializing resources' relationships and whether it uses resource `links` or resource linkage `data`, and to update your Mirage code accordingly to give you the most faithful representation of your server. + +## 0.2.x → 0.3 Upgrade guide + +The main change from 0.2.x to 0.3.x is that relationships are now one-way. This better matches the semantics of both Ember Data and common HTTP transfer protocols like JSON:API. + +In 0.2, the following model definitions + +```js +// mirage/models/author.js +import { Model } from "ember-cli-mirage"; + +export default Model.extend({}); + +// mirage/models/post.js +import { Model, belongsTo } from "ember-cli-mirage"; + +export default Model.extend({ + author: belongsTo() +}); +``` + +would have generated a "schema" with a one-to-many relationship between authors and posts: an author has many posts, and a post belongs to an author. Now, this just generates a one-way relationship from `post` to `author`. To have a two-way sync'd relationship, known as an inverse, you'd need to define both sides of the relationship: + +```js +// mirage/models/author.js +import { Model, hasMany } from "ember-cli-mirage"; + +export default Model.extend({ + posts: hasMany() +}); + +// mirage/models/post.js +import { Model, belongsTo } from "ember-cli-mirage"; + +export default Model.extend({ + author: belongsTo() +}); +``` + +Practically speaking, to upgrade you'll need to go through your code and update relationships that implicitly had inverses (from 0.2.x's hasMany and belongsTo behavior) and update them to define both sides. + +This could also affect your fixture files, if you are using those to seed your database. Instead of just having an authorId on the post above, for example, you'd also need the author to have a `postIds: []` array. (In general Factories are better for seeding your database, as they save you from having to manage ids at all.) + +Conceptually this change should be straightforward, as its making existing implicit relationships explicit, but if you find yourself having trouble with the upgrade it's probably because of something I haven't thought of. Please reach out to the community on the #ec-mirage channel on Slack and ask for help! + +For more information on the motivation behind change, please read the [0-3 beta series release blog post](http://www.ember-cli-mirage.com/blog/2017/01/09/0-3-0-beta-series/). + +## 0.1.x → 0.2 Upgrade guide + +If you're upgrading your Mirage server from v0.1.x to v0.2.x, here's what you need to know: + +- **The default Mirage directory has changed.** The default Mirage directory has moved from `/app/mirage` to `/mirage`. When you install 0.2.0, the default blueprint will add the `/mirage` directory to your project. You can delete it and move your current Mirage files to the new location with something like + + ```sh + rm -rf mirage + mv app/mirage mirage + ``` + + from the root of your project. Mirage's directory is also [customizable](../configuration/#directory) (Although you should move it from the `/app` directory or else it will not be removed from the build in production mode). + +- **All multiword filenames are dasherized.** In Mirage 0.1.x, database collection names were taken from filenames. The idea was, if your API returned snake_case collection keys (e.g. `blog_posts: []`), just name your file `fixtures/blog_posts.js`. This approach turned out to be insufficiently flexib-- what am I saying, it was just a bad idea :P. + + In Mirage 0.2.x, we follow Ember CLI's conventions of dasherized filenames. So, you'll just need to go through and change + + ```sh + /mirage/factories/blog_post.js + /mirage/fixtures/blog_post.js + # etc. + ``` + + to + + ```sh + /mirage/factories/blog-post.js + /mirage/fixtures/blog-post.js + ``` + + You will then use the [new Serializer layer](../serializers) to do things like format keys in your json payloads. + +- **All JavaScript properties are camelCased.** Similar to the previous change, factory properties and database collection names followed the format of your API in Mirage 0.1.x. If you were faking an ActiveModelSerializer backend, multiword keys used snake_case throughout your Mirage code. So, your database table might be `db.blog_posts`, and your factory keys might be `first_name() {..}`. Looks pretty cool right? + + Wrong. We're JavaScript developers here, people. It's time to start using camelCase. (Also, the idea of tying these keys to your serialization format was bad, as it left us without any conventions. We need to stick to a single format, so the ORM knows how to find foreign keys.) + + You'll need to update your route handlers, which may look like this: + + ```js + let posts = db.blog_posts.filter(p => p.author_id === 1); + ``` + + to + + ```js + let posts = db.blogPosts.filter(p => p.authorId === 1); + ``` + + Note that everything is camelCased, including foreign keys. + + Similarly, factories that look like + + ```js + export default Factory.extend({ + first_name() { + return faker.name.firstName(); + }, + + last_name() { + return faker.name.firstName(); + } + }); + ``` + + should be changed to + + ```js + export default Factory.extend({ + firstName() { + return faker.name.firstName(); + }, + + lastName() { + return faker.name.firstName(); + } + }); + ``` + + This goes for all attrs that `server.create` takes (and returns), etc. For many this will be the most painful part of the upgrade. Please find it in your heart to forgive me. + +- **Mirage now has its own Model layer (an ORM).** In Mirage 0.1.x, you had to define either a factory or a fixture file (or both) in order for a database collection to be created, which let you take advantage of the db in your route handlers. In 0.2, we've introduced Mirage Models, which serve as the new canonical source of truth about your database. + + To create a model, use + + ``` + ember g mirage-model blog-post + ``` + + This will create a file like + + ```js + import { Model } from "ember-cli-mirage"; + + export default Model.extend({}); + ``` + + Having that file sets up the `db.blogPosts` collection, allows you to use the JSON:API serializer, and more. You can still define factories and fixtures - but only if you need them. Models, factories and fixtures all work together, but now you won't be making blank factory or fixture files just to set up your database. The models themselves serve as the source of truth. + + We needed to add models for [association support](../models/#associations) (which currently exists) and factory relationships (the first feature to come after the 0.2 release). Read through the [models guide](../models) and [serializers guide](../serializers) to see how having models can simplify your Mirage server. + + We also have a plan to make a separate addon that could ascertain your model definitions and their relationships from your Ember Data models. Adding the ORM paves the way for this important future addition. + + Currently, Mirage will still work if a factory/fixture file is defined for a particular db collection without a corresponding model. Eventually, we may require all setups to have model definitions for each collection. But for now, to make for an easier upgrade path, you can start generating models and opt-in to the ORM layer in piecemeal. + +- **The ORM object `schema` is now injected into route handlers.** In Mirage 0.1.x, the `db` was the first parameter injected into route handlers: + + ```js + this.get("/posts", function(db, request) { + // work with db + }); + ``` + + Now, the `schema` object is, so you can take advantage of the Model layer. Fortunately, the `db` hangs directly off of the `schema`, so you can leave all your old route handler code intact (with the exception of making the change to camelCase), and just use destructuring to change the function signature to + + ```js + this.get("/posts", function({ db }, request) { + // work with db + }); + ``` + + and then start opting-in to the ORM (and using `schema`) one route handler at a time. + +- **Specify a Serializer.** If you're using shorthands, you'll need to pick a serializer in `/mirage/serializers/application.js`. See the [serializers guide](../serializers) for details. + +--- + +You can always view the [full changelog](https://github.com/miragejs/ember-cli-mirage/blob/master/CHANGELOG.md) to see everything that's changed. If you think this guide missed a critical part of the upgrade path, please [open an issue](https://github.com/miragejs/ember-cli-mirage/issues/new)! diff --git a/tests/dummy/app/pods/docs/getting-started/upgrade-guide/v2-deprecations/template.md b/tests/dummy/app/pods/docs/getting-started/upgrade-guide/v2-deprecations/template.md new file mode 100644 index 000000000..2f96da643 --- /dev/null +++ b/tests/dummy/app/pods/docs/getting-started/upgrade-guide/v2-deprecations/template.md @@ -0,0 +1,3 @@ +# Deprecations Added in v2.x of ember-cli-mirage + +## miragejs re-exports diff --git a/tests/dummy/app/pods/docs/getting-started/what-is-mirage/template.md b/tests/dummy/app/pods/docs/getting-started/what-is-mirage/template.md new file mode 100644 index 000000000..55962b2e2 --- /dev/null +++ b/tests/dummy/app/pods/docs/getting-started/what-is-mirage/template.md @@ -0,0 +1,38 @@ +# What is Mirage? + +Mirage is a JavaScript library that lets frontend developers mock out backend APIs. + +Unlike other mocking libraries, Mirage makes it easy to reproduce dynamic scenarios that are typically only possible when using a true production server. + +Equipped with a Mirage server, a frontend developer can build, test, and even share a complete working Ember application without having to use or configure any backend services. + +## Why? + +Mirage was originally built to bring conventions to some home-grown HTTP mocking code that was getting unwieldy. It ended up proving most useful when it enabled frontend developers to work on their apps without having to rely on any local or staging backend services as part of their normal development workflow. + +Since then, Mirage has focused on making it as easy as possible for Ember developers to maintain a mock server alongside their codebase. + +## How it works + +Mirage runs in the browser. It uses [Pretender.js](https://github.com/pretenderjs/pretender) to intercept and respond to any network requests your Ember app makes, letting you build your app as if it were talking to a real server. + +In this way, you can develop and test your app against various server states without having to modify any application code. + +In addition to intercepting HTTP requests, Mirage provides a mock database and helper functions that make it easy to simulate dynamic backend services. + +Mirage borrows concepts from server-side frameworks like + + - **routes** to handle HTTP requests + - a **database** and **models** for storing data and defining relationships + - **factories** and **fixtures** for stubbing data, and + - **serializers** for formatting HTTP responses + +to make it easy to simulate production server behavior. + +## Alternatives + +These other libraries solve similar problems to Mirage and might be a better fit for your needs: + +- [Polly.js](https://netflix.github.io/pollyjs/#/), a library for recording and replaying HTTP interactions +- [Pretender.js](https://github.com/pretenderjs/pretender), the low-level HTTP interceptor powering Mirage +- [Ember Data Factory Guy](https://github.com/danielspaniel/ember-data-factory-guy), factories for Ember apps powered by Ember Data diff --git a/tests/dummy/app/pods/docs/index/route.js b/tests/dummy/app/pods/docs/index/route.js new file mode 100644 index 000000000..5233953c9 --- /dev/null +++ b/tests/dummy/app/pods/docs/index/route.js @@ -0,0 +1,7 @@ +import Route from '@ember/routing/route'; + +export default class extends Route { + beforeModel() { + this.transitionTo('docs.getting-started.what-is-mirage'); + } +} diff --git a/tests/dummy/app/pods/docs/route-handlers/functions/template.md b/tests/dummy/app/pods/docs/route-handlers/functions/template.md new file mode 100644 index 000000000..69a7dd562 --- /dev/null +++ b/tests/dummy/app/pods/docs/route-handlers/functions/template.md @@ -0,0 +1,277 @@ +# Functions + +Function handlers are the most flexible way to write route handlers in Mirage. + +To define new function handlers, use the `get`, `post`, `patch` (or `put`) and `del` methods. Here's an example: + +```js +// mirage/config.js +this.get('/movies', () => { + return [ 'Interstellar', 'Inception', 'Dunkirk' ]; +}); +``` + +Now when your Ember app makes a GET request to `/movies`, it will receive this data. + +Each verb method has the same signature. The first argument is the path (URL) and the second is the actual function handler that returns the response. + +```js +this.get('/movies', () => { ... }); +this.post('/movies', () => { ... }); +this.patch('/movies/:id', () => { ... }); +this.del('/movies/:id', () => { ... }); +``` + + +## Timing + +The last argument to a route handler is an options object you can use to adjust the timing. Use this to delay the response of a particular route and see how your Ember app behaves when communicating with a slow network. + +```js +// mirage/config.js +this.get('/movies', () => { + return [ 'Interstellar', 'Inception', 'Dunkirk' ]; +}, { timing: 4000 }); +``` + +The default delay is 50ms during development, and 0 during testing (so your tests run fast). + +You can also set a global timing parameter for all routes. Individual timing parameters override the global setting. + +```js +// mirage/config.js +export default function() { + this.namespace = 'api'; + this.timing = 2000; + + this.get('/movies', () => { + return [ 'Interstellar', 'Inception', 'Dunkirk' ]; + }); + + this.get('/complex-query', () => { + return [1, 2, 3, 4, 5]; + }, { timing: 3000 }); +} +``` + +If you want to add delays to a test, you can override the timing for individual tests by putting the timing parameter in your test + +```js +test('this route works with a delay', function() { + server.timing = 10000; + + // ... +}); +``` + +Because the server is reset after each test, this option won't leak into the rest of your suite. + + +## Accessing the data layer + +Route handlers receive `schema` as their first parameter, which lets them access Mirage's data layer: + +```js +this.get('/movies', (schema) => { + return schema.movies.all(); +}); +``` + +Most of your route handlers will interact with the data layer in some way. + +The second parameter is the `request` object, which contains information about the request your Ember app made. For example, you can access dynamic URL segments from it: + +```js +this.get('/movies/:id', (schema, request) => { + let id = request.params.id; + + return schema.movies.find(id); +}); +``` + +You can also access the request body, for example to handle a POST or PATCH request that contains data sent over by the Ember app: + +```js +this.post('/movies', (schema, request) => { + let title = JSON.parse(request.requestBody).title; + + return schema.movies.create({ title }); +}); +``` + +The `normalizedRequestAttrs` helper (documented below) provides some sugar for working with the request data. + + +## Dynamic paths and query params + +The request object that's injected into your route handlers contains any dynamic route segments and query params. + +To define a route that has a dynamic segment, use colon syntax (`:segment`) in your path. The dynamic piece will be available via `request.params.[segment]`: + +```js +this.get('/authors/:id', (schema, request) => { + let id = request.params.id; + + return schema.authors.find(id); +}) +``` + +Query params from the request can also be accessed via `request.queryParams.[param]`. + + +## Helpers + +There are several helpers available when writing function route handlers. + +### serialize + +This helper returns the JSON for the given Model or Collection after passing it through the Serializer layer. It's useful if you want to do some final munging on the serialized JSON before returning it. + +```js +this.get('/movies', function (schema) { + let movies = schema.movies.all(); + let json = this.serialize(movies); + + json.meta = { page: 1 }; + + return json; +}); +``` + +By default this method uses the named serializer for the given Model or Collection. You can pass in a specific serializer name as the second argument: + +```js +this.get('/movies', function (schema) { + let movies = schema.movies.all(); + let json = this.serialize(movies, 'sparse-movie'); + + json.meta = { page: 1 }; + + return json; +}); +``` + +### normalizedRequestAttrs + +This helper returns the body of a request in a normalized form, suitable for working with and creating records. + +For example, if your Ember app makes a POST request with this data + +```js +// POST /users + +{ + data: { + type: 'users', + attributes: { + 'first-name': 'Conan', + 'middle-name': 'the', + 'last-name': 'Barbarian' + }, + relationships: { + team: { + data: { + type: 'teams', + id: 1 + } + } + } + } +} +``` + +then `normalizedRequestAttrs()` could be used like this + +```js +this.post('/users', function(schema, request) { + let attrs = this.normalizedRequestAttrs(); + /* + attrs = { + firstName: 'Conan', + middleName: 'the', + lastName: 'Barbarian', + teamId: '1' + } + */ + return schema.users.create(attrs); +}); +``` + +Note that attribute keys were camelCased, and the `team` foreign key was extracted. This is because a `user` owns the `team` foreign key; if another relationship were included in the request but the `user` did not own its foreign key, it would not have been extracted. + +This helper method leverages your serializer's `normalize` method. In the example above, it's assumed that the app was using the `JSONAPISerializer`, which comes with the `#normalize` method already written. If you're not using one of the bundled serializers, you'll need to implement `#normalize` and have it return a JSON:API document to take advantage of this method. + +Additionally, you'll need to use a full `function` here, as opposed to an ES6 arrow function (e.g `() => { ... }`). This is because `normalizedRequestAttrs` requires the `this` context from the function handler, and an arrow function would bind this from the outer scope. + +`normalizedRequestAttrs()` relies on a `modelName` to work and attempts to automatically detect it based on the URL of the request. If you use conventional URLs – for example, PATCH /users/1 – the helper should work. If you are using something custom – for example, PATCH /users/edit/1 – you’ll need to provide the `modelName` to the helper as the first argument: + +```js +this.patch('/users/edit/:id', function(schema, request) { + let attrs = this.normalizedRequestAttrs('user'); + // ... +}); +``` + + +## Status codes and headers + +By default, Mirage sets the HTTP status code of a response based on the verb being used for the route: + + - GET is 200 + - PATCH/PUT is 204 + - POST is 201 + - DEL is 204 + +PATCH/PUT and POST change to 200 if there is a response body. + +Additionally, a header for `Content-Type` is set to `application/json`. + +You can customize both the response code and headers by returning an instance of the `Response` class in your route handler: + +```js +// mirage/config.js +import { Response } from 'miragejs'; + +export default function() { + this.post('/authors', function(schema, request) { + let attrs = JSON.parse(request.requestBody).author; + + if (attrs.name) { + return schema.authors.create(attrs); + } else { + return new Response(400, { some: 'header' }, { errors: ['name cannot be blank'] }); + } + }); +} +``` + + +## External origins + +You can use Mirage to simulate other-origin requests. By default, a route like + +```js +this.get('/contacts', ...) +``` + +will hit the same origin that's serving your Ember app. To handle a different origin, use a fully qualified domain name: + +```js +this.get('http://api.twitter.com/v1', ...) +``` + +If your entire Ember app uses an external (other-origin) API, you can globally configure the domain via `urlPrefix`: + +```js +// mirage/config.js +this.urlPrefix = 'https://my.api.com'; + +// This route will handle requests to https://my.api.com/contacts +this.get('/contacts', ...) +``` + +--- + +That's it on writing low-level function route handlers! + +Function route handlers are flexible, but also cumbersome to write out for every endpoint. If you're working with an API that's conventional enough, hopefully you'll be writing fewer function route handlers and more Shorthands, which we'll discuss in the next section. diff --git a/tests/dummy/app/pods/docs/route-handlers/shorthands/template.md b/tests/dummy/app/pods/docs/route-handlers/shorthands/template.md new file mode 100644 index 000000000..f5df22ae3 --- /dev/null +++ b/tests/dummy/app/pods/docs/route-handlers/shorthands/template.md @@ -0,0 +1,239 @@ +# Shorthands + +APIs have become more standardized, so Mirage has the concept of *Shorthands* to deal with common scenarios. Shorthands can replace many of your custom route handlers, dramatically simplifying your server definition. + +For example, this function route handler + +```js +this.get('/movies', (schema, request) => { + return schema.movies.all(); +}); +``` + +is pretty standard: it responds to a URL path with a collection of the same name. + +The Shorthand form of this is + +```js +this.get('/movies'); +``` + +This is a complete route handler. It infers the model name from the last part of the URL, and returns the corresponding collection. + +Returning a single movie by ID is just as easy: + +```js +this.get('/movies/:id'); +``` + +There are also Shorthands for creating and editing data. For example, this function route handler creates a new movie: + +```js +this.post('/movies', (schema, request) => { + let attrs = JSON.parse(request.requestBody).movie; + + return schema.movies.create(attrs); +}); +``` + +It's also pretty standard: it creates a new model using the attributes from the request payload. The equivalent Shorthand is + +```js +this.post('/movies'); +``` + +See the full list of available Shorthands below. Shorthands use default status codes based on the HTTP verb: + + - GET, PATCH/PUT and DEL are 200 + - POST is 201 + +## GET Shorthands + +Fetching a collection: + +```js +// Shorthand +this.get('/contacts'); // finds type by singularizing url +this.get('/contacts', 'users'); // optionally specify the collection as second param + +// equivalent +this.get('/contacts', (schema) => { + return schema.contacts.all(); // users in the second case +}); +``` + +Fetching a model: + +```js +// Shorthand +this.get('/contacts/:id'); // finds type by singularizing url +this.get('/contacts/:id', 'user'); // optionally specify the type as second param + +// equivalent +this.get('/contacts/:id', (schema, request) => { + let id = request.params.id; + + return schema.contacts.find(id); // users in the second case +}); +``` + +Fetching multiple models by ID (for example, `GET /contacts?ids=1,3`): + +```js +// Shorthand +this.get('/contacts', { coalesce: true }); +this.get('/contacts', 'users', { coalesce: true }); + +// equivalent +this.get('/contacts', ({ contacts }, request) => { + let ids = request.queryParams.ids; + + return contacts.find(ids); // users in the second case +}); +``` + + +## POST Shorthands + +Creating a resource: + +```js +// Shorthand +this.post('/contacts'); // finds type by singularizing url +this.post('/contacts', 'user'); // optionally specify the type as second param + +// equivalent +this.post('/contacts', function(schema, request) { + let attrs = this.normalizedRequestAttrs(); + + return schema.contacts.create(attrs); +}); +``` + +For this POST shorthand to work, Mirage needs to know the format of the JSON payload your Ember app sends along with the request, so that it can insert the appropriate data into the database. See [the note on normalize](/docs/api/modules/serializer~Serializer#normalize) in the Serializer docs for more information. + +## PATCH/PUT Shorthands + +Updating a resource: + +```js +// Shorthand (these also work with this.put) +this.patch('/contacts/:id'); // finds type by singularizing url +this.patch('/contacts/:id', 'user'); // optionally specify the type as second param + +// equivalent +this.patch('/contacts/:id', function(schema, request) { + let id = request.params.id; + let attrs = this.normalizedRequestAttrs(); + + return schema.contacts.find(id).update(attrs); +}); +``` + +For this PATCH shorthand to work, Mirage needs to know the format of the JSON payload your Ember app sends along with the request, so that it can insert the appropriate data into the database. See the note on normalize in the Serializer docs for more information. + +## DELETE Shorthands + +Destroying a resource: + +```js +// Shorthand +this.del('/contacts/:id'); // finds type by singularizing url +this.del('/contacts/:id', 'user'); // optionally specify the type as second param + +// equivalent +this.del('/contacts/:id', (schema, request) => { + let id = request.params.id; + + schema.contacts.find(id).destroy(); +}); +``` + +Destroying a resource and related models: + +```js +// Shorthand +this.del('/contacts/:id', ['contact', 'addresses']); + +// equivalent +this.del('/contacts/:id', ({ contacts }, request) => { + let id = request.params.id; + let contact = contacts.find(id); + + contact.addresses.destroy(); + contact.destroy(); +}); +``` + +To use this Shorthand, you must have the appropriate `hasMany`/`belongsTo` relationships defined in your data layer. + + +## Resource helper + +The _resource_ helper lets you define multiple Shorthands for a given resource: + +```js +// Resource helper usage +this.resource('contacts'); + +// Shorthands defined +this.get('/contacts'); +this.get('/contacts/:id'); +this.post('/contacts'); +this.patch('/contacts/:id'); // and this.put('/contacts/:id') +this.del('/contacts/:id'); +``` + +You can also whitelist which Shorthands will be defined using the _only_ option: + +```js +this.resource('contacts', { only: [ 'index', 'show' ] }); + +// Shorthands defined +this.get('/contacts'); +this.get('/contacts/:id'); +``` + +or which route handlers shouldn't be defined using _except_ option: + +```js +this.resource('contacts', { except: [ 'update' ] }); + +// Shorthands defined +this.get('/contacts'); +this.get('/contacts/:id'); +this.post('/contacts'); +this.del('/contacts/:id'); +``` + +If your route path and collection names do not match, you can define a relative or absolute path using the _path_ option: + +```js +this.resource('blog-posts', { path: '/posts' }); + +// Shorthands defined +this.get('/posts', 'blog-posts'); +this.get('/posts/:id', 'blog-posts'); +this.post('/posts', 'blog-posts'); +this.put('/posts/:id', 'blog-posts'); +this.patch('/posts/:id', 'blog-posts'); +this.del('/posts/:id', 'blog-posts'); +``` + +Here is the full reference of the actions' names you can pass to the _only_ / _except_ options and the Shorthands they stand for: + +``` +Action | Shorthand +------------------------------ +index | this.get('/contacts') +show | this.get('/contacts/:id') +create | this.post('/contacts') +update | this.patch('contacts/:id') (or this.put) +delete | this.del('/contacts/:id') +``` + +--- + +Shorthands are a key part of staying productive in your frontend codebase, but they only work so well because Mirage has a Data Layer that's aware of your application's domain model. + +We'll cover how it works in the next few sections of the docs. diff --git a/tests/dummy/app/pods/docs/template.hbs b/tests/dummy/app/pods/docs/template.hbs new file mode 100644 index 000000000..139e246a2 --- /dev/null +++ b/tests/dummy/app/pods/docs/template.hbs @@ -0,0 +1,45 @@ + + + + {{nav.section "Getting started"}} + {{nav.item "What is Mirage?" "docs.getting-started.what-is-mirage"}} + {{nav.item "Installation" "docs.getting-started.installation"}} + {{nav.item "Upgrade guide" "docs.getting-started.upgrade-guide"}} + {{nav.item "Overview" "docs.getting-started.overview"}} + + {{nav.section "Route handlers"}} + {{nav.item "Functions" "docs.route-handlers.functions"}} + {{nav.item "Shorthands" "docs.route-handlers.shorthands"}} + + {{nav.section "Data layer"}} + {{nav.item "The Database" "docs.data-layer.database"}} + {{nav.item "Why an ORM?" "docs.data-layer.orm"}} + {{nav.item "Models" "docs.data-layer.models"}} + {{nav.item "Relationships" "docs.data-layer.relationships"}} + {{nav.item "Factories" "docs.data-layer.factories"}} + {{nav.item "Fixtures" "docs.data-layer.fixtures"}} + {{nav.item "Serializers" "docs.data-layer.serializers"}} + + {{nav.item "Ember Data Serializer" "docs.data-layer.serializers.ember-data-serializer"}} + + + {{nav.section "Testing"}} + {{nav.item "Acceptance tests" "docs.testing.acceptance-tests"}} + {{nav.item "Integration and unit tests" "docs.testing.integration-and-unit-tests"}} + {{nav.item "Assertions" "docs.testing.assertions"}} + + {{nav.section "Advanced"}} + {{nav.item "Environment options" "docs.advanced.environment-options"}} + {{nav.item "Server Configuration" "docs.advanced.server-configuration"}} + {{nav.item "Simulating cookie responses" "docs.advanced.simulating-cookie-responses"}} + {{nav.item "Mocking GUIDs" "docs.advanced.mocking-guids"}} + {{nav.item "Customizing the inflector" "docs.advanced.customizing-the-inflector"}} + {{nav.item "Switching between scenarios" "docs.advanced.switching-between-scenarios"}} + + + + + {{outlet}} + + + diff --git a/tests/dummy/app/pods/docs/testing/acceptance-tests/template.md b/tests/dummy/app/pods/docs/testing/acceptance-tests/template.md new file mode 100644 index 000000000..b70dbd966 --- /dev/null +++ b/tests/dummy/app/pods/docs/testing/acceptance-tests/template.md @@ -0,0 +1,184 @@ +# Acceptance tests + +Acceptance testing your Ember app involves verifying some user behavior. For example, you may want to test that the user can view a list of movies on your app's homepage. + +Many of these tests rely on a given server state. In other words, you want to test that, _given ten movie resources exist on the server_ at the time the user boots up the app, when the user visits the homepage they see a list of 10 movies. + +Mirage was originally built specifically for these sorts of high-level tests. Let's see how it works. + +Assuming you're using Application Tests (introduced in [Ember 3.0](https://emberjs.com/blog/2018/02/14/ember-3-0-released.html#toc_updates-to-the-testing-defaults)), add the `setupMirage` hook to the top of your test file: + +```diff + import { setupApplicationTest } from 'ember-qunit'; ++ import { setupMirage } from 'ember-cli-mirage/test-support'; + + + module('Acceptance | Homepage test', function(hooks) { + setupApplicationTest(hooks); ++ setupMirage(hooks); + + test('my first test', async function(assert) { + // test code + }); + }); +``` + +(If you are using pre-3.0 style tests, Mirage should boot automatically via an initializer. The only other difference is that Mirage is accessed via `server`, a global, whereas in 3.0-style tests Mirage is accessed via `this.server`. The rest of this guide will assume 3.0-style tests, but you can just use `server` in place of `this.server` and the rest of the documentation applies the same.) + +Now we can run your Ember app's test suite with `ember t -s`. + +In the test environment, Mirage will load all your route handlers from `mirage/config.js`, but it will ignore your seed data from `mirage/scenarios/default.js`. That means each test starts off with a clean database state. + +Within each test, you can use your factories to define your initial server state: + +```js +test('I can view the movies', async function(assert) { + this.server.createList('movie', 10); + + await visit('/'); + + assert.dom('li.movie').exists({ count: 10 }); +}); +``` + +After each test, Mirage's server will be reset, so none of this state will leak across tests. + + +## Keeping your tests focused + +Factories are important in keeping code that's relevant to a test as close to that test as possible. In the example above, we wanted to verify that the user would see ten movies, given those movies existed on the server. So, the `server.createList('movie', 10)` call was directly in the test. + +Say we wanted to test that when the user visits a details route for a movie titled "Interstellar," they would see that title in an `

` tag. One way to accomplish this would be to update the movie factory itself: + +```js +// mirage/factories/movie.js +import { Factory } from 'miragejs'; + +export default Factory.extend({ + title: 'Interstellar' +}); +``` + +The problem with this approach is that this change is very specific to this test. + +Suppose another test needed to verify something different about movies with different titles. Changing the factory to suit that case would break this test. + +For this reason, you should use `create` and `createList` to override specific attributes of your model. This will keep code relevant to your test near your test, without making the rest of your test suite brittle. + +```js +test('I can view the movies', async function(assert) { + this.server.createList('movie', 10); + + await visit('/'); + + assert.dom('li.movie').exists({ count: 10 }); +}); + +test("I see the movies's title on the detail route", await function(assert) { + let movie = this.server.create('movie', { + title: 'Interstellar' + }); + + await visit(`/movies/${movie.id}`); + + assert.dom('h1').hasText('Interstellar'); +}); +``` + + +## Arrange, Act, Assert + +Mirage recommends using the [Arrange, Act, Assert approach](https://github.com/testdouble/contributing-tests/wiki/Arrange-Act-Assert) to write tests. You'll sometimes hear this pattern referred to as **AAA testing** ("triple-A testing"). + +You can see this structure in our test from above: + +```js +test('I can view the movies', async function(assert) { + // ARRANGE + this.server.createList('movie', 10); + + // ACT + await visit('/'); + + // ASSERT + assert.dom('li.movie').exists({ count: 10 }); +}); +``` + +There are of course times where it makes sense to break this rule (for example to add some extra assertions near the beginning or middle of a test), but in general you should strive to follow the pattern. + + + + +## Testing errors + +To test how your Ember app responds to a server error, overwrite a route handler within a test: + +```js +test('the user sees an error if the save attempt fails', async function(assert) { + this.server.post('/questions', () => ({ + errors: [ 'The database went on vacation' ] + }), 500); + + await visit('/'); + await click('.new'); + await fillIn('input', 'New question'); + await click('.save'); + + assert.dom('h2').hasText('The database went on vacation'); +}); +``` + +This route handler definition is only in effect for the duration of this test, so as soon as it's over any handler you have defined for POST to `/questions` in your `config.js` file will be used again. + + +## Using scenarios in testing + +Typically you should reserve the `scenarios/default.js` file for development, so changes to it don't affect the rest of your test suite. That's why Mirage doesn't autoload this module during tests. + +If there's some logic you'd like to share between your development scenario and your tests, you can always make a new module under `scenarios` and import it in both places. + +If you'd like to load your development scenario in your tests, you can always directly import that module and run your test server through it: + +Create the module + +```js +// scenarios/shared.js +export default function(server) { + server.loadFixtures('countries'); + + server.createList('event', 10); +}; +``` + +...load it in your default scenario + +```js +import sharedScenario from '../../mirage/scenarios/shared'; + +test('I can view the authors', async function(assert) { + sharedScenario(server); + + await visit('/contacts'); + + assert.dom('p').exists({ count: 3 }); +}); +``` + +...and then also load it in your tests (or even a common test setup function): + +```js +import sharedScenario from '../../mirage/scenarios/shared'; + +test('I can view the authors', async function(assert) { + sharedScenario(server); + + // ... +}); +``` + +This same sort of pattern will work for Integration and Unit tests as well. + +--- + +Those are the basics of Acceptance Testing with Mirage! Next let's talk about Integration and Unit tests. diff --git a/tests/dummy/app/pods/docs/testing/assertions/template.md b/tests/dummy/app/pods/docs/testing/assertions/template.md new file mode 100644 index 000000000..af37486dd --- /dev/null +++ b/tests/dummy/app/pods/docs/testing/assertions/template.md @@ -0,0 +1,104 @@ +# Assertions + +Most of your tests will assert against your Ember app's UI. After visiting a route and interacting with the app, and after Mirage handles any requests, you'll assert that your UI is in the state you expect it to be. + +But sometimes even if your UI looks consistent, your app may have a bug on account of sending the wrong data to your server. + +To address this class of issues, you can assert against the state of your Mirage server within your tests, right alongside your UI assertions. This will give you more confidence that your Ember app is sending over the correct data to your backend. + + +## Asserting against Mirage's database + +The simplest way to assert that your Ember app is sending over the correct data to your backend is to assert against Mirage's database. If the correct data makes it there, you'll have confidence not only that the JSON payloads from your Ember app are correct, but that your Mirage route handlers are behaving as you expect. + +Here's an example: + +```js +test("I can change the lesson's title", async function(assert) { + this.server.create('lesson', { title: 'My First Lesson' }) + + await visit('/'); + await click('.Edit') + await fillIn('input', 'Updated lesson'); + await click('.Save'); + + // Assert against our app's UI + assert.dom('h1').hasText('Updated lesson'); + + // Also check that the data was "persisted" to our backend + assert.equal(this.server.db.lessons[0].title, 'Updated lesson'); +}); +``` + +This is a great way to gain some extra confidence that your Ember app is sending over the data you expect. + + +## Asserting against Mirage Models + +It can also be useful to assert against Mirage's ORM models, to verify things like updates to your model's relationships: + +```js +test('I can add a tag to a post', async function(assert) { + let programming = this.server.create('tag', { name: 'Programming' }); + let post = this.server.create('post'); + + await visit(`/posts/${post.id}/edit`); + await select('.tags', 'Programming'); + await click('.save'); + + assert.dom().includesText('Saved!'); + assert.equal(post.reload().tagIds.includes(programming.id)); +}); +``` + +The `reload` method on Mirage models will rehydrate them with any new database data since they were instantiated, allowing you to verify that your route handler logic worked as expected. + +Asserting against models is basically another way to verify Mirage's database data is correct. + + +## Asserting against handled requests and responses + +You can also assert against the actual HTTP requests and responses that are made during your test. + +To do this, first enable [Pretender's `trackedRequests` feature](https://github.com/pretenderjs/pretender#tracking-requests) by enabling the `trackRequests` environment option: + +```js +// config/environment.js +module.exports = function(environment) { + if (environment === 'test') { + ENV['ember-cli-mirage'] = { + trackRequests: true + }; + } +} +``` + +This feature is disabled by default to avoid memory issues during long development sessions. + +Now Mirage will track every request (along with the associated response) and make them available to you via `server.pretender.handledRequests`. That way you can assert against requests in that array at the end of your test. + +```js +test("I can filter the table", async function(assert) { + this.server.createList('movie', 5, { genre: 'Sci-Fi' }); + this.server.createList('movie', 3, { genre: 'Drama' }); + + await visit('/'); + await select('.genre', 'Sci-Fi'); + + // Assert against our app's UI + assert.dom('tr').exists({ count: 5 }); + + // Also assert against the HTTP request count & query + let requests = this.server.pretender.handledRequests; + assert.equal(requests.length, 1); + assert.deepEqual(requests[0].queryParams, { 'filter[genre]': 'Sci-Fi' }); +}); +``` + +In general we recommend asserting against Mirage's database and your UI, as the specifics of your app's HTTP requests should be considered implementation details of the behavior you're actually interested in verifying. But there's certainly valid reasons to drop down and assert against HTTP data. + + + +--- + +And with that, you've completed the main portion of the guides! Read on to see some advanced use cases and configuration options, or head over to the API docs to see how to use Mirage's various classes. diff --git a/tests/dummy/app/pods/docs/testing/integration-and-unit-tests/template.md b/tests/dummy/app/pods/docs/testing/integration-and-unit-tests/template.md new file mode 100644 index 000000000..9e4b90cc0 --- /dev/null +++ b/tests/dummy/app/pods/docs/testing/integration-and-unit-tests/template.md @@ -0,0 +1,255 @@ +# Integration and unit tests + +While Mirage was originally designed for acceptance testing, it also works great when writing integration and unit tests. + +Let's say you have a data-fetching component, and you want to write a [rendering test](https://guides.emberjs.com/release/testing/#toc_rendering-tests) to verify its behavior. + +You can import and use the `setupMirage` function directly in your rendering test, and use Mirage just like you would in an acceptance test. + +```js +import { module } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { setupMirage } from 'ember-cli-mirage/test-support'; + +module('Integration | Component | FindRecord', function(hooks) { + setupRenderingTest(hooks); + setupMirage(hooks); + + test('it can fetch records', async function(assert) { + this.server.create('movie', { title: 'Interstellar' }); + + await render(hbs` + +

{{model.title}}

+
+ `); + + assert.equal(this.element.textContent, 'Interstellar'); + }); +}); +``` + +If you want to define some new logic for your Mirage route handlers instead of using the global ones defined in your `mirage/config.js` file, you can use `this.server` to setup new routes. + + +```js +import { module } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { setupMirage } from 'ember-cli-mirage/test-support'; + +module('Integration | Component | FindRecord', function(hooks) { + setupRenderingTest(hooks); + setupMirage(hooks); + + test('it renders an error state', async function(assert) { + this.server.get( + '/movies/:id', + () => ({ errors: [ 'Something went wrong' ]}), + 500 + ); + + await render(hbs` + + {{#if error}} +

Whoops!

+ {{/if}} +
+ `); + + assert.equal(this.element.textContent, 'Whoops!'); + }); +}); +``` + +## Creating Ember Data models on the client with Mirage + +Something that can be a bit confusing is when you need to write a test against Ember Data models, and you reach for Mirage to help you create some. + +For example, let's say we were writing a rendering test to verify the behavior of our `` component: + +```js +module('Integration | Component | ArticleForm', function(hooks) { + setupRenderingTest(hooks); + setupMirage(hooks); + + test('it can edit an article', async function(assert) { + // get the article + + await render(hbs` + + `); + + await fillIn('input', 'New title'); + await click('.save'); + + // assert the model was saved + }); +}); +``` + +How might we test this? + +It might be tempting to use Mirage's `server.create`, since you probably already have factories defined: + +```js +module('Integration | Component | ArticleForm', function(hooks) { + setupRenderingTest(hooks); + setupMirage(hooks); + + test('it can edit an article', async function(assert) { + // 🔴 Don't do this + let article = this.server.create('article', { + title: 'Old title' + }); + this.set('article', article); + + await render(hbs` + + `); + + await fillIn('input', 'New title'); + await click('.save'); + + // assert the model was saved + }); +}); +``` + +But you shouldn't do this. + +Even though Mirage pulls its initial schema from your Ember Data models, Mirage models don't actually know anything about your Ember app. + +Mirage models exist solely in your "backend", and are only useful in helping you create your mock server definition. + +The only way data gets from Mirage to your Ember app is via an HTTP request – which is also true for your production server. + +So, in the same way that you wouldn't create a model in your server-side framework and pass it directly into an Ember component, you should also not pass a Mirage model directly into an Ember component. + +```js +// 🔴 Don't do this +// `article` is a Mirage model. It should never be consumed directly by Ember code. +let article = this.server.create('article'); +this.set('article', article); + +await render(hbs` + +`); +``` + +So, how might we get an article materialized into Ember Data's store so we can test this component, while still leveraging our Mirage factory definitions? + +Right now, there is no first-class API for this, but one is in the works. In the meantime, there are two common ways to accomplish this. + +### Using findRecord and findAll + +The first approach is to lookup Ember Data's store, and use it to find the record (just like your Ember application's routes do): + +```js +import { module } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { setupMirage } from 'ember-cli-mirage/test-support'; +import { click, fillIn } from '@ember/test-helpers'; + +module('Integration | Component | ArticleForm', function(hooks) { + setupRenderingTest(hooks); + setupMirage(hooks); + + test('it can edit an article', async function(assert) { + // ✅ Option 1: Use the store to find the record + let serverArticle = this.server.create('article', { + title: 'Old title' + }); + let store = this.owner.lookup('service:store'); + let article = await store.findRecord('article', serverArticle.id); + this.set('article', article); + + await render(hbs` + + `); + + await fillIn('input', 'New title'); + await click('.save'); + + // assert the model was saved + }); +}); +``` + +### Writing a helper to push Mirage's database + +The second approach is to make a helper that serializers Mirage's database into JSON and pushes that JSON into your Ember Data store. + +The actual logic might depend on the configuration of your Mirage server, but if you're following all of Mirage's conventions it should look roughly like this: + +```js +// your-app/tests/helpers/push-mirage-into-store.js +import { getContext } from '@ember/test-helpers'; +import { run } from '@ember/runloop'; + +export default function() { + let context = getContext(); + let store = context.owner.lookup('service:store'); + + Object.keys(context.server.schema) + .filter(key => context.server.schema[key].all !== undefined) // Get the resources + .forEach(resource => { + let models = context.server.schema[resource].all(); + let modelName = models.modelName; + let serializer = context.server.serializerOrRegistry.serializerFor(modelName); + + let originalAlwaysIncludeLinkageData = serializer.alwaysIncludeLinkageData; + serializer.alwaysIncludeLinkageData = true; + + let json = serializer.serialize(models); + + serializer.alwaysIncludeLinkageData = originalAlwaysIncludeLinkageData; + + run(() => { + store.pushPayload(json); + }); + }); +} +``` + +Now in your test, call your helper to seed Ember Data's store, and then use `peekRecord` to materialize and work with Ember Data records: + +```js +import { module } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { setupMirage } from 'ember-cli-mirage/test-support'; +import { click, fillIn } from '@ember/test-helpers'; +import pushMirageIntoStore from 'YOUR-APP/tests/helpers/push-mirage-into-store'; + +module('Integration | Component | ArticleForm', function(hooks) { + setupRenderingTest(hooks); + setupMirage(hooks); + + test('it can edit an article', async function(assert) { + // ✅ Option 2: Use the store to find the record + let serverArticle = this.server.create('article', { + title: 'Old title' + }); + pushMirageIntoStore(); + let store = this.owner.lookup('service:store'); + let article = store.peekRecord('article', serverArticle.id); + this.set('article', article); + + await render(hbs` + + `); + + await fillIn('input', 'New title'); + await click('.save'); + + // assert the model was saved + }); +}); +``` + +Something like `pushMirageIntoStore` will probably make its way into Mirage at some point. + +--- + +Now that you've seen how to use `setupMirage` outside of an acceptance test, you can use it in any kind of test where it makes sense to run your Mirage server! + +Next, we discuss some ways you can go about asserting against your Mirage mock server. diff --git a/tests/dummy/app/pods/index/template.hbs b/tests/dummy/app/pods/index/template.hbs new file mode 100644 index 000000000..ebf45da9c --- /dev/null +++ b/tests/dummy/app/pods/index/template.hbs @@ -0,0 +1,30 @@ + + +
+
+

Productive

+

+ Spend less time wiring up HTTP stubs, and get back to developing your app. +

+
+ +
+

Test-worthy

+

+ Use factories to define your server's state per test. Acceptance testing just got a whole lot easier. +

+
+ +
+

Shareable

+

+ Share a functional prototype of your app that runs entirely in the client – before writing a single line of your API. +

+
+ +
+ + Read the docs + +
+
diff --git a/tests/dummy/app/pods/not-found/route.js b/tests/dummy/app/pods/not-found/route.js new file mode 100644 index 000000000..b65e31d9a --- /dev/null +++ b/tests/dummy/app/pods/not-found/route.js @@ -0,0 +1,95 @@ +import Route from '@ember/routing/route'; + +export default class extends Route { + beforeModel() { + let { path } = this.paramsFor('not-found'); + + this.redirects.forEach((redirect) => { + redirect.from.forEach((candidate) => { + if (path === candidate || path === `${candidate}/`) { + this.transitionTo('blog.detail', redirect.to.replace('blog/', '')); + } + }); + }); + } + + redirects = [ + { + from: [ + 'blog/2018/02/01/changing-mirages-default-linkage-data-behavior', + 'blog/2018-02-01-changing-mirages-default-linkage-data-behavior', + ], + to: 'blog/changing-mirages-default-linkage-data-behavior-1475', + }, + { + from: [ + 'blog/2017/06/05/polymorphic-associations-and-auto-discovery-of-ember-data-models', + 'blog/2017-06-05-polymorphic-associations-and-auto-discovery-of-ember-data-models', + ], + to: 'blog/polymorphic-associations-and-auto-discovery-of-ember-data-models-1483', + }, + { + from: [ + 'blog/2017/01/09/0-3-0-beta-series', + 'blog/2017-01-09-0-3-0-beta-series', + ], + to: 'blog/0-3-0-beta-series-1484', + }, + { + from: [ + 'blog/2016/05/31/0-2-0-released', + 'blog/2016-05-31-0-2-0-released', + ], + to: 'blog/0-2-0-released-1485', + }, + { + from: [ + 'blog/2016/01/03/0-2-0-beta.9-released', + 'blog/2016-01-03-0-2-0-beta-9-released', + ], + to: 'blog/0-2-0-beta-9-released-1486', + }, + { + from: [ + 'blog/2016/01/03/0-2-update-only-inject-schema', + 'blog/2016-01-03-0-2-update-only-inject-schema', + ], + to: 'blog/0-2-update-only-inject-schema-1487', + }, + { + from: [ + 'blog/2015/11/03/inside-ember-cli-mirage', + 'blog/2015-11-03-inside-ember-cli-mirage', + ], + to: 'blog/inside-ember-cli-mirage-1488', + }, + { + from: [ + 'blog/2015/10/19/serializers-ready', + 'blog/2015-10-19-serializers-ready', + ], + to: 'blog/serializers-ready-1489', + }, + { + from: [ + 'blog/2015/09/15/router-handler', + 'blog/2015-09-15-router-handler', + ], + to: 'blog/router-handler-1490', + }, + { + from: [ + 'blog/2015/09/10/orm-not-ready-yet', + 'blog/2015-09-10-orm-not-ready-yet', + ], + to: 'blog/orm-not-ready-yet-1491', + }, + { + from: [ + 'blog/2015/09/06/thoughts-on-model-attribute-formatting', + 'blog/2015-09-06-thoughts-on-model-attribute-formatting', + ], + to: 'blog/thoughts-on-model-attribute-formatting-1492', + }, + ]; +} diff --git a/tests/dummy/app/pods/not-found/template.hbs b/tests/dummy/app/pods/not-found/template.hbs new file mode 100644 index 000000000..ff6dab082 --- /dev/null +++ b/tests/dummy/app/pods/not-found/template.hbs @@ -0,0 +1,4 @@ +
+

Not found

+

This page doesn't exist. Head home?

+
diff --git a/tests/dummy/app/resolver.js b/tests/dummy/app/resolver.js deleted file mode 100644 index 2fb563d6c..000000000 --- a/tests/dummy/app/resolver.js +++ /dev/null @@ -1,3 +0,0 @@ -import Resolver from 'ember-resolver'; - -export default Resolver; diff --git a/tests/dummy/app/router.js b/tests/dummy/app/router.js index ea07502c0..c68a6ae3b 100644 --- a/tests/dummy/app/router.js +++ b/tests/dummy/app/router.js @@ -1,22 +1,60 @@ -import Ember from 'ember'; -import config from './config/environment'; +import AddonDocsRouter, { docsRoute } from 'ember-cli-addon-docs/router'; +import config from 'dummy/config/environment'; -const Router = Ember.Router.extend({ - location: config.locationType, - rootURL: config.rootURL -}); +export default class Router extends AddonDocsRouter { + location = config.locationType; + rootURL = config.rootURL; +} -Router.map(function() { - this.route('contacts', { path: '/' }); - this.route('contact', { path: '/:contact_id' }); - this.route('edit', { path: '/:contact_id/edit' }); +Router.map(function () { + docsRoute(this, function () { + this.route('getting-started', function () { + this.route('what-is-mirage'); + this.route('installation'); + this.route('upgrade-guide'); + this.route('overview'); + }); - this.route('friends'); - this.route('friend', { path: '/friends/:friend_id' }); - this.route('close-friends'); - this.route('pets'); + this.route('route-handlers', function () { + this.route('functions'); + this.route('shorthands'); + }); - this.route('word-smith', { path: '/word-smiths/:word_smith_id' }); -}); + this.route('data-layer', function () { + this.route('database'); + this.route('orm'); + this.route('models'); + this.route('relationships'); + this.route('factories'); + this.route('fixtures'); + this.route('serializers', function () { + this.route('ember-data-serializer'); + }); + }); + + this.route('testing', function () { + this.route('acceptance-tests'); + this.route('integration-and-unit-tests'); + this.route('assertions'); + }); + + this.route('advanced', function () { + this.route('environment-options'); + this.route('server-configuration'); + this.route('simulating-cookie-responses'); + this.route('mocking-guids'); + this.route('customizing-the-inflector'); + this.route('switching-between-scenarios'); + }); -export default Router; + this.route('api', function () { + this.route('class', { path: '/:class_id' }); + }); + }); + + this.route('blog', function () { + this.route('detail', { path: '/:post_slug_and_id' }); + }); + + this.route('not-found', { path: '/*path' }); +}); diff --git a/tests/dummy/app/routes/application.js b/tests/dummy/app/routes/application.js deleted file mode 100644 index 701e1231f..000000000 --- a/tests/dummy/app/routes/application.js +++ /dev/null @@ -1,30 +0,0 @@ -import Ember from 'ember'; - -const { Route } = Ember; - -export default Route.extend({ - - actions: { - createContact() { - let controller = this.controllerFor('contacts'); - let name = controller.get('newName'); - let newContact = this.store.createRecord('contact', { name }); - controller.set('newName', ''); - - return newContact.save(); - }, - - saveContact(contact) { - return contact.save().then((contact) => { - this.transitionTo('contact', contact); - }); - }, - - deleteContact(contact) { - return contact.destroyRecord().then(() => { - this.transitionTo('contacts'); - }); - } - } - -}); diff --git a/tests/dummy/app/routes/close-friends.js b/tests/dummy/app/routes/close-friends.js deleted file mode 100644 index 6fb75c379..000000000 --- a/tests/dummy/app/routes/close-friends.js +++ /dev/null @@ -1,16 +0,0 @@ -import Ember from 'ember'; - -const { Route } = Ember; - -export default Route.extend({ - - model() { - let store = this.get('store'); - return store.query('friend', { ids: [1, 3] }).then(function() { - // I request 2 friends and then return all friends to be sure no other friend - // was loaded into the store. - return store.peekAll('friend'); - }); - } - -}); diff --git a/tests/dummy/app/routes/contacts.js b/tests/dummy/app/routes/contacts.js deleted file mode 100644 index 04941c6d7..000000000 --- a/tests/dummy/app/routes/contacts.js +++ /dev/null @@ -1,24 +0,0 @@ -import Ember from 'ember'; - -const { Route } = Ember; - -export default Route.extend({ - - model() { - return this.store.findAll('contact') - .catch((reason) => { - let errorMsg = reason.responseJSON ? reason.responseJSON.errors[0] : reason.errors[0]; - - this.set('error', errorMsg); - }); - }, - - setupController(controller, model) { - if (this.get('error')) { - controller.set('error', this.get('error')); - } else { - controller.set('model', model); - } - } - -}); diff --git a/tests/dummy/app/routes/friends.js b/tests/dummy/app/routes/friends.js deleted file mode 100644 index 9479f43d0..000000000 --- a/tests/dummy/app/routes/friends.js +++ /dev/null @@ -1,11 +0,0 @@ -import Ember from 'ember'; - -const { Route } = Ember; - -export default Route.extend({ - - model() { - return this.store.findAll('friend'); - } - -}); diff --git a/tests/dummy/app/routes/pets.js b/tests/dummy/app/routes/pets.js deleted file mode 100644 index 8803a0801..000000000 --- a/tests/dummy/app/routes/pets.js +++ /dev/null @@ -1,30 +0,0 @@ -import Ember from 'ember'; - -const { Route } = Ember; - -export default Route.extend({ - - actions: { - createPet() { - let controller = this.controllerFor('pets'); - let name = controller.get('petName'); - controller.set('petName', ''); - this.store.createRecord('pet', { name, alive: true }); - } - }, - - setupController(controller, model) { - if (this.get('error')) { - controller.set('error', this.get('error')); - } else { - controller.set('model', model); - } - }, - - model() { - return this.store.findAll('pet').catch((reason) => { - let errorMsg = reason.responseJSON ? reason.responseJSON.errors[0] : reason.errors[0]; - this.set('error', errorMsg); - }); - } -}); diff --git a/tests/dummy/app/serializers/address.js b/tests/dummy/app/serializers/address.js new file mode 100644 index 000000000..fc169f874 --- /dev/null +++ b/tests/dummy/app/serializers/address.js @@ -0,0 +1,5 @@ +import RestSerializer from '@ember-data/serializer/rest'; + +export default class extends RestSerializer { + primaryKey = 'addressId'; +} diff --git a/tests/dummy/app/serializers/application.js b/tests/dummy/app/serializers/application.js index e78d1a9d4..54c1691de 100644 --- a/tests/dummy/app/serializers/application.js +++ b/tests/dummy/app/serializers/application.js @@ -1,3 +1,13 @@ -import { ActiveModelSerializer } from 'active-model-adapter'; +import JSONAPISerializer from '@ember-data/serializer/json-api'; -export default ActiveModelSerializer; +export default class extends JSONAPISerializer { + appSerializer = true; + + // I do not know why I had to make these two lines to get the home-test to pass + keyForAttribute(key) { + return key; + } + keyForRelationship(key) { + return key; + } +} diff --git a/tests/dummy/app/serializers/blog-post.js b/tests/dummy/app/serializers/blog-post.js deleted file mode 100644 index 724140afc..000000000 --- a/tests/dummy/app/serializers/blog-post.js +++ /dev/null @@ -1,5 +0,0 @@ -import DS from 'ember-data'; - -const { JSONAPISerializer } = DS; - -export default JSONAPISerializer; diff --git a/tests/dummy/app/serializers/post.js b/tests/dummy/app/serializers/post.js new file mode 100644 index 000000000..33d31a206 --- /dev/null +++ b/tests/dummy/app/serializers/post.js @@ -0,0 +1,3 @@ +import JSONAPISerializer from '@ember-data/serializer/json-api'; + +export default class extends JSONAPISerializer {} diff --git a/tests/dummy/app/serializers/word-smith.js b/tests/dummy/app/serializers/word-smith.js index 724140afc..e6a924729 100644 --- a/tests/dummy/app/serializers/word-smith.js +++ b/tests/dummy/app/serializers/word-smith.js @@ -1,5 +1,8 @@ -import DS from 'ember-data'; +import RestSerializer from '@ember-data/serializer/rest'; -const { JSONAPISerializer } = DS; - -export default JSONAPISerializer; +export default class extends RestSerializer { + attrs = { + address: 'addressId', + blogPosts: { deserialize: 'records' }, + }; +} diff --git a/tests/dummy/app/styles/app.css b/tests/dummy/app/styles/app.css index 9adb5ad01..fa171bcea 100644 --- a/tests/dummy/app/styles/app.css +++ b/tests/dummy/app/styles/app.css @@ -1,3 +1,155 @@ -html, body { - margin: 20px; +:root { + --brand-primary: #0e97ad; +} + +.home { + padding-left: 1rem; + padding-right: 1rem; + max-width: 600px; + margin: 4rem auto; +} +.home__section { + margin-bottom: 2.5rem; +} +.home__lead { + margin-top: 0.5rem; + font-size: 18px; + line-height: 1.5; +} +.home__cta { + padding: 3rem 0; +} +.home__cta-link { + color: #22292f; +} + +.blog { + width: 100%; + margin-top: 3rem; + margin-bottom: 3rem; +} +@media (min-width: 768px) { + .blog { + display: flex; + } +} + +.blog__placeholder { + width: calc(((100% - 1400px) / 2) + 288px); + padding-left: calc((100% - 1400px) / 2); +} +.blog__content { + max-width: 869px; + padding-left: 1rem; + padding-right: 1rem; +} +@media (min-width: 768px) { + .blog__content { + padding-left: 2rem; + padding-right: 2rem; + } +} +@media (min-width: 992px) { + .blog__content { + padding-left: 5rem; + padding-right: 5rem; + } +} + +.blog-index h1 { + margin-bottom: 1.5rem; + color: rgb(61, 72, 82); + font-size: 2.25rem; + font-weight: 800; + line-height: 1.25; + text-decoration: none; +} + +.blog-index section { + margin: 30px 0; +} + +.blog-index h2 { + line-height: 1.25; +} +.blog-index h2 a { + color: rgb(61, 72, 82); + text-decoration: none; + /* font-weight: 800; + font-size: 28px; */ +} +.blog-index h2 a:hover { + text-decoration: underline; +} +.blog-index p { + color: #8795A1; +} + +.blog-detail time, +.blog-index time { + color: #8795A1; + text-transform: uppercase; + font-size: 14px; + font-weight: 500; +} +.blog-detail__back-link { + text-decoration: none; + color: #8795A1; + display: block; + margin-bottom: 30px; +} + +.blog-detail__back-link:hover { + color: rgb(61, 72, 82); +} + +.blog-detail__hr { + border-width: 1px; + margin: 3rem 0; +} +.blog-detail__comments { + margin-bottom: 6rem; +} + +.blog-detail__comment { + display: flex; + padding-top: 2rem; +} + +.blog-detail__comment-profile-link { + flex-shrink: 0; +} +.blog-detail__comment-avatar { + border-radius: 4px; + width: 48px; + height: 48px; + margin-right: 2rem; +} + +.blog-detail__comment-body { + /* padding-lef */ +} +.blog-detail__comment-info { + color: #8795A1; + font-size: 14px; +} +.blog-detail__comment-permalink { + color: #8795A1; + text-decoration: none; +} +.blog-detail__comment-permalink:hover { + color: #3d4852; +} +.blog-detail__username-link { + color: #3d4852; + font-weight: 600; + text-decoration: none; +} +.blog-detail__comments-github-byline { + margin-top: 2rem; + font-style: italic; + color: #8795A1; +} +.blog-detail__comments-github-link { + color: #8795A1; } diff --git a/tests/dummy/app/templates/.gitkeep b/tests/dummy/app/templates/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/tests/dummy/app/templates/application.hbs b/tests/dummy/app/templates/application.hbs deleted file mode 100644 index f8bc38e7b..000000000 --- a/tests/dummy/app/templates/application.hbs +++ /dev/null @@ -1,3 +0,0 @@ -

Welcome to Ember

- -{{outlet}} diff --git a/tests/dummy/app/templates/close-friends.hbs b/tests/dummy/app/templates/close-friends.hbs deleted file mode 100644 index 0b214ef65..000000000 --- a/tests/dummy/app/templates/close-friends.hbs +++ /dev/null @@ -1,3 +0,0 @@ -{{#each model as |friend|}} -

{{friend.name}} is your {{friend.age}}-year-old friend.

-{{/each}} diff --git a/tests/dummy/app/templates/contact.hbs b/tests/dummy/app/templates/contact.hbs deleted file mode 100644 index a90a2cbee..000000000 --- a/tests/dummy/app/templates/contact.hbs +++ /dev/null @@ -1,13 +0,0 @@ -{{link-to 'Back home' 'contacts'}} - -

The contact is {{model.name}}

- -
- {{#link-to 'edit' model}} - - {{/link-to}} -
- -
- -
diff --git a/tests/dummy/app/templates/contacts.hbs b/tests/dummy/app/templates/contacts.hbs deleted file mode 100644 index ef7c2d9d9..000000000 --- a/tests/dummy/app/templates/contacts.hbs +++ /dev/null @@ -1,17 +0,0 @@ -{{#if error}} -

There was an error: {{error}}

-{{else}} - {{#each model as |contact|}} -

{{link-to contact.name 'contact' contact}}

- {{/each}} -{{/if}} - -
- -
-
{{input value=newName placeholder='Name'}}
- -
- -
-
diff --git a/tests/dummy/app/templates/edit.hbs b/tests/dummy/app/templates/edit.hbs deleted file mode 100644 index 757d7a289..000000000 --- a/tests/dummy/app/templates/edit.hbs +++ /dev/null @@ -1,6 +0,0 @@ -
- {{input value=model.name}} -
- -{{link-to 'Cancel' 'contact' model}} - diff --git a/tests/dummy/app/templates/friend.hbs b/tests/dummy/app/templates/friend.hbs deleted file mode 100644 index 911ecc752..000000000 --- a/tests/dummy/app/templates/friend.hbs +++ /dev/null @@ -1 +0,0 @@ -

{{model.name}}

diff --git a/tests/dummy/app/templates/friends.hbs b/tests/dummy/app/templates/friends.hbs deleted file mode 100644 index 0b214ef65..000000000 --- a/tests/dummy/app/templates/friends.hbs +++ /dev/null @@ -1,3 +0,0 @@ -{{#each model as |friend|}} -

{{friend.name}} is your {{friend.age}}-year-old friend.

-{{/each}} diff --git a/tests/dummy/app/templates/pets.hbs b/tests/dummy/app/templates/pets.hbs deleted file mode 100644 index 0a6d37868..000000000 --- a/tests/dummy/app/templates/pets.hbs +++ /dev/null @@ -1,11 +0,0 @@ -{{#if error}} -

There was an error: {{error}}

-{{else}} -
    - {{#each model as |pet|}} -
  • {{pet.name}} / alive: {{pet.alive}}
  • - {{/each}} - {{input value=petName}} - -
-{{/if}} diff --git a/tests/dummy/config/ember-cli-update.json b/tests/dummy/config/ember-cli-update.json new file mode 100644 index 000000000..73cc7e5cf --- /dev/null +++ b/tests/dummy/config/ember-cli-update.json @@ -0,0 +1,21 @@ +{ + "schemaVersion": "1.0.0", + "packages": [ + { + "name": "ember-cli", + "version": "3.28.4", + "blueprints": [ + { + "name": "addon", + "outputRepo": "https://github.com/ember-cli/ember-addon-output", + "codemodsSource": "ember-addon-codemods-manifest@1", + "isBaseBlueprint": true, + "options": [ + "--yarn", + "--no-welcome" + ] + } + ] + } + ] +} diff --git a/tests/dummy/config/environment.js b/tests/dummy/config/environment.js index 6a378d3d4..dd130afde 100644 --- a/tests/dummy/config/environment.js +++ b/tests/dummy/config/environment.js @@ -1,26 +1,31 @@ -/* eslint-env node */ +'use strict'; -module.exports = function(environment) { - var ENV = { +module.exports = function (environment) { + let ENV = { modulePrefix: 'dummy', - environment: environment, + podModulePrefix: 'dummy/pods', + environment, rootURL: '/', locationType: 'auto', EmberENV: { FEATURES: { // Here you can enable experimental features on an ember canary build - // e.g. 'with-controller': true + // e.g. EMBER_NATIVE_DECORATOR_SUPPORT: true }, EXTEND_PROTOTYPES: { // Prevent Ember Data from overriding Date.parse. - Date: false - } + Date: false, + }, }, APP: { // Here you can pass flags/options to your application instance // when it is created - } + }, + + 'ember-cli-addon-docs': { + showImportPaths: false, + }, }; if (environment === 'development') { @@ -40,10 +45,13 @@ module.exports = function(environment) { ENV.APP.LOG_VIEW_LOOKUPS = false; ENV.APP.rootElement = '#ember-testing'; + ENV.APP.autoboot = false; } if (environment === 'production') { - + // Allow ember-cli-addon-docs to update the rootURL in compiled assets + ENV.rootURL = 'ADDON_DOCS_ROOT_URL'; + // here you can enable a production-specific feature } return ENV; diff --git a/tests/dummy/config/optional-features.json b/tests/dummy/config/optional-features.json new file mode 100644 index 000000000..b26286e2e --- /dev/null +++ b/tests/dummy/config/optional-features.json @@ -0,0 +1,6 @@ +{ + "application-template-wrapper": false, + "default-async-observers": true, + "jquery-integration": false, + "template-only-glimmer-components": true +} diff --git a/tests/dummy/config/targets.js b/tests/dummy/config/targets.js new file mode 100644 index 000000000..0b433b73c --- /dev/null +++ b/tests/dummy/config/targets.js @@ -0,0 +1,27 @@ +'use strict'; + +const browsers = [ + 'last 1 Chrome versions', + 'last 1 Firefox versions', + 'last 1 Safari versions', +]; + +// Ember's browser support policy is changing, and IE11 support will end in +// v4.0 onwards. +// +// See https://deprecations.emberjs.com/v3.x#toc_3-0-browser-support-policy +// +// If you need IE11 support on a version of Ember that still offers support +// for it, uncomment the code block below. +// +// const isCI = Boolean(process.env.CI); +// const isProduction = process.env.EMBER_ENV === 'production'; +// +// if (isCI || isProduction) { +// browsers.push('ie 11'); +// } + +module.exports = { + browsers, + node: 'current', +}; diff --git a/tests/dummy/mirage/config.js b/tests/dummy/mirage/config.js index 419fa990a..e9914bf42 100644 --- a/tests/dummy/mirage/config.js +++ b/tests/dummy/mirage/config.js @@ -1,47 +1,27 @@ -import Mirage from 'ember-cli-mirage'; -import Ember from 'ember'; - -const { isBlank } = Ember; - -export default function() { - // Contacts - this.get('/contacts'); - // this.get('/contacts', ['contacts', 'addresses']); - this.get('/contacts/:id'); - this.post('/contacts'); - this.put('/contacts/:id'); - this.del('/contacts/:id'); - - // Friends - this.get('/friends', { coalesce: true }); - - // Pets - this.get('/pets', function({ db }) { - return { pets: db.pets.filter((pet) => pet.alive) }; - }); - - this.post('/pets', function({ db }, req) { - let { pet } = JSON.parse(req.requestBody); - if (isBlank(pet.name)) { - let body = { errors: { name: ["can't be blank"] } }; - return new Mirage.Response(422, { some: 'header' }, body); - } else { - return { pet: db.pets.insert(pet) }; - } - }); - - this.put('/pets/:id', function({ db }, req) { - let { pet } = JSON.parse(req.requestBody); - db.pets.update(pet.id, pet); - return pet; - }); - - this.delete('/pets/:id', function() { }, 200); - - this.get('/word-smiths/:id'); - +import { + discoverEmberDataModels, + applyEmberDataSerializers, +} from 'ember-cli-mirage'; +import { createServer } from 'miragejs'; + +export default function (config) { + let finalConfig = { + ...config, + models: { ...discoverEmberDataModels(), ...config.models }, + serializers: applyEmberDataSerializers(config.serializers), + routes, + }; + + return createServer(finalConfig); } -export function testConfig() { - this.get('/friends/:id'); +function routes() { + // + // { + // "message": "API rate limit exceeded for 72.229.126.12. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)", + // "documentation_url": "https://developer.github.com/v3/#rate-limiting" + // } + + this.passthrough(); + this.passthrough('https://api.github.com/*'); } diff --git a/tests/dummy/mirage/factories/address.js b/tests/dummy/mirage/factories/address.js deleted file mode 100644 index cf5aa2026..000000000 --- a/tests/dummy/mirage/factories/address.js +++ /dev/null @@ -1,4 +0,0 @@ -import Mirage from 'ember-cli-mirage'; - -export default Mirage.Factory.extend({ -}); diff --git a/tests/dummy/mirage/factories/blog-post.js b/tests/dummy/mirage/factories/blog-post.js deleted file mode 100644 index 6da02d311..000000000 --- a/tests/dummy/mirage/factories/blog-post.js +++ /dev/null @@ -1,9 +0,0 @@ -import { Factory, faker } from 'ember-cli-mirage'; - -export default Factory.extend({ - - title() { - return faker.lorem.sentence(); - } - -}); diff --git a/tests/dummy/mirage/factories/contact.js b/tests/dummy/mirage/factories/contact.js deleted file mode 100644 index 6bae0bd01..000000000 --- a/tests/dummy/mirage/factories/contact.js +++ /dev/null @@ -1,17 +0,0 @@ -import Mirage from 'ember-cli-mirage'; -import { faker } from 'ember-cli-mirage'; - -export default Mirage.Factory.extend({ - title: faker.list.cycle('Duke', 'Developer', 'Artist'), - name: faker.name.firstName, - age: 20, - - email(i) { - return `person${i}@test.com`; - }, - - admin() { - return this.age > 30; - } - -}); diff --git a/tests/dummy/mirage/factories/friend.js b/tests/dummy/mirage/factories/friend.js deleted file mode 100644 index 6c8671285..000000000 --- a/tests/dummy/mirage/factories/friend.js +++ /dev/null @@ -1,7 +0,0 @@ -import ContactFactory from './contact'; - -export default ContactFactory.extend({ - isYoung() { - return this.age < 18; - } -}); diff --git a/tests/dummy/mirage/factories/pet.js b/tests/dummy/mirage/factories/pet.js deleted file mode 100644 index b2e4db09b..000000000 --- a/tests/dummy/mirage/factories/pet.js +++ /dev/null @@ -1,11 +0,0 @@ -import Mirage from 'ember-cli-mirage'; - -const names = ['Rex', 'Toby', 'Sam', 'Andy', 'Lassie', 'Annibal', 'Spark']; - -export default Mirage.Factory.extend({ - alive: true, - - name(i) { - return names[i % names.length]; - } -}); diff --git a/tests/dummy/mirage/factories/word-smith.js b/tests/dummy/mirage/factories/word-smith.js deleted file mode 100644 index cc4192d93..000000000 --- a/tests/dummy/mirage/factories/word-smith.js +++ /dev/null @@ -1,9 +0,0 @@ -import { Factory, faker } from 'ember-cli-mirage'; - -export default Factory.extend({ - - name() { - return `${faker.name.firstName()} ${faker.name.lastName()}`; - } - -}); diff --git a/tests/dummy/mirage/fixtures/addresses.js b/tests/dummy/mirage/fixtures/addresses.js deleted file mode 100644 index dd39016b5..000000000 --- a/tests/dummy/mirage/fixtures/addresses.js +++ /dev/null @@ -1,12 +0,0 @@ -export default [ - { - id: 1, - name: '123 Hyrule Way', - contact_id: 1 - }, - { - id: 2, - name: 'Mount Doom', - contact_id: 2 - } -]; diff --git a/tests/dummy/mirage/fixtures/blog-posts.js b/tests/dummy/mirage/fixtures/blog-posts.js deleted file mode 100644 index d7659a9d4..000000000 --- a/tests/dummy/mirage/fixtures/blog-posts.js +++ /dev/null @@ -1,17 +0,0 @@ -export default [ - { - id: 1, - title: 'Lorem', - wordSmithId: 1 - }, - { - id: 2, - title: 'Ipsum', - wordSmithId: 1 - }, - { - id: 3, - title: 'Dolor', - wordSmithId: 1 - } -]; diff --git a/tests/dummy/mirage/fixtures/contacts.js b/tests/dummy/mirage/fixtures/contacts.js deleted file mode 100644 index f8dc28fc4..000000000 --- a/tests/dummy/mirage/fixtures/contacts.js +++ /dev/null @@ -1,15 +0,0 @@ -export default [ - { - id: 1, - name: 'Joe', - address_ids: [1] - }, - { - id: 2, - name: 'Bob' - }, - { - id: 3, - name: 'Susan' - } -]; diff --git a/tests/dummy/mirage/fixtures/friends.js b/tests/dummy/mirage/fixtures/friends.js deleted file mode 100644 index 57342b277..000000000 --- a/tests/dummy/mirage/fixtures/friends.js +++ /dev/null @@ -1,14 +0,0 @@ -export default [ - { - id: 1, - name: 'Joe', - age: 10, - isYoung: true - }, - { - id: 2, - name: 'Bob', - age: 80, - isYoung: false - } -]; diff --git a/tests/dummy/mirage/fixtures/word-smiths.js b/tests/dummy/mirage/fixtures/word-smiths.js deleted file mode 100644 index 8e8c4dd3c..000000000 --- a/tests/dummy/mirage/fixtures/word-smiths.js +++ /dev/null @@ -1,6 +0,0 @@ -export default [ - { - id: 1, - name: 'Link' - } -]; diff --git a/tests/dummy/mirage/models/blog-post.js b/tests/dummy/mirage/models/blog-post.js deleted file mode 100644 index 3cc484b7a..000000000 --- a/tests/dummy/mirage/models/blog-post.js +++ /dev/null @@ -1,5 +0,0 @@ -import { Model } from 'ember-cli-mirage'; - -export default Model.extend({ - -}); diff --git a/tests/dummy/mirage/models/contact.js b/tests/dummy/mirage/models/contact.js deleted file mode 100644 index 1486a7240..000000000 --- a/tests/dummy/mirage/models/contact.js +++ /dev/null @@ -1,4 +0,0 @@ -import { Model } from 'ember-cli-mirage'; - -export default Model.extend({ -}); diff --git a/tests/dummy/mirage/models/friend.js b/tests/dummy/mirage/models/friend.js deleted file mode 100644 index 1486a7240..000000000 --- a/tests/dummy/mirage/models/friend.js +++ /dev/null @@ -1,4 +0,0 @@ -import { Model } from 'ember-cli-mirage'; - -export default Model.extend({ -}); diff --git a/tests/dummy/mirage/models/word-smith.js b/tests/dummy/mirage/models/word-smith.js deleted file mode 100644 index 954ddc28f..000000000 --- a/tests/dummy/mirage/models/word-smith.js +++ /dev/null @@ -1,7 +0,0 @@ -import { Model, hasMany } from 'ember-cli-mirage'; - -export default Model.extend({ - - blogPosts: hasMany() - -}); diff --git a/tests/dummy/mirage/scenarios/default.js b/tests/dummy/mirage/scenarios/default.js index c3933552f..63244cef7 100644 --- a/tests/dummy/mirage/scenarios/default.js +++ b/tests/dummy/mirage/scenarios/default.js @@ -1,17 +1 @@ -export default function(server) { - let joe = server.create('contact', { name: 'Joe' }); - server.create('address', { name: '123 Hyrule Way', contact_id: joe.id }); - - let bob = server.create('contact', { name: 'Bob' }); - server.create('address', { name: 'Mount Doom', contact_id: bob.id }); - server.create('contact', { name: 'Susan' }); - - server.create('friend', { name: 'Joe', age: 10, isYoung: true }); - server.create('friend', { name: 'Bob', age: 80, isYoung: false }); - - server.create('pet', { name: 'Pinky', alive: true }); - server.create('pet', { name: 'Bobby', alive: true }); - server.create('pet', { name: 'Brownie', alive: true }); - - server.create('pet', { name: 'Cactus', alive: false }); -} +export default function (/*server*/) {} diff --git a/tests/dummy/mirage/serializers/application.js b/tests/dummy/mirage/serializers/application.js index e2785094a..6753a45f3 100644 --- a/tests/dummy/mirage/serializers/application.js +++ b/tests/dummy/mirage/serializers/application.js @@ -1,3 +1,3 @@ -import ActiveModelSerializer from 'ember-cli-mirage/serializers/active-model-serializer'; +import { JSONAPISerializer } from 'miragejs'; -export default ActiveModelSerializer; +export default JSONAPISerializer; diff --git a/tests/dummy/mirage/serializers/blog-post.js b/tests/dummy/mirage/serializers/blog-post.js deleted file mode 100644 index cb65bfbb8..000000000 --- a/tests/dummy/mirage/serializers/blog-post.js +++ /dev/null @@ -1,5 +0,0 @@ -import { JSONAPISerializer } from 'ember-cli-mirage'; - -export default JSONAPISerializer.extend({ -}); - diff --git a/tests/dummy/mirage/serializers/word-smith.js b/tests/dummy/mirage/serializers/word-smith.js deleted file mode 100644 index b3d65d7a1..000000000 --- a/tests/dummy/mirage/serializers/word-smith.js +++ /dev/null @@ -1,6 +0,0 @@ -import { JSONAPISerializer } from 'ember-cli-mirage'; - -export default JSONAPISerializer.extend({ - include: ['blogPosts'] -}); - diff --git a/tests/dummy/public/CNAME b/tests/dummy/public/CNAME new file mode 100644 index 000000000..3b03bb29c --- /dev/null +++ b/tests/dummy/public/CNAME @@ -0,0 +1 @@ +www.ember-cli-mirage.com diff --git a/tests/dummy/public/assets/Ember-CLI-Mirage-Logo-Horiz-Color.svg b/tests/dummy/public/assets/Ember-CLI-Mirage-Logo-Horiz-Color.svg new file mode 100644 index 000000000..3c3ac1503 --- /dev/null +++ b/tests/dummy/public/assets/Ember-CLI-Mirage-Logo-Horiz-Color.svg @@ -0,0 +1,58 @@ + + + + + + + + diff --git a/tests/dummy/public/assets/branding/Ember-CLI-Mirage-Branding-Preview.png b/tests/dummy/public/assets/branding/Ember-CLI-Mirage-Branding-Preview.png new file mode 100644 index 000000000..536635201 Binary files /dev/null and b/tests/dummy/public/assets/branding/Ember-CLI-Mirage-Branding-Preview.png differ diff --git a/tests/dummy/public/assets/branding/ai/Ember-CLI-Mirage-Logo-Horiz-Black.ai b/tests/dummy/public/assets/branding/ai/Ember-CLI-Mirage-Logo-Horiz-Black.ai new file mode 100644 index 000000000..20332243f --- /dev/null +++ b/tests/dummy/public/assets/branding/ai/Ember-CLI-Mirage-Logo-Horiz-Black.ai @@ -0,0 +1,2683 @@ +%PDF-1.5 % +1 0 obj <>/OCGs[5 0 R 35 0 R 60 0 R]>>/Pages 3 0 R/Type/Catalog>> endobj 2 0 obj <>stream + + + + + application/pdf + + + Ember-CLI-Mirage-Logo-Horiz-Black + + + 2017-04-12T20:08:31-05:00 + 2017-04-12T20:08:31-05:00 + 2017-04-12T20:05:39-05:00 + Adobe Illustrator CC 2017 (Macintosh) + + + + 256 + 80 + JPEG + /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAUAEAAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq7FXYq7FXYq7 FWD/AJua1590ryvczeUtKi1CQwT/AFudpeMtuoX+8ihoPVahYgBuo6HFWJ/842az59vPJthbatpk SeXreGRNM1ZpqTyqklFT0KNVV+IByV2A69cUl7Jih2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV 2KuxV2KuxV2KuxV2KsW/MX8wdL8kaGuoXcUl5d3Mi22m6bB/fXM7/ZRdjQeJp95IBVYZ/ij/AJyO FoNWPlXR2s6eodHE8v6Q9Olac/U9LnTtxr/k1xSzb8vvPuledtAGq2Mb200UjW+oWE20tvcIBzif YV61B7jwNQFDJsVfO35X/lgn5ieUYfNvmHzPrw1TUJ7j1VtbxI4gI5WQBVeKSnToDTwGKWWf9C1+ W/8AqaPMv/SfF/1QxQ7/AKFr8t/9TR5l/wCk+L/qhirv+ha/Lf8A1NHmX/pPi/6oYqhPyts7zy3+ bHmjyKmqXmqaDb2FveQJqUonkWSQR86GirRvVNaKK7VxS9g07TrDTbGCwsIEtbK2QR29vEoVEReg AGKERirsVdirx3/nJvzb5k8s+U9Ku9B1CXT7ma/EUssJALJ6MjcTUHuBikMJ0Tyn/wA5Paxo1hq9 p5rjFpqNtFd24kuSr+nOgkTkBCaHi2++KvR7JPzD8rfk35ln816n9b8x21tfT2l9C/qGMfV6QEMV j3SQV6YoSL/nG383L7zVY3fl/wAwXZuddsa3FvcSU5z2zGjVpSrROafIjwOKS9K/MTzrYeS/KN/r 93xZrdONpATT1rh9oohTfdutOi1PbFDzb/nGTzz5p82WfmObzBfvfPbzwG350AjEqyFlUACi/CNs Ul5v5X1v88PPHnLW9F0DzY1odPeeWl3IyRiJZ/TCqY4pTUch2xVNLrz5+dn5W+ctLsPOOox63peo srMoIkR4ywST0pWjilR461oRT2OKsp/5yk87+bPK/wDhn/D+pzad9c+vfWfRIHP0vq/CtQfs82+/ FQlMHkP/AJymmhjmTzZDwkUOtbpq0YVH+6MVZR56v/zD8ofkCZ9T1Zj5utZUW51KB+ZIlvTxAYqt f3LKv2cVYD5V0r/nJTzN5QtfNWj+a1mtroStBZPOUuCYJXiIIeH0t2jNKyYqzn8gvzj17zTfX/lX zUgGv6ajSrc8BE0iROIpUljACiRHYfZAqO226r2skAEk0A3JOKHzJ5k/OL8zPzD82T+WvyxVrbTo C3+mxcVlljQ8TPJNJtDGT9kCjfMmmKUT/gf/AJyp0O4try28wjVCzoskP1o3CIGYA+pHdIilR+1w qadMVR3/ADkN5587eW/Mnlez0zV5bQXNuDfC2ASOWQSqrNxbmQD2FcVD6ExQ8H/5yk87+bPK/wDh n/D+pzad9c+vfWfRIHP0vq/CtQfs82+/FIRP5f2XmP8ANDzHpP5k61dwQ6BpF1djQtASPk6/D6Qk llqPjDqr9912oDir2/FDxX8zfy/vfKaa/wDmP5S8w3Wj6gHXUL7TCymwuGWiurR0HJnJJHLl8R2p XZS9Y8s6s2s+XNK1d4vQbUrO3u2hP7BniWQr/seVMUPDPy/8na55v/5xss9F0XURpt9LdTyCRmdI 5FS5cmKRowzBW67A7jFLKfM35RedNT/KHSPJ1t5hH6Y06RHubyV5ViuEUyUhZ0DScIxIvCoP2RUe Cr0bylpN9o/lnS9Kv7xtQvbK2jhuL16kyOigFqnc/Tv44oTbFXkXlr/1pbzd/wBsa1/Vb4peu4od irsVdirwf/nL/wD5QjRv+2mP+oeTFIYx5W8jf85J3PljSLnSPM0VvpM1lbyafAbllMdu8SmFCPRa nFCBSuKvT/NFt5j0v/nH/V7bzRci91yPTLmO9uUbmHeRmCHkQlaKy9sUPm3y1pGveUvLOgfmtozN J9W1GW1v4eiqooqhqVPCZS8bHtt3OKXoHmTX5Pz1/MrRvLukGWPyjp0a3l85HFqMqtO7Dsw5CBOt GqehxVMf+cNpWMPm2E04I1g48auLgH/iAxUvPfy60v8AMfUfzD8yReQ9Ri03UUa4a6lmKgNB9ZA4 jlHLvzoemKo/zjZ+fPJ3n7y95j/NRP8AEdqsga29KcGP9wysQqhUAKFw/AqFc9T1xVln/OYVxDc2 /ku4hbnDMl/JG47qwtSD9xxUIi1/L/8A5yja1haHzVCsLIpjX602ykCg/uPDFWYfn/DqEH5DSw6l IJtRiTT0vJQah5lljEjVoK1ap6Yq8n/L3/nJWPyZ5AsfLUOgm8vLET8Lp7gRxs01xJMCUEbNRfUp TlvTtitMr/5xm8peYtQ8y6v+ZWsKIotVFwttQAevNcziWeVVB+FEZCor1r7YqXunnWK8m8m69FZA m8k067S2C1J9VoHCUpv9qmKHhP8Azh3c6YLTzLbAoNUaS2lZT9trcB1BHiFcmvhUeIxSX0fih8w/ 85X/APKbeVP+MJ/6iBikPp7FD5r/AOcyv+mQ/wC3j/2K4pD1zyx+U+leV/NV1rWh6lfWlhemWS58 viQNYGaWn7xYytVpTbevYHj8OKEb598kaj5phs0svMup+XTas7O2mSmL1eYApJxKseNNvip12xVh 8f8Azj5BeSxL5n83675i06J1lOmXl05gdl6cwWc/8DQ++KvWYooookiiRY4o1CxxqAqqqigAA2AA xV4t+SOhX2ufkNp+nWWr3WiTyXFwwv7LiJQFunJUFhsG70IP0VGKU4/5U15s/wDLla//AMjB/wA1 Yod/yprzZ/5crX/+Rg/5qxVPPJ35ea9oGr/Xr3zlquuQGNozY3rK0RLUo2/IgrTalPu2xVjPlr/1 pbzd/wBsa1/Vb4pZt+Yvnuw8k+WpNYuYXu53kS20+wi2kuLmWvCJTRqdCSaHYdCdsUMGN9/zkyLP 9OfU9C4cfV/w3+++scKV4epXj6tP+LKV+7FKd+VPz4/L7WtNs5b/AFKDRNVnJiudKvZAkkMytxZG Zgq0r9ljTbwNRih6IrKyhlIKkVBG4IOKvKf+cifIPmfzr5Y02w8vW63NzbXvryo8iRAR+k6VrIVB 3YYpDAtM0L/nLrS9NtNMsbmGGysYY7a1i/3FNwihQIi8mRmNFUCpNcVZvB5f/N3Wvyd8yaN5v4Xn mm+eSLT0VrSNTblIeALQCOIUcSHff8MVRP5V/lhe2X5R3HkzzdarG169yLiFHSSiSkFHVkLDkpHI eBGKE7/Kv8pNC/LuxvIbCaS8ur+RXuLyZVV+CCiRgLsFUlj8z8sVYX/zjf8Aln508jzeYB5is47a LUVtDbsk0cpLQGbkP3bNTaXviksG0X8rf+cgPKvmrV9Z8sWlvA+oSTKZJJrSTlC83qD4ZGNOgxVH Xn5Mfnd+YWtWUv5halBa6bZEgKjQsyoxBcQxW6+nzen2nP30AxVlP/ORP5VeavN9v5Yt/K1mk8Ok pdxzI8scXBZBbiID1GWu0R6YqEhisP8AnMOKJIo7yEIihUFNJNABQdY8VZV5m8o/mn5n/I6XQ9cV LzzlPOjyrztolMcd0HX4ouEO0QxVNPJP5V+r+Sll5G832qpcKlyJVRkkaGSS6mlilideS81WQEfc e4xQwr8rfy9/O78v/NsWjwtFeeSZ7n1L64WSAx8KU9RIpGWeNyAAwUEfOlcUvoTFD5288/8AOPPm zS/NL+avyxvhZzSO0psPV9CSJ3NXWFz+7aNq7o5AHTcdFKETy/8A85da1PBbajqP6NgjkSQXBmsI VBRgw5/UQ0jrtupBBxVO/wA//wArPzA84avoF9oVtDcyWFqUupfVjhUTcw3wrK1affioS36p/wA5 j/8ALbD92k/9U8VVvze/LD81fO3lbyWstvHe6/p0N5+m3MtvCBLMYeFOJSM1ER+wMVfQuKHYq7FU BLr2kRa5BoUlyq6tcwSXUFrRuTQxMqO9acdi42rX7jirzCX8lvMMH5Lx+Q9N1xYdSjnadr0CSGGV WmaQxPx5uFow8dxild5k/KLzlqf5RaP5Ot/MVNX0+RHur2VpVjuEUyUhZlBk4xiReFR+yKjwVeje UtJvtH8s6XpV/eNqF7ZW0cNxevUmR0UAtU7n6d/HFCbYq8i8tf8ArS3m7/tjWv6rfFKY/nho2tXF p5a17SbCXVpPLesW+oXOmW6mSWWFT8RjQVLOpApTxr2xQ9Fvb+xsLZ7q+uIrW1jp6k87rHGtTQVZ iAKk0xV5d5zh/wCcfYtA1y7vv0HJJfJLNcS2728l5JO4LAxFCZfULbjj3+nFKd/kSusL+U3l1dXD i6EDemJK8/q/qv8AV617ejw4+1MUM9xV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Kux V2KuxV2KvEtb/IPVL781bbX4/MOrJpTwzSz3q3lL23m5nhbW8pHJIWWQ0AU0AIruMUvUvNfluDXv L8mlT6nfaZCeDPfWE4t7gCMg/wB6VYUanxbYoYI/5CaQkfqv5281LGBUudUQLQ+/o4qv/wChftN/ 6nPzX/3E0/6o4qnnk78qrTyvq/6Sh8x69qbGNoja6lei4tyGoeXARp8Qpsa4qxny1/60t5u/7Y1r +q3xS9dxQkXnVvJn6Amj84PZrorkeqt8yrGzKeSgciKtUbcd8VeMRecP+cX7K/V9L8vjUpYnULJb afLMgYnY8Z+Naf6vyxS+go2V41dQQrAFQwKkAjupAI+RxQ88/Pvzb5g8qfl7Pq2g3X1PUFuYIln9 OOWiux5DjKrpvTwxVB/kD+ak/nryxJFqsyyeYtMfhfMFRPVjckxTBECqK7q1B1Hvir1HFXgX/OQ/ 54615X1W08ueU7xbbU4gLjVLoRxTFA4/dQcZVkUEg822rTj4nFL1fStcvrv8tLPXTKTfXGjR3xnK qCZXtRLz4AcPtGtKUxQ8a/5xz/Nn8wPOHne+0zzFqv16yh0yW5ji+r20NJVuIEDcoY42+zIwpWmK S7/nIz82fzA8n+d7HTPLuq/UbKbTIrmSL6vbTVla4nQtymjkb7MailaYqGJSfmN/zlRb2a6jLHqD WIUSmX9FW5j9MjlyJS32WnfFWf8A5Lf85HTeZ9Xh8t+aYIoNTufhsL+AFIpnAr6ciEng7AfCQaE7 UBpVWntHmPzBpfl3Q73W9Ul9KwsIzLO43JA2CqNqszEKo7k4ofK2pfn/APnH5z1x7TyZBJZwVLQW Nhbrcz+mDTlNI6SeO5AVcUqY/O78+PJGrRR+ao5ZopPi+palbJEJEBoxiljSNvpBIHhir6f8iedN K85+WLPX9NqsNyCJYGNXhmQ0kib3U9+4oe+KGFfnL+eumeQAumWUK6j5jnj9RLZmIhgRtlecrvv2 QUJHcbVVeH2n5q/85H+aXe80Q301qCQBp9gjQJ/k8/Sf/hnJxSn/AJD/ADg/Pe386aZ5Z1yye+m1 CZY/qmpWv1OZYuskiyIkZ4otWLMrbDFXsH5+ebfMHlX8vZtX0G6+p6gtzBGs/pxy/A7EMOMqyLv8 sUPAtC/NT/nJnX7R7zRLi81G1jkMLz22m2ciCRVDFCVt+oVwfpxSmX+Mf+ct/wDln1P/ALhVr/2T 4q+kPOHn7yj5PtEufMOox2Syhvq8Rq8svCnL040DO1OQqaUFd8UMGT88Nf1gc/KHkHV9XtmB9O9u uNhA/ujsJVYfTXFVU+ePz5Ar/wAq1h/7i9n/AM1Yqtb86/Mel/F5o/L3WdNgH27iz4ahEg8WdREo GKoXzV5h/L/84/KcnlnRPNUWn6hPLFIkE6tFK7RmvpNDIYjID1+Amhoe2KVfzD+Rlzqv5UaP5FTX pEm0iRZfrzxlkmoZP3bRhwQi+r8HxGnEYoeh+UtCby/5Z0vRGunvW062jtjdSCjSGNQOVKtQeAqa DviqbYq8i8tf+tLebv8AtjWv6rfFKY+dfzhMGrf4T8jWf+I/N8lVeOM1tLOmxe5lBC/Ceq8hT9og 0BUIby9+R0N5err/AOZF6fNXmF9xBLX9H24P7EUFFVh/rLx/ye+KvULWztLOBbe0gjt7dBRIYlCI o9lUADFVXFXjn/OVsrp+VqqpoJNRt1f5BZG/WoxSHzf+WnmzV/IHmfSfMxif9F3nOK4UfZntg/Cd R/loQGAPenY4q+yvOv5haL5a8jT+bPVS5tTCsmnBTtcyTCsCoR2etSey1PbFD4V11td1Jm8z6pyk Os3Vz/pTf7smi9N5go8F9dKdu3bFk+2fKcqS/kfpTJ0HlyFDXxSyCn8RixeAf84if+TJ1L/tjT/9 RVtiku/5y7/8mTpv/bGg/wCoq5xUPqTy7LFF5W0uWV1jjSxgZ3YgKAIlqST0xQ+NNen03Ufz99by nwa2m1y2Ni8A/dtKJY+bpTbiZQzAjam+KXvH/OWV7cW/5YW8MTcUvNUt4Jx/MgimmA/4OJTioW/8 4oaPY2v5cz6lHGBe6heyi4mp8RSABI0r/KtWI9ycVLIf+ciNDs9V/KfWXmjVp9PWO8tJD1R45FDF TQ/ajZl+nFDA/wDnDu8nfQPMdmzfuIbqCaNfB5Y2Vz9IiXFJeSeTtPX8z/zrT9KuXtdVvZ7y7FSC beINKIQeoBRBGPAYq+27S0tLO1itbSFLe1gUJDBEoREUbBVVaAAYoQWqa55c02aEarqFnZTkFrf6 1NFE9PssU9Qg+xpirzL/AJyflim/KKWaF1kiku7R45EIZWViSGUjYgjFQ8j/ACQ/Pfy7+X/lS70b UtPvLue4v5LxZLb0uAR4YYwp5uprWI4pes+Uv+cm/KfmbzJp+g2mlX8NzqEohillEPBSQTVuMhPb wxWnqd95f0HUL62v7/Tra7vbKv1O5nhSSSLl19N2BK9O2KEfirsVdirFfN35XeQ/Nqsdb0eCa4Yf 72xj0bkHsfWj4uaeDEjFWEnyR+bnkYmTyVrf+JtFTf8Aw/rbVnVQfswXPwjp0BKL7HFKpaf85KeS 7fnaearO+8t61AeNzp9zBJLRvFHjWrL4EquK0qS/85J+RZz6WgWeqeYLwj4Laws3Lcj0B58D9wOK KYnafl1+aXnfzpqvmm9aTyLpeswxWl1bRyiW/ktolUcFKhfT5+n8Rbif8kjFL2TyX5D8r+TNKGm6 DZrbxmhnnb4p5mH7UsnVj+A7AYoZBirsVdirxL/nLiV0/LSwVTQSavAr/IW9w361GKQxTyz+XQ87 f840WUFtHz1rTZry70sgfEzrO/OEf8ZVFP8AW4ntirx7TdS86edYvLn5fRTNPb2tw6adA1fgMxqz SHqVhUMRX7K1pir03/nJzyxpvlfy35A0HTlpa2EWoRqxADO3+il5Gp+07ksfc4qHtPkSRJPyI0xk NQNCKk+627KevuMUPCf+cRP/ACZOpf8AbGn/AOoq2xSXf85d/wDkydN/7Y0H/UVc4qGO+bfye/NP SPKEfmDUpxf6Ksccrxw3MkxiikAKs0bhaKKivGtPlirM/wDnFHS/IdzrdxeXkrP5vtAx0+1m4iIQ stHlh7tIKkNXoDsOpCpZz/zl3/5LbTf+2zB/1C3OKh4x+Xn5bfnF5g8tpqPlXUZLbSWlkRYkv5LY eopo59NSB9OKo/zb+VH56aV5b1DUdc1SWbSLaIveRNqMkwaOo2MZNG+WKs8/5w5/45vmj/jNaf8A EZcVLytZL78ofzqM00DNb6ZdyFEFB61hcBlDJ0WphfbsGFO2Kvsry15r8veZtNj1HQ7+K+tZADWN gWQn9mRPtI3swrih80/85f3FvJ5p0KKOVHlis5BKisCyVl25AdK++KQzL86//WcNG/4w6V/yZXFU g/5xt/LDyH5q8jX2o+YNJjv7yLU5beOZ3lUiJbeBwtEdR9qRjipex6P+TH5Y6NqdvqmmaFFbX9o/ qW86yTkow2qA0hH3jFDNcVdirsVdirsVdiqQ+bvIvlTzdYGy8wadFeIBSKUjjNEfGOVaOn0Gh74q 84HlX82/y3Tl5SvP8YeV4vs+X9QbjewRD9m3mGzUA6fdGcUsm8ofnb5I8xXP6NmmfRNeQ8JtH1Rf q0yydOCl6K59geXsMUM/xV2KuxVQXULBr17BbmJr6NBLJah1Mqxk0DlK8gpPemKsB/PD8ttZ/MDy zZaPpl3b2jW96t3K1zz4kJFJGAOCua/vcVTT8pPJN/5K8jWfl6/niubm2kmd5YOXpkSys4pzCnYN 4YqjdI/LjyRo/mC48w6bpENtrF16hmu0LkkzNykopYovI/ygYqw/89vyj1f8xLfRo9Mu7W0k0152 ke657rMIxRSiv/vvfFWUeVfJ99o/5a2vlSeaKS8gsJLNp05ekXdWAYVAanxeGKvPfyQ/IjzF+X/m u71nUtQs7uC4sJLNY7b1eYd5oZAx5ogpSI4pd+d/5EeYvzA812ms6bqFnaQW9hHZtHc+rzLpNNIW HBHFKSjFXr9hpccWhW2lXipcRpapa3CMOUcgEYjcEMN1bwOKHzn5v/5xP1yLW3vvJOpwQ2TP6kNt dySxTW9T9lJUWTmq9iaGnidyptn/AJ7/ACg8y+Z/yn8u+URqFsur6VJbS3l3M0rxSNDbywvxbgXa rS1BZRirJfyd8h6j5H8lxaDqFxDc3KTzTGW35cKSEED4wp/DFCbfmD5buvM3kvV9BtJUhudQgMMU steCkkGrcQTTbwxVhv5E/lNrX5d2msQ6peW122oyQPEbb1KKIg4PLmqdeeKp9+Zf5TeV/wAwLBIt URrfULcEWepwUE0dd+Jrs6V/ZP0UxV4Hff8AOJX5gWlyW0jWdPniBokrvPbS0PcqscoH/B4ptNfK /wDziBf/AFlJPNOtwrbKavbaaHdnHh60yx8P+RbYrb1380vy1uPNH5dxeUtFmisxbtbC3a5LlFit hxCkqHYniMUPDv8AoUHzv/1edM++4/6pYpt3/QoPnf8A6vOmffcf9UsVt9YYodirsVdirsVdirsV dirHfN35e+TfN1v6PmDS4bxlFI7ihSdP9SZOLge1aYqwRfyk/MPyzQeQvO06WSbR6PrSC6gVf5Ul 4sUX2WP6cVVk1z/nJG0PpXHlvRNSoKevbXTQAnxIlkr/AMLiqlJZf85HeYl9C6u9H8o2b/DLNaB7 q8Cnrx5GSOvydT74qyn8vvys0DyYbi7gln1HXL8f7kdZvHMk81TyI8FXlvTr4k4qzPFXYq7FXYq7 FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FX//Z + + + + uuid:c3e88660-02ef-0945-ae6f-c6951e7bc3be + xmp.did:3d58b951-e27c-4e2b-bf80-af2ab47a27db + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + xmp.iid:61f0ef3b-ecb7-4f78-a77f-08f867147dc3 + xmp.did:61f0ef3b-ecb7-4f78-a77f-08f867147dc3 + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + + + + saved + xmp.iid:48fef565-7731-4c49-bee9-dfbb0bfe5fa3 + 2017-02-28T19:39:58-06:00 + Adobe Illustrator CC 2015 (Macintosh) + / + + + saved + xmp.iid:3d58b951-e27c-4e2b-bf80-af2ab47a27db + 2017-04-12T20:05:38-05:00 + Adobe Illustrator CC 2017 (Macintosh) + / + + + + Document + Print + False + False + 1 + + 550.000000 + 175.000000 + Points + + + + Cyan + Magenta + Yellow + Black + + + + + + Default Swatch Group + 0 + + + + White + RGB + PROCESS + 255 + 255 + 255 + + + Black + RGB + PROCESS + 35 + 31 + 32 + + + + + + Mirage RGB + 1 + + + + R=39 G=50 B=73 + RGB + PROCESS + 39 + 50 + 73 + + + R=110 G=116 B=125 + RGB + PROCESS + 110 + 116 + 125 + + + R=54 G=181 B=192 + RGB + PROCESS + 54 + 181 + 192 + + + R=112 G=201 B=203 + RGB + PROCESS + 112 + 201 + 203 + + + R=255 G=147 B=67 + RGB + PROCESS + 255 + 147 + 67 + + + R=254 G=201 B=78 + RGB + PROCESS + 254 + 201 + 78 + + + R=214 G=237 B=162 + RGB + PROCESS + 214 + 237 + 162 + + + + + + Grays + 1 + + + + C=0 M=0 Y=0 K=100 + RGB + PROCESS + 35 + 31 + 32 + + + C=0 M=0 Y=0 K=90 + RGB + PROCESS + 64 + 64 + 65 + + + C=0 M=0 Y=0 K=80 + RGB + PROCESS + 88 + 89 + 91 + + + C=0 M=0 Y=0 K=70 + RGB + PROCESS + 109 + 110 + 112 + + + C=0 M=0 Y=0 K=60 + RGB + PROCESS + 128 + 129 + 132 + + + C=0 M=0 Y=0 K=50 + RGB + PROCESS + 146 + 148 + 151 + + + C=0 M=0 Y=0 K=40 + RGB + PROCESS + 166 + 168 + 171 + + + C=0 M=0 Y=0 K=30 + RGB + PROCESS + 187 + 189 + 191 + + + C=0 M=0 Y=0 K=20 + RGB + PROCESS + 208 + 210 + 211 + + + C=0 M=0 Y=0 K=10 + RGB + PROCESS + 230 + 231 + 232 + + + C=0 M=0 Y=0 K=5 + RGB + PROCESS + 241 + 241 + 242 + + + + + + Brights + 1 + + + + C=0 M=100 Y=100 K=0 + RGB + PROCESS + 236 + 28 + 36 + + + C=0 M=75 Y=100 K=0 + RGB + PROCESS + 241 + 101 + 34 + + + C=0 M=10 Y=95 K=0 + RGB + PROCESS + 255 + 221 + 21 + + + C=85 M=10 Y=100 K=0 + RGB + PROCESS + 0 + 161 + 75 + + + C=100 M=90 Y=0 K=0 + RGB + PROCESS + 34 + 64 + 153 + + + C=60 M=90 Y=0 K=0 + RGB + PROCESS + 127 + 63 + 151 + + + + + + + Adobe PDF library 15.00 + 21.0.2 + + + + + + + + + + + + + + + + + + + + + + + + + endstream endobj 3 0 obj <> endobj 7 0 obj <>/Resources<>/ExtGState<>/Properties<>>>/Thumb 66 0 R/TrimBox[0.0 0.0 550.0 175.0]/Type/Page>> endobj 62 0 obj <>stream +HlWId )(jܺ xexP0܋#HMYh:8׏ _#\RsǏ +ܢc~?? +'W᮹+;خ?>%-__19W2d8~iOs~%1V wLx7:篏Gw;wʰS\.9MU\Z]pѤޡ)p&d{PڥdֲCw]4$Kq +vxR"a%4bBc! N^7"ʕ;^-5]PB6M@C.I#N~Ue}C+\E8ۼ8-)#F@Z% c ADyo7OH-!"wmI/ڏ@i(J j;ALRo +wKqE5~ ܪB+W:L]% 9%҉ !SFIwHGE%/gz\L'o:. ]U-^zQ暠 +) + A7\-bX/ߡ; -h61[XڎT&yshT}3Jzk8! +T#F{Z]H|"hK"OW<ڝ1~ͩX$#P_ӝj +T+< 5C +O3NCBvw+k",M7OP8h߈}}2JҤMYx!Ir.nDq_$g@Z QJ_]Эpk*_j 24^87 Bny%h޲ڀ"*.!$M)v:^vKhض==Z@m12 Lo k6v_ޤiNϫCE^Q^eWm$AaC,jiLMgXTsQiE+a%O]́Pcm'] +l;(/8,~" mj,eBm҇Z~ɴh<  Y{dgZ.>`l1e7?|@ +n# c¶БRKSLJwXl]%i>eR[>?ObL,aȸuH=ؼfDl/`BvplژArwo!3Nh;Ne:1j9>3*8>@e ύFއ?TXn l.3_=Ht-nDB:x )MV  ڠw/Do3{%_1>iO- +h~*xҟ?1ed":y2 b0ve\1<4`7qK򝪖vtܪ }QĊ>0ޑ nmv}!ͷUbk,woe$l +iVMC FkZPw\Q9lZ;,x^kK}sm;`"$IQW٭e\ [8).%ӈsPʡkYk1pEVxZG͐~ˈ!^A>cBP`R8 e]|@sF@Ads&4E[ܨIT7i0Dl nbRpO_:⮆zh[*1]{m#2h p (=:WR&M/{x-Pۺ`r4P~ٗ ihQSI8x !5[|Ybq~۸T  Bz,r |Ц87줶}\De_|B4fHc {"KzH(TEtיҍWN/FMpF RVo#d}U )E#6n*T',ʕޥ5ai[۔>*!@[7řG + |T3yԷvW;zkj(m(@~B`mD&V~1!7g Sm\.d'-mmg(('~ V v^)nZLoO${6(&4gM `8y)͌wö z3=MSM+N {U ;VQ4$w3~vڎrrDoShl㌴I S4D.%ĶAD68&D얒pA4NtG@`~> \b*o<XS!p5hsrsėZpo3fJ,19eڍͲ;)WlG8ĹA"9:; ;}S9ISe0([ Dx)f\dp{DFؠAǐx%2jyNƐ"D u"nHp!q PIw|i +6 ;vO9'8]4hvo'[E-"PLWlicLk\fTIcHN>k H#b.s@h]~&c"<Jy)f8GOJfA|ގV_5Nֶ3/]@?[ +E\Pw=#^1*3Blcp/E-A 9]hګ :'|#l|pι t Lؾ`D Wf#㲠} 4s~)g]qeG0!E?Kct +`9g<"x")ppbuӉ79F A @@~PrcDPeҏA#f\C`nxȠo*,"fg>0:7.!O]`=h^=sC1H~ *<@K^TO Hens[8dP N1@{>stream +8;X^Go<`K@!)p.T(k=$9iqt"o^6F[%GYUO`)H0es6gqZBao\ +o;FP/LtaS,O0,8 endstream endobj 67 0 obj [/Indexed/DeviceRGB 255 68 0 R] endobj 68 0 obj <>stream +8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0 +b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup` +E1r!/,*0[*9.aFIR2&b-C#soRZ7Dl%MLY\.?d>Mn +6%Q2oYfNRF$$+ON<+]RUJmC0InDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j$XKrcYp0n+Xl_nU*O( +l[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\~> endstream endobj 60 0 obj <> endobj 69 0 obj [/View/Design] endobj 70 0 obj <>>> endobj 65 0 obj <> endobj 64 0 obj [/ICCBased 71 0 R] endobj 71 0 obj <>stream +HyTSwoɞc [5laQIBHADED2mtFOE.c}08׎8GNg9w߽'0 ֠Jb  + 2y.-;!KZ ^i"L0- @8(r;q7Ly&Qq4j|9 +V)gB0iW8#8wթ8_٥ʨQQj@&A)/g>'Kt;\ ӥ$պFZUn(4T%)뫔0C&Zi8bxEB;Pӓ̹A om?W= +x-[0}y)7ta>jT7@tܛ`q2ʀ&6ZLĄ?_yxg)˔zçLU*uSkSeO4?׸c. R ߁-25 S>ӣVd`rn~Y&+`;A4 A9=-tl`;~p Gp| [`L`< "A YA+Cb(R,*T2B- +ꇆnQt}MA0alSx k&^>0|>_',G!"F$H:R!zFQd?r 9\A&G rQ hE]a4zBgE#H *B=0HIpp0MxJ$D1D, VĭKĻYdE"EI2EBGt4MzNr!YK ?%_&#(0J:EAiQ(()ӔWT6U@P+!~mD eԴ!hӦh/']B/ҏӿ?a0nhF!X8܌kc&5S6lIa2cKMA!E#ƒdV(kel }}Cq9 +N')].uJr + wG xR^[oƜchg`>b$*~ :Eb~,m,-ݖ,Y¬*6X[ݱF=3뭷Y~dó ti zf6~`{v.Ng#{}}jc1X6fm;'_9 r:8q:˜O:ϸ8uJqnv=MmR 4 +n3ܣkGݯz=[==<=GTB(/S,]6*-W:#7*e^YDY}UjAyT`#D="b{ų+ʯ:!kJ4Gmt}uC%K7YVfFY .=b?SƕƩȺy چ k5%4m7lqlioZlG+Zz͹mzy]?uuw|"űNwW&e֥ﺱ*|j5kyݭǯg^ykEklD_p߶7Dmo꿻1ml{Mś nLl<9O[$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! +zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km endstream endobj 63 0 obj <> endobj 72 0 obj <> endobj 73 0 obj <>stream +%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 17.0 %%AI8_CreatorVersion: 21.0.2 %%For: (Lindsey Wilson) () %%Title: (Ember-CLI-Mirage-Logo-Horiz-Black.ai) %%CreationDate: 4/12/17 8:08 PM %%Canvassize: 16383 %%BoundingBox: 40 -2056 544 -1903 %%HiResBoundingBox: 40.9218139648438 -2055.67138678544 543.650695800781 -1903.16748046875 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 13.0 %AI12_BuildNumber: 242 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%RGBProcessColor: 0 0 0 ([Registration]) %AI3_Cropmarks: 27.119094045298 -2069.11139443028 577.119094045298 -1894.11139443028 %AI3_TemplateBox: 306.5 -396.5 306.5 -396.5 %AI3_TileBox: -75.880905954702 -2269.61139443028 658.119094045298 -1693.61139443028 %AI3_DocumentPreview: None %AI5_ArtSize: 14400 14400 %AI5_RulerUnits: 2 %AI9_ColorModel: 1 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 1 %AI17_Begin_Content_if_version_gt:17 1 %AI9_OpenToView: -2601.92589258926 -485.070807080707 0.3333 2549 1289 18 1 0 5 43 0 0 0 0 1 0 1 1 0 1 %AI17_Alternate_Content %AI9_OpenToView: -2601.92589258926 -485.070807080707 0.3333 2549 1289 18 1 0 5 43 0 0 0 0 1 0 1 1 0 1 %AI17_End_Versioned_Content %AI5_OpenViewLayers: 7 %%PageOrigin:0 -792 %AI7_GridSettings: 72 8 72 8 1 0 0.800000011920929 0.800000011920929 0.800000011920929 0.899999976158142 0.899999976158142 0.899999976158142 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream endobj 74 0 obj <>stream +%%BoundingBox: 40 -2056 544 -1903 %%HiResBoundingBox: 40.9218139648438 -2055.67138678544 543.650695800781 -1903.16748046875 %AI7_Thumbnail: 128 40 8 %%BeginData: 6784 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C45FD23FFA877FD7DFFA852F87DA8FD7BFF52F827F8A8FD7CFF7DF8CA %FD18FFA8FD51FFA8275227522752275227522752275227527DFFFFA8FD12 %FFFD07A8FFA8A8FD08FFA8FFFFFD06A8FD04FFFD07A8FFFFFD05A8FD0BFF %A8A87DA8FFFFCAA8A8FD06FFA8A8FD04FF7D7752A8FD08FF2052527D527D %527D527D527D527D527D52207DFD13FF52FD06F87DFF7DF8A8FD06FFF827 %FFFF27FD05F827FFFFFFF827FD05F8FFA827F8F8F82027A8FD07FFA827FD %04F827A8A8F827FD06FFF827FFFFFF27275252F852FD06FFA827A8FD0FFF %277DFD13FF7DF852527D5276A8FF52F827FD05FF52F827FFFF52F8527D7D %27F827FFFF27F852527D527DFFFFF8277D7D2721F8A8FD05FFA8F8F8277D %7D5227FFA82727FD06FF27F8FFFF5227A8FFFFA8F87DFD06FFF8A8FD0EFF %A8277DFD13FF52F87DFD06FF52F8F87DFFFFFFA820F84BFFFF27F87DFFFF %A8F827FFFFF827A8FD05FFA827F8FFFFFF27F852FD05FF20F852FD06FFA8 %F827A8FD05FF2127FFA827A8FD04FFA8F87DA8FD04FF27A8FF277DFFA827 %A8FD08FF277DFD13FF7DF87DFD04A8FFFF5227F827A8FFFF52F82727FFFF %52F87DA8FF772752FFFF27F8FD04A8FFFFFFF827FFFFFF7DF87DFD04FF7D %2727FD07FFA82727FD06FF27F8A82727FD05FFA87D2727A8FFFFFF27FF7D %F8F8FF52F827FD08FF277DFD13FF52FD05F827FFFF52F852F852FFA8F852 %2027FFFF2727FD04F827FFFFFF2727FD04F87DFFA827F8FFFFA827F876FD %04FF7DF852FD07FFA8F827FD06FF27272752FD09FF277DFFFFFF27A8FF7D %A8FFFF7DFD09FF277DFD13FF7DF852527D527DFFFF52217D52F8A82727A8 %27F8FFFF52F852527D272752FFFF27F852527D52A8FFFF27272752272727 %FD05FF7DF827FD07FFA82727FD06FF27F8F8FD0AFF4B52FFFFFF27A8FD0F %FF277DFD13FF52F87DFD06FF52F8A87DF8F8F852FFF827A8FF27F87DFFFF %FF27F8A8FFF827A8FD05FFA827F827F8F820A8FD05FFA8F827A8FD06FFA8 %F827FD06FFF8275227A8FFFFFF7D527D775227FD04FF27A8FFFD0B7DA8FF %FF27A8FD13FF7DF87DFD06FF5227A8FF52F827FFFF2727FFFF52F8A8FFFF %A827F8A8FF2727A8FD06FF2727FFFF272752FD06FF52F827A8FFFFA87DFF %A82727FD06FF2720A85252FFFFFF5227272752A8FD04FF27A8A852275227 %5227522752272752FFFF277DFD05FF7D52277DFD0AFF52F8F827F827F87D %FF52F8A8FFA827A8FFFFF827A8FF27F8202727F8F852FFFFF827F827F827 %F8FFA827F8FFFFA8F8F827A8FD04FFA827F8F82027F8F8A8A8F827F827F8 %2752FFF827FD0FFFA827A8FD0FFF277DFD04FF27277D7DF852FD09FF7D27 %52274B27277DFF5227A8FD06FF5227FFFF7D274B274B277DA8FFFF522752 %274B2752A8FF2752FFFFFFA82727A8FD06FF7D2727274B52FFA84C275227 %4B277DFF5227FD10FFF8A8FD0EFFA8277DFFFFFF7D27A8FFFFFFF8272777 %A8FD07FFA8FFFFFFA8FFFFFFA8FD07FFA8FFFFFFA8FFFFFFA8FD07FFA8FF %FFFFA8FFFFFFA8FD05FFA8FD09FFA8FD07FFA8FFFFFFA8FD13FF27A8FF27 %7DFFA827A8FD08FF277DFFFFFF527DFD04FFA8527D277DFD5FFF27FF7DF8 %F8FF52F827FD08FF277DFFFFFF277DFD07FFA8F8FD5FFFA8FFFF7DA8FFFF %7DFD09FF277DFFFFFF7D27FD07FFA827A8FD5BFFA852FD12FF277DFFFFFF %A87DA8FFA87D7D7D522752FD5BFFA8272752FFFFFFFD0A524BA1FFFF27A8 %FD08FF525227527DFD2FFFA8FFA8FD0BFFA8FFA8FD1CFF7D27F87DA8FFA8 %7D527D527D527D527D52527DFFFF277DFD13FFA82727FD09FF52277DFFFF %A820F87DFFFF7DF8272727F82752A8FD06FFA852F827F82727A8FD07FFA8 %4B27F827F82752A8FFFF7D272727F8272727F827FD0DFFA87DFD12FF277D %FD0AFFA8A87DFD06FFA8F8217DFD07FFA827F87DFFFFA827F87DFFFF7DF8 %F827F8F8F827F87DFD04FFA827F821F827F827F87DFD05FF7DF827F8F8F8 %27F8F852FFFFA8F827F820F827F821F8FD14FFA8FFFFA8A8FD07FFA8277D %FD07FFA852F8272727A8FD05FF7D27F827A8FD06FF52F8F852FFFFA8F8F8 %52FFFF7DF82752A87D52F827F8A8FFFFFF52F82727A17D7DF8F8F8A8FFFF %FF7DF8F8F8527D7D7652F8A8FFFF7D27F852FD067DFD12FFA8F852FF7DF8 %7DFD08FF277DFD06FF522752A8FD09FFA8F827F87DFD05FFA8F827F87DFF %FFA827F87DFFFF7D20F8FD04FF7DF82152FFFFA8F82727FD04FF7DF82752 %FFFFA8F82720A8FD09FFA8F8277DFD0EFFFD05A8FD05FF7DF827FF7DF852 %FD08FF277DFD04FF7DF852A8FD0BFF7DF8F827F8A8FD04FF2027F8F852FF %FFA8F8F87DFFFF7DF8277DFFFFFFA827F852FFFF7DF8F8A8FD05FF27F852 %FFFF52F8F87DFD0AFFA127F87DFD09FFA87D4BFD0827527DA8FFFFA8FFFF %FFA8FD09FF277DFFFFFF52F87DFD0DFFA8F827F82752FFFFFF52F82027F8 %7DFFFFA827F87DFFFF7D21F8A8FFFFFFA8F82752FFFF7DF827A8FD05FF52 %2027FFFF52F827FD0BFFA8F827277D527D527DA8FFFF272727527DA8A8FF %A8FFA87D5252F82752FD0EFF277DFF7D2727FD0FFF7DF8F852F8F87DFFA8 %27F87D27F852FFFFA8F8F852FFFF7DF827A1FFFFFF27F8F87DFFFF52F8F8 %A8FD05FF52F827FFFFF8F827FD07FF7D7DA8FF7D27FD07F8A8FFA87DA8FD %0DFF7D5227527DFD0BFF277D522752FD10FFA8F827A852F852FF52F852FF %27F87DFFFFA827F87DFFFF7D27275252522727F852FFFFFF7DF827527D52 %7D527D272727FFFF27F852FD06FFA827F8A8FFA82027275227522752A8FD %13FFCA5227277DFD08FFA827F827A8FD11FF76F8F8FFA827F852F8217DFF %F8F852FFFFA8F8F852FFFF7DF827F8F8F827F852A8FFFFFF52FD08F827F8 %27FFFF27F8F8A8FD05FFA8F8207DFF7D27F87DFD1CFF7D27277DFFA8FFA8 %7D522727A8FD13FF7DF827A8FF5227F82727FFFF27F87DFFFFA827F87DFF %FF7DF8F8525252F82752FD04FF7DF82727FD0552272727FFFFA8F82727FD %05FFA827F8A8FFA8F8207DFD1EFF5227F827212727527DFD15FF52F8F8A8 %FFFFF8F8F8A8FFFFF8F827FFFFA8F8F852FFFF7DF827A8FFA827F82052FF %FFFF52F8F8A8FD05FF52F84BFFFFA84BF8F827A8A8FFA87DF8F87DFF7D27 %F87DFFFFA8FFA8FD1BFF7DF827A1FD18FF7DF827A8FFFF7D277DFFFFFF27 %F852FFFFA827F87DFFFF7DF8F8A8FFFFA827F82727A8FF7DF827A8FD05FF %522727FFFFFFA827F827F82727272027F8A8FFA8F8FD0827FD1CFF522727 %A8FD16FF52F8F8A8FD08FF27F827FFFFA8F8F852FFFF7DF8F87DFFFFFF7D %27F8F827FF52F8F8A8FD05FF52F827FD04FFA852FD05F827277DA8FF7DF8 %F827F8F8F820F8F8FD1DFFA852F852A8FD14FFA87DA8A8FD08FFA87DA8FF %FFA8A27DFFFFFFA87D7DFD05FFA87D52A8FFFF7DA2A8FD05FFA87D7DFD07 %FF7D7D527D7DFD05FF7DA87DA87DA87DA87DFD1FFFA827F827A8FD0DFFA8 %A8FD6EFFA85227277DFD09FFA852F8A8FD71FF5227F827527D7DA87D7D27 %2727A8FD74FFA87D5227272752527DA8FD7CFFA8FD52FFFF %%EndData endstream endobj 75 0 obj <>stream +G-D2FΪ&'uBVЖ +t[$a"LR7`yz]X^W)0eS VDn ,q{JR$ +D2'tX̃rODx" 1$H)ˢ[HיNi >mT l:1@$erTY?u40$zjs(M !!\0k'dE !=&Hؖ$x S&+vc0Vha![)+/֘uؖJV0H3} bL"(4)YTIb6TeP ISóg|,,"r$ RL =<`2exG Sf͟}y^+V~h .<"Mr !)d^ q"v>Iy;yM,f(D/ h!c 15)/LUea̅+` OWy avhKt + u Xiv# +H zIڴlЎjX)ߥ& ^u!@r1@JZ0$*#R'1?a4FuN@lU?p  JP-8M0qG^3f 'M ˌ=O1.scdH.Ŭ1z6Xrf;<oB +WhGE9H_"<<}Q`akZS΅al.V½4;A%BTeb@af4e! Fi($球bRA'lmn~llaÔ 3Z/vB^3aeF"iǶbuL<`1$F~bb +-ԩpltRb}H,N'ƀuޔ)Ce9$D8R^4 lFr@5]X1NIbV BA(f -tdZDRIH'd}72dz% +jZlV./!joYw0%yv8R3rVoG*YJګK]@8`!Ț'fPiʻyvF*).GCR# s\-#h9Bv +q# D( g(T1^8Gly@op%BdJ +|Tf2.Yj沐lx" f Q-1]F + @AsBH)QT#UsMHU#yi)i$AEx!vIB ZS$, I^BD'd@gژ-  +PWO;}$^rI,N$c bл*T9=R]#L^%W‹SO$Bio%a1}Q¡,<i5I+*@c$h8, a4+ku*V:X uX%+iŮb-!GYKޫ"Y`ESVWV|IhJ`g'ƑqtCIBeBeBN0x0"spL'2˸hG]Ҥ,n "L20F9lQ#?+`%s_8cސ#[T軚)F9u9efBnOD$ tp. 6aeC@Rf#VH4`ى .<Ll=!',Ţa$ɖg/(`2q/a*C6x.\>Z+?v] KmAhPfcܣ\>F=<:u9^NW]k4h5l9w[8 !͖$2:ᘃm&LjdʣGPJ$ ,SbWz/OۑnUJ.5 **oG8$0ə#f3aqvgQā4O&\*Lx;ҵ|ZP&h:KėU!%:TH+S$|6&3/AOG&@-)!'hxBC G;qإQ+ /7Tk JIb-u Hۥkf4K pT&҄`2 +&ƭ9H/NDgr)Y\ϊxr^ʂpr~5P\mJ07-V +S)c@Cjia98m\Q"F!ʬdfuuURI$SX+C3S6.m͡8 +_L(Tp\wpA5b0DW%JJ89zWYS@֕adlmס ftpg&o,Bs)(J<$0 %-)$2#,Փ74W4$j:.^]8 Yd FNR +j `;Dx6nuKoގt)ЩTJao9ٚ1 +?SQr9Є[REVļہ1"5;'V%F Tօ+Z._MV)B- +'<.bTZ#]J*ERBeݬbOel_-1F4'9Yg_;ҥR_.;jTkK]vF* 4*TRSե\5ݵ\vkK>\D#R* u+1JiC0 O K!X()Z̄ܶ9aR˙:³#+#%s.Af/ ]TJ\4堸m~l PTbŒeG@YpqL]`R;vil>޹|,CJK\ +F *NJUPBR5 ëc-p f6'A5jy Pbb +nB/̇43a" Q{Np.vh\Hoz$Iz 'B ߛT5&_wq7ub$DGa"SRxґTW,ۈ R52Xzܾ$F0)1~#„>衂"ž< H&&|"$?+͏zE7 bLW BP„ϱ2 %(fLzH3` %;نEj{G"=֖,$ LwU\Mt +֕^LLd<7.qSBܢ%ȸfsGD usTGoWer!'Р aG4C}'f?6ٛ”L"dɏs2N˓JM8%WL;&㏽Gc_X¤2y]Q 1N&,$Sp)2VYR.7*iѬNd%L tčE~plKgY[y!=x~=0~?&C(ãsF[''Û߽::>N<4h\::/^s#m{G׍v|w;AN:@>5n4g#ӆ0$ TQ)$h9e| "; jIP)}HOײɾҌg{W*7R ZbgX>4nK/BRE 酽 N1މS-SCÎ| v QAŤkZXIw$G{ds ʭ猪G+_qDֿF8Ę"Z i{g|Wa =~4B{_dsY1AoƆn;H*jK#5ZHYNSj2VLyCe.i+9Y,[ԥ?[yw˗`G6.mFtA>3)nxNj/ݐ/\~x~hՑ5tyI +8ssف<΍~*`"~,=4)$=ʣyN^Wf9d((3+@yho@qCv k{ϟ/b,)͞FƷ S +YØv7ɩ v`c[Є IM^H Ǒl礀F/GC4\5t^z4Bt;u؋)-};uէp_Ǜ;XRLiq?ޮ7b684׎*: NѼO EF厼 V%F6XPCD8[~DK~#&o\*}Q@ʞaHL$A:?`SUCTlJ%qXTMM+v8ةHt'PclFu}"ٔ5aM*9Pk6 5]ta}cX£(y,Q2h]ygp'e(g.G"b oF~L +&IaгC\-.ps$a4Ą EC?놮98X)';`Xٖ [Ftiml؈ +3MFE,:qQJ:s)Dajbt>m  +8rQfSsj΃YJ~>q"[ 0(>ډ=Ɉ[AJ>ʙ t=?)b"VFIc92t*`tĽ<ّ9 O8`9{@JZW@FEN.%#0(V*isMCpMNs ٸϙ&ÁN&DBz'T(ZIWwf*'v)5NϯDw Ft;P"Prv=|Z JQ9XgepY(5j8F6;ebV +|o +mA(aQsg`ɤ Mvp(R%ޱR'GsC &lG#l˭ h.[kiBcZ u_ѶaC׀ +3]iߢkaB7Δ0¨YZhDl+]_L\Ӿ"̑"=QsDݹ_EBxYdܱep6{ wHW8\{l2E|l]~)*QH $Cepj,b8MD5Ň"BB^$ZZ[Lv9W|x]EH0Rl*)&4kRwyf%8t,l5Ss;387p4 H_:[N'cZI` X%,|1K?T=&$p,UH*Lk-kHJΩ6&;6baUƉ3+Y9H8Gb P_$Ɉ"b"[1ZБ" \<a%f?m\I6E:U2O,J7-YDxI| 0pnuF!"zs& !|w(a3Q)XQA\J:S̚$2.(ިye)  ?C-ݚYe,nPbG|ڃ4+?? ,q'p wLXl +55aNb%59λCϓ0φ2L`\ +&Id?ҫE2؄cJL5E6N/tb -bY``ĝ|꬙Т?$F" --yNɎ$d hH'bqYfjw_(>ȃT n^%4deSG!WJ,V;&F+.F'bLs}i%"5W +5K^68\bs+q}n&̰P!FsTEmFIKvL S8TfOt;8Fp2ؾ$B>)uB@Zz‰-n/`D;_T`Snu-qiU8?/~ڝj*(VpgfGi>-jbo 1El6D|)*.~n*š:Ha0<8,qwGr°ǧ 5M^CҶQ!9С%,у GҶ)/A Hh^"eU^9|*age3m%:/BKxQuq"S w9B/i%G#␽HwY4}')+<q>;vPQ!e_C)1ZJJ,5&mCsJ6[8wp䔥5܈ 6)>\ߒ#0tPC!F9ˆ_z ɦaJTfi7/Iv60a.&Yw3י78I8~oyTnmj'iqxuuoNv^B5mvf")";\?GJ_;h1Mj)Ԙ"t!#rHԘr?)2I\>h}r̫OFF^]r}U\Wnv)$0@dÔ[FnY2#r$G2U$6^S9<@lph8$)s9! '2di(de#'$!1.c$zw и*qT*~ FcމLGЂC!Fl7H*BAwкɍJůS(C?d + +"O0 Ќ MffY80HnLq[6 f wSס:F9{T~Nh{\d$*mXw7fcK7A*ʆh8=  H%;=(LK(Yw rS ~ _jybNʔƺt]WH= (;+e[c=а;~EAẠ'ߚ#_ rL3iSGڽAtHz\orru蛭LHvHqȀ%Lpd sf1E$1 r$̘ (|x#.&.Bi +$Iʀf~^SNVF'1"7,RQܪ2&P$&)uM7e#4sc7@>W%ܧ%gV3BŤκÇ9"JTbỸ8|nu@qmP䠴Vϼi6\X"%1( MQ:Dih:<e8IKLnsZZPQ~F:2Zh|+(Qߋip"Nrg2]? Em&(}tafid OÍ3 #u*VQ=E8kYك<-`kef:;$. + v* 86E a+΁21dZfWN +$Pp{3di&/3PfP 2) ؛?l"ō,Yd@;kZ0N!{`Tqɑʀ PAiP; ;Bg@REyK~X1bL1H& +0Q~ܳx'v@ȓ*G &0JBiJ:Y,zcB( Trc^qEA@hl;&ʴRԒpxir>!Iyid/INbqN^')+,~NKy`PT"y[p +Ee13GÄB8ƕȞʫp/ˆ:ʀK^@YlR#90zXd`@9 כWO"Y8A&ƖHX78'z=U:42eg zlvЄӉ /tvAk(7)`6y\7Ub|µt,MEC3P8*(- MēDvr@O9S'>6",p9rʃrsfs֙ˤ%Jq}r穉-xBX ȱbL450ZBnlU6 dCXd/hMK:oX,-!ʖLk3 j,}Mz[GM(X`.hi]iP4|"Ȃ/H- On 52o*^yJB~^"6*&͒yPWT ==Nr'tE>YF;3EK.`2˃dE'1kZ9l]Ҵt]& ^,{,-|nݍ[Di,Eur)a L' ȁqi\!n}Ч:ҍ oܢq df9!aPC˄2NnwÏ8Zcyg3zYA/jc7w.h]=|r1$3`꓋֥QM%ulw&u1S\0'E>0 netM`{1iw# +57)x崣|J0V.]d\J2EurVUx2k4[nӮp׋~|ܹ_f~ӫo? Y`,sC<*^7ơIĸYjTqqM|Vrwuvϙ}LJ(2dC/{XUYPT>66C.d+|@_,͠,Bڙ~I&^'U NƊ - 2.KYCF˧2P>eH +@Me;Q7Em'e:λ<]o-.~j}ش鸝:,Poȑ{HB$P1 :9+딯 _ePO%z:w)=w [ޒ Nȡ q<[^IF3c4I>upB:VJF"O>k(*v(Oh>qy1P㌎3G X~&*Yڊ=y8s=]i+ɧ2-'Fcys@!ŪsKn1 +KtZc Y$.%]aWNdsVP>oR\v[PENu_NJݜNZ(% u]+F%3!fK`Nf΢k;IfL'oE6tU +B~>B?a4FG&D>L,G֓BeMʪ ѹВUk'Vd,-h.侚cE}cEyT WoqpE X,#dHcPNre W99aP\6r8tse~EV !]!{vBg(':LH@^pqPQ(ۀrHtʼd݁y'%+ւ@ؔ! i 8#OƜvX@ + yEp5ҝS4XMZI@LS߃Q Z I xR/6O d@=,d~r/ZW MPp,QANeA.4ts#t:b9P*9anEm-6~Uact]ȣG4,u}TiTrx#L:cB.#n%h:: )V_p,U+rU7o%Kޱ`K*ygRNj r0)~tCigЩxFנt@٤A&o]5d>Ҕ[ذcO1(cMD3Ac4F,IZ$"‹Ů( {*NwՑKsxOX?-?y9PX EGx4Z =L]yY) ^8XHvGsesf?Opuȍͯ %9'y9,teoPɕcixVIi.xQ֝KR'6`B33wXMـv6ή4;=ѶZףmGJ]]z-h[ѶK]OXףmm+u=VzRףmGr]S'#u=4h[ѶK]mu="p]m+u=v)\-pa-h[ѶRףmm+u=VzRףmGJ]]z +I]mh[ѶRףMmu=ڔzRףMGJ]PZhSGJ]6md7!$-SѦZףMGJ]e%뤮' vbTzhSѦK]6m*u=^zZ}\Mm*u=TzRףMGv)\'Y`m*u=\}]6m*u=tѶ\ףmG.u=VzhۥGJ]mh[ѶRףzؤҦKG;>9r1`Pצ0`.*C*^lF^@@JDRۋ:zV3J&'gf.vY$8srё `:MuuhFa( +9 Daaj! 2fKSiaRѠ YapH{#dQ$; DY=\F#; ?+0B~F90. #^y,8 *,pviʠ Z90a^a@; haA(raa X8 B[!Җ a $A'Yր R)B۵#spDAj# ha@0; h'auD9 B#LHuި@V4e#@'ha .,04@U-J0߀PoQ; q4l2)$ER8J W0MGuWEfQ)d&>$w!A5V#EM@iԫZB?0̶}GoLΣU]0l5:{2ˊؙ /-b@'ieyw}`rE8(Ra-YX>V-a R#TVEnpd}`HB.a}`&_@=H5]}|{wt{`OT{L~I2}aǢ{ȵXo/бű +X.y" DC01d1Ѻo{[a;;"MrHy`OAbOB1:<[JpU+` :vm}2jL`+RXxSЎnH fY&O4E@= +K6yFCwiVI ɸ9@.G'lmcq ra"f"`fX"6*9,Ar=Jqǁ}cub q`0M7ۤqq`q wXBw- SpXb;t! 1q !T8Y>fѸH )>3ߚSi}AT: ~FB*yN=tRaץ_C)c3,exp:Æ[r:uX ǯou EҥaJ!,cKag9\b1K>aǮ"~r;JRp_~ 8T\12X!qwavr\rZ+kg#(m]QİH +ag) +REKWHt,'tR1-5KjʱCZ +W+٫Ur@1HZpT5j%{j`J%`s_Zr, +IQYB@vBH4{}@dXbUPg(T9 z6Ơ7U 5`vOcىkXvмdX3j$t \ECqNe'Y%U I('  A!ez-}`>M{72Wl0u>RKaH*"^eP(4<k^ehH#Um Ma»V󦊡G,^86?6* nV*O?&OW&ev]Y7 Bfj*ag2/,MZx$pۿX-p<;UjU.˃WOḫU>23xR fD'Bh<ޓ6t I(CskAtN$~g9?hp8!MNbhND"iqiq*T$g9 K(MYthIE +m,P9THju`q eWC$-'%4}ar 2iKmnTDֈ6Gg;(Td'+\@B;d6)Q&D5̇&S +vP$B+sZm;iWXM PIA^hh<<;.«nŲ!EB _7մk$ !Fɾpfߡk*|A :g ""r!\Y^LyF1I1T(spI0b+eÄ:>"=f];XZg[w=eMID%,KȻ @_= CǏ"_S?3޸dXlyC +1#*{uyNE!$s#sPB3ix/2RBG F4ĥ??L]lT +>Y | JrEVy0-D %PcX +a4t$SH>(_$// n0!$r0?=%oFCU?^T9Ldq\r {W_nF +yR`Fݲмuׇ&2= #[UȢ$x ξ2d7R']KR{560TρV0kF61#w2ER?ЃcW ǘ)%Ug_JsP$*'7b]T1~߆zE?P|5%?cMoLч9l>PIJNɱ>`u4%<2<"҄0v` *C +z&bBeڹ=X*aMc Q<?n~nJJTG @(H#:dЗ:fJKL ;2p3 +"z"I#`(= h[>! PLd:e "#hpȢ QPe3)~F?h)܁Q4(MG +ӋR*8~- Efliً%3;~\NS7[kᚊ`5*x q1lu̶iK^~PujCPYV*zթUolhmT<ՏΓW}k[BT{:8V'XЯClkUjn,9H@UЬ14yIf` oA׿P%])v{Ī@~קw7ghӬQ\QW/hCu?(2χ$htL$O rXJ^ ҚDŽIq) J m[-Ia*?:, 3J4x!E/i>PEX*D7ǞXv&x^ovxGEtȘ +? +@eDrL-A)a<^0ʦMivW"jL%|9B/ s!=UiHRfc#z O猨ǒ2#r\]-3. 9&0/,?].5=pL +[|,*2 Y.x916qM7f:i6aLsãH˦HN1\ |w5t ܢ|5]P^m ϶U@;]`쁚vKcE&b(NEWLL3+S $1=f\a㔉L"M61 'fOMEaB6}8cdnPT!.uaGEA,044/, qU6ЀO[f:Rzl 'G6h_Xr`nQJ=^9 ePV$eQ@\HL"+.⍆MzHJSECu +)G, I#d Ic&2u[yPL[.(,06EE $:)t%M6aI IWP=CZ.3lM'Èg76M C^JfcbꐑT,C" DXdIF$K0Yߦ'?#!"ب?1@?L,|;x6kq0<)t qe15A$s䖥Hk\яϠc1LKBG.אT&'khub@ Uxa&>eE˖Q d6U,T\LtiiuG/Efa,(@ Sfٍj Wa.Olc=VqprSz o1[G#"Ƒh0M +Qrbx̥J(Tk%aD:ה#K܆)9I$fuyLAZgBH*trz?ұR*XVfz6syPs +G+ GQFh%:L3"DeL0,yc + R 3P@‡B%g `Y$nkJ%<].=tt?EmG<+ d$eʁL(h,TEF w߉Y?,nFn#A D]LSD.Y{C&KIœ6p 1.Bd8 #m%\FHv.1K +%\tsm3rz0\_TM2a4j4N><ȝDkzR}MC+܋:ߧa̼DŇ;e3SB%ݏmvZ܀$$W}JeunV2j +cxxn!͟"B"PELQ#9N p)RHJa< q`\ r}Ar@{ɠ…uy.kaHrv9ǣOQ=st-qHPzdkZiJWi3j<E0,Xՙ`DMݥG*Qsf9p鵰)Rk1G1-.OLbw"Y(*׳|vPb/e11.iPc`YT + T& V`ns|Qǘl*=S/K!Y +ZQ9} c=᢯۵\TE<,@#K5r!~POސphPc$>pK"Sˀv #Π@ӐS(9<˞/a`K$׬*ۤ=| vN{ihPQC` e v̞ˢ: a@ع2x^jCh1NJJ0W5cј] @8 +/MjePUMyp8Pl!aj>>9':xy@Bߎ +Gq U0uzU85GtϹ=)MxjwjL:bt\aⰍ8z +&jŲ~%vPjNS:ssz)_j^3c^:v4Xw.H[+6u g}GRc;]SK_yRGD?jNFɽ:uQR5FWR.ZmQcذf;JX UCdL%N$aWQZAt}%f2;G-ke3i>"RZɰeM +R,5jZ%-S=Qcb긅}<9E&Ǫ@&8FMe:At5.ܙQ1~5M^l9ѱ-m0`(Fo+2`mSČĻC>7hA0uD]OjɠZqPLYh v _Q&%4 Y|75`{gou;l֤/c&3ȈC dг2~įK9ku!XzcX%yE.ko`gR;zȖ4Vگ>te"t\r^BGzuu`wUZVGV1Ƣk⹕f9`8(A 0T]U13mZ4" "߳PY"J>6C#%ǎ]g?0 RX +b+XR:+1ZiL`ta{zs4$Yt#qdNb +Oh@ZG66t*mK׹{/ =ui{+CDLrE`{`~|=u,pu\ e*/3X_È'·k/^A@|L,~*}@m16TawE1]C;2kETk5˄ϮxR_Wm˰_P +z9T-RX0ؾK/Rz`TZfZԢ_H"!0Ų/ŝl[O" FMGC_jYz a<~䏛cx?&[ fkk쮾/=:^=ue`jQ =w;Qì$umx _?(aQKD#5Lu㨶kQd0ܵ1Cu#_cy >W2_pM*1b(ʿ+PtL E OtWK矰 + +zǘVVz~f3>,(JQbFB/mB]Ō?i!}EY\ӻE zt5;F9MS`2\0)A LfHO1፽g٪3[_f>Y_:뿜EjCu^ɝj^; ,WTC5Mi(庁]2]v$Ό.up0oVq\ܐK~C5@M45p3$c@ra&5:PGELTPVaVw1.F4u ߥTJFT"fa> 8 +@4!xЧ d)lډ mF.o10.Uǵ&HvS0s[J@tҫ35VU PuW0[FU3eG xp^?-39 +ZCW!P XzT#A#NM¬F7B zs~pZ騶ZfE,H:iڪ)&4`ðCs lN@j*&¶0juA蘜NT. ʔBUQI$2,1+`ֶMYa&mjL7Lxb<3Cp1JpRnY]>u@Fg1r0iPxDJkh"k4 1 Y,bO##PtUt&] ɀKc#J*CB҉J=8 ]"R+1(&ŹȑlB ٤ nb@|N'4)ZaM\,1,@`H;nD"`IXRcb f lrb`"WE $èDW-݁ +S3=1vj/@h(LS5FО\҃@kF`6 3} +W(*Dp)%߽5^0>7@QP?1'6 05i:䮙 EQ@0yн[BKjN101"Pa.*. ؄;1A f!Hz)nB$00,2,DK gиL2]X07 AR[gdn "'|"a:aT"]nht&fvR9AcA +N7Gg_4a  P"ʰWA8B*)i(/f٭6R XCuSa~O} es?XesjC(f 9g0i?EUO,v`Nu0J| 6թ5+:HfUcGcyz/17ErՄ[^uJs{lѫϷ*K:)a9߯[Uo+z~NzNKhKBRK^xMVGDO⟞-19>~-u+R0oR/bywD=ȣ +F0{TxR0hC3P.PbZ9UƩ!uUP]~PLګ4wTC1΁ +Z$) +^+5oNxZ;@eWLQ/Co  |&ҋITpA^כ $;hqAF K>>b:n>,Axky+&) ~Y*nuz(`3]Xt狣^jzʐIߊt3Dz{ y{pYF~HN^udY4(MTiX5]2,&ѵyV* k߳xǶY; O@ +@g2 ruO|i t#(vCcv`kt4+Hߕ^mX3Hc&]#R.W7v A.}~ޮh0zz6i<(.VoV$n29%!zG&7nTlr3_T-b^㠄0 3dX>zocU7^GIehí) +75;fN3>Ci?8E>kJ\xGm+}EhiV6o|W+5} |R~hQPx1k$Z9Q| a@ۀZd?b `czulZ;@=4$2v--U^9eEcL8S^845,z1ɫFJJ,W}ΐ3fGH<6ybaSa`2A[mk0* /ۯ&\a &4$.IaU"F] ;cXۍK]Qv*z⩬'uiUGђL峡f+Pc&WLYpؙ Π7n\`j`G5{&{a7`#phـf&L!9ݸq {< Yj#!F;j~e7-*avGi5ku^] w1 ٩6S{ T:heaXӌwpsXļ}JU.K($"#D]w,7{c,W&&W?Co G+A),^o7Sc(lmlC8 0v$( +}pX~U0h(U$Z +MN`R>(#wUek5_?^ye~m_U4Z@1  + er6;7yQ=@JkJ cláFH6YNĒPp9ߜh.gҩ7m5afr;;Gchvajmvts3[/&gsR;m]l͋ccyn`ӯłv$TØRnKyQ\yHo.=mi"Jjk|:=<0~ƳIJir5>3~7s{YXż1}RH䟔Φmɾ<˜җ-o7B~1/&O V3^7Oٗ^y&_Q6W7fX?0nf;՝x6|Μlץj"~I.T +${1WV3 }f!{ya37{QyݩJj 6,Nmra'6fS~fl ?O$L2XX;XYwk5^>NeG]x]V+%͞+].rK%_`-ZuVpN]] skM۹evY+OS,hݚ-&i=:g8j^V~ TZ)>up x^DB)Oya?^Xb3Lvu¢x^\T>N&*ew PkX3̌gjRɜ,䟖 +t*_n3/^xr9t}3m +ן7>ֆ5̩;bnZB ݖ֧Va£p5w˅|pA;䘵7mQP.]m,v5XYX'UveX?Vrޛ̜wם8{K2Q8O]i^O::E;^['c+>R/v>P쭱9zsO\qCsleUз_>Za"[ :YE+OWFUbo=Yv݅0n)W,䖩cmnjg;XՊ<J>C:XX+}>ïc9_%m+s~z޼<) DbuA)h[ZqZ=ﻅی^byvvlޞ띔|:ws֜HH,\ynՐȘ?efB2X|26= )>4Ry[ye xr}=fklqN8V9ms~ŵ<7YDqnڼy)y%S*{j5>ެzJrn5K^9'~Os1T$Eq +Y<=$C4.-v_y>6%BTh#~˞2FQ)JQzw +.6mF%)z"!%Qc;6" #LW]p + 2|!Cs{^GV>U_0(x->U28H`1x$85c@%ܐ. +LLֆwܖ{Ai_|pQ»`=9$ +;6Cv~P _ɰ8 #!4Q4=gO \[)^} 垛ifN@kGFrYT׉Vb3iII$Z|o(eiI$כHa i`eYPnGZSʧbF%; 2&NkW '#fȣdi"si_M7F\`|vn2G10\j(jaJʆR8wad |f׭߾}mxaڅ3۾O'ݳ-d-m]o 4&1`(.YיbcZZyj$AW&mɥg+deasjn pEh6p[- +)dڧ! Fރm? O`+K.(0> ;˾,j2zZZꋨskq _֪嗮W6'uš7LLۗstӅGy:?M$ +~*=ωW`]:̜o"ɯ&7;)9>]_=8OW/z`<((wǕ[69Qp~Nۗ T1r"?-—8TP_^?YG7+mW\5m5?UYVoU>iyfΔho壓:ma'*׷@4 nLusr1Q6ar-._Z6S9=WZo` 9X>Xo33ls/G}Ƅ׻=UeAEܹ>_<7}!)gl5>gȬ2 + +Js⹯`%mn@V֛̐.lo7kL^lZ)WB$w8!Lwf .:a>&'7bYuŹ^fFJVՆ(Y̒^˘p)QzaKݭ󵄻Zԛ >-{{KLUNRł,.gN'ņ^%/YkzJN?9)t~og22L@{=oEL lj@9g GVO1>f"|ƁRL42T1|pVL `.Wd (XtϦro{s5: +VBgT*461ًB[GFFt?nFr·vVd˴^ei o,[:򥳭ֽڗ*Ӥ%A>}*a*-Z 0%6tظ⹕K~g^+]Zqeq20pLS1ʛLzr7?3g5k9ۘtHvMPe _h+}dgڠ@1;F b+ۀ֭烄;Z8Z^=To)T)[۩w\Jw&I@ ktnL@yzMܞ{PHdb_:ř~,X:`iK69Ui$B=f~z&E<aFzAQ7#AT^i\LU3' !+ UfǻsPP*ˇ~@O2*yY#38$[L{֊Rh3Fw^~X8sM1fg[zq=6 +Nz;w=۽{qd-f>ۺ`\mo{w>P1ԋ-nm}r +UٜEϸ4S|K + :̽ܮ3Ǜnv Z֛+k~TWWSݓT (qRIl"?o/ K1sוWP"=>;WNO&\q Xu9,qK2E洵Z{Mfqvvux{s[͗Sg>9O 9]Ɵyr[.ߞ2$}{9ҷ_p8鹙j/h~4Wf sJqr9B+"|=g MmmeZo%qLɧX-]'got5.LtR^-+m6&gpQ_[ y͕T?sꬂ*eZL'3++Ys5K3U*,83[:R:>^Zn:O| +TvY-MW6rʪZveaWSMf<7MИuӄߺxӨjV9vDw0< {,Q~'w$ ny/rU{w#!oڥOγakzVk ӧłrH~ۮUX-}^]#,WQ3;2,!}Ru%LFWKu`ꕞ=#$5׎<\Tg|M|O!~oMix-Wƒw?a3i~͞ˍw\i;i)UĘJ-)Șj*bpɵZQwH:0k +Ow;d>-/MڀՈ˟ꌇH1tH-8)Fe-zҘ:=aʛ8|(6 T{'@` s)<;q:O^ZowZZi?7^^aX=P`@n놾)@Qcv+xc1 Nf=3Ζ7Mofpj@P"wPnlY=0x`$T1$,@æPȞʘ!FS_(K-Hqg:"zǗ OKuOn|Rc8y0B)cxOh Ğ؎ a4߂ +]7 s>YH{=w:7]CB灚Cx\GT>Hc0B˨6θ*Ϋ03$um]N}1  ` &äxqkGIn?fUgQPRw;z' %l̿?wև;w=>|ٝ %[W 3)i;x<^ǻ_:vWDg-{t0+%>cln.mZBι?#g'D1 G(qms‡~=u8?Vv̼ۢ|ϕ]B__XOeZDoÇ$q<5z>ؚMgYB\,1gRǙnXk}<|K{}@Fѳ _L_~oϗ̴;^؏-ͻx7JNw4SG*P ˜{ך;s ['g~wV7N3Սlai$o ׵Lz~+{g}ξ.W7njY ^ϰ_iՙW/w,kv +*^z +CKWcuw/̟Z=W{ qƓm驘ĥnܪt +eeٻzM'ZwollLC/e{$ɓ]y9_i+vRh,Κ|`=l/ #>5S`'_8=$߫[|~ٝ'}bml9Uٝ{vv|&>9sZƧr՛ +nάƭũ>vwv|"_T`k3Wv|}}(ql |>zf:f|;Ѿ{~&_J<73Nvr}_ Ok/08?Yzݞ?U/`_gxc-:Jo*Woޢ=)'كədbr!LϓAieRWIs8\YnMϖV'7;7oӳÞ1sSܿ><E|F~2dzd#?h 1վl;;0JošO,gazz"<%^N^{ks3;]'oꗚ8~4fՒ13Z=I43=2|l2ɉ̖u7spڜ9Y\tU))5c3ogL?5w5;ӽJͦY>=rr7k;Gg٫Z=9}nf; kdɽNZ\uby6+U~Ud/797*sK9{}n㡛zwӯչV|o~̽s>[ON[mu~[OfZ0kvz]{_Мdy!YyZ8\; nbˁ^MTvQ+.ZnxTN-닕zaQ~JM6_SB^NeR÷^4绫k%ik\Ooae*}:.]l䮾:=-/9)s)~X:ZK.vͥㇲLfVbU0KEew<\>篔n*MWM$'z8ͽ;%@hٚZVs-}|%jM[][{Ѯ[[?5Ϛe}s e1&-k{0i\O fkt鮹:3+{ќYI=+mg7,GmKgo;i{IQŬ(&D;g~kSuwu ̏Ykη(l+9Tv̇w܍zqw»4Ω'-ZU%zm7]Kߵ[xe>X_V֫TiWpzZ}MzY6+֎^wzMv~ѩsOz+ޠ^}-vݫ}8FPy( n7ZGruc7K*7O3V}K]m՞:/[/[ҽms{lm7DR<ȉ-UFFxTUbz{U?om-$joN=}oX_-yp4l$W 5v0K6gMN߫4Gk},w;׏zcvk_^֯{ /F6ֻv":MoZY>/mW߄۫ɃzԮ.䅃ϵaqzX{Hx-luGw߱V?>3D9dO2#dCit~(<fΒ73lch%sx2z~8=ηVίN7gmnoᅱKS)zy>RrRi^}=wnzioa>zNQ;z<׏{;'e#7xl_g.'֯Փg|xq)rx}3*>ۯt]};>_~:hO9zwz/}<[Ocv}tgssN~3zoKZ}6ŋׇڏ.vDW/˿;AR,SlYwYU؂~;ȸ1=afd^|G-Nok`y!w˒k&q2*z*W@Qufk|,owz/s /j"wk_OHpz!w/o_ȗ{5~(q~!:'AZ;^/h7ޛ '3) +5B)}|ϕ\~}1[9M._Vn_J ^NVP}YD +r ev~%zZ9ӇevQ_I披^;gG>~q9p Ik%><ӯmz! vE0V}/ 骐.W= Pk ;sj5 V͇ǕS/kX73C r`yp[mŖ/7KȤWФw3k{71'S&m.|ܧ +8iki}IDGJwkIQФR͚4?*_iE$z'n݊A67{ҵ0. Ȥ vwϧ[֤Փ* W*kR0R皫1<_SA5)W~ ti ݫs+\pR&U<ӍN!L +N+{ݼ]^֎.9N↑!&Z}2)JK״dRmv4wqxʞt/}W,~<,d}QeLjH{Rws otj\kNz?(MõeϤ01mKO3Ƀ R[ՅI߸u%s椷|w=,ƴ7ݖĞ0?Μ^N:߹˕Ffu- G8i4f~^[{IW~2j92ɴ]s@&mi=ʯ|j8鲟SJ÷tsi4m=0-v nG+npjudQ;0iL +Z…1WL:{fqբ'F_I2zI9N ?յL"x0-z6);ߊ;[˗׿?D [l}{0}'['gݐoO~ا^Z,{/Ӷ;0Ɲֶ0hYZÐsh\bȷMk5+:{֏tw/woAˬoMR yۺ${PC0~ 6ַ݁cW%ち9%K*d~@>§wmta{;_.^TՍVH.O(]_ԟ XH;ZrJoY8H a{C aO"ZXi_J|jy5)H>pRL,$R:Ӻ&N +<)9.JvO΋5iマt-'Ni5҂3)xhӊIW?ؓJI뽢sOKI>`N7pR|cQ +&l^Ф'ΤB^;xR)ܤ.?Ls)^~XbVLiI-G^`I2J8a޸ n"z^3r]?$1~vp U淿* jdf`ϏץrlN@h9ݤcO ]9r)dLBǔkzdۥ~5,ɱ"s*[L7m +N\Yr-> ]|/?צo\̕RH‘nӻ:^g_p^!{OY燧:A ڧaױόNAV01^b7_6XxOƥb ˜l8{-JYS)ܢy ]?*.Fw5wپl㎙ \yWn؂ɕF<~ .r▖v[2OA쵛j!Zs4l%/~"q|g|xhi#vlK֍{+}7@C%Ry7ȻUA\T_8ߕV? $Y Gh8P*OBoebI}!pc9 9RtI# +sNf +juA`Kkp| 0,`j=5rڏvͼsQ ]i&֒Р ԕ'P HS;ce ]1 xV +_WbYbƄYbLcZ6 m︾4t$XSr 96H6\t{phcqLGc4}9JM\͒g5l{,;\=*ɱrк\ +c!Y˶xlˉBq {CE5I:miRzQfdů+jo/h0̰`Nsv- r; ,8xIc +"2K0l'ns +H[~$&] Ev=/Ljg@#'hy#KA Ȋlbw6ݡE/I.箛'%+$R8ސ,; ɲ$ۂlkRٚ+xrhxދ?K9ц_ctq]܍I"󼒹 נ  ذD+6K~Sg1Fӑy~!_g/$']ōt-omez~#:0.52,%U9zD HG8ᘒ4$Т$R1m]%/ıe1Y86> DlC!"%H/áVq%F[M-/O'LRxN ۫f{|(Jz|#_|m]M {_./faé1tZ j1g +҅p1qA0(CE m 9l /#BRB!]@]ӕIWF#aȠE&}(Nbp7 !y*`Qq=˹bټv3P ]QGJXTmjzУ,ل{ѥd"MSy$Ð R tfXm Makk&B0ONg Bij,*%XO`]NWxH& 5= W|VDj4nwiz;<7LCAgdx #3 sw NCAHͦ.-8a]xH˙Ѕw' sULCA$?MCSV |nk'NY[E.ZR%h%՟*p6ŰHo4|۪WۻΊixO9q,s+zi&^;7 =Ea 뜋?#TE@gI>wf$6#"W2N\$W_-m7wWVFwmܢN!77:1Z"HU OlvLjbԡO1 p7E>+gZ.#WceDH⹽dIq[LMo+pX€83wML~1'`W^Mw 0O7}u/HiJGO ͅ%9G9>>w3jfh{l|j߂0> auNB;fXH*d|y$x~G_RپpdըLd;f"[3#/6`%Bqtɓ";+: wlBXaABN:-, aHۤas6E~4:bp!YO\z I4+#<ӎd:+2mGwD%GEǹπoԂx(ewbp;Q>= αDjdqX/"c/55VD&dI;USLȈ{+"c86lKyg-ŋ]hY\n+?w`30}JFd<؆6mDt#2AwE!F9' +*v o9r4n"i`-Lߓ +Z~7+ǙЂJHD1&'c.铮3] W+eZ}u֮$DLZ čcgyE7~8#툛u?46I?B;f7Mj~á7N~8 l~8VϸGMY+SW"GT~jpIw=tt1ENa/$Vɭ.5]Wwuz?E1j[{&pd,^cYT.iF/ɕM/ wr./ݷ="Xyn6%㙻#K*C;CwS{Vߞ7n017ͯ^ ,gkِZ1ܖDpqgys|>P6+m/p"2bc/lEil uNΆQzD})o~"祼`6;u&Nb\%.fX{ALX{U}w kaV4k̚+c#ظ10JpsyhƨT>k%R1vuz&&[ļ6=FSw=/#E퉘{w+LtcL_ '.W˱YB5E/;o CvXg1n{x,1%[1T=W0(eÆ:\'~)/s7t3yHEccymkȬ!1HlTJVyҤm}Y2wOGfo^WJ睊xֿY%s +גߴG]zVtw2''nM {q8)WVY&RCw_j7 .dFRtȕ oW jM ӎ7OI4r\8jÓ_s&?@ b޿fPáz/&&% +kfBɛ<dR۽ם%ϩ"k')\"5qF?\OƀuSTĠdi.rƣ:ܧhV>= _tW~, +VcbcD nm*%/Eƍ$hJP<#nݕ6^iUHX>+m zZ]_lq (ٌ?W,8>KrU|xnlܬUe svmGXu|o( b̝eo1Xj[ݵ1|ֈe3>Y&eZIFǎ,S2^Dкu% fVW6Pv#InJ]quO43[K/f#gs"c]px:*|uA;w-/ xjn]viƺ#*>F+'o$?6EQFߣBGAJ-5^KG6.Fn2cZ9ubwlo3jG](Jͻ~.Z_go_'}o|]?V;,zߴOZ]w;c5~en[h/SZOW^J'8ݻ~ 2ٻ~tͪ_m9~~wB$TGT1{|3xǪ?~(%M_~O_x ͻ~An14ƻ~f]q&׏7{|<lHL8 ~!/G1FI wm 3~v^ㆤY9r7p7]4yowQ]c\1 όO_x3^hnU 96~Q w2~Mtc,^%z{'}׏$m>~~Ð~/WtwKD*Fe~ {lwXhN848ƻ~ݵx/<@3ͻ~62_ ]0 g/]v9Fh:,Rxo-ݍuOpaݧ>\l&]ClfY-;v0EK$|vct`].v2ԗ*%+\=>=N ++Տ|y}{iv#ruoo\ck\ jZN'z-k.rU}/Nዻϝ,W֭҃2~/ VFÅΗNo5KWgůA$H݃6XȟՏ㵾tS+p$:Rm Koz2!l + +h1:`K~8|G (s:X> 'IjwJٳz@^7zk{?[8S^IQU0-忰0ۘL7-*>y,me|kqq_Mwkwqq.x7nzx#ű9!Z2%L? FYf.VEha)_k_6q57Fg+\,e5auV>m*O`(_ܩ} g[4/[|b)>Rc=|* ި,S_+;Eln,H O~7Γf. s>mB6(5 p %ZnI¯d؜k.ߞ兵W^QbJ36cD@W]IMRq|O=Ip@PF$#\ NTn#/Y*&/^r G; +'VlvL=ʀL[!4ٍ3\%CnGL!,g$DVE]wd&JK,Lnf6/64wN -9xm+{mv9*q<9 jԃ=W0 +Ҥf5Y>J,WMgD|;Re,<ݬܿo=rEǣS4b<ʁoHksqT]`CΐcYZf7rO+,F_8yNjv'{2W]7m" Q&,9 ܯ0MQ[S +w6EV0|{by +#:օq?Aj{j y.QCo;&}[FL`$2sYgW^\\['KHk gW?OR/. cӄ!Ȇ#/En+dlfeY DݼA}t؟7vwfܗ0\<ٗH c5(#(nm$\HHx~S)֒ +rI=‘EO0~~ $W,%:HJtL*iogl$4o-$ tvi +"$BcaCYCLBh c9tQkX,^CTqRr@#>ɍ:E>T9DLTנX$弍FoB5z +w 1o4e3K5&\")įZRq::䦥kfZ㾲^zV~17&!|۸SCƖ_KӜh{Ę Cg㯁b|㮸 Bnf+oqo\?Ckw+k'z2c3|Z&#z;|-ޫ؊oŽ'̯z,l~]ɛi$Nv.T/8aN)Yœ+9ʷvPtt<\/R_`<*"3bSSC9̃ >ŋdQ$JHΨ!YDa\yAXfrC8. ;Fd5yoɰ"fw`9@76WqUqltQ|m=>{;S'@ €d`-[h߸^NjWOG;mRn6̓܉vPU#BuC@z\AyQR0-:) YoIjK2ƃYlgDQp/ܽY/VlJ1Z.W +ڲ\ڋy:$4 9il,Iť!"\`$И@CH^qݩTZ^5+L)sHl-_[~O9j<Ml@5b`><| תMl@5И€k>$Rqʜ׀aRDv'_[Ǭ -`P+K߂TmU,Yrg?Xߨ'O-4˿-s3Ԧ]_i,Xؽ]+-/vqȲJUriIrBGZJdl >#W  Q׌D5<W(aK gHՂ!P8iY2 #2Ϋ-: hj:fޱnLgQ/*h8aEg +O긘)x*UKt!!C_KU@^ +H_W"b/o\r%>& ϜnR, ϻ=gxIr+GL!KM'+81n'gv upE\T+m!6*߮!k`*/ !:\sHOչCaZ;nɩi55u0À5ŅmNJ;N7]xCZ{X鎟,w|s^ߓpv +$RtFRRW;%ڹ If%#B +=f%#2VH"5.Dj]"="YvG I̲K$G$%4mʬ--mNpѷwCkz?Z%.EMXd)kD +b ^s +_1`$^jZ$7`^, 0u)@)v$g+Y,2ӽtIgENgQE]]$YEyQdIx]T xYAdN]y_vxnn{u$x^* + J\e2ʪC}Ģ.s&ʺsbmM)ʺ h2P}jkiRQDFt+7<@SN8Y <(dsѧ^Aᵢ "Ie& s!5M4AYap/j$ BSxU!IR< H-sd쌱Q<)M֥9֮< EQ8<8RQRZ ķ+;xq}Va4HEl @[X ^gYթMA1"$; ~yXό]Žo?}<+r QaTFxE ^S $C)e0gjklW(`r)`Iy3ao?:<rv  ƍ@:g,}v ROީ޳cxX}ώ 8 t()T|'p_T -=7c&zK>q5,ܨy,nU@+B۩s͍q]MYّu, }d? +9qX w &"ޣ`0HL><+rTQ1' + CrQ]2H|2 +Iq4p9U9M(/K[>"1khg *MD)dP4 jQT^ajTp2DEM%|0 $IM=q؎F +_u^]A4yL0",yc=p:E`f SyUEQY1!\QV%{qw(5"IT>(`TS*/i6k*$e ( uM$;qW1:+( +~ +t, nQeVQY λpET)IYr9oX 9T- R4 Ap* <C;i&%3A"JoC$158+`R!,pJ^Rt 8?L) k: H0`Fr+ɻu~$g\H iK- Sg!rƙҔEeGI8'\CŢIij` $ʁ9d&Zl @7EӜ2 h#Naw Xa)UӨ#Nq +.z%RA\I|hd"Iqg7#ٺٺo5z5 p~ ?i6+ĎdFܧ8uK,Iv9ٳd4|@wz+Hu#g,E DE#@o0&d="X, "5i|'WNjh--Dx( bD@ 9c- TQxD%FL ģbWE +hX.:i ACuv KnN㋠+&ʆEZ8SAFtPe DY@P?[8ީÂqwTF7d8X),*I,@/ѝ3ElG#٩ÊS~\ - l=Js (bK%[al X48$TUq6HN{ ú/`+jbaXT [0Kl Rw't,W$S!H]Fax| b) @ +W 3J-D2L98鋌> g*Pf" `&Tws"h% + al..!4R",3"u6.1d$6f?b`c4,J@*I]@rl;;t2vըXkp&d5Vå|E0F(cBSIBa) +fXc@-=@ +z^uHrRi eaU^srA!: .ځj:ڱ$pL"&U7!"b/XVa֢4*~G]Xd`3N| K ,5AX;E\+ nm~Zk x8 @\u6I{Ȉ+kl`SxAT`XZFՀ436} &v<@8($ +2݉Ty:058<@"(c `\>@ }FgX _2U75 ړ|'ؕF q}2ٹˋ5 ,3MTPg@>F .`3oX7`4*VہXޡX@>:X@ ;|d"|n7u8m VPvƷ%+anr=%+~6B)$6IVi0n(J p*CKT 0y:4 nJI TE[(;H] 'LZQj*bb"d ]7cLdlj4(pK"*Rj/I-'GJdUJ \@pE3Zl#TJx"E[8k۰33ŤH*EOUd F QmPEL,kE[] l +4 +Pf Xe6MJE;yn݆i]E{8-R=jmxM6:(rbӠR4طN +D*_c qAP4Ϋ +g]vU#:I8()}{p#O5 +2:D9 ,1"L! Uf4$D ;)%x~P1a{@,A2cqsW;ðz%#Y@"ZlNW먙SE3'rٹki<xS !Ohz:V^| e-<Â1L +uU˿tUbKuLiX/۟$>gi+#9F<̺9@gF]cefO@$ t0a$_^R,aI9ŒH9N-(W !]::]d$T;F갰Q"ȁui!*:ֺ1 0Pz,B.c>#>&XATT*kUb1s227kt@r4K6q +g<@'Y+تB1*ᭊwxRoY)L]g@$ߋf޹`DG?6ӝFRVЈ}`9 ɦQ!TcbED" mRIUI֜Z 8@2D)j%N;Ӻ`,UEø +*J]=t[(Ҏ;I\sT QT>"'s5 f9'$zj14B`Yj\Տ N¢ELuBA +'?o> @ pDn: &xY`dJ5ib|d60!A)ˆuRh<(`Fn8_>Y,RVEA|_IVЅ@8 ЭO6xvٕFd FTME&7X{*Za5ཋa7Ua5 +oŖ 3':Jm!E@:^*Tς@%L˺*|RL~JV@1@Ѝ׊>>8 +XxCLWeͺqxAxE +.HMLF46;|~G:Nztn@v#yY4*$s -ofGIQ߱ h[1C*L~NQWj`;}\Ɩ1jѽ_Ύ$Ђ9_h(@ibx\hoP9\i[U ސaj;/Suql adLm';~26d0=B2"18^$UJ*[b.h @Pc jhtbt3a O>DzmXPz" +T?>˰sQoo^{П~??Sa=Y{ endstream endobj 76 0 obj <>stream +%AI12_CompressedDataxdu-b~.Ӈߤf0@Dd-Hdžq(w}Ykm|DDVe4\ATVfܟko|q?"͇/woo?{_?=r7^՛?;xw7yT>믿{޼'?Eo_%*o8_{/W7/׻~:_e/KWgs=ꗬ/Bˡ|wz_K~Nb<|կ_~wyW]h9.JwPs8pӜ[\\.1גwz櫗}w~͛pׇ_9_{q|z o2}ꛗxi߾xwps<}ꛯ{)uR]w w~]7/߽ᆜ_i; |߽Ҕn߾/+ZcM"7|c}=rM߾`Ü a;P/Junsj)ϛT/[6>xW/g~wU;1.loU˿[:Xٿz5Z5_}=fQt;"//޾7o/VZw_ewd />?O>H}+<*^|;LR?|ưۇx͛ovW߼x5/0kl?GluT|7z_^/}۟$݇;W{o|}~϶NU++nɷZnԿW߼9Sopy'/Gz[A{ӛo^}:o~o^߽{_ׯ@m{WmɇgXջN|)7~//~RO0Zf0o8_U|8__wtKx8}=N炒QJ=TQ9P*J9et*䧓COx?ܣ<Ɠl\wb_b[C~ t>[ptzcGn6nb +r₲l:1c#jҟݜjh%c)9X_㜋45P>(zK|wC1(X_c8}7JsI@o"b#ؠq+(^}7w1=1+|_{$͹\g.m-{|%͌38Baf{rw䌛#Ru  u1tjʉK}3֮fϰk&oZ tC"|8ߔ睘Z/VʦdfI@(S"`_M.s79}G7)k)aC/V$̜3ԅ-uWʦ]"G!%7"ݦ~6Loscჟ"i-D@OeDZddJɾI39G2p'JطAS~DRNu bu$8G>]$nn؅og( B)4) ry_H>F=?N2# +dIt>ֶ-WeǾΒO}nc>]0 +p0ROgD(.5Oo7Brh"9h(q($mt-S9j2*bI8#,-˔Ujk}4_R:ŵ@S6%,ҥM>Mơ6vt-lئd{LQ+UcWI +D^5huѠM>NƵЕriR@OҠO-Y~џӢ?E4W-s75Uٖw^~@l9OM}=/bdr1HttťﱑX\(<2x0IB8,ڧϷL6\d2s2v"ɤI ɶI>YٴYSy9Z`^ba#}3fCrlw.x~5b1d@ksKS$H)SV 2K&?eyMg;̲PrDis7~?|/޴ş5('Zi2˦af~2Ù.ԅ+!q,A6,AoҥJIӄL,V&m>H%s[ϲ{Q79r?K!22T<4mɺF K(Q L~)[q_|Y.|S^I¡0a-LZ+ű v8ϋ،.f5a8&3OcVK3: 5U"q&7}gM23/dU])gqIJ35Zٳa n|7$+{Fd`^N~JBn"ߴ{,,Yic.Sc5RmM>jF+6MZ3 [zKr`_Nr];H{הhv?NLKIڭQխxZS3K*Qv{mgz 4Ȭ4P@ݛ:h 2. kcXjlϦh)#M<㱛٨њMwe1ì"-EYBߎÕesN`t)r,<.+U}l/^Zxl>js4M]4Y&µβZP*/AQIx5/ԼWVX iS([ޔ5,|(m.+ek)٘@ئ yo ܚiٛFBX8l‡+lU : /΍AL!ir7դHC"w<~v|LNW^ēH<$'tAE1™^C.os=A/t|1撄=,b'G@Oy7^ >/y,p˶n<,^m/?/"yiC9MNKy^F c+Hm3+S)O Oҡ}g1aAΫ#dOݕ(WY춸ٮ͙6ln5'!C[phKڏ}q@iEJh%wp}%Iۥض +mfZ6r*I66QRױϜ]`.0 bet}Xwۭs-k="еs%Lǭ"Vي8f#enSeu;zxǝOp4`ڻ)q>]U ٨.&|+3 <QkrOZ\X\z;\s^,_qK7TQwƫ;KH?`7- +z[h*b$۩na /;=?LĔZ/~7ܬdoX`3:rO;Yν2t(ҶScn9%d?Q8|f igj?~bX`Va/n1mưD۵̙āH$^%yq$'ˣ{EUY$VyVZ+({j+ɂ$R[ҺowV:[#}3_[tuFat-F{=?7#!epc[i#h/!Twx6@KtYs?GY A-4*wmm +jpi4Y/[0s4trkQ[=r2#w< JKGQI %`kL u߶SAoz^ Bi|Օ p;W'']r4T1LmaCԍsЃ吊|{Qg;5$Vp"wB,`ZIAWTO>H z6 UyK4etӂ͋Rk*K +WFM:iڶLE\QnlU@{d,x}(y)Fp4~S?o/JV_G|Zy$/gB)Ӽ0oO,7#=[ル;*{xV63Bo]0]\x<]#?D{>?wb0:o`̓wNĸ8G6}l9sdȦϑM#>G6=ϑM#>G6]D66i:K8. dexƩ+={jϚ:,5mMޮ0POE=Р>2mZľ~ϕMߟKX]Hw-Qu} ?pP]MwhcC7\=8Tcږy1SA00L tkPKhv[&#o.{~T4/kem?F^`y%5`O-?z[}z}]Qb?QKfc7ןe;kCzdu9Gf.3MYCVb{l]&-2/pJ +^1\=fa![z,@>vΏݱ5hm %N[ף%Xa%hq=R"nXA7 +0{t~Fij 8]0f a3 +SĶIf82=C]ba;o/w{qF^HH_@xbkJRb:  +SU{F 8O͜k{ϽEάn{?̐~heqU?liă\ W PiB]+t (q H7Ouԥ䥤M&ʀ ay8F5&R8{.tc96<^CZ:3Fǭ1flGтّ?B>R(b~9NxN:لq,]?LŴi=LCO:v1 #HuS0$ %!Hqe+㨕E;n1@D!fS?x7۞_xdqamJ>qcdO8j7tfqIAvcG՝\UFh;d|,ۑ!-?-h~4 .҄=ͮ(i3L'Z/2i!/eq8eUni9p~[r^2~1Cׁ@9+\Iq+NWbjO7%Bv!Zƹi oi=|3AO"(e ButЩ]nnAZw;E8t?*MA!GnLW\t]M7 +mOMFXW;z3OV~DY Ƙ/pb:(3OtփoYbr.5Zg Y1a;}WͫNOȍCㄗo;|~GH>W+{׵#`u8Euga| `1g1dv +]\u&$ӞƠRnk,@oH&x4bqnjxQUfܝvh5TS0"oens_Fec2@mGc(2y^Nmx@}q <.ql|*qHt8G,+2.ˁJ.4rT~Y 6/sbGx_F{״Ulm$ FuLKr]e׬*i[MiH=/#l1ux%nF]>nnDvqpL}h.>6&p'P?U!4O nqGI'C"-s'~Oe|e0x1q.k>|9MK> \BppP抉n€EoI7rЁ煉rql6\?>r*٥,YCR t_60ٞE]*2& [/EmdZ˴7Itq!c@m{LbWT|b>TKy&F*('p56 مb=7MY*pM p&+PVѷr^E4tI4QBeܭ4Y)IWL%c6.whq['ak0lvz!d%f0Z +f% +8YjP);7j~-U$@gPrk<@Š-o ޱf͝'m'HGsK瓸MDs9>s9>s9>st9s}9s}9su)ߕs$_Mn՝P)W +ʴ KU’..%]j9w2ܑ/Ё<1nG#MKmE_e(SG#4bZrF ȃ&ٌX$ mrlqC rhK6A)F6" K.9eZ\۲ P_\38ϓaYrĐ1[h˹.uYib,(*H "׍PuN'1~LYeYBbēG\"lN'|- ޳2_®MYO].WKGB#SQ'χ~)9 AK' r}^0 bo|yg2LT1n&97%)iXrmڴO29̻YesZu}kAU Vlg?ottۧ(;+pv[!m$v+ty;.Tw׮ MǸ-mmlǦw=f˳fzX|^nY3[o@i3ňKв0jn>@빍sܹ_e`>g .}Cw (ms3NO/Mii-簛\ZNڱmdta@OiA +Z)q!t MVQCU8f&P6=OuǮ99l Cs9A;FuKZq`s6)1/VJ-{=~5?_{hOӍaaY_|7f|߰lOW;eT^MmI^.έA"è]\zQ=H)<]ux厍[뜟4#tz!?NtzKE폻!܂|mnAO%Ď=jW'.y.E\>-=\wx};@?፡kv6穩i*l85ie:Ӻf:=.⑥~iM0]sb[y=F$8~tȴ;*İAAT~˴ұ?zpSЖ1ml^%>QcN㗋L<>KT6Lnn% Spe? hn[)$k04>tX%n +楰XO݊:|͜@Ҫ&d:ҴtyKT< Y2-I-(1Nh+DZ؍Q+D1*s18[=:;-1/#,%n4]o9{+^U s+K]X;\DU7˒dߦѽU>tBݧ[G(e֚i6)"ܟ<1e;Qwr;.g2.Y]b ==9n\7ƭż?|tqll3nk{ur$SQN{`M튻QeP w~_/>\<6}đ*}]۰cSVi {;1ڈgmg'm/s3=:aڇ]+g&li#Fq +Q\/CSw4Qnڄ*>2&ɞSG%xK?I8/rxOX +B'3S*D|:?iw2m(S/nSO٘{q*#br)欨4.ژSvD(9ZJ2 #B|C$?q!rk9Fh*#Gv&~ _X/"ן7aw'x ;p}.ſt.}CLU23=8:/i,O^7n 'N0ټ,ѱUOYeXg&x=c8w{a".=yRYu6 +fο$~Lf% +ƻDptB>sjр6 fl/yfzh *L-.W?s̢tYeDLBIP]8hSJ6m@z5=]jPg{z'ha`sКV6<Íwxܨ4Ѡ77)+81bVKT>8y<cE#6P=UP~-laNЬa~Hg4@*Rqk:t_FqBŒaA9p/e%Gj4 q#E8<\cm`0xkeH7\Re ]{{^ 5ӫA %Dj(:T`73hw]Z֢ZiDS?H[ւXL,Pb کq}B +lE`  +iy`p8!896YpK5cpהT-t*U[`[a/ +$((Ps$̝ě%QIٮ⓱Bi( +$'(vq@3o̤` %SW4@$3욧T 0!AE#$pQcPVU .F1ZL<8qhѱWZ@ :WdS- b?DY)k՜Hъ^ADH +gj2ٍ nԜHv-L^ (m=IȨx'ܽ"U85[>qe̢$ +H‘Y JL;f@hF^H]Hv^i3@yM}f.15aӊVFW"^SsaāvH^IANJwG 8 x B(K(P&iP~ׁ f@^F2<&x`-PRU$*Ue{rZ{ws@ˑ:!=ӽ0T#Ue [NtZ 4Fqg7`B`ExNz|m $<衱^.@1 ,:rz*H Y]d]*آE,7*ܯ玪:+?k뚮*g7֘oERX(ud\ژ7&ѱe]UYx_:nlPy5^ DB & i Jb̃ f~B7pː+_u?3V, @iPHT%A,$P֫lQr\ brV +n]L+Yrsδ!<4#z@" #4 *&xjy* +A.kaWh\HSmjoZ +ʼ| %wx:xhf6@q3J F^oT$Z}ƁDs;Ϥ\SA FŘy 8T7W}f +j piƍ)C'NiTVjfeB9ABYTwա/A뽃R99]yAY^ +t8u7乖xRsm|.yf,`v ֝g*Mc2[j HuEN7uYI9H_>YCq ̔B~+ԝl --є0.YFIX)ņsIu' + 0u'x\y1 Ԅ!HKψŘC +{a/͈[x> -:mՆHC &b*tucS3 hoW +il>$zi&Q SFZFVNG37*FK(l&K^+t9hFWX5݌[NVlhH>L-Tsq(BZ"}3QD=NIpp.(7$& =< 3Du҃ +r/".5798ЇiAjx8mtajAWh5C jA[iyxF@?Ym +Z9 +4ihr}ݩ8y [h-slT+@C.S 5> +Z`m'M k ^"OW6 3YE-_40p@ʊx|' ^K̅fNܟE0WTK1iC bFǙ3,δ.QU @;.g+K380$d:DU +5Fǩm}+Žh^(BЀsNfln55C9C-w'[UP֙M4&S⮁UzqR|0 6SҦ[ H}@ٖ!DH7[PͩDS<wJO4:Y%qaI0uȖ@\ Pu,w9{*j3;-|o;B>Y. GoeMk:U+j2GU@ {ΔS(a)-@K4/Y/ʿW U2@ҡcdעTbhbZȋR c% ^$: 8ar (/D&C& !uϋGq`PZAe+'ZxX2U @DDBpxX"VL[VSo (K< Dc^ivfJ +y_t&@ԝVl~x1VA`]ȎIЉt +(ZTkD5@":tt:ʯTi)Z$(\2gQw^Uii\/dj!@+Y恷8ә0|nPWD:uG{nLMjE +\$vRڵ@B}کך$sElEJYqaw/dbP?$.l +%br4`0 + S3v;ƋonDw CÔ)gzI)!Je +6'Y-\+Ebe+ji 脰(K2P+=gmf"=/ز"21 +1a?6"Y#E: ("q Ki]lQRX f2{Z#t>q*2:BԒ[&鄹~QA]k$~iե`>Nrxuc&3bAAqQ$D,/Z-.y~&DHM䍻n:33_"Pu,\"Q`ACQLL[XIx8L핂UA6+Tc{/v<^_ka5WC2WVZmfLYxPø֡EV^1BΦ2< +D+Z:;b>Llxѯl{F4~kHoXrpµ1S_¤b|# & b-hCna* +h|,4^㛩f,G!)IQ56ste|NcAeV!yL{h\Q^ўAOz놢-MÙKTPHK[P'-Zf]JS3ʍ}GHP<5Hn0&C"bf"dU?UJZw-.@̲̄eP"`j!^)}&jᅐ6Q6`\Q]F4-3{2OII23Df2P]]3͐MĊӯDIFz)SKP4݈- pCS8+Z>}9=}'Bё*5G!EW_9> "_Bdj$j.[PI]P@=ᴒ5h*9^1̈" u,,¡&-*-@Ԫ[NVٸľ p2xkmeD'04FnMMl_wa"LnK< NUSB`Ԙatf3.-5}8)B) f‎fPITl-sݠ(4vu>c(\|rHUNbfgD4"  cJc">BZZn,ҁ8nl^Ёk:#DnmzXA<D@l24brf=h&nW`d cţ)@D* [wJ0Ga40G}K)" j:/K;xQf.ʋOpLr#}MCĐ*+A,geQnC8S+!Q)3.INxkA~ɘ5 C֧^O.:)\Xd@hM LV`NfZLw `0Np6 Fk鍊š3*T/$4[3w^Toz6^os>πF.Tm_P61E5S<2A$2 !Khe4拓G9Y_ kӼH4Cө7WM?#J;PƤ2Q!&tO wh%[ӱUy [e׎;riMglSG3Y,oᛦ7_X:Z[@Wg7b& e.4  0ݥ7 2EyW'0d&I-',vOMaP à#,ٗ@ُ:Po eP =U)2WvL ZwZ<bϊz3N Iewbw4MH!BNމ;UzG@3Z$Lހrҷ@9e`ݶ(tM0:14{Ꞥ\͉Ip6/5NόG",ԜL`o HCgf+oQҳ[B}gEPHM5OՌ1Àaf2IǬ},M%7j tqklĘ'u 4 +3 :MØ).-fIvf7P0}g4ۺf>) H{Ѽ@Dfڌn +檅0͚6 in%P8F8 %&u 0.YuIROMH| ?`ͻ^W7^.gI^atH`׎IrR1@wZ)S4X2,Sj |z`ah*7q9iԴZQ0ZX©~B2P>~D.1<3f2 ?]Ҩt{ZJcP,XW?i{(|?7(t}T%6SiB+1ql2Ái vxn6XCskݤB*Yl:UBRTF$B +"~ۋ))w\JRJ:{6(O|Ts2ip 䕄YI9'2BT'̿sqVƸy$=(%єؖH8؊A{֊.˳PllZB܉: `Jl[s~k.VPm%s6&m%bT`'Zp&%^ H( Fu(mڌkf s@N!h֛U +mnfӟ* 1WaKQAfdӢV T>E ,Ce6uP9"h#cIlQ,m£0B׉2U'+!N&d"öI$.!49S:W4:DeDDߕ>SFyNA jj3ݘ?ނKxrGL$=*aS/QH0.t2D];KPC[pP;`^o\n0 &钤k%.fjjϱߖۖ-1L4Ҍ-<}:C&NS.!?/OLy5hS!Rh$dq7CޕSݝJc#@C`3(GXS {[$[% $Ʒq*RY`I Tt 뮩E><)J7o܌4BȒsr,r\QM4(@}GZ3 dF-s@\B:fIlr)<)! d޺K+Mig-EI_X 铸 + P`oG-$#j2#y+rd1cn#Gh35/Cp A,Z\icU|!! !B_$pS_Tœ_PX`N C„H>g 2ꪞ2͟R `$sMH=DxGc$3u9*QLyNv +pA}\T,纽:*wD]Er-rQ _ (TwIl;o"%Ս:>T93ÌX:q0,OL@;B$܃dN5h E6XyH)0f4ɥI x'UX4  IDHO:8Г7'Fif +F(`qLKHuؙ6 ?H^* Rl kDt>g+7eMܒbhPYEMvMlzC&38=")d9#Ăwq0d 4ɟx#7[#0XLT~H`Vˊ(f1;Bڇ|@*r0]v7+A`Y[N4YM $[%8)]|TǰAЧL% PNP YRQT$C0x Yx_8Xw- cHHߙ҃9ArP%a3}Qh&<4IXaif˫qYLUI;*+k +jPQzǘMo\a荦Iƻ3)dKlAO7 +=3dN4Q5`R +VwhL`@PT,YLb2 1!A nW*;2ɀ2'e+Kc$U2dRyQ3򍖨|T[SN }$@X^L:b~Qgbn9tlVU8x -ƽ,%HWz sԸb,/41rti!%lTtCr(Kf3Åx + db`L=3XPI8 |]~ļ#6yS}QBB3b((BHD<[$EbmVTմYP˞iײ?B%0.EF %uћB&[8< =~- T#7"0.b)[ cG˥L4- Md 5!FJAHF!=9Sx#ČTaJQ HP{E*ltƂU2<U(R2b9,w)#f*$Ēx jPBckzekm$4A6bZ$ r#Siv)4gN3V.K ߲+es^08F'deUIiA˦ כ/cfDK\ 4XfXEuɅ $} Rnd՜rV)Ի +akd*|өKf7Nr3׭~$@cQ-+KJ|!ӼҔ{HL%(:$2 S/x4ɿp b*(TRF}"3ĹXvo0)F=)V2wy,pkUlubW #t;(F4Dz=G; /QJTIK12ZkE gj\ݠHB;3Cy 1c(ASKf[sU( -u苉25t|SZ$o)j~m]&D-[xER evD ߶ԊbDly?%*B!)!k\8rObPXT$51 rMwDZ,aT|oE͕E#+Ek/!EhqMĖ3'2מ(1ߊoXLbj'VlecS{FR +Tg&E-N"8ϡc6 +ʿqtRFp̎Tle$TH* +h㟕 +`B"]S`˿4∩ +h1וlI9j4?泔 V/+a\-TK!s{J+eyҍȻ~H*A^N:] s@Ziɂ 5EFr-U)dh=~qXHaֳhܣ-%H۠EbTZU-ѫ)#A} 2>)jI&cz"P3c.:UXtXQ cBȘhYֶY|h2VfUlKLUbAojiN\0X`yFhܱAB:*5g#jL縦3R@-)ߎfP0@/Zt|T1,`rƗj8r0RA+O29WȔI溘+:(h?0l1ڦQ8 +:+)-tFF +r{Z+&LBқ! } +vOIp_*BnE]'kG$au৊`Kw)2>LK@c@x`>EpILEV"H[c %&UHRPwUbFH6, 9d s7&ʐ^9(3hqE&J2JM!)˒ RNh%`5Ī6M林 ^ xEؒLfHB* )6y$SoEdB" +rǙ;dJj̳֙R0R &U97ȱF:q2FQGEv|Z1宺)֊Tdz`q%f%9Ⱬïؗ +$>u)CD;:8D ki>wD,<\60(fTєCO*yD(Oѓg! /ΝT oY EaGq dl 4Og-B̒GJK]Յ2Q< )i&9bFYց9 C#f%j f9 ܅X}<үbq^fRCe|MaZ̧;eAh&̵2oeCGY<#*r%7IƏ +#wȦPnmlIzVWeIpCliF]J:K2p\HJиy*)`MOx TxJՙb*M̊JI=5]Ӵk"_#:v»(*ur+OdߋPbLD# E7NYԃ#9UX*$VQZiE2^Qs%7zBǫ:Y +82&o'PΥȧĥ1{ۿW_D0wx_v *|<d@0ԏYbZu Q&xˌܬЉ3GYU@X)J"n_갅( +klv2T0){ѽmz-.tVIKbCNB̄5cJ~r<-RQ93Q:TB fTnUA+hg6YSe J1ztg}fkg+͍+=C' +Yu|$0L5p&YdO[ h4*xOl7YXہGM5kڰzV1@m"]%"@`$ #QSNRW@eh=UkZ%s56=T|f]b#c>ߺM1T-7(?ٷnAFB}hǤ/0R5d SbmM3.η}ee}5ǩ+8E )PXgWxCT@oeGg:ȽlA݀U@Eb3h`(gE?kG56$ +B bͿ3j5@ͣ!qU*`<w'qT:!7^ EaS;t k@dV'o="2ދ0I  4dy-Mi,ktN:xHg=_tWk;#Wz4|U0zxmT8fwr"Jm?O++0RP vE +ӗ %x-H.I@bt1Cl1;_0=y^}xzIH:Tt?9CJ㧝 xW/W:ǵ#@͏(')}Џz\'h/gt] l(F頤^]e39S A"m + P0zvşCUۢ!U Xp榛QT1F]}i fQK =`!_CCYwn.Jzhi8ack>^p"}z-8B/vlB _MԬs_4Pyj Pb=)}F^,UӠ, XoUx>"#qz`Pt蕱&(To G5o_:ҩ)(X= #R2붎.F03W3Д[QG׳&k(d%R^Y/>L7CIb7*W&"ʯ0#Zd*-ኯñܸ N;/qFZkTs+Z:2YVX1/JkHQ''Wﹿ1lE̿5'!I8C o4?Vc<<&}[ +h܊{0c>)HW!.A)ˀ +CVKcO_Դ3"ޚr#\A +ebQ n`4T 쯔P JLdjP̰@YֆW{E'ʸ8@q=۴C}^y$2dv+^h=!e8) +\O$*IAf@D~ A%^*<2Uʼn Ž,w2NyI%h޾bY1pI,-_`{$$۶ ڳ$P*td`}!XncW#.bd  ArHqȌvb"*|SV9sQ9Ԍ?&!_Q \5zWjrfqcy^Jyy+57& +8OMCYADT;C{Cu乴wl Ek*w; ONeEacƂ&TVS DҾwB?Pr!dgSU&~Vs߁0#L䂉҆PGĔN+/"Ѓ&[AaNJ^!ԑx齆L>QDs8o*9[s,=*qY>קC{ȄеM' ̨"k/uz]0 4Dr}Ѩ_8/ pTݽ<-j3t%b+Uvfd*RdsdڭYzβYQ ŮJ!yj\r^ztJ[Mq(n9vh̰wrm|&s35Ã7nG% d0͛ +H]؅w% [ EvE$FB6%.tVjbt +pѷ%Qs?%OIO-qQ ȼ zu'_ᜑ(њCBfC t,u\YqDLrZC%RSNNWmZ 到O|K~HK-;`(>EIC]<pM(PƙS&L)FIo!5)M{8] >˼̷6rT(FrT(\- 9y2ОKC;z[%Tld|C+nh$$jCqsl2yM.undz5]Y`*jWe-,(/bj2p9g ZpnI{ Kr&0Rٸl[$ +pЏiB/`PF;AI%Ș>(ֈyWTbO}kG+=@,*Nh{|I4="NB,G&vEs*/C`p7VӓAzvn a_7a +C=S -I +jTG/wr9oߒۓ3JeRu:c&3*Ӻq$gp e|zYMp+S>zr/Nh/͐dfCgi>VR.ٙ紶&ǣyS$1ާ.>AMbKݔ'T9O!$j\wP Qz]G]J0$g }In ). +s!ΉĸII] +:JͺW艽5| "޾ +b;. +ÛD^VkD1x*lMN1PmOf~+"rB50ˑ)mUWrS{"f>?=kX^]p/BB#&a&+",%Z bEV7$/G +#BgCsx[ Lu܂0"@]M|ΟkOt|mju@-G]*,yePy̒)4 +Fr Qh~Vj픋xjkuQ1 ,naZ'YOޅ+.[kVc"4QexDN{r67ϲ'~˨Wh\ԗ/idB*_ysY:Mἦ Ӿ^5q<'6y2L&- fX3~J쀆Ci5X}C? +\ 3NCDg!TENƒVBj@^ܨL&<ʒ>Q?DŽoX Ƴ$"}ɹ%WAj.2VՈ5VD;[ qkN96U"hGG: udql4FM#?,A`I=DQ7o H~C VLmoYD\'l´֣q%tB*+3lQ^-SRa׈S}Hk[p ȐIjRneʆ37BUw]Z?U[hcVaPfEu`GقkFK)'rޒ&755U@lmx JBvQC9\>+C @G9̧K"bsk1g;:vh2C1,paB+ dϤnoI[ mWT/'FN +K=既ǿ???__㷟~so?O˟:/.~7X`wOdB%)*hᇵx +2i9)=; [8\%%S+ "-P4 +@ZD4`ҫB169! 8.l4@lecjXKfW8M g(PV`q섬e25:amfS}kavc!W`GDn.Azt$d +KPė F!0UD2Wњ@"N[(T`ʂ!^M٭/Jm +-6 ;^H}BA)m^0Z׬Z+*dT +1lO5 %6Øò c.tؘS~&v†N "!h~(=C1`F2T;"D(U̍>`-mSʵYR(7Ç[a"҅ 6ÿu?(n; jw'WU5@E:?2'@hH<۷X׏EE Qn4d&.{f.( 0񊯇UWS<+p63Ӑ{S5{[*HFJfG!ܣGŻ'Gy@Gё*i_(eƙ%!R#vg02 +7Z% p0~I3;(ۣHƜw^͊t&{]&4Xа[v5ZaF^7X2Izju H^iѕ7`CME7ߒY >uBPsGwam&FSxFmW_3grMsڍ+H^!ȈW36B,t6FՏuו`7*;ʬGzE_^`4 (ԆF9[tj0OCu@BE2ZyZ,&_c'z +fX2{>ydE⡄:t!@(`࿗Sp/Z$ʔtZ0 Zٸ&]yWm -|p"`@,q̥udk]8tc< b 78FptR\A^rknaˮ~gd| +)5-xD>5P_= Հ)h= KwKj1}@ЩrXpEls ]./g(x5{/mAiRodZDټz<a}Bf^zx#?ʸ:/.RY (0WVm:vꥠ0S +]VMZt=3*q`;֗okp`tg4Q|m5m~hN*2׀ƥ :2dS}5FOCܺ}vnjR,   +[ƖTUv97RZ)a $ݷHT&[e/JX{d=upllф[-lx<,JxS"r, _fHN1wAXQ8`dn0 +pbmk onZa.}~yΪT$m- vɺx!0yT>7ꭁCzmEl"!Đq`U;4h8g~)6eXA"pS{?ZRlx=v>]@v)VZl*w +䭳$ +<{C#̟vƦ3Ik5` vĸhMbEi|v{㸎Z Pk<қ8qk&i+a4T w0J3t{S@>c3n~`Z f2^}Q6#+ TqAWJLh(Fj 7gBc}^Ny[ Vwd\ׄRCdOE>$ +EeOoS/:YUO _0yZ:ޖUa"߅,i{ÅNKdzoΖ‚-p 5.5%WV: +Zߵ~)E/U9eM$7UekV\^`َXHPB/} C+5*Sy8! @V؁,wQPpɊV RS׾AL2Dh%2k/l .8a|8,f֍kv\a5._g8p!TfT!P#{B9e JQGނ U[Q\*DrQU80mˆ w +IGv^ N&+oԶ7FTA*ˁ%"tGqs& Q= %;lt{Hs+}q !X)$z 랁I`d9Wę.Hv" E NNt6P`v]Cwέo-N +|9vhPzja#67hZ2[J}[$TlR@(=DkO +wNa8X% + w @"'Ae'>xZgv_ETOqFj]dɷT\f;;fl{(ύw|=DH'3sjJqo8 +Z;e^{]/LpG&4]EMevW#?(*op7קY}ՅA(FTL lDF<'RT2sn|=A(Q."lG']&5[_ +ãHۜFXC_Zlj`{^<"/' bWvu"a=3P8puC3zjd9Ee3 1^=SK 2R$`DpE2`^ЈS҃}ǻUXdPbf\7饘um,k/U;fkR,1SY?0IgpČ vDI$\e+SC~ +ͼ&W@Jf'9-l)an FO PRI늞<ka AeJh~}&/T6?0H,5xkf@/Ok0}8R32 ]‹Uv5tt"{q^g|(4_ +$O ZL 0U\mts6<VI* Tf^_Ż@ wķnu+Vy׼y8',T*9L=!i +FIrUih(%U)zA]@W` c-D@!Mh) "Q6mmUQA +EЮY"N[j8h0ʚw5d Cj$4H$pWks +"鶸LQ B횚 勷^[,ռhø^|XOʩU7jpOw32^չD I\>MKP@zzN푉suHuN/%cXOa$S}Ÿ'H;E+odQUϡ CPST^6S#'ԥ,ժ,P@Y w߰N8fF׌IhݱT ă#<Ժ zB h.?3Kֱf +&,RȽR PFfҟ,{1@P6. ;kYߑO[RH9~mM?DޚDckԔ˲=W3.CLHtŀ'ۨ3o+(b{޵/Dx:@B#mȴ{u j$_unl~!QePGGPU+gRSFjzV>gK&}P#Nd{Z)VgU1[` skb&_1Er2mGc_m0kϜQ6Qǚ\ +>%p+H$~'b"Zܭmy0[dD2}w+<ፁCˣ攤|Եg+ʙxl[eoy+|V>~j)$U:A1)rF< fE uH^no)GJٙey7x*kSCK"qTL'YI iYm"!㬕oD5\F߹Fz=+@ k +mr*R\̈fӥr%l9=KФbr7j7:.EP $g l׽KZō Pp +NT7TĦR9 M҈dUV k1 FZ4I:[YIbJ4;DrfFFOFfc/i'=7O `1k:0Xso`{"ґ?qx9^l.k.Ms)rE}?1Q>h;ab +!(fHE +;Khel\[19`M4ڱUQ-^ +b>Xb;b-iܬƛm?_KYd8/&{zS7*e} < +lO +Yْ(/T!{\#[ o&.3q`I; !]25 t ^D.Gu? ASӀ<=I0YB{yp#eIe^H+3A1Jh!Pymx*,E$ ڸ`BxCمՇ5|5 G+Rfw%hA? da fCa3 +͵֯nN*"V]NCvUUzX0ޭHVװz ^•Fm_ʤ=`!WEqo\s"v8tbMjWכR{v,iuGi ]vzByyk;T3@nF$Br}\OW^k![T7,7 q,$JQ&*$~7x);+ +LʒF_=,0:,KlTdHp +QߢΣWR +N$:U+s u πT[;䝛z'OƊEZ)TYrkVv!1{R"[K5 Vދrˈj(K^€8ŠcjD!ŀ }8iۿU=VJ;yH K>jEj\UAqʁOZS.O5#`C@}"?D $ T6EjZ|Y?8< cJ^#2¨k<5SD4H=dTZm{5WV#qFes*3JN:"[oX(BdLT 4u(CDooc/2VzĎ^ +@P5l\kc.=x2S`W0aͥDd4f.ydB*t_n7l- + L7!^5G\v0ׯ<'3]p}d/ "&vrgR\YPbc.[%đ_Pfs/ݲzKnL%$'ѢH|]#ٴ6◮` l 6lZll<;$B%1j{g ɽ' D~oۈ= BxGQ'݂G+"SΑFilJ޶ϋ0CB(M@nKX$&WT+ʡ Đ]!d׆$F!J(/b  Yr cu9QeP\Fm$`.?lSl8¤4ZNnG4¢AE!~6ކ70%bۨ"8l٬:y#1h’-@u\" !#<*`V>95%l=! /H5v ZC1g>jDIi("!cY-@mq$*Hv1\HyS^F0R'oܛ@\AHHrd2~k n))LOW|bC u+j]$_Hi +ugfm+8Y3Sx`1Y##kKxnG{x+_2[!J1F}? LH2aLjnGp@Ti'݆sX9J4 "/U]sG/$r)7ZyxE:l+~.C^M*ܮvJяTnTNS\YngE8F,*ƆT._͂ĝ\l6d:62R3z=$Si8PYfrP\!bMwY4#}(%ja9 ׼ȶf$I@4S((?Qpv*3M4({Ea.HE$+ rsҥfFwx쯆(G!Ӎ/$gHOGCD-׭IםRd9h0$l=# +eYo)_ةan09IIJXtŦ)ՑZFuo!d^ź $a#%Te>|[ k%@>tiڻ% V#69Au5A<axiNWzVW޺D%<@--(yGsT-Th|^U) + 7 +;7Bѩ Da^E Zd.( R#5ٷXH'[< Y!{8F]m9Ƅ; $QrXK?9*k$f(]-NYDRGf +"I(K7|g*A :9>H~L[;eDd ݱ(8ȉv6)A2YZ$HS=;,O[<7+<;v -B*0+D+0cw?1vA$݃}HD,μXn Eut5}-^CzV>NDag&? R~)fPʽ=$t#4`̓h::B +t0gc׍a Bt8IeK@y0+P{Ԡf)hP%Mp0LJ縆1a5]'dZ:脱-pPM7W&|Nd +sSRIZQswP%] qB_tl}&,j+9b^ 9(>kf+ӛ\a !}%D ed܅"1K-K1K+;cC_C2?#Kd9 ,+p{Ls.B2䖚oJ eܩ`}_-=c^$CO@9_[lz*8YIY-#H%[kX>$4>:J&IAMm&`٠]yem૩r KW]J}Rkm8k2jhY,FUC[ϻz\ qld 5iMCM!E_ͽ${>\s1Ȅ|GVʽC,;I5&$(༦&3mR7^+^ΠS v f`Ő!8)]30U8,H+iV3@!eVSEz&bő LLSPgtrv+NM %ܵ/آ7;Azd HAΈȯ(Z?,dyAp D~ů*"o݌#|oItϲ/3)1C3(鶡}wJ3 Ns+WDATH +F}:GOQa_`dll[sG!IMBh6^ko>@;!!WG*ORjISCNB:Wܪ1bS,%`MQb Dz] t +bL[^Qb"?UL,G5%1"VcouA$\*p$kaFG3Q >?d45q z@0:) -,Wauf`עCEUUv*=P,xkﰳ*VhXaO +ڊ^؃dlA+SdRE)PZfҁL_QQ\Jo`^4)#SW,dg@Ԑ1㵅yZm]oMs^߆ixIVb9gtT>ejp̀G X+5 d k~C)+DLѠIioze07MҀ>ҐV|YVQ9jn0žFx:`A(if2~Xwj֚BH@pm>RW̄~ |mbԃB-^,TEĖ4D(q=[ܢ][s %TG4{5z~orPmFDk 343'Wi=!Mݙ0KI41f9E@|s@EG$GǽdtNjVlZ q$x'A;r}ܸ3[uخ jsW 23Ҟ*O[z, Bϔ +)T D97uuucR۬cŹ-X/~wlUK8p/@F^R쩌\ Qq^kdF(!s2P0[ +&'ka_;]aD䄰M5SRuR6*863#-ݬΓ_@"0f[ NJKYɥpL54?ԏjORn)_Mh2n䕿miuJ`EfFLG@('@apdkPvGUrD : ཐfk/NdG;\3h|~/-;'疯g +fy9^3e24kf %ck8 wT)EA!n.؃(X*s#r]ˬBL'P3'yÉ] xphv#. 6ќ\\a 1 +&2=س0{Y[E+S39v[$0鲌JYv@eO羬"m6qɺc|\I2#äѠFbTx >HB>'+¯i9#1~t1$VQ^\.gB4Bip7Ԥ|* L5`|k˱<.v߯(4]V<+HQƼe*yئ3Lf0D7ծlB8Np.l ]?ɦ +iX F'pyim{nUJ'-}hG KlȰƺ h)7(2AZ<}rHJ]C- ֧'܎mE3k\Ѱu\磆IuxR58o  ZEEC_祾-o*X84ʾTTWTew*Hih]Dl4{vYrQ?jfĠ;@h>us;crZ;2 }A.2"SA ,C l4Ķ={3#ia%3G%JuV:2{sQ^8Ӌ]DZzHf +^Ű_$;f Ie], NOoMHǒ$X -?թcQ-tx E5*(ФLh1j(H"m,01o>66mjoSHVTBS͸u²p| +)7p?DsrSE=sn2[p̿Ǒ$ ++A:s$ + +^S=v }p1@c[\4y6 z5tV +{Mn.rIPSaPҿC`f&u"hon@L%ܷql5E]a%KyjM(cګF6iwTеdyuC hVh(RtG]>kxKƳ`+ *w,ՀqGqVK_t`<MZGΓe‹2) WJVƪQ +޲9 x; P)9Nnz$Иg%)W"SytIʿ=KeoLxW& NY)WG3a)rJ`TY9D\{ͨ9^MA+|?ﴂ|;ΆUIk7pb3ßGuאb LN.*m]"-C[3g E.hCBP[ ,޲T(pJw_ +9;<]sFvd9S4%w 1]:^ u.y)n׮n{&?13GE+ 0z,lՈgIgXȔskn\o8hP07QVl, 5u#ܢ/I"v:צSRHQsυ>oD" 2%cJ07<HƇ s xҤml6b@#VT4X#< $l/V;zZʺ"N˙h.[1yi݆~9[\6KNԨPa^${&q݆V" |XhD( ykB!a{zOѰ TmZkrla5~o/a M؈ O6(3+2I5ݲ+}z-AcKa92z@̮C1r@3AW㬅%LF{Lxb7!*tϓ.fsYӵuqk DvgX׫<ȷ#y(3daK@b4S㞃>5+a o}G=m.=: HW5 k|:xpI/b#T`*VaBYqG{>_l/IFMOS0=qώ#ڨWcs'S(0bϡà;^%!K*[δW%L2gc:2^;4I[K_;^Uҏ1h.5qOɪ#7yj y{w-x ed^sw4RDSYaů8(&e;KYb16zI6|Hn(Uyc=ƶNիe NmV6*rk("mĉM_ӂ݁+x&b[L +d">.&RMh~ B{ F@Zz%+8FPRU%ׯzu'y3`FD b>-@o.;I9GuǴN(HEZQ6\{ Jg/ 7WxW9 }M//q&3gR3vTyF {(~cd^5qQ}Vz{ls +ORX053J}kizG/gwidsdVUFF!)4sTW0eu=&w#6o57ŃxI~:-0u8t {lSMKZLGy!r&{M2GVͺRA&M;]v7Z΅J\&$V.E2F(z8}Hm/$}E ot9"Ԅ7sW@?bD$҆"/aѕܝxtst&e1Zv{Ӄ8i[^ԍt$qVKAS^჏ +C2C xƂ dz0eF.sݛ)HcA1*@B9i#I R,"ZIGBּJVlf^ұ\x_7鮉z2ǚS9~g r*ƈ(k}EGu_vq9.`V\>@T)@LWgp* {2Z ەwb0[rfSBiw'k"=$P2;=HRZmb9h:!Z2 I1äz l$ۙo]Mp(C[}sjUfML\ \r_I#(q\ t>ElEtC)$s9u"B˃(dGDf7 dVc_W5fhߵuw 0RȅHpQ+6ǗRYDm7A gGF64wJpl %C)D罟#xxu#xg nkRrmG-_{rD_ Ո+ XKX^ܴvIMe{4sb(25.d(j>黛'!>);ՆCmНm!6Va>"OHS%7A\b}Yغi:רܗ4J[ +P]׊ #׆7IG[ܚQL?'xiU{٢sRele'c?ή +Vx1wݳHcpJ$?Pb/G$oΊ!-f[> *XWr^}qsƩ8WaЮ#Г43vBkbo:S%2>~ Ѻo Э껆 ٩oEpYv] T0@zϸT`LfV9Hs1oրH+xmNVq3[({cck>~!Io$g!XNGj͒ ;E5zvae o֚ +]Ҕ` 1,n{_ +rEr(.U,SZ UgAbYLH=6{DpW +bGv %#FܗK liGKym[<>߂IR])E + E"b|غ(nޤJQ`U^M_JݭH/ BPUSbK ODչ>Ej;ߊPmr*\ndg EUA;TTGN^"1BBE(jNCcc UX~}ALM f6i +ÆMIaE .Nڬn(R],o<!LTY5*jpNk4uipT|n]lWdĻmT6#EL,j!QuɃϜjP%P bӹQHB:ɡ#@NB槞_6l4OKFo(6֗J+-Kf3L͈k ݰ7b=O}h)fMB.(wRc*00zVE>gחyW.3(?<`y\o(DNtjGc Tn +5oq>b$T417USS'_lW=o8ֹ%7_L6kyL<]TKe$0@G.:S&JUEBc CUPǢFj a^zI+ +ӈ42ZVYF( @PV4 hz﬛HWi?i@ܗ3^ VHV]ИttNփ,nEBsgd"ܛ

4Rac'ʜÕy.W{ Ex0=To%uXIIH$KHc0]J34Pc !gk}I y05)$3a(|q2:l7vndrvB)B5rFl2T%X]v™R9;n@G@l"eISG0Z^WA@^{HiXz+^P>)C˴ /j`E,lpLG]00B,R? ^&JFٵƮu}@:=[v(0/XPSXo5 )(<` #?q?r{Cšd_[.?#h:or_䕇1$vZaY4DFzuoiŠ8k.,#C JUzEB~4 "kvZfXI<:=* CaO@Y~~cLnߙP& +Ix֓-Vwk#O֊W *߱5~nU=g vGR&e5{L;Fyb2zc:x\+1Fzmx 45С+ u')#y45VCBO瀋&bcCњgէ@~d6+aP}ՐtiGD^X&S5Wjg3>F3U;4b@w/G0s%Vm*-hob^FyaGKv^ ;1=oo-\sfj@`UZItH'30 {՚%cu"Sn.1EGrUџ!iTECVtLdzD %Ul +8J<|$>S o ϙ\W/^2J}Wmb /aNGEKpD|F穱VӻkN,RӸ< ^[p/*}q[C<ٶF")6?rY3.޼8LL˫D;6OdkPc% !p{Uzwd[ڢ2%F4-ԩCbCnz넊mߵEE"~4]Ԥ<3qq*`^\YUKjó2]z@U8NvdufvAk*})< ]N.(mHp!-Ѷ!%oHJcHt)\;olp.$`zV`!cknseu'>P-%bi&@ Jͼ7C25'F~v.1sUЁHe>?=2Qĥኛ +b[kgFh/'튼~oH,_Nmv;Uyzr̭#Qqc Q9#1ixFfHnפqŚX=ȝs_`83JA%G 2j#8 $bd="ĉ;c)C`6$_vcK5bRsOvek+3 >wH![" ,й#un>9{3žFH E2y+ zÀKv;g# JNP _"5jN#P^x Fiϧڕ`%'p|“T#Sۅo s'5r"q&H[b$+vl4PMS֠ Y ![k@HY }0%vDD E$E{q\fg2lZox,v(##,_|.*ƩgÙv{-}uvX(5]j1qMBEtb٠<! 7}'`UC@`#MDcYٿFa4G5;NZK8#oa2Db**J_4㒺R=Z[2⍋42!ucX[4|W~gPAH@!M.yp1zj2?1PHP@)IZtٵֱ$, ׃v`/ f ZZaAo\GÁ>46l[zy5dkGb'-ƨt{P4`q'E&;w(+o%n7Kۆ%)QPTC6+8yAY-U A:'ygUHsϐCaIUժ񰼡mWoaȫV2%*ȏu{OsJ{>+"Z]C|e&5GE-6Jrig90)j ;6^% 3.=FB$u:5Xzc sRwq&)@dz-@(VXI_0k kh%6n(>YbSn/~E 4L hΕh[OOn;"p}m[=dk8 +5TI6,yPҠ1ѓG4U&o/_sߓ\Hann +zJ^*6L@+q3i2376oMYq$P|o/A!#-Å?,!`o]!^L[]O +_w*. X= iS4Rh\:iU ڱE)Ê.L()p2ڥ,tyֹ`QH7]a-,3 7ܚe868Ďnt/[CT& f#2ՙ&q\@9^b|h7T?0ÚYxɐYw^0K=<#9BRƂa?N $˦&Mxv>zT'L=o31IAyoZ/ur)G h~rr<(Yv\$) (Wެw{ iLI>^8*!weל?NFf7#o/Xmk>{K4cZ +Ճ $[8(T[QiOУź hdIEqϚ~Jr2J3,.|EkμrEhhļ 0:ȴ+2#lpDiox'hMv3q(ȟROaG(,g؎23׎4^p2+"``s~ms&xCG" KH69;AZj[`"{m[S՞%54Q;9g?ԪPD.G7Tr)e0>o 9;APE@z +db?اVZ&iߚL>{dk_C̚D:$=JQZ.S#B_-̅i + ,cy5ώGv |#.YqnzDwbEmNH;a|sE/+/F,_ +M5 }WYS2cYҵmX!sHTmax2=#dPtБ=`vpdi%PxWn}VĸCߔ"!|*xFPiL|8Ug*28066BKo9{=qJx;Z/TrƏ.Ob_;D[IS[(P ʺP6@73A'JДI\/lō@t?'@+)=q +Py~MZjrV=m1E(rж_4% +K`ckA?_0_=iUNr{`-&%]'ƒݜ33EFf=m(ȯ*}.o_\`sGI-MuOYP#H-DFVIN1Bq-lQ KvIBҤ^ Z yuሃfEGe_@)Bk<]* +&7lEi \// +@QxMG: 8+)H7"-6Ǐ))z0` ;HkpN !w$S9Jb){[?mY%-/ircgvH$SLQ#eo{sG(YIqc :D@؍ywI<&;Ei*ރ2$Lvv\uKcD fI7q%Is 5ZbZ2DK>s4u40qCn穁yB׿x`c2=erO_k>YX<[അ +&3ܓlрD7]; + o=vڃժDt +{ +3F" +RB(76rF!v{ďO:9ie0xx!ڹ `L@NG\.4ip0Q Mܡ}竾KKXeYh{d*R" J8_/y+{~RUEWWJFNtmJd?| + gɈ߫8eU +Lak' qȝ."Ju-H%hQXRfxPj6Pޏ@eTB+ŕlu8Hn̘hiK)h'#y|=p* +?K1%T89>M,-L3]4i1t8ݝ$#X9o+^;,kM )fvzNETCvJ4ԓץשI]5$BFF- +kuHL ^< yPA巽.ȞYόßv1L0l"ZAChxO I4NL'[pje2I9٬ٳy$ 3BncPn3]FB)Go!Eurz/˴Vy[3Vip {>O$d7GX.+ +ԩGN:t }9gdP!w(QHu>ͱF?H6د#m4SMѭRM{&-R^"/ ?5zD)p6y)ټ + h(:D9ۥf">%S:3#"S3lDuaJ9q PF¦.#; "}MG +@H+QpBU(!C,{_' `y:۷m9$7:_ce"lpyLuXs+80"tp;iI)ƥǕ +zX+(+EtvُE"LsXdX WFveu! @LrG-B9K8c<3`Y[ǜP-!kĒh_ )B%C47וKеdXdjjZad@ґ?B6y`d q =w]Km KpF씇%uZQq|)";!`@uco"@HS{V15XJ[HGa/raL k>SNP2T ڽجP7k^B?΋} z)T5S$_ p6^Jjb0PCD|Mmq7iV ?P\9 y\"~5 Q}EtT(7w5[0<75C:<AN1 +aϷx/(d;x :;u]jDB^7 6 /5J{b鑼Syf%8yE.TQ. +QеOsiDH򵞃QzpɌc"Ϳ rmx$R!d/G;H)ŀZ`'~^g:@Y7 QYtF@*V#P'`Cfʘal 3[! mAͿV*/H"}%.jgT@ú2C0ޯ}`HD*^Pʘ-CR%ǝv:t +G~Ȩ:WG1jZQ]tV{~GU턪x)\R5US PRh/W%P 6yVW%J6A;H,\֏|5F-h-Rxlj(WK೸hkGs{lhpW7c?|g" ^<" 5oZVߣDPLNA\-}`D!| +opg$BX,0T3IPGսا0KK᭽&7ьz^3 zM1 +]RuO^#C{jBݿ?BGB M/cxt;Y=`oc-SɹgPk,{@CÏKi04˳Q{SX4E۫y"̇=&\ 4WF ˾doXʆzr@'8$f:tLA(ߍ* tN\&j|}o ~ZH0iX+tFħ(?1nZϢ8f5&`Na bE8'|̱xXWPI(R-X l4׆L)$px@3r B>FyZ`d 9`wNuƇQĥ*v)^`jk/9N+8˕O*$"vlc 2q"*>:VeTbLZt?=` )*vN{=FrE +@({@$:Plo?X 7O +8 +ַ"Zb:2a59[ +y,:N&03I{D44y,#m-q?o(|fYj=Dž7ĠGS?iډ%mWn +р4ӵGf *59WZe0R=M24དྷ(y hD_z6+|[ +TR_1I{_F7Sm )\>jrЦn^eO~ĆPxNnUJ7iﻥ ݦҿ=hlE:T[ю˕ϸfZ?}өJD\(Y)lMzw`$ D.C@;,:v)Ne0;-lj~>fy1RHli9dTSn=lXk +wZhvEB5QY/x m8QK6Ay_ ̅w ~أe-4ρQ6HyzKrU-o.= +7{<Ji!:!\EH{SձA[ihol}>~k\E(];ąк 0*mE(OfU@ +)_4>~FK3=W"?SthdzWb31â-DurQP( ]/ 2V@l7+3f%vˑ؝%o.JBe-)I9N˂LQ+?'Eϊ#ג5+h:e'!B|P^@Udcǎi=D4*ͮ|ܯrGqBps@_gN5$7:T{~U F~h0z ׃@ +@/.qFӍׂ&kuгuZS +`R9םkP#.XW<؊DB5fSSֆQꮂO|p"<xԆGz{#>u5SA>=S$Olu7YX +j <{̂r;O vI_W>\Pj{%$Etftu٠]|Tƴm^hS@2umo̿XZ0 endstream endobj 77 0 obj <>stream +~{BZ7y΢R,a&ۏm=\Qt\egA ?D )w\;UD : YȖ\?N~,IO| ۑ^v=qrfClI 59sl80e|g响ׁHr14 +l6m߮p -Ihv1ET6E+z+ȱ[rEnݍ2fBty=Ng‰; aAѽۡ 1vpmji::Wsxn(=QֲX)s'4;M[JNq[ϻh6`n{3yJDgl:Aq@qDO:E!Q ;_n5h>=ߣDYejݴ$刀" dF kJKi,0eT#q:j"tًj_H + $3ʡMvwLG !<^Xǁ9{حj盏EMHۋE=,Q"ddYI^|ªcPAl< F:D̈PhĈy"]P1b+ԩ$uuQzZ6(4D~|ŒT-26d=Gw!OK )r:W܋ T𭻑Åu9DǔO&&BR*@]({XbН=;= My {pp!'S0~;XMd-I&q^xFOLꔹ!L/_M}0jڑ'FGu.ރ])ׄHgYqn{mwoSPDc]6+=FIH^4ϩk$+Y{a S3WK6{lhg6vp='cb $ (bORkVC;٧W$O'CNYz>6C!k<.:-㢥عt}4 +'ܻTGlC.Vf(\rYGƱq|A +=V90cH~gQOZw0Z|,z6Q!FoQ2Bh`@IhBjLz)gbu zrTĖW%{h넻4s{Y#ڨ_Bf3952+0C.InjNu~ X'a Ǵ(+W kRxOD?dR(RUZ$Tj+Oݼw>gq]&1ğ%GgLPvgc)!A q Fstؖ~{>4mtwуJR}Cл#9BszZKP+ׇ\(8MIbD0ES ܜ*!L2mWC¤QťoPTkVA6ݰd]iUH5V\zOW26u3Zl-RciE=ԭ+kuц[P-Z+Q,=K Q$P27v2M?^Euّ#^19#qIbCHg3v[ hKfyi#-jH~p,I>ȜEs(g0 Xm*f[ߐ-&)k![sЎ1,Qy2|; 0w׎hK3~͡ qK +rol`a8 HY|wC +p]C2aa"${1i:ă8͹n:+~ + 2CO$#`}5~xt; x.J!&͌ GiI(p- U;%ah=|2SBM!fH ,b>mvCd|)^}@o|i9b.~^Vdi=r 2J4*) \:,0@f  + jѠ#XRt^KF߳ //ʓ%l)B???Ͽ_O??S\O_Ow}A{?;cϭXa\eB!sfL}{(dGrvʹ8'~ k >xw\Z1֑(d@cp$#2P y"""ΐTNJBkJ gb{ޣdOD' Goes@=@awTc~:y:դOΞ%q[բ%AhWi[b #@ע&hsD>ADyA"ǟ$0&+h1HO#ךf(S|(SeD@y$b̡cB~߆YY[V\kģx@bW&E:=k<4mEh%dz4hB"LV+IUԈefϚњ: +;' +l"Y$/p ۝!K;Zz+1Ӂw(&݈X6_;BOiFOJ#JP!Wv r4@ ONP7"#`q6{;ڙ,[:PU;gPY7%}Aˠu +HfV7½l,!PΡ~:@t(~@D0N%S1Pe/s5Ջ +v ~ͧa7jlDâo +PxB 'taT{6D(!YX  IEmP^~i숺(I/`%:Ռ/hU鮖8n{𜩏ByiA}ɑP>_6IJVM 7Us~)yrU? > +89;PNiVUh 1Zb0aB8# &iӶkjFD;Fٰ\V^b*g:_|oB\yQ Հ,f#sXh{kj̑`"_JqIa |r^fASVJ9xZ1p;r$ W90(PcWu,<3P= Q9 stKq%Po( +/y,wO cȠaol p,eWX&C E},Exi0Z _o#C$9U\xBT֛ +%tvviZS{6jp;2D !a|.dC?J@e&k$ZaTO8ۖqMSH"N@QOKLfỶBrϦjM [P-1P@VFq5fo IlX)\)~! X'jIW<aD$NyQMS\y4 ݎJ-R]Tg_%I<\)ca*2# tKǺ0'$TmQ8c#GlOj@~{ZS"h^ RJ{`*=lv^"ط)MQE4ʈEC~ D "xnMU]jT|=r1(S8߈Pֹj"›GWax]bPt|D5xy+}D=!^FKx Ff*ZGJ*NېF|FD57Oei _eb^P  EWȸM&XWPDs tt"bvSA2q-y=R%o4G~)FP V>{, +^ zw{-m)U4,%!9jlCiv[V{9DQQH+s.Jy^*ֲMZN#]4 2Jo.{#|&1{%*Q6\v7Dh#Q0TWDhQATx#CY_1"jHζ=$z +Xk-Xf9::b ۏrPY!.IR.+,^OC9xbe2=8s[$-zF~T&@'W)wJ_GWc'A=##$y$~eaC[S0_6 3V+<$@QԵ!CR )0M"wF'ılm>N/`VME~>QX N ^TyLb&`;r}?eh;*I5@5ԁC_#"4kEa6% յIG6؀/]w 6_Z)L^VP = +KEz_g*X>8`ڕN +%&HB{75-YLoǽv )h +BYF|qw;o4#$d~)y>CV?J;i7{A{}56XpAk)&$*?{Vo= + {_ b|88vNEU\d/8׮p%c]8)y*Ŵ ĸc=+pBh'CW?}UIfQZ8M0d{|fjyfܚC+;z +iGQ8)OuųqVLA0(] fIM:;Bk{%yGɧ"FYUo*$="eLfUߞ9oSfFaT:|F|8 +WՎ@TmZ/U]]P +naO +9_};@5|sr'c3;|\ :fuX +;.)oe_y1j!R~7oBX# N[|hP[':vN)*HA/|YUv3?rB'v`DPa- S0"˯S4pAj0_ 5< + 0t,Dȶ?6"1a;Cqe]MR>eڌ/IR9!3:ˈIžUu?"Y?Qposi5{!ж!g6۸a[*%-G'@Blo{{ȟRkSKZB-Fgѐ.ص!˵TtTi\YeUKH*85{HL>XDJ1(S36{O0}G +[,tխqEʻzPqp/ +eDwR^oD F$=/u+u'jg %O"ߵ7*wݒW>՜^#8A D q4HG g+jH.Lڪ\tCҥEXճv<6$Mz^t(+Ȧ,lͿ&ZϪw2"P#vkܔpoA3z::e\,h;a+lF:jxX'Yqrśw't[R7Fd3X:WEAFU{pvg~1 +2T3*b(.[KBDA@c{ + q<0zɉs1QPe9>ElǡS;¿SiaV5v_h84 > +L qVd57MB!ьܤr6DBQ'q6x웩`ip=e? +pGFUėG|OǗVkGf]Gۉ©>4Ѧ(Bio zG)1;"Ӝ+((kIN b(aąpB WtBX(.fƇ_ʾUbjh yD%JxAԿP^*vG('1EHiC+wncsFu0P֧dZS۵%E'FCّfJȿGCWY$>V +$ 0ݖ(SXSŤӌH&i3gSSCfLZfI}Y"@d")CqNx]%P,SzD^3U#P!JDP,;ו,1b)@1bޔQ#c hCw1-m! @4  +͛=>"-@GԊբO}wu^2zb;{$}0vX Ϟ)=#["P&Jx#> p;L7%چ{zx.bAhRg}pٳvf_l?f +2\BS@f#*"č"jDdQ3וbDȫFC*Yj 4 a'Į͈:ЌUC"cgWM͌B4aZHv#$A {*?#Pf9~?vT*wT:Yy$?u*+AuDT69ߏ-t>91ˈ?Xo$+~ʲ>^ +!Y\k|Ih{eC*C`ӕ)u{]o.jo&h׍Tj q6LlT#H]|/3zyk z:L&('.h&]tA)JT@$)^Ml]־@ԻBFep\DI{(8PU(zD4[="F]s#>\i}D%\jfgL@xޞԃe|uN8S[CWPlҧ&ŧyf!GQ)SvN7Ɂ@ FW:}9} +|A9f a&~gwԕY*G@C[ٯo `b +^~""0uԾX1`9(wb#MÉ #В0  wgZ MG4{g ،,>[(ͭ# T)PAޣ{Řq7RE!(g)%MxϨ44~4wyW5&Ri}aO>Ci +`ϴGtƈXG~FĽ +HHF{5Mb6$B|3W˺}ü ҵ`%fɑ}2]`,z|5K)Fi t}W&j<輤Ե6d^\6ber%:W| +:#S]N?\ +B 1aTDߍOO P=^<) +4ۀAMtGԻ}xAAH.eWrn/nGV lzPTˁȴ~sG_~愈`u-!Z\ KmΦڎ`(4?THL>[4Jͻe]v9kfΕ`2'vbGaOiV+ /(( t)W4~mO`e9ȖŶcPȶ$m;:3 >juXza͍Zؾ/Ԩa+6(֤cva[M& 1xĩD5>#¢$d|+.l͡JK_+۳5.f*uM.DTZ.;%A-Pd G5 `vPɛ='oSUTҔmíWwTqU 84u]:+ǝ~ WEwMIfz8?sVQCJ,?Pp}* 05ԔmK +DCP;njpsKgHfV0'0ɑ1ЙJPCb|]Ԕi//0pܤ?GĘ6F03ω>Ol%CZau(u8}?P'3vxCP Sw|bﰄHN :_m<:_> +ED[OBͿA_r=Vyh2~:0|痜Bo1#Toq`F\q2p-@ר(@Pg=ph ZVȮYZn)b5܏I>Ȇ:6> ń1#jޓ& +x_>' vOA^ 9GxxpBs* JUF0\o'g hጭ1[c8F('U@ +x]^\;}b"ѩö`=3]uBYɦMGcQZz_T VKBJ PX 2# U r΢ڲ|8N+=pH! 3ﳠU2W:FW"eU|-ܚ.GZׇ4W"=OQӈ ,eG;EJܢHwbv"/Q$NTyIk9T3IGHRZl'}T#tw.Do)DB_hEC]N98aeu>>C~K&M@.B r42Ph|rU[94blOM+N"{299﹩aoOt)ʣ,4vbYG, 8 J Bu~<m,}8 +<1XP )6K5in i%1 ]-ˆ |xT䘋ED!ʧ\=>"*ݯJ$D0*oBj1㥐DKgV8:YWk89ʼnii>W6 0壚NA54n^*/CUd+C 9g+D=>}fKHͯ(֌ORהN`+D9Ek2*qD6uN4{zJ™ +!TAB;rY9D` )Cq!Ŷ_ ր9AE.ZJdhf+ $þ82(潟 }lDF;%TOcH ~@[gc/9}0jVb3\Jt:U%+!ɂ[v6贎YCW1WÎ(G+Z{˖G; +[[/9p$*16nHdT,*it9 F>Þq;yN(N¹Mxa/cdÿJGY)4u0ZiPA4zk"#Ui) \M!PE2y0{}eu2yicxi, 7A97 8f#̴V&IyFi" ƞ  +wG ׸=jL<=[Sq`N&Jq"H>qR)#RWPҒadMH%X?2.gDj`a[O +ɛ ++q@Ӎe/0K; +>Bt &7#~ NLM3;{*(A(h}Z>X²e" odMO`c=$H񨦺?Eo l]Q4{*/ /]4{}f{ +e)V~lF`6VG+Ȍ8hv{JV7U&1딠uXL }]<Ȏ |t;ĐW$=>=!syY"")LO(IOzWX {@'B)4Sb/JwŅR|uËgP CuDvbfpBᷪb^5c,ܒ-7[=z4?sl S }#7O9JxRP {IP.x`쏒0$GQ%¤+<`X4[׻"sB4f;>2PDkrh*et7_ҲVxh;KVvG *~BzbQжyFDTU)'B↉VEDze<2#d0Jv`X@>%*ZI?! eY_lOl +@LsiC\g3>Ҧd󌦪 /2N$j,{H^^j*|0i65!2$aw'Yb$ *nR %lCtgQAM]^WfU7$\f/F3@hh1jE9KܻؑpoLW:Yz#e=(amYy]2]-p{(ToB=yF=*{҂NW7m8bܢ>SXzуb_'(Ems8 p;Ho'?0џ+wـAs#Esarցi$g%$XλBMSy. QJ_KC".j#DSN˖?+uHILx'&Jџ1 +Q3x +W#*FP&"cy2VS!X;PcPئH(o*gUf)D+pH?@vT~#:fa$`:XAC.!==v +"Ażn?pÕ2ZB2I|ko>5 g (_Rea=9u!aPlpOH Qž~A0V{]1'8H<09{E # Ǎьk +/ %J *t:sl:jb )2l\T1~YsUəή,2Va>:qdOYUr 1k +l`b}mP@YL+Kb+_e퍂E +Ëx.txT6S߿~sgXb1НtC(GLʮ R`LˆYYIO?Uix픔yKJO+0 +Ʋ&Q+PXI"T:N3O@GyeStXv1h=0 +׍`L+4::$7k"rKPY^ę&u9 \,Nb fD9])wDA#|%d}?I"!Gdb(\ጪ&+^}&D_&#]aA,2 Ţꙏ7se3)HF**W"q[zU{:%}O4@: +>͞󊣜ٯW͗` ۃqZv%ƁkM%%%\&{wƲg#I!{#7@eS3읊 +XLK#4@ zqE`+vBpGbOT`͖DY +9C:z4(u.rwE5NJ_@tT/,CmfK8(ai6Wz04f]D_ +I ž%JUn +C^RIPx+(90VQ=`*~!-q+yA旐)/( *SBըQ"]OK*|LS"CJ}%wuZ;oTu͢LdԃVQ>KRS'(_΀ 5׌i̭pYn)Yެ2tA\*_ȞȼQַ8%0ٲB "bYRLU6 T4LJZ%NmAgJjw%`aWc9d/-eyIǍ0}ejJQ/+'׫_B_T^ey$ȡhXA:YDo0DP%"]J4RGTh9S|O^6`3X6.َS)a75%鉪Wiꂸ>F6[ jJܹڏ>CrFF}O:E &, ,]v v&Dxr 2,UUKS?(A(phR043i`8<X!'#D!3G;t[NX-9w$q*Y1gXBm&ftY0*Ne{ +$ +nEGyW1X#txɯdzr5HMx2 SJ 4ܖپ Om 7Ieg0jjTG$}>5V®-{@8 o7%)X@+%{_r=]̬  }' M,!Y ,DG8%/!5]LWD\Dxse筞]:> +LLK5z@C;|R޾᠀ r<^vDDeFOsR}'G{ n#^IXT߽5eD{2$7Hȳ#LJr`t^W,)DEٻQ**@4gg-sTS^6bzuEs(Jf(b.}F LBPq9Br;9\;QE eh-e@*;b &w2!a >/Ya fR7h]SΣٱov +UiM j2qTZ{p³_-d^i/7J Y *{gp&½[Vƶl54":ë*!vx @eN2s +F~N(VQj&u8 ;†Ul/:A#,MD qشuk+"j!|}5:2x; +>ψVE>xl. . ݎ^Kc W9AӜdGXiQFyˑM)K82P>+)'Êxqp`ͦ{/5tkV67ߍϨRPcNcKgA4_A':KX 47=[܀f9+8X&~垲?#5-d(vz=Qobz8hiko~@XRHHȗsu5V iLy>#͸~yw{{|FD1犖 QuoT'3S 6AB4O1媴F Qtdy!['R>35fl/ŠD(I ")!u,G!v# PՍd =f+2@p-F  c %0ڏVicv$bH\Hfy8} a;<]IRK>8/h>oV\g#n~4KuxB2:Uw:"7+oE44!5ƕ% Ubo?, ȍK5>S#eJ ""p?sLI /S?7Cٽ@YQ 5^LBPTy80!$$JQj4گl$#"QOMGZ? 5%=x3R37K!Q=BaӊY@9М+Ѽ'u>)W +MDf)JDE_<(ܮÜyڨ&a5@sD`bm>q! >ϡx|ulUZ1_q"h 6jMhd˰%۵$[ߢkZX)Q(Sr&I[BX9.~"k{ +Q3BP['*td8K5m+6 嚎i<9.&H%4:"NĞr[o axdm(ӼH!5xf=ҽR D:()zNF~Mo#fZRG:XUVԳ̡F#U~Zt<Q=O4RQJh9sg W uE+41q~vqȪ{9Q A<[<;o`OϿǤvݴNi7%.%ڊ> |S--'NJ u̍N(WpO{/'jJ+$I+ J wc6eHwx6=|>aARʔ+bfu_vƥlyűĮjo1N} „>! +Aؐ/?#T C].f)r!"]8}V H8b m' l两yjE8J6O6S +#F]bT5 83dPZM ;$xLgvUQZ^sWGriu.֏ .y[MC6Zdm Bʓ:SZ]od_gð= +z,L승mEC01"B#LLvz!&f1=@-j`EX6O=/#nFn.EAmEQp@ppȹ}{tJ2~~Vdr9K} sHQn-wsxwl>owQH.@_v7]{)%ϡSrAQ8?.=q_i^6q:W?L~;6n1NT8%ΎY s\Gh27# oRhNڡZ iu 8Q3KĜAH?~sQak2\A8Yˊ7 +~4(g^yHa=WFl㉔x"h F)9)C2 +xftz#{c,Bނ32&x=[n{>!#}Ħ2<_/Xԃ۶dş(mx`5e>J =iz_$ư|€ۓt}ȞuoW JlfF -"M<6Ur~/}UCS4{bmvG+8 3(3.6!d@[-msWen,э͕d&Xjt (+28CRA+G\IƔa?&n-h S{*kST%5qCLPҵ&1:JCCLߦzݔbu]&#v əªIkkAe)]ݰw#T酪䊨9(J9M>;1Am*qUOٍ1(7Z2=nGjIw-ל:xι΃^Ap,? .E[OIxnlIފ0Cl8ڴ]7CßZOn!HCNאzPD񉚈Tƒ6%jU#D{({y5=-bxLmŠJC5 hzV1{H"ez +Iђ;eT]jAQ03Z[=6H?mJTxPizZgc3k6<-R"5As:ҮuϏ \h0%M`QD(b^ :"\cQ+~Q~! g5WYZƝ}<2r!/|Z(j:zwẄ́Hc1H1+)IVu6 K CLYJNATq(uY*r>Zw8,׸1@r@&Jf0ืu Q֦sM/=(W`DlH+"S,#gAoԎ3:Bs*(H&je!\DdZUր k+[Ij*[ד6n u&ѼD5 "-֠=-ۏxLHCb?j=`]smfis<N-Fg/3%:ࠝì#Bu0x-I9ޣϤTkW_z!DcyO/zf+ V}?qPF> Gq9>ߎ^?HE&*}e}QQ"dO~@ +²LHhGn :]Ղ~p4ُjGĸbDD,'B\:#F(?".S DC81W*|X꟢\<&"4z$CDZpGhUs{k_86Cv*4:Y";aw1*5tܧiHY`k,L装~PzLLa%d,CrYDZ ϩ".ŕ?P3CHxڦoW8>gvCe9|yx!! eO33ւ|uonr oZsk5xg:zr<1<`@y#ȑ2+f,kO2DQ%<^+yn?"%q3`wΠH(:tB"}IZ܃>#㤜۹sGkR6wXc&f_ +:%s.e|F`1īѯ..yh?Te"`fUഺ< Ey9H2ke)7eU8K 5rCYź#atHsMi=x4t(ԏbwńTfIQWm3Ho#YTB2iM?"` RꈮmW*R$W#W a$h lYÄ[NĐz +[_l^+60NKۃZS,@A0 =jXѾnzžzx@MraG|ȡlD.s8<'} y,Td꜋ -9 "1"3-f Z V}pAܲƧr`vN*kN)ޕ)Ckj  7wNxd-#"m+O k3"Ը1NeczDMEAsߡ{#GD␨ +q>&5J~90{A\u!jPh0,|Fʕ4, !vDTM;7dgqЀs(z pRdԁBr +%V$ AkjE_~KԷDo"){\NQ,ndHvpPCz7|?%ԝa5!/{)=;}ԝv>֮RN{DEjmiL jWj+ 4?#"T$RוKǖDNRZw3#PovO\fCpGHkynVȂa&*.wM#xm^GEZyh)UO B;gZ \4ltO[י#zg޿Ŵ~Mq8s4Pz6¤ ( +h%K Qڃ7L"Dt%i3h"uF4AT\柼 !p.Hw ` qPZSwB{,m4SٯբQ2Dž|H,khfEIW0C%TM3d `޵[{uȪxx9^l3Iښ<;uuQ]ÊL^kWIrNy'i8h;_iR'5Np8;{ 4NL(DbE@0VZ +Cm+ B3\%Bg-6`9U2uAHp-wC ֤gͶ#G };lon 6OߋEnCMD) ]mpKAuݽлpϔXJjDBrNmS3X*_^s;PQRTg+n UՐ'm {ޝ 2f|c %&d\6V- y30p{/m]va-V$>DyhrmgMHZx#T [Z^GhbjrNerSkc ոhx]>}ٽ.5*T݀ n'!\wT^{4 4yrQP'0"qi|]h&[m5b;oVSffYy-ݵt +xIi E"Jr.D?cdF& Z# +7cB,RW3ȝ_+qiz(}op6uEq&F(!މp>hC+!*Ԭ[Fw|7q$#j_P@[tFQx=j"(,s98v_ީV~AV=sx׎\<{2$é{_QSG`+icB=cTDڟyl撚QÄ"x]I rO' ZzC_M2ҭd*-KM:Z</`Nfp")V>$ȭQ;hm/L(|nF9F*ĪC4b!f +]#he_T_.[گjEkh;Ps971w"Ƃgc-9䭪VWc+,$QKKB7/D~K@L$fSZTnkDM3Ϣ֕( % yP~`Cqw""x(aBִ쟔ĩE)W*:[Nό➘!^ &eMG\U-s6=yz C8w-&tmog+w)euX!hψLy:9#mB67f_U9ߣ„\z|RtVqD1˕<>C\oeWU3xGjiS5=?Y>ԢXjtxS,Ҡe6 ^e#ZZJn#ةLfv}(VM1i`BGlHE%4yL}jZw7J t_k¾EhP<Ϥ”Vm1@L뵭sޣHMv&(qX-ax)dC: +.ӯ7SJGOQ NŖ#?ؕNnE:Gt˝m\`%Sh&p;W*4ـ %Y~A#ls5lρ1_|{Sr;=է#~۠BSǧº&3$C]XkWIYex8;H4LE͎;`\I984?;Iڷfiy"gm`F"p[2W=4*D&H§D-B$Vێ&;L+KQ5JwʧShHUsluUs](݇u̷6x,Jkj 82ӧ :Wk2Ⱥ#*' +s$Jmun60pS%|/ a l$uQ-01;,q88Aʯ!qU[At xcVņmOEpJ|uf,-MȬ k9 :W( Mʚ0dL*QuˁϝYBpMX9oLU }}b2`5YPȂ@SW)~`iY%'- cͶvt18BG+TEDt] ETcT# +uD!UAT*6{67v,U>8T#Բ 6=6yHJ4A:WGn nPIc +V;I +vD\/ߚ(IYeK]#, ]-l!@hVbRsWMXJ3zw. usW+S#ߛ '_-5h޵1q`ն Jsfwz%R ]kd +9HA~ cdqeY~??7f|CTzY{o/Z"<.ev}K+: FR)_k~"NUnr]q?)7J(7 @ŧ +xưMGJ<̠2W ޤc}&>!P"pM[nE_ebV|W >T$;"W.Pb YD`G]G^Ux/w,sO&ڂ޾GѼm#xUh p z}߂Bymq쎡ꠘpo3ax D]N3]Z!ͷŇ*p%cSqAMQ^4 뮂BwsGQBăP@{ʖr>1y#LtkC^@5P)z#m +:ZmpH"y b؃ /!;'t+zQ\ci|q7a{#qEVdž #5Fj[f#UyQ3˺7u(Ut:li$תͦ{wysR9IJG"xގoрhWe ƍE1^3 |v|폳#KoD} W!W^?D\&J +?Q )"(!S)Ft;W2a]Fj<WW;ފ˅)by)w)Yyjt\RAn9GhM7ðqo,,9S[ ރߴb=^@UAm kx囈E9(%2Pͤl[ߩdE:EO,wī 9 + ndqAns8c&SCqܘDL +vA7=i CoS-.eU֒%v\H,zhT\5XvlB`>1{43UwQh ج1kQ;:/}DnBᑃћS&\I"7/x`,"zn.}e֞ l{$9&!(Drbzm߃IzKy^pit#b܉@v b6$M/aRtT9ePJ{OSŴ^r_hz'miX56 ͷon9yϕı1FmZ糕>!$7<6v?9vnc ITLThSԇ^D(W98h Nཛ@0l2yl` +()]3YYՄUu2Vk;Av3\(TWb&.>[%0Bǐ2B1m'!OCKU ".-FI4o&"zmW0sQÁ7&Q2[!:3pZ~x +9F`t!Lw{0H_ԠCEz&1NyWf' +ALjL^׶T׵앺m5sjhWzBJ<4D5\]0*-#`kg[=:B] \9fsc=ݞgS > +.<Uy3yӴ#9&@^U07h_\7]~Es̕\35U0s< 2űltƝ'G :<@O3Ћ[W!/nЬTsckk|uLIoVz@ZkC^XQMmZ2>YQyޘ=:okWhȥɭ/&ʎ_Ҟ[u';׺YBR}M +6ڙ(n}WXTʚ*󀨅k7Q~vAj`zM +LCD<)L q@>6p^*G0+e &xw-'}׆k;+]* +>?x4 +:Ts=\"5ZI8L[rz+d8[zUwx!Ds#:y9=>Z/vns f'')B<<~L +D෇ JLP%&_Ck]6¼zʲe6+WS̕e.b@WExȖXkrS`Qx=,_jwRf^܂_Pv)uxg`)z}8!|< WTH0BrMP Q@?(rCw,Ҫ{ V0h%11PKۄ>Չ+wty5l`#&* gܜGklְ>&Q9kE{ +Yѝ7m,|:#GTV oA.(Ēu^D,4%sMrׅزuq: +|bG.T[[!lFT4֓)D0` B[{Xo)ړsm\M+忸D1G*}MwWЪ؎sc,3k-}otxyjl~QYJma^^3V n>jWB^K#ߩ%V%*uk Xea1ٚkx^<Z}p-&W^ϡ3ы1I~/g4= b]rM`%|`8 "Q}GMSm +tn~R5[La*(9$*-'z) +MwF7D. +]@>2!XwWI(b3X<ǖ'?!lt۹0."*7f4 +fz7Ih,aEbY!:8Щ ?ՅKhR͇ 1o7 r`~FZ)0d gMT`wD`Q~mH–jOt!:;sG kFDL/%؄#ޕE"35,B1djى9 H. }Yy$^PyC +ZSݴix+Io 1*NIH<QB/_< #yء$Ս'bs{o&*X4t-q _?膴@g=GmKe z}C ZV}lEbO2[ģSdGZakEA/ +\9HRM)Ʊo-[ADIrx.LL3ȑ6١ZWG1qu;ҁD3ecOB$Y5N}/L((0KiKh !tVP!^ZI涨P`!̍R6JAgg) ]-;"!b*@ݺH193#L,)Jm.yυbm6ʧs䔹p~@śҏhwE鎃n3_u-6C`rDB]7=Z ;NdW Q=3a@[BRGno*ZHs\ľ}P +Bmeu/Fʃk;Ō{S2Qۘ/+i;Ǻcg۰ +[ڗx[ Xι;av]#FD{_kknEv:qސ*5x7u.w[k\D)k:VJ:d]窥D*ڡjT:5Lz/wDU?O)7舺 YJ{lGBUc Yh\FDbYMDd&3j;|s'OX/WBF_v}%f7虅Bm#~V @8)p+cTٽ8kGǝ:Y,/AfZhv+tl hډ_#$QU>1U +כpH$#GUGxrպ.YgKSws^LYַʠۥ_%s+"ih*9vuA\򔁆B6d}ó(xqs; uwyگH>G?ׅt6[2Kj!AS-QT:lRy5'UDz4xQh#̅hPMLĞ;Ǯr 3 +|wUa4#(ଶM"{|oW2ZeWi@I UMUg`b~" mՀjⷓ6aRSvm^^i{؝dn'eHzF~n&`)3-Y?X_ht9w:xm|u*aopw@%Czդތ>vlm-%'Hսs^ͩ{ZaԌ;H5~OJB* b~|/[bwXcvt+Y;>!}Bb. ,۶Qe/a Kng@/m ߊz-/m|"(6s! ߵ#(Oq_W"bHKCo&JsWH>/ˊz +C? +/[['B<u]G)f6|܃ܞ*TۡF[Ҫ޸v|䋆5AmDLVH5 ;'!JRx1* ^Dvt&H.p" +`$`<3jG^-T \ +d*{mQgfw5ift^XՃEV[: f} ' :;1#(!fzhzwA螢O!Քa4.KȎ˙+8 >JW0c#$4^lJ!ӆGZQԜA2)2^AڃNxĭ#VI¡1CۣmH@d=@D󳏹v޶x "הzZiJ5Du6 C>SB ̮p-mtL e.VyM﯌(e()^9᝞'Z{C9(T[J + lHG12͋:zgfkE +&eN.,6aam;fXϊ>x7J2(i"eAhZp#e4F'( +UEb-&&À˜)G\W +t=\ӭxwOE_I!jN!)#鍲V>hoشf;-,KŅ!S.P+,+dW4G ND +, +ߪRA fPf p:S•4;0yP$aG1WKDgA0"g`Ɏ̧OpKhM$F\~]& ەm9-ya֭+$IFBB=:;<ӏTnc恵ޓ0D/|*g%f}[[ER)cߙYO9p _pk3̔<,+*2~ݨ:rYptVMΟϤtRظwN@2,K +Vt`7;UN&T9 L*F)ZhCwJ_$P[TyتM?+Zә7pKr~xH GpE݉7D"kC*Q"-,_Kml{br5ùQɈQ-u@>YӅf~~ 4ZvDfMʅ'%[Hw{fnfSRɹn7L{c`<̕>G:I6RLDMyVn|Hz}$&MS\t_ tAI_; H8RDD#0^=л Ȕ&&sީΜǭ$vPˀ! G`lRea4!<؀9''NY k8ud?p'9KI}_l >POGލrsP%; +jH ڪ^>l!􀥚b ;sH |zy]IR,9TVnRLlc^$ΐ "Hv`-4?0)Ɩ #؂8oNe2)g8+ySo%G^(Gu/WG(V!פ݂.,+VWɖmŢTmJ(xLfTbCh{Sl`D#:h-[Q87,HP}aV$m|ݛ-^DIdbh3[|dܼqASc4Poܳ]daw q*B ߥ'7NC#Tn+NjoK,Eq ~Ͷɣ\לlh]<4\QH`j?'g' ܥF9HHmA\~m]!=%jߢd9)_q+#9=E}n]1@'| +$Hsӱ-Bוj%N2Fڝtz&fQrFw&ymWqif <ܲšL`{/ tX@Xd c!-&5I")1@n{4hT7!*Mnw[n`07i3 P8=H톽[LSrBfCvss%*"{% epyF([" + N +<á,v+,T^zw'ns@[ W"! 9wSQ 1_\9i]E;|1smL<ӵA-E74QZXg풃Z<.!^& %9 Oc*3& '`KADjEiu :oR2S*C:0cBaO#c+gW< Xq 4| +GUA!lވkw=Bȷ /9~mv#.Gk<Ʌ5pcgosA8OX:WEm\ΑT7훨 ~ #y7 >G?` ܶڜ#6ӥW>uxWFW@SC+3ۡUjv4@ U TӔy߃uIB3w5w|-ok׹F!@y[jKDڍ8iQWTX>5&izTD@ eX[`"Ĺp rmia[ׯ7N+xeZK"2FS@7YrT(Z'}D168$ԢGfEov]7j&ːbX9(^#/f`b޹Y0:kJmbY6fi}EkdrޓarV(~-m #(.ऒa$W)ġEˣs9 &Eq=\хVo&Bۍ^=%eۨ#W !m,̕wJND@TzMw)2BB;yhp^nG1 + AX3ZS 2XZYh8\#ב"'nx*ŗ+n$ZQ/[oGjM/4MQxLcfv+YLC4‡S.jE7Y-wʦ&nwh8Iarpo5&B2̦u7?~J0QߝpNt"߲ׄ'(xK\߱m)1A=Լ.y*>6$~ܭ,|GTucJ=)-te:=(6R6ں?z8V@;)w yLi>YSw_z/-C]]ӅTCiRyoB!%fM5 .n3ƤvYSK87Ԩr|2ckؾ̕"KO8"ʫ[wM6|lZÞ+C6f8u(Z6xƹ_nW#4#BB|MmG@~ +[zNeckZ@1^kW{egQp:6J*Wot=nBpSCNzZRr|$jJwpÈlscᨪ}.e֓a|4Kk7׭5(Cӏ#bO3GAԨ:m@-/|=y;^Y4KWg/> 0Ş:&HQtPɑnjī$(!Gpe\C>C:ж<- ) +dX~"i-"؞_\no0V`bvn\אQ#z+k_V +D{Qv:`mɎ%Yf8Y[[sm  VR׼)Vam`.{VӸc53(6[{I?PtX{|~ϷF1Rb]d5 A*5ރ@jyF2Qge#6a;+ŁMç{Y,xZum B,v}#O [Ж1J-zW6g)LM'gU#)Wzv+~gJ;dڢ}o*5>H/ow{t2寴w'aDBscY +yXKל]s器 +*d׬?Bjl$[xRXc??N%=N똩X"1َ8wؠ=sAВ_*uFE.;XEQqE'OF񛡋ǨB^::/x~m8|.TUMsJ +dB;&D}/$6=gdM]tEǖHu;;ÏދT81}u”Zw1M'ΆB +28{{ ]T3t>npn݌c r pWڮD%#B"W9JAH~uv<[;|_t1>EQ&"ny$<>vƥZZT<GY/Ь =\3mFIIQ9j@6Cԑ *|cx-4GL:Bg(yB997Ff+C.zwAR\NGpG|Eom)a`xH(PWDxQwU_p-@J@>nHzɝ:UVj|DRQxPQ=ZS7bgDx"/A_rdr*ȼA ȈeDV!4Xjx10@ylsK셗^r%뺨1޾>kGXYAy ٙ8 Qt^ G)!Pm] 4*MA"5G # e+<w<΋}dw8AVaxۉ^ǑMw|V}Lo%= kco\h0iA264_@X ;-,ߜv.Ď,5&̒߮Q,(1KbK%p 1iuۉ/mR/5@i1 eRH:|pK5#^?JvGSt[=7}(-돖/D+Iog*(=AлAKdo 4 I-M7{%ڎ?/|7<&;Bːc>;\?}oda=xJT:<9ݒ6h\ˍ$ 95zx#NF +더g} 8$bq(sG.)o@cNn9.b}zW戛Q +4eSࢼh{D+GF*S()Bw|Z+ F$3Ӷ5SҤWj.i¢DVFy{gG+$3FML R9@FX%UeUQ3urdWR!4çQhl., q Fr'A +y6O\&$+'C}=ccqt9mvn&U[DT=g4YP$;TA4+&smr2Bk0D⌌\c@|ݮ2?)ѿ9L fB^ּx}'IwaJ% ̧ajgԟeD>tv+bI_(j? e(DhjF-쒉eX6| +v[#,T[![>Jfyxv(zC ++?-uko!dH!`!4 |k_$$ m\Pb"u(q^dw3 >h!~qtFDnh17J墕 4iRgDVsk7ECmٗ8@Qd 5n5 m,ih8Agvnut=5Hpt;9VROKt +Qv rGng/>Ar7RM̍RZDeb%7Yr^ cҟz0eʈ҇"lPF[Q]tB("|W1?axCq@]fY +j a#iQwM3MsƬmЩoIDGڠψ-uHKym[+`7E?fvPsJ)o<:~:.-ܡtځO7vY + T\;ZuKǶ3a(}+C}3T a?KP*p +od"^u-^yDem{3#0㘲oJ*Bu3?ٓeEm CZ^sD~(2gs3YJ7\<qU|tA7=paL@QC7s8/iSύO3Ds5_?x0)Q.?U=U]Ɔ77CtI&_j>gL);<(~(~ R@pOSo{H Rlfe+wD +u+e[!~m1T,Mg-|m =)d PNB'-D ޸O,,@[)}$/,[O j5XTRVܡh@j}/! +>e]82,?D&bv%?mʲKמ^/:;+Y"+Zs}g2[Ru2خehU<g@-Β'c 2%dmEEwESXDBUZr(y <ډSZ%(~0y_*k=H>^{ 6W' +{ NzU\N T]#X]Blkzk=F1G ؊3 Y@Xc|;SHZ D'j+>4bOܢ-R j^ok-3.F4+-JK$N-@ԈMDw"֖SdعX +E|=Zxt2g6tsK7P׶T7̐VCr`mlN<'Kmn+'Bٮkbx'Fϴ`/ + += p@lo_ˣDZpYeUg?S|]b 1Ad_0CDE!f ئ.4uG2NƾrD]Q| n0%#'3zƿ1M-ӕHԽق +v"}P=(< ƣGe3b4xo t:KM & Uz6Y}zaF^J7Dg+]TN1hUx$::ZP {\yMLquo"\[vD_-+!x]ýY-pZk^X LC'nH]Xs<ѫg w3}l<*"nSb"Ym&;aX\x]` )ZFP5b8cO1SS;YgvտB6X,҉rp+鞃u#P +Ba cQ|_>A u?7!6K=:XϣY]t:gQ:=."oC>q~D":V[65]>95TVtRˍQ,X.򒁭,趼N 8E3Jé_-IT: 3ӽQFv6Av&8&_Sco*?q^kt|)Km! oDA;Ϗ%>kmh?nYwO4;Sb xoZ2wrD"{'v!KOV[y,X1eӪ+M7>D 7RJUg֍6ƚ*0^<@Oy҇=fIa]5M{+ӲQb0;XHkLwFcR FD!~C97PW4n<]S.߅C/u$$KkG*qMG8XC-]jd^DЙyMHEdլǺ"w[o8JŒGmDQ2BNr Fkf@ЩR@ip _2 1XxCr&H\ID]C4{ɕpa`t F17@YzE`%s~qiPl`/V;I34_0:qL!vJBZ|d(il&ggUg-~_2# (7d JSO͵AѦ04Jv~g"sEcڠ0\_gy_g?b=&QW[Cȯ׈j2r};.c~s2E[d:bt$Nb~a]mįrȜr`LPjBY@yUˏٟ$}QҐX ڋ]Sl0ɉ;&1Q'Pު=lq/sQӌ݄FM+UyψKYL_Q?xG9UiroZ:x>QʫĚu*{ZSkU)R]b41=hѝ+%:,+?@ R׵窣2|{ٶFiXwuĻJI2Kmm +9ͥ^=Pw+VQʜ<0jϛb"8#@*x44֐]GID?(K4l %}G<AЧA8V*Qsp5xOJ"+uDa[3CQ٠_U[)֌:o{3耼ٶ}AKz㻈#6~! +>G$&zzܪm0]^qlaFok1 H>c}wh[chkT"M>7ԝǧ/i n7fSe|{Ա]UPE.=O?>ThD;CO  oC2rvP"xI"pD<5f! يI=-ͣ'Cx}j<2bw~Q߂/ bEh2{ eɧD񿙋e2b$H+J|y8nZT@ؿH:ѹk?ҿ;C).ѩm_G$yhI6gT8LF|pqnCV2VFȀs9sޣ3'5=]e"iV;iȈi?Qu 4v?2b3+0"'YU eeM k;W*b æӲ4 1n_;{ +e?:Rn%fyts_hxS&\SJȓEފŰvY,}JkB +09̼!/Xߧm?hԲm|Rf:% +1]wG< 2>7sCk'Y]_vڥm1[;Z)sm߲kXi}B8̱U?Nkq)Lf`-FC=} ^pg6"Eٝ[_O {,ӉBmPaNZOw7/[jϼ]@P*Z&j{.)=]Ct8‡\4,? W A5EdA/dnu+6qY#o?HBC,tYWA 3YT$H/J7jSk?<%ta?ssOfە).uu:ev/J1n\j6oyIi%VkMC1CwL$ׁ+giT:8)g/Ĭh y[ +nHwVF7wQup1hh?#΍4oNLJuqf[z"\JBȳƭ7q1 e`' f?hQ,ob ɏiXa3G)[Ƌ +YP_p㠼{4a%nj @OSpQ@wƆejm\xhUTp [LBRѺ0E[DUJҹ((-󬌔׷HBcV?#l3b" բEb(۱G]=ˆ3_ޒN 1YQ&2 0HBp;w@@(AP.e1,,$˰o3~4ٶ6  ܎;)H::#aq'4[y}ZyFR GPN%hOĂ'](ѝD`cDr_WJ{㎤=5fN=OMƣ+"~x%6eqe47E:9b/#K7-ep}d+o"F4(Ps]NBU\zd,R#`+AY#DTٰʮu@%Tod%  f'?čה!z'A#wآ r1my.A!adYb Q/%7!ouE`EDϽ&xArP%_d/?.ah(04`D 茭A+SeZ?BK{f{~ 8k31>"){[Y7ޣyF|Rq}="WDRǺ#JGCZwӍkS;< ) +;v؈kNxoV Cwv̈XꈭQ|@d]])#ɾ#qr@gʴWhWK +ʳ*hhqDKu@Ȳffh}hi@My@ ͋CL6u .υd|hi4͋yJ7i[PBޡC֣䰩Gf (,OHR4dp`(XٞŸz'l(Pqyf) )(S) XcT„_{WN} ɩĕ5{abC wAkËZIkCaAڈ׺9?#R?H-<0Pw8yqxɤ0z?zTr6* ㎈92~-bʖATO؛#za5yĨ ЪMIqsKra;xUCgxv"Vs;maJr85 +#/^%WVWRXW<,Ab2͆!5.tf#=kt[ +Ug] +ccr2[e@elgd桽1F'rwx7[Ukή(l^9ff~#x"p^{samOa7z2SF2F!E4bTsu< }Єf1eIEՠ3_HSm`/% +qO@gM39n1ʗ*҄!c',g9NoDxtHvF|cx&puEޞ + V>}ZeL޵0 tAňeX;KՄlktG!RGQx@!_Xd]ްَQHȖDzGJϪwMm"J8OWt5\MbT rl[K|3}em#+7uQdAszJaqS/4 g:|4|}Z%\E,""WUFE>|ZT)BQ4ֽd|(/в-ԕ7 t:Q- ~`?}x߇oWWaBZx/Ѫ~XxLG,Ū Jfvֽej.N(@QvtE(0_dMc +_+=^¦!7 R-UXQ'Bx|/pCˢl#46,"H۩.Y9T44[B^Պ7ʽPߩ(X4D/+ȿ!ځ5)1K,۰ g  +[Xkdu1`$ ̮n8 W`|ͽNJυWb9CZ?fXcPv-m¸XO.ӪQ_-dR30"ec:EiZ#슈^F|ҽ0p v~%V)lF*o9Bs͡rNz]Mn[RNg:b^`Q> g}f"TW:ZD[Qd$Lr4o](Oob M>)]hVR>Vv> {Ӻo%8 +L=Ux @$~ O]-OH{iǰB`,SiCQ&2\5$RFyZVE,ۊ\,L +xG 6ew34K9U_ (B sA[7ɇP;R2he1M +x.Du!7U@d eRz u-ڢx.76(6j2+`GB‘XX͛)Eg*1D{yVt8_)pb,CpTPQrrW&WiQ?vgS贬k"JI(cQjBb{Y^Ic/ R: +~.ׇv&{N ޲9ۭ@]>xMNll`bO`a42,/Ip|NX6Ckȫo5'B!MW} +zpgH?Y(;{BPaMdOedt/Ud洀+];T5`L>]X5:5 +7;V =Nô>S"L0X +tl +*OBJ. hc&\/ebB(ۓϞ6Zvo zW/Džzki#ߎjYŨi}jcHإA +I)((t +CG>}gyymw.^z0%q\iIЛ؟o_( +C ut4o5E,r LpTO6K`zfn3a >.Ơ |N [ġwBO/oyN7D4x#YFM.^%Q{սu[&H?%2lɘY5 ܿ|O覧(Ey,Z^O&c>J!d)+ 59%ܭCwAa^w2ބڣȬKcoLũv >?-_CL-n0InsR_8&EC.Ue ;}\3D(\<+"p"C#Ѱނ\ىze=*N@tP?! CQP[f?SeE-6=f6 /lFqU q2^1?,+ P( C߬I{kzR&S)ExeôFG4VC!];3dxPƳ rxDy4Gw> +).MA`AO)E`ݕ~t."ojD_< ++5Bdʪ8:?ӆE@_uZ,+%uQ+C[8o@QhQW28j/إ:/ywJuuRXi>򙃙8]౭+ Ydfl!ezՖNJ)5i53Q1O!cAo +j9A1~)f5*0u?/NpTJ'YgfκNߠr0 ]lpO9R2Bgm?jI\KɞIk>:3<(K%x w-[ +@u#Bl}M,!n<p/f Z{SjC0{a?vݘrTQ@7]ڶ9{M2 //vDжy;jR?ya1mo-wp £I=r|.4P=^LJD`԰%vF_iNaME-Bd<īǼh5)qC90?JPY, 6EnNt˺Qu#$"dRd\`97TGP`rUFkyiRN5g>*E%U;Qc{TArկIvH=ۊEZoUشF˹3`OKr- bPƫppSvC #&*Wd>@iƫz3b{\zV2Xvfi:v7f0;ޒLH= Q`*0>j H9"Ls n)o@ +P[<uëӂjd-(JF˃jj5"g}u~4#g.}B5'k {;OJ697{tS:"Pϔqt0gP6rԌ%Q{L*0ȉz$#yv +1IH5irݮ%l0jN.ElУ=X)?RyMqp0NFW}L0H6 +ܱ`׹1Ru?Rg1}Op0鉎_,}!pw+/ӈĆNjԌBXQ_Z "FB +ݍ#<փUGX=^(/4x.OVYgtDl}5˨%g1k$7!".$N{S38?#3 +u;dH$+u~if/TS8rKJWmCONR!C~yǕEaY>;a~wVɞx]go+ +9t52afawRh~һ* +"RąT{@  so۶x"E ba"mkԟ,ʟ\>"庠cBVj5Ĝĸs P˨sibljeh#c1ntFf-UA|{PbO[`L(q9rau֑I/?yXsݪ9|Z1Qn=E@]-Zye2"w7䖊 @sxt>eFבقg]aK`i?_¸*b>n!cLtۋHTŞmz2Gq="z{EXЈt&V';ۼ#ڼ_ C4ftģIu[> pf=Gəeh*?K5Ol R&2å-_P4)7f 'i9Q+vl飻bړ8(E%䆅LF-bֽ'zzr{ +|x@ WQ3 QhSΙ>krt곍nOg˪ _Be_hT׊pմ966g+gTLj(5/h`3UR~tq?q sWY^y=}%qUPP+L$Px6GPIX#׊MCvdRK(}6h v}8QۃE5T}]^JR*o ow7_y`ΙOJ0g*puVd,9ܳ/Q>,Qi?\ydnr1Ą}UFìֽe7%V,Pt=\^LQwrLMḦ́%LcDQigR I\&X[IP6%zz5Ffu!@L:Kh=GFFw3>. 90$0V/Nm_& 7ZtHa+A|bL\gF%twxky3Ϥg9{i̬J3uFGo( 𑈎4l3/QS]ɅLZs E\ d‡?/6OrA˭dl1š>D>[^PfV;Ī e#чŗwMDxf:N%7QEyi=e&g1J_EKج &6?9tρPԌR5Dt?s}>Q7_E}<)aE!e$րDxMw\Y݀ +8QFfٜ툉LZ@4>ަ^K/l*G}r- o뎩3(QTu@/ >O +O B%|hgN?DDG + 6HUz"V_'x,uhXbn# x /cݽTGI$ |6ϛQHFVzKا Bk)dn0 +3"BH":h.Vc_ݩP}͚7~7DdfÂ:T}9K$ K߅C`ɉ55"Cz[|{x\?o]|{鶇~egi+$!BM(6e2kKZןM8JC`ek]K(tM^@sڇ{ Tw\@'bt:{`t[i9agWqA9{yړԋhos%UZa`^޻G, ij-ōTqv!iu+y>|#4o@x\xk!5#i)na0f`堳0#'M;iKgdU43ZiWbqq ͦhߒ݃ƴv_5mЦPD\n9Oq_('"ar_9^@Krƚjg7lu# +531U^1㰶?+[Rǫk$6yo5ʦh)]n8{HIy/AMgKAQ HDB F -S4]A >%Pzi"O(}'t3C;D_fdg<#| +T)NS*F#E:P-ܼ + ޹da"hRl|݄"LWq43ԮOncWnl:aXԳGw΢!X=t N%}-"-B|[uBjA vF +J*ߞg͓Q%$(uR eɎ>6GgHmRO=,QӜ+@CJ򖵕j +W'joom-ɊNFphEu`_vj)F!,#Kv!Dz ֛Uӷ(?0oGǷ;~R@505[6۟d}FQzH+׵Wbg|_Ia⛷: &`h|Oū#mQ+A3qb%" +ZB P]Sk;Wt;m^e\50>0(S1aڣc:76kTsfd;s8}T5{v!nAu6S%)춏&ZxTH"U' G I:/'EOp5hEAy.'&f\r;VOX-7FHpT~- h~˱ +:1%9Q]ݥ;꩚ιtۜa@BUV@x&:%GY<$~ !ǨL) ӳiO&I /ణ= +㳓JI΃CXW&'A YP&z%%(pM,{ h9uo)7C4 ^q@*lQ>nmNPG%?PSs``jֿntS䚖CBTɐӞYK ~; >9yÀg~<)>  +JVrúncqE kO o&'*0޳ÔG`21lۈͼAI@l+E0'!Q+|knXS&O99ߣK+b5-fzdAU%j9x]L"s9ghb'ĒS`v;ү0Bs_|0󯢓xgcIr%"cZs2z_> 2! K^tK_?9[- )=3Y$wG7IσT>yj%0YhYob/oJʌt=gFJ9pk(ws @G:Y!G/ޱ{#)7]9e-%M)ܦ/>&%R~JcOv;E>R2s珖wWoRU 4x7M|&l;,ºQ + 9WD j,O]76p@D{@䯄X*'xSr9G$&`-KɺyJusc wudyWP9`C܃C[@]MW$4TNv2) +.J Hsd/UU +zۊQ|+q'zֈGQ+V>y%~I$R4U7 p3yAzШ-a~Uk<;Nq| _n[5HaG|G +-7.rKWPJc?bMS=%hNvDEA8bPJIȀ[dc@c6JD={O|}_!gKVoPPYeA[ܻuA2SboQD7:/u#:y"BM>"͕3ZL22At4hy'`{G^G kjUE ͳ~r> H!sѸu{t8jm*|s{ܨ'kNk琰2ޯsQ֧FTBQe<,X$ފ& 5?'yk1ԘЃ}^ wA(XȚ)2ZHŨBifpka 6Hq ,kFi1Pp *jF}ōZ}6:\0 vﯴ Е`3B2c[}LJѢPј鞻H}2tgIKqZxds(*(M0^nծq3& |œ!9DCUcJ=.IPyT[׋b_#[˟B<)mUI|~L0snFH0|(H xQ<@zIy. }$ TCe ZhzգPאG˯}ŊBm +- wx(;{>C5B>>MN_Ȭ%>MQGD`srZIw(6#aXh*9N@RVUzzg @nt*O$[8.HeO|\M̢7SICUp:sV<:hd? ay!gɱJc9@mdr͗K-UaAɲy4kgЋ߾9^|yqCDF1jz{>wjEo?Q(  -P誎c0Q!͎;E}GY5 J7.+ A1P2Fŗy{ ޭ"BRk$ d՟³ޕa%m6`A'̈<0Ml#k1ujh`PɭSWV-X>7V&/R +@ M,qX5l3jHG8oq=ւ$ӏB8bfW,?mEQj1=Ŏ9NL;RU?}oNSb ^".]/e!}^ +8 _^GaY4}"JόQk=_d`툲sxMk#S(z9E#,Q녾O,|5h=3ܿe^_߲n.%yH!@[UF`6|׎sS|A#`(Xy^~GO|JB]_-BWAIՈ5"LbGF tVFQ)ʯDbJ%*5υ||1rJԽ1ߝy9ݒ&T}F!+.2jT+RTx +`8f%,b%4~nE0X7Z-_xVw/Es~B 34p&i r{2uK-0@ fޝSeVMDG/Ǜ'uݑY Tyť3='bDP\Bgb'vڕ 7pz +S}"8"Gy\Lwz!&ٻ[n8#NU\ghUHvK~Y f} 3+9T `)V>"WNzaˋk^#%q*:OoЌly_鹅PB`53Dt{Qx;i3x !0 Qf3W6%԰C%`1^:%B6 +GDmu_K5_$`̾goګ/X$vGݯoگAO1XU ħo w4~9)H+Ö?Śo֠i\j- A/6s5|npO;|J(-DQw/~kÝp:CD&FNGKψ0a@O$soò Ӌ'6}TK3/Pd(x(~ lBs_/)ЉW3TE<ެ܈_S٦T k:AJ(8W<}Pkr`]%l>n7Þ NwQ8ӱ"J512RHQ(`z=61{`[V`.Qnd%ٸauNF:g \d:^ϓ2}eSRln2Nx*pߺcO%:fLp&~'Qݺàf=I^߁_<*`wA2]0esF(Qm69j媠lK R +:&l)&?#¤frYO|&nBv 51HkI:-{6BJ* fɐKY'h2G5^'8:INNJTa+:̭ܴFy,ֲ0՚+o1x5#YǗhv!*~>sd+ +g{lDO2CկꭧЕE Eu.hFuj$Pqu8Mpҟɻ\^;_FU{ endstream endobj 78 0 obj <>stream +@i@ t=ȃ _Y'fBXѿF4/o V~'W9bg(3)PD@5ɐ "YUOJք$Y{R̄)R {*DF wGuvs_"r%'wNrfqm1Mt):o(޻ j#% Mׄ~Wz[@:c㶶5FSD& HFS}Ǘ?712Q*hřa[hhjBL Qe_#ĺ*kh߾9Ocdede\!3RE 8( d%H3ޚx.`"_"-;@$6F:5Mi[t7򺯎m970upի鼪H9HƑV@7íݽSJ{^I"v P͇ krwM~;">T ̰M2վ*]Qj v C|.ỳ5|`?0t5WE@A1EB녢ml]$2qVY +Fmӿ\LtSl {N׀?-5!svQ~ N7zo~tdFQ%KMy.@46=}M}cqAY&r:n8`qNKƻO>gS5Iښ'6䇆t?Q-Kgs!:6hE8+UDkpρte +gM(+-$}Es,hXa=Y2%[<4bFUoDKX#l:!IO$AvʍE sG,(\OD0Hĺ:Lflg+y :D敇)pX8,o:hl<42>rBYS*ˁ]0һwv$Dmm FWYD S#$([n6ц&ʢkR#QU:g4u?(a-pޒZpGI3EsKmW>(8|^֨A|NTm;.(QW*d| "@HyhR\7ǻ<  +Mۻۧ;,XmAA|A߮!GC4 + vNHTl:òAē +@҉q! H>Y9@*'*v쩤eqG5=U}  "' +r6l4k\I\ےrnqJZh2  iA>XE'H"(+ؘ!Y;`ZwPͦQoUļgT=xrY<=7j`Aez߀Y"bfi*)$>[64;9shޡsEa|?.$_\I.BgOV̐_=+ _fg~ϲw\<۹0gUP $a7KH [ق(py|9(\׹J 1GGrA~Kb4鞖tSUOi|o""#/ +KZ.! +DQ_, VVy]v蠧ƧQ{t%6:"INC΂h39-X畲Xv uzH&&VD sOD/J"Ss/.TDh0kB!Dx"ϛ>Zf ft=m1 OOt2%S$ KNt/6 {/T(k}9eZ*@[\/:O@-^7|({v'k׈Ϥmh7<>Q>-7t@)<߮{-p rwGZqv11υnP.뎠QPӄKf!9pݴ tBAZw})h X +# j?~2ܽIW+iRC5Cݨ}BF:WmZ @A" Yl2_2Z&/B= tӇ +%0|@lnȁ!sH%|H0X>{\|9I +EtG 5g0yK9S!Ƹ{=[֌VG†)slw L.@?kDP6&kTUWN;^.=.6ܹҗG_]``wPŠPLC@X`E <Ì +&SC;eC(=`x%t5H +"6qp[eKnÒ^j5hT.kIA/L&c5UjT[U+RkAG- "ޭ<v9:4I/'U_$F!#$YܦU`翳U:>-ԠM(aƤ J"d&f0\wS mռ&S)(Or(@(n4+TZUx;)h AEb iM?Rb׿=&]&0*_#ГC֡/Q 4N3t &kSDh&矧NG1-g{=Ԏ;ylc! c'/^ x)=wBjMCv!joH[BrdbDڗhō(:u>3Ďg/6%tѤI;l90A0)5BNCx -ݪ{ K 3հ%\cbJGܤ::хEE%Ч`ED2@msR+?RW齛:A@ȡU«,4M +in~2l?)K=(rvfhyg0;5#k(Upb RaQ :Waex7۰ (Y Qttv~*P7'°#l.2<(NAji0`^^s"~C=݀0ov%7=xWTFWjvTk OՂnSD\wN\P?6mt;˲R!DddO ]P1|}eF07R#vo\(|! r-9mMwi8L)qwB+f{@57An(s@I =,l3(EeHmگ>Dl&jf|WnrHBy?d q/Yٮ6Os'x8A$:UTJTZ Թ}JM0#„1'6`A޾~ʡL; V|J`Hg{ğo.@sB y+Ϝ;,j,[uZ"@\Y)Ϫx9.ĠMhSq[o*L&pqtw:.gj-,H]MRQ:/Lt&JԀwK0BVdCy)iɢr8 +'Ͳ!h:}HOǘO;3f  ۻFJXxX#ausB)H|B +B\/q4lVe).0͹ hl[ʛzٔr8Xݯwv"cRjvVV:, +& u]7%V +_$k1c*Am3 + `Nl027wc4Z]Tw= v$ˁV@L}*(O&Bm28iS__;m\* +4A삻%2=% z61uIci8|(sr KwwX"*6&D1&?%]d`=;b8~dj'vMn0̜8 aY!)WRI[C@ȝhL +QJ1,T(Vs +xpJhE_4 +{64єBMlAч-'Looۡ'y+/rD1$RV]4dʚՏzx +dWq5Ȑy!.rD$ʇ!.x\۫<wo?HoiAg @m~S]O`H6 WϦtb{b4%PIjBŐay, \m}d-5L"dž},EV~V kǤ]d Dbh[|]ӣGƜ؊-{wUBL?u}pQ c%yŌhmM+IqK~h9J `hM<85f<2$XzSΈ4yk +T^,G#\vΆXݑ0a!wavvPe L*ǒ2|༷,W7svvGMPڏյb(J@~5ȫf iD| yY1quC`zUnWĮ#vU#IA:B:J,ϸ{DY"`伝;AӽcA!/#:P$%>[k:(zI "ܴKx|@ uC~P2H9b-vvh|1{x?+%V=:ܮ?`Wef]E?[*rM +BؘBvRݦA[PἍcA|ar<6"Z:eAuI( +GB4O\IvQc/W%=j(^\h܂-Е};@oΠlQAOw+LL_~uH=.V5~B8UU0>ݟv\2R5כ0kJiՂ(^deŶXCoP{hIo4jfRs%܁(Lߵ(tw6˓͓JGY Kpu'[A_TծժvHŜ{6#ʓD]>Sˣ珮粯3#kY_F2vt-<~ ND {XBMcݫNyWZf9 +,2f8#3\[i_āb7XMУ&~ )rre-*+ZrPuu+:#}RC5dMۨдGP=NՍ1!F Zɬ|tVN%!—PJiӗP賚Tx,=TcLVN"}{ɾ\5uƹB _fꙶ_ce* iZY)|0s`_=x +,# +i~ }.,x0I]ߤ"w <-QJCiw$TKSw#wb#Jq"F"F s%9+`%Uy%/#( 8vnQ7;~ +=a0&`fG{3EX]9K4_ v-7 xahiVe=H/lA nO}<$ŕD e:j7nOm*YH|KFi tbhQMq|"Ax U_eL)]MT?SP0q}fj;pܻz1J/Uȿh/`o,|%,_׭Y$KXnXxlOE:VaZ1XaԊplU:pqY5H{ONIk*:"gC:luvІE]Y[5ɜ"'S0E~\)QGamza"1EOP`S%1ukȨRbI .Pv2{^J}tlc-΅9t}`.Y&Z~GjzGLbO5.jLعKϧ}K1Ι3/fTy/~z(Y#ҳzu&nb8PP/{n{Q m'H C!B=:)Fd,&DDyQD969d8 )Zɳ@1̭Ag⽬"^ŒUxtTzٞ! +dKR c&+]MKv#pV S*sSRJ8gZUPŧ~] AbpY)G .tTZTXlZG'NYCs>՛^&JЮPع +T]Gx䡐^`VꯑY\/S^uE -tAKdu7r`mP.oiwrؽd^Q#9{9| wNn KHQ])@7ki~3z0 h 2`w0y8w4C1D)c}".άP3FTڅKXN5.[NnpFh{lH[omC*u%@m)$8_;}WT{J̺Yw5Xnd`WHXsYC6&J؋xhsNԺƁ'Ʋ#؃@RfE>,{S@uzDF;2'1:L# LVhjYдNYEŨ{e-\edAV5u1`wۊف+k(k;?*Sq%ˮh[z`9P *^ #a䦹w)N=8V4a_1+Qtۭ*<vJM-It< 6Y lj4UtaBS +|Oy)6RODNu/p= u7parH HJ ~T74EW˝# d|"Sj/t҇ 90]؆Ec +iB/)V֓zlVfddPĆu1jcK`| :jãt=R^赆Z_lU a׀LʗpG-%fFl=W$ + {fGL"Z}`gD%XϕɡRϨ#Rj)H; Xf#vO$uv Tf +10pW/z${JS lFIeAAv1}! +{svL"v*:Pը5$(Hy7YWdW6PuhQHZ2$pk’_bVeLI9|?Z! +~?v>M}߾{3y+Pd~Gw R6 } +T7?Vn\AP{(k5}+6NwWJ%d'㑉^vpM$=/Ԉ`_0^`[V +(_<) /+?$Blۿ+ʹJ` /.ʊ,P35=v;~;9yIT#?U5aLԭ} ww0c:o"xs5G|Î*vM);"n/He}\2 #%]~Q2si 0e'3 \Y20ɏԩMN7MEgT QG1C*\}5BNBu N +g߉*m]\r%JhL>b,0{@NZmfG +ᶻM]88*#|]{u=*=SfTщ׬zgF) a)։ɊU`;"t&/A-fۋ={4>\(]vS.K" O DᕎxBй<ߜj(Y8̒NU"׀ ?H̯Aݕ0}~M_EX+>瀧# bfRxJT IEYQc]ُS Nzg:Dfh]a ݜٴuէ1jF42cM s=ޫm>lb$'O9a9Ūs̳5PVmߗ뀅J/VwZAhQ'N*^>}kpCcn1ov G9kt@Uf3fu=VqB; +HCGpoct%~W#.,YRG v?~sP/-$N d.]=Ҋ[Vٔ )gIdͥt@>3g,ǎ^whh/n,yw(gD!.U!JeX*!~GfCZ[Pkl=Ѣ@aG z'RR-ՏJ`,x u[CҡK$1}}˽ H]9 \@ ;Ur6x}E8C)ÊЭizN`3sMJϹNbiik Q94in[tq┴}_ilOC͈/vzTW4Ї'ӓz%t5@u 5 WK6xoW#͎)?tos{*aED ܺnZn!zTl&%@W5Z5aqIA}0?ź) zIlC1@4"-;[i1UG&Q3}N*HaT>u-ִ/]t0V%u9 Z@-kdfW^Lk>d}[Zs .;k +:>(xیcct<*ژz?ZRo,7v>+X0:*y"5OoBh^-PԱܦT>vN' JΤ/o"jݸlS?](*h 7d=c.;Jg,@mnOi_CkIMq^ ij6s+'!xn7od6H|;7lM̅*0ƆNNIdc+Cvv~XӪͼR=^X2F vwekMkr::J\?u -1PbO~VŔii YtZfGEc0(S=> C) LwLDoρf"DA&MD_VM:Ԑ#l+Ħ#ՈQ#..$-Plf3\,) Z('8±Q(G+Mg11]z*wRzw7TS6EChq+j#W`O{-?Տ{Xp[l,&@ !eUDP;C6U&+ A= + NGHvZZ]y͇#]"6A8ڥ1ؾXg"q{%ӝ1#wFc3&E檜WkU'#D]H)B"es  sl28Wv5 ϶'3QزBGdtWTUMѭh QԂjLG"}\I u2$%+9@AnS^;"eA蔏R7\v]R)}aڵ lH;eMMXk:xtW,tl6JSlVW?r-s2Ҩ$b+CttC ic%2SӦUy ؏ӆIAk%4]_df&޵;3y\]cI_#i \Wfլ LW$xg#HC%w#,gOpB !=?AH2S^F&וb ֣UύFH&LM)l1I0eWJWg~s;kh2 /6TKxwf4S;lrqּu7 [q&}]B|o{-#&#Sg`XhxuWktC ]5@M6݉s Q>t[iu[&T 7fĆ|1Iq2S??F&Ԍ.)<$qSEeҢJ'zn`_)Z .PLS2@d0Ù7@7n:F׆s_BM#Bk}=ʀ׈ TBNoNIˮvɯd(1q=HSw!ߡZCgU>^߅gЪ</ͅ\$5.UM,g!6Mqi%EuNOqM֗N= 3ȹUg2?[fHs/<[̛6C aGpl+u%D./uy +zt"vtFH2 )l:7Od% J"AZ̤O-}`KKj7܎1nѢFaMUDh8J,z}M\DK MF"nr@9W;0^ܒ[f2wW|+. +f'^{Wj<6C㨂Bd9:j۵`(D w*!|J\&Pg0sH=N|]A QK5ac(&qx<]ۗč_PUahfi 6G펈P}] ʗ嗂7i[$i-2z/+7āq?(CaIm*JMXB+pI ;PpUQط! u7NNRtGLғB+CNX.9$W~NG2CSxAf"-|/EOi1Dwxb$LLnbG&~mX^mڋȧ?*#+5g_ 5oBh{\̹ C[l4X_k6FH/Y=BM>Z]{?}u.K kUy?jŮD@X,G"h=WN2BJZnn!""VßVWdZiSU+* +<h(R'D~e]ITA7Kw"Kh+|ʡr5-xY'\Oc]7SPT@: ,(wD/DVEvu%Qs(*\IHT,p7 P bl뗧V D9];Q K}-*U'.:D^ E*g%I@Z B<*̧mݶphQĬa-FwZ,C + ~šƔ^i>_-/wzp=. .^HA<wdWbqƞcp7kp!^uחte"3EFuWDS +F3}D4L+2GD\kb6!Gw7Dߦ P'C@눘os.ݷw6;mdلM,g }y&QW&=ͫos@XؚQH,Wp&S=#‡3|xG 1t:foT~{tݐ3Ğh +uX Xf2n +XmaqId 2XJ۝֯^FTupzG> |@)FK8ȠA]4*mH|aZXDOlFIBEs|}uS +oEd}R*Sf?穦֊@,rǑ yڦ4eABQRA{@֒xEjgQJS(oqekYdv6P-"¯?YFٙ*T.ǭ8w"BCNztו駈.67˾t@R=<% k}q=M4 "[sv3i >Hq0Ҟ+St&[٧mo2;WM=^].-Σ Ȣ/{VVkV<@r`rtZi~ƫfW֟ 8s Pm*5IoX/l=bb*UǷRf)@l,&)sƵq(!q+Lt-"oɄjQ #EWR¦ +PVgJ!|lu v&ZSDAͣʛTMφnztwR+M +"l³~Enn~_P+P{QTB rLR|qsFFf4edMRӠLC Ӻ ?>^&EE𵎄]aW#tkC Ƃ= \&rę 4wPk5q ~?p4.b̲evqȧ8|-CrFl:#(򶜀 vq|j@+[:ь +zG +}In.!?~= z z,jSQh;]5=$[BH+B}%Ή\tġPtpn B~ /%bxOBy)2툉h*#WIV)ؠ{D'b9jSP3e{w1DHvF[+Y7S +P +ΩIA#ϝ1Sisò$x06Ζ*ιmmcoҺkԽ20PM\vM F2%#~?O17߱oƶ&~:S\uD\vU$:łGDշ~W2oVNp4 +$E.pd>{-CӎV cܺ+-v}v~F<۰Be3sOŊ`}zX%lyk"UCl8ԬPhdAMZ*ѮZga<#cfMtAǨf,I˾dN%RN9Pd[x^/S_t`S +7 %%Iz1e9 B]ʳ7 e0+#tH?8J{Ř]j}8ND˃3gܜJDK?x:>[b'䵽>$ߨT1}A~FS3BVaiއE5[Ϝ3õ% +aEG|66ňw7VpG[v+Hv.0= ĐvS\aPbJhڡHQ䠚J EID7Bb|q)I<_(TOf̤w]VFйXf۟aMG;ċq5v:#"ndFWm{ޞ[G!E[ֈ +~^:I +/+& +@8Бb:d=Liˈ~>,%X̞6h=c@V +hǩziH+Z4R0^F`,%Eu驱bJL>CܮX{6\{g?N݅Vښ9iq|Nˍ=i0$Tf#ۉ=*&]1n‰ܪxG6sl +Rb6}M dѬV&U58zYTI}׵ ׆tff@;Uhh eV&:-fu t)ZX٨2L[-CɊsFD'{"bׁKخh&u)$᣷nQe32-w\J#$v=j/=ỸN]GCTMYL`D(sHG"sъg*z`GP.*=G SUv~{/F[bܖ8a_ҕ+1 ,DwFQu]sQ.*x?JF&mD̈KhuS`DXgPUQ'-~WD,>=<6 sPtk:نSvu({t+A]Ə|#_gc`ұfG, Ft+V?V|*gr3ҳ K\ m)4#c XSȤBW]η<ڍuarx'5 + *"Ϙ~0kG3~#Rl%(ƣID:&vw~yׯRߴhX‚$#!Nn5)"dR;QնmZ24Uћ&uɎvcv 0_- S( wԧ$)CQ`2TT.)V=M?>#pҶ@Ov"=%_lK~%h%خ l/<ܧ WiS\R:0ނsP-gEoDnVQO14fyPJ[Ē8ࠦH/zuĕ A\\73^u)i"  Ǭf*+*%Bߪy=l$h(*(W\QQ;%|Fz\"h1-@:$U N)1oO_ȓGMLÅJlC]_j*\m1fþ L|qiD]&*:?EA4ֈYJAPj-cj߹ +~&SPPB*V=$-5B`7-8 nAo7yN N^1NGFH+O%Dףu~Wxow~,ʼnj8y=C ;"(AR1+'Ǻdbs5p]_Gʈ[ogXQGg?ͭ"I;%HK >i < јBה,<  nL=:qh~B箴`s x{/9"{{;իRH^Y +X/=폀,6'KP"(z`GC) ,wʽ#Mܚ5@o X]SzR#[j1af%91d'[%)>Ԗ+A>*I g-"觹eU7+`Aqq;~;uGc sYh|Ľ(yM*#M{j7pW{xc2msklv)[\ܴ]`}Q^kjEf ?BMʂ5OB*x`Jx"zgzF +1t%@까M *SgMHjuϾfZfv?+ ȴx~h~v ϙ.C]ykp+*x{븽G>;`@tnTv)13bZx(QeFԑ:oJWIV1" +|gf?o"U3!:{Ԝ{BkXㄭ\ XA$?~`LX2%PӅӤGDZ_h2QOTyjƄD*m3H$ rc6`(&t4ۥ +sT HPEint6RN(?1p[{zF,&·7>tש3\.WFJAz uo3+oy[K4Yw>GE}+V';kW18P']./I6 +QŸYs,vndfm3/#%TdjagyTB;h H„Fe_#nbift=,X2+ypmZ3ہG^?>`J[MRA/)-FYbT]j=tI,x&^ U >uLd{C]j[o wxBQ܋މU,9j(pSJJi@m'cFTht޶yJZҚfNwoZhʊJ6T0S9(.vl'𘕊`BX`K. !D +<~AP$:Gql's3t|RдZ10ԡ:'}&1Vld]u;'>qGJ&SE*G<htk,EO\ĒB(6c(E'+pNl1PYT3 +( +aעQ+`?^jBR[g$aX)hͨ(Zy< CC)pS+0ֿw7*=6Od`@ho79*PH׺*ٮ[Zխ~naeR} +Պ5[O +&C +CA +>J/+I%?FDԱNig[kz+ +ȬtQ_:bM #ĽMz_aF5liI_TT;s*?_oN%O +oq0aNk]dUے y| +x{G>|s,ef29@"t,ub9ҺxsRZ\D)"E!%7{\+ {zWvaJ~HM2V[c5|G fp$ϯ}.r(AvV{3(:m/e4Ys6JeXa_X GfT9}TGm&g`Maf,׺iĮ"gDWq:)&j?-üsgՕ3Ac_ձAU4y&$_iTDZY% !x*|Gk!Ae묃AQ.zgG# +m2c־>>I4 3ϲxDl \yl}fT4̺ +!Jɥj@/ҲO;a\\ x) +@y#8`9T2oj~auGp7 87:rC>#Z_v +VN:#6x!m5(֜P( ڰf8LY-~BdqzZxex%y H%OwU-{Zl/O8Z=5ܘ|$(1#h25(@"aHz~5s.k*&$]]Z_ka&R< qGu'yҚ\x;ﰗXk< f PR3CǹiH-#(>*)jkMg-[ZOQ[$ko#dCqk+](8kgdr%Z\*o,3iluKqNfnQ@B6OtmW+ɗ-ڱv0u8g}sH"r`UdF塰^QfHi m.+J .rXEI- +Bϭ4f 9Mr8S_χlNݻiv̒4SJkxc:>"|rq)k\9RV^'A ;lg.O.Ǻ{h5ڡR(fiW^聾SX~z>':newVN00*@)oӾkg3 E ) +R؄jKZ"K(XBslR/p܈a`mWR1bͬpn a:HBWTa㌇wH -1CsD!gn3|9ZQb+xb_V=nk$k KtCѪqGm=U-5Ln8rr_C;|"Ou*ªXJA)AA5Y;P'{_ֵk+{yavijq?_J6E틺 NL]%"LRPzʌ@hG( *P5`P9Ϻwi>ӛfׁhgs&a'Vn?mq]cDZq4|%{E=o]wNxJi+H!X9[TA&CUur]>y?t盨ZmDW-YkH':`@p[+sD)YtٮtT k7Gk;j6!d@C׷s5Y,f!܀M3sQ8xp>Ń!(*8>+LIVȸG3CQﶘ"6gxIjJmp,(x?=oM" Jhz ([E\;5-3NQm lH_75pcj-W(Kbx'uѦ@jQH+8ReP$1X@ޚafǘ՞ϺG}EVHD?G:0j 2 zT۶LPE_|O[P!#8I +#tk׽r*64Zd"]SF2zyGlHn +J5I5)xD R[>b)mi$u),ОjR3_5Eqn,#9Tj`(ENq2ܝ+~ 0ibo-RY$9`]j,<:iGjEaӦ|(3D*2&>f2 Jg֨+!ab?{I|U"*ǃm碉\GCY}Pie(pmur-V#ZC%d}p04پ띣(&/{ՊVڭV#)wHٸjӵZnU~Xo/QBǓKbe#ċ u*u +! !<F+ud8-̧C;__k8IuB!(qh6i p켛]TyX#+~@y0i݆M1D-h?%5ΈaN\i,Vl.vjT#EHX~a'3;#ox-EaM }a<c 6:\mC1 agY2|uk  uOYst̆򣶉/+ : TDi*_*SXө}vX|7j +ԏA"+NplEEU=eZК٧BuhW'hsjud뻊KqAr.GL<,%Pt }4  @KӮϔ' FveGp F@Wu,Po1R&W4Xf\ X{2L^IAPe=ce9#8r,"rvɾ_ )ǩ7Qimp?.%8l+ׯo" +ԡu4" +Wm+Z 5'X6LAt fڛ RC98ռ>cBM!X#M#hj e=nzaDt*Iu #78AIdJ'|I+uIo֛#= |ܱ[mbjwWu%K61Xzn}5ֽDA9K]Q>A&טtMj>`}p2\BcTe;Pi_B"ۣsݩrDPn =/ ͇T~F7rm GcSRdsGekѵے%' _2#5TUc]_H^}v xtanch{DeS;"LVHmREM(Zr2Gcr2$}|&b&L6z`FD +Rv37c=wEg<klhZU5!׫u 2R8(`/˳2t"xjX  (1%jшױrq"gm۱EHmc.c(J\Buj(ᾅ)4혨J])L ѣ$ˊ +dC<ׯLUƫ6<K_+S"{EwԷIv̅Wbb>#R +cAT~Y~杢TGߒ8DG{V^y|M|ۥOE*7i*5<IU(~ +6왜|Vl]&B;R65.55k}EZ$ՇU/g%N-2BpTaɈriw 9hKŴA^-%WѨ#|Rۖ"]eU#\O]@sEVq[56,-.eJUssFirڑLcK4̻_nWtd&nyD\sk9˻},e]DF^xX.T(D!eH]hbBU ͚bHL]W@%=tz%Dirm8>y3N@@M +˽} EP l>*ح(0Pkolׇ((E +98C!fD[K +C:CQTQW#Һ2|/VDEh2X2ՌG} s`Są8j[a8'P8*2{7(;ն~>"Re#';@ʜ}֯T"ViޭdQ} DQH86 Ტyo]ljc ?@1e:6:{2$D̊:'+IHUV$xl-fkK# +S{(IPt 9%gm 6$M1Ew1%ZTʮͽI`֡F6ǽspJ4O'mIMSj~!ޣfH{X%U$NSL=+*b4^ψネj4 +~gC2Q@» RSd`÷'⓰0Wc7X m~=\Hql}aܥ1x." (9.rvd7j7֪GcTE'sc5E%Ƥ:8[>jݨɢߊhz1 P\uȑ^KDr,ɫRN4A\Z~ >=bO/kǏgԱ@k,wWHS%yv@~5Wh/fL \ޏqG 23j(PJ)[!Ha>d vv>!`3`3:= 3'p1z'ai+b3BJSDS#\tQ=VUY3g +!&*RdcYMEG6(Ii 2]ִfqͶvaZ igFVGݺ+y-=\2n"l@]h_ۺb= +h+ g_d2t'j.?I~9IPY_iSV=_VZ v4T̶jlRZhk؀FG-v5]׊"cߏp؎fh1{lDqtQ1 +AEjPg)w(5n$\nԵW8'81L0{l T@Z*{O}$Pl"cթ\[ƼQjZMl + @Aql+;MM|R9l#3(mڮ[=ZHS#/"I'4+j+|pF$a"cScĚ`hEtky|uaj:.WC&K>H4lQ5-߉SGVݨc6 +BԙLc +@kV;A8Wض<7\ ðX[\aPd;9R v]3|4DY}dՎ mX.MonLW=fn)8s6b1E{7Nf, n7rxŗNhK(x} z\ʗN8uM7m|`VM<_#܎ qJw4-|(ݵ{x^oz9|;]VXJ%#&u_ϽAR'bZA}H_x7WS`Xlؒ|C"X6jOQB8PWZDYaGDe~̝!A|49{ nz@ fa"Ul?#<(#n?m$Qab."htWWt$Κ (`FEmhư|x=㾿^PȽk#a ~s?'Nڑ /p8+cr_XY=Y3ۙAsop[͏I V=5q[QB(8&L8&pOM$Xb(t1]/;%mGS]XRdqFP 7DP $QZMf(D'4 Laez#%{r(M%P~(׎ }ƞ,.7U7uR`ij ChJ0x~FHex4,}>;cT[M2sAޏ1Ƹw믬 +ڱ;ыQDf=VSFT2Sno \bP, +cvd6B੸NsV;6D>~qeww dgt;ψo'ȏ((!ʋTTb +&tm0of,M'B4/\[\j6 +{zMC 'ʗPs"bXغ- Tq%8X:UѢB De2.<ߴ)&Ai""5:dME{Ч&S(bFJpCԊ&{?wҫ`p:,hFPv1\5l}PȢH7-B *=T`.dNq(R.[^ys2#g|tnkӂ1ݸh%]2# AwhPQK-ZQH#8"ttTD KD-<rLv}dk<6̛S33Z\ +%VbD!M(~ /wd=dLj@0mfs9:@GGa#*+EhT@& Hoؿ+BHQ.ٱu(uk(J#w1,H8W548r"5 vc|YɎAwH{#+Π2y4$H]M#f־JՈWc/pZhAk:T;TgFݽzT@M K$8j5>"HoL2DGOJ_7j̽adc2ׅyf碼D 浡L3â! 雬}[|)PIWMΟ$bŽī2B֟yH@Yh߄DDJAJ'#^Pͯw."*zX>y.nk4WPVBޣS(Nw:0k"5Ԝc`a}tm\. b.qQoj^Q("7Fd"'K\֡/3 ¬W88YFN Ek{ +3آB, 1[6Lr l-: +p9}?S$ơd5*({":JdD54?OڝHJ 4N5nn>1ߨP17h\`$bu\VRPZF'{DoBT}q] "MDZo1oty.;NJߍ~έGk*}?kʳL^n ]W]@.r6׋T˪c@6_x:*KpKد Ke腸 # A!SV]u'kB(˽S1] +Ca} Ƌ` M RM`SMOjC? HV+!*پO/qX#!GA! ?{Oyd:L66W6Ġx-4BGI`,sm*~Bf`< ;xrYG~=T(m75f"<~Bund%v廀zbނ 釃"S*ꈇ%sk&LK>U,FG=<)}(]R=;|IBhL*I!EyݱaJDjɀwul(M>ʬ$@%%GoiToqo(P&yaG +2h-.BXe)Z__q bs )l*+'mKWBi>-;7E +Qċ:QQ+G}>wrXݣ0A~/w.,W觨|ӛTKCპQg }^Zq*VV9_4v9އok(UL+ +Mm!*j0سD;6)ۤ`ƃ(B@sLut?ބo6Jc3.=} +=uԵ~̞3 ''_ +ŻX 'bu2ǿsZ X`Rnfa]Pf$wZAKK$H&{qLI/3b @U,G?[ ڴm_$lnBpkA:S*YiM %H>ToͽL8h|RCN(h3_]vSԜJHe_T)WQ?5tHrc^bjK߈%FYϿ]wguoT a`L̚el0nP~!u7UY8#}FD^C 8ŴlΜHQ`C+ƕ>LɡZ`uS /ňkO$FAt:uN¿QP{e^u8:1w~|YE謏N 5t8R1-ףM} +:h~o6]h;xaWjhGJǐ#w͹T!5Xš" 5Z뚃H$Ȗb.sE@~Zȱo" qo&ͣ"cM4Ɖ6o J9miNz6tŽfx#]`nLVp͍{<9Ĩ + +%{o)(1ODP_}<ӷm;>XOLgxv G֯?IQklYܯAޢ cf|3߽,%*]z 5}o^jq D^z+ee$ײ2{PM=grsT1|g_^,,jK"6={(Vђ愵y&y~`x-1mWCWٻ(t'42#ʷS]Թf/bw(BNܐFx씇zohƒF9}5p7%G"x8Ћ&/&4X9ŤO_TJX9R Tv(pNMrZ@vj3AzeYx6gǶn0v/,ǐ˷ nibpX: +uz|IìIJyT~(2Y@ "|eB0JO[+t͕2w|gXw 2 FcMkE_Gۗ()~qM# SFTsr!}G!|Ο s< 3O|5cLBPC a8 qψAsy#p$xFa 40uE:KWR  Ҭc?*QZE&KԒ#7J;jBwV4XytE=&,a<j ++-gz䩳la 73y~9U[iZ_WյFѻ^Fn;h}FxESZh}UOz]vS|AH{3{ fDl]Xӳ쾐eZfB Z x޷޷Zn.5ΉVi@8a~@q<Τ=#QEO|E 7"kcAR "4iD1<^BArNHI& msy}EɣJ^r |L )WF@5xq#{3 PK?:~ųFkg=3h?]ԓF˧<Ϩ7xR:{2ψ2@n(Р:M͉6gܩ~D DΩg|[At⎢>e鯯EہgZuG2gAU}f5cd27oߌYYs'-@mo`y#r(ݣ~T U?3d^QU_Ǡ,YAkӔB`MDHDu z2荻tur1ldV'5&ΤD\пvjpOc(Fڇϥ V,gK8,l|ME0vy,}C /jywЕ;F05?#.)ɼ(Z-J |"OU+BKd+Q K? [!Jc]f" R= 71-aoEu 3lmpڊ8^V[v,CnWܐ+E].݃Hq8h U9m[P<ߣKG;@ ijbS-_o!P5gm9PåJS(\)'w„҅;`)j#Y6Aυ x*Rl)"DJ{p}@YT )r&I=Jh|]ZGف aL@ִVg*tyS^%DLiapZk%J++'X/ibDeQV12S~JC u9b~70K,+]h_߆^| vgΆ7g/gƳ7 +PWVfg?bvkrb+f]-c(5b\ną +xtCB>bw`Jtg]ޯJb[N@%B ey "T{KL{lq%Urܓo8L([E+T) + +(}~g=/H>Tb){z͚5jNk>w eDtR5dCaWHȯө}bU,{LEy#DҢuw*S{w{'Q/| ˷,]37LŞ^R +e8a? YxjB4Ot[A'p~=j*&#\WSϋ+|X5ȥS "V +T 4*s؈^()K7.TuNV[#r%jI@R1H[W9Q=Mw c뛘Rů'Uy͓ZqT o?'~+MHpЃ:\@b$\ݒ{Qpoct(b: +O@+Z6jI !bKauP_zZJ(7`@8>eortT(W4|*PD#MVťoX)#ૣ xP JR|O uB: Lr=%H]-%Bt<#HHrvZ /$)U![?j4"- Fm^(+zy4?}aҁ3Ŷ܌ٛyjQjq9q5q:-%$ Ek쮆x&NIpЮUqpj4!l)is4yr.#(q=s@,HBt5|Rf1<ª"aTR9o֓i_"sv6XP +)m;*4FY"<8mIt] ]oFh1&HgEE$+n~ЬûS@ dR[|9PLXz; p`6 鉋7yUA6-8lDw(~x QcjʢYLlhogͤA<ppVFpbA]u>П" ; +2cGu YIF`,h'Mj 5KUW`ܡв,^&RRHRbaD׎/@xT'a,3GEq q`,fvљ?}eewd_QHdʋ/ s$ rYɯ +:ˮ&5pE儎# +n!]6bX rs;x+WE]ץM]# +04b%t3e#8aQF-4]ߤ.>Id ql³A~F2;?EcjQ nA14OġFZu/vdhG0E`9}+KvJ +_Ԋ?QCD5裬הB/)tA#]ML^0 @?K 1*Et,q!XhH A0FYj,,¿ѓB JD<%εB`K2RPS 㕮ȃy PԯQ4@@J=ƙ,ZM[?ѓbZ"Np qgMoSTUc\_ +ucjFM̟Ɂ'lpQ0\8\z>t,!X]#q•?+GH$ >&Tzj$X-b +} 3Oy?K*ۦ}ݤǂݲѼbo@Ny@jٰ8:66gu7Pt7B6$^̭!C*[`;O1qMuC(+m#Mː(l{=y$6fYNљzu5E[$). 8z?BwcћsJyfh j7lv;Mm*~nbHd;0b#,cDyn bn&TiF0X. IJ`[ޘ(u"{S)IڈضMTRޅv^ϾjWOD)+Úu+&6^t<4mWa0WI-)Jknqv_Xԕc# b5fr5h(# F# $XC#2UA#0/@<ھ@8W_X,F[܂Bj85"Qg|n3 o|pc >gu'KVPb%I:o j1!SXSVHxZϠv>?dmiE!Ϊ~?Nl3F|!&>1v/ms: !ld"۟B"e:B͂<M#uieVrimz$Q.(Oh{x6#[z,# 1Z(߰Bw!?<!(A"o2*x̘;K-ɪ^T|w',%4]۔G RҟW[ԥBv NBArnB J &"JFwY*O@1 ?%qPO: fvJսE~#t(lk"1 #L\̺\ k +_,ɴ7bNh,sCAD~мׁ.QU0N~@mXmy6Zo~ bK.sJ?SwTT"`A8-" t?KT +VD6FLcSOIKrΐeDL +IєAR݂,VL t7@?5,@;kᥥ MxI״>yÿyOy}F‘}m;$\>I_V'^SkN'vvPSY[ʅ/8BcwOjR8KWBYl餏jEaQ\]qSEq :C7J)^`i + p X3{ @"2Yc*&yͺKwDY4-N;W&VO,D{hKci-u)`p=^O8#F7r+w`ect!YɏrgYUWtĺ8uC lUC"O҃(%LIb(|6BL˖\q>LHJvQL7d'x)!IwIP|Rf1ϝ9D3iF9L(%썔=0BTR@ .bqq{8)(;x + + >4F`hw'y}R +&O_El@Yb"D&3Wv4l- + +bㄅuHj6~̀g +%i9~+;O'Ӊ.hH +%V /Ȟlo!%"C5I.ح,e~eUc&iKCA̩P(ҿ>[@rN vttr +W9+3xHX Evb u9\*-oi7eHz1ʩ\c;HrU1FXI\htIDJ/st|xc_,%\`j%?C芠Jls(+% p}"1b#l= + +%DA9^{U,`_u L`(H,@ 4 +_)LA ۬Mo6xMlG g4/HonFrq`\e|J>$ĺE.E$^^4l2ȇcSh&9be-76I -Bͺnpǹ9أF2Bn^| X䍟t(%f:4؉n,c%,BCO ̻k m*,LKnCW=z[w +׹/f"ͧh;6r9K!z!!LHb q%*UK܆|vֈ- U!RX tzŢ%$SUp ?K[bՋ*)7AA[I:&@rr{Fu9SDəlgbFz| ӵJ1łT!BC3HtL`W.PSP,+*FV@ܤN_@YeU(`GYNit=6eM-x@K]Uv-Na*0T0SQqDW|GH+:V-~oz%D + +, ꃺ5KWVDʴ6ui6j.t2^Uoj-R{j |]^06Z RЧ"N 6b&F-QD,ي[",\ h0BMltGT^a\@)ps,"YM(fPzFQ +$<! hiFANO՞`![I(ą(T &kœIE_CgxKi_p*)Ov@]C2"ӚOU4sEqX,Ix*$A J D VFC$/kΑDn 1W=!)n5*Dݤ}Nu)n"ICz>dEY%lP$Bg=]踒Soil@uHCvvUd (C%^5$N9ڴ+&= e8S.d +Ȉ@$1%"k ` .:"`ǐ-w ifnnB*ĥGYP4r]='.8wME}ĭ;L1h_A 51ӲW7cFԳA?UJ6Unu< :8cT1ѢTy{4x[rኈNy?VD}vPR]4}QN<) Tc+iwF"T%:Xp֊+&'A!\\Q27C*lr#bSCT깪Y5@Ld]b#\qޮ\^Yri[!XpSxP$S΢@P ىGBxa|-.S~{4H w>$W'$I1j),N`+Q0^f|1Ÿ&Ȕ!ҋ/0B0g028a=P/_b3VJČH3ay9Rl,bƾnC;5u}Qcxϱ@dY(Ckp3qͨ'Nuxhno "lDfߴ*ڴJ0j[%<:ɪ6#Yӟ>\{GinC&JS=6gLcFn0>pHT#"R4bJlvpfraM٨3(h}E:͒xa!ÂTlv ^d=ܬʁJTƤڷ+ 9MK4u`T  P4gX*BnƈzCr"Ι'M 'a +s݄Fxqs7}X L$7~T ^l:٘d~HOz"D[:J}`4-FyL+EG Ȉ7yask1Ts S䋫g6mxʚq\z|@jm ]ۉTO雲[[@>+AJnCQUݛ0]<_E`L➠"ѦӛHV[V]-),sq~Yle8XGxRTF3E mqvNyam5mUʖY, 38SUr^%&/Z'fvwGFdɥ<$Ljl sKN,I;`z}yP+3xD]U.qn_]}b9e} uk>Vq ihMbdycn\Rg/,}k0-sNABQGs?r +S +f )&M$M}SU \!Q$2艺pW< MFeMs]AAJrg& X+A +Jt5ު/4M `S`ST`EN +7"*~L6kU,M3ctAG :1VSbL'F p@~_V}Qnl $B̘ տI,WQ(ͪ%iJ)q`ӣiӐVRBP򭎠.Aҏ)ayxp9"#ֵ mq\ j'GF9i޲ 3&R 6e$I@@s@qNxsZ`O40߅P1P/Eobw N`~~~,:J)v9ƛyPitO"ѩ=,\wDS?ZUq@^oqP\A!^,T6vVJ;\9p[GCH,଀@}N'ufFI 2#>QB$y-PL@!F OuDiFB@SpR\CAO]T@zQ`BeYHqPvg@\厴Ph pfǟu9tJO rً.A i T&ѽѣ7L>y6)40FHAR]>mkZ_ɡ99  +@Q;-Aa;hO`ԾJ d[d3<( +9:I%[zw#={7g4>M.3'Qn[!fD-!O9TE>N# 6F4Q6Fi`dF`3RNw(Ҫ-1 OKFTL`Ky7]Z<9Ȧo՝_D8M2jG"u>uBay栬 2ŖG\Qxc8 *Tt=ji1 +CIPT<[}Fu,ρ?9] 9T)b"s=[=!o| qYn6b8#Oő1F{Vd._Xxn4!/B(ꦈNRw##3ߺͯڝ=3 +u5`isW:& cE`g$뎂&UBO4އj# 6n¿WJK' ]( dQnN#Z=Yň a9%* +ţJWi b. tIuUpQ*y9LlM:hnq(.cxwjH @bDSelTܥF1j]9h{MAE5ձt!OD *bAȸf (B91kBDjyv:4h)trn/^ӵ$El#,F jh6X%@\Xɴ'X@u+ ;<Ćlz x#R>^Sloe/k!FdZ6(yKF93u!&'P!d^5Ņ e貰qƺr "VJ2 cd@YF^WF$D̡5}D,nCBck5 +FBO5%#t1RpbC( r*o5ޞ"܌tF%Tk\D=,:6lN +U >F2bDtdƒzB s5 a/|W0/ɥkIIOJ$R;l3;FZ"xX)5ඏ-c;I+uN(Ahs>=iCl cx5wB&PB-R*nOGQb8_ CL}ΊJ]s&n1}؃@HmiH9M:-I~ lJnFL*DŽ Ti#ڦHX_onw0"TńM$I, }sv$HnGɻ:p +IQjRJ8LMdh(eCqt)i(JWh4.;[<Y/ $^][v^ 5ϩbn7]H6JɢK[2 e턶VG沏C(v8G(@aAqP6v`M>&KIo.eQ/nHŒ|PURV6 +E;M$k>Շ8aۇt! +^b+|$\v~QRplE,/0#N>:6 +/E'$NNG,:M1 @ѺͶP.CzCvs.tEuKu%$%ggV_/ϾϿ?W__|WW\+8~x9!_o?_o???o~/f4狿ݗPީ{?X׿z< o+zw/?oױ_}ͯ~?O?EϿj|׿~񛯿zyyU*\aVA%40 Xi?YN>/n?o+{/W~x,ۨ~yEox~cO_}s-2Ed/Y߰́lt +*%NOܦzƂRud +6P ܋DDw=Q nKSӨ<#|1Q#vu5zKH,M@g>8w$0ج2}tI[voR=~ 8Ex E2Ill\ qz:MFNK#oUFۻwoƎE{]0*P5C,ZYuchgLEɉ +@DI"0@) RDGӔrA%lW-6*"Z^K*k'kJ^8gM_Td,Kgvu7kAڜVXe}I>1ߏ9I45*sN;b4ӓ (Ÿp57/bBX ohkMUŎfPB+&5X!eyOhV ܄ۺ#ʒ>3(i,m45(ʏ`V)YnH3?>>~oޢ~M%O~Pv_XbmO?/w7~h~qZb/|_;{&³W+-ubeJ!E9)2`Uj 4g׭m,4WԈ]j Ud +Q^uE[e ,INCT9]޾ޡθzM(SSp1IxN 5Z,Gb鄍ETu+!\*$YRrhmz.qT;#m/ѓ&H4*a'm4:#?-֑8!PvϢ6]& *-?|wr#ϞOoVC"zB/EqQ SOB.]vxll#/i~] "026irEWH']m FN י'K^FY*8qDS+sd7~@Hظo`'Gw+s$с2U4#Y֛thPk('vzQVيpbxUa5Dh g@uT+8 40k||H2^u:J/6IG}CKai)9Ph\hՁ++$%yh7w+2@Mw)biOq@D|?>&ڂGx!8eV D0򡭖gz̈6 EvqVÁgY3@`WLV<؂aPaQz/~ ~{ؗ见@ Qwv% >سlfӺy;W[t[pwM<)pY, _|IC +EK~L{ޮ^p>nr .PRà Ƞأ:~x. >yzJ.XDK_U]O"M9.-\$?Y`kC}Z= +k?"@,M)̫2zR,k2km^/%IxՐG?"2ǂ[W$W +]S"zcEUPC [) Np?7-o3n-vs0%8ѱ<\>(|/YHSw"lBHfd63U*]H`+~:1~BZ'8/*y F:E +WXdS,`97h}LJ23Z>%y IaL}\F ?n: F8"4B1^Զ|X?Xd o-OF M?{>Qe|33I &13hه=L $"dws[2rf##wjv [߮%?UfyK*z݊_qT>p6`4t!|ZF@8>f +$AC8e'H(aLp]Q C̒A+V`qunb-tyYE䏢U4d$R\ fa` jJ^v%`cMz~FuD}~WҶªU]:w|8ܣޱ@L.lg3J ߖgдK[n&# k5JbrZ3,q/cN-<5[Oa1|lA?ua^Ƀ@Qmr,*b|[I0sRWt*b,{|OO[e(neRMS9ԒЋiO$ !dNN3j] `,Z) ,ԁ™@TF:"l +g + +kExl'YZa+#1%z|4ԏP˭Tf-?IkYP;{^4]\$Qj*U-2F-+Ea|Rm}nym: U[Ul]sm0 ,|r}Xyj'j23n%q$ݡTY$Ud*=Hm=W^*`CZ-2ԲZB4{ 3ZĜm(nOzVkZRR$u =&'m+CUk-+BT[=le!ZKe?4/k#@ J,MqB5[} ic^g` ֗Wɖ*kܨyدY;&vy} 5l}NikFFLeuq-EJNmD#@G m)ict(t _4Bw?hݘܵwCRq>٭1M̼S]Q{~Jݯm6lmmYٺַޖ_-~nmzۊAnw Qn@;al];nC'w^<;\c7>l@0dÙlDhOf6̈6mav8r|fA;@ь{76N{➶}CK%j#6֖l ۜfÈm/}]ZҽBwoﶤu7yͨ%[ƾ o 渟eEHn5iyWptl έta@oK0t+lӭtWHuAm ٭alo`Dwmޭ"*{xnYP w =zNmuEko ʸ(!g)yoE TP[|oE o[[ICnm&_3akllĆƋ+;bmO%Er佭U_Mt̯NznQ1ܤkU)-tP/ _>zA$׼5= v= + +[S ze! yʲNKfm-CJ(c=sPzNjQϩQe6 b՗Vb-*Q SkwGmX[\[B\koSkos 7ލ R_q +,'U.8ŷ +z2 Bb&ly +q ZaIʾ4Y.#Q:Ѡ!|ܝIB@K0\+:Os1;܊u}Vz>G߽gwBD+s?`cΨךפhB }mTV]8եMԫIM$*Ԝmf}6b/geyhapnۉ䄍(R@ݯn9 GkZ"Տ9z/k3bIR`'erʑbPȷN0#EOT;}"m$(`Ճ;!KIfY|^ +W{%wK~Glwu]e˵LıXU}BO7/v>q.=>Lm\ݗ>kĬ}pCk@l~jEsK@1$du>聞:A#Q5U+h'H2*ٕ)V fyTWBNi<ƃ"ew1hb @Bbn))NxT@YqcEA⚒cXL֞(Z"EnbQ{\( I=JiTFa`P]zW{J6l1R5cw%e=1L:sұkWzON@B+8H{(uG˜7.@.ݪZ Ff>HȎLn'rDbypj-Y/ah4^2[nbwwʞ/,0v7e ւ)SaTOjoKӯKh}іd6+yXF!pUENq7V)woJi$MST t~;/ E{Jq vQOF)h^mާ/ wMqh5as 9oG$ZS;lϏ7} + yDբn*hmZf]EBӧ$>bS)l}0BϻKﲽGOԀb<zwwxY-NhMTT=>rYۋm -s>}YQ͂}[gӾi3r|om_ߏ-X_G߽{XG4A,-R`9{l ?PPFԷ?G[N[3ik[QΓͿzG}{߯lS7a>XwU>eЋI*!%EPaj$su6m V^=M8 )j)8lܠ}1yĄW`GA};#YeI *s(1bl!?|‗dH-3㪐c}odu:Ri5q,`tzP䯭k`BPؓ<8lٴ^QHC0+cN2B<dԆc{vgD4͞E,nkeRT~r.MHSMWEXMa ч$,uN| z-x }4&'+)a|*uexIv%vD"k'+)eOK$ +*j? фs-lvʠ>v| f~v_M"OЬ779? TE::ANAUJZ(2/o<*5^>؂? !Z+Kn𸡞V[?1f+=H"U YlO mFq"y͑RT"MlRv/A`"'7h%If[;Y\[^e7+,B#R9T& B y6(6 endstream endobj 79 0 obj <>stream +g'QiOk=U\3uD[%)˓"YdTx ]dx5rP#C$^M#$ClPO^ޠCJXG^ܛ e{XޙF08۳MGTa XBzNdb l|󡮶݉axXŖJ h^X@HfAx|F(%A{IzG<% ׊9by˭׉g&̧ΫMKIAGSO}~n;aY_Zw7+~ofZu5o{ۺ͗mw:ߛ`y}c6\ [`B1IG8gN\ݣoP2繋kSJ_RaaFi3Ja&ǰ\sZc72iCШ&㦧½Vy֥@cOB{{=m47LNvČ:*fo^=zˢmqCpWl:p/呙ZhIFgSo?Ji϶P̴T]r$@B\ٜbؖ +Z3X{l)fM~aW͎Neq/c Vvl+5ƭ4ߨgAe`2H[PNjgs9쥡"ӆsDK-{4@vyRцxBdgH\d)SFbm)l6{ژBRю@{8TmG}68(ZosѶ)@qMlM*u:ڶ@H~$!N;0c|#Ѣpځ~ӳ;8Vb/bn#fLxuڑ9'h[@wѶjJrGlCxÅ˲6c|{ϝ(i5䬻λoz;yP+uiϝHS𖧏k5VP!ߙDqrArٖf<ƚJQy187RG;ŨOUvjr1|n3,MD_wbre|3;]o'0! +p9QWTl z[-;lco.wqرRΊq!˰Jrw=*CvuP6g*ؿRyQ;| R֢V |s T@# +8[{I% f}8-yܙp,&wbD9͈T;1I7{މQ0`kV.,JRgtb W|ίh!-{BӞ}&Lam<З> .ֲ3p߇Dd?IfhC)>aEJ*,]c{[&Ѭ}RA9،g0rB<}6e}@0wW:0a>j}֍!]oiov%INs߄y${66n6/cۇj9?G˟ /}4$wl}t罛$T9-۲+_Fa02ؗK4S-h(l>ON8T,Ͳ]l9\ǫJk0.UQ֬CiE< _J@0k}(a_"*ʦkShڒvPaU|G"i$ݪЮR,^z7 @,+k|QVBeXR.--ZIƖE~-^2ų-I.T5!k%QAdZGvGO~wj +zt1vt)+} Jf62L(K̉;tK]}OKC}c1iۆ:,=k JT^/ +\Ib8u!ɀDȫHi3|Ei_lTfCʰNmybǤDd"A1֐וSaN{EIdcxQˇ8.}~%pE#a~e~Q~aKI(}*wjN"Cp *8>lڧ6=!ءZ}+RKb%`ϴ`UN`ۅs.u/^xЪ  BE93x-:!s1^?kJ++Ӂ"b{Wd[)p0wZRsXX4jySyrIQR}Ϸ᫲Ӊ%heP|H5zs)g\ϤM%f;-VGD."'[a^awCoHЩe5 3IϿփ/\l +B΂jrt@_x%-=nut'~7 DGBB|Ot%< *6 2d-q2dTL4yNKJ7(zE06=ͷVyT qU<9)!k-õ.\%Q|au`}[r}qc_Wam<K|;ݼ:=lu?ھc|@s^MzK)8/;)k 3JnCc~lS?H75,MiX\c +,l/1'zLGj=eV21Lzb/FsP j3"8gfE|Db끗m=xxD;n?XK JkYkAva9\n+Mx4Kȓox3ѐ9* +KfR,#.}!a۸G5GWbVYǹX+m;V*Tז8y1jU&2e)b[n&;r;ݙ~m3OT~bc MZll:I&<[9 _̞)#|9C)sMRzԞnD)ar‹~(8l۳0u_U;1DȪ.UnEʷ&v> 9Nܩ&> IV~ՆߊW,wMU6vi?+j$V[Uޝ4V[b VoMzI:V @ʫ^]woo*:v8]6m;yJKzKak~mumۗfmlo_޵t/ݤkXOZ-}[l[5ݒu{kmklokcqqf'rP{n_ۻ붸Ku>oWkvݳfo`ak%oօֻ imMB۰kkoAQކ PWbn,6((-F@w +>UX#{1&{28!=Za3 +ٓCF5]`F{ +S㴟gGi-(z + k>ˊk{. VPs{ih`n JBoGо#`p-mYwE 9+}~r +s+inѻ8UԉLʭF`Jwz .|[?V'>yo2ު;zmYJTYߥR)c 7]-%Gfyo,غLňmxRXIi +)lskOYJQbnQ3Sja#ubl}y5"iQ`dWNJkڴۿg]ygPqߚ;_{;s6kswmm^6YTM%YgCp٫1 jh;!?ō=[R_n)`{0yU1DDARD>|J 3F Z+G.HE|U!wF γՔgx ['bF[?zFx9VO5?JxOAۺD[_;7˗ ^RȾvX &J71nAu ^=%7yQ&3㧬"Z:'<#aa;{>q1< Æ)d q3p};7hG 5AP mAZMwFӝj=˽60{8$;k#ϽǚO$XR˲Ӹ5m] &h04$g=m&E1WQ}rq'нbi֗t]Icȶ7u[n\ضGYlWuƿ9֟̚P{w)P%.AH.l,X%FX'V Nf΢f% C)c6KfΑpL3%BΏ7H, p wsz/HOa㷹$&FҼ;sDyT7'K1ۅ=݆wԒjv +U~ukHg̽ρ!$.p0* q}ʾ޳Np hq?-om9N~ $ZbC~I];˝O?_~~0&:Ŷ㔘-[X%Q7cZV!)""sJtA;G&tROqݳPz˗Jlrewogo#Kg9cm<[3D G %8,=%B-lZ,,REvS~{BٶvV5@wqJoڹevWT8A ?Lπ)6h&F bͻ>Xm"a69 ȦJhv0lIe+XeR P-i٬mDwI$g0yqpU|vV QPP_'@|{Bm:gsjIU&G@-Nt&0R53k +,:'zlF>nM [g +W:6$7p7{-@HC~ [|E3B"i'΁`c(6^ h(-v+ȝZ5p]>}5chNs(] Ji[`n&)8QJSBm%v*aS}̘9 L{y,p4@!M]C񒇱Ii>Ej{jcsU0?G=IAG#f>Zw-6ٶ4gwfs`?a[`DqFsN 1sIF7`鿘4ٷouRS) 6bF(9 b$fmٺƊq}B\uHD鷻@R3 'WfF~2g o]6L6xLxٶ7]%)h^c‰s\іG}|"} 7w-S:05aQ\df:?žlMK;(|g1H֙OTljc)ԀY +򬽝K=:nl"9gܡZiNg]v\Y&5SYD밑99;W`Mm[1ʪ1v X~Pc`_VTԊ搛DUvO0:ƅ&S8(-b&p=prm !Pa84Cq4/MYBbw500 %ڛܛ +&[oidLׁ.t8svZ*Z&(m65<@BRfH<$jQwhͩϣm;iz逽 lYU}eqۊҗOH3u9u/2l_PsmObO {^PUhN0 LW ޅe%gGx&*\L VXɂN!"8p>n3)ˊQK[Gi*06*%ҁ"%~@؋<&-$O;.ce]⃤n^*C@J %ݕuy/e^MOYU!U}(Ql#(=I3\Ўn0I=21#i{b&כP[dy Q?.\MBF3}G' A9ٮ`%4!.SXj(M +FKr`)CW>Ce.`lcxIFY0udЩiU{ :< +wx\96x%=DSyU-M+"|M y02De EQXh0="R*X.BH5faW;ݣг#޵0iJ 1˰iKuor[ۓLVdAI] QZApnHuj%e\BM#PvIXn!4ٵx?h͢=owQS)6;z7hLEGӋLo q5 ڵNƔ#_^NGj9㤍itڈLVpES +`M6rFDGKֽ(&2$c㍮jU*.)M*LRY +Tm5Vd'uD(E_ ڌo<0CO?jEt[j&v0M-*{9q!{Vwل~[dXM @ؘ,7M(d:C蓝lwPPD˟`"<G)ъk8^0h :A EIb%FΪ +O|Ltmց-9. og5}ǝP4FvY!.bX +|9V49`.ziQп:8`x/8n|jtOt@ݺQ2.$ pLNL;;v~`k'R]CBX#H|Og7mڨ1UZ)Zpl +!( +6J'tAz nGt3M<ẼAȊ̽i`h&b_!RVA[Itv74gȞ~'Zp>]6@Bѷ Q{2 qSLN7}b6ba_7:JI]> =uzNKܲV_g$`M #Om @*QJL/36.,@TwW7&Cg%CB +cw}tK,$7N8\LIwqG +@ru%EvJI;]S5ݬ:^@q~v۫Bq)[Dcf`TYMG8-l +:`7B}_>Tbݔ +oOO%dE#(m=Wu0 mα:wis^!pLAb9piMOOqa>v^ۆ6_'/}#4+젛bE-ܮha[};HJ6Y|tVQAJDŀU}V4gsiQNVPr4wRU{FH ʼRp챫=`(XU`f&#b#aw_0d[M!db97 & eQ f1a"ݨkZp!ș -$Wv5&mXҊQN(7Jݦq:69XzbAq6%mcS,RPkTI V]IT* Ƙ A MQk15{zqY*PMq)>7=ɴGVJ3oN| ^X +7nx>Pa +zҟ@޻/w~Ԫ";a(uZ+ApⱵU6wH3\pp +}-6V{y[$HgШ,ab +Ң+/j*x|9%MkȧRQ6ߨp6Glwh'1T||pjOp 5,;JaVIi8[Q*yE@S؇7"T  +P[] YA݆bAbՂ5k[C$Ծf[(TݽB^B_B& u%, fWIPC`ϢiBҭ +RZjcO(]]PxΛw^,4ZK:6J;zs➇/@COYkC"oB^O%?\BA6tB(a5a + k0+4GpXhFBFʅً#a; л(C 6ZiB4tPgƟ۝Bk,8tmCʡI)D>R yh +а5kb!YZB!4m9#:B$tmS//dnb󉽄Qvg̖Ɗ=XߒYtb2}b݂A#~ͩ o!-w!!aC6g +ۀ"I_^ӌz3Qd+}{'&=ZfW"Leܧmܘq=y2 4ښ8T +Vm9k9~˚#Ym'dMy] &^SqJn[+† a߿-~f-'o|70Y):lfB=8uRl0ILx8q/qFemUmA jEe9yϯS+ek_oqVG|(;| ωt]S0F]8um.!;.S@l`,)]?UX ~.^`G(x|w37;NkO;/3K-GڤvD#LO,6CS|9$ob|~r$,EnPI8C}^#\{6B.@A wDT=ycy >+P1g6~8qoDBUEmg}=U˶π(?hd@$[?ϗ{~P0HK}mdZ&@(t;)aRw|0idm̓ﱔdR 5A䬊"?ӹpEZ*DҶh%1IbɄW;.|zt+Et1T4Ej8wV=]uZ>gj :2qƪq(fSt`1zC|Oin)aoGCuxҰ9lP +px9%):sIZld"0'T{\tׁIW$a"4s&JN aOXJ͋l`?&( pMRW%Dj#Kky +IX_"|=hDHu$3Bb3kTOi?Tؓqڬ;pؖTnOpv^ 5jZ&֍LOWz80=V@< dGP؁c;Z3V! "=, R')dQ7E^o!JrƠxl#ЇN,(!Y{Q$stl/q#!|L=bOG%Q8 I#qGEma'IA&#$X&s^+RvĖHË;ATKVΧgOtAK$]'}j뫆}'6YaUn~M=FhQvPTNuQEo=ǁ +zPwG:Z*DkV韛^J7OIʉ LG ʤ\-qm&M;+N* ܅%<&JG)QgwɍCs4Zs-:Lc^( wrTnXWu{qyHz*.n`gpɳ(iNڼHM ³>aj%R xg؎(9鹊Sz&:a+/&#|5:N̈s Yzœg=8M~d +n? :O8 UHtSsbw:{RC}&WR%_ c+5TK{h钪)HPE\ФBx**p,iI Ҭaj]A*sTE >Zf@Y5H,5E6utnTq1=LEg3=(Iq<jEOt7}?lYDLlZEQ4?Lg.qᑷuFRJ'n҇(cnge7wIIi LIMMg4C+/9)ܷw*zJ]Sk1?A SY) +'k_EM *Q#թ_ +VO"Pnewb߄h =ɟf"2HHH"hQcM;*mฺ_wiºrQd6I޴Ӌ@FXxdȎ+{ʡo?8*#!o5Z":V/:W\pDWʾTM9J꼢V0qin :d|²w9}l]^(W\E/ZZ*}f}ʈLÉs)e1к*>VuV)a4>ݏ3&lNQlWԚM+-wˎC$L!Jy O`VZroZe0>PJIyRNUUp)5й]ڏy6EPL 䆃}:(F̈a"OsQ^T.~e`0C[m WaqfA ++g|O#|@xiǽk󝫚HMأJƌne:qK *S{J_{~ +}I,{mEvU)79m}{?Mi]6l*m">\=Ll(E %{I`dZK5$'mUcF:Mw}8 (-gh,Muc-w9~;kͦű'" Sh}o宍ں/OH/R57Fy ԅ=(-jMEubZ8-`*'A(+kpmv>RTW?:?Zwl;>!Eu}zOy=#wYG# P6m@pvR" 4֏F[^Ϫ~YO_ZlJ^W) o@9z5:`Y6ʕ +"tG'K֬] c$(5;B[]5ɟWe0ܪzT|q{AB+94ݡ'" tL)4$(C;jAu$UULMTQ'4WYP*b'rӝĞb.@=Ӈ kJuHqi;]>f)93ΰpJuB&y>D;mknkLqҢ?hEtTz!wpJTIO#%xk? +4x`F/aW5rM ..*Jaa +x5dƂOSDy]{܇͈9SUgz9M|I,hS"BP=pId5BgOݰH}MNzD) }N]5+u2o* 5zl_`OS&tސC; *@\.r#lH +K)UCT;r#I6J6ޟ ~LsT:w.jzV&@OQYL* ήՓ4f])nU2~Rnݎ =>KĶn%h&<-k{k^`<") h٧bIȠ{ UڨszO,MUwPpm|2L .Scyk΀3< UE )tfpLwB Īs gss6%wGX5ǍH=̫w]ŠrrQjנ`QQ,kM͍8Pb K ybP'0tTX{PO ֱ +m݁Hٿ<0w䁼`k/8;|iԽI/4ze=0^4ٜ^ z,$7҇O)ng RX#z(d4.98>x;ee*T6; +Dj&ecg&3ڠU3V6YSf4Y((!"BL4F"ed +&LaA'XL-=$ũC͛ d33n؜πEX?FD#]{πwr3* 8SuqR#DhZ-5z/-̅^1Xi^Ȕ쌘L-G/[L8wuƦVbGP"} NK-pa\{o^FPzr=[t7`>Cf 259AmoRcik +Y|-0r[# +2 5ov\u*j7yki3[3& (TH|ykm(, Ƽu9$KZB)qI`o%LSZY#$` \)6m5T/ _&c2\(H`# ?U'/ +.ӌ>Py0hgcDcJD>voz֠}V!v?p2ԉ8wC^Ϲ]nn ᾉӇ0PfsFo@=ue¢b$` +STǗ!På{x鎁z}$% FS=b=uQ9p>!TCѲ!{ :\<g~%d#&^=sE˶Q!{O7ў[ ٛe:ⶏ'@c %$/d'l^B&DKgvr'Rh_[c>auv!<}>m҅ٳ4LSg7QwĿ)WBy~O lW es:_s{:`P[ a'JVJ[ĆUr$jIAueͶ#P!mMϵ{e:`c#SlcMv2xCn2R[삗%$ ͉̊nA;qN%}mޔ.Mù3/+fuƖoL 1tCp0|u~lOjw7۞D Baw5B+3Ln6 icTpdb^[D9D轄KF:,D0gr&sYf'&$ŹLqW0,B2jTl@>%Li3T *,X "85| +\ǘB]Tп!zpN9y;*xLWfLRhYag;E?U d"}S#A ;K(i|79J޿o*cSzd LOƏ#;\Cr&Tö%al8hqt̨GB` +.r8 tߒ"ᖡ=lXXA.SŠRÒS\2n6z"-{x μ>?X`' Aլ +Jފ$PֿF89m ス^i2u_B'`I˻MÎ`UDؼ<"XV 4եs<`38r} Oo'3V֠%CbFL2& {&n}ܖ & "f8lnVF@!^ޤ;lOj(z)>GU ^go&6CQ6@_T]Ts,!:mb7%qNCa!8)HvV(g,:*I}Sc%=NLc_# ׹o~ބ8(2 L7; +㦔31}|f<4^$f#)a'R}@6)j )dlhYh i9X$QQgci H,jIVB^MD$ngjHQ)JDQSެBʡAZSܞ]5KP$p EaO L)+ D n]WP_|#rQQW|SD[WAfx4^RtϳU){ _Ŷ&mThP$HC!mECG-Sh-1hZB;[t g*]7!+4H#xhoұ*j5WAj2nKgv%حD⁶,o: +S%(*؆0>Vo>$0݋!Lcߘ>srR8';}u=L)^/]sy?T 2,n'd2po`+a綅G sWp-8#&p2q_meة+TX|W:\r`9ʠ 2U30iJ +9DPWN3:> +gs@dwaP K`wm;DP SE-$ѝBc{^*jRR-6U k E@"fߚDUNxF5vAl ;'12q +X"JոRE1I+,Op&bYߙ b4u-%5Oǒ*Y\p,%˄BXW}tkh, +3:6Jj̓ꦭnrQtQdw-0jzBx6V|Wͣ ]di$`c&(J_ doI0ns1k΃Ԙ@T!m} Qѻ싺/HeMG\6d.@$*1sG]ݡT.Pk5F/c*5cL1v*I[TOafC[۩jq +ڈƹxɤGgE-7FuT xL\fچZ]TUrjzo^lMM0i ELcfuW\U@+D j~Y#Z[}/5]Mx"4_Igl9.a4uFc.[Ufc"1ohgY7|Js0v2qH(Ox!G1GB +k&XxpzʲLV6ZJSz3rX5xړƱ^7^G7.t )5$A94rN>}4Ir8Դ~. # N^.=^SkGi^މDԍJbN"7^s]^>PRxJHc>j!L>ZbZĔ faqrKiQ X :<b-y|z^.goпvN +ίmPޢ bMzޙ8UPN-k;SILBgX0Q$YHu +|pU/*.#Zb8&`%Zs6$?|׍U((iؔ 8ޛN>$vnJVJ4oW+th`W\Mɔ>`V 㑫O va-쀫+TWPcs/Ѷ Kp(@fࣺ|, urO+ + wg*\F4p>,hNym[N>Cܹ{Og% N}(_#('p [} +sj!y 1!uǚ'eC$" .=P ՔڂH5ܡ6 1BcGL@~k8 |ŝ2OjS [Z%us? }I1Ƌt=qJNHԇf#q%eg}J.),.jrp$:C7wt_1اc^#£bb);H%XVWc;!һ@o)&)^-pS~e4wQQ-*S9?-C} D9RLM &j!n s\VּG] _DV#|f֚\3.chpDjV`R)1ltN%¦鬶SUu]yL̓LsoL," x2?ڴTRzaPҝTޛ5H^.a^y;,懴Kf5}VBEp$K +Nazi1T cPkF;GfY[[ܲN"F1>S;XD%"Rf͋BC5?ǺaTյJoa! qbBÖ|sH@?ln1 n͓ Z oaF!.Z1*kAqkBܴk~ Bÿ +T +PDU nJP3n b: mZz*P,}ڪP95^( +2omn( ; ԣ5!B9[@BI\bBiy +E} 5[n--Fa(JZovE 5LSuP;{?!Fcqݺ0V6B6SwŻV. 1oP:w]>˹>ZCP~B}kh$ԏJeB5턆 +RK@1v +WlXh1c 7aFcI -*ۈ⚡U&FCj 3cWhFk9v+iǞ56ڮBX=om ,Dc'ٚ!iLC|Κqk#6'YoĆ5w:mT[2K.X[NZ޷9.v456ê_SeBzLR$m$tU4d&6^k1ܓKtc{v:N-ȸ0V3~@e$0*@i%RheNXX`oDnՍOYKsњn;3k5],k=.횹v.7Z@7Z!&" [ߴ ں+qdnҒp|GiVPGT",6/l@M; +~!Inǀ) +=FO˅T$wvSnO4fI0z/瘍8-ϭ"WX +%m#CiV^oU3)9"]ƕ?~7bw_zdA:-7FM84&4LȌ=a3~~$MO&+za+^:o >7߽_ePD؀I)ˡG]=?O(_&~=<a$TqAVJ P +OYn:-)qb)YߺCibP<r9VrHPb H +b5?_Zʻղ)7/\X?ؠ "=aP"D굾l4]SO3ػgxϮ<D?9SDhF_JiBΌn` (V߸G?PLx hۼOh"] )u+jevG2&h@RFNv8xY ?@O?Eq>?Şhʹ%f%xMdP_*f +a&`љs Fbh>F%$v +>=WEhMĶC>%i$Eg Ig<&&X?= ,mC=fhKYƍAd6sˎ8PC +B{Sϴ9\{;9aS]yTtF6Va%בmȺ>!)C/XDڌG\2bIq:0h(/tReuivV\BjM wIϖzov(Y-Ps8hb#~×Q6 tx|7;8pH}RgH[Թb:Wp Ng_q:[?q:??oq:~\Lgbv 9Tg@Bu:~ i3@o:9!`gvH `gvlعbc` +vdY?vNd͛c4e, >`{V]YlcxzV#.'U;=nÓIF3qyqow, /g3lOV#.ݚKP\X'M3(w(ˌd\)wtJ#W]ey>*4 .8waxQR&hip_]Gz";^R&m+;iiC̴ȽoZIx(']ɁׄLu96Rw"yx lxTV :Kk5%絲7ļ櫟*ۍIwD +oVd6o5rצ +kf1#me'-⟴=i#Em攼vaӠ3;4uK%~=|M}yP]:>ޏOCv/2J/2J/0Jn5_` o2J7%j.PJ5(%L;5PJjn Z.PJn\ .Ku8%w.rJ.rJ..RJ]\]\uYiH2jH2j6vmrvwrw??›M#;9-WNy]ߙ≮̌yIjJ!o< +<<N~t9$6iWuWɴG=qFUQ}KSQ|%uJ҄Pim[!JǧiĘ(ͤ`?"eJR`읕O; i-A aHl16.@V:'ʐF˿#B 8@Z@m?Dr{q~:(SRU64J=l[~ƛsÏRu]Kaˏ&}ډm%ңQ>H1w;4z2^EϏ'Lƌ7LֻpfI`W˄0 1{8~q~42NyT}a.p DPʉ.3R9&Sec6ԇ;OI{VUW`cݞ&-lV m,* "l4އ, OԨz +v+8njt43nbcϠh  RIBx8zHB u$a&X\C[gi$;4,E>ɀ})ZX_ 1Z7n]է,&~/Gb‡BO~q)>fq>׭`pj*(3O}umv& y~3llj~iBPԿnT.F~ +\.nF}B{?$!F&ds +qQ@'fGXHw,uKKa@w 3h=taUSZ{K{eWJAMMBϱsjo#Ѳ2Oz g|ATiR&LeV% R/,ma{D fwMd昩1 ++Wvف.gee|a4z)$ L L묡(?mت s!i"2A7A2&=ѳY)ZF1O܎sFzQՒ/P lRvI麘Z?ѭ-nPEFRh-=Iv^z J3[xYM> I*qH 1Ž]#Z{= R_vk5XZS=Y +2:hhQ2xL9JAtJLEgSU2fp:x. +9Mg*LM/!UmN*_&}UۖVGoeL( +ޞNpj^ЀW=GzLh $SE6;:?z3S)#8{[Q-z&c0):TA;_nqoq,洕۾<%\xƏs-;VlpgQbkֿ8dM+߼쏿~_毸=/t])ӄpʧ1HWςdJA'نAEѧ K~3c+&AfZۄ[ȒIOZD2 1f3 \ǻVr29p*;崇:;&,-#~+NTDdQ!|ߪ&@.); ^е]+w$%2~tQ*LLF* #ð)29Ȅ{f]T$̦j+[oAc3L>z n0@8bfS + h(1Ѻ˙Qt>|L~jw4m'ij>'t)؇=0s +.}z@ݯ}fiL*r{ٖIգ(rL!ߑIQlYZ+2ǣ= Ua|rPzbl\dPQYyfjJ:8(ͫDq!wbCC8( LH a9  K4;ڂ%A[?d"BXfj3!`e]PT욼MM)f\ +t&S}PB%wpW#H*WzncP(b44~er)5iLo'u'2e9;][FOztb;T&g"\6YGdUjroNAPnq'9Z[VI~cJqr b&[^^`98ovõ'JpnC жc›jPNUҁC~>w8c+ c ܒQ̯8EdBJ`BPOPxRAf:Am2#n'ss- >*rvn;z;맽b3?SW +3TTx[g%$VCp&4fĺ!L3/~QQ?.H۹T25ILR' ;P25kUȑS%G(ʲjo(#mȉ%GC1zl[ה.Lv5!s .f;j{:d1upGl}Tb'aߋhC)16u@}G}UU`6x["|+v{NbϻQؼ&P tt'-
dުW+m"k|FxV¥avK@${iTn3t|VBdfvR rƧR b'wU +mݦ"^PT>Tfl"Լ͚1 +0qpǁ#>(9Cޖakqf%eT#=::^jADXP m_>euu +=.,f](,WR-Mݛ YŔ  %8 j}svu;}j̱( !.kN`{;%5U=F7}ȠmjʊHy +04Tu.i$&(ẖ + ciᎫzJ [Tp:^VO@Zwi`Lj)PZBE|Kc;pW/;`^1밂#: aiƺ,@RϭB_v#}ۭOG7\*rM=oAy'l{t8d%ܵQkVdGT fndq +T%md  5r$ZQ*10FzF DZ}ȹ&Wn Rl<Һd}U)ϢcI` SqY}_moN.;k|~gfRbP6f;Z`6og=0W/Mج۔uc@ ,U9TECT J @!ұlC|‹Y 1 ժg׹5"%g +M&\;v.ga\݊ + ;T+b| ^,̍V;g[o0{ep%m:d;?sƥ 7OrgvLaM!\ͭ0 G"oSG g0txCTgN:(oyjrt@A $bMA\PL,8:Z*Q4bP(Q)Cȯ[£ 3DLfeAF6)"FYg|},18vnXwPYGFtЈM?rф@ޭ%jFu1DRBmKK d Jǟ1 ΗH Iӹظm>ݟ+˯&sk~y{ϧ왐}`>gL@-'%9Y SzRJ`^m} _ /X]1W'WobuGMВlۦy1X @kt}┍^Ob} +| ˳dxAle6' BG F'kkO3|ye|"ڴQSL+{uTBy&/șއ&+θ&*/b!BT2a9;r50iM(lNM0s~ G̺^WO&:]c% Xz1P@<=ilDHRqjqw1!ًWup@Vzx}N?O4 dg;MѬHq6i:`S@FE qvsX=FCkwa٠cR\l)UTU~P"@dV݆E=nS iPq]Lt|q $HE0A!xSbAƵ3[ &i)i0|0Ρ9S7:3cKC9(1W~T}n*}HǤ17;jXj@^CN>6W GahtM\ViT̀BBxVx:ʐ?A YJsfHQ|Κ؎)fͪ]sVg텥]ϞXS-&\ӛqwi)Yӭ x`/(6t8K&{+|*BJ=͐JݐB;TL1?k +ު!*QTQ(jPJa(:4Tul5, + z;ԓ?lͅPP"PjƸ :" +>ZkX(= +\(_ +&`( +7rheYyW Dlԡlk:`ƇZ +%s{b ɨՋ ZR2qԭ9\k$Zܥ3k^PsB]a1671}`t <CJ|YuޣyPQUFM+(fJ}BΈ,C,e!/v$W~Yam(%,"^sʥm>{÷:8s] KAx]75p mzȉ6M(jڭb~%]?1?KG(}sߍ@`yC.wu u(3rMElA"i~BB.V49c'|0߽[HZݞ {˙@PTx +c#u¾[i+mob(;nt7?}u߽9u`'#|LGκ hK6Ouˀ +K8)aw|0syA\6{o_0TP,!S2 i|{_\ӧ=Dpc_F"7 t q-sR^ŇD!M?2*\éCDP + q뀎<D )v: ;/@RsсZDێC)͖L + > `Q n,JX$FKMu`W JRިy<7'qm.`nfkhcGwO8Rn1n&Jkw$ {PDW㒪`|2a'޲74qe"GBoWX&p YjC䴝~ NֽTaّ\o$gѯQ3ŁPDSت@G;up Qvy`~j&4U"ws-qP3Y?&Wq@XցNj፴_Qzn=vF\W!5>t҃P!je$fh!lA*l鞔np0pTHgSݎ(9!S҇\~%Y4謰%B jxSoET!06L>2P-%g!btuWhL_  |z +izZr^c3$c0]Tw Ar5Eڢݱj<}5Rj . H;P Rp͇HjQ;Kj͉pj'dHϪ#sj{q|"XC;&x#f >>׋SM >ڦ =\au @.*$<7->_b1g#a= 41sDx0{m% .hx>\QXRvwys\TYH표hAIsbq1rڞGcJ;9["j1yWi N/mJ$@2ȃ$u{g!FLubhqQ[BFy uѮXN1cc<"5J;;A:*wHB8<#:`5jra3EN<`1tJ/ کL2l>x|/gC#{)[VIZO]Q߾f3N6ȡ +KSm'lN zY W D@W{YDq';S &, XTH(+Bcq`V)1*|$De5bRe"'WSfݑAu}oz,>/HSVОKn4338I޲NQczQssdv~`ic0}V-6 :vBvr͓VLg9(^f?=Ve;T.V$&z;sNLnScH1yE2i*;U&]QC%`umdOp]spjLLm/(SvoTg߭}~v{ߗQHQGy_OX{?!\ sv-x Kb Qn6UaoFm}K/g6'WgN۾\|v׿ͯ~m +t/OLGǻL7|o~wC???_}_F(2ɛ_>R9>|ǟ?羅鴹:37?/?Wn_r@0<aCwo7_8??J_O'=~?7W_◿_c|_|cU?xcǯFd?jKR_>^_W_oj87W_ o_Kp|添k㷿|C4ýD$ j!XoJoRnh[j^*\iTS85ΌVޙX>"t?ǯrŬMlA$_>~/ 7jWI?/ËFzȉs4U|\-iuOT?m3@֔ǚ +g^n]4E\iew^iR۵[ygUc7D/I{a_p~qMmjwwz:8GyYsO ݡ1Q3ɏruL1=iLj; /0.B ث_%ZEq0ǒf<%潷۳~y4%b:;_ hNOM=MIiSi~ ظ=i;]99R܌瘱nißb~wϜ]ב,7`_s&(2)Uʰy}];%*BB?|tZR]ʼ>jȼ{\1{ +2wu_#gZd ~*徦Z򞏼m܇Yeo?a[/ϸgE(rYWסuϗJ0nz3/C|>֔9˚[*NNCڱmn?ENƻ;_LBtXy,p6py*s|_={y|P'|L`g>FY^PƸ9/)33m W{^|D~Zz|Bmв9ODz=y֏~(t##s,cRDNjƶrl#qy'? 4eB9ԡ\>sЦz{S{Ǐm3]|hju|y^TM!Q9Gqv~Xi<48T=\GK~ +e >f9UE_k;0"%0.ל(λB[_.'cj'|rs[s-Ta\(ycnGĝ=.zi3wcMTJ*%.6Sa#Vff{.lH{4; $=VP+;t~< @slz|b.4PD{i?jz?|$埏=9nrs}Na>qwqp^#q?u>}>Qi -}^ԯf^SS9"7gz*{kt|V 3z/uGb+U,쇢#?#(9ʼn̾ 2㦽S"}bAkK_04t~5e3/~X3I _W_,m\#: .S:Cyag$ɷr馡9|273 -xޭǾzokzGKWpp0hW$CRab32s 'eߎK_ʷ%1{tX@v\n:bs->wLVg0W񮩣Ezu]}s y~LRRNDI-;Pq?aVBhQ}̐㞏m_5>J{oL,yy.vOixђ:.0f芫#XumgF*b[s[_FJ_f*#Kշ baH{})̹Sꓑ$IwiEOx2 )#2Rk-UWt%#@Hi%zH[mnn39-T,-G}>~՜f Êmh@:XH#<'Z +:4 >?4ITcˤ3X; Y\Ά@"md]'Z&J%#thFEhIOogSgHԨ" +/bfT`K]L**āOYQ! "(hD[10OQ+F *.>þM@LUdS}56*_w '*Y ]}nfNReG,D)܏ʕMk1Q!,"n3Ll8];1X>6w妰y@<|}lU%SЂ@8⳶0~C3Jч*C"I"Q*~=/U&.8/E&sqJQZ(DT5@/g_t멙21Uɩkq˫ Ua/-1Ah<oMG.dL>1h6/#p;Gf8YZGk4!:/!X3kM86y%@UC};5$Rda&Lڂliu|F6sBS#L}]LR[>"gDF`QN +j@Y5M+x׀>DD}D@DXOdc wO_/jF8hv,$'ȝs9%bČxB& JOOeJyF_b8tz/ +l!<YNj+ Yf(ʷj>`++T`)MXBɾO߹jD,2@ztb]~m|YY 9cJ4GBɘ3ؑǬ/uy1?BYV'E-w *H2z(8DL L4D0E^W(z>ɶp 1JN mE~gxι%|zJe`nN0}CGVK5q^E0ic5LZ:T(iɊ1.OCI)յ^-\;2&ގD)9j**p[WĨcl(kWK8iJ0jJ:pTsůd2tI)"bW !SA㙗A^qlo`g~O0'0WccD[D>B1Nk|VGoO궅P` gdS$/P mس kJpp\8SJTϾcj-CQ!ưXhIy*e D E]Z%BT9,Z@2!_v}dxV 7,eՅGI%#Ou@]P0$~ŒO\Kd֒QNV''Db YSUEIOeʱcpbTiBQ#2`0A^coFG hA&B~&}%rX@*6?VFՊi+VC%M[(օo5J%#M޶6%N(TQ(.hOaZdDhial3 +f1<ppjznQA F lT A +|/ػbye >v5dN* +=33-بr t *YC322Q\<2Zczlݐڈ g;+jXP +47βsꚊƬ ?˟ ” ]ЖmYJ;jr-?'R9-oD8~J~W֙QE߅*Kg(*/cX5ppOų,HF) ,itlcm [641`dOt-Yo'9Pd or3 +LzE$ +Ccz }iA]1ǀsw-|""( i5SR=uM]ѐ~L܀2.f,UmJębvP3ˀ]Lj*fs_YɲG_ljD +o?icE-x[jJ%X~FŰĵawgf4z dSv:Da ھ[*,BvS ΀Jϓm,֯yrO ~@X'0'S>*?Ac*<4ۦ(SfpaUvVAID?Co#O2SWD+9_1E9YS1M "aO[8^ +pk'KĻx! JO:&8Hbӂl,φ#7t"Ӱ Ɋi0M-Ȧ.*y}!'K k@!S焻 #~-Ȟ$(hD%&^oT̜&<GdJ[fQQ|+;U"+|LK<+vܔ׆3֡dgLHP[V챫dgPqUya%؂gRȵѩO y6¢?RQ.ʜca۠iRk#AGJE[o ,z]Vy&vd/|>LXvB5b*'n +E(!9@@`S[tQH}x(c 5mp?1LtEo*sD𵰏|uYa]Ō9L*{.p9kZ.̦Ph+Be"&y1s*ب+ +}m?Q W ]Dp]}"@GfYf6FRe>/lL~'+2G Ĩ +fáp`vLJFZDl26n)q&c7=T4ĩdY + bʲ D;*]& A !YD6$6vI!F^dDeb0,AZKj$u!%>QF"!FQDbdob?5MK"S®\@[Nx>,/"}Q^&rr%"s*v۵e=1$S)o Z\Fh@ oR]ln2\^[]kQxbCV)>jE+BeUbIHJ'G4+kהj*00̘DMC .A-C3ވ4 d`1QVQ.ֱM#֔|OXOTKOy2}W |"㱄 S1H~_9/IV@Lo% H#0fg"ՇyMMyu_8ZLrgHT/wJCňlfmȳ35ًަtqmi>aM,3[97J?B!EFԱep3?#@7Pv6@/}Ye+ [HP +ҁ1Kv0HFĂdkD٠Rh©DC!XqU Aݬ>u%rkUJ*Eg\6BH kEE޸IJ4Nt^YΑ-UL4;\벸IJE7rH$YpN7Zl!zW-原kšҒ#}\a8/klQ |y., 8ڈfb:_x +2.Hh]Lsp 6B![X-%%S+,L1lY,`_G?}>ٶ*X-#RLu7#oxiL+2Œď_fJÁ'Q[*7515[5eLLX݄m K +KU~7Ӣ +|V#g|XjyyVr'˲MVk:m}i'("٠XgLDپ;' .۱/o1 tT}YlGTF_rtMYU{CfQl8og:yÇb%ѱ^UocDqUoUsQU6q*߶^8pt]mĽfT"ZwE-eG`qfIN)ֽr ڝSBFAڲc:1bt]CgFYƺAZ&\{5 k$DKfp&:eDCGY}ffȨ0$8mG]Lr^ā щe+NSu-!/d:t__ ck1${$ptq19KVS]"쮭/Ͻ [܁738YtT6eB_RWEH{BlIVp7Wd8!j~ͽ cRˤ|"zx7=hEI<(:/N$3}oAA+O߾|K׷#ˋNeb7ի; +M; QPٹ`HڰHXPKKd[ioYzx ~c +WU}؝K,P> ;USY1 +˿4Mtʯe~Xq"̈Z [dͺQNJ>}]w; +btlFڄZ%&h0Ky,0ib*.xdtׄu;dtÛoN}?}p^ʽXyN{nI*d$v!Gġ퇃{$@ܝ᳖އ`,gu>\$/ ߴR7q z߽5"4YͰԏF]?x&Yt=>_\]|a}| ~lQިXҵ8 vis!{Ve&ny.7C3_k]22;v-Xu_|(EͺևC@ _5 +xKyégz_d!֋_l/`jA^dE2EM|6Έouq\i(8}.ƵX&? HYY""Ϭ4e&Q}n$mln]ô>.8bb z}+au} żH9|͊;5}:23Ҵπ/u} +n [s`nE`Vč!ۘmWo_f?<}̵E|VڙwX1`闯?a^UoofhSm>Qc`ϭ|4a8m%s< ۛ4]<3K0[ ÝlRA,ӎѦRhp'L;S[пsyfNxHI0fim\; ۍR4>T|>X8[LfQVԏ7QJlOq0QSrB6{_Yh8TkV!R5*EuM7 śh] ۉBj%i6b'Kٞ^je8I4.To +E+-Iv౨݊ͰQKvC/RvԪJh$௴*0毛Wl0]ڍ矆iH$J+R?WCկ ͫ^MN:70J t>FjnY*233C}Yl^'R*q4ywcۖw`Wp;iMrs>нn8S; ZaABz D"ӊRz81_gHd{\6v^bs8f(1ș4[N4ժL9B*ӋӰ^MrXyn<# +ꍐaR>(D`0i*̪TTCZ ;F GJ4 *@ydD_Ң6g{i/j9b6Twiߗ'ufro?YM䞆5ms.-r1ٮu*Δ$m*?f"5+ R;*penD?O)_~ׄOf8f{\~9ƮW,i0x]wg;pv2޴ػ +()isU}Ϳ}"u[xڧ?O,ojûίw +Z])eqVlC)zfpb8y1 +|N7 X8Oe'N"<|q:δ/ +q.NQRxf?ÙoEDfĨf ݷ*m'Z *U`Dn|ގrD5vM`:O=ͷo.`DZŏZM3[^K1g' P%M1UP΀AÀNG:a(]U> {Q8M`Wqɒg?Af3l8\ULof@ +lA6`-^[Mwp lPrYcfzMC<]>I@O⠞@Sl@EQ{/ n̪$`|@Uv}Q Peg7Y +j5`0)~ m!o +[N@k&W@IaΦ[ ~;[zP R%lOZI)#ft栞M*x3kP$0io% p.@8 +$!Y^d׭ßpwě+Ӄ_.gUAsZv{?|0^m<~S-_8Wze-Swކq8306Ǘf"aҙUyl +kf>['/ꋯW@THHԁ o ++[#3L_NoTtZGRѾVU)X"{h,>vENkg;I@7i$.$Z~3@0z/Ja+}{m:b5{ENtՊ30Ԛ[wP ~!Q"`$왞]=Ph_ +C1iB0ZN~\r @~I$]f[(ߐV?{I%xQ:;Nrգ={OCv8#P;i-inE؊8g@~gg֙Zrbpt;W^C4\ +L|Wja 7[%M&vT>ufYsGVuY^1m)U4+O_Οٛʨ蕃|[0(mw3lt3vx;`R!mk ˀuASBsm`9cś+%ؼ`m4ӎF"Mzn;*ePAuxc!0Q^NWi/Eڰ;[a+ w>d|dvc2#W!#b0 -{iY0 1`3C0Ff;b6p # &ˋ$i~PwY`t0K~v3*_v@$ -0-. i FRV0 " @n7$^Llg+#p k7:_ܾ7OUvbY=7.Zn.SLʉBapL`\L悥m~zfܻD/1~Tc$.$] ܮʥU V`j5 pWꓐ zh7wvbN +(' HH8I鶎ꓫnK`S^LQ}a ::"c IAɎ888,t9le"()o_)N;y}ݏaړSʏnl'lhv7$l=ÝZ`3LbR p鎳D"pV‚4 +z<!δg6b7,_} ++F4Y͢0H8!ShVVpLoҜfK!\Xw[e.]dU.B&Y>LAy +}0Fة4 էQR,֭3u4RJc^?bd[VTo+^ұ7&i%Z:|]ҽ|uIJl t@Zux^8I +6QK0 +uBF,NHbܻ rq@Xli)͊#x@KОO8aIYM0h>}~2HCR Y;Ehi,b_ͽD(j7Ze_quۙs$4FԒ^\%Hixf'JJ)kڎ]J'p$_Oij};q{SE%V\u՚4&V03Rc0]zFijW nV\^S 9m Js_suwL X\*WjY۠ +{L°bf]x;B:3Ӥf{R{ljm~dl%4NF9_fcf;? KÁ"Am'َ19 +vsZ &]r$܉dۭOd/YeUJ-wX%j4i/E-`7`i_djqصk:%3tX~9me^)DGԁFr ЋgRc bHe.3]i2NӮ^YC8υkx83ՃLG?ϔ< +FZ%mmΎ]=Ms|,=80k3PZs1tM/b0$lVu )kkh+0]ƅV)Ч"m2ziB4nG2{RtŅ3Xfi(n@Zm]ipfN&P?QVڨŨZ!Q*7Ne1&jqnUKyHZ=tq;wÏ(Ώ(-LnҍrmMJ%"z6Vp4 + 0n,@#/Z׏֓4qOHkA [,2C~_Ap)/ gʠgA!LR67oS.smscw['6'0% ni}m\.ZA3x>Ce.L+I"U#f[|WI{K,͝[`E8ȶ5_g{BcPOa#`Y ,'VyV+:`.y27٭D.r@EJuJL_ n8wCIJE{jq!XtT0]uIH?`AKtq G00Xl@VhgW[oyLPlOBgUL*u'aɾ+PQ6f6l$iwy@,iFqd/ծ[`<$.'3D Q TvN2yRUxFBz~e 8drn'd`4ˠLaw@n'3L F4 )L xlxK[%0O3i ު,"F-)PQ0 .-N$hMuV}X(S?vWMB*\/lUvӅt V2;gj$ttUWghǿ3{ +V{mTwaGtfhk;^N%^3=&]iWQs+U3mnXtv/I2&mV9-dGZ~1ڀӤH4 Fqb6f+lvZwgo~3} iݸ8+sNm8+P +TvlrIP+ivW ."Vq;hW߉1dծLLb =ZHdA fkOmj׽|(ӽxL'#ƌ:sKa v{Evl6h+Qe;]؅inLDNn^a:,b _ L؞(}vD.L:sv`h=i״b>ă}ZWq%l$[?ZpV'Nz R=!Oiн_hMkO"䫰8FCF_0CzCOnNhM)*Ӈo\U%hp;Kݩ(_[m"(^v#& '|g~՜i*3ix +Vm/vLo'm fxW;X.n5:oQ˔ 8)cVJŋN*.˭x bLazd(,Wq̌Sx0>T˃6]Xu\7Iq0$:?z,\1pj4&sC`dEh,N;l Y1, qt~^mPF\aw˃7O8Íh|6zafu'6g +2c`Θ(J`6Jqj ɀQ u]"T~;iN} .L8(/mwvWm;FҴM8Lh2C!}0ie ˢfrl;sf8*@A'{b ]xw~?Wn[bV{;=+mnEs;V8pIQVW,ywcRW( x48Wcz=}m8 +~4Ų{^܁PFr+4zV͍@)@5"=VɄj7f) +zўRˀ&ﲻv :1 @+-i6OpfGUwЪT HݝRï20N3L@>mufz,|,Q{oiʮ"׺5 @SavIЎs) +h*KdFEyfHu&ؙ 80azb,߽*dn4: 2Qa&@85j-/b%`HpA8ݣ[URè .Ҭ\l`0dX*JY<1{?nUKz'h6AJįj5F':\gځ8t.^>VG)A8IL,f9xnv qFek@Ű(+Z]8Oi,-?:O/vS,RIy l1RYaOڅVyڙz:l+ |HPQ9=4%z@m=F| +7UHdڹE&\9 ӅU=ʶNC]`DzvоoOB[:CYUt!1PYv.[av/_M(ظȍCV]s5bN9`-0UscGƝ92&0!p -Ja +8Ⱥ@7;QZ5fljl8#}HCC+0O(ygQa*8'Ӄ4+ǚwOUQ +˞Z7Nkl"`Zy/EhZ:u/ˋ{΅ ,1j~=]L\sjU='Sf,=/.H4l U|:|S<7F<|AÞfۧL$Qju?/ 3r.9/_qev:O3Z*VF)nWKtc];;Nt\ŪLvEmA7{^ m.yB;YпJSP48sOi)g +Xji}M:7uin_s0:̞Ϝm4eӿ&#qb3?|-ޗ/*˷lϮז_VKTwu8$ ;:^>z=~29.d&Ij2DW!`6jqdimп#`m +L,9㌟BuNi)ϟ덃 3ux? +x:{X<}}ntS?x8y[uN7V]Ƽwrt]c"9W`,suP`&x{i|C*3Tq{nzguN7X ׽7?;zAeZgݳgtpf]Б]QpX~X, "۹if)jyu~`QmY^Gw侺|5~|;:s'ꡲzh>4^;KLD-M*f|??uOyesZTwk?nR>h ׀C)W]:ޒ޵ݹ\\{sB>[^Ť]FKS[3j;b58Ņs֨d*B^KMxʆ7&:l:'6Fș=XDmٗR;xTy=a =jt\% M[ld"&Q3U)Wzm5 +w+?{ +śLt47W^RXJF'6n_~*Qл0:bFfuwv*S;w|-X_7֥rZrɽR^EYb2 +˩;gOufv>$Pnٙ9hA,_ E1+v&i P0"΀^9 wjn)O[{by5p:Z$N~>AszffkV6mxT+=q*=5 ܼ/@;kɬ"X@(*WOO\<]ϥ"|~='g'v/~XBO ,]ӱx<iN.Yݽ.?.U$3 {H/.AbN7ܼ{A?MT*P*:+/hfsBy/!% ܜ +PfHm=9}^jaKfW,qK99D0ZkbajhЀ;Lnp1g,,ڼwJ2XOL6Ĕ;T_۽gcPILrmrn3m.>Z\Y_1@q&!7Nھ8|h(-kksi\,\8k$`cÓ2vsvwOUW* 5< x:FiecP,0*!BU-Qym2TMw=0o&2-,+]*5"P40I'(.{]-iwFADZtϹJmr۵{3Za\nf?;}0}*\*{w>h]yd rPשݻcϽvL" tZv*sRiqH<:(Rfwz-=׻WcҚT\"'X:SB<O{F †|NvrqC=z;h2X F]Z88}JvO"ҏ9𾉝*CPe9ؠ 'qp@dLCfΤ'PѲjnM7ZY,4L\oR%77$8{h 0wm.,"cV={s9&sx=V]٘pyz+޽$S]<\V׮ );Z;!Tjux dlx?,AVpN~oW\j6fhq R\<VmB2VSyPIԘDbjY6r DarM#,b je hs#޶jDJ%!3vpb;}gC)T B;!XN\&R!': iRL WRʄ,)31'U!-%jD;:;G%:*(˫ttda,MH)X6dv^ez](u.ڄI@By@*>RY,^r+Q֟_ܹG&7ɩB*E=s bD0_hl D|_ࢭR 5>G*: s.d: |a]&PVM"Ow+sfFJ* _^2j6:Eu@4bi̝0BX%&zqR pd:na<=P.CK\~R`.Q +;va%bq@лr9 +mwlFB1z:gaF2L廻Ҫ;:ᐪzw3b|+n^i%b݁Œ :t-lO20kcw@=1 +&,ԗPx Pn+t0rwbZK͗~x}iީܠtlDWh;XZֽ6gxD]`M#LXd3&aVOMLG})m# ++A9z&$#];!rp'ޭ_-] VVe6ϐS2Sc!ssD˒€atMw[ʤ4T[X@e ƵvC2j5`b/Ơ¢CX60I΋U1,B\% J6O!d0pVL0HtV"Hh +L`Ε@@A LPeZi=6E?-(kŞKʫޓzϹsK|bRT 3gS[Rq,L9;{7K,CjS#>@V1 "Uҥ|o?Z#Uo{}nր0q_'16E|XDB4D8@uHVv@FH>Q6egR(ڼQ` L V1_Bxq)uDBiNMZ8& Bnƒ*tH v>p*oQc&W(;DO6uN-DBXЁ~hdw?7s>V6@P96&*3j VZ{3P'T|4 152;hgbc&֮6$ӻwy3+QCݓE4̧AIJ+lԊTTgvfb\~a&<&4i٨ȰW(%pW+ [[ [}q.QNt 3mO4(Bƭ}L0(SU*]^3toAl&JLN@ 0d{Me$2Z".ܑ*=rqjM&K h茎#Cc#z3$@N\c Ew*:lD>Uq-w6_"R_3S q|XPvd'ÇcfJ8 ۾Z;GŋQ +Mݑcca5sFgpX]Rӛ ܗm_iI宑 +8#eD촕 H9VIg.Q0ԆF٨7ՆhrBJB\|rHa#oڨ'XU#Fvz R00!c@f;vocG'/7ԂN ;Ptz\39q;O Oƛ?/_?puLoQ׸l`8HdR7ۜ/w'^,ܺz{'.|~+ӫ")7:n)OJ'Lcr>8w̍=g_޹+G_?xwGyճ?yivpPџ8}?+v+kىJ}isǞ}?|?=uN*$J4 ob+-D +ݕT{!T`ejf_'swv +zz ӛwCfe.L5VSK{7n=}?;z߿ßo]]$L$D0.ydFDd7\gB{徧}/?̹ywy\>ݛTZ(e#Tb._ALX) ə݋nz }w_~~߉&l'#SQٵV:Bdmn~'~~}'?hcMIzDI%Bu囷yշ~~k?xWx?_/<=cb/7Lt8]̞>wg^zw~o>z}'(Ͽ/sg5.VOJUxͭ_硧_x7w~Ͻo>//yr..g'|*-xx<1~ݷo>o=cϽO?G_|?~wzq>>I=jޛX9w{}/OO~ˏ~>__뿡[Ϟ{R~zTA9 n5[()?rǾ~Ooݗ·|?>ϼLrmLg",ĒDq]Y޺pp?қ?o>/_ǿO?_|uV%2XSgQp: L9Whw]追|_~~_?}7~ܵ;lq;W3[;/]zx7?||g_}+ +l7 ʢ.w{9V/}ƝGo=ؓO~o?ٗ8^ދ{^H9Rh3@К\-.,_t{{{?·~_~_^sǫN!ExcnO wVO]+6Ӆj,N@oLM-\=w΍W;&(/cŝZ+G15:FdZԊ҂/狥Fќ_Y[]Lwv׮߼p}/_ٿvkܥ +ŝ'qjSkvr=gVNb|:4{>}g?+L BV(X lܿM&f5ۛ:uj}owo/޾F6ł]f_r'ՐkQ-28HEK ^/曯/ΟoΝZ]+Tk|وǴ6/;xG '2¹3|y{o??{Bր v/84<1j:9n1 fbљέ>sW^?zW^xg+/羛767ÉUXj endstream endobj 80 0 obj <>stream +e}( +;2#n_ڼtSϼߺtƣ>?}7/=~==ٽŅRL7lekP._W_Vz'|{߾|r"W83J+;Uf [f;I@4WF0ݥ&dzQ`cJY1s6;p, =b\gB4fւ.!9ܠa=zdL5PFk" vXjTYޛXXEF9E5Q=0 +=# E`&܃Q>ER,͕YNPRMR,1Z]:5JGXľ6IZȻ$LJsB"zsr6 U1A逍Pߨ +VXdƓc1֥A=c$IdH.M\JDR&k5z)i#'  +lGTG5qmN|P/&H*Og:I^ Ѭτr=UDT{ UC+o&$ / p((fn3B pUѿy _Q]cPm%#.ugwn[c\@ ]!3D v^x *:<6n u@gT$aZDF;7bIyPX)šL "4!BZef `nKjirO(l_jQog!qsLzs{3*j$ Oy#xxX~|Px2b66CG,Tr@,B̃:4&ӍB~C0#ccA fzDa]zj(Q٣+ζVϊȘ +Lm7 +0YL<4||hvAƴNգBxT'ٽ'e&*P hiL.4Wx@oefBQuK *:)WJrbL * JFRMZ&ϦA!0]CA6H +IԘD EcR&t}l|tLwl\s\鵨LF\ʛbNa| +eSzG@,te(.)׏5ꗐ:<)+EkGFFu2#ae`("NY8>nn:9fv8:5V/q@nא=2bP^3"t{J+̎+'f?YXB\pyM95)wCjT0~))ozCٌc&ғ,wp Q M2B~2(GyT!W!Sfgh@尸:"hn)Vp4pqBȨilc\Ir.la]@ `O4F1_2d,d6q}@@Xa"gbȘy@nQ# "-31j_y `[L@Uˌn_ۯl),.-@yLF:G*@P'#C]3"t|\a[4~JhPY+2+ (Qa +jl)k1M}]K"Ty6!"G.;AZ ʥǾfDM78<9ءr8RRj;!9i#0GcFrŒ*kpDTVk :o(;fsU6#::5s7#J}HmGa%A F}%Jxۗwz fgPfvqX:>l?1(?=czHAY~ĨU +:/w љΠ}RCP9bk[>,^8Ip5N%'1o\_^> &Zq[#s#4AcNP8Nt㥿5˙\>+6{z*jph6.t/]A(] G[ȹĜ%>[F _`NoFO_Di*D+;|ePte!2PҦqFgAuqĎVR9ԓ7Q1=:BudX;j̴sx>0HX4G a-j"c`M'Q_8O+Mi= dqiO(Иق&vװаY`m9S)l(.1qn.! tmF+:HMqG@,BfΛӹ#FϨ͇`}'; q`&!38&ר a݈!3z@u/7CJ|Hk_r=*;7WwM2=q UX*_Dm2\: :*jԴ՗7RQ2PZtq;hp\RMycSTQ9PW!o:%jg !VYDZZ\t|u5訸6$hXۿ^a,m۩Q7rIPWz7HbIϨ1aD`':BP&As:&y\*>Y=6*1QP|6:G*n E+ qi3FB%qqƃL2t%`|)i4`)Qo$qĸmDEhPZ!یKP(V #j؈әg%3LtBU{ڄaѿ7q'0 'F +!iX:z̏x2K!,nڽ%R,G+ktR\ pG{VsMϩqQl73C"S*dqjLj\ό]bf5k$p.%Sj`!s]̒X߱%xyRi(OPBg #: mLOa|Q`$Kuww@3PqE.TW70nXHLM>!\G5aq@xdʧh 'Ä6: + DLI{Pn<&'XFQJOP~ 7nEHЈA +yC#Gr=e#܀-ɇ6;Ð/'K =; NDFl+. J,T:#\ KzojԌ󹄬'ZЧq;E_fv+5Wɐ6LGH@_l,mO( X|qgW/=9kRۼ +Wk >_abS/&7]bFaY_\ VDK ڰkP7nb\ݗ?")\ƲzvLi|jr;2EУ`Tlb6ޗ`{XVI&Pۊ殰eykz gh{oér w A Nj1 zKA:4Vh"ZX'ILnnl?shȜkmӡ֘oq uJ3 {7c6Q:jF?2u +Jc,p~Hi>5-!;bu.g@jp;})[YճRH? d% Q̸pe5?{1xhmYm\$+ʫ.J?;ǻt+<(CF@z윐[VԌ`|*Xǥb +ג[k/]lu' `ycnﱽ_ϯ&"Sz22%P*!F׍ :)x S<t%#BuP@4ϟA+&2uxLѓ +fg& OLucI-lslрK7N]8ݸԙ#r luIB:!Gù俞P)geV.Bs[tr&o.ɞ W9}<Cɉy"5WYpGO*꫰5oaMȯ -*bMGq 9&7Wr]X3QC74G +ԋ 9"T5 $-{zfBȐPB~!PvU hDaAL5>ʭC(Eꛉ3+0N+7K ףb ?{5N0:T{:;gigV珀&gpTwG4'F8RnjtXP9KJ6HĖ;>$"#fhnJ 22\W9f@I^wgg/\%w4f ZvkϦgC[H>٢3Gd![I?9:j95_na|u \ayV&@-+2Tѡ-!#W\@S|qj;YғlAF'ӗuĈc3 +6߀8:f}~a;6eWx)G&25 CSi9Q"$߰ g00:`Fp*w'U(}\v5iI@ آ4J# \!!$V6X>b8D!^Aěu+dUR5'^=W^<7Hʄߝfܯ;!SbT_[%Ƅ`Fh3آQ"^KW,N fg^8=ߎv{}ZܯuG.;չFWæ#!8 Ð+C#*`n1wN*ӡla钕*hi-<+eZܸb @FypCp?Ĩ MV!B 5VcvJJOLV-a +:2F>̏YU ;6'epDc5k<_;>od2#OiPV +1`i+X9:f9rR)aӰ1Pf6OEgNGU6*M舐8KO(ظ.@:%wv<]61I3"LXzAS(A:PcN*k iv:r=P՛{@)Z2^ V$%U&uK? +VpQI=1iIY!xi\r3@GFׂ{P CtSۅHy1.f:;RelNϊ5wtFt  >< J& !LCꯟm,nysvmwBsW$(TusB%h;Z[=O1Spx #z]C1#&Fъ MH+q8:aGie`ӭ-I ȈaT㰑q=ѿ:bB&+t{ =#J?10)W<.<_~uAj\bl,bmk2!ZwMQ ^XJ+iP#TP T[/B]Q|>6&w5_a5ս WhSy }uM>cHeWeoV\q#& ]:=R|+$;ӛ9X[i*KFLF0JH),&G">nWb`Lcz;6jom 3ULbXXmV.tn\띺.{ݍ{~4riTX9=YZc#Mr'TnV({KA{^_39海E;zU\qɕ`|z+6Ea5>5jpAQZFnPKѣPJJBnr]Pn:%:"z&# cP>^b#D@iV*/p40q^*N/o-mpԨ춒1WDؤ׿'I3TGSQ# 8#F4qpA 1? Յ~4{!d)>38Z[Ӕ,(%2ذR1={tzx LT8 j%ۍCBzuΐR)PXdZU6Nn"MD^CN4;ybxrjNb:oHס<$pMef I]w,-:DZ؂n62dE#@_=yc5P+\bmxL7n۽`q'TfCM11f:y\fwqhv +nLq?Q_t!VOb9_1 hHo%\|HOnP†p)_aB.Ve.=pYgt]Aph5=3y'=?sK`IYa4\ZD+pŹ* Ki!ؿ6ڄOohM0Bƫ[i֒F/ZiPZak^4xʍAMehtv9Z[l-N]w(m:Ro/]N2B!񉅳R iHzU_ 0J'WkaÕL0]㦓rÓ򂤧TW )ar}&5u՚E6*KM )+A'M_;,S\P2vhPqb?oz3G.һLZL@pBPK'~|ؠ6j a'!e\ 0 +pLP&Z<1y"x_B cQ׳#<'`sȄUc' p؜ l +dHR5 Q-DeRF:j"#( VV`}x1^]OlW/{ܜK]w '7 v~Q,&i CJ{B1F|BxP>Mklrʛ_Lu%~^o:dFHCbǧ R)']cêcj? As7:Ds9݊f9u:ZqinY,$f/pS淮%'!-BlP2CAg9,CY|rO\zaj D;x{<sgvwMN(l{ӀCkCTih1%4)i![&=2x LYnK_Ax &lLJKR>P꞊z⤙| gpJ 3j!B|~xPzG0+ڼy;ZlV۠p3`$Pk;Hݍ6Ȱ63LHッtuڡ װ CCP3$gDr4f$jv/qND~}v Bocndv)Y 6<:t';cV;? +!5Pjlꁒb0s$4i^ X! >aR&u9f#`r0Ht)::ywI(ϧHVwgy p8N +Y6> A +rQ 0 q@QF/Uf"/L0ِ әFBfJoJ-h4YZbveB*O Gܰ !׭xIŇKQk42҂Y,(t6(ZQ{U>;]!-3bX2ow/m[`A'AFB f`*0ة>Ps|{4I9t1`s5Vdq.Xw~Ԟ2V'VvZۤ-+ 2>^uTs(tq4aǁL B& @5&,Vufw`vrkKvQQ7{{6yȄhT@M|V7vO˓|I/D,!6: ;!Ą<:1 +>_TwO+7 +$<(7ri rP(6 ~g&̨'܄#`p,3 o(f@%>@Śbn&9nnEBHmoXU\O+R^.t,ݹ ~J7wg6K Ԍ@`"1KgW̘PŪחz'VsVTqꃪ&D‚N pηFM9#qn9wj6\&zBq5R;6LӒ-_} +4W416m"})}8o78( ].<uycR@k`jHjS-wpFwEm&q:أ +>٩Ș+h"lnVw ǯ\~jv겗rM'A-vꨕvzJ8}X8?2h7IGsp~6=qT$|r@mryǤluKzU|mZ"\p~$TmqfUf؆V<<zV$ceJH}#Z]Mw.%뤒>XC;1!]H;ǯ2nBRT3X1ErvLwL v\h<ך]/lUWfl?{t7?__y_rZ\9UbLkF.dFԩ182l㌐ḁOu҈rnW޺ߺ_~;>q""-p` +.85%Ǟq|ę!'I+D:\Irx*u<Ҧ3^ g ȈVr=KƻrtCHBd0d `{wʘ{|p`9fX3raV*Lks3재Z76rAFo#¤s0 Q8qmuϏر \ 7B8B(a'5$=T@ͨ HEjJ̃2zXm9I6Z^RKZ Ǫ˻+6L, ZMX v5N({/Zs0Yݎ'|yij`ĥ̬X^oGn&̭Gqcj0 eo&Jq 睸:WO^|\

QvP<|RY\\LzzU*W]{1TZcU%"Z<"p`(`."4Y4X`b,:rj DJT +R}\^vݧrjP+c.z `qivnɬSޑaq +7_9~TnҍQܘ~_;ss&!::#dW ̷7j@%>=LN|rZ6D?JoG0_4)'93~ AQ>T_X<[ M;u 0vaz=L L\w7?,x臽˯zqH#8l(#$Beuv ^)J$\.jXwrtīݵܡR_lzUkY:\lg +ȮPf_5'AӰRպ/R +!.mftKk.:Wsד]$&ӻCi1ׯo>T;x'UN-_u`qg@),3̰Q .Gi!_|AOF+kti )Dnwhr}Z-uj?n'|L,^Y© ;u6j#H6O@5!%=FIp0JzszU)7f/y~.cEq'`Oe=x8Yletr> +8Z@k"m?_^\R2^TЁZ ʵ.97sN*04;"<䘴}pJkpPRufSA{*rcD})M;ra+jw^g8)fgH˥xZڦ`*Kh$z [},c6ЊM<,Mo4G{^noxz;ھ6s;kڌcn~lt2KWwdgKKײre8P_<^jj'OGB4@⨃cӀ*R0E#$cBъFf +݁ +HINY8g cs~:" B[&]`NDO(T%:pe,˸a D8 )D8XAk rw~qel@e`ep& x"덕=>3fScb&4x1?a՚}g1V/9۩BD* \x^1Ĉ ӣ lbX( Rs2`Kޥhs; +HY1VJ}T`N)Hm ˁ•T8? ap +npR Ώ;r!UB ds>8{Isq/ٚ;xzrvAE|̭_y&bvpq@JIɴ}kV\ &T+f,7?{'oSmviaoͿ{7? +B~MjҽkJ১ >~tӺѩ->PZLYZkShI\f{WD$h+aav0$3ӱ5.B 94l#\:V]DŽ |levj2k"uL[A;Λ} +|rx8GGʨkf<m8i@56RKf4lCP0I'z%\i4p.tF-\BP*xf ChNLp@£ `f=7 ]Hr"sx0^WDDlB%%c57'HP yi,`Cs.+z(`'D+M:sc"p \ "f9@eTJ}HuBWv>%UZj5|LT+&+%sNT:R^ =>08gne0^Wjwy}aKw<|޵g?Ã,=l-n{~?ظvynu夻qR?ҫZG_t$4dAT@kKU8 b~*EOZ(ݭ'/J+ٸ|3m7$" P|hɩ'|-\q2\!;qLXtFT:[͕[ PuL):*jF/Ũ9'1! lK(?<s8n40X`Ql먐Cp N'ѹ$g}L]L-W'ZRIE!n]p0 +60g' 6>50!бv0gS]:$+bǨc!ͫ 倘TR5&Z6CL(֊Nuspv|)1QE# XO}de溇B*Gkt90&%L:PRJys +WA 2kCKzMB!AOa34pN!/W68 X?t2 ^0TlFfW}X֣v0b}$TlpǡBxk+&o '[{3{.?<O\{3RX85ze5b%x zat#P'V<sřo~?s"ʕ+` LސaR$>d@V6o_{wLˆ\&x;/<!8lfp)Y\ +F +68hCx/cl='&PgBˬ]찕0V)>n 6h܎9騋MKR.:aҌR3W[7ژC m e`F+,@SdbM4`̰hBDh!*˪yEb8VU3ml> |4Bjɶ{` uJJFx$ Iy8o°CnLp""@0*Mc-%V-6ӵE(4Y_I6L+Nh0((nød@٘ >& 6&&ژRv^..qf\k{r"S[ܾe]4krH~\0FOM%C)@+52|$UkbeM(%zG11/L/o L55rtTS)wݻO?0zS#!+3<|I.`81zz1nW Bv U9Qsc ~Dm$&*sF_KDR0yߨasB:]Vbz=yݵbf* YtRb 59p` +D +E[@drt(+7毚QANBx6bp̔MCa#D .g# 0bŽr|6u.i*ˉ *8I!4jN3 (,dd/ 3g1`-uCe)yP?!x0ރ)`Conj 2i!>XpSq+{RkRH9㔘L 1Qj͋[܈ \ q08(x-`*p#XTA6I죣>f""u'Qxu,|܈k䃐NJA1o0N\!I!-wz=XMVWn֍vŒf0lA%bX fu2b "D:8_q.\3Cn?nF2A("E>UŴmpsKr +M7P^lGIٽ >q^BlBBr}6\4h&|!'0(xVx7i#,^ +FopE}hŃl4/e|4u "Czĕ W䔒[r5Z&7<4ڼ\mcLټY0`1)58P]_0@0qeqvF 70$NBn482 +J95q9!Y<$BDwMx '@4JS)5bռ M.d28@q!-L7ϙCΡ1qO`R- + "D "L,80%jA-H܎zh2d9vz13򋂒MbŎ$eotA,ȗ/.Nlhs2V4EZmmV+}'9 \Xi!miҁ)f:/0 /3F'2S0z1ML.-X0 }j :h_:=>nLlcFPP-[ݹ1l@U,nXF&=B&:_ȋf7}qӆf|v܇lؤ1BF 8Q/"YIʘ/MWN Av0R&yA._ jQjtNL8{(0!uc$ ."FX1&DR$+^]5 I1a'츏QF$p$D(*JnC iu6'a!Q/C8ql&rL8}V7BR԰x=7lL/ L0NZyюIV/cqS@K NΎZƬpp bc8%43{5/-R @{I2ҹagҊrHQh xraIM=AJ1h25?CHH' 5)3A,4D!Q **IzG2!wBfBsB8I]OhS7>&ǭGMΐ%<ò9]Wj4[m&hZ0V7ֶWKSR 81`_d: 0\H ̈YMW2TCIQ-U(S.?mrgGl9k0z8O va`2!-[4g du!<+")FP M'E>!.b"ʥPZ% E`ш$Haa PԇJ%1oaPEN ^Dr8bجFq\1c˽vf[K+}9,Kڇ`q~i 1\!PeN7lBLh}8A(æNzeˆ}h5::|EǸ 1Z1cuxX ^ v(LDp&:n09f|ᷚ(b\it)[ңI\,ՏDΊSgGG#)h~3-hAbE6PT.ɍwwo-޺'//ð!hH}\NT.A <:8߾/?{s9E#,湰Bᨮ jUa#*N1j86_Tڕ;ONZ7a*@M:78}jf≈cwHB>silT2&v5a.G{]S +~~k(' +q~}֋Wܻt|锵qylC T`, tNt5'Rmc6oGO/_?|vog}eTʱ v;Ojx@h )IInԙV]M-4/o\]~z[BI4M8AW.G 𙳓gN ZVbg4*bZD3X:T]SnqHXqhƜ*w/Վ=;ϯ7XL(UC;S7"42' b[v`?7?~oL7Lv bώZ^:sf(z!D$ZM kOnm}~G7393=՘鬟PJi5> +ٖomÃ/zW_]~_??>=.>ip`@ kI[7MXMջg^}NWW?>߾?t.X,(BT @*晣kfO.|~?~u?~^׷~7O6#2?iu89VwX;|jo1Uwg:_|'{v郛HĒ8\h[_Oǟ?0?~x\dE9J`het: _jGVٽ޿_t?}߿n[ґ I,.!1%hM}0qG7{??gí_wr)ȅA*7be|{'^[䵕?|^\뷷?߾ǯn?[k02jy<'V:X]%ѺߡnEջ;>_g?|?y_?~ߘ/Sz@P5X.l?W/v7[BjdrԈhfԻ'{w~O_~77_Õ(a 0\R7$M {[/G?_y~ڿo>?_~?٫7wJٸdw#L|JixEGɆ?oO߾r:No ؋"!3Yb#>)t_p_~_{oyi:A=0Êɐ]X7 ^eo~>+?'7o]n\!(H>  ؠt$КotlO'_{[_y~SkI`= 'V8W@$x (}d˛k_}<_|td9k7|\&Z,$ƊoJsM]~wo?|lV"$JtѴkzƼUradqc5o>O|t{w;{,/Q3*'34!%VQ˭R{;׮t_{xnl7›Mmr8: +)(X!#x" -E:gO_]g?'߿};fgsA#>?`%I b.bά[ Ίx'ޟ~7o?x/ֳ1`zH!tVlIg泷7+=Xk&'g vVteEhZb0,7jqRW~[S ޕvTy(V؆>:i,UQT/D` O\Fe}gpTP^fZx35UdP 5bt^$d8@-Zh/Mǯ/߿;ՋK?xяo~d_\mϨ8[}!(Nx=x*+utTTZ]<Exm?;_}Q`ԫG$7 *Q(Z*fJ$@&6Z=.un/ym˕2-`!( +?;rOdTD9]1Ψ{xأ\.3N l$9 hE.&Xn2UL.|e^lyq 2ᩌaa(w<=6M +B4 ~܈?db]TTF/;bEG,0pv,#ƲM_@!v`;ЩAk*VXRLޠ DWL!Hf"`eB,p2怏 6 (u'hcVbu*`fN,-tN&=/f[(_u̢ZX©Id  Sc'|˛Jyn̐b'lwN@.*AE<q+PϿ2gcҊ1$O^?A nnLxB\7!w^2P ŧS697h:plܸ2fY:t|h^,';ٸ\TdǠ{1lI$4'_WƮg6VD*ާsl`Gy:5a$6_f+ؽF[|/I'%P"=X,zYV-ӑ&*D/uR/;8Bn),e"c|BQO/ylDR ;Xd/U&!ajlAtqY&9 2>WZFT']vx$ |&6umFGF4b!{!Ȧ_11bǝAw@^:;s'm&6q+9dpIނifDOt WDd 4ad/ve"RgռAbr42{4l. F䜛ˁ|w.:I,\뗢H{lOk+w# W3󭵻kqw ;]k! 4x ֻ-TIFnZp!@st|ϭU;!jY(e">ng@ x$z\zg&bP]? qD;Ju i_1:vqv2eFtaRˡX\NO/>0Y~BDƕW_|^ZTJ07!1?oL !iL{twv0:۰T Ħ,U ;xT1^&NNWO"h5;2047s. =\Jn!c (n?0TN6MĦ`vtR0=sB%Lc!S` 6Mo?Ţb-۽Q]}w|R e>$Z^1eTԖo_yW?m<&3@^u.[ EkLw#Ź!aTHnqD(u*&X5 +DvKǀ_h) } +4 ePmں.G'Ӌ|fN dxHLb/(hpVJMgFY +Z"]T7J-o?ziY0 jͤ;uPbKFD1PB:ۯ2jeiF^3f{9=} UVp!VY.(@j" ++H65i@|ͥ@S{m{(e)m=36Jc3Je|gw sBWlvhVWVX={\Ztbĭ98"XҋhJibS"2`<[JWd}V[yUm_I,bBU:Л~2}RQ;myތy$qM$6GBe17oe;&FˋT)>KȕU7⊝Ѐ UsbiL-ބ7lnffR61 +P<_ efBǥK׶}oyqNsŻ2&f2Gab-9~ޘ=p*%IqNw=;mYP9 tz֯ T(ÎY>kDjI xBS>bs`qxJz~NFA$Xp.&`z^l\BNG-L;2VխIwQjjKMlꄇSmjtfw2T#%!lr:\kH6֓Zy4z'RsfCżV_>|>FkQmAsV{/?R9@ +tjZ}煐(W"_M]z"fvnRL!uJ-Kx*6q1}`#eT/7Rի+ n@JR1ś٤u07RuI/'̏ZQl5D.+Zs_k]IFt +=*\ 6-ĚÅ`?/7 P6mhyaa-_Fy~+ \i=s=/8XڊTdjwܯ]tSr÷ƮRߖ[dZ|g]l+> "V8dKT9SS0J-6 }n&p {9 y +ZnKtpц8V(eBÀ/W&JvXLOΥs]R)!dfz|sQcTI-7s倥(@sja^+/rCiB&%+򌔟 D8gXGxT,Lۡ좐[r|k%Z.5<_K*PNJ!P7uFZGby[ieEcnNM/?+/OxLfP~) 'o|rGhL|BI/OY<u?UWaů| N'G3{hIVUF\キ7]eU"YdM 93;. AG:ZZI`VFdčϜ37n|wG_S}UKwxqw!UѦ_]Û_ 1ZÊq!0 (f؀o7?3iw<_X=},VzUcJ9)7:{&;5l|U>7fc Z Rd0h1dHhJxւ$E+2$؆8 H}Yi@ޕ<̼X;T:=Eev{RmQ_ +ϼ-ůƦ(9*!]:ٹǷ`q6Z<3B3/qO}uGY?:%HFk^}%X2RmIm%op)zv `>xkOyլ= gMsbbZX든{W?xG)r+/!ksMKpI0T7;G7Mmy0}̞?뮴L{EPsg$lwk]ިyFS:\jz[_HiIXS[ށR_7y^kY|e9OjcXihkp/kA+3hv㎯*q齦XJ#Ob8{Ǔvpv=K9~:Efs\ݮ~xCʛ<fߟ<]ͿVz%Z_>&+j3?&s[ H*m=XŠg/`,F +v7_+h|jj<=3ب6}hyQd1o.,80?}G qzǝ]\Ϛ?_RЯD6`~w.Q:h Od:V_"\-WUSJ5kB[c|eA|!.?3zE֯~Ұz^ Hǫ&Qf3b%Yo͞e@+w][pDcF9.АDkqϹ`܂ O+ZWz9Fnjxxw1X޷70;)sYlL-۽[µj@W=˒)oeh +Fdq'deHWi(^r j[ @2'Ɣ" s6cw `^}VSnr4S"yIM߃p"Q=fq\ZJ8͋ͷ÷Yl(ɞlTE0{>8V0h fa1Af[Zϭ1QU +ǻC(0kZR~b,3v4}-^WB +b3Cު[wV1,3WóPYQU ~>?iÛ2 WoPPH].wp}/<f"A 8~_hn10T|2Z0X:1:P`i:eaLivW/V}1 xU`aYuO@%1]jhksD]^N8y=ϢY+Rk9F/ ,k7!\{[VtSvX~\.Fr l,.hE<.N,n!*E /M;͞vO g&O0 >R.N/ XY|h}r pcTكwDj؟<]zxAo#R=QU9w͟r7OP#݊X.Ю3{CjNڸ{pE@ 7Op/qu9oi{$ጷ7~$**\O߫ ۦ޸"֫|r$n!~_^8Oo7Su'Qa-7Ҵ O߽\ջ(^;SL<H@("8?̲WFo+nVH&'ȟUU veo'TU$vmBg jaC"e{eO-@%KNH.X`"\z9_#.c(gwΜэX[Fq%#$Of+;g4=M%2)f8jc>jspoo!Z!ZO><|vqΑ:&ĞT?jgWS;%R7+y$ӸKT gxkw|M@6L?;֣~! :+zzFUj|>;1=A|}#!d8!ojRӡ?|D,fV&eMx\NRRϿv){k0Cpfw/G+(7&Q +7RyC_ 9{J2+{EAKyF{[: f(gk`|IS`F>?jI2E-P:moOB09Ѥ1[Z18)~1j͘mRkF`ػ#e(QӧOxek0Zw1D7|b/Axr7JeDsj'Ls`pMYke N~x) 侮~ ] Fsqg=}>O$Ox|g#!~W_ųmߴO %,aCl#њ0J+Sfx2'E6e|E …їrT([ Z5M!8E6I8^o +f3u +*ywVG9Ȅ_OU4\jIDtʝt.(pa•Û,AKo7vVR[Eꢳzi*.NJ~1 9$|"B*Ż;_ i4̅ ߺ;>  qј%'>8-DHN;cpp,%,FJHkZ _wb Lj$Q) rt x,@o_49hKgVF?Qf?KUMw Zcq(3kyqb؛˭+ gPsHV"wi{M2V:P[h uԚe#\1,Y5NQyqR6VͮdE˟fg_:eM7޵=xNlLj|Tsl p?:`FڣA=V"XѲ={VE6?nQ +;@9O >gMoZ%TDQImp(0)?LP:^O `zy63oo'g_:+P1kkpk-axP,p8ݪZS'z_w}:9$Ժ Mͳߟ})ɪR$ J<ƝYme;[bm'Es8giUeL[;(PZwP 'ܥY{u_ BD *VADGZFqmTVq SuQ^s|s!:D񣜘. d|IU=QHՏ&8o;'413{m8(r^߀[[Tsucn0du$m@ZssGŘRZ_Ea)JvS< bP\'櫶"̮<\!R|z)7S0`pɻSt@ R:3%ZÛ&<Ҵ[yp&9Lblm8G'u\iHW^Rx$E,Ơ"K3?P[Jb3E;EBzޡ Bm0f nrW6hC{+ M0y&ׄT;F#e:ܫΘsq0Fڏ}HFBiv?n|[V` )RU*wqh7Q c6@3o+*ٗYuYd_]wMF c̣R*Qt"1T"B(c\pj,ي(Y$d0YԸث:%AبfPih ^vA61zK&n5:'_$cK55\Sop5`*CDy1 ipN[hH r{õٿ<XĊPM*+xGZ_۝SP `1kh,} UNj@B$&·)m RX +0K8@a +3d}!ܔ(1vB.KP[9 LVf]@܄A\Qj3ާ\ ցӿV')Jch8ڠJ\Hٳe8{"Fx6#-D,x~Ah0VP]?ʞ5Go^\лI $ wJщT;aealPON E8̮8R{)#œ+}Y$lZ WXg /\of8o,HxN zqe1W@L }pZ;e#:62[bi۠:i\CtœW1o kVU= }g04ƛXVi(l+֤†BP8G1P)pKl/엵:)Q_nĽ ,mf4/vO (~HtjBh+K'RQA1*4_w4ڼ_XDBٰ$\$,n]HkyU΢2D@^=|NYSz?[P L+bֆv9d12SRL8 d\;B[#O)k\UZeR0x{$s*RJ߿ IBT ( pU֐WkY SK}f!>mvg"7}LZ#p9TL@c09܀cT~k&"tU+ N}Ep|Pנ Dh]*b.&E?VǍo *i{ +1`N +( V +AUFCTX/UXc563&6M+ {yZ= yĵf{66e~\ XNhgQ|Β !Q-珊V'Sed<8Ud=opIQ;|F/$fp{'I}Xh,_s4h/Q;AEE TW%KB0V)סּ8>V먡r"x1Bip<>,v Yڥ\;O>遦]$W5^"y>wt̆\' =*M|ou`P0B^ \TqF7G;r +)G;('NUsM):GϴuEn$"֠@HcJyؕc\>\f0gtFyoޭ@h$K'.r+茲U%YdF 2(0_ˮԦ 70nw⨛>HAl1,4IOia@H +⒈* 1W`Ow,w-E_ZTk.QtE}_~BRB2Λ\j"Uu?#&ZTt_icZ },78mV[l{OﳴW#py_ͬFbnӸ_S@B4G)'ڭG_Sq + Jz }1a7K z/E pe@ ZB :!1 ۔nLj˷ ,1[ +Y`O+JlPdkfHsn&*F%>XH$}#Jĝ4żY+MJXocDEHg^Q'Lkj,6qmu}5VJeTj"|\t"uUz`u?G6P?[Zh^WFRV|tIIgI :kkZ%&JG:S2?9ԑd)RmA.y#6I(IW;cC]B/C4H>8ڤ[f|`!ejr"msn_7@ !t;}6U0~  57&1C!87z禪t+ !HHh<:K0,5.`?{,E|O +aT_.uh+! urt=>rT;*ۭW,ztՏAax=$vTiEݲIvpO}ww#VE)Dֹ gBXVTLTu`=DN >~ +d*vhmw.P +l|?|&""uN0g3cdeGQ/r%ʒѼ$ n`,:?UYաWVRLT)jEͺ}J1Dl-_;:'_wN\w^c֢, hkB3R Md/sg-.b5aeޑP?#%gHJ\W`,y$@Ic5cIbl,f"l-@d()%NOF\FOW;MUY͵:d{#0rwȓ_eumQOe1A̓.GIe`D)cTl^4RUD gO ? 0`$QV*\ T`]waB PZ|x-\뇔>$nUeQ3W[=K3^2Qh}""X֤B^-JBE,rBZc{{Ggn \h5Ol=_@0.1oπOaA1R3_!U}yީcOiU )µ$* >%+FUZۃ/!BTfGV310x|WP\"ϸ`8 brݓ_[-*sTkXjdvyjM\@Vo0s k`s8zkvOҨe ي Sd- ΒV|p?W{JU +d0&}oƒBpA>@dz߫u_ȒiAE<(JžT  *XX O VtP,ou\$^A!MPy}fowNP9G 3XK{a A +z/{ ʓǴmkV QUnA]! +X3W[&XiB%F +@X:*[C(OA v!Kb=R6?M,`@5 + WÌ:ì񣂌 f0*r^c[F[e%I8:*33aywJlGu88}|ٿH`_Ɵc +MqjukkG;%[ S& q.RHA& ,aoi7ޛǗ ҁ?xI@K*, R;%5er\;x[0m8")G/~uoSX@cbopwcN3_`{2)La.H(FaꇲF~E惡26.8 ~\ qs->4׻7 Ta-T]JBO;1:)))̊9ym>aW5RngIQ1e6ۏK[%qa+>,P_u=8KQ0գR8a#'.ca,pm`[E?EFQXTJ'BZd#!"&\<bɝTaƹ;}mow b5e)k\Yjrp pEbl ]F\q'HܯT)׍`,IՓH?OA-q]aNmaA*IҘ7_.Wl)Dp­1[#,+BpǛؼJzLr@Z]kk~ w䮵ܵv?r@Z]kk~ w䮵ܵv?r@Z]kk~ w䮵ܵv?r@Z]kk~ w䮵ܵv?r@Z]kk~ w䮵ܵv?r@Z]kk~ w䮵ܵv?r@Z]kIr_=+EhryQQRfW'[NvpsJ=VTfHz[q /YJelk0,,>k? +tu1~q P[XD?kEEldI;ϸµ.*BȵPmLXST"\OEoA[c0C92.(R6Y{ GK.X U}LY+2{y2*T0tUs$nJqe:K9:Z1.mܞ#r7OiD6 c(7r{$u:t>UKL9SuK)$DCzЪjSij' [?- )GmgjJi[& z?E9֫ȭ<~I,Fup*ͽI/-RWvY؝qQzIݭhU=K9`qӨFC֞br79ID+P.%cI(2Ls'3&UuXQ;D<Z'"Ì0KYagMK\-O{U X]0CL"rvrIt$0^!AFVU91/;y@ܯ]\R6GuF"[X;`I +S%x `%dEwV<%\z7xI(!iN)ku'q,qq#9SԘU^\[Jpm Ƈuf8XM l{Vm?EQ2qL;KXiHqᎲ؄?zWb\/Cqm"]ࢲV] m2L\wj jQcLhů;GsB-|p.[W9GiL)pb &Bl؝<׆0eYESɏP}&iNVW$f $ffhHe/)v/JYAL jHƬ,J\1VLT<*u  E18,'i*D& g[}"%5;_ΐe>*l(CC7[f C;%#9ً")0 9Dj\o^KRYӗqr=ʲ28ŭq5>&Q%?I1;nlTh[*M.׬!84:5)%_[V6`}I{.׏_HѺܖj'B'yHSTb,imؽ1BaoRzU.FbCn56ߵ_EU|0g%Dn];Oǥu!Xvު [a\C(햕ݲZ"! E2WH]8D1_()$f픔ϲ|5ae3#m),j煝,r-XJoeY*xa0t +bqsE ?Mw1הck^4`ѹA')l+ T6@@t;졟U%H8U_Y"&X}XA"UT*67aEyT`C0MD:'T%kXz+GCy :9^?qYjٸX$ZaYqݒyQhT rRg}DiW~IlJ骦7X[-PG3.\*0t\0. {RbꌽHݲXOF2@i"$)vժR 4z=&x}}ՏJJ[i*C sp[ L AE];WFI\ŅRit`QKR".v(0R`,W/4"zJ W>e]wjUl#&vvKlpωӈB +_ɊwJF>vb }*p"L°טB$ ZZ>TH!nWZ>D З}BJ;Ey1J +5brƹx{yn;Yw5A~rpzL_*+>8jFImoxuPU^6VjIS0ubЬ(=ynY%tqGC85:/@VY@E-B KCe6Ϛ֙P?he Nd"p  +ҨIbc7!bPyۆ@~*R(@W!pA*HI܆Y<R\JVZ9[>ManpMP4s/E +JL()HWI'6iH9*4[U9 <DYn^Q h0&n;yR ިHG :dNY~&$GI*Y@Ǵ1* +0iyzl).Մ\emMi{Z@6~*zꃒZB\A!y)Fr/615}F7CDaZ5"iI=8AV0uԲ-PzܙFʟ?Ll'k`~qI1ϸ`>)gMEg:  j{ Jct{Y %E\TUj\kRhvBBlp@٣$R?gqaNsw];KȒنX' Y +k~MC( pRUA`q4K XNQ,5]:m| vI7XgH y1`_lhl~ﰙ8 |>TXC;lبYDH|ʌDȀN*Ħ ʎ&:1Dt2Pd3 ښۺ$;_sxpx +@PtΜ 5H JƵLg_6-2dҁR7f:l?p1 AMQۀ;jMr1JXZmpY~x҃x/!jA; +#ۆm\#@\n`k]LΈʅ1184bFy [YiSjXux&q/g_O!3iJ ;֍IF's`3laT!{o}Yn?[ip( @重E@W`aA7xLP'ջ$0!#Y /,xF=̻$dQ V3SS;w(|4A*T#Rs_/S6CXO\y6^_;d{(C臭<+&6oF >ïKDqp ,b +hcVZj27wzonEִꈍ9do)e5f_,h0۾\>>?t@QQqꝉWGlCmk$ ӌGׁsJ뽀'HHeV{䠕ܯCF@A2J'}t ;:A0NCq+iv>'&`͇M؈#&r"EP4BLr?SkȈÌ&<R2AU<;8jhu`ix2aG!&3>0| ۴CK A;BG#@>@̈́!? $gQa&4l/,3` +gP+@X[pQ\j$tg]]BCAmA4픃Ҽ|ٯ4L`S|NhT* <>eacn`?!;``L+7T2j՘1z76u.HA#1 ƩM91 ;#kta KAXq=$gFnmzyHFE!>';  +vP P' P n~;4yz$fKLlJ%ظ;a +|fxnG-1e&lUX{M^iDq&2Mw7XG:lФd1(bo`$gC޳@CyAo@@H/lܨ"1@iP;wDYq&oMeL8Q 3bh)nzHDQК`' ^!\mbF,i|b%TV"@^0 6P +=d&(#x$g|RO-ڌJ X(urYCkL[br;x|XɤYGG\ ȤHM@Ѱ0C!nT_:@+u i3+mǁ ~3ZP06B04ܶQicҖb`F\T+DA$_@OuV|t qЩX|CfZ [)|ާ9< t +8^v*m@N2IZ:z8q1aL̾-CEH<nreĄ⨉?7bu7;tk҂(M7l2bF! +j}voxz? dsGFCQ?¨ 1,wq#fFgdb΂΂A2yZi[* aRrgBI_@Ӆx C&e,90Cf +ҁ(g;PAvc\jL& j+F%25\0(J\(:(,k 9E'("=Nx#:nn;قB/,&B : vR~99_z=J3'g*6" M46Sаtr&v!sƜA`c Tf2>.oŔza; 5;I";8G}X#L< +Z- [KaBC O<ݧ? }!ˠ<^ذ5FQ OQՌ&lX,b@ 67lN8D+q`)O@ʸ3ne4a`6l ȃ\QLȀ{< +a1+d3'N&bF7`!!rK뜂 U H_& |lt p74bC41N"ig30h&ܑprec&'ۨ1;q>s@;[TI!>JMP z?@K>MO{,ЅOl?v ÎQ#='Zoѫ bSGw€P&ق312 ZqPS6?Á0s4lCPCF#,ˀV? öq@nf_fЈGd_! m̐=}>&|B +rUr aMN(`؆omC>Gf@&!T.bvp ^x݄\1Xjxt]Ș A{!Y4s€[1.1jUVbC#TƒE< CVFu0KT@w0jBɄٯ!F x!.SQ4FLoHtJP~43S W_ wc&4ag|lj>츕Y8m31n!È ? U}|䘅A褟OR~888/_=j&D6!IDՃFl?[= ,T7*H +0xPRkr 701S#f2og#T?QLɯC$_vox듛"ut/ǣCN~)WAI6,Ls !~꜔_bN6=͔p,4H<#;AqQ $[8.'?`0=E/"B B qFɄFQ'bmBi؉/6b{-H X@ TcVŒD #\Ŋ'\CA6CFbAk@zm`n=:5d懭 Muq:b"!#&Q> mMGqփGc K[ȃȨ1,X;`bIWaxzt@ Hh+ +2Wu t#b>?jVv8Wߐ~N4jtpSn~'r@Ŧ6X +"Lгr6Jm$A%ߍއW}q'߾qi2X %,P3YiL.ZENz4rp#1DȘ :Ө\dF]Fꐑ'76tV:11d+s1'i;3wZV;]lx g 2z|H/mFThq q苡bk+ާ> X V$P n Ow1 ?D`Q7٭w U!QAٴNFwG? ?`s79ɥρ+C X O2bK.: =N~YɸOI,岈P-d0Whas`x 3 9dMɹeP0FHyh7Bq/P0K< h<> Cp&$d'xs7Ϲ +Y_NɌΎ{CLG"`?#9.'=/6D܇qah:,תs:Ac#{h9ͯyeߗ tO@1'?8Uջ%@hKƨ`qĂYIKqIJ10eCIŤ,dQ9>*v&g)c ߐxճo=bcgn6z|'$zhfup vvR7P2Ab]_HDr~):W|lh@HvrXłHb*Լr`SxgPŦf¥@~w]bXu="h+/X2⪝y 4՞/ܲsy;,T336ZBnZWBSjfJSLTå4`\}J}+qcn⡕F]# +pxR|+tZHn˥-D &yNxB7JEcaҺڲ1"@qwE<ڤnx53+5$mTa8شW%%Z ҄WF<^wi+(:\O^b#>*-q&z9' +il)妸d֪-6уDo@UXJ5''/5Qk9UϠYt@>Hђ yX 9:La&[ ~Bn4䔘Ţ5)fb5);mT)j'H(<=i tZ/ᒀO3:4v Tj!9"96ƚ͞h\VF%_| +M;:љ~#dyD  5-SrLgd!e:dgfuE*Zr=>;e"Ա%HRJ6:`ߒ Hipt.\Zd]T2oqN.btbNE4]X5AWizBPmORQЩ̚,i<ãLuxe(ǣj+"p Ox8ab5> f# )SjN: L%\_lAbF[dէ@~9ZÕxrtxE*ޡⓑ& Eƚ:h'[O3rsyc cZ;3م3:NyheT3h-F;lj~A%ld6h Sr~1;kT{Ct ~Pu¥Hs;+fB6V.VSlm.4wo[roN65T|Iα (zvv1bgC8MT,-9=lSֺly`]tWBGE+;ޙ+_m_stmGB~VmU.vnyuIS].5<:.wn9%rv*KrmRjq7bOfƦOkS`aBU>eb;ml<mn.On\;qI+ba`%Z H8$䦕ڊ 2{L|T ,Q)jX?ǧzJADjbr'P^Bn6;5VHIlIPZ8,fz;{Q:ԗϷwo.'(Rm-x(^_0͋K͝!I%Ȱ6BTܨUZitE\\7cA#@@hr`rUR0R-/4 wR_yCE*뽂OxyZd6al陳3 ,N0hĚJuX=؋oh(7Xk`m8u9[[9޽vqy];'^ +7O+#s'ϝ,z7]@~h9r,{>\n'"UZk]P;KS'^!{cOTu(dgΦfe.WnæDkk+$D|xG^zS| +4\_j.9sV*fn![rn1:h:-h+Yr%*1* Mx(sc ZkNp] 4M%)MmzNz¢AÄp`-@슳ha%2 41ZN5*Kݝbb'g\Ɲ'D*ˑ"=S[B~wNE9EH + V]=yuE)rczLB;l씋V\Ro]q"m>1)LzD{+'< q6UMu˸RHI*ř͕+Rl`2FJ hVN6S\K-ĪkV88n!2`?Ĥl(9iqF,C^["\k;Yq=b)7x܃f յ1IeGM.ԺsWtՇٯ?ڷO?w?ɇn>S?J%T:Uj-T7 ;'zg.=̙ع|/<̝7z卷_ g.fKT$bB.Zx(-rloykqK]?^=uߓG=r|~o?x}sn<+|t8j +.kͅ3ݭno;xşG7n.쩅ޠU|L\+Z>.>ᤙP[Llrٻ/}~rtӂ̓"u2{5%*f<[;}{|遧w~ǿ}?=qlc .A" .ڱ+!lR-.bY:{#ۥ o>qG=koċy;##E+*YbцV &j|X9~Gwqe|˿za6ll6]JVw .iF:.rI\JG/ś}_:}|8sQJCFA'#hɥNqǞz7}O>/wfةWV0K '_?wOG|≯vRy>\#ŢKvܴ!5_ko=s|Ow~>/?_ǿ/?zg]`LNJ5T e'kcۧ.^'ͯO~~>ß_뿡[^|퇉ÏH`NG +*eEN읾{_Əɻ[?z?O u."xbI]9q囏|WO~׿_>}Ozn-&q3A FN*FR^o̬nx'7O>_|_7{g.p05I$LW68uҕ+c~}?}g_kj7q?H*#D\ilz<住>쿾ßw~?L7:{s-!ZR3Lc6Y3۫[{[;׮\}?|O?r7|o~xf󸒟 x69}z||}|'}gG,PVCx ю01CV:;;=؛0o~_^~_}}U)D$5¹n$̭O/:}W_|//?×_~?Wm;)֊."QljӛGN>sϽ o|'_'᧟~?~/ѻ᧟9wxy ipV %tsaȍx{}_w7_}}G~ȥ{_gڰBvDSso}g?K'/],.)^Ct%n*.pOXhvgVN>O÷?~7|W^~GcR!z'eТo[?/ۿqzc`pbVܴ\[YټxG^} ϕU{a=8b#FGUӊSsK kG~z]7_zW{=.4Q>bsvLB(!幠VB,>~ƃϽǟ+yg~}{敧G9{fkr6YΟ {NAdvն\v^g}G_zw~_W^)Z$8ch9|(kxWL-\$of:8ffԃ}tT' >6MCZޅ߉0DxA=,LT& 6Ca=ĩyޤHAŏa,ˤ2|ԝ:yn~s'ziQ~ "]òl Y#8„(IĒ!%Qcl:gkZXKēVg\*ϻ ¨ fWGl&(u>X +ZQ1U[vXL{Z$8&[|ǎ +VRLf{l: 60bs?8"%E+$2xQω"l.u{$%R`8'&{JoWh]p Ep9GˬVԲG}8()(-:iE>=l:bл:H6܌/Oq4I"ɸ%CH CcNŌc]B∅L1lA &r!LP-3R dYɌL A2$>y‚ܼ-=+3B.JEx:w^KW& 62H'aTX011nH1.C6\Ci5!Rc5?v vp6vhoʾp\ky Y E`@dĔ]T{nq(!fJ.,o8ֿEH&[Kg|B~`=ds*v`=fn XUT[ʚ_4ۙ1숤4UoTM& ߠu2FLn'Y2\BV&KR"%7)T.o$x!1[BvOǩ@ +P>gGz>9jDÌ/װ`a6yƬ>V6"brM9^@NXIhhtӉa3jCx-u!a:2*i޺*QV̂P>HNadž+&:~)o#\1 +"uېu.20X qp+vq~14uH;YSZsё!#2j@0F0a=Fb8%µVb``?3rf!_\LȩOY|As|>2Vll|bdt5fL5&$KBj섊1)ӑ"6F$8d@P9{Mm,:ěmiѨuI\ZmQZ: =F(Fۉʘv,GDaOo%'XmfhWԔACU+0a!39bơP?FXioČWL_2DP66obh(,aTӿ>vȅɕw7`rX~t( ;m): WԂ$J r=d%'z +"3Bc/̈q+Y`nF;XT2ihQ(ťbؾ Ipup. f"\6͈ܺ>IY bCCf]򸙂4A#W4WsY7,ߞn& Y\aBކEUC.:p 0huP{ʂE> + &e-) %BE>.iHNRض!g̀O3l,ǛB/DK.^ `o6; Et@7* x!=^f5i_X$>3TX'6FYAZkv:j(߿yp b E?| mpc6LĜ|n669iKbv,R>! +'+@=T/'׈P7Kpjqf@Y&tN+u;ArZϐٯsRW1'$.FC%6ߔ&P.-':7P*rt[AEɩHvVJZ`a^ތ|b42[Wt_:uq; k30*?3unp,je=RYw oHE 읪._`Ԇ a9(< ׄ6yC .\1{q+3f6J+>(blo]߭!P=0lbĊGX,Vӭ!X(JuIYo$ѺWʊε+O;N8-J\znF|jruiѿ2i\NSsJ)R[wvGRS'R3g "eb\= -6<4"\W:iJv"2޿l  >J@MJJ3*ܐ[Wi !e6ZO778u5︤P-sχ#DΒRsR B -RB,JNnN砆A:-8.@ALK]␍N<⢣,h0)9 Aoڱ(&hGHZX6L 2{EFL(nQ;qajT] Lkm1)(%!S]/6b6։Q>(.:Ow?qc$dғ7% @g&ӻJ[Y޻.wf$hfvV3{wݸ3q˾FG6M/<0kitPޘXN\IL/h5ND\HtAM4*ڐs#L8ESN3%Cy/%,ZKY; %f|JqFqR]ǥVQE'p|kPJgS!lnG WZbT/7:/^7."a1Unum+"z t-nC\ipZ3srDǦW=4D > N{_(AGkDE>556nJ.v[ Xк1K)ED;>`–^?V`ӀRXi8˭;w>Ju[ؼZ:vd$gimq=u t*V~>K (1.AULB\{r@(o{RYFFT@]8,H $5Tc Pۃ6b58\ %ӽxm$~Nzv@)5P9Je&VԒ}?-n;& P?gxKO`ť lWp΅F9DƏzKcs,H<X缄a @v~Jv1(S+o +c})oׁuQ~BfԂ d &HqqNT&-dE8A)lVUb:KwY [FJ@)\8Gc-$(I&@he[H"ܠPi';鋽nC\~',y~M .51>W6gRi AS֠t4C2ݹ(eD(X 4]nl\{-?gɰ?͵c/"cFkτ̹1ϗeD.!JM/QV]yV؊1F? Alfǽ\"l7x&9vK.̸Aca>"*x^UdOs@MJD%Ai =39\>Oi#;bRd +ia$mmGai*]өhQIƄdA ƥXc2ښtP)Pq=`Xym~f4FG'?Vq(ݹ '|vށfpނO{X2I6>9Pt 'nCU2Q+'oyݧߋԮL$\.AN6) |[E\ BxmoД\_:GRau.P\~ f!QȌ(uA_0n\M7]3_;7k# k)㢕q?W`g/ Xt:~`߈7PH|L7RE=0Ez$x,^bKvi/Hϸ>띴c3 ^%JU0N͵ͭjbb 9*fCƒVߪ=Ɠ?yɈ.0M¢N1ƀO/`jDp 21?NVOnydnjZ?9}Ѣ4mc_(y!l,pI+gm@5&яVjmBN8Y7r0ohTmg۠႗Tޜ/d@i-px,x+. cp?am8 +@F<`[@TR.j3|v Z}ODbp,к$BN;pPպ %$:BQ[= I +K'w?ٸYa~(~HCZ + U"}DTI4}l|4*X_d'1!fE\4ySm{9 mǗ\B3Vkpswk/wOfkRʎZŻX}tq24^:-%f7My +D6>R R0xSHo1Z ؗ+2abq+VnrQg<&4:Gʀ4$QԌs|a%V,nTVn^F˛˽텝&#QsSnDąts0o*ޛjn~qO/ F#-1le Ly)hBGE!Y( +!4(x5"Ds+R^T*FP,z7Dg[HB$V',C`SNrE @8rZnKv xcMonFX㲲^_޺3ze 'f 0:*u|5#TǢh=K&vg]$qSb<> +3Zcc:-)%RZ8ɴw^+ +Z7Bg`d :PZg|SVxr}\4:QoδcI887mjLcÁD~ԛN|xy79'NIL&Ĝ8! )9?bԕ NJjpG>B}!,d:(0A^,gtR]>3'#<:qq$%ZnA BE +@s33$z,[n~IkV Rbk g `.VĀ.4RPk QZK^HY?ݵ6N]_<|kާGOr],#9Xz8I~a ´ @iOhr9J^*BiʕoOLsm'>txB1[+p0j}88aQL*rFg2x|K0@<Дq|$l=Lw7V=eULJGrC!n-/\.Lbم͛zqҐSh̅ŽdrҤ%05kb?i $-(9xQth KwN NN2;gR4(_ D_9`gly{LiBV/?>;.Zn" +9 ƶh4A-MZ1IѲɉ_:/RI+2m ι4>rɆ`iZ4993蓕 ԁmO ccs>^MURS 6mrt8U@8v +9O S6tEXR)^2yg74)Karѓֽl{p޺W]VH(xyqy1kGFJyAow]`O-gGl|Ow 173P9*ڌVۥbaA+ xƳLy? 6< 7qXWDq16$0g hb&Ц|i_p g5)LG{L"ӹd7OV{޾B/ obR?^= +ECצ] -^R71R,N;s&?LSv7 )9DLrIFt77FײL}1뤜$(;$gPEDQퟛAÖ1$Q(U?FG@'AȒuh0x /hbf(W_5Y JAJF 6dvlEpzuz|T\:y?m274@we&j>^ԃdru麜̹pPNV XQQ!?iET״a} +^4 +LO|30@':RiYkl<qпZZV",c`_\:7i!qʆ=! 줐7vn5 _ZƣpUTw#(BsaF3#L.FVrjko1ZF-@̱!QК) @*>.3Θ& 6G%*_޾_qF=R\J˷;OoܒKk7lZ5BjU wk|5-A-0HmIMpWd`OYDAD~)WRѲ Za :7aڳ⌛pҌ/|f.B!gZl>G2,, d +q#5?c+ɹ~k+W_h: +a*ʥ l +Y/ШP2%9'#A\(?r@ԴFY'Ȩ+X 18G)9Q*

~|fm@rkwx3 a糨T$$`hφI_`8I7$7d\ۋHFF:Iwj;y>ڽ/Ǥ[n-l܋i~ڟM;1"HC.zBjK{Ot7"R LG֍M'PZ)K/g:[o< Q+چރe7!uaJ+FuݎJ~VS$v\c.}ّR&;W=a_pk`|)HHn{ՉHZ+ Npe+ny9tusɇX4dt)e7voInwG-(;@x*:} @KV;Yδc^s`Ɲ|sK!3a +Υ[WJ `.j^u5X+[݌ Kˢy˄vv@#&'ޓ2#7ƄܤdXL0:@]29Ori9O x{bmVڼ+ UдY)ȇn%=ZYjl=HtR+Qˀ,eR.t%_l\htAGk}xM%\R+-"9t+ endstream endobj 81 0 obj <>stream +@"?^re:Ѻ}cڍI0Kw|,ꥍ\<:I y;&4˴i8 q9b#Q#(bťoZk@\r=q⪋F7A!փB!$ݨ +X0A&DZ=+-\_{^3pdn{_ݜ<\%"URix5IE +0kL:1KP*+y!43?lIer~\=ٹ<^dV y.9jWr7R#O|;o¢ 4󆟏Xo}HiQ-/w_ĻWCahĺuKE|xuKH pQLt "ngD@Jߘ.a&\'zN4jJ%9hO||}uG '"+ٰ9At&unc0 yaH/[Bٹ`he*RϺ+A &݄>Srbk8[٭> QCF/`rUM5擏H)d3G[Fc3KLnsrĥ2 B;;嵺Fo뛟ݴ9?\![em-1j9E&T8,ˋDžV]|էý;O$z!oeycA*gߤ1{HV`>[}pEmda~>Ɠ_-'ڕdp|+o}'pi-5]t6<./nȳx\(5U6 ^ryr5kk;wosρ;O?k_UVn+eBIk= DnHGB%"ִDdBVh)kNbք*79/.O|4( & xX pIJ@e. P̅2>&j9۫-tF3ȃ?w# @sb%5{4Xvf{f/'F+j` J.Ci/z2vD += f/L_p:(?I2\t fI|cutQ&(dqST$ iA6ƪ[%u6ˣT0[EKjmԗI%7Lm% ` 0k +:c. I561AWrڍŭo6NÃھ7-)Qӝ|su 1;PK+{A$Z[M'\}ùe.57NjnuvOMgoͷ?-&ڤR)` S/@Gi \xEP6uI^.ƆF}x)tҝm/xi@*Y%ד %CUR >Qy]H +ȆsMb>G(nTfi7>-\1z;>j?1iD z9g@p PӃpqYktl*D^J!V^ӛ{Zc!5ϷTÉ +t?38Ivf{&&kU5Qyf c|a+vBVL'J+1P)a@ ]7s^:0)ŔYǥl@(zqg8GLbDO*bSR,Wj/%251˹Z{hG+HZ !ya:?HAV 'zA+7+Ha=;?||#Ȇ壧Rњ{fuյ?Z=~#]7?sK0<頹R}t/5-yg9Dƌ6{zße8$sw)xYYi\*%!pz?2RD_2RactO|D擏oC :i/[t(7jfmf-C|HIc)YKCi'EIZĴ`1ik ҚV۔Rio~ lq(-¡d--J.h f&Ĕ 'Q;xe(?*a\Xܼ>ڽ e򜋜n-?|ɓWalp-aFPk]OAA<u\z*Qkv@,fۛdp8\#aebuLb,.dz|h>;R:?3x1sZw~gZ\u$7|\0F S/A*2IJGR}@`AٴHXrQ/-f͜(/y،1 ) P j"%9tvҺ/E/V:[ƪ# <Nڐ)$+ )^7IJq +P 2n,HXIr@IvP.)<$(AJ*j<*P?DVf<06/ׅo4'INbj7>'"Q6II1V@H'M `u*va<8ѬOԳePcbq`!!WEyS`\Xfx~21.pG` #Fy9Ӗm\L +rJP(:&Ӫى0d +a)NBYUwpњHJfuS^˃VՊ+ީZ2fv +E?@E%P!ZX𣑈ݽ}gZ#R=H/Mvø`ɍv8lND" xi9]_Iעe97C2Rl4"+?Ws ,Ai9Ҍgę i&VLڍ@pJuaQ6apywyidg;/žW&ePxA<@Fl/7ؿ){z c HxU%U$-2RZJl;lT@ؔB Frb'#7fc/j cx= я Nz-څi'!xN D!+!ֈfz$5QƸ8.;`E/1#f,x(rBr)Jp"0A!䖜`?g4~4V$=7嘳[WtlΉ:<$X1CE/"< P}#s8%” "DpJBs_vc}ܜ SӞKS4Dt>bdW8 T<b>XD;zLk?m~6 $9)1iPV71kG/zAqPS0uB$d͋f7.[ܔtᬬDkwF!G# 1{[QL]LHLjZIY1{|wsˁpX<F% bbD(q@)HBYwʁN'bDCa!F\[@l]7g0@hTC +|`46 *W+'g%drcM"]ؒx*oIo6w섁GRdc3-,' +hn8@IN´]OۏIgX&$!VOKvOnqnj= %I7PՁ݃rDs{q?cvL:"lXH0.SV`aIwf.G$<:stbp2_b%1Z% kXg/Z.Ng͐݅S|ҏJsV 2Q)=@%^Ҵℕd:zy5c Z4""FF,f'ē8Ñ d.ژ{0"grv4Ä+JLUjyv9a\>Vh4;!bfa}]|q"(d.++ Q,OZ9Aq* dYJ&!;I #/;۝ͅL=#ka^Q|dxگ KJ$&  j T/~"];C.2mqΏ/yiK6{P +ғsA0t6,DRc[Z2PS"‰ e BŊd8m`&%Jr1?*JJyY.1T*U1VÑ0I $4lfT' |P2 .㶻NIj|-58^xps{YE: >IE A?EQHDþBd1fXB\Ҍsx#J0sv7ew^8.PH'q&A 9'|~ji' H #0h'GR=)ZffRńH*K&Ӝ J,)w%dt+UpU1>ץRIY={r{Wܤ99y4'A##rlymUdm孅??O9O K%㵪mg\L @ITAsi}s E,x U{l? Ca#/l02|Z)^]_^sY%S-a8C4|9S3q1˕Qfaѝ헏>zuGwn #0E%5%(·BoRtm.^?Xݣo:wѻOn/eQA1֠x&gJ:^U_RkWzœ{j]O](xг9wƂ^{e^'G;{{Ow__a2DIjw9msϞ^e|Kڊ~}z]݇zo[zpkO+c08&h,54t#G|^OO?~|o<pn;N``H%+.Ġ@,TFY$AN×_?O_<{{e{H0*^2\,Q.`p*DYGs +Zcwx;/N?Oyg OD|Teٗ;7ߩ;G?|u?_ֿ>_?NO@)4/kkJCſ;×/~ѵ}/_>>OcrdAJf~!u}:^^rO֯#齞$;3?bbF" ˧yL}{[MWUjp@(r$RD##)Bʋ#iv$jFً}t9|<_~_'>M4A97_A;0;=߽{߹g?~g{w//w?} NT8" +kKo%AM +Xy~Q{w?_|oӟ|[Wh7/0JIensOj0/fov'?|ǿo~/^?|;yR(Y HLJ9I1ZU1 +I10>H%(lYv{?O~oWۏ/J{YC!x0vPʊsd+KwLlK>???ɧ|_Gŭ}t;-kf#E9Fr^DoNx:y_ǯ[Ogw ppY^K8âq]xw#o~/}ً'ݝQtѬ1.pN Zz7 emxRYYyRF%kVT޾59|R]UXǹ@_ 2Kkز2Sΐd*gB^(4nA=-bUL đfs =9WBB FdyRln϶G;-Gkf[Qgl`z(C<(]pV.7&{{~uT^sbe?xZ{c%1 asRNx5$f %({z|tquI' 98l%!U>*Ϗ?/Iњev{5Q*kJr5HG /Z\V-GH:ƓZ@QDJИ{(!d2 I Gl/P-` Ƣd`mg ڍn*\2B)}3_^%)'#7W\_Da0PBd%KY4fT5|-D$?~Jaޘ_^PA{n0IS:zy#P*Ihcrj{_Cx(#-B&G˫aD3F'#n2_NדfJIsi촲 L2n/PfQ9?`"k5\1LXQ2)drDIR.Ug`(T!EW3@~+qF͵FJN uޝQy-JEs|u:MȒYlL0ΌǓIsq [kYm}N P5FzynVvVT0)aB57ѹjD 5{pd|Ii5aR#߻-3J򥕘D~BoC{ZQkqGs\Vs~oӕ񖟼C⡡_zkcٻnŝ`Zd_LRlɇ67N7IKf+p|V(mjJqm3ьY|a!ʛ>~h5R+xؾLnnO-L;ĕVӤ\ƹmU'JW>GG?}MWO{g[lB,Bi l^i8{LgNYwD}Dm@}R) Ov}N۽!"@9zFn4{W CE\q%QFZfGz)(]~:aO`:6(WcFg~_.LaW|Rz3Ftn0; bQTݞPF'JX z737lfBa1m VmՈzBDe.ѹb!vBT9$1_8 g8YM@Yq/:<0"Z_܋ f4c7bZLw{o,z5 %ݒی&텙\Cq0AHEj՝y(Bwh5+[whho/˨pҏK-.Ӫ2 ayB8$_o?9U@_طC67ݖ]AM^GRNjizaZiBG7n^It/l콓zwrC> nPˬMo~=~r~s*ؗ: 68sIq}w/-T|tKQޗRq-ұ<{qdݞѾ)OAyEŬ>.6ے;JnZakxT +3g-쑅]Dl{K/m8_ XZ.%{a/q ݝe n?~ը۴Uub[NzBY JP?V;%0jńqu9ZA8Sv掟|u9y͇H+L:rq0SʇV//f߲|1%ՌPA25IgvKg3fèPTPq^CO;LNSz퍌 Ryj5ތ#xcym~Vv@Ǹa T?'bi \ >+*OZK<_ʯ2Lvv_ˏn%oZCZwF=)o>||#ڛ0:J؃\cSqFZۻD7ʨO\*"|5~*mJacjpܺ5B,)?<}g?z/>{1$yO38b\U(ggwY>jwAs`S`x !r +npXoʕHw>"wo3 QE} INX!|2G,oTpk{ q)@0js:7g~Z^vio)N߾q=gL]߀߁%.6 +\=ȍ/pV`vQi t'fk/&xre>{ۿ>|iTw:{ 1?qgNnq|w|oڝ] uͤTʘ#vBe?A-FojRݛÛ'_waOB+ {'lս9iDވq;d~B yj6bBD Hw=Y@Ʊ<2w)Cnt!Wv|Zܩ={ry VpGĔ>ݧꜾ.Ξ*9ꓻa'Qݫᄄ=->q勗ѓ_txn?g1 ^q)@OFk{=hwΥډҺY~~{ŧ2nW랲VAir'Y;bPk@8CLmz{{sH. +AK +EPɻ vݶ7FH BF-o؛><;`@_~qدpX`sV<̶O 6VG'/''/:_ҫ϶ e,_ o}g3>{iӻM#wV*i|u|f8{.u>;zum*7^s xB~@ڠ9c}nPv<8*Boj@wy=8Y3цDy'|iKkSy1[jѺႪG:z + +kٻl+PEi-o<$?yӇ"hZ [m >~*f1jӏ}~1Փ}XmN=-3wtlVݷj5A}{}7գa-n&8 gi@̍x~<8ze6oJPUƔW==s<4BQ"k!cF_ZS:4m\obuvk|mptƱUfB@Xn째z\*6Rf+;3&;̵=h" jĕ 0h*3BA<2yBn|Z̳v۟Ѩlcz!bq3pZԌ\ԫӤ`ZAer{ &`$mQЇ]7GكML dZAnu~2D ޛV_PF`vC  y=(9*Wt$ޫԷtN,11"CZiɍL.ʖ-gmsW(}D@`[@3Dm_i=+n{H~'P;7bZA`rzVn+n LońBBmeXإ-D&U?Dz\l["f~p:8y`]RپVx{ɍ$<+fTIDDӹ /׍G_΍..]A^~O7I$!%QSZp qn4!Bqg!zRVts_]1%̶9Az+$BFR*fD)H%~{tsx$ ++Q,n^+֏٨KRdU՘?D?JKÇn"a)SH A|mw'[A:r@UkL[Ǡ7kGѻVNoe=7nArr C˙:|w~Z([LaLkqȹ#; xL伙սƳQv՟UR2fӻIH5#`RscBq;L_L8Rq68}VtyJ9(T+)b̍r9>5!-VA[ơTݕj;f+BX#D=ʙn B5H{С:py|)*82}\X/筃!҆ m]w3̬B=H6\3)lAHnJRJab$̫A&Ɩh&U6; paz3;in9#gڶTj%iHbT&(iؼ1qvrs#@_CRޤ.[8SwBi5x@34GQۘ3fbuzuO,nGm7a4io54E;S.֪ W PJ.J+[ڣRffFJnHuJ_^ˬFD\o͓􁔟Fps5%؂8[o$naT X B-fJJ,.TƥF-CF'Vj3"ۏE?'EV>*ϟJ=hMXmҨg1΍Nw߷}z;w~(c@57c|8L@ʬFC2f?7_ ޡZr5)T2FWagAILVOCl~U[JzZd-B܈%Vqm%S΄+(|< V#dSbC0 zM WC1BN9'L<<^O pIƛ#z76|q=o +*|i}5&PzS/֢5?N/vUdЏYݵ{!l>ڴz7.S] (mi|Pi1^=\hi!{nmYj1͔!P~DUٓaiѽm6{(wP7\n_.nuzSD$Iuv7o,G$[-BzOBNa/6 jҎfNZB>]IHaL^d;~\㽱ӻyoZM]gh BlTOoهRq~u\)N2A*}i araz1!RLom`P(c(*0k_Zs([/ŮF$DV?F)uQ^ ?I\ --ʰ'r `5ft' nti{lo[\q}p& +\N+U>Tl/%q<ǓXMȕ5{/#Bu9JhU4RM*ۂQ=yǨ;% AX?^y罍EU%?bqJ,CQnj()^;"b7GC1ѹZ .([+<ۻЛgrU+'sAcQ-?,k} +FYv?9ib+VӨY]1PBلD@X@ri/t8{ CLXݍ%ݴFۻeV7rkQ* 6FtnJ&0i͙bn2z܈Q^(\ o3jk9řBbݱ8[XLH*^ǪBi\B\Iu5/1yd +o(xV5 xc9KaLˋ90̤!>C[KсPjk-FUiB7Jۯ{x8QD=L-qPA" 00*dӌ$eTvqzF.Y܆ %Fiމ{WiwP.Q*ҌѮV9r0ZvfLIHUqRez9%!R)2zB=X¸F0N߇iLnVy?pqEr0ڐqJ}s,{wJ]yu3?ڇ~THIjwFTGo=QAe|ݚF6`7 N0)TcF8ӻ%X4 e?]Btqq7%Kx5{5%(һJ.6bt~-*qs5cÏQ6Ze/qݕVV?"=q>t! DGWbXH^A@ȸl|~[w>K) v(E87g 4y˙8J0xQjF[bqb獒O༴o%ZtSB5cb r6 dɍIe>7GbATO-2;Cr{c59HI5zS $:Θ x k3{A{;plדzr;',_0]@8Db;ae|ٞr%do5lg9Lu3$*6W |)@JN; b+0{+Dx/NmnvZo]yaZ̍^q/M̊ u +tO)gQ?M<{)&Zʇ\9LH˛durPϫQ͕ ,L@(aY{SI֗%Ln& \s@saD_|ُ~e)rai0/!}PulJ[=t`/w}Ae3z`RYƝH3;K衔m"b)r 1 ǯ~ t8zwf9tFJCrʭ$դD>mC jRX + PBTMy`_$ŷ6s HXD낡{71mT"W!#Gt;Ǚ_lUcJB!:4cqI,f& b5*F<$MD]Iƺ3wj7ߺTKTV0O#8~Ja-&%hƌ9 Ũ(!zBną bE$(T(({#L\ZcF71q=@2_]ND#KSZT0[F zWrΛr'.bt{VW[_L~B"$,kvT+osN2Y b +@l!R>-xJmڝb-fO,^6^Kգ`#DvH/ĔA3zUY'@ R-̕TLa<+$7/oYLuT_cZH*܎1Մ2l0!$Fd'>:n}Շ͇&8\Dq=I;a ;xvK+I+x AcQrsqU;{h}( Z* +v{%B^S!2-_=Y@ZLJC.@6?,mb d< (7.T{K.'ڥ |-% +$CPHlf(e@nFY VL0KZ+OKPzXctvԮ,C.uruOS&M%K+7Bi*Yge_R'_Lfj,(\zg1HWyDlK~,}-7yc9}yKe _ a*1nvaàҬW)VWJ3YrA #\()Xnh6< b6!)*Mh{`O=Řݿ/o՛\q:C/ExtP8 `Zg1az:VK)lv"Q *u%$gimI%wv )#ٝƔ* bz!7ĵk![ʗ$\q}/mHHUn/՘䪢7'5@ ܄<_K|R3dOGo'f)'冏pǥMD\OI,V vy=̄YIDGPR__.m_Y_@([-P$Kkhw +~zy|q M_嫱]O1+hAz#YX7fP%\_R!UUgCۇARHَYJocyr$-5PK 鍵?G (8W$H 4RbSjZG BL9j 0! RU*riZEd ѵO +J-(hL38(b5"|2 JR <ː|R ,,NwI1Bri/쥤*$MT}j7f:WbWP]ɤ5 #+[8zJ^Ш%P͍'C 96/٣|6ZEp(g"\6JQ +yPJ-p6 A/HWy|IE ̚@Ψ\aA! !k(]ZxV:1f9{)(f\"!у0M+@Sp `9ʭu\nJg D]Oi nK +Y2W.E%&)&ux)Ià+!&e1L/,m@J{s% "1Kώ_Q=}s%B^̀_/nOl9rf?fRFݽg>]*2$Аj^FC/9 \CƇ^K,Tv֒:pfJ.+"Zm?c}H6INRW,aj HJ nځ\q+VH $ڈH[Cw;-U6JE!}1v3%hr+FhgeȲ\ǔTETkU3f[ݤ؄4In-JzGzB(fjBx0)Ju#ʬ0fARr3Rv4P6qE5[)c)g `+)抛I%T)fBPHL)+e_j[vTkJy?Ay1N%7Qe9BzvٻRZ͆snuBCfFz9D(7Y,_ +11Eo\-1_] ŵJR)XZ!^?bFZCYhjFJ`kQk%]1ߟv%DTRkrӇ9W0{5@18$-pHMkAo!;֑b:P˜*cM6zP8;7}+!BWq*=^a4aX  +=-r;3BftAmQ$^)J@dYA- t<CD@/C5zd-!}9㨋fAA&` ly)×0#F9)(ރ6A" oR@ rq&+E9|~?G!RVT-gh/aJ .IVHo ԄJTl7Q*Kq=hc"Z׻i- +T=#[>ԼZ "wm .Ha"v֍ ̸,A0LATZ[\ obĈ/ \Gŝk1eA[x)h#zʎ|{ُ^iE77V?3[{Q,iq `shoFOd>T Li-] 3WCtrIu]{P#h?b)/W2oC$Y +PQ*O[3@5(s-L/YP*$g1r^9MhU'$4jS(^K q=w;%qsK6(UJ*nV$Ζt2zió2]waudQ)B:Nqפ\je}u)"r$I^I-% p;hW7a\Qc!7UL (N`pHsƄ5 ,@hb<+A׏9w +v5Cۺ#Fk76@1v_."562WҫQ K>$ArYкb`.aԌF 8 fo0Wt!Jfܰ48 $%PuD ^BnֵZ>B2@NP +n8SH[DJ6 3&YaCs7!T@xVpgvpvc|c8a\,1/7O0ˡr J\ry5zJ>n|>ʂi4ӜVb4=@V"zL^ +Asp9W޺GC[%]]O*E&j/n} +1Je\)Na/ƨFVmb?cIsYe1M}{3.֡6,\;[ba6B8[rkB\ ).]?#J')u3Ƹ4~b`1[i`&*x|,㦄NJa@"b-kb޼ X*+)}'<,{ebK 6P0pU~Pc-X!F(o3v-/k~f# Be[,-B9Bd7G41Rt-MimnfZfZTVUVuUuuW fgw$ %Kǐϲw2=``_{Egx}E|kbjc2B!Zwƌ5 A%X[Oƻl(O<ٿ 5?ab%\ X>pT3:`ij Nu\ag *`ɭe\Kj}'i *Ӎ MLyR(=+ޥFʤS=XMXPÕ:5t.SF B]y~P+]E3C +_:ct@zL\ sw [wO? , +@ im0NPMHcR?uۇI6Lfsp_g{Lkqy Oȅ/e)h͸eFgdJn;F--`8t"2!2 R^{ygab%ʗR9AźQYv3B*AXq" -9Sz~ڲjTmf'eBHdPXVZ(RQil=*H_݁U]ʥi0]\sVK'sth!~)rxmuPm?n0j#81n-ơ|l9\n`Xt!9G_4$Pv֢߻YHuv}u.—h+HM$,.30IOTSFiٝÈqlaJ5)b,hY!LO%o.*mavt<2#D&*1HPF] +PV 62m1so扐]2I~T&gnսn}! ,Ofuo_oQY6PXU[DY'B D(6@1LېZo(77||{q?1{_@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nDFn/~}o O4Or'~R>:b- O! _KÝП^/Z-=x<Lk1x) }k5.>StJ( FQH~Hz/REa$Nx/?>qEw) +qӋg}'O>)~¬k:D%O?9O^pg,v?SBFC2]6=[%SYk>i{o/k)(/dLPZw C5!oÛ|z-D׼"@zL1I#_jq\ѤzJ%:a h{Dh-L(io97emuB1v#&WpLi;]4 +SS7lvMg}IgbF(eW\2R(!vQ̻3cԏIk ʙ`j+dS٣ZI5D6m*0n"\QpGf/L7vsQ ״> }DmD|8=gpOas ]hz Ï By*V2|&CL6\!5abZg6P4#Diff4) ”& ΈT[ bF"Nu pyFP}5EH'L..P怴Ki v<]@2ʗi 3ԈYBl1dY}!B9.̽w?m$eRF,!H! bj7b H!҂G\JjbB5)V[tv#Eˏq).j'%(ΌL6<0&2kCB# J3HeEi-%gh:يr e%"1)Wl'~TQw7G5ƵT*={\ֱ`-$B/7.KoL'Ja +Sޮ\J+SFۈ/BgFB(JCoe:Wۤ.;֚'s}N8Fw~usuL*IK,l"3!2PL9+?#x{`2.,Z߈ưJꭸXMPKMT?nD00eqo;(II3Q<aʖ#ufIe=2LC)mr5Y eęl+Jj )@uʅ_~2FWr=I{!&Qsw2.v(KdIɏ@0B&LB1)QZ$-CvWoWѫ?[򹙷AD( KX e!!2KuLHLn$jLP*l[c&[rvX,pA]X_ƙKJm(=zH8[!|!k އ*PcnLuBbP?$tL(z5rUT_6v(m=yB _99kΞðNA*lv9uqky͞jRDMTG%oPʸb|IP>2IQ{:+GV@e3_I{E fqk<\ڈ +q `!F:=L(Eϯkn5ʆH\vAg5{Rv6 =L|);!r- J ģw|@$rZQr>`7ZRLAIO04+1z^KMF(СkX?_QۅI_IUJR9m,VAo*i$)7R7ܑ݇Ry[gd:HDnZ'øaVC<׫s4%6 -J5q(4p4P  mGHOdt6F|vXڝPƕ:c΀xA_mDkh}vRaLL8} z?obr{O湷9XWa~L_Gu1cb"֋ +F>m͵(>_RzRH,Wg^N0ƌzLH)LYqy31`䎟Lt62T&'Bz oMvৈT'1:@Wx(B=('ŗp?#/.SqiPyZiŹAIo$U?fP-DdPvwT)6zWB !V>;K*-gJQr%<XQZGI"S=Zi-)f;i&gA&dXs.Ÿ3v0;< 6ʾbi,-+1_uZDn#J͌DgO Xnۙ/yU >Ak jFBJ΄wcFB2#'T ( +X_BX7|qNmZm!bCOJ2ܷPVc5!2VOדQΗB),U5 ,{?m` +Lw(vhPː0iά1i#&Gp7VC(H =V#gԽ`hxLأAT&J +[ƞ@Z7%ί黾Tw~BW(]]o&3A` RsօݼqV +jF'6ZUΎ@sNlE@7Pn<!%m8U&\δk'usYB.voX %n@E(8E*,@}mõml,_B)68 N^w.&1@hMB'N!_󗿵+I$N@B%D&$۶6RW; l`!6fB&Rl:q$WK[lƘj\6\#KUĀa6gcL0*F̮?fBl&ͤ]n%_B[ k1 4ceKb5L0gBm׀2*)ˏ~@.̈́H$@jP}9 !5V˃zJ6@TU$Ɨiw%.@ǝ̳ bւNIaR*,iQyrG١QY产|~CtgVʱV9 R0J#; P&q\i7WLaf2}C\).RZ[Z 0k;)qjS[ͳ%0WG*BF,=!ُJUvP[VRe&&fR FJ Q6{GZLdYFZBnm Dn2 Obf\J)0CQQPFBl">B|֢x?քT3#~6G!2rXDŽ_ @>"W +V8"Xc0&UB}TAcL$vCt&b\v uрXc1h ǵ&`R& rzy]̂I Q-I ,TX( y n8zIry^ki3e,j)N'ov#zb=x+8SEh84gPƇRD5u7@[I1*`N&'?"Duq -_#k6UDPv+6$0ab%'8dp= #ie8wMLL89}~g \B |\(ZGt' TJŤT +p@9k6;E*bstfdf'/,mHe?mݙT=+,T֎s!>mv YH(_3@8dzL,Aw`$wG\~`qrE( TZ!`cd&aau") _Ea޴2ڛn-!C񀝇Z #ӕC9a Lq:&XUˢ&DDZWbO֣R5 ϬCa J(ZW0*R6MG܈>DËr@R^ zhSVr37H}<2TN[u\Ck*"N֖7+ +vy%]MOIe*%TI !a¸g{R2.4 Dݹ3Lj cBƒl1WwRpF:)EeqJx+g0)UI NB9Kc}B-iL~M\CTlFe(){-P Q]uJala 똺IpDTOK[oq{Jn'B!BR.ATD0=kIX(JQ +xLI JiS*< QQJ1D.`7ډk%F=< a-@H8eNϪPi"%nޮ 5PVҠ18ڏ(y-NSr^v@ +'T @GBXț u@ n8w?H{z|g|ŪZ(31\6*.WgSg&F\a6@zL yH,&.6zB'N@φ "JO%:x\EbϕZ{{׿s?|FFȌsjnCoC&WWJdк)uD!T<rK}׺q( \>T:h'R0 (DhuhB2TPT"iCXǨ1CՕLiE-y;$N2lnwmދ 66.$"_0eŷO7>t#J'`nж1`/C}&":Q<Nm=BC%$(W 2k 8y7AHUi.Z=x> 4H |3| "DphՐ`i'6bDl?o"`j={~4*)M(-@ixZ #k\ 3 t`cm+ +-y'HƀU/"@Z+ 儈p.f9 Ujq6k@DI>EEm>;M0kݤPRK 5\QF ZqJ`m4719%Wh yTIi0cC.CԚ8l`JJkPOڞ'Z>TK K;ҀSv{a&PgejY\ k@BfRTFы0Yp`|x 6=ZOy  +"ZHgbqF0FI#pHH0!*a +6P˧\_AL +0m7L cd`?)DJ3pX:lTnBFMN6F^e7〱z4q7R6W,<@&ޅ +^6Hz50)AqY{PPtx/Hou*D)Aq۟T}1(|wl׸ىҠ]X1(]v>L(50mA Q0N'D^gV:32J )VrJozkz? TGU#d<mDlD +Sl2F1L~ !f K|vAOBfRJûDkޚrv5H(!:ڋ+t%tLHq`1erT[!4B9I0j/Ub׼"P R*-Bq/Wv7xLJF;@v+/Y&z\HHwx3Ҝ5}|MB0r)FO,2Ks| D_B .< DFVJ~J0Fm؍݄N3s|bs%,=tYݥaJB : 72#73P;Kqj.mO",y)Tj  biO@)"1,}g z/Ζt!ލ,xl1k;e\-B91.T9Iy!m{|?R.=<*3Z\B{ 77` +.)WQ&  `x p7iKEtRR +VY$'IA&ջmAlę܆w4 8(?󻡍H +'_$"+6Z<]\iT'R|C/AŪ(Ag?w61(pBBo`` +`ƻ*hJaZo=.F2LY~4L|<]XK *! ~ ZJťk"v yRM&%0zuԛ!܌(1T#esp-NKNޥ՗r36K*I.$Ab"iPsOW'ݗ>D5[QJ5n|([TqJdg/ }փYqp&A`ŭ4Jn`gab%!ZG)n +E*h}%ʀ +S$_  I׿}sjFwA'/΁5%4\'<qg 1d!W?afNMT`z\ 椒d0~D $@Mq VCj`AԃP2NФ6)4C;멵?[Oc%W-FkKL4] b&MԀ2vPs -p +F4 Gny'Jm5`VbGHj-ôQ-.ԬŘ <GL3${sqa5)OPJ o,P ƊS&&Am~ԬRV(=`.td6J <`E|LV~Xna MM׾? w#L72_\}I"^c4@I09!>:5/2B7+D0]큐1fO'62&\*l v +2&CchZL35KQ5'kɍ%] Sq*ԴX1wF + %!P 1?]<<L-@Re:g?gN#n@\rq#ɔg|?ߍp)+N|3[*[jMaΗ} Xe?݇%+ՅJ dFzzi= @xv: o +ԏ$ +Z j8_ &q!\2&*o >57 c-!#J֠}ޙ1x`FL!rq6HwD킑Fu q5Fk119SDeIk-3LlQP3K9T"Ñt $qL; -P>%54N *hπƤE mDct&=[}`ơ0TM> `lr.'%VF0@0#>Ab5([`f6\̂^ ct*H?]#>tj#; x*ezW4]Ow*Ǡ6ğݏd(L@Ja\ +/M‰s.;5Jy)gZ}0;TfNygO3KDjRDypkjQҠssQ7MFT1/š1FS҂5 &g!;iNWbnXi{ "IʓR j #MC[]LmAHugwzդ +.q>4oB].7aazg6&*iXg݄ +d1.[{ܻ*0gAt1RA:K`?#L>ԏ1ff&L#ixs=ƥr+l4j .J_yW.PBCu_(KKbj|q1kaX5Ba/E&h,}_ 76J1rԻT3mV~9< 1j8\IEgsR˻Fm׬$y m$WK;c.7-h]pCZm'Př=+n=7iwum% FύJ2rcfGP~YZ 7pJuJ  kʺC!7*/ &0C93#vӹ-Lٱ:@<6;3NuPfOr))|S2>7KqTViGxU V"ROqa^PFI=\_GLi x8mtʶRMHm:ӋKU? 0p\K[Z_@aŭP+m2# JJ-'"!RqAg0L +%P1ƍVQp@]ւ̧&"ւT>K9T;w/AAE,08EjyJe\~vGe t3UJ_rcQ@8@j4 %JJq䳔Va.eAG=>;gH7SM[=}'Ba-4.L/Gby.GJ~}.R#\4q1 TZBA5}+{-Jg\BB(HhmH(5/œ{T ɗv֙>:ھw譓 :3\#6*c\!f럖i09—`Xw Ǒ!]ʈ%6X&&C0c^fNBȧAHmHTvpkT2c\)mRe&"Ҩ5_\ydΉX^f2]tg~/wXoYcL*SP PbafJez^LTJ2@ t78tG .(N&W9< ]ۃJ-ե\.LAubIy0w^;Ԗ/u-gv|Xٺn>0jKm<% WHեV]n=N5TJŹXs{}Y^\[aUkje<(̟iw+Fu*>T aoN#~`ڇ_XsLmn$%LR*Ʌ;85Gv}yyjiuh/RJn;[f e"r~w_\}T=,.Gg_o]hL0ie4v~}Ek;{+2'^[1'O֡\߅oQ9$Ux/Ku]}y]e;s{ju_uluNӫ]s0 +M$V縼q@9L&&EuYez|%VfڧPI 0X&FP}E8} G;0ťl(jjg/g;/ +k\vU献o[Ow^C\n78][\ϟr~|wNϋg=Is~1fՎBg٩M._{{5i_=x~ts" S)罓[[?i~TOL+ݯ/C ݣG_Ϯ;|s߈WZwaV~T)"zĝǟ>O^[>^~>?֦W-AZ0 +;'wOqZxB{NeNe~hUJY ԿVY챇W_R ;oJFV\\w]ۑI~iij|!6ϧר.IkE7/љ5kvyv}18x<;{j?@ze\ln̟e{˿:x#@块Vl>۷[1$tO~nxw[4Wr׻O~Uv_~7 usjmݯ}f{խent{һsl@ Kt~dTg+2zm+T P /g_QrnGo,ǖBbM(m& ޡ^|=L5hϞ|1OG3s2Ӫs3Qu~jQ-Nu`v+9}{^*zgW_O?|1{nm,g?1@[!7)^/2ݳ?sz/G?ր'ˋk[ôekOF_|vv[I>Ύ@հ1W>vU%ͮ۲;խS\j|2"zLQI0% n8:=|S:;fH`e֣?}"d{-Nayccecy{i!J1>e5i=2Ν1<}5(Ƀγ[yȘB{`xj/9]R*ڵeMsy |纅K`ܶic|JocuWb֥t :f(>l?Nsho':ӳZn{y`s~飴c'?`g_M.;|'?6JzaOrPپ.j;o2m^1>e̶\^ڽsowk˗CLGƹݔZ1ao tH w@g +r܃\w_i3F*8|Aꍽ;x ?]=Q)_e@wUoDa;* O┵l':nUJ#6;~Uey-Ʃ*"=$ιaqi 爐*!TAYcho!i7iŕVXpMs~aԦR:'OSDtڲx1;jp6?3Tq&){+ Δڡ(m=Ӕ ʬ4@l ^Xf,9~Q^m"8 c`,0 @Z|3I%=ܶεIa$@ A {>#f4H^,K-5qĉ;vqzrrs׺Mݵf( n̗ǽ/J5R`UFc 6LS,PK*6K|"f|KNjoT5lBظWk-ԁ!Mch)QY K'7wgRZ)-4v[GeV*x.nή=so<㯼~g?WѻB,]-GSD˷ũխS/?߹|雏ї^{7YߋU F"(L$ѵ3'ݼ=G\zO=/7՟׻맨`L +Z>L@8.{f~r\ٞ>wg'//*TS:o 0RDe C&'鍕zkR:-;rmzvx^[O{rGZgpx5.IHT\=Qnf[+׮?Ǟ;?_x_sx4{.bPO Wmc!Jӽdk=W+7]|{޽~~so:;\bU_b(I6.lsqvlcjvĹg|~??ϿcjdPQq_|Zί*79XʗF 1Q6N7m]w}J3&)dTHTO,;z>īoÏǟ}_?3"lA@hT,=}݋WO㇟{ͷ'__?ҏ߻+o3+&7bNFg~ˏ|+_?AO凞6|&(vS:x,>}ƃO=ko>o|O>ꫯyeHa+LZu#US",T'윽{~>wϾ_O'_}?;sW9$"/BޛxBsnr囷o>G7Ň}?odų,\QX]#zTNm@;gb4ߚ]?~/=w_|O'|/???|MlPcEf܄KRFomskWo=[?|'o>x՗.^ZZ _eusK\ie}ݷzG ?ßWӟݯ<^xo/f[@FUcR ~?/?xϿ⫯/.ߺ^uZPJ확#'ί?yko>·_|GϾ/>O^zG.ݗn)Nz嗟}եl dPRɗhZw5cO>Ͼ_/??ӟgϿꥷ޾'s!*ʹH ΌAHW}>K>~ǟ_埾z7~'[={z(['}Q +M+r>-7ko|/>y痿x_<ƙˤX`zk1/6w_^ ooޯ?oo>䓧_zK3K[X#Q[ +B-\}`{o];w̉|{$mrPU0U0ƉX*Y,W&jŵL؉q鋗N_~dBej'@֛M0 wnٵDM>q?|O~>݇|>s[gNצ<:b S3eSrjM?~ygo_ox^x{euh1E]04`aTa"V'xteqޫW^}WzWw?=;P7Ūp+M)X0 Rsvvix'~櫿/OQDw7s.^|/<<ܳO?W^~=6lFSe˯uEl20+?w/\#O| 8Twl+?GwC;.ƈYa:(,/o\tW_^'}w?x_xjP]>3:2*=lHqL؜Ys%̸Kpi +GrJ[vAP܇H+%j&;<(s 1b+Q! `z0 (KIqV`y EFbd.tv'V(LѡZG q +3R/ H/~1GÉdP}R8$G*z6Y2cJXFRX&S\lsЌ E +^<*Ӎ攛eÑGm~+@L@YfʁX$5MgKӻn_l>!Ip|B)QDLg;czΨ!TXY&Ho ˑdHFyN:ݜ/PQֵ />A+97TZA 5&eu xy/D˰+G:Ԋ ԻDoXwXe VԋPrN6nwG=IĘ 5:E6"&m8U6ZQy=L@n1 LeY;@&ѐ+:E59k5TH*7n@5V\eagLF8MY ǜ^f`d{Q&f#Cv6=v`gF¬BJY1!$B?f"GAV 2lq-Va谠 + +ESR47ԓtBFCj;䔇P`g.9zT"oqbCPax,8prTRCzVV6 *`hƌ$YwxOpy-=yMP;2-3jIԩLkv'XFXk%F-#zBeVdJ(7/&4rh^* N7?խdvÇ*<q_ƟrR# !3d"v.oJu}#~H3DxR7cwExuvXaV('[T|#P:mPmF &\(A),.4,Ʈ\RaB +39G@ )Β +23_0bZcwN +/D&ܑݛa5CXAE!:j&$JR (ocXa΀R]:IC djmōcZ˄z@xce +l:٨7\wp4x7=Dz0 gz\: 3V2!R(8ؔ d0UwpQ#9vkB:T:||FMFӢDh,Nछ(PuQ6 `dDevH;T|Y6#L "Wn$}@@)8 ܨ4Ap1p<6Fe(ln= 8dcL.qYG ĝ#Wf# 25nv쐱@~zE%|iP -3N*l ݁"/&\ӃYGC՘ a/ˌ)X*&L47 !Έ=l} +ك|8U:1+mH#lzսLLd rAI` v7Cƥ/d> +{S6 +d qqėsźB~ Vm. +b\-\R ΀]Pi/ @ia4#zTMWuX*DIB +\1 > ]>:v$J,[ؤBauULƴ#Y_t +EIKe-TZ41*$rLJ7\:Cɵ~SV*l\ONjmQ%l''ovD#Omł4v$RYYz@yx(0c +hCcX܂?`vm^Ϝ&Œ +"|9Ir)ރ ǍN 4VfTGiPڋ\B曇ԃb"0 +}g} 'Bm j cѯCx,0(B4q7ef3꥕ ܲ5_bڟfhމ"6/5l58X}'.Ϟ׏k B_ ıH{!6} FģG}FB|E!@u5`~_٠IL8<V (-;+z N r!W T-/B'6k"T3I &j1S>Ǽy>لK T7(Ű;f"D;Ә3⸅3@:(&0O6{fOz@>7;#vx62 CZ[C +x@@n"H16Z# +J!ymJH}{@7100TV7@]ap0tL&8HFUȸ2!+I +5:0sHF7LAxc̘7ǡ3G!tvmdL*;w؀#L,]['cV Q1ғک,ZމIy$X]G+7^|{iBkbvE.o +#U 3<#!WNsd]0H=6WKtxl,^z:N )&5;L|ƛ\D+ d!C/otGiq:,?b{H9\2` +܈7k`7p"B0JRs.V`a>n DXf̜Yq3=F"B(BlL + pV-x 6wR:7@L(5yPӓT1u@!ƻPB9Op~'+,lf"le PZ $܌ Jpx* +ҹ1GFE NF,j7h,,¤QV2OpRf̀WRVf\gz\c-WQpkOORtvܟ7(F&ybLi-$슪aCCIo'⢝ AY\̑rKvJU;=}#u1=wl:cu|+Rsޙ/据BHvo ?5wL!d[֊H!;^^<$'6N^}*IBlؘ.3v ;\;\U[h8fsgj<k7t63j \[vc˭#ɵPL ,0f^MVXh`Az4ZGMɀ;\rEϠ|)ܑFF\E'|# 5?À$uv\a/3%t'B @!  l412(AbX~yl +=Ro8Uv*yܛC4 4S `EG^JKRm䩻Ě/#׏ +EZwNzƸ;E6 *(P'ȥ9(k^$&YTnb!XZ5H73k$.17G;@nq=3}LLDl̐0SaglN^o*[Рa%OX=w3Ϟ|8^ۼLp}\@H-\tI9CW9u~:Ojn}#f~%@@s'ٓ3X/7y<72Sa=Ƨ#.3frXl,OoaI-6%g.U-BOpf0TI靇2g4v! CdD)Ot0Ag`cZD7NMՏ7 ?GB{VÏ y@u0*MQ?B$t +4&GdFlJJ3J/ X؈C0jt*<8VwBf&X*NlKM_~)9 jZdqjXPX1#c@ +&ŧhHxGt^?W\{FjrK/#D >5 \ +!! +Υhf$(J|l, +P~A,Jk|ffbdd Tatse6W!B*__8u`v,zta(GŦ-LlDal*\XAN Hƺ;PiWZVRHL4A UA gǯ1r bd y6oV4{;RFg05d~'dƄ romYaT#B)w'stnA dKh{Ҁ5x? /Aў/ pF L]ۼ.=%B~+_մ.ڶQrRaQF,z;h_аƆNG7 )&1RÂI C*lPj < +{+!VB$FXG @E4%P a*L0~0vUc0Ғ7f:4)VbTdr[{O5,]N/PA=E7m}}/MGaDr3X<h`wmx +&HDMt0>IznDfj'R_X:[=ńk||"J7sIAx 98#(/1Ivmg6'ᎁLϝ|&?r#/CnǛ[s;\y&;{6걀QB@Lΰq kr  8@aif3_]:jq!gqExPV*jSTJ [zRs_T^A\[[]M B3shi@`ٙfWj+So׀J4H֠! * |0JE4rr$;iC@W"Q!vxWς1 Q[^-:8KbFuXdԟLs8MVLD-nw'c2LK-Ϡ$<&MͭqxLTl| J;暝B7Zm_?7loӁΉ{!fMd䎣b-_vO.\Ơlbדl biv6 |i×9Fu*_ϝnT < hz,DypAAH(4\XY9s~+0!issJ"ғ&'TyCRi%9 X15VG;۷w'NQ"݇%4bvk1pEʕcru~pX6hʌ80_dOT3Ə&T眡ZcuI3.@Cww=E. +y0-Nj'j¼N -t`u߰ИiiHh vBgPc!BӁ\uKNbB R3~;V"4x )#& sdP|a xdQOjP0O FϱrI'g SXu9Vﭞg`.Kvõ#yϚdXr2c&JD*bL +C}W=1 <m Vc[eOz +T1Y܁i!މ7䰆 %4nqSX+JC9Oc!%# +񚃉j V.H\86>zzWiǭ +ad`e<.3(rse'R'%ZL Ŋ79(+p×Zl,SRCi+T鷉ӢZjbe-U WlkDa`BlK@ؿGN!G'Mv@i=;+xKGx}g[[ǂZoB@(Q="xٗa߬G\IFHY 'N@\^fzg̟wb;ٚsIS"Ac%X1g@=RI@zHVXόN?MdZ˵{GQ]8#7l4Y_8c:%yWpF%a6c$M:-nuF0gtx&I؈+1;`3T"t}yMZ*rǙr 5Æ&0OVeeZ0G +3c$J}y4xoo(L䘡c%_v zGo%ɵ +Y0?%4!lWBDKJj|g@;xw,^W$յX;$%w; g + 4) .E{`1 ,)= +`̎<E&JVxС $4jdN+T7R]9-P 2TMl6e"q+&"s@Q s@G #Mx@>VO] U%_q Mؘ.,i/m!&A(ִ`*ؿ @=s +L ǁ~'|<`O~]?sܴM$k+e9)τ*`'lNi;ЁR[#Z1ہӈ1\ȍbgkb̨a~31P!2\ VuFn*E=@ 7l7 0 lŒFuNP͘@xR|=V"RtݟS'e'*+da")lk|Du+3PpElrTus:븿&#->ҒRBs5ei`qٙͥTCͷǭCFFc:/9ic"&*1EP_&PZGJ5q՗]@}y2|x=nsOl]yn/ExS.i&B 1˰ +Bܨrp `Gͮ1K1@R ;zJ 8VܟgoO74$!p-˶wpkpsPvpҊc +%FP<56׈;X_^9۸o,v_uG:\Y9W;(,ྴC 1CNɧpt|S5l',ww'.u#X]s۸~̔'%o.ڴ/2av2p)7.,#`%~`8vhsr`&%D*ݥb}nub .ii`o4[߻mq b Za+V\V$ޱ}vWK`J jfP<);CD<2Fu{TT)=ӢM{ DZ4Zr_XL6J|`!^ $R&< P.10^=Ě(0P1-2QW9o?0"29112`n!C3thwr0u0#!8'di7CxtΚ1Ҡ660\@ I6Z&lZޱDe[ǯCTx=RLy0q`g,W'Q4PFE/w7k-P'd2'W@/F8<)IzˆQJ3ŔLdCk! &\m\=q?]{f*6toMu&;M*-6O +ʈpנiq6 \zXQ춡~kl4Ș" >7#UVLwv#/;GgZrSܬ'1j꾅p⥛/;Co908ŕf(N.ZN^wK|!<.fT6bE;g't4aBkT,:2-%-" LI +0'KK 1+O+ ݑ͑bg˾tk]]>yy񴐛jwܱ ")bSwv/<3N[`ݝja24l G8Gcmk`' +KV;GTQ:Fy-@5 AC4ZY 1PbvD (ZnfφGXDG2BHlMc/wqPh,LgLO'twVAdȹ9!ժ\;rs+-XebVL0{6I+Q/:$UbqIc$!ʗBj(zt`@uVNm)& +Ң\px&g2paA..PByvl#A=ǜ?2+m$D<ɞilF̤,:n|6h6ZS|۠n݁R}vp` 8pΑSWD$M+I'•M>ll\z,=8<ߣ >§*@pf@C(!x3ڑ`j:yy♇<8}hk1?Mk&▊0Z Qaɭ45Vcm7HoT) ,J+y2SW! |+<'z&g!fLND +Ou_̜uFPE&-߻3h>XXovG,Z+k= +s*˨7;&*| +;Kxba|!؈V3dsl/`;<;ѿOE 0Pb (DMR@k?oͮ(̄ Vܞ޼Q-2`3oze5&Z)9ڞXkǹXW F:ώ[J⠊3:Ts`vzk(qhp#Jiۧlޜ>4b iH[*a<pT$5Ii.i4֯7V&݉mn:bb?d9JXտS@ 0eEyF*ΊũD}nzkgn.DTck¯9Lxqz/_@ +b@w0aBoYg%:T1JD(`@&RfyP6/gҭ 17,ˋp5-o_j4"Hu&:N܆zWƊJ+$DD-T +<@`n',B';fl^|r\&_[ݹ&@EJK3x8 ܽ7Q];Fš]:RbR ^igXrJU8#Fr=w4Th=9czDP)TO5咈'fυJʼK̖fw6#꯰R!.̜.쮟vs=s^\fsn&LZCD- h /ݠ&PRInǻۍ=.Q뮝)RcÓuYͱP.OwI/edjBE6OׅݛCe*.sz" B,Ⱦh8,J:TF& 6),\ˏV6\.@TrLwfYa-D6+-J=.T[Pza}baO6g+5a 'opxT0Uglx'\6&O݉ܥi$TLa&Y3F )*gl!#VYX~#e# +f6 :6s՜I&Kv~j;9"=j=vq&3#>-DkM&TOe<TŽp;`#d|aǮfw&7v~7whcqmw#{7u%Zgț''N#Ͼgj JXJ̦\^pԱ˹ P?XU; Ό;Ls6'޲:% 0>U)b\9'2OL +Y+YOq KqerFCq= O k-kxP Iť6/awIvwH,˔G;XbԤKu<8g<̇JˑQzZb V]bqHp;Q16"r`wiϦ&4ww/ܜXvΝ|sޣ3I֗HI7չS=v 7[Y8ݸ  R[h)mݑ\YzKLm|z {L (eUXU4EhmhifQwFҌٻպ_ZDe "ϋȳ׏OZRn̦Zy{[+J5wKߖKNkv}O~tګ}^x;juCl5y޾{qN:+땵Jqc8+T$iJK[`T 3Rq7sc<" jNis}:BOer|~"aTؤ MT0 \zLdW4@D#jA: +z֪{)eWE)I1 o5\aM \ZHq\*H_\{f: +4Fa"%f}7<$N{iB0#fL' QI+]5KKUs=1 \Xu2$Vm.Y8Os0WYlSfO΅>&"&! PD0TZ:\KLu(, 0%1g60kk.mVJ9̀JgVIqjNuEu]4wHkWKVyFgH+G޾[}[G7￶s4v^h>K=xpK/Iűrcw\&hBD1(oXOZ Z˙6jx^N3KqS>ArWBɹ7 +p+Ls~Oj^tR=.De0&yDL.1Z7kgƹI+EDLuj l3Q1'8m QYah1v!LDjl%STG))1+Wkbժ,qNMw8ho_fr޻wH +F0& 2jm*9Kf~d Q?qux5JYڔ ㋯W #FrZ1ҵk_M)'.ĤMͳ>6Fs."L)W8U2C-|sN#\qY5*ˣK6hս0Dxުʒ6p3qhW7",#7Eτx/y8N-RUKAr U\Bxc.ì)Y6Y]nߐ#SrK :^9')c!Dr!?(1 -e1Bh`.CH(F\ppLjݭB{ 'o3kk9اyZMIb@A\g!hRü?PBZ IS҆QSrovF:cF^.eEI#WI_iQ6'gV&g1!+|mXh=]^1+@> hm]ϰZᵏܐLlR7FeKJƗw}0 +9VByw 8ȶD%WY>ʶ!a`BSz\̣B* >x +?Ĵ?M:xJepoyLulFK)Oa"Cy9 IjFwC $-=F<ZO0@3q! xCRqQt2=)E-? +Zm{T NF--蚸0ه a>'TITHO=SjPb0`/Lydpe[a\'a L[IQJF8!9/  8J"hJj iPYT3/K%ZP oxa.DhX,Y7xo1@ яjnHZp^Xą y3c%zqVDg˥)vCvZ "$Ahy"BX$@Нq=S(( )!X-㴂/Bdc0633y7 c|xj!1,&+U\M3g,>5xv:tf 6>C)60T`͆&gsӋ'Nyp|s|}*OF\! +aA-0lg{s'=Ԝ̼S%f45UԔ+PbZM?`mɮ'$Sn1sBļ2*`Bm9])I2s QAOYў9 ~<)5J%aVTݵ QPm4 ]ߔSKL_ qDyk:$p1q8c O81Ape R.HB()-%Ú`RvzP "&83)ϼ;4:s|"^0"`O#q& +Q%1x`AR>0t;H>+>FN +̹Amqrp)=g9 2@U|Q>D" 315Ӄ,Crg=AXyPqE?6FN΄@pFR4:|v.'ٹ ;x=2{oIvy6\>ʕ![_,"xb)?BBRj2[+{=0{z!B) 5FJ$E2"X1j8ExNNEa !di ,xhJM°?1rջ>HuE a3qׂN0% +vc+H~EYP JV4J9?(4"J'0m;\؜z.NcOia\sK@1Li2#8Z"-0VuH:Ũ&B`/ /F*F eg>:yg,PAPyBICxUQYXȈ7L-;=E`bO=Oκ|% >VHB:@<֚^>³3sA%8'󋑩iq'=YONb~2N^OO@3ɎDx F8<˘^;s8&[\rq^EXTMXjW6 @R!D\,on|>H@(Dtr֖ob3><5?5HaYMSxAE":I;xpHLGO|+FiȲ H(Br8MBqi֖/J~|/O^/ a;2c@hơ.UzzUk[j7W7_<߾ڃK/܅ jJZGB7D͸gg]3'90=/SxP"B!gme0< +phHe:74_8߾yع{y㫟wG_?ן֣+;qYty,vxF{jf]ٯ߭QޣV_;ֿ7z0Rbr/(ϗ?|qGoY_|y_|ί{vw~;vb02@R\ +-`9T+T#K:θY_J_k~K]=vy"=kAgdXg<:oal?~p.?{o^yNlFC֬M%ҕϿzg_ [=ɏu폿|ǟ:Z(t$.p B@> |ϾW7[7~|~~Zwr鴤DS5 +c+/4^}?_W>/?yxꕷKʢ;vj68-X/}y#i?.\|?xtǷ^{m%0Cr*; K+_|O?ǟ_~듯Y)% fHQ.PG|frT?W^s?|?~}u_}z!)1, DOZ^WV{Wݬ~{7+???:LJ;W.ȣqM5ko<?}w~KſzO?{V?@3@,#k^^+_ww?xϿypr?)I)r+EHpw~y{~s?GWW[?h\\_ΙM3 襠x}yx~?^'7~ ƻ7kFf4%c4t"a[θWa4޻׏ͫ?_~y雿yo?}篮}%^㓼Vf&~4L18o\~᯾xo|k1* x"E6Z. ջѵG~|x;ۣ8P^rSUG㘴/+ k~ǯ}|{o>}qZJFQr"/6(VLDh9uu-|p_<}]^ztܼS\&*9/BRbI4gL5RY_)w=ǿ~??/u?{o}KGAID;+F5 X%A4xَɏ.U_k}o>o?__Ͽ߹wlYYK` B#r)T' Aoݟ~zŕrIY"yWL̈́PNvWg+Ǎׯ ߸ÞyMUXdR҂d!͙JVcꩣAgn+?o?\ G͇gKkeIGJ!^QA4l*v{+ǥ_X??~ʷ]0uJi^D #L$D"ARWNVZ⥍|'/qg^䉂>Ϝ+qfv52}ys˗xBןy|e +]J5q'sYR)rζ4͢Xd hsZݹLielKqjBf LA/(.7sۙ_X~y7ƹ/|ƻ׻W-B *~XF$D |2]86jZ^GlXO}o~}εWntRpZNqDX#,׊f5dY.&^dA?8Z)7LK$ +L3L)"a0RN1*;VJalJ+\521Sp8l>Y`0~,9FʥJŔWˉk͊tqTHx[+sU82xX6)&C4Bp L7BiRҖQF,0FGPVRR1i"Fm6+F 䠒("Ӌs!2HJBRԴkzlUMi2J\ng׫۽jzwwrV.f }zja14Y~?q7%` zRy` M N'ы/5KI!*$C$(:K\R*7bpy 0..qBl:]]`i%#1if:q&<&tWT %e}X4 "1>Ĵ1ƆP2KNHę4c ,RlX&0 ҪzL(Nҩ)Bd\w#L¸gs^_~mϟ=3%ET-$ BAQIT\)ULRBf<(g endstream endobj 82 0 obj <>stream +93SX48oFe(.r[@̅f,hU>UXQr|DZ͙&2lkQ,'E̴d"D9Z fpÇhnφٰ8tr-DE)F+I+ʤpFuƨ(%MKxFNɤ+&q,V/r5zn;Yc0JvX !TgX<rAٹȓ3asCŒMzLhx-]&˓1"Av#S3!\]=*u7bz )iJvVݸ;lʌIQ`d8RC섙̙3r +X~TJu + ^0mzCeUΙ"'Ss`jsfc_H3S!_DX_;8D,\֊{Fr҅ q)`pNMd0ˆ' +6y劊s!~!&HǃYX܈LΌoBBQ!GjH~y"&1.l?,A:CK[Yg} \9$+XdYIXL|fLCZr3H.GՊ)94vIZ&}}^mM>DhM" +eLb4 T,_ s>qǭr$^vwKjLnƊ 1dfB\#UHs UwF8VcZOX]0GֆV9fJZqOlGt\FtL;"`q3 K2Ih T` +"q; E*.b&,# Uk1:}hDTAjEE|JҎ~v1T&MȌM{(S"&ZaK yk.h7*H i~r4\q k pˌ +ZggqDaeL﬛LLo~dǤ{;Mi<F\meeFY IX O4̘ͮǔF+A6Ѝ&\FKJH(ƤYr f7@Du!;4{Nniu6:pn/vw^l޷{sëѲ]7qiZlv#8 ;YsJYLkƤOf5r0xPn*djqz:Yä1EDo\ +sQ# E?#m"j`@mc?jmx^H 2a!)uXTC`5dWk~TG&*!2L$zZ"9'}w&,Oy u\DFW + 0":jtjqZik:R ,#m.5t3܋@6N\k9@{Nz\[R9/m)~w|׿ ܴOtΥve`BL,+ݴGK#V~x5Za@GUC&jy[*>cZ!|Dj0Wip]n}$Taɥ/~jz7;_{k~=~ɮ ow_| 1=8tl&Zk^O R>O(7a!F__h}2YߠNL(}jyPtf@ pVhQ2Qv*Z]9{x} a&]A6$UCLZv1ei6SsxUXݘ q'\8f-H)PݔfTqFf7D/;< +w@Yʇޑ.Twc&l T*@AmKgsw.08z}"Q᝶RX +zsLTmp0Y ( MZ{(娘j]ʬ.:ba OXQ_"JNF~,ϵ_1)j}wwt 6zD҃[\ 4`Ypcz}J-<%b|;UÜ^gryG+oH#Hhlaj^)d׌Y߱[vm7H@Ҧ@2,۷ctνઘCuxO\bj~8QX_]ot׮DH ٕ{JDL@D7šX +kqs28"8f2 Q'\)/zMwh'ňT0!)XiF2,aDqkA&"O$uG<5†<Lȅت´YTpi%1L%bBTnV${α^aV "Dȍc}՝ABa8[_}{raU76?r{"g.=عJ1hqMDmѽw +Ev/lv>k/׷oǭ\ߡ[w:nHxtjG&SB6,S|htzcZLkcm< %4P֝lrQ];z};?Vv Jw|Ds]+\z7.kl[M.&;Rv6.;[7{[7"P%&GWu6oɂwg@K/;?,MV=%"dVQk8τ$:Qfy|}k^ѻΑ:Ĭ$Z˸RDžix&WaZˏ#N.$>0s!:Eq8i >ʎIEZHPJ)jG쯝2.@Ahtz +sByc1)W]n{j~| O]^iliaМUݰ۸QnfW@v(ؕU1;$1 +N31̒\R;zyC)ս__TV+Pե@B!=GM&h.*Z٥/:ͭ'(_-QOoE<Ұ ;>,n=vuk~?ڝG͸[5ʮ<99㆒_r 2:={(WQyDg{KvYpdqZ]ڸ!JT}K/,boFHC ?0cNɅ(52/DDt~ݻ +Z7M0|QQGlPQtE02kdn P]q&(a4ji70VՁ#%ڤ3 %/D92qOTƮZٔǜ lPU)qET.5QtsJaXKzu,V3 dbAl*b3Q.C-lq!`).|?ꄜb2XTJ`$e/f{H7r {xިG'fG0}է|86ػGʍ@?<'A‡BTWswⲗHr5!9+UrfT_mI?-vȦW8&׀aI7TqZݳ/UVe;vu :gJmNڪ'VNGo.<(QROv/bf X7/=JMJ\pn.Ťz٥"$\9ɟ0vZ[7CE&є)n4WBi. `M/>;q +fXSTSK{#,."Yu2\f$0A"WPjqSKg&0y'6hFbX("zvm. +TJkUI +{^2%FZӿRڸr´\X +3jaU4QІnFmBln1 TY| ++w({tf"NgLB|-*ATXM޳h ͅie%-vv}K2s15 :gխFcju^ۘT($b2Q#2FSg(OPg|"l@BˬŭyHczix "G& ճE~ ,(h`:h|bq|M7?fjO}8BT66vK(l$GՍ;z s悂얇G ]`ր1T kZ~5LjwOUYz>c*Lg!*3>L:4s=x^?"y?5G%ZVa JaM9'+ e`eΝ4^q*nHU\&ed'$dݠ%@K:FgA6 ?-@5pO% +y7a Ͷwʺvb(}t f+,'[fp@+x`&DmҎtHKISV#%;]1ՙ 3 ̓n2@eAЊ ϡTm^+EXE +VBVXSm9nc 1ʓ>Lh?F(g1!bN\DD}N("WXW.PglDFLuŨ&m@֊4Iha>$5aeu*^bCU2N6lv13P"DV/[T EWT\ZTlaMj0pZۥe?Q[劸P|f&> !ڴQ)9KO n\zd/s|WQ)r.=Q!Kn* SkHKkz,(jyM4}Lzf\[);gVDeTbj!-Ж2˛.mܡscO\&T4b/%eG#)7LBtHCZd|n|@ &2u)݁|́u^ "7I05NC9$T})`T6(|LL+DzLq-u~pzX\<õx"•6i +q $PISl MA}>Ed}l]J +$icJ=*TT7(tŕSǍ$Zz&{a1:NVf@.3L{j:rr1NshO|,eb"HBT $C&Ĥ!Xj?5 +1IRJH\Ƀ猗S?{3!*Eȅ5Tr! +B$&7sz) i7tz:H<+Oze=! ;5 eN]U`RY{0lT3ΒcFM.w 2t&h^ȯ)?!$NmD8Rː0h@<1/];$:F,=衉%q^n)a8ZL)MvS>n>F^sZJuJ,ec LA} +DaLoVi܍q)ij31fYQFөm!.9S- Ai;!AZm8T.*dVb6b[%\cVT(3ZݳbBhiq +^PP%!D¥NH9ezYs^sX,Ӹ6mO<&NPhƥʔ ɾcA*5i +vMϏ@h_^D]aiϜXr)L<AGIg1ĝZD +,oL 3g&9/,5HiD3}3Uk>@|nӅ|\(Q䂤(cTsZf6j'@ KnUPbQR c% N F0R^FMvGIM/nw7bBs>L [cˀaY;³z%'<0Es#63WjD܅DK0[\e29Ȯ\kޟ_B*8خ/:uօ+/U7( hNuӮ/B\D Eg}qn [\ 6ErRt爰hf3!c\,q X.s Cd7] +"dj3Yk5GT^O#.Hƍim\B%<) ?j"́p`@(e9[Y-JqӅ.`w=ଈ"R^@t3&N&gbצ#=+HZDեCBx6i5\f/n x~CeƪՊݩxt@~܇# i͹(=凃NZi?R +^̊ 1 +ƀ^r.|IcBi砐;bg~dI{A}!,w{SUYmx}DFFz{s>wfwvfK +K"EIҕIgH$$@T u|}DD=|F"?)ٵW5M]=>v5'c>GoG?ӗ۪Vy뿙}Ȇ+ž3BmiR ӏg~7h /g hMoGoYI]1jejFkJKXu8~7Ćjxo)mu|Zwۜ^3d@^RqF7lo,Սڙ3޺y_b]goe.)ə3?B+Gڜ5h- ϿGc)XוnQ|.0\}C3FVٰHNp~^$nQQ/i"[l=Fzt~u_%ۗD%Z =nӋO_o~b'PK?&w[k6\}7oڔ38O7 WWO5yY*?ׯxx_hsn.wWw5l6=8ϓ?S9NSx֥z ;α`h{\Zvgƚ_]}rr^ hwuk2o$ggggҧ׮(G}BOO^)'GX!=rw:~h5vkB X3OjY u#=e~%5^RPg}gwUՎ gOY-; ތx99x38x58\^ݮЖ^R5*R4MV&>YtD3^O*802ІO[>M4$xw0X]eVȑ^Qk|E?>Is5b)ESp`wۧҏOGd ]3ש| ϥ\DhÆLw0Ԉ^Ffۗt|$d6o7J MbC) Mw原ks)؀jOF7]TX2p8+dnMњuf%-?}GٓeI!dKޕ޿F%[Ӫb͹31\Z+s>w]HvLmm˪j?φ Fר΂6WBHs^vC"%obVL?Ϭ9 59wQWE֕lt`BdjZ/jy$` D[PT#<9qE*Bd489ۚQjE$@dgTc,BP]k>8*v4ks0\b""}?sW9f6u]0}H-]&-ڝ?쾳~/ޑ0v7>h'j` +K[F͢@#E}`QLk2߫&Sʄn75)[)ݪտ%Hީ+S5V#pFW +/^[&\%xSHtyl $xNK]`ڞd3R(Th^@ >$ٺ^#ȸig"D[07zZ{^Cus$&@#;\V4a`9D0pR'>FK85ƫW^8o +DA(CHg/49(IQf| P (\U1DVk0;es f!=\W&NZ7oZw2ZO`b<+únV2-Q@+|܅we4G<3 *%V*ZݤC@i ݿ:3댹p+wΤk=tn țiYGV"a+sSF7gu{%N2ѯ!&-Oy{u5?WY5zY +VMjGoLPZ i*;a/r\ YklwNo)_u +TS)ku.7!>h=Jz8:>zg(F4 m wkop5:>^eiڄE.AB.댤p A.D]k&4ޅ+\(g`t`܈foQٹp p{'?ePjK`Y=AE>AzL;z8WNr 3a( \4Ԗ/FK2;9k?75SsBB purfn?sF%9=ϞCԩm?/o~ͺSRt/"D';P"ajj*w nYSE0:|P#ԅ<d {7T!lY0.E Z#홝K5C]+-\dkJarg$A$Cp?WkoqBLlD9er}3>h`{ۿ$aoRn_րg5x\p|ڭcȻ3֞ h@1 }BjW*3|U..wT"6W|8a h9xc:$g͎xӫ>ܱhFSIt޶c@)Ѣ.*]-BnŏJ+I5fE@t'ವ,_nz"k_s-ҟ@Z쟶51n\RP{=Ni䫂@I-;8Dx_(h + revOCi6Z;=w//$㧿qz=tƷXhJ u)B靁JHJ{ckZa映7I@%0A~#:*R:&vw +nC؈!<g]ҟN︳zVcs0}f/Z6(~C>?!6Ӕڶ;F븡sLciTU !Jt`t.뒧\#ZI7STA韶9S7)]w PaNw>hm<4P49R,މٻ'OE``2:VfmuIlvmks +tzm@CSwϱˈF#G*bG'*j;j%CEGeL"2l'?&~{kxg,#)K^q0_)z L悻zOp!#f0+=9a1>ewgMMâZ[x-ڽg~轓ީ94UCBU|oOZ&1 +^cUWBtس[2f}}}E[gHim=^SzPagB>izgƝtE%& ^;f~uj؜5|R lO=-J+%=^rw:W>~ktfޢylq7o3V`,ŝ6I^ŇO^sJRz1ݢ4u_P[UNr+8o/wsIlgIPn3eÍ9G0@2O3wπjX"P*`EkT pHlGo?րU J$F +c:3`8aVC*^9w.h0=磋g47;=gwj+H.2|?NOigƇ +4X6_|{"V+{LJZTiFO#$1S;6gx c=:,Qׄ&j_avϴ1H{,Oaz>0zɷf̚ēQ^ޖ9VpEho4m RVӹˮNInme/QR/Oz{eS;z8͕淇`%'H%w%&)@8㧨%)F$l^ cn\\;(^{QVb_WwFx `|S ?Y+iҿ_XVo#9c +F^›ɁBUX Nپ9ϱ!pNPiC˼ZOӗN* +X&4?:w$op[z잫BfFk.gn|u]*8\&bxhҝ='wlhm5&O%ZͮIH]RGnƈR;I2f),r*"8|nc5-$4X!v?0F~&0e1DN{?zRDyhΞR:"hPzV\I #Ec!ZW[0Z_z+6_ +׭u .1zk.s>t5LbP]+< *0A|E>њʙ\y%Vq]롂~ K}ڰٱ:[6`Oi-2\GoygV{%̾?;~?kN.`"Z{yC{9>AhmD6D(Kf0jr&fvu;/y{Z} jr韏9: w yT6:h's Bg &&\`Sn$(paL +|DΝz9|w:ѕ}h2T[dMgt.9\dԥ&PWZusqðrA]tI](AykwVmyN縎OHM*I8?xye4 ٽKFӟ_I)X=pQo9UV`?l^;D?Qq0JsUe T"HO/~?Z6G5}HXS?mNѥϫSŠmX؝/iAWlCe`ѻU+Gߌ/.0=;9Wതe-G{4Kye!N(h).pjrke9/n .n{uYW?9~ZV0-LمbeMɋ7U} 6x_S0LJ9>ҚR񤭩[i0'3&!aaxo!y +1>/EƇKCK?k}\#*,N] 1VCwirhٺΗ/ʛ4WrxIh%˅GZYn|[wQ?)I<_[в띞FW`.PZNgھk?LpNQ- +I]J1f/b91so*uB}Ck'S IE"-q4n拋/_}BΔ+MJyE%w:$ 0P,&WQ\7ʴ359I?H{/i?+gӿx_o^i/>GpysOw@o/H t2K/>5a%:P4$O?I_)â\&}"Eit+ I1kW=ɭEwZҘނ1_Un#JvgFTn˚ΓZ!ywj5ZJnqMĦ;Ԓ5mBt@3u¸ګMƙ F6tgIwF| )o$G;Ңav`TΟx`y>YUVߵ>˗Ys^]1᪬$BdiC@لz"z#ޛiXӲܮȝc9:ƹS9\qr%c֔ꭃV@ 7zHpU!)1p^;RZWWE߫jUU; SWzbx DaU J|Pz>R Z3.fkr&%Z5#6~k>j;U-KҦ6o̡,1.)ٺg),DxzU֜1Ƅ/!VukU>*~aJwW,Sx.ca(g^%.ۿǴbiz_n)`m_o Vְy7=ӺXM2u iHgtZ;>A5UUtKڞW }І6Ȓ.Uc@;3{\}}kVզ>/'?˷|넏`}/7?׭aIux- نz0۴hcœƄ;)}*r9nElUĸĥ{&k 5ak\_1Vxrگٯ;% Dc^S\΍ Mj}Ι#HßJݻ&ޣ"T v"ׄLˉDꃽnj7GZ Tn*B(%:%~qjBIGKBo_^MG}J^Mj8?o0'Frș(CY5i.=bvr>t3׍ ZhB 9xqX_unV?9 Yg|xPP*Ljr!< n=')nhs;×x1z?㫿vpm3up5ɏxnԳz.sN{k.:eҗ)&tr}J?)NYΓm y9# 76Y^8KyOjfobeBX[)|m(,4l5,B]hY25AwJԲLk_Js9:wV*g mĹY띫hqBCQq8gU(~"eR+ZԤ^]V +՟fI3CyŘ  J[B3zT;x65Ys[9(SWZ`rk@y]Pʧy` a ki;>\q@5rBZ, Z)9rg `E3[Z=<j_+kM3wO[yƣ:em!GE>*KqO +|"Ho_43E:17Jr`d\[#Nbul_$ot6VсSN1ƻ_W9HQjƈso$PO׺y6',sI?P۔>ΐDZa2knJ5'%6o9+1!dQAȑvMJ( +l6Kj"&aCg-6%RT48쪔 bՇ)+7'! 0HXH_UJ<쟻#tt L2ߤ텒zgV"kume/, +鸴@EBup?aN)sG? ΥzK9\PZI'?*ut7BrhUWk5:!˽3`2_{u7J4^noފQ5R&uhk!Fwn9rGq'f$wQR2'F\\Y4yzwãE)ܹ;O_'&E8O=;|Z^RBmc9XXn>vtPUKBGe.Oa8X˜*ulNxe &yLD K'#"sTr~\R D^*a +Zu][S'jZ,h-; -8VO.`sL;2ɯ1tfdVnWUerg*U`t#`5Iq+'[Wg)kv.'GHhfm`P\KwJqze4)@7G`d,$zsxH3tM9VY(3{p\}=ڽP r_q! jջ}IO\4$*ruj@O$Brf礮xo{ek;'og.i8dSrb"5sCI'M|6֜sW,D4sQC`m śt8!48ݗۈns^{ c"fZBYc0dwu~)0! #ԥX[jB+Ox#S rx&"%3.5fx:kEwQdBWЕ#"J>) *T~E*|[3'{Ah]=cOYs;~r$%mA֙~ڦ%B$1B[o{'?Y+ɝduʟpegJ?ց݅7zi3_Bgټ,!hs/g:;~NAÚқ<` ]Z6Rǻso|_O~W)n(P;!/.P=1r؟<\LZasL@[Hub Zm76glO5m3 4>fw2!!?CP![ǚثKn4`<k[SyԚP£.Ɯ2J-@~@Ѭ_E (mP2U8EXcQ)}LW 6HpL;"HN$?ЪsHN1 #"5n *c\Æ6llZHuq1j_ 6Yݩ;EaTX6(¤5xnJš DU#uD;cxFzx^s.\Slncg1B*@#wCc)ks= +VN(I8Sotvkwz{Eһ޿Uۗx|EN]VSk\\He12XBJwX2񖃃F;B*\֑e ˁ9LwKKH Vg$zN/%o|*0f<._20I shKg  ̹aFJ|RcսyCә#UP ]R_55OB@c]Pp֩Uj(9#K(E _bNVv>,FÂa`7|;5LUe Z! +?-8o1YnhmXcCNNN䰪)%'?1&xgE ťf cy+,+mE}A¶Ofݺiy.noqha R$g>z"reU^9BNMC}u44y/^;d d!#=9ҺE9i^s;3a-@/BY_s?&^x,%kM[pyvh:;aUאP9BEYJ QMLj"Z# άĺaj:B'{j $E55"N G +z'TkQTPvk!3I0,6 jb!wi_&vz`e! (!&ݣiGgTFhտjG9:WWA|[RH;UD4kbkJ05ʒ:DVk"6eӯhr}BH-!X7$AVꞣ +hq 1FABp1rio~(/r˚C^`!MXf0yTR4|12Q38+ˠ, *HS-:ՂgO< X˻ڮq@Mxp[PHdzC&eha>[7V7NrƐ夅,}v󊵇O"jҁRG'0p=],e] rpsN;usUZSP=zʵ }MQ1':>)9:m>mZca=R%$}n!Ģnr0\yo +'VCn"gb2pVr)>gbyg +czgy6_#_ Tsҍ[ 8#Fm'~i|~6X7=O9b+RߌOPг` eI v*TaMhgH9#LW7D + 9c[3>)t]BiŐT;۴~ůYUk?څ%QJl n9q$}CM8AB"> G&~UB$bb6L3 |\ B:Sř`n?E8eeB &hr0FzЋophf4(iY)ٺUĸ9~TbEkbS˴ÚKY@LEPNֵ$UdBv>ŶCc䣒WGuO=Hbpu0)-Զ,[gjv& H'6H>B5i ? L`(vSʇ}6RvE3ج=9Y5*rP7Gv}>:ߑ޼(@Ԍ3NqXoPgݕ>s"֕VU0o%6.p `uTn}xMΓUP\Y=)39Tɹ *at +U +y|aM ͔LET%,\31T&E@,,vrO+ʞfzqP@%N*R[t +[D] ֯vxYYLm].Km#h(Kd+*)j|бX$ H +lWQq&q鉏tDBI*{8W rG _hؖyRD62e%}w$e~zd#RO` +H7_Ghu+j=qEINpUm-^BO)gL޶o(s;HGEO ЭT,a1*Ϊ,?U< +fSҞ6/9 =D^;c)=ʚ.F6GtͷF2gho%1=ĭH O0Oܥ> O5'1İʧHnY` H\)^z(# "mR<( P+lD=V1C((#&'a#aQtlPz{ x U.`6g)O UÃ=]cNOji[vkrZ*0 ĕ^5P}Vj [71-{fGiF(=HM.lJk41 amxO"?h{YSL9fA$!>? Gb&W_ZHЮI]<%مV'r\t>ڳghU\\ ]d>A\tAk1'w`W)0|tG'ޗ.w1 [;e>=/FH&EF +3f'>0L v<}.kɞO`FZ1aEN`Yot1.d \ y#=2lXm@&4f1bp*U%RN$S +PlH\LBBSߊ,$ T@fnI3ޙNξ +p*${Uu*K9*JxenIT|))OrԸH X w#zg`$1:ȑNE.fgIP,֑4iݓ<%a)n(:HsR:qIjAZZGTl΁:bܥ/Eo[h-)X,,I )"vvҬò圹om{]֓[A"^ĞBi3C=.&>.)kKXqq?wtZ%$NRjV]nS XDUv`PN$=ܸt?ۢ9* +UTBPsslMRLHJrQ+Y䠱-ʶeYyog=?hхP^@V{`!0p 3A/|m @vt9fmQ[H/5`0'}ulR=UwN"6js[8w;D`cGu;G }Qa|AŃ &JYt?q y_ +Ux0%ǡSwڃ_-ЊZ1~ @w&\+oKDaV&<(uI-֢COme4P𛙂g"c.6g%8pYTY;1{c+nHEkY,\Z jR֣]Bɗtqq<NO Y#~uCx4Bs&!(^ 2`]| & p [|)g ;>C1v΀F}诹tJIo0usVBvV* 9*[n XQ-jjA?AE*q%<Ңծ;X@ČHy Pr^!67h*@Pn.-d`K̻جVihEۀ+rIظ=Pq0&<iJjJ;bOY$Ц[jR^rjsO 9+3:pLz,4&RqMMYQdY08Xx;:o-ѣ! s2Y*EĒ=JOh\\ +#a$ #8b]=r~j i[lvЉ)& ݙBC5.;˨M@ +Nm[2zOeL<FH(> {TWx+Ք\^r@5Pݐ 䘝1a!TJ Re5=Y]"_/5dJ99\"g`4PAw vܘJJn-w[6Trjpru 0)$>E-& Xzwp7leT۷dT+fS3g44BepTj\nJJˀ] , AIu&\+:@Gi#&sj'?}S6?L/6fsE4pXIWC_Hur*2 +AXȾdՄK3龍(_U`q/,9xp9Ti,\u Vڀ/&0-Uj[廥*\YOVNEBcVnz/X7@*. ׈pͦS'XFP'cPu%&s*\3byU؜}ẞ􈙐XRz格~+s͕pc=<#E{N1801f}jϟSCMv@m%*6 Dws:7)o)e, +J@|n-<ܸo t WED%Ri!7svNMZ8q_AFۑVOM6wv,|OJկ_f_XĻX cb NɝP:fsTO"tb:T\Leݨ+` PDTfksP 8;`R͇rmCmO3I*UopQJu;;kI5ւ7zlqL;6Sl>P'6m~}2Ru:*/ +Y`jwށ{\UZŅ<0ܼ~W sg7 ~KWKhur+Ƥ&AE){ރOi-inw6ogj՘?ybZJk N{*9yvj|cn20kmb-)?ٹ>_d-G v۷3WəZX'jj u¥%9JVTT* $H p`/3A(]lBq) +"եšXPLuh=;u8V(-9ΨןElybdpD@5.9eƒx(K TM7ERkL6=b.,-/gϔfOek\vg|qh_Rd$gz#Ov4sRjg?9wnQx2S?TVFl1; Qi<:h7hƫKZrj||E>sv+Rpy&-T+tM+U!ѵRQPRXFF^~z}Cn۸ 5h&,@GR~9TNv+˗&OfSnorhs;Z[K'ܼ/ֶ1sܙI"ZDVJYG{XNEY25o{I'WjnOsI1;I-TV䊅yGZۻE'w,x#8rf*/$ʄ;.77n% +W3x6>3_oZt]t4ZY 39WX]YHR.L\r(uI+]&5fc [i;b?5GDRNm@PIsI#.SZ]J5V=A;`Ce13JOUidU{ !Fm*m<[(VꝂG{Rv87y!/ M +w,۵KraA'v/=R҈??q < 4"怨5Uc΄+!3uj),d:XH @H@,"-&:>)*͵/ Y$G\ұ.2F&gwvW >V*RntsӧOJL($eNH({BhS_fML%3`6|&KfcUJ)1HN'!t⭽E~I.Ǫ~u9!JlOxG)R. ,R⵭uv%=g WnjuNTO:IM91cRZ-\LNJeDd; ƭ%!=O+-:F"4 LHN:Ƨ^w|#r=Wb3x.ejWԖBE0 ~)VoĆ@k(8q=0 [z MFOtN836=r/NOxYO6z,LEp !N2 +D sLfiz ]*£M67m)њ۸\_: Dlt8)N.+:U*)db1\ن)Lݼ ="oz#N6'点5h%iW.r57yKtor4XPL;h 7a"J͚Y'*B &"l!8pivZH'H c%n6DTJF931_6H Ctr@Τ\\Mͪ&tnΆXSQ>WIǧ:Do[HW6NYĈYO(Bf< OuTz8$#u,XwCD\*C=BJӡTYglBll9ؠ2RVT'[` KԖڂ)3@)x3=uP[Тa@;N @^^Lp9q=f"$r )='gH>PO qL>6fט<E(j@q[߽O:\(T=\狈  O%;3zu.0l&{kٙu1ԧ2]" +mlf\fd  +/;'<8+=s|-ʓ(^\2lpD]~2~401<=&Ue%|CSܞ 5NI v +Zr2.'x\ZYmMڳxttĢrnVLI="3B%pO.[YTP|4^Lś&5b$ -NSⷾO|n4XR,RكyO9WOBs'_^OO^ݜ?f=\Ni$M;SF(ߕk?/Cϝ{s^x[]#uNFk0TĤ/XV)lsinbczn}7\7/??O?o G'5^L$6ffF!4O7/}֦ٝS,T*PbR}pܵWn~?ٳo|_;?G?ۿ+Ͻzp/xy0#Xܛ[8}< Ͻ}ڿ_|?ڣ6DӉA%-W6౸wpG}77z'_||u0 :-{ʚ+[NJK[/scyW'OOo~BBKu9^hO.mv?Ϗ|'Gg_P?g/C8;j =cVʀNFb,ߞ8uǮ>?}_|o~ǿ?ϟ{݋7ù„4VcBX%Lcj}K737o~?هSzJGl! +R:Wl/:K{>?/>Ͽֿ?}׿?wo>du/ypޜ[>wpk7?Co/>_믜ruzy=oɶ6X'ȋr6WZؽrσ7|O⋷~k>YuRbB3iԹSWxͷ~|w>٧}ʛ=wv$d'(`fM1:SBmymy񣟿~ޯ_~_}W__>}%DCLTkG|_}7[{~_|?~姟[~\sՄIcfrH~3*EB{ys<ϽO˿˿OO?O_WGx>+:4vϘ eɇb婅=[>x'?Ͽ_>o׿uz z;pp\FYݴƈ0ܞ9{G_||O~˿?__}GϽū˻|mpBPngKD:WԚ\\]tou3|.4 Œ12aB]_ +SbҪK뛋7/{+WurezUd0%zdh&i.OEb6p`<{}?>~w/Ԧ8κ  th; 3Nm??7_yݽ]h̰h Pr 2jV/M 5|_z_ӟ¿6KZ0jvS!xX+H%ȕssϜ~ч}|_}_|_?t6S[#3tG'Ɲ|HNz3S Ϝx+׮}/w~믽 =OoډNu7cǃ?X9@XZݹ|3ϽtG?~o^~{xsgV+n$OWˡ'1VKVV6\O?/»?yʕ{RCѹq#>wE:<_Ά3bs5bX=>˧0RjV7fxû=c`4I1:\&'{J؉[cqێLvŠ0a\n7Ax44ݳkjң&d`Zg@kq+Aj R@0FCNR(ƔDR-TS #JdX|fꏳ+KEX![J%RJHCJOcf]V H?fV48GΡ ۉ1m3"p-RHTܽIJ._贚fEMLc#Fe߉aFrJg‰<m.hU5U5fiah#.O`LyG12XCeNU(jKg+ՙ3[-/D ?#Ƃ鞥#a%8Eg`1 #h2E|(W[D#;&YBMNEǽ|F-L- [4 ;qz77Cpw jVCX \%QT&6!Fd"y N6XabJ8*rzfp`ࠬE`Fm;u jm7#Dc[<osFp)+&0bwk N6Ą ÅE?PvJs@2Y_A!W*6*qs:T6 biӓL|rP8Q:i׏Or2}.>-xgBw YظVJ8 %5|`hG85xNքHR!XȘ؄y`bBZ1;T9эg0!7l%Nd(k!d]0Ha\& +juyF)_MuϘꂛMF iR`e8sRQOWj(]W9q>YmnԌ݀:#&b_mʬ FLk8}@ Ď[NRs1IGqscvn@`1u#61 #jsF4w+E'MGG[T:Lpi<J"bv2fdBȓrc@4 q (+,TrsV\#&6 6s'N @z +j?LSJC!=j7TttAƕ̔?Z=u%A[BŤhC҂˟2._!d==1d2Y')0 E}&D"LqQ="pX|f*D;gǾ:fĀv_ͨ/W@;tL=Wи? M`8јwFmdBo6{&X6!?nP 7ԻWFFToLzsxcOj Ƨ F,WŃFqJ +I #V䑇la ppa|fLYHX~˄Jf?>>b{xp;\ƈQ7ڥϐvU21Ǘ6|v!SvILlSN0 (t-DLX;kF cQ!AOENwX &eYWhcT:\YzIaR3bb&'cz/ֻ{X ӐkF+NyZߖS7T.!#µumvNюy<%itod/ +E\O*ϕ 9锃X+P`"]&8,_1xeO(%Xy2PxDŽޯXcᚙIjPIMZryVzן`9#)q T&LQ1FF,;ҩE&Rt9oQ7!к f"8`:44w/4q Jb17[\h0!vLw|ip `&dsJal +S1L[0X6lr|='LHKB t.yH9p2ZdĀ7.:P'!J,V4'{Q*Bj +Ar Z&t X`!K[ظEMpٟ!沽 bq&tKwbÃfLwinn! +o5 BjRv5RZMW9jQ|x2ٻ.pق lfw%T\wSW.5S`3tj,\guJ&[0.Ic Y|rG9p" ` OiMj!P W`SxB'tǀ +tI>5+eDаcLpY"L(y"ʗlt + q U-0F%p|VnX0~`ft 1!L +8}dĂYo 9j \=e".6T$+T 3=#8f$HFY΂!74o܅@9#c##/-N92dX7|GJV<,-sH3lpݬ ĥ3DLa:o]>7OD.jՕ7+-92f9sݠD[t5l&M87t2SryE*.9{)Gjd/R^vvks{٘ðѺOlX}6 + c.R |~>U^--Jɥ|֨xӉm۫Bnʆ Fy:yƨ+6\64԰%U eV^0 VPJuB⌘._x2< ͛\>͜2`^>ĺ{~iZ{H4VPʀ1Lȍ9pѣ13HPt#:c:QZBu۟_53i3W* fR6*kZ<pΌ@t0FHj8CAuNP@r̻+=.mB=o %2wKSg戋кL *P()p{`&RSQ/(o`yNL2rٿp*mlq9#IyNmA3z{r0ܼ9ktT #f&on . V:|\ﲒr nݵϝHyE-Տp}|mR9KP'˟#Cuiujn;_ lcD3?wr!3ooTʣ/|o҃fB V$4ÎM XTt =u\T H]C +WlI6wO?uٹ q'-;LGcv ϐP"W?ȚGF<{ q%6dc=B=Q;c%bN2Ex +(:4bRn8 "uܔP-4GBM'_/5b OG=qdee9JTbQ Av:30:5v^!FYa? d$a#X`KdlR,o BNE6 g&;8-:;~crh +4'XOaWDdFG+binBǸdu|uRMk@BEd\v!SAyKgD QWDHQ'`Dm;ɐJs .xIv`}{&T\*̜^pgnD3:HEh; X9GL^o\zDK=6zR5nZ}ٳOt.ܓ>pp;v,r1's>h(B\dr2R;2<|B7aƜ[Vz;"΁;wջ(;7a&N6 +W.?IG +kRj/]쁴$32#>H{lz ݑaӡ!ӀU@]` ! +Y*Z3|}ҟDI8hICq! /cNQYgQJQشIC-=a,E.(v!@ CF!`B1g"UWtb cP)ni ^].E˳O9 W6)uI%/6 Md< J !/F _;1Y6Ӌnc^*RcBk406|a҂U s%XhL] .݌\tLcgt<sSvt.ls vHB?: &UhuZK4)(lBRaȒцoZ[1Ft.wE!Ť´WLmuE=;N̠ RNCK3;nj9|)K{/K K͹+^vSnD$ȦTcTs  mhٝl~%BҔ2wnKfM~2Je 4|- t֘.R|I Ԥ0Fݒէ.4IvA,x@hP,P+~r/WDV΋|=,Mq1 "(NrEOB]Px4)'[[XW*X3Y[ܸ:qN;1k4P9ñ֌KtdxS :Y􉠁zEwA W#&#%&Z͵֟+pQ+.ťQU9[<hhXS|b>66|BBq6ب{ +OGX2{]:aN:JhuӬm6v@`/SSi8|:TBʉ# yHA/7SW")g+Y*q?e}<0EKQ.zzb1I&:Bz|bŇZ3V;xΩـ;iY%*-{l3I2CG:Z/Fռ-}_~c{[/(9wӺ5(\@J^ wW09dgdgvZi0d/Y@CLs LB#p9>?k 5 p~@3 =/oFrB~ho֮f!FZ ԴYlK<;j;5 ck +ûC&¨>!Yߔb K#V aB4O{R+2f N)I +JRQӘV3nضfeR~BƸȴU/%BR.s.5$P\UV|i 2jC\u(IFōрBOL$AŚ[B|pq=ڪ6W/U\J.ZY/N{YP;&H4H9' r]h% +Ͻy4,B +7rwrO/r&ًT`gڭL7GqWe#K9bnL6wƥ";{w5)5[;L7CV8(i7LD:`y8 IvXFI~l5fJbl U|V,Jؼ?@E:޳B`S8Q"M/aN9Y/J38;8s3' 0lRLH\JP37/{I٠D%1;C: Qm(1,{qp)a Ғ&@Zy-Jظ1t~Jvsn5)AC>4nqa6TeocNFljRNwfhS t-F~p%m}'|p0#! +`(gGdWs㎑)ōN wA#eZ̀cbZ33ޙlt&ZRτQoQ}VuᲐ陵wHڊnڄ mtXd'ƨ/4 `$,5"gi{ae9;\%3{vw{;ʹE1 L[Pȵ1fGBn`=%)FJ1qlL&DAQvjH_6e) M'YQTӵ`jJ7l=P;dgPGxVAC?Iz *~.U7@'dɉ3p/>V,3AԃReႚjOpNV Xea6F4B̍Xѿ5p>TsxE/D8ݻicmh7c?-/j%)=MBpQS2ZF,GmNZcaC֬B.2_$;kA9=& +M0(Ě^Sc|` 6&8ģR1n:ӣ^_rR1.CCE*[ܼQc5l۸vY-ηνdIEqBXwt ^73e_j>O('5A}16|<& v3댒i%Nm,.А`)H$D"n8 +~< @jυ nⴓfb5+${n&" jc͠賒 Wqdh #Vx(Q&k~*E.RTKg_X>|X"ttOz12^QlBItbi' nX]Ӏ|9 j +B^M/ 2I+v|,`H +rYRZY7}F ˋ_nބxHn}*m,B A>رa7OLY | |{xldX-^Z.EXh.LQL.⥙" x'sy6l"cZf.=sNT]ع+LF\4!6 H 0^dKkFE%דSM:ZJ7οu]D/Gk*ɨTt1ify5VY)? +cbV$rΜc.L(?2z&OzX,;'-$ji^. m;ӫřx[P'Ĕ?Rz1܍d^}e bzƆix(j)Ν8gTBb?mN)g!TqQ28n9=w;D; Ԧ2&w'fWNd[&U7R׀uom/^#}2ZWpId )op(4\\iI>;ܾ +sRw L6VRul Ny&?{lspKTK. F+^}IqA8JQGB>VD@~@ӥ`CKGO_h\,)~$~^z {Xw|jdߎF#& q|v4ͧ>ފk.Ilg;;J\>0j+@|b8ݞO;qEDK ͠0 7 + J0 6K}7BQKwsvV\j__;*R!NX +0؈EJõpYG}>q}{{&[gϿ']WHk8xGԁnpŎH'&G]8f91 l|1 +gT1DǻdMĝH(/`cx{r}y/=}#;9x!0*٢ddn|n*0=|R@ر)/7\yƨ,+gۺ`F%Bf Ǜz=?sp%RZE_e)HGLFJL>|\Ҁx+Z^L5VDTk?턋Kf}ݬqf#jnޞټR6.n wu>4t^4A s ΂v4."TI%~xuֻWb@̗g4xLiv}a{UJ0e 6 +*䰰VS3G~6Yj7A>шUV@>0​TO;ʥ"9Nzh֨ÚD`ZCibBu2hu}tg6./kW|Fr>z8a +~n<8bC Ǧ wcQLB GhL矮xz3'[ﴗ~y-R_]M/^QJniyg+|c6"fF c-P pq\/QZZWݿV۫[ޥҝXcM!jX芙&1/dV.\1A! 퀰B|!Pޅ46`juED?Xܺ:B,EH.hM,T9iAHK+/*ބ:UH)81>\5pJ&F5NۛWtu|16;R~4[Q6\Ra` H@0zG[O*fK-Cy$)}4tr +v !R&D%^R0{$twmވ~Buj DLj$ןP<""(贠Cp:Smܜ?R}r +9y黝sSA &܄9);a)HGaVvOFx[lg0'7^x7I9˱z8t॓nȚS8Ekraca<;굺zw~ZeQ~N܍HoRNOyH@+efZ773wauhne_7WəHL?`[3 3W}Mmd4T\IΜ][7gw/K'eN h +V{:[޻ KW"vF׆^L7HbE"ҰU݄2ѯ/V`4૱x׌|;\UW Y/ziL>/"|T%TJbmF\lą2>&y5ӭ.u6nFP'9;}xyI+L{h,:pټ^?R K)7pYOuLR A6 labڎbIaĘ)ϱӮ ' rxgs fI|ku|?&!(%d  # Z2Kdw?cE=ՊI-˚+1Roֳ2a>`ÕVt܎& +ǃ;=D A3ÛkGٽ Ofm^ycֆv}顔ыKk; %7%廯6CE>K G^M66:s۟|r3:۵~{xG҇_^z׾UV[5Z6?j +B˧ryZX X'cm`&iY]z gXIN6 Q_,6}\8!5`b]{PD"_opO5)5D)6noSFM WhՉp0! .ёZد +F:Rb=T7kN242xvPRhm~iNBJH +(H( 21eIDx82'\sI#.Ɔ}l|c۩J8Cj-ە3sBYlj1!^SL`CsN "ٹI>GhnTSScn>1;aLk5DoWV/conMDS~bR\.\]4ٽ-6Al Wx3e;̋f IJ˃kaXʈvmڅ'?(/iJs8.aKx@:ۤVL$7$fPKq͞2^8U!0,lb;m]8qp ?>:Ȩ \_HvX뒞FDsK0#cԷih%&NTTRQ}6;G%hDO:0ըKNNBcv0&.CBw;(i-tVԀjh}wm""';V2!-QYoNc o>:Ӻd9Y2jRdF`gDUubZ?0yu&I(BG^j˻7UL4g9e !ĵ_t/,{u[sĭ{OX\>x` F4ZΖ~bڷ^x{~iQ 1;wߺRZ7tk 9;Z8zr+7k+&M'ܜNr1QY`/HM!§7n~'9Kwߺm=7倕VzFl<%',97NXY3~<*G+Pz873" +JKAYMq7c`jdln`(KYp_/dl F+Fy!p~M5c TͪXY:Hû +**hL#; NɉJ<<D@"V Kfe< >邕 GRM0ƔA(fxtn~Ngj maI! T camG(G@PL5"P>@GI pM5|k UO32pFr Eǜ%gYI)?v#;1RJic Q]֍TwfL3VD.˩ch4fW|ĆۃJ*paU))\_o7-\/D@Q1 ເ懷a94"A5 n=x|l"8XPm^[ޙrGӐ̿<,mb(J0L+@h bB+gZ반alGB;r*;+xbjNke^cc5||1FgCIv E%dpKZIPrJg岓 {.8d0sxinbvGFPr 0z"e5N⪔fy/# D'lHY N +ZR1k.$eېj|ڍEΤPjFKQ> )yHтu3gp"k){"y$JOl<.TD(gPjvdd,+@))1j4BCxa$oz1ՃuDH"pF$%(9-EZȤ7:91[J4FLyDбLR@H()+f]%V:> Kϗ/67V:RP&.`BozNMT ΀q ^q~ZrLBqbpQNWsm\CYK/>O0r UR{^ϯ sN`Oj"zQf T0&)h+Wu;"x)݃(>`zIp7>iG߳z,q~Ȥ' jKJfrbT^BWcu%q姣zv.Zڂ-_g\~&F#¹9"FKŁ꺰0Dǀ1ؔ!v% IH MXpLq ^L8%WSKקPQZfB &pzx\x l \PN1?v9n}jX\/BE"RunW.?  QLBhӾQKTDDU((0'F=ύ{dž`)΄3$Cy>ZڔkSSN!*B$W3 =,I'&~AyP ReٙSlrMaYfAגBKڂ#+ͅTnʴB2 qquNJT,nN? +ӵh1_KUg1&fA.@@>; xشc)&ZN(9#jZtEűF=MV䌇[4Gq]‚>b8|AL+ƕi%" Kpfh6m{gv{IπD\/BJL8ci{pf~wL;Q<'%|EDLQ@MyuMuYSplܵP4!G騘ƕrOOá;{7^ﬨό +%=s>6غ@e,΅"x!Q^dʙAfPdDAIA(R8=px2B>-_2j%52O9>̳6Ä +XfΈp7(x^kx9sS݅SBV$4eG SfJؽ1sAq׸%huk(Fnvtv{avCv[AIE2V-L<lNf11 +1i<;<= |@pR!=>t܉` e4Z"h"HdbKKs7>_j/Xӓ9uU$?r"eyv{$B^KҪ4G@0邬)Udň!ELY'Rj=ˇ\ ~cK|ljd:E%Vv +d U +)x7291Z#2xOB|ď0rL p" $b*R^|t`BD!2J}Avyv)r5WSs/Z\4"aA0jAEƧE A?EhHR@ydiChIcJ +0'?udq䟴N991vv7ew^8P6Ӳ8>>b"i' H!8J kZ"kr,F/_oǷmRD}VTiig\gvb^I]j7}g6DOmI3'F<6K$8 aͼo@jlŞ}>xOxnJ|s;h5J۷j{3 _|/ywϟ;?RZe^7d tJ.̍3}<˯}g]WoiگlΗ1=Jɱ,8Te_a^oO?//??>|p䕽_~kvjOO^d/BgwͳWrGkyao?Σw\{͘ \8jl7Mm+;7f^?ǟ{|ՍA1n,'F r>+KƋO'xǯ~K'o{w?_^8&P\Xd.޺Zտޕ+?>?<{gޯ>>÷/mJ 䑟BbI-K+>yy7Wyo߿߼/n߿w/({ r\/>?+JJp _}?O+;+^.Qy 5n&1d747{~o}O?o{Wͽ>_~>ֻ˻=%Xt?6 Mg;ăw7^O_>+_}pWW޼Z=4t4H8fw|?C +oݚ?pW?ןo_k֊0g%&ĸ(k\ r}xz?ˏ?O߸t6I0>Lj"s8?<[oK埾|=z|)$AqQҳJ8i ]R!d:oU??_zlۗ>z{령X*!#ǩYHņLlb.yq)9gx⧯{Gg6 +˝H9 ӌ\K騖ԘJJʭǏ~~~?~_/>W~ݳ==eD5*LOM%#s1yQɥw^Xޟ~¿Ç?ޝlyuQG:/eAV$)x=8sL_rw\=702p2^ +SIۃҙ^J˗O-|uyDv +uxgCIZJIZNL6ft~ܟ+Ɵ\|o>xo_?N]>8S\*T" N(ރՅ`@:+r%l&^<[|?yk>::\)`zC9BI](|;ZE.Vw~̇O\Uyb1eA!76tO"EV>vս ͙d#6uAW50!CyJ2M]7YQ*cC.b#qvra}n/Jn>LL]$)ԄXΧaBq|˅*ö^`>}}=݅/< ?~߹򃧻=7/w/a!!W݈q ҹxN8oDss+^_}r7.xe™ڠªgD(oPB-)Č"R7kóip=?(գ\>2C!QAܸ>9Z3%) >Eba=LRL\LbRP0ex0*ɥRz}`R9 &|~RBTi9B)riZ/dWj%<(D +fA]6BTR.{q[ǧ'Oa"PZFia:?xre{^dHA-,Wp> 9ACˡV.s)# M)"Hq2Dl{0r(,3b,4|WHe+klX&QYFxt$#5!'0!5D8&d4Kj>0"1^ H'[4Ĥ0R3q#b5# ѹVre_(,wv6 +Xù3cQ'sյt1&yOls.?|j2MA2!*:Lw!>Jf9>#)%ΤR\yVܤ?O-H e\` C>|†L9QAяČ\ Er.?O m}[0vJʇ(EPDZX;'j(4PR'F=>2)'Ƴc RUSӓB#0.0bXV8 XF#Z(m\uC%ݗbl(]HM1֌DHITҸ>1址x"3 br@jD2J:O2|ځ"QՅwLU1QiPzI0铧rMf]Ih9nRrK> pIR2gTTWJ45ńK^6n" ?q[P*|@+iިZ0B8Yyԋ9+$D?7vK~];,M pM~pIS.b8=^*Q1;.%l՚:L_'"|K\6XsAX|⸓Eb#%lcx)+IZ F/B\,vH)~: kfeK-ncVu ICulaoK=#~>>vSasp,ǽV7 )\4du`LY<-AE'g-ra% %=~8R^ +HY(sf=DȎʘ3=4um^{ln>lxM-+=:> -iQcqYE:梠K6Ds +I%=oz7V=uwҪby*ip1iY<@(2w~vOHH`JM~1 +%eroukm\ *M(D>e zb Nk^uS&8Hm\#Do!z0pr̓IĆlUryq*IRM'̼ZX 5!=ЙQ6E7t"Z %{crZC6z$.ĻVua zllV+G*Wf"][*>\LUD*v5:1KpÊjÍPSs^!4/2ntՋk^*DASsAPG ɾ=pqÕ{Q Ȧ^֔pӾ;{Ϝ~Y Ҭ9# >>@]TI=L l'[@R +WdL:B..fgd{UXjͺ$H]ۈ^&1+3sWO˷|D?z-NɠT咋Fcm,ˋQcbmd]a-/gg/<<.Uޚپ3H->H\.\ѩ$bknczauzx.,{Hrfb vCeVz{&{Yޛjl 9̐˙Y; + Л^G:ѫ{ To=Ui|9? 6wyA Rp)>RjJ<,MGL#w-4ZG_ /wiފUH +W=uw/Iov3{-+_'LfqX Bv? O~%ft%IoWl0@k/Je4}.mڐGGO~xDսzJt1Km֙Wr s֡5,w ȕP^Y$Z!W=ݬYARsFyfto:}5o㴛`Di?+ԳB?l~{2{c8Tk {y=x=~n1{ ʔ'P@@P&Z笺dWn}׹;x˔ncُ$+{Z<{}ͻ?ο;GJm<(Ϟ5m|w/KŷJڄ޽bsٛO_syZ^sb? rRkړGGCe=Qډq$[Q۵'JkS1}80wH\Oqږ%_3q.wkgpK9ΩOꜱ;Vu4)Oo|..^83MuJʛ>~\으f7~ovO?6_)׿~PIqN.@q\\>ڽ҇>NOP9:WdP\lewzϿknGSܝa '?Lc΂R%$ [6Zit-/5(1?duҤ8{vwN]y4|WA@\ v7WѵK;W_=@=gu˗;|$*>_޾ySmp! g#}5OAyC,Nr\ypߍ~Y^>/͟1`Βe( K)L#l3\]dZRee]} HvAmf.RF@ӂ=Boqux RꝔBe?~(4GqZ7b`tà`T0Fwfz=㟶s I-ڜ)lWF[cg7n{V3n8]ox7v9GTNK%g;zYUJG_6 +Jm)w8Pʙ>/}-!ڻzcmvy/=ߧo4Y{_o[M ^wիg_]#rBV[G\~E-YC}qw6Ղy o~W,NƝrEZhDHgsRݖ:gѯO!wΥ|nR.F1>ZHk7+{&i!JX=);,/RG2&إ)*B9h=%Q[=_\TG]8^ +Q˻v: .I`a₯~JP(-J{xiv.@"8m[3sviF=v`u/b{Yk;te՚ur4\, Vg]άLuv&5)x{ly%s&ӫgD=ji88~V#ggg砑/yi? (} ?zf]SO-S\Uii+v6,C黝Ռ{0Ƒ:1o+)?o-x3p?Ϳ=ko^} P8xO v5x\~]<ԛZe~EXì\C]*cDj+AVF cjy˜=83[Ww# 8[}M&V@u?O奞]_^^]qbܻd<cKJmIC7Ɣ;/ /qXw[0G3կz' nb٩`Jo;ݷ^eM^3NFP=T Q9X34N^nGR*g GPż#6!iS_/&WqIKzwpjt~뽊XfrUg`5{kXOk))و~!JeR\Lߍ? ́T݋b&@4G ȨNk'FVQµWČPA*fm[/yn+ˀ\KYIw/M %ag\0VbyhA=T zQ \y1}6y1بPaQ^Q{p+! H팎+Vb5Ik+P w!HڽRP9Is%D +ms4Ӵ]Vg`59o,mo<]$Vvrl3 \ᅠPU^WNojalH+=VlQBZ#{p}vӤLy/d-pJ[QO.NiAmTi(dOrj?! {5ڃ8KKS ! +&yvnS'zvGmo{_fJZ(g +.>MR6Pg(+5Slh?¬']H$!3.l +D ՛sĵ"!({"{,z!xXnRp=WkX emriԄe[IlyGl++ux9G.^Ҭ7;),f^Z3ZbvNIs2c +|xт#l`I;IGshYmt$YE V0+joe?I b~svN?~jӝ>RǸ3H28)|7q8LkɋJwOr5Ҟs֞aR{#Jnr魯|9u3)ӐFTogb4'J^]32}NiC:`<"ھP?!cYz?I;Ay(Ԣ<3Oa1.*2b=oj'y[ח}=Qc+w _pU@fc&͔aaqr'U + mw58JlfF !k \idz5Lr;z봱y<(}6FcJk!Õҙx]/U:ׯ´n渠5x<)WhkF[Sv >}=- 60iJyȫ)˜(b)y{.y@V"(쭆1L97j`-e RgPoBfTF : 4 _Lqt|BҏF aW=}o"ߜ`+a4EovNIѥ\,:hRJ<iQh3C0RruY9s7r:AqF4d>aC T!V7x4{"+QP˨ܤfmz$R֘+Bʽ,.^u7˳(aoo$w_}uy + 脼PzF(sC{gRam|#%"r5/T@KdyO,=@2m4I)g"N8y^},SlO/N.FI7<8am2]P0Iې-G V*ݻ};Vs]X$SZPYdcJ|~kT&@VW Fqk2$<8&,c}UjJq`b4H?sxb_Z?C;I:ъ4gY6ƴ9%n)0(EWҫ**l0V~cԎ:)iҸP&o6TZmTn\"+wE$T64`*6Rrlu=|#O WgAb=mJ.bYέNGt57+ iTk\Ds9M ~ +Cu\_*u4#2f-9 +QsByZk +bJ:q0_ Yw*׏>?i $ӃT[`!{02Θ2V*6 fVFźݱ>pgV0G)qSځs|Dl6`FI)W@]l ^d9Tn51f@f\y5A +jj='޽ a[M"wsrZ1c@ʍj%N}zaDޏAu0xdVw>,DļeE$a<E +d5UAM2f$1_O:,[LZ S# +(A:Zn .˓kgpƸ#6AUcrD,x@Dԋbff_jJ3 RT4*ׁLh] a;97 zQT;r7f΀R+ Z\`\QJH cBd¬blf4ד4k $!rb# 2 rV 8դQ4kSl%/m(=gpcO;{:-DGFN`&g(`nXf0 (l%DQj/M8B9I]܂T_[KC03BL Xm5JYq@aќ +Mq71s3!Qg s}$8,宄$@J;CWLo@o$UJQI0^tH &W(}7XgQ Е g9w#}UPEf0~Uc 1\c> n&`V I9CC\qS;jXn('"SZl)nVT4E0%@DUmR'oq f>琖Jû[!JhS~pܺ ]0ڑ u)#8Z $ ЭƸ;R\pp=:ӅPm5r븺OLV>stream +Hvts\ S[;/ ͳ4ی^I͌ŭ4[B&_|"xPנ PC$SVo&VWnǏh,[¤)WK݃=#18{ ^A2jL,fh;#!U҄LTSsVB&%h &m(ƬPeK{q@Oh=੍$2~}|8a#($i*̈[9rbx+̋11#nqbiW͡>҄0aFX rj';Nvej۸7PDBr2medr,߂7v-m^y, _DC c9ڴǖOioABPnh]R"Fho '0nH5X͌쳞>H2j;j@(1 j_rj9lu:^\A~8(>+#9ZcmU Jm2$'2\%qJ;~J9 wcu]Př=ŭ9@.T8rs(ɶ0WgC4$agw S!6 +'7tiY?C  D +g-n'!iy%BsJ(r}6&PeqeJ ROq'F=5;g ei*jeyApػP ϗv4Nx[Y5ಷr4 B8/X`&!yXM񵂳,/1ۗ>Rba}xsXZ=B&䘊Uuۇnv3c;oM {q2XPSBK&@ m:xC٘f.}5bbTnzMAum$rIND423z$p SԪ:!̌3^^lzF nw1"'M9_MQi B-+պ7gy#re4zAR?LkW)[kSFrօz`AP:)OIjp.f zryi9ն2r>ȊeR¬$\ !:N0}m`pүB(`SIiz^wpYΉ5̊a(G ߷^+!V 8ySzPP6fc9 9Z0X4*V$FZ>F eo7F6Bd0&>FUPyS^@|LqVB>P%o10_܊Ramȗ!Q y/@@`ɂR^hm&F C*+тEaAnb$W]K[od*d*p̙R(_x#5b'u1}T[K(YȪQ‰΃#$=xLX x$i`iCu~u/p{Ŭ d +rEm][CO2VRtSUN< PiHBd1'9o/vŸU P̰^rWi^JBQ A8a,[je=n捕8/ dy7-ZOfNAtC{L"wzqt%JUJt;S*5#V!($ ˆv?B}BCrA̶Z/i`6 R/.8{ ]P;҉P1s<q̈t=xh2D@?3i}#kQWvjLqCkΝq<f0sH P?J3oJaIC$剥B96+52d1)f6YG\5+5R},)l#"7ФWUy^2H4a3zW.w(83fnp~¸{ >S"{eRll FFDjE$zuqs_Df^ +9ֺǿvS`&EfJ^ 3nʳW!E>S[Hŵq+q$Ŗ8Qq韇>TO8]Qe Y5 +8͔.d\Q;ly?TaԺabL(l$/j&Sdg3'!7jƵIkvDsTsbKxAF:#qg_n=,Oߒ,(*SŸnkirA- ~_oa4Nm`[<,w ˟SS^BmQDT#D{0xW3}_@n۸ 䶍@n۸ 䶍@n۸ 䶍@n۸ 䶍@n۸ 䶍@n۸ 䶍@n۸ 䶍@n۸ 䶍@n۸ 䶍@n۸ 䶍@n۸ 䶍@n۸ 䶍@n۸ 䶍@n۸ 䶍@n۸ 䶍@n۸ 䶍@n۸ 䶍@n۸ 䶍@n۸ 䶍@n۸ 䶍@n۸ 䶍@n۸ 䶍@n۸ 䶍@n۸ 䶍@n۸ 䶍@no s?ol;Cw*(>1?ę#~68W +D,Yr%\'Xl~X<>I$WW=$G2H,r)$I |r $4Nl?> IDzD:NdR~AQgr <)U(̣|I['';8+Q1OCpI?'Ζ¿_ >`JJq6w~  J*\I&r˧Q/_YI1&7>xVri4giF(nx//򜗦+qˊ]Dgz,koaj1 H1 SP!I{jH]̘ z_,eޡQcQQ z+I }̹K;$UkWbVNI՜F6W^ƹJ[6%8`FJ%o9U̬XDČP]qW VA;ZRh޾ҼyJj zNl9/[Yq#P9Iy+I>+E{AB0nXPINAmPc--ndpAguVVĤ6s\=)1V0pi +ͤp/rZ5)y{曫)1U;ADZVQJb8(Q#!~,F zF,WFIbFrs09%⨺~Ȯ&`N3MRd99ꑂCYy#)FXr4]ǔNw&{,':`3R0ahnF #:Lc,3K0nrpP_P9d~_eAe~Vd˛.ne$PTn0܂ulHXN4Nq&y,Tϳb'B!cFԭ{v$ +*Jxq#-6|!D&*iMeqpgƀ'B, r[jɔpF/MVf~,LF f?v! !Vl'z*ǨJęZ>6J-׶j 7# 40}+'RB8DW))ZمmaElI kJ3Wb3T|3;[Q*͝S 鎲R33?3tE~^O k4[OPͬD_N*[}˜2v3N3ʍE|zD Wvwi{[J뼵=Iqf^̊ b-SToȵ35{be8p?n}HJQeX/LbL#vy{"~#]ܚqn5.dj^bF(9WL 1~4U Qf-Rȧ8.Xkie320 ^i@4mrP O)Чyfj0PѠar*'K}~ Dr"f9FHs`09gr$Q$EJJ^Z+rZd+ۖe9wVݺ4[1?<11=K64&$4Enm)*wx4칃SȄšnd +6 ;!ZDWp5guN` JdBy̾b p"bѮ+i]x +}_ W>HwOL! 9T(Az_drO6(m"-6_=_2@v& + +Dq3eB$-btjCdt6b܄I d rowub'S3EP7#avD3x'- G蜗hT5PV + $eH([yФS ̐ _*cv9Pf6"ᢳ62R0~C7&\$hX *|1hԏH=)k1fjiF4dmT}̃cFL x[N~@Dn:cV.> Vx'TXx;Y&ȀJ.hNeCDX2?D6=:5"icrLrΟ[JM7PV9 3ƛE3Prsy6: "&gTjOKF<6n,DȘVD+)7v#z!||B&Fx̂ +ZyYQyM0·CQGt؈r-:WD輀?" @jW$x+dSV, jtG &[+OZj_c[h !1><'P Tw +j]LaR I cp T@ݸ%4CfCZ/洛ǘ722@z★>AL:@܆k *D R{B= _5m7dD(Ye`]R/IFV"XC#f:mfy!ᮐ^x$[{CzowFz̀Cl;zhC^d tO)mtK;CS)+c's *vLюUJ1GCj-v2BZ_ȀȳP  0`=|ȔCR;DnAz>&cp,#:J΄F8!lB">_5P H;ᠳ `XIM; +̬1KCC0 JCjסIܨлF$t20a&(D 6 %B:ٳGt?GǁŬ+1Dm);I֓5a%!郜bb>(-6=nō7PbSspEL3y61%4, Y @"\(Rа2>U * X_{,m0 #5Ē/B09'v@-شM*H3_ 6AF ^D(e<6aD@}RnM" k<{ ? )^eMw +6ovv$bN٠cf_BѠ +xZL7b$x CQ i}cFԐiLL&-09t,+xu +10zN*>agaxŊj/XPq"AY &7K0)+7V<&zŤ26&*, x@yD$LKjؔ'.&ܢ!Ƥ[#f"lJS.q@,,";@v>TX@#Q+6jk{r]Bb&0NN h3pr`!? V}z ^yHԸ׺m{d =hL٭.vkD@lw߼O&p#pH\ +baXXM;iz7yDU3.C% +τb#f,j]x51@*튅ehrg@aA;脘@0vN1[8qӉ"uCf։,겹US0XC}ҁ(3hܠBXy*fBNO_~R:a5.޲B鰛GJ㴬g ] *~'a-jDlM MxNnH62n=F$hŠ>X8j.@Rպ. *LR#ftQ8EJy/?<4f2F d|S}&Je!'BZGiB̃)3UL8H'츙u"X#9h: F80t)/-ykXK[}Q3$q48S +x |و z\ 5*i@Cea9rs9_!LL6=cv*V.D>;j('yp[0q+i#n. 7 DƤ58 +h'X^7ČL:A$%[1+ec26:[F2Ghp5iMDҟPekL4 3>gɖL A&ZZ$IʂnBusJ|b^,o₆Q;F46#h5nI&M I'@k+E"NLǖdjDR`UASvq\ˮ< 14 3Xa!֙^xY0:?Զ & u8AM΀ΡyQ@cY-413AdWN|ALPnЄuD*YB|yNH- +4=ʻ;O rdf'V Ci5NzHǢ +(xTy5Aޗ2S.쳹3sPI5 y:T3VN^l +ʥLH9Ck_|by/'b&RfU9H wȴOk D[(XRДK9č]\UL7dofpڌG|HD-veL֡4  C:2WCڒr(f)AB݊mxTm@/!.< +c)Z 9wT=cFJ.NYHLh3Y2M+uqeP[TaۄHn*P#Oq#YX3r%V"cz\eb5 ds[,cZ4Oq3uCŊChP829< GT, A8jaqqDLp~hYjUk伝W`xZtLhg!`B9Z1v_TU(Vnf!gJY {q儔Qu̪\Z\!&`ET TlX UV`1$62lSz~#N57 Trfʾ@J\ld|bɌ!-CLsP1;jf5&opB)]cծʠb Jg'zrHOɻE؞ bL%:i?4ilbtNDJ@&47^?:3 BJz$hVN4 m5e =1_: +PuE0Aj8B[4>PiT 1;f"KMNIk#M`d7_TDk,he2Z+1A`!5 +nJ59D͈RyBtoDC5BCC x׈=7TGal~*6+$p2)tq HЊ0 s7(\HN)XM: SD~Thv.;1]a,{mx̨qPO:Ct`UH&l^9=BiٱwCː)ޫXC"RN-i3$Z2:;7qjFY"ŽDJ*oL lMLCܼS)gdl5 :ؒ`ʾȰ3]u:TYrldXKdzX?eeL CujP#R[a2}HCL PѦXXrUTq S=Xp0@)_n@aXeh +ŤgC@aJ34=)R U5TcɻM4'Զ;_Z8Yk@Db |ẑMt UXMSԪ-:Jj=3RN?C3poTAÕIqxM7_S)k-"h̀Lj4% l- Db M"I2嶅NBkp&|/av +E1#11XC"q ɘ0(QH:-&" :,ʘ+uW,x×pBaZJN +CZDk 6ա6Cס_v u;  umc3Z_ALL联A\-|AGł/A#3` ~d&yAK٠E#M:5u,RF,!"pk p +sXa P`FHA H+U"Tw*H$J,,ewl'#V"bd4PeS=&9M:F*L'rEP=:*9 \$]B..*5O&f|BDt$76Rɰ TLBⰑ ST|29 *Ti""*Fļ {7X!ӰP_`=zD_Xɥf2Ǥʊ7Lgu!ׇpy6\rOQi0LkV":aAL#o :NŻCԧmtn +TAj!d[ϝ^(O R\`@EOŧPuMh~7@G.?HAIΆ*BnVuN&fkKdOa(-Uh i\б:jsƦPXv: Lbv&|eF`$)V ++N A6.JdK&#-.,"RVRdM΂+]r{5y..-47dWt+ ǪKҽ=EeLn{#u"e]T 62i!DG۾pK,,eή?3Hw6lOWMniDڻnj\bU&Ս7KZ{׃hu})21O$lFn6aJgLhHU*/qy;f 7`m.l'{D_::Uw33WO?۸߹D;܈6œ\._l^B*4Gc*T_+Moxw==DWu ؼܺ-{cžɑ2tjrh} +˧zTj0s,Mf޳wSK UvڳzkH+^--pnqbo.îJlefmH@ 'PbMBnٸ-F*[Ņ3NP0g`WA /|c4" K3: dK +t rcmz,JJ{ +lety<0 hcK, +:a/RӱEwOV,m_\ܻVדm _xdc}a~XCXw,,^ +dK۷퟽ɵ\NN%q=\j/U6ltҟ[;PL#V6`3kbhlpnod,Gj+5WNWtϼsG}?ږ>m +>wGx;ڼ7P͞MϞ_UۼIݵ- $d|tۅ_lg {U4THwVߘ߽BVH'_Bm1hMt ;,33V"qVkK򄓟t0NVF:rm+=ϟlo]^8PZĂŬu} ^Ó1SQ/e.O+P*K'tE\G${)*3HY2nadfp ANBHe26o;{!IH8 T|,>\秷 @߿xGX]8KgѫϠ';}=^ljMPSs{\tˍm6Rza/!Ŧ މۗ ?#ݕz%:c J c*u='hdv" ܅LJѦDWddPL^8XĤgJ:ػ3\_5,ZfMPMPFnp<78Ν%:V.O꒕ +K3-y$38&{& CPBB >y)?#g@,م7-jq\ylfzO6l LXSvJ3ae:n >57j, y{*# 5 d.m!|z f e P{ꆐYtr#D4.D2ggt_zHYݿszHXuxz)s Trg`=S5,Z'*3E8,R/Bmm_xBLZvCB#gDLc@_:4L +f(,Œ!yqy1_@@u>]6~$ =>%#E+EssBF2'57cA=q&UXcWM.7F*N1ll0 P ^iqɆL8Y_w%3.1nszp"ZeSM MFCFlR9fÿF, +orфPl$XP=&f#ѳ7ޫr0.%Rٱ 6#\&h!#T%f\s";7OT`݊qLʸX"ZqA,hŒEh)Uc%PɆGx; +I >eب(Lg?_T>c%.jl1,fr3`lX4#⇰IcО KƶWT/3 '7;ʋU(q igdo Hşɥxy U1>Ec&ߘ1 +yɫFstkBri>O䁂 n>;s=j+d7Rۨ8D*kRnVN^;,䤋A65!zd{2BI[ ;LO q))A4:kruْm2'ۡҔʰЄ'䂩iR4nSd#|{'U) 2xT\u# 6EK-6{W\CO7zͷ~?ݟOwOUr]LqX)kɣ\{K_{^qڃxOϿٕ2)lm,bBgswm3< +EҭXFR9w}Z;uO+wKL'N(EҬ +Jsսw~mk͗oe ߸r3Pn9U9{&TĒ9ןĄt8v^qW+JpyL2bxkzye/^OwO~_|ɇ?~kѣϽrQ+tbr4ٖ"dm\8qڹ+7|WWg_c/?G?~so\`,Z/vWT%Siͯxs?ҫyWoї"WFmh(Di),VZ3K8vµy/z_'_|_7^9yR8;n:ʅzgaؙ~c~O~?~zwᆔPZ8Mk ;.^{<oO~~>ß_뿡[ϞƊMZPNbaTLm~Ooݗ·|?>Ͻo$33|:a$%roqooƻ|_?G_ox7}]Ii2$teuĩ =z᷾~/>_/]ruik/U +y%i>++w?tC'_ß||o[g~mv\eGrmΥӉbsvigm{{ow~᧟}v7|ozhvx0e&烉R}zve?}=/?OO>>^z>XꯣLed'Z^?z Ǐ~o_}o~_~_:sEH.bǛ|/t7K=3x_y^O_~O?⥷~g;)ƘсG@"J|}uOw~_/_?~~_'/zsWMTPƈ:;.īT-i-~c?y>? ;?Oٻtk\7O]>цyI5X;~}[z͟~ޯ~/?^zWWN|w?[Js:_N/@ڜY^Y|sǵKg/ޖHKv/Y1 V{;3;727n\p׽.^Z6Z XÊv~/|p{BRY?wc~{_ǟ|3/p҅R /DW<$%&;t=R fזO>x~g?z7^}yA,y8 +Lk'-.sͭ/[͟?ۿ~Fskt$|| .*^63B46[o;G~櫿ϿO{O?~r8ٙ#*У<$kxif~yq}nW]^|oW_ ?쿼qc3EL^:Te^=K7wyg棏˝Wy~}{ƝO~'6sʠpRo^M/[Qh]6oorڷ^} X鉧_{~߮\{msXo\+m!z$Fufe+HVt'}dL5."%CR4] yvǹQrو&m LIGN|Xg|# XMaA +{}>tZo<ܔ_k&m^4"j0\ UDžBIARp4"ҹL2_۝P:fB$Ѡ:x#V1 NN?޻4K;=! @{oH{R$)$lWM;=6ܽfgwkٯH s2 34I![hMϟم;Ӂt6N.x70μ˷\ @rG +D~/"g{xicFp\|*.7POWf 1SX bnU.m;Ym\\ IR*עYGbkX[tŋ8[ Ҟشgʶ//"BdW 'N̦͚L*+ w'|"J%JmL,uCuRǘl'e( Ony,g!b1&KU:UO +r4JtE S#RGUoysb  ^Kb!H^LOEVAH9%?D<bl΍T=% +j;>cYA#:$\*1cYε%$L^M?>vHldڻV67&S[>jG@/'1(msF/"TSToJRo CB8ބF磽!ToRmJ1\fdB*ׅY +QjSLfK-/[J~pˏ$laj6S`Jy){1!2 l?fi _Yq-ɧ=c G8\uF58^t%&DŪf{pl3"m_Dr-aRmB-[g~xʒ";!y+! 3Ηc\)8'qJTP"2.Vuk%F!8kC?nPkP Vbj)V_ Shux7.G({9_t'oWXh+Q} 򧷂s.,BTϮ,ϭDJ\P +zŅ~=;Mz"U!kBjd'lq.%ipqy !ICZ `RXD7֗Ja&5Ҧ<UfXrM&m67[p|,K!d9B2!RT` Z%J}MklCEBdO&}*{VT4Nn眫˱t%yqwLRD]z7!U &Tf;PbE{ +DUs>JZqFY(zm3ri0D'Ru"sqsa;Bx^ D )Gg r~UrV?ƢBj:0HUR-w%lP& ʆ;mL = +!JtmulB V0n,uG uZamlG\nLpF`_bqLY-<6kS`ymi9.4[xlsk1qBb'S?Z 817xP(볗?'6w.B4WIaaqqڝ_:K(\c3 ,eTmQ\+ƃٻ~D&0kYIU*j *Ө\2 Τb~ʅI2ypa@j9 AP@ҟ!*V>ntT[oVg@WWx9`n\$A uJr^XsE?Zz5GZz^`y?e0PBy0 #Zuy8_P"8Ѫ[VD*ovwq)6tO;Iar7?iKHR@_̘=y<|7ʢR>@Y i>LGdVoaTSiwsA,jym|_gT+ +[\ϴi{t vӏ})M>3.ͺթqura,F= +~@p՞H>OkZy{?yY~P\7tTr/$A~yn/GD?]H4Lϴm?Wv/, UZsK_Rr!nN9.tsocrU.oVw^~@ ~.%?uYK̤~c5: pUj=q lh4Nj%L BiLa +a0Njpb4F}8 Vڣ{z븾jڬnEhaa5\1m9,P09a:$U&Zax9s;ӋvDqn6ic .6ڙ֡QWDff 4%xՕmۧVLR6uC}0MNq&F5:|&,gpo~oNL*.F8R+y#DA"\%;&Y]ť2@ꓣG$gHNI!Z"Հ* ~in/ǹ0n坉{ YShY9hF7;bi[l{gw?Csu xg UkPs>vemV\–< [Ras9'br!DQ6}ý|ER[Y+.>cJac rvO,ƂIꍅ_\Y35:f"9Cj%{#y9|_yۍȮila~Ҥm.?B*8gJeHr9ZB6H YY1Lo{l77,n1f0~qr$7;uwL:  (F;!X{:7`SuRz>=o7-M_λ?6^BzQʕ i店Z1%09@#dCj^~>zRBfL( \!W9kZ+qx[kmu$83 ঌ΃Ɲtc[IRBJOBu%*E] 7b8k?k+>+w(:7}"R}K^P0*}NBN Fp +f\MwN:]Q1 ?%o\) +ҟ-Ů.ŁX5g<븾_ˀWC-JY't28x18y]^+ZNu'f1]pvޣYg(/e0t%DF"L&i%ZY T[;/Wyw_H6KDzhNGoBgu!bE.oJn{Yʹ^}Ri YzƃxyVa3`$\qt;/#}5zKpCίeP`)mMJ!$'D33ƂDV6!R8c ZOhue Eh鯒57$\2Hغ:E^ `vB,E&GHw<~f4)Uº +d505kŗ33jm*'!>. QZ/oͦ] W\񫮸;!FS-X;FiI"QFMC)nN0 lczPkATsy+qW%f3؁ЕZr#FZ]*kߧ+Yuz~W~:' 6OUι+ ̈^=*`6N8{NW0 ?a20?+]BUJr6p,^VΏʔJI[-\-*=o{ri-@kB5!D-o Y +Rq_Yz * :N:[(ѫ}P݁ҵ{k//*$\NA6|qZND{*ļA1~%LtgRbvvgaƤSpϷ=˅JwwvT+pZBvB!`$h3bJq&D0rG8Flr^QƄB0 U&;P׼݅lǙUݕe0]abBͥ9aC+qci{/ӭcWT cz4a<6Rl* tR\v`N/GO襍XЇj08wg9V0rFrc{])l tbD% %X wvA< "x 44F~p36*6Wm]|%+qً:O)u f QD1,9WL`VMe;S8>rcsLfWRvO^NO>|"&YGh5ޚ͵ZrMu2Mt%8AW[ 3㠼Az `Zɴl6:DBzsyxJbr (ijU+386j[lN]6{V7lkRHYbv:-&ryaL: 9tzZ~ͮnuTR^/v^[cjpף/9{48eہ|?Yχ%_2I %+AxqB[C>z[lebiTd?=ԫt)(m")@;Vxj;a8S/JʄZv}u[P\ƔzR^/hW뻴VOGJi %:vkɜ@O#?[S1'j;UZ{oߟ<238u[>׎rZZl>,SӜz!lWAL[`=15YQF"\k %/rR)R7L鍍$,?k>4Um>&fB@cL.N!![ޘlߺՅ[>PT[lfD߼x9 +EL&".Rs=\).pJyTOD . (baL[.Sj ҊS@f2 qz` <1Be̐Ps$@H92{FCi&%,~z+ymڼdjty"E RV1;'g3 ٝ}*vZh)q*fo.!opvH(6gT@Cm2no/G~Fȴo˵vw˅5<=͔}rY?L9{5Hf\ Dj)%C pQ;*8qgZuΥtpn/.>9=}VU +c); 2ۊF( CkKa2"-&~ɹa1QKA c APC6фIEWs֣JwFc?E`ioB %-{G;cRޙ?)V7;Xmn=: z^*+jo&VD(%Y2TW;DN'[c,-:[5N+n+9fz0<1JcOpZôf2ܤڂs;*&3WD +ڋ$xDrHZs:ݍ{_ZwkOZ&wf!D|?1_XH\SQ +/\nt#U؝EqrԊfc0gG)i4egY=^v٪sx:LBD G|B*/ƕ+.ԅ!kDɦj;;ӳ'O=7G*Bl:l R)nܕ{ ^mrwgǶA.ib#l!c1`n_l'R;ɆLK2B$T{1X!w֚{r;rq-ô a !+`l>YwnHeQ~uW >\C،h5LӨ Olu{E1"b4BٞMI%j>yBT,')f҄K>Fy'[|%4W15)V*k0Z<oww~}UMLATaZ+֠5NOj?'4o\#B޽1ܽK~&mҪک\fV.o..?lfɒZ˨wM>Iw9w?C}џ_/H?ǬlW*a\SKW\0br1Ld5*퓧g!d^[JC.*Ouq9 ,Պ0 DZ}tvݍp 7Z-\c]D jeΏT?|'Ͽ 5vB&Z1j/|pmA8g~Cng&Vs{_kdg?4F28{NJ |I|IؼZ-dͻ>?z×K<&0)/T#\a}>J]wޅ9114qT@ky >Yȭj|܇Jƈ|}}S`}[\Dq.A} +sY^\+\m_[ +QQƊp/tRrNM~|Qޮ?Ll sl-T,H7k(Յ. Q[@Sd7c Z;{:҆3=9;<^LiKS]{z4, )ōif#lĤkn^jI*Lc~mK$$eF"kei,j&8@Kr{0in=mb\.Q!,PX`$ε6"tƏ8W_47l^=4O?O_㕘B:a~+:NVc"I:0VTW:=9~|G?}zw+no.A[r#fFa̤$CݸNWoį/r{c1 B~΁hwIWOʎSLn@FN/?>k]|螾Ϯ>vu ivY%g\alζw27ݨg[1qy;΃w~kgo + "l6}|3ק:;/2Chz9 +C+1 5D)fZ| 1)j\qPʏ*!!JEzGbn) O~6=}eӀoMaJf;}+ avZۏ|ۼXDh5gow_/WRo o_~Ncg/J/8{UypvK.F_ k4Dbkt<غJTsQ>j`-1ӝr<Čզi n`wK3M' +VHeM%-t*6NpYB.Μ<z2)U&I-f3䂏K6W]st"dԻ1*}x7 í}&);}ft*,0zmoO~j*Ew*vcBe1@]] p!I>pPG}mO|oZI!xV[V_h]7"/(._|65Q&%?i ɻoxF,LgQenq/yJ:xOw + &8@c3=nsF_(f +ӭ2zZUB Rg~6'luf-̶EMJ#Lba\ܩN/ /^O qů/ǭGzars)?)|WV)@Xap7'(. z&pv6O?PÍ=P{Ln4\r`#z56`RNBmй:HTGƘc}BoZ=HVI"gŗ;_?? xzsj|3bwA+"|Zk k8b( N.}zW?%/~}1 + >/9kVu/SRzs[Ь=אol2>nl=lm?߱;;jaP޸~ekV3 +=)ۛMeg~JU(Te::ys6ݻ;/gAqj_9}i4PKjmVQaFR(rC͍Hl"qc >6^ m% cJB Y^N +vR̦ yCփTuSH72CiL+=ɏ1 bX tgG,(8`L,ؼ'D rs6[{;ョ'|ztX_WF'ZkƵ/j_m\OT,tw/#\.UݕVx[,N&_jvoO7ow}_90jm?}H ~}ۏ>,ʅTkOnRr:l$Uc0=ln\=NK+i{x,8M priwVIEYQ9kgGRiMȏYg]hbEL0FMLK:S@a2(ebB$ݏ\z) 1 \p sjJTPr}?.XB.cvRFI2 +Qk\+B L(.9D:!g;hTy\|6Y1Ze()UZϵ. #[SkZ}|5ӥLu쟐!4_Bs'/E"T[kV9 c`|nm::m01'gjnh&Rt{ɩmF+!9RiΖQq081۩`ikz+w7Shz^}W}⋵{/{O~?y7g)L@nn.DB/!TWTsxK0 ං^[Ff8udrij쪵 *:c?fVWr8ҴYϴr UFJ"V^+khq i+ǹ9w+IF6VϓJ3kzy\\=+SnWZޗf/۽ߙr "ZqBM(Q:KiU0P]z"-(RrBIɛ\,Ubc7ZtOk;T.tVWFǗCí;w0FR۔$h-qRoΛX5UfkFy]̍|6yt)(s+6}ճ*|ٶYG_ß&Fovo2Nvt?d;vi?>DF3_?pg:_ʣ +rurG?}կk+d%"&5 k?~an ځTG;}oʓ}~U˜HȬ |MoE?}zW߄0'7}?+Hs2msl3#Zd%t*߉R(m`JI)۽Z}+^ +2eVD]~DdIhAG OMEDfKj\coV~F(J+9@+Q)ԙTFu8J\ QVЁDd\R^2T cz2a1%q)K)=ھvrB/ڪQ3[XuF.A iRqaO>>ˆ:ʚ ڂ" *#;LrMQ. +6v+[v'GϞfvwUkB&ThED/,XV +VTKJydU7ě4{WW^V14FG8mL(d[VvJ1g} ~*QwҍC9;բbkݍ583{gՍ'>T~B)a}d5.*jivV4[05M>wk+ň!ѳ{v(׿sqOL>l|+#MCQ]޼WcJA+Ri># .< Y$JZ@u^'6%ٓYM降qB*\(!&,X׀X-Y!&o7ώYMO^&d Ly `CΪ(3y7Z돬vJ?Qʌq?G` |aT3z +3 +ÄI'̜I W, )*lx$k$9m !X ~p0rA0瑱:T#J6„BHYn2dՍlCH1׊N}Ÿ0J#,p-gZQӁq%pab6 $)e\4p1"VDbj3/B-IlRlnq8{.ḎSR-T.',.ꤠTӺBgۭw×!TEi3 JA)%AaKY5<2J#J-(FQJoP pqgCJ$⬨0b%-6zGv RnW[$cb(FI0a mB!B_>Y\V`zx +|Q>i +`)"pQpMrFFuK+3z3N[ C+Zl FZAD[&QLҲ2uGLjK",mҩ:8&1c 1FKn$blދ!I8͠LjŇҭ\y8I8pRi UӁr`APֺP4G .壔ቲ`tWd͇X01!׋6I%ݼ#[0“R>9I.K'p6=Eo2ԓt̷\S֫(kћ2XT0e@BIեl?&e{H >ʜ;L*LȌ6s55F#ЮZEݩVw/,y"ɳg+lmIN>o0LQib +$HRi!B(`RqXl,uI>V! +*ՅbSp'SpI3K@'te;ԋ(9RRJn6]c2B*z$)ǒB J>!B +¡PshchTO8 +1>\C"+vV +AbHNqOF"j!Aq\GW 4ZP@}Fp $U1V&q?$qU ZTR+a:1\x'@,.Eo$F 9Y/oqʭ_RB1JULf~.q*/y^\YU (+bn%'1:ITӃ|y}m1١hiѫrE*'XPʔNJe=wqW|gWo,"/y*:{ĥ/(q8o1%2|!,UB Y/1RMU8x7(-zQڛ#(-5)= cU 8lT@+ih(&' E8ə?Q W2*tEț;BQB>0G-$! ^ﴈO?ˍ#IH"${o; +U(T{ fws$Dj6˖-ٖcI3cǎdl'3Ɍ'3wf9w}9!~P )V(ye°N1tM 2P {QAr!XChļœ'T˥Zqvy/.g rgϜy2)!Y4Q/CI<RsK../Fv u4# +S3sQYR⌡8| ̺b'4G'\3WwL!.H$$fN{.!P |s;;\i1zb^DD%%]WťE߅y7N ,i*b0QUɶS G<> %Kí'KfN5d>d_g:JRbq +T/`ς# o-7!gb0ƅ;HL0tE(szA*acUPy7UQީr:檐*s2!g? #V.FH&MfzBO(+2"FQH_HT "\ DEP qz(z}^y$IjӣFvo~dxګ=?6zއ=3{%ACp4L8) UQDQE01 cbpWzj̙9.'ksBϜ .qty ʖ"(A(IA`~ӔY g.:\H,ƇqEMUJ^[oVvh5ҧzo\jf6ҶAf矛_Qt1oZEBn:'j2hIRX_>8zҵvpP..x..Q +IDE<^59^wj [G;euo!}k?OjbCd\,EɌjn.$UN'8}A?Hb^n7vBwEcK~dz~L(93G+Tʹ|: Óay^+_y(96 J#8ژV3U$P eTR˥ĜkǗז[zN4,x/_h8lYi3FAQMIC1J6ߩꭊ>Z'+wnyw?/go|zlVEA +G@䎊ɦPq$˵^0~V:ŝ{{ɍW_zfiM蹙;;8;4;7 DP[ +KR`lGbs痠aݾx4籠J)(ޣ޾=?_~|߸=m%Xq.!- ,υ6jMa~ ;'ˏxaG<~ Glsy 0F8%"QZzOV?|{/pW~W雏vvY;B+c*1V+%|Fzr[+[;_}77??'WA]Nw Gũy3g/K:D$t֭sNI-hU'WzGz?=,W)|n"/_=:nowiOw>oo'ϟlT&P,`_ӿxӯ_oݏ돟7_Σz5cilVֲJ0lJ͚po\k=އw}ϟ}?{z%mW|F |р;rO%vnpd^<5W>xo?+-3폱QTdq`9rŽm|`Ͽr볯/~O~7߀ݿ}wro6$5#CL!5X/aWMw>ɧ/O޽ݷ?_{^UJ,80uu-Ͼv|vkvkw[7Oӿ?ܹ\m/QDx^n;o=]o^ݏ폿_ۯ~Ͽo?kAE]h4J,;(-#|7G3j~_?䝽|gw巟ϞmU:jڴK0{ +Ͼso/zg?O?}'_](ܼss!` r,ݶhx'_鷮嗷߿߸lga(#LN7no =ZWN|Ͽɻ/>:?Oo/wY0 H iAJԊEmd|zzds;˧셟}r}_ N& K |eP{ɛ?揾q_~_?z>.WS (&ZA lVk.ןÿW~o||y/|ΕGW;GFZ" "A8/>Y|~gO?{7oq~~=hofJȥW?W{w?x|g߾/?{Wz٫ͧ'aESz&?%SeZlhU+|o]yF;ovo~';odg}W$ΥbTTIK73/mT6X b# U4|./O+|iw?|ƍ^% Aʆ4Ph<ft\]yJWwn޿<1׽ x|*RjI2ƕ՛[uudrͷ^zk_ɴ/fSjTVi&jސʦ0nۧwZGA5/:9@RǸ+^o(afΠvu=¥܇/m|?}qw|ޟGpT_LA4BRt-66c{UV泷~??z{[͵^&VPeKB9fZ]ʔbdr0_[+<8Z)l״VNͲ&xg` R-%frfavf9)|s~ڗ_zxp8 M,e ` INp$ˉZR9KΙ0‹j"JJǧ?҉bLh'啳z,4Q,_K 1GhOn=뜝wqxHdIBj;ݪ_O6*Wb䭒"gɽܱgf2&ob鄀 .'cY1+>{ʃW뭆JGQA ň+BFrh͗b(X +l^,m1jG"25u>r!3^O4D!l[@澨Ơ1-Lpd@H8eS]97rF/L~m(wP*CYz*(.гs8ggѸfBbT xZ%F" )sN':xo/_Sr#)3N\+@g +V'<0j1>!DAI7~Bp.ɮ2kD RjPf{.M.i<'57vv6hrO Ëjܞ!i1,E`LWLՒ)eV QfZ֛ѐ}j֫A&tč0 QigT + 79L)9Ψa"ۓS8Γ$i6槝~ b:kA/s g a1̕YB91睬ɏiב& +Zҏ1ܞ  U,$tF[LmДGZamEBBKZ~2D>̠RH01b̈IBln/|,'ڜȏu5W8fQ)Ƙ1!H/jeo&x΁YBݱMC…ZZWRC1抨gް8ZB\KjˢBňzI,HBq4 AX);p#H\ﳜi!(,E/eq .IR•{ՓEjD,PF5[rfP]e*ŕ<7(kؿ9/,&Ԏ"U4-=E۱emܘJ iKxpOPgVu섹[[VV^‰(q#̰P@4T68aZF/$գJ4֜h*@qm.H/I*3ZJbb=aӛ&sӺ1" LB1Pʞd0'6զd]QnƍzbJZ Sj +S@*5{}d`2fʉ]pysbud$Q$QhEL fT=c'/["f,&WIƒA*Ų asxrMFŢ]2^ܜRKQ :DjEL1" Y'艈Av!7<1%Bq5(\1;stvʬExXVw\E%Cb.[\,^ئF\Kq#V_0E'jD\~+| _>l K:QVX'dچ S~:FU"T9ZʖQ\0۱dh;zտZ挎dBiqd$7M.=õvT@}Lu:N Y7$RjRzvu ~aT'.MaFIJHuM?c2f `0S6űxb誘 !XG0"CDl>h0Dʥd}?YhcVdMP㼗Zډ n,zdz5hbjv5ȗ@PŒe6O \M[C;TT^_ȮFGHOX|fs^vr/j{qbH{fgp7c!kE Tڤ%-6Dg:'v2BXbz],kB]2."V7 ^d +>jLםxbq+z֋>.bG+;w]tz pDkF:fMFzPѡ}H$VƷ\}:Y6u"Rܻrx&ĒɦݻYWx!rʮĊZw_Jw_j<_!î +cuv4v^ɮhDbMnVg.eTQF @kJ/=:_WyqOnrICadNWT& 6MɬtļQ0չFg6zTm;cLPͭΆ[v/ =~Lc3J^qcƔAq{9?=QV2j_+l> TO5.:)^&cu)A`1TA|l4|i\Ѕ=xD:@眨rB~Ko\^Hշ D0|>TԀɬw/ǵJ8.AQ%\XmjGוLɶ\ڵm3B~(%4 !i. xenit +-@{ӻLv](oVs{>.2+[BeWǧ~{ёew8k\J%kFecr}7+7HO6ftBbήg%Y%^ -~'m"u+7iLJ+gZAދw^Ν/}|:39Z~Ϥ_3E.,o>^y+;tck:HH5jZKEŊ>tcKրm/ݽܼ7F넶WtF&kG1ҮZkEz-Z0>Q]ȯT0ӿFc|r(ZLhp7[v)W,\t~ih|5rW]x*f tOgAa'_! vW-mWJ[z{JֳK>0x & +m"7˧ZHE0;s#bqEkt O`,j_Y{^ߺ(5'Sqvxy[o਻ϯCFjHŵT%j57HӓQܦ@kPbah^^~?r'fdM|f-Yn6ne:yCFk(}</)=eZ\'jy-?cS=sd5zTv,ּҽSȅ].!7 @bJ]/om?՘T\ZNcqvx[ʍ P?;NDq~qq;~O￳y+Lϯn=m<.P~%3~ S^KRe/mSG8b )gr=&#,>;&X G ~Fy^knG6M1iOD.>ٖz -eAi'F}KDmH By) 7տi /o&6bo~^_a3+jq=ٹ#w\ֽ?R5_L:8Nw.51Ÿ5d3@kҸ|-;1:Ǹ6PdvP뾸 O<laֹE)nKba)>P29䥭\ UK6F%@)jf 8sp(f~xɎ"ri\*UW&.7[{a-}8~HwUݸH4gwp4g٬o[KшrV" LkCmBwc,Y )۟ PxO)/kmxq';ꛐ"^{膏+dYV 3?յ'v *V7恔fg;7ގ5? ʵ3Dj%*7ClAϯ4~\UٽM\)ɶOqq;&VB4l6B">JûD [NdVN_:3>9BTj%{.&.*$avUj9ʍI֯$*^0œTeTon7v?UPV\2+E} SRa]k؃[kʯ r\(Ű  Dcɦ1l2K +K' Y"j ^|!jSVɭCcr1҈*t^˥5d=ITj)ZU.{{ݽa{؅h"E_ڈ1:o6vkv}؞8Re+KQ V}|Tvۅef|ug#f bm EDzet (fTU?uS^*V2ux([B1Y/@U Nh#cuv{R~78q{! DjDir]+n`| kCΪm=}1—@\D#tn1({P}1,c*cx\ѳ/"Z1Qָ411_i݅8eW1S'˹S)!;ߧ):&RiT-|Ob>TmL.Wʕ-.ִ&,BԀND']-/cGl/#Ɋ|vTۼ 8is0Zy ٍDI6&Q6e.S> V5{YyE<Tڎ Nvk \1nŤzDVLWily) +js.9#"( BHu6"(՘P4B|6]1b 6N/l5d1f?@\*O\Ba8Y+"lިvq^ڝKM{V!-b|g^Un~pM^T0A:Uy{幙Eă(ppu{S\J +>"ٸ\ى +%P~xFDL},Yn·(kH-3r0R~xVK| zΝ*O@՚lCd@0MDu($ֆOwƏZp1km"C\*hr*|X .<&qM7m#R23=잝h>:+^6ӊP)=B Dd.@ wORg0AzM R4*Xr9|[ȎX\FQ+K>8Lwǡ:s>?G&9&d7ܨVY . ud2<RW-y7 d5\sF8L;fIBIMhG%tCE JWΏܺ/\ +0nR7|&Vb3]J`Op@G0lzT녥@tQ6WlnS]a2N\ AhN(ŸT\ʯ\/Abbo)Y &jH\nʛ Vާ iv젲zӋ`js=ݻ +j Wf;19Dw +묹!iʵj28SŰœPێ,znny+mrix]̯>u>]2`kQ4 #J#"ҮZ=!:Ǚ+gCN!1vlZL)yq7dL4"BLPi@ZNkgs8Q*KYȎ/F;LʥPi9YG*/F4pbPLH&" Ό ?>0!R!:MZ~̾ b0Ƭ 88Ș8#d /V]d<рAMXN/iC&;\DԳKqO<b2HE^c< +siGuPzr=}/WaR浼,1FH A7n~9~1~6-O`z+׿s-E"Kv|j0Xrl]vYhrfW+G촗_ѳKq160j6vc:T,]Di̦AvMA qZcÛ`e`6(}lv_6[Wb4ڥU\oLDG\ + QJ)j>j(X rQ +Z4"BŊyF;.צL"O Йΐd5:1Y돘(q#3$)G̬n̳3<`UP#_p`L''&D!>C X )\X'";"l2ѝܜG)᭘cP܀$}``KF()&&jA` xvEؔKL<}{+q5?i*M. + TOBzڍQO4=Baz90)gBjLB]KvX¼ӉܥRB;'Hn`:d\ml5b:-[k{/ZyV}@Te{),BF23rcC*2l4XsA1.KMĔJuJ:8i3 +vqxR&c =0#.W"D4Oܘ2A"fL&kJk`[~ҞT[r0J&j~U)l>rPl@vSN,ta7Dk ++A2#Yy9z>7nD_ _tc0 12K+BOx>,4a~6d~Cȥ +E$!Y#* Wh3h2{ 1?2m^ %nb<t81HC%lLȳQTLRqO*aMcz=q: AVcBMuq*;ĵZA +n,+}yJZk0!vޏv,sඇDŲ^BlSzanaɖHKVϪdcڃ;bH +2ED RLkׅHeTLkUF7elfrՍ )fc'F|U6`mO:/攛3@/RB hD+;{5w^BL7Ӎ)0߮JգP9MOI]y=\9HNôi7 +wDo\?&70K~պ3B2 %(.duO,}EP\dqfi.w\">“T. 4-Z+"}I`\Z?3HrEl4׹T't+׽ itH5tV33?:ueD m4TKbI5YJ+)+ZeN" @ynCD |%!>C-.FChTb&M2[z!0Z#.WZ<ٞ(~.d +7ջhR0ٹq0DLb +ƋE/L9/BAՓljHh=B@.(限QM[\9⦜Q(!TȂX;Ĵ.Tڞ - AGl;Q n.'; +IcQl>]𲎨]pZB'g`1=LP^Ќ!ܜ'>YOc&"hY#mHQyKmU`]@t{$UX D1 9G$7?"̜ Ќqm''&'|ou0\ĜLB\0<#Dr,F]?Sg/N603^L~%vO00[/q}!bÉLbtZR+1Ξ,~$$5@ɯ26Z4ipgŕ"I !:k->V޸_~, +IbI(-7iUXh G!R.Q ,LXA>`Q *f1L.,XS٠:NuDH Kjz%O +03;9tf M.{L +PHOqZ9P +[JQ=OGŚwc]3"-nxU[Q@*#"M-xICtf+SƊ,% +$L]>:p6oe/h?3f\+ +JrYw\Уm2<R;/LQQ0j &933g"즧ĥIK~םHbj@bR !zaG +9場͗>Tg#g 2Y +1 x "Mj81mNr^Õ + o:O. H#BLȅjaXUwR="la)b!F#'Jb/^fBl(:eăxJrmB~LiLx#s1"AEY{cRW|FHuZd6t\d1x{MH:CbךTdݐ2ٹKw!fP#ԚkPl&;?A>/ HP ES'jLYb5 FACAx 7?Q i71̥*zW_t 1e 7b P91|\Jdr) +J.0yiba7"TfsAᙹ9&0LƁmR%bR yDr~*I*HH"&#dJT( +u&=%e BP@2&!..qkjECSzhQ6 FT%PyHm0݂C ||P$g\s%ڋAh1\D8e`r˂E\ﳙ-ZlN7$"5D˯{!@"&Gwnz-FHo8k:%^p%zDs]@#T;G^D1)!.H~fk~T7.32(E) k!$C +U?a"Ei=(fw$5gD̓&oz) +EW8qn Di2$T&hb1WL҈ +yJBnKhz1=Xf',"0Bl/>h>5pTXk`ŋ&zcrQDSJyOQFQe>6A&jQ@).de>,#kP*ޘ2&b-:T +iCsaY`C&{U@:n܀4@UJo/E"|JL.PVg_{ B+!2ƥ!&ݨM13+"b2!rj޽aԻf("#ҌF4K~zIbqɮ{deBKgss6{]riϮ*4Ѹҁ1s>Wj "\՚.\! >j< ʯU.q$e 7M/ e{Fye\m^ciRuu"1Dj&:HT.dC4K\*P܌sC!Qu ?99]0~ Ўa$Aštrb!yK?{ܴ&HdD^}=ch'BȃL@빙+, U;n-CFTbqftg{8zUlΡJ7i'ZZrx'΂b0_I:^:CwKē:R6f3 + Rѱ{P5fgC<&BJ{dMm'+[|~ujk72g}3KVpmK5赋&if|~ggW&HY&;d\6;ТuY;tuפ9ȮOo?{kg4k4iY? f> fsH&[nҳ z}mo/KS+'~n&ۺ@.BmhBk/ǖ^B^&jT#89Fu-:1y͇d*_!L`no<\j6R"{4U 0d&PG3&V_Mm|;[3\H&DJ '9NF;䰌/<$$+?_]v\ >_}ws~LO?/W/^_005+$f?a&_^KzRX#! +Mb۫K_G[dM꼞6rҥs.t}Ip}9F{w}g= ] O._R5w&V[Ɲ'5'_}}::AΝ]O1Lo.g`W_[6\SP] rNnf:{_~'<9OGd.ʍtG8vyq{K/D 2MWD82Wi ]s}T|igb׳sI<*/X#||mҪ/-\_^kycp̉zrjtἽI{'S_6z\:ƒ"c4WIl\#s}u.}^gu}ʋco?{xtg;ro֯Γ"ٌ&dpkdlO+7^̣^d -f7_M#}:v8IB=,9Uw._㋋Mo +^N\87fh_(ɍٍ+6>B2mF3@#rlsĶY2Mݽ|32QWϛy2o?o^]:rbӛw?"1 Yw!^T3OHkwk|YIii˫s_%/+IԋcW&ŷ[}nn]6zmml 9R+h7{o1sMcM;Wgg(?g /̼}ɫ|I$ ՋڋkQ惓KkK6O<_|Hեܣhvhv|e޿|}y7իxbnmC]['7g|eo_zxx^2]"Nk,/+c;‹I|󑝼y``؍t~']؝X}ID/حd +o>Yݭ_̒_]c>J柌=s"ct iUr."jlU]]iq7 5ysRBym+ݘc$fIN,m_N_o/?FO40%uoV:ߞt5'O]H fp!Ygcm"{90zN =W7\_yIQ+M<;~btl&-"||@“߯<}o +ZC̐}bȾgz]lnn/\N<~Ɖףj9ol^.Ffꞙޤg>mޒ?8brⓅ͗c[זy^IԐY~1?gg|r7;_DdE\Nˏ_#99q j? &ME;wS7^_ӿҹǗ_]z9EDBFݥ'o5arՕ'oa]"5&- zՅ\gf9^mi7WƖ\]{p_X{Zd=c[{6ꟍN]|ㅿ4 +'>~?M8I<\u>Z"S!'Qw{ݵ dW߸{zs➾,&Q7p1V.vvl}.uj{=0NJ̶սd1Nz{4[=A&Px}urדk/,NɵW3lߪG璅sf6)wז_|xsl7.]]sӍWN%3KPLܛ|޿x}-W-<ĝgv3;ֳWAx{ۏ.8ɥq=>7yk>2Nqk%^vţidݯ\B3ڝoqcW&ݽs:s}|~߸s@M덌ݯIm@̯Sԓt~{c`|/?SW_}-^,$7~۽awF>N{?էFd>5"OȠ}jDS#2hAԈ ڧFd>5"OȠ}jDS#2hAԈ ڧFd>5"OȠ}jDS#2hAԈ ڧFd>5"OȠ}jDS#2hAԈ ڧFd>5"OȠ}jDS#2hAԈ ڧFd>5"OȠ}jDS#2hAԈ ڧFd>5"ϳ|gߝ;wp{fdkȹ[)}<V+˩,֛}vʭ=W?2>'9w{Į3Yfh^ڏNg{r}urt3B>:VGo[W{:E>:xuz9LC2i.`QӐv!.`~©g3l{hu>`>`\2ϊ&3SݭoH=ۢOgo0>|M}y>Alc5 an{[S]A4vv^O?#evvi#һ}vF?mXggv듭z)$weƏ%=C> ϛ}sWt {.zxgvEҽbU&EΎ Y + xC}2!Q.?h,ybu>茪i$Uaq> 2(2aduk} "rF=o5 ?"zxd}{zxDuϡX {G$<5;Hx +?<ŰRE3yM3$?8£(wl ܙ;RghhL-(~7O}nFiPpψ Kj{o0Epݣ=㶜A&ngnٕnL ,zdXD٩=k,?{`݃ލph,m>y,zdX$=L0أAQ +_{ŚeXӥHt ^Ϯ젋wcϗiXdz;lo\Ljk ˍ;GL_[GB8iг\} +!Þ{[֛7Qq;n3z{'{o@.'gR$~uܗ&7~rԻ]t +nYп~+:z81sp>1\}lTZ6Sy?Ǒ.B >3|::xuTʛѰ]IAE>Ό[_iHDôg gY[qIf{0`Aw3Lguzy;"N#"bU?>H ˒ֻxg?/ |vDu?@k 4Hssuι99FspN;缽 ]0ΰOYZvVkϢ9^ViEynPi!9|sW徏o{s >B,V\Cp23GV{N؋vp,ދ{G퓱u; ШO7J%=G~;xs."_ ,>W.wǩEfYY~;ڙBV^j<Ǭx +"_,o~sG necթҮ9u0:Ss>0Ѝs\dc:u0:c2TUԑ:2ʺ  oh 3vٗpX(=³'Lgޛ + xg~u^L3Ѐwq9*n5:t ֣uwՇh8L3?:ѥ@8uwGV WA7Ϸ^g߼iz7Jw}tONZ n\}wo-{>:x= ;|s:zbooѻz#7Ǧ,5p/%vz7S uRU۝RG'GkS@ 4) U;I} 5R``A! : cԹQ;^ +>p +u +l0fPG;Bl{b= + [G/_?%Skp$^5 Sj/p0] r/X;,c؜VUX8Ό8Ί#& +3 +и_o=j?pv5`x{gzYqV$RK1D~!/cWs OCVXC@GZ{'_#aSY9|,{N%:V¿Q>/}1ؐC|aas}>`(l9jíxN>zI|y|GG>6#MCrXo:t Saϲg뇽7}$?:RQG_fjpX'3u yzl%?o^ +weƏ=,om X[O=XOTO^w +kx3r򡉧QOVB `Y?|Or; .`\GD"o^Lo8bu :;>sA⃲'[{a F}_k氵6|B[3n_v~)m UBÁ[wz?bp(H,pFCaq8rx?lwÄꐖc#MRӛQVY@.#ʨ/?,giG#I4_ K{H}@6LcIk#Z7DA%QA3(}Q&1yH th$lFЌXǩ mHH)mh8084SlD:66HtIFA.´qkdTfLOkFM1!7&-iH[zبVMm-W6UQōQ4i68/I4 @$N41j*ma3lBTa3 L Hxj4aZwѼ +CRiB ^aNgYTSQa킦1XE flgڴ9BkԄ_-A (#4ȁk Us𿺉)[h@oѦ f' " #0h6I`|TŶ;QDF44($::m`nBչLHf`T"*DY( hC>NXPIz4݃0 H]IĦ<|BM5JScVjZi#C$@O 00)TBaMd6=J+b v`wB(-_TihIh0/hZDe8(ؐ_N1@\7k fh5!$)ZVjL4ZCb;:d⠇% +ClzYU("% &B W)%- Q,`B8hLEXҺ=̡ay8T 6+cE&$z b^x$*H9rQ$""z ȅC_BL_* hu0Fu8I7GBqe3V,YM-] +K&&HZX0J@L \殢jCby +4IA(mD*' >0TABhV,! f 4KRH $]$F,܃S`Ib0*5 _,cDSäE{) endstream endobj 5 0 obj <> endobj 35 0 obj <> endobj 44 0 obj [/View/Design] endobj 45 0 obj <>>> endobj 18 0 obj [/View/Design] endobj 19 0 obj <>>> endobj 61 0 obj [60 0 R] endobj 84 0 obj <> endobj xref 0 85 0000000004 65535 f +0000000016 00000 n +0000000173 00000 n +0000030631 00000 n +0000000006 00000 f +0000635481 00000 n +0000000008 00000 f +0000030682 00000 n +0000000009 00000 f +0000000010 00000 f +0000000011 00000 f +0000000012 00000 f +0000000013 00000 f +0000000014 00000 f +0000000015 00000 f +0000000016 00000 f +0000000017 00000 f +0000000020 00000 f +0000635738 00000 n +0000635769 00000 n +0000000021 00000 f +0000000022 00000 f +0000000023 00000 f +0000000024 00000 f +0000000025 00000 f +0000000026 00000 f +0000000027 00000 f +0000000028 00000 f +0000000029 00000 f +0000000030 00000 f +0000000031 00000 f +0000000032 00000 f +0000000033 00000 f +0000000034 00000 f +0000000000 00000 f +0000635551 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000635622 00000 n +0000635653 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000035972 00000 n +0000635854 00000 n +0000031043 00000 n +0000038971 00000 n +0000036288 00000 n +0000036175 00000 n +0000034956 00000 n +0000035411 00000 n +0000035459 00000 n +0000036059 00000 n +0000036090 00000 n +0000036323 00000 n +0000039045 00000 n +0000039397 00000 n +0000040878 00000 n +0000047900 00000 n +0000110777 00000 n +0000176365 00000 n +0000241953 00000 n +0000307541 00000 n +0000373129 00000 n +0000438717 00000 n +0000504305 00000 n +0000569893 00000 n +0000635879 00000 n +trailer <<2F7299D099E643789F82D4E71CE3A018>]>> startxref 636118 %%EOF \ No newline at end of file diff --git a/tests/dummy/public/assets/branding/ai/Ember-CLI-Mirage-Logo-Horiz-Color.ai b/tests/dummy/public/assets/branding/ai/Ember-CLI-Mirage-Logo-Horiz-Color.ai new file mode 100644 index 000000000..87c002887 --- /dev/null +++ b/tests/dummy/public/assets/branding/ai/Ember-CLI-Mirage-Logo-Horiz-Color.ai @@ -0,0 +1,2757 @@ +%PDF-1.5 % +1 0 obj <>/OCGs[5 0 R 35 0 R 60 0 R]>>/Pages 3 0 R/Type/Catalog>> endobj 2 0 obj <>stream + + + + + application/pdf + + + Ember-CLI-Mirage-Logo-Horiz-Color + + + 2017-04-12T20:08:04-05:00 + 2017-04-12T20:08:04-05:00 + 2017-04-12T20:05:52-05:00 + Adobe Illustrator CC 2017 (Macintosh) + + + + 256 + 80 + JPEG + /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAUAEAAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq7FXYq7FXYq7 FUm803et22myPpdss7cH9Vy1GjAH2lT9o9e+WYhEndxtVPJGPoFpX+Xt3rc2kwR3Vsq2EaMLa6LU dgGoBw32G4rtlmcRvbm4/Z88hgAR6ehZbmO7F2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Kux V2KuxV2KuxV2Kpbr+u22jWQnlVpZZGEdvbp9uRz0AyeOBkWjUZxjjZ+ASj9JfmAIvrR0y0MX2vqg dvX4+FeXGv0fRlnDj5WXG8TU1fDGu7qnGha3baxYi5hUxurGOeB/tRyDqpyucDE05WDOMkbCY5Bu YXoGgjWtOXUby/uxcTO/IRyBVFGI2BVs0ul0vjQ45SlZ83d6rVeDPgjGNDyTH/A9j/y333/I5f8A mjMn+TI/zp/P9jjfynP+bD5ftd/gex/5b77/AJHL/wA0Y/yZH+dP5/sX+U5/zYfL9rv8D2P/AC33 3/I5f+aMf5Mj/On8/wBi/wApz/mw+X7VPQIpbLzDf6SJ5bizSFJFE7cyCaV7D+bI6QHHmljsmNXu y1ZGTDHIQBIkjZklvbwW8KQQII4YwFSNRQADwzaE26qMQBQ5L8CXYq7FWJ/mNqmoadpdtLZTtBI8 /FmTqRwY0y/TxBO7r+0csoQBia3Sez0v8x7u0guotTX0riNZY+UhB4uoYV+DwOWmWMGqcaGLUyiC Jc2QQjXtM8pai+p3Pq6hHHM8UyNyK/u/g3IXo2UnhlMVycuPiQwy4z6t0F+XvmmbU4ZbG+lMl7D+ 8jkalXjJ3+lTks+Lh3HJr7P1RmDGR9QZDr2sQaRpU99LQlBSJD+3Ifsr9/4ZVCHEaczUZhjgZFj3 5c61qeqRag99OZijoUrT4eQaoFO22W6iAjVOH2dmlkEuI2x/TbzzlrOrXlpY6oYjAXb96xC8Q/EA cVbxy6QhEAkOHjnnyzMYy5ImTW/OPlrVraDVrhby2uCCQKMGWtG4sVVgy5EQhMbbMznzYJgTPECm X5lazqmm/o76jcvb+r63qcP2uPp0r8qnIaeAN239pZpw4eE1z/QhU0T8ynRXGqJRgCP3h7/7DJce Luaxg1X877f2JlrU2vaV5G53F0f0rEwElwhrXlNtuQP2CB0yEBGU9uTfmlkx6fc+vv8AikemW35h 6jpUep2mph45eRSEvSQ8GKnYpx6r/NlsjjBohxcUdTOHGJJ15H8232pTT6Zqaj69bqWElOJYKQrB lG3JSe2VZsQjuOTk6HVymTCf1BmBIAqemY7snnOoebPMWvao+neXAY7dK/vloGZQaF2dvsL4U3zM jijEXJ0uTV5cs+HFyVf0N+ZllJHLHfi5JIDJ6vqAAmnxLIo28aYOPEejLwdVHcSv4/rVvPmtaxp+ oabDbXTRepH++Eeys3IAmhrgwQBBsMtfmnCUQCzvMV2zCfzK1nVNN/R31G5e39X1vU4ftcfTpX5V OZOngDdur7SzThw8Jrn+hU0KHUPMmoWvmG8lRLG1kl+pWIWpG3HkzeNQD9GMyIDhHNOASzSGSR9I ugzLMZ2bEPMehTaWL7zBpd/LaT1E81sSPQkI2IK9yfeu+ZGOfFUSHW6nAcfFkhIg866Mn066N3p9 rdleBuIklKeHNQ1PorlEhRpz8cuKIPeGK6Ppl3qXkeO1tZvQlaRyGJIVgHPwsRvTNLp8MsmlEYmj f6Xe6jNHHqjKQsV+hH33lzVJ/Ldtpkd7/pMLAySsWCuBX4SRVqCop8syMujnLCICXqDj4tZjjnMz H0lO9Otpbawgt5pTNLEiq8p6sQOu+ZuGBjAAmyA4OaYlMkCgSiMsa2OWP/Kc6j/zDR/8aZrsX+NT /qj9Dssv+Kw/rH9LI82LrXYq7FXYqwn81v8AjjWn/MR/xo2ZOl5l1fav0D3pdpui/mFJp1rJa6iq WrwxtAhkI4xlQVFOB6DJynjs2GjFh1JiCJbUyPUo7+28jXUepSeteLbSLNIDyqWJA3oOxGUxo5BX JzsolHTkS3lTz7T7W90vTrHzPaEt6dw0c6dgBQAH2cVU5lyIkTEumxwljjHLHvTzUL5vOnmG0sLX kul26iWY9DuAXJ99+A98qjHw4knm5eSf5nIIj6B+P2Ij8pWJTVE7AwEfT6n9MGq6M+yT9Xw/SkWg W3mC417UF0S4W3uAZDIzkAFPU6bq3emWzMREcTiaeOQ5JeGaP7VbVodb0nXLC/8AMw/SEYasfF/h +AgkAAL9mtaUocETGUSI7MsoyY8kZZfUmn5ruskekSIao4nZT4g+kRkNL1cjtY3wfH9C+LQvzJMa FNTQKQOI9Q9KbfsYDPH3JGDVV9X2pt55SdPJLJcNznUQCZutXDKGP35Xh+tyNcCMG/PZjGg/mGuk aHDpyWRmlhD8ZTJxUl3Z9xxJ25eOXz0/FK7cDB2j4eMRq6TP8utLv59QuvMN2OK3QcR9ubyPydgO wBFMhqJAARDkdnYpGRynqzTWFlfSb1Yf75reUR068ihp+OY0OYdnmB4DXOiwr8p5Lf0tQjqBclo2 I7lACB9xzJ1V7Or7JIqQ6vQMxHcPOPzP/wCOzpf+of8AiYzM03Iul7T+uL0fMN3Tz382/wDpVf8A Rx/zKzL0vV03a38Px/QynTfLFtpupy3lncTRQTcmkseQMHNqfEFpt/n22yiWQkUXYY9KIS4ok0en RW1zRrjU0iWHUbiwMZJJt248q/zUodvnghPh6Wyz4TOqkY+5KV8iJKyjUdVvb+3Vg31aWU8CR41J /DLPH7gA4/5C/qlKQ7rZQqqqhVAVVFFUbAAdhlDngMX8q2kt35RhhiuZLVy7n1oqctpDtvmr0OMz 04AJj7ve7XXZBDUEkCXv9yK/wzqP/V8vPv8A7cs/JT/1STV+dh/qcXf4Z1H/AKvl59/9uP5Kf+qS X87D/U4orTdGvLO59WXU7i6TiV9KUgrv375dh08oSszlL3tWbUxnGhCMfcgbH/lOdR/5ho/+NMox f41P+qP0N+X/ABWH9Y/pTLX9bg0fTmu5EMrlhHBAv2pJG+yo65tMcOI06fUZxjjZSX1/zF9L676V lSnL9H/H6lOtOXTl/sssrHy3cXi1NcVR9yM0zztoV5bxNPcJZ3LnjJbTNRkcGhBJoPkcjLDIHvbM WtxyAs0e5PwQRUbg9DlTmMY8/aHqOsabbwWEYkkjm5sCwX4eJH7RHjl+CYid3B1+CWSIEe9JLay/ NO2t4reGREhhRY4l/wBGNFQUUVIJ6DLCcR3/AFuJGGriAByH9VOEsfNV55T1C01WkupzFlgAMSj0 yEpunFevLK+KAmCOTkjHmlhlGf1H3Knlny5ND5Wk0jVYwpmaQOgYNs3Qgiu464MmT12GWm0xGHgn 1RnlnytZaDDMkDtNLOwLzOADQDZduw3yOTKZtmm0scINb2lH5feXdY0Z74X8SxrcCLgQ6tUpzr9k n+bLM+QSqnH7P088XFxDnSTWflrz1pmp3V3psUaGdnHJniaqF+Q2Y5acmOQALiw02ohIyiOfuVpv KPnLXbyFtduEjt4TsAUJCmnLgsY41NOpwDLCI9LM6TPlkPEOwTLz75Z1PVY9Oj02JXS1EquCyrQN wC/aI/lOV4Mgjdt2v008nDwjlf6EEsH5sKoVZUCqKAf6L0H+xyd4vxbUI6zv/wBymeo6V5l1LyY1 lehZdXdwWFY1BVZKjdaJ9nIRlETscm/JiyzwcMvr/aidH8s8vJ8Oi6rGBIBJyAIYozSMyspFRUBs jPJ6+INmHTfuRCf43Sfy1oPnLQtUW0UrNo7ycpnDJxpT7QViHU+NBlmScJC+rjabBnxTrnBneYrt mA6z5D1S21NtT8uTiJ2Jb0OXBlJ6hD9kqfA5lwzgipOozaCcZceIqQsPzUvHSO4uPq6Kwb1C8CCo Nd/RqxHtjxYgx8PVy2Jr5foRvnny1ruq3djNZRpI0EZEjclQc612DHI4ckYg2267TZMhBj0Q/pfm z/v5Putf+acleL8WwrWd/wDuV/mry55m1jTNIDRrNfW6S/XCWjT4n4UpSi/s9sGLJGJPcnVabLkj DrIXbO8xXbOxV2KqDX1qt4lk0gF1IjSpFvUopAJr074eE1bAzHFw9UjbyveJ5YGkQXYWdXLmUVVW BYtxNKmm+aw6KQweGJbu1Guic/iGOzr7y3qc/ly20xL3/SYWBklYsFcb/CSN6LUU+WHLo5ywiAlu FxayEcxmY+kp3p1tLbWEFvNKZpYkVXlPViB13zNwwMYAE2QHBzTEpkgUCURljWxyx/5TnUf+YaP/ AI0zXYv8an/VH6HZZf8AFYf1j+lvznaXkkWnXtrA902n3cc8ltGOTMg68V7kZt8JG4PUOg1sJERk BfDK6T+aeGCMyzSLFGv2nchVFdtycqAtzDIAWWNauvkVbG8lm+pM0wd3ZDG0rOQTVaHlyr4ZdDxL HNwcw0/CSeHf5o3ySLseV7AXVfU4Hjy6+nyPp/8ACUp7ZHNXEabdFxeFG07ypynYq7FXYq7FXYq7 FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYqw688j3M3maO+W/uhalHZ5hL++jeu0cbdQhDeG ZAzARqg62ehJy8XEa9+/uZPqFil3Zm3eeWBdiZon4P8AD/lUP05hZsfHGrI9zt8OTglYAPv3Sk+U LYLyOqagF8TOKf8AEcxPyEf58/8ATfscz+UJfzIf6X9rf+DoP+rnqH/I8f8ANOP8nj+fP5/sR/KJ /mQ+X7UVpvl+OwufXW9u5zxK+nPKHTfvTiN8uw6QY5XxSPvLVm1ZyRrhiPcEDY/8pzqP/MNH/wAa ZRi/xqf9Ufob8v8AisP6x/SyPNi61B6sNKaydNU9L6o1OQmICkjcde+RllGPcml8DxfTXExVLz8v YZg1vYCdlIoyQMwr8nzFPa8OQJPuDkR7BI3MYj3s2UgqCOhG1RT8DmY47APzx81a75Y8hTapodz9 Uv1uII1m4RyUV2PIcZVdd6eGTxgE7sZHZB/kX+Zs3nXy3JHqcqvr+mtwvSAqerG5JjmCIFUV+yaD qPfDkhRWJt6XlbJ4Z+fn50ax5a1O18v+VrtbbUowJ9TuRHFMUDj93DxlWRQSDzbatOPicuxwvcsJ SeoaZrV7dfl1aa2ZSb2fSI70zFVBMr2wl5cQOP2jWlKZWRuy6PIv+cfvzS89+bPOV5p3mDU/rtnF p0txHF6FvFSVZ4UDcoo42+zIwpWmWZIADZjEku/5yB/NLz35T85WeneX9T+pWcunRXEkXoW8tZWn mQtyljkb7MailaY44AjdZEhir/mB/wA5NW9oNQljv2sgolMv6LtzH6ZHLkSsGy075Phgiyzr8n/+ cg5vMmqw+XvMsMUGpXHw2N9ACkcrgV9ORCTxc0+Eg0J2oNqwnjrcJjJ7B5g17TdA0W81nU5PSsbK MyzMNyabBVHdmYhVHicqAtmS+ZNR/PX82/N+tPaeUIJLSGpaGysoFuJvTBpylkdH8dyOK5kDHEc2 viJUx+cv53+TdUiTzPHJNHJ8X1PUbZIhIoNGMUsaofpBI9seCJ5I4iH0l5J84aZ5v8t2mu6dVYrg ESwsavFKho8be6nv3FD3zHlGjTYDbD/zd/OzTfIoXTrOFdQ8wTJ6iW7EiKBD9l5iu+/ZBuR3G1Zw x2iUqeMWv5n/APOQnmZ3u9GN7LbVIAsLFDAv+Tz9N/8AhmJy3giGFlPPJH5s/nbb+cNO8ua1Zvey 38wj+q6jbfVJVj6vIsiJGaIoLEsrbYJQjVpEi9Y/PLzTr3ljyFLquh3X1S/W5hjWb045fhckMOMq uu/yyrGATuykdnhuifmd/wA5G67avd6NPd6hapIYnmt9PtJEEgAYqSsHWjA/TlxhAMLKYf4t/wCc qf8AfGo/9wy2/wCyfBUE3J9LalrGnabGJL2dYg1eC7lmp1oo3OYObUQxi5GnKw6eeU1EWlI813lz vpuj3NzGfsyyUhQ/InkMxPz0pfRCR+xy/wAjGP1ziPtXfpXzd/1Y1/6SY/64fH1H+p/7II8DT/6p /sS4+ab2De/0a6gTu8VJlHzI44/nZR+vHIe7dP5GMvoyRPv2U9QvdH8y6c1ja6gsMzsrBHBViVP2 SrceX0ZHLkx6mHBGVFlix5NNPjlGwuvfKclx5ettJF4Q1swb1StQ3XYrXoOW2HJoTLCMfFyY49eI 5jk4eadadaGzsILUyGUwoqGQ9TQUrmbhx8EBG7oOFmycczKqsojLGtjlj/ynOo/8w0f/ABpmuxf4 1P8Aqj9Dssv+Kw/rH9KtqnmXhcfo7SYvrupHYhf7uP3dum3hk8+so8GMcU/sHvYYNHcePIeGH2n3 LLLyossovNblOoXp/Yb+5T2VNq/q9sjj0Nniynjl9jLJr6HDiHBH7Sn0cccaBI1CIOiqAAPoGZ4A GwdeSSbK7Ch5J/zk/I6flmqqdpNQt1f5cZG/Woy3FzYz5Pnr8uvNOq+RfMmleYzG/wCjbvnFcKOk 1sH4TKP8pCAwB707HLpCxTWDT6684+fNH8u+S5/NPqpcWphV9PCna4eYVhVT4NWpPZantmNGNmm0 l8Ua22t6iT5k1PlJ+l7m4/0lv92TRcHloPBfXX27dsyx3NL7H8rypJ+TGmMvQeX4l+lLMKfxGYp+ puHJ4V/zin/5MPUf+2RN/wBRNtl2bkwhzd/zlZ/5MPTv+2RD/wBRNzjh5LPm+mNAkji8s6bJK4SN LKBndiAoAiWpJPTMc82wPkTXJtPv/wA8/V8r8WtptZtzZPCPgMolTm6U24mUMwI2pvmSPp3aur2/ /nKS8nt/y2giiaiXepQQzjxQRSygf8HEpyrFzZz5LP8AnF3SbK2/L+bUY4wLy/vJBcTU+IrCAsaV 8Fqx+k45TuiHJPvz+0W01P8AK7V3mRWmsAl3ayHqjxuAxBoftRsy/TkcZ3TLkwn/AJxLu5m0PzBa E/uIbqCVF8HljZXP0iJcnm5og8r8pWC/mT+cafpRy9tqd5Nd3QqQTBEGlEQPUDggjHgMsl6YsRuX 2Ta2lraW0drawpb20KhIYYlCIijYKqrQADMVtQmp615e06aIapfWlnNQtB9Zljian2SU5kH22wgF Xm//ADknLFN+VMksTrJFJdWrxyIQysrEkEEbEEZPF9TGfJ5X+TP53aB5E8r3WkajYXd1PPfSXayW /p8AjxRRgHm6mtYjls8ZJYxlT1Lyt/zkf5W8x+YbHQ7XTL6G4v5RFHLL6PBSQTVuLk9vDKziIFsh J6pLZ2k0sc00EcksX93IyhmWvgT0zHljiSCQLDbHJIAgEgFWybB2KuxVL9R0DSNRB+tWyM5/3aPh f/glocx82lx5PqDkYdXkx/SUrOleY9J+LS7r69aj/jzuj8YHgj7fwzF8DNi/uzxR7pfrcvx8OX+8 jwy74/qbj886WlY9QjmsbpNpIXQtQ+xA6fRhHaeMbTBjLuRLszId4ESj3rm88aS/w2cVxeSnokMR rX6aYT2ljP0iUj5BA7MyD6jGI8yl0ei6/quqXGoSltJt7lVjkjDcpmRQNtgKVpmMNNmy5DM/uxL5 uSdThxYxAfvDH5Mm0vSLDTLf0LOIIv7bndmPizd82eDBDEKiHV59RPKbkUZlzS7FXYq8b/5ypkdP y6slU7SarCr/AC+rzt+tRluHmwnyYv5c/L8ecv8AnHSzht4+WsafNd3WmED4mdZn5w/89VFP9ah7 ZIyqaALDybT9Q84ecYvL/kOOZpoLad00+A1+AymrNIepWJeRH8q1plpAG7Hns9H/AOckPLen+WvL 3kXQ9PWlrYxX8YYgAu3+jF5Gp+07Esfc5XiNkllIPYPJMiSfklpzIagaIVJ91gKn8RlUvqZDk8S/ 5xT/APJh6j/2yJv+om2y7NyYw5u/5ys/8mHp3/bIh/6ibnHDyWfNIPNX5TfmbpXlRNd1GcX2jrHH I6RXEkxiikAKs0bhaKKitK0+WETBNIMSy/8A5xe0zyRcazcXd3Iz+a7UMbG2loIhCy0aWHu0gqQ1 egOw7iOUn4JhTNf+crP/ACXmnf8AbXh/6hrnIYeaZ8nkHkH8u/za13y8l/5Y1CS20ppZEWJb57cc 1Pxn01IH05bKUQd2IBR3mn8r/wA69M8vX1/rWpyzaVbxF7uJtQklDJUbemTRsAnG1ILN/wDnEj/j neZf+M1r/wARlyGboyg8yD3v5U/nCZZYGaDTbpyqDb1bGcMoZegqYn28GHtln1RY8i+ufLvmfQPM enx6hot7Fe2zgGsbDkpP7Lp9pG9mGYxBDYC+dv8AnK+4gk8zaLHHIjyRWkglRWBZaybcgOlcvw8m E2XfnF/6z5pH/GHS/wDk0uRh9SZcki/5x5/LbyR5n8l3t/rulR313FqUsEcrvKpEawQOFojqPtOx w5ZEHZEQHrmk/lB+XGkalb6lp2iRW99av6lvOskxKsNq0ZyPwyozJZ8IZhkUuxV2KuxV2KuxVCal pOn6lD6V5Cso/Zboy/6rDcZTmwQyCpC27DqJ4zcTSSfo/wAx6IK6dJ+krBelnMaSoo7I3+fyzC8L Ng+g8cO48/h+Pg53i4c/1jgn3jl8fx8UdpvmnSr1/QZja3Y2a2uBwYHwFdj+vL8OuxzNfTLuLj5t DkgL+qPeE4zMcN2KuxVYJoTKYQ6mUDkY6jkB4060wcQuuqeE1dbMD/Of8vNX89+XLPSdNuoLVre8 W6ka458SFikjAHBWNf3mWQlRYSFpl+Vfk6+8n+S7TQb6eK4ubd5naWDlwIlkZxTkFPRvDBOVm0gU jNK/L7yZpOuz69p2lRW2rXPqGa6UuSTM3KSiliq8j/KBiZEilpif52/lXq3n+30hNOura1k0552d 7nnuJggovBW/33vksc+FEhbJfLHlO90n8u7byxNNHJdwWL2jTpy9Mu6sARUBqfF4ZEmzaQNmBfkz +SPmDyJ5outX1G/tLqCexktFjt/U5h3mikBPNFFKRHJzyAhjGNO/Ob8kfMHnvzRa6vp1/aWsEFjH aNHcepzLpNLISOCMKUlGMMgAWUbesWOmpHolvpl2qTxpbJbXCEco3AjCOCGG6t75WSzfPvmv/nF3 WotZe98nalBFZs/OG3unlilgqfspKiycwvYmhp4nc3DL3tZgzvzt+VHmLzJ+V2geVPr9uuq6XJby 3d3M0rxyGG3kifi3HmatJUEqMhGYBtkY7Mh/KXyRqHkvyfHod/PFc3CTyymWDlwpIQQPjCn8ME5W bTEUmvnzy9c+Y/J+q6HayJDcX8BijllrwUkg1biCe3hgiaNqQxH8k/yt1jyDa6tDqV3b3Tag8LxG 250URBweXNV/nyWSfEiIpPPzF/K3y157sUi1JWgvrcEWmow09WOu/E12dK/sn6KZGMyEkW8Mvf8A nFjz3aXJbStXsZ4q0WV3mt5aHxVUkA/4PLvGDDgKaeWv+cT776yknmXWYVt1NXt9ODuzjw9WZY+H /AHAc3cog9V/Mv8ALu48y+QY/KujzRWgga3EDXBcqIrccQpKh2JplcJUbZkbPF/+hUPOX/V30775 /wDqnlvjBhwO/wChUPOX/V30775/+qePjBeB9RZjtjsVdirsVdirsVdirsVQWpaNpmpJxvLdZSNl fo4+TChynNp4ZB6hbfh1M8Z9JpKR5c1mx/45GqsIh9m2uh6iAeAahoPkMxPymSH93PbuO7l/nMWT +8hv3x2XC787x/C9jaz/AOXHIU/4kcPHqhzjE/FHh6U8pSHwWmLztejhJJbabEdmaMGSSntUkfiM HDqp7ExgPmUiWlhuBKZ+QTDRvL9npfORGee7m/v7qU1du/0DL9PpY4txvI8yXH1Grll2O0RyATPM pxXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FX/9k= + + + + uuid:588cc91e-e173-b34d-9c0d-df9db88de746 + xmp.did:b6d881e9-8136-4708-82c2-a5818995bc6f + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + xmp.iid:3d58b951-e27c-4e2b-bf80-af2ab47a27db + xmp.did:3d58b951-e27c-4e2b-bf80-af2ab47a27db + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + + + + saved + xmp.iid:48fef565-7731-4c49-bee9-dfbb0bfe5fa3 + 2017-02-28T19:39:58-06:00 + Adobe Illustrator CC 2015 (Macintosh) + / + + + saved + xmp.iid:b6d881e9-8136-4708-82c2-a5818995bc6f + 2017-04-12T20:05:50-05:00 + Adobe Illustrator CC 2017 (Macintosh) + / + + + + Document + Print + False + False + 1 + + 550.000000 + 175.000000 + Points + + + + Cyan + Magenta + Yellow + Black + + + + + + Default Swatch Group + 0 + + + + White + RGB + PROCESS + 255 + 255 + 255 + + + Black + RGB + PROCESS + 35 + 31 + 32 + + + + + + Mirage RGB + 1 + + + + R=39 G=50 B=73 + RGB + PROCESS + 39 + 50 + 73 + + + R=110 G=116 B=125 + RGB + PROCESS + 110 + 116 + 125 + + + R=54 G=181 B=192 + RGB + PROCESS + 54 + 181 + 192 + + + R=112 G=201 B=203 + RGB + PROCESS + 112 + 201 + 203 + + + R=255 G=147 B=67 + RGB + PROCESS + 255 + 147 + 67 + + + R=254 G=201 B=78 + RGB + PROCESS + 254 + 201 + 78 + + + R=214 G=237 B=162 + RGB + PROCESS + 214 + 237 + 162 + + + + + + Grays + 1 + + + + C=0 M=0 Y=0 K=100 + RGB + PROCESS + 35 + 31 + 32 + + + C=0 M=0 Y=0 K=90 + RGB + PROCESS + 64 + 64 + 65 + + + C=0 M=0 Y=0 K=80 + RGB + PROCESS + 88 + 89 + 91 + + + C=0 M=0 Y=0 K=70 + RGB + PROCESS + 109 + 110 + 112 + + + C=0 M=0 Y=0 K=60 + RGB + PROCESS + 128 + 129 + 132 + + + C=0 M=0 Y=0 K=50 + RGB + PROCESS + 146 + 148 + 151 + + + C=0 M=0 Y=0 K=40 + RGB + PROCESS + 166 + 168 + 171 + + + C=0 M=0 Y=0 K=30 + RGB + PROCESS + 187 + 189 + 191 + + + C=0 M=0 Y=0 K=20 + RGB + PROCESS + 208 + 210 + 211 + + + C=0 M=0 Y=0 K=10 + RGB + PROCESS + 230 + 231 + 232 + + + C=0 M=0 Y=0 K=5 + RGB + PROCESS + 241 + 241 + 242 + + + + + + Brights + 1 + + + + C=0 M=100 Y=100 K=0 + RGB + PROCESS + 236 + 28 + 36 + + + C=0 M=75 Y=100 K=0 + RGB + PROCESS + 241 + 101 + 34 + + + C=0 M=10 Y=95 K=0 + RGB + PROCESS + 255 + 221 + 21 + + + C=85 M=10 Y=100 K=0 + RGB + PROCESS + 0 + 161 + 75 + + + C=100 M=90 Y=0 K=0 + RGB + PROCESS + 34 + 64 + 153 + + + C=60 M=90 Y=0 K=0 + RGB + PROCESS + 127 + 63 + 151 + + + + + + + Adobe PDF library 15.00 + 21.0.2 + + + + + + + + + + + + + + + + + + + + + + + + + endstream endobj 3 0 obj <> endobj 7 0 obj <>/Resources<>/ExtGState<>/Properties<>>>/Thumb 66 0 R/TrimBox[0.0 0.0 550.0 175.0]/Type/Page>> endobj 62 0 obj <>stream +HlɎ#M~|g8ApDx>gjӥNZwP/?nNk3.9)(?u>ǝkViM8L14 v/|8اEIZq:=wqFZ'id{zo[,dG_[qw\i- aēXN c=Q0$r^ߋo]>Cܖ  6gݒAr:3] $϶av{ZجіNq#Nm,duOI#zO}l% vCqgr[J<7k`*ൡ{N_nm>!w>r)1gZZkZ I&|3538MO4}Dub0 N5' *A7`Lk]dJH=Mr3UhLglmBٝ}-HjENo=/7n6#-+Béa5L/x0M_|<eэD[/Wj>JcЂqfRpiU$>%^*߷L[fn4.gtU^vUkqo&ETȉ>CSZU| R3`(K/4YrR'!3LK$|܂B1PUNB ^u  Z 'zH:L 3sT%|]4<}H8N5KYPݘ$do], C fXͪ(+A!^srIM7'Z#rhx\9Ȯb`#xJx+{B32 -vm GTRvCYY^ISɵ@j\L]2ߵₚ.HGM{} |X Yf^2˫;pWվ[O\'x,_!7Di ֭O ՚jl +Ir=uG&315ܷ!O|+ԋ|lCt#r"`Gpy⋌ybj19L-_ZE!6)f@:Q[bɧ5]NS -zW3mq(o2ʔ'/smٺ5l82ְvŠ5!|oZPZj-j)cϏ^Zdx,-Ɖ hxŌ0֫hvՠu"q2VHa3 -a7wŲ9,Wzx;Y ڲlěovq1UuxoJfy^x@wd9ox-Cs>W5$ƕ +7+BMkH-޺|Myd/g dcn?@Mx{`U U~6"vV--.aETT% d!:KvhyVi֨f1,z戂j*XQyю?Z9@f\(+4‹u(.g\.iw#b4uIpJ"xI]IqSd-M4FWex_ |[ endstream endobj 66 0 obj <>stream +8;X]Q_2ZAe#h6OcN89#B8RAchQ]#!-R!'5R2C,k\A60![`jQ_=OVQe=Co?ta"s*>% +dHJb$GDcXP86o:n90R+?B1Sme.%&1-g$*\%Xm?Ak&5)@fu6G@%IFFG(\k +.qR2./$MUeaC4h,JJ>=Wln,:"k&Q(,rPG?$A95%BS;nX_=9'jQAR(M$W=$l>:9t/X +J(#WY.Ua[Qh\@S-Kr*'ok/O5ZP770;epl`g%-YHZT endstream endobj 67 0 obj [/Indexed/DeviceRGB 255 68 0 R] endobj 68 0 obj <>stream +8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0 +b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup` +E1r!/,*0[*9.aFIR2&b-C#soRZ7Dl%MLY\.?d>Mn +6%Q2oYfNRF$$+ON<+]RUJmC0InDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j$XKrcYp0n+Xl_nU*O( +l[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\~> endstream endobj 60 0 obj <> endobj 69 0 obj [/View/Design] endobj 70 0 obj <>>> endobj 65 0 obj <> endobj 64 0 obj [/ICCBased 71 0 R] endobj 71 0 obj <>stream +HyTSwoɞc [5laQIBHADED2mtFOE.c}08׎8GNg9w߽'0 ֠Jb  + 2y.-;!KZ ^i"L0- @8(r;q7Ly&Qq4j|9 +V)gB0iW8#8wթ8_٥ʨQQj@&A)/g>'Kt;\ ӥ$պFZUn(4T%)뫔0C&Zi8bxEB;Pӓ̹A om?W= +x-[0}y)7ta>jT7@tܛ`q2ʀ&6ZLĄ?_yxg)˔zçLU*uSkSeO4?׸c. R ߁-25 S>ӣVd`rn~Y&+`;A4 A9=-tl`;~p Gp| [`L`< "A YA+Cb(R,*T2B- +ꇆnQt}MA0alSx k&^>0|>_',G!"F$H:R!zFQd?r 9\A&G rQ hE]a4zBgE#H *B=0HIpp0MxJ$D1D, VĭKĻYdE"EI2EBGt4MzNr!YK ?%_&#(0J:EAiQ(()ӔWT6U@P+!~mD eԴ!hӦh/']B/ҏӿ?a0nhF!X8܌kc&5S6lIa2cKMA!E#ƒdV(kel }}Cq9 +N')].uJr + wG xR^[oƜchg`>b$*~ :Eb~,m,-ݖ,Y¬*6X[ݱF=3뭷Y~dó ti zf6~`{v.Ng#{}}jc1X6fm;'_9 r:8q:˜O:ϸ8uJqnv=MmR 4 +n3ܣkGݯz=[==<=GTB(/S,]6*-W:#7*e^YDY}UjAyT`#D="b{ų+ʯ:!kJ4Gmt}uC%K7YVfFY .=b?SƕƩȺy چ k5%4m7lqlioZlG+Zz͹mzy]?uuw|"űNwW&e֥ﺱ*|j5kyݭǯg^ykEklD_p߶7Dmo꿻1ml{Mś nLl<9O[$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! +zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km endstream endobj 63 0 obj <> endobj 72 0 obj <> endobj 73 0 obj <>stream +%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 17.0 %%AI8_CreatorVersion: 21.0.2 %%For: (Lindsey Wilson) () %%Title: (Ember-CLI-Mirage-Logo-Horiz-Color.ai) %%CreationDate: 4/12/17 8:08 PM %%Canvassize: 16383 %%BoundingBox: -246 -1520 257 -1366 %%HiResBoundingBox: -245.90283203125 -1519.4833985042 256.826026563773 -1366.9794921875 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 13.0 %AI12_BuildNumber: 242 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%RGBProcessColor: 0 0 0 ([Registration]) %AI3_Cropmarks: -259.395080245988 -1533.53794810259 290.604919754012 -1358.53794810259 %AI3_TemplateBox: 306.5 -396.5 306.5 -396.5 %AI3_TileBox: -362.395080245988 -1734.03794810259 371.604919754012 -1158.03794810259 %AI3_DocumentPreview: None %AI5_ArtSize: 14400 14400 %AI5_RulerUnits: 2 %AI9_ColorModel: 1 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 1 %AI17_Begin_Content_if_version_gt:17 1 %AI9_OpenToView: -3343 223 0.3333 2549 1289 18 1 0 5 43 0 0 0 0 1 0 1 1 0 1 %AI17_Alternate_Content %AI9_OpenToView: -3343 223 0.3333 2549 1289 18 1 0 5 43 0 0 0 0 1 0 1 1 0 1 %AI17_End_Versioned_Content %AI5_OpenViewLayers: 7 %%PageOrigin:0 -792 %AI7_GridSettings: 72 8 72 8 1 0 0.800000011920929 0.800000011920929 0.800000011920929 0.899999976158142 0.899999976158142 0.899999976158142 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream endobj 74 0 obj <>stream +%%BoundingBox: -246 -1520 257 -1366 %%HiResBoundingBox: -245.90283203125 -1519.4833985042 256.826026563773 -1366.9794921875 %AI7_Thumbnail: 128 40 8 %%BeginData: 6858 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C45FD23FFAF85FD7DFFA98435AFAFFD7BFF845A6059AFFD7CFFA935FD %19FFAFFD51FFCFC2C9C2C9C2C9C2C9C2C9C2C9C2C9C2C8C9FFFFAFFD12FF %AFAFA8FFAFAFFFFFAFAFFD08FFAFFFFFFFA8FFAFAFAFFD05FFAFAFA8FFAF %FFFFFFAFAFA8FFAFFD0BFFA9AFA8AFFD04FFAFFD07FFAFFD04FFA88484AF %FD08FF9FC9A1C9C9C9A1C9C9C9A1C9C9C9A1C9C3C2CAFD13FF8460355A35 %6035A9FFA935AFFD06FF5960FFFF605A3560355A5AFFFFFF5960355A3560 %35FFA860355A35605AAFFD07FFAF596035363560AFAF3560FD06FF5960FF %FFFF606084843585FD07FFC2FD10FFC2CAFD13FF8435FD048485AFFF8460 %60FD05FF846060FFFF84358484AF606060FFFF603585848484AFFFFF5960 %84AF60605AFD06FFAF36605AAF84845AFFAF605AFD06FF6035FFFF8460A8 %FFFFFF3584FD06FF9FFD0FFFCAC2C9FD13FF843584FD06FF84356084FFFF %FFA85A3584FFFF5A5AA8FFFFFF3560FFFF5960A8FD05FFA86035FFFFFF5A %3684FD05FF595A84FD06FFAF3560AFFD05FF595AFFFF60A8FD04FFAF36AF %FD05FFC8CFFFC2C9FFCFC2CFFD08FFC2CAFD13FF85358BAFAFA8FFFFFF84 %605A60FFFFFF84356060FFFF8536AFFFFF846084FFFF605AAFAFAFA8FFFF %FF5A60FFFFFFAF3585FD04FFA86060FD07FFAF6060FD06FF605AA8605AFD %06FF855A60A9FFFFFF9FFFCAC19FFFC9BBA0FD08FFC2C9FD13FF845A3560 %353659FFFF8435843584FFAF35845960FFFF6060355A35605AFFFFFF5A60 %3560353684FFA96059FFFFFF595A84FD04FFA83584FD07FFAF3560FD06FF %59606084FD09FF60A9FFFFFFC2CAFFC9CFFFFFC9FD09FFC2CFFD13FF8535 %84848584A9FFFF8460A8845AAF5A60AF6059FFFF8435848484606084FFFF %605A84848584FFFFFF5A605A845A605AFD05FF846060FD07FFA86060FD06 %FF605A35FD0AFF8484FFFFFF9FCFFD0FFFC2A7FD13FF843684FD06FF8435 %AFA860355A84FF5960A8FF603684FFFFFF5960A8FF3560AFFD05FFA86035 %60356059FD06FFAF355AA8FD06FFAF3560FD06FF5960845AAFFFFFFFAF84 %AF84845AFD04FFC2CAFFC9CAC9CFC9CAC9CFC9CAC9FFFFFFC2CFFD13FFAF %35AFFD06FF8460A9FF84605AFFFF605AFFFF8435AFFFFFAF605AFFFF605A %FD07FF5A60FFFF606084FD06FF843584A9FFFFFFA8FFA86060FD06FF605A %FF8484FFFFFF60845A6060FD05FFA0FFCAC9C2C2A0C9C2C2A0C9C2C2A7FF %FFC2A7FD05FF84845AAFFD0AFF84603560356035A8FF8435AFFFFF60AFFF %FF5960A8FF605A59845A5A3584FFFF35605960356059FFA86059FFFFAF35 %5A59FD05FFAF60356059603560AFAF35605960356084FF5960FD10FFC2CF %FD0FFFC2CAFD04FF606084A95984FD09FFAF5A8460845A60A8FF8484AFFD %06FF8460FFFF8560845A8460A9FFFFFF845A8460845A84FFFF5A84FFFFFF %AF6060A8FD06FFA95A605A8484FFAF845A8460845A85FF845AFD10FF9FCF %FD0EFFCAC2C9FFFFFF8460A8FFFFFF35605A84AFFD07FFAFFFFFFFAFFFFF %FFAFFD07FFAFFFFFFFAFFFFFFFAFFD07FFAFFFFFFFAFFFFFFFAFFD05FFAF %FD09FFA8FD07FFAFFFFFFFAFFD13FFC8CFFFC2C9FFCFC2CFFD08FFC2CAFF %FFFF8484FD04FFAF84AF5A85FD5FFF9FFFCAC19FFFC9BBA0FD08FFC2C9FF %FFFF6084FD07FFAF35FD62FFCACFFFFFC9FD09FFC2CFFFFFFFAF5AFD07FF %AF60AFFD5BFFAF84FD12FFC2A7FFFFFFA9AFAFFFA8AF84A8846084FD5BFF %AF5A6084FFFFFFC9C9C2C9C3C9C2C9C3C9C2CFFFFFC2CFFD08FF84846084 %84FD2FFFA8FFA8FD0BFFAFFFA8FD1CFFA8603585FFFFCAC9C3C9A1C9C9C9 %A1FD04C9FFFFC2A7FD13FFA82828FD09FF52277DFFFFA827277DFFFF7D00 %282728272E52A8FD06FFA8532728272728A8FD07FFA852280528272852A9 %FFFF84282728272827282728FD0DFFAF85FD12FFC2CAFD0AFFCACFC9FD06 %FFA805277DFD07FFA82700A8FFFFA828007DFFFF7D270528052700270584 %FD04FFA82E002700280527007EFD05FF7D002705270027000552FFFFA805 %2805270027052700FD14FFCAFFFFFFCFFD07FFCAC2C9FD07FFCAC99FC2A0 %C2CAFD05FF84270028A8FD06FF52000553FFFFA800057DFFFF7D002753A8 %7D53002700A8FFFFFF5200272EA87E7D052700A8FFFFFF7D002700537D84 %7D5205A8FFFF842700537D7E7DA87D7EFD12FFCFC1C9FFCAC1CAFD08FFC2 %CAFD06FFC2C2C2CFFD09FFA82728057DFD05FFA80528007EFFFFA828007E %FFFF7D2727FD04FF7E272753FFFFAF272852FD04FF84052759FFFFA92728 %27A8FD09FFA827277DFD0EFFCAFFCACFCAFD05FFCAC1A0FFC9C1A1FD08FF %C2C9FD04FFCA99C9CAFD0BFF7D27052805A8FD04FF272727057DFFFFA800 %277DFFFF7D00277EFFFFFFA8280052FFFF7D2700A8FD05FF280052FFFF52 %27007DFD0AFFA827007EFD0AFFCAC2C8FD07C2C9C9FD07FFCFFD09FFC2CF %FFFFFFC9C1CAFD0DFFA80528272752FFFFFF53272728007DFFFFA828007E %FFFF7D2727A8FD04FF272752FFFF7E0028A8FD05FF522728FFFF52002EFD %0BFFA827272E7D537D537DA8FFFFA0C2A0C9A7FFCFFFCAFFCACAA1C29FC2 %A1FD0EFFC2A7FFCAC2A0FD0FFF7D27275900277DFFA827007D272752FFFF %A8050559FFFF7D0027A8FFFFFF2827007DFFFF590505A8FD05FF530052FF %FF272728FD07FF7D7EA8FF7E270527F8050000F8A8FFCFC9CAFD0DFFC9C9 %C2C9CAFD0BFFC2CAC9C2C9FD10FFA80528A87D0052FF530052FF52007DFF %FFA828007EFFFF7D272752525327280052FFFFFF7E0528527D597D537D28 %2728FFFF2E0552FD06FFA82700A8FFA8272828532E522852A8FD14FFC3C2 %A0CAFD08FFCFC299C2CAFD11FF7D2727FFA828055205277EFF272753FFFF %A805057DFFFF7D0028000000280552A8FFFFFF7D272705F8050000F82705 %52FFFF522700A8FD05FFA800277DFF7E28007DFD1CFFC99FC2C9FFCAFFCA %CAC2C2C2CAFD13FF7D0028A8FF5327272752FFFF28007DFFFFA828007DFF %FF7D2727597D52002859FD04FF7D002852535253525327282EFFFFA80027 %28FD05FFA82800A8FFA805277DFD1EFFA1C299C29FC2A0C9A7FD15FF7D05 %05A9FFFF052700A8FFFF27052EFFFFA800057DFFFF7D0027A8FFA8280027 %53FFFFFF7D0500A8FD05FF520052FFFFA852002728A8A9FFA87D00277DFF %8427007DFFFFA8FFA8FD1BFFCAC1C8CAFD18FF7E0028A8FFFFA8277DFFFF %FF520059FFFFA828007EFFFF7D2727A8FFFFA828052828A8FF7E0028A8FD %05FF52272EFFFFFFA82E0028272E282E272800A8FFA82728272E272E2728 %27FD1CFFA0C2C2CFFD16FF520000AFFD08FF280028FFFFA8000059FFFF7D %F8057EFFFFFF7D28000052FF7D0000A8FD05FF52F82EFD04FFA853052700 %050027277DA8FF84050027002700270027FD1DFFCAC9C1C9CAFD14FFA97D %A8AFFD08FFA87DA8FFFFA9A87DFFFFFFA8A87DFD05FFA87E53A8FFFF7DA8 %A8FD05FFA8847EFD07FF7D7D597D7DFD05FF7DA87DA87DA87DA87DFD1FFF %CFA0C2A0CFFD0DFFCAA8FD6EFFCAC9C2C8C9FD09FFCFC9C1FD72FFC9C29F %C2C3C9C9CFC9C9A0C2C2FD76FFC9C9C2C2C2C8C2C9CAFD7CFFCAFD52FFFF %%EndData endstream endobj 75 0 obj <>stream +*ɉ,k=$D@"%ݖ Bl,1 X^6ו~*DJ#LhEl!l郼wܞ2T!.Ǥ4+ (9 !V(27rC) Rʲ:V5u櫫SZCx1yCp$4!N0u:I!զ1uOMg|cǰ+aQ+f었u:,O4O_&D2:k&isa"Kp/hP (vq1$U끘('n(PrYgMYwHnQGZ= +I9ౘTЉ)[ۼd A#f"f0% D v4B,]eO^ @ E(. !k;Z.l]V I<8S( +x60C +@SF#DB}34w 8H8piM2i pUw*Wf4-' aS]o̶ {x4E&m&VѵO'L=Aa @ڱX<uI؅B3u*ۄXa60/1/oĬ7eh䐦zYI"30dM=VDeXAwYC "Tz6Rl艣)5dM ^[Uy<#Kb#%L FDb)$' Q(7Xģ$BA1o2)-~Dh-v>&¡LR,p#Q cQa ӱ8 ,غ#Hδ{u_ P) E@_}F wLy1l㠝bAc8i4lcyHAM6_dW h'ϕB`ز ُ'N,*X7Ъ<]ũO?B˥AB1B!T| 2oP̀dUHXiB6w񒀅,6fupBA`5=@@*bWwK5b' +UNThw;}fH5WɆu[IBLsEp *tZMұ<(%ʩJ:f{" CZ9V|bm])2n Jqk*| ǭAQuVuxcQƔ$_c>q9%ohݐnwPP075LD;#2AӠ2.QA4)[90@S*Lįaob-QN?[D +$XiH%I ̀i8@D hm-lb˔ؕv[EKMCʇJyLr戙rD]Yq&ēD0 +ގt-_8 ZΒ'8U3vɾN%Ն8Fd " fӑIPKJ А.y>viJg R~{bea.H0v_$B06\2 4aE. ?qk<ҋq\~ +9dmx1׳"^g ܢ_ (Ǽ-WLM+T!cGpPqZ4CzNpWQq2+౻C]a]lT*VpʐTg2-,9 K[s(-;2J%?Wݳ2uPMơ/ QUdҬ|ER)`^UVT3PueY,h[u4eI<*uJ! +Bb+. B `Kq + .L9Ku$0, 蕫&<12ͻZhk˼Wצ-dlBAԮkbMBқ#] +tEk OaT\ z%:54aև,d/1v`Hqf UɄC;u +iz WfCEl b5HJTiY7+SY6WkpKL=Q1Iqx`YW*ߎt)ˎZ#ڤjR"3M)J!FTu*WgMw*ZR)Ȭ +CJgL'HDfH,Je`33'9-FprfN9ʅxɜKKyBF<0M9(9bx9@(( xg,xa3XA 4v:(p<CSsW(]Z0[d e+i")43f`ӆFe5@H<pfKx2\sGz%>YAżB^2 +_txg>-\SsڜliDeT2g W߮5D o\`'ZXW)+}Zϊ:8^T\i$Ķte֖kZAvj=G<8v"90y* bL2*t,a%jB[_5PR$@7JUaNDMJRGWkquE )mr{X*j;T G4JP6Ȧ7zH5jJlpwGԅb %-x{*qʲ#ڳJmZ*/\$;"B!d"Ghaŀ#y'.l9 X51D"Pk.6*su*bRJgE +ZY^{Lbɂ%JlbU0mt|^p7/9c6K#ɔwJ_! +.|Q"Q jldքEr>$4efٟ'eŁZB.Kj9|q(+2.G:㑡 bB[q\\gnO}{iPPfJ*unJ|tz"%p5jLTجt +!0X,Y)4hL(8deN 48D+j +UVKa.UdJr51MC(-ZjRF$Rr:rIR^s8Z@S)&EG*%1*pjTj$j!Eآ,RJ[ڽJ%q5XLBH5"bGvȫYRǹ<^5kWU$a%XLx 9yJDn)Rʹb:!Db.5l~/{9;U t1|Gt +8 .IR(k-K!.Ab+Xy충r +R cqUN9S +!Wݒ[ܳ[)JGSJJTQR)sblN{1|P/\l66֢ -TtNkفTtJXor76|qiʲe3hPWm`ysayaaw"aBaܥ"RXnXP{q&UWf&?(+HeIX +%)/$GDGq'@by3fPT)žS#ؐr3(PNĻ /t1#Z'`i-6rx*o#@=\'E i;f4t D jV]sf!UdrXb +29εP^0(6`H6D7F5#Y=q2;b9t3P +(bO\J,,Safp#]ݔ] h'Bd|#HعGMewf,V)b*NurII%Ƌ&>Wũٽ]^-$x:D^W:5 @Bg! 3.Kޯ%̺]\ݦ<_i$^/vy؎37F=2y|R81_vM, 9˹n+[/ݎ{+>2C33Prh+ad@vY /E(EJx'o>_o|?'kŁ*47q~v^as$3dEP'S+r4qn?W(/x4y|ue Mo\,hp~(2rqܑ?F$4*h]|j7Ûy\ȉw<4(dCĻo7G߉GyGf0%F"D#-\G p:$r NɕN-cr0Ltu^%Af'BLjj# T%nUVn% bJk4Y <?qd4YVoi9V^sO!ށsO? y_= 8 +~ǜk)IwO1= W7{rh^Quc:!}Nzз=EOͽ2; 2 C}6kd+lT| + xN%$;^3ZhuyYaģ݆\Dr_}dsnE![+Wpmv47k3ʋc2"y?,GELgtA WJx + S.s¿'v%8]ec|/c$;]LF& +P`.!LRF6১ ǻhlhB,%zt:|Z$j4Tʠ%aE_->ӵs4c?ޕ? b9CX$8Mv TGvmBza/|S wsK):#?aThP18{]OL + +?(${7?Zudy8]^\v3sc~@ +불KM +Ih޵?F9YY# +` 28Ǯ +8b4ځ:,pPG#r{';mÔB,0&Mrcg%4@lRFh9`Rq$9)Q%|8 W 籗r3N)b`K_N]@)WD:a&S !vDjnǍ腅 ͵c8༊c2Dt?!E~4xS'B`ѣQq#ofO;M|+H@4EsuD@'pƨ6&`D8>7S 3(IlAc60j9qDٹtHjhީr.h>o,IFY>ʙр$-[Ѹ½aR$P>W.G b 윦a( 1!7caЏkN6F{5h$vGֱ]s[ 86 |Qn:r\Ҿ6zr0[]h?`,jlpPrin9FVڙ(_1?w X\heyXD;$=D wC,a4)2 bCTn0ءp-:Ի޻2X!FFZcG˖ b^]| I4XL)@vTۡ >9Qa'{Iy/ +V."0 3=C9TWiu.X{x1gaPCƝ"oNa>䉁xH"8k|Yj[m[:]A|Qs3/i,l [E+~,waU8H5 =E] <<&ҎQ,PqF@8PBx&ly#0ӯnmW͵f|60+4!&xب"zuA:+D0b56j,\kfԦٔ\ @ҀO j4/>!D'LJvbg2j7Dҵr&;AcOʻؠU,bX ݁ +q/OvGyB6NyFсrrI ! JErUJb\?\ӧӜ1!H6sI-p  "%A@VjU䝙ʉ]F +9pSpz+tġ1sG|dGB~TYvV/ʤ~vz(3NNr{2ۿasJGX9gu2B1TɡwI~ܐ.AáIHt<r+.1 ZV6Hi]0aWgP'5 +BLDjZr3=w|:͇3%" 0tZ$/ۊd#ׇDH+l2sHOnffwWdd^!D)wlYf3(y(3'#xLpW,_=JTR~| p =ySi4ufqHiF;:ɸV!|^ny{{c3w1J;p *" M횔1b޹GjjN$Kc![q\iG $B>ƗΖӉ똄Vz>)$˻p;_Uφu $ 37K(SZq %eŚ'sXEXqJV65Q>2>bXB<7*n2";/V ~>t$E2Om AX| ?Oq W}EѫNd'h͢q8|^.k' [cQȄIeŝ~4JnLT +ozT0 ?@(&K%7jpGxYJ(O3rpg)L*!a;Aboo9 + ̍H0`S!GnEFߨگJOT΃#V|hڼ9Z+ҮiF m De $t/.쩴*`RwtdnC9s񋵮:?Spat܏f $brJWpg;_$8Ix"1-jwb[pKc&ᚏ)PKp&pEV9@X JAOl!w?k &{(B]~q6V#6).@d}MXXE Gzwn$LE峡@(0ׯB6*gB>GG!f 6F3X}|0>9cM7 0CX:X(>X7q'=:k&-2HBifeKk{ES4 G%8҉XzO3d<> rE9wIk9 Y'D;pȕ<鎉ŊKŭщSq0(\zC;GH B  j@o 0c +%""y_[I?3,TȽUEQ`RҦ;s1զݾ2N4 9k9o,$ ~JݱPާlkpbK X xWw0ؔ[] pbZ/xlO ߆v +!JkƮّb8-g|L /,%~߰6@c ,K+=Q00HE=c,zMӻאmTHt".a K`DmKGPCz63 gYcDWN>6JYx̢}E΋nfiDv]'rB'jp{G |'Cq(H8d/zkͰ8F |7PJ"1Ҭ-!K̈́In'8͖/9ei 7FB|ʯ׷ -|Ƈ;QβރFC>,oEiXGY { owcV(yu& ο'>s>+[lg9_I@=;h,m|x|۽F:j?PMYFʇN?OőE?ZLFgZ + 5ȹ%C|yƈ;185&O gk衫?Z#_*?|Q6=Wרbæd-|[] +/ 0bd!|FLD"Lje>ɑLt"=y;Tnr*п8* 5 (I +Gv s +Yed I,ji} ^ r_;vdY-Cqqs6̝An?=9"-w/tcWC^_ =xH`cZqa:Eh ,C^]4n_U_;Xw"2<`ȶ9 oPdn"aErRik6@2 +q29H%44jh2;1yyΆ: S\ .$OHND]p@,pd{4 ^`_H#g d@";= K"ۃLp9Id *׫- =J43&ӛ@$fls>GFHtF?*tZ"-#rм1A1eFn^~Btvr)r9|0Dŧ0bRWb_=SuX +Tp=Ty:t(.@~rL[\rߩhԀugEcϥ  %ݭ|X"`er.4* |#z)e|$qt'HܝO{!;㲟6ˇv@)fW\! q_nlZԑvo3s>כܭ-1fkyG ҫ]fh(u|@1 g }'Яlq~ l2;ԿӸIG M&TaT#LuIJrM=X- 'b@;o qtə P1)寳ne!!r>*_HRXe* ߺ[r\=,9(3o yir JCSQτpx(ۜde)L/ +JGb)D$SYG!O!Bu g_/bYE|Yp}rU@O*2N;ZV O 1ؚDپr}%厸 HB7,h8H`sLLib8VY%y(I6b 8-Al 8) s<H00cHq#(r53ZSUA\r2`98'{kP28e7zsȫ$0T@|@_+VL0S 0L_,Ɇ'­ PZơa ,^؁$Oq#m7C WjRΦ[eq_<.@wǥ&%S4{Snll  L&^b0ԃ]MJMMX"p-]; &fSaQ )J&J ){8$]2_OpN`JHr}Y0%yPȀ$M&>NxVH / += < +r ą׊O񉰏M .\ܜtu&8{g~!2iIDR\_yj},+;r2S$MMD6*E[ 6- Z(|$-*3SBp03 r_=ESj,VQ28>K(ZW% &.,#3;Rp HS6-y̛~lރP8H;Ibs@c;@B'o\"]rO@v(LQ蒋xE, ? Yr"EZ dNd<([4-]E゗@*-^-s28[fwQE+|n{ܢiyqXI$r`\%q|r5)?[T3ECt's DVZ|z1%bӋ4S䲋n>R rYC+ i29Y@Y~4L@:g82\ +S5e[,M8dEt=JَǶ?`.hLQYAGI:q4#7mYneN"p#H[}n4M6gMr)uîOtc,h܆kY{Hc(2 [&rXY3L^e Zb͝K.ZWO \́: uiTfElGf4D o] 5I|v_g_PCu3( mkrv_ɵI!ad{'H /e )iRVǐ) OYu>RƇEtvNMyQIY.!OWrCZ6m:n'N6 T'r嬐42>1v N +'F:D2Wzg Sz޹]JO0{d:?F!r(Hw3W~RLi+<03AqFjzeUӧZA9ʀ!ZOl^cn T8+&Qy2_4ɱJvE6\)pd|Ci ;)vˉ&X.y2'~Hܒ[eGB06؂xGV% :pywIWiŕS)ٜUd,~꤭TpS.SƭRA7gJIxC]f +QELْ-htιb[ bРPC ;2ˑdPYnb+Ct(d2uډ0 `4.&DUXC\E@[Y~iPVW_wzMA `(NvmʡMzGA" IQy I*dD+h{ںm"%!3@wkbKAUΨ@9;Km.a:sz!t=ErT%BgR':ԋ,Ӂ<nr "KՇilEiTSg< ,ݜ _|EH&!1XTJ΀p;{X+|l[˭DUX(]h(tMK2yzU&@)S􇸭@˶[ lv:K`Պ\~4[ɒw, +lޙey72L +:=]`PY?t*5(P6)y`FPI37~[a)Bl-46S DL͇ tV2b+ +e4luҜt@3uV"O sA^"V6Cmk$Q Va=rD?SW^VJ2db6<=Aٜ䁙 {ggrclCINho)}$BAD! ]eYAe$T~rXG/C,UR u'ĉM%cwu̝,Vv6 >50/u=TztkѦRףMG.u=YMiTzhSѦRAGI:6պm*u=ڔzRףMGJ].nm*u=lWhӥGJ]6mhSaG]z +IXJ]OW_ףMGJ]6]z-h[ѶK]m+u=vѶRףmG.u=Vzh60юOμ\  حʐJ@Fg۸;(QΪ޻̲hʼnٿ]ɾ$N\t$:`0ˆÀ20E!( 9 B 4sDl|i -L*tp:8 B0io a d(wdgB[ψ@3er`aa+0 \aQeaER"@U@tD 24la@Ӌ: ha-60E.8 $ Ah+@206V8 D0w pD*2/Zhvd`2aZ-s` 8 aDa L B1Ay)uH +㝦q,pH$ 8 $E}uHxaA mpa | .6Cu5M?EHUT +Gi +)(,9*ŀ ЇD.5Vj59͟zՃRa}`T+Tf6>@-}y &}@gOfY;E%]Q c3~Ĵu1 L:LcWE@*4L%+ܪŒ} ,Asڢʊܠ @r8]LIH%8,Su}" Wb>0]\>BRx|{L≊|/Sf0>k䉦H(R`_y#y5h3*4W<t(s`@cS`,9DN?,TXL KfP%ǁ%HXGY78o,NL4C8C)fT8B]8,#AK:㎼apKl;$8$䶕1'a)-0HVBM**tI3Q  {Rs!䷳xB^/9,UB&tɱMB|~P<۾(lEg;(tijX0.*ءHϔ/Oae܇v (TqLfq5%ׄ(/|ʴZ$vPcr=pn;[Km:2J~)#*8)"h z-_30gAx<٭XX H]P#6TX d!(7B,;bTQo?(A'XӗT~,!\CD. : )o]R91r|18& +eNn1 FTl3]ӡ,qSTXl] xKl.̴)iHğbI4~y7"5qCkgƃ19RD/ee/E$w7),oİdèbEa)HRARXE:VЈL~sL HeB$g_꿼Th{G7ðט +2j 9&4q~$ Q(LU5O '{ 0-oH!FrDe.7 (ddNw~JHCq& RbVFJH}mJg:+c/$PI2*/!(Dj5PK!`2YɖE1pm6$D\'/B`hNj*2l`;KqrU?ҍH!O[D^@'aRUx˘(mrE2PBvwW=.nj`'u;l/x²NS,-)ݨ30YA,E2LU _CM>v7?PF(kz[y]bb CȄ)\v1%e"\"WD㡳0: /[TS*2.R9[KC}la9(("ELA/aC&9=6I:KhVT +F9;`a ?#$+8x9.U`8 J +šuv6 YDYKc$A +v,6b)+FRD H]L\ch6Epe*(WFB 3\1F2D+G4ߝz췘;YMC$i\&E" gDKPa+ ?8<C:$BsAxG ?rtwT3t3HuAh9+ѧ +YB۠WFF_]>uRjƁ9b +fH;zS[#Vzwl:J9;3+_)}D%]١Fl`ҿ4fZ oPȘ>bdy#`#gp0=-^>^*X6)9VG.#Ґ0C +!4. + ab%o"v:1t!09/gOЍQQ=iD2LzRP6,`Ciiv7q`GBc&CA$¡BB/B#i| mk`GPހ7LG!CDu YT0j +b&e/:-ő;0 +Haz1x\tzZ/uŖȌ-4{dfGՏKi)=.eWY {2%)LGЖaaF6=VP4;D% 5g`\B^u>'~aF :3 Ư $Xcyɥ4lC1|kXV٫W|a)Pj܄w.`[Fɉ{:]f&4JINV,v/Gcaq]3ͤj&/(R<.{9E%+HQJ!(N;"AuJk0H; ذFz%&žr(0g-%VUS0Gt,oP30Mh}[GHn)e <5L @ٴ)9#mJcBD 预a#"X弡`^=7Ļ`886IlxdS/XRfD8_bK1WsbA#~ %|?ؔ^ۅΖ3UakXPxX:^qPy6e0G<=4&L'p0intxT5iI;ﮆn[& ʫm0ٶ(W~+=P>niDYթ@=(PX#ifej!ځ$nj4 65x2i^^٥.03hپ2>Yxf4сe=qq$.iaa ]']J!stB3D- T]n185bw- +]Ig6^ 3' ʊĂ,+iS3\(aٙL]WYh}:ïa^T:E#-+ *D~f` +?s@P;(Y4Ry_zІ30@+h*xxlw⣉Wl$C˰HX.{g! + Cq^M H@q(50F#D!G > | a m3kx(հ"ld90;%Na,;6qY#88)fXCg +\D"Lnzc7xQ-~Kt/6)t۴(ԉPD )d l + ; JmP 3ynΨ iTX@a0>h3:PTМF +=6iT@"z4Ģ"a1ck}Ϧ,g +&K4`cZ"Se1 L@ t5>B6e), 425"^8.RuKi$bIydc3ĤqsQ1'e4~R:уcG "u%AȲ։,P] K(!)py3KMᰮlemeMQd7 9H³D9AF:mT +p6[ѓ90i0O7dawbq+-D 2y9Y +t3ɐ{Ұb m(ܓşY*#;'q \SVdqSeBeQѰIIi +]޵(`N!Q6)Txd s|3i,DΓakqCh(ʈtDiF,p e:uL:Dart`<=r +WPh=L? ~rѸ"P#ౣ2ٍqMCA˥΃衼y%4A\vL9#J!< ;1 m$GuheH,DHj񃞡S+T-)}uMAoih{Qg4쑙R`LCyf +C-.W P4JSI2, t +Y&UMaL8M1BDHh)j^Bq$' .EI0lqA64Lˠ2A/:@hoQ4}R0¶6b- I.x4)*C 6Pctn<%JlQwYK0M@i* qFUX-gԡF຀:hV% +bތ1.9_ +sZb-(Ƴ%IPI,.Z@$KtSzώQ"S,&%Jx 4˓[cdjaO:P[bSr#Z|*q~e)$? _!P0 ["v '?\u`v]<;0GhdS9 wnQSuy6!!#y`(pr +#$L'GD/Hq:YAբS`496}S2' FhX{$B njM>>Xʘ4FŶePSqtz4T 9\&eX&AU1E_6^3Ea( +9 Y4 */x8i0~;s\`G0UqTxDA瑋g.E=@]F"S! B@NfꄃdcR`2[F?5S@ GnNB}KXL,S5u h:-ӶèU\4b=$Kri26W-Pcƒet !ya טCt(1,2T +HH4ƈA$Cd;Z Դ%L,&).@ݨ܁F U4 zyB.T6)60O[c0DLJ @>n /䑙pi?2[|E:*MZ%X6DPn忊bgօ +=X^Ц>C`Fo_ʀN&"DG09A.Gh +;w;CH>W #bӕZTDabtb 8Nc\%ԣQe#H;la{Rc56L7ph*3QկٔU(#%a%,4ELDwA5Ƌ + b^_DKct7lJxѽ"k=6o<]6.xOᥠ + anA/^gp71GxŐb! űܖ&|-nQceyKm؁NT*u*5&ͅF810, ŗ &85xQ:U }&=_9,ږ Ƅo1A|;ȉ#P8 !iL&/)3p%€tcŢCU^vU%>f*5y(%|{fF % ȕ ;O2 <iP8IUO\i::LK JڐX7VYu_Jm/hU=Zzg6iǧbxN*unY9Ǖ?_[NكIR?Lr\ߣXD2SmXJҳ׉u^gno1cTמ;KkҖbfKNRpu|pe=֦.RhUbLb{kb >+/CրGM(RҢ.JX*V(_ +8WoEA-p ֗׬5bg^4K3 +aȟiU6$*1J+1s񏮳OĬXf16P~ 1w5GAXj]+= ~B[]4WYK1/%z*';j,xԡZ[L'ǣXS#=qxbBpɡL5(CրF;3 +q>Ə\Ëp1':Tд  (5-~Eøm1x7zh40 8aNÚKI/_+Ҁ) vѸ;J$Df?lu'ߚtdt zRϯu)ǵb<C5c+c$e[ ;W~GRV&jVGLĖKސ^z֫YhCBlNJ *Ȫq8XtM<,v,%a&k*sƳMVQ@FAY{*!+xVDfhرFD* k]Wa9Sl%6KJSG{%F+"8l^o?=$.@]b=P}@X M}^&wn@e1z:7b%5|ooeI߽uҏoX΂Le z1$XvE+|G*@h((@u"[M + J恉@<:RaU*ڟ^ڟ'?^s0/ +?{?`Töu|8khxGu jfuOQQmbB<0U>*sAa@5E* wE?Z/VWLZ I$$Xe8s` bZ¨aKa5:}`[O"w{A?qa翗g4u[16A~4{mn +z_/GM#?WI|Վ~h'?Puwa8Y9L S*gΌ: bT` j:U˩VТ]l?[wByiu]y ']T@\vwKz%`Xv s{juإ?X{u_~0 븶֠(31N645[#HkaB)L E5JnlkTb5[ 3]5IeL\(sB*{ +tcUM2v4eQ?!͔MJ݂L *m(骘GӲu ZQPf⪨:LTpdI_91_G i4j<+f@Ln:90, Q8"Q{%M`] =%]1!IpLh|W)cdL(q4tX.$f|YꨈV*=fňƺtJ"7Z=R, g'ARp&OL1[ M;QmՈ0ƅvnuJߺ>\^[f{k`P ȚPzu4JJs1*fՈjL0c&'[U4u64D*KO1u$h )>Y!FhTbX"AsN26Sp]G5Ms\[00ڄ3`lvbc`va\ Tm]DPVTր1TM`.)vE9^2T0*Df%fڶ) 4ĠTQ `@[#O5Wlgf.SP0N- Ӷ+GbH"<,C&Hi  SWdp !=E6pY`add b$p)zlDIZRH:QI+>[D_ +0{s1a6ctڄ8W9Zr!MDP|p0e@RK7L9~0ɀ%h apՍH, KaP3PP L(!d;PUa;`'N iJU ړ`Az5h btQRt7"P +EPŒ.S ( +7'f&MUߐ5 ( +1&qAh_}03)&ACJ2 EŅ=tt :(,CO1vMEbehɁ WӁZK 9:!6\ +pk`̭aVCUO$ PG2 qj\k NV*0s`6t|;aS &WwQb@6L4q *@BV*GT(_%e3 E2Fkȼ}*ɂl u\m,B"l&6MGR +%niUn&X镚u0ƶ:~Ei,j~:]Z%(V.a딽Ni.z>zV|WT;e9 9a q%QoϩRש="p)moO_UyիiW%&gǯNwE +-WZE],gnI7_ +f}0Vի~2]W֬D "_\OXH|h5wWMäU2F*nn P}r8,7Pi4dEe_)0ӮI0r#wCYp +~7m:`iGVgJ5 6QeYՋ,M3-mkw~U)[Sn@ezGXY`z@|T,6ޔ!:^tt/tw6?Y=>Ҍb(9juolbzS^yԚ=S/U>f˵. +0z.Awp~,_Tuws:>yya?#Mpw-YO3޿ =VWk u9EzjWO򳒏МT3.fdWE29etKn犀6Vᅥz)jPm\tEwv-8{i ?`jL*V꥞+_4TٍKm:tF+Jj06[V{0;Ůd ujUXZV[}S+_}u*^_K`uZL+j]d{mK3Ӗbk\ `6^"lPz<׽l0yp4# ^4kKтD8sA*X +4jR^u&Dȣ +F0{TxR0hC34gbA2N n{ݖb^ۭ2xWؽW/v3Vz%MU8V\ xsةZkcG4 +~[H4^Lҡf :/L,&A~ 6J ,&_j>q-Tb zgūX^k[1 WkaRvC¢>_EHRӣw?HV9 Y;܃+Z6LDҧwUb}'ˢAiJڮ }^>Pg00̫UiXοc`L+Տm3w3&$e@b"=Jm fG67Qtw'H}ewE $iV+-;g j20LCG]$n(\j`?&^3a4nJ('l6xPj^ެUtIdyݨe4rJ`CjL7(4ڽoݨ?<Ǿ[V A սqA maf2|ƪn;=1D[Snkw3f|(;~p&W}> +,=.yƏ2|V*|ClJVj^#w ТN#cH r4rÀ=z/ЉA(b,:Wf[w({di!Hd4.3b5V[,[9h`ǘp Vqh$kX*AÕcW! Όޕ0YP!5 gr֏xRm|¦elTaU^_M6FÖLhhI@]Dv +2;7;3ˢ(mU&;0SYOȣ0%:g3CV\jMRc 3A7nݸJkLdnhaFxx68gel}2j]\μz 0xMJbRܞ{e)jTitCqz8|q{VTPoMv3 sXF$Mzgs`ca5 A yGq|Rص#?=7RM-Cr1q%D:x\FBwo[U|a1jj2꼢x#F`ün[@^cND VLtp1~x)n•dk渝;h5[E4Δ[_/Op(1pR?CU 88FԱ *FcÐ*h3P=N?^aE1xG+/0Wo>eLۗtZRoR~?|[,2BU~zO0?rxe2i|(9">^v9?/V&ʦ>t3ncG2ȏ{YF,V۫ArUAдT ֘-u2r{g\UZlWmN/)bz/^ʴXWտxXY㥦7+uEɅmir{yo~ N pC=Ьg [ MXk.*^FV)V/}ët A+/8&($f  (҇ٵkX;V*Z;|~>,q忿QA#eXU8N~M}P&Wjsu(ac0=jdJ, 5 +V~&Zq6[fm,yq46fnVfWJ׋Q*j,?7br6W+vZ޼Z?06f6;],hNB5)E͕bӖ&+񎨴>ooY^ɧӳCWo`<;_L,۟z/YSj1hw3;guk_W/٫DI-lv˓ۻy.}9zPk~sn,br4 `?l}~}^OjgumsucSZi-S݉gSΗYjp]'BP1Oqe5g6sŜן_ܝzYTJPxa#RԦ?/vzbc6Ygfps+/DZ4+%qVTvԅeﱒ^YϾҕr-TU֒E/[l7Ua5/;Ժk=,^Vo=uL֭)ܒ[:i"ֳsVeu_QKՙb|SGꅪL$A֋UaU->δmPZYX_/,j5J?a(kQRvן}05v02*ajs)u/b u{A1(^ZU7-ړe]X1#Y鶞rnBn=vUx3 9DOb;c:؟=VϻZ:xݶ2R\O$Vvaugk[͈@%Ƙgng=fNyIi߬a̧3{7g͉Qn\ Sf!$Nǹ -xn2ˑ_!I#!*,W'W@ kNf7ZKcvZ0W\|U??LdJ6O٨b^Q?լV3͚ ס)YA^%s4SZ @eO]zKU8.Jr?4J#BbaSA/4 +MI=׹+ѪhlzLnHw{GPbfdP'?],l)^Fdɜ(SBYK ҭcWw'Ǜ!77e1?W?ޚQ~X+9s>¾^ [ӰO.!Ń|G\m@R)v7d?{db|lAeM pnoL}9۪~}Yhqv`-HQOfefe;{z >&+żI[XVD'˺ϧO/:&w oZ~zeSs[z>#<|r[5ALZqR,x٣ @}-,[O +Qɚzs6j+Ovw ث76-n^SIޫ}Z{}R'}c +˴d0}Y?A1]xTD:gmr\K3xNݥ&jrrӥڃ;~5"7L-σrwQ|\yY5`o/q紺}`A;~K-w.Zт.|S>Le |tvz/PvNZ#+Qj6XS*f9z͜KjL9V\>:ӆIf|br} D?Ȝo T7W[;n.%kú.7|^Un;q6a*C9)&w7b+|Ӏh{t)+>N͜ +_zAsW(g6s~>!Ǝ>RqgLX| S\T͝kcsٺyvO]s*# (4j.ٚVz +de ˾vڝ1r5/K2}QhtgmPkS`"|r.U'~X9enԪ4a5_m, \9࿌ >.z<_K;L9IQan.T5,U,OrtRlU8V̬gDS?ܟ"/Mv&s-?)n*Gf_T62pn3.sA]m&§o+N#NgDr=oOF@\ OEgxl*7WS鹡`-tA>HcS#(${d$jXJwnf(gYm|hnMLh^Q*"|S+-_:ۺJl;/}rox9MQlmG/֮[ܢjSbN+[GpRW'~dݮ>{[Ʉ'wSC=sVn?1kQ&I狤)mnUFWKq +iԺ a*~>H5SAujv q[KBz}yg2X1I8I$X) +G7PwD&3{]鷽ςdSF.Գ_ow'n2Ycvnz3;q1nAuTn1s2Pev);[zkr|P??h 1?L$Қ?9CByp?ʹ^oXO/F=,>nt凅3<Z>A!0JcvW{Kgk픮7sד0l Om`wKrh棭 vw*nz8qahL80'P>\͙Z{K,_J3>ŷ@{1#[1s^>[aנei+kK{U/xOO;=IU΀ϊ(J'D_-'R1б h|9y>}]YMq%30y5!d2kU俟Oq(s]dN[WdFggW Y-8g X {j|;j[޺yl&kS)s轷,MIxGdiպ8.^,jnIW*U)C"ط#}NJ39:>OsNx`PO>8G//#k9/"b;KqOДV]G͔|Z0A}Aqv+QnfHW”)\M**"6xicr7Ր\yH39*XKRX/z2r;j^{$:~q\‚Ch8#3e֞'Oe^Ҵ|Ձnc og^+oye:$ns*IP/[9M7mcGtSXлLψi7yrGRv+*XkAx:]jtp[ORQsxEuT +o@zr%kƨЛtgo\1O +CCr7?ڴ ]ؼxȡJ7xH#2ϋ1nTF_r(_NГ$w ᚌcǦ{aOѷԑao[nzF9J}/Zc@֩KOUթ<)Ia ?:0"4 +ɋY:vc%8K]žj주Ç*ocH[q=(Cn0K쥫v썡s551{ٓV*Mn8H5fҮ7Ðyl3Cly }f&qQ%|AKͦ>\Z!O61HBCH" 4l߬b$_1KK;Up{wz# |TD_ǹ8!5ʘ[P!TYƯqN6|HNb߫|[ïtf>cӭu!W/WO!үŜyï5U%Yܡffb~~)ϕjIzv)u9&N˷ti dL=TEZ~vY|L{9%m/H_bܼ'yXt@35p^xBh Żٽ(~˸;Gi0[%{rwiu+{4sZݘ O2_]+̴緲wruqP) _yAjqȲ*hw{yp'{_<~?^w 뽎-Ȼs7wi<ٶ Y:A\{Z0ƭzNwPV'/ ٔ{rugff]D9RֽG<م[~e![О2j'vNg֣[?Ssj*>Y|%_\]ۋS޿nZzc'lqhlǗ/Jv(6sewkͦ.۩xa3/mƷQ{*gcpca.~;;ɣ1yZ?iN^.'o.S|]M_.KSO{/ӯvo+&B. YHά'Yb%q68ӛu~Y/Jc&^-3ՓL=cؓ+3f-HlY{3ׯ͙ŵO'[噒R3f=vJSsW3ݫl[5.ӳ+'+wٽ1stV=[ߘ%۳'fa8{7OZɵ/N/Y(\'+&ϛg3ɻR%Ym'YJ{sY2[86鹭|w8Z]}nj0[1Լu6^iodUiy`Ϳo{ۅi=.lO򟕧|}ຳP&8=XL>NejuXkGX׫d5J/T&9|J՟ZKNO}:HO_ROJz!{{fKFI]&җv۬/MKS2r퇥垾ba \z;~(+dfU/^ TTv{SsJ)҄qNr"sK܋SRԋe5RǗZ⭖ѴmUk{z>ekoS\[g=g~Џ~No_cHHK܂j7 tnFW =ӽ'ͭ\.a^,͙Գb-|vrV1tf=Zw/53{^ ۓ3`2L29f9ǹ$͌&8ڪŖjuṘwܵzy{v»4Ω'-{ZV+vY^^w7MAze_"wmmy%=ZYi'Afm4WZ"*UZ-=\=ݴWwҫ{|,kշ׵×{:nѭsO^gqwgGAypSm{{ןBQl7˵ϽY:h6T1yI%7>7[Vu|o-}RIU7V c>sbuKh'NCS[{AX9٪KKzEegɭkH ?k<Jv)vvziޤVp޺x[V6}vX~ӛ쟰S/wNN_nv^:nj~yDy:jgA*T$kt|W~TN^jr?>o)syasvPkn9jo>^7{Qߑ?:3D_^gJwItv,?dNStcp%spJףׯ6Xouy{]_xzԶZHJgW=_=e8i/;X9<|;ԯvWϷIlo:^Nm+RAƥ=`=dm |,z2.+W}MVjlf!{xZ~[gX&R[zd_|~BXe r 3/wj~PJB~e$_v"G_`U8Uj{kxR!~$bk=Y(ϗԓ/PtE-Y͐d5{$  .mܕŊ&j^k^)Z~5zZՇev^l|_J]6G>~qBnʵpl=iϮje0y |SXjMacu 0wk=`u\h\I:1H@՚ q(_8ʃjn(|\rF:O:^Nn]ɿryiktt)NkɫB{h=]^^:ͯ>Jk07=\r{NOʢzgu5NkN.tBdk+;pyYLo?/Xº\+fgUX^FN5-^I{V]kv*̏:.:N)mQJ+"pF %}_uٝgiui@:%0f6nXVf,,]NQH+v$|SOI#V\u'ӥ~t +wR5.٫ΥKTt:L7{y)rح~rl̵~puzYۺ|3mReCbuʵ?I(-]ݒNCP n=t +nOD5Wi)J^II6ӿIysni6׹M=B/Fm=$7:KoeV:}.A线K>2No;}_Hx:^n7-A~'x t{+̘Z294߱Ӽoym:]ʤ?cvH'}"p0=czZJCCL?JF# +Sb4he-z0L3j:mNA9pT87:w NOwN nt+)TG)iG碶nw^U?=IA\*>nR˗׿? wiXמғ/ioOO{!Ow{ɏg{Yb1-NbKhYZːɝ3*n4\ .=_<\ )U3字Zp|.y8~f_>KAˬRb)z,KRp~YX ,M.嫲U(\+[^ٗڧち9%K*d~@>}bua{;_vk FT+$fi6.O ,-F9 ,,|$ƱK aϡfZ^'ti{} C5o)H>St,$R8ݺ:^v +)9.Nvwγit-;Ni҂)xh݊N?؝JٛNE=X?]@^`08Wbt +A;VNѦp".Ls)^~@Mh˭l3%1yA$?r&q2eyQ6EuT !~w& W g`R96;scU9٤cO 9r)dNMBǔ: tר!WJ/Z +YcE`W5~1ݲ (8r2Yf 50tH \6s1Gv@}#S 'E=3Ww /=Z?\} +<}xk k[3G5ٿͰɢ{"5.gc))fpE' Gԯ9;\E@{. O:zԯA-۴c]y[n*lܕF<1h )odbɰ{B$K/us($Zf=>P*o A`Kkpc}IeK-A/ )zjz崟X9ZbAt=XCB.PW By 7"m~p'V:1C0x:}cq%j%QL%(feіs{JýDX\<1%ˠ cdl+[nO|]9XQ&L\RPG  ׿tҋɱrк +c 3m Cؖ ک_ox??j2TTc +ږ&iFfUy m:l \n:)P~LBZf fYč鞱.SH\`oC GgCrҿc3|rV<ɉ%`DLblf :w-..?NZDtDH>w[|XY M"5S ɲ,K-ɦ&eveP5Z os;v)'+z,Xv.4Cwc}[\ƈkІDlXip%)Liq,_g7L*R "+Gq[%g|0gVa|=bMȫ@"eJ&@%Ah[vק8y!-U#]P'*n)\v0~oGS䋓 )<z9rqض{ V bN}WA;St+. ͅю۾҅A<6< u.[`hËHбzmHaŰ.0Pr$#lȠE:}(HK 4EGl_x6bc9A,RcƜp3CBcdbF^0%p6^t)HE.0$\FL)Y3̶&;akm&B0OV{ Bĵ,J%O`]> )#H>L26-p!*۳pWesHmFv}pޛC01.AgN G| 0t:7Zpr ]8. .AC N GЁ .AG N GйЅ#'_`"+yʁmD]!X䠬!UD .dIeDzּ޽tV.N̼t +8Gd[S`4@x'_3i)*˘_4f$ 9w~FL\AtϐX}D\q@sAf3]}ٶ$3n tmܤn!l.6uc@"H v8OEEcDz6uj'LCZpM Ɲ3-Xq߈ceDH⹽dHq!Hf$ +9+$1 N}&Q{[&k٘0 ĦтfWFWL(Z O fb@ܙ18!9KY@;v5Ca3{>511m9Fc 4OoAg\SfFP̸ 9 +b6$=Q3 G)H61l&rb ]"t<'B:W.~ݧ;{pg:M g~P,El +g|A|2 MC[ޏ&G,.ǃVoAg-ؕ<ӎdum+2c#>Qvx[ HL=Xg݌RAcc;}HQ>= X"5^xg2d\"5֠ƋCrEzA N)+"%#2^rGdvƊ7N31_ӆ->w(bxRE x +pj_3uDahx)L R6mD;#I]v9csp.+#/u,MX[nazLnL**kٝ0[#e쑈bL]9JJ]'9k;8 WKeZqs^&$2ii9I}}"8K"f&ñ2T6[<4pa<疖AMoՈ ՘ ?c<LuSW<)^lHmYD9n4{~1М/Myi'{vbEEJuMMkwM" iqGHM&Ma/چVj8{B7څ-<6VT~7NH祸Nh"~tn.z>#D3A<5yv%,0|h6d\Xp7vP8c.-6+(wAO߯d66+([F{SB~̡pptPxs0[=ލhGϺ 8%6jufÙ0բ,)$; P7r!QΈ'ٽf0^Q/ܹ' [m9*M.?cq'\;?h/g_<,pϐO ]B(IŠƝ/=W, kQ@U2a7o!v:}r#h թwV]gEIn`@`йN{|ǟm,a7;m.uN3K{|ŰNNa &7o +UV/s!˧zd[5o>"[T~o{ztt1E#J_+I[]jn qFtU߯ޱ:L71Nȹ +MȜY$Dz~$Wf#7i?E2<E\wf\`mdž F+?k k Js䉉#2~Y|GlV tby8M,bvh:VLt3)toh:.讛tӠMBӱt9X4Fzh:֕@QIJ(u:4 KMxcFӱVgca| SXX:"afc/3EEXJ3Bӱ +<Mj*Mqt3XM8&CPlh:.6*6%3GӱtgEcFfca(uFh[ggcm MӯMr>C4kA`VȲvǼ)Kc@S .&xeYW`]DWN!QgIqmX0Y~%v"bH(`iŗ!2%lPQ@Đ, ԖcJZd=#BPUye0tܙ n];#A󙻀ײMzt wɷVϢ(;`91s\er`yWikV4k̜+#ظZh%^\^AZcdĄ1mEǵfuz[db^xeHcn{" +S-SfWJv +cb,K蠦HB[b\Od/e!\b\k=ںGuO myc.}z΃|)^13e(C_|,+_/X])O0iԪ@K7`7t:d&13!C锎|!6*mԪX> +6?./nnBR6cυA':{Hύm~aiق댝V/ߛ)$<swً [+m}6v>1лlbǺ?ĵ7R׵8/#˔ZFlba>m@+IfVǒ03er57^ +~].F}ܖ'<5Y.xqmZ+ɁdǦo=N /8 Rj1q\> + +\džr~E`x,(gP'3xͼe v5}q놿=Ţ @uf~V&bg< +px(@ qQq14(T($yb`\ Gb,gQ>+3995|.Q>fnE>G 5|Q>ČQ_(Ah"]WfPſjwnw£B^;yw_n(ƻ~ |c,ǼywEr"[DrxW7Frwku?CuwXp\qټGkqJ~~7?~$ o%=iŻ~wjwطЌ_ϵ]?^ƽ{/It'\'|ndJ_m9~$"uvo=c՟]?ֱ%M_~ޟ]XA"5wx/14ƻ~L96~dLAoy\3=)! +n)oo 9%ܴx7L_CmK)[L I 7sH o6Ep7]4yowV(ܱr3c7K]m$}/U?}wv_~S- 9~,S0&qwC7 WcXXJ$Ru4)# z챉caќqhDqwѵx/pgw|/(rw8>꿂 +=kg|PݫnHt,*úK}=lv!Md_ۡE[K+$$|wcVP)t3ԗ*%+\#>9J ++'{ՏJ>|ݗ4W^77-w̵׾|r"wF;{{x:"wPnwQmq["r n{i{2.TŶg";J:wVI j>?\\ƒ w'+c!8LJ&RV^PKo$ +M)uwL}ƶѥ=\O@ZaX0%n/s>6\5C ImD=ͯ +5yXUnc>Y%f%r7?|x>sy")#vY'5-om^C:ΑKVvznvo_#^žhq,n`xNezK$[i/|h>_qX-ca)_\p4FR}/\,euauV>\m'Xf?VN7ix,RJ}pzUUzL/V׭"#s@<+  +yQ8K\"e7#*mz`+mPj1lT9(r$O>fs9Wbi]ߞ兵2W m@r`2zWt ~Tef5y&E⊹w|V'&02Z];@+/.%,PޜqvƳ٫\KbaLo0Dch׭ʄHJ +}/g5Ճww:0Aް9.ߥq_ ҽ"t/"5оcUpIC]1VnSHZKY$J ȕ' 4n: +'!?tSncbA/AR^-dGXݵк)οYD(ҬEHš9sQDa%{e7Q-Jڕ'Rv39Lf +s(ߞAy hrH`<*"=lSSC9̃U}Yz C 9$(pWfP`?m@ #\1=oc9a8* 2;Fd5y7GgYLi70ƀ;@76WUqtt\(>k'@ Ā;`-nvyto\j['˧C<;mVnn7ͅފvPU#BmCB@vTEy^ +Ρty+RvNN /K2~Yҥ{$ i6\r_ w5K./Z7ٚ˥b\vQ])|zvs,P0&cc9et*.e7O#)7̿޳Ix5:j-e^G´2XQ,%q.'TMTUJkn9(mmwcsT~VJ['mMsh+ߩT`3L. !Q7[ \썮N1&3SxUrYh$32~BdoV*ܿ^o(|ksm'(a;D*x(YAc%S}~Gv~Rl:ԧ!$CYIUjEm^i_(էhmg4|Zm MvUn~t.ZJ!Qwr،rN eKmQֶ47\L[6^d5gX cl+:rhQ8G_zbѫu&9| +"e +"D\Plb"`$ͬL) Vmb"D\!ƀk>P̸DxuD$T Nh 5-Hoeei͒?P~o4'Z϶j/4e;W[U:E1JUKL%9ru)0~d|Ӎ"` Y/WOhG 殺9ku1I"Mh-SiqX$Xl"BÝ9{!M3rNͧ+n@/aD(;#$o-(tD61yxI;xB+~>x󜥛ޜ<| qIyR[ب~NFIJ+|8~:Mp#U.GJ>iykj돦Ki~$2j(E`^ 2l5qP")"D!+JmV%] XQɿ*LCi +$D.`i@j6@]yF]+5X<^VEjY)B(Ue$ +< +āTS9qNE#DBCQ ASxح"%TD C}(x^Q\SHAW R%Y%"!w + M%.k<+X! Y殃 "H岢k*OT'PKF +j +(QP@ځPvE<)(F +2Y⚿\$ZO߫E*#1 `Qh]G #π*2i 6}AVAZxhW.,GBz k@5&݋-@Fѻʡ} +4U^P`}ovJWP(Zb$ _bl_+%T{eE(IAWR0 ^tP +.b72Ha,PU/"`y墵PAPYf7&A! +hTQ^w@(=\D4s``@5W,7P T) <q5d4{تbf'@/$h:X8f$VclTӭŃ ӹXIAHϺYs|):6p*^j`2o#e@x'b<&j{;E,`cZ(;sE%bQV%JA +hCEEL0\-6ê6}[B7 oU+r*O1#d?ehfsz8k.hYl]{ږ"޲&EЬLrs0Il&ੁs_ "%-E̪-żЅ5saW!fEAea(zCkR[rW%2)uJ]`^D-z,uɖ +8|t 6ٰLgT(Ɏ*wN@$1Ad腣RqvXNx[ yӿg +rs_2M5H?U hVTt~*ap+o2ƄUMpf+*)iDuQ){b G6[uludM=(SԠ(`gb0I`}b9Nih &6J9 +4*`6)A#4;pr0#j%N5 `K7#xٱHCu+`; λ(6`@45feElLZ"R*P$*S)DZjB1 v9A$g7nwZ)k4Ve^u5M9H'+;c^杉_zbDKx +`ۈv&\"_*n-WI&W^JUׄt0AzQ7"Y֧mnIW,S17D!g֪,Lnu0^JFcv&QTrR!ՂD]Ҽ"g^ @QSݎ@uW8-Q# *xpC!,*`)Qv+4ґ+9U@sdV8WVh M _ 4%1%ֆB쐑FupT8<`:/Dѣ:]3SphA饒U)Ogs+kvz+xWwaxY7?{k}BzAVwXx&!l*Cg:BwA jE5iOHH|-zفؗ{͙Pe*hw +EE=KVe'`ŴG]`Y2Fj5q{7B(] 1^K|`u'EU1nY#|7OW>$ynBq0yo$4 ?)bwܿe5ՕfW![Oi8Ց?Eib7 W IoD.*nbG9)LF| u4<@p3u\q0șx76tmJ{_3C0(Z\)5pk+aO_#>GrLp@ciFus 4PS hG5lC#ñ1cPAq$`#Ye*h@xD}=\,)KqbTo sF +y&LddR Ό>7c½(`L*ʪrج"@?c1ȢD T$'A5[Y,N t +&i-n-0cZjZL.&ɥ8CY}!IUL1"&Y$Fry< + *nTOE%'Wxf%2*g +(VT%IJ +,$h+:G/%6ˢ dz_ bLJ,{n<Ȑ1)\D]&[D́8 _ 6X eWٳ^ Y4hb %Q E#"8',8j[ \LnTp!h2cB@ &>#"M!nmMQOW07&fT6GE(Qo%0e C2O39= !@( _ x41th82b L pP1s97alWE {va3b~8`!3M4")y*nh(|/*0;%g. <@uMW1#VW,mh ]cʺZ_^.WSaB%u櫄NQ v+s Z J]ED)a✢P?}Oa.H2L-u";C0*+/,[%n%.Y;8N29]kz1SgxX U,w. 1v'pOf%XoQ@ nB/]GDP(bB4m\DLԇE +@ð%EgN`TA!fO&vFh”yI `X`hm!/,B (bR4mf%~\GoJ !a6 )Ȯ$ы +Q-o%@DY6M̀ZfIա<s{AC1҆qaָ5ATZ@L꼀>2| esIa Pk&FBОʈhd::?w V+NnbAF8YM +>I!id]H Q*#0tUG +aqf 3DDre[M0]D `x +.w弎 b1*e\ -l В!v[-/X^A&ksNh/ Hb<{Y|2?B q!@3*1?O@H[o*Ƙ݄Ss|oM-rȆ9_A7w*mLs B,s| < 8x%7 + s]oz!3IĨuNP7Su5SHU:x^!? ? 43INO[X o["߰; VX4AU. 9Q}Gߟifi-.BDӋ;PR5'aCFg}`i!b?*orPHRđG *VDT \Ls;Yw_2AXGA IEi(H\#k$vZFQD]G# E +.%y ZхN|P:<iJw(8ؔNO !PF-8VP(x]e0>Knpa;:G$LdZ*5-.p`nT _-v.o w7F  4@̏f@c"%$#M&)ĝpD<ޣ[ F~]]4TEAcG#A:b !T +B'P{𹓊A]p"D\HRx2SVAЩ`֡WZÑjHVR3.+e:ShGh7F_y{;@g*;T tq"Q0:+'MEAˊ=EiZ7;E4xUA mjUlkmCHrxM7Kjіh)tj>vJ [!A\Y,S3&PװmW[R:涧#Iwm|#bq-I1 q#BdKĢwDf/Z +`xGmU+^l D٩IH^'Fwpcpj?h}1êC͊H{F7E d=2XrU!bPȾᄯU.( >. v7Vςx)g!X-(:vXD'be0'P9s?ggV(ό?ê 06/ةPsZb;U ʪf " ʠ%|#bWV-6cȫYsW|-1Q亙y: Ļc:Xxy t쀼XQHgkc:찼'5TFo:GzbjHSbwTz" +T:՟BPGJ{П|~?RF*p endstream endobj 76 0 obj <>stream +%AI12_CompressedDatax$u%?dFmwm""35\#%IjL6V.Q5ꮢUWSy=\?""T=-N2p8s/8~^~Wu~Ż7oqз_~߽{˯~۟\eo_՛׿8xw7yT>믿{޼g?G_%*o8_xůWo޼{c0;\vP1o~^wԺjw7߿?8|c>|ᒟ>rF/lksp>"b 4G]y9PJZiyWKBoۗ훯^~_~kXQ5t@y3>g?-߼{5g=^e'/'>x7X^/y[.P^+?5?7ߞMӧd,o`)/Ͽ׿Ão4͛?Xjpb7o_fߪ~oG߼}L?3 :`uU\w_~Jc@Zv}?)˯O ҭ߾ +6v<9ԟ_}1r^~換n݇7/^x17B L!|xc?lzƍ^K:j>}/޾㿼pzwr7,}ߨ_S|Ɗ[b.xwmN\ Ȯk}PW}N߀6ꛗw^>f+'6{^&?w[!8V|G +ˋ?[:LaU.N7ׯ!/C~><=N_O8_ӹdU|O{~4RN%J8P||Dy8(v? PJ@(8}7Ե&/ + f\qFCs>`ZjC/J)ʜ'Tr}:MWM9x5b.!)4(E9@~Ry1>^hQv+?[QFIs/%^cӝoiy^~mҗg}yT~>xOr~OOyeZge F䈥rX4e%`*%P\\KX~ڰO\'6CX4G,3VC{t8}K +L9a7c_=bjcElGy@y䢸w(>p6=^=^}.k?`iCŃ_}yzKučk8GFU6{jĂm|'٢b0ž4:z,<|X1#ڣƎl. &e]tbBG % >9H}|@Đc"%䬯qE(NZ_=%izP!͇VC/1t]SyƎQ"ۈ@=6hx\ +W ]Lz0>ڳ6%iJ8@pik1ݳ+ofѴŹ/5 +3ݻw#gܼРK<N𸭮uuΘ7PSN\¨웙Dv^7|]7y"嶎h^_Od]$nn؅og( B)4) ry_H>F=?N2# +dIt>ֶ-WeǾΒO}ز} H~W}燇{HNLJȐzF>C&zptDqAxxb[DAC0Gm'ikkiYW˨QKR<\giYDER&G\;ԥlQӰfZ@B1͊K#ba8,- W"t,,%.iǤkҏ} |^H9fjS'8dc+7lt1_}(L9_*b+~S®u2RJR6J۔t9ol?ctLoJؕ eySQ&6+]9oZ&9Lٔ,E*)g d.m4ij4WIlI`K6%e]ٮ27M-MjP'AEmy]w2K z}Z4hҠM.РRl鰬ڼ,̶,bˡO}mJ|a|l˥Kr1HttťﱑX\(<2x0IB8,ڧϷL6\d2s2v"ɤI ɶI>YٴYSy9Z`^ba#}3fCrlw.x~5b1d@ksKS$H)SV 2K&?eyMg;̲PrDis7~?|/޴ş5('Zi2˦af~2Ù.ԅ+!q,A6,AoҥJIӄL,V&m>H%s[ϲ{Q79r?K!22T<4mɺF K(Q L~)[q_|Y.|S^I¡0a-LZn4,nJyT>/b3JVҶY4us4i.l//˭Ʒ^6}9mup:nB"=D^Sz*sJ(;1-'يkGT6iNl,TGͷ=4@N8 &@uo-'ȸ6ȟԏ!~g`}>N=r}ҧ L;4pcnfzFk +F6qŨ.~^˶ee +};W-AJ;.񲘒(>ǮV&xͳkQ=,qҴ7=vgxn+Z +:VkAv˪iF% ̓i2Wi]h2d* fiAAuYG=.3ÞL~9imN[KZd%s=Wv1ÈAbali.WFxXWSj^ [b5dMY,S_[l {S>?fӲ(rzedc"4Gڊc6&佁pk"=do" b% +Uic0l&872ц8 +gHt=e0˿fT"W.A@I29]yMO>"/x4 !Hqzgz %zK螺]|/e +EbiHǘK粈D?=xx 9.Ó=uW\g9Ύrf6gv۸՜چ[mi,áv.msh?vZ`y)vW඗& nb*"k]Xi&lT;DK]>s6wUfPs6ivEb]YnϵtCe@ϕ3u<[Qg+l◹uF*&N-y{w>W,pCD]=i}scsxsMz|M/PGM,!U0DFKnĶ,*Yna1ȊqԒxo( 3YSjQ\pba1t/tzO{pY:l\{0~AnŇj->!XWlHN4ɋynQ};PgO9!7ƃ P@;]VOavE6qz ͹]jg\r9MdK%L 0\ZzjE45T2#w< JKGQI %`kD*'fvJ8M֋aA(ܼ԰>Օo2a"$^*bஊ[n5 +a0ӿ.!;խEWpӥ?s?LOT7 ;GAyTld{p"1*A.*(SѺ;/!xzoKZL ?TL?VFLbf5nvF2IѴm#9ˑ{`}&,HƘp^:N~HeM醷Im ^~*׼{ ?O?N)e2 (O+N9 <,GN +K`nh^AbXn Uة5jfXJoIwVic&J7va)kw6wyD:N=\a!3mKtޚuqgsZݺ:)˲7{Y}q]go%, 27㓥=m~t)e_d+أ1 "Ad̸$CS:-n8`v)Y^8p(o]WGy_c ?`e`iӒn){eޔNˍ=Sխea_Ϸtç鉊!nBnf^&[WK[\00NK Rj|G"eӍTIy\6cdɹC\/GR.B.4wO#>G6}l9sdȦϑM#>G6}l9sd?A:9sdEd>^nFtSO^yd]>JZ5h삦7@>ʳPyثSjK(r\z0<_[Ib{`=/?e<~]`Z>wIU7XgXOÌ{QHVc0QxBG IEb5 ab}vCG&6Fk NcDB'0YnWs&Q<'VUܘQV/5(m ^zx],E|Nj/2z y֞OpGd`Et,q&L  +7ןLGrQC.. Փ8Ԟ +NOiK`ڀMObV X6nzYϵQu1X{pɶt e1Sqs}|%-rW6~GEOi)o뿙gN=}D<탇3-G]ΑY ySиU@sܬ'tw8rڂ?9/.24cs;ˢ{Y`WiNx@dLi։!dHM(b퐐A뱌xr&i1(ZO^'%Z| O &Q~|;M7li ` vs WexvYkִxl 9cvwn ZF嶃%prrh5vXt\$֣$|P^>>-.NCyt،b)Cpvg Lл|X|Fgr9^ܦQ1!)W((bؚRβ$m~st^/xw#ywy3so33'Zqj}z v }?xڡPW5J/{ҼtӁt]?u)y)iS@mE 2`nX/N{Q$gMzΞ.2]1XM0,W`琖{Όq|~3EYQavЁ'X_wx6aAlqKzG=S0~1-wZ!|Ó]0sˆ7ҹsݔ0 Dl nIFrFz8j;yNGy#Q~k;^Ͷ:0Yum҇Oܘ?5 |\tPؑjug<4WoQ,)ڎu8=~ ?N;FY1qZ\ubmu e@J,WzJӕ"MPŴݮ|H8qnZtAqp)[eZ~m*LwЄJقw4t'aרA~l͂!DZƁ_3'wb*G6~Q=[jE)U2]WBSVU񎳹ӫp7QVë16 + l=!ݲ[tzK=p:HohU|>=r8ߺU}}l +um}X]Wosw373Nϋ*:xgFtiQF8F6>׸j$|{pXDgь#qq@n%?*,Bޗ9#/#q=kZҪlcw66dfi:]X%XȮ2skVӴ&{]wEcuK[Qu}<I t.~n77"arи`8|M>mvѐ{MG7$!`9;x *ldK㖑l㌎UVX6 b7bYt1)`MֺȨV cN _y~(N3e8>ωSYcG̮Cz:~Cܥw:_bmlq7pCJ\1M (-F:p"^tR.M0{F@Q.ryZ%dx>tI9>s9>s9>s9>{?Hs}9s}9s}9KD\t,(YMthrȯzN\9PMX­tq)m5V[|藇1pc?R6mZHlH<,*DYǞ>bMӒ3bE4fIJ$I8m`ZCSw^9rO1YXZ~v))ܖmz暑$9o|Sϒ#l\D^uqbOS_c)܏@QAXAn,"خsL=cdJ=Ⱥ,Ⱥ$<4u`ܴpj=qkY|>]v%nzrZ*?aΧ8W77>tPCOMq\ZbΟ>,z:O͹^iǮ:ЛJVm%㮴,ӚOBY't3O?ɥ\3k!.08 jћ]z욳24dlTg?iEI6a2 ktsgi[zpOG~J]B=y w6]W7i! ]=#fۈ:<Е:$[MeL;HK:,1Bw;JF +ϰPY<,X_tֲƫvjv%j#ܢ}!sҚGz6>{x+YzIcjg7'ճi?{4wf.=Wx~ =ys?_)}h+x=M}6z`-mFl|_jrKys|W3>WO>݈XߞeΧ-~co tY_6JLo֞D;u$)1!E + UIH!ރB_'،Wظu '3Ig#>ITJ>]-TnA>ӭvezۮ^#'ҳuÏy V>wno ]ðe9OMHTa# N.ө5qф,hNk*h`Fk1"!CܐQ! ?cX唎mqԃ>icW%(s\8`z)O,:ܷYwe"tv+a/{4i@sےM&Yr,pSh0/rxV$älrϕV5% 鐦4[ꧺ,i9HnGIЍqB _8n:BqW.|LO)~ǔ'66̳S\ddu)I3Lriie͸i&q QY`.O;NWG:ygɲ6]+FoA٦'Hޭco}.ruG>w8-wmÎMدNyWOX{4<8Ṃҫ&j#6ia)+`g ߞ4fL>@q5˴㢴O.L>jgcũ|vL<ɥҸOkcO+mjy*%K490 _ȏ9wȡh5]N0Cw-|>.Vn\b _S#j5Оcѻ8 1UH: cC:ʰJL nۃ}zƮq#]D4]R{ 󐥦3=rm:% 0 =TIy dž 6B=?4¢ܕ9,{Yra.4UFJW:+g.\?#R˿}7o_~bC5j~ݻo_oZfC7*W}0 j30ē4[ Rh9*YQ?쏗{z×s|ڮ-ߢtխVW[w|^w|}|W^yWӛ7~ve_>|ݛ_^|/ꛗ_W~~?pQi,ƚHi.`,UgoގTP9&/\*W˽FtVS.]"VBFa\wK%+a=RfEċUEr"+zkwxDB` pPGZ:D0|#8 +`+޵9ڈ#"V&  x\*Fn\8 AU 3k1Ǫ.rj1d_{\4CY^˂[EWo|@jAju0x-@S1(ggVLu3G;Cdϓ=5,L ~T0#CB+#rt ,t@w` j\̐M`πdgDzb$S<{\ڌ r`s祆Ҵoךti_T@R@6[wԡBm6#(wfl zȁ{)s`/9XVvM)Ib {=l X,-CҬh*l| hZ߃j^ y.'REաAX%ʵJ@&FB=bd*eY @dm(Nu5s;bW`+-t`XNK;m ɱȂO\{椺n;PQ& + +K|f W(&IDMD$e, ެ, ̌MvJ{DQ'?)@xώ+7yc&`7LX(ѝjگx% xp -e e<26 (<'6،:"Tfp1ڏBgѸĉC (-hйB j1&JNY+D +V역x x'ZGT8#6`VMdnĬdh'vDk$ `b8Eh`OBF;I" +cUWHT|bFJFI&` z7'[Ƣe&OPK +?A]!UJArs>*G@HfE$BK!n9:P?3bȠNxhlPgHВ㱉F`.Pl7rp#%FLg3)F{2>40UҴ$\esSyd0bN;x}\mXɣX Q"3α3o~8%h^P jg+M%پśU2)sF +dD+pHwx#T|b2/Xǒz㛢TN5J+")p5FN';dlJ^}BB +SHcb>*/#}'^W@i]Tb.g2H1E4ʭpGo +DOGk~3s V5/72u0J#FJ +t*WL?Yeb&Œ,$J*CZlڣ1}$Hi/1q=Й5j#xV +V:JȘv#- |ϭoXTͿ(}18z-H ݭbBYBt@2qOCX0+5R51In@&7XU,ۓڻ˝#Z YX +H*[rl1;S+sGs'Hn!Aw``Y,ԑӳTAبȪ86HG'R(`f)T5~E"UȲw +:}$4IA2clAʗȀ.t*u|Q6%(vM~H6nSEJ7O?OݨJ)6<ݞKX;V`h ;EН |& }Fr_xF,bU38p5iFIho i+6Fb 4aWSi/~M̦s+0MA\@G}"Uh L>d !ѓO3!JLh22jgMw>QI5%_BafC4YBZˡE3>fl'vdE#ĤFaghECLdD\Ղፚ -wJ2sgEׇtGTDqL!0y ЇXЇ)qF!B<3T,x&vy}Ł>L jTdYd5h3&xO KlU˨ :D{"lP ZOLlCˎ62]oVQICkNũeBkc]/w QMso;iдX{Lx4Gyfɚ/:h9RV;YfXd.Dn6s؟-">unZ)T0L32p<=gitvAʔZ<%bqV?\Y!'!%zZPV1ZGs֌Rd,XD9 KhUwZ2}F?|AD&~IUUjʖ ~%FKFPB^>u#x/9 'Yn k@y!77ऄ {^<*hUS +-[99TEÒa_Z07Z$R>%rʀNb2U$zpAYrapPv'\ Lhl;5sUU4BdËq4]} RMEvLNlhxV GԢZ#IѤQ~JKъ&1GW]< eL[Lz! /V3 "=0-[C*R|*B;H dӛE/3JB|bDbJ-Yɂ0΄[tЇʸJ%d;v-gjR+tlT"c<ЮN-\ڌbåEU'Eh?v`Ќ>CБÌ4)Кͣez==.g OʔԉPl4\lHY5#S~a_a,Z'PHB+B˭E:gÍM :pMuЭM+҃MƘRo[++T 7PÂ~ V8)̔1Sd"C!>)lm2<{yA ZAGLL'̕ dvx4(T"caNQIf( ]fo)`UdDMGeiG6Q/Eyq In/TC)vY UP`2 e,2-ygj%=*~_2 o-/zaq( eR'3 M)j@L[΂ w h<P$d̠UO('+ y0qFch:g c[ ~֘[4*Ąn 5d+r:4ϱ`al^qG25 Rpjb3b&ru#7| KGk+RR(UF̄!ŃD}D( +DfL׿{?~v:o l=C9+LγT14VN*HN1e{Y>bKszabՖ̬`x*H3 #™*: tU +r€c3i+J/pB o&[sdXT։ ,B*F 60 6asPuP5K +#5.*3ބɧ]2E8zJYmA/B:-S#2.'6B +PQ +VX8^ȵX +aЏ%4PgluB&5KnO?]i J0.af +73KgIJZb#>,R0&0XIٛ m7f849Z͍pM* ua9%˰?ULM[RHoIb|W): N 2LE7ʰZH#x0^qF[H#4AM,9("%$H> '!p5 =@K{@;o27Q%t_c&W^@+`Дv9ZP$%`>`I[ + F/oQytK2&3g;*Gf3F6z6]󢻛>ĢŘ6&(\u̇"a!ă o1Qbd}\uJX0ˬLݲg[2`JS e.KXQ W05LH%̉e +t{\ 2d,L*H{ ΜLy>,J@$hnDꑔ%;#)T +fq^|WJI,0CUyHÂ*Pae 掶 AVP_nT׿tG +S> +Md&bE4oYq +$3_DbU+Aޣt ,12Ջ5WHh-X -D /|$Ɩ +fK$]sTj AG^W)3rVT+$!b-S+A\(eJZX`` b8{UX"T`%fgI1E00T +T3Lψ-CCލrmMۇ7 H0oHM*L@LoCLf"mYhFRUq8(nbX;5j 2g @=٠!dbOv`gw,LQ-|=9Ue`=B.zXSkГKDmK&zV ֒Pqg +kx0Tq[#K ry;㗙mAYq4gJ+YO'h'{?H}.h%F:Y|Oh+ K8= < +1ptaHPwʙ-c̆պJc%jK%Ixlzg0 e{E'ALð} PwS ʖ7ゎWg9M?W #*2C(|o'b5HwA +Kbyy-n)ͩifBxQ 9]lexMfyb"9@-$s Ac(CJ0I.XLjk<¢M mNJ&R&@xׁE980J4S0BKcZBR4YE0 +Vae(bWf7=X#;.9])h"G +/jkbS2aXVEA7)B(,e>RUc"@G1l_ ςrɺGoL&ٚ-!mM8>ug-apg(R")jcl$w4CGl_EΔ| J>؇* {髌JE4ࡠLB +K+T|7#@^^#b%dJJQYA\SVS26Xd;$oz +Co4M2ޝM![b ziW_%$sRhKF#vfR&H2bb"L qR L9!([ d_㈸ )@%ͳ9eoD تrM $2 +e”f@P?@O8s+͡c: +ĉ[i)4e)FJR-}cƍ(cxfǎS H ,a#ek[F_2単.ăUH%c*qłfH`Psz#țB,HCA W@B8&j&(kKedʬxJ(^LJ-1v)|6 .ɬSlU]oz7y4hla=R q4]qOJ;X3yn'd#0j]XW 敦Ce2(AYTЉ u!N MUFxQƣHk@SA0D٤4!Ų{I1–yM˃lei[ +g(%ZAA69]9ghyUJZt܈B_+J8SFUBl˼MC Lu/^2*ߟBYL.o3ȈG_L3r("yKQ+}Wo#l 2A&ja*c.Z(#Z0V#"f,yPL Y‘{ b"l"al`k#'8d S+擈|+n,YI4(Z3,}|I )Ek"9ODVu8xdzU;f-C3-R3zTX:?3)niw8!Dő@~Q8Uu2 `v42Ed+#B2TQDD4V4+隒_GLU@ˍfۍLQSG15B`mI!Wv47CzѢd.R aM4Tđk Xy:El͹BL4]!xFA)a6MQ((YIm̷548WۋК\0qf +h"̤V LS{JCR!]ts4( 8Y>" }?UXMɆaZY/BKbe,ڕ!DN3h(1rEB̮3B`AqXAvfg$kA7QAA.00VT +h IYgrBc/'Vm64db;u,–d$.7GZmReH!t9{$r|G."&p~'P;b3@ ",IHdx ^-3j9`C(ި9$o _1'cdvVd8a*Y_M'L +* G\gl=D;˚*81zՔ?cJ.=XhӋ*GJ(d1B'w#(  +_s̱I8F j)S@a PvVkOKH#Z-,fR~BS/UU+lۑG*_U\l^Q&3A!C B`{; (\t +3΁_q d:Z2+gYI:7񉌓1/>2(KՊ)wMVblE& ,1+)_Ϲ-]~žĞfX!!|}=LM'ѩѼ bYT1yb,sH)i1G-50b/ra2%Ĩ\3a9<ʹBJyXT&:T; +CCx*^tCJuʧۺÜ`! +\]BH|OH,=VEZc@𲑂8VѯR(&~*]PhmdK D#-;X:&/g[oTkD A:%IsJ\uTL_ ٶqm.K!At`ʍzU]W)2̿,EmƸ2H¹* -\= %i&U(CS2z+#ji1*\V +kJBV +D +aXA'9D7c'b.iuΫB;>Ž bzA +䃞'>[wV\TP4όTdPŒ,4- ?;OIg+36FOU]h :|X.='> Cъ(G.IfhOI'#( bHZ}\T<'r1Gl o`: 92)ߺM1T-7(?ٷnAFB}hǤ/0R5d SbmM3.η}ee}5ǩ+8E )PXgWxCT@oeGg:ȽlA݀U@Eb3h`(gE?kG56$ +B bͿ3j5@ͣ!qU*`<w'qT:!7^ EaS;t k@dV'o="2ދ0I  4dy-Mi,ktN:xHg=_tWk;#Wz4|U0zxmT8fwr"Jm?O++0RP vE +ӗ %x-H.I@bt1Cl1;_0=y^}xzIH:Tt?9CJ㧝 xW/W:ǵ#@͏(')}Џz\'h/gt] l(F頤^]e39S A"m + P0zvşCUۢ!U Xp榛QT1F]}i fQK =`!_CCYwn.Jzhi8ack>^p"}z-8B/vlB _MԬs_4Pyj Pb=)}F^,UӠ, XoUx>"#qz`Pt蕱&(To G5o_:ҩ)(X= #R2붎.F03W3Д[QG׳&k(d%R^Y/>L7CIb7*W&"ʯ0#Zd*-ኯñܸ N;/qFZkTs+Z:2YVX1/JkHQ''Wﹿ1lE̿5'!I8C o4?Vc<<&}[ +h܊{0c>)HW!.A)ˀ +CVKcO_Դ3"ޚr#\A +ebQ n`4T 쯔P JLdjP̰@YֆW{E'ʸ8@q=۴C}^y$2dv+^h=!e8) +\O$*IAf@D~ A%^*<2Uʼn Ž,w2NyI%h޾bY1pI,-_`{$$۶ ڳ$P*td`}!XncW#.bd  ArHqȌvb"*|SV9sQ9Ԍ?&!_Q \5zWjrfqcy^Jyy+57& +8OMCYADT;C{Cu乴wl Ek*w; ONeEacƂ&TVS DҾwB?Pr!dgSU&~Vs߁0#L䂉҆PGĔN+/"Ѓ&[AaNJ^!ԑx齆L>QDs8o*9[s,=*qY>קC{ȄеM' ̨"k/uz]0 4Dr}Ѩ_8/ pTݽ<-j3t%b+Uvfd*RdsdڭYzβYQ ŮJ!yj\r^ztJ[Mq(n9vh̰wrm|&s35Ã7nG% d0͛ +H]؅w% [ EvE$FB6%.tVjbt +pѷ%Qs?%OIO-qQ ȼ zu'_ᜑ(њCBfC t,u\YqDLrZC%RSNNWmZ 到O|K~HK-;`(>EIC]<pM(PƙS&L)FIo!5)M{8] >˼̷6rT(FrT(\- 9y2ОKC;z[%Tld|C+nh$$jCqsl2yM.undz5]Y`*jWe-,(/bj2p9g ZpnI{ Kr&0Rٸl[$ +pЏiB/`PF;AI%Ș>(ֈyWTbO}kG+=@,*Nh{|I4="NB,G&vEs*/C`p7VӓAzvn a_7a +C=S -I +jTG/wr9oߒۓ3JeRu:c&3*Ӻq$gp e|zYMp+S>zr/Nh/͐dfCgi>VR.ٙ紶&ǣyS$1ާ.>AMbKݔ'T9O!$j\wP Qz]G]J0$g }In ). +s!ΉĸII] +:JͺW艽5| "޾ +b;. +ÛD^VkD1x*lMN1PmOf~+"rB50ˑ)mUWrS{"f>?=kX^]p/BB#&a&+",%Z bEV7$/G +#BgCsx[ Lu܂0"@]M|ΟkOt|mju@-G]*,yePy̒)4 +Fr Qh~Vj픋xjkuQ1 ,naZ'YOޅ+.[kVc"4QexDN{r67ϲ'~˨Wh\ԗ/idB*_ysY:Mἦ Ӿ^5q<'6y2L&- fX3~J쀆Ci5X}C? +\ 3NCDg!TENƒVBj@^ܨL&<ʒ>Q?DŽoX Ƴ$"}ɹ%WAj.2VՈ5VD;[ qkN96U"hGG: udql4FM#?,A`I=DQ7o H~C VLmoYD\'l´֣q%tB*+3lQ^-SRa׈S}Hk[p ȐIjRneʆ37BUw]Z?U[hcVaPfEu`GقkFK)'rޒ&755U@lmx JBvQC9\>+C @G9̧K"bsk1g;:vh2C1,paB+ dϤnoI[ mWT/'FN +K=既ǿ???__㷟~so?O˟:/.~7X`wOdB%)*hᇵx +2i9)=; [8\%%S+ "-P4 +@ZD4`ҫB169! 8.l4@lecjXKfW8M g(PV`q섬e25:amfS}kavc!W`GDn.Azt$d +KPė F!0UD2Wњ@"N[(T`ʂ!^M٭/Jm +-6 ;^H}BA)m^0Z׬Z+*dT +1lO5 %6Øò c.tؘS~&v†N "!h~(=C1`F2T;"D(U̍>`-mSʵYR(7Ç[a"҅ 6ÿu?(n; jw'WU5@E:?2'@hH<۷X׏EE Qn4d&.{f.( 0񊯇UWS<+p63Ӑ{S5{[*HFJfG!ܣGŻ'Gy@Gё*i_(eƙ%!R#vg02 +7Z% p0~I3;(ۣHƜw^͊t&{]&4Xа[v5ZaF^7X2Izju H^iѕ7`CME7ߒY >uBPsGwam&FSxFmW_3grMsڍ+H^!ȈW36B,t6FՏuו`7*;ʬGzE_^`4 (ԆF9[tj0OCu@BE2ZyZ,&_c'z +fX2{>ydE⡄:t!@(`࿗Sp/Z$ʔtZ0 Zٸ&]yWm -|p"`@,q̥udk]8tc< b 78FptR\A^rknaˮ~gd| +)5-xD>5P_= Հ)h= KwKj1}@ЩrXpEls ]./g(x5{/mAiRodZDټz<a}Bf^zx#?ʸ:/.RY (0WVm:vꥠ0S +]VMZt=3*q`;֗okp`tg4Q|m5m~hN*2׀ƥ :2dS}5FOCܺ}vnjR,   +[ƖTUv97RZ)a $ݷHT&[e/JX{d=upllф[-lx<,JxS"r, _fHN1wAXQ8`dn0 +pbmk onZa.}~yΪT$m- vɺx!0yT>7ꭁCzmEl"!Đq`U;4h8g~)6eXA"pS{?ZRlx=v>]@v)VZl*w +䭳$ +<{C#̟vƦ3Ik5` vĸhMbEi|v{㸎Z Pk<қ8qk&i+a4T w0J3t{S@>c3n~`Z f2^}Q6#+ TqAWJLh(Fj 7gBc}^Ny[ Vwd\ׄRCdOE>$ +EeOoS/:YUO _0yZ:ޖUa"߅,i{ÅNKdzoΖ‚-p 5.5%WV: +Zߵ~)E/U9eM$7UekV\^`َXHPB/} C+5*Sy8! @V؁,wQPpɊV RS׾AL2Dh%2k/l .8a|8,f֍kv\a5._g8p!TfT!P#{B9e JQGނ U[Q\*DrQU80mˆ w +IGv^ N&+oԶ7FTA*ˁ%"tGqs& Q= %;lt{Hs+}q !X)$z 랁I`d9Wę.Hv" E NNt6P`v]Cwέo-N +|9vhPzja#67hZ2[J}[$TlR@(=DkO +wNa8X% + w @"'Ae'>xZgv_ETOqFj]dɷT\f;;fl{(ύw|=DH'3sjJqo8 +Z;e^{]/LpG&4]EMevW#?(*op7קY}ՅA(FTL lDF<'RT2sn|=A(Q."lG']&5[_ +ãHۜFXC_Zlj`{^<"/' bWvu"a=3P8puC3zjd9Ee3 1^=SK 2R$`DpE2`^ЈS҃}ǻUXdPbf\7饘um,k/U;fkR,1SY?0IgpČ vDI$\e+SC~ +ͼ&W@Jf'9-l)an FO PRI늞<ka AeJh~}&/T6?0H,5xkf@/Ok0}8R32 ]‹Uv5tt"{q^g|(4_ +$O ZL 0U\mts6<VI* Tf^_Ż@ wķnu+Vy׼y8',T*9L=!i +FIrUih(%U)zA]@W` c-D@!Mh) "Q6mmUQA +EЮY"N[j8h0ʚw5d Cj$4H$pWks +"鶸LQ B횚 勷^[,ռhø^|XOʩU7jpOw32^չD I\>MKP@zzN푉suHuN/%cXOa$S}Ÿ'H;E+odQUϡ CPST^6S#'ԥ,ժ,P@Y w߰N8fF׌IhݱT ă#<Ժ zB h.?3Kֱf +&,RȽR PFfҟ,{1@P6. ;kYߑO[RH9~mM?DޚDckԔ˲=W3.CLHtŀ'ۨ3o+(b{޵/Dx:@B#mȴ{u j$_unl~!QePGGPU+gRSFjzV>gK&}P#Nd{Z)VgU1[` skb&_1Er2mGc_m0kϜQ6Qǚ\ +>%p+H$~'b"Zܭmy0[dD2}w+<ፁCˣ攤|Եg+ʙxl[eoy+|V>~j)$U:A1)rF< fE uH^no)GJٙey7x*kSCK"qTL'YI iYm"!㬕oD5\F߹Fz=+@ k +mr*R\̈fӥr%l9=KФbr7j7:.EP $g l׽KZō Pp +NT7TĦR9 M҈dUV k1 FZ4I:[YIbJ4;DrfFFOFfc/i'=7O `1k:0Xso`{"ґ?qx9^l.k.Ms)rE}?1Q>h;ab +!(fHE +;Khel\[19`M4ڱUQ-^ +b>Xb;b-iܬƛm?_KYd8/&{zS7*e} < +lO +Yْ(/T!{\#[ o&.3q`I; !]25 t ^D.Gu? ASӀ<=I0YB{yp#eIe^H+3A1Jh!Pymx*,E$ ڸ`BxCمՇ5|5 G+Rfw%hA? da fCa3 +͵֯nN*"V]NCvUUzX0ޭHVװz ^•Fm_ʤ=`!WEqo\s"v8tbMjWכR{v,iuGi ]vzByyk;T3@nF$Br}\OW^k![T7,7 q,$JQ&*$~7x);+ +LʒF_=,0:,KlTdHp +QߢΣWR +N$:U+s u πT[;䝛z'OƊEZ)TYrkVv!1{R"[K5 Vދrˈj(K^€8ŠcjD!ŀ }8iۿU=VJ;yH K>jEj\UAqʁOZS.O5#`C@}"?D $ T6EjZ|Y?8< cJ^#2¨k<5SD4H=dTZm{5WV#qFes*3JN:"[oX(BdLT 4u(CDooc/2VzĎ^ +@P5l\kc.=x2S`W0aͥDd4f.ydB*t_n7l- + L7!^5G\v0ׯ<'3]p}d/ "&vrgR\YPbc.[%đ_Pfs/ݲzKnL%$'ѢH|]#ٴ6◮` l 6lZll<;$B%1j{g ɽ' D~oۈ= BxGQ'݂G+"SΑFilJ޶ϋ0CB(M@nKX$&WT+ʡ Đ]!d׆$F!J(/b  Yr cu9QeP\Fm$`.?lSl8¤4ZNnG4¢AE!~6ކ70%bۨ"8l٬:y#1h’-@u\" !#<*`V>95%l=! /H5v ZC1g>jDIi("!cY-@mq$*Hv1\HyS^F0R'oܛ@\AHHrd2~k n))LOW|bC u+j]$_Hi +ugfm+8Y3Sx`1Y##kKxnG{x+_2[!J1F}? LH2aLjnGp@Ti'݆sX9J4 "/U]sG/$r)7ZyxE:l+~.C^M*ܮvJяTnTNS\YngE8F,*ƆT._͂ĝ\l6d:62R3z=$Si8PYfrP\!bMwY4#}(%ja9 ׼ȶf$I@4S((?Qpv*3M4({Ea.HE$+ rsҥfFwx쯆(G!Ӎ/$gHOGCD-׭IםRd9h0$l=# +eYo)_ةan09IIJXtŦ)ՑZFuo!d^ź $a#%Te>|[ k%@>tiڻ% V#69Au5A<axiNWzVW޺D%<@--(yGsT-Th|^U) + 7 +;7Bѩ Da^E Zd.( R#5ٷXH'[< Y!{8F]m9Ƅ; $QrXK?9*k$f(]-NYDRGf +"I(K7|g*A :9>H~L[;eDd ݱ(8ȉv6)A2YZ$HS=;,O[<7+<;v -B*0+D+0cw?1vA$݃}HD,μXn Eut5}-^CzV>NDag&? R~)fPʽ=$t#4`̓h::B +t0gc׍a Bt8IeK@y0+P{Ԡf)hP%Mp0LJ縆1a5]'dZ:脱-pPM7W&|Nd +sSRIZQswP%] qB_tl}&,j+9b^ 9(>kf+ӛ\a !}%D ed܅"1K-K1K+;cC_C2?#Kd9 ,+p{Ls.B2䖚oJ eܩ`}_-=c^$CO@9_[lz*8YIY-#H%[kX>$4>:J&IAMm&`٠]yem૩r KW]J}Rkm8k2jhY,FUC[ϻz\ qld 5iMCM!E_ͽ${>\s1Ȅ|GVʽC,;I5&$(༦&3mR7^+^ΠS v f`Ő!8)]30U8,H+iV3@!eVSEz&bő LLSPgtrv+NM %ܵ/آ7;Azd HAΈȯ(Z?,dyAp D~ů*"o݌#|oItϲ/3)1C3(鶡}wJ3 Ns+WDATH +F}:GOQa_`dll[sG!IMBh6^ko>@;!!WG*ORjISCNB:Wܪ1bS,%`MQb Dz] t +bL[^Qb"?UL,G5%1"VcouA$\*p$kaFG3Q >?d45q z@0:) -,Wauf`עCEUUv*=P,xkﰳ*VhXaO +ڊ^؃dlA+SdRE)PZfҁL_QQ\Jo`^4)#SW,dg@Ԑ1㵅yZm]oMs^߆ixIVb9gtT>ejp̀G X+5 d k~C)+DLѠIioze07MҀ>ҐV|YVQ9jn0žFx:`A(if2~Xwj֚BH@pm>RW̄~ |mbԃB-^,TEĖ4D(q=[ܢ][s %TG4{5z~orPmFDk 343'Wi=!Mݙ0KI41f9E@|s@EG$GǽdtNjVlZ q$x'A;r}ܸ3[uخ jsW 23Ҟ*O[z, Bϔ +)T D97uuucR۬cŹ-X/~wlUK8p/@F^R쩌\ Qq^kdF(!s2P0[ +&'ka_;]aD䄰M5SRuR6*863#-ݬΓ_@"0f[ NJKYɥpL54?ԏjORn)_Mh2n䕿miuJ`EfFLG@('@apdkPvGUrD : ཐfk/NdG;\3h|~/-;'疯g +fy9^3e24kf %ck8 wT)EA!n.؃(X*s#r]ˬBL'P3'yÉ] xphv#. 6ќ\\a 1 +&2=س0{Y[E+S39v[$0鲌JYv@eO羬"m6qɺc|\I2#äѠFbTx >HB>'+¯i9#1~t1$VQ^\.gB4Bip7Ԥ|* L5`|k˱<.v߯(4]V<+HQƼe*yئ3Lf0D7ծlB8Np.l ]?ɦ +iX F'pyim{nUJ'-}hG KlȰƺ h)7(2AZ<}rHJ]C- ֧'܎mE3k\Ѱu\磆IuxR58o  ZEEC_祾-o*X84ʾTTWTew*Hih]Dl4{vYrQ?jfĠ;@h>us;crZ;2 }A.2"SA ,C l4Ķ={3#ia%3G%JuV:2{sQ^8Ӌ]DZzHf +^Ű_$;f Ie], NOoMHǒ$X -?թcQ-tx E5*(ФLh1j(H"m,01o>66mjoSHVTBS͸u²p| +)7p?DsrSE=sn2[p̿Ǒ$ ++A:s$ + +^S=v }p1@c[\4y6 z5tV +{Mn.rIPSaPҿC`f&u"hon@L%ܷql5E]a%KyjM(cګF6iwTеdyuC hVh(RtG]>kxKƳ`+ *w,ՀqGqVK_t`<MZGΓe‹2) WJVƪQ +޲9 x; P)9Nnz$Иg%)W"SytIʿ=KeoLxW& NY)WG3a)rJ`TY9D\{ͨ9^MA+|?ﴂ|;ΆUIk7pb3ßGuאb LN.*m]"-C[3g E.hCBP[ ,޲T(pJw_ +9;<]sFvd9S4%w 1]:^ u.y)n׮n{&?13GE+ 0z,lՈgIgXȔskn\o8hP07QVl, 5u#ܢ/I"v:צSRHQsυ>oD" 2%cJ07<HƇ s xҤml6b@#VT4X#< $l/V;zZʺ"N˙h.[1yi݆~9[\6KNԨPa^${&q݆V" |XhD( ykB!a{zOѰ TmZkrla5~o/a M؈ O6(3+2I5ݲ+}z-AcKa92z@̮C1r@3AW㬅%LF{Lxb7!*tϓ.fsYӵuqk DvgX׫<ȷ#y(3daK@b4S㞃>5+a o}G=m.=: HW5 k|:xpI/b#T`*VaBYqG{>_l/IFMOS0=qώ#ڨWcs'S(0bϡà;^%!K*[δW%L2gc:2^;4I[K_;^Uҏ1h.5qOɪ#7yj y{w-x ed^sw4RDSYaů8(&e;KYb16zI6|Hn(Uyc=ƶNիe NmV6*rk("mĉM_ӂ݁+x&b[L +d">.&RMh~ B{ F@Zz%+8FPRU%ׯzu'y3`FD b>-@o.;I9GuǴN(HEZQ6\{ Jg/ 7WxW9 }M//q&3gR3vTyF {(~cd^5qQ}Vz{ls +ORX053J}kizG/gwidsdVUFF!)4sTW0eu=&w#6o57ŃxI~:-0u8t {lSMKZLGy!r&{M2GVͺRA&M;]v7Z΅J\&$V.E2F(z8}Hm/$}E ot9"Ԅ7sW@?bD$҆"/aѕܝxtst&e1Zv{Ӄ8i[^ԍt$qVKAS^჏ +C2C xƂ dz0eF.sݛ)HcA1*@B9i#I R,"ZIGBּJVlf^ұ\x_7鮉z2ǚS9~g r*ƈ(k}EGu_vq9.`V\>@T)@LWgp* {2Z ەwb0[rfSBiw'k"=$P2;=HRZmb9h:!Z2 I1äz l$ۙo]Mp(C[}sjUfML\ \r_I#(q\ t>ElEtC)$s9u"B˃(dGDf7 dVc_W5fhߵuw 0RȅHpQ+6ǗRYDm7A gGF64wJpl %C)D罟#xxu#xg nkRrmG-_{rD_ Ո+ XKX^ܴvIMe{4sb(25.d(j>黛'!>);ՆCmНm!6Va>"OHS%7A\b}Yغi:רܗ4J[ +P]׊ #׆7IG[ܚQL?'xiU{٢sRele'c?ή +Vx1wݳHcpJ$?Pb/G$oΊ!-f[> *XWr^}qsƩ8WaЮ#Г43vBkbo:S%2>~ Ѻo Э껆 ٩oEpYv] T0@zϸT`LfV9Hs1oրH+xmNVq3[({cck>~!Io$g!XNGj͒ ;E5zvae o֚ +]Ҕ` 1,n{_ +rEr(.U,SZ UgAbYLH=6{DpW +bGv %#FܗK liGKym[<>߂IR])E + E"b|غ(nޤJQ`U^M_JݭH/ BPUSbK ODչ>Ej;ߊPmr*\ndg EUA;TTGN^"1BBE(jNCcc UX~}ALM f6i +ÆMIaE .Nڬn(R],o<!LTY5*jpNk4uipT|n]lWdĻmT6#EL,j!QuɃϜjP%P bӹQHB:ɡ#@NB槞_6l4OKFo(6֗J+-Kf3L͈k ݰ7b=O}h)fMB.(wRc*00zVE>gחyW.3(?<`y\o(DNtjGc Tn +5oq>b$T417USS'_lW=o8ֹ%7_L6kyL<]TKe$0@G.:S&JUEBc CUPǢFj a^zI+ +ӈ42ZVYF( @PV4 hz﬛HWi?i@ܗ3^ VHV]ИttNփ,nEBsgd"ܛ

4Rac'ʜÕy.W{ Ex0=To%uXIIH$KHc0]J34Pc !gk}I y05)$3a(|q2:l7vndrvB)B5rFl2T%X]v™R9;n@G@l"eISG0Z^WA@^{HiXz+^P>)C˴ /j`E,lpLG]00B,R? ^&JFٵƮu}@:=[v(0/XPSXo5 )(<` #?q?r{Cšd_[.?#h:or_䕇1$vZaY4DFzuoiŠ8k.,#C JUzEB~4 "kvZfXI<:=* CaO@Y~~cLnߙP& +Ix֓-Vwk#O֊W *߱5~nU=g vGR&e5{L;Fyb2zc:x\+1Fzmx 45С+ u')#y45VCBO瀋&bcCњgէ@~d6+aP}ՐtiGD^X&S5Wjg3>F3U;4b@w/G0s%Vm*-hob^FyaGKv^ ;1=oo-\sfj@`UZItH'30 {՚%cu"Sn.1EGrUџ!iTECVtLdzD %Ul +8J<|$>S o ϙ\W/^2J}Wmb /aNGEKpD|F穱VӻkN,RӸ< ^[p/*}q[C<ٶF")6?rY3.޼8LL˫D;6OdkPc% !p{Uzwd[ڢ2%F4-ԩCbCnz넊mߵEE"~4]Ԥ<3qq*`^\YUKjó2]z@U8NvdufvAk*})< ]N.(mHp!-Ѷ!%oHJcHt)\;olp.$`zV`!cknseu'>P-%bi&@ Jͼ7C25'F~v.1sUЁHe>?=2Qĥኛ +b[kgFh/'튼~oH,_Nmv;Uyzr̭#Qqc Q9#1ixFfHnפqŚX=ȝs_`83JA%G 2j#8 $bd="ĉ;c)C`6$_vcK5bRsOvek+3 >wH![" ,й#un>9{3žFH E2y+ zÀKv;g# JNP _"5jN#P^x Fiϧڕ`%'p|“T#Sۅo s'5r"q&H[b$+vl4PMS֠ Y ![k@HY }0%vDD E$E{q\fg2lZox,v(##,_|.*ƩgÙv{-}uvX(5]j1qMBEtb٠<! 7}'`UC@`#MDcYٿFa4G5;NZK8#oa2Db**J_4㒺R=Z[2⍋42!ucX[4|W~gPAH@!M.yp1zj2?1PHP@)IZtٵֱ$, ׃v`/ f ZZaAo\GÁ>46l[zy5dkGb'-ƨt{P4`q'E&;w(+o%n7Kۆ%)QPTC6+8yAY-U A:'ygUHsϐCaIUժ񰼡mWoaȫV2%*ȏu{OsJ{>+"Z]C|e&5GE-6Jrig90)j ;6^% 3.=FB$u:5Xzc sRwq&)@dz-@(VXI_0k kh%6n(>YbSn/~E 4L hΕh[OOn;"p}m[=dk8 +5TI#VPS?ko+˒W> % J A@=iqT l@@SEHl==xQedfO Um zk'Wf?g68seZgbom8~H.^aCGZl g$x~XB-߾tCZT\N{88Ҧh264ѸuҪ qcxS8]PFSeKFSY^]% +S9ڭsn.h[Yf ,o5pl,qԉ^@;L"zFd3MƹsT_Dy?$ CSΚQc `i˚'AT]o3R6.#N WE2B4Yܫ '@^] ІxrĦnAY%R@ J__o/tê)n1# +dhkPY(5Owzg\XU!f=jƠ[ԦiosD?\r4 Z R ,aҎÄgi{j`=PUqPVABMeCd{pYi9]pi0/x>eEu.HQhq{[cLL\| ?"eDޒ.N^ P-z3A[ +NT2xd&%]t G9#JU39ΌO/`f0+Qլ\AWa!|:4o ?~>` Ň5-+^!h@`zxFrF~0IMM8|2O +{fb$^8R0@>`? )PQFYt/e=g8Ni5dVDx]L0$'B5?E2{:j+lsRow Զf5D@ڶn=)=K!jiwr1~Us>]4boĩ2Rʀa|bcrTwry֨KdYjvf 㓂L:W95UJgR|;С#hVom@c~OѭbL(51u|Zh|5Ta?QuIzlOߵ]F,Z8 )>'!YǖT'jw@F +\6lݒ~Ċڜ`vc8'<^1W_ +gBY4B+jTXye; RmEdƲk*~L]Q{Cv$ۈ:2dh{FnY.g#{zJ,%ˉq))tEue?BU񒍠BӘ4 pJ8U@e"q`ll=4r!z5_K?㔈vt ^\D/v'>P4ulxz{('gWH불3\6+wVHpyۊ=H֖mY^] ll NFʿWU*ˑQ8~*Uy:XrJGe /mxC];̗d'kYl59oBɍrk_OPXgmڭ(hѤck yq(DbY"5T^V53$CeK1$KE"n[ _=cZ3xl +Ϣ4e\za&7 9 rx>,7&r,yG(,U)_o NH0k~fIdjN|[ofɗO)qG_يUOWRza+}!fq(T4zbX}'PGmԗ)aǥiYK:J=(ׂE.aȻz7;&(.`ZLKN_hOysGKbݞ"Ilߵ ++ŋ US؅-xTL\oJ ي~y_^y@MH'4 #_#9%-@37bkD +BXօfMݲvIHڴe1ST~;B8cR;|v@ +וt.qVFS:tnDZP3"P!B  +t4q/4`PxL*vT,j+e}CIؙ9\\coiǹ6(Lj6nRJHkLĴ(3d5}>iQi`&S\idJ{:+|Xұ kyji Lf'٢*o:lw 5AzIEU( fDJQpo"l>y3_ vc +gHte|a m*[F"<*Qi"K&`7팎_VB|'X+TaHb|E<zڿC@sܱWp`DVwҒ~\SP K+: $S=4VP W$Ӌ;Dh' Ȱe*젱C-ROZr]pxf"< 9Z:*#,\Cֈ%ѾJ RN1K63ho:+k%ɰ0µ5ɀ#mombK5 +mA@z 6.V29)K괢&=SDv$+?C/ZD8=ؑPrc-kf~A?&^_1" =6|.+7d{Y~oN7,~9j{AARkHl5 2.0=`ҡ>], +ʼn1Lk &ҶG->?k=>(EiHPOB6( +_Tv=SHy;~O)\Uun3認1Na _ykl(8+$6f}>D?gTM1W[` J;@u^:Qub +մĻ8mlģ UQSX1j, +^XJDK9Z3l4h+dKޕlvXʹkf[^ZPgq[ќך }2^Ƭbv> {ƴ[b/!*ſkXJ(]mdZ +{Cgﺮ|J* c%w||G6uu ̇04PէR:v-iSżdVUW额lPYPG RnC{,Q^(*+ԦuW0]s{`K0ZQ?`T{Jd i{%Qe1EAЈ`mV󥮿b4,Yoéۦ,S2V}ԬM +_3֟& ? +21ɝݪnwKA=M짟{؊2@ub+5!q+ʹ~S?LfQS8ؚ I]=vXtR5>*a& +vZZ@7|:ͮ#c 1+rȨǧ"{R۱62;/T2݋:+ׅ#j# +Υ_"fplF@z 3LG[hm[]D 7ZO{o ܧy= *YFCtDCjl# c9D@t[ +}׹HQQw uK`'N98TڊP&M~,R i6ə}hfzE~ jP.g=fbE[!{u$2VP^eyMI(r-7H-T\%Ӻ~hqRY{聣Q"8o%PM>"z( ƸPVn|+2Q U/`Ab;=5Cȸ6(wAN^Ya ovJe#0j= y#ۊv-WmR>A³eovA9ȊAAܓ( LU؝nPB!4o)q{9@t]~E>+mFb fȗT;f_ٳ&jbKYDKUb  ,Oo. +{~y΁uN: C1. BƎzhT];-&(_>怾$'jI88n3tpTW9ea@, ځ +_RY9)\㌔M4g#gs09;( +:F<]xx5^Lj -]Dy88͵J z WjG| wsk#|0z1,I>o>)VxY%y}w:QuhG1(\|G(JH /7ɕKAi!*$xѦeڀ`! endstream endobj 77 0 obj <>stream +oEX4Lt?1z܃~j34Stv-t@L-%ȹD)~ ZY@#_{24$s:h)y͆"3j4ts(Xcqףa + '-@{ycilZww۾]rZ07vubX}8l8VVczB,ܺengӅG{aw(r0Â{C_AbE6yͱ YZc[uuBAQz(e9SzNhwǕĝ)w\m<"fd{(Uئt΃⨅<ßtB@v,ہ?j<|v'z޿G+fj'>Ԑ=i3 +n' =ImQ=DPȌ֔!.m)Y`G=t xyEXdfHfC[\ &bog3Bxy`r[_{7z* Y4$DX" 䫅UIǠ|x49tR牘ЈDXhcĸW:u;JiYSIo)6;ulPh=#%ZdmJ{lTCo0RPruT|MvU+=?V3[w# 0(fs,Qُ)]MLT(TP<6Š;{v{6*xdef}]`եt.@>H.Bn`+ƌOж^)y"C]BgNEn {2 n|_T2:)e(veW*q,y?"`Hb:zJ$ +4f/P5"B@^Ft:(;Pfo +a!{h$YUc;(q?~Ѣ+&w_a:5X]9W]v +^v&OYW G:}VBDO@w'arwȀ [ M)s1C^b"O`̓=>$*d]#Oߍ6\ҽޥS gϲKަ06ǺmvW +{ `LKT%)9*'Li&S5SHV; ug 0gl* 03\omzO6<I2X*QĞ#׬vOEI^ +OH2O P}lCx\JtZEKs =hu4 Owꅇ.\%F>Q`#䲼czDӭr?aƈ&ΐͷVD7{y:b|Gy7c>#⶝蓂5],Ē3q~P|`kZ#YlQC~eÍޢdx vaф>~ gǙlNs:N!{QV + +N,̉~<17lP +,Hf8W yq! |ϒ /.NmMb*?JB?r.R*B@-| + +8)SiH'+?'ֹ; DwGs(xfiVPp`ߛPa@."B97UBߙ4eڮT/:.I8Kߞ)©^׬lXakȺ>8~u᫐.jŭNel*ckg!Z|?!Ҋ$ǃ{zy[W Avv#,ljf0 +חn03O;FH[ժa;` ,Y0|9ˋ Pa5^aMCTͶ!!ZLS2t BхcXI:5dw`T/:: + 9g&C2|"L*]1 q_bb=$PZeÄDHxctq&s't&y%- oοטMY-B{O|WV+eIFk8w;,Y]2/BM/A3dҒQZ@0)vJ\tz(dd֛#C̐X|:}҇hRnB.ܽC(u3rDH7]zܝA&eiU2S.ZtX`*Bs͆"@1AG +z#輼g^._'K"_S/O5ǿw?/???o??} ~wƶ[ 򃩹ʄC̘K:oQ/$Ȏ b+a`¤qS+F>jy|7th +H",zADV-,JPD)$L* 4 +! 6h$|LjӦmA`wx Ўʨޔ28L˘EKT͈]֬P!J@P*kQb8>hJ(b>qdi֪&{WZ")aM$255C^FIA8N%oPjw:b8ⱎ޽?6bY/  "*dL"&bHSiÑ(JZFVVoΕ2B+AGrű%xW4%]o=-8Ñ4BWPԺIL4XEX%!͠w,uwfbϛq慔Gg>7jA8̦`kPZֻ̪eUz)mY^4Os?|f}a= Ą TtQuz&(,+>AYF;1:` 5t/[#qEVF'2#$R Zs/ԃrD +'bw䜇Isa iQA)dž5Y8yfzAJr@v 2(KP^*7Y +ǐA؞ XʮLѕz3X{Y`pߜGPIl'rs!H7\KvҴrG=l8vdB/@]LɆ+o!D?!M(Iԃè*ڟ!q-;r#D +Ù̲*υųl'M՚h[Xc^g&kٰ0SvBSB6[,}8=ϾJy4S W1TdG@FUޏuaOH H#WpG^OٞԀ(P'@3 E$Y<㽘9&:U{8L +6.Ehgo߃/,Sh +Dܚ&5{bPq2)Aqs(D"7 dŠ4(k qWzB<nL"U*+U!9N[j +)CobOAӒAн  qO(d!L?ԯ+)9[: FCfE +Sd`ZzNKh>RP=}:X4"W,sA-ZBS֫iDYK4Cr؇j$sӉx8 5W]8Te84Fܻh0 *e4E\F>LbKT%m oo~G`,Т`G "_[{G0F/|bDԷ#mΑm{HS!H+&3Y]g[LMSL O$KW]y=M^h"$tBPfWMW(H8e/ą48Mʒ;bĶD1&ΕͳcyKqu;Sdp Q!2iW-%jGE_VH<ȉ:VSd*mAXJ]~$*pVYjfP)U1Ue|&K%j B>u]aջr]V8DYڽr"[Je{p8Hxȴ_I0X3>+ $0ۀN#Rv"iY 7R@܏io3/I|'ZLNR@CT +ҏ7N{GxwGHo gB+O";=}%c$)؂7|_< VR'-pM.=}~ 2/?V=M(%v \備~ =vUkj( +*A"GzEhJc#6mJAK9Qk^4mK_>#PlR<>Z;y(0[T @ě[?Tދu=ϙlTc)]6—{rْa-D$וlyҭ(N3" +/Z5 DvD"!So>M1 %=XbOL#{oyMH~]|>{9zZ48F4 T}q_+fKL̑n+kZߎ{\'׏SbD͕(~1whGUI4Rė}$<~vJ7nQ.܏=\+jFmރ():SMH.U7fOT{ pq휊8Pʟ_:p]KK\oqǺtq USTi[q{V(cN:$~O>еq4a~5VwTx-243sqRgAXC&fDU')_]+P^]6j1 Y> +.##x8Ya4bD ++r}؄Cvìnj ph-|"j@uobB\ Il +yhAlH/W7L/U+ ֎R4ѷQS}" +TidM NC8 +h|7{+|D8Z |ߏ)E"8evH`F2Ӈ8(@|=RRCzGD&L(Fc}RwoDMK: 穇] ك<(:M!g7E̾ +* !ڝe(nFUmՋUDEՈ=_! }%{Oˤ >pħdQb^=OMO3B0B/8Rn,8u=Ssd'ʟsZ)Mπﲳ+U$)2M쇶_'< 9AED~a}bsP -#Fz%xG%a@=DAbϴ^ +h~45Yx}RP"[G4R"G*1"oie)4{*jy!͢$4ODUVͼH<.6(u/wi3oׁ!םVptTdE8/3&tr~a&i/ JP?E!ά|w1Hx*+{G;o" "%Sߜg脟"D T>"jߣFٰ#!9lir8e52 ÞpGQ5%Eζ"ȣ(Y!N@(IUQ ϛtYMAp^၎~J@#>;TLHE8LH@Gu(l!3ߞ6 N=~G`V:d/z P n4A;Vh(hq3|tl^;I8g+uykJ̒#dX6j@ R,8fLԜyyI)_ݩkmH+ ȼmKFu,otF$9~Lb9è")CU"$>F;zxRh 7莨w̃r!-\@; 5`_xwȇa.c%g=e˼0VmĶ{Fh25"V!(d:zM_W=4$OTp yp!:5贍9 ii?ϹSДk(rdPR=>ۢ˂ɊZ]&1 ' `M2 c ~@9JPqH#mM"jֽPK$Ho$)/T0pwg'?Q&g 1y 4dA3iK~NI`$BF"|]ҡn7pFQv ødgTm4_g"|t41,(2GVֲ]Yt|f8 !N0jG\?R‰3/p؋F sp1|:}fL ]p*hXe[9"Ќ%?΋)sN傗rh؞`WDΣerV7ssSޞ "SGYh +wXB+p +Sx?~Yb?pxcⱀRm80KkrGӆJD?c@Z y1OmC'O0Iz"}DT _ۃ/ŕH`$wU8#*KWBPGlv]i3Cb/`Q>W-wL5(0^r%IXUb$mP&1fsɨXT/~r@|=vN%Pxp)G*t]u H$|hs_&ɆS/i`*Ҡ"i^,1E(GޫR2B,{O%8d` e)z ";Q'j5J%* +Y(=f]A܍Kob]?ro=2OpFir/DM>)fD,@=9)UY5kA.S B1_q5{ڙxzηd/H&/K.uMhPsDFG%.Nx+| #0S uGدۡ =1/%b ;wK^!d\Έrղ¶0?z7 WJ03<_`vҧ}@MoZ[G5 -&Q%GgwUJ-Q9P Ȼ:!B}e#D@A7k6ɚzHQMuB68$ٺ£htGU^(q_"hy2Rs t#6l,8V#q< lSo"L|5Pcj)AU♨Xx5 v!5>Hz}z"B梋5BADDS왨Q񯘱:/@N!GORh9ڧBŪ_0 Q%Ϡ4A.hoUżX jdY%WC;[nz= i~2J+Grojh7zs%n) +@e]6$?%/):X; %a3I JIVxjӱ.i;w=$ +E(y iBv-" +}dB9,RxU'aHo.eyB:Q!סbK G> ՁވҌpV8_]r:2685{@: 5L;=(2iJ g=.Sz@TU4EƳpa:Ȉ*K-m Rm\[fKTjXuXG4ؤ+wj6AkNNl#Up;6˪w2ԭQm+Uv{ @ъO{=PᡅP N3qع(P0Y7TļLN0w#9?!% Qre{w7a[~4;"{f#D]AeHw.\E!EicH{_9$Aj#EG NA*h371_NPJ0W;*{;;bh}ȭQw0U;<  +m@#"MU6M]i_dHXH1&h"Ta.j5'tmt-jBd67 "HN :IU-z K`$8_5ˣj ͪxoH,yh=A\@sy8 rɷ* g܏2>Vh9UF6m,u|6t3_:25 +gbԊrj=.8 w#;왮4j?:\uYF/<%yzP۲dʻZ\7Q߆z6$L{T*oqq E}0w/ܿNQd p +9vqNVYa?5V4`o7$F%HHKHJ,w27$J]DD]F@䝖-#W<됒⅙ `OL%B?c g >fBkG$Tt>MD, d%ם)$kC\w#ǢM QT TϪRVJ~B!/pAFtH ^u\B4 wi{.{E8 j;y+2+eͅfUReescD;)h檒3ߝ]Yẽ֭}Auɞ&N1B&#" "Bc^٘38 "ULW: 0Wi\.lN1ɿLΰbʡ;O="ny!HQt,]?0g><$ﳒ~* '))t,V`&D-eMbWn(DL.A.ug.;VSʦ0bz`4V*ziutx!bHTiIïU}ixfWC[?KeYRlAn뫆|H(o^D(3M2s@2Y8PŨ+_ &5W r\)ySe)!FJ +"EBHA5Pl٩5UMb7{Wl #JM +LF‚LYe@E3o#82fS*U0UD㺷@ .>tKbUi t>}=5 >G9c _Ǜ/= K,-қJ;JJMe!L-MFCFov*f7f;N"Fh,6,\nW6wŞ(-A^Is(l%`u0h4QB\2Xj+ə_Xp"P!:xmah,3͒t=K,& + +VPJs`ȭz.NUBZ*nVP/!aS2_PZ42%UQD"TU D7וMJh9Lv&El*m|;OP쿜k~酙[ < %RYeLQTV=y+2)K!Q oqJ`e}=Dz/dNaDlz=ZAh0 ׵JΔZHKVIYr!^[<#a@_VOMPO,7W"2I|CѰt68`쉠2KD6i"D䗳;rrlf(l*8@5]R<njJU&N q}*lՔs)5| 䌌1t@^3LX5X.Va!%ʥxAL ?(T#eXۗh ~PP@8#NaifD1ӈ7+qLOfG Bfv3fZrHTX{bΰB^}?<vM<*Hѵ$aTH%܊>, &(kcGJv _a5QFkYy}kdcd&i-} }ھnna&ը(:Iڿl}RkF][_qޗnKRhWJx!yHP!l(onV:LzEB:V} +{Y4/~IOꩽ>4YsYB$?1XlqJ^Z?Cj/:6,ױ[=t}60왼jZv}AAny,(8(2R8OAy⿉=/' O?K+S4 +1SI)/>gcg=硄T<ڏ2x۳fe#ҘA1𶎹쨺7,$1zZ84!]J0ӱHœNϣDgF"P=ʓ= "Rkzlq`t|G0 +{kw)dH,nHgG4#P 9YR^w*T$T&iNBϞ-ZJ멼 lfT Q`QNSk]&\ArwrvL=[ʌ%TvLDd2Bxˆ OAX}"D)^žAͤnGcvҠۛUA$856d4 + +g+%r[0>"*^~!oNc%4<# "PU>Lԅ{ *#mjip/sE6/tGWUB^:e)DPi5P1L:9q)@v:9 w^tlFXh ✱i@VDԸC8VPktdv}8<"|&K]A\NymLr0dz9ɎyIJ|F.ꋍ #S$tqdZ]}VROD=M^jq֬lo"Q:G?3,ÕiZqOtA!j@SinzٵD:/V+Ip Őj +p@€wx 4^ }p^j}˹p?F^hd+0qu" 4tD(oW4"hhBj+EMK~X=Ǘj|F˔AED~?瘒^TKn{y4Dx%ZPYw|Q%([m$29ˆ,6E25ȍ'J5JU}~W:Wl_H ]kDP'R|xP]994QaM¦k:,"(} B@|C٪*صBcDlԚ -a=J^k% IHU:{ER 4PXILd-귄\f}s\E]">ogO0Tpj3<2{W.)-Om5 y`s]L&=<#rKit.E=V"1PLy2CXkz,٥{bt{!PNS*n F굤t +gCFZ*ŵy={i*] +]mh؛:C m,X=' tBߦ;~}x3dd"B>hPW\sBiVDaw$[S`t;B={M.RP۱!-T |j +Dn:GN0V=❀{/B 2`SON YCmB ;S.Wƿc֎B%Զ'B@lO?mKl7Œ))ydu%4j0ks]Gpk9sd{ebF栅c]kjn4V$4]G@Mx1y c%POt w>wJGjBz ]Xم=>}a{6X(sۨ<ևa bDFzݙ dC6Mb$I{,Z22mrgs{^Frb9\Tڊ a3t0s&"Jd>*< [ s읗^&搢PW[Ht>" +} ޮmO(\ -&nRJC7:ңCQq~q]z4)xelt9.vmܢKcpJDq?0渎"#"F3en~GN'Aߤ\y3n4εC͵@$cbqx@ŋ<΋sE?Iok3/<iF~%0ZӮn[+˞NC[2JL-DzXM3Q=(=q}=Pl210!$3%8m3h!ϢE 5Ωu*D r:7rS9zʍZ)DRHsR x58/e *6"7F hiY6gdLX>"z |D)#CFTDM#=d>My*4_mɊ?Qjj|>=(!*(l{Tn/9_I؍a'Z=؅@Z͌6$[D\#txmR<_nh4%roǷ VbmvG+8 3(3.6!d@[-msWen,э͕d&X3@JQVepT9G7V&l)~MZ4@T֢;/JjQ4&0kMvcu:)MԻ)ŰLG?3Uf߃0hcS޻aCG@E詐QU䆍||pqXqcLV`~1qo *0Mi^zQҧ٨(WDtiYF(ςߔs#f u\:TPMԔzCzNz޵6&V&|mU*'#mfI \/8f?= MyE-jAD - +_[AK{Zj~z!6 +n#nxZ I#(i^fJtA;YG`T[$rG!I1XפۯLC6⯟Pmρ3^>Vx 'gRԚTV@3%־ q 3n~3T\R㤧:DtKp@>JNs'ko%)]&J6d5=ODHȹGn` +B^ks_ޅaZG5y|<~ o;x7n% A(*|sO=# +.}cޱLU;Y7/ ʈ?DRɞJ[߅eJ1HqX.T@=Nu6h0;s:7qňbYNTw!tX94FQD\$e뉆q XT=G $'=TKX1FuK l?[A#JS *mE\+ygZ3#!Ms, p>}4;:sC0 C.yֺ׳S'pAw3۽knzhF+QD@yK'Hۇ*? *榒L ;-^9Mh\(tb*u#s_h2Yv#`pP=w,_`z ;Q:#6 +xwh3ZGnG19Btd p cȶ!`;8(<s(Vtfn&C_P CSG17+$XPu~ <ʝg,&p@B QP,ɜkBc R {=E Tz[h](+TC OŲ-Y{#V=<}%36\K0]|g5fסSct9޴zklt(X%"ybyGl#eh O+,_AW + m/5Y<:1se#%d艨ϣKxl۽W2 5NEJ)Jg8*t#1AQ=u.SIE5+-N}FI9s/t9>#remxsl>"UU[RdRJ Ttuaֈj:@(*D}Lj;tL%J> ّ%]cʉWw_E]]JUD2Tiuy)r~md1RnʪqjuGPB{T)hhQyz &(5ۖg|ގ F -5<|eӚ~L%EF-1@0-]ۮUH*F<HPز N1!ڷj%Vl:6aꓷ!UBY\a"<\{԰6@}[/=񀚂`k{BC=و\ + +px Nh8>YȮi9X}[s@DcDfZܕ\ႴeO]"T֜S+SAo"8?,+_y_Ypbǿ/_O_Owwwu_} ~Cg!1oXD`ףSXƝ4X *:^0)n1~ K';3k.C$^Rz,w|E;|]=H2艊ۜӘ Hm; WhAi~FDɩH+5l(-5dzfG= *꟢߹VN +ܑ.ݬ,ÚM%zU\0"6Fڼ>='DRN Iwδ:b3iV73G)?iuqhl +I#QJX%@B'>3o$D7KgE:ugh$湋?yBP ]"<0P8(l;Yh_cEusleT;ݏ %Z)wYd08͊XⵯDa(K3,g,zk",(Ur4/gh5y~w»Ct!֒(t0ѝ;1 +#OҞqv< LӤNkHpv +$hn睘P Ŋz;<Ba`3VfV(30\g޹t/KZ4Ems*d4}`z9ZlA +,@I̛mϛGΏ&'?Jwl+.ܞLJ TR@DB@රO{wO %k 9)=-xMj'Ո*?)3ڦ4Pg^oթUp[QێbuĿ),M2qGNTHaGa+,Q=M# aԯӠiV֣c.n7h}#J9A".;__I(kْXeLL;# +#A)A-S%olhx}нOȲarSL~20d\?io NzYqk@!@"oBdžCq0eu$TdzYzXAtq]6 슖t*wE Aa_V" vu#Ks42lA+qm4^#Г Lam?W-?a Uׁ/&~0O]<gD~SZY+o؞ɖΓ)I9;sޞGqlSUd78Ua?GZ;[xzV6D頜7}WZI\Uq{[<\ŪamnS/E T6\I5Zk%褜L=0SjOx͊X@O71"zlQwDjٛeZbr{Z( ,踿9yq:E-||`ߓe & +-@J(LȸN@m[t5̅3f`1"gEy_B ,` Z#%I| Κ> F!4sp$:Spu{l-um?hydj%5HSU VkӺHxR+Eϴ=3zU+" +Q]\[ nVum[,&=8 h +{|]f;0N)͊5r}z;$; +|?>S%5 E .דA0OhR3 ޿d[ %U[lÛty#_:E5R|$I[wТ^tQ* 2 +rH^U6U#vZMro3bjeDP.ZrN9#[UVR5YH:( +"n_ |#I̦|صdfs!EW+QJrDD

GڵוdZy$ٜuQǭ vԅé 0} +'G6:S㙬: Q.&7b265DeW3"FJ:Ci୙38B*n.qH+}ѠxpI)Pr'5b//k[g GߛM4Q+fDZ9Z" jSTɌu^>E]++o~]>녧_o44ڏŸΣ@|-+%G~n5@+݊uJ;ۦJ"(LvUbs90h87@JFѱJk؞c:+k@vz OG@(A+TOuMfHI~HւxFUIYė\)m)-O3MPѿ9%ۚAxiQ#5#E=STҏxV"ݝ Yŏ$ #FH{w̧+QdW[U1QI$8 +jj8PčJ=۱K4{Jك9Hd}u,!i{2~H<::)NE@ }qzw>n i&*ʋ<wĽ)-rqi<jw\omEzDطFe{iTeMZO[' H\q;MwVUHjO !`+QJ%omYpjeON0u&euGUN8qHڪ+ܜ9&l#`ܧJ^& +=T٢I(h[a$fAcvXpp_C5"7>8Ǭ ۲L*L7X%[Yr u?#P<@ܛ 5QSaɘTL;u$] rF%uᙾ4F@+s!z9dok ,ƙ:*.RZL ~J>O[(%ADm*bp\VA<é\GuBUmlnHi-Y|q'}%"Ձ^5%PF67FȉYZ@1B+Ў'kyŤ殚F,Cgp\#ʯF W RGܿ7y=0O\Zj/ﯽkUcms>8x4K-c" PPq?ry?|?ʲNq~nz.ޤ_&Dxt]VH-u@R֜"E䙝予~GTSn Qo~3G vJ[_e?4a0:CA1Rg7.6  %Ad5fBoTJǦh]W9wj維>3$x~ɍ9pC87 ` Ϋdr{?((X6$2uK'A>dܥ!M@FysZLKk@'5锷2w5OPb.L@hIGl}V!^1?wOK\g,Sr]2&RgkO;ޣjl]ih%2Y.)5Mzѡ,W%tM~E6A{uku)[\jRRP]lu4. h5{8j2JKJXXl('yK-DQS?ͨU 2E1,qڞbM0 k YXX3D\l8HgD.0;7 \cBŝuNs/H6 RŸ?j4W.4~ 8bL[?%OO< qD!.ЕJk\*,w_h|sKJSJ·Jnټj!}B;Nz7r +QKeI8pnOS5>Au-*YPW04r(= *R܄+pdM*1 <62Pun+z_PZ\ʪ%K=ع$YFѺũjU72)|btifY{cע7vt^pB##ԣ7LtE*o&_XD/z]3B?ʬ=Oج IsLBzmQPĆ((. t{tZ㒥WQlDY/yA:=D l>C‰[ח.뎉Y}OZlϧ[~A|NOŻfL ׯ7X dC v重&g +PLZ]&}J`(!ebNB.D+1\=?ϫ D\n[0hZr%MDۮ`=;3w#u;!oL eBtPag ;sB`n7AVLMHc2O,d45m&kA+u=kA'ѮlǕxh\|%7j` +Uu'X[G#[2{G%ru~(r{|nၵ(^9WTOR}CO*R@7yVSy"o ++"C\ JLֺlV٩yE:$"peˀomWd~_)£ T~.Q9;(XU-@Wwۗa=FKbc4 }W`$3j +F[GLTDO9؀a }LDr)*[XW;oX#u<:FboA%=߂]6Px%YhKeqׯ e6u.\TT-%&Cقh'q/5,SahR'  G}۸lVqc2pT6U5Yf֬eg[@۳Rە x2^  Q,L&A $0#0J"3(@6vunK2c5:{<*x.t<HIBIDrh#|G؂Ǥ$?)u9ݨj޷:,R 4?.c߻kk+cq4OyFYVe/3Bi}s!j?$Jg{UeNBzBpmlP=z|#z'+cC?l<6-p8j܌~oLh,x P^VJ"N7FL显duxc'1តv`sQ4Ryթ4i"fV, !?l !5y~K1RG̲=;v̏5IlH.9 ]2/=֧jMƊ7`jvSI +U;B)< 8*(c'jַT84QQsRGIT)[D OR)NMn\T/HY}dB=\Q~gmDZy-O~B>3@ sa\ +DUJorinX-NzŲBt<;i5:pS~lë =ю AbnCEV̫-RTay5h"<*"lې-p!#ԔBulw8*>^Kұ #|][G ++dE*fpkXׅ~9!bRX/e~?+:rjH] ZIFSNiW(Pc.2Tȝx^8x@hGȱCHҫO]X;.+Lu T +?"i[ZMeڣ iՁwz@+$Ç@ZkyĞxe*EGɎh W֊2^^zrb}R#c"[ ط<(]@f#=!mC۵c wfp" +Ǟ~HjRk9^KəfQ`Q`jӘ0C0CB?*BpΟmQ+z&rC PmDQrgBcGYR\4 ۨmGɹ/O3Y ~)s[?&ԋ7s(33@g.)n9[je+v_R~Z5Rnb u%؎"dSۅ%гdۙo#"W1,tŲLguwVSaNMGVO!^:72䳯J3ny3 G فqR(WH}0{qX&;CuXj_n?-VX$BѴF\{iI|4b7ᐸIBGa9 $u] $VoA :K;JVDРUxs0) ׅlF `IgQu:Qwjҵ_}:~8 um2evxB +1'[hEu6٤0)^kNޫzei࣐F "6=!wJ]fH iFP6YmDF%dI8lReFAτ~ŮWE({3o'm¤uڼ+;B z1=O(ʐ΍܈MZ3عR":g6>[~r\u2UޢċJIQ/}ZJN{W]RS33ީow^j2ʟ@4" |*_u! +@W#^U=NO6x!갻S|;l&tӹ=Up:CUǽq@Q [Uk (jovOCbTxlgcL]DI$x^ggsCmA4EZ)ѵ؃-1?Ӕk8m|4 +v%Ab ]3[&W!k 2# b1ʼ] _'QPVSrn;=OrviQ|B_t@ِӏcdUa4t4."  Z׊LPE7\Ymnv̰}godxQDS˂дJGg%N˔iN4dQz9܋c[L^e#M1ST+*ԯHz[:F^)ϡӡqCjBRGeZ}Zm*i0_wE1Z$XL6 C\ +3V?;YW4gɮ!xi(.ۑXU@̠ʹ%܏u+7ivcaIŽtc4*>ςaD* #OlS,C0Z3}Ipg1L+Wss[0? [ WHȽ/+lztv*CyۙSW'oaR+^.&&TV0KNB[Qȋ;RǾ3CPsb3!J5꡷ag\);iyXVH?T87eQu2:"鬚?I.k餰q*;Yd6Y<=nv)Lr2Az=T6P8RІ Z`8fIܡm $FLU ~(W3oN36. + +|ґvኺoE֖T0ţD6[,Y濖g6 4nks:ZtŁ}? bh 걉̪Ǖ O%DOJ72X(z8ǡ+sWov > x+}:~tl&K,3#^ I6Mu辸Oo+HdJfvD Hq.PGa$+{w866)MtM$S?@19[IQC8ؤd&nhCTyHUsFOO@Tq^r/*Oasv7BB{"|0ӏԽyplzT'yh*#mQW.h:&@琂/S[ea3Q565|%f鈐Y+i͕ \lx:MzӦ*5LhTMʈ'SZͨ: E䋴PTt{qd l|\7{Kvn@˵U|BK5|7-v򺒨uXrީ.ܤ:I!UD "4:[h+%[aS΍-AGJ5qR ߜdS⃑x~X74%Lz58@2Gb5 (Mg =/Y ֕`ǂ+%ey" Z ؉eҾ +(c_6ĆI{sycIyݦxrG#9S%ٙEHG4B:,zfEme%"ݕ=BdCMi#*a ]!C ؈+EKZwd^Nn"zd dFQL Cb~Wk\( +  Y@jPYجMuom0& J2H@?*[Sh' |-(??EP\д3LzzfA4"._1s x;: +5~v J@ZdhG?6΁Rúr +aI!Td_c}px!W8KxQ,6^H퉯lQbjCI].Y"WIR-ۊE{%(rې3Pf̨4f) +ҧ& ~}pG*Hϧuh[OqnXJ5H7'B[Ӊ X. +g ɸy{3>R.MRO0i#gS +#iZETP=;KOnFQ2Vb!X6!F%-mG}k9rѺyh& + -) +7xNZ+OoٹK[/sڂXںn7Cx{K >EsRVF"17-rzOݴ*c$$NH=3) +_c["#+IK cE5+ʝeT;JT~AEJ0: UPD:^$xC;Y<>WX$1 O8)瀶&3$DCr0ǝAcFsPӺ7vR*b$ۘ>k/=xkZ6֩o&i.UI%w6vy]B:>#LJrsA.z'-UfLO>Y#zu#> _XGը=l몙A,u  +?dϧtTtaDŽ$GtBW`Ϯy %Ahh ӃB, !N#؛{&"S5o^Ds|F9Q'/F\x AkBOǮ3@)W +9) +qTtfֿ9#Jo7QuK3J*Gn|Tm+1 9mGlK}(0 ʱV YgķC#fh@ګʑ7* @Av/E)m;<~4Vf\{Ek[zs B1Ֆ8)qX=H9},jMx޳R~;} /?NG,|Ds@IӮ7B_o!9WBjFY+5 $pЁYHSev9"A܎cP05ү'7gNe0=;w=p|"F#GEN; T/WJCI^ +d*(Ԛ^h z ]ڝR5V"h< h)j]$pIՊnZD-MM/XqYX=tuCޡk6Ld Mp ot %`-;=D eOQ湾c!Rbz䫩y]T`}l R I>[YƔz S[ JtzbQ@m4֥xEm>p+uq^*v_=R8v9R|"C5^ZT k4-诏 !8#@*=CJXj4\fhIKpoQ#E*ne֦'%}+E*/qDWQ!Qm*q)d=OW>mpQrlE sܮFf%70 iFd*ڎj[=D߭&*Z=ִbUT vʮ΢6g/ +tm5ߕpUX9.02*Pz݄䧆xeP=E,黀Z}Ehٕ֬g Z^5k{v.ܟ~i^ }vK9`K3=uMz*G㣬頒#WI*,J4ۺA(h0í¯y)R@+5]­q{jfQm./~&#Пovcĺ9jT^k> +87dϹ=bFmvWNOIX0,SH|mZgAX>É1Uǵ7(H)F~W۩y,ᨌ6W:Zت8# +s%Jy궧!Byi\{BڤTqTh]\kes(Ng?ĕV)I/CrsmDm Ղ* y )9,`mm~q/pf 58W$4l݆9QT}:7v)-cZ mSNt"Gz}eSVו wUɴETj|ґH+u/^)d_ix_ +t$5DNxt6]xe?J:@!5wԬMDu8 cKgo*8m]YVh|N6¸9nn󌱖9u3Q/311TFKY=Hƥ8|x ~Jz*1SE cqA{抷%5PU8b\vkO*rP =Oı#r7CQ-%8tu^6p5*(#]x~ Ȍ ȹvM^I3m:{vȚ7-/ wfw qb߷)c66 O veqg|0$.8W6m;ݻ>*$]`KF@E:so땂B?v,xfv4o`ֱaBQu*Ѓ1__E3dy(w=`#E3{ϟ5\2g8-Rzqe eɔ_ݟ^ WUIv4o~Hx0ɕޢ-B~z Tt,]8TH4/{x!nvߜgRwb(Y&ĭ嫰z3JH\O|y6*wc|OMD] ]->Hx§}Ktx^YUGA{|ٹgjیTĭr +Jm#uT@1LjZhuPe srhoV\/0-rs̉b1>*0ښSÚ1Fp)QС}2ZX}Dݐ;uԭ XYa5(8?z6ܵn E_$8vD!Txueg/͑yUۑˈ(0gC`ci *bGa<)F * /2<_WJuQcL}7|(׎$3q@0>[RC,.iT뛈1$DNk>(AGA.Wx6\yji×Zeq"'R # t#Kb{޸`҂dr=6mi߱gwZY89}=\#YjLlg%?#]#ߣXPb2@GvJb8_ۤ6^ky73b@ʜ-uJ #%kF~ +6z 1deF^ {jo0Y!Q[-_>"iW?>ΔUPzw/]@HiZܛn?JF^+ox]6ӄE2;M>ώVI,gԹBAx+1r^*(Ky_dmDFZۗ9 +h|G*+g +hEW#tTވ]~ )OEx BXUڶ'x%MX)x=b<9"ZQ@ 3˜Gw\3.^FIG +S,|`$+BBVRQ\iJZJXؐBmb /J*_U^OG̺ŧ2;xLk:j2e2n4 7_ݺƸzo?z!U]/走Km\2' Dt:6njݿG`Rq{8S{ p +O+XiK:k|ʐ۫xq8>ghTChOz]X@2dL]4NJYmΟT'K%O)L0IWOTٛ/zR[.rD,MJ≨zZCBTK˳/q$k(bWn~L*fSxZuBt \j[CH,4՟nF-%!v릗mg,|QVF׽g,@„T0DZ.-6a#g@yh쫟GtD^@1sMAsXjb<UuКk#0-@%&yu/9;Azl3v)]AU + /#\hH>J>>It Pf g'yU4"r~BE B MO入 +_:Q<uG(c>\[GJ˅CeDu>nǂǂn s;[F/MA5<mWGtѽ$YU~oe\~ "ҌS4M85MNk Ѭo0GC j&& @K[,HA%ݥtyjʂTgăh +cP9n$Ssk_} y.gH3F +@ך:Mt #v-T~9PE9C>nbS s/)߬8ſ??ǿ_??_]~7ƴМ"TqšI%{HYYKW8l<a˖woVq|90XF m? σJ)mey3vn^.1/Iia.%dEPSZȁ~2uDdX\ֵ 2Jy4rp7{ٙGA(λ@^y$ +@CǓw)Rh^khZt %THQk̤´'̄{ n}ReˊL凂eV7E "Pzee,fnx/)n6M-I{ontq^Ӧ&f4攅k\a"Rd\2~z5э o53o +- +M}0Ϙ:SfwxQ$Pխ1x9ۧ@V`M5VVʶBp;TbYp1I[9:3SJy{pS8;NZ(quYfY>ŷR +H_X>FkBI "jc1C"G^<DZC|ʺ!qeX~㙉MzJ~9eگ=' ٧^tvW8D&Vw1|{k ed9(d?];1Ъay8(Z4%O`'>@\e1J@ۊBõQQ;g$W9x _KP a2f- T z|j=ԝvAlh/O.?EGkDaxB? P߾Gc᲎g˪~*@b*+lɾaFGB̀@M]h@er;,}!,#"&@daJxa?FNXgycZ+ {)+I?(D.6 0z{TQx7*Glfh.ހ:tŗ(o Mlvϳ>"I#0ZÌn ^ Wv9b4Htt @i5߁# JCDTcZWCb;{ZּcD +O'C">d(ȯxW@gظx +T> -0U`v*Œf['wא5K6bA+|D!)j ̷4x!̷C EX|S\1SٿHВ<&NL]K'73btwS^eװFZqc3ё$b!*S-Zvz'dΊmDl;2u:1)Xtnƹ +(w:o?@_> ՞yρ0ULӵM8]S{ TI_8nԆ֐#xJNF>n'j̶+ST]ra4hu`^bܺl +mL߲ /ZjJ֚c,."67'0$ 0#IB 'WPҨ6upRxS@dda=g:h)TP*Z+(J[DwGiz{8~0Z(4ȃZn&lЪ0Bv"&Iq] +Qv,jWס.IBa, +"琉vHhE ҠiKߒ|Om0+wWOC}*>kހLtE0;Z/܀ ~e9-e҃SAݠ#9C#n2 JvLj`D{8d5 snk)΃CJk$|~Fi x5͊H!zEHf:)*g W[o=cZm1!:Noū!~FтX[ffR01: fn=E +AyiJܨՀځ%&'с#f3 !`E1۸'N ᠑AJ[32"u/IaPe ĥsi3QJ-QH;Zd Y)oܭ~Fټg<"EEsx!#QзcMzL9g%)$o# LA6( Zc~!Lv)06e< Ha.z5 (uQi>/n;R<Ka!OTQ;BLj(-6ՕI{j͜|{G VvEJlJ!ʇ'inׅt~ݩs^Fn +Z70hVzD+&hTIQ|2zhx-EYVFVGԍa}+]sOK~ Ky7fN2~o)CR6>OF6)(1E 4"brs]DC~SSQFL9SL' &SǨ AS%+kĆ׆8ֆMʃGus~F~d+Zy4?a`qlu. #Ia~ER+b mTpqzUgUisle[-L-1p7GX j8 +QAU%i(-v tO'?(a'Dح*w”pjT'G^&J ů +x2Y & d+ C^k\:bG{\)`AZe{fY{U],= +tPvFocml|biJmXj!|y#U* +Vcf1bŽ۞ nd,eB6 iĨTџ;Fy%xDH^ bDLqB*;6jEқ=H<ٶ֗f~) GVnȘn#`"E(^hth3b6"1JXDV+q?3El5M55| ViXa#S҅@Th{Q%^e1ݵ[;+oAtWz2؅MCo*)AZģsOxi$_N!߇EE,G hk-2lYE:oΑS]r ih +#o< {:SQh^^4W#\CkySb0 Xa&^>bfH@]Mp A{ş rfӇ'~Ͱ8 $C6|UZ*q/eo{4,]Ut-Zwb!FgaDD^uHG{?*6{al c`x_Z/K:: S،U6rC|+$tFub*"|0D9ϱuV6O!:dH$Gh8P| H35~'q}45SЬ0}8|uJp{<) :4I*Z--x^6s&႐??+)\=mĎ,%Ax +DZ].J5GO^.ё2qFu + fS ]gs5# PQ`=}ZlӎaXog6eL ejHϵʓ>!Y&+Y&l(? 3g+h̗Psƿ8z1'P"悶losw.eZѲ Gc\:Bn{I=X'6tMwˤ&. `n[ZEc];omP5{m(e98PeVTDr# +7;"SfU>cpP[7ۿR(Y(HDž  ,v M8ӀΦiYADLQǢf՜H&!t_5u(%X]*MVe?s[ͳ}B`P(Ğ́GiXeX^詓lfWkN>DB4""3ZMv~ȳ' Q.`ewnȞnS^X_i==V- vܩ*k}Pjjtjn>ow@zti}:%E1[-ʫaO1 Tߟ8WR]AL_N!OQ'=m0P6n_ + yO5Dك S1BoDzn ;[l.2]]J"I4vxSYU =?#TgCOJ D4U8 mi*ykYQ.h=.*M?RMWv]UGӖ+f*ˀG-t< +|F6Q3 +"K~SPP8L S}2 k8%\`JҒ 7?H߾z/JQFW26hVkڋX$9ਞl*m!H\+fd}\MA CL<8_!5oif@iGLEe]b8K4ţ{ozL@J +e{ْ1ӳ7 +5j*AMO/$QYý"AMxD}6C(RX!WRjs@mK[s>t;4e G-Y8pݯ1SB}~[6Zf`$X*#!䥾qvMho`]/>R)hv* +tyfQ<@Շy@WDh_ vI+DT8Gac5F9pK{6Uū{B_*~Bˊ +;*Zlmz' mR_،r7TXd8 /9#b~YWPYie9v/`qLJ M=yW|Ί-Y,)Fj1L} gU65F${5DDC*rA5[ch e>8SRsfN^УWoB0{)sW5-3]b3#zÖ _.rq9m)zc誽uv`ZJ'8x&Žy%ЬRY%)vO+%N>uug>EyÓ +b MqšԅT6i#r`Fܩ|]DPPקՈp"x*Vjp1n?޳OɔU'pru:'K 0XV@7CKV(pހ`ц+F;dp4^_+1RK u,^ҥ|33q(,~4=c|tfB+xPJ<[¹Ϸ=`jl)Gx4EtX Bk)ry- +_N@p`</ +n;ʧ1?>?,pn (=mwsU+d@"^^S1Wmt%v8^NEc&Z@Gә{d\hz+ JD% aS Jl1 +ӜZ΅"x0CWyj-SR/sa~ᕐ7tDYwm&@%Ac5u oo[4N!#tE5:/姏Ȥ+n؆kxz^h$0WICTw>)6dLJkM +휑<M=wUqfcΣ9h7~\j<\W-½XLM'8r;['@%(`8D2L5#x#:5! J~ϕ>J1kL=e b(! I&4#ըTE}9{nbDv =3(a鎠fD?Q3ڝwĻܻpJ-t?爟PDDb{!´A'C("<#ƒ8lTˉ +S!hi +(_ݛk1O @`^1nhȶC  +e hV=qI+P<,iPl(GWæ{W +ŝ1:}# +iCA=MjRT@;)5C0skU<[yy] #=18iy답}׸bFlյ5"(Pt.V7-,lRWjl+-= usg*5'3a> +Ev\tV`:x~gE*զh.L1#I[FS֩L ϕ`x-80 S=06ɉ~Djtۊ\ni[ `J#FnIlx{d t!B2|踥kdz̰BwwCUD S@:caY4mDE֨?Y?|DuADŽXk9qo@/= +Q_(ŬY7v˦FbN#S Z6&pEWŞi0Pr$#;^x:y\@ ZzI]`,6kEhG$}nRBF|UsLUBcz`)ǁZ|1dD` t+o-=Hn]I} #-:!Jj/–S=^~6̅qU. +1Ţ}C!*ǘ87@=8d]zDBqL0NvyGy@*PS hxiG\'"l}4={3?qT~\kzLre*K[m[ hRnj*Nds^UΣVGw2y!'qP bRK6 (ZĬ{)YO 轉偤A;P1Sfa%8Ѧ3}gݞΖU˾Ш$2i-sml WϨJ]hլQ-j^gHT*vzJ +FG! !̡;VI<:(lvFegMO[1ĥ1Pl@$>9d +>Pq8jvֻB5goUUoпD3+;LQ+`T>IصYsgG- +_|X))_~S.޻c 1 +gY{u'nJT"FY,ݓz;-> ˽*hV咙NS EKƈbwg)άfM%m2UK3#(DjpC^85u̗{N)"&f}\7Br`4nEIra0_N靝"0x/Nw vDM*n|p VTʝ׹?ό"JY1T l{1gIrf5ӘY( >8g뺍0$Q #ig^\ 5虴@~Ʉ^nl?L9&傖[jb5}|89!ͬw U9 KwG/k8?tɝJonO싁{M=bϕD]+v#*YC5A,Mm~sz=./jU~|nlIk(HM*4yRR_ÊVC\&IVpV94h|\?=Ms^m&2M{U2$85Z.@SgQ)7V^|~=AV}u݅JΜ~)l%D_WOXаafEu\&\e S~1]\ϛ5)hqoyVYo;@uH9 |r +I@ȗ) 9X(,ҭ;$j kDjAtS|=.!pד ^:,N,IUɅ6Z'h} HKۗy"Q9Y/v3]^;zthyQ];neuJ @:]`C*Sh@׈iֻkI "57j0\Dv2 O}zӤE8QOGukgvpy\): y(GDpRTG4*iuZy=9OA5?s%DФJ iE*p2>WG#Nӣ,Wf2 ,Kp]E0# Ieuo K./w`v +1j`6| +"7` Qb´GaYt&omר@(ɦw*pXaCj C(1lJSm &aM5D*tO t_ Okъ2l$B\GAOL8Nw6*C!;[nڑ#ZѸctcy:d{xcBJMyAW3x3"}Js:t3KwbS5s09Àz7;MJufKyH@C+Q#RاgӞuWMH/AM`K_`9]aG=a;V {Jg'+X+LbO@9LJJPY5@b Ѵ/^7rh?)+Rrohf'‖ T ٢}1} +R/ۜhKA ը5-9x6S|/k<F?=uy׃H7?מ(,90L>OdOU`>g)~ oec ضy189.8V`NC +$W7.zMFs>sG=hWjXA!Z&y׃J r`% Ds<A|O%çjbw_a縿`_E' +:KȹOO#Dr1d<} Q5_ d5B(@\> r|[S zg k=I:n +8U| UJ2adѲ8 h_&zFsόߕrP;R%7$!suCٹB.-F_cFRn+sZJRڹM_}֯MK41ƞvL>}d-ܯѥJhn0R_L6~w0gYXەu'Lsw*!RXolv=T_ (W-7UN 9s 6H`Mj=2>[pcuy/&09p/ ;1A:A]b3@ s&(" ;  ja7<Hh7dA R]@<@J^VC %ģV:NWD},Kl441W/Ih6o@r d%lg +$ +Q[ +ywxj30l߄8 0ϒ{fȧBmOqGwk݈v +S_; 6Q'$E|88L_#Dݶj:Î[n\單>8{J59`ќ*m⃘qܡi%>ܑ#1*ف^l +Y{&"RCΖ~͟M (ʂz˹wlÃd^*ou_G%t8Dh^*+%}D`+g> e^e(71h<I|Ndp3Ԫ4nA!3gyz}<CB ƣq 1D8m,)qJմTQO<u !ae_C;Q0O[7$(yX(y.~sTo]94kx}䱱H+Lfk~ +Oc1ue񡷡9<u2/P6v5Sdb_jv?Q_#.|F%*l\pkXpmcD,430k/U&̍mt`d_i?+c/f eƶ4<q(YE1=wK>e$"ΒXt?QTQQ8ϛ`k];fDM*t9Cs4*ƞߑϕzx[&!Z0ЖsqȝqTKMpl>^>oTOT#"t;*A5%@B_T;ejRv-P`_)j@Ft%A)(S>Gt>jڕUP=6E*P["--[PSSDLQ~9$P[ U!`t]E>"*Bw>"j@n\-Wb">ʡ +e/:bA[E~s"{I]AA?g+Jl REO_ybSanߛcٺG ֢5"c}"ۓ[/[}oKM_4T?콡3@X<kx {fՐpTL${̍Ic?*q`cPX~ۊ(Lc{sw~,҅*ߜĽD\:_"ˠCd/QWEq2 NòhD>'M?ɣ{Ы ^hae &sրGP&r5#FX; }v+1YkDѤ{g_)( .e\J4BLvq׫ƍ m9uPV.FPBՏtc ⅺ@[ +kDJ+dqŎ~謌R _=*ܕKTj b╨{% +c;s%wk7L<[ BtV\d"UV1@ w%qJXJ%*i7aƱ+nZX_qn_/9HZm+#gh(vL^ӔJxeyyyT msʲߠ>K_~Jx)@﷥c8d\FC.?@j u6g*R{d(HcԞXTIvVTlx>$< +/f64Vlk.;# G s {A*4"תd +Bs*<مUlcAw?_XO?/OOE??}?s4 IkHc>ƥRJC.̙{ʌ!`$*}r=GsHLe*7ao,4CL4w:pFR5ЪЫ~!l fTWsSV}=Et< +}A׼hGJTt\ߠs jf؉R?Dv&ӌ{g_J@8 C`A0 9?=& +83Q |#:fl*Kso%aJbtJȅ^m B=7v'FkEIHę}wڛ!ߴW_#I @ ׻_zW_b5{bvA)Ohur SvWT;- 5oޭAӸ[Sڃ_5x>e DxEë7"Pex/=3SVFL"& Q&2itu. yeEr/eB˯אB[B%y&hi$}x,Mr}D15U)U҅Y?:{ 'ng 3$_1} MρF{lB@st7{1I4^WfAxv\h Su Txj׮~ 7-/ɘ]aoO[[NE>ڣ:^v\yhsg/@W^QrSAULjWPt&V6sL6^ '"`x*{WZῇGyB" FĞ~8vE/8sKu4/D7TmYKk&UD yڲH7"}è = +cv~|R^]yJ9PAPCAJJFh}9hNRPv/)  ɩȒ)©2<=܂!-~>Դ̟ݨ15j h@2NSwݻ+#?,4hf;/އi عKrVWGhc ŮaL 1 z-j9Z35 nJ}+mxkdͳ w4-Pz[2VtRE_`;#t +*jMbQʝ ++cݏ(VU68(e/`€ 4!Ie!? 8Nlڗg_? o QQ:Q@؄澞_"RDfyY#M,׈uɃ>Qx tq>4y+HлRK|n+=Yuj-F7ģ⟟q@c?DjMc eTߣP}zlb&ҭi],"n) 'uKq꜌'"uRw!Eiu'+reʦ^܈e4S4TnA-uA؟|Kt͘*>uPMNuAqK͒q{( οCty>G5Uvda2ݻPPrlr<"UA @V>@u\Y[M$,SL~FVIG 䲒L݄L7 @AJ1kc֒2u:Z l0TS 7!2OdkNpVu违Vt[i Xe a5W{ckG/њBT+,.|<"WΖ*9d_[O+zqr5hj<].?+*Ԭ/&%I0M qyUqKr2kx15etJ,K{Xa0Kwf7':egu ;.f#wA|T?/te1wsr}";(:?1& endstream endobj 78 0 obj <>stream + H0Ӏ@z)%.+N̈́D :h_AN0uyPOϏ$;~%+v#< wܽGE2LGjXMv?\Zs<$#*Yr:jn ɔ&].yIX%K?B%}syK ׽DN8+0ptP'1zs=6iD\*=Zz@VI-5oi/5v54'\"@7A?8'%TC+y^.(7{xy1.ADay@ bʅl^W!#m0{oJϙ5b;y)%<;be]JXq +n}ds Q6.gNOsS+wj&!2E Ih2$ S +@8U6؉Hun#Yxۏ|$DJObTNSt p QwA>) Ty~`D^ݐ@˘j_#鮘oNRӌ:J_#"}F.KT  7Xrt5śDzmmk>LFd /v{o +Oce_ NU/Њ3H"!A8>N\FuU(}sJA }Ǯxbuu'Iust>O1;3`?]ܥr + j摽JTyMB0HcA@kB;Ws,#K1K`|BfqP;A:J9f5 u]DDdM[vHlyE+Cfl X-/p{}r?B7Ju:k#ӶjWJou_ r +7lo"`)ثWOyU; +W-s#,9oV[#r{וd\YE;&ޛ(-6z5Q,y@]wE}Za2ad}#T^=_39`< ;# \>>wgk _b3$ak-b΋ EۀٺHe:⬲8 §غ/3Hԯx[jBDynȌ .;EGKw (\)0h:lgi.e}ЅXCڳڅUia4wcHз9>xڳ.xj/F8IPVl ME4 + F&t"x7ho@P.=[) % f>}PDp~Q 7 n9% wx]jQT|oUEC \ owy newOwYQ@]C<"icg+\Qte'Bu}DsTNOT&$SI#6j{z ADWODOmi`׸( +R%oO`6ӛd:x]z kO"0 +hO,(C^R4si,|P{ۃ}"NVDPJ'bY'W1;BwM*R;yةzJx{ +ǽ%6yo (X!DTR!H}lbivr`=7}uC~]IZ\Ξ45!aw{W@Pˉϒe! 4y=sKa 2h1EHn +@(y)ya"{=ZG<ј󕢘>@$k6}Dťӏ#r5+5&> VϧQHDXA!H y8tEѝ ѬgbsF[+e@LM*Ji4؟r_D^\``҅CE7}=lẙ).{b5 % DrY!dbJ /IzGnǗ?^l^Prĝ),>EW˴Tb_"PyotŸ( iSa[+#8?poOPNI +Loy}C}[VofR7Ry-][>@k@c#c ݠH ]AsLۧ G +"QW97|C2V/r=%i?8~o烴0D{S@F~td{^.WӤ̇k9OλQtL(ڴV:MÃ*Ev3dbdصL2{7_ z[$9J`Lݐ1C̯J si',`}lsp6hr @"k,`$+0sBqz(!$G% S\$׈3m=Lר v0\z3] +mqs/Q km<@NWc3僯d yzLpv &Q8^{9*F94:FKj;jԑD: m,޹d9%p]o-jz'] ֒ރ^8L0j9ѫx%K q-~cv*w׈I{!-DɰM-`4t}/8۴yqWMR(QH2QPQh mW +9w?Sd$-=)AӚhN +ů{L.I5L` =Ut=pF}'C{{[_H -irtg(nM` +M=?OY'TՏbZ4z4weCu;N_@A_R{N?(><;%B"ߤ鑶p=7 WrB~{7=Qu\ CWqYh,dR V{Q|lv\a\w*j0GXPq4I#.9+@b>¢8uPGoaA +P*q# +>^I U<%nNa3X}G\eyQԨ'j;a 5DLBۇ{$5aJ8n6g{4.!,|ڟ&0T7`E$(ﮝ~顔mmw +>eBȞau!bʌ`oF,߸"'PFCFI3[r" /C>2pR(dVN `djohhz)H;X19H @T&Q+AS15`#MDdpdXvFTx$?-I$s#/D,ðT.:fwI][@a>Ia]70PHM%G*= aN#kٲ9>g%V;p.ՒI6^vWVܼQ [6FϏÕazȮWGD4v_$=L\@O}GGLVw3#oـr}vhXwK{;~e 4I<.ziK6l8bd/(qQl~/@d1D,UlLbLddiKd {w =pHoW(KIO\ a9p@òBS"rb';Ь7,8bXl@Q +95o>ilh)m:ǃ[N2"Q  ZC7OV#_b +I>߻h25 tǩ'Ȯaj!B]C\@Wy +~҂* t:%7,Ocosny +6;q +7hU~X /%hOM,Od&oJ +>l<ب>BLnԳ'vRvEUQ9KlZ8)ڬa=! \% DJy)F"p3 |l May5&uRwa9+PyNl~!`;nC.ʹs )'Fpҁ;!{K^5v[A"+(uu~J QiTE(%jPThP;x6"3S0#\hwܐΕHx9Ώ'uVEc-SINMg?a pzh9}QE&эrlj +3vjMQZ4 TTehDAEGWDۯV{s6ؚEFI͊GsAfIW;=+MG|F$B +Fw\gxGL.#8i¯?%xM>! LS>kd_H X~ b5D^9'N{Ckk*'\Mi n7*JṔrhG~|1qSg45q7u?dn3:VXWW8etR kYYgʢX3leB|9,dW"iA1US +i82EY[_H{p֓$B]7lm?AdmrVQ0#`b7t^(]m:Ae`! 4;C9*TQB=pLF:R}YJ +4H$>j ԢdUNnCcπCDөDx/#R5BzAe5򸅁CWID;Π% Y2j3쿆3ۻސX1NFmuxH 6\kp fw?qy`1 .Zk HHtQ|QEiFdfsZ + c>UWJzt]̺"&VU^M41»M }9u<4mF'9ջ}Ge']e_g\G,d`H,|k[x,>0> F,GכBW QGU5S󮢵Ls ,YdC2qFf5ǹ@.-ҪFRև4jȨ׻jQij61\zp0cvC4YR JB/1̙/'Y g5PYYzB D"}ɹjQs݅@3m!$\O)T$שPR`DzXF.(/Ӂ]X`I7LIEx$)[죎H]WQ)i! +Fz7~GDD덀AJrVoJHKJ_FԛQp5 UraovRzaM^gTL-r"iZvG+n5nҬ$ +{Б_.Ň A*8xH+2:;Au n<ݞ&T&0ni!8 +KC(ТП('Dy4 +k˘RY#$5~<`$ +w`͚v!wb^Bm"Ń^nő8YJX[Hʗ2=!t,w?To¨,UIH7ȳtxc Y<=%:=j`Q+yLٕ_q/ L,aAI%qq~L L]^S21 +Ps"'ǂ 4,6,޷+ :$;؝vۂ^[8ڪ4CWv}uMAX~ziv>'Q%4U=V A7E Ԕd6;Kz"%gWe4D$f{1 +FKi3_!MV_{1Y.=W{ev=.& g&"D ;}2րUtD,"#=tj/ٚU.! h!j9EBO`|RRI1A_&B *VEb4󋞠2TKfcL!6Q! +\d4؂Z*3 9r"ld3\!:L0 BԀ" ̿FŞj] Ԍ㙰sOb3g̃_ͨ34^Pb?4Fg")NeMΛńqDh 3 +_ܲN>rQA]$>B7;z@oubSY]2sc+x%>$0C!Oh_#3^ꊰ[:җol!8QD\dFұ{8VFrs +f &T52$4޽R2n\Ӕ>gRaL@e`p(i%c6RE\Y9fgU*7 8j\^aK጖dE\CT "JVSHp/w +8 K:>u}OjB>6 wmL $y:Khu)1ONeG<e B4s|>Y +vdNc|)#tFA.Բ:Ziѝ@QQ2 %ZȂ"%jhcSϳ#WQv4Y TUJ]xH @wzs :T@FMsRi zpi¾bV$[U>y8&.p'*]ZRxl٠hRy< uըQSdOU+|Ä|\ɟD_(SlG',_zAn3ΕA nh5&',*;G>?#%DΧ*^~=r*a± ."K^R' Fm`=0 ͷb>+:JwtG zǽyk ""{0"/ZǨ{~#IR5R1==7͎EnۉpK24*+ CQGP)R +vAoGYI23X(cک`GhC_ +*WɃ{I/5=T'/@،˂^bBC,tDT uQ9[kHQnXna$lEY &:zE +ˣL e&H)#k79<;%'F1- +D9rR ~Ó^l{ɍ?C-&B=~|6Y)#}k3(N5fxV0j#Xl;"N8nI)2!E> ++΃QjVlRSxJ(O#bNI6{_ yӒ4J$fD$ݖ`9(zOw@[Zqq#$B&8[Zi65雭q7rlINf#af۳i6_~PVV}]U + -&=T\T. $ǘxUBXO[QO +]gпǪ쩯(v T_ ?tGcBۨ=BEy:m=<Lo +w_}`J?$ +#"C?'Q,#y'4R_V~H6Wi_](Y]gj09zwvs:F~8;Zk4ϙ["[ `!FuDЫ5Pk:ByUR*wJE r_eA:!}aGP=Jy9׻8d"4]u`OfdHaܓS cnd 9c@$bTTj`$*BUںJcј: }X4`:B͎Vmw &q0pDE!UFzӏz,Tz"h.ǣYKΌRSY!>O 4wE@e;sO]MH_rZ,;zh|NQ +\EAA5+񐅠sy9Pp%E~6ȑ{_+?MapM,-~ +W*}tO FlQ̤;Hvk|OǺ^?'At"-FʟìA-"9iO'"xcԌidưZ6z{W%!}=K)y H*mu(=[sd*<ͩHOf@h"%Fu;q{\[N"y 302*FZ䀠':,盃t7f~z*| bx cMwM"H8:b9BѶXAؑ= Lc\WS:6W wG)R꯫/i#j5D&٣mw\ru4ʟbLWb!s0Y\"!J-oS +W'8ؤUFhAPqy~Og*!E[:Q:@9ՅڕQ ҈boAJTV6CAU^^]/ _''CjX 3S oDDR%"'=b(ŨET)R;"9ݨ"D-pQ}"D!v1{q\1=.2">|3DJDzy*\9[.tEʉ`"bzeI1?3 +G-WDL'Bw}HeYۛ 5k/ נo$ ~.e~e-:4q5C]qLmk6K(2S5j&&.m#Ho))gXG7)}֚5m yrsKK% +g#lm@$_e/Q0D׏6X}{XZϔ lϲmf:i)~2 !&@ꎈgɰu4T텗1[A\)\Ԩ!wƺϕHIyF5=?697Z}=y]t|;I>OY(søsSUg!kġ.+۾/Q 0_ҭ$O0U3>}Jנ#,h=[&zO `9&ڣ>B/ri68})iO):|ٞ_&өi;ce7GO'ַJ##ڹ%j @$k.lޮkGSVP;ߦHT{wØRSuݴPC>݅3L(KkkTZO`vucS@؆$b(4iE6[8vӘc:RëLgʇgU>y4 6RC+})Ƿ[%i;^T`uKs>ZȒͮڙ|q3e/~xgwZ0oW += dͦ\&blk5wp\39FS5xkpwSgh`׋?ɐOZWA:cݥ%OeˈZeWP5DxD3$!62C5C{^GfgAqZk# .1!9^G}#hwh&)!@jDĜ~Vu=m/"c^fNۻ[nk{:nECC1^_Z#ϣЫWom2[IoQjw)WH"?:xCiq9~ɥ&Qh2]& "@w<.vQR*MAU;P#֨V܊Txψ4M1Sp">qax)! yYqr-7wEgMn б=>5ClA)[t."'rE~ +iUYC\hsKe,L-9fk=2gr綕P}t|Pj U xU<1DP.-YpoJ}WaHEwtTZDjH:)>޽[.4)bKۅc]?M[}N +0I_JkDԺqׁ٦D]yeiQT4.x3An[[z(\rw*@3As+%Ynh-F`7ݞҾ~`ׄh 5㈽@jӔl6VN$B>#~t4 o3C]^"mvn|BuZzTQ 3U<a VF|UYy>{dK\֚ttZѹ~2mܣZcߡ #vq}#V)vͳ2B,& `Pz} :4D S*ޞD5Lr#t!]G6WMG~;KKKFh]\Iz[ %,Tg+XBS-%75POpc{gPJ"(V8Tb_ݥc*TP9wcoWal>/jl=5IWG*)1[/~2BYM6gt+C8˪4qSw?l8MV{ >4h$v>)G,?'D"Ew9mpKc}DJ;cG?*5g4VMX;RU9<OFRRE7uL'|=d pk@:mSOge :e5f1^n[1*W+ѨA!\՘&M EX!18 @4d3HJVr"姼vD@%"ʂ)nS;QS ôk+5؜ vʚ̩0&3"t>(%XCl ~hv%ZPǽ6eQIVlrk9: ӔJ*+dMU Γ$Kii1<$LhkwgP#le1ƻƒFc%F֫YH +!+GT;JG!Yd)ϨBz~`&e.'F#M+ŪG=sjLN57),S +5]badˮ)w6׊d:$_l@!:~ivǝ:? y#k +7no4<M.)#^c[)0ZFLF4dw96EZcs)ܯ~bw`% RdeHW\N։ +&ylXQ=3"<+r7%z+iuPնkPXa%6TCLY<5# 8gԒߣָc5oWLx (zЕfnӠoOǂmQ,z{K$sb:JEŵר5 ]/PI:qqq$(tkY{F:;WuthvIwCB"j̣IxtX[/0񠘂݀Ǫ= +ڕԘi;B{A_wC5^/ jTѫ*e)ѹnŞ\~r:SRguz71=lD/>, _Į_Y1~ſ???/_??_?O߭Ctr ~E,?PIVv.ɽtd-\ˬ,\{v Fh)d: >R*e_U(XSoO`Ug5Z Qb){|FUŎL<ڱ#X +54-⋑O!TG4oWDkb}(ek:s/*2&:ibH lDh)_z"}0V}]RyZy[Y,6\,4~ȋ]"XD(a5{:d6g,+2#+dB4DOE +q ?ɊӦ4WUl.y +(P8tNoDDܵVvCyktm[NƺE o:&.DuYP _JQT>m蓐Y(>nA>D/O5s^w4FL-@ZTR9O\tXK U΀)pJ:+-]x.yU}Z<^e=z]%4Y/]Y T:>7x_E=!l#pnCн/1tu# kEf*Ӎl>g׭hhWd:Љ׾6mCnHKXM%TIND1k}H]-o3] 0m*w0R YA8T!L>(Mz$W߈)^5XM§{GBgُ?3Lctj&#!37gR;=118țH;=APheBFQK֕$GӓT?y6)e<;70 _7 F}(R,[̍f=qAh"Tj_´ ؈:0yn獇˽֣(0.pE먎]1]=[s~F8x[=~*%saXu^ܬ,>~S#PUk; +"N}T2w41t(%o,أ@(+NP*&:6mQ:i[D_"~Y3U\'`]2nׁ[1qD7+v++/O]P-+ln}-F:=5|{x +K0no+!_>{ڟiEff5=}Djak=-VLhݷO= r=1gev3{s*][GE_*-֦hyLq m6?ӶW!ͮԭ?7pfYc!V7wK;Tj^^{FUɍ #f׏o͈SNA)"Ӂ5lٞ'P YLsSk QBB'Vq[De I>y[F&0T{iQMaDG5PϕC= M̧AcGo=7t} ˣVp!aE؄gv.|4Wr959I$<˵嘤ލ0̂i1ɭ@ɚJ_\wAu5>+uA }?MT}-.k î*G@/690"tA +{iM837HiVjR~"hP]Ģe53SFʫ;5ce] I`l- Z1Us1ހoy $u;{e`i!ѡ1FE tdJyHT"XwJ.~gBR9hdf9pfwl-#S5tV"ԧd !׃y#NDI\kcZ +PBN_So] +Wz)f?bb3XΡ$ۚ2-Vu>`+erdiaE@DSEb'A)B;Hupa ?g38ka|F -^bocߌmMuFꈸ xHmu ,od.g(&FiH^ˋ]m"R}(1[ :ǸuaWZ^ bx޷a!rf?7$KO& E,4c(0qYy* 8M7=DU:] 98xF%Nw'̚ +DQ b#HY}EɜJr"{,Z *E(?b=_T9M7?oJ9JXCcr~0cʻgQoZ` NWF#H'~qj_3"1q~ϝgθ9T~t3}(vOk{}HBGQCa<b,Ixє -?71]bŀj<%5Qc"u:B a;a="RKȫ!M9_qԬN +V_ۮtLoˆgch"|ۧf*$Қ;$j9gkKŠЙ l1mn2޷V) \SaP9)z*`!*觑ŔдC#A584n$=g.R yF^ QbͰI*!,As)ӋB?כ$vOYkuFD8(5)`G'=շ2Bv;ҷ;"ُ(t^VKM"+W:U;Hq#ut%{ӖMv}DYsKl=m)4zƀ#l] SυW]i\5`XYvYK9NSc]i'*&|i9])lφ~6M h5ms<5O3 ";9z Ba|1Hvr%Gķ{TM.%xk?dQwKvԪVJlWnDCxm}c>݄uU-lli-9O~CMm)PXYLokpTkkb d1̀v~m'xˬ@-M(tZI1R4/ˍQe +??ZOD6 `5D)BS]? Mz[StIGo9't&trgdZ6[2GZIz^*zR볘)Jh;#ΏT ?y€cVF&4 +=I + +:uԩL/H^Em[SO1P\;xC%M\O? F~ =~~ +?D'$hR9^ܰN9Uf3Djw]2F!bOmNG u;h[weZ~+qU.@eR@rd+ȼ4(9UoW֭0٘%=|Onw=ywtQ"g[X'$` i5DŠ4K1h]I:{W}I:8"yNQuݑR;둇=7s}l*Hl2QX)Dt5Yi8 gT#H9>\:Tz6ş$j_V> ĸ-Wqnf+hi+Wrc:XL\ύNI#1Nq{]Tnn5L.ۈ *lޱΠOkTD1&a3*gNG ?J`Q"G3rZt +L2|_+2isٟѰ"IF;B0fw%|kSDȤwm۴neh7Me ƈ`ſ[k>(QOI4R"z߽e(d5]S{~d}FἥmD{*JؖSKK]A,A^LytW=ݹO(u`([7 +.1 :EAݬAb(i򠔶Ň)%+uqAM^.+"~s%O! L~T0r{*Ii[t-kt-j8oZp܂ߠo@Xcxx&V`QJGл2,Ng3npsX`q#z+ 4vDP%fbV8!NuXk $a{Oϰ&[EN9$wJ u3>}xV37@1)Yx0НݘztО]i8oA9^csEvW + ^zYllOȣro{];DQѥҏ8tRY*+,{G$05kZވA5&!+(Ḟbt5%K2rzcN\CX5KR|-W|T$[DOsC˪oSOW 7(\v[%v uBq Ab_- "{'QTGPƃM;nFeRb / +i>:4Պ A~ O,6+".#kN#(U Q"xͭE@1ħ>@pGc1J~s4U70|!}̴̤'~V @xiU\)=3]cVTnq{}>v>0CnݨRc?Jw7cgDŸ&P?ʌ#':7u,xb}'EnY?L~(ފEgtSCu95ְ [( !H`{dH)J6;/ I#(A@e2d 9TfH?@#fHTxmaQnMiKyZ'@{*~` +m|#TUQ~zӥc5 9jFXL؅oo"p}ׯSg(m]93hfVGh&V=ew}}V Z+OvǯbpO\_mAV&q x; "JY;d9=ݐ.dfw ^FHK*:(6)'v[3:ѺA $./ GҴ0/kzYVeW +zfTӷ~|h2C^R[JD?%{PX"L@䕫39}L(|ն:!?LG?yE9B5Yhs +PN*@ |SNƬ.m'"ɥ5:K#c +JT_84m` rP]N1+ ?7De]$8+CKR6y4VUr* It* tتOfԱ7jFei=µpk;bC%a˩C#tNLbȺvOܵ}⎾L(= T6x3*jɻ>X3(43%Pl\06 Q)NVDwttޮ +*Fȇ^zs#B.êtɻR=lܛ]ynv%/Kz*zljੂSԒEEhrW- k ]^ˈ>!#RltހLEwh!\-I 6$5YR jZ%7Oq_NnHljʷo,Ե5Q{Roe@u0yv{iLA&(a/$>$S,sׅ[-}u$XP>^m|'.nwnʑ&H VeuL}}M3|i8Xlr&'R +ܸe8&3 TS9"Ĉjl'r)$h/DblE6ҝdvIj[')ԣw,U5[,D9'Ր{>@{hsE^Qѡxu' ;#0bK2vt<F/ ͩ]q \ڋ)'p[&T̃:#ǀޟ-.]ZPLK\]G{G3W?FjO@&ʠ6ԿQ}Pf6P 84îECV~pԖ7 7fHx~PS2*QwQy*R$+b%Wax]}ׇzoT z%vmB-t $#o sUu/T].[ʤe kpLŃ9|%^\W0J~$*c5$VY9'0esuĚF({ٛ"2ò j DF#^!:[[vT~^ߜK"~`y +n( i.۟)ۛ^q^{i@?'vR{6ݧh@2kI}n+hqtɪ%Avwg%ǩA}nY8erXD6fY|5;su7礴RD5UgM+B8P3KHo)^ʳ=V*T”40d j9P\̀=.EI (͟_=V]QXs@gP+u>^`si{l*4BXV3Ə+s8Oh<*eLXE+\H#>Xu+Ӯ]EΈ@uSL,[yo+g3"ƺ7ciL}1Ilk+LcPKBxEU~9$4bC8# &Yý :4h5\.zdGNeH}}}i@V9g:-!xeC'/񼉠=:;tc̤۩m3iu)B. K._e'ߟvn-¸Rhˋ5Kǹ(UX$Tf!(Z>,JSmz"(MQxW/[cNap=D"!j7Cac&M11R ͔T9]V֫@\.04Z0Y pD[;isqF 6(1(w%yLD,I%B2/]9TkNeTRN]հr߶ +!VI >M/2/GHgEz6nmЦT0FfKn.2IRJ|=}?B£UBA\#dELpEF"ta +|y0Ļ5tgQX Wobyc#F*=T\kfJOU3ʼ<*au'F{@\vyō ]\)IY/rn%+-fa|k + +I5sR`M<]T>`Z%dbN^*T˂_hx ?T@FGjG3QܒJs)YFYR29ul]y5'ŦQM=9c4[(>{W']Zs7ʚx \Q=vo-16SdzƉ=+G i=q;\2?S8_F += +#j"(&h{mqʗ)ݾĈBYyzfԅHݲV|9S#\# r q)3f6*ְ{ŴdߕEKt}"h<gku|E:S RWrNF4v\\\u? .:R%1HkC%:P5 K 'lk|Nt&`2?aT:7rKS}zfFAS ' ܗ9EQ%j^|<<8cĚYܺtבfl'¼=PU5j[bhpCf2r^_(w_ňWx29 +`z#ZH&,AU㞏$wKL{>;=Jי=[jjqdB'0#qwD= UU{R@ u5|7)T@m-M==Nȭ ~۰ƈ:hH#J\{@Y;ߺ&V&Br2jM= 3}~Pҷvj*ZxVGD{ _uidꠣAVH,2Ybj<?([fp=%o;̴+ב$PvH$]4i^@%H0΍l$MT6u9YL$ԯqe7E:3*{*4xhʨ;҇ʊR(]CgIp@^ǃ{ڡjcd\"O=4gVnSc"#qbt < PdKMA\,6w)&vc_%A)ާx(9E"$” zNfէ5wpƕVbrN$JͣG Xf0x[OE>׃]Y]->b6KSܲyɛ+#-Tɶ诟-J;^fD3*L҆ +@ޝ*3ՋO(K|g83" Yؐnjt[PĜ6NhM-g +&Wq eHb(5 +I5ױ͎1=u*u tDs=`E9@xeʩm䡊890Tpc!(0~C +Gp2FL&׮{5*Tmh,<4Edؐ܎Dik-kS(`'Mڑ|XR۔H59RX=(+66gj"6QܔaYGrvQՋe;Cg {ŅW + `ŌZ2 IsXxtҎՊ:M4Qg )ۛUdTM| d@&άQJWB~:&V jETf^ME:|-P+ke?[G.aK`h0};G{9P&M^{yГFP4 iXHp]Ghݩ*n]ɰc0JNEP3$}[ϭ4GSD\qk(2\_&&'7~F%-y'UCB6y:VpZO!zvAqƵ6`CQl,?8Ty7oMGWF%`Ӻ !$*cZ+ў'JjQpJV,Xj\}MxըGb!,,NgwXGPP[H<Úx&Al>tx5b ۆ& &ٯcϲHe\et)%1@2(qہ 凙 I1 MGm'_Vt(TT<V#@RS*n0gDnIW`؊*z˴5GO1*3!O w"079\ޥ9x"Yn)J$ti (# &])OX?@2&+ʎDXtc:Mh.pe*X7z=DJsF$q4YE :}hRҏSox,|X9VVr]jKIq˹]W_'DCۓhFEP5Vj@j 8Ol(++@079A0Q(rspPy'|*ƄCرFzG$z ˆ"URGu + nopQtz)%LO +dwWw)߬7_Gz@c9̷Ԛ3CJ*,lb5@݂a&k{2 rH՗ }R9#>>L1鞛|b dhƨːwo}!E6%\G-mS'Yi{_שqœ+v>Qo0 4[_: T[Sɨ.>Y˦8k%K(QO2djGjoxgkC ёCs6-㪞38+y!A< +sGLt+Q[z$y'} Lva,d3_åVDS%Obռ6 uMqh=vŜ0dE$dOdAhqJ2I=}&|Am7 \4ʄvD +˭2 ,_Pʋfe6dH +M>L.Bqy֨娏[M +S +=P.exZq hY1> +W(k#.f,ok,"p3{u:ף zld$+]Dr$bʥF5$Ϩ0Q{f d/<84Xv0>\l][ZꀲvU6^O8wME +aC̱!c/dVtkmaGT+aH.\c/V7+唊0h2h-$kkӭ5FZ~Z%'my"@N{, +IBLJǣGR΢ղEigfalNR^_(҂VlF+@W<:Lfʂ7(y6z<;`4.s*;xK}i[,HmMo܋K@9Jʴ}q +Z'\ %9mx  (\'3`r0O9GF@~R|SPGI"Ɇ=0yh_~WmnyᗾVDxJhfm]A@ǹ5nk]`)&\:o G" FhbHw~"RGE-Tkr7r~.ukv!aj0X'UG1mc-\gnCJ=7~pfoHfNOtN:O^VFm bjOkDnEnQQ*UJZ7,]9>!unn ZJ˒7*F!ۨ:749l *4χF0M^´* ȶ +̂ r`~ӧo^`GIV!X}o, -ž}F*FV&M;EL +%q8ȭe(}9KUnTjx e-ME9XqP"l39T)LJ7-w0#2mj]kFkR^H=ë^JZRe’t)s$IiǃhZ6+JQG +<-EmxG>:犘>jlYZ].;ʔޫ=܍4#e '1ǮiwV-$LtI[+*'rw6Y˺ +5WnXR(\x3Q4CBĄޏ5YI+10́Jz贓#Jbap}Rgg. 71:{l0;0|T][;Q`RRQ!>?Q &ٮQ7Qrq +'!&C@͈@%]DHt&GueZn_HƉ. H%ddzu?,=\ѫ qLm1v/ +pONp:Udtn +Qw"my:$}DTwGOv~99=_3 D"ѣӼ[ɢRApm@eE)6H֩'~cu@m$uh #dHGHљuOW`)IBZE D)FP!rJ@JlHb?2ҵ(bJ=,|ͩ]o{%2h5Cm{iNd1BG͐ToO#>'aanRq(z¸Kc<]DAZMQrF]n3nU#)ƨ(ON#rW'l#jJIQu$pL|PQcI9E4 bERf#җ::xYaWh~n|{Ħ^֎SϨccXTȱ) +J"o/k^6>6A޹Ƚ֏(4ef,JզQiNyS BΑ&\Z} @^LJ"|`aC-fpfDuyY|z~mgNbN*,/78$:W bfԹrF)+j8"{Zg:CBLnu PUT"Ʋ(m%Q,\ei&m +kLuW[zdD|"ѾuW{J-34V0^Ͼɜ7e"z O:@5\0YU97~='s.*)ﳾjP 8­{ @h;m?*(d Zj_Eƾ<W:cوdW<ݏ1c~uC7DS*QkFI>H ܨkۯ08q>NOq@1 c/`V,TH>DS|;y+4:0<V~wgn/Х rFf$ǙQL7#*ٵ]z&ʡ#DBG^DZ-liOuiW+VITèETǦƈ5КɋԷD@Nt\Lh}hk[= Lc'$`QsG l*@W 35 +l֬v\q,O7my7oAT/8f3 8JGP(›8V ?z?k9X.xttWӼ2E*JO5]@ GE}3YdLXd=gUUCh8Y:%D)#J@b +e} +Qz9qVM +pL T3Nwy]mIPb^J}K + э@nȉHģ(P^Ni VMqGJzwQ&jJ,PaAD=Yr\n4Ro..E,*,aPC@iY|F]v29e|̃/b0q Ug_Ycwj͚{=#<ȍdzܮAp9XD$KmSqwlȩ|i ,п>,]:Y wJNQ=QCz%Lj` YdNlh_ķ‰xw߱ZwLRԳ2,NȒwIy?噹]fq.9De$ɁZEf{s qREIh#øAzdWչ(DO {GD2bD'/[ޑ|l"6N/~D m AU&u7[@KpuE TY35AZ+"6Z]#:d](xiS> "M4> 0EEz%ktȚ:O#YM,'Q <5@8x kM>~xW uX>jq+&(?Сb>rj8mEyƴs-) rj* >Csmɲ$wu#sjXa҅zO]`clj_fn m8_]#F]{-|n[؅T z\3\rRqɝHQ%\f÷  eFN&<0cq +JdF*AzD 8РiaZZGqD J9Zx8䘞zy0m7)fz75g~m }eOKFĈB<Q^6{< (X,a8s.u0 =êGTV TxAM",H+߰WH](cQ0PlOG=cX葀Cq$jhqv [Ej@-"o4Ua{Ȇd g]"HEykCO1 +gE3uCA s7YT RcB񋛜?Id=OWeڭ? +mc큲ь G-T%W ^SŞ1/APC) }]D,UH}a ] xai.(G P +-t`J%- Ej9FcgBa\\N\.Ժ?"jB\9Q,6En̍ȼEN4* +E_4C5^fY5fpqZ*7:!fwE Y BA}bl؜[t*sxH%C7Ș۟k8UP9=Dtĕ<r j*=iL3X!;Vxij*i&}bQT=b}AoD1"sI긘ϑ@'xNҗL!#U%2Ujɟ(D\~ b޴!^A]vq1][AU~֔gm޽b ເ]^wmCCU]]mrt@T_ q@!bu)5F4!B4#^6O"7UQ{ G3 +c"6V c,$A$! %)"=%~䑬6Wj9BT,}^┱FC% +B#ק7b~J 8tF55( Xs;ޭmllA [jiXj } TxD[ :[w#@?9zPnjDy}A{Q-dK\Ura!;sJ r i`Sks&$QP;W4ЫBT2:Զa5gvmRзIvdQT˅yʄt)-\%S[#FK-V|]ߏ@x:LTߊӝŶh(q^q;?@Gt]x~жFf踇i4U#~ ZpGa +p[ f?THe ڀ`WLIQnSDS~]ۓΥ7Vþ@;yIn^MyYwO!Tu~:ωk;;0¦c`ǿ/_Oǿ_ۿow9?7[,1~PjCJ%6WxGuCw7OJ7 ʎ_KQY׃ČTx,f.8QMK"ooEwAU$O'(/yVktZpcr9w_ 9lhw6p`7mS@*?)} [/6?r4uCkB1RMG=J1i OA9 Og>$_!~[ҵŋ*9,9F DD@_]<=cGa#Jv7FuCw)c d!ˋ6pތXCH;MbMM?shs"r`vU1C͒!zv7 +^mc16iå&fnkZs2ACĹJsCP|ls؋$,6ԗ(ŃaBW)̇I) L'Y}{}Tth :1Jcf7 +M\:PT+Fm lƱ_ZywZ )T=.e6A%gW5H(@|W '߾G0G9X4zd!혿c|-2$5XJ]"np^l۝haƆ<[+|HŧO+[u"7NJd^ +nMcrHQoj8?ܻqM``|ݙF1ǩ lf\{5 N[+ ({Bkj==gNvOOwaѱN0-Q_+d3l'ºl 92vI"뵂^3HxL1_fZX~dZiH"J`(V 6yrQJXgSDQv}c 맟j W?*qDZyogv}4_FNز_ fEciPg{Y8K U89kj޼VՄCg c= ;*W:Ieez +(dz\c7?ɩ:bcξXXԖElgw=z6ekQyT i mv@EƠQߏ۳f~iQ:I5":~{yk=zssuM'axD_M ǿ')7'ݼp6\{lF< +N-~ܚt<ܳD)j=2Mo;\ܔ7O&Ոl볬(N +b7')3 !C:yHk^2&|EkLp&QkjXW': HnaW( FI"'9񀍬h8` k +u>7*ҥY~%8?Tڵ"M#%GnHwԄei~r袥j{vMYF y3"VW +[Sgu@n .3gvsҴ"kw+s).۽Vv Y_Ѿf^& ̟\9J; +.f_+( غRg}!6͢)Kݵo/do\jc ߭ځUq(r$ .$xI{F"'cC NnD}ǂ$#DhDwӈb+:yD0ܱ$L@ 8n9G@ Sb k|75G /{^g@;(u.g2zzge󻀩'㍖Oy*Qo7 +t1g-deܟe xP:7AuJm(SI)-J!NSƃE} (__πSte .:^O=jrEdY9n޾>vaOZތ!47G>Q% +G)))6fg}ggȼh.1AY(1\)6,?"Aew{btmAɌNjLI}"P:ڵY-.KAX:ppY~5F× `Xd_N`cW說+'w!<-`j~F\Ry%`?yQj!PCg:ZJ-DJ -W~ɐW AE~>Iӵ522?Cە"rD;z$n2cZ7 +6ފPSgZ q"XX!=VK D:鱃k](lCq +AU)ۿ rڶx޿Gv~7U8,T6§H[.Cn7j Bsrm  |K!,IׅPRN w&RFųl TR>D)OρJ1;Vuo{Yw |/éXS<Mķ{vֻďXEK=6vi4UckIwk7=hνN!mK!7d3 +z1{+VJ +PY32WWn31N^0j6"ʢ kcd(@@z\sЭoaYVи @l ΰ cohH_8όgo*4~#$26J,6XcEDE:0`޻6[syaI*>(Vъ-UʅB"* +纟Yku Ҡe^ft?}Pʈz jȆ®o_S**IX<"F"Q (+E#%UR#N^8o)X$-gnt(=ʺq~AhN'b5h,!Oz"CT$LFWH{9kK@&DhTX=:&.PRn\58YwA0G 0O Jb rz:@Ɯ71‹_OǫL0t['.-)2ĩ!.$v'~3OvK!'W.u~iE[b:Ÿ+PVSh~t-¤'v+gdm70prjlqEt[K7Tw;HT#ג] L: ] &kh&0BآShM,]MGF)Qz$X4#Dk$6bw `cy +U[hEܥ]sެ'Ӕ#hD^blB39R8WQvThD@8b2inmb屉C "8_Ѹ`msK(iWڕ2ȿ!)ڇjSQGY),^h1<^+iV,HA|L& H [<f䟞~UMIӏ/e]y[6ހղ1 +n,vD T4#s +yX*ߌ$tZQ0:zPvT4fm$L5M[/mÓq/@Yc1oݎRGaMgbuD` jIS4/TFLut@ߦQ$krS]O9*$k8CgKkD܉b>S 3mhWJ`/3oo(a<*Y&*lk8xKm+hDfM_gF1:N5TpdW ɬ2^ 1J/xFMZ RRi0HKl@ .>UO%jo0ȦiDM;yETLqjR SdZRS;f|ih=,a}ecSdgK"ě qm h$%ADzedRo^@sۆ@+׀/ pďZYtJSG(^A@Se쥊 x.z< <.{M_Ԋ)Y~c=U4PbmFHs[@ugQJ3>h|Dw>QaFX2Lj2@ mjM&|ӌ`]e1Q7DF;SmtHĥ '}9zЯjɉS(VQ5 %@WMDm\xG9iۮÊMaJ[6"x3S (W<>T+H,G$2kO.jdTQ6N_#hGAFHf!F`S#(dكFa S_x}pfY2pjDg @A&7|FM0 /Nh 2V z"K{u(bChigAyx$UޠR+'GiLX>d}ȝ TeQcޢ+&r!R>RTq +#=î4ez6 ˾yP9Ǝ7 +A]eu3@N6~#u.JZj H~`RŲCuϤQ"pV i_Qӈ㊸4i HCm#DsIC?S4@`\L}𴲟A(:}ƋBU~f8#CDM,Y}bv_ltC,t>-I7iE?Dtyr(F|?­JҰ"Iϣ,\hQt,8lFvY0 cGb$Pa;B~xx%QQ^R9spCDFJJ7[~0L#^+RgCx}هvbTƇ,S?+BҜ2G>U(v9J8ZrpO!0Fa2dZPf{ +\c8#ME|!S$cAsr.Ec;_3g<A0Q:mKd=Vȭ[){`4W/f2*9v?n&Mebd5U~6#Re@$6=z.MG.EC;Gr# +_4X>bcBN +jԿ ECүSpwe0s&8(e+W͝8;q#Iغ9p[8KH jtUA$ťA8zu*e΀i2dh-#!!rRR:F>nC;捎Fzgk0r%(4Uн`Z!8r~&Oj4 &wB4Gc~4:x@ +1";L,:C)xv`hLͨQc(!g=:?Fd t[ҵDҔ8PvT$zPtuDGHC{jc0 $x:zH!He7RȪAƈ]F1jD?F@{4lmXaH9sᠪC_"tKxNNNztQ|1hIZ)s4;Krh0kP8 vlӊEzhzd6M l7HzNɪ3p9I?Z zmEkUUe6S)$$цsJ$pt/] Iu|_wjwWBQ"Yִ;]`sd6^ ^`*$E'UT'KYg+jgl$sYRte1oas2<5NM# ?QXt%^)I萇~'0Ә}B.QDL_d2(Uԥ1wZU۩vNYKh)6$?a5K=8݄@*}+@L"EHT)bF&K.t:u==0R_!.{G6iP8N֮EbAF8޹uSAbWwY.]YfѓioX%紇F.(%y]`T[ڰۜl`AĖ\~ :Mj#yD~׃p[6E~.,`4mJN!s!> 6V4)Ń>'A9Yxb DJ"f$~$T($Đ"s] +UZ_c,\wE!ǯGBgwIT(TWs >yeE=oّnHtеk rlVˑ+%(2DR/ԃo@oԪfq6?]N>-3?lO@Y>T@ @Qr*)"F.# zʹd%A~I~^ʚxu\,? +?y&Kzjpm*sd]pFrzIAĐtɎ8\ ks iy.;5%" e#Kio~69" d@$NBo*%;KWׂԖͩb Xt:dI@<qcXCD Q1+H1HRDؓI?PU,ubLKDz4m0="ǖef= +ԇP$d+}R>Qve=v,|@v}fiв'V Nd)f M<ܱý:ـùD|eMfJi4[ m +Jr6>}agq%aWv N]֑J@Г_=ެ3BJ*#D2kx]&ű[Y2ByMҖ=SO+2Q}(=,m#6唝Q2rVFg񲑰LABe!@bIsEeuTB[ ov3Ir#,+bSfwP9 b!>T^@ϱfJٿXK J~4gAE2Q&WK@^# Z+EbĐ%2PmGzv/3Jrp!csEJY@n4P(X|ti  R#(AY$@Mm؎Rh^+b!T(x%* 7MK7|*>Iu]"(Hhd +>tsLr!2[o(Em֓D[8_;DUIuO~w2m=r:#CX5C9Bb _A(%*T-K0T,$ Y*%.~-Ew[vūNCEK<I~īUS@o uLӁ&-jsf;!<=3|Ō(5k3b5B.Nf* <|!z%)\=",Y2W,U<I';HMj˪^Q84zl˚Z((f-[)T`'*tad~;0*j9>fU& IVtMI[&p40JPYukıim04l]ld6Ԡ[0J[ "talٵOEeAmL&ZYWE(X裳@*`.¸ƁRN >+YL5E jPͺ IxB@2*=4->UC Q QZFL־)?'b tgLU#UR*\쀞N=?feTE5ןh*s ]HR./H02 IR5hUO[VR.*$i,J7 Z,OU]"Pҷ9a*iQ;`͞q>o̊0} Af5µ H^ל#X#X$ܪ-7IA8ѳcLoS{Bx# S)4kLEU6IօS"IE$|*h rK>JH$zq%#C?M4?؀JY뀑dc98Rf%p/yޝ0D+?w;;=cU8mNw;),5>Z[n{eF@F!\%/F!'K'C]Nwe48 IK9̀pi@ +°ZAjBh k2P)K д+() + YlF܂L N-b!K\+(c:!n2\-lvhO殙0:U5ГR$4lfb˟8DPʥ,Q^%)~Q5-]Ժ;st;(PM "@S%@+EbcIE $o'\ yϚ&9 ""J%\D03=%J'fSka!d7, "i>PyRV@*dEJu +jWLDOB{ =dƻoT8GĦ݇8DW?UIsU j0.jŪG((]ҶC3lq_ ǧv+zITEŁ;P%!jZ\~{!<8h +4|'I*2OIVbSXV|7%a"]b>t?5M)C]_|1`4`w9`H!ez!/pz_f`gwzGs~)Yfc}I +w4wkN 0c8Q8[cd/g՛QQOȝ$ADl7#~E# x@=Ȗ{Y@]4ʍIowWzs `UOi9 ":!hNϰU)Wy0"܏E3OAN&O#h :]o6Hnө&$ 4E/t1*j'.=p1-Eu, h[:V)oH)2 gbW=.m8dW5a1cǁ$m#H H'45N)87e,54L^lBc ʩY $lA{%e`]:(MvvQ9$+rG :z$Βj5;6gN0@@='{L4_tcf$<=@Կp΂4o<KMJ9"^0I ζlxFz E*ZAc5L98FB[ ý!FܐFx,ᳬh d3]b%#^onYеp@FɔFF$Q3-cW'}VPQ{g0<]bݾ拻9szANo}1;J0њH=^X>תaZ 縝0*NTU~,^ g(@RMIQ-gABH"euBx@6후.y08@fPbE$c]YG~^}ʚڇ) +T \sՕJ6'zfM6VfGЕ +jU_h@DI2$"ƝnE8Uld1"X>!KśfY2 +@tcN x1 D`RI1Ji#9YZ  QU5#JhӔR<.GӦ!Хr[A\$hǃ3=Sv\sD8Fk N<2|sҼefL7å=AmЛ I"ÁL?<\Rhpa ]Qb1^@%ܝbXu)MS^P)r7=d鰱DS{8Y +5Y16Ud+}d] _z 㠸CxY20Dm쬔v8 s[ᶚ ;/!*X+uxY$O͌“ + dFP}tIZB@$ꔉ~ՅȁFEAje ,rF@S v`$>clLvz켓t! kE P<|altO~v}5Z6_Ir_k)fKyӉ^tQ"wwdvq=`9I, Ib{`:(>"8LEOÂBԺLF v4R9dЁ0H$e| +)>uĜP7L+H*irh/70(64b,&lmlō"i -O8FBiT_(7sz(A)A`&q+*  }/C'L1baKE wI +[ B X2 + +qL(zs2 ;mݲ`8# N)Yp%-@y 3)*)ʇžZXFQ+r#p|Ȁksɯgy Q,N +su*KFz #n>.h|.\O]fPOBRuI[C1BrB +sɩ}Fzmh>Em Ȍe g>.QU[Ѝc@aXT)$"oxrM!5;q=dkE"~l}¢AY&/d-+(6tqZT4E"zzTc<(%yNXr0(#(rKRdEzD {t3BV%) 5 ,XlpTG#-cȤ]4bkdimC.^:QTMJk)*F@Gfu9_;{f8Jk 80t12qsuLf#iNJ(`#HGL *i!F6DlPO P4{?ܜ8@Gl{Z bArJ +AUHG3 +A\"vUvTT +s&ɁuLTQ@]j?4* +X=;p0 Xqňzx*K c,oF/sT(\)ktcC"&TĂq%Qx|vjϡjOo/}ACaDqL_p.9$hZ2z;wE`fy ZG7bSfx= ;dh )f/aL;9 DXϠt"3uV4:'Y"ۈ + BaOݻiB'3*Y*niDK#jD)ε%:Hr;OIεa% n$z#VyuD'_y`G9=h`.B%Ft4}ds b704:thS'";x_kSIFXNSѶmJ|4iO걀p VvHy %@~G}ND;^B^>BϵsmP@P r\gCMNCk0 eauA !E8id,5Ȁ:j K +FJ+.(!!b &!P +T.ߐk=MO{Eу#hKp!>: XsaiV{&X +)>\#Tn/ )G5H#4/88/kw}$N=pW_ +>`r-_^/K Bג6"LZInQwfvƵDFLuSj(mZvƓcWuQHcXG|zӄA!:8!^Uiak<LL؅ZP` T/ ܞ>&H7(w"#@]kS8i%m3=oZG14 +"mEd m&D ;eQp4Q\92 .m)}M6/3N3t1]>*1ʢ_9೑%"<%C(mw$(I6r}q0àBt)8=#iW.ĨWH5!/RQ܋Y^ya3F>}lAum^2!NH.NXtL~c>9um5h]4=B].6:[$KJUa ~IKrϬR-tyes"&ſWY IpBX4F-CmI,]cZA\O @+1=exu@_aB@m U"t",_"&5B1Dc>sxM;& +"e@W'j8#?d.P-_,o??}_|}w/įǯ>xWpW_rB~|~|/~_|h_/@9S77Weۯl}yvM|OOW_~wnw~?c-_??~ӯͷ/Oo7_6'7*x?UP).&K@i8a@Xѝ|^_mgKW_)^dB>zYEQW~P?[[enlC_a 6rs*5 T4J"3Mp+Do +vm@9z:>hLM=$ݖBQyDGb Gy5N,Oj|K6IXZt^$Ί7|pHUHva!YeP蒶vzHp -`2\ye ظ@8u4 +F, ѷwߌ4`TQkXtn/B|E+EϚ-@q +Dp)`%'NS:)5K .=گn1ZlTX-EJu^UYqOځהHp0$6X7vYWD @ bsYZ0n֘9,@}@9bs +ii;jT4!v h +'q}Q\?kro^'xF**E{.r}HXy@ {1 +0EU7ܞJУXzj`d]/)^R΁ + uJu'&*YNXV]0#yQK!j.<ܐʎ +qp)G_Ϟް:\ Gfa+],T$ +vgrLhJ 8~yWgVY3>T6+, ʖyBJQAUrxvxC%C" ]W91óB{Tug wm%CS(=x%zՉrg˺-"/~i~-!MC2EԵFRϛvM^PUɊ˭˵dtp!ED 4$@P ey%@6WPd&O@1y^cLH)rUoD`G>hlcgĥԻz@U%Q0īrtREVKxbaM@WkNM[0agJZ6"yЋ+=9AO ]h}{ >[IW(~7dgo`%#1eAͽP+D8'l,(첹;>I;*zEPn@׊fjڟ\DiJ8ϳ@:@tvzkOgdH~ KC-|@֚͠VMOYk> B?,oЬ CS?uGR7%}fQ 6Y>ijQ R8ܐ҃MOg}}|E+J޹/?ෟ~_1oЈ-껿$w_"YwoMq?%g0-VZx  k!Crwn{_sS*#e"xԨA7i^Ϯ[m} Xi&lpԽꀋAXr}Cqƃ K>Pۧp!b2 nekX$: kVCUHN6z\ah?v3G:^'M ip[U4SEô=N.ڶit F[#qC\)#E'7mM$$@,U:Z~vGH=!h߬E։0؁_-&H5V>TٟV<*\648$4G A_+Ea~qe.,;mpyۃ.y҇`G1U[F|g٠S`q&b +i 92UX8%BDB<8]s +P=Lٙ\IteTӡjN,r`JϣJ/pdA&*JCfK|:' PG劮!NUXɽ@,x0/ןpkK3ohF$ng7JitA~DSq0iZO{ؔ(j k@s\40"L刴.TxʜA4ܒ8cgL,[O*c1F1=ɓ2df@K8myQc-N^K(zí1`*+X gknى +#8 -V/p,ha֨et_0m?j&S:%2s,Ъr;ԫWVtHJ}ojgE63gGWdL~;|c?h]Uű E/RҞb4>#z}MJC:(BE@$1E,…6\9M$mfT5<^D_9ǩW$t^icm`39Nq_T@uȐ^YM!Zsnjђ#kef|Jh)0o˜*E~ft0v[qD>i:bmy^r{ۜt).z @^A./,@<@QR/v n)h +ljz T \v4gDmɅPM%hY|L_]//R㡯~tzZLt ՎSGL +6Ynd8p2`=G t6Zۧf1L¥Y,q͞km/vYS?USҖ>P[M7»CW[=W^=j I]>GbrFuP02 |'fdT)*IACDu [I>]@ooQU cC8# 3;YwnYgFjC#UFdEy0nPj.;~) +؀6 sq)UcHq4O)Ska#҉,u֏GqFoD5h + %囆1Տ;!} 3~x0:(*[*$y}|ˎffMcf3,ᇳG{zAHD0dFFՐ$$Z"]1K~`T< &%J|.4l"hBεf{)$p|HS8p&EOʑPѣ<,%/WnTJM=^[̋EWm!hH@:¾@<Jv?< 5"V&,OmU;tJqGcq߻]leg-1f-==Πi/)P)dMF4dk)Uk(2f<#X(^f[&ykF¦cL7 {ق~)-dôρYTIJxmajY/ cTRXH-x\^L8uC)G[7%3k$H tDTάc@׊ <>VOVFcJl 1j1kok𝇤|[cry;fs;㭣z2lZ;[5y_sm۲uo-s[|[*Gnr`݀v,غvη tNx޻wƺoH-|؀"aȆ3™Lc6mmolqDsmgwn0-l.kA1m=mK6ՖGl(-@^9͆r ^W6V@[kV6VM[En U6ZɳAʑ z37V"j޽q7P]5xCR +Aߊ޷ߊ݀pL?6%6f؈ Wvnښ9w-Jԟ{[KH_-&*=bIMתS6[)Z__| HNyk5zt#zq9a,Hyo BheZQƂ {֡݃':kS9$N /m*AĪ/=ZŸ=:ZTkxk۰۹_ק9q׶ߦflnV+*YjOī]xq0o% 6P{dt#MقP&@lÒ 0Օ}# +h]Fw^uAC;O.aV0*tc0wv1bt2{$3#|{;v`cVD{y?ӯ2Q#5I ф"ۨ8q KW듨IU9̸mr_( ˫8 +d QЁyx_r0$ךD%ws^g3Ţ)vOc#j ͡o`GLfw&*D>3HQrs3v\C>}= +?Kl\=?-[`%k9ʼncn^* |]z|jVY۸/o_}8YLx+!քzy͗bH&(u}T9=uPEFkV$=O98 %veT8+iS̈́>/x><0Eʲ1&cfJ;>R0Sv 8񨎁2(hq5%)ǰEw0=+6*0+Q]OE">wD{Q&k{$2zR1 .;ZmbJkJ8{bu*hc $Hn*,WpP%1o\ȁ]U` | 2GINzԦ[^hze=Y_X +-anRֻ¨"t ,_l-lW||AӍ\gC؋eo$Rޔ҆I2,§+T]R $w[{Իw^ӕ,kA9c)RB8Om_ez 7jª1 yrK$20H ֧w.oٞ{oƯ%&Zo@.A{Zрuz|hY_.-oy[2|a}>}Φ}\g&&[b{Ud}ߏhދXZr O'rC=~E/o%?~Cf$4 +RtM':R7/7Nfѿ_٦Ho!||$#1mTBhJ<H#tQcTm"z%XqAPk;*RՂSp +Abщ b1 +v(GJ YATPbZ;7B~/ÑDUQ[6zg/U!ukYd_['ypHi+OhkڇaiW$9b e`y8 ƂE:58ڌ}Ej#ME^DOn K|_C™Ͷwڳ(ʶodWXGhs4-KL*J@mhQ^ *7 m*+ endstream endobj 79 0 obj <>stream +NDWz$tfJR'E<<x4jP +E%G@6I G-IZ嗇 Aj5yʘ* G?{g*fyz(HEgђiі0x9eFrY˰Cve +{ß[<&XaB;mٷqTȀLĶg{%-|3iw67A97B+an73`"p(gk(h('OsC]m&-@*Ѽ0͂6zۍPJ/$/hy.eyK+sB$[-Kӯ?M&9O W k 2iKާA? 0ߕ6ܲw' ϳoZWެv{׵)mkus/{7u|7;lA"?$Ʌ bVq'ޝ61GߠdsצiN^ xfZîM諏aidne&QM!#MO{'򮧭Kƞzvin$w=uUF;"ڽz6?s&'E?ல89t,^>;#3ВlϦD^.mi=fGHZU9%$E-  g=Rf;i<@î ѝ"^g2Wj[iQ2 |eơe rKCE 爖:%0[>iH> 㥢 $KH.V|S?l=Sm'01S J)Nqh"dYmpPQZõ%mS,#T>tmHBv`GEu7g%Z-wp>^ԡrG̘#7DsNx}܁mͥr"5[H1؆+s em2l;Q.ӜjYwϝwa wҽܡV5**.;-Oj x B3݉-t' +7y5bpodw;Q= +!p5*PU<Ժ bergY*?rpfv»%OaBvrp;4,\!2ҷC;E3[,vat]c+[qCa,Z{U:+9l:T hw1 .ާ8El TGp BKҁ!+pZR3{2X-MiĈhswb0nl`5|׬\:1YP{h֯ oY1_B[> dbQ=>L1l>t8-6x/}\e+g#~҇Sp}<އዔTXu>/LY50r/~axx0lL=޵a ata`|0?C048F 6 ^KV I' #ll,lZQ_ƶ$s\Hi7?O4_hIz/d{75IrZeWad/h"1rk[zQd '|*q"Yet;‰s۹WSS# `3\Y>a4Eyo4S@aֆ0QþDTY'M;?p<д%ªEIU]#RY^Y-+n8.X +VR*ʰ \^[Zz-p[@dg[]j`C&Kꇛ z펞0xbRuWܕ?ld.C'Pw蒗0<Ǥc屢 u*Yzf ?E^z!q2Cx;SYaNA]MI>=uҷjm ,q'j~E=>Y9to!xzb ]jWuY} PZ>Tt;5翟uߦR僛k)[Υݐ;g՜$DtTp}pO=mF){LBtC3&͉ V9Kid d]^1U5 rg=Zu>;C0cٽ~"WV_Enx@Oٶ·5s0(yM{ t%Z{=5k#}iAr !4PakjdC0wi$f̈i"[6.Q}6#+4ȶ*R`p:'ҧh䒢o+-WeKKʠt{o jhS(ϸIs=JKv[f;藭Nua\DNrjêގS3 +jf`5_b1|? (ޯUK.ZzHOVa=nDD *'ڏ΅`UK.yLTlP eZdWɨ3hL?13,j nQR!:fal {~aqovzA&y^ +z< ` cp0u}xrRBnZk3])Jl:},&J04ƾ:t%x>vhyu:{t٢;}ɋZܽkSp_vSUf naRnk YӮt(Yn_֋^lX/UJ{uKn1{oruswsSśɔқͪoUw~s>i=Vzpnr%o$Jl[ r1M+pӪ­Mr6-лě,!z3FQfԢL:K}EҬ;}Ԫ;MdvRnj$gңM8wTw34{g.ݭƖN-ؒ)t=4:d][#t_+/ږ޼k?_Iʱvf]/Ykk[ٶjn=%wm "*Nءݾw=mq;m}ކgomzJB =w}l-"ښ#Za֦߂? pkg +s"YlP=]Q[(" xcW}BGcM$eq5CZq/{ft'}+\燌;Qkx)ݧ+i? + fu[XQZWQauv_XQe{}d%\6VZ}[!kG6ZNېvrV6V\ї%7V0w p:[7R lמ67vש>Kv?ΆWc +*"ЪwxC~1{SD `cډ6U)$}d oAfiW#\j>OË~Cg)EyFO^r)Z7߻rGs)j~\}دΟuwpwn/U9_)0vե}3$;Lo\+Hsyc2Q݂EgzJo.1MfOY^?~]E;uNlUnkNJ~ݞux6=m+붥Ύmkضnsη{ܷd m/l6hzP ? O/ʹo unE[jn%_:N-MVY$]G~G;HB(vsaW{L˫V$9V TouJSz댒7|FU+[ap^ձIv$F{5IeK7qSk. @VM`iuI6{@?A۰Mx4ʺ7LcSRG<1e-7;_tȶw#5vj7܆!"6-b` +8^M)o>h_?N'yv/WII?OtQާ*BϨ;1}b^wN{{Ӭ/~)~ݑmmYo2>mv[ٱl[ٺos5?,RJ\q\|FYlȍ7RKPt׃ NrQ&IE'`K@NSƶmmw$͜#frKRȏ*XH_osIMʍz7.Iy#/ew.I)BDy%o*O$c { y%Rȍ7m.ILܚrIB&}Ȍtc67ؠTm9Q0H*JZ +cIː(X'llw_}i}y- ;Iz)vsˍw|2$%Ւ>$ {'B 6;I\`,KU@4 }O9g$>t C p[rto@!Hlk他3?w;}뷟~Ͽ?W}c}aMum )1u[J9bo}Ǵ BRaEEcBsv0)rMA@11QgDȗ/ ѕ8آJY ϾFrxuwf J+8 ; d1;KpXzD' JZ61ٴ0+YX: m Zk G.s1F2p!~7Sm>V %r?M(6v@w+}䱘D"-6 lrM2`ؒ.V#9å4 [Yۈ:H`P "]^ѭ0Tk$Z)G 7NB0Mtp$LO`R["FMLa(>kf&qdY:ux(x!1dLek #4*8gpHe;];Nف鑆"TґP=}_uח{~%ek]pb%GBJ-1pEQ{\ksiZ#JtWպU eSn"^FiQ.I +m:$jYt#%/.{IZN5[4x|5QBG:RYc(fSGtQ^OTSj3E`2%]{Ăl:Sh2|[Ot'R qZF%g'zlF>nM [g +W:6$7p7{-@HC~ [|E3B"i'΁`c(6^ h(-v+ȝZ5p]>}5chNs(] Ji[`n&)8QJSBm%v*aS}̘9 L{y,p4@!M]C񒇱Ii>Ej{jcsU0?G=IAG#f>Zw-6ٶ4gwfs`?a[`DqFsN 1sIF7`鿘4ٷouRS) 6bF(9 b$fmٺƊq}B\uHD鷻@R3 'WfF~2g o]6L6xLxٶ7]%)h^c‰s\іG}|"} 7w-S:05aQ\df:?žlMK;(|g1H֙OTljc)ԀY +򬽝K=:nl"9gܡZiNg]v\Y&5SYD밑99;W`Mm[1ʪ1v X~Pc`_VTԊ搛DUvO0:ƅ&S8(-b&p=prm !Pa84Cq4/MYBbw500 %ڛܛ +&[oidLׁ.t8svZ*Z&(m65<@BRfH<$jQwhͩϣm;iz逽 lYU}eqۊҗOH3u9u/2l_PsmObO {^PUhN0 LW ޅe%gGx&*\L VXɂN!"8p>n3)ˊQK[Gi*06*%ҁ"%~@؋<&-$O;.ce]⃤n^*C@J %ݕuy/e^MOYU!U}(Ql#(=I3\Ўn0I=21#i{b&כP[dy Q?.\MBF3}G' A9ٮ`%4!.SXj(M +FKr`)CW>Ce.`lcxIFY0udЩiU{ :< +wx\96x%=DSyU-M+"|M y02De EQXh0="R*X.BH5faW;ݣг#޵0iJ 1˰iKuor[ۓLVdAI] QZApnHuj%e\BM#PvIXn!4ٵx?h͢=owQS)6;z7hLEGӋLo q5 ڵNƔ#_^NGj9㤍itڈLVpES +`M6rFDGKֽ(&2$c㍮jU*.)M*LRY +Tm5Vd'uD(E_ ڌo<0CO?jEt[j&v0M-*{9q!{Vwل~[dXM @ؘ,7M(d:C蓝lwPPD˟`"<G)ъk8^0h :A EIb%FΪ +O|Ltmց-9. og5}ǝP4FvY!.bX +|9V49`.ziQп:8`x/8n|jtOt@ݺQ2.$ pLNL;;v~`k'R]CBX#H|Og7mڨ1UZ)Zpl +!( +6J'tAz nGt3M<ẼAȊ̽i`h&b_!RVA[Itv74gȞ~'Zp>]6@Bѷ Q{2 qSLN7}b6ba_7:JI]> =uzNKܲV_g$`M #Om @*QJL/36.,@TwW7&Cg%CB +cw}tK,$7N8\LIwqG +@ru%EvJI;]S5ݬ:^@q~v۫Bq)[Dcf`TYMG8-l +:`7B}_>Tbݔ +oOO%dE#(m=Wu0 mα:wis^!pLAb9piMOOqa>v^ۆ6_'/}#4+젛bE-ܮha[};HJ6Y|tVQAJDŀU}V4gsiQNVPr4wRU{FH ʼRp챫=`(XU`f&#b#aw_0d[M!db97 & eQ f1a"ݨkZp!ș -$Wv5&mXҊQN(7Jݦq:69XzbAq6%mcS,RPkTI V]IT* Ƙ A MQk15{zqY*PMq)>7=ɴGVJ3oN| ^X +7nx>Pa +zҟ@޻/w~Ԫ";a(uZ+ApⱵU6wH3\pp +}-6V{y[$HgШ,ab +Ң+/j*x|9%MkȧRQ6ߨp6Glwh'1T||pjOp 5,;JaVIi8[Q*yE@S؇7"T  +P[] YA݆bAbՂ5k[C$Ծf[(TݽB^B_B& u%, fWIPC`ϢiBҭ +RZjcO(]]PxΛw^,4ZK:6J;zs➇/@COYkC"oB^O%?\BA6tB(a5a + k0+4GpXhFBFʅً#a; л(C 6ZiB4tPgƟ۝Bk,8tmCʡI)D>R yh +а5kb!YZB!4m9#:B$tmS//dnb󉽄Qvg̖Ɗ=XߒYtb2}b݂A#~ͩ o!-w!!aC6g +ۀ"I_^ӌz3Qd+}{'&=ZfW"Leܧmܘq=y2 4ښ8T +Vm9k9~˚#Ym'dMy] &^SqJn[+† a߿-~f-'o|70Y):lfB=8uRl0ILx8q/qFemUmA jEe9yϯS+ek_oqVG|(;| ωt]S0F]8um.!;.S@l`,)]?UX ~.^`G(x|w37;NkO;/3K-GڤvD#LO,6CS|9$ob|~r$,EnPI8C}^#\{6B.@A wDT=ycy >+P1g6~8qoDBUEmg}=U˶π(?hd@$[?ϗ{~P0HK}mdZ&@(t;)aRw|0idm̓ﱔdR 5A䬊"?ӹpEZ*DҶh%1IbɄW;.|zt+Et1T4Ej8wV=]uZ>gj :2qƪq(fSt`1zC|Oin)aoGCuxҰ9lP +px9%):sIZld"0'T{\tׁIW$a"4s&JN aOXJ͋l`?&( pMRW%Dj#Kky +IX_"|=hDHu$3Bb3kTOi?Tؓqڬ;pؖTnOpv^ 5jZ&֍LOWz80=V@< dGP؁c;Z3V! "=, R')dQ7E^o!JrƠxl#ЇN,(!Y{Q$stl/q#!|L=bOG%Q8 I#qGEma'IA&#$X&s^+RvĖHË;ATKVΧgOtAK$]'}j뫆}'6YaUn~M=FhQvPTNuQEo=ǁ +zPwG:Z*DkV韛^J7OIʉ LG ʤ\-qm&M;+N* ܅%<&JG)QgwɍCs4Zs-:Lc^( wrTnXWu{qyHz*.n`gpɳ(iNڼHM ³>aj%R xg؎(9鹊Sz&:a+/&#|5:N̈s Yzœg=8M~d +n? :O8 UHtSsbw:{RC}&WR%_ c+5TK{h钪)HPE\ФBx**p,iI Ҭaj]A*sTE >Zf@Y5H,5E6utnTq1=LEg3=(Iq<jEOt7}?lYDLlZEQ4?Lg.qᑷuFRJ'n҇(cnge7wIIi LIMMg4C+/9)ܷw*zJ]Sk1?A SY) +'k_EM *Q#թ_ +VO"Pnewb߄h =ɟf"2HHH"hQcM;*mฺ_wiºrQd6I޴Ӌ@FXxdȎ+{ʡo?8*#!o5Z":V/:W\pDWʾTM9J꼢V0qin :d|²w9}l]^(W\E/ZZ*}f}ʈLÉs)e1к*>VuV)a4>ݏ3&lNQlWԚM+-wˎC$L!Jy O`VZroZe0>PJIyRNUUp)5й]ڏy6EPL 䆃}:(F̈a"OsQ^T.~e`0C[m WaqfA ++g|O#|@xiǽk󝫚HMأJƌne:qK *S{J_{~ +}I,{mEvU)79m}{?Mi]6l*m">\=Ll(E %{I`dZK5$'mUcF:Mw}8 (-gh,Muc-w9~;kͦű'" Sh}o宍ں/OH/R57Fy ԅ=(-jMEubZ8-`*'A(+kpmv>RTW?:?Zwl;>!Eu}zOy=#wYG# P6m@pvR" 4֏F[^Ϫ~YO_ZlJ^W) o@9z5:`Y6ʕ +"tG'K֬] c$(5;B[]5ɟWe0ܪzT|q{AB+94ݡ'" tL)4$(C;jAu$UULMTQ'4WYP*b'rӝĞb.@=Ӈ kJuHqi;]>f)93ΰpJuB&y>D;mknkLqҢ?hEtTz!wpJTIO#%xk? +4x`F/aW5rM ..*Jaa +x5dƂOSDy]{܇͈9SUgz9M|I,hS"BP=pId5BgOݰH}MNzD) }N]5+u2o* 5zl_`OS&tސC; *@\.r#lH +K)UCT;r#I6J6ޟ ~LsT:w.jzV&@OQYL* ήՓ4f])nU2~Rnݎ =>KĶn%h&<-k{k^`<") h٧bIȠ{ UڨszO,MUwPpm|2L .Scyk΀3< UE )tfpLwB Īs gss6%wGX5ǍH=̫w]ŠrrQjנ`QQ,kM͍8Pb K ybP'0tTX{PO ֱ +m݁Hٿ<0w䁼`k/8;|iԽI/4ze=0^4ٜ^ z,$7҇O)ng RX#z(d4.98>x;ee*T6; +Dj&ecg&3ڠU3V6YSf4Y((!"BL4F"ed +&LaA'XL-=$ũC͛ d33n؜πEX?FD#]{πwr3* 8SuqR#DhZ-5z/-̅^1Xi^Ȕ쌘L-G/[L8wuƦVbGP"} NK-pa\{o^FPzr=[t7`>Cf 259AmoRcik +Y|-0r[# +2 5ov\u*j7yki3[3& (TH|ykm(, Ƽu9$KZB)qI`o%LSZY#$` \)6m5T/ _&c2\(H`# ?U'/ +.ӌ>Py0hgcDcJD>voz֠}V!v?p2ԉ8wC^Ϲ]nn ᾉӇ0PfsFo@=ue¢b$` +STǗ!På{x鎁z}$% FS=b=uQ9p>!TCѲ!{ :\<g~%d#&^=sE˶Q!{O7ў[ ٛe:ⶏ'@c %$/d'l^B&DKgvr'Rh_[c>auv!<}>m҅ٳ4LSg7QwĿ)WBy~O lW es:_s{:`P[ a'JVJ[ĆUr$jIAueͶ#P!mMϵ{e:`c#SlcMv2xCn2R[삗%$ ͉̊nA;qN%}mޔ.Mù3/+fuƖoL 1tCp0|u~lOjw7۞D Baw5B+3Ln6 icTpdb^[D9D轄KF:,D0gr&sYf'&$ŹLqW0,B2jTl@>%Li3T *,X "85| +\ǘB]Tп!zpN9y;*xLWfLRhYag;E?U d"}S#A ;K(i|79J޿o*cSzd LOƏ#;\Cr&Tö%al8hqt̨GB` +.r8 tߒ"ᖡ=lXXA.SŠRÒS\2n6z"-{x μ>?X`' Aլ +Jފ$PֿF89m ス^i2u_B'`I˻MÎ`UDؼ<"XV 4եs<`38r} Oo'3V֠%CbFL2& {&n}ܖ & "f8lnVF@!^ޤ;lOj(z)>GU ^go&6CQ6@_T]Ts,!:mb7%qNCa!8)HvV(g,:*I}Sc%=NLc_# ׹o~ބ8(2 L7; +㦔31}|f<4^$f#)a'R}@6)j )dlhYh i9X$QQgci H,jIVB^MD$ngjHQ)JDQSެBʡAZSܞ]5KP$p EaO L)+ D n]WP_|#rQQW|SD[WAfx4^RtϳU){ _Ŷ&mThP$HC!mECG-Sh-1hZB;[t g*]7!+4H#xhoұ*j5WAj2nKgv%حD⁶,o: +S%(*؆0>Vo>$0݋!Lcߘ>srR8';}u=L)^/]sy?T 2,n'd2po`+a綅G sWp-8#&p2q_meة+TX|W:\r`9ʠ 2U30iJ +9DPWN3:> +gs@dwaP K`wm;DP SE-$ѝBc{^*jRR-6U k E@"fߚDUNxF5vAl ;'12q +X"JոRE1I+,Op&bYߙ b4u-%5Oǒ*Y\p,%˄BXW}tkh, +3:6Jj̓ꦭnrQtQdw-0jzBx6V|Wͣ ]di$`c&(J_ doI0ns1k΃Ԙ@T!m} Qѻ싺/HeMG\6d.@$*1sG]ݡT.Pk5F/c*5cL1v*I[TOafC[۩jq +ڈƹxɤGgE-7FuT xL\fچZ]TUrjzo^lMM0i ELcfuW\U@+D j~Y#Z[}/5]Mx"4_Igl9.a4uFc.[Ufc"1ohgY7|Js0v2qH(Ox!G1GB +k&XxpzʲLV6ZJSz3rX5xړƱ^7^G7.t )5$A94rN>}4Ir8Դ~. # N^.=^SkGi^މDԍJbN"7^s]^>PRxJHc>j!L>ZbZĔ faqrKiQ X :<b-y|z^.goпvN +ίmPޢ bMzޙ8UPN-k;SILBgX0Q$YHu +|pU/*.#Zb8&`%Zs6$?|׍U((iؔ 8ޛN>$vnJVJ4oW+th`W\Mɔ>`V 㑫O va-쀫+TWPcs/Ѷ Kp(@fࣺ|, urO+ + wg*\F4p>,hNym[N>Cܹ{Og% N}(_#('p [} +sj!y 1!uǚ'eC$" .=P ՔڂH5ܡ6 1BcGL@~k8 |ŝ2OjS [Z%us? }I1Ƌt=qJNHԇf#q%eg}J.),.jrp$:C7wt_1اc^#£bb);H%XVWc;!һ@o)&)^-pS~e4wQQ-*S9?-C} D9RLM &j!n s\VּG] _DV#|f֚\3.chpDjV`R)1ltN%¦鬶SUu]yL̓LsoL," x2?ڴTRzaPҝTޛ5H^.a^y;,懴Kf5}VBEp$K +Nazi1T cPkF;GfY[[ܲN"F1>S;XD%"Rf͋BC5?ǺaTյJoa! qbBÖ|sH@?ln1 n͓ Z oaF!.Z1*kAqkBܴk~ Bÿ +T +PDU nJP3n b: mZz*P,}ڪP95^( +2omn( ; ԣ5!B9[@BI\bBiy +E} 5[n--Fa(JZovE 5LSuP;{?!Fcqݺ0V6B6SwŻV. 1oP:w]>˹>ZCP~B}kh$ԏJeB5턆 +RK@1v +WlXh1c 7aFcI -*ۈ⚡U&FCj 3cWhFk9v+iǞ56ڮBX=om ,Dc'ٚ!iLC|Κqk#6'YoĆ5w:mT[2K.X[NZ޷9.v456ê_SeBzLR$m$tU4d&6^k1ܓKtc{v:N-ȸ0V3~@e$0*@i%RheNXX`oDnՍOYKsњn;3k5],k=.횹v.7Z@7Z!&" [ߴ ں+qdnҒp|GiVPGT",6/l@M; +~!Inǀ) +=FO˅T$wvSnO4fI0z/瘍8-ϭ"WX +%m#CiV^oU3)9"]ƕ?~7bw_zdA:-7FM84&4LȌ=a3~~$MO&+za+^:o >7߽_ePD؀I)ˡG]=?O(_&~=<a$TqAVJ P +OYn:-)qb)YߺCibP<r9VrHPb H +b5?_Zʻղ)7/\X?ؠ "=aP"D굾l4]SO3ػgxϮ<D?9SDhF_JiBΌn` (V߸G?PLx hۼOh"] )u+jevG2&h@RFNv8xY ?@O?Eq>?Şhʹ%f%xMdP_*f +a&`љs Fbh>F%$v +>=WEhMĶC>%i$Eg Ig<&&X?= ,mC=fhKYƍAd6sˎ8PC +B{Sϴ9\{;9aS]yTtF6Va%בmȺ>!)C/XDڌG\2bIq:0h(/tReuivV\BjM wIϖzov(Y-Ps8hb#~×Q6 tx|7;8pH}RgH[Թb:Wp Ng_q:[?q:??oq:~\Lgbv 9Tg@Bu:~ i3@o:9!`gvH `gvlعbc` +vdY?vNd͛c4e, >`{V]YlcxzV#.'U;=nÓIF3qyqow, /g3lOV#.ݚKP\X'M3(w(ˌd\)wtJ#W]ey>*4 .8waxQR&hip_]Gz";^R&m+;iiC̴ȽoZIx(']ɁׄLu96Rw"yx lxTV :Kk5%絲7ļ櫟*ۍIwD +oVd6o5rצ +kf1#me'-⟴=i#Em攼vaӠ3;4uK%~=|M}yP]:>ޏOCv/2J/2J/0Jn5_` o2J7%j.PJ5(%L;5PJjn Z.PJn\ .Ku8%w.rJ.rJ..RJ]\]\uYiH2jH2j6vmrvwrw??›M#;9-WNy]ߙ≮̌yIjJ!o< +<<N~t9$6iWuWɴG=qFUQ}KSQ|%uJ҄Pim[!JǧiĘ(ͤ`?"eJR`읕O; i-A aHl16.@V:'ʐF˿#B 8@Z@m?Dr{q~:(SRU64J=l[~ƛsÏRu]Kaˏ&}ډm%ңQ>H1w;4z2^EϏ'Lƌ7LֻpfI`W˄0 1{8~q~42NyT}a.p DPʉ.3R9&Sec6ԇ;OI{VUW`cݞ&-lV m,* "l4އ, OԨz +v+8njt43nbcϠh  RIBx8zHB u$a&X\C[gi$;4,E>ɀ})ZX_ 1Z7n]է,&~/Gb‡BO~q)>fq>׭`pj*(3O}umv& y~3llj~iBPԿnT.F~ +\.nF}B{?$!F&ds +qQ@'fGXHw,uKKa@w 3h=taUSZ{K{eWJAMMBϱsjo#Ѳ2Oz g|ATiR&LeV% R/,ma{D fwMd昩1 ++Wvف.gee|a4z)$ L L묡(?mت s!i"2A7A2&=ѳY)ZF1O܎sFzQՒ/P lRvI麘Z?ѭ-nPEFRh-=Iv^z J3[xYM> I*qH 1Ž]#Z{= R_vk5XZS=Y +2:hhQ2xL9JAtJLEgSU2fp:x. +9Mg*LM/!UmN*_&}UۖVGoeL( +ޞNpj^ЀW=GzLh $SE6;:?z3S)#8{[Q-z&c0):TA;_nqoq,洕۾<%\xƏs-;VlpgQbkֿ8dM+߼쏿~_毸=/t])ӄpʧ1HWςdJA'نAEѧ K~3c+&AfZۄ[ȒIOZD2 1f3 \ǻVr29p*;崇:;&,-#~+NTDdQ!|ߪ&@.); ^е]+w$%2~tQ*LLF* #ð)29Ȅ{f]T$̦j+[oAc3L>z n0@8bfS + h(1Ѻ˙Qt>|L~jw4m'ij>'t)؇=0s +.}z@ݯ}fiL*r{ٖIգ(rL!ߑIQlYZ+2ǣ= Ua|rPzbl\dPQYyfjJ:8(ͫDq!wbCC8( LH a9  K4;ڂ%A[?d"BXfj3!`e]PT욼MM)f\ +t&S}PB%wpW#H*WzncP(b44~er)5iLo'u'2e9;][FOztb;T&g"\6YGdUjroNAPnq'9Z[VI~cJqr b&[^^`98ovõ'JpnC жc›jPNUҁC~>w8c+ c ܒQ̯8EdBJ`BPOPxRAf:Am2#n'ss- >*rvn;z;맽b3?SW +3TTx[g%$VCp&4fĺ!L3/~QQ?.H۹T25ILR' ;P25kUȑS%G(ʲjo(#mȉ%GC1zl[ה.Lv5!s .f;j{:d1upGl}Tb'aߋhC)16u@}G}UU`6x["|+v{NbϻQؼ&P tt'-
dުW+m"k|FxV¥avK@${iTn3t|VBdfvR rƧR b'wU +mݦ"^PT>Tfl"Լ͚1 +0qpǁ#>(9Cޖakqf%eT#=::^jADXP m_>euu +=.,f](,WR-Mݛ YŔ  %8 j}svu;}j̱( !.kN`{;%5U=F7}ȠmjʊHy +04Tu.i$&(ẖ + ciᎫzJ [Tp:^VO@Zwi`Lj)PZBE|Kc;pW/;`^1밂#: aiƺ,@RϭB_v#}ۭOG7\*rM=oAy'l{t8d%ܵQkVdGT fndq +T%md  5r$ZQ*10FzF DZ}ȹ&Wn Rl<Һd}U)ϢcI` SqY}_moN.;k|~gfRbP6f;Z`6og=0W/Mج۔uc@ ,U9TECT J @!ұlC|‹Y 1 ժg׹5"%g +M&\;v.ga\݊ + ;T+b| ^,̍V;g[o0{ep%m:d;?sƥ 7OrgvLaM!\ͭ0 G"oSG g0txCTgN:(oyjrt@A $bMA\PL,8:Z*Q4bP(Q)Cȯ[£ 3DLfeAF6)"FYg|},18vnXwPYGFtЈM?rф@ޭ%jFu1DRBmKK d Jǟ1 ΗH Iӹظm>ݟ+˯&sk~y{ϧ왐}`>gL@-'%9Y SzRJ`^m} _ /X]1W'WobuGMВlۦy1X @kt}┍^Ob} +| ˳dxAle6' BG F'kkO3|ye|"ڴQSL+{uTBy&/șއ&+θ&*/b!BT2a9;r50iM(lNM0s~ G̺^WO&:]c% Xz1P@<=ilDHRqjqw1!ًWup@Vzx}N?O4 dg;MѬHq6i:`S@FE qvsX=FCkwa٠cR\l)UTU~P"@dV݆E=nS iPq]Lt|q $HE0A!xSbAƵ3[ &i)i0|0Ρ9S7:3cKC9(1W~T}n*}HǤ17;jXj@^CN>6W GahtM\ViT̀BBxVx:ʐ?A YJsfHQ|Κ؎)fͪ]sVg텥]ϞXS-&\ӛqwi)Yӭ x`/(6t8K&{+|*BJ=͐JݐB;TL1?k +ު!*QTQ(jPJa(:4Tul5, + z;ԓ?lͅPP"PjƸ :" +>ZkX(= +\(_ +&`( +7rheYyW Dlԡlk:`ƇZ +%s{b ɨՋ ZR2qԭ9\k$Zܥ3k^PsB]a1671}`t <CJ|YuޣyPQUFM+(fJ}BΈ,C,e!/v$W~Yam(%,"^sʥm>{÷:8s] KAx]75p mzȉ6M(jڭb~%]?1?KG(}sߍ@`yC.wu u(3rMElA"i~BB.V49c'|0߽[HZݞ {˙@PTx +c#u¾[i+mob(;nt7?}u߽9u`'#|LGκ hK6Ouˀ +K8)aw|0syA\6{o_0TP,!S2 i|{_\ӧ=Dpc_F"7 t q-sR^ŇD!M?2*\éCDP + q뀎<D )v: ;/@RsсZDێC)͖L + > `Q n,JX$FKMu`W JRިy<7'qm.`nfkhcGwO8Rn1n&Jkw$ {PDW㒪`|2a'޲74qe"GBoWX&p YjC䴝~ NֽTaّ\o$gѯQ3ŁPDSت@G;up Qvy`~j&4U"ws-qP3Y?&Wq@XցNj፴_Qzn=vF\W!5>t҃P!je$fh!lA*l鞔np0pTHgSݎ(9!S҇\~%Y4謰%B jxSoET!06L>2P-%g!btuWhL_  |z +izZr^c3$c0]Tw Ar5Eڢݱj<}5Rj . H;P Rp͇HjQ;Kj͉pj'dHϪ#sj{q|"XC;&x#f >>׋SM >ڦ =\au @.*$<7->_b1g#a= 41sDx0{m% .hx>\QXRvwys\TYH표hAIsbq1rڞGcJ;9["j1yWi N/mJ$@2ȃ$u{g!FLubhqQ[BFy uѮXN1cc<"5J;;A:*wHB8<#:`5jra3EN<`1tJ/ کL2l>x|/gC#{)[VIZO]Q߾f3N6ȡ +KSm'lN zY W D@W{YDq';S &, XTH(+Bcq`V)1*|$De5bRe"'WSfݑAu}oz,>/HSVОKn4338I޲NQczQssdv~`ic0}V-6 :vBvr͓VLg9(^f?=Ve;T.V$&z;sNLnScH1yE2i*;U&]QC%`umdOp]spjLLm/(SvoTg߭}~v{ߗQHQGy_OX{?!\ sv-x Kb Qn6UaoFm}K/g6'WgN۾\|v׿ͯ~m +t/OLGǻL7|o~wC???_}_F(2ɛ_>R9>|ǟ?羅鴹:37?/?Wn_r@0<aCwo7_8??J_O'=~?7W_◿_c|_|cU?xcǯFd?jKR_>^_W_oj87W_ o_Kp|添k㷿|C4ýD$ j!XoJoRnh[j^*\iTS85ΌVޙX>"t?ǯrŬMlA$_>~/ 7jWI?/ËFzȉs4U|\-iuOT?m3@֔ǚ +g^n]4E\iew^iR۵[ygUc7D/I{a_p~qMmjwwz:8GyYsO ݡ1Q3ɏruL1=iLj; /0.B ث_%ZEq0ǒf<%潷۳~y4%b:;_ hNOM=MIiSi~ ظ=i;]99R܌瘱nißb~wϜ]ב,7`_s&(2)Uʰy}];%*BB?|tZR]ʼ>jȼ{\1{ +2wu_#gZd ~*徦Z򞏼m܇Yeo?a[/ϸgE(rYWסuϗJ0nz3/C|>֔9˚[*NNCڱmn?ENƻ;_LBtXy,p6py*s|_={y|P'|L`g>FY^PƸ9/)33m W{^|D~Zz|Bmв9ODz=y֏~(t##s,cRDNjƶrl#qy'? 4eB9ԡ\>sЦz{S{Ǐm3]|hju|y^TM!Q9Gqv~Xi<48T=\GK~ +e >f9UE_k;0"%0.ל(λB[_.'cj'|rs[s-Ta\(ycnGĝ=.zi3wcMTJ*%.6Sa#Vff{.lH{4; $=VP+;t~< @slz|b.4PD{i?jz?|$埏=9nrs}Na>qwqp^#q?u>}>Qi -}^ԯf^SS9"7gz*{kt|V 3z/uGb+U,쇢#?#(9ʼn̾ 2㦽S"}bAkK_04t~5e3/~X3I _W_,m\#: .S:Cyag$ɷr馡9|273 -xޭǾzokzGKWpp0hW$CRab32s 'eߎK_ʷ%1{tX@v\n:bs->wLVg0W񮩣Ezu]}s y~LRRNDI-;Pq?aVBhQ}̐㞏m_5>J{oL,yy.vOixђ:.0f芫#XumgF*b[s[_FJ_f*#Kշ baH{})̹Sꓑ#`-W$N?O=eDFjJw3{bwpHI"=~՜f Êmh@:XH#<'Z +:4 >?4ITcˤ3X; Y\Ά@"md]'Z&J%#thFEhIOogSgHԨ" +/bfT`K]L**āOYQ! "(hD[10OQ+F *.>þM@LUdS}56*_w '*Y ]}nfNReG,D)܏ʕMk1Q!,"n3Ll8];1X>6w妰y@<|}lU%SЂ@8⳶0~C3Jч*C"I"Q*~=/U&.8/E&sqJQZ(DT5@/g_t멙21Uɩkq˫ Ua/-1Ah<oMG.dL>1h6/#p;Gf8YZGk4!:/!X3kM86y%@UC};5$Rda&Lڂliu|F6sBS#L}]LR[>"gDF`QN +j@Y5M+x׀>DD}D@DXOdc wO_/jF8hv,$'ȝs9%bČxB& JOOeJyF_b8tz/ +l!<YNj+ Yf(ʷj>`++T`)MXBɾO߹jD,2@ztb]~m|YY 9cJ4GBɘ3ؑǬ/uy1?BYV'E-w *H2z(8DL L4D0E^W(z>ɶp 1JN mE~gxι%|zJe`nN0}CGVK5q^E0ic5LZ:T(iɊ1.OCI)յ^-\;2&ގD)9j**p[WĨcl(kWK8iJ0jJ:pTsůd2tI)"bW !SA㙗A^qlo`g~O0'0WccD[D>B1Nk|VGoO궅P` gdS$/P mس kJpp\8SJTϾcj-CQ!ưXhIy*e D E]Z%BT9,Z@2!_v}dxV 7,eՅGI%#Ou@]P0$~ŒO\Kd֒QNV''Db YSUEIOeʱcpbTiBQ#2`0A^coFG hA&B~&}%rX@*6?VFՊi+VC%M[(օo5J%#M޶6%N(TQ(.hOaZdDhial3 +f1<ppjznQA F lT A +|/ػbye >v5dN* +=33-بr t *YC322Q\<2Zczlݐڈ g;+jXP +47βsꚊƬ ?˟ ” ]ЖmYJ;jr-?'R9-oD8~J~W֙QE߅*Kg(*/cX5ppOų,HF) ,itlcm [641`dOt-Yo'9Pd or3 +LzE$ +Ccz }iA]1ǀsw-|""( i5SR=uM]ѐ~L܀2.f,UmJębvP3ˀ]Lj*fs_YɲG_ljD +o?icE-x[jJ%X~FŰĵawgf4z dSv:Da ھ[*,BvS ΀Jϓm,֯yrO ~@X'0'S>*?Ac*<4ۦ(SfpaUvVAID?Co#O2SWD+9_1E9YS1M "aO[8^ +pk'KĻx! JO:&8Hbӂl,φ#7t"Ӱ Ɋi0M-Ȧ.*y}!'K k@!S焻 #~-Ȟ$(hD%&^oT̜&<GdJ[fQQ|+;U"+|LK<+vܔ׆3֡dgLHP[V챫dgPqUya%؂gRȵѩO y6¢?RQ.ʜca۠iRk#AGJE[o ,z]Vy&vd/|>LXvB5b*'n +E(!9@@`S[tQH}x(c 5mp?1LtEo*sD𵰏|uYa]Ō9L*{.p9kZ.̦Ph+Be"&y1s*ب+ +}m?Q W ]Dp]}"@GfYf6FRe>/lL~'+2G Ĩ +fáp`vLJFZDl26n)q&c7=T4ĩdY + bʲ D;*]& A !YD6$6vI!F^dDeb0,AZKj$u!%>QF"!FQDbdob?5MK"S®\@[Nx>,/"}Q^&rr%"s*v۵e=1$S)o Z\Fh@ oR]ln2\^[]kQxbCV)>jE+BeUbIHJ'G4+kהj*00̘DMC .A-C3ވ4 d`1QVQ.ֱM#֔|OXOTKOy2}W |"㱄 S1H~_9/IV@Lo% H#0fg"ՇyMMyu_8ZLrgHT/wJCňlfmȳ35ًަtqmi>aM,3[97J?B!EFԱep3?#@7Pv6@/}Ye+ [HP +ҁ1Kv0HFĂdkD٠Rh©DC!XqU Aݬ>u%rkUJ*Eg\6BH kEE޸IJ4Nt^YΑ-UL4;\벸IJE7rH$YpN7Zl!zW-原kšҒ#}\a8/klQ |y., 8ڈfb:_x +2.Hh]Lsp 6B![X-%%S+,L1lY,`_G?}>ٶ*X-#RLu7#oxiL+2Œď_fJÁ'Q[*7515[5eLLX݄m K +KU~7Ӣ +|V#g|XjyyVr'˲MVk:m}i'("٠XgLDپ;' .۱/o1 tT}YlGTF_rtMYU{CfQl8og:yÇb%ѱ^UocDqUoUsQU6q*߶^8pt]mĽfT"ZwE-eG`qfIN)ֽr ڝSBFAڲc:1bt]CgFYƺAZ&\{5 k$DKfp&:eDCGY}ffȨ0$8mG]Lr^ā щe+NSu-!/d:t__ ck1${$ptq19KVS]"쮭/Ͻ [܁738YtT6eB_RWEH{BlIVp7Wd8!j~ͽ cRˤ|"zx7=hEI<(:/N$3}oAA+O߾|K׷#ˋNeb7ի; +M; QPٹ`HڰHXPKKd[ioYzx ~c +WU}؝K,P> ;USY1 +˿4Mtʯe~Xq"̈Z [dͺQNJ>}]w; +btlFڄZ%&h0Ky,0ib*.xdtׄu;dtÛoN}?}p^ʽXyN{nI*d$v!Gġ퇃{$@ܝ᳖އ`,gu>\$/ ߴR7q z߽5"4YͰԏF]?x&Yt=>_\]|a}| ~lQިXҵ8 vis!{Ve&ny.7C3_k]22;v-Xu_|(EͺևC@ _5 +xKyégz_d!֋_l/`jA^dE2EM|6Έouq\i(8}.ƵX&? HYY""Ϭ4e&Q}n$mln]ô>.8bb z}+au} żH9|͊;5}:23Ҵπ/u} +n [s`nE`Vč!ۘmWo_f?<}̵E|VڙwX1`闯?a^UoofhSm>Qc`ϭ|4a8m%s< ۛ4]<3K0[ ÝlRA,ӎѦRhp'L;S[пsyfNxHI0fim\; ۍR4>T|>X8[LfQVԏ7QJlOq0QSrB6{_Yh8TkV!R5*EuM7 śh] ۉBj%i6b'Kٞ^je8I4.To +E+-Iv౨݊ͰQKvC/RvԪJh$௴*0毛Wl0]ڍ矆iH$J+R?WCկ ͫ^MN:70J t>FjnY*233C}Yl^'R*q4ywcۖw`Wp;iMrs>нn8S; ZaABz D"ӊRz81_gHd{\6v^bs8f(1ș4[N4ժL9B*ӋӰ^MrXyn<# +ꍐaR>(D`0i*̪TTCZ ;F GJ4 *@ydD_Ң6g{i/j9b6Twiߗ'ufro?YM䞆5ms.-r1ٮu*Δ$m*?f"5+ R;*penD?O)_~ׄOf8f{\~9ƮW,i0x]wg;pv2޴ػ +()isU}Ϳ}"u[xڧ?O,ojûίw +Z])eqVlC)zfpb8y1 +|N7 X8Oe'N"<|q:δ/ +q.NQRxf?ÙoEDfĨf ݷ*m'Z *U`Dn|ގrD5vM`:O=ͷo.`DZŏZM3[^K1g' P%M1UP΀AÀNG:a(]U> {Q8M`Wqɒg?Af3l8\ULof@ +lA6`-^[Mwp lPrYcfzMC<]>I@O⠞@Sl@EQ{/ n̪$`|@Uv}Q Peg7Y +j5`0)~ m!o +[N@k&W@IaΦ[ ~;[zP R%lOZI)#ft栞M*x3kP$0io% p.@8 +$!Y^d׭ßpwě+Ӄ_.gUAsZv{?|0^m<~S-_8Wze-Swކq8306Ǘf"aҙUyl +kf>['/ꋯW@THHԁ o ++[#3L_NoTtZGRѾVU)X"{h,>vENkg;I@7i$.$Z~3@0z/Ja+}{m:b5{ENtՊ30Ԛ[wP ~!Q"`$왞]=Ph_ +C1iB0ZN~\r @~I$]f[(ߐV?{I%xQ:;Nrգ={OCv8#P;i-inE؊8g@~gg֙Zrbpt;W^C4\ +L|Wja 7[%M&vT>ufYsGVuY^1m)U4+O_Οٛʨ蕃|[0(mw3lt3vx;`R!mk ˀuASBsm`9cś+%ؼ`m4ӎF"Mzn;*ePAuxc!0Q^NWi/Eڰ;[a+ w>d|dvc2#W!#b0 -{iY0 1`3C0Ff;b6p # &ˋ$i~PwY`t0K~v3*_v@$ -0-. i FRV0 " @n7$^Llg+#p k7:_ܾ7OUvbY=7.Zn.SLʉBapL`\L悥m~zfܻD/1~Tc$.$] ܮʥU V`j5 pWꓐ zh7wvbN +(' HH8I鶎ꓫnK`S^LQ}a ::"c IAɎ888,t9le"()o_)N;y}ݏaړSʏnl'lhv7$l=ÝZ`3LbR p鎳D"pV‚4 +z<!δg6b7,_} ++F4Y͢0H8!ShVVpLoҜfK!\Xw[e.]dU.B&Y>LAy +}0Fة4 էQR,֭3u4RJc^?bd[VTo+^ұ7&i%Z:|]ҽ|uIJl t@Zux^8I +6QK0 +uBF,NHbܻ rq@Xli)͊#x@KОO8aIYM0h>}~2HCR Y;Ehi,b_ͽD(j7Ze_quۙs$4FԒ^\%Hixf'JJ)kڎ]J'p$_Oij};q{SE%V\u՚4&V03Rc0]zFijW nV\^S 9m Js_suwL X\*WjY۠ +{L°bf]x;B:3Ӥf{R{ljm~dl%4NF9_fcf;? KÁ"Am'َ19 +vsZ &]r$܉dۭOd/YeUJ-wX%j4i/E-`7`i_djqصk:%3tX~9me^)DGԁFr ЋgRc bHe.3]i2NӮ^YC8υkx83ՃLG?ϔ< +FZ%mmΎ]=Ms|,=80k3PZs1tM/b0$lVu )kkh+0]ƅV)Ч"m2ziB4nG2{RtŅ3Xfi(n@Zm]ipfN&P?QVڨŨZ!Q*7Ne1&jqnUKyHZ=tq;wÏ(Ώ(-LnҍrmMJ%"z6Vp4 + 0n,@#/Z׏֓4qOHkA [,2C~_Ap)/ gʠgA!LR67oS.smscw['6'0% ni}m\.ZA3x>Ce.L+I"U#f[|WI{K,͝[`E8ȶ5_g{BcPOa#`Y ,'VyV+:`.y27٭D.r@EJuJL_ n8wCIJE{jq!XtT0]uIH?`AKtq G00Xl@VhgW[oyLPlOBgUL*u'aɾ+PQ6f6l$iwy@,iFqd/ծ[`<$.'3D Q TvN2yRUxFBz~e 8drn'd`4ˠLaw@n'3L F4 )L xlxK[%0O3i ު,"F-)PQ0 .-N$hMuV}X(S?vWMB*\/lUvӅt V2;gj$ttUWghǿ3{ +V{mTwaGtfhk;^N%^3=&]iWQs+U3mnXtv/I2&mV9-dGZ~1ڀӤH4 Fqb6f+lvZwgo~3} iݸ8+sNm8+P +TvlrIP+ivW ."Vq;hW߉1dծLLb =ZHdA fkOmj׽|(ӽxL'#ƌ:sKa v{Evl6h+Qe;]؅inLDNn^a:,b _ L؞(}vD.L:sv`h=i״b>ă}ZWq%l$[?ZpV'Nz R=!Oiн_hMkO"䫰8FCF_0CzCOnNhM)*Ӈo\U%hp;Kݩ(_[m"(^v#& '|g~՜i*3ix +Vm/vLo'm fxW;X.n5:oQ˔ 8)cVJŋN*.˭x bLazd(,Wq̌Sx0>T˃6]Xu\7Iq0$:?z,\1pj4&sC`dEh,N;l Y1, qt~^mPF\aw˃7O8Íh|6zafu'6g +2c`Θ(J`6Jqj ɀQ u]"T~;iN} .L8(/mwvWm;FҴM8Lh2C!}0ie ˢfrl;sf8*@A'{b ]xw~?Wn[bV{;=+mnEs;V8pIQVW,ywcRW( x48Wcz=}m8 +~4Ų{^܁PFr+4zV͍@)@5"=VɄj7f) +zўRˀ&ﲻv :1 @+-i6OpfGUwЪT HݝRï20N3L@>mufz,|,Q{oiʮ"׺5 @SavIЎs) +h*KdFEyfHu&ؙ 80azb,߽*dn4: 2Qa&@85j-/b%`HpA8ݣ[URè .Ҭ\l`0dX*JY<1{?nUKz'h6AJįj5F':\gځ8t.^>VG)A8IL,f9xnv qFek@Ű(+Z]8Oi,-?:O/vS,RIy l1RYaOڅVyڙz:l+ |HPQ9=4%z@m=F| +7UHdڹE&\9 ӅU=ʶNC]`DzvоoOB[:CYUt!1PYv.[av/_M(ظȍCV]s5bN9`-0UscGƝ92&0!p -Ja +8Ⱥ@7;QZ5fljl8#}HCC+0O(ygQa*8'Ӄ4+ǚwOUQ +˞Z7Nkl"`Zy/EhZ:u/ˋ{΅ ,1j~=]L\sjU='Sf,=/.H4l U|:|S<7F<|AÞfۧL$Qju?/ 3r.9/_qev:O3Z*VF)nWKtc];;Nt\ŪLvEmA7{^ m.yB;YпJSP48sOi)g +Xji}M:7uin_s0:̞Ϝm4eӿ&#qb3?|-ޗ/*˷lϮז_VKTwu8$ ;:^>z=~29.d&Ij2DW!`6jqdimп#`m +L,9㌟BuNi)ϟ덃 3ux? +x:{X<}}ntS?x8y[uN7V]Ƽwrt]c"9W`,suP`&x{i|C*3Tq{nzguN7X ׽7?;zAeZgݳgtpf]Б]QpX~X, "۹if)jyu~`QmY^Gw侺|5~|;:s'ꡲzh>4^;KLD-M*f|??uOyesZTwk?nR>h ׀C)W]:ޒ޵ݹ\\٩}h|c$AEhG*$vc͍SMdSzRPuLf.V9%Hأ=WlW٦S:*1b>YM[Dw?\_mݚ?/yӽ\Bip!=UXRYY<{%#`e $99WXhoδwn|*3QY"6X71_ٸ-uιC%>pBDegljnQF+;4s)2`m:N_VdKcBtd.Dꧢ:Zf\,RP\BdkmjFm%;xk;T^8S|PPN+.gW.?lo++:A&fY:mwy*'dܱ&m.ՍTW@\ +ޗ VYPpĞ+TegyWe{RuIO;֎6WBME2RTw&M#<'z0@u؅*m:u ?@.Vc9[\8/. aLA=B!DPԁlx l*ƪsr;n!La`41I.ݳܛJԖ})#;l~LדУF%]"kل[iK&ҁaU^w3hRLY>PZMip4?!{̛=}+ +DmL{}jv>'ҊP]Ry ºe&ލ֓6dv#N szl. S̄+X\s+z.9mLLC{v= +OD$'&NNʋoܟvktMEGK&]7hfg +ӧeOr^ڕqH..-_qOѽK=[l$Pk/Oeo!a;'G Q/e&?*x7G +odj,\"T^޼Y3B3q;p%:6(I-.rR x3:I-ējgĀ!lȗd'w7ڊѓ:wSF e!l:ۥӷd$"y|=TU *P:|2 +7 dH4xnnLzr ./- i솚;px5Hv-UpsNlٸ7=6P[ Kzwpi-2>^uz#&DByPRكʭpeS/:ʘQ[01=}wojʟ0WvI[UMLVi@g 6> 5DRӐsX]Ik[+bnLƶLoi"Oqa^f@}ejcf0.EC:Laeo&T SXXhU>sX02Nspؕ{ae*X/~tw2wYafdp(FhST +A#PYypp*UbB'Pl'ίjw}LfP2\'eVu + Cm7h V"gjQ +,x,ۨ?vGxfzl)3{&h$T[9(wa>,J"v_"m(oCGf/ [6&qx  RZ8 jŕ?ٙXA}9ZW@ e22{RAg #w'tn8|9-w|ca&*at1Ogb]J2ҵY"X,z*wܕ`eUf i1-3;5v?7Oݾ,( (:A':t[ȸJLJcaKTvРj\k7;J,Q&߫On *,:ecs优[sK"(P"0ToB + gʔ #MDkh.Š$`Z+닶pn \x DM_U]Ѫśa[tRy@bH_ +&\칤=w8<'&(KH@y0s65%g䚳wca)868_9d˘PNo,X/]u:RF+kvo 5fkjJH2{@hp7}*5[]!>=7_DpHC|JN!ԨBx=YNOHIMufkg&8`oR@ q8}N_ x̸@uX꘹Dg)NP}o8DJj,ThJKۧԌ +㾈XP2/X5A:N持 )aҬQKw0_DPvN" +bɡBܓ(jdqPv踑>2=6WH13M5v/P\tǻhbJSeGrk%"53LJuz ewIv2d| + =fԘ Y;9 I@˭sTx\on؄96f<1nVc:`t58`0o%5}ʞTiiЀp3RFĬN[T(i]0Qdlq CmhzSm!G .1}/ l$[l '="IzU8<8>bi+-s R9dVk9fkLTnyb~CH-@E7:3{o\=O+o~߿o>XDŽ\u D*urw~ry{y:wiwqjGwB8y7dv_XITcz9[=w֣o>+?ީhaI.D"LjGfLDPHvU-d+W{{Ϝ^yW~^xؽIR\62@Je.6drx=]ټPYٽqƙ}?HnvB0Q.:.]k.IݯCy+)!THJm_osO])L%[8:>|wƩ >ؓ?W~ǿ租3/Oo^6ԘGTb1),T ]y^}'OG卷ˏ>3/0)rk4Lsnݾg{Wz?|Woї"7W~6]buL Dؘ\\{z_{|{Og_پx_(7rv2G:Ҳ!lG/}#Ow?Ko'}__ŧwxy lೞD꽉sW{oOw?'W~,G AsV#b>mά|#Wz[yݏO}|?~_}+on_4/7tv-B,Ijݕ 7S/o}?Ň^{\g%\^"5E6H |(sVo~ܕ;K'|w˿׾']ÆW|>=3ҥ7y7z×G~ޯ{՗]2ָxh,pLaiuwnyփ=o/֏~}yڛWo-쥛n_J#v0S $ +ɥK|g_~g}ś?;wZ |R7jkzi}`Sx7|w>٧}?{v>k!D `/5e##L|^q͟/㟿/W|/? /Sr.Vʕ\srnugǟzŗ{o{?ݗ}/?|OeKZL95DP/HD܋ k۷{꩗^}海~_o_?~~_'ޯ<[tr}LRb{y{_|_w}O/}zU\ȝ*Gmtl\X1m\o~o엿?/~~G=˻L/lsZ#b3]ƒĨsܸx3l2VܩzScjDE(-"xXjTՕtgkw w}k]*MΰRK{b?69fNZ.۳yqfT(ϧK{Gn?x߾ǟ|S/>}~29"T m2z%dXk6[S6~ѷO믾ҋO={-njS,8ev(wR b*$X44pko/|vܩB͗{Lk28x:y|R,S,;sx'ƫϿ/{O>*d ` iC3 b/&3g.\|y_}{owycs}3(Z\^թQ&܇ endstream endobj 80 0 obj <>stream +ҡ`Ê)3KKo? ?KWn<?/~w؃ݛ_\(Ut3;͆_]_V[(5Xnqqy5`Ǟ||{O?˗/'r%8|\e֘piLczJj]JKn"`NA[ 6ꬔ;gDzP#u&Dcj-(bs)9 jP0=֣GT e&€PN!mx6AH(Iڝe_$jtZdPcc + 0ѣ:b@\ P*`=%xA +P4,\ܝD) *t*RեCY.tLk*Mr|8.$b /~7X.gp^9بaeHf<93h]3FDkDZ*eVޮl?rr "vd@utPGMbB,AtFPFJmVtS\jgd:ߊ;}yҟC(prQA_ M$SԞ zCL!#PEO`{X?1fBRܰP< Ymvᦹ8#@WX. oU5 ;1f ZV2R\wv@E8e$LΠR>71vO€7!#F<`c3ttB%B-<8+Lc2X 8+qohWa-> +3b96DpImG65F =:LlknΌpt`NцqCCGfkLTZ=*@{M{Rf@nxYJs!TV*mJ(Jm%kp0YԠB~U*$'Ġd$ohjily"Ɏ5TazXJ̬A MԨڡZD0/uo2IFGt5e^dΥI;*ƧP6w DB'[~]~ q#1 ̓B\vdxlT'3V& +6 r)-d ]2àҬAX_fO: +L?Vi %7w)m~-r5wH'%FkZ3U6: &,-~uKRfp`}a&0 7,[RJUvBgL]yt׏:7l^o ӠM?d\BkB蠟p 7ц㦓c&.l+J\cVx )#:(Y9+BGL)ѡ)q|Pbl%% JX3r:DFᇐoM8͸=>f"=b{W +wP$#'rGrҜ рVP!Z¸'aѵ.B%;`YgR!QyDҹT͠\zmFԨ +٨訮ӍÓC:.#%/ic&0:p4f$-̨ѭBgLOD`eL#6:i+c6w\e:>Ә]#:w<ˮԗv6La\`DQWG*}y`veJkUPتÆ1QSӁ"Cكq1wʍ7NZ r '5 #Fmn#jz WX+Trfshа=lՎǼ52:7bA4V CJ',=^[^㾜峲a'6_&:j2H.~K\S8+8߿E{hDf fmd5x +H>B_JXWv +EX6")*mjgtT,ϬLظiPa5`+C=ySXھ.$[G +L>7j tE;xdp\nb&2txDߔ@Hg* -abw z uX 6іO99[3wx fi@1jQY |tX"d漙9+:b|X wP7ylla2Sar{B[эh2 LPr9ć4N%ף}1IJ~uxh !wQuE@1&å0QFONM[}y#%+K׺g%Uؔ76Ou›IڡCW2Vq ZbS7|ʛ TVZjC-G*>| -1*`".TeFJz-dL Q6i-1=$,Ww5"(&|pqSОLEWXcQAaAV/ɲѶ9hPO u5w-&a+DFa vS T ed:cUi჏PXcP _5 gsQpa6:*o$$;XI 7;f|OMVOV*0ͅ +Tx6.y_+H˒n&K|ktcx5:kXڨSlt P3;O-J_JqKe 3Ν[⬁ PY N5kwyvٙv!+Ekpz&6bar%fV^*o8UnuL ku&x}3 MU`,ggΔϧ&# .3 +Y=6I&fC} +n`|mqjo4ll Aj +[XV!:Px𙷦. Px&ލN?8/pGΙQ3 JauV*uB͝ԹCAP?̹6jO^;_JO@Z4'Aq <6nu`iT8 #1Qx+ +=f 41 npK(Sӑ2Ra#V7B}47aӗyQ=;!ՈII6\`ʌ[ WVWL,Z֖nƥlNLRlﲉ s| N':94jD %_aM͘Ƨy\*1!p-Y_߽vEV^Ÿ +7ۻm"2'#ZRnas`2?-1˘m@w\21"T ACdb"ZI=i(pyavAfr@h9Qg> Ԣ|067 Yy;ٍL9"VXl$dr|9K 娑r\fa-8 +QN'nl^jbVa)qE+wjn0W ]z gN.q_P8 +_քٙТ")xd@=0cr |%71Е5`15*.YꍖRͳRvۯ΍(Ɵp d}\P'l< C;HtϟM^:`k"Pc=fT@`!jUba)>lxROH4ƍQ Jkz΃ŻfO! .=bun + 坣c#'2fo1 # nfTt>qTeӡ젲݄Y،#P-^Z3PrhIe4;,„8P=>fАv@a?=H-^+`/>U)_in z%3鵐oEO¯QRNjPQi"Qd`%I^F b'X%7d{Tltx- e0tJ'9]ݏ#A8m\#U1XZsGgtMAPppa-1P"ddM|;4IƲ79lq+?7zINIW7w T*=0w5j84j3a"m=.jlXɰD)@3SvV6B̎jF5+!)&!*i_L0s:n$ZR`~BWG n%8"!ƌ޻-"[u)uiU?2jH`9p /@\E2/d3/kcbx_ZVS bq6w  Z߄!8TvX`o|\f7b  +R5ax?x*5{JLB3s%dolxۛbz$&q%4whcV?C[u4/扥fkBgƵީ{sꚁ + lDip_\%uD Y$V^tZ̴&CdB._Jgi#PCduq}Ng4hLz@yÕxqnTԍH5*B:e4`)Z+B9ݸG.@gK+Funӣ^q-1v:-|*Mf%:g^{7\3 \υ+\9xXMh.Kl_8VpS)5eF5= +D$&jxK\*/rIoo29"Lcv/(٫Bv:UmfLPzӘ=f%6RMT!]f_@ #gp@n+}EM:}k|24IuT@<%;5p:bDTa~+s@!Y]x7ޯJgBƛ33ӱJ՜>MiZ̒_" +ӳGGAiAȰvPnQB0Zݘ??d W .%Jk +Xi^e&MubޢM䛫-f<`#C&\TI=գ7VC܁QLN˹u*ֆ19Dys[ wBm6|mevfq'KbN)6S]z\À[V2'dHKN(l bś_swFV#3^|r3@IX @TُO&zHCX 5uL$p1n-/];"x̱lML#{m`y0jnvJa-i (M1|%0,GgRSP9>^^nԔrz=qb2 3`'m8sT!̤N'DJKL tRڜ!JȎLJ j36tRsq9c]_Sz˗ /@Ęب 1RFG6Ϩz|\GL̰XYs|XQv&,7"D}on>^|, 4q[k8@ DiQJf'Ӡ +qtGǿ~dkG(N*ljS0d'j'D&T\љXyCf4${|z +R*xJ-86:9iml?Gq}39:J4sݭXifʝSU疅Bqz_iraj +7Xk~*QRKH~b2"Ć +)3dpL4z2t@퀜'g4֯;k@Msz;w֮?ooKK{42&MG': 86A6]B& ̹`C* SUPoD`D)x+N)GPY + +2#"*j {d}> #͛7f : ! `?Ë L sD7AFTZpRmaF@)$וOF"n.gFͰa2LFz}eUtW7n%H!$A?#4#Q#=g{}sT'D{+6NfrO`ãSKǟz3f% BR() +3|>nA8LBVP@&ua ]c6 &$o@⭣wǝ|Թl_.h~wv[:ӭe~:1 n?UJЩ  -eRefa@-9X 0mD.*dԂF=?*.h'Y[&丘1$ "py )r݊GT|4ufL##-(łʍBgJL-<--^o22c +,0%vW`R)߶6~tQi$T`.Z`PA >ɮj%*- ?̷7J;3@AQs6 Y/lJ%z'@I)3lEΛqBkegM:ڲ "Ug@ `l>Aw|HvȤa/4jt@߮\saaR̒,lUWnv7Ozfw>,|duyggL8Fiq3l<=SbT T)f3{?\$Io/8Pdڿ^.8Bًҝqp78 tsN!~f.k4`AͨjD&3DyvzxŌ Z\+x}yqڭ}b^).j o0gE'>jB4ij~A+,! Q|j 3smcNE(l'W#mc4-9y@zMskݶ!Ǒb1އ vpjcQW:W8&66zg o4{_d;o=x(P z:;f,f8٬Lmu/pGLm p0f.{)tbZ1 9i'e\.6q4y1gwA?NO"'&Y_wL)+[1FH XtwQg%2{W@Hu>kp7;jF_l_ehmhШhE2Vvq)/ߌ7tRN*9,9Ϲ(҅Ts*|&T.A1Ê].g}ęq'I`5 zsٵBo͆Zu`vaJwñgO%%[͕Xu/VDF?h4BfNCN#6i&\]'.8IXQL.'^}:qY.vP`=7â g{Wv\0i7[!TXP{IuHrIod67.W7҈$T@'=!`8PKj 0VTmyD 3 {o}egjsv­{j<'"R ,^@o2ЍS^B*}!wNMr@CȕHa~!GR#m*13epVπhH}-7\_[8)Sd+'{O.=_(DJp} O w7w + F#`%;9<#ft67skzc/Wd7X;"L:Pn_.s w6Pwep/s+RvRcNCEԌ:pTWL@DtPX K+Ֆ*mJ"*W<(Cp ?; 2Q栦CL&Bʆ RR8{xfpމ+Y>|Wc`"S03z8p20cS#6_{e=lD&mկCE;8einzh<پ^}vk+qėCʝ/ GڸtV=2/YΌ<@!MF`1 |nFMݾF =Qy-ѺRU֭dA8QzI4G䆇JZ`qIx'5¢3n Zj3HnGc~.ʧ{+Łt ,Q|}ڵ3{IE:VuQ"i#R8H !>P Oњ/A{9V,,z"#l@H-Wne/}!<5۽\\?梇̰ fk +n:EF`Zr-~ He֝-/YōoG17ʘo3Bv,Y}|{S_0Hp` +4,\ӳ4'nqG|eC$|S|O/6n_A%Mr}͜3.؀c@y(޸@ݴc`Q3i8cd{ʴuwɍ~np[{~ػ:z4⹹KCֈ2B"!PV;a'0/pMMV_uw+KGL];*ugQ6fz +%mlXݱ XsDyO0 +%X{*P&mOGZy(?w=U+@Jb>{?sCwZUw2 })y1DdFGfHB@q}g΋ -קՒp!!P;vxi!ڰSm6Žm0hZRcԹ T7_-/\ ^.?q{~c,2VDw^փyzVI'磀f 1Zŕ/P.!驫ZyIJu8訕0y\Țs>si_@#CI+Zn.O.NNG-' %Ug61e窢)7Lԗ2n)fXjvwu6s bv4\׫mJ) ~O*G̰ǂQ.>fCxH0Ѯ-\OA~.w3ͣ'ĻT fˉk3]^kn~߿͘:G\1oF'^8|uzNvt-;/W㕫]~~24?{$d8ۉM$:;Z1 ".UY$\1B2&Hho+^p Jt=]ՊL|>6秓?. $l~e6>*DdAUoZWv;@rO43{V k:q7'^6ZT6QwhAp1!RX3n65X)/ƚnB'VyK3ng.N:o1a.DŁN`9=`F +➀!)?.,v]6ɩc5G ZR\Զa*\ Hа(K'b1(R%伐M67{742g'+Gow$j\l-fg ׺w@DˡTԋLݷvna`OEbnifrcj~wf0֫KnwW?zʫC0/ԬV٪-[a{_(T ~z'A7;3}˄F0=ցjxMTJZVn3+N2?Za(1"4P[;𷛳H6ϥcuLș`Vo.SV RtGz0'0)st +PP`oF@p Tlxp)dF&8t^•Ll b^JgԲ1*ig J=d$RNNwRNDBܤ:7<} + P΅ɠ b6ޚ0ZF\W/tlS^R +VXDlP~>$A(5E +|f:Vfsu5^{7OY-_}']{O?j#qsxv[an#Sî:|z2 +k3}6եMR"+}: ܼZِZI%Uce3Ąbx{O$Z>ggaGM~^._4€tG&P&i{.BzF'ژco^Ȥj%7=p. Y 6D$D rd6~J3{ '^\dCj$flm8iͨ6TC.jos΋M0i͉p/6oF Uz[IxTBz:(,n *Byqs&{Ͼ_reCk_)?sR^<~K'NfNnxڇJa^o=`#.vAbJƝ-wQbM~r7O7ε7#S#WF\#V҉`.K7|z{ e|bNS>^k='\ɻb 2 &NCdeW^;L~_lxieYa L̓Z rsfF``621&ޑK+.sb z&tj[ Ah6az@`혓ؤy//(9?ٟ{u?;S,9 ;0j,QO f80UNv!!K# f(Hr[Z)O YZ!*cU5ӆyQ +'H8{yzNc(˩&lP4JnG'- ?'"B 8L; Y:c+"!RǸ8NP~ +_uxWg.ύ&L> $DJ|D;sn:drG݃uaaunif݈a'̸aƉQ2.x`Vg(# B4?13a$a RSuXLq8!>ty}-@ʙts_L/z%v˺Pc%dI*ʦ]P($$׏oEv`rӋ?aG{6嬰h']ǡlV<8+FJR'{ACY"Z9WA\pELN)5/WerqNKq +E^:o:}6f xɤͻ +RSH0 յ%;c \nlpC$tq^,F#S,:/x C)cV?PQ<MEi͋.lFp{А7 m0#FE:o:!hBx1p-Nmb"Tăk\H q˸CqЄ yj%p93yjʰ`A`再.`RA``R-J)Y0~ܘsA Dt8UR3-VͻPBF.(P 7d{?4^zFp!%Т B! .R  SXx&CI6s hG.*3c.((tq*V`PI\6YFĂ|ڙ1'cE#_F0fGqB1 e)щBѶ &R`F̬.?ct" 힀+.4Q@s')nEц\]HAX}2=;^<җÒڽ}w뗆O_0,qaB!X6tV p߇$2J IY8;lzW&/؇=\Η\t3=VWPŹnwϏDgf cFG;~و"v1%vMM%=RxqaϫLD>uvttpx8h-7ق(VdLEYaظw뫩|˜¸<1 bpDWυD5/TS;w޻?7S42Rl +J6jZ%i=c:6{cL]Yde|60@1sӧ!(l&݃X6McFz^:O.7?՗w?}OOZ^trI XQ5O3Uyc*N#Sy zk֪o?{xqd 3l rk7IIt[@jOioprX¼uč_͏|շt?yuoO?{Oީ.L碚łb,Nzl9ZLvmnrǿï>W'O?>{}W_=~d3"FQсnM~EAxϧs]uw6zG{rgמ>@, I!Ќceލ_u[Ͽ/?#~㷎{وHVqo^F}4+?Nl+GWox.  Lr?SK73xm~x??~Ow//OO~??~gZ.- \|#6[Gw2^O^[W~{O;;?zp #FxleUZZAG __|vg?r;ZzZ U"֯>w_[On/|bOog>_{z~J*tFF-O8F9`kF; ~W~qg?Ͽy?7}ݿycqqo:\J}#pXU+~3LRס߹򭝟~t]7_/n棝嗏㛟{ yKv,1DNȧWttl =_ߜ/_+€,B2%v;ÝO׾zWWk޻s@3 IIAE}S^ZVog|x{||֥FXr *HG"QFGߞF:佽_qջ';k˙F8փpˊj%3qE +DG{ЭҧOᄐw?~Ͽ~K'Nv˅hr*@a(4t^ٕ-~___n%BbNgM+A|Gn̻Qn-vNv7V[gO׿ws8p2C# ]l[j+u0_S~J׎続v#Ԧ + ׁp?lR\0' +Rt{*{yvՅ~zϿ|~p2'ѻsjv6; FZ^Bn/"̊\!ՠwOz'{b= Nt9"HgUΖ~fo>{{уՏ>9{Vny"|Fi`7{h%NWVx%Qys~jk/u_~5uP]iG+)Iibm8B)-QE5BeT_wf +K n7j\SEP#F1a*EBn].ҩVtR3_GK?'Opo*nˎS/׃"R\HGEեS\}?o>WVKzTxZLz"%;!b Q jLdl3R'N;۽\Y!RP N# LQ̏ .' 4ILFL4(Oj,ʉ= +rM@n?F2-0VBi2妺+S^^ W + F;9 +R/ʨ&vry>;lcãf"=`5t?ܟ֟޸>ww*P8gR#<F)@Q\0(sTLkJ@(D'9;΍CBh#vF ebɂ吙@X") +I09|6'fsf1jAMra FH H&,+WBܓ@/|8kq!'J@*"LHCÆQ/!* +rTIeߙ+,5#3Ks~%UO -)6ĤcEː1`RxIi[Nn?i?].^!7BglNTS13ˣ=UA| #q6Iũm\xx'=X&F~L A&z ~6cG*[ ur.2j9J>b\sN\uQT,R\URaɊ~:9QUJ8%dGՃJΏqN!m9`\fI'G+cGc.EeHi#Vt2n72b,D2Xic +vR@*hU/! Otdo؈bj6,b +VX&2 '3l^`݀Rw6h%)VBQ0_frLdlj)XW,5>|-DNO@&`п>5v~G( X 9,.v|TdJ̬znb9+Cp&;&Y)Orqsdp?̄'du~ .3 P|z(;`csI\Γj9mz'h9$x=ǵvyy;ju f@l.#=/`Y}{w̎kN2I]&Ǖ:!|mt-djEEC^^%B%-06&f3XjyBlE:p`ej~IG/XP7孨bPΆAomƠ\wrO=/81f1+][0:i" +?\Z'|ba>rKh(cl_(GݝDBCnz/j}%>}]mzmcE4\}*1v: Ɵy]#6@b@km6ʃdvB)   DW)-&f}T%W\WxP^5/%\U-#v1ZTb>\ގw:W55XsJuDxY”jugLURq.@bHA֐1K!熜̘%{ٌri>3U[@XnTڤ@Klt)/_ u,҃"1e2iB +K@ZG. +Ҹ#F@M]&,2,͜7@/pEReƦt(08Aes 3~eDuBaKގAgbSPG0݆jtkH#rйleX#|yt拾=gzy1afbӈXN@-f#6BPZBGze RM쌎JyLk ՚'[t>0LxCYC i*v&CiK65:nn>ݶR CDpHD&@HFrmWn^&"uVK_.Z(&WHS,,WHsvYɠmTyLιL}~碓%~)>J\Xftr7R0x%13Z[ZwPɾIݵA@Ӫ bByMd6UZ W +>Gܪ\^"Y&ⳉQ~O|&>D@`XGLǥ1}f,v E۵#0xyWLTw /-ag'SfDw&*lzߌ,5,.HhyyMTn\y'_sVz1_ϯ=Jޤ::NXq?Zu7^p^32vVZtzEm|wy~cC$3 ؉RxIIŵ 77:%;ɘI u _((@t:޺R\B*]*\VJ{9cJӋzPor9/_v:$PGN_Mwwn=c K@l̒Zp8󀎷AeA~.V/ c@Z}/=}#?wK;)"`å2ƀjX{Ӛ\MuadDl:9 fHW-3gq*dZR$:2 +`}os m],*ֲ'l~'ՑPO_FJm_yc21c /X炍RT|!\lk@Tiz7RrFL_ڭGRYnUZ+A.PHm4{ VryЧH^6 ƭ;yt >gDj`A&QϚI$RY6/kLqhA5jU,%@u+ntBsN).+۠LC[% dDܱQ)]MNݜ*V6nd:X85>=hnReb%="J 6(4aS\ +;NֺRb1?c469T6wV-_{0w,zvnj֛Ji%=}Ul[۳^QI'Az/u.V.0j!"H@tzuI6Jk;͝Wܜ"&T 1'z'UL*6͘IZWDbsTj)[s6\cbHE3D\YQJZuC+ a(\n07/62pMxff*a3@ +Rfnf>,|\tm:\ zq cBj&3}9N&B\";,/${׳'pyY.@g`p@E✑:,/5ΛFN$P֚t/ـ'9+.6 '}'LdDbRXe,w´3 j5Zjt0NxX;ѦVInF{Z}G*.J5R^&õIKziMO;h=ٹWK3{KwBiJ.5gK=Tko6:i5wc1/z @M w^0rqI/r٫/'bjvnQi_-JDjRԲTڍwj37,V;qPJUXhy#؞^Zk`[ $J[Z9MZ Z}C*-Z2pb5\CR5֕Tny@zm?ޯ`Jy9\X&:qsXo6vO2%Zkj`#=׳HuO vEG0.1%׿;|Xj*ma;O>~օfc +!b +kCK53 >ZbNAf@ ̠'Dmi`̌R^& 8 *ze L8dg?ѹu\:%Lfw756^Mr3^Xҫ 4*=&jR-HYpLZ~5/qD(XIBd. +e)7g6\[S{σ%!UThpXju$1\Q4D{d Bpz:[[y'74FD'Ԙrqd[XueVZϧ@tw~zƒ@wMoo{{SYuuWn 40f93$2P"dBz#ۣ]EQՕY7?sܼTGC5M髿/LJ7rbB`Po.mn +g/g&y4d6z~]?*XP/LU]}!/G_Ͽ$Su +XW ɓ7./~nL.m؃f +lX_{'/~[UU6~-4zW`_[?(]ڝw6_GZ'"ŷUc/ԏmۧ߄;?/7b@i_oNnngQs>:2RvW>g7l|J fjS&z(~}{֞f Y;8zΚld6>|'AxRV^(CY&/7`V1nv8o.4OqwG`:= ~]iҙB +Ip-3׺Q-uz9wWwé7̑*6 Ӓj+Ts!n \@Ss8۟ +T:;j/_CEi3Vpg_U{MFF4p'G/"zsduV檹]?~hy37gy( ;?yћnKB7Y?.I}TMV[gjM*FӋo@"zU`u[{^J HY팯o״;:3u[z xzUg Qkmmꋢb>]|Y3q f a0~2:r;951_Xm"\fnJ4=A˺#5W?njsx]!RTms3F%:8|͟V (s hfbeooavSؐV[)yt$V&iHuQӨ6s߲PPk6b .)ol5`,-K{ۧ}{Vޠz]f_y,̦E.@‡pÛ";ba !`e.a\{%u&bttNj'8^Zí (]Ic*:iEò2J#ꞀBKb8z9*p`{E2gW0Hs^XnB@h3Bx?|])=8| <XRi]ryL]~Y"BT!ZyOy*?LCV h̅AmF7Vwte#/3c;1&a2y9>Mr S)8~K#JczQ(YB8*_ckLlՐy)" 7svsk:<"iYp]ƨ*7Y +.!?y>o9 +.s>;K~  OY={7MsmKI3>ZVڥyJ™ݽxb4G)H! :i.4gR)*|c$~DYÔ.7;x"ᴖBODEMUۜ]/%$OTF)^AFUbN>>y?%hVѾ M_ˍ(y(3e5isd !I/8e>\v KXw5VϕAꇃW?#:M.ϲ)#uDh-w7Wߋ3#b4F|F2g1pC%Z}AӸ=rF/[vNDkơj>Ɲcoz/`n3A?5Y Y_;ܥI4}X=\4/ǯ;Bm]%Qkzז D,nppmĸdr;Ej%IXB^|?Iֻ/}]5޴{:F@d}N#JQQ̱fL$=R3[sjJ*nRQ6[cEsj퟼}匮@%R@Aí~xoG@NtjMiXWB9vxhPR4'66AKJKkl6~w?$J4Lʇ+uwfWoZL UA;o)ks^fAͥx,zEnٓ*`Hk U =/TvUĘ<8j)ITⴏJ m_z{_Pd{y^>Ѓ]yޑTv։[ G`U!L2mI@iA%Ppf1*dDuafXymghǵK{xS[%xOEyKzM4fυ5Ərb,%UDIL#V?[g+ʟ,PZc'bTw͓F㠀Q{?|n;nQI>j΅֍ݻczw/xi +AcJ2j}i4j4.x+9 Oƚ2:g +vu@up ڊ0R6WRҟs4K8OPCa%N_;HP^5HΔh oZGKn`0b"!hW@q "]JzMoKm sGN.ah@m]+ai!z6lxwƷI|e2 ]۸ ;7\_R meph_;cJo'ŽZk?Nn! )4ǻU 0m!X!HUͪǑDE&<P`,g_5gUf0!…nEs|uN7îdSTI0J٪`6;bFUd(R=L p!Mbg+du@ WdgRbrƛcvAu}.{Ydb-ћ3ě~} +.piO8яUT9mu({#1\LjO fj7Y"`+B-6eb j}mwNA-Ǭ1 hTJ1pV Ȟr/- +1V5Ja+,U)ϐpSzĄ o(EL +8kX|BDڽjLjO(.LiUņѾ𧯽?73dEGئӿ ϋl}$)'GXeM_ ۗ c0ime#JQ @Vf2; D}P3 +( +ɒRueڑk-ʿ)iۍ5nt!I)(I|SWӋҘ'QGE&K9_J#Kpwѡ))(a}yi>e'2<%&D5t R>N_7I`8O0`T@ETBR-wΞ5V/1ZěiAlH6 bCB*9z M] q\lFVN - c3Tr'vbo (wqev!ܣMI\Y"abx:#LHxqz}6y{eAsl>+x0ɸ`J#"W))!ٺH#͌HM=I$r lnKX2 i^hcV =387IJJ@@a[&6„ƉU?bNX^`{YfU!LH`t+'dD07!JʣTzZ1 nN]URiae \ѹfRl|K Tr+b0GvID [(ᒳF%2H%f%x5fMLBּĴa0N[%o/rDnjeB" tD=|Ԁ2KELWŤj|MA:w8]_t^W iUգ1jU!Js +wFrƤ@i0z%tu4OYy5 3cƦ,a # +Yr1$#AtQjxj,=|;" )ʜ QҘ138}?rz[P>nv +u2Wš)S+l@*, aUR\FN& +Ά&< ww~^(ރ$ IYgoճ$SnxB|=kkΝ&mt>j'(J9Z=ۿvIh=5j5TnW:\(p9 ΝLJłN0Tki]#=TpJ} \D=o|ÇpNِ|ǺC +F6Zv㏟ J##y'S΢B4谹~GY$Qۂɣjp)Eֻȍd\d]Z`Ty P6rˇ w] (m-]DO^S7z\ŝ_c%Q$,qx_@phSF p1`ڔ!͟zwNu)8!)# HIT\Q@ŕ!> +L.e.%P 0R+j6U\ABy9Bm^{Ba*.:m_!!2' +|mt/~]*`9oQ렙@ ֜~v +Th $C]\|8CARX/&5| A|R (cA[KC(!_' FdIm6Z%tp^2 LiE l S,a-Ф@Ũć> iv/aDɒ7q #_ -r?+ + [iMTmņX;RJMB.J.h15U*gC!R b9=—Sꀏ.5)y,i`Zbm ZDɲg2 +_϶%glcwu(?РLJl:2Ɯ^Iǰ(Cb^T2g:R,Rm>E"8{d6fsi4aYwKNIC.`7Ai+q,cZ(!AQ'q{-CpOsu^'iڀ<`jgLpH+XeƲЀIG4p܂,:$l\T.Bdm.ޭ^2$ނnϹڦ +/အƤ6t0y(gRFT~$ M^g|pX@Yg %4goueBZ[!]jb 6gX/M[7UZZWb,τd>嚐 =`o ݔ^b\X@pğ!N0҇YSjGE}U`[]op~C8\5΁1P3hx>< oGߗNUaJ?My[1YN~59XON|\C`ԪC>:(:`:@AT˪ԑsj쳇?zRL%ԎJmRQd@ Lqwf ̂( +EDY379 W @秪0:]zܗ5e\(YwU__QU;&菭AkU kZmM(pF +eVj@Vb&գ;gD IJ%\6v "f1IULe0(9 ErI"؈ I}w +_ 5[a`oS r&@.yR+Ӹ첳.4I!4f=Hy҅(= G)J{"6tqO!`=xsX?gI‚HĦ=6QuizTR}}팟ɝ3p4 dw]U$QZpg# P"XøBt") ~}'W 'ϴ)C67s0QJ>״5Ad&T@oC#5??I +WXƝ2rAcF^ o! [kvyY$,@ nLW5Lg"Zȩ.5"xPQ;>,˭^Y~#H(W3{q,[O׮4!K3SFr=| >AfH~U_pw*vZCJkp-B|yhɊAtը+yU$rL _U;T;W3.Fo$أezzJ,q9/9]0| 7JR?'>,D +/1V;)?ś |WWPDH1w7frfhY[SƠ"rui.H_nƌ4Fuc¼a oeE$1,jx+r}tgBAT[C68k׬)s>-WQa!Xr#[ Wh^n!'UW } +S%GYr zaPnaQAFfw3WZU /ǍٿhnkJO\XCڙ0<[%p^6@ i죊:[>_$0 TDpdo/185굣\)sYltnކs MD]s4 \AG]%BHޚF9.]<ܭz6foyvwN:|7),V^bpW1h{v߷~C8 y1g_`{2)La.H(FaDzF~E惡26.8 ~\ qs->4~л7 Ta-T]JBO;1:)))̊9ym>aW5RngIQ1e6ۏK[%qa+>,P_u8KQ0գR8a#'.ca,pm`[E?EFQXTJ'BZd#!"&\<bɝTaƹ;}mow b5e)k\Yjrp pEbl ]F\q'HܯT)׍`FS[c :99FX0{WM7yyw^䮵ܵv?r@Z]kk~ w䮵ܵv?r@Z]kk~ w䮵ܵv?r@Z]kk~ w䮵ܵv?r@Z]kk~ w䮵ܵv?r@Z]kk~ w䮵ܵv?r@Z]kk~ w䮵ܵv??m3iz2W&WO'~4Z\|}?*WdrtJUO/V'`m69ZrT+]\_J xTdro}|t B4IiK7/OVpǂ_6VnyhA׏?2{RTfH'8?DP25BJea5VzZ?vgV!'m󿨈,iSZVEh k*]-hkLf('C4^Eʡ&kh Ҟִi K{Ef/OPj3&ܐjbM)0ΠXg)GGZ3esD !a QQnonPΧz 9g`4e{VOZUm*SĜa%a4娍{L])sD(zg}T/(QW"4etcUE.s6.JR/Img)G=Nzh}SLf0'he۽w,1>eQ`v򤗣\cƤ+Jђ[+5B_Cd<fI7K81ipj~ad_˴sID.N,f3W:(a*j7G;9&eu'/+Cʜ9ybҨ\dk5k;Izo#L׸$uҕõʔ+\f/E6$)e0."E<.zD9U}ҋ z tU)!cq 8pzS"pUOQmcL\6V7x\,6Oygjmf\Hk,9mfF%?C;S:W{s`uPKbjQsZj0y+1c..I:[9v'ǵa6vYFofQfc!TɸlӸɲY1=٪?!R y +qv}$(z1+ag--OE&J"oD  liD"y>O?ݯlg2`rW6zE- + 3!҂E SŌmWC~7%8OeYoWY8(~UFMHޟsΤGߘ~Y7J*4ޭ}R&JHsDlFkVKƚHKpV-z=G/h]\nKq<])*A +^YpCNm̷P)C=`j#zE!7ǿ֯* >ђVUs"kwNqgꝧ:hoUVUcćS0ZvnY- qTE{"RA$a.dvQ"_NYyfMvJY>Lϑ6Sn5N 9 ,<0EmeGY:Ye͸"&ԎkʱSCD RgqR OOP$/ ,pG>N*{0XXТ<*!E{&SRf"RBTd5,< [/ +ȟ8,l\[,pذ,ԉnɼ(v*~U 9S)\3>+Z$Q_`tUp\ƊޣgWh:s.m=D)1u^TnYd'P#EX?LG4ڔuHX_jUE=fܾG%4O!包`9stpcxȭn&P  " +ﮝ+$fB4x:%)s )^^YJi=%a2^E.;E*xx;O%8SJiDK!~Aqʯd΋E%#cE1K>J~LTd8&aXkLu!l - -LǁGh DC+lDR~I y"i>!up%{S面{e%eK9J\Vi<ƽ2{E%Uu!\jH2AA$-qmT;0ѠaӘ80M䄝:*R(Cryڊ 3q=MU`"W%9 + *hlQlEUvIxP%\5w!hv%8<qEI<0ڧ֯ȝv!SМ69٧nt(}1^sY2$]6o:'o bDX#_XҞrᦪ Aep8E@}W:lo' MGc֙Q\oD'7ϱtP%䩶s6X'_18XAU!9(v@Td@,%H:qk +8a [w \l!ݽ yވS+CT7ɑ< DY`FUh >)}#K[vRpU};>L`Y+(VN@AUԸH/H{5 D/B A]1Q%?ObA2Bp'!?zuA#b"vJl(I +0AVbN-!$߀=x̿ !X_͟aZ; ?x{Zq98q/ +@7J:F//_7"):O1Q^hV<7zO#rGi L,K" pyˊ%!Pg̓RL_EЄ'SSjFqieU (DhTCƛ +"0ysδ +RKi[`ƸY%vnӤ\Y ;*ӊ>W lD#DjY @ZdbpTUQP/ U7f*M9)1^k o`(ZkA0ErJLw&rp`u&$T \{/bd̃ Y +eGhg `NQ? `FB-0:Ġ*+Tj:(^J`sYaGXqX$&+ڵ!`ڃ4 omDT3Ntx%ʋ.Ne0>OiTQ\0^Y-3<-%϶%F}܆(IJ(?Jbgi|,aR 0' JyV/b' D0e&LGIb(cIQ,b7F\M(D{,=?LTzid˜lB(=W +I +Oct~a uUue%HDGuiV.4UdUCq$Ekѯ(]ܜfxgyQh`Jt8;YdZ%ֻ.4_$kѷJ2X6X~B ?k*ѱݽ^ս%nwQ RٛhM՚RE>H VQ+nh wo}1(#pĄ)mF\"a+R8!Fs\yrE7-#;ZZbQ`H +< ĘU0y/6rORK46|jwLBxn>*6lFYQ ,@ UE$T>le]"d@'fbPeJ]c sE":(nImm]el<8^qE K*ڑKn9]˩i [,dj'<2=x!V p7y\AWsw?8ruO1+H5;}iO7j^k u2෎jY/`4|m_d.\?~:GͨX(߸CFwDc+#! c5X iƣG9%Hj^@$2=|rJbO!# n>:IxSh !۸4el]0&lČY9"(!H9\ԟsp5daFy [}*p?lȺ 4 W&Rs D> P'4*17]vi0&畛f*fj}uw: }`uۘЄԦ̜hӝ 5: MD A3b#LP<$K} o;s Nx^(OцG(Lx7?frsCB@_<E7£2fvp6֎*R=jZ&x[4֏u"`[ 8t U &P;`py6rzhRbr70lYQ7 R$Jc6nD\ 4?x`;d"Œ87⦲U&1 7h=cy(hMr/xא_A6b1#y>*qe+s y(T2vNN\3>§imB%,:,!5-1<>eEd#. + Ɇ xdJ& DhXRۡqO7y/[n ܕ@zW-(Ef!z +nۨS iKuCy0#Ha.*jv" /:+>lb:O8TF k?Gt!3-D >Mt +:kVb/m;6 a'$C-X} Xq^`kf_T!"lxF\H2b vqDG:qeiA&JYL@6r#VA +Y>7 + D-%0!Pʼn'MNpp>WeP Nlš|#qۨ׆'ͨjF6,EvLbnqP'8ݧGAe?tdZﰉ 0@X}AL_.(&_dD=U0u蘕e2u“Y'q1Y#s ~xxͥuN*P X\R(FDQ[:VO,nů|B2QX %O+W c#na<\8pS[3 +%F@mʣRA&`@.29x|A Ā 0rCLJmCf$*D X b4pڀSe!2`#v es>`R:g|1!Y'43f` +H8aⓇmԘ8lp9^O?bo`t %CB&WЃ=Tu6;}g~aǨOUfCVaxnlAR|-8G )Yqg@9a(!#e a8 7/T3hD#CFѐ]`6fȞ d>`!\}C9̪L‚nj&`'0l÷6! +Z#fo3 *P1?@;OC65`DZ HvJ묌r~aĄv>>Ar t'os?GR5C[n$A#_vz_P̭Qb<53T7 ]WTC!RߍI/OY`D::m!'?+ Fbzz&Lӹ?uNʀP PU/ i'vfJNy8k}d  θ`s`ݭDd䈓sa0fq |"8ndB#XP64D×n$p + }*X1+aF".bœ^!SHCT@ !#1b5 SDc60}X2VAʇ&:иop1}Ɛmp(Ă6Ϧ#8#1- dB|`YAR01$th+u0<=:d $s+t:D:jǀ V h|?d[5r+;qOoHx`?'5:}Ceo?9_b`,XNg@K&YG~6bL⠒F~ë|>WҁGo_4,ؙz4&x"u|bN 9̑l"dL^ ~GqiT.mcog2#uHPI`ox{:e+sZɴ;?P^vD.3F>`$H`M6#D*ո8fPF5}bS,qbDkM`i'P;dޘjsv`0jg;Pc(t lZo' ~;?lF6þѯ[_P}p3 0;`!CXMxaD= +y +tkR +=4X3:q;;datHuM /Ts$ 9m+`Ni64 $^ ,bi$pPj^9Ok)<\3hbS3j ?Oǻ.ds: PS4XÕhy,q<jnٹ<qy! T-T+WT!)53ZHՀ)v&Oe*Rst| +>e%JS81Jj.8?)> +N: zG 7" x..`a1\\Nc*T Va`&!q8-7a*x`siT* Y<@*DW|?T!IXPiEͳC :_:u3Tzh쏵܂,N,e{.RJ3ƚ6cNsi˔RQ$b|:upIPLV;*@5ݐGTVJcMmmfOwFO+#/{@ +@&SpeMLxgv2<"PAQ̄KRvV J)j9&3S~Cw[s2b23ޢbJ-ISRؒ s$`IB%HY_oɄlV]8_]:.-2.PD'TY[i:1e~ .,Gǚ \v4=F'(T ff4PvxJtG2TOvIrф'<0l +_)5'Cn/N6 Ro#-S} ok +<``:g"PHm"cMG-L]s`Pi99ڼKmె\1j™HcMtt<x*u4PՖ?R#6E5?62NFD)M9wt!e?j:rix3Ip)6ى6K7Bheu'I*>$q=;{_3! &U*R \\Ξu٩\k QAgP.{i:S+n! #d"•tLoOv//i:ފ6# !?6*K[;7¼[ʺO.NNL S{wgfEm9;mnuMffd~QʸħNk3gcӧjet0k*]2bn1V_͝66@tzơ( +.c#I$!j5B•NT!RށPL'eTt T\"p ,riBkE\d3JmV8;{ԝe5JRzp6=s,=?kn^H6w45}Rj} ˓ӥKZ{t"KJK榏-8w%.PYO͞vCi+aR0ƃ1d͝k'w/^6rl_igh#fH Vr#/#GTIU>휔Ks;]Ra#S}g<),\HwSD)Vhm]nnQ\8غ9zx^)O';G`"3gOK(5{-.t=(ZJyWF\n!X TגR~*?moI!3 T ?+Wc=ģpi)< SW73Srv)fg,uؒTpS qGk͵;lT +LJN6k'7LqMy^rkrXv]FPZ]rJmEφK =&> *]VX}ꨔ5,̟Shu% hu51(/yM!7dṳZ](-g3Vaۻ7KG +NͶN<IYr]֤da!B*nT*-]4F:"`a.XMS LQ 4909*uH݉tI;bҢ^'B-@0@f'PLWbu Ҟ{ŷa}lt4j 5^Zܺz{kS^[߸ؼ.f珝{IވT舕ŹNuN=.` ?u4Igg=.ofvW*X.ҥ/&?nabwj)2sӏFAp Zӱ6a|"7V0-+W\zJJ/b}4,/giU&/2t):}y\r{NLytiHs&O߀MMv#啋ٹ3L}hom%*kZvKṈҠ'P;> Zi*^I.ђ &tVJ{_BTQ##:vDAE#Y15Y^8Q_=46|JK/zܸ#?wV*0Z7="ě;2J59ӋDxzT +Gk+˷7OwB΍{f\3bõHuSm6J%=w屧^N:3gS3sʫwU7aSRgb5 HbL]Y#vsL{Â)P\ Hwߜ۹J+Bw3\Ey-9oI4wNܬGHAE@CCPzN&<LE+sSѺPi-X7B#ɶZ݌uN6/ϟyP*.Buk}H:;cRvJGMXOO{ĴWL+l#l[-'{Stz2lhd`f dTNts'"( ;,BpkQZ-$XI;s~7$#59(@%@|/7efoV}rf,e;;G=K[Wv/Pry'p=Tޘ@dDLZR˳lHw-.R8u8kARa5=)`zTu +&V䴜_It)ٙ B-&ĚFrn( wRIOZUgO&{ dU$PqH4LٸƥVRŔ:*Ν-̝Gi xeG|<.wO<ٺ}b:'@skxfăf< G*@N{Nt IPR8wQ1 BFd 7Br(ti7ԔZ[ fx\hL^QjxGkӳ\r.PZ4BzvxvXf$ohE;֊3/y,=}Kt]l 0%`nJ.`y)\u/%xF.rIHOnњ{BER)8nEFHm̄pY";lfG#`KǪL|j +l)ぴ! sRAD*C`a9;yxRjV,etD>[W)f`Յ~)%OՄ\qlgzsZgBNL>A*gbXaVVxcJrA.E tyT* {c6Ѫ)3t w-.<;ZmOmoa%H^|nĊS9j%ho:K&JD 9R`N0}-s Xs+qC g2ZE[>z5೓h^AbD{C +hM'6:20&m+E+dxhc|iD%6:P^[;{7-2chA'f(XVC Bs\fjLHoJ}Ba樜d;GX?{y*/R:LFEdOY}"=r^V>P` "cz!<TŠG )ՀڔKh0AD$E( ɩ(L{/[_c>[q< dSGal\03"BXp01h…ʥY,D&c2ZkziB`QNV+Lɑƅ+$! 6d@NҎ~6ar #fbTsT)>"\%Cw +!PI~x8픗vBinm'/7O9PB(?-`RFflrQ.Z[|KVt5^9q5 |.m&IWfCΎaRRF?{F,4h9Ж  6 'RKNzaҠaB8 vST4N-'djͥIrQ1Փs^.kn "jHLNAF-!@;94Ԧb#! -dzG|Ra\nT"):I5cMĊJg}}jԝ<_7BϊHVoЁ*>&fsMpL(X-nKj}6YZ9yݏ_}ٗ?{BivBp=Zki\W^뭝>wϽO_;x߾`otL`m @ +X6{Zڽp}_}䅋78w{ᵷ}ѝK,q1hC+XWm{cwsw_~|=Lm 6^6.%;4a#~ q$c.B \J%O^y`͋>q/mX>W9(!#~۠cxcO=}>~'~~o|G;SGTD+%Fgv؅篟z'{;?z?{=kz?÷g?›3id:r.7V\x=‹/w釿~_. z@(& +<֏pǞKo|o|{O_^;y<bQ̥Z;nZ`7o>y^|;?{/_뗟~ooz.0R&i*̆ƱS?O_|'GgOЭ?g/D}Yl$0#qVOWWN_}k=/xǿݏן?ϧ:yxe +bffpN<\.o>+o৿?{w~/_>??w=Lmn7]Kl丙#'d^O7fV7N]ʛ~'/>/߽3z8 Q&{+NpʕxG[ӟ>~˯rdO{$x"V4N^{~Gz__;?׿o-v1L խݝkW|᧟}A9~?>⋷~?z{O_qko>߾oo>>쳏?Wk{k(l/_~?/>?yg#O?ҽsǯ3jmL|!W`ف`sz7|7o}_'>zWqmyd8uBJ֜.7&s<Ĩ/=w^tjA n\2 79 ?!L!_o:SGvN=r=pk+ŕ`"EˡR<'߹{:˅s޸x{>䳏{.t/!7dc_],43kKO{'~g?zo+/?̣ޱZw)}\NGkpyhQTr7zW___xzog1^J081LC+nZs +JD譬l^̣? ~[??>J=d̰Q##ªViũ#gnw^~xW_/ګx=ǏO(9;&!LS\P+p!mlr^O˕k<3?Ͼ=pԣ=nck59,OWOӽ[CӠvT2;Kj[[G^Գ>/;?yիwnj-CFcs>RrԫVwRЎS.y3B}jr3z3>:K~*a!-BpD bVKf"< an&sс!D\6aE2ńd2'өlUB$F2 וB0bc}#a(ԉ +~1CKک{x-S + K [q1ˁQaw̌y!6Th) +=I\Ή;hI%JJy/Z}F/mK +Br`_1uDA EE n'Cݤ + +d\ʒRHit1 bı`E.RqBPɎc&ߘe `v&)R2,HPdƁa& av!?0{29;0QF7*xeM/ȘCvDit⪷[&rzo:lt \#&,.Eʋ~!f%J){* eV+6q>12u3|a%!5{vBEHy#2 b؜=&6D`R j2fZ6|zKhTȺؤ_. +i(-E#QoxDeLMBr +#"Lpŧs|idTF+bjJH͠Jؐ1bkuM#\EiR΀7bFx+̌/\v"esS40bPm +q ;T0LGZlR:hƝ6E넊bje9=L aRKřXsfډ,h07g#Ɲ,rI44(Rl_äl:hMyPR3 +.nfNh¤տp1!!3TLJˁnj.yLA ‘+р+˹٬Nvow7]l \,.0!oâ O vLy(=efD2іM!Z" 4y$'llې3f@6Mx¥ kpsf7d":p!dΘ]u6~u[ݹٺcN{EV#ZT\"vog#N1C"鴇S]@?1OG+x/Pvظ5}:787ǢINU/0jÈ` L΂z[ރVtkA!PA=⸕wp@}3WxApL16狷(6O {c1bţdE+Ί,7TKh+ex{iBD'[bU.=7` >59{:__H4W.g'{T~;#3Lj2L^jt`vP+uF4y%;W6X%&%ǧ nHXȭ+z촆Y2R dfF:Św\RLL +9["T fgI)G9)^q }BI^! b 7sP rD {@qFXa'qQ 4C7fgXkl#$z +ai,\rIx ^Wk"#&]~U + YS@L 5y*XA &Z^p©I  (gqK{?9gi%,P@¥7H d&Ȅޣ +]jtL4;z#C)qIҮNsqg~s |}ϓ}Œ ug`JbzA+v bE3zl2Qц`.vgܘ.{,aѪ_)M(,1V7w:.e|8? R=<.:qK[R:?@? +)ds;_Hwn"+{i~ݏ5w zw?o[K\hqۨJӚ֞'?#b=6VfIu'A,%ZnqB :Zc&.aqG͵{>VHcȥu@&6$>$4 Z! kyF)ڞqp5Cz'[,5@ `q0c v|օ;1Kth#[Vqv80-r XrZ.kB8 Pa-VGp""s>WP s@/[ )bg0ƁF\\C%1Ex&+LpPްQ׋w{0 6oFA;(ĬU[P!+#\;:VJJ'hs'@$IEIέdׅP*ͤ0RZ}@֣_֮_0A3oPǑO87m%-iB,l0[FRģ%h y]VoHI'Kv4Bgl );/WpsѝHy]Hmz3#<|mLG.m4Qr[z^:%)?<^M("q[ZM Ǚ]n߹Q{lɴ #9Ok \0S`X2d@&w :И} Tjitk< +p ; u2ލ5{W^a8;׼\2w;}WnѲ> %ۗ4>Z_nCZz]k\`V'ތ:3BF W+5@$[~FHR[^غSX% xe8 S4%pнE\TkHy04m<2\l%K@6AҌs:@0i)/%."9X Jdkv3^sjH W"6T-J!J.gG<k$DIJ5/G+jmG*!לJk >w7N_fw"O?e̓xeum:q)799;oHK0 ?bE^.C'@M!Bwcsh9M/\lnx+-xi-6]x&d΍F~?tT.#r Qlz͎̓g_V̈112e+5; +e3Q&G\ra r I'Pū~p@ȯڈ%x*gߏW6jBTBH * JNl)]  -՝scu L;?᜘.ᗭ/EЕՅ=f?o/% +*5a +Љ_"\yJ?ET$S얖N 'fonc&t/78K W삝N@Jg7&% J(5.1 ֤DMH.Wxkw~#60x/1 =Z=ygɷ+w@99?L5|BMɁM8qZ\>y>^ve'r +%xt2hIMPEggk*"UaK h{CQe~?Z\ +hԀDpCO(7 Bf|FϮvjBoڹY+fXM„;{6 VF2Fc.(]>$.*1.v HE;&;/g@_ߘN{AbxY6P-.P2Bwq"mnn T kdVP1Ā2LV}4KFLvi|t1|zS J{Np}vۯO_ ;8fTͦhK-ooBo a|fK\=l,B716ƛA> b#-8RJW˛[=9?/w_}K/YI'yp WAS1$L^R\U7*K'w^vц^`t;"~ +VljwAͺI3=< + +7dMϋ |/bҍIA"%&Zҁ3 ]2{L/̸N'l8>T`d +Q\dmVWSBv +t#)A[cޖӋ.L9սTR@|;P>/%5i%pTjP{58B.!Di.-KZ.۩(;vX[\Eż# \ g&pD` ](yZos>X8J=RNnpa2m+juAdN$.ellZSM.PZ+IO7z('@%\Hv@%/,rPˈ gc=[|o' }Gc֍'! $rځleOV/!ʈ_HWX:ٸ +kC%CR4?|_VX#J#dyV)Hg%; 1.;jghۤ<|"")ZW^{\|2[[8Rvr("͐>3=dii/p6iRS Z +!GƛBoo\j``Ǿ<^qxs^^Iu:;1y8'&%FJ /Yl(8;e=K6NӢLșG>eh<]nc|OHl +R%Zi Ũ V|.:J;0H4H'\ ++oWte;Յֽ-GFy+VȋsY;$5R zX{j 8<*f㍍konp|_y?BQf$.= ˄-t]!3Vv`קߘt_wIJe"y 7&i`Xsˠ޳cFxhEL Ǚf86J&scAJGf= 9HêL +si lЌRho^溰GW_Hޠ}k ̏voؤ9`{ y+N\RBfDŚPSV<yDL§*uDHM<4f98cC`Ƀ/8I7*-U[orKld@p [,\97d +sA45J=@6cC&4Dž/}_=7a!N8Ij4ӛsbaL.FG/)խv0_SAҪrq T> Dpn*~q1ivZܨy @BUh9 |\\Jet5XkOm$RUDKI->2XƊqnZ8c@k=36 O,؄9KίIe:R\c)7%;xzfGR~YHvxRyT(6HMhh@9bqA3dBT!L!b +N2zq1f^'t$Ѵ@'9*J' +Jo r$uDt}5:: B FQkxqFs0VFɅ:PgP +R0JgPaf'&xc(ӫՓ+z0\Щ;?o,4hT[$Ktg΅rV7J܈BI+@uMև*Ep(o?d9 t#ƶQ[_9|} JiE,bj2FVѪ1slN +zsiƋ^e s$3N @FmP719(:Я\S1V-뷶?rF\ʋxͦ  +%#^QsP05c +/DM[a/șzzɊؽl{R-竕oֶ@$v7R +~>JEBvPml ft#QOxC6ZzmdTsZ^-zX(.LqL*˹ƽhay:G?, i'fC$i(مBXH-8Qyi1&]ԡP +$5(XYܺٸJ+E})ݢLgk͝!j%^0{p&>> PizeݨQُ~jʁ.ۙu̥ss3q1;RjWd窇2nz O6T m:Uk)L~6/b¹Nno>.wݡ,-).<4<e8\QE'v|قHpwJa'3˙~,k.>۸o.]{)d6LùtJi%Xsnrfkx!tiY_;o0~uW9{Rf&ߘZݔ &Q}ZXK&xC.-z)}u/Z Sx^wD<;^ +vRu1 1Qc G+K^u0+w?h KjE$0nE6@ endstream endobj 81 0 obj <>stream + ?SVG;B6ZWo^:|\Q]>cλ؂E['5!5odFc6g!8?Gx$;jRt謏⊇MQZ#-O҃pGkZ} hK2N\ux9?(zP(U !=D򼛈aZ';{ {w.̍{oߔDJ* /#8HfI'f +ZcG$t&2Z3Q]cDwĀ.Ya舐QOtvkw:O{kOc63F{V^JS]%;tr-wẃzҎ!'3Zu%Z]̴W-?r΃dwӚ^6u"o|6 +kե۱:*&BMHƺBf=VfgA.BK %r)$[([^767cu-OexQ'CW+f,M$!:^ R^,+;?:oBz΀KԮ56^{w< x3ܹ`zBku3=8Rfst>xFjM#;8VM8Ks8їR D6yVKƞ +YDbJC)Bnʍ;g5*VqO8u}۸Bb;řकf=ԟ3_4fù8AG5$?޼yeAK{?=}7Xn,ߖh὏ZAjΞ^Pvʎr]0c BLMjURv|^Z>OOoV]7eePN\'d"]#n˹pc|:.A Z3"@0)%Fś͍{@j::huxGK'D|TB2x˪D0ECteQNݘ,.<55?J77C pxW}e'r0o7=)lSN܏'_:;Nj*>%ZJnF{ɛ޹z ]X$֓ڼ\q~-1f%, WtFra%[ɣm9Qz|*~ll=|X`5 ܹIAU: +(s977eAoBTrh@RMvUV)W7o>w{RaN^ht/y3.͔W׎ތ~ΎR%$ȹᲖlGr 4jFg7=~ؼ-dZ;w*7]'VH=9%Gu)VښYB"1>副V%dXxp7. \ Ӡyl҅a!PDŽY g{}hyg:sbNLf.XpLw}x"WbhEMA`(EQocBƎHĬvi˞sY' R0:oLΛ.,nd!-ƣXufyts hIM2F㵭Dd=,bP:aEg8a6iq&| ;:UJYurIqxz[۷?\F%%jro|!fji~w~1(Dk+Z8䃫sz8̥{RͭA p~z~_|{ܿ'H)51b4ڛO~18xSL$__X!KC`QJ BIZkO6nOFsQR-BkoTW>ȟOg +3V'jq茇ŤBK)e RsQ~J,4-;be:V R)k ~>H5ր0ұWP$28^w1A9>;Jxh1MKiK +zʧDTj taꅙ c( /3( ;}&8VtШ/#e™Nez/ H%zRvpzW2C'0 TXp!Q,`ōJVw;?!‡ǨHOiDT{""մiv6nkdu>^rfu>"Bʨdۡx>8%9YKVGrkCdsK..͕:_wE^9:|>woo~8W{>ll=im?{^l] Xu7\S.CFWkFH.I?}r{8ʍ]{1$RGvet{'>&~Bog'XmG &H:@tAo6퇠P3]*^BI2Z %ZaNˀ')DGa1+:Yey83p8OaQ<`R#X~v';)VpKL} g҈@X$@i?.CI% 6ag\ ns3s6 |z..y>c VE5KBQB)kzsOkz#j8Q!g'l!]`/ d&6/} ]2Avda/ lrnPHJ>z;|v@ie0&*%>+x+Z&"R2!⸔mV]os3N ghiUT%U1rJJVW|&Z}9[ko0<}IQ#$/L':Ȫ _3CVx;HaeFq)g{G/ypw|Q*ZsܬGor[=zn '4^\E;_~~Y8vИp/v}/R^/6|L{rt7X{ e}?Q]?78u>:Kduy?$NOFk\fY*l,~;|矨v t4\S6b{ݷ֯]3S~gc*=JFP zCŌ)BVU2,PoW{G)J$?rǬ⌛99 267L"6:Q>>s#~y?j۽gjuc T,m?\.u4\RMrz':H"REZSJr -8@A.NY.Q\[<|ݼIw|O c,Lr'LY E#T p`u49aPBB&& V<ݪu7 + 42Y[GP,RRXJR-aIQR.11nDpXFLyZZr6T|۹!-[lo>0Jp(//GKRh% eZ0땘`$"hq 1%ȉ|m6>6wNvt;7=^Yʏ +i7v((ƧaY<"瀛FvX:7r sZ}Wlco}jv秼s_o +CZ@4!)* &,$Y)1\=6WH؃GX! 1ټ%`N CL֝Y;xBF]). WtQCK;}lLT2XP6-(e>/7ֺkdh>Fsao3% s)+6c'}d B`bȆHIt2.kj~KV zp6$gJ!6 +HJ*M.@m".TdRF\8=PKr"6{ +01J`'"O9 +8l-.:Z p?dTF P.j%2Ԃ/ ;D2R(t=0 +~ +9vu[wqӽAAg O!HMRRFRI7X].-%B4+leTmDp9g|ta#XHz|?Y,/hm?qL̇ \j^δt4ʨ΀IjvLBBpPV\-@#Yݼ{UJw6Y'D`O*"xQ f4T2)h$vwo~VT%Kqg0.Xr[H16AZNWhqY΍䐌*HOBKmPZ4c=0'i)qfq~c`6?v1Ţ"\@u]X @!\6]^OXH|L8Џ^Xb +`\AiPQ:NLF~ApxA2 KxpyCНc?wn9c}lB8^ +vE>\~Aq5@N&g]sv!9ߔ%FDLITdGr<_\\N. A Ҍ=xfI \sM}Ԥ5p !>2By z/?);y^# /;)o잞sC1R$%xUI %e ҅.)!*6e;ȳ+Ɉō!!AKB6Ęp8l"(ȳi ǻvan n2A5^SѨC')qH+(.5aI 7!Ds8++QcݰQ6yH{Q**dH%eL8"7wVT3Sn?VyVr ܤo2mhQIAeñX,3"Afܪ$Pd>P=>"jr`1Ʉ%%@X|;@<`/[|` L0 Z1"D(;P4+ aAYI+EF#f$F4;aT;XL Bg+2+ b|S0aӭD@V &(!|RݓAvς|}vy du`>ч^Ϙǯr>,2˔Xk읙 .OΜ79k&\%DIAI{<Z3ًY3dwҜ?ev`JPI48ae#Y^qXV7HQ;45 ;f; , p$Crk6&\M0! +sծmrN U*MNHlYX_W29:D\2 +-)DU0*„ .C$nSZ>1_Ko7G/^>^bQC0b3s??3s~asQ@Cl6OQF9Ű/s<a 'gD%W48s~E,45o&|g.{.L{MٝA 4i)IIBj 0>/vIRH9+ bTOrJٹs٫Tr1% +2;4zEy] ]JU#DU 5uTR{Ϟ?ޕ|%7ivNA IĈ@+_L\̨r`gmdystg壃^|ѝ{aHA? yQ@I h2A8![ho־xۯ?ݯӫۋzY$@h5(6h4W՗A+Խ}}^=;yqZ:3^/45rzYzq2 .YfL.\)Mn +QYXO +9=4la]u^|QA?~kӧu}kmL&Q]N'{R_߭mWa[^=\?onw:v?N Z0@ #Q76ow7_=ܸNAX X)=RɊK-mo!1( e;~fuW?^^=g9 ̃L3&=6K " QܭBdi]0}΋_|/pqzuW}nG$'Ã@~q_͗?z?_}~W?{C~|`z +~rOn}xown˯^k7>yzxX^, 5Nt$ظl$p{#ݥ7ϯ~٭?/?_~'~| Mڃ&Kr!泉; ӵFyw^?^I=>o[G{ =A *SB i鯿?9wQ)I!VTCahb?W7 ?~ʯnO7ac\~?ʣ,rGF;|g?o'w_6JV<RNRVizL?Oݛg_:i://~_??޷ow}-d(%91Ƚ`fE'߸{?x~_n18B͊fU #o|QŶ;7ݭ_g7ÝُٟuvU^@D,p\ + +53g{ۅ_{9x7?~}?:/oVЃVincc S;Mݟ|~'q?WɫG׿~ڬh<t](Oe9;&^j?jl۟?ɧ|_Gŭ}t;-kf#E9Fr^DoNx:y_ǯ[Ogw ppY^K8âq]xw#o~/}ً'ݝQtѬ1.pN Zz7 emxRYYyRF%kVT޾59|R]UXǹ@_ 2Kkز2Sΐd*gB^(4nA=-bUL đfs =9WBB FdyRln϶G;-Gkf[Qgl`z(C<(]pV.7&{{~uT^sbe?xZ{c%1 asRNx5$f %({z|tquI' 98l%!U>*Ϗ?/Iњev{5Q*kJr5HG /Z\V-GH:ƓZ@QDJИ{(!d2 I Gl/P-` Ƣd`mg ڍn*\2B)}3_^%)'#7W\_Da0PBd%KY4fT5|-D$?~Jaޘ_^PA{n0IS:zy#P*Ihcrj{_Cx(#-B&G˫aD3F'#n2_NדfJIsi촲 L2n/PfQ9?`"k5\1LXQ2)drDIR.Ug`(T!EW3@~+qF͵FJN uޝQy-JEs|u:MȒYlL0ΌǓIsq [kYm}N P5FzynVvVT0)aB57ѹjD 5{pd|Ii5aR#߻-3J򥕘D~BoC{ZQkqGs\Vs~oӕ񖟼C⡡_zkcٻnŝ`Zd_LRlɇ67N7IKf+p|V(mjJqm3ьY|a!ʛ>~h5R+xؾLnnO-L;ĕVӤ\ƹmU'JW>GG?}MWO{g[lB,Bi l^i8{LgNYwD}Dm@}R) Ov}N۽!"@9zFn4{W CE\q%QFZfGz)(]~:aO`:6(WcFg~_.LaW|Rz3Ftn0; bQTݞPF'JX z737lfBa1m VmՈzBDe.ѹb!vBT9$1_8 g8YM@Yq/:<0"Z_܋ f4c7bZLw{o,z5 %ݒی&텙\Cq0AHEj՝y(Bwh5+[whho/˨pҏK-.Ӫ2 ayB8$_o?9U@_طC67ݖ]AM^GRNjizaZiBG7n^It/l콓zwrC> nPˬMo~=~r~s*ؗ: 68sIq}w/-T|tKQޗRq-ұ<{qdݞѾ)OAyEŬ>.6ے;JnZakxT +3g-쑅]Dl{K/m8_ XZ.%{a/q ݝe n?~ը۴Uub[NzBY JP?V;%0jńqu9ZA8Sv掟|u9y͇H+L:rq0SʇV//f߲|1%ՌPA25IgvKg3fèPTPq^CO;LNSz퍌 Ryj5ތ#xcym~Vv@Ǹa T?'bi \ >+*OZK<_ʯ2Lvv_ˏn%oZCZwF=)o>||#ڛ0:J؃\cSqFZۻD7ʨO\*"|5~*mJacjpܺ5B,)?<}g?z/>{1$yO38b\U(ggwY>jwAs`S`x !r +npXoʕHw>"wo3 QE} INX!|2G,oTpk{ q)@0js:7g~Z^vio)N߿q=gL]߀߁%.6 +\=ȍ/pV`vQi t'fk/&xre>{ۿ>|iTw:{ 1?qgNnq|w|oڝ] uͤTʘ#vBe?A-FojRݛÛ'_waOB+ {'lս9iDވq;d~B yj6bBD Hw=Y@Ʊ<2w)Cnt!Wv|Zܩ={ry VpGĔ>ݧꜾ.Ξ*9ꓻa'Qݫᄄ=->q勗ѓ_txn?g1 ^q)@OFk{=hwΥډҺY~~{ŧ2nW랲VAir'Y;bPk@8CLmz{{sH. +AK +EPɻ vݶ7FH BF-o؛><;`@_~qدpX`sV<̶O 6VG'/''/:_ҫ϶ e,_ o}g3>{iӻM#wV*i|u|f8{.u>;zum*7^s xB~@ڠ9c}nPv<8*Boj@wy=8Y3цDy'|iKkSy1[jѺႪG:z + +kٻl+PEi-o<$?yӇ"hZ [m >~*f1jӏ}~1Փ}XmN=-3wtlVݷj5A}{}7գa-n&8 gi@̍x~<8ze6oJPUƔW==s<4BQ"k!cF_ZS:4m\obuvk|mptƱUfB@Xn째z\*6Rf+;3&;̵=h" jĕ 0h*3BA<2yBn|Z̳v۟Ѩlcz!bq3pZԌ\ԫӤ`ZAer{ &`$mQЇ]7GكML dZAnu~2D ޛV_PF`vC  y=(9*Wt$ޫԷtN,11"CZiɍL.ʖ-gmsW(}D@`[@3Dm_i=+n{H~'P;7bZA`rzVn+n LońBBmeXإ-D&U?Dz\l["f~p:8y`]RپVx{ɍ$<+fTIDDӹ /׍G_΍..]A^~O7I$!%QSZp qn4!Bqg!zRVts_]1%̶9Az+$BFR*fD)H%~{tsx$ ++Q,n^+֏٨KRdU՘?D?JKÇn"a)SH A|mw'[A:r@UkL[Ǡ7kGѻVNoe=7nArr C˙:|w~Z([LaLkqȹ#; xL伙սƳQv՟UR2fӻIH5#`RscBq;L_L8RqoW>:.,fiÆն.r;b~fCCM.YLw $FY7%z)c0Hk1b cPJ*N{@0et|i3fm[* l4}\wK*V\4Rlޏr; Rۯ!)_^GDWo}}-\r) ׻kq!hd< #DҨmL3BIƺc'A#s07ME"Ν)Vk+|X(%V}G )yYjFcq~xk#CZ7$:%/eV#"Iy@O#llVW70K,zRTPPR3j%%*dtR#ȖHBeq`LGtד"{Qw+LO R&6iJFX'ʻ>=~ѻ\e?1 ݛ1R +]jyw{jeZY#[PH!ߟޯBʅRP-P*PT+x۰ \ׂ$I!6*q-tO%wxy=vi-g!Gr\nD +8Va)gw @]>T|{V}+e)Uo}ի!ƇqAdNvi]i&WCm'_Zc$V8۞ͷ„@y(fkQӋ].(oY,cVw^7O6M.fTWB$J[Z5B5TZW@@ޅ[|!:}zH}\kaƩFF\ZW6(]v/񋧽jI݈ +ZxވP^/vA+= :"(4B `sKjWZNEmJf:kayaen 6{kaatk|jz:BvqzyB\s`f;CԊ(Hantp 7 ]L,/5I۬='C){9j  .A@bLa3F,ԶQ~q0{X~ntED8$԰;1[>k+Ib8ur]36ɖwӯEKk(/MôZ;AhOWRS{ƎxonkCޛ_ķVSWZ/m 7wT_Dbi::WSLJ_ZH#dr^Lȣ7&8[-+0 +) +g%LZ/hKQ2|i(Q6Տ~ +c]WutOcx(HK2\>X f -]fWme_&&*Jo)}2K 9$1Vre~qˈP])ZͲqvʶ ATgwja1c|{4'iV4yxWyo#!GQUɏXoP{=![nZ>`HXy-.GMD'Q~PgFatvô ʬ7.&ęoUg +bDvy!bA |aQ;wNX84j|n`mC `v6!>\(S1Vw#.FI7-7Ѿ r4kՍZGGAT +µMѪfi"8 a5LrZE{Csۢ.7b8ׂZqq+Xw,ױPZn1P0B@R]K~mw%›+(a= +UM3yB'Xr1|b~N<)3i=@t>ϐR"at >T >fZKi@UGп5+.NFGESK7{{ +4$IseFK!H QwCzgJ4cU608Y0S`2Rn9p4aEĪTم^N %B){GT +eޡPr0Q'aw>\\>"6dRk00>~WoEp'/U6RFR)Q[dToP_@:Ap" (B8GS";L +յ㘑%&0@I'0*dُgx]\pM!=E ;6i&@p^p ʣ.&9M_~܀rpMV fp%¡ ո8wOeoO]Q }=XzvLn5QN<{X{D` y}>YDL* ͕py_ ++NJ'^cF+ w[CrqW.qdq7Bs#fKrBiƙhT{d^ + a,W6&*Y\jTxs%uy 9(2JXrqބf+og SI|@3\#rz<__Y +Fr-0=aEEfo,T])ۭViruO%2n~P~'$,lq'Ry2z(gdmj%\u%b9뭻OY2@%pҌe{ +LZ7Ff+#4 Ynl/Ԃc€ZmC;BQU#fJxHzJK{)bWbЋQ:[Oz{5FI:Ga45Ž+d{Aꪟ/ TnD s9DR4(1 +$0#mRo ))z +R^YGHjS%&3XHTtkVmj0&.mk!"^i)#ۊSkko9gɗyc[K[hvK>v'VWބKKf9#_\|k9j/] RRK,E2tqB;f\LU[fuzi!oP@0iCD!|eI@Y=C3h\]ICPIQzu'/嘐 +Jq:Fe=D~Zk8(XY19v\x1GO]E e(kr+I5)7zې.Ax|19WjG+I t=!pG\/Ѻ`M~L۽$8Uey-q[i=.P}͘d\R.3٪ 89B XQ:cQ#tRf t39(bℕ LxηㇴRX kq 1cNc}1j#JހPq!kQ0 +J)8Ǎak\+F<0WS+A,,Rkǔ3Ur5̖kBv܄ ݄&z ) *˚17ۜӧeV¤X>/¢B4[O ^Ffv'qdK;ͣR(]2 1eŌ^m)T se"US + ˛EfVb8c)"U.WV6 +&cLe58["A* ps[__ *Q\OrJR3HXt\ok;ZeJ^T!rK)g({A:V6== O+KFBs9ȃ!ʍ U`xޒIv)_@ 3P,l$@#/ۥ@Qx`#- LVRk{5 '<'+K" F\l>I| JPfYkqٗI+K> +Yq6"?tG璟1 |_MXN_|ėB +x ]j04.UJ" .L\P8FeGD$" +fc{j6HMo$mJA +@,dBy$9Sχh1&g[b&W\ΐ @)& |"(kBe'YLFR +}T7E]DbZjRl)Hiv1 +ȄäX^ !fqZ9I(8W\_ <Kkq:4|4K!a5$Is (!3)7!0fL%IeI#qiѠ= "mb(Ղ]^dz3Dk3*ԗKW6!.V` ! iZ^$i0_\l&—jkדa + r?E*m2 d9D-Y2TD חCfGic@af6p $7bFi*9etև1:X`^f\9IK TjBzc-}O +# Ҁh(XQm)Hx0$A}H(TJ\njQ.dt-DBFz -1b6N4X _LB*TOE268F6_<s3 bzRЮ\ {) +I|/qj̈́}ne8%@b2iM!yֵ0N"4t c ws g_tw.")TQvqMi=:Ji@K`}thDpvաa@̓:j+l_Z&3f 7b"\IHALRxx㗿mTO\Aqɟ63`S|%۸tqû1y9m(Qw٣O~ /)4aFq|ZG6F"Q ~|qNWaR8 ݦ\Ҁ(s%|q?n%VϘy afhZa>)6R&!8ŵv a +RBa3I/6b?%NKʹfQ6Gy_݌q ڥ\=抻YY,1%%#l8r ;DՌVkbq7)6 fd7[RiٽPr=LʤR݈2+ 8.(ٸ!xL6! b\EkeQuCXC@'J)fRf(UŭSE?j|jzٗcbpROPzLd$) յ[Q(UӚӏgvWW%ZIS* M9k |\:5"8`3r߹wn@1`Kfl`fF GU0S" )P'as/~_"^!r/17N9=wNz/&E@SN mD@ 3v@1Bm-{-kGW+qˆ{om"WHqb̘ +R,ͻG+Ari-_Xi'*w kiMTYޠݱ;cnVec0q=^1 gwjbL.c~gWCDdqmaV4pτX򐣃d2Zi9oFf{ZAZ qW|z'į] Ԛa05^ `o#@&AI 5\!RZ[Υudm2giX1:TvM_J@U\nOtW}p-0M֫Af)Ÿn2Fw@)ٵ0 rP@+ jzJR>k'ok1B{|)nQ0P!YKH_8"୴}`С e'r*3 [}{;{c%̈QN + +`Ž'xvT Pzǩ\ +alQ>ߏ2@4U?UcKҁK+A8қ7le5! >6 crʒF>{;z3Z똶HVzZ p%x$U5/mVd8c,]h۴: u=R@/o)u"`; bR9~ O]^x0.Z /& g}e'DȨuc3.3K Sr0ׂX1 r)=AiqbLDlP?{g +ZHޠ^D|k񍄪w{^TKZ\:C1X30|[ 28H%SZKkWlJdՓs0?@+Ǵ PĕFBm +kz `Zn:n`_`p)VImr.QF/-|x6@0k.Ν92EH)#[LoTBy!H4$#D[dB8~kLzs[.&Q<8"쭤Љ13$Aܺ`_| 1IgI FeĄjDm0]И`M 7WS_Ij1 7zZnej$OqۓWA!ޮ8]\] +dR| e^b !eť7WR +$`IZ"{I.fis䌞w_icBiA+QF0 y\RQxJRJ^Zm~v97%40K|5-Ujt~ M7&A^/ m/qY3v2z9p\5H޲7;O;e8&)p/%X֛e ~lqz0@4@7@g[\ZiC|0SE"pfsyX;M4sqMuœ,Vt'l\g_wa$ɹ[?ERnpcq$k5nf:+J~,䦴 +)s=0ppΘq@h C_RZ,g%1N!خ&xh[qh&( CE&TJz5*rßV}iЇ6HU\\?Y1< ZPBL%qԈAvMJ.DɬhK5Ժ7PˇZ_ȉj|AA gi ~r_ &aƤ\;+|t&*4H +n_nol`'L%&)F`9TA?BVZ |Y./\O)ޙǍrGYб";fVJ&JDXkQ!Y\>q.[(w@cK$ID pŭ_!ԶU!63Ui+)L^#ۈsފqMLgL6?i>l=>ƹ vo:4&}{K,LbFT6'tkBnYhA"xuD$n@Ll1Fz!6  DeܔII=B|z|9L#bZDeuClқK\C\E> |%/cϠSl  +F +oj,+bҀpNl$B\T,`\_Z}k%VZ(GfB$@!]K3snZk{"EUU]U]r{w;]4HbI1ݽe^{{?af66(3,ޯukXS~ b1T !aoqhdNO˸Pv/&?hP:̐/S> A<[gpq6K +Q64}wޟ@࠯2ݘPĤ(+/Uzn^Ѓ)]j*LZ=~@ڃՄ9\j NYL2eP-M]5g\dk׶Yw&*rj@GOhf}|v!9 +is]ǔjFunzw6ӵX0ә>tMLLYqہ1;1ƽN  (ĕ0 x |- M :, VV 3ݏ Řܤx4&S}dɴk6G_l?uw˴\XhR^]ڝVߌ+\fT]AW? AVWo yHg:!"" H ۿ7\~]-V|9!1}@Tk7#'Вs;la-|@avRf+,A mu]"懲LJXե\uFk%cGn2O+ZBa Q ҙb~>L4l, jY%p:h0+ Q5^Eu"PN=`˴ ;VrsG'o><'ո 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍Od&dI/g>|_L>}'m1>Y .di:Y kb؃'4'|_8EJ8"kE a(ڮ"*HQFb(J?~ю"s   ^D|PG?}֋m}Rd'Z(֨CT1bg?)d?$ 0?IjӳxZ2Ff/BEu0]C{;wR0K8a|{/q^42EJF'eINMJZRƀG„sSV'!#i7x;i`rɴkUK30e1epsft֗|q&FhRfݾX\p%^\.Rrn˼;SK;Fؠ l!Lf0A=՝XCof&wdŒtiJ 1GmzM)_GFχӮ^sWzDf:\aP%vJǹ0`,w)Bh5*gaR=dL.RZ&ujN^=Bvn ?nFӮ La`H! f$Yd[gNW#\tbL.beHk뽔 a/|ֻp8OIa*d,L6J"܋p#FR'eb &{# "-x{Υ&&Tl12aKg7b\vRRz̈ksj/X./0D!>"I4T6[R[rvsZqN( RV/2QrEvGeu'.psDXc\k{yK0bQ,nY3a{AR($_:gz01t0ځ5QĹ?el$"tۘh$4VsU?M*cy<3!mtG_7w^Ǥrvq=!2"3Jedn4FBƄn¶ {`ZwJy&MTDuTv !ƗTP #3Irh TLC +LSJ + +v4D&LicgI +e\a1V; ƉPAVתiw Ƥt/{ZPa@\c&-j{e.,x&uD x;]c<&V!R`PImT\_y[as/e'Ս N"|p&Z aa?!DŽD:k7Z3FͤMi*He8p"$6jAi~Hu{GLŽ.CrR|a Ci?=?KFhXYFRcBD[iwWJypo3.Ǹ|%b>ᳳ{qqJ|%[ Uz r0IB˓g X:GMo4zKͭAB*$ ֐X.vz!&bBY(uS{XΡRPatRjѮU4ۿ .Vq$(s 5CQҖsXe@InȥL6{_7%m_e`P\FQrSm8P6\u)bJmĬzbn $4oO~^=[{AM; *T2 @4]o"Jqm[<h#5qb3)n&jl zN{ۺZQf)ƅaj#P9BZTA hFms0bz\c&@fBL*1x z_ Q%@30P6+Vô s&6x (3x{JRj+J(0Lȁ +,y/HFWC@RIo%<{LmDZIb|)vW`J< +3P8܏ +k %H9m*&#g-ʁkMHu13ris">*uLjMP~#Bpj0+-5X zSF ZThq.SaJvPs2Ǡ}KL)U0ˠuH|M.cR%IDm Z O*IY9V r_ hm p:oWTR"mJŏ~`zF+|*(Bl`0Aٝ+.;ÄV2&$<{[qzuG)-w`pZTfjt>׽rRԚQ4*^;6'5DaT@h~^uZَf{똰AJeG`vR,",eJ;j,DE+X1P.޳6tu׬̈́Y۠F0CPpsOYHVu"zN"4I6a-"Z&r2.E\ɣ||`rJ.RhMD%u(_~DS0[ݝ3FI|&cA%DTBn=, +D0FEdP%_, e+FIXg#'Ӗ@yEbƩ97R6{DzB\f{W xdg<*Qa)@0o6pQjy!;FO5)1.?mHkdJ[G֗j(d*"|d0 p̥LρIIZ>KO7ccRRfxQydNJ3+]zP#AeAy|! qb4%(>hpMrt!xX1P7 t`fJތ)ٌs4ǧx6WqH>{Aj3rUp`;zQ@anOjDP!oB,m':|2ę l b x]BgIUD(&\w 8g `dH..0[*V>[\6<$^krU^D9JB_GRH!q=BsAvRJ eӀBZ׌-T)#JJѻ.1uK>T] +ϔVԒ,pM"(3Az|gF``lB-SQ\|[=tC7tm &2gB(3#4TBrPO)wCYVՃ`|*N=p@ mlѱj; 7//.O&Z y~b#&@Dac&" (&c?GCۄ׬00`@>ֶВwj W"N-$E^N"l3NPgsq/DPT#M +%{ZÕe0ȮZO vHsSr6g.?K3:X<{I \όc&ڡyBnC *! [0ep.@_J&> +ayV֑Uͥ/)t ~/m&EHkD'LJPiQ߬كk!b-LEhXt+g n4IJ }r@j|*X vt0FFp=JxO0al>S^QX ;3YP!:IU&Hl$D ocUQv3GILx lcz5d]%h[W#q29P%w/_ O'0F\\άBDz.rJIʇIzpǶ(p;I( 5015j3˄R0ȏ eK ctBIuh3#qTrm5)6ʙڹGhHuT>BC\PFFL4@Jan+A;V(cDDG"b0 zLrU5caC*7cޕbp[%BNADMg&H5"l@Wh$d&4K)aWC鍄sIhIWRJ{Q\ vQ&Ku)I#č`\ :\%.FH{+  ے/.D1r5gww|`deɯxtO7!1C),Y ݇. *'Є*$#7]?yOnD_n` B)ӏjq;W!` +K%jR-i@d`iI`ԆM9;13'v1_C]*!)"#!3rөA J]ߏPO71-%U0@kuѝERz4$mbQ(jAiFFmxg@PSy,]r?ڈ0~Jr-ϻ Jl3՘Fz-%7"Tt3~gB ,).Ff"Ohd($eGYӅո,PT\qx-Bm'{jRëWwI82C<"*H\F눙1 t1QDZ]*J[})7cs[qAR_O +I$V-5te8z}#MT<TPSLj=P0A.ZJylۧ_o=aը'n|]JqXJ&&Vu6ઐ_D BW H0OPP9q0]p+Qއi0gIk=optxX3_BzNw3LrV+odD&GɕP +mN*IfG@j5DF8( D=%K MJn\B3Zx?=Q"|bt&tɟD l jBD (`5nD`-pw/QpVz͡lh%&& :L@ZY 21hpH>Mg:w/Vb8 f +`8ebb O.e?2a:I9Lftp RV;טDmdx{! q7p/@*5hU !ܗTA!BY5K qs\"#yI@ uact2j3)cR-FB ` c;kq1f@dM<kY>]C~܈pQ :2aLMks׏lDRZQB(.ӕ/Ó$R耑 $UFsF#;{>~[>連l +'+(eq.g +Q0LIpc"iT=3>;% ~6Nє| ٗUS}XBX]qLVxjDGvڃ,ޠa:ɸ4S@(B=I@13z ҂uZSRó$ +b3&nD_R3kf>qe9Bxj#al"fWZ] ¬/._\kbArǽ餻z4cHRE n$AŁZ2nr~(ӋQq#*A; xOWBk! +߻΢\  Ի;A/`*)b,[ˠIۻQf'  !18#ġgPq3HF4ҙ(y?z/zSr{bn;#LmSzҚG,ECiH)̅Kli+eP Qy\ivd{Lm ^L^ɠ)8\FA+M"J'n ˄6"51 8Tx0oe2y9 B.Ar jL1YĻ-`JVAT;KYk"{ f +Clj]̎00m=Fl.GrRn5 n>*]VkF0i3,h z8Fq⋤ӕZA=RJ7L0ˁ "܊Rw*LC ~?Jz.} *?aJOVPaoj„ +e,Bt 8WSqrqwCej{f4ӻDN\&J46) :7|#Lqat@rY c4P)-hkXBi~Yip% ϋ z <)ՠ8D@>FtT{vAlA>^P[MPܮC&Xr&w6 `cRFulML낻ǽ{ptJZ)Q3@CPhv.\m&aT>7c\J,'2ƸJA w!{5AiB *4\82˻$6NU#Rdlʲ%"1zCnC| !GN%>o +zS;Q/UꎟZĻ{6Gj-kv.Nb bFR 1yp3r7v %Qݳs{vǘ\AYǬP@iXOhT !76Zlv5r {Twk ž;r"bB :3c ;Bi7.[TcsA9\ jv$!R)1 +/sCGJuj{YHM@*nH !"U&etᘴÕ:uɄI֛I C FWl+-Єަ3T3ɕu0@ 4] ŹR&3=୤rB( Rr(tfHiͤPc(a%i7A Kh-|Ji"b-HCoAZk-0q\[dͮVg:{z}TZm}-QրLpKiRf|tXsxԫIxC>-Z߳ڇ|q"ݒJ2?$B~Ba)5(>;@Ws?/@%T؇ǙbtfL*$VۖʋR)iGe|iGmS@KQ{: yꛭ3@=lr9<``1ii#| Vu,Ip)"mOѥ8_heRkY? +3Am$|q4TنDeαIe:k)3ƕ~*UvkB(+^s;|I ᜈev ޅJgAyvi'RJixg&e9?Ƥ?e/\n8TޯuτXJMͯ+k@wCazrY)֓ +ˆ; ^꥝Qn̮s+ AgZ#(gZY}GQ`3@wZG=]5o-4Kkӫ\ɥAk^e$8JʴӮ'aap9>j|enpv^[fGWfqyNar@Xo9e'Zu[.O ju"PζƧ_ʵmc펼>`c\ȅ)P +jybN0}鞤܀NيQ6A_Ź{2R}+Inrź=蠔Ѣݾ\]T,T( A[zL\@Amb/J[Byfa· +Sh@(mqT]j%K\CT->?ݗŵo,fZ;QXVIavG bTQCBX=,L>̟>.>Vĸ\=RGZ }=FR$\S}dۇϡ^gYQ!~>S9iQf "7n~w׻O:Ju8*rtV̴ [FcGo׷_^ٽgl"s}赅++{Dj]ARTUޗU޹;V'>[V<-AyE8ӪDri nu[;oC[LP9djri]TUڻ'_2.A,-on} +Q[lˍqqnri+[*ЀZ0?yn +S\Z%fA <ohY?:|=8ڰ|R-J+.ߴTq.fVx68oG )ePuq4>x5ϸͅv)sڵ/?ڞZ;^8{Fۓ;Wa6KYX*n8?y\z>\jѹ,.؃G?'20e˞:on~;}q7[U^L.~O|W?Keδr9=|tW;W__.PyuNzg/_;ll{Ju*bywN#g|Y}uOV{ڝ񃟕gH.Xʥ)0&?jk￵ T+L4T\5OjwRa ;|;==xyU?S*/?E"(Dkm}yqdz^oi9=޹/ۇ()f$+~~r'gjuX +8:m<-O/ʔʹ {_<{(gEmѹ9l?. |lK[H?l^?&郯O}n?ϏΥ6ֳUcmV'̯ f-:`"2_ ξ+_/ Gn1l_%x7L@49TYAo8<ÔaV嗿ٿ3]i%G=z<{>-/ lعJ,V4}O'O9+jNDoͽPJ;]?cmzy|[(꺲s}g,QVkj]G^Ԛϟ@k{xyL/??!)?̠|aAk}?ڵ)?)-䷞W?B `|Jp鞴v^|S?IogWdz7WF)\W?z} >}]yi}5MBת{Nl&頋{K]|/WaZeyހmln]7wϿn}֖OjWlWz\{]F7/?-;kI{>38W+3:>U ldkZvk:2j˝7¨|vӿ rQiuq"=K/k8>x8}ax_i xr8LQ&  HdtŇ?ngxT h,>x)QoQu~] +-sZz^?Jw)+ځe{ S6×<?iKV}Q?*/_vl=g'B?6v_6ݽ|hSV(Zc2 +n{Q<<oU*w v[%][v4_}`w|[=mKlf=pt7Vp%Ƒj]*L@簠sav84v{<=u^m67}>J;qaz +Vjpç9xcs4}49 GOL&;Sl%;v|o,/>TT~iMjjl ̨YSr}4BPҹ8'5鸝=w`t)ip+XM>7({G_N74Lq\WDo[{o;'?W*e꼹xfhg kĂ7j݃q)JlJP+|iƔP.6"[?&A_I䖧*^]VϾ]>`s21Jo]r6{ioui t~{4=:">wU۳B~ +VA!BaftFG~&g1ܹ7Nu%ZpxaydکSDt0 +] +,RJ(]} f\D.yw=bJeϏ?SRլ>T(Obn禧qō +a4Pj6M@BVoPCFWi4l5JgSm:{Ͼ~%iZMOοn=3Jm4K,L[/aE&gN^b3޿z<.KJuGyqt Hp駔BҤl<Fǟ:}ߕGǏ|!'`&TK\W0s@OfsOv+Np }[K!3BT @YKls7)1]tN@UZB˴`hl/|~C},gxZOIy`@3UwhVuCٽD)NYfz3HΣgJ4Ki,!Ø8vO_,!np?LU&O?yp^FLJX@Z]4rjG_Ugqb1K+҃I[lff rYJ8K$56[v6+zyX[\iU0PU4Fm*? :|$;EDW-ǯks>CgyrLZ#ME\%E/tZ{@>~zwnmzQVW.vOew ,Va ++Taet´fU l' *Ew 9|!"Hӱrq + +ji.5X#{pʺ]0M)̺;/L3A ЬerW`01&"َk`1v/: @ehɇ7ãcΝ$*T$ֹO|9)V>H4 $H${/2gьFiԋeɲe5.q48qbNܓ8SONsZwݻ׬!} ~VYfA0 %:"$p 5}9-ĀPBn\*4ظtsk[Wv" 0_w(yH gg1.z3 +S9%jvz-ܘ +{|k^qiJLy-XaccRv:@RhOh9C6OK.:I_.yʓj uʘAذ\0~gZ(I.ɒC\~XT6;$f>Ɔin`)j]M0/yXT~G_zg|vbf}/V&ItLzl0v3S+GvϜvC79r3? w|Wg^ﮟ)3)havr0U`P-vv˛Zse{nGՇ|?_|[SMl.dHJu%7Ve:KXȵ٭'~'{'o=qz-kX\B0{ $!QrDm7珯^s7{OO~y}͹ MwjA=1—6 ^(YL`#'N_}{|gn>tyxۗ|W]zOr!L W}IW$|L6ͳٵ玞v_>'^&AF}i94z`)_&d"R>=t{/??_~ڏ~/lOl +ORtSw/sOß_=ڏ~7{|›?{K?~oXNeSpd>s؋?Ͼ_|o?쫯?~敭s7#I3i!֍TV-NɊxbP\>}7?7m^r +yo ͹ţ+{o޾yx~gx/׿o?ϾpqFauqP9Vl|kv}_?ݛ?埼|OW:{O(7AQq,Icg==[?o?>|_Oק?_}/tעFnhQ F0a[ ޥ[|7Ͼ?|{Wn:+Po.=}̅ ]o?_|W_ڻxijiM7|ɖ2:x%n/eswߺv}{/_Ow?xᵷN\m-1V:rJS+sk.\~'?{Ͽo>w?㋯z翸|V{iSHi1Cno(]gV8~W[>;~~'/?/O?yt_9o$;򄫁4&RBmiu[=[_~_կ?腗_~Wv.2ArK%_OTk݅= /?7{O?z5WL4*#83%"]KZK[=/k?|Ï߿G˗|go=lE54a`ܛ߸zï~/g_>Sgw7/baPa"ƈ:ܚ={/֋{O~g/,mbDm+ +VTOsIQӓ +/]u3'N&)qAYPViTm'bd\M6׺3c'6sͫ/^:} Y>YoK643Ef׎Gb62{w}?ɏ?w~g_| m9]bl(y,OyBkGliLʍV=?7}ѧz퟽߿_՗_zow4 vtЀ kP[ #$ѕť{^y_}W_}_wvBވ6­4!;V`q +Z(6NJ٥;z੧˿/gOw_yś\<M.A"]^;N,l^zߓO?#߽p#<_?{.Vu)^s!MXBij۰<\Fgr|OW̤bJ%/'f%,` 98?4bL(bAJcP"OqA3)xxTkL7Sn GOv:(2eq.+bUԴ7ilL,]N}Q"H$4D%3]F;FSag ,G!9Y֋#8tsGBE!Z/|nߐzPi%dw;ӗz5-I0-îP+.PaamDXQ/zBUZ9ٸ$1c&MD؀8VٜZkEy0R0GYJ*Ŭ& 0gHFC֐ P;#lBܸXq?0e7e%szcE !|OYQ# +F )flH^̒lNpBf~X >ȰƵRXXգÂ*k&D+ͷOIܸROIKSw5SRl@aAP&ZQ|oej Cy}FeR:J [Y,`+;A:L3@d 6>%i669C˴C~G /'+S2؝<8bQXc鮕 X+ܼȡ#z 08vބT~I.9<Rjb0}vK& g,ΐعTe(֡o!d IތIՍ +aYmKnQReLdB<§TAuDQ>[St3(s!tHDDb#\ڲ8ÃrI *Qg$Dҟ;K*Pʬ+z!L`.y90bT0LVPWxhj5}j;ҥBM&BT@Juܟ]I6*PB7]`A=!lѠwjhk8LGN;ndv[Ra*cZ84LVC?ݴ;x`2b>/Ek1N-}Lg+XA8(`pGvo^GHp@iPb5cv訙(!OKJxHc7bmؗ9Krw$,BVR 67Ngi.yru+T dp QӨ3}rkt,qK0X DH`SF,Ti%Fί PI5N*8ARn@Et6̃q=*Rٝb#Paewڌ0 / l\a/qz ( L*F42s8RݣJ',Tk3'%3D$eWu'wR_ 0D׸oCƶ h`A5x87\vӲʚpiL[?0fQTc.T/3nZccAX~g@?p0ь768npp;#Ի)nskgQWĬ!Վ)Ÿ6WW011=qgJ' /PߠR{[^ +8(MY8(2_ +2XdF*qqXpIK28zgwC-PXuy_J҈Q 4R_b% *p#:Āltv'@ty̓8F+r&0obJ U1>8f:0gN) v$-!|Pi8Lp 3)Ts %MizZr?9yFľ1۝ 6<᏷B Z;=0tKfeɷ#f<8jHpT*8Ycs ܂yHjrs;?sK*ȋ0'Zȥ{:0f?4n7:6/P fTXQ9jAk/^p oR'177`E (RD+`m q66΄ӫV.^?*&jǯra6T[ 7""2҆X0Vs'@J )6րG}ev&3;X;7‚18%\1RbD +XDJ;SP&5EPLZxgN.rFo +RYܠmOcB@zH Ԣ(<)&LN==sL "E$$Lio +e@W5wI 5|(hY6*+U46d)!ݠn@ LthPmW[Ycw2 # T!zʄ$)!0y2cZt@'<0J+"dL"Ŋà F1UAԛ2Q"'uelw7;u_\z3!a0tmY-x D\BKOFSkwX0kmz'S'`uO\z/ݧAI1Gxs_I=: +XɛMOrr\/7GEZ]Ԫ˗=]?yHiYsޠ#`13+&T^v6 {sgq1G5.ٕ+VmMp߱9%ɮPW:LHͥ{g2{Û7ZBr "ڽiė&ܱ3m[+Bg#zyr|4lR +[8yP7b$ acJ,ہ,88p)pUm⌛ϝ͟_;Xy ΨpRrm9َuO.<$v@r0a2y!6{rJX.Za~ Ѡߢ3jaRxxB+f6m&p)>XpG +mZp=ĎD|`Pٵ6 +r{S"ނ+ҍO6,T 3_*P>OˠbI)hKalLV۪Lqo8wb*3hNa$ ^yI*-KK~k\?*iy"9QkA0B$B?Nw # w|_DLɧz2dRysK`i%8*/GG##̬ļ7gt~ \3 31CFLf9z]Hvv\9|}ǃIхGw~0pai?o5;% j?jA]iq[I;#2 *,T5i..5MN/MۼYZ`njJQZn*&n dJQ!9_tǧɞX/Ν:zӹ5.ѣIԐ\.7u +KG{ܺ;cc&qn5`>3:vmꓓ[K  h`v~!TXVBFhBFAIE-*L4ߣ}Cúo:_6LLH &2 A>!4,NnפּXE{!c-'C| +ҔC-_0DWHFxUqJKRnrߘa@8X57SڒWmn,>1?\t5:Q;_@E&i޴4j#` (ze`ݵ)ll#! 7$KdH}ibleT{+Ms''uTl G'␎P&r%ڰ;B(0EBv.?w`~٫U6JJton:r*;#lJ;Gn )%29Ł2Z4 6{~uꨍDžAZNQ*(?noI!|Q{:rnnu7% +#bv̡W%Ofg.]qK(* +H`HOR:Lx V^2"]Ǿ}`\F@(xn"Z &3֪,i`(+ˡ2Jˑ줍1__ZgӋtt_^GE]a> r$xFmeVV{ ^g/kԲ +a6QkLO2 7Y߫.Ot2eߝ0Zh@.yZ*ON?D@461Q1ZnI,P(ldkv:hi~uCK{O~M;'=S5A;@~%=]_lsNI& +2{\O X @71w$FJF _^+֩p~>wџ\PA'?{L3qI[y>DA:#:sbazgTx"'otXĺ+V@sHO(#Po=*J667cuԄRX] fvl..ߝ: {Faw{Ј٭YH)WCJaL[1+3n@|w +>QG?뷛0S;sj ׁo'͸UѦ;d*Iô/Σ :rXЁ}úCc!-{3` At +YwOs1.9 y?0H + [el.ħAGiM\0!“E=A$;P<]X b(?Uo'HL馧JcXaz>R/ ׎6gʆ;>kvh]bˌ(`C71)w'"_aƀ|O/Dk[n S=)PT6pgqʦx'XГҸŵOaݯ*m !<+k&Xpz#EPsvt8lIa^a*NU?:ĻTZX1s.XKgj1+lv _jOLI Ϳo̮0Rbw&NjQSXkT +7\! /٦9jc 8#7 V6LT^g-mm j] !P[8G8Xsg_~zq%mD!e1\;qQxų/23ޕċfkn%U4N w8l#Dj#`Ŵ۟H%U@GaRZq#qXaڶ2ںS>3:7i-6kg2wFuT߰diᔏ ]&櫺]ٌl69K봸ÜU('Mdc#@ς9`RP嵓7igʁ RJe۫+/)XZ7wrm>~H!VYUK #W1  kQ]e/fȀv)L ̓ݼlJP2pqccgwǀ!E'_&aw\a (o/!  sZgHhQ#Jπ:fQ1^@4 _!& zrms[WV}\qtr4ˊ * hǸ;%'Uҍ#FMհ΢d8sޕOnЉkO{R]M8Mb՗rW=OfG#u.bwX w!:]æCZ8xƓWwDthgeK|ԍ`umBoe:\0S~OSNTѺkӾʄ0¥~Lxt`:aڡ1S?m[tNeՕc7F;Tto}6ZhqDXipY6{z h@`]1.#Up*%Js/Al ac!QURegL"ftf;07!,j.iTkia1< +*x5Ker3XCĠRzkߣ D@mƴȐF]!~ǿu`vX^FȀCJWĄʀbB|z_\ҭɵ~U✐Ƨ޴ &]8k"CJڄ* Hp%$h +\jzӗn0#l*R;l%%ڋ.cLT'c6%M豠€ iy!p3/trA +|%٭.^۾qdg+\YٽΧgh U1> bO\!kFLxM[lxV1w쨞8ɴ zd o`≁2QQ:h.'Ks̆Bj{tQm JE2đ#^uߟD@!wݬ@G˜\=t$Ys +#:G vNJ@( vϸS0A. $p1sm|v-ҙn4Qh06ItjNw _>)*#i\jLPǟr&Opa o FmJۆVΊWTL=#cB4܌TYK3돼8iMs헊n yh@W];h:{.Rq*ۈ5|̟6ҡh 9VQ˴djsh$D3%)`~ ,-5LT$F><RvGZ7Gz3+狝 F.v~fvuBn1{qZ2XƒMٕthϔ;muw:m^Ұ5@A>ɮp+/YSFy)浨rG@TyJ HրMhe!\7@w11dh=ac-1!Qv6 ϾDŝB2Pj3 1!>ЁYAw Tr{Z=nm_J`Y1`dw'FD|\Vpg%0?(_z 9qlFHӁ vpY9cw/ \Ak3V.X0(3D +i$g Abw) 6^mui!{6s:E'Npb hzcZo[! ̩913C^.vxLԎ0-?9bT޸OS؆N3lq& +d{ncRΗn'ˋ']$(Jr}͛!PgXO …CJ1ڹjLu`sʬ${jm3\@hUOom&wJ [۵V`1QW;GN]y_]r 7M$W;7D9s\gSk p**vΪY 2I$jG݋gZ8\7&;[*l +h1D&XX!xn#U}P= Pz[o+=~s칉#N:sJ̿\~`Ţ;X7:8t V@80Ţ1~Ј J"ZFnTdjP68tK"$OI?*+.1[]ј=u`ex&1'T}sɩXc#\^qg,?bG`l++7GnΥ:*o@1}/74\5\:|JT6W:74,DH #  (zR0V`:$s'.?Z9/gpY tSYh'ˉB0UfA`4;+#*PzPmBꅩUN__cWo?ٜ=Kc|DU6STuNc8KpEژP Īomw'*s2ʒ:R1;|k d͠8A\X5&geb~4FXF0r+ &#֦7@oUsF&aқl,e{LTDjƙ|o@nL8'7P?P ;nMJЊxsOL^ݙO۽Qj& VƵm^ʶ|֕j!on>><;}ӻVV/'< +aa*>3rzRr}S.fwKgs'Bidc[y +a}_?yavϟ!4E ++m!&RU\ 9"Xա/߸ތ +9Y +Q/ &R2LmV.siT <Ʀ0tgifL<nI <0QJ'⛕ q]A#Jh[ɉNs<+W,8;30=zRxt04F 4VVeNOzs\~jGžxB >2)d8f=:%to/= ! $DN?'wXaA4l$D%!0,.S)Pc)ۊMlzS.1/㼟t0*-GGiZN}qqxrT uXkWVnl^/|%L^̈́y`"rJbt :o5]>aփU:Jz UV+F^VK^b8WxÅtCU}\^yGfuHwDyXq>{\,^x5yv&2gdKNu}V +ow~EXkq 63 [s盙0f^{ݫK`O <҄9HNsw.z ='OxPe]ǛU_^^ OĦ|܎)uoTDqs|o.wq l;J@4`Qr}~l{FL/dnX +:<*g]@9qLL;ܤ TP6׊˴]WJq+=1>NiHo&B9S}ˀaA499_nlt7{q=DaAB3k$ +  1 07$lL'JBjX\U:;ƺ'*?@ d*Z Ң/*)٪I }<HIsRzIu:@偄Sy8%FjcfʔPܱ 0z#Ulʊ^aM(R +Y;Sb.tbK)%+!r? A<+8kJc6`.bFH`\YgC1D33`4(fAO݅4$\&L0#i>Wvd]XfT]mP߼ +QLED(I0kZ^ɴt^IZ4o3x^qR"ѸQQ`x +";VFE5}q}ȃT5kexx $Dp5!D(T "jnƍ>B0^ʂu#憤E\Ȁ93F*ZJnEt\ +ab7d*BZn,Ab'"N/MRL>q\\\DI/1@%D$za ʙ/DwvCH”|D$4DP- +Q6%_fs8PQR9e`oh !چdUwa:^ˆA0_9N+"TMH;Fc<3>=w0N͇bjX%NE0SSgCg&`s>L`8=qڋKlH`}֬1w8}7qɇp8חb_*\DYo3v[:wZ O8EPlf1NSSELMb %&t # )ۖ +pA"1Fa9'$\^A!9/kY*ԖӵA$3rD8M30ǓR㬮ZzfE5]@%`FCM9gM&߬@C06Xcq.}QW6 /$[9Rr; f `gz(b3A̻cKs; 21E<<a #B]l0gYeQB1\H F D !P!;yOCǸOϻndLIϩ$'gؙq֚ TQ.N$8Sm==2D(wfӮep?O WXc3nLgI.a?LgB~rO{j s(wdg;ʅ 3\Yupx""'r#-$-&_w"!j!@.Ip^cD"Yt*cJ."&sZ!ptaQ4B֜‚^d*1 Ql! #YTWT8|? 0q-PCዑ\`7x_+dE4?;B#t2 s>܉۶y!r46&% =V S1BsU!n[\AS +a"I&/lrnPv@ap',?9ϩ'Q%uj~c "(asX}!O>GQR30MPndIЋ C1`.<{=3tPs"8 ιO+J8wSIoz!'!8 1N@'aS8㹌Y<cUz*%_4EՄvl)٠/ * Bd榚)̇i/RIQM$M'8Y{mm /; SS4P$(4c- ֹrQ S0!늃LDUN(*Fc ^+3Hk΀Svze#qOct| ]j z뜤@Lt;%LJX#[_"(Rz!b4K03CyVb)"U=$K88LP] "`"( aXDp=c|~_(a-Rz4xn套nRbAÈ|>1iG q"A`&, ~ ,$IAqfmY/ԉiOO?ԤQdvTg΄=O12Ӆ(BG!R`0?RIO{O/ι!¡Ʊ&,vVFRIF-yݹyyksWXbH:<;ԉyo(V%d˕&HAqi:oqg_ۏ#M0f fR% WVV~s{;= ]8P֭qT(yCԌ yLpօ>sb ӳ> +< Q+ +/2x1.rV6 +SO\ c]6sC훇?}}?K_}tegc83n5h/^׬+p\;޽{kwG?w幃b:9w%%t +^~w>xi__߹ӇݺN̆ %Wj8XN. +R3g֗WZo|__{҃;gwDϻ]`<'f}Oo?7o[GkEWAg0a}6]w}~_Ə?.Wo^QuwTNZ:4c +F2Vol^Ë/>/?{_sICYtN͆!P za%t~P/o/mօԃ+Ͽοk/ޱdfb`XN{b>a{/v]'ÏC0˗o~;+!Ҍ)%s7֌W +y|'ky߸77{;+7 Ia!._$xB򺲒e^޳޺Z|f77oǟ_'?:ŧѵr9@E$nz]H~?[}_\˷ݗ߾n9=3b1Ba~Aj<^R/;􍝟|vǿOp)C-RNpww:Oo>|Ͽ|7A*rh=L6@/wKw?xO?ӯ_nsvihHSBQ8F:J'V{^fKݻK_|߸_ǯOwW~;֕܃z)#@bOZɛel:0q{|xqz/y𝷯nǨ0D'$mj0^:n|ޗ\WlʦJCyAzNUc\ί۫>8,|?ze+}s߸okrU2 xIEd2%m<8G˩k|K]Λ<}ң歝z7Q|KդI>c)*JY{P?w{//>٧Kk7_?<* J" +X1l_-* vH~tZ/oyw?x~ֿ|Ǐy9ge-&L& +qDnS6LC-NV޻=gwɽ^ WW%Eg\$35B:hZf_)lT7^6|7{Q7qg/WAcIOK)RH j^L6g*Y]KWO7p/ ^X7-% bp)ه({чF!5"\Ұt:>za?x˷~+zt¸)z%0Pe +Ki\b;Yin6Jϟk~ų?Ɲ{' +v\ogC ^*8ww)iҦ?`eI@y;4F`"5ĢŏjvfcoX3B- `1wZq(0 }x$PtWΏ2mg>xawx>\^^t. +E$ai#t=Li{}c=7O觟k_9[_T]ᴜt6FaYNIjT +]L wa%wkpRnLA,I)AhWv'fRD"am]˥b*UvV%jdLAc =Уq> .$}`X8sK˝)6xۨhU}X.ZENCAXJMsӳh ,S#Kʈp/ÍW[᰿߯Z4E"(*ʦ=,é(Ij\ʧ-e,AiYE3bg)+y{&H mi.UHbٜ 0R5æ=XJ%J[Fu^AYII` Zh X/J`OO/΅ +MZoJSӮYOU5F+9s9^nGq3%ZY``驅dm)ߔy0V&c(Jтf$4-;G/޾|~gKbZ +IB9E"DSP˅xP9 rf( endstream endobj 82 0 obj <>stream +᱔iqb-n%g̙Q\d6 Y,泫|jWBm31%MeDٌ֢X"Nh>i/DrHA ?6ܞ saq>"Fo5T[0+LSVVIZQ=iQJ!:Eu?ƍ +IWL *Y^$ kT@Mw$8Ea+@B=x6fs'gs!熄?>G$0(*Zԃi-M'cB!D$Ff&CNUzUn@RӔP˭Lqw$ .H5,i/ %q 33gXaRZ}'='A&a*q!.-zq˪)3QEO ۧN-ƾ^qGgBr"pbY6gōQ kʳS,-(az3EO1l>BBL m(-4B4*ՐRELr#b\~Xȁst򽋻޵ZjurH&W Cɲt۱ ie ̘4; U/f*\jI-haSrfiZ5qL$F8˛|zJ՛DCʘlŦhKQ$lY<ؿR} rŏ[>aIf? ՘"bɤ'̈́G$Z0p^Ǵ'`` kr@2ȵr4َZvE㎱g<d\089D,Zwsa!:+A:ȓU6'\8gM^YG7,Aj%bruшeԞb,1>cPLh Q&'r!!Z 7SWN](@oT(iι@@ +Q2FGY7 +ȎI;dweH) 1y*-č,]ˌbh1]) Wσ<*mpMPōI  n2='Bvh6֡JFqmtn5D_ؽoWYeen" Fq^O'{!v攲:֌I%'Vktea4.TJD +t I#bދ޸8碊?G(~2%fGJq-Y +rE4~:=dBR!+V"jpDji;QMTC"eti{HfҹQlj֞ P3>r>,ĉůWصW2> `3q;'TƅX^2gBTt2L:~Ÿ,,1OFVRPTvE8&f<є +[Nӿ*!:W\!58F cRn,zNc7{WG/r%P|j)|r!_R}i;ڝK]f3IX3VT-iKG*jBJRRiLTX} pC>;1`ۯ>8 6"Z4:HzK_$ \ow^{ +] bzp:je|6AP&e*f %k7ᬞ8e2٣.$Trp{@LV)l) .mHr+'= =_9|QX[ȭsݝ{Wz~SͯGc޸د jnm7ݻH ظlmԋ@험Ԓ^Y>{9X Vw' ޝivw/W4Y?L܊YE|>D=H_{E^0;GFV +h5V.J"፛0_i-?j?;:sC`r;vυMĥ⤁<$(;&Y`bv&j\#@)j6v( v,?\aT*& YǤ\qtso-<2vy +$Y@sVunlF-j皩ƪ^Yٍ&T`WVtL*8Ϙ>`2KriK- 8 :gTn|mRe[l[@UW6 +zCkK7he.4\|qӻʶ\XKF~ro,I/6_ة<\Aq![w_{Aŵ}@8Rni?)>\2=ZlocDK -Y6XҐ3joLX7nɵC6e1 `N쿗LŤ:}z-9kE%?[Tj{FwV=ٿ"t=n\3d<<YeZX/]a/W,QSa: QEdҴdmIŸ?*aR_P ++l!>_i^vM/`+vɧkE+Wq5E2A.%;!!uV.uҗ]://h5:3i`h1}*9@Vͻ dhW}uLG<@c<Vnx0Xa8:0sZqij3 L'jv|CZ]2L"a,銩\ `ft* V,l|nk.X)Z-*W@<2jp}S\WL7`:D15B91 tr%$"" +p@ڽvytJ=g#2g+&/F0iͶVܠHE #(W2sZqfѝ!" zA"B~p X('ڥjg mR+腁./;"(Wą33i(U_ѦtJi YzL +&Z.zS nn||g,Pߗ^޼Vi{*0Z}/{.);//IAef%@ך'sZ0!iK$lU\2xX \,1Iqʙ i;~f6o&HAc2`Z!S=@hg no=MA-$緹LT& OzȅdKhoV2 VmE,J& gCBTZUP%I{SQCEuODU,`ƏZO3ܞM6#=A*MgFФ3tƃA.' = ?J~} 抲VBa^6:6cL2%js S9?XdW!Ys~+|fR@@*3R=iXtGeƕ:Y*Բ gDPU|\,RF TX.]-_C|BwwnQ+ZMϕ7nŵSAzKQNK˗} f,'Zb~‚4b„A]U.2V׋S~ +*082PN:>25|XbLJjp1|]6R[\+aVZtrN.GVsP8 ZT(ʅ-|̔ +SZB&4Xg|) 3i\a?n$֢|3! KqȌ5ragSӑqB.XG+W|ؽϧ'c(}@*"@i( 29%& y|T9-WIR*FJ>08gğ3Y/ Q)B.,Di? Q&5 @Ӌ8LYmLӳЙEA ]Q~+ VD\)umOBO$dbqK4"lr1HI |3yGB~O!qZOh'*AW.55 YaSQ]ܼ;ٕs!Iӡn˂ÍXFr3d*=c +jtE17TTy ([R08V$=}MhV.9v{6`e4VypRK[>˜IBL#@u@Bf5.h `!)UR9?fE2=q.&dF08 +X<R@ \|Zǚ597;h9'ɢ9K.jJSn ef\Ly +29H;Rﮰh5OK{ ̉E*+d3Ԭ|tCܩEBHƴ0~fҟ"X@t`|>7PC 6]J.HZ21N5eoF{z8 +ٰ6_N +5z!6%0&@\0h #ae`d'ʘ~Tjov{>q#&D;q1ôaɹ56 F.%́;n#7a3q1>qF$@]H/NyEX&ʵ%TZn]pO~ԈKŨ<4oܘ!ƕ:,T“([™s,"׸. +F ]s'hytPZ.twgEÝi7q5xp_8S29A]@'*g.zeƳHj5{q{H8]nOB,3V VDNœhs}>aX|M+mE)?tv'L@ jͬ\ŜPbVF@P7s!LrJ=Xb{Y4^P_ݞ>TUVz{oOٝH!B҅tA" Ѕuv4y=QE"?)ٵW5M]=>v5'c>GoG?ӗ۪Vy뿙}Ȇ+ž3BmiR ӏg~7h /g hMoGoYI]1jejFkJKXu8~7Ćjxo)mu|Zwۜ^3d@^RqF7lo,Սڙ3޺y_b]goe.)ə3?B+Gڜ5h- ϿGc)XוnQ|.0\}C3FVٰHNp~^$nQQ/i"[l=Fzt~u_%ۗD%Z =nӋO_o~b'PK?&w[k6\}7oڔ38O7 WWO5yY*?ׯxx_hsn.wWw5l6=8ϓ?S9NSx֥z ;α`h{\Zvgƚ_]}rr^ hwuk2o$ggggҧ׮(G}BOO^)'GX!=rw:~h5vkB X3OjY u#=e~%5^RPg}gwUՎ gOY-; ތx99x38x58\^ݮЖ^R5*R4MV&>YtD3^O*802ІO[>M4$xw0X]eVȑ^Qk|E?>Is5b)ESp`wۧҏOGd ]3ש| ϥ\DhÆLw0Ԉ^Ffۗt|$d6o7J MbC) Mw原ks)؀jOF7]TX2p8+dnMњuf%-?}GٓeI!dKޕ޿F%[Ӫb͹31\Z+s>w]HvLmm˪j?φ Fר΂6WBHs^vC"%obVL?Ϭ9 59wQWE֕lt`BdjZ/jy$` D[PT#<9qE*Bd489ۚQjE$@dgTc,BP]k>8*v4ks0\b""}?sW9f6u]0}H-]&-ڝ?쾳~/ޑ0v7>h'j` +K[F͢@#E}`QLk2߫&Sʄn75)[)ݪտ%Hީ+S5V#pFW +/^[&\%xSHtyl $xNK]`ڞd3R(Th^@ >$ٺ^#ȸig"D[07zZ{^Cus$&@#;\V4a`9D0pR'>FK85ƫW^8o +DA(CHg/49(IQf| P (\U1DVk0;es f!=\W&NZ7oZw2ZO`b<+únV2-Q@+|܅we4G<3 *%V*ZݤC@i ݿ:3댹p+wΤk=tn țiYGV"a+sSF7gu{%N2ѯ!&-Oy{u5?WY5zY +VMjGoLPZ i*;a/r\ YklwNo)_u +TS)ku.7!>h=Jz8:>zg(F4 m wkop5:>^eiڄE.AB.댤p A.D]k&4ޅ+\(g`t`܈foQٹp p{'?ePjK`Y=AE>AzL;z8WNr 3a( \4Ԗ/FK2;9k?75SsBB purfn?sF%9=ϞCԩm?/o~ͺSRt/"D';P"ajj*w nYSE0:|P#ԅ<d {7T!lY0.E Z#홝K5C]+-\dkJarg$A$Cp?WkoqBLlD9er}3>h`{ۿ$aoRn_րg5x\p|ڭcȻ3֞ h@1 }BjW*3|U..wT"6W|8a h9xc:$g͎xӫ>ܱhFSIt޶c@)Ѣ.*]-BnŏJ+I5fE@t'ವ,_nz"k_s-ҟ@Z쟶51n\RP{=Ni䫂@I-;8Dx_(h + revOCi6Z;=w//$㧿qz=tƷXhJ u)B靁JHJ{ckZa映7I@%0A~#:*R:&vw +nC؈!<g]ҟN︳zVcs0}f/Z6(~C>?!6Ӕڶ;F븡sLciTU !Jt`t.뒧\#ZI7STA韶9S7)]w PaNw>hm<4P49R,މٻ'OE``2:VfmuIlvmks +tzm@CSwϱˈF#G*bG'*j;j%CEGeL"2l'?&~{kxg,#)K^q0_)z L悻zOp!#f0+=9a1>ewgMMâZ[x-ڽg~轓ީ94UCBU|oOZ&1 +^cUWBtس[2f}}}E[gHim=^SzPagB>izgƝtE%& ^;f~uj؜5|R lO=-J+%=^rw:W>~ktfޢylq7o3V`,ŝ6I^ŇO^sJRz1ݢ4u_P[UNr+8o/wsIlgIPn3eÍ9G0@2O3wπjX"P*`EkT pHlGo?րU J$F +c:3`8aVC*^9w.h0=磋g47;=gwj+H.2|?NOigƇ +4X6_|{"V+{LJZTiFO#$1S;6gx c=:,Qׄ&j_avϴ1H{,Oaz>0zɷf̚ēQ^ޖ9VpEho4m RVӹˮNInme/QR/Oz{eS;z8͕淇`%'H%w%&)@8㧨%)F$l^ cn\\;(^{QVb_WwFx `|S ?Y+iҿ_XVo#9c +F^›ɁBUX Nپ9ϱ!pNPiC˼ZOӗN* +X&4?:w$op[z잫BfFk.gn|u]*8\&bxhҝ='wlhm5&O%ZͮIH]RGnƈR;I2f),r*"8|nc5-$4X!v?0F~&0e1DN{?zRDyhΞR:"hPzV\I #Ec!ZW[0Z_z+6_ +׭u .1zk.s>t5LbP]+< *0A|E>њʙ\y%Vq]롂~ K}ڰٱ:[6`Oi-2\GoygV{%̾?;~?kN.`"Z{yC{9>AhmD6D(Kf0jr&fvu;/y{Z} jr韏9: w yT6:h's Bg &&\`Sn$(paL +|DΝz9|w:ѕ}h2T[dMgt.9\dԥ&PWZusqðrA]tI](AykwVmyN縎OHM*I8?xye4 ٽKFӟ_I)X=pQo9UV`?l^;D?Qq0JsUe T"HO/~?Z6G5}HXS?mNѥϫSŠmX؝/iAWlCe`ѻU+Gߌ/.0=;9Wതe-G{4Kye!N(h).pjrke9/n .n{uYW?9~ZV0-LمbeMɋ7U} 6x_S0LJ9>ҚR񤭩[i0'3&!aaxo!y +1>/EƇKCK?k}\#*,N] 1VCwirhٺΗ/ʛ4WrxIh%˅GZYn|[wQ?)I<_[в띞FW`.PZNgھk?LpNQ- +I]J1f/b91so*uB}Ck'S IE"-q4n拋/_}BΔ+MJyE%w:$ 0P,&WQ\7ʴ359I?H{/i?+gӿx_o^i/>GpysOw@o/H t2K/>5a%:P4$O?I_)â\&}"Eit+ I1kW=ɭEwZҘނ1_Un#JvgFTn˚ΓZ!ywj5ZJnqMĦ;Ԓ5mBt@3u¸ګMƙ F6tgIwF| )o$G;Ңav`TΟx`y>YUVߵ>˗Ys^]1᪬$BdiC@لz"z#ޛiXӲܮȝc9:ƹS9\qr%c֔ꭃV@ 7zHpU!)1p^;RZWWE߫jUU; SWzbx DaU J|Pz>R Z3.fkr&%Z5#6~k>j;U-KҦ6o̡,1.)ٺg),DxzU֜1Ƅ/!VukU>*~aJwW,Sx.ca(g^%.ۿǴbiz_n)`m_o Vְy7=ӺXM2u iHgtZ;>A5UUtKڞW }І6Ȓ.Uc@;3{\}}kVզ>/'?˷|넏`}/7?׭aIux- نz0۴hcœƄ;)}*r9nElUĸĥ{&k 5ak\_1Vxrگٯ;% Dc^S\΍ Mj}Ι#HßJݻ&ޣ"T v"ׄLˉDꃽnj7GZ Tn*B(%:%~qjBIGKBo_^MG}J^Mj8?o0'Frș(CY5i.=bvr>t3׍ ZhB 9xqX_unV?9 Yg|xPP*Ljr!< n=')nhs;×x1z?㫿vpm3up5ɏxnԳz.sN{k.:eҗ)&tr}J?)NYΓm y9# 76Y^8KyOjfobeBX[)|m(,4l5,B]hY25AwJԲLk_Js9:wV*g mĹY띫hqBCQq8gU(~"eR+ZԤ^]V +՟fI3CyŘ  J[B3zT;x65Ys[9(SWZ`rk@y]Pʧy` a ki;>\q@5rBZ, Z)9rg `E3[Z=<j_+kM3wO[yƣ:em!GE>*KqO +|"Ho_43E:17Jr`d\[#Nbul_$ot6VсSN1ƻ_W9HQjƈso$PO׺y6',sI?P۔>ΐDZa2knJ5'%6o9+1!dQAȑvMJ( +l6Kj"&aCg-6%RT48쪔 bՇ)+7'! 0HXH_UJ<쟻#tt L2ߤ텒zgV"kume/, +鸴@EBup?aN)sG? ΥzK9\PZI'?*ut7BrhUWk5:!˽3`2_{u7J4^noފQ5R&uhk!Fwn9rGq'f$wQR2'F\\Y4yzwãE)ܹ;O_'&E8O=;|Z^RBmc9XXn>vtPUKBGe.Oa8X˜*ulNxe &yLD K'#"sTr~\R D^*a +Zu][S'jZ,h-; -8VO.`sL;2ɯ1tfdVnWUerg*U`t#`5Iq+'[Wg)kv.'GHhfm`P\KwJqze4)@7G`d,$zsxH3tM9VY(3{p\}=ڽP r_q! jջ}IO\4$*ruj@O$Brf礮xo{ek;'og.i8dSrb"5sCI'M|6֜sW,D4sQC`m śt8!48ݗۈns^{ c"fZBYc0dwu~)0! #ԥX[jB+Ox#S rx&"%3.5fx:kEwQdBWЕ#"J>) *T~E*|[3'{Ah]=cOYs;~r$%mA֙~ڦ%B$1B[o{'?Y+ɝduʟpegJ?ց݅7zi3_Bgټ,!hs/g:;~NAÚқ<` ]Z6Rǻso|_O~W)n(P;!/.P=1r؟<\LZasL@[Hub Zm76glO5m3 4>fw2!!?CP![ǚثKn4`<k[SyԚP£.Ɯ2J-@~@Ѭ_E (mP2U8EXcQ)}LW 6HpL;"HN$?ЪsHN1 #"5n *c\Æ6llZHuq1j_ 6Yݩ;EaTX6(¤5xnJš DU#uD;cxFzx^s.\Slncg1B*@#wCc)ks= +VN(I8Sotvkwz{Eһ޿Uۗx|EN]VSk\\He12XBJwX2񖃃F;B*\֑e ˁ9LwKKH Vg$zN/%o|*0f<._20I shKg  ̹aFJ|RcսyCә#UP ]R_55OB@c]Pp֩Uj(9#K(E _bNVv>,FÂa`7|;5LUe Z! +?-8o1YnhmXcCNNN䰪)%'?1&xgE ťf cy+,+mE}A¶Ofݺiy.noqha R$g>z"reU^9BNMC}u44y/^;d d!#=9ҺE9i^s;3a-@/BY_s?&^x,%kM[pyvh:;aUאP9BEYJ QMLj"Z# άĺaj:B'{j $E55"N G +z'TkQTPvk!3I0,6 jb!wi_&vz`e! (!&ݣiGgTFhտjG9:WWA|[RH;UD4kbkJ05ʒ:DVk"6eӯhr}BH-!X7$AVꞣ +hq 1FABp1rio~(/r˚C^`!MXf0yTR4|12Q38+ˠ, *HS-:ՂgO< X˻ڮq@Mxp[PHdzC&eha>[7V7NrƐ夅,}v󊵇O"jҁRG'0p=],e] rpsN;usUZSP=zʵ }MQ1':>)9:m>mZca=R%$}n!Ģnr0\yo +'VCn"gb2pVr)>gbyg +czgy6_#_ Tsҍ[ 8#Fm'~i|~6X7=O9b+RߌOPг` eI v*TaMhgH9#LW7D + 9c[3>)t]BiŐT;۴~ůYUk?څ%QJl n9q$}CM8AB"> G&~UB$bb6L3 |\ B:Sř`n?E8eeB &hr0FzЋophf4(iY)ٺUĸ9~TbEkbS˴ÚKY@LEPNֵ$UdBv>ŶCc䣒WGuO=Hbpu0)-Զ,[gjv& H'6H>B5i ? L`(vSʇ}6RvE3ج=9Y5*rP7Gv}>:ߑ޼(@Ԍ3NqXoPgݕ>s"֕VU0o%6.p `uTn}xMΓUP\Y=)39Tɹ *at +U +y|aM ͔LET%,\31T&E@,,vrO+ʞfzqP@%N*R[t +[D] ֯vxYYLm].Km#h(Kd+*)j|бX$ H +lWQq&q鉏tDBI*{8W rG _hؖyRD62e%}w$e~zd#RO` +H7_Ghu+j=qEINpUm-^BO)gL޶o(s;HGEO ЭT,a1*Ϊ,?U< +fSҞ6/9 =D^;c)=ʚ.F6GtͷF2gho%1=ĭH O0Oܥ> O5'1İʧHnY` H\)^z(# "mR<( P+lD=V1C((#&'a#aQtlPz{ x U.`6g)O UÃ=]cNOji[vkrZ*0 ĕ^5P}Vj [71-{fGiF(=HM.lJk41 amxO"?h{YSL9fA$!>? Gb&W_ZHЮI]<%مV'r\t>ڳghU\\ ]d>A\tAk1'w`W)0|tG'ޗ.w1 [;e>=/FH&EF +3f'>0L v<}.kɞO`FZ1aEN`Yot1.d \ y#=2lXm@&4f1bp*U%RN$S +PlH\LBBSߊ,$ T@fnI3ޙNξ +p*${Uu*K9*JxenIT|))OrԸH X w#zg`$1:ȑNE.fgIP,֑4iݓ<%a)n(:HsR:qIjAZZGTl΁:bܥ/Eo[h-)X,,I )"vvҬò圹om{]֓[A"^ĞBi3C=.&>.)kKXqq?wtZ%$NRjV]nS XDUv`PN +{*}roglbjvnP*TP B!rΩsnI6I1")aGadْrd+ۖe9g潝s=ODn~_@{ah|k#nBണ#1 7n BZOɰ5a8aƀ+`AStQks ~x&<|?9zdخ2o&G&,.l0VHXؠNcU९:%,?㝺CxojV& Њ) f3]\xC5,X"" 32W ELjA'&а$~j(cǀ8s9/Ł`쾘zpXqC,|^bA"'$CݟbPʵ0N3|ltҀGGx"XO8@} +{8Ro0Ajq Nh08n`HK9AN͈s4D\4TJꐍsK?G"X}πecZhUuSG]F4ØwɃ͕Y0$'c. Q.%E]}0%4CHuwd:jfGCD؝=(ZP +.:InFlu|C4i.#c֯ YBPӧ4)d 0fj@vR-wE1?KĚ +fDO+䜃0Y P͟04"n> +?aN.">3HNz 36 B?iS'E\0;`3d @)6+2 ztdlJ[y-s*t  &i=Ҙ[0axbymL:D0у#0S]wʗkڨ3#Fƀϵh:\JR1 OLnREGBie&*iH -L╍xH:Oژ,4HĴ.qΎiͯ4aۡ|If"#ot2d}=84!T 1ȍY9PpHN*ILEF^9JSS0qT劑E );fyӟRiqPѨrsexBjQW *RS,v"fGʋʈ +EWrs9h!&\bft +Hx@/\LjU쁊ɘ05 HPPUU6$6Rϐ4*mSd|j)X4Yo[fJcq0(KljO'%'΂a}n  YR."TvB6rP8e$m#54SᕾH+VbPNL1IqYFmLTtBFmkܒL ,cB 0BBALأbŗݽr=>5dc^5ꆄ>` yPZ*͘}!+PzPDg>6+wd +Lgg ~P +'W%po۲G;T󄛾x7X\+X(I&-Rm1iNJ?a+:ؾ%]1:9gqN.K+RrTz%T=UZ,bD`9o rLS6lJ\aױ TzMħ\ߐkjd~꬝IP +|: P)>4p ?1|j4Xx+@D+a)X4y!abXg;R'φ@V_firs3LJRqȀ.3\]@O8'՞R̜I'3n{;0FRqq@] +\zVґͰ*&W@Uk{kWwo]~mRidvZal8PGVBZgӓBa%T5Q 0ЋA+YF%]f v̤F~ﬦ#A5҅'PE/VV./NVֶn]{;rud;Rۄ${ssKkRݝ-T&kWJԶo+T"d[pHhJ&r inE'd+] VH|V[dןgJ:3|f f1< ])WZ2Ie;37+-=b&.+$;ƎTE=$H}3X^-.\/]=ytwWG|$C-v[^ +E3&'gD[(1.7pT M)L05yms,J}-e*Uri#f +K >ƛk}A*8gUׯ'gM!7o9O \y|fBykL|2q= +!I/\[bm[,.^/j[0$Ly\L1gW+9T{TZ\h|pSɳSs{Y hkI" nA8Io0bF_@rjV0F`瀯X73 P9egSKYQ\'i!9 nCB#뫗[ssplc썗P>t2S64^X + $:."RV(jKw_z2;yzzE,?Wj+…僇A).L.uy x ZNL]NN]+g6j JOө!\Y.q*`{E7p3;Wd]OW'յS]*T֥N~*!\0"/\ $⍭}ͯ:|bgR +D5TZL42t{4 nЊr.VێOuP12VSkkg\J R3Cm:5CE/Z>n&p+6_MO+)+=^޼ܼ1Py&!7OڽIP7VklfΫӸR[=u|ɥ•Hk-޾H+2G80xTsU;!.-əVh"Ra FpMeπ{9BbdfNiU.4hĂbKG٩Bi!tF-/R fK}&3%"\v..q)CY*`j..Zcz9sfi|a ?{4{*^㢵?t7E@_*'-&9Գyⅷ+R;Yw;t“y2b9HJ|57}AD3^]ҺW+ٝ+^!j,v6i_'ÕMne^ +Œ t.Z7b6{rceNXA3a!%(:Rˡv[Y4y6BTu }{֮GZͨ-78}(dOъ'jU**Do?ƺv*. xHZ >'3S x!LW&܁Xuq+9uW RcMy'jgGӇgעS׸҈od(̹¥XmG*bvif> +H}TfB&A(sBBq' $D˟m6;mb..93\w63RJ9CFr8w pho%.Lpp9V3@ لVRdg{#="N͸Jv epumVK+I>3HlwCPv-̥5r)-L'nʩRmbuR*,%&{i^7neg. yZi6"apeBru1>=HrS+4O\@G%Ce<w);uP[ut|,ЀHпz#6,wZ@!VIUOB+NG|qz˚|ca*ڥȰqQ j[d0S_LT+$L8Rmy`VmKYg báLqj4w!\٠IRP1Ha& 6Ha`jMO0ȷ &q9!=̭A4.H⸕p w.] +{wΠD-ȀD4xe:A ;5\L TjςafDr1q2[륻kūƄ2a:5 LJu`t^?O7XtI'B47{CqF[fOhĀ{W^sz{P4#,+,r%!VEP/1C``x%R.&ɵ A5 3F\lP2Y(\pV" | `fDkK>Fd(T0̀>',[(P BjZR WJs2')齁B{aa,Svr%ҥc=RA`Y&v/)& 0!Tgjms3aXKNclބ0lA=&z#M$Frdq$Fl΂}BP6 dPG:!c" "RRꘝgʲ?3dȥdcF2 >1chx\ \"Oi`JCP驃܅lo_.؂ ruN~ZeZfK1![Hx,nH99@9xcZ11}.BPtĈP|bEP> +;_DdHx*9ԟĄիsA͆d3[ά+i>-7L/. Pl3f7z7$d0Ud||9yƁ\9+STo9P@b,a(N&:+̜\1*,$UBğfm0h.ȨqNKw`N0^Ւq9A RjcmNW m՞TmC#sbLNI*9kVtB(`*t0#qllq2⡣V,u Ӑ@84{yIYܣn?.(1iGllddjA>-fYuwv*)_bz#UDOx@X,BXF@L.9WÀ eU1Ӆh +D䓋Pױr&*R/+|rzH8ar3*k-ĝc#6ODe5RXF!w`e11c#+m)g'~*\&E5^hv6n_q}^[?釟Owͧ[ToQ7d$jLe*^N-Mnr.<[t?u'^yxu62D)E:ZAJ$ gnO~ս{ߺЅ}ow>9"2A:-R52҅Rwtce'?9W[\ou/>`yjCJ5uvFgcNT7QYv⥩Lw9ZHmfn=^yK>}:TuBb;|ȹz̶ V޸?z)4`.vN#8Ƨ nn؉J7Bo\_pWzG{_Wg"133\  QE+Uҍŭ_;{ŕSWKgӝ\GvĄSr>3|r=ӯ?~ǿwsܥ6 bARańKj탓箝rcϼ^Ϟ}{ڷ?o?^|Ճ{xmƲo~^x~/ }>?'@N *l5ŭk>K/'G_ o~}>/_ǞmI_i!ދV,^pRP\:}7{?x/?G_է_|?| l\˩Bs~ri{u~o;?~>??j/?{*QoPRDp2*-cƩ+*cU:g iPVpDRչb{ԙ_;7'|7˿7{ѧ c|Ƀ ɽ /_qGz~?g꽗_|OްŢ> D^{~~G??{?t׿o_}|6^)^\=*uWW6V׮^}?|O?/~__{򎐬RNխKm윺rko>߽oo?>쳏?W'!;p@33n:᠜jkk<țЎo~׿ǯ>//+LlE('bZ-7>3Ͽ /O˿⃏/?Wz䚫&L3FBgQ("]O˛xW^__~~zO>{|ɧ^q>{L(#H>+O-l^7ן;?goO~O_Гn^۹KT 65FąKo?o[ַ_?7_'ꃏ>zW/^]Dmr;['ҹ$Ĩ¥ko=xkϟISpEXf̀ BR0J˕V^Z\XNo^y\zp+s$Y.#CE49Hvy|$m5~*HՅn{߼ǟ|3/{6=Ǚp X0׷/4SFY9ujg|oS߾BcEsdȀ' kQziZHե[/?X7bՆQc& +,^E +(DԜ[>Ï>sOۯ??OO?Rފ84;>j?1t$Cr՛ZX<}Kw]v|W__xzoN,UvD4;DHB뷟yGWo/W3*T<>Ŏqh-.r6isu\>yt҄?tl|T㴺YW4#YNN29Q@h+e4(?hD5VN-xp؂ӏv4`V!$xo#0r ƣ\잝\^ U5!Fר:ZL[ Wʄ81pBPBQ5$jRZe%Vjl&23PMt\?'l_*4/ +R*RBW|:6ZFza7Q=:uMNl#&k&h!OEⅤtL*^TrB6+j`rx0u4/N|3bFSJ<N ls G R1hNS D,qyf?%"* ( ev|L$BQ\:l-_Μjx!M٠!4PDHL,ׇ.A(:;\0DH,=ɀE!V7/"B10q| +jrR.:3jaja ޢ$HɈջ!b;4mP"J*)伌ꤢ3Iذ 1z%$mtBy.ƊvwVW`;0e0.*H&0j#q4G-uMPC6aӘv8rb~7a> 3<:oѺ',Q 3j и3c;XndLC$e7ƏN720? 9!1sqzD9m'&L.,! +.oV@Нz: + +2TQQӡ°NK <`Ⓝ:ĉLf~d|si<;1#TnF57xB'vءc)tBň! iǡ=l30jh%Bx#3ƲIԟuTJ:6b6:}#fכk{ZwP`0> l0b X*0JSTH%2&<` [ǜG63#fbBjl G]&T2{yÃ4P'z7FwA.V.6xlK9)׶4&͵谝 ޘLbbVGpA +3^G^t10;Xݯ/xjEF"UJ*'Aw"[LF,@_ ֠ΤwASnjA=AC&_W*)Ij'd!^>sܼ:T/qe.8rE;()^ҝæa[!G&DC-/nа&bBq\3b@  zB5(rK*`0̨6.̺EO 3<{Q_#7N ^3_vsr 0+hdsvL<ȋ}(I;Gx#&|QH/R}PqlItJe\2?6fejG+}G,,˸ ;&\~ LRJZ4lꯇ׺D˳j$Q@O\[(b7a4* 4b!qN-0 4cys }L\  N87DӡQǠ0n(KPe }݂PotIK`S=RiK U}JCoU h\_$7R<=TMLY)3o%"-G#f{aB#QdSH+MOj56*Ak\棵ZwÂ63 aR5##zQgXB0/,p@'YH1h1+g'A2Jvt Ơy.ʹ1xiuȑ!¸;"T&aQm̝Ca[f}% Xd%.5'lf +xۗy"wQ\\ȋ1ɘG&ڢ#a3_lG$+Rq(`S-H9wpi“IhAmHm%݋K[Fj\Vgg@n!`Az$)I Rf6 +TTVX[vf⤛7BRC +@sjmݧ|f-\\piApd#*6O@A%]/<@5Nȶ&B`=\=l勏AF L x]w%*-צϜ@H}[-V_:6G\܀f`PBIЇK3ҼBAxMM+tbK5KPi5 +WbhcOsjsB +A\3:OpF13xPevKHvd'\^zvc{߸d~G+jy~n_~D CELnŕOi]R=&]C.O Tss؄1h"5O d3}&3 x{-RG{;4 =ʦtMxbcef󞯟HɅKūliMKDϽ=yy [$ٙӏf&/h@0pD>a"Ɯ*KA:.Rv1qLmf׷ov r:hg􏸄x=B%;s :D`~RFݲ:j/Jwp;0ٌ.LʊE̠cDž!w¤[)Bf6X!Z{r}/ggq;&#h\CFڀ(alUG㮀MjŅ+W=D6L3B~ޟFhu#gSR0/ +)PpjF<)C6(E,9DŽL+%$ +kK6/>\-sן +e'eEۋg8ōD|BMʤHb N?i1瘅pwF\ " WCҩtf#&/g6. ЊU>M[ 7<2JFci*Dҽ|{dъ+w 9Xi*9%y.7sY'HHC:G\?׍2666A\L̀f<4}g&wo/Z,|L? +=/ K`5-xX@N.,iAIS$:rBw h`-nM S&TLcg_i&x1;3z  FxWT u;D Q }a"?Lo,&6Ӻ4.+U͝ɹ7/7+~yRq2mchåɘ-N  =v2 S(ؘ4.wG,l.E$'2~ftZX;G+5Vm:Nn$H@"vl"_ Nq#iP0EBv>?/l]+T2fcL*;];i!a==Ox̔@ b"tĀ}3?#\ZMNARqoh͞}pq1c9cA3Ea"#ޑ1 3b#6? u)mFA] 3u9oXr)M= WXR{?fdD-. 弐A)A:08cc;N  [ i,WRѺ $*E0HjAN⭌ ixuڈ:;R <ƦLj c,HpAC  24<ڼ<JgvK J0v)Zuc|Զ0Isf/O*y̰lh"P: |<4j Ͳ^vR*Lo\ mԮ8Oh0+y҈wǨШuFcB.Zpfc;tT뜂s`H wF#?P{Rm4XI ϶Smxhp%ōQ+a/4"Bȍ1xǰsHkK1qZD^&UGRd`L';D0btEz̻ . U6EmAζw!t',PCz ׿^aۗaHJ5o efN/]|j3K +{;>q'WXa0Ac)M,vpDr.a LcrĈڶҶ'uп}fȴWj;Lm=ieblS6s3x0 7Q8z'93c$}r齫4UYY{]]ڢ -A @%шDHJHjf퍸{7{FL/0{0`=nX[d]phMR&Y=!5[,mfucTApǙ]]L*L{-V']ԳI :+%4X43Ɲ+zaptiBrݜۺ9\ai7F$\LlJ5I5" цV.ߘyQ.|PRq(*M)hl|gƻtl'ZJKgY11"5`ǝpNMz1Sa-Y}zaK`GAHXĂmQJi^+/:RqNth^DX + +- ?$G]$Ĺap]WJrmܻuE>>ō3L8OSz s>kͨDi>@G7ձ0*I8'\$qPyGp%|<i2Rb\k{?or Z\*[[#(FHua8'&cc't ,7j#Gp}T+ݵc^ڎi&YV76klkDy?Po:B?U?5'iIL%h; p1u%BrۮϝSChX_St墧'!/l#gI-m_|:5cx@윚 U=S!3tdmNYqZѲI7&]5q7[38eCP%WWQFSQ +R23;6ZR$ spK`Jea1! Fqhd:`c.yq7*y)23g.T[=r*cu39 +W6lS= !!fZg 3Gw>(dpC.zW+"!gxk[Lxݪ;I}s P8xE*Y;J3kA!d#?~po\z!X1hys}1ZRtc=hŊ3vcADĬ'< Ӑdun$F\c$fP5gx~![/$L^=k <ȈyP!攓"::3q=s +#&4E-]];s +IDH ]2k#8;5~i܆s wV/ "-YmT2=T8C-i7ƣdSA4 3J3@6nCNOP6o>6qmĆ8)twډqj֎0@rnAlWr32*jaPZrvD&x>7rZpw 1R >&Fe13)ΦKo|kb(HLWnU. Y;{MhXFׁE&}B08aBc1 vIRs+rfV +w*&Z\2kw_޹Ay[m>{ \sav$& 69^Ҝ}kTs&dBTe ocZt1۝Lu9]&x6EaOvukkQ!y:ޖF}3V]/?|.|lqV\޴ -ۏ>%:1zl qԆOyX 줘5.>d*/D/B(1*NZa.cSBI559mm0FZ7ؐ{hc2 C<*>>= L%'=4TB>VS + aiֽ kk|{KT+T +zWY@7:{=S^_RqRc.Gcçm`9(^ -R 8 +V/؜D@N$.N[0\0&N;i&+.]3[Bf.> +`l>+pwzH2bheA@"^"E5kn>>tÇ*B!LGSMA.&D7~(VvPP E1 ȗƬ0* bvh .xGyl|Xx`M7WF@r/dP@ȠT&ĔI'[ϺgoJF*ꥅQE9z0ؾ4/䒚]l.^Y/Ҁ+'o~=mcN̆.2eC19DՅR̤oE:IbA4qvIiQTr=9դt{c[Erk@!MfWcU;*:&fh5@"̩>iϔ3Q)3ЪgDŲ~q)(B@L9Z9#_vplSQ7fw/} evl1f}{vtnYݷU8QEnAi@pJLCN*.Hۘ_Wν gl9sF% dA-椛rqVHJ%ӓ~_CAm+cR~~.1i+|2kvMƿuk nRuS*,řx X52'uD~@+&H|gB{m^&1'!u7`dP`cU.UfP߸o$g6- 'HN okr{՗xg1t +Oy$91nE4 ?]-m <kl?tta⑒GR''Ze{QyNL +h4nZaMǧqlGcA),|z>:<㭸ᒔQv%_ ']D84b! p:H2aw[ DD{8wanNkx~U>xB(R{5I)y81KP ++<\K y.۷g=ί-]8woqnu&]_yЅp\wHƱq Wtb{|c>n:gpFJtKFt|,Xa6VJ+Ww[;C.7Z*ᨒ-:LFۻ;'N< qÕgR2n-/_8|p˽f4\,DhVp3* W"UT-N;:QrtjD>~8I/ TcWL4QL6 +Ndg6" * -X.epQ'CCg%+KS^07,8@`Jn>,BTXgʋWo{/||>JWϔoWT8 S/nl`zXI ke=5sgzcSxJXe̡C/H>9\*s ꤇fj;騘A <&F +.T.]}-?VWHGGQ!pfKv5g.Aᣇ#ƃ#V:Pqlzx7Ŕ*rF| tppʫ7|2>ؿN{7Z"w\M';fmM-BlfԎ?;:12؂pi~;oh~Z\IRPK(8i9 g. "STu@z26(J{ֵ7^քT]/*AWrel1Y\xԅznj:rldphVR e̕w/ kr98F׏<.N 7BO3dn|]XHcޝoV\D4@o|ŭS)PVBč3t@"55j^y0=?H7;WY5TsFO@}b؈AU*u[]u-G.d\fgP.Rxzq/ߑ3W^?z{szq;gNrMy;3Zs-U#ѨdmhmTcTy~EL7[Wm#H5՜l%+YT7zԺaJ0ǣ5lj Qy +̶ IXHyByzvl}}8ۻlz5m\RʴV6,*H6DDm~cJ ҷNC'`"l%ĻN4lpZ%ih@Gw:XiQ0k'P;ٰiATFrIul3a "l[N +1 g1;eF/W/˫\Y:7`rM>t$Xledƺl|S+zq7/}sA.]_s}@^:9f0_9eAS.6Ƴ^w7^yc(4b}LR$=C幚d|.@245* R韽7s4xsjY磵Pe1P0݈& Pfqs;sgVVo/.~9T$3;o9s0{wtFFCŕ̹ܵ o-\|~N/~wtRT@`#d R^Ϸ6/|iyZ]^ysϿaux+?ZtE+.pl'mtm>e tS1t!&:Z$" ;jPZM( +bE6@CxȷͥXuEL/jJw!T_n># "'@UBo!ląa1F\(cBW3Qgkp9_WJ4i-X´v;۝#rS^^ +T7(dSP&N= &VO;pP~B!9 b&ķF\'#.jb-nRArpy9R٠%#P{48HvC96\SXmb )E`=,# 6\9mE8h`K|<>@Ġ91Zi)m\8:vT[dv7>imjۗJT_߹ Pr3\/\ۯi3]}pdc3??zZ(7h][=xW/}}{ZeE+HXc~o3{O0( Qp( $|J-n l0ZQuB96f6ڥpVd0PaR&ֵE^N$,qTsJ\Cbcvn6epVRP) :@i ھa#u[!IAUpy$#\ACY!37hi)E)OfF*xԪRta Q /tQ@#}"?ǝ)+:blhƇ;PjozD3Ѳ]93()5KFy%X0dO/6> }Fe?5;>#RS("^,-=0 n׮~ҏg 5smHfSMu1.e:l%*]7j ldžȉƆZem3]m7&zքOX=W &`EјnnS&p7S,\üh<lV]xy,0v,MjEZDr39Kbv `:g9` 酋*\b #BP&&= `OZ6|EpqӨ +PaQdm.iD4 Z>RZ1;F}6묞ZbDE%K%g3sZrV@Sټ)$4f cB2-tbrJn (>IwP9n@ wk^&("riE "Y)ҁPUV??1> #0KO.&HZoz fyFHT\Ǩ-f+#Cޝ7[gn2.|x{3\JDsjz3^&BH[ۻ`L\k(L[<JܺŃ{V6;K~o\gUM^|`hAhlikG++F}7ᗦ3\~s*|s?H6pȁ'rSNϟZzl܄. V͟;T +r+|zQί-}wҝ#ts3O1YX 0)*>iGm^r7~/=3wBxxXJsp3#B +PCBŔ5jٝ;r~ࣴDyI pմ_w36H&=A Vyi IuB bbr ^/+[S>BEѬzc'<+B +^4^щNT$"h%PݰdVV@Z.X z$4 3hLyjWKt֯(ٙ&pB%0/{چ:~aJ|D eDY !B +t$[TY˷Pe4x) zl$jP$IP-qIQrKa7"#l6;.u9٭/nHuaZk7cyMDK⼜0FHY6 LczGl=^VhUxj[lB S0.ί_l XA j~xJ.rTpփ>~&nq՚Q6kH>)y|; }!vȴT"&lx~ N.fv$L9\Jz`B&m^e!a,qVn96V + jaAct6txi RQIPRNI`A%WtV.;ɰ1|C3\ ࢏-tKMp)!IQO )'$o '` xt5isc؇v"T_P{h/"Uv=3ұ EiȄkڎ 6:A%HDxY5 }zlܸwl8 rL( +00@3#N200M 95r)Dr9Г̲T~by  X=F)شht-Y -1r\H;L++ȨXwP)IAqI1]չTucBh= Q #1 ⁇M;1fn2NU섒3R!:KQ\kÙTmUIxKc|:HE/,1#-(Ⱥ,0`\HV  +hjSnѶx?ot; HQ Ą=6꘶gw7ށȴuxHsR‡J^DyȑIȏ˄]ُS'Xl)D RfC3ǧmش<8=꙲ 4-toN9p'UqDO@'A- +fӆ3 YoM8(Q<{rTJJ\ܔ[ԱQ'19U Ƕ] J|i\)$0wΊQϰR\SZdh8?1@+C |' +W"X} nXtxP Ռl's)7(42!Dr!L\,mSN蹒l%_i0!oo3@1L +d*H阐 +LT3m8t`BJH.budvJGON =*OwSǯj.(2/VP\#S]^Ԙ<;is1L@i-lxQ +@H{-g1]8%$= hy]WEI*'Q'iAX,˛[t-!A| dxۯ .ȚQEMV8^ lϔ~"Uڳ|8˵P>y?&8 7NA9ȦFl.XTblwaY@A&P0ȝ"y#S>R C)Y !ȉ:GS:)HPxX G8Q +)!@Hi-("yGP &4O@tx"d\nmw,Ws~51\ܟ=;x­E#FTd|:Wόq\S芦*$| H1f8Y>srcYG&GI+ySciawSvg텣|e0-+ }u{o>Ջ;X aȋ:=J@ JQ\`|Bhbߊ/nV\yW{r|VD$ ?;b L8TNЭ L3йra7?zxaR3 0^/4:rz 4iO8it0DLj̑\*ϚD) HX z=UI{) +wZWڷyr÷nh{?᫏.l& v6M nڷP-+ep\:}t}w'~ӷ/\)"防q:D9N[<J>7g}oOok+G?x|kv+J`%M\|&O̕zo'{ԅ/_w޿}fsH0*t=sbc@L +a+F \ݗpk׮^|f,~G+>CaVq}k7>w޻?yٟOsϿzӏ/UuCV@28O?8O޾G/w.OѵϿyO?|)STHO)rQ)XcKeZk ~~ۿ?GO^/`7nV{IVB |6p<{~%wVKf?<:xɵߌqQ#vFbsc_?ٛ_zϿ·_rn$ p AOdərw/}߾|?;w{|~ūx9`Bl. EυA{a|b᭫^^]O_.kGɃwg?|kVK@)4/+R]߽>zy?}_<>?[[?xZ/ŽI' R*ԭ jᄚg?~On~_߻RPf"SIvJ{/~ާ~ٝ/+oko{SQeIc>`=$|#_^I<8yg߻~?K>?zuͫգH#IGC8Y1Yj6ڋ|73Ѭ֭_?o_~W~٭_?ŋO^v!{lC~XbBVEK1 ;+<OO_Ko`/ zX(2óo}/߻y_˗ݣmϗKd%=.B +AV^nO{ŭ ~Ͼ}飧;J2rXlXQL>Od+A&_m_}/~޻7ytqm܉z0.?EljIɨ䠤ک}h'7Wџz|=ڃlQaAT$TY:2_WU\j~w'/˯^?|W{E|#b[h^i%Iw㋳;7Δ߾'~ѝOopws\Q (C('3:Q0ij+=(.T|WNd\ix~6PX3ťRH% =Y]xSN,WB{fųG_/^j׉>{!) ԅɷ3Zbhx{|ͥ[.'S6|cH!,RT9i̝[n郾a_ݛZݜI6raStU٨x2\,uE21).6g*V[BtE@M+|&\߯2l+[]̓ᄚ+?x٣[yryՍ(( b jD6Ld>7߽'w>ҋW/ I- +zVMtP>y!\- +љbL̨l!"uv:<k۳R=!3EYčȨ0SP$ֳD!,%̤$& +S頊\*u0& =0n'.MsA9,"V+йLvVƒBd`t59nz!D%u|j|I(b eK'W^_ULQZrρI49 +iR12ұPڔ +(j'CRL*UXgUMioN4P 0'lȔ8H`\!0 RKqV(ݷC8iyD|Q@U5x8Lcx%i;zb#rRo<;96 b!U55= 4#e2 1Xe496:X79T}9/φuacxQ^AhD%^.{S '"-1 &VA,s٘>a8)# "[]ȉq'DIZ + ܞ >y/ؤh֕dK#&%'8$*qFUNuDQSLeSN<&"NIeɇ J8;ڡh #e=QAx3rONBsSg') ٵ҄p ǹ8@D=U"!ӓ )ʱ^2̆+\Ѩy]`N}"Z*n57n0z';YD,&;RF>.=nȏPaYm:"ĥAabwrC~fVX@;f%[P24WǦN[&Q/Y<7OzNZP?szaKJ 1POi7E1>7 +rzkuʐeNNMLCVG 1|e S^T\tAx"VJPWs^)ꥀ2gC^ipJ쨌)91IYYMӱ\海s.ʆԲRޣX.p2~:1e̾^m. +hC4'ax(* 0ϚM?T3&xi%*3ZZ}G)J/R Wc# \ -sg䈋 +ݤRPf(Z+XgɕҤ Bt܁^fKh*v |FU7e65B7= WK eb '7 0E!֟.(#^:SN,9]XdAs.sіM2:#ED>= {܆ t$/ú0S6 \)5+ԀNrI 3:x6=JwOJC ;˹;6y5߷h@`53aplNF|z,:$A +Bo#6Tgc3je_op 2Iu*I~h[zq(,'ƽ{A7ff}NEB +Y˩ˑ9e67"O2ѣ#ʨp62㝋Tzجd B< ,tR̫%`zX +j[tI'UR;q>)5DkSWaI2BKjU7fz)O{e谱9*Sq%8Ʉ_Eiq,\T| 7655@ArQ.FK/`ўL0Y6aBt$ ~15uJxȘۃ 7\Հl LoMy = I7O9*͚3bjni IEŜt$@~/pE 1ATÁ 4[bvfOHQpX)ج[n@bԕܼeRn93w|gId3L JU.h9&ޖr5&!JM&+jarvf“Qm.K ;c>̕@RQ/6ƛ;68Vz[wkJWO"_Z ` izbu;h.+>L7! 3ccj E/X""q)b2yW?6w/0UmΟfjRH]+{4}]2uFOލէyJBbTHkc{NLpU_\~MaC^iX?e'=K< +F^΍5z.|=~c)N~GΛ?{6^˪Q}>S^y)\0VlAme&?euob+M8@1iLӀ]Y5;LyOVvxY9K4j^l&JZhj o$`"7P댞JW[5`{Rn|+;`3HR/%&kwƗgtqfvkok{oa"WZ됰3v; Km} 8&o!5N޹vޞQmk~hksj>KJ>]o'/~Q[>E ōnV`N/)8gt7Pw29wIٿ=]IQsz{PkdjNjp_<-sK[VRަ7߿?ÿy;uF`#夎Ҽ*οp_6Uu|Y|*ٓW}3>Z,/qϞJ)ѳo{OP-ikWV(G9ly $ +ewΫ;/){ MWly5OsO˳wn~}W7?7Nx|bpR'ݓϿxlq:5hwit\7|e\ +صO 9Ϝɓœv_,j(-K)7y"Asy\kR.۸P:; <֧Ju:w:{Wݖ'7?͋>տU>4ssʡ|cw^iS @<yfitvůۓ=qh~×S* s;{Mm}NjwοB +eZo7_>y7Lqw+g0 ÕѿRt9`PkI9ՠ({ jϋm[J]ߋ9ЄPS=Ci$)$:dBFN?{[݃ "ʼ>79zcta} /ww77d>).^E(wR&{_8Pb ~* қ೥Iq{9eu+q 웿|o*h;m.n(X,ٽ}sR^]_hOw_/7Y x{^?zFi`JI/v^/Jl8|z%g +4]&6֝gaО-rBm-%%2qޞ޾s +Ff 6'fO64ZLq\{XYAͣ1D8V{qhr;%'|9ows3+I+9[٩.#4i,>=PLq*hnKr9#տv7O-|wGo>r**/`zq;}QFn@E0ڿ~cmvi^w^YGV=/nm,7Gw4QLd唪⏕,W;Gfmy ůO>48]}e6Yoʗ\`P͝WjuGGvG/ߺG1`~}ruH+u g84ÔL4 +1Lмp&3bJstπMV3bIgR}Q_y3<\tJ3TjdzZ."*ϛwBqQ]PDL%Y 7dY(9[T`*3けg vXi54W\~M Ʊj8θvix=vhw/b{yk7RGLeӛ JSBy.Yuriv"I (o^|˸}P깓o&44|+: Hٗ= U +>ndqHPpܭN{Ͽ+|Umkv 6,fOejVlYJXm w5PamrOߵ9Ϳ*={l^{Q8|O vr=xZyS<6ze~7EÜR/C[Dn{kAN j7Z=8Z׳ӷޏ E8[CiQv+Z/+=c|7Mw My. f5ϕڒLe`io^};+0agC׿92$;ׄ+HuDV2{y#)}N_p/[G_:Q5rlA;OX#8I%1Jv*"h*p _ {o~;<U,R21;2BZ9gf8ޫHiN(Puvck#W,V&7 nj]~|{qd[Ymݓ$Wȉ[1N}6/u0?|9 +V=n.^W&/f=Js3Y랜wTvL]fFAィ %w/ vugp\yC{vNwhNfA^lz=vCJ-BlF f򢘕Rer{ &S%HShV ,fOSҞ Z׺vXy[)igH;](k=޻H\y"j36겠V\%@_k uN;:y_mq()W3+$C"#p}`d@6_Xweu9 v. SlwRql'ԄʎP+rŪeoXkI!' i%ػ"1kl%3aV_XM8콌܋ʫSy*HYAZw)c$U  g?S^ @" Wwt;~¨Eٓ8f"B+/ޥ J#R7×+VvΩ800NexV==M |tTsv^pBNf쟿-Yܮ=Ͼ-FP"!8M2*eukVPn(-ĺۿTkm!kQ"MXpP'KSrc6hI^'SϽc Sgpgg+aDe?{n7÷Zh1ވum{TɈ\~?z۫w_~'R&ԝ< 4W2[''~58za0'( t/gl, (mH*ڙ( dIz3ka F,V¹ۙ<+z?#7aY wAme+5N5,1b`{fW^o?E΍ET[Gj uB@zg-%p'^yxU>Pm-Cn J 3,)=~,/FiKѐE~ C9v`;˭lj Bn8?~Ή9MQn-MoDkΜV%xϪN!SEh?v"M` +/+]J.r^?(gfu.8gʽFZ͔0@ꚭ3y$w{u*7 8g8]PJ@OjbOpwjEyn?G Fʈ:KsPf}Q lo8/|;gxI8˯z^w{B !_!Zї 5 (wVP:YB c"|I,ؽre'͕6"eIx@Njp 'ԣaq4ZgGɋkc6v19\٥ܹT=Rw淸B 5սπg63""6>c{Ng)ۦV7ÖtWygi[-Mӓqd<}fu/d~S? kqzWjn}w<8\9L,=LfHc@4lc YrU0`V;@|09[i?[I!yCPEj -f9HBHP[qԀC{ev%@IH;cN(ʙ=Q^iHuBoaFG38Ej|aG`Y 8{WJ&I F >WGac|ITS!U7SD2Yg*'P˨dfmzk/Bʽ*.^u?ʳi Ճo$0MҕaVBy3NLEmr;)xjzW %DjХ-8n* *{gB7j,jMbq9CK| A!JW2BM3^{GP]ppwn*IY2/zBe)KDy[?nekf+ҡis޽7^2RI%Wq;F=eL2ify`QԺry:*S4 aҎջ-M^1m9vq(Hu6a8W-K&Ǜi6Q(Hle`>NF(fi[[ned\|7"Ŕ07N֩W#yti FI/8={q%J(NgzFF⃤XP)Zz2Z6捫Gϡ!lRk-fOo'O {IsH(fo@|6IcEJɭskXWӸț S{fjM [Hv7`1* /;OZ/1DLi){xg_)/_bPQϊEun\n>޴AWyCD +hK˜M`Rڝӂ1(N^$K`1ʋŜzX`8sx _z?˸)&kيcR6r˘cƚz7ǖdX{fJ+DUc +ZyYN}e a"%XMѪh=׌)Qv;Š%U$JM%͡r#+ WBLDL%JQV85x;s]-D,B *,wqk^>qzW|ipEc_mv U^iMV6#"TXݪ*LAQjfGX9(M'͈~4c5AXy+0.<NoF};l5(F r\$˨1;ĝ2 D4QI3)=ҙQ"'7VdXN&x(j="^q54v"8A }ꙍ}Rv |J+XY#<>ӬˈIúC\aO[<@NqZ2AX S L맄@SWH,M0yZ8X#~ +ԇ@Ble4]{^ Cq1 QNh +vubq)J)ra8F4F +0RTq'-7W^DzlYVb|s})k 4ʰi.Vq}h4zA,m$fDm#BS{~3Vd*W+Bi_o!jAV%,jh`4bVy@l4+YZ~k9< +k|q'Xk 'F]PX+u(RLnBv=B>YMa\yy=XqĈ,%g5Qj> ?ơ:jڇ?W[dUw?VRAn2!R4A"| ++>FSI3y"wS.8UD"JR.*[(؄MEQ r; ބ/- = "czy"5 \*u [6[Jv.i cX3C Ts (*NRZy%70k;:TkZ(8NF$n/+\T`3b8{h|8' ɖQ)w|AIGi*P@xQA͜*@m eD[}?CAVh!z?Ɣ7Z<CU 32@@a+az҅3E\j]$j^~ίGp` +(DyM7+Qv=6rr?@Ҥͤ0LßqcNr7SfZUF,S!v +Ʋ3HkDB.H7,ɭ&HA8Q/p@W>QrO5 PAd{gqB 뀵>I 0a&PN I*yØC|q:ZDaZ7+PeS\QhCH,bB< EJ .7(pUZҺ[BmkYuZ=VÈ+zLZx$Jv@Eb^q@lJt;ޮ\c\9\OsNtaT_1a:.!>stream +>*Gy<_µK'Z<5T5JTL}3EB ;Õ 5.:}Ԑf*) fH3y;w &ǕpF)R>f-@ ⢟ 1$YrCH iR)״3X@I-0zItu4O Iu!UDlʙbybK@?R8f=`6ƔŘ\iAPzxj#ł__l,_ex?AZV"EY +6v^i^, R4z +*1N{ jBToAs(xa=# Bm-{:>jR#[)f1G^ol#$P-@0\iœ]}9Ox^( t.Gv<~LʹY— e2i.4%1;R"j81qTEe QJXeZ,'FsRpL\I _ +,[K㤁jUv*+J;2jQPtFik-HYv1 +Jr'k'$F'$q\@~H)rs! @mB0/_O`YrXF&&5BJ RHB3/6ӵfNMh'8̰5ZgTR Έn>B(T5v4\Hg[X5_d<|,z DnC RʻOV.w<}C2`FAlR(I@3ތu=*(킾C@LU;)'äSA2eLnr=N }\Y+kH0fr# +B SF690Kb@ ~AOXb( e15NV$I'A%kO?kq9KnAT9DdW|ӄ\+ܞ0ޒFQ0+;j 3 [ ~*9 Dblq8}UX`)>UtоtW2'4یJ16tҜZ)֡ݻUri5I9yA5̒ƈpNԟ>L%q>嵴 aItA`J6uYOkv&vo7ٴ3s`v0 %w(Vjei4aYגjRIuT_ry38[N + ze$xQGF\^AFmHPU'nN`!!SLjd}q>f|`ѡe:Hd&(9o WF!d ,XP;UB-Ϸg+ɵPȀ@ލٺE$1Jk=L`=x$MY:_0LZ۸FY=ʞ1+ 5ƥֹe1}Ald+x +-fJCivأG9O1pr0I$8vFIe_/| .袭tNV +2 M 0oH,Sd3c)hsEHA^cIB.֓!2; ]j\|3x OmBEPڗFW\&pJH32'HZ'ӫw4%_!JfpGO˷I:yJYkia-J{s3yU0W#8%9?#ioTI峚!-\@Rnfe`4x^@*X^;BevwT D`S~(Z&#l$$qPjr ,.gAeaVe8*qzS8MΙbJ3Fl4'Ko9.B1*ժ3otIgarRƱ;xF)k= ebme?+M_ ~[RZ|dJ2 $'9%VPȺl\qD> H(+Q2Wd1s02h{LPڟПBc d@aYOBXHGjZawվb! ρ707 +%%W.B4Ȅ<[{^]nfMx A0--6ѽkh/2ށ7DiVWVNJPNpBHj)3胗yU1mSFҁU\#7z9~;~;AN,qɏZ('׈s|-Fl j5Vrӄ>\9U}㋋E:;=:T)!UoE"ΙJA1nٳm6C٢7Quwj/ IH}֝z:'Alx U`NST)[kQ,MFmG WnYIeJ_pœ$\ #Mpc%`үB(F`ӴXmQFf_ˍK8W%j+v'oʌ*y_<ɫ=((^CٳZI"JP}&P,kIril#ڄvv;L +b#) Tڔq$o7@4`c}<XN +#`Ӏ4]*͔"dHPB%qY[bJ+ݪjAަJNH@RLPZ0!07r(#Ayz7FaܹQ#x}8B٧'IQ6*6qzp&1^ψ),*h W֍7zD5$ JmE)g-Dp-7UOj0 @R*68+[YxyAˌYI !(T;?(' xbrFK,pGX͂Ԁ,FNEkK4BBq;chLD)7J +ZKCgh$p3rm{G}˴cW43 +_ b@8B;+϶ϰo' Sʛ  +@W( { .Ebb7/vR/fV -X񜙥ꬵhQ|p>Wsr3#׷"26ʙ!J3 +M^gY)ʐktF[0k%gBy-)Xi^md%FPAX)ҕz熰&[(mx<}=.0@ie%n{I*G(^If\k]1"rZN!ԮT\$sI*EI\(-C:.fވED;Fz`XG?/z?q]ܵq]ܵq]ܵq]ܵq]ܵq]ܵq]ܵq]ܵq]ܵq]ܵq]ܵq]ܵq]ܵq]ܵq]ܵq]ܵq]ܵq]ܵq]ܵq]ܵq]ܵq]ܵq]ܵq]ܵq]ܵq]?a'2 qw({U6X5ׁ{GG{x,dz +?Jٕ7-WBxҊ}8vAo9^SqJj%Ջb$3H:F$_)lzAJ1UpٕƇ# [gt꣪ercT+~$(?'ui]Ykk]Di)7a4裑fKY LzƔ3BAAg.n" ch4'"nthwFsgv +*1潥napg;j^n#J//|u%-|(+' 2O:$i+'6)+VOj'di/WäbyW^c?P3OfFc6lURQJ9bҌBmԊNFeyYbkzL,&je zw o$\nz?yc+-1f>1IبLD8GQ+ZQ)ݼˊ\MK[9-9I"؂vs=Ìp7 T1Y0iXM 69խ4@(ӭj xy2L-M㸻arb=Q"S6RjcNofzAhcjW;޹϶s|,ڀ-ɡ$|f`IU0JA5)IAGk$HU6ȳ%lnٍ[.1c9eA/oRKSuʖw ֱ`ʋ$HzXI(酃zѶ v!ّb+Yō5hK$U㔗⪔=UWmUøJvl>)]DjM-_FV^;zos0Tf2YI7) +:`,J\A[X +1+q`k)yPNnA킾]жA3HAn7VZd(*-A"]=*{W0B~nd@Am%L(mb ,WHP=YIŸmf!31#Zq#`372h +5| 2 a$p{-ly0b&Yg*y}P䕇0 Q*b@#Th彛;|'"5,. Zw+|("'Y1;B 2zYC`5 6 J1q)ϳl)MICkard,]yDY[>K9MS\q)^ /R%I'j+qr=AZs|;E9.>}+')'/`|y<[ʛX;'igHzcܛdόim|5:LpkZYe޶}j[K k)1ABRT2y=!F&vҥä௦XgҞoդIʩEu)3cV#ZXuFaRs%BBR? a+aA[%NPeڻ9ȯ%f#rgod͌NIhǃRuH-D&?/҃C4F ȇhAϐ$|6zdC/(A(b:M)rHkx C+9!)j](YƗεѻ5z77/NfE$Hru\JHܹ/^$T+]8]OB8V ]]Oˌ>ĵOj\%Xe/Qu+(`i'7b$nPVfH0 +ܷD ʫgO&DAj$iXMspx1-H [i g>V{0q_ib-AΩ@n4R#LΙf1IIQ%+Wʲ,ʶeYݽU=VC 3 sdQ"Ӥ<-͝SefKh;@v\ HSHW@M:A{b +hΡB'<ROUE-2>`6<_HP]P!:ODlYo'#BJ% ,낐|I22qEŒ7i3 w#݂{6ңf +eCݰv&{Nh[rNY;fPfv,R9Rn:7BeD@Jhk F!BppE' 1[EeѡPr&tU6 aʨqTLx@ ` LjjP`f厱XJ2QRM:F6"QE' 31EG!bI.q$=̞=CiX+q ^aH*3l"mSy#Џ; St3zw4Uкsg# qjH37. ) NOZhF4vLA(S,ܸZVolJuTgF$'@ PfJmcL!kB9hrKPO2&,?h*3 N)74D[Q&whUO`%b~T9p3I vd|d04iX_g@^ǫԕWx,wR ; 80<+V\Vc} dJO8x41 6XINO!<,]씝Q6ѣ.&ܬݟ1YP1`I'l+lʛ&"d2E\RCŦw)ZQ+=ED<^ۓۧb6<iXo9B{1GJG:sǍ 6S6P:΁VS Sn &*I@LW/1_H5nBYcrcF0a"Y +\}l#6gL@L,) 3fphqwێܼ18#h!W?loQDq3 V!Fr|ȄqJpzN_Ujt.eObVoT|&KN!(zNC60 0(:aֺ'Lf.j7PQ %7PCZ 1D-HӀ_Untp: jQq6@N7D2P'#a(%n=9%U<쾈'̔bd[%;vA;80p ifRcFzmms #SnpOOA/O pudnu1NӇ\&N&@b}rhl0d@G8"T ‚oڱ/O;0 %q/!Ux&\,8d0cQ/$ggfv£ h &ThW,,;Es;  +#A'̀);tƉ;N4ևt^ B5SNNDgPͭ:07 Dɝ)wDr0P13r*?Z  pUzH5FO@MhhV; 5ߧkQ#`kDLhosrvGq!eL6ؠm8$A/iĢuQvڨ `tIPa 1Ԉ +)TCp`1˔0:El'{4Q*9"8ObHud1`F8aeS6$h?V- 9,4Z.&?f$2HN<[A +Dm%#}XrjάcͲi\RP6CCf(Q7h HDA@wHP=M_GexD Vkp:;񪌤:a ]hԈ!Ae݊dx)f@H'o6c1;7 oND[|q0Sm'u{*|l`g2nHy }@#cxFV,qA4xlMQ#8l <#@V?• qBdB#ɒnZ+ݢk&DrC8U"txҌw²-I,t(@ĸ* a<'[*e:a|jȍy*VxGДgD đ)IDetv?b t!mT ` K͍#d„tCc&8PZ %D蟆&rD=Ӣc:|LG@; d G. t⍁# +jEJu3; =Sj@܋+',mcV2(o\ +'Pv0/jHeXĢMor%)x(g,[xq-_oꠕӗ6CHE@7y#J vTmV:;֓CzH/B@-T+f*IId/栳v:g&2V2:6ix7q0%%hIhRV#Ar5 ,mDdh) qL:.!V+®H,q( VA`ߢA"Mՠ:gPi1\jvJZ+(yhuH# +$*$ +]cA#(ZqW Qa;jl'*nʐvDXS;\g:!;l|H+ +Yx匕 SV'jQ:r*I1A%C#PNDo^„ +tI7e Vfcƽb]2dR=w eO?g3|nI(Oġ6"Fm tnH!ٌW: ¥C%)BdO]@L`LBt6=@m,xdP§H P4"X#U*4 +Wل{e =jĢL.5>&UV?(`:x>TGH˳源}J+G e2\ $b=xCMxw*U>¦>l3Mv]W +R ]eeu`'c +7N~DgJDyZ8*zU.>nxlLG[a:rA +JBv6TYrTCDp +47)Dxq;-M_K$\v.؈wXBf܌P}lyj)\*rIA2>;)זυKth$lnX4QMb-c6\f$(Tfdt07[[:G&{*ehGYm\,@ XHbTչT+P46¢'\s)m-a2d˶39+7%#MR>PX6vBPu\TqYT"]21oAuf% lr6X^IvۻX)`snvLnL$b[Y8V]:9,(cr.\XI -<[ba)?uvA)d{:/jwCHk'uKU#&`&0nYZڻllG+;DOMy:5$a7rs V:3f"@3LFRy͋ܙX(v 7oo˕ElTls`c?;M%re йHD߿z%~@%Fzub{r.\Ǧcٙbqafqgl#fm!w?-dxI$fNg3ZuTЉz?klOE[P tZo$H/GSH!2IRkxw??Q[<x\҉[Hvӡ'PtABT @gx(aqhi&;o +N Y(-zr b;A]҆w YMtXSnl 2r<5(/] N; o @Edg|[il~p|qXdPuFzT,fO٤'H&&m7Kvv[{wv.'&gBeZEf=iР˟{`bnZ*-۱>'k3dpNȭqhXg߽H*d>).^􏭝wxnoo_nm^Z<ܾ=vtcߎwvB6TGa"3ՋkŹ㽍N݋Յx8_,._<ȧ ٘8E҃Ba0l2i>;L0'k+Wb}?EˡrtdmesSb#t%Vf.}Ԓ`s +'ӽrk[ oQ(Q(TjhXI C"h9Kґr,[ n%\-l2gS3`<,N8Z +Jgn߆P`~~7<WZizƃ߸!bzwOeN5n܃W{E(UN#VGOW?]>ӯ{Pcn0{;Z:lӞ=[;GjT\bnQn/͜xhSs;{pv-PZd}.3#Vg?88HmCZ=kr Vƕl1R*.qr> +zffl<8~˧XX=7@M CX +Vt,\k;ǮWW/`WUzMX\g ^ {5w@(w]~pfidnC7/m]x' gxP6Nus&xgaR ;XھmHbtr.V{~a ځgo癥WMDʉI{.3/ U!39na +ޱʥ6S|nX<57c٣vs$fL 3}"c3\wkf_w.X@Y\|}zK, T_)-MtgξOX6ؾv}s{'݀7MLhebn gu AfN,] ʕc$]O!&LSl-@MD7\^-/ xYXFl*TVILF;zUy,TԶhPXsw>I潁bnlz\nBe=L~X]L5nQ!!&;ե.<*xg;&_ՠpEr*\-5D*8jDhgd'siP6L&g`5AĤt:_[:5wpO'q24?Ցk[A~d{™",f[[8pwzf܌|!.3p3n:T]2ϭVY:..":r}%ϟMNQ9Fr=DTLv '3r*D* |n!xɧwO N:ED9(pN`B??m2;Y:uw^} 7?١|C`eS?noB*/_ۻwvz{\nl<քZwR(.HVu],2XXMv¹څ8ʛ +6:ZfN (m#wcͭHy9VZdf`js'SLf*$:n^e=3! 6=S?[? Hىы{ )6}\(N<ݾox鮜+4%ױϸXToTAd8PހjmL57rAv/ѱrI-WT(^ꯝyh#i6s0I2'4n K8Re.|m]H`MtԴ gǺ6JuDj"d)>uO8Q#T]O,-_n] +h\;u#^uds~{q\IΏg#BҚ?9Opf*  +gB@~:u7ܡ $:\Je:֢c ݍ+&O Yn݁Ef<`D7*.*&40q ¸̤\P +qHQGehU}gd$;wpi s;CRu C ӛ@OĪˍųK>[N>뙪fF};R_x7h1_l;\5`!Bjވ/PQ!y Յ3N~z9V_غxCԂ h"V*O+DFWbPnѺ%"\qjͥ{ޱ7qBtN'!åg H d̘9TU4PD7X+2\7n:M^цEJvjL +Y2rxgKsgZWS}/8e'amDL+њ?T)T,He6PxlCvok"tdҢJ)= b+M/ u`W6x}Gcf< ɋ˫,,(Jͅ#X.) ^)29$ !3¢nri4Rq7gcdgI@ +eLkK6,Tdu8..qIvc*jZ@}~n2Z2`J35bQ@xc&b#>@Hڅ11;uq^q d,,R͎EmL0A R},1Ci׸&V޹V^,B1[H;#{E_8OD*DO.l)"3tNX$ N^e56TN^[ZKC+gԔLVVqZeB&B~a~-%냣-:@I[|Fh1iK.rZ1{# 'F b8h-px~$S fj'$Q!IsgUxk^(vB+\NJem+>XuRn!ɦݰh^aDk3 ,]i @\t!LM̐4q"i;NY("D|H:sQ_o-B\"h\ޛ<=Wz꾧+oß~׿_/xpGmMe3LXlv7vO=O]SglSwx~ͷή_vHdßnc:ssn灻}o|Ǐ]}מ}_;o?xo>ta=T(nŊ]6͹3㵅^ک;xGݷj-žnɆ=t"^˷O~;⽏zʃӹ +,.Zc,*Y}A[@\Z, c96wۥsokO+[_5ƍɅr˩ڮ!h,+0&D́$&Ʊ'|`⍋>v/l\9W=Ncz;[+['N~Gx7}O>/_}wfZɤɶ'3fwn‰]cϼ={7?7{c}cZ}h"*Jk~uŋ>'{^;?׿{?ݏ__翺7jGC>&JKdҚYއƱSȳ|7돾o|}>/Ǿ;HPt{I]@P.; ~7{ƿpϿ轏ˏO֛ 7Ԁ +ׂŹ`n_[<9u_}'}۟_}_ _|+?L6V.nBr\ BodjWGo_}ǿ~Gw>w?O?o>N~#Q9;&A,){{'n|>[?>㝟ǿO?ϟ}]?UtvIlĔ'IZLSbg1hήmx7O>/>/k߽SzHJO&A+'N]t#~}?}g_}╫K[{Z/T+LP$^6wO^{zޯ?ßw~?L盯~:{k[*m>Zls.UNK;k{Wη?? >׿/xG?C[ÅiV.3<Lӳ+;^?}~+y卷~|w>٧}=Re($;ϟ%hXwvw#o8~^?//?/Ͽ֙+Bp)+> {|;1X?u'Ƌ/?//?×_~/>SIY`6ƌ<Q냭'|g^z׾?/?O??~ГOro2M2Fq!^ jLkq{{}_w7_u}|{_xV76KJs? }7o/~~G=gou2pTRuzbk};]:{|(D^{'&謸ΊhXh3ݙэg^q}\pꅻ=vҪ,J0?V{X{ X; gw{{>䳏y񅓗.tx!')1)`0|>O?oۯ/S_ve yؘMX!`Z;iqQ~8lnW_~շzow7ӽ\&ycpQa'a|_]ݺxۙ?=7_~ ϕ5ƹQǵȄ!9^K3ˋGvr]׿/7_xg啗{;)P.bVQ\L*RX2s>7}_z?{?7|k=Ϟ?՞KURrh +|ي +F|}{蕫׾kJO< ?O{vkzBg^Io ^Cx%Q73+{^Ab^Έ0V68#czu$qx/ˆJ0^p 㵣80F<4iÍ.aN:v:Ca\`oB R1 Φ ron~久h6Z;6ij Q`. :.$:H +r$ +9eB,D*NWeIZŬ_UY n(78 +gf1_LxL^tjRӟ0HBL j-ڄN:J9b*[/*uxnLv1<6UI|+ǘ)d1p{Y8#\-K $y)5ʟbhc8 @9NHEhj6X*l],C(E1:1"FnSsj Nټa4#<2IT*]H2\M)^ r%h3& R(7ڷ :H,*5bAx@pi/8e\D؊LOGIυq>Htpr(V&T1%ɤ & GL^I!Y< 0 "+Vvs6$b}-k?YuH)v닱EWXۈә+K AMK~ylBb!R!DvpRl۬ɤRXpGoz·yo,BZTĒ]^wZ;Q'zƹ|RZabpB!cZS/KMWԛ0*8k="zY)Z'1/0Y#0rO6IBx&B8}crsd8B\Qv1Cԅ4k8qI ,Xxp}a3Jx0X 1rIFR*F([+sOj;' &bGd_B|얗$0 9Im\2g⬱p^+QƼA+^ڭ `Øi䷢= /F!PT[je?SCT)Q`n-(JejSBͯ^T"4eR*k"V lڻO +B&&4e&OF.r]K fFq.}1p=Q ѥ;פZAXb26 rH>}}6YcaTQcvJjpCD;~ˇ-GhTqTurs47Cq. JnhV6 uɍ&iPW_e4JUg,MΧ~<5@|I*-*dZ;/ DR1_pTY7cXCyJ+ H{LvIZƜP8GWp{rJt%x)P(aR] +PGo7sbbHUL}\m_]FBxcܕ9J ,¢2C(vm]*o@\JJ}: $e;?;}CDt|V Y C +Cl!bl}^FwɣTQ7{Ynt_^)"3WcH0 =Lۤ1jlzM!\$**bS۲.rB> 16"Hj zǬQTk3XaTȴ7-GfIZZiˌR05rW: V#fN0='LU0켈[A2Œ2|׼X ++T9BC\pYC17aӐ=Ls,z#;AHp9 +%$Vr3?$Cr fsޤ7.Z&)`NWRf''ܜ_ r"*1f/EAxj}O+lfaRS-m0K! +Pe֋O/df}RB#."UKUwKsHieb.ZQ$! +9m6/cTኂ. Nf}[jFqę q;yW-.=L7N=K43U:*'Z01T{T] !ϥ|nrq?zO(O[J=YJ!8?oh;fiҾ Po6!&8 ` @ȍK ws>T +d0Ja2ݧ2} j%LHCOt_qιAWwd(EѥwRzlnBe1!  !P{z~8\?'N@L\{Cqropr)D3z7w߮3…I96ӊ`R\Fզ5Eb<[g+HdTr:ʵ(k.ZL-ǹ\(jKW'q? F$ $ rje[FKFiq{${}qEg&xEBk KYׯ*W)(5W>lD8Q&( EO4Zqi0uّwq{<~? ם]y;ݭ +\ +%7:p +2Uw%eNlw'bL8&w;^t+U,0ٳǓ/;g-p,*t1IoFe=Uf{q);⼭Ʒ?y{F[Ro;0YLIw`7*3#߬[ZW'bԃgHY@d;s''ŵzLH%/^"ʙ ARןV rD\|ӅDO4=_9x]?Lsy%i"*P+[;o% jb_pAR@g 86&ZF~au7 +4ڞ>PSw\9:zArD%R r 3 Qޙgi8=8#n4q#Vwv?4w\ +JywP 5cWff_\ /ls%6#q"&Be3?{_t(}?埵#161!gDb, +-^Xŕy?YCsav/ҝ3FH[1Ҿ>sjG Q!+;݈m6'M:#D"JsTv4{(<.d/\T𚵫5SVvsra'[Or|s?[ߗ_wpչ 'T SgptCRmirg#q;U^' +e~tzL ju6ܼ/V6\qQª:зmvLgXÅ GUL,BH)2O<)HWbNqs/cc%')\Q{cPn4"Lf>D ɌW/wo/%4hƄBʸ9|5(U)VG#:n$.4*TWbRQtpk>pc*ø?0byʌ"s,"՛~OL!\7[d' > b`v_4{ 3;o\ l Z /RRUsƳ+ x9❡a}r0N*Rq脙Yw2lg=*=|5RV MWBaj+T.mVP~ј% B +ݽy_}ezzՏta3DV봱|t6!~\"VTCvY0bcb~" r3A Y_מZǣLշ+o g<:w`6F:L稽sy;"WOD\7Znd>ȮDBrB13n,Hie!x"U3VI7|^~ZWPvN*\s#QOU(t7J'g[帴P Q#'xvQ.ԚLv8>ys8#|/&biCm)ۈZCy9 BL1 zOwP;~e!pc9ru)2 g&P2_e_\T6IeA*QLJ6k(mI;HH Z k Q*K By1Hv( Kaɶeg`$kTL٨<_|):C9>ֶxRBV]l˘ݕpꊻm4zølT!re4N6 D5Ww\r<1n6] .7kե2}RlUw'q3~`TeꜻŒCfㄳye9 +sxάM&c%Td*7pk 7eHL9 | q1r_X+w.t +軱|,ԺYBƀP  e5ps8sLjR\^  -]ؽB>LG"%贙$htM4,GA[WMW|j;.%fwhG1{|fL:U M^m|G__ڣ\twg7NbY%d'>r 9JIF0#6:gAT c)wc &eL,TPe%?NΞ|]ؙ.vY]9J O\6 Jf.F]Q)D\zA-poM/\v94{i7m2:onqE0HFa#J)EȦ`1jiAH7,efﴺz+}^X}V o~w~mC,g!@>H.Kו–9_`@\qq `**/FT_Pp9hC!bLBJ͎L_n'zkl;{j+nsWR~Rb aU@CbsfJYFZ?Պpl 78;dv5!U\o8̇H*bRzV\kިZ(T'DOMWBtE09ʻg Lvk&4;FsyYv/e-)2}Y;X-͞Ahyc⢟Ya+;V^.ŹiF|˲~{K;=/C$7yQjmϭ$< +>A.G)k)@V8q:)Xm%Եhhy>8fq)v !ňX1!f]8#|Ba"}t{ONC0Q^G-/%Rk,;F +ٜ=:Gs>3ZHq|X%3+ ),_R2ל'=cٹ7 eVFO.FE[O}}ޣHJRYȣ uc9A0 x)*,G "*YϾ^9q잖&lmi >}@ pQ+%[[H *MjMa +T2b˕^0B% d4ܺ4>?^wHWוdUkQ\ȇIUT6@CQ 03R35A|I&U77v-֨nv7.hgP\Ry'kG/+`v\Xtu7?7A q΃ۓ&LWLݡpӋD4T'3XZ8-WJQx$_%=aAGn |ĩoIl>޽`P̙=\甔KbƓAb 0Z;UDŒ+Dst Ȝ?{E?}RrŗC$zB)!R4ڐzLvZMN>:F't[CJ9-1!B2eL'*ڋ{Kkn~t[nF) /t1 ? +~QUJGIى]_?~_ɳ/3㏏A[s(g8U9)=2pĴ(vSl/u^b(Ǜ-ř.*U|I:Ԝ~qK@S.CScbf!D 1t%۟^]_H +Efp)AoPjR.r-5ÕRGXO "겟"ƴ(2|q"^;Tyn*P(('gѼ a#T g;o;|Ug\*OG*ӧ_h]0R!k;&x*BBzMmǙ301 5dsM4Zp>7o=t˽mT1FI=P&P"|w^sm1JJ1*apƽYZ8}ޚ%9}Lb|ު]ab%HZA(CIuOCt?RuaZ0D˿[H›>=aa`#Z4)ደ1LKjV1!MZ-?ZJb0q%N1.[OG$4\~5wػů~pvlmzgB4g_ōk ^E? +P=Bu|VJ7RՉnl]'GIh66 |v-oFSv3 o0Ǐt:.T[Iq'b\B]b1Fl{~!9=SZ{}1={s={bq-f)æ`,]ׁn&wg{|l ԛHRֻ !v)L>B͞>϶m<s}^ j{z۾Ϧ[~"y +jlc +lDt8.#T@oKBӍ=xg*7#"|>LېFyrI^ޚuqfqPF|1e'\wY5͈VS4Ɲ[w~w_q.#-B*I#ٔ+qQBA/'DŒz}a!M(_nzuG^_BqSbUʭfȃV{gp|݇_uOĤK:;@Bh Z9.noiB?"1gFP*Zeff0iƙ,pt}^l|?uRZqf}R ;zŕX3!&@jDVc>y:>zbMn54䲭Wg3RM0 @ڇN0@hױqb>5Oԝ`>V^a|?:Nup{h00ZZcK)MnGi+kmNSGK ז+y7XZp&ln*|n5?_VLv^~Cs?i!l*.}O tGTͫN:ؼq󣗿<|W;TS?iRjixA*h1\}1xUO{]H1.IH}ܪVފ0}ak`jw_1 &7YKd{dڧQ10BUe+) NW,-nO\̶?f XZB"؉ٍt]]|]PD*md:9յJRhԍkpJb'׼7,y{v4[\~ɎT04dŇCaW. lf'?Url{ sӍzfO + !*gg^]<|/v0 A\,Rhӗ7c~}":$;cZLaug ɝR(- Rr4:ilܯ]{qw$g'Q6 ZV`hJ;{ 1 +/l;EVS{Vv{O*`t 1n~?R-m_g7"(lTřvKKD(Fǃ{ID=p: C03 wC̨\m +ΚV + v:tBj4kQTR@H7{O^0=`3%o>G/REoRZ+Ԃ n6\N.Tis%5M}Q)BfI2݇w,o)fKn" Z ,c4P}{ꇝ_{GriH9kG/l#.ZtKm +JB6iTmaʶj[ȵhRٞFv$Zr͍ggVu#bB(ŷlYkRaޮn<-NPrٛ_s@0ǯ`tte_v^Q\1dsˋGT{z0:_2aŒY463{6gT/?嫯QZinv+~?ݺ;/(GuPJ/ox-D [ +(ugpRV<iKnlQԤ:d(,ƥɝ0nm>=/ظ_zW}&?rkWzumśF-zc|2 _Qjgwyi <8{ FY1( + +6Wjޏ}/$dNe{Tn=&'6Ճm r韮^|9e{[Ϫ~7}.8 ͓qV$lD)өq cpJ?rcA<Lί7*q1<12r@N_;]9 BS'J<8)3 WuEۖ0hItdks޸o~My}iOP`yRkD'쩅05eyV_B%p#YSX/xF%rsmĹ+1f΋#)hba'^cfU2)-;U s &ʦ*/^.xZ>i50mޓT}ID^ Q\2@+OU7'nݽ̓{#͚_뿞1~&j*vom7bsnXARnLUiGO|}msiUs=8<<}G?԰69{o{/.mvr\q>"UK„2tf lFh}%F7/V + >=>R!>HHCHDIć". ?ĥ eg l!L02aO)Ѯ 2lMwdUjU-;I~TeO cJN'OZۗFcUkVih$)7܈T\KΖ+!.7sk V1i ͠?Ư-0 `'lp;4>nm=(KU7t*.c:fNϴݓ. @Hw}rS +Ă?!A{@ I1mW]3>x}r׫GO[yetFi\?BL^[DMB7ߘ>2R]aw.udy^~U6- n?}v7???}W4{^׷R\K%h&%3=ͦLRM83ѳ_1괴␶Rӄ/xg5T$hk|ܜ%I^f+H}V|$քzօ&!\Ĥ cTt˴|1 د7F.ӏR/&DAM(ar R:ʕP:8I%#b%䒚1f(ldn,II6Eθ,Byr aOB~cVNǥiJlsʘU6R\knҩ`:r9 Z3]T7] )AB%9wR "AeX6m5ӻ@0V(G/FmF srvFi+EW +6i"(#F[lՉ +l rw8z=i{_wz|/X;/>7wF/ +I)?ߏ_ak3[)*Av[۸zxqU|~=^>muI>~JBv#z/Z1}] wWO?@-^L(0鎐.t;IJ~5p-b\S+Jq;xi<4Oz"Ds3f+NLVCqrkAd0*kBxQy,BPpEE 0伟Zsn+edO]A&+ƮZې3cjq%玳 !ML 7\/Xlm!BKkea|6Za8 +ݱ=snbK +XXajc<932eIy} mY+."'ل2VU # +݅!r"%' .e0R\.6VyeNwkOBWMnu`t| 04ܺso`$UMN/)USik8g#IZNGw|2z`ޗZ=̬o§>xm{pLuο}??ymrh_o|&S AN*dG[;/oCs`Ɵ~\ATn 1opo<: b  W.w.{_*9\AV"b+QZ9_FoPH]~'o\xշYh鵭 3[fAGZIF9t؄\Djhį?&+َީ<޾f̓7V̝cQII5!jٜ]]C +jJĕeHD6[Lu %IK0'+SSBQQޣ{o'/خ):)]gJ&ED#-(BB9B.T2`j^`awrTifwYeN&djYLe]ARe`HpDPWKVuMI#jqȪm=> +<Wyo +F5z08I?0=LؘTp̙p*M˜`JfOaHLFGa w Ӿ(D }Je?"8tk#L(&*KV6T>cx'Q 4r58\&fSO"YFI#JW}\.lE$!Xf8c"Ԃ+fn,Vo'hlWiB1%,BrN +J;.t.~:<};|BU6 >R4.ٜU3#4ԂbDVUH p;DO(ΊJ +#)V2jcʪ8;JY?~tl U^}U?J8&b4T SƌJ0& +2j!tݬx8kEq=P~Ø!r $gz{AkT:7e8}0BU̶0mDeo"$-i+KQwT*!2b&Qya20PcFq.(_ ʤV|H*ʕʊcZ41ށC +'EfPE9-Eq +oEq4R>J( Fw%@|hً%#bph#TQ.;U#<)哜䲄@.y +aOisѓX&#I=Ig|5eRỶ_-%aOeQF[$,T]S``jkRЁC̹C1<„șZo3XSsm1 +!8OHYѝjuzg.H.Ȓ'!Px3_Ң <Ң^ғ0fQuΛS&IʼnVa{P;`J@ %MW銺# 4%cp$bq +pnH QNH$]Bŀ2_nqLbG&{cQ(Ծ/B +}hf7&%RYlɶKD;v&c;ɝIf<3sϹs_9uxI,}-d*Jjq:B0f.|a $f.!7sxCFpx^g|s/@ar1/<0v U-r)'V`\`aދ h8&y3gyviL +9!ntEP(5yҹ ˋFEGxz>B!iԌc~~;u8c(z9N.3=;f?-y84 D!jqq]=S 7D#Y/kӞ o*6BbN"WZ Q:AId:el;omn>xjo|q)pawaލSq + GTU.Ϣ&eŒyp~jS O$B2<N祄Ti5 س[dˍboE9=q8Ss/L9]Q)d/.Fa^DPJkedލqUԡw*rF*\L%?2!H4KQ!5B*r2GГ ʊL1QnWU$QTD?"xC\(&^s|I[>^k.폍drv1G̞vzI3 $NkJBUQCBC!E!0ou?sfssGy܅3ggn#]/DJR@4%d=ș`qx@cռҵ֛)$Z;Y--j=`Tb9'y̛VqP[Ή( gRT$֗tG/k `yQj|WMWZNY[->}xw߿Oӯ}dkXFP>3<Kl2cus I& N_(X+퍝o~xؒ^xb8gLQJ*r.Gdi^WojiB>N6&LeU0mb5r)1aVS/ /߼W>[Vڌ@q0@qRPgwz8J㝇|Go^Ͽ˟/7UQQ<E(fr- _77Nqgcޭw|r՗^v|Yoi`00=9'zn&0N9N-{}>$ 41VbT*)2%hX/ y,j +2Jt{胷ok/O77nmmF zxe H?sv}ӼuX_7^xO/_Q9\+Q2NHackkӫ_ދ<\խ}G?_~/?yl֎ƸPʘJ-/ntJ _ѭ<޳ǃJW_;ͯ?xÃUEQqjً~E,(1u뜯SRFm Zpzɕ^޻ϿkUku:<|ʥ![ab)m++z+꫷?_Ɠ~w~w~'9 }3À$5XD?8(o/wxw~w褾^XZ6,2 t|&-+ZO7__gw?yz?^I0r)Q_4"a][=63On ?޸ϿCLclY/$~kq/l/'?'Gۭhծ6풥t2^p=+?7~?/OIjWJ!3477=\2?.Kw7Z?ɟ=_Go;~k7n'*%cX,:$f~CkV~tߺ=~~/>{N߼?Kk*<9mVrz LBZbjQm8%쥞ܮo/>{g{?w=W!!IB4iYF6^=m}߿o_~ןo|KT!p" VPB"ak_|'?o4~Z~JSJ$dJH@'mڇkՃAv[wF<~d9yoׁ֡89CY1Qt)/Լm63'۷?/??O7K[ͪ<#m9X!H@#C ߪ}7_Z{?}ƵqWzP5` h|zyy:olW^蕃}흇/ Otu/8(ʯFn@qe{V7G]\کsW2nj&0&'Z"hɠ1&7)F֥QyPKN25 !P01. +xpXn3]]Ͻp)KO_o+/ow憩$8SP&P)gFT1ml ~}պO?}yAsI*T{(gPFVFW,!2/Y> +O֪[eSCQ`g]\lz 2Sx8Ģ1K +Tm3HgUlJUhJ>$H\ty= CagB:_RF5ygSV +5me Y#T bɩYD!mErNs*\߾^:&CS($jy8q<|B'rVFΒs+𢚈Ri'⏫tE$Zwyl  @45C`"љdeר_¤Km*qP\=7 gl"!5V-,gDZ +KQKn³KRy;p%~^e$(fQ Qc͖T׮;pمJq(! 09Z)?5K:1n)c*H/-MnKOv,@Y!@#!7R=6CZq)TDy1;a.V>U9OT^Mꎐ]!Jm>x16&iq!lJD-7C|梗p"J\3,'M9լ Nky I!5' +Piw\ A҇ʌVRXwxO&5| lŴnLqSk~L''>Yd;ezDF)'mWqҤ”PJhM.DabD71,]#?pQɐ נ;&˹'?W#R܈':;kɲls1ߊ_*|n’NTc~" cYԲNQH6(պlwee7ׯLcar)YO.-%XfU2هr8=vbb 0ޤ!^ml] %P`a"0cmSaP,fQ܋&@6^\.9/@r|%MsEȮZk:B6yIC Ƥ0љΉݾ ^k&i-PfW +|* yD8Ojl)u'Xʯ_y]^ 2QfFѿN{YkѤ(itt_1(IWNjT~/.> difV6^Hܠkҝ#'k嗚;WG'opqH(k-Bi'Wk/&Z'bӠۄՙKa꼽v:mbymv^(bP&S!&I{ÁMnvS2+{11DT+!3Luљ <UX2.8ؼ7䧜 +V< #MmG/oVGJ3 q3_?*x#?U%tC?Y&rPX}yɗ}AyxH&kUKziާlL(jBk B)V#RȭX~S-=;X;~Em9K,lW~{׷'kIu~in}]>^q[Fc:8n?PQrFq'vdZ x$k)Pl{4~sԤX'Od܉}v&YGq[1C81yάs^QZ=lvnqKJuOn)#@j.Z^ˏTsYm*e2#5= tT,-!rqo 0PR[OD5&/=o{ޖr#ԻǏo>3l6Q(+m/nί3,o +S&*k[{O; k/Tb_”0ҦTKdp(λX?aCgjk\d.zIEkN bj;,VcrZnu^KA. [ƍK7_y~h4ҮT]ySuZ҃T{tq5W޼%>Oڼ?ۑE-D`nLfZG;QO^qCKrYPÉlQߴzGzRvp5Q1P{^f}hoZ;K->tt~mlz'@q۽߽AW̊Z\ϴvvzyku{DOnxTjykvu'wӝjaMm`h1ne& 4/_KN1nT6i$Ժ/.)Oń:u|unuJ)qR> X؃p +A;"L΃%ry<"yi+*9km)?’ ?Qj PJ-oZ{مG7% J0e\Z&JՕkl˅ckG_*'kU7n! Y6Va4vB;kXE'KVmCgS|llnE&{zu[-zv)Qd=VlnzpOkV=dWvbw]B"Byӗ)KJi3YZt^A=t6 +;wB\=~vTZ_{w=w# *Vo`5"Hc:,iw c *h^O4PMRL%Fj|t¨L~> A]p a-\;4f:#1f+RDe?) }t0xK٣Xvi+Dn "|JuT'Urqu!&ŬZ8T2Ձ,bZ3V#ikHub:'US++c.Q}0څ2QfwN^m&>j㲱xynq/Ȗ'oӗ̆.aNZ^ 9> +) F5@Cfr#w+A8;eud;,Cb۠ۍGlnxOr$."L&eJl_&:ȔTXךVeڵ7\*Jiu1,q3;5BBQXg 5ۦj8I`*HրZ_;|H@ŔgrP\L7z/{4"h1 +]Wri;zdR-?Z +VUޞhw/xv!E6bΛMں]ߺ7'TRT)9U?߻vajiE$//s[Byw}^]D? +?krf"ʩ=而qEd>>yz5ʥA }LKP*XԷ+N^jz::.F*Z0Q,\׊!25߬/a%g9ڐj[Ϸv_%P?W4c[ T_(6˘=j +n2ză&}#8gŵVLmrT(5. sLLWGw!qUgLrTJewʀkTg&U ӽw*@ }reK( 5. /;D-"5C4 pEiAzmQ}*Ƞnb<6qNr\Vނzv)2Qer|MTfB6üfM^2 9!fwQ~:E+cB~gWL-ǴFD[1h,EF+kU!Urp/[^B*Og[Bn8d|x"LێJu& a Z>Rw nGL_:(:~)ksC0vBe?).9~ruD. k08Q + 8$ݫ#\Z[rW' + Ie\oS05MLsO0ggsĊ"TJf,3u P烧%=FE/-œa/1Lt^y7M +G5΁Gt{="#QTmFRq"k)9Bᜏ@ϑGι k6:G+ 7UomBn)ϸqԕt jލ(0YG-nM4לƩYl+nFmE$Qpq PFwpC/i7}nҕc)' ;۫G굉/a h=3za4 vE&۔kW̪WBd(ڬJ1.i.+ wP[JV26gWF)haD0D%;)!\OnZ;}~Lm,B:k.{cGr-Z @@Tf1,{$Զ#*Kqvx+3[h +D9\^k!aj&=Ov 8ػZT,̈́$҈eVgtq +1/x3sH,SJ^ō &P|:<1~9PS#Z#?l#N*婅hfat_Q-*r)"a@2TzCNʋ -/¦)9$R 3!Ϻ= BgHg}xN/EDS&/:m"1B.#32&2Έ0Y+m@UW<O4;eD4KZRO "#RWO\@]4D(^\iOyq}dy-/$KQ%5H͵_άD̮ͱFG AчȒݣ0#>\1[Wv]a7d:;*fRaOT2!MPQuV!ΤY"{@,D6fzKv*k7~(v7| f̲ڠح"| ze3Qa-]tSPBXD@bn#.5c`) Jo.xnF*'֕- vixכ~:k$|"B|bRZϥJa=,gܬgh&7i|zHP',wv3!* g#3j!6{v>'I3-@t>ϐV#|ʼnȎLppfnftg'7'QJEx+&+7 IaFJ +"§IIZF:] ť{6Olwt^{.40v\*xqOJaK(25tS鵸v#nTMjFPX^s9L٭s Prגk0th5wT{)Pa~N{7X'WVދkǯwm/jvw{ߪo9i!,.Dm6Å2BY޸lu +˧Э jܘ" +(ALc?;!솸\Py`1j]N=%Bh51DTXHO>̈UGD9:7fLkɚؖ|7 MtA$jXF Yz~`*r*k6@t<}/IAuÃ)aֈJ%Hp;Zeg!LbZcBOL vWbɃaO$biN dɅ lz+=ŢTܓʇxrr3^O\ŵBPv՘PbS]\`@[{X Rճ*c6٘ΨL3>:ąT+u!d+ZBx(=\ucFD(ou1Xɯ<$i eq1= =! Jbk|h%7a{X^ +Ӌ7KPϳ>ٙمOCiw>Ld2ToLbD|bRs1@2Td(2퉪^vI|9M;/LD|κcU=KDեQ-Gd`:oTX]bNID$e>fm}л.( Bt6%Ť:+(g8i\kTM6O2ۈBk[Xr ՗]ۧfFDco5X%ӉvuƕjX(|qžsKa9g Ћ*k͝>ǁ$Ӎtc+k +L+R(,Tj9bSiqށA&W7SD0mڍ!菆 LiĒ7@dp 蕙L(Hqxn> D~#Y cny9W(%G+\Yu]?W:Ϲ'Uƴ M 39JH_pr1rv}3¤":\7u.vI=u/CZy'5R| bv{)?7rstLya7q8@.C .UARsMJV٢Sg<lރ:_fzˬ!ALj^ֈO#ʴ 3)BDal#Z;=Lv.*;ar/x K\;gtFp"݄J'3<)A"Ik >=PLM$*Vdx`L; +\mu&hL.χN S.wT'?Fh;HeI#lL)wH'sq)8BҒu'Z"PiBs@wQN9(-|tE&LB;&HN *BuzpH[m)NK.'.DtDy"rZj՝TsOnz}g/mGXrX&х1IFX>䋗dws0 \fDSc#ވD奰D'\zmxePQޘR]/(Y 5^ҫΐŵ(&j7Lv].T&$[OrKjs2HTBlԉSnn/"oDQPffZu_.l(k!!.Ũ91ik'X*X-Xx\({cPKFْ FPS[۳nG ! ę9$?=_p`aK׫Q6r1Ψ2OGTǥ:5qBtML{h2/0s);BLYHpƍ­TEL RvDh\ ~2L`^ZX؍D(lPxf.r΁9 (q $DT TcQ\Ĭ +@ +R䨈5H2نBnI"BGY e . GE\AZƩF@>`͂Q U T('"|Rjvf,r7>⽤)lf#,!/"$\ b>Z$v{/N9@X9`s~lf8vC:͇)/HM,b;ѝk^"ca>z8#jNIᴗl\|nc2ΑQa@C^,+uJkBN'.xD0Q!G@! (h%`XgSpz4B;F9'^DL % Zt U'68̓bZP ((EKp7̺k !t`c\pug)*Ƅ,c^fU gD,Щ7 60 +\-524NF{&,3N@!=en0~{]3(5h +7L5vf/d!P#/D6夢L1sȕ͡ + ^fa>xcaأZZAsgT\iGN) EWHĥ₏q kKIMK#H^Z~ͥt {L\[R~2zIڿ`lir5~5z}3=ٕ R迺8FIp!W矍/-h]>&?ű 8Ly"Y|՛Og/]]35ivrN5z+Oom|(M)MZςOY;p|u+Eɖ2q0llr2qh,/۟ߋJ{w .P00˱ȅx;nnGy9!@NLD^v|!W2Xyk3O!Wک` {n|kC. Y"9$̃hWS=<< m~ool9, O> &_{JOW!uW\6S듫oח/-/oxu +I~XxWR7HȠw|{: ritk5A -]_x\_j;37}{{_YO? C/5׿Tt͝Ֆq|8űs "l3W_DNsgwySr ( h/%w[חƣ_wSWɾm4Wyt)^Z~ftg'9)ٻɆq_?34"Q9gj:\Ó|z_V_x+GL7v s_X;"*}2Ɉ}> nYkߐFK#󹞾 z"35ǤP7^wU7\##hyԚݓ_"Ĺ+Յ魭;_.S+;dЬѨ\ۥD7SW_}?;fyɕg ?X[ÃxpV&KNB[M=[غJ 5Nww_'ܼumՅ{'Jw "$2J'`Z? #Bpq薾~1"ݷJI*ε[-u>O9y\Ӽ6|x.l޾wG$ɽ=OFh${?r#{F]^ܽr< ¯LG%"`Wf~s[>w/g\[oWX&VZ~7I`#Q@Zrej/hrsW׶~,ѓ/ˤ~se}7~;y4;NU:z`Byi|F?3_+ؿo;|y4ϴ +K;7V7_|6~Kc Wڿ{zw8,#s⼞Zx86{o4]8ooyxן^;׼`H'Ui3&\Fmrߦ_Gm]_=blۏz[5d缈f6㹭;8s0{|ۓ͵=44H WwH~|!N'mrN`lW⃃G©;c"΍5Z8 +grcv`be4ʵOL&gbd/ovvfL5swo'7ߌ-&IBrb8blu*ip~R{;Owui<)_ٶ/__i޸sa?}w}v3X#~ş[[P_x׷^̼v5}:1gD:{N"a|d'}n^%3>vc3Iv'V_ ==v)Y›Ow+!Wr'76oo>o.]#ECZ\Dc[UWW.Eho܍o>B}ޜl^ +{7f6G.YKW矄?.~mݛvη&c/}p(ah+s#0({:}Hgzb{}0:y.^DC53}Fx}Ս7W^sJzd'N[ɇ_Ok{4N84Wo=>ooTI|wme7^ޜo>涉wԍ{w\Kfݿ[mK7nos/R&m|u/Sķ?=VOl ^_\|6Z˫w>1ģ鵓frէh"8jѹd᜙M_Jokoo?_<[KWW.~go{Gtc4Ṣ/|9f6_/^_Knw O~;qe0_lvkj^< 2q,ꩍ+2ؙBkh|&yXZ +7S,=^JW>5"OȠ}jDS#2hAԈ ڧFd>5"OȠ}jDS#2hAԈ ڧFd>5"OȠ}jDS#2hAԈ ڧFd>5"OȠ}jDS#2hAԈ ڧFd>5"OȠ}jDS#2hAԈ ڧFd>5"OȠ}jD=#w<ܞ:??rn}Jm>i,{zedfuwtu}*6+kyA5V^p߾иLFjߏI7CmThG7b4 B6a&:҉1AU/E1L&IlEJSAEtQu#FGlѼ%7wWNhJ||tzwxwbtTSm#˯ +͹ٽ}+KGm|-,;k`~a=s~u=*]>nwݸrWsW6Z\(^vk\ݏ_xual.lJw}t:8{]XX?ɀ }44~Tm{}wk۟#!8<.R϶۽- !G_o#ygBz{m 죝}Hgݻ}Fnflя`_a>|xzu<}tdwƯx +ɀ~ݫ`ٹc!yϐO~s@kh귻ufÞ ^9j]tXn A6zBPA vcT=)"G{'g~Xe{E'::*:rI>)pXܥH L;Y{k0|Bg-=2tyGD :;=h&Qs(e4wD OΩ+ޫBǏ?O1,>~L} /7' +ĝ;#a>*[;w&;>:ڟ:n9SoAv jxk{MS/>h_ۣr3"=;L3\ttjhE&-gPIfۙ6wv[-H=o? K10zv*xk-Agwcv.OA8,ܺA ;5E3 s׆3-ӻ[~ՏS{N|(?>_cx1%Շ 8b=/3f^jڇ'K[O'=} K1IvE9; hiT^o{ֳ"tH׳+;beއ=[=W,Z:4wrAS|ѫ4N=,WBVs9|t܎>n oIl n"[9_JŻN!OO~?EA=3v}SL?n:3e3c2,hR hHdXfZgl>'N"{oXΔ;DEА覺p.9}$[gpwLEKa|L>pΜ=u433S8;&"~3R8Ӈ0$o gZu0L"зC"~!Cd)YabԽ#~qc83-#'o=-O d=7$͒nK3C'[o|*vv[kZKZҍ[mҭnt;k-6z_r=#dp*KX3QLgk&D{ߵWvA:>a{.Q)cWJ SOK%CnSգ'tP?h;;F?4Zv{gIU{d);NAOj Wջ;lŔzqKPòO .9=^&=d4DwgwQ13֗z0k™ks{Y9dp#5#>tAuw{>] Y*}^2{󈄧ȇrDU:<ò.3 ƙ ?3Qsu'@`/ RsssuιQ(<9odA }3,go݅{>ڳ(sCWohQ޷Tt<8}tHaU}{^{{BЮg4˷!:W-2># =wh~d츽=vtuDgNu'4ӍƸRIޜ˼HtzƩOqjџ=vVNvfFEjzׯ->17˛߽"kѱC8[YX:du!+`N̩9u0 i t#N̩9u0<+UudLk:3l**!nϱw 3әޙb݁g+G 4]9zGdrd΀ +[ =3ݭ>Ȇhݪn./QS!@wXju&Znm}[ii5\t ˢ~0(sڵwQeJ+`һ> E gLvTe|L8}Gݢc Ꮸ Z?L>䬄?zG|t)P?Πhgf]ǀ?ĝlQUpCµx'h7oڇލ]ã{AyWcKតa8,^O}NX[>:f;[壽w=bi4K E+Kk㣃 tB~nTv~)h|QPF<vJCND9~f8~hCu!5GeHB;!ulԠǀWggr8:)ԑ۞υB?KWOɔ}0W{}k/=  /gנ /AN56'n`n`=3ɀ }44ལ[kj?]g1ޙ{:lpR _Ȁ o>¬/dE~!_}z9ѫWHX>~xjhKޅgξi~TOeK_ 6$fo.DgX\O0 +|=[AowZp+t|AAǃGOw_ޫ-QvMH=ۆ)c?3TسaM Tsǩ>W wǩZ3{,ILfD^-:>ۯgO&[Wo<~ݫ`ٹcgG[Cb SSm&q;N/OczG=}򈄧fњZ*pA&tFOSn W_Pu}|>H6>>_ir@áh.'!Q=R۷ +w/%6,r7.@(8t3 +n)r׎.=ƃކ,况XgKO͒]aC\͠z?w~yHRmceﴏg\q/W9l P9s֌AAns5>_p:BpO +>6-&6gbXܼ!p5.09,:e?>sTvv@Gn2*#˯F~ZsF$y3ҩi=@_&з XjJ(퐏058xEƆ3M`b0 "l,0t"c )PST㦰󘄧&9n+ G6S q%l7PXt1 wĊf`$)h4#JK@%U3@AĤod@ V1km-$!56D .Y":7ZrMH3IoJcIJ& ֐8!`Ib&^jH 9B/9UlIB$X5S'V$tshbX=UMbX)q@ $^,W "E +R\ F|r%״1ӗJZw&65L.QNc͑(5tcٌ?5KVEFsKDB ~i57@90@a)Mj +etBO3L/U<4Kȃ*Y͒8R#"IG%17 XCǡ1J 0(`&0E4@^ʑ+i endstream endobj 5 0 obj <> endobj 35 0 obj <> endobj 44 0 obj [/View/Design] endobj 45 0 obj <>>> endobj 18 0 obj [/View/Design] endobj 19 0 obj <>>> endobj 61 0 obj [60 0 R] endobj 84 0 obj <> endobj xref 0 85 0000000004 65535 f +0000000016 00000 n +0000000173 00000 n +0000031372 00000 n +0000000006 00000 f +0000637627 00000 n +0000000008 00000 f +0000031423 00000 n +0000000009 00000 f +0000000010 00000 f +0000000011 00000 f +0000000012 00000 f +0000000013 00000 f +0000000014 00000 f +0000000015 00000 f +0000000016 00000 f +0000000017 00000 f +0000000020 00000 f +0000637884 00000 n +0000637915 00000 n +0000000021 00000 f +0000000022 00000 f +0000000023 00000 f +0000000024 00000 f +0000000025 00000 f +0000000026 00000 f +0000000027 00000 f +0000000028 00000 f +0000000029 00000 f +0000000030 00000 f +0000000031 00000 f +0000000032 00000 f +0000000033 00000 f +0000000034 00000 f +0000000000 00000 f +0000637697 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000637768 00000 n +0000637799 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000037025 00000 n +0000638000 00000 n +0000031786 00000 n +0000040024 00000 n +0000037341 00000 n +0000037228 00000 n +0000035939 00000 n +0000036464 00000 n +0000036512 00000 n +0000037112 00000 n +0000037143 00000 n +0000037376 00000 n +0000040098 00000 n +0000040450 00000 n +0000041882 00000 n +0000048978 00000 n +0000112923 00000 n +0000178511 00000 n +0000244099 00000 n +0000309687 00000 n +0000375275 00000 n +0000440863 00000 n +0000506451 00000 n +0000572039 00000 n +0000638025 00000 n +trailer <<99D9DA31BE634348BDBBAE81438842F9>]>> startxref 638264 %%EOF \ No newline at end of file diff --git a/tests/dummy/public/assets/branding/ai/Ember-CLI-Mirage-Logo-Stacked-Black.ai b/tests/dummy/public/assets/branding/ai/Ember-CLI-Mirage-Logo-Stacked-Black.ai new file mode 100644 index 000000000..77f59a00b --- /dev/null +++ b/tests/dummy/public/assets/branding/ai/Ember-CLI-Mirage-Logo-Stacked-Black.ai @@ -0,0 +1,2830 @@ +%PDF-1.5 % +1 0 obj <>/OCGs[5 0 R 35 0 R 60 0 R]>>/Pages 3 0 R/Type/Catalog>> endobj 2 0 obj <>stream + + + + + application/pdf + + + Ember-CLI-Mirage-Logo-Stacked-BW + + + 2017-04-12T20:08:50-05:00 + 2017-04-12T20:08:50-05:00 + 2017-04-12T20:05:19-05:00 + Adobe Illustrator CC 2017 (Macintosh) + + + + 252 + 256 + JPEG + /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgBAAD8AwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq7FXYq7FXYq7 FXYq7FXYq7FXYq7FXYq7FXYq7FXEgCp6Yq8E/Pr88PKTeTb/AMu+XNUF9q+oEW8stoW4Qwq4MxMo orc1UpRSdj4dVKP/ACT/ADx8m3Xk/SdE1vVFsddskSyZbssFlCnhE6ysOJqvEGpqD7b4q9sxQ7FX Yq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FUt1zzL5e0G3S41vUrbTYZDxje6l SIOw6heZHI/LFUj/AOVvflf/ANTTpn/STH/XFXf8re/K/wD6mnTP+kmP+uKu/wCVvflf/wBTTpn/ AEkx/wBcVd/yt78r/wDqadM/6SY/64q7/lb35X/9TTpn/STH/XFXf8re/K//AKmnTP8ApJj/AK4q i9L/ADE8gazdLYad5g0+8upvhS1juImd69lStW+QxV4/+fH5EeT7Xydf+ZfLWnnT9S08i4uILcu0 UsLOBL+6JZU4BudUoAAfoUpj+Sf5D+TrfyppPmDX9O+va7dql6BdFxHACecSiGoU/DxJ5g7+2Kvc sUOxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxVJvN3m/QfKWhza1rlwLezh2UDeSSQ/ZjiT9p2 8PpO1TirwW4/5yW/MbzFeyxeQvKJubWM8TJJDcXsor0ZxbmNI/kSw98U0q6b/wA5P+btF1SOy/ML yq1gkh3kgintZlX+cQ3Jf1B8nGK09/0HX9I1/SbbV9IuUu9Pu15wzp0PYgg7qynYqdweuKEfirsV fKnnPQG/MP8A5yXuPLWrXksWm24WKMRULJBBaido4+VQpdyxJoeuKXov/Qp/5X/791P/AKSI/wDq litu/wChT/yv/wB+6n/0kR/9UsVt3/Qp/wCV/wDv3U/+kiP/AKpYrbv+hT/yv/37qf8A0kR/9UsV t3/Qp/5X/wC/dT/6SI/+qWK27/oU/wDK/wD37qf/AEkR/wDVLFbeZfnz+SPlryD5f07XvL93diR7 1bSWK4dXNXjklSRHRYypX0SO/XtTdV9L+RtQudU8j+X9QvW9W6vtMs7i5Y/tSTW6O5+kscUJ5irs VdirsVdirsVdirsVdirsVdirsVdirsVdirsVakkSNGkkYJGgLO7GgAG5JJxV8tef7k/m3+elh5Tt L0S+WtOHAz2zh4yix+tdSoyll5sf3QPsPfFL6Y0TQ9J0LS4NL0m1js7C2UJDBEKAAdz3Zj1LHcnr ihC+bPKWg+a9Fn0fW7Vbm0mB4kgc43pRZIm6o69iP1Yq+Y/yw/MdPye82eY/KPmU3FzpEdwyxNbI rlJ42CrMEZ0ok0NC1KnZduuKX015T85eWvNulrqegXyXtqTxfjVXjf8AkkRgGRvmPlihOsVfNeif +tf3/wDz2/7p4xS9M/Nz87dH/LprK2lsZNT1K9VpUtUcQqkKnjzeQq/VtgAvY4oZB+XH5gaT588s x67psbwL6jW9zbS0LxTIAWQkbH4XVgfA4q83b/nK3ymvm86MdMuP0SLj6sdZ9RevLh6noca+nXev PlT9mu2Kae4YodirsVeIf85d/wDkttN/7bMH/ULc4pD0r8sv/JbeU/8Atjaf/wBQseKGS4q7FXYq 7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXzt/zkxrev6t5u8t/lvps/1a31YQSztUqsslzcNbxCSm 5SMxlqd6+IGKQ9B/LX8iPKPkO+GqWU1zfauYDbvdXDLwHMgu0caqOFeNNyTTauKHpGKuxVINd/L/ AMj6/JNNrGg2F7c3ChJbuW3jNwVUUH78ASigFBRsVfP35aWb+Q/+ck77yZpdw8mjXokiaNzX4Pqf 16Ll4vF9jl8/HFL6gxQ+a9E/9a/v/wDnt/3Txil6Z+bn5JaP+YrWVzLfSaZqVkrRJdIgmV4WPLg8 ZZOjbghu5xQyD8uPy/0nyH5Zj0LTZHnX1GuLm5loHlmcAM5A2HwoqgeAxV5u3/OKXlNvN51k6ncf ok3H1k6N6a9eXP0/X5V9Ou1OHKn7Vd8U29wxQ7FXYq8Q/wCcu/8AyW2m/wDbZg/6hbnFIelfll/5 Lbyn/wBsbT/+oWPFDJcVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirxj/nIL8p9f8zSab5p8 qmvmLRgF9FWEckkSP6sbQuaASRSEkAneu24oVKL/ACc/MH819e1efSPOflt9PhtLYv8ApV7aa15z KyqFZZP3bFwS37ug26UxV6veSzQ2k8sMRnmjjZ44QaF2UEqte3I7YofOUn/OQX53pIyN5DKlSQVa yv6gg9DvilTk/Pj8/LxGt7HyQY7mQUSRdPvpCvuAW47e+2Ksk/In8ofMul65eeevOzE+Yb4SehbS MryIZjWSaVlqodh8KqPsrX5BV7lih816J/61/f8A/Pb/ALp4xSz784Pza83eStXsrLRvLL6ta3Nv 60l8RKyCTmy+kPSU0ZQoY1P7QxQwH/oZz8yf+pJ/4S6/5pxTTv8AoZz8yf8AqSf+Euv+acVp3/Qz n5k/9ST/AMJdf804rTv+hnPzJ/6kn/hLr/mnFaZ7+UH5t+bvOutXtjrHlptJtba29dL0CYIZPUVR EfUUCrKxYUP7JxQk/wDzl3/5LbTf+2zB/wBQtzikPSvyy/8AJbeU/wDtjaf/ANQseKGS4qlPmXzb 5a8sWP17X9Rh0+2NQjTN8TkdRGgq7n2UE4qwaH/nJT8n5bkQ/pl0DGgme1uRH9J9Oo+kYrT0XS9W 0zVrGK/0y7ivbKYViuIHWRG8aMpI274qisVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVd irsVfNeif+tf3/8Az2/7p4xS+j7m6tbWEzXUyQQr9qSVgiivizEDFCorKyhlIKkVBG4IOKqX12y+ t/U/rEf1vjz+r819Tj/Nwryp74qrYq7FXYq8Q/5y7/8AJbab/wBtmD/qFucUh6V+WX/ktvKf/bG0 /wD6hY8UJxrmr2mjaNfaveEi10+3lup6deEKF2A96DbFXy75C8la3+ePmvUPN3my5ki0G1l9CO3h ahJ+2trASKIkasC7Uqa+JJCl7Pef847flDc6ebJdDFtRSEuYZpxOpP7XNnfkf9cEYot4ol7r/wDz j9+YzWLyzan5T1KMzCEEL60Z+EOFJ4LPE60J7r4VFFLO9E/5y68n3d+sGq6Td6ZbO3EXastwqj+a RFCOB/qhsVp7hp+oWWo2MF/Yzpc2dyiy288ZDI6MKhlIxQiMVdirsVdirsVdirsVdirsVdirsVdi rsVdirsVdirsVeA6T5R8zw/85T32tSaZcLo7RySrqJjb6uVeyWIUlpw5c/h41rilBf8AOV3lfzrq 13ol1pdnc6ho0EUiSQWqPL6dyzV5uiAn4koA1O3vuqGef8456J5q0b8tobTzHHLbzNcyyWNpcArL DasECoyN8SfvA7BT2OKHzrL+XX5vt+aT8LC+XWzqBnXWCknoisnIXH1gUThTf7X+T12xS+2cUOxV 2KvEP+cu/wDyW2m/9tmD/qFucUh6V+WX/ktvKf8A2xtP/wCoWPFCG/NzT7rUPyy8y2lqped7CZkQ dW9NeZUe5C0xVgH/ADibrWn3P5fXWlRsq32n3sj3EW3IpOqtHJTwNCv+xxSXtuKEn8weT/K/mJrV td0u21I2TF7X6zGJOBanKlezcRUHY0xVj/5mflz5R8weTdRtruwtreW1tZZLG9SNI3t3jQupVlFQ lV+JehGKsD/5xH1i+uvJGp6dO5e3069/0QHfgsyB2Qf5PMFvmTikvdMUOxV2KuxV2KuxV2KuxV2K uxV2KuxV2KuxV2Kpfr3mHRPL+nNqOtXsVhYoyoZ5m4ryY0VR3JPgMVfPtv8A85I2Z/OeWSTVJB5A eL6nFWI8A4QEXPDj6m8tRXrxO47Ypp9CaJr2ja7p0epaPeRX1jKSI7iFgykqaMPYg9jihIvOH5p+ QvJ13BZ+Y9VWxurmP1oYfSnmYx8ivIiGOTiCykCvWmKpB/0Mf+TH/Uw/9Od9/wBUMVp3/Qx/5Mf9 TD/0533/AFQxWnf9DH/kx/1MP/Tnff8AVDFad/0Mf+TH/Uw/9Od9/wBUMVpP/J/5qeQfON5PZeXN WW+u7eP1pYDFPCwj5BeYE0cfIBmANOlRirzv/nLv/wAltpv/AG2YP+oW5xSHpX5Zf+S28p/9sbT/ APqFjxQyUgEUPTFWG+S/ym8o+Tda1PVtCSaGXVRxlt2cNDGvMvxiXiCoqe7HbFUf+YXmDXPL/lC/ 1bQ9MbV9TtlQw2KhmLcnVWYqnxsEUliF8PpxV4d/0MJ+d3/Ui/8ATlf/APNWKUt13zt/zkH+Y1k3 lu18tSaVZXn7q9mS2nt1aNjuslxcniqU6hdyNtxtir3P8pPy6g8heToNG9RZ76V2udRuFrxedwAQ ld+KKqqPGldq4oZnirsVdirsVdirsVdirsVdirsVdirsVdirsVdiqV+ZPK+geZdMbS9dso7+xZ1k 9GWuzp9llZSGU70qD02xV88W/wDzjdbf8rnlsZNOuT5BSL65HKXPBqoALb1uXPaau32+I/2WKbfR Pl7y3ofl3S49L0SzjsbCIsyQRVpyY1ZiSSzE+JOKEm84flX5C843kF75j0pb66to/RhmE08LCPkW 4kwyR8gGJIr0qfHFUg/6Fw/Jj/qXv+ny+/6r4rbv+hcPyY/6l7/p8vv+q+K27/oXD8mP+pe/6fL7 /qvitu/6Fw/Jj/qXv+ny+/6r4rafeT/yq8g+Tr6a+8uaStjd3EXoSzetPMxj5Bio9aSTiCygmnhi rzz/AJy7/wDJbab/ANtmD/qFucUh6V+WX/ktvKf/AGxtP/6hY8UMlxV2KuxV2KqF5f2NjAZ724it YF+1LM6xoPmzEDFWJ6j+c/5V6e5S48z2LMNiIJPrH/JgSYqkc3/OSv5ORkcNbeavUpaXYp8+cS4r S2L/AJyX/J13CtrEkYP7bWl0R/wsbH8MVp6XZXlrfWcF7aSrNa3UaTW8yGqvHIoZGU+BU1xVWxV2 KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV4b/wA5FfnF5r8k3+l6V5eEdvJdwtdT3ssaykgOUEaK 9V7Vbbw6YpDMPyM/MDVvPPkYarq0Kx39vcyWc0sa8Em9NEcSqu9KiShptUH5YoeGyf8AOUP5hDzu xEUB0YXnpfogQgsYQ/Dj6v8Aeepx71py/Zptimn1pih2KuxV4h/zl3/5LbTf+2zB/wBQtzikPSvy y/8AJbeU/wDtjaf/ANQseKGS4q7FXl/nz/nIj8vvKjS2kU51rVojxNnZEMisOoknP7tadCByYeGK vMk/MT/nIn8ySR5U006Lo8pot3EojXh73dx9oj/ikA+2KUZY/wDOKnmTV5xe+dPNj3Fy28iw+pdS Gv8Ay8XDKf8AhDitsw03/nFb8rLRQLlb7UGA+Iz3HAE/KBYcVtPYf+cevydiUqvlyMgmvx3F05+9 5WOKLXP/AM4/fk868T5biAPhNcqdvcSg4rbPbO0tbO0gs7SJYLW2jWGCFBxRI4wFVVA6BQKDFVXF XYq7FXYq7FXYq7FWJ+ZfzX/Lry0XTV9etYriPZ7WJjPOD4GKESOv0jFXm+s/85c+RrZiml6Zf6iw /bcR28Z+RLSP96YppIR/zlH571MctB8kGRCDxNbi7/GKOKuK06T87/8AnIxmrD+X7KhGwbStTc/e JF/Virafnr/zkDBGXvPy/bgCKuNN1KJQDt1Z3xVcP+crvMenNx13yVJBvRm9aW3INafZlhb9eK0y DSP+ctvy+uiE1Gx1DTnPV+Ec8Y+lH5/8JitM90H84/yw10qmn+YrT1W2WG4Y2shPgqXAiZj8sUJn 5q8j+UPONnBB5g06LUoIj6lu5ZlZeQ3KSRMjgMKVo1DiqY6JoekaHpkGl6RaR2Wn24pDbxCiipqT 4kkmpJ3OKpF/yqn8u/8AEn+Jf0Fbfpr1PX+s0anrV5er6XL0ufL4uXGtd+uKsrxV2KuxV4h/zl3/ AOS203/tswf9QtzikPSvyy/8lt5T/wC2Np//AFCx4oQf5g/mx5M8i23LWLvnfuvKDTLej3MngeFQ EX/KcgeGKvCLjzH+dP523ElnocB0PymWKTOHaOAr3Wa4oHnbxSNaeK98UvUfy/8A+ccPIflZI7nU IRr+rKQ31q8QeijD/fVvVkHzfkffFFvVwAAABQDYAYq7FXYq7FXYq7FXYq7FXYq7FXYq81/Ob85I fy7tbGKGwOo6pqYl+rRF+EcYj4jnJQMxqX2UdaHcYq8nXy//AM5HfmnSTVblvL2gzb+i/KziKN2W 3Ss8oodvV2P82KWZ+V/+cTvImnBJNdurnW7gfajr9Vtz/sIiZf8AkpitvTtE/LzyLoSqNJ0GxtHX b1lgQymnSsrAyH6WxQyHFXYq7FWmVWUqwBUihB3BBxVjusflv5A1kN+kvL1hcO25lNvGsv8AyMQK /wCOKvP/ADB/zit+Weohn0763o0p3UQSmWKvuk/qNT5MMU2wuT8gPzj8ns03kXzSbiBSWFosr2jM eu8LmS3b/ZNirUX5+/nF5LlW38/eWTc2/IJ9bMZtHY9+M0Ye2fxoq/Tir0nyj/zkZ+WPmHhFLfnR r19vq+pAQrX2nBaGnhVgfbFFPTYpYpo1lhdZInHJHQhlIPcEbHFV2KuxV4F/zltrmjS+S7DSYr63 k1SPVYppLFJEaZY1t7hS7Rg8lHJwKkYpDDNM/Oz8ydf8v6N5J/LzSJIrmwsLWyutQRRNOTDCsTOC R6VuhKn4nqfdTirM/wAv/wDnGG2juhrn5g3Z1nVJW9V7AO7xcya8p5mIeZvEbDx5DFbe8Wtra2lv HbWsKW9tCoSKCJQiIo6KqqAAPlihVxV2KuxV2KuxV2KuxV2KuxV2KuxV2KrJYIZePqxrJwYOnIBu Lr0YV6EeOKr8VdirsVdirsVdirsVdirsVdiqyeCC4heGeNZYZBxkicBlYHsVOxxV5n5v/wCccvyx 8xc5YrE6Levv9Y04iJa9qwENDTx4qD74rby67/Jf88Py/wDVn8i67JqGn7k21u/pSU6ktaTF4WO+ 3Fi3tilguq/nr+etjcNYanrFxZXUJ/eW8tlbQSqRt8QMCP8AfirJPK/lr82PzOgr/wArCt5LZhW4 shfT+sqn+ezjRP8AhqDwxV6H5W/5xM8mae6T+YL+41uYGrQr/otue9CEZ5T/AMjBitvZNF0DRNDs VsNHsYNPs06Q26LGpNKVNB8TeJO+KEfirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVd irsVdirsVdirsVdirsVdirsVSnzF5T8teZLT6prum2+owCvAToGZK9TG/wBtD7qRirxTzX/zifYe udQ8kavLpV4jc4bW5ZnjVuwjnT97HT3DnFNpAv5kf85A/lkwi83aa+t6PGeP1uf94ONduN7DyoW/ 4uBPtir0ryd/zkp+W3mH04by5bQr96Aw39Fir/k3C1jp7vx+WKKep29xBcQpPbyJNBIA0csbBkZT 0KsKgjFV+KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Ku xV2KtMqupRwGVhRlO4IPUEYq8384/wDOPf5Z+Zucx0/9E3z1P1vTaQVJ3q0VGhap6nhU+OKvLZ/y I/ObyLO935A8wteWwbn9UST6tIx/y7eYvbSU92+jFKpaf85KfmP5XnSx8++V2LA8fXCSWUrD+YBw 8Un+x4jFaei+Xf8AnJX8qtYCpNfyaTcNT91fxMgr3/ex+pEPpYYop6HpWv6FrEfq6TqNrqEdK87W aOYU+aFsVR+KuxV2KpF5j89+TfLcbPrmsWtgVFfRkkHrEAV+GJayN9C4q8X83/8AOVMdxL+ify/0 qbUdQnJjgvLiNiCx6ejbJWSQ+HLj/qnFNPWPyuufPl15Qt7jzvGkOtyu7ekiLGyw7CP1VQlQ53Jp TwpXFDLcVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVUruztLyBre7g jubd9nhlVXRvmrAg4q898wf848/lPrRd20ZdOnb/AHdp7tb0r4RLWH/hMVee6r/zh/YCQy6F5lnt mXeNLqBZW/5GxNDT/gMU2gh+RH5/6XX9EedwYl+zGL++hrv/AL74NH3rucVb/wCVZ/8AOUgPo/4r +A/GZf0hLsRtSvp8/wCGKrT+Qv586v8ADrnnUCBqhomvr2enj+74pHvTxxVOtA/5xD8s27rLr2tX WpPXk0Vui2sZPcMSZnI+RXFbeveVPIPk7ynB6Pl/SoLEkUedV5TOP8uZ+UjfS2KE/wAVdirsVdir sVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirs VdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsV dirsVfC//K//AM3/APqZJv8AkVb/APVPFLv+V/8A5v8A/UyTf8irf/qniqvYfn3+bsl9bxv5jmZH lRWHpW+4LAH/AHXir7E8+aheab5G8xajZSmG8s9MvLi2mABKSxW7ujAEEbMAd8UPn/8AIb8+vMl/ 5wGhecNSN7b6qBFYXEqxoYrkV4J+7VNpa8d/2uOKX07ih2KvCv8AnI785tT8rNZ+XfLN39W1qWlz f3KBHMMO4jjo4ZeUh+I7bKB/NikMw/ILzVrPmf8ALe01PWblrzUfXuIprhwilgkh47IFGykDpih5 n/zkl+Z/nzyr55sdO8v6vJYWcumRXEkKJEwMrXE6FqujH7MajFIeXx/nh+dsqCSLXLt0PRlt4SDT bqIsVRVh/wA5GfnHpd0Dc6oLtQeTWt7bQ8T8yiRSAfJhitPpT8nPze0/8xNIncwCy1mwKrf2Qbkt HrwliJ3KNxOx3U7HsSoYr/zk35782+UrHQJPLuovp73ctytyUWN+YjWMrX1FfpyPTFIeCf8AK/8A 83/+pkm/5FW//VPFXf8AK/8A83/+pkm/5FW//VPFXtv/ADjJ+YfnPzbfa/H5i1N9QS0itmtg6Rpw MjSBqemqdeI64qUp/wCckvzP8+eVfPNjp3l/V5LCzl0yK4khRImBla4nQtV0Y/ZjUYqHlH/K/wD8 3/8AqZJv+RVv/wBU8VTvy7/zk/8Amjpdwh1C5g1m1BHOC5hjjYr34yQLGwPgW5fLFafUf5cfmNoX nzy+uraWTHIh9O9spD+8glpXi1PtA9VYdR71AUMqxV2KvMfzf/PPQ/ICCwgjGpeYpk5x2IbikKn7 L3DCpFeoUbn2G+KvmzXv+chvzY1eZn/TLafC1eNtYIsCLXwejSn/AGTnFKC0788fza06YSReZLuQ 9eFzxuFINP2ZlfFX05+Qv5oeZvP2i3tzrOnRW4sHSFdQgLKlxIQWZRE3LiyDiWIanxdBih4r+a35 z/mdo35i69pema7LbWFpdGO3gWOAhFCg0BaMn7zil9XaDcTXOhadcTtzmmtYZJXNN2aNSx28ScUI 7FXm/wDzkD5o17y1+XU2qaHdtZX63UEazoqMQrsQwo4Yb/LFXy//AMr/APzf/wCpkm/5FW//AFTx SkX5aMqfmP5VdyFVdYsCzHYAC6jqScVffn6T03/lrh/5GJ/XFC+K+spXCRXEcjnoqurHb2BxVi/5 ukj8r/NJBp/uMuRt7xkYq+B4pZYZUmicxyxsHjdTRlZTUEEdCDiyfdf5MfmJH558k2uoSuP0taUt dWjG379AP3gH8sq0b7x2xYsh86ebNN8p+Wb/AF/UW/0eyjLLGDRpJD8McS/5TuQMVfAPmPX9S8w6 5e63qcnq31/K00zdgT0VR2VVoqjsBiyfXH/OK0yP+VSKtaxX9yjV8Twbb6GxQXk3/OXf/kydN/7Y 0H/UVc4qHt//ADjh/wCSY8vf9Hn/AFHT4oKRf85TTeU/+VdyxagYDr5lhOiqeJuAfVX1itPiCejz 5fs1p3pikPPf+cP9M1BvNOuaoqsNOhsRayNT4TNLMkiAHxVYm+/FSn3/ADmN/wAc3yv/AMZrv/iM WKhG/wDOI13aQeStZWaaOJjqRIDsFJHoR+JxUvdf0npv/LXD/wAjE/rihXililQPE6yIejKQw29x ir5I/wCcu/8AyZOm/wDbGg/6irnFIe3/APOOH/kmPL3/AEef9R0+KCxz/nJr8vfLl55GvPNMdtFa 61pbRMbqNQhmjlmWJo5SKcv7zkpO9RQdcUh5p/ziRqd1B+YGoaejH6reac7zR9i8Esfpt81DsPpx UvrjFCW+Zdbg0Hy7qetTjlFpttLdMnQt6SFuI92pTFXwbpllr/5h+fYbaSb1dX167JmuHqVXlVne n8kaAmg7CgxS+1/In5W+TvJWnxW+k2EZvFUCfU5UVrmVqbs0hFVB/lWijFDINX0TRtZtGtNWsYL+ 1brDcxpKu/gHBocVUfLflrRPLekxaRolqtnp8LO0cClmoZGLsSzFmO7dzir4h/O7/wAmx5n/AOYx v+Iril9v+WP+Ub0n/mDt/wDk0uKEyxV5F/zlL/5Ke4/5jLb/AIkcVD4zxZInTNNvdU1K00yxj9a9 vpo7a1i5KvOWZwiLyYqoqzAVJpir0H/oXD85/wDqXv8Ap8sf+q+KLZ/+Rn5MfmV5Y/MjT9Y1zR/q emwRXCyz/WbWWhkhZF+GKV33Y+GKvafztJH5UeZyDT/QmG3uwGKHyl+R/ke086+YdX0K5AAl0i4e CcivozLLD6Uvjs5ANOoJGKUX+T3nS/8Ayz/MiSx1gG3sZpTp2uwsdoyjlVm/54vvX+UtTrirIf8A nJ78y/0/5jTyppkvqaVoz1uihqst6QVbp19EHgP8otioSH8z/wAs08l/l75Pe7j467qUl3cake68 0gMcJ/4xKP8Agi2Kvbf+cTJUf8sblV6xarcI3zMMLfqYYqXl/wDzl3/5MnTf+2NB/wBRVzioYr5S /Jr81fMfl+11nQoOelXXqfVm+txxV9ORo3+BnUj40btiqXebvyb/ADI8qWLajrWkPHp6kCS7hkin RCxoOfpM5QVNKsAK4q90/wCcYvzQ0i+tB5JfTbfS762jae2ltgVS7C0EjScizGYChJ5Go8KUxUoT /nMb/jm+V/8AjNd/8RixUPDfJ/5VeffONjNfeXNL+vWtvL6E0nr28PGTiG40mkjJ2YdBiqff9C4f nP8A9S9/0+WP/VfFbfUP5GeV9d8sflvYaPrlt9T1KCW4aWDnHLQSTM6/FEzpup8cUPBP+cu//Jk6 b/2xoP8AqKucUhG/lf8A85JaJ5N8i6Z5budGubqew9fncRyRqjetcSTCgbfYSUxWmMfm3+f+t+fr FNIgsl0nRFcSy24kMsszp9n1JOKDip3ChevUmgxV6T/zil+XOoael55z1OBoBew/VdKjkUqzQsyy STUP7LFFCHuK9sVL6KxQwf8AO+GeX8p/MyQGjizLmgr8CMrv/wAIpxV8v/8AONV1awfm/pIuKAzR 3MUDE0AkaByPvAK/TikvtjFDsVdir4O/O7/ybHmf/mMb/iK4pfb/AJY/5RvSf+YO3/5NLihMsVeR f85S/wDkp7j/AJjLb/iRxUPjPFknvkPULPTfPPl3Ub2QQ2dnqdncXMxBISKK4R3YgAnZQTtih9l/ 8r//ACf/AOpkh/5FXH/VPFFO/wCV/wD5P/8AUyQ/8irj/qnitO/P4kflB5kp/vmL/qIjxUPB/wDn ET/yZOpf9saf/qKtsUlPv+crvy49K4g89afF+7n4WushR0kA4wTH/WUemfkvjioYn/zjV+W/+JvN /wCnL+Llo+gsspDCqy3XWGPfqEpzb5Ad8VLPP+cxv+Ob5X/4zXf/ABGLFQnX/OIciH8u9UiB+NdX lZh7NbW4H/ETipeb/wDOXf8A5MnTf+2NB/1FXOKh6L+Rf5p/l7of5V6Jper67bWeoW/1r17aQsHX neTSLWgPVWBxVHfmp+fP5bL5K1bT9N1GPWNQ1K0mtILWBXZAZ0MfORyAoVeVaVqe2KvDP+ca9OvL z83tImtw3p2KXNxdOv7Mf1d4t/ZnlVfpxUvTv+cxv+Ob5X/4zXf/ABGLFQlf/ONX5l+RvKnlTVLP zDqsdhcz3/rRRukrFo/RReVY0cdVOKl69/yv/wDJ/wD6mSH/AJFXH/VPFFJ75U/MfyT5suJ7fy9q iahNbIJJ0RJU4qxoD+8VO+Kvmr/nLv8A8mTpv/bGg/6irnFIZB+Uv/OPPkXzf+W+l6/qU19FqV+L kSNBLGsamK5lhQqjRt+zGOpxW3j3nbyhrn5cedzY3ASSSzkW5066kjV4p4g1Y5PTcMp6UZTWhBGK vq38tPz48meatEt21LULTR9dXjFdWFzKkAaU7A25kYc1c9ACWHQ+JUPTcVQ+pafa6jp11p92nqWt 5DJb3Ef80cqlHH0qcVfBfm7yz5k/Lfzw1qzPb3mnTrc6XfqKCSNW5QzJUUPT4h2NQcUvo7yJ/wA5 TeS9T0+KLzSzaNqyKFnkEby2sjAbtGYw7pX+Vht/McVpkOr/APOR/wCUen2rTR6w1/KBVLa0gmaR tq0BdY4x1/aYYopkP5Z/mLpXn7y5+mbCNrZkmkgubN2DPE6Gq8iKfaQq3007Yq+Ovzu/8mx5n/5j G/4iuKX1FoP57/lLbaFp1vP5ihSaG1hjlQxXGzLGoYbR9iMUI7/lf/5P/wDUyQ/8irj/AKp4rTGf +ckNUsNV/JUalp8wuLG8uLSa2mAIDxuSVYBgDuPEYpfHuKX0F/0J75k/6mGz/wCRUuKLd/0J75k/ 6mGz/wCRUuK27/oT3zJ/1MNn/wAipcVt79+aHk+684+RdT8t2twlpPf+hwuJAWVfRuI5jULvuI6Y oYB+S35Dav8Al95putZvNUt76K4sZLMRQo6sGeaKTlVtqUipil7JcW1tcwtBcxJPC9OcUih1NDUV Vqg74oW2ljZWURis7eO2iJ5GOFFjXkdq0UAV2xV5v+d/5Saj+YtppMNlqENg2myTO5mRnDiYIBTj 4cMVRX5Kflhf/l7oF9pl5exX0l3dfWVkhVlCj01TiQ3+pirG/wA6fyG1f8wfNNrrNnqlvYxW9jHZ mKZHZiyTSycqrtSktMUsA/6E98yf9TDZ/wDIqXFbRNh/zh1qbTD6/wCZYY4QRX0LZ5GI7/beMD8c Vt7f+XP5W+VfIOnSW2jRPJc3FDeahOQ08pHQEgKFQdlUU+Z3xQkH54flJqP5i2ukQ2V/DYHTnmdz MrPy9UIBTj4cMVeTf9Ce+ZP+phs/+RUuKbd/0J75k/6mGz/5FS4rb0n8kvyS1X8u9V1K9vdSgvlv oEhRIUdCpR+VTyxQhfzp/IbV/wAwfNNrrNnqlvYxW9jHZmKZHZiyTSycqrtSktMUs/8Ayv8AJ1z5 N8i6Z5bubhLqew9fncRgqjetcSTCgbfYSUxQofmZ+V/l78wNGFhqYMF3AS9hqMYBlhc9ev2kb9pD 19iAcVeE6f8A84m+dbDzBZ3Savps1ha3EcxkYzpMyxuG/uxE61NP58U2+psUOxVjnnn8vfK3nbSx p+v2vrLHU21zGeE8DMKFon3p03Bqp7g4q8B13/nD7WEmZtB1+3mgO6R38bwuvsXiEwb58R8sU2gt O/5xA85STAalrenW0Nfie2E9wwHsrpbj/hsVt7r+Vn5SaD+XdjdRadcXF3d3xQ3tzO1Fb068AkS/ AoHM+J364oeYefv+cYde8zecdW1+DW7W3h1GczJC8chZQQBQkbdsU2kH/QnvmT/qYbP/AJFS4rbv +hPfMn/Uw2f/ACKlxW3rPmj8pNR1n8oNM8iRX8MV3YJao94ysY2+rChoo+LfFDyb/oT3zJ/1MNn/ AMipcU2+p8UOxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2K uxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Ku xV2KuxV2KuxV2KuxV8e/mH+eH5naR+YevWOna66WFhqM8VvbenAyBIpCAhqhYgUod8UvqHyB5ysP OXlOw8wWdFF0lLiCtTFOnwyxn/Vbp4ih74oZDirsVQWuazp2iaReavqUohsbGJp7iQ9lQV2HcnoB 3OKvje+/5yJ/M6+8xSXNvrL2Gmz3PKKzWOApFAX2TkyE7L1JOKX2rih86/8AOSv5l+efKnmvS7Py 9qslhbT2AmljRImDSetIvL40Y9FGKQiP+cZ/zH87ebNd1q38w6o+oQ21rHJAjpEvFmkoT+7VO2Kl 7Z5uvLmy8qa1eWrmK5trC5mgkFCVkjhZlbeo2IxQ+Lf+V/8A5v8A/UyTf8irf/qnil3/ACv/APN/ /qZJv+RVv/1TxVH6V/zkn+bthMHk1aO/jBqYLu3hZT/so1ik+5sVp77+Un/OQuied7lNH1KBdJ8w MCYoufKC4oN/RZqEP34Ht0JxV65ihxIAqemKvnL80v8AnKY2V7NpHkeOKcwkpNrUw9SMsOv1eOtG A/nbY9hShxTTxXUfzj/NPUJTJP5o1BGY1Itp2tl+hYPTUfdiqJ0f88vzX0qVXg8yXc4WlY7xhdqQ Ox9cSH6Qa4q+iPyd/wCcidP85XUeh69DHpmvyClu8ZP1a5YdVTkSyP4KSa9jXbFXs2KHYq8n/NX/ AJyF8s+SppNKsYxrHmBNpLWN+MMB/wCLpAG+L/IXfx44q+ePMH/ORP5r6zM7DVzpsDGq22nosKr8 pPimP0vilj8f5q/makplXzVqxY1JDXk7Lua/ZZiv4Yqy/wAs/wDOTf5oaRMn167i1q0BHKC8jUPx 78ZYgj1925fLFafVn5d+dE85+U7PzDHYzacl3zAt5irH92xQsjLTknIGhIHyxQwX/nJXzn5n8qeV NLvPL1+9hcz3/oyyIqMWj9F24/GrDqoxSHzr/wAr/wDzf/6mSb/kVb/9U8Vd/wAr/wDzf/6mSb/k Vb/9U8Vd/wAr/wDzf/6mSb/kVb/9U8Vd/wAr/wDzf/6mSb/kVb/9U8VSL8zGVvzH81spBU6xqBBG 4IN1Jir0X/nGP8yv8O+aT5bv5eOka86rEWPwxXtOMbf89f7tvfj4YqX2Bih2KvmP/nKz8y/WuIvI umy/uoClxrTKftSfahgPsopIw8ePhikPnLFL9KQQQCDUHcEYsXyf/wA5ff8AKb6N/wBswf8AURLi kIn/AJw9/wCUk8w/8wcX/J3FS+i/PX/KEeYf+2Zef9Q74ofnliyfbWg/kR+UtzoWnXE/l2F5prWG SVzLcbs0aljtJ3JxYsW/MX/nFryreaVcXfk2OTTdXhUvDZNK8tvOQKlKyl3Rm/ZPLj7dwpt8qQzX dldpNC7293bSB43UlJI5I2qCDsVZWGKX3/8Alx5pPmryNo2vvT1r22U3PHZfXjJimoB0HqI1MWLC v+clvOlx5c/LqS0s5PTvtcl+oqw2ZYCpadh81HD/AGWKh8jeU/LGpeaPMdhoGmqDeX8ojRm+yigF nkb/ACUQFj8sWT7D8rf845/lholhFDd6aus3wA9e+vSzc26njEG9NFr0FK06k4sbSb8xP+cZfJer 6TPN5XtRo+txIWt1jdjbzMBtHIjlgnLpyWlOprim3yMDe6dfggyWt9Zy1BFUkilib71ZWGKX31+W fmw+bfImj6+9PrF3ABdhdgLiImKag7AyISPbFixj8/8A8zZfI/lALp0gTXdXZrfT22JiVQDNPQ/y BgB/lMMVfF1nZ6jquoxWlpFJeaheSBIokBeSSRz08SSTiyfTvkH/AJxP0O3s4rvzpcSXt+6hn062 f07eOu/BpF/eSMPFSo+fXFFs+f8A5x7/ACdaL0j5cjC0pUT3Qbb/AChLyxRbBvMv/OI/li6uoZ/L +pT6dEZUNzaXFJ09Ll8fpPs6tx6cuW+Kbe66dp9npun22n2MQgs7OJILaFeiRxqFVR8gMUPD/wDn L/8A5QjRv+2mP+oeTFIeEfkf5f0fzB+aGi6RrFst5pt19a9e3Ysob07SaRd0Kts6A9cVfV3/ACoD 8n/+pbh/5G3H/VTFFu/5UB+T/wD1LcP/ACNuP+qmK27/AJUB+T//AFLcP/I24/6qYrb4y88Mredf MDKQVOpXhBG4IM74pQ2r6Jqeiy2RukMf121gv7OVagPDOodGU7fZNVP+UDil9qfkd+Y6+ePJMFxc uG1rTuNrqq92kUfBN/z1UV/1uQ7YsU5/M7z3Z+R/J17rs/F7hB6Wn27Gnq3MgPpp8hQs3+SDir4Z 07T9f84eZ/QhLXmsapNJNLK56s1ZJZXO9ABVmxSk2KX6QaWQdMtCOnox/wDEBixfLH/OX3/Kb6N/ 2zB/1ES4pCJ/5w9/5STzD/zBxf8AJ3FS+i/PX/KEeYf+2Zef9Q74ofnliyfov5Y/5RvSf+YO3/5N LixROp6lY6Xp9xqN/MtvZWkbTXE7miqiCpJxV+duvX8Wo65qOoRR+lFeXM1xHF04rLIXC7eAOLJ9 rf8AOPVrNbfk55cjmXi7R3EoH+RNdzSIfpVwcWLyv/nMe4lNz5Vtq0iVL2Sm+7MYRv22C7YpDGf+ cS7WGb8zbqSRavbaVPLCfBzNBGT/AMDIwxUvr/FDsVfB353WMVl+bHmaGIAI14ZqAUHKdFmb/hnO KX0f/wA4pzSSflYUY1WHULlIx4KVjf8AW5xUvHv+crNYlvPzNWxLH0dMsYYkTenOXlMzfMh1H0Yq E3/5xG8r2175m1bzDOgdtIgjhtOQ+zLd8wzr7rHGy/7LFS+rMUOxV2KuxV4P/wA5f/8AKEaN/wBt Mf8AUPJikPnX8s/OUfkzzvpvmWW1a9Sw9atsriMt61vJD9ohqU9SvTFXu/8A0ONpv/Urzf8ASWv/ AFSxWnf9Djab/wBSvN/0lr/1SxWnp3/K17f/AJVL/wArE/Rr+j6Prfo71Ry/3o9Cnqcae/2cUPiX zKyt5j1VlIKm8uCCNwQZWxS+i/On5cf4o/5x88savYxc9Z0HS4Z4wo+KW29IGePxNAOa/IgfaxV5 B+Sn5iv5G87W97M5/RF7S11VBWnpMdpaeMTfF8qjviqc/wDORH5mr5w83mw06b1NB0UtBashqk0x NJpxTYgkcUPgKj7WKvS/+cafy3Om+VNR856jFS91S3lh0xWG6Wqg8pN+hlYbf5IH82Kl8u4pfov5 Y/5RvSf+YO3/AOTS4sXzD/zl9/ym+jf9swf9REuKQif+cPf+Uk8w/wDMHF/ydxUvovz1/wAoR5h/ 7Zl5/wBQ74ofnliyerWv/OTP5p2tlDZwXFosUEawxH6shYKihV6nrQYopinnD80/PvnCNYdf1aS5 tVPJbRFSGGo6ExxKisR2LVOKpl+VH5R6/wCfdZiWOKS30GJx+kdUIoioN2SInZ5D0AFadTtir7ls LG00+xt7GzjENpaRpDbwr0SONQqqPkBih80f85jf8dLyv/xhu/8AicWKQ8e/Ln8xtb8ga3PrGjwW 1xdXFs1m6XiyPGI3kSQkCN4jyrEO+KvRv+hu/wAyf+rbo3/Ii6/7KcVp3/Q3f5k/9W3Rv+RF1/2U 4rTyfzf5p1DzV5kvvMGoxxRXl+yvNHbhliBVFQcQ7SN0Xu2Kvqv/AJxP/wDJXy/9tO4/5NxYqXjX /OU2ny2v5rTXDg8L+ytp4z2oqmE/jEcVDK/+cPddtodU8w6HKwE93FBd2wNBUW5dJQPE/vlP34qX 1Bih2KvmL/nLbVtUsvMWgJZXk9qr2cpdYZHjBPq9SFIxSET/AM4i6pqd9qPmYXt5PdBIbQoJpHk4 1aWtORNMVKef85f/APKEaN/20x/1DyYqHzf5B8nXPnLzbYeW7a4S1nv/AFeFxICyL6MLzGoXfcR0 xV7D/wBCe+ZP+phs/wDkVLitu/6E98yf9TDZ/wDIqXFbevf8qq1D/lSf/KvPr0X1z0PR+vcW9Kv1 n168ftdNsUPifUWVtQumUgqZpCCNwQWOLJ99flfGiflp5UVVAU6PYkj3a2Qn7ycWL5G/Pr8uf8Fe eJltIuGiaryu9MoPhQE/vYB/xiY7f5JXFKT/AJT+QLnzz50s9GUMtip+sanOv+67aMjnv2ZyQi+5 xV92TWUNvoz2VnEI4YbYw20EYoFVU4oigdgNhih+cWLJ+h3kUk+SfLxPX9G2f/UOmLF81f8AOX3/ ACm+jf8AbMH/AFES4pCJ/wCcPf8AlJPMP/MHF/ydxUvovz1/yhHmH/tmXn/UO+KH55Ysn19pH/OM X5XX2hWVzLFepPdWsUjyJcnZ5IwSVBVh1O1Rii3zn+af5a6r5A8yvpV0xnspgZtNvgKLNDWm/g6H Z1+noRir1H/nHX88Y9KMXk7zRcrHpZ+HSNQlIVYGJr6ErH/dbE/Cx+ydjsRxVfUwIIBBqDuCMUPm H/nMb/jpeV/+MN3/AMTixSHnX5Fflzonn/zdd6PrE9zb2tvYSXiPZtGkhkSaGMAmRJRxpKe2KvdP +hRPy2/6uWs/8j7X/smxW3f9Ciflt/1ctZ/5H2v/AGTYrb5u/M/ytp/lXz5q/l/TpJZbOwkRIZLg q0pDRI55FFjXq3ZcVfTX/OJ//kr5f+2ncf8AJuLFSs/5yd/Lm48yeVYde02Iy6noPN5YkFXktHoZ AKbkxlQ4HhyxUPlPyz5k1fy1rtnrmkTejf2T84mIqpBBVkYd1dSVYeGKX2N+Xn/OQXkTzXZRJe3k Wi6zxAnsbxxGhfuYZnojqT0FeXtixehvrWjpF6z39usIHIyGVAtD3rWmKvlD/nKjzR5d13zNpA0b UYNRFnayR3L2ziVEdpKhea1Un5HFIT3/AJw5/wCOl5o/4w2n/E5cVLJv+cv/APlCNG/7aY/6h5MV DxT/AJx5ura1/OHQJ7mVIIE+t85ZGCIK2U4FWag6mmKvtH/E/lv/AKu1n/0kRf8ANWKHf4n8t/8A V2s/+kiL/mrFXf4n8t/9Xaz/AOkiL/mrFX59/wCGPMn/AFabz/pHl/5pxS+8/wAtopYvy78rRSo0 csekWCyRsCrKy20YIIO4IOKF3nXyD5W86afDYeYbT61Bby+tAVd4nV+JU0dCrUIO46YqoeSPyz8m +SVux5dsjbNelDcyPI8rsI68RykLEAcjsMVZRir86f8ADHmT/q03n/SPL/zTil96flxHNH+XnleO ZWSZNIsFkRwQwYW0YIYHeteuKHz5/wA5Z6Rq175z0eSzsp7mNdOCs8MTyAH15DQlQd8UhEf84k6T qll5i1972zntVeziCNNG8YJ9XoCwGKl9B+d43k8ma/HGpeR9Ou1RFFSSYHAAA74ofAf+GPMn/Vpv P+keX/mnFL9BfLasnl3SkcFWWzgDKRQgiJagjFCR/mb+XGkeffLUmkXx9G4Q+rp98oBeCYCgNO6t 0de496EKvijzp+XPnDydfSWuuafJDGjUjvUUvbSitA0coHE18D8Q7gYpep/84kX2pS+fNQtpLiaS yh0ibhCzsYkY3NvSik8QacvxxUp7/wA5daXqd9qPlk2VnPdBIbsOYY3k41aKleINMVCS/wDOKGj6 vZfmJqMt5Y3FtE2kTKJJonjUsbm2NKsAK0GKl9XYodir4m/PfQdcufza8xT2+nXU0LzRFJY4ZGU/ 6PGNmAIOKXvP/OLVle2f5aSw3dvJbS/pGdvTlRkahjioaMAaYqXsGKHz3+bH/OL8Op3M2s+SDFaX UpL3GjSHhA7HcmB+kZJ/YPw+BUbYpt87eYPI3nHy9K8etaNd2PAkGWWJvSNOvGUAxsPdWxVJFVmY KoJYmgA3JJxSyvyz+VP5h+ZJUTStCunien+lTRmC3A8fWl4J9ANcUPqr8jfyZn/Lu0vbi/v1u9V1 NYluIoQRBEsRYhUZgHc/HuxA+XfFCQ/85Z6ff3vkzR47O2luZF1EMyQo0hA9CQVIUHFIfLX+GPMn /VpvP+keX/mnFXf4Y8yf9Wm8/wCkeX/mnFXf4Y8yf9Wm8/6R5f8AmnFXf4Y8yf8AVpvP+keX/mnF X//Z + + + + uuid:4117ab5a-c2d3-5446-9385-21439d6eb9ed + xmp.did:61f0ef3b-ecb7-4f78-a77f-08f867147dc3 + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + xmp.iid:3b81609e-aefd-4ee8-a794-d6d24a4d8ac6 + xmp.did:3b81609e-aefd-4ee8-a794-d6d24a4d8ac6 + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + + + + saved + xmp.iid:48fef565-7731-4c49-bee9-dfbb0bfe5fa3 + 2017-02-28T19:39:58-06:00 + Adobe Illustrator CC 2015 (Macintosh) + / + + + saved + xmp.iid:61f0ef3b-ecb7-4f78-a77f-08f867147dc3 + 2017-04-12T20:05:14-05:00 + Adobe Illustrator CC 2017 (Macintosh) + / + + + + Document + Print + False + False + 1 + + 300.000000 + 300.000000 + Points + + + + Cyan + Magenta + Yellow + Black + + + + + + Default Swatch Group + 0 + + + + White + RGB + PROCESS + 255 + 255 + 255 + + + Black + RGB + PROCESS + 35 + 31 + 32 + + + + + + Mirage RGB + 1 + + + + R=39 G=50 B=73 + RGB + PROCESS + 39 + 50 + 73 + + + R=110 G=116 B=125 + RGB + PROCESS + 110 + 116 + 125 + + + R=54 G=181 B=192 + RGB + PROCESS + 54 + 181 + 192 + + + R=112 G=201 B=203 + RGB + PROCESS + 112 + 201 + 203 + + + R=255 G=147 B=67 + RGB + PROCESS + 255 + 147 + 67 + + + R=254 G=201 B=78 + RGB + PROCESS + 254 + 201 + 78 + + + R=214 G=237 B=162 + RGB + PROCESS + 214 + 237 + 162 + + + + + + Grays + 1 + + + + C=0 M=0 Y=0 K=100 + RGB + PROCESS + 35 + 31 + 32 + + + C=0 M=0 Y=0 K=90 + RGB + PROCESS + 64 + 64 + 65 + + + C=0 M=0 Y=0 K=80 + RGB + PROCESS + 88 + 89 + 91 + + + C=0 M=0 Y=0 K=70 + RGB + PROCESS + 109 + 110 + 112 + + + C=0 M=0 Y=0 K=60 + RGB + PROCESS + 128 + 129 + 132 + + + C=0 M=0 Y=0 K=50 + RGB + PROCESS + 146 + 148 + 151 + + + C=0 M=0 Y=0 K=40 + RGB + PROCESS + 166 + 168 + 171 + + + C=0 M=0 Y=0 K=30 + RGB + PROCESS + 187 + 189 + 191 + + + C=0 M=0 Y=0 K=20 + RGB + PROCESS + 208 + 210 + 211 + + + C=0 M=0 Y=0 K=10 + RGB + PROCESS + 230 + 231 + 232 + + + C=0 M=0 Y=0 K=5 + RGB + PROCESS + 241 + 241 + 242 + + + + + + Brights + 1 + + + + C=0 M=100 Y=100 K=0 + RGB + PROCESS + 236 + 28 + 36 + + + C=0 M=75 Y=100 K=0 + RGB + PROCESS + 241 + 101 + 34 + + + C=0 M=10 Y=95 K=0 + RGB + PROCESS + 255 + 221 + 21 + + + C=85 M=10 Y=100 K=0 + RGB + PROCESS + 0 + 161 + 75 + + + C=100 M=90 Y=0 K=0 + RGB + PROCESS + 34 + 64 + 153 + + + C=60 M=90 Y=0 K=0 + RGB + PROCESS + 127 + 63 + 151 + + + + + + + Adobe PDF library 15.00 + 21.0.2 + + + + + + + + + + + + + + + + + + + + + + + + + endstream endobj 3 0 obj <> endobj 7 0 obj <>/Resources<>/ExtGState<>/Properties<>>>/Thumb 66 0 R/TrimBox[0.0 0.0 300.0 300.0]/Type/Page>> endobj 62 0 obj <>stream +HlIn$D}~pzÛYr@v?c8ZN⛜YSB~&?ڙ +ʎ?xvZo}@™[ؘa$rT;L.YZ__3棜%rzgK 7bE\ϡo{V$fl9\(u΂M*V~z$ٮ/QE(؟ B:Dxuj{=!HzF$=#Bs pl~Yjčg*Q-F[{<%Gݻ{|hq_*ՀYKJ6tyͫ|m> 2!lf IFS*QƉ̈ 2eiC[^B.]fK wCzU3">Qe +{^2 \҈ƅ3O9CWsfieF'EK(;}lFbاnSGF-p#B-UD;]) AIV"//N@|A-vdj*|7tu@a}OІ [: S^*R)\6XUjee؟ա;{w$ㆰgBG8Gt_U=jQ\n眞Fc5 #ۣJJp ^A5ŵM(ou=YӣO࡜Y܀f1cPH5llm WC]Dž<21T4"2&P Hy20z[$p,K9[ HqzΜ95q9+WbE?EHv@3/eԓWX^ +FA t(EÇhg+-0Sdr6f#6#'5@of44,dVj__ DML(\ 4]/K0TZ#!zst~}o,@amL(AL)EΌGoܲ%TV(ƼJoMQE4i1n0\)$XS}<Y]S jJA}f w ;Dev# +Yವ{e>^IxѲ2`;!$Nw]1Dk +buʩ{F蜜BA7v'bc@T%gN5悅1E!]~ޮnD6e.J1^Չc]>C*ط<,D]M)Ҙ,'Uّ0@ݝaIg.͝dFV'P4+h~G6hwBHtOx_9[+H'ud-DDcS+H*z=K*C)Zw?+( Ҕd(zg~jiY`Y94l2 BTzpXl4TtB Tmڨ:gyu-Yw}l-_CVaYMXd-H +BXDKVY5F6iF *%%O':=iQ;CуYH+;<ыŗnuXɔ >3D"q[ B9D m(ס]T6E?jVuE +1L@Þf!Jh,2p6yrUT3!i?S3qCkEz9!ݑtv)H ]){׊2$prv, }ݱ ś/9߬ +R<6 Ӕc2WԗE˩6:TijDlySI>ܱ mUѷ)dK=T~cܙKЩ MwYg[P. ]llSZ|[_O7eI3ƥg"x6Hu.kȀ;+[=pnx; ئ̵fj\?^,Ґ0L^x5'&0 7~5~S{fzzf +k͌MKԩB1!?*E ? awF5 F[rRsuu{;].7M`^i !Q궍(l'.Cx]N,m]4yw?Iq~*b_lUq +z3Plʠ"[FvzY4`Pг-I5/`35 +^k^tdW90 "EcC~V9?u7G*@$n41ƩwqCa]DJS,l_r!lr= OA3=XȰmicPe+hӤ⊆XVѢ2vs-YZĵvX{2'}R\S6%KrUD @ r0Yܵ?y'YOD$TE\^I`*v3nuZJHRBpçOwem{B[d㌯s2pqRBspsGJ8M8Fr4n;&寏??~S endstream endobj 66 0 obj <>stream +8;XF49+ln3#Xg[HG23*K>\AY9UU1tqPa+kjp?f_rVB6CC,BI\;D@P^>Gr_'te/@#?skB;\_ +:MbbX7;$AjkN5PQrmrOfdisbt>]Q_2@Xn5DV)7;eO\]PRp#nSrS[DR(a1GtdWHtp" +P32O8g"N_ns!qD;L1bF\hZ-XYc]%~> endstream endobj 67 0 obj [/Indexed/DeviceRGB 255 68 0 R] endobj 68 0 obj <>stream +8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0 +b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup` +E1r!/,*0[*9.aFIR2&b-C#soRZ7Dl%MLY\.?d>Mn +6%Q2oYfNRF$$+ON<+]RUJmC0InDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j$XKrcYp0n+Xl_nU*O( +l[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\~> endstream endobj 60 0 obj <> endobj 69 0 obj [/View/Design] endobj 70 0 obj <>>> endobj 65 0 obj <> endobj 64 0 obj [/ICCBased 71 0 R] endobj 71 0 obj <>stream +HyTSwoɞc [5laQIBHADED2mtFOE.c}08׎8GNg9w߽'0 ֠Jb  + 2y.-;!KZ ^i"L0- @8(r;q7Ly&Qq4j|9 +V)gB0iW8#8wթ8_٥ʨQQj@&A)/g>'Kt;\ ӥ$պFZUn(4T%)뫔0C&Zi8bxEB;Pӓ̹A om?W= +x-[0}y)7ta>jT7@tܛ`q2ʀ&6ZLĄ?_yxg)˔zçLU*uSkSeO4?׸c. R ߁-25 S>ӣVd`rn~Y&+`;A4 A9=-tl`;~p Gp| [`L`< "A YA+Cb(R,*T2B- +ꇆnQt}MA0alSx k&^>0|>_',G!"F$H:R!zFQd?r 9\A&G rQ hE]a4zBgE#H *B=0HIpp0MxJ$D1D, VĭKĻYdE"EI2EBGt4MzNr!YK ?%_&#(0J:EAiQ(()ӔWT6U@P+!~mD eԴ!hӦh/']B/ҏӿ?a0nhF!X8܌kc&5S6lIa2cKMA!E#ƒdV(kel }}Cq9 +N')].uJr + wG xR^[oƜchg`>b$*~ :Eb~,m,-ݖ,Y¬*6X[ݱF=3뭷Y~dó ti zf6~`{v.Ng#{}}jc1X6fm;'_9 r:8q:˜O:ϸ8uJqnv=MmR 4 +n3ܣkGݯz=[==<=GTB(/S,]6*-W:#7*e^YDY}UjAyT`#D="b{ų+ʯ:!kJ4Gmt}uC%K7YVfFY .=b?SƕƩȺy چ k5%4m7lqlioZlG+Zz͹mzy]?uuw|"űNwW&e֥ﺱ*|j5kyݭǯg^ykEklD_p߶7Dmo꿻1ml{Mś nLl<9O[$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! +zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km endstream endobj 63 0 obj <> endobj 72 0 obj <> endobj 73 0 obj <>stream +%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 17.0 %%AI8_CreatorVersion: 21.0.2 %%For: (Lindsey Wilson) () %%Title: (Ember-CLI-Mirage-Logo-Stacked-Black.ai) %%CreationDate: 4/12/17 8:08 PM %%Canvassize: 16383 %%BoundingBox: -411 -2118 -138 -1841 %%HiResBoundingBox: -410.727600097656 -2117.44189453125 -138.495178222656 -1841.39697265625 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 13.0 %AI12_BuildNumber: 242 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%RGBProcessColor: 0 0 0 ([Registration]) %AI3_Cropmarks: -422.880605969701 -2133.7610619469 -122.880605969701 -1833.7610619469 %AI3_TemplateBox: 306.5 -396.5 306.5 -396.5 %AI3_TileBox: -560.880605969701 -2339.7610619469 15.1193940302992 -1605.7610619469 %AI3_DocumentPreview: None %AI5_ArtSize: 14400 14400 %AI5_RulerUnits: 2 %AI9_ColorModel: 1 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 1 %AI17_Begin_Content_if_version_gt:17 1 %AI9_OpenToView: -3343 223 0.3333 2549 1289 18 1 0 5 43 0 0 0 0 1 0 1 1 0 1 %AI17_Alternate_Content %AI9_OpenToView: -3343 223 0.3333 2549 1289 18 1 0 5 43 0 0 0 0 1 0 1 1 0 1 %AI17_End_Versioned_Content %AI5_OpenViewLayers: 7 %%PageOrigin:0 -792 %AI7_GridSettings: 72 8 72 8 1 0 0.800000011920929 0.800000011920929 0.800000011920929 0.899999976158142 0.899999976158142 0.899999976158142 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream endobj 74 0 obj <>stream +%%BoundingBox: -411 -2118 -138 -1841 %%HiResBoundingBox: -410.727600097656 -2117.44189453125 -138.495178222656 -1841.39697265625 %AI7_Thumbnail: 128 128 8 %%BeginData: 13736 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C45FD50FF7D52FD7EFF2727A8FD7CFF7D27F87DFD7AFF7D2727F827F8 %2752FD78FF5227F82720272752A8FD79FF7DF8F852FD7DFF52F8FD5CFFA8 %7DFD1B527DA8FFFFFF5252FD5CFF52FD1DF827A8FD4CFF7D7D527DA8FD0E %FFA8F82776A87D7D7DA87D7D7DA87D7D7DA87D7D7DA87D7D7DA87D7D7DA8 %7D27F876FD4AFF7D27FD04F82727A8FD0CFF7DF852FD1BFF7DF852FD48FF %A852F8F8277D7D7D27F8F8A8FD0BFF7DF87DFD1BFFA8F852FD48FF52F827 %A8FD05FF5220F8FD0BFF7D2052FD1BFF7DF852FD47FFA8F827A8FD07FF52 %F84BFD0AFF7DF87DFD1BFFA8F852FD47FF52F87DFD09FF272752A8FD08FF %7DF852FFFFFF52277DFFFFFF7D2727A8FD0EFF7DF852FD46FF7D27F8A8FD %09FF52F8F8F852A8FD06FF7DF852FFFF52F8F8F87DFFA827F8F827FD0EFF %A8F852FD45FF2721F827FD0AFFA87D5227F852FD06FF7DF852FFFF7DF827 %F8A8FFFF2727F852FD0EFF7DF852FD44FF27F8277DA8FD0DFFA827F87DFD %05FF7DF876FFFFA852207DFFFFFFA827277DFD0EFFA8F852FD43FFA82727 %FD11FF7DF852FD05FF7DF852FD1BFF7DF852FD43FFA8F852FD11FF7DF852 %FD05FF7DF87DFD1BFFA8F852FD43FFA82727FD11FF27277DFD05FF7D2052 %FD1BFF7DF852FD44FF27F8277DA8FD05FFA87D7DA8FD047D27F827FD06FF %7DF87DFFFFA8A8A1A87DA8A1A87DA8A1A87DA8A1A87DA8A1A87DFD04FFA8 %F852FD45FF27F8F827FD05FF52FD08F827FD07FF7DF852FFFF52F827F821 %F827F821F827F821F827F821F827F8F852FFFFFF7DF852FD0CFFA8A8FD38 %FF7D7D7DFD05FF7DFD06527D7DFD08FF7DF852FFFF7D5227522752275227 %522752275227522752275227A8FFFFFFA8F852FD09FFA85227F8F8F852A8 %FD4EFF7DF852FD1BFF7DF852FD08FFA8F8F827522727F8277DFD4DFF7DF8 %76FD1BFFA8F852FD07FFA8F8F852FFFFFFA87DF8F87DFD4CFF7DF852FD1B %FF7DF852FD07FF27F852FD06FF7DF82752524B7DFD48FF7DF87DFD04FF7D %FD05FF7DA8FD0FFFA8F852FD06FFA8F827FD08FF27FD05F827A8FD46FF7D %2052FFFFA8272727FFFFFF5227F87DFD0EFF7DF852FD06FF7DF87DFD08FF %A8527DFFA852F852FD46FF7DF87DFFFF52F8F8F87DFFA827F82727FD0EFF %A8F852FD06FF7DF852FD0DFFA827F8A8FD45FF7DF852FFFF7DF820F8A8FF %FF27F8F852FD0EFF7DF852FD06FFA8F852FD0EFF52F87DFD46FF52A8FFFF %FF7D52A8FFFFFFA8527DA8FD0EFFA8F852FD06FFA827F8A8FD0DFF52F87D %FD42FFA8FD20FF7DF852FD07FF7DF852FD0CFFA8F827A8FD41FFA8F8A8FD %1FFFA8F852FD08FF7DA8FD04FFA8FD047DA87D7DF8F852FD42FF52F852FD %1FFF7DF852FD0EFF52FD07F82752FD41FF7D2727F827277DA8FFFFFF5227 %F827F827F827F827F827F827F827F827F827F87DFFFFFFA8F852FD0EFF7D %FD06527D7DFD42FF5227F827F82752FD04FF7DF8FD13277DFFFFFF7DF852 %FD5BFF52F852FD08FFA8FFA8FFA8FFA8FFCAFFA8FFA8FFA8FFCAFFA8FD04 %FFA8F852FD5BFFA8F87DFD1FFF7DF852FD1DFFA8FFA8FFA8FD3AFF7DFD20 %FFA8F852FD16FFA87D52522727F827F827F821F827A8FD58FF7DF852FD13 %FF7D522727F8F8F8FD0427522752274C27FD40FFA852277DFFFFFFA82727 %7DFD0EFFA8F852FD10FF7D52F8F8F82727527DA8A8FD07FFA8FD41FF7DF8 %27F8A8FFFF2727F852FD0EFF7DF852FD0DFFA87D27F8F82752A8A8FD4EFF %52F8F8F87DFFA827F8F827FD0EFFA8F852FD0BFFA85227F8F827A8A8FD52 %FF522752FFFFFF7D2727A8FD0EFF7DF852FD0AFF7DF8F8277DA8FD3BFFCB %A8A87D7D52FD047DA87DA8A8FD24FFA8F852FD08FF7D27F82752FD39FFA8 %7D7D2727F827FD09F820F8272752527D7DFD1FFF7DF852FD06FFA827F8F8 %52A8FD36FFA87D5227FD05F8272752527D527D527D767D52522727FD05F8 %27277D7DFD1AFFA8F852FD04FFA852F8F827A8FD36FFA85227F8F8F85252 %A8A8FD11FFA87D52522720F82727527DFD17FF7DF852FFFFFF7D27F8277D %FD35FFA85227F8F8F8527DA8FD1AFF7D7D2727F8F8F85252A8FD13FFA8F8 %52FF7D27F8F852A8FD35FF7DF8F8F8527DFD21FFA8A85227F8F8F82752A8 %FD10FFA8F82752F8F84BA8FD37FF202752A8FD27FFA85227F8F8F82776A8 %FD0CFF7D52F8F8F8527DFD3AFFA8FD2CFFA85252F8F8F8527DFFA8FFFFFF %A8A87D522727F82752A8FD6CFFA85227F8F8F8272027F827F8F8F827277D %A8FD71FFA12727F827F827277D7DA8A8FD76FFA87D27F8F82752A8FD7BFF %7D52F8F8F8527DFD7BFFA85227F8F82752A8FD7BFFA82727F82727A1A8FD %7AFFA87D27F8F82752A8A8FD7AFF7D5221F8F84B52A8FD7BFF7D27F8F8F8 %2752A8FD1CFFA85227FD5BFFA85252F8F8F82752A8A8FD16FFA85227F827 %A8FD5CFFA8A85227F8F8F827277D7DA8A8FD0DFFA8A85227F8F8F87DA8FD %62FF7D522727F8F8F8272752527D7DA87DA87D7D767D2727F8F8F8527DFD %68FF7D7D5227F827FD0BF827205252A8FD6FFFA8A87D7D527D5252527D7D %A8A8FDFCFFFDFCFFFDFCFFFDFCFFFDA3FFA8FFA8FFA8FFA8FFA8FFA8FD05 %FFA8FD0EFFCBA8FD05FFA8FFA8FFA8FFA8FD09FFA8FFA8FFA8FFA8FFA8FF %A8FD05FFA8FFA8FFA8FFA8FD15FFA8A87DA8A8FD07FFA8FFA8FD0BFFA8FF %A8F827F827F827F827F827F827A8FFFFA8F8217DFD0BFFA827F852FD04FF %2727F827F827F827F85252FD05FFA827F827F827F827F827F827F8A8FFFF %7D20F827F827F82720527DFD10FF7D2727F8F8F827F8277DFFFFFF5227F8 %27A8FD09FF7D27F827272027F827F827F827F82720FFFFFFA127F827A8FD %0AFF7DF82752FD04FF27F827F827F827F827F82727A8FD04FF27272027F8 %27F827F827F827A8FFFF7DF8272027F827F827F82727FD0DFFA852F827F8 %27F827F827F8F852FFFF7DF82727FD0AFFA8F827F8F827F827F8272127F8 %27F827A8FFFFA8F827F852FD09FFA8F827F852FD04FF2720F8FD0527FD04 %F827FFFFFFA827F827F827F8272127F82721A8FFFF7DF8F8272027F827F8 %21F8F827FD0BFFA827F827F8F8F8272727F8F8F8A8FFFF52F8F827A8FD09 %FF7D27F8FD042752FD0BFF7D272727F8A8FD08FF5227202752FD04FF27F8 %2752FD05FFFD0427A8FFFFFF2727F87DFD0BFFA8F82727A8FFFFFFA82727 %27217DFD0AFF52F827F8277DFFFFFFA8A85252FFFFFF7DF82727FD0AFFA8 %F82720F827F87DFD0BFF7DF827F8F827FD07FF7D21F827F852FD04FF2721 %F87DFD05FFA8F827F8A8FFFFA827F82076FD0BFF7DF8F827A8FD04FFA8F8 %27F852FD09FF7DF827F84BA8FD0BFF52F8F827A8FD09FF7D27F82727F827 %7DFD0BFF7D27F82721277DFD06FF27F8FD0427FD04FF4CF82152FD05FFA8 %27F827A8FFFFFF2727F87DFD0BFFA8F827F8FD06FF52F82727FD09FF2727 %F827A8FD0CFF7DF82727FD0AFFA8F82727F827F876FD07A8FD04FF7DF827 %F827F827A8FD04FF7DF827F827F827A8FFFFFF2727F852FD04FFA127F8F8 %27FFFFFFA827F8F852FFFD07A8FFFFFF7DF8F827A8FD05FF52F8F827A8FD %07FFA827F8F852FD0DFF5220F827A8FD09FF7D20F8272720FD0727F827FD %04FF7D27F8522727F87DFD04FF20272752F82727FD04FF52F82727522752 %2727F82752FD05FF272720FD0827FD04FFA8F827F8FD06FF27F82727FD08 %FFA8F827F8A8FD0DFF7DF82727FD0AFFA8F82727F827F827F821F827F8F8 %F8FD04FF7DF82027A8F827F8FFFFFF2727F8777D27F827CAFFFFFF2727F8 %27F820F8F8F827F87DFD04FFA827F827F827F821F827F827A8FFFFFF7DF8 %F827A8FFFFFFA852F827F87DFD08FF7DF8F8277DFD0DFF5227F827A8FD09 %FF7D27F8FD042720FD0727A8FFFFFF5227F852FF52F82752FF7D27F827FF %A8F82727FD04FF27F827275227522727F827F852FD04FFFD0B27FD04FF7D %F827275252522727F827F827A8FD08FFA8F827F8A8FD0DFF7DF82727FD0A %FFA8F827F8F827F87DFFFFA8FFA8FFA8FD04FF7DF82027FFA827F8277D27 %F8F852FF7DF8F827A8FFFFFF2720F852FFFFA8FFA87DF827F87DFFFFA827 %F8F852FFA8FFA8FFA8FD05FF7DF8F827F8F8F827F827F827A8FD09FFA827 %F8F852FD0DFF52F8F827A8FD09FF7D27F8FD04277DFD0BFF5227F852FFFF %5227F827212727FFFFA2F82727FD04FF27F82752FD06FF52F82727FFFFFF %2727F87DFD0BFFA8F8272727F827F827F852FD0CFF2727F827FD0DFF7DF8 %2727FD0AFFA8F82720F827F87DFD0BFF52F82727FFFFFF2727F827F87DFF %FF7DF8F827A8FFFFFF2721F87DFD06FF5227F827A8FFA827F82052FD0BFF %7DF8F8277DA87D27F827F87DFD0BFF7DF827F852FD0CFF52F8F827A8FD09 %FF7D27F82727F8277DFD0BFF5227F852FFFFFF7DF827F852FFFFFFA8F827 %27FD04FF4CF82152FD05FF7D27F82752FFFFFF2727F87DFD0BFFA8F827F8 %FFFFFFA827F827F8A8FD0AFFA827F827F8527DFD05FF527DFFFFFF7DF827 %27FD0AFFA8F82727F827F8FD04274BFD0427A8FFFF52F8F827FFFFFFA827 %F8277DFFFFFF7D20F827A8FFFFFF2727F827275227522727F827F87DFFFF %A827F82720522727274B272727A8FFFF7DF8F827A8FFFFFF7DF8F827F852 %7DFD09FF7D27F827F821FD0427F8F8F8A8FFFF5220F827274C2727274B27 %277DFF7D20F82727F827F827F827F827F827F8A8FFFF5227F852FD04FFA8 %A8A8FD04FFA8F82720FD04FF52F827F827F827F827F827F87DFD04FF2727 %F827F827F827F827F827A8FFFFA8F827F8FD05FF5220F827F827A8FD09FF %A827F8272127F827F827F8F852FFFF7DF827F827F827F827F827F87DFFA8 %F82727F827F827F827F827F827F827A8FFFF52F8F827FD0BFF7DF8F827A8 %FFFFFF2727F827F827F827F827277DFD04FFA827F827F827F827F827F827 %F8A8FFFF7DF8F827A8FD05FF5227F8F8F8A8FD0AFFA87D2727F8F8F827F8 %2752FFFFFF52F8F827F827F827F827F8F852FF7DF8F827FD0BA8A2FFFFFF %FD04A8FD0CFF7DA8A8FD04FFA87DFD08A8FD07FFFD0DA8FFFFFF7DA8A8FD %07FFA87D52A8FD0EFFA8A87D7D7DA8FD06FF7DFD0AA8FFFFFFA8A8A8FDFC %FFFDFCFFFDFCFFFDFCFFFD91FFA8FFA8FD11FFA8FFA8FD07FFA8FFA8FD07 %FFA8FFA8FFA8FFA8FFA8FD13FFA8A87D7D7DA8A8FD13FFA8A87D7D7DA8A2 %FD0BFFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA87D27F827A8FD0FFFA827F827 %7DFD05FF2727F8274BFD05FF2727F827F827F827F827214B52A8FD0DFFA8 %2727FD05F827277DA8FD0EFFA22727F827F8F8F827F82752FD07FF2727F8 %27F827F827F827F827F827F827A8F827F87DFD0FFF52F827F8A8FD05FF52 %F827F852FD05FF52F8272027F8272027F827F820F87DFD0BFF7DF827F827 %2727F8272027F827A8FD0BFFA827F827F827F8272727F827F820F87DFD05 %FF52F8272027F8272027F8272027F827207DF8F827F8A8FD0DFFA8F827F8 %217DFD05FF2727F8F827FD05FF27F8F827F820F827F827F827F827F852FD %09FF52F827F827F827F8F8F827F827F8277DFD09FF52F8F827F827F827F8 %27F827F827F8F827FD05FF27F8F827F820F827F820F827F820F8277DF827 %27274BFD0DFF27272027F8A8FD05FF52F827F852FD05FF52F8FD04275227 %522727F8272027F87DFD07FF7DF8272727F827FD0452F8272027F827A8FD %07FF522721272027F827275227522727F82727FD06FF52F8FD0427522752 %275227522752277DF8F827F8F87DFD0BFF5220F827F8F87DFD05FF2727F8 %F827FD05FF27F8F82727FD05FF7D52F827F827F8A8FD06FF2027F827F852 %A8FD04FFA12021F827F87DFD06FF7DF8F827F820F87DA8FD05FF7D52F87D %FD06FF2720F82727FD0BFF7DF827F827F827FD0AFFA827F8272727F8A8FD %05FF4CF827F852FD05FF52F827F852FD07FF52F827F82752FD05FF7D2727 %27F852FD07FFA8F827F82727FD05FFA827F827F82727A8FD09FFA8FD07FF %52F827F852FD0BFF52F8F827F827F87DFD09FF52F827F827F8F87DFD05FF %2720F82127FD05FF2721F82027FD07FFA827F827F852FD05FF52F827F827 %A8FD08FF52F827F8207DFD04FF7DF827F8F827FD13FF2727F8F827FD0BFF %7DF8272027272721FD08FFA8F82720272727F87DFD05FF52F827F852FD05 %FF52F827F852FD08FF2727202727FD05FFFD042752FD09FFA827F827F87D %FD04FFFD0427F8A8FD13FF52F827F852FD0BFF5227F827F827F8F84CFD07 %FF2727F827F827F8F852FD05FF2727F82727FD05FF2727F82127FD08FF52 %F827F827FD04FFA827F827F87DFD0AFF2727F82752FFFFFFA820F827F852 %FD14FF2727F8F827FD0BFF7DF827F84C272721277DFD05FF7D20F8272727 %F827F87DFD05FF52F827F852FD05FF52F827F84BFD08FF21FD0427FD05FF %2727F8277DFD0AFF52F827F876FFFFFF7DF827F8277DFD14FF52F8272127 %27522752275227522752FF52F8F8F8527DF827F827CAFFFFFFA827F827F8 %7D52F8F8F852FD05FF2727F8F827FD05FF27F8F82727FD07FF52F8F827F8 %52FD04FFA827F827F87DFD0AFF2727F8F852FFFFFF5220F827F8A8FD14FF %27F8F827F820F827F820F827F8F827FF52F827F87DFF27F827F87DFFFFFF %52F827F852FF52F827F87DFD05FF52F827F852FD05FF52F827F852FD05FF %A85227F8272727A8FD05FF272720277DFD0AFF52F827F87DFFFFFF7DF827 %F827A8FD0BFF7D5252527DFD04FF52F8272727F8272727F8272727F852FF %2720F82152FF7D20F827F8FFFFA8F827F8207DFF27F8F82752FD05FF2727 %F8F827FD05FF27F8F827215227522727F827F827F8F852FD05FFA827F827 %F8527D7D527D7D7D527D7D7D2727F8F852FFFFFF5227F827F8A8FD0BFF52 %F8F8F852FD04FF2720F827F827F827F827F827F8F827FF52F827F876FFFF %FD042752FF2727F82752FFFF52F827F87DFD05FF4CF827F852FD05FF52F8 %27F827F827F827F827F82720F827FD06FFA8F8272727F827F8F8F827F8F8 %F827F827F827F852FFFFFFA8F827272752FD0BFF522727274BFD04FF52F8 %27F852FD0AA8FF2727F8F852FFFFA8F827F8272727F827F8FFFFFF2727F8 %F852FD05FF2720F82127FD05FF2721F827F827F827F827F827F82752FD07 %FFA827F827F827F827F827F827F827F827F827F82052FFFFFFA827F827F8 %27A8FD0AFF52F827F852FD04FF2727F8F827FD0BFF522027F87DFFFFFF52 %F827F8272727F87DFFFFFF52F827F852FD05FF52F827F852FD05FF52F827 %20272027F8272027202752FD09FF20272727F827F827F827F827F827F827 %2027F876FD04FFFD0427F87DFD0AFF5227272752FD04FF52F827F852FD0B %FF2727F8F852FFFFFFA827F827F827F827A8FFFFFF2727F8F827FD05FF27 %27F82727FD05FF2727F82727A8A8A87D27F827F82752FD07FFA827F827F8 %52FD047D527D7D7D527D2727F82752FD04FF7DF827F827F87DFD09FF52F8 %27F852FD04FF2727F8F827FD0BFF4BF827F87DFD04FF52272727F8277DFD %04FF52F827F852FD05FF52F827F852FD05FF52F827F84CFD04FF7D272027 %F8277DFD07FF2727F8277DFD0AFF52F827F87DFD05FF52F8272727F87DFD %08FF5227F82752FD04FF52F827F852FD0BFF2727F8F852FD05FFF827F8F8 %27FD05FF4BF8F82127FD05FF2727F8F827FD05FF27F8F82727FD05FF52F8 %F827F82752FD05FFA827F827F87DFD0AFF2727F8F852FD05FFA827F827F8 %27F82752A8A8CAA8A85227F827F852FD04FF27F8F82727A87DA87DA87DA8 %7DA87DA8272027F87DFD05FF7DF82727FD06FF52F827F852FD05FF52F827 %F852FD05FF52F827F852FD06FF4B27202721272752A8FFFFFF272720277D %FD0AFF52F827F87DFD06FF7D27F8272027F827F8272727F8272127202727 %FD04FF52F8272727F8272027F8272027F82720F827F8F852FD07FFA8FD07 %FF52F8F82727FD05FF2727F8F827FD05FF27F8F82727FD07FF27F8F827F8 %27F87DFFFFA827F827F87DFD0AFF2727F8F852FD07FFA827F827F827F827 %F827F827F827F8F8F87DFD04FF2720F827F827F827F827F827F827F82727 %F827F87DFD0FFF52F827F827FD05FF27F827F852FD05FF52F827F827FD08 %FF27F8F82727F87DFFFFA8F827F8F852FD0AFF27F827F852FD09FF7D2721 %F8272727F8272027F82752A8FD05FF52F827F827F827F827F827F827F827 %F8275227277DFD0FFF5252275252FD05FF5252275252FD05FF5252275252 %FD09FF7627F827F87DFFFFA8522752277DFD0AFF5252275276FD0BFF7D52 %2727F827F827277DA8FD07FF52522752275227522752275227522752 %%EndData endstream endobj 75 0 obj <>stream +ɉ,k=$D@"%ݖ Bl,1 X^6ו~*DJ#LhEl!l郼wܞ2T!.Ǥ4+ (9 !V(27rC) Rʲ:V5u櫫SZCx1yCp$4!N0u:I!զ1uOMg|cǰ+aQ+f었u:,O4O_&D2:k&isa"Kp/hP (vq1$U끘('n(PrYgMYwHnQGZ= +I9ౘTЉ)[ۼd A#f"f0% D v4B,]eO^ @ E(. !k;Z.l]V I<8S( +x60C +@SF#DB}34w 8H8piM2i pUw*Wf4-' aS]o̶ {x4E&m&VѵO'L=Aa @ڱX<uI؅B3u*ۄXa60/1/oĬ7eh䐦zYI"30dM=VDeXAwYC "Tz6Rl艣)5dM ^[Uy<#Kb#%L FDb)$' Q(7Xģ$BA1o2)-~Dh-v>&¡LR,p#Q cQa ӱ8 ,غ#Hδ{u_ P) E@_}F wLy1l㠝bAc8i4lcyHAM6_dW h'ϕB`ز ُ'N,*X7Ъ<]ũO?B˥AB1B!T| 2oP̀dUHXiB6w񒀅,6fupBA`5=@@*bWwK5b' +UNThw;}fH5WɆu[IBLsEp *tZMұ<(%ʩJ:f{" CZ9V|bm])2n Jqk*| ǭAQuVuxcQƔ$_c>q9%ohݐnwPP075LD;#2AӠ2.QA4)[90@S*Lįaob-QN?[D +$XiH%I ̀i8@D hm-lb˔ؕv[EKMCʇJyLr戙rD]Yq&ēD0 +ގt-_8 ZΒ'8U3vɾN%Ն8Fd " fӑIPKJ А.y>viJg R~{bea.H0v_$B06\2 4aE. ?qk<ҋq\~ +9dmx1׳"^g ܢ_ (Ǽ-WLM+T!cGpPqZ4CzNpWQq2+౻C]a]lT*VpʐTg2-,9 K[s(-;2J%?Wݳ2uPMơ/ QUdҬ|ER)`^UVT3PueY,h[u4eI<*uJ! +Bb+. B `Kq + .L9Ku$0, 蕫&<12ͻZhk˼Wצ-dlBAԮkbMBқ#] +tEk OaT\ z%:54aև,d/1v`Hqf UɄC;u +iz WfCEl b5HJTiY7+SY6WkpKL=Q1Iqx`YW*ߎt)ˎZ#ڤjR"3M)J!FTu*WgMw*ZR)Ȭ +CJgL'HDfH,Je`33'9-FprfN9ʅxɜKKyBF<0M9(9bx9@(( xg,xa3XA 4v:(p<CSsW(]Z0[d e+i")43f`ӆFe5@H<pfKx2\sGz%>YAżB^2 +_txg>-\SsڜliDeT2g W߮5D o\`'ZXW)+}Zϊ:8^T\i$Ķte֖kZAvj=G<8v"90y* bL2*t,a%jB[_5PR$@7JUaNDMJRGWkquE )mr{X*j;T G4JP6Ȧ7zH5jJlpwGԅb %-x{*qʲ#ڳJmZ*/\$;"B!d"Ghaŀ#y'.l9 X51D"Pk.6*su*bRJgE +ZY^{Lbɂ%JlbU0mt|^p7/9c6K#ɔwJ_! +.|Q"Q jldքEr>$4efٟ'eŁZB.Kj9|q(+2.G:㑡 bB[q\\gnO}{iPPfJ*unJ|tz"%p5jLTجt +!0X,Y)4hL(8deN 48D+j +UVKa.UdJr51MC(-ZjRF$Rr:rIR^s8Z@S)&EG*%1*pjTj$j!Eآ,RJ[ڽJ%q5XLBH5"bGvȫYRǹ<^5kWU$a%XLx 9yJDn)Rʹb:!Db.5l~/{9;U t1|Gt +8 .IR(k-K!.Ab+Xy충r +R cqUN9S +!Wݒ[ܳ[)JGSJJTQR)sblN{1|P/\l66֢ -TtNkفTtJXor76|qiʲe3hPWm`ysayaaw"aBaܥ"RXnXP{q&UWf&?(+HeIX +%)/$GDGq'@by3fPT)žS#ؐr3(PNĻ /t1#Z'`i-6rx*o#@=\'E i;f4t D jV]sf!UdrXb +29εP^0(6`H6D7F5#Y=q2;b9t3P +(bO\J,,Safp#]ݔ] h'Bd|#HعGMewf,V)b*NurII%Ƌ&>Wũٽ]^-$x:D^W:5 @Bg! 3.Kޯ%̺]\ݦ<_i$^/vy؎37F=2y|R81_vM, 9˹n+[/ݎ{+>2C33Prh+ad@vY /E(EJx'o>_o|?'kŁ*47q~v^as$3dEP'S+r4qn?W(/x4y|ue Mo\,hp~(2rqܑ?F$4*h]|j7Ûy\ȉw<4(dCĻo7G߉GyGf0%F"D#-\G p:$r NɕN-cr0Ltu^%Af'BLjj# T%nUVn% bJk4Y <?qd4YVoi9V^sO!ށsO? y_= 8 +~ǜk)IwO1= W7{rh^Quc:!}Nzз=EOͽ2; 2 C}6kd+lT| + xN%$;^3ZhuyYaģ݆\Dr_}dsnE![+Wpmv47k3ʋc2"y?,GELgtA WJx + S.s¿'v%8]ec|/c$;]LF& +P`.!LRF6১ ǻhlhB,%zt:|Z$j4Tʠ%aE_->ӵs4c?ޕ? b9CX$8Mv TGvmBza/|S wsK):#?aThP18{]OL + +?(${7?Zudy8]^\v3sc~@ +불KM +Ih޵?F9YY# +` 28Ǯ +8b4ځ:,pPG#r{';mÔB,0&Mrcg%4@lRFh9`Rq$9)Q%|8 W 籗r3N)b`K_N]@)WD:a&S !vDjnǍ腅 ͵c8༊c2Dt?!E~4xS'B`ѣQq#ofO;M|+H@4EsuD@'pƨ6&`D8>7S 3(IlAc60j9qDٹtHjhީr.h>o,IFY>ʙр$-[Ѹ½aR$P>W.G b 윦a( 1!7caЏkN6F{5h$vGֱ]s[ 86 |Qn:r\Ҿ6zr0[]h?`,jlpPrin9FVڙ(_1?w X\heyXD;$=D wC,a4)2 bCTn0ءp-:Ի޻2X!FFZcG˖ b^]| I4XL)@vTۡ >9Qa'{Iy/ +V."0 3=C9TWiu.X{x1gaPCƝ"oNa>䉁xH"8k|Yj[m[:]A|Qs3/i,l [E+~,waU8H5 =E] <<&ҎQ,PqF@8PBx&ly#0ӯnmW͵f|60+4!&xب"zuA:+D0b56j,\kfԦٔ\ @ҀO j4/>!D'LJvbg2j7Dҵr&;AcOʻؠU,bX ݁ +q/OvGyB6NyFсrrI ! JErUJb\?\ӧӜ1!H6sI-p  "%A@VjU䝙ʉ]F +9pSpz+tġ1sG|dGB~TYvV/ʤ~vz(3NNr{2ۿasJGX9gu2B1TɡwI~ܐ.AáIHt<r+.1 ZV6Hi]0aWgP'5 +BLDjZr3=w|:͇3%" 0tZ$/ۊd#ׇDH+l2sHOnffwWdd^!D)wlYf3(y(3'#xLpW,_=JTR~| p =ySi4ufqHiF;:ɸV!|^ny{{c3w1J;p *" M횔1b޹GjjN$Kc![q\iG $B>ƗΖӉ똄Vz>)$˻p;_Uφu $ 37K(SZq %eŚ'sXEXqJV65Q>2>bXB<7*n2";/V ~>t$E2Om AX| ?Oq W}EѫNd'h͢q8|^.k' [cQȄIeŝ~4JnLT +ozT0 ?@(&K%7jpGxYJ(O3rpg)L*!a;Aboo9 + ̍H0`S!GnEFߨگJOT΃#V|hڼ9Z+ҮiF m De $t/.쩴*`RwtdnC9s񋵮:?Spat܏f $brJWpg;_$8Ix"1-jwb[pKc&ᚏ)PKp&pEV9@X JAOl!w?k &{(B]~q6V#6).@d}MXXE Gzwn$LE峡@(0ׯB6*gB>GG!f 6F3X}|0>9cM7 0CX:X(>X7q'=:k&-2HBifeKk{ES4 G%8҉XzO3d<> rE9wIk9 Y'D;pȕ<鎉ŊKŭщSq0(\zC;GH B  j@o 0c +%""y_[I?3,TȽUEQ`RҦ;s1զݾ2N4 9k9o,$ ~JݱPާlkpbK X xWw0ؔ[] pbZ/xlO ߆v +!JkƮّb8-g|L /,%~߰6@c ,K+=Q00HE=c,zMӻאmTHt".a K`DmKGPCz63 gYcDWN>6JYx̢}E΋nfiDv]'rB'jp{G |'Cq(H8d/zkͰ8F |7PJ"1Ҭ-!K̈́In'8͖/9ei 7FB|ʯ׷ -|Ƈ;QβރFC>,oEiXGY { owcV(yu& ο'>s>+[lg9_I@=;h,m|x|۽F:j?PMYFʇN?OőE?ZLFgZ + 5ȹ%C|yƈ;185&O gk衫?Z#_*?|Q6=Wרbæd-|[] +/ 0bd!|FLD"Lje>ɑLt"=y;Tnr*п8* 5 (I +Gv s +Yed I,ji} ^ r_;vdY-Cqqs6̝An?=9"-w/tcWC^_ =xH`cZqa:Eh ,C^]4n_U_;Xw"2<`ȶ9 oPdn"aErRik6@2 +q29H%44jh2;1yyΆ: S\ .$OHND]p@,pd{4 ^`_H#g d@";= K"ۃLp9Id *׫- =J43&ӛ@$fls>GFHtF?*tZ"-#rм1A1eFn^~Btvr)r9|0Dŧ0bRWb_=SuX +Tp=Ty:t(.@~rL[\rߩhԀugEcϥ  %ݭ|X"`er.4* |#z)e|$qt'HܝO{!;㲟6ˇv@)fW\! q_nlZԑvo3s>כܭ-1fkyG ҫ]fh(u|@1 g }'Яlq~ l2;ԿӸIG M&TaT#LuIJrM=X- 'b@;o qtə P1)寳ne!!r>*_HRXe* ߺ[r\=,9(3o yir JCSQτpx(ۜde)L/ +JGb)D$SYG!O!Bu g_/bYE|Yp}rU@O*2N;ZV O 1ؚDپr}%厸 HB7,h8H`sLLib8VY%y(I6b 8-Al 8) s<H00cHq#(r53ZSUA\r2`98'{kP28e7zsȫ$0T@|@_+VL0S 0L_,Ɇ'­ PZơa ,^؁$Oq#m7C WjRΦ[eq_<.@wǥ&%S4{Snll  L&^b0ԃ]MJMMX"p-]; &fSaQ )J&J ){8$]2_OpN`JHr}Y0%yPȀ$M&>NxVH / += < +r ą׊O񉰏M .\ܜtu&8{g~!2iIDR\_yj},+;r2S$MMD6*E[ 6- Z(|$-*3SBp03 r_=ESj,VQ28>K(ZW% &.,#3;Rp HS6-y̛~lރP8H;Ibs@c;@B'o\"]rO@v(LQ蒋xE, ? Yr"EZ dNd<([4-]E゗@*-^-s28[fwQE+|n{ܢiyqXI$r`\%q|r5)?[T3ECt's DVZ|z1%bӋ4S䲋n>R rYC+ i29Y@Y~4L@:g82\ +S5e[,M8dEt=JَǶ?`.hLQYAGI:q4#7mYneN"p#H[}n4M6gMr)uîOtc,h܆kY{Hc(2 [&rXY3L^e Zb͝K.ZWO \́: uiTfElGf4D o] 5I|v_g_PCu3( mkrv_ɵI!ad{'H /e )iRVǐ) OYu>RƇEtvNMyQIY.!OWrCZ6m:n'N6 T'r嬐42>1v N +'F:D2Wzg Sz޹]JO0{d:?F!r(Hw3W~RLi+<03AqFjzeUӧZA9ʀ!ZOl^cn T8+&Qy2_4ɱJvE6\)pd|Ci ;)vˉ&X.y2'~Hܒ[eGB06؂xGV% :pywIWiŕS)ٜUd,~꤭TpS.SƭRA7gJIxC]f +QELْ-htιb[ bРPC ;2ˑdPYnb+Ct(d2uډ0 `4.&DUXC\E@[Y~iPVW_wzMA `(NvmʡMzGA" IQy I*dD+h{ںm"%!3@wkbKAUΨ@9;Km.a:sz!t=ErT%BgR':ԋ,Ӂ<nr "KՇilEiTSg< ,ݜ _|EH&!1XTJ΀p;{X+|l[˭DUX(]h(tMK2yzU&@)S􇸭@˶[ lv:K`Պ\~4[ɒw, +lޙey72L +:=]`PY?t*5(P6)y`FPI37~[a)Bl-46S DL͇ tV2b+ +e4luҜt@3uV"O sA^"V6Cmk$Q Va=rD?SW^VJ2db6<=Aٜ䁙 {ggrclCINho)}$BAD! ]eYAe$T~rXG/C,UR u'ĉM%cwu̝,Vv6 >50/u=TztkѦRףMG.u=YMiTzhSѦRAGI:6պm*u=ڔzRףMGJ].nm*u=lWhӥGJ]6mhSaG]z +IXJ]OW_ףMGJ]6]z-h[ѶK]m+u=vѶRףmG.u=Vzh60юOμ\  حʐJ@Ft X +0QTx`!`PYWH4sCb?{߽ƍ<ށD*uVޭfDM,N?~ ]H%qr#At3RѠ YapH{#dQ$; DY=\F#; ?+0B~F90. #^y,8 *,pviʠ Z90a^a@; haA(raa X8 B[!Җ a $A'Yր R)B۵#spDAj# ha@0; h'auD9 B#LHuި@V4e#@'ha .,04@U-J0߀PoQ; q4l2)$ER8J W0MGuWEfQ)d&>$w!A5V#EM@iԫZB?0̶}GoLΣU]0l5:{2ˊؙ /-b@'ieyw}`rE8(Ra-YX>V-a R#TVEnpd}`HB.a}`&_@=H5]}|{wt{`OT{L~I2}aǢ{ȵXo/бű +X.y" DC01d1Ѻo{[a;;"MrHy`OAbOB1:<[JpU+` :vm}2jL`+RXxSЎnH fY&O4E@= +K6yFCwiVI ɸ9@.G'lmcq ra"f"`fX"6*9,Ar=Jqǁ}cub q`0M7ۤqq`q wXBw- SpXb;t! 1q !T8Y>fѸH )>3ߚSi}AT: ~FB*yN=tRaץ_C)c3,exp:Æ[r:uX ǯou EҥaJ!,cKag9\b1K>aǮ"~r;JRp_~ 8T\12X!qwavr\rZ+kg#(m]QİH +ag) +REKWHt,'tR1-5KjʱCZ +W+٫Ur@1HZpT5j%{j`J%`s_Zr, +IQYB@vBH4{}@dXbUPg(T9 z6Ơ7U 5`vOcىkXvмdX3j$t \ECqNe'Y%U I('  A!ez-}`>M{72Wl0u>RKaH*"^eP(4<k^ehH#Um Ma»V󦊡G,^86?6* nV*O?&OW&ev]Y7 Bfj*ag2/,MZx$pۿX-p<;UjU.˃WOḫU>23xR fD'Bh<ޓ6t I(CskAtN$~g9?hp8!MNbhND"iqiq*T$g9 K(MYthIE +m,P9THju`q eWC$-'%4}ar 2iKmnTDֈ6Gg;(Td'+\@B;d6)Q&D5̇&S +vP$B+sZm;iWXM PIA^hh<<;.«nŲ!EB _7մk$ !Fɾpfߡk*|A :g ""r!\Y^LyF1I1T(spI0b+eÄ:>"=f];XZg[w=eMID%,KȻ @_= CǏ"_S?3޸dXlyC +1#*{uyNE!$s#sPB3ix/2RBG F4ĥ??L]lT +>Y | JrEVy0-D %PcX +a4t$SH>(_$// n0!$r0?=%oFCU?^T9Ldq\r {W_nF +yR`Fݲмuׇ&2= #[UȢ$x ξ2d7R']KR{560TρV0kF61#w2ER?ЃcW ǘ)%Ug_JsP$*'7b]T1~߆zE?P|5%?cMoLч9l>PIJNɱ>`u4%<2<"҄0v` *C +z&bBeڹ=X*aMc Q<?n~nJJTG @(H#:dЗ:fJKL ;2p3 +"z"I#`(= h[>! PLd:e "#hpȢ QPe3)~F?h)܁Q4(MG +ӋR*8~- Efliً%3;~\NS7[kᚊ`5*x q1lu̶iK^~PujCPYV*zթUolhmT<ՏΓW}k[BT{:8V'XЯClkUjn,9H@UЬ14yIf` oA׿P%])v{Ī@~קw7ghӬQ\QW/hCu?(2χ$htL$O rXJ^ ҚDŽIq) J m[-Ia*?:, 3J4x!E/i>PEX*D7ǞXv&x^ovxGEtȘ +? +@eDrL-A)a<^0ʦMivW"jL%|9B/ s!=UiHRfc#z O猨ǒ2#r\]-3. 9&0/,?].5=pL +[|,*2 Y.x916qM7f:i6aLsãH˦HN1\ |w5t ܢ|5]P^m ϶U@;]`쁚vKcE&b(NEWLL3+S $1=f\a㔉L"M61 'fOMEaB6}8cdnPT!.uaGEA,044/, qU6ЀO[f:Rzl 'G6h_Xr`nQJ=^9 ePV$eQ@\HL"+.⍆MzHJSECu +)G, I#d Ic&2u[yPL[.(,06EE $:)t%M6aI IWP=CZ.3lM'Èg76M C^JfcbꐑT,C" DXdIF$K0Yߦ'?#!"ب?1@?L,|;x6kq0<)t qe15A$s䖥Hk\яϠc1LKBG.אT&'khub@ Uxa&>eE˖Q d6U,T\LtiiuG/Efa,(@ Sfٍj Wa.Olc=VqprSz o1[G#"Ƒh0M +Qrbx̥J(Tk%aD:ה#K܆)9I$fuyLAZgBH*trz?ұR*XVfz6syPs +G+ GQFh%:L3"DeL0,yc + R 3P@‡B%g `Y$nkJ%<].=tt?EmG<+ d$eʁL(h,TEF w߉Y?,nFn#A D]LSD.Y{C&KIœ6p 1.Bd8 #m%\FHv.1K +%\tsm3rz0\_TM2a4j4N><ȝDkzR}MC+܋:ߧa̼DŇ;e3SB%ݏmvZ܀$$W}JeunV2j +cxxn!͟"B"PELQ#9N p)RHJa< q`\ r}Ar@{ɠ…uy.kaHrv9ǣOQ=st-qHPzdkZiJWi3j<E0,Xՙ`DMݥG*Qsf9p鵰)Rk1G1-.OLbw"Y(*׳|vPb/e11.iPc`YT + T& V`ns|Qǘl*=S/K!Y +ZQ9} c=᢯۵\TE<,@#K5r!~POސphPc$>pK"Sˀv #Π@ӐS(9<˞/a`K$׬*ۤ=| vN{ihPQC` e v̞ˢ: a@ع2x^jCh1NJJ0W5cј] @8 +/MjePUMyp8Pl!aj>>9':xy@Bߎ +Gq U0uzU85GtϹ=)MxjwjL:bt\aⰍ8z +&jŲ~%vPjNS:ssz)_j^3c^:v4Xw.H[+6u g}GRc;]SK_yRGD?jNFɽ:uQR5FWR.ZmQcذf;JX UCdL%N$aWQZAt}%f2;G-ke3i>"RZɰeM +R,5jZ%-S=Qcb긅}<9E&Ǫ@&8FMe:At5.ܙQ1~5M^l9ѱ-m0`(Fo+2`mSČĻC>7hA0uD]OjɠZqPLYh v _Q&%4 Y|75`{gou;l֤/c&3ȈC dг2~įK9ku!XzcX%yE.ko`gR;zȖ4Vگ>te"t\r^BGzuu`wUZVGV1Ƣk⹕f9`8(A 0T]U13mZ4" "߳PY"J>6C#%ǎ]g?0 RX +b+XR:+1ZiL`ta{zs4$Yt#qdNb +Oh@ZG66t*mK׹{/ =ui{+CDLrE`{`~|=u,pu\ e*/3X_È'·k/^A@|L,~*}@m16TawE1]C;2kETk5˄ϮxR_Wm˰_P +z9T-RX0ؾK/Rz`TZfZԢ_H"!0Ų/ŝl[O" FMGC_jYz a<~䏛cx?&[ fkk쮾/=:^=ue`jQ =w;Qì$umx _?(aQKD#5Lu㨶kQd0ܵ1Cu#_cy >W2_pM*1b(ʿ+PtL E OtWK矰 + +zǘVVz~f3>,(JQbFB/mB]Ō?i!}EY\ӻE zt5;F9MS`2\0)A LfHO1፽g٪3[_f>Y_:뿜EjCu^ɝj^; ,WTC5Mi(庁]2]v$Ό.up0oVq\ܐK~C5@M45p3$c@ra&5:PGELTPVaVw1.F4u ߥTJFT"fa> 8 +@4!xЧ d)lډ mF.o10.Uǵ&HvS0s[J@tҫ35VU PuW0[FU3eG xp^?-39 +ZCW!P XzT#A#NM¬F7B zs~pZ騶ZfE,H:iڪ)&4`ðCs lN@j*&¶0juA蘜NT. ʔBUQI$2,1+`ֶMYa&mjL7Lxb<3Cp1JpRnY]>u@Fg1r0iPxDJkh"k4 1 Y,bO##PtUt&] ɀKc#J*CB҉J=8 ]"R+1(&ŹȑlB ٤ nb@|N'4)ZaM\,1,@`H;nD"`IXRcb f lrb`"WE $èDW-݁ +S3=1vj/@h(LS5FО\҃@kF`6 3} +W(*Dp)%߽5^0>7@QP?1'6 05i:䮙 EQ@0yн[BKjN101"Pa.*. ؄;1A f!Hz)nB$00,2,DK gиL2]X07 AR[gdn "'|"a:aT"]nht&fvR9AcA +N7Gg_4a  P"ʰWA8B*)i(/f٭6R XCuSa~O} es?XesjC(f 9g0i?EUO,v`Nu0J| 6թ5+:HfUcGcyz/17ErՄ[^uJs{lѫϷ*K:)a9߯[Uo+z~NzNKhKBRK^xMVGDO⟞-19>~-u+R0oR/bywD=o?{YOD^S%xȺD͟8-VRw+ܥF-ꁺ=:5*?6ՀxYߩxYt5)_m)C~!+u Z?m~{|VQp%?ʡʵf'5{^^|̆k\xwaN]*=ݰYPfZu|2G*?FZd#ğ,ogJ?{6v֨A)skgOJR1U$92g\8= +esE.U9l*z' KZ7RԠy!5nZڟqf'ZRx=(Q՘XUmK=/V۾ȣ +F0{TxR0hC34gzbA2N b{ݖb^ۭ/xWRؽW/v3Vz%M8V\ xsة*k?`jG4 +~[H4^LRf :/L,&)A~ 6J ,&_j>q-a zgūX^k[1 W`RvC¢>_EHRӣ?HV9 Y;܃kZ6LDRwUb}'ˢAiJڮ }^>Pg00̫UiXŃ%%V?eܱ_xxR왐?f{c(--NK\FݵFC ][3YAVB}?@3Iw;`Dfrv@ ѸE+գpNA}>xt9zRW=%u) ѫU>2!ޠhw`2n[-,TzD%I!ˠ){2GHr($CEnUNQi6wJ)\X3|P?mn[+D#GԇOVy+Za{d5C;a$^#ʉh ZDp"@'[#ԋc\՚oݡ_*I?< Ѹ̈]״[ol-u.c1GZǡa| WnN^̷'80zWzTrggBUSt$X61KV?BI +sBزm[SVNx~5 [f0%uId4J)Ψ +gn\OEVOe=QK#:Œg`, 5[r5IE7bŵ\\pݸtS+=3ٓ=އk<I9ʨus9^"%>X +Y17y+I{"RUG{iƑ|!YScD[5u,SaLD.7M띁΁ְ602z- ;ǝEc׎(7K5az ɱlƝ[ieR 1bܹV+;9nV_ KKw U8rKHcQ.̊yx~ CvԞjB>::ZxY"4\411o_iK7F9o?QDW];g?ɤ#`QxJP + 0 +[C(θq ?Bf? <6UmlɱVjBnS1XcqUٚjh`W^9e2x*vc]aV5c]frR\bﶥQξ6:1-Y8C1o-4b 6a^ xZX 6ۯvԞA7l&Hfz +uc+FLX9tja rG6>:_ۗcUa;ͧ5"bL†C\k^ԡ0a9ǚRpMS+$d*\7'Z˙tjMlMΎc=a8]XZ])]/3Gfg܌\N[kjybkX޿=+v8 0^T7W󛫋fwO[Hl;n/}jxgz%N> _|1lgOL^֭~1oL_eg&'en'6s;SWE¾ZSvzY]Sz3 ZpKn+뤉pZϾY)}E:/VgO2Pʓ;}^X/OW=V=X:n@kea}7x?Wk+/GJ])V *3#a}T2/ B4;'K9d5v?cLA獾"!4}x :sζذVP%xB+CD.\ffra,\m9fc/.d[Cppb]M$Vbf]sl)5ϺUnm&3绽 (#;)]lu'eҵLNS+&gsSNgQV0p<mEԽt~]b69{keӮ{j1Wm[ٺvm>eϧ"sH,kƒNVUkpzjO]wa8@dezպ5 eXV-4Ov?Akb~Xmd>jk"ivʜ7/wJłsr=X]P +w>8څ֡Van6# c69z'm`}2ݜ5' ?n3Gs5$2gOه 8-/ MH,G~廏$zVx^Y(\a_O/Y:9[lj*.-U{{۩j_q-MV`3*iܫۀ>mg6ol^zm~j^({FTʞZͰO7k.|^Ҧ\>g[mxo|Ή_Ӝ{LmDk1?vm§/yV+(j O+(| i~jφM '(4Z&_gwFQuD|ʃlp1y!B sA*?l +(H `4{(zyk mԘl-%oB` _sph-^-ObUW+2 +1CO}yU ,2X  iXy(P 75,]g#ޮ`Pl2ala͐d$ek߿:a2,7>h9ChH8MT) @cYG-V +4jsfӧ=P+9k7Uu"zLZn?I{+q|py-DYjZR'$ j%&d0Dd.,{YkTۑ֔i_w/h UBjm(G/s<ȜvdzqMQq:_lQ.{: ׮!ZXxaT.N3i~3yXs~'wuz2Eu{uoeAlߥ}!=vo9v!l̶/Ilv| (Yx1}[&oC#Ml Kcu樘r}VgoUg>pr@?jY> +0wdYX?`=`AQ;ͽ,jk|p +"b`xSO g-6K]͞oZn$2'g\U {kF_celA +{//o=> +̺O ?4쫶~rQWICߐQ' 71w3 Km{LFy(Ac[-o\̦%'f'W_2`6uvQD­[O0Fk ; Gq<*ɗ ]& \;'ma~~XRf_/n?>6"ܚ,6s5ȗjjMYo{m8Z3Qk:Hqhd'i0o=I+;D%kz\z%˙IWIKZ1m3S'Ox`s4ۙ baϛb|~Q۸PpÑs̸qvq ;rw8Um˕g?-r5> +e쳩\\M熎fY| + MfdQ`)O@g]U42yrGNp|ln+uʽ=4"tFzyOJXn-sAFL:6xnYJeĆV\Y vTLm&MYĬE͚|6&/~TJ_-+'GǙ6(PN~Q6`u WOb-t +m-U +vz3WlcaF$cv&G:n`(Pa@9uqF? XڒMNUI8hP~rߩdAwعQ^jjTȻ}a,Wc;SUĻ#HJCnnF聯C_5t0Jk^VbH  u24Ӟz{c= ѝ=|$U9?+l*eTz}![ĶbǟK|?Cǒ'q̦f\ue5Hㆼӓɬ9W\>V]?Kܒ~>šaw9m^ea]/,g޷F%`콫wkm}{xO># oO>޲4%N=ħU⸺zXLION'E^V˷ bb^W+|znZ :>w|n?d>9B?m箾R|\\Њp?s/Y#CIvۭv^KbբHțv)ӽ,mZ+A&ni 2 /߶k!/VK_~Wk=nj:ա'o`̎ˇ}Hw_kr|} UR:صzg%l!?IF͵/_o[S)5qb$^˕?qLz_+orcWNZJ1RK +2fڰX%~dDor$h x@` LBoӝep<)Yra*v @jӮ6w5b:!Rc"*e`#)d.3l<)ƸQ}u˵^4|;AO:{x%|k2 =qGRGBn+Aj7Y~/|L6SF4>N z8j] wAQZFvUPw^Mx% kt aȤ_|@@N0&]+o?Jwq6{x2|8ݗc%>i.(}`se(>yCh(޺jA@M!LI|NqB=>oѶR,%:kٳ}}0\)ctsh֊w8G7r|<>?;'w''_8#Fk>LwyƾÇ tg77/,}-|՝ z*, +}8'z>$'Ռs >ͭl:VPOغuϗ+M̧OS]Rb *|^KqͬRWZ 3F{1tjdq5Ϥy=:ΜuBv^X' [42mBf*w-?}|TOc=6~L$/m1n߼OPuD8/Y N.<'^O<8+oSdQRܳ?3əb0>- Hwfܟ]Vɍm|p֊ﭤ 'e:l7oQz+VzN?9Ldf&/ e2M|TJ+zИHL_w'rnr}:ٹy̽MɝQ<4'/z7 +sON>' ieG]@dفQzYgzjxRg8S挾04Jݩ+OS_>Mwϔ݉1ue-5u357;u'JǥΔ|֘}HL5Os/SݙbyzaeZY2m/^;>˫z&5}peN.vצ[wKӥ駃tNWk~b?{PK̈́,$VgY,r8[Kd:P}KTԬėljS1Lzў1ɕcvfIN$f˽̧LI3Ϟy;_gٙUj6-]ٕ^˘9:߭o^Ւهu0ynn]_'Our,Wͳ]b%{ٽɹ٬W[-s[;w~]>{sse|zvj޺Ͽol72*ߴyo_kV' bpupY(Mv _BoԞH,&Zqpq5պ],tţJwjX_| UjyJ%Rr*]Oԥy>]^ӧ/'%=H[3zz .Wtib;]m֗&wեiyɩNKrO_th.?d2SʆY**)9OtSi¸jb'?Pù%ulE))EԲkK-Vh삶*ԵÍv=ܲY}.-c3?_vvWw7/ώ1yuL$^nX[gݛIz~gx7]Owͅ^ٓV.0/JY1mk~>a9m]:Or=Yܛ{ΰlwZywm_ko﫶D9cf8`L03:s7Cml6F;]88|x9V7s;ͥMNLNunTs]-t^/޶bxV:<휜=?ϲ$?<˙~^v+/ޫr_x;x>\?~חُXlgbsxy-5793Ȋ_a{N/7}uGvvnnT׸'wS\VWǽ3O"RA֥#fn}=`F=dQ[YD^H +ܲɺwةk䷊PT'x_5j7޻vs7xa/sfag鏅`Z!Y]7o_Hpz(ެu_w)r 7Qzq"T[@Ɵ$eqo^vs"_,ˇzoO/՟T\^y.U`鹗W i=]$t#ӫZ~OK-X\]Y޹klyNy!޷B[KezW~7V6~h/qwy.ϛgͥե pI~Mhߪ6/B}i r`^53ol]V H7Zt~m}|Vwz 凱)T /gX9Wr9C awU+WҳȤWؤ׀oZߤKoGNzMڞ{b7b?}|˟to)[]l&-.<(!0f-^S)N5}?͛ThԽI\ijؤBk?i]/&s|iwYT#H?ճޕgZPjETNet TؙMz׻&MeoWVɴ+9lҶ}q͟tq*=2)i݊|n7iqqa?l߹Λ%rv!47wj~eǛTh~nN:mIau9TO{&I֍޳RΛ\9V}?طڸ|o&= +uSI uemYM*t>dRiɤV>lkac?f|\1,dڃ-YLi)JȤp~opi]0x ]y t]8VIakڎ=ΥgC'=Y-LM*-u{~(专^OmN>`&Yi/U?Nq;| tP!tkH+)c&eeҟulOnȤ'=2)h\ۇnq{I炜zXnä+}vҚv\dDaFFoÞh5qrPfnN?IdRb(\NI3ơ%NT|';=/9/`ڍ4^Qt'mZ2ן¿K޷-V.}5^Bcq+(a:+  D|xV=}L9۝oM61ॱׇ;sZg||:_&?¿=ٝVy|~{^ÿzx1vSN-(j1Q9.݅R(5SQ¿ݮw~B 6=[η73[w{V%PN%U? lsftzX[lԧQJOݕ [k^6= zZr+Ky8ƩH}MI٥ݒe{C:-gaO"Z9ʖ/"oRb TNeӹMzv:)?r(?-z:ΤztT9ѻJԤޤYN+&U_O'jޕ}ZbL + X!݄N +{jh{%Ȥ`Mq67ey>)~RoܟJTX)ׄ# +h8[Zc˓DR F;^XjNkRvYXGl: 1?R{$=nwZTǸA&h~L`zvg:BOP3Oж(tL a+/GVy3ϴ/2;w3ٶ@ɋ7oQ%5K9¶혋 +˹f4NW PYx;;}'yB4: +ݷ0 +'K~7X"bW̰PN9 )1ӛ OC# =j/zqxq6!]xY( ⮁:jn ۷\q+&_psҊqVm-1[[ۊؚCYCBl屨]6g{^b6DKBws }t>%H I:1 Z<-m.zz-gVٺvnn|{T&|0ZE?5YuXq/E]uz~c@MɰЛXJE @\+BwpT ^s njK +d廸`"IJ}GҊ|Dz[ba7\c1biwc/_±"+*j΋q՝ +ӕ+j- P] +A/ڠ)w333VK#c!Uוj0a'1iØmB :m1{׈JRIci+9xm,||n=qr<3L\[;dfY Ǝн9J*&-uBbY϶0H 8wSGEI:miSzSfd/jjσh0ܰ`m=Թ0\Cu<_Rpl!6 7;LJ[ֹt@KFf6Ė_'IGWC +O!!>9 +:RC*!8}yeqϰ7Tfb ,On-Ѷ伭2,[#^r7.H2eƂG">$ i>w A_oJW&b6c'1t fDN*V "{q[%It`R:kdXJFL(:6Ī0ʄG84(Т2 on]%O'e1Yس>TbC!\"%(Ѳ/áI%A[-OFLR0Y!^8l?J*xũ;SAF =gdgV+_$UDG1͛cM9L +ɨn!N9PT|P9hAq$KcCXl/Zqյ@Q 2b(D/vc[JGH4& pDX8CK4Rb_(DstemEyVЍUnŠAz u3THƤM,&'3N-OBf>IiGI%g^ȥ] F`1V^!|6WPUj FNb<0"\Mݏ>~9=}хk1'ʾO`1{zGF%o߇°,͆' a.n%6,Ʉ{ѥ"m]=~D0\VL)X&Xm kYL&BrOOvNg Bij$*%XO D`}OW0K +R^l[NxTf2X4zK7Ew17CAgex#衋w CAL..-8b]tHˉEwG롋UCA$?C)Hkv]xY,ɯb,O4OHAuw?bXN7O!mspt]g)$'e~E,-$k;ơ:,k=#QsIgŔHg+gF#=&r/4ͅ\r Tl̰Q#Z9ݵIJ餹TLv(fkP an1TfqH/6:#&<(^p`l gD5|D8I2,)ii*^2<Q$pO)TޕFo2ꔕtp}`+tcW(ZIKКtdjh.%M.;:B̨b#=cٖC } BPd,aօ:ebc1H6~_RY;pՠJd;=$LEJ|Lܦ5|O 3?05 7Nc$JP8ˤW<5э q G^qi qƽꂌIf[]nKg9WcW'ƔfHHG8sJTqHNhTGT7AMp2ԓ uL#d"'k)/Ak} "@7Æk(Z%l+vT+wA +_lRp$no ++' +Nj*Lҕ~0.a]"Fxcn%6js&v5aje=Q.)$t̝@SgJo8K(_1L ǽf^Mz.҆kYzYI~ '58g?4LZ_2%͛ũ٨ʥ26=}qvaןjEu=mN:+n.KJTgJԢ,%9Q.JZd=aSU\2YlglE?t7I}.村0]kYFlzXxaOMznbgRP}έշ F ؐ}򑞠5yaUoyTk g~^$1]ieC xa+&8[i]'StuCU~N +T5gj6$oC&|̏[#䝣ipWüO:Y.HZ&lot&fw.Rwr(G2>N% {jGL縪`Ma=5E#w>aNWuM"KF-d!xdZ#42V7 Zb0XWx%!ƽpr޷D3 wZýp8:FIOp& _Vs~Op9F;\c 1s|2zcIWq:KhQxѬ!kq`b87( ߎ'R%aM/ȆY|\+IЇ֓41|. nz칌|,mO%tozԡqK?ƴpǥ!u:T=KƿHYqe/:0_ʛ\,q];}.26U#]Mes Xf l3^/%}1|n"=:q v,5$JH =wx.jӮ۷y +wV@+ɔLsՉ$߄|dnY$q~l .]O. hO-ޭ L?iwJo;"c6Z9z#Y1ڏB7E/ѝ8XSj q|>0p&?q+WLOҨVX-n5}a;~{8 0%d0 +t,> L~ 0i`[5†H>H]œGt>l`Tf.=h䑻>p]bh- ^MpW c_yO1][#?,F&(_;y^]Ӊ?|ܞ?7+ccZTl&n~o\*]wC󮟷 _tTG}/U. ]WPrW4߸\V;&ԈpW7DrwguBuwxpþGɓy/ZѥbRkIKЕ6w-~lwQ#N_($n|w3Vc]ƿfw=`h9y/5ٻ~Ѩ2]p +)7LWڤWBm!&Y:R'!;V1Fᥭ\/iw_xwcd #vUȎ!7s SE0~tuUqͨ`Cjd1oopy%ڴOp7_CJ1s &4${/!x/Uɼׅ=Y{|_fxnl|w/Dsۯɱa~Տʼ_?~oc*!|׏ޓ8~%wmI ~C9XJ2u4*cne챑yȈwN]}o8}/rw(F>=wu[V|PҒ +ETh7ފ[Lpaf>|l&[Cl fy-06JٿI>;An^oIZ]ҙ/]Igf} kR6_BcGfcEh^]߾.U藅*, GoqE8ƌp|_v7ATY/} pxR_z?T;Ɵ[ղ魣WҜ1uP*6wսŮVtSl{(78bJU%O}ݥ3]P|O@vbiYYv+ƒ+,WIShM#$u;RaqR"QNY=[׿^Ϧ}K?*Jvc& +W?|z>sn4+MaOjKkD[ڼć4M\'g` n\sfe& <}19U>Z%κ? FYv=ٿea8>mj.㟵]E*U%lH[ͼLB'ï:ŵuM̷#zh!RC +ާb&.Lmb͑e _Wy( Rw&wاFcdW͑:I [gz!Web:8M2] ʟBSr'uf,kznqv+{\l(o^ewt9#7T kMfD2N՝gJ{X_;[aWC,wRfkȝnfAsT ~=ؙwT;yBt|Z!}'#V}ET?iۭߌOhy͐u5w>i#ȎvW!+ +N`Z[J~%>o8up, qijy1go*pVW͋4e8-@n͍Iy:Pns ( 7%\~#7g(;y֑֒-PYsD rg9*C(--[mO_li?ge;+eWWQdl!^DklcJ R7ǯ`IUϻze@uH}v7*Z#4C}cIUMv}<e[G9NyvRbYAm_3+2u$_e1)k&lk;!Ƶ +_ހ/Qv샱Iٛ wl7VYi~ +:Xڀ&b)3ٳ. 2k3ugYjbB !6O[lt^+գ1ЪΝώz|[B<ۻnz6{s_4oũeLoDch߭wʄ/2Y("[j:YykDϪspgKt,;GiҰK譝]<\(-k5#(&(pn]$HHx7~S])dӷ +rI=G RM=; 9o{Ns[q!SUH#2{7{GdXLig9DWpypQ~.>1tn293 PӪ6c횇zU&g;+#)W%rYo=jgz7c ~B~^#s[qSM醡uSWvzϯ_R (}=~7{aAm}P݇?hT";L.-!Q2[pVeٟ_Ɍ! {\?YtSlׄ4FX>T&|)yA}/3]qWv65dj*O$kP2y{Z~kԮZvqj2XXndE^8|U[ǧm-}__⻎N90#'>'9r%fV-g pU/XVe,mt6+. t4r*l@$5bb><| תl@$5ÀHj>2IʜրaqRDYᶎ9Z:gg%q{ ҲP/͟ebkbii?G6ݮ|vx=<yps }J4>_p# >~ET-Yٖ- B>R˾)ͬ0OaTY.`=v6[͒Ub9NEP7Qdl :/maS篪k ZJR@[tSjŗTsb0s|@ ~9W $R=)4 ';Mxϥ &+4w1)"Ch϶4ĺiڶOϵS~2w%9 +9vDY;"¬?uIo"av/y/a-P( +E:u?^;H(^}U~P[7zt*˥&PD!\/GPN+tBn'MCҢ R1t9Vz<vxcr6ƒ%[}UwoB")*w}^I6 +3˵o5pQWw{SgB{쁞ҥ3H} 4WvHMc_c80qQQxqvήL!Y avL~g/\H*}GF gXp>=7D:{r@qXY}71kxH/-b?/NC,s(Kӿ>LO~vJ9˞t$ Ym`4=ImXF vB?bKg +]f9+-ךshx9_jyVx}gFpC*/ݽ?u vx-ZBmwh~eLBہ/+нZJm-;_Wh:K$G$`Hh)THh7ˤz:x="DB{DR v&%#kK$G$5.T&q-V:6O-FQ[ujw֕T}G7amFS)t1 +V8ƀmtή2xi܈kx[r/@[p|<޺9eB;g1wDL7+^:':cs-,y<>J(dYAv)Ziol/IO5̛#Le2AwZs^JgOORUOO;o=Hen*AauVho77` %1z#}7͓ u;~t~po;*/uo'%5Ӑ]TS5(l +' dj(販Ț))#ʢKb + $J+` +@ޥ_67?Dֿ+#{?Ul QdSDʲ) O>a%6k&F*W/*6 `8~Z$i!r@f5u` ]&5.!rh=rXV=!I!P, ,$+ ݆Z$?3*hqpoފ vE dS1ȱ(H8. 8PRYmSPYJ8fa7( <) 8N7Uujٵ%YKA ,k /FѨjVS]I'')\! s%'W> $A-BO>A{*yZEe&P@@V,!|Y٩I77U&aI+ W4ѫ$MɊm'^9U6jn}h\7 xaPTj`l6ɠru`:Ұ jȎL> #(zd;Ϥ$ lGPh쀢c|+#1PK0 +UH(@-3(W'%7[`? .AN^<48|"oTPJBUĤ84y'cI]`{fX@f™usa2 +t:Ba~>ME`@ٕ YEx-@M' ~WPTкݴV0 % PCLUUl.["`=dYV)Ͷ$lxR;t 0hn6 R22@pU.0J`/Ө`8EN;*@;eM ȖaY^2]W7lZ3 `ћH@@.h^ Ra]^tjPp63&Lԯ@T@hxd0XDNFbtYU-N(@?{, @d7ҧt0B]w6HJ1r˹Phj$哺tcuvD،*M9 +A"5 "ɪCaTU)iؔ4}<ܧA ^ɅmH[-ڼIpjB  lvA EY11(@Dx(^}e^"YC$M6A:\ i + RoznQV +X7V1WJtLp# nSF*3 cNC0{ (SUlE8,ہeګflc[R'bԉ{-H QF zHT%zO.2mpWb9YCtaВXq7~FZD,Ӳ$:" +6<:U,a@Ny+M,-އ3޾D2P!dvIIQ;= &YDM X|LTŚʢdPA3HFR&P4/*hI$;$P;c" Y- j Rl}nGdr2 =`HI)#g8. U;3b> 0 ; ybE5 +ZB+D:0V^s#!auF- vD18Xh]e :|;QEI8l` Xl\sk  д +ΩE!#@VAog0?Vd׏ ۮmAl$ pLvd<[& {q !C'>v[$Ue*r>O0! !F KlbeE]hA@qzTe, +jOD%$ʦHQ'fQJAfX MIrf2ms+ד-8(0TMDIg$h`8xnTM%_}2d EbKu7,( ihΠ;UboA~?Oԝ#a`C씘@ `S,SNUݓBa{} y[P#0@*NF3۠ǥfwZ$ :cӼ"`i_e\v.4`kHaEvܜ +iђ6P(n XJT♕E./+/;~n:|kT%Ƀ +eAbc"pt.2 Y>9PqfLCAt9Vj*T";F`G%IӲ泍Q%8PVSzP ;Dsg^8PUoGaH/ [ %b8 @iѭM2U@^VIUL3mG|2Mw1pW,8c2n,U_'Wv0d*"0x^Le^ln (܆! ,&-t BVI WfqA] +tP$"1H!YܖG]yAҦ Qx5+nR1P>@#Hj@ /;YvkA]; )T.e]"ئxE]A"ӽ+Z Y(|4jM P4^hz-lx+Xd\fZ9BQ"("T<3Xx^K`|( #҂ת4v((cuE0| +e +6_@[ H\;ŁTll4 +\ ؖU:BqX5؍Qwhzȑ53#i3Yb" +\t3qe` ^lKŊHu 7?a`lL +"P`G²_UE@tu=LQ) ˊ֬8/ 4ur^0^ +sJ'l -2z"%#-ba sA(o=j\\qE%EV5Y!87`H 'b6Òf=O.FY>stream +%AI12_CompressedDatax$u%?dFmwm""35\#%IjL6V.Q5ꮢUWS}=\?""T=-N2p8s/8~^~Wu~Ż7oqз_~߽{˯~۟\eo_^՛׿8xw7yT>믿{޼g?G_%*o8_xů{}o݋W?A/+~kֿx}Cˡ|wz_ѹ޹zѡ~ۗ]/yVrʺj)8]lɕWwZn|/_7_o޼_>݋}7ogBӗywwto ;_/-_~o~;<nȩߜ*?߾+,y?~~Ƿ]smK d7gbnx&X-9=-^FCht\ -ayn?zo8/߾-~Zoۿ^yw7_yW֟/;7|Nۤ;`N/0ԛ+_0%q0/_8/_ѣ|B a |x1G@ <~טqxxLz{.M` Wx_mmW_KCzwx`=o>X1;<Ř:כm7wx<ͷ\zߑ*qry[~W .Rl`s[/o/_gFAk_ʟoyej^`"xFP`M3nݿ^?QIw~7W߼fFrmx3VWܒoom_ܨot{msr}NEvO^5(ݟ7߼u7W߼ݟ{94_=w4WےɱBw/ם?R +>_^`ap/xrpz/~._~-W֗pz%$xgP|z<=ܣs쥡Tr(UO'2#xFi(dUGq8(5yV f\qFCs>`ZjC/J)ʜ'Tr!{>&$k1pР 9ꡬ^Ԟq~ŀ:9!AL? ]/ߢ~7J~ɔu/ޱ^b#aM싄]Rg SN[.b ;bGثGLNx .u( M\zM;gg; 2v~TnQ=#ŽC=7w%?b( l}:2>Z!ǘEJ%8"M 'O/eߴx]=x(yCwg +֗?NM\Rh)ڳ6%iJ8@pik1ݳ+ofѴŹ/5 +3ݻw#gܼРK<N𸭮uuΘ7PSN\¨웙Dv^7|]7y"嶎h^_OdlYee>lDvInnmm|ӫj3ji3ih3>yUfsf5y.Z#nwFa.Oeat ^B܅Y"Fhj~l2s]ͧ.9$Ԭdv,J!q*^qxv*V̍m ~,v]U$%bU^X,AoҥJIӄL,V&m>H%s[ϲ{Q79r?K!22T<4mɺF K(Q L~)[q_|Y.|S^I¡0a-LZn4,nJyT>/b3JVҶY4us4i.l//˭Ʒ^6}9mup:nB"=D^Sz*sJ(;1-'يkGT6iNl,TGͷ=4@N8 &@uo-'ȸ6ȟԏ!~g`}>N=r}ҧ L;4pcnfzFk +F6qŨ.~^˶ee +};W-AJ;.񲘒(>ǮV&xͳkQ=,qҴ7=vgxn+Z +:VkAv˪iF% ̓i2Wi]h2d* fiAAuYG=.3ÞL~9imN[KZd%s=Wv1ÈAbali.WFxXWSj^ [b5dMY,S_[l {S>?fӲ(rzedc"4Gڊc6&佁pk"=do" b% +Uic0l&872ц8 +gHt=e0˿fT"W.A@I29]yMO>"/x4 !Hqzgz %zK螺]|/e +EbiHǘK粈D?=xx ݑex~+,gv[Qlnw6CAbtˡ-e8ΥmǾN 8"%; +վr$Rl[Ud3q k9m$Mcwg.wJ j2q:ο>];Vn@ӵ Z}Vg+lEP]2H)޲=<{o' +g0ESq .醌lZW>癅nK]|'osvzO._[ZI/*{;՝%fo|ߍؖE=- 4fY1ZT}0Şd& byZ\? nV2Y7,FڙenYo񉧝,a^ցUa:[i)1ESMڒd2ܿG|n>|]5l{?j1h`ez+ VlcC"AZLl@[]/8Q|aۢ,yJZ +RKp|/-Z:C|=՞ɉ28y1-ʴٗ 3;$xj<^b5ԝ)>#Bo9&116 +H54s,TK9`:9+(Xt=` "~BDCw +˻boK[iP͒n0GRsm " u߶SAoz^ Bi|Օ p;W'']r4T1LmaCԍsЃ吊|{Qg;5$Vp"wB,`ZIAWTO>H z6 UyK4etӂ͋Rk*K +WFM:iڶLE\QnlU@{d,x}(y)Fp4~_hu\q^ܯ]#>-q3_mKi^Ae񷧋R_כqfsבD-HwLl=wUrPtnu}..ڎoo.Yezi n?> Xb ݃1.QyrtVxG=y #p|[bg>Ə:4dF3q{7 FOhɹXT޻;7aA2ƤPO{tK$G(oJ7MoK0rU[yqzOo.;pاFZ찇5u"pTIda %8wRp^sFB2<r;Ma RNQ3RzNN3PKi\ý;#̓&1uR+ YiÝ_<=m,Ԯ ;;}ܞ;XŨI^޳;:ХD}+aMȐѾ),홥n˴K,WV";\y\ "sd'0Դ vymv,KWCyRr(O7<;`++KCp#M#(t0_npUbn-@ ~U/>LOT<vLKp0;T6ٺZׄޚtq\BdbP+>y.nJʻ6H油o &KΝ.p9ZݕrRu{MwO9sdȦϑM#>G6}l9sdȦϑM#ȦϑM#."Yr4rSOwz&;'}ObW +"hASe4uT ƇS=,ؽ$^z`T[B"ԛ7;O#%y?9,o75=N̞xV?zfdˈBBC':ZLا,9o;#?u?601Zq&J:yw39^ƌZFxaT}@i^p`׃=d1,KvR{U{F˰}?%+c5a*M .?a^p4 |LF f:K uwaę=Tp} M[hzc"֐=hh㈎ xhMp[@ 2a@啞=gMZoW[xho6-b}&C /%.~䨺>9;L)Ս <3/7ŞrElaa`:*6ųCgM2F ]i^v~ڽ܃Kk(nZ~uS(d#(i ;*~LNy[L_n? v$o<χxn9r̚']gΛƭBxp<-8ϏfG8>)yqiŕW<_YU޳bLuThXƳ2&cJN !CjbF@o$b_eǃWO3OAA'tUw_ײ~R8q(wm e;Xݵ~Z𔆨46'n|`+OL[Te^8;c*{ە\CcXhq} ǵcuk 0(-,QwK%%|GKJzD'%1ln`igpq` ʣfKm<qdzIJ3:oϕxw ^@69I ` BF֔@t%Ank(zĻq ͳwϛ9{Y~!8,TXӈ!AbOWPz @ nKKIj3-bMؕp|q:"9kL˥pt9])rlyfٽ#8Kuf[=)b:؎#/|8QĊrtƳ bX~s?Biz䋇tbFΝ름aH'b)EuKB43CWQ+ɋv8c2Ch_[p~(o=iVo۔>|ɞqnX&㒤b0ƎT;㡹z6fIv1XP9ܷ#Cֹ[~ZВi]\ { 䱛];Qfg^!LO{-6_(KCeWQ%ZB^Ny`(g?tc/7p7fGYp; -iWo܏_G'mUؗiEwT˝{BwtSW"Ua2`snݚo{)h/~W®\ΤEÜ6jZech&Ն9Ǟ>rl9iZ68i=6g=N;vrJǢv,mh;nv]WL㈻UmŽU0q#}q +޹7ʪ n hrZE,دe3oc.rVbV +L oJ-nvC<؍sbK9*k{Vgzo&LDP%-覡S?? F` ,\Wy>wYqdTx37~J6.ڏC邏/6OzYeנj(`?c|ⅹuV)0G|\'{xJdo!*2"W9|S9յcBR+J躚o `⯊wg^;^1_xuPOgHd 閭ߢ׳\kA|cDNvW >Gn? /w@}cWk#^;=GqF:&)fbb=Ļl)LH=aA,c x\ߜ@ 6[ .ˣ΄zKA7GOxuz^dW;+Ng7n2TlAFSW$uOݤ F AGI{qq]vcboEĶxX: M4 {mH4#vHa=&郢ZcxUW1RKV"E#]bHwQЈǍ3:E-VTqswAΏ}PE~N=<ٞͱ~ aFbn0˼`z9+un\a54!>6]T#Ӆs"GM.ŷ% H^cn V`#\rd7gt&"tim˚=tߏmMmm>FFJwZ8Cq/}N(ʊ5(˞=2`vc\.e]ָ}snc}凣\BppP抉n€EoI7rЁ煉rql6\?>r*٥,YCR t_60ٞE]*2& [/Ems9>s9~ `]w% >gGnCE~u'si2mn䥋KInZ:L8w}GTɽ󡃲zjuBFsIc@Â؛7}8j^䙫L1.UlN AIJs"e6퓌hNf>nV𿲹yՠ*نG\OJ+6SóӟirSZs{qQ-qxsXqqPosXKw;]ykÆ&c]6cȻǞw3}Y3=t,>vvNnf7s Nb%zqhC^c5Sm ˹|/ɲq0O3Z󾍡r6^9Oǧjn۴sM.-'O62u0\޴\Ib~¸B&D+(⡋d3dyyzrƍŸʈ_;=v޼Uj,w5e|Zj?y(L."Y tYm(T 힧|:cל}לG69 e:I%-zH89YeVe?K*+}=SҏkE*XM Yx躴Qq7Fֹ>A ުtm-3giGCZY>fٍYKyV0RxŅ9fRD;7^ʹS+U t=Gh/ճ~!;3]һMU;d'?M Vi{m06sGHϛNA}J=G_.+eIumko)m|O7b#.R#֖[ߞh/Uz{TFĂ/s>]n3~kol?AP*ez~۶$ag @\La.JU]xJB +a(P.H:frƭuO?H:=ӐY_I:}Wj"ݐwnA6N7Ġ~]ubYn+<v".?];G~C_ Ïpsxc/yjDڥ +94NxMhvvN}ǴN&xdDsZLW1G3X;V^ =2 +1`@2-tl,eL*FOl`[ tp?\8ïnz_ݺZݼkwzo|_޼/[W޼}W߼/z |?%4Gkvt">Toz;JR CmLp<\wK.zA CZAOCwjX sM-#H/Vͺc@WU t8RoAi]|:x*xk#dFZu4# RvAraŻsF,6Ħ ,V-8[Nȡ˺ }gq qktgy. Zn]`pq#ZE UMqZhBY_S0Bj<oxS4;=O*vX԰0!x$LYS с3߁1@q1C69 =' CxLu0HpT`j3"6ȁ5JC? ^ki<P4I<{ɏТb1٬ؤe6}F|4.SÕ xsV1 GE+,ĹRV?(SSrio >[ܻOw`91* +o9%<7()XXhT+X` ߅7W)j68~ VhW +SOOsrgίuݨ^*X'UllR7{jw%%N +Ԭ\TdWᡵxn@gN-Ft!sQyqf꺅T3CE*zl+,Ueق\$e6jvD`Vx$03 +6)U|2V(E!Y=;h捙>3aDwJકhd&5`5]F<$HwDܟnP`3cRh?S G'-4:W A +lDCǘ(+;e4)4Z_2(rhS؀Y 4qs]&ۍɮPX‹z= W +b'1BfÂ#YTg#\!Q ՂE*I%%nݜ8`l}7NLbDd +l + +;μ㔠q{A%5 K4d,oV}Q̮+]et!PzcnTH`ՙHۯi:3x(?0X{;uiY J*swUR&GGN BVZ{/C3X) +J/Q("vxR1,,[=4ZTѱG !S("bSѡBJ 60ĠP)B$n*'1Ƶ]U$D{r m4,PQi*|𴒍 +8QX6W*L?~*l +z9$m}(i;&wtZ +Ⱦ] x*u2;8n+)hҩ\2g3r*2B!k1 j +T"=Tfm @g:@|ԨY*XI8+!cU`XV$=aQA7&Y#t{VM+f\=2sb3E- E)r1ӐײdfC B9OxLLIϝ Y =4 "?ePGN^|SIV^d`r ˞K[bHPtVUQUP`zm]U,1^+EqҶN]d>:vLW02KkW-0 *>ϼk[h`$\d:DILyp̯[ty gƊ:(b +$%z՜-J^kAQ.@Э]ܝr0K:cΙ7D>frBH!wdxd@dPt4UE!(e-*1Kxui Q?MzB@!@AG(nfZi@덊D]V8htnT#k*5=_ 3O{g*Ϭ[ᓀBM b.׸1t)JSڌL00UhP4.P#:R;y(I6IҼ +7qzoZ2_)IҫN +ӨTA؟cja̦_7wYdixځ4 c\CzVQX$Y|(q-4cxfY \ u61|C>(j$Qh0qMϴ#EZMOZihdT|5L4c_*i#><6Wz}]%W8r^ >`=t gе0wɩHJE@Av6P+ +HQX4)ܕ"7UZR*4z$8gPI*l8sn56 +Q72$5Q%):LсSi֑6ekVG_kY >wd*hPEwCHA$B/0pUhXd +Gyںf <6V"N@6*Xh'!4yT*_N _w{ '%P#iЄ]]L61޾q`|*b4uq T50 T-ЇDOV<̈́4*3QwH˨j5 hF%h| =d k.*u` T +@ɇij^ 2ZsU r"s\o7j򿃨Ƕ)Ν]Q1d\>@V`aBtāy\zP#^EDE&!]"0-R gՠ=.,U-2 QfrA-hyb <1 9/;'t [ABR+G!& tB;~jEYfJHdϙR"X3vJb0,EwW/h7%VW!ҿ*[&HV:Tb SZJ,-C^L y1XJdt4VBg5!'LHdhܤ$yU"N *[+lB P#bKc?|jhHS(;K$֊i؊Vt-eBٝsq, Ԃ2 ^TViW!N +/Jw8H51 :Y1㙮ZA7%Rj&HDG.6NG*-E+e_uQ,8Jѫ~j3m1,;Z0 \n.GC%RZHbˆ 59Oo$P* e^i)qP^Cg% <c:omC**qH'h WIӱQ!ĎTj@<\O;ZdMH4+.72;EL@ ą-QDS#UFVTaj.|x؍}zRR#Lb;|P/i"%DlZD9뺅o]l7lE_PM< 8Ab0Ve R +Ey猾LE[vQD2"F!8F$kxHgT8!a :MR9J + LfOkDgP5NY&QYZRr~]?0Ov 11kO264,I|{dT,H H2.[<ќE+%τ|8 Iq-ZGyfV +|K$;l;t! ⣵p ^+ 璩R*fjl5`Ŏ68t:~ͻl`!{sW g'R0صchT {ǿc"| LE1:-PĪ-YxU8:gF3_+TuSf V,^\M26h-AYTl4`l栄6j62"zGj]UTg Od4pڂ7<_/XuX%ZʍGd\N5mVA *VpEk }):K h)ό$L>kO4*ݞV`0'\4bogBʷF|*MYh`22&M&a87 Ankqhs23ubTH%yb@CR3"ˆPHRo0t{1%\IBQIgφŢa>s.X&-0 7"6 w>'xzXFwδ};8*7O$Gcd< ~[1hZEpyVt_-CZ(;VlQb znyV +dƄ< DQ T߃*uW d+6;I£%h"MqM` a7t)zsQB-t ~l3Y!*,`)!hӌ wZ#ҧ(ew̦*G$-xDqи"Cw0MQ? +eYxxY(:W$%iq݄,Xdؖ9å=&g*8\ +#ܡ3FhLG[V\1zJ(4(yAMvfb[0} Op}gUEU"lʰ% +ƥV.B0Pk|ij` .j+ f!Ѡ$]tdLmV p59r?!FtpTg`pi%Da)om*D{]J͂Ă,fȻrJӸSi`L{(x`|cy%sJatdˑޒ6PES*#u>, dna5{G`"EI换Fh<YrQE+JIF}OB(Ckz v(en(K@,M>3;g5;%d[W|i%)5r(IK2}W!-_ޢ袅dDSMf$πwzU" fmDmEw7c}.=r#E1mLPѹ3D ;dC .c򅱼aYe϶dpQʧ5@\`jљJ +5dXCUlA9X]|X!6H?T-#)Kw4F2SS:"YIL㛕Y`l>2^Uʡ +.mAܨ'y8V +,7}pYLĊfi޲ϥIf + u=V4}G@Xbddk& . +^[ Z_=H-/A̖dI>0X<0*ΙR 0*f嬨!VHBZT'W^+P^fBt;pD֙ފ5 +J E8=ڲьP%doqZQfİvjF@e#@zACĜ; 9΢ h5X`rk[> zs&Ы {t]ݍ֠' ۴Mp9@%4i&aFQw$/3ԃTh(lѕ`WN\O]Ju7s#Vqz!Axb$)44 731Z> +T uJ"ՖJ>P  +a 4Or*aJdW+-o*QMկHr X#~~GUd(P2N('ekA|Ķ&ZR^SCS98̈0h8 s$)Dr=(@[I$pXPd 3aJ\*ԀxREI)@ LL4s=yq"<`h`Ǵ*\i`aP(ŮozFDw\s6rSFD-)au^d歡:d2x#+,و8AN3B,8pCA0H*z7bzS0 4IuYWf}n;S PXʊ}l)"( E0iwcؾ Du1QߴM5[CG%q Q}4:ZeP.Hj!EER8ݍՎ́uIh9$ ب$)=//}U8W&iQCAIәVnF/GёJȔ^୦ +el +UɬwIhd;Bt33JHDU&ju:F̤Me.OAŒD0!&Z2y!8 H!sBP|,4qARE!SJ&g5s ,h7HEUi?儛@WId^˄), +p/~ +p&VCfuPM RhRxZ>0GQ(RLC#hK'YF)XLEר 0$rdq13\pK&Ta3)( +:G;n#7%,Y83(,ZqLʳM)P$֖lKYZM(fFELSieU1HQT\x@ߗK-U |F[ !gH@F7$^qQ9jv} ,g0:p +NG4a@11Br42+M4;dPA2)C:hA38y 3$^8%dU?Y]Rg) +(S# Ag0\QEVȯ1GeL¼U\$PfG`mkA-FD[͖Yn"$bƅ#$ELEY/tGd NqJW'V\Y4hPf0H/XܑRDl9s"si*(p+6vbE͖[8fZx1ʹg)hIu1~fR$dqZ!BЉ# :fpLG7!e +Ah@eVFBd?F9YixiV.4+5%{ K#s]iͶ .Lc>Kyo¿5)͌>٢J%$:WDȹQJ)݈ 夫sOص0ɨŨ,RXd$*k{٢_B-f=k=YD Z$Fũ _BA2Y 0q9(Ȋ˚[*n&d2'5S>梓XE8o +mP:&! ဖU-,`m͇&cef_% IQ%V&5x È .l1v =@L,Rs6Z1D-}k:#eq) ڒBhn *Ew:)]@"( &Gi|#?!#u1Tt*3ؚsLdiCS +m勣PPRKo kd+ +i pP)+H9Y5IY2a*DI,Ч`dMB!Nh8Q5p}DP!1Z~t- ô4&_( $Xd+y+B$5fPbR$x])fd8 +ⰘPqH0wn 镃2&G-}]a`"$#Є9,*^V3Oj-lyi(ŀwX-4I]n֏:(2ːB 1`sH"96\DL+$"Nڡ wxC<+n/ 9*#/lbXs9lSy*ʃL斟i9<lAFoVj <G- 7 VuW+O#s Ԃ-fЂv؝as/̈́Ab #U'2fP&J J=x:BZ27%e8 KEYy֔'K= 䝮Gđ,*FN8U&)&e'P{Z^"]k3rf}:f*DXBykT(!xЕ4Ȝ6ܨP/3h~^a ZbNgYEBؔR "}QQl9M|$k]Ni) 13@Zfr,$XPQs*I ="c Olp*;UBO0ꙒVT(S +&{w5U(pb)n-]H{"D Uԏ4P2﫝bOGPa-cp.hFS,38֞F[Y?d^7V19 !ٶ#Uƿ$#0~'L2OgB"yÇnvPֹ!f6 +ft*7d 4Wϲѭt>[!o'cd_Z}dzQdkǗSbH؊@_M&YbVRs;[*1}=ͰBB(hzSǙ2KNSyqAc!8XRnbZj&a^dJQg„ ryiI3*IMMtv>TJ#醔 RUOu9CRIP @)-PkYz2UõxW2rb "\Tv5`ZvuN12:1ߠ70ᴛSHP236B@[Pc%DaN#ta|'TJU 0ȑxFW ;B2+QnwΔg<Ȕf̳R*rU\%OT~H$B,< ^?8Nxqb@|S6"\-B ;m|ƀhOg'#e#yx:kAXbug)*ddE6Qfy+=G)Q+II2~@TyC6 rnSeKҫ*3wOψ_EJdSL3Rq\lvBRPIClz2S/ ^s VVhbVHV"Nj隦] Y +fgձ}pEU_y"^̅BcJ'`(*ܯt"¼<ɩR%2J[/Ҝcn.u@L:^չR)A0y;Ar.E>%.%["ij4kU Sh~٤~,c2,[f|efNT9U$ ȪJYV}v+PLyy>Px'E"?kg+͍+=C' +Yu|$0L5p&YdO[ h4*_Qr(.6JM@8 +5$x|$YSp;QUr:WcC`Ve +?1/ +860cLrSؚ꾋2:@#8};dQi$ԇvLb}S/PC;%+6<ܶq8|;Jܗ\VwYsjp2[ِuvU,=AKJ%)PVvt勉kkH 8@\Z+&06f|VVp_cC.t k 0V<\g_2 SA~zG@#r@X6NIйHou8#; #0SZ Qp HN[4ƢOɫ׌tzAw8=rGLYUO*@lxG)'үʣe Q+9cpDN|2%f rEӦ$"k`j1#E +bY0}i RW"4D +.y +$F: 6U `y!ӌNyyw}|g K*Kc/.~^;$D/=~)q58}5s\1 hr7ʕ:|Rv?rFnPɆjJ5UF L;c3$bf^ȰEG*mZ)/;]-R: Rq7jnY^]/EIjcz=Зb`n ž!L0:Upf颩4Wvݟ[6V;}|n/ǫGҏI(tyLlm=&K :.kEFa([/ %fMѓga(^5 0. B,; Q7N 2 +׺ngjHE^{kB@}tXޝp,2%0"%na; =k +Cx<|5S- M u}=[{kɻ&BV"RSC=$vpk!2zJ<N37ZGK {pYԘ/kB-qw(+TVDz6f,hBe1YAH=!{' .Jv6UegE03I.(m%X@}TJL4j +2Z!< Q+/=hUvzzB7jثkȤET:6[@J<5rP! +op}:.YW9*]tΙqXZό*!RWu cHC]!5R^* RLkjӢV?C Xr+!QngN"E67 O_ݪU,P캮G]}AƵa`!OToZI_֋cVk {/Na27}/P3:H2NF {8俘*07{&WROWӕU FPX~^²b .!sqE +疴' JQ{/L*j#Ι϶e}qhL*+\ y 6 ,V \oC$Ԫ{nQB. @hE*fw<ѿvD<΢0ǷDӡ ]!0$4LrD:lmoZ4J`9 wcuO<=韉g*xu֫04>oFu!@*p'- a =;ӻ>\&U3h?r11;G2{[Wgϙ5G2S~H'x݁$yn ILl&=t֝c5*byNkK@PlB}&BU.@䄽'gcx#1,n9|Gzu˕O} +H6*7#k<ř^Ssh7/ar*iV05~>ġhXhrZQ*04|Jln?Q榱:d IQOÄ_7D76*ҽ7`tl/`P^q4ݹϪ/ 9+{[iSOZ[+ztRHFqj4< +B xCI|uր1{m0nE fXء.OE`xzF!L k=ZYB*= o ~k\eт1%>`(Y<ՈIgu- t 5Vl(1s#Z%yժZSuF9fE j^TgFYq$-fT2xy2j!-irSc_+[ZVn (zhU={XR?ԛt#|$P@!@a(6wߌ{n.ΨsVSc! ;o +$NL*vE {m*_yc*q?ǯ,o?/oϏO?~ǟ׏??Iӟ?S +~_7:Xhq&|M,[r+vȚ~Xϊ+ @PUKZRB<€ r E5NDN# &* DLmZހl]FZF=ŊivjpEh7NJ^.Pf&8߇*h=VBoyvHG1ZI{KaaUI| ` S%!II4_+sňy $)"@H + V,XݬՔz("pb'4x>k~ڡbBV@>NJrCa}`D_3]b: +`1J <0,0J쎍)o0gm'lX Nx!҉w3M>3 +Vzj4-C9-B$Rk[lҶ8\k܌].!r>|8k>5,r+]ҭocxiz]=sl_Rzsm).(ٲe~?W>[vprU%_TD:^CIx*s^<ģ}5Yt^ OC&k(ak>^zXe;~>e3@ } Gh83 )k/=dywլnLhb%l29IÈ5 :0NѼoQ9hTu%wk['_ڰ;* X]Qy6TtJ/}-N |@3^+-57|z6fhT0ϋO@gv o=ѝWҖ(8J@Ze+~kM0j1D+Jy3DV Mi%OrNJa-lĚ9w up +~%_nN) + oA x0 __Ezh0ms>C΍;/> }4Ewed8ANh6`/}^i B Oܚ緘Jη3XgdkS!cO߾kńa c\\1MHlx,)\2 +{> \rt-z(95#y&T1ݸrQ+*}5S.k#Ng6BpY0GZГ聹VC.[ÊSٕFLevRDi0ք"j~Cu`|~¢NyrgeS7 7xޡ,y5l'w {| DVŏFr; _6!u.4bM94T+E,WZZ_i~Rh\ Cs!FK`>З qE6khx-kн*s?l*c}kPbӪ%2u8}WWCN`9`emDimTB tjjϓ!:/ hbrT [?+Չ5@^o@5(wؑvxwitZ͑g.L$-IbRp7po +U .FcTXw +x]iK vBJX˼zWEH F BmjX)ULS$ѿ:X_,\$b:vG_`*󜷉KfxQXT +*JC"Mf1 {>ՙi @bLJNq Ӡ`HЕwF2(b{R .Q ϒ\ +]G6֥N7S" 2pccG eQ5,GΊ`\^ZowOHƧRтGS3O5sЀ[ >O2tT^G{*>]p ! ^6Brz}[Q&KE@ͫF'd楇'0򣌫s8H"e荢 sżl%k ]k>1l^ + +3E@UnnAi%+}]0*,_ĬK~#j><Zxϱc} +o FwF/ZW ]cw'|o +2(!-MQ:q֊X5{q+P5~lR6)_7x#~-Qt;5_=.mitV=l;1_`L< 1%mEa[ ^vsXQd +fl i`dUɺ h%<'ĩ(s n\9+c +@6WcīA.4ĭ ƪG8ލퟷXJE Ny NҠ b1ahoZkLq~N5,ո?f=យ0Ց_h VY@H~R"oFAXSHx̀}.3$س8 @e,w}~ Is ?tƉQ&N 9ڸVCc}@ha쇜oS$7M,ﺩ%ņcma5 $ +k>!bk?ŦB~@: Llü70ihl:D0VZbO$Wg3,FG016Ӑ mw|ڋ3%Q/ 1";,&iDZRx>~8tKKH>ނLt<iP\K\Kvu49-v敏G۩PAuˠû:m݊I 2]&Jlq 8؝ IWlIBs~W754 hx")Gv[0NT$k)Զ{z: 4p}JxRC$.8\7{5/lpZ  );^x(ǃaڞ8Uqrc \#BhqE59J݉Ѧ}B 03 2xU %ě + '4Xq zќwh|5hTDcAHhPP2 +bkBOJ2-pkz,`$ +9۩Sg8\`E.p!|C0ܼ4}G%疦њ/.XI Šs:tkgPƌ -xAg~;2CzrYfdet &pZk&]X(zQB +iWruzI5=f4% 1dq=ExtJ<6^L#n9ƣ޹/f+yƸB+FK1^nH]pg/H4Nw؈938s귫`&>>ZeC?Ht{U$τB oƙ{s&DC&~{k=6G2H'm>%$ +Ew7R몟 R)h#b}奯QzCm]rLp3 +U|^wB|a(r)ZoLyr/w"5?Ƞd- biB\ +H R|a(pqC%\[)Yu4o=$nie}h8Rͤ`t[s> IQ\*5#5\`ԗ8z@v czV"CYNZ^q9ɰr3}I26Ɇ@xX9l!t.7d( ^6OC<'U&(V xm?5{w`uG5}M(5 +LTJ.PTv_{Kf?U|_ YmY&RA|](ʒ7\JﴘMnDVڪ[hl zQQ!L͑.,x) +B~ +'PȠZRSB}e驣U]]RS0HAxSuQfVI*$\0R8UGˌ d=n1A(PiXߜre e*Jao@= ;8 $C֚^)S–@钮ݎjW(b]A`(iG0V#qc W`BeFb +=A-)SP5q- +P5L``~Ll!U^_a!xGT|1yi銺ow}t0lFm~c$HX"rJg{{q>bBJEڑB>XFcquMdqj,_$Dj#fw危^;}W{Wo +|c 56bsӊ%9^ԷJB&D^҃M!NpP|a%p9Yr Xpt+rT/^6{砵z owUDq'`쯦eL|Kef߹cVpQ Ά}bܘ{ A$t2}>D PSW2ϴ wdB@U!]fw=򃒨m zs~}W]8oDQroM5Ȕ?Hds"N :RR @+¶z*qR%h2]y0 =^Ȓ,P]e#>l*3E-ptGbGKUֿ2Q>@krEo$`v3–kN궙ahԌ "O +%e)![0^\$wNgB5mc +oβ^9&k ׏#?#Ð~)]umWC!JG'knGpq·BŰKz`9Ŵ[FȾA8aÃ^0[iT@eEU0|I|V/`ewowNzcy¢K2`4/WV YZw>nq +t5 9&B> "ڄp,!Zm3]Y %eV[_NѬ kyW!K2FBDb Xz6w 2nPڽ(Ԯ٭\xkϛR͛<[5T{Zu&t;#XaIĐĕi#(ȻٴN$x'8Xt~1n]"oYM.X0DF2'yrSFU0tLE0Em3%8bxK]lKM2n.m~]ʢ eh{p' cJ1+kt韄/{L) H<(8C0'DHQ ":io`2A U[ !`ejy+)ZD ^k3"@(۰e){0kt0%eք C)K4;i/FM,+| N9=ȴш@W_ x"Oʼ +?z (  ]B䌧,P $=ۆLaX +zMR[LrUfZIzt4[ UPʩq&uH+JSK$gvlZjDHq`dv +=bvèzS \z-?c/ '8'o +gGPjF>邺n_D?7"ZQ +oM.`r +-oTt>03hV XI +5|P D[5 /惯;(V[/:C!& Z֨~lFUOVS?Yh"y>l1n}RFޗ -BBpL55 @O;ar0Ro^L>ܽ%SS@g I@rY1p45 ##d%Y7R]F텄2Cn&"^ +׆7=\tOޠf 47]X}xPG]P_#rtQ,epWB]@nи?4V8\mZd"`4ik'[UZd x *EJ 8(\Yp`VepLA r[gE?'bC'6VqŨq(PjRXw p=n0z8^Ё`emϡ'6`kQCu=fD+$ixM1NHu̲j}ÀBAe@<@G{,ym%C٬nςxp MIEW |A-*?Z HuH޹*wa\1BՊ*l`Lo Y=,UQ/!Oչdq^] _.La(% X1h>*9vjKdR W>)OH_ae$i:_PZZ4PU55Ta9R 1T$Qi`'C@J +JeS[E}\=;̗zꉠ=F5B/( +( SȊaZS:uJdNC_[MI6\se/`5baT69;4.oE"dHDpH3Q2DTP6b.anO@وj[ƕ6!,:e +xF\JDFnG&dBf{#rtaE_sD eWsjas"~=׊ЇH b++8!nLi(wj!uE.vh1H9UB euHo6-G;ĻH0j\Br-T/5Mk#~={a:)iæ;ƳC"T7x_{p AaG[ Gzx-4 2(b*>iD*Ʀm\<Ա!<|@4 fkQj%ᐫKbqu[Jʞ@ Bvmx)ˎ8NBk l¯"b+@>vIXQU5zoTFsl <6ņ#LJp{D#),\mmqS"6<@j) +'[:0R&Q~,,rT% + 2Skf5JSX2[⠏^sQaPڠ50s惭F,.=6Н d/GiÅ7ze*{9` D~k/$G=a*3yTd+ `{ }W,1dPE +:ѪXYwlֶ0:1G }%j?i>F*vNϩ%y bѩsi Ȅ, ˤvDDMEF~m^Qe۵8}1y4B"b|g(?*W+I.w.2Tuߤ2zaOA4U1ɉ!̥~+1\cS6|_@ +9K%E7&&EN!6ܷ֧Ie$#9OblH5 +y,KI%AfslAh#-#1C2 ue/EP"4p +xށkL9҇o]]v&CpLlk6AQIc+ y8"%~7oB?cD:9Y4DX!A 7.]lfthЍjr2"A{t9y40Axjit*EF?[PvSI3@^fɩ +aGrnAźv`+UeJnhPp@_|s#@JHh`QIZ EH> %>R}K(p`M#^|ӯE?j9%®'k8oFKxKnLmߞ@%޺¾qAbԘe@$udf ĩތ鹤pnWpDܼY=CÊĈ[w!:S:P9kKDJXHag$S%A0>ݳx8BϱsC ϳc@>"A/{iJ3vy:xcM=k>O+ .PT̍HZѡm5LjkDvjr9Y@ u*ivUkܓNA! jQM)o=zN"G6p8Qoz:iY A@M32P/b +6E7|Vڔb_ &e, 4TݺJZ>ɵ!VqbSiNjW\B='Mu&NбPVل.9t"XKSLᮼo5 8LwoeJ;Ģ}3T#Z,!q)تhIk +o8+us뵸5P, +9`aV ÜM5Sl%HA-1DRfo5U8i V[> unL'gd]0dX] B-zs$Ko]> D2yۨLOaIG)`,AW*"+"8]P0BN,9BG rA4:TNō@l*st4`[ Fƶ5w4I$v .Ȍn녽 sR|(d/{?d:5d$s +#9/aR6$[%1.)@ݕ@w-!>(ʹeP%&SXyDrqQZS2c,b5VẘD";M!ʥ G&Xv(nth85PCFSC7ߠW +SHB^rF^wl}-:T.p_QUe]≷F;`=X9A{th"8EF,UR e+5L%N#iNr=0uB&*hK zS1O.j0^[4畾mvˬ/7ϙh%&;sQLG%Z 8xXc@l z =MT$A lkY zof+xYFysT)* + im!MFV +C1y\k$׬#d?a&uv`) x P#uL&F=+BPD-`KlLcK׳[-:ߵ5W Y©L%|tO WN&X)aDN?C:I=zrui_C>ߝIH iSں$KK:kkYG=G +XT~DzX|tKH!D VnkeͦgH⋷q#gɍ;l//̳8׬IS}g9&ḉ&~,ֳlMhN8ޓӕÃ@!3/8S,y먢,Dz91Y?)L鸪?bK@CSQW':&:PQۂW}Yi&^SY]gBj%ŞE@e鵆MfDH2\,ӹ`rbsejLDN$X3տߛ8/]W!es`S:3 +艮<$Nkƾd`Ļŝ\ +GT3@HhDq N춫[mdZ&pf>A^\XV>` ja̤p {"]ݯ0+Oew[%GXZ yoͮDvy5 +Ҳ|rnz@Ъ`v5S!CSlfP2!yGJRFa1=h!^="17x*w5*Zt0y8XՀ Ɂm7"8 Ba8`"3?= gQeU:5#oEC.y +묔Nkd(\t*+ϮMm;>ϕ/C):02L* ;|i$Fp$s**ivϟ3GϊAb,5%r&dO(DyCMϗLQOx>_C!oƷHS bh*Kee㺒ek [Zm:#iC$p#[&|Bl +L @5h${Gy1ֶVً[,̮x7vyĆ k"{Ì"w.I5Բ`}ZzRXV^4C [ex>j4Z[ U#Q0piUT:Da1}^[)J6\򋁅SAKLKUvB쟆fUH `0@HP{y+a%,i:x +fI J +

3v?YP2st*_IXHon#N/7E38z+dΩ@_ ;AjƐQֵ20[Tt,@^:("IGPTk Mym6c/_Z sjkF6e : +(aEP-1Ռ[+,ǧ28)H>~p3 C?'7U1v)cA{yL`849s ;W< aH5haCn`PP *m?EaàWCaP:̹7є/VB)<8ek?/;6k60l"^'&d\]m}Ƕ[ YV𾩶ф2o$`vG]AvwJP7&`e9O!EpjV7d< 6ЩrXͯ}7rZ w7lU-@ S k1Hqd:nt u^woRsEcNd=F31-lY mKu-t)ZܐJگĺsu{[QirV| Jlpi 5vs3y~4^G~ )pP48>"ʫR(ۆp*b"ߑ->5Cy&P6/dp!΂-HtG#5!`oH=LSq39bY',v)gri9p@XԾ+zBiQ8~Vt|5\!iL9'̅IpiCیEkyeRPS:-2$b#pm:%E5w\svH{n.@+ S2sȃ$h|9ppYw+M6+n}m3-v 4RnKKՉ=c[K~۞b_/DI!/?x(c~mx# eؼA + VEggmh؎J( 1Il/L=ߐ)rG(HW + +N @զ&VNFdXkc2"gkjT-R ܧB1:ֽ#pzʘ:#9 z}=ZHQdZ!&9M_rHi/MD$FM359hCPFqSң~= ~U`hIƊz̗3?wOwD"&a8K%xf+ȫaUZ&4ws/RnԴzI43ݎc8z%<>|2b~#f> ]L{dL{+zQ>/z:yc,C#oHQ{1]%33Toˆzz8f-ne:O;^2F3,A;-+~sU4sGBF20Ph;$1d"` + *lgAH]1VrY`6}a):G;[z'QQǹvQ|^׈+<,X_?l l*ΙzA閚M8AJ X +ĚdƋ^{x&ŀRq0s +8kwG[/Z005ðFTG1 5-rq$KI@0@X7:|̳pVQnDG$CR +:yӑgݽ{PF8G z[i}GS-E46Z၃bR%lmTaÇD>Y5zwY=cl[ +o)y\ZV!L +8!fm"7ƋrY)"nF(4.<- Zg"Ť@&("nr-e=ބ퇾 (GO "jܡ^#n> U.UY[™zG l['M~N:CqfDO0Q0!ӂ) B)Κs}TzL4jT$5n/K =tfr_ B{pwuޛP>gtg2k:x&e?kPKpWlW7NUs?i5̬mdž(1`O{^*P +CX3C=QDWwrzF}wA6 +y!@fe]ih"qK3wJmyekSVoY:+|70nVsYһ2$?mg,RAVSfhX9ؽiޑ4vad.<ϞH +(Ϣo(t4y.iͫdf&ᅑQ.[yͅ Aux,聏>y9eap |漜n!lz1(WTpTewi?ViUDĔ ~u 7-]پ}'_Y-g֪;%!vY{BV.3iL%ӃDM!l&U^0^) 8LgFn!9".=W :wXeąh(4AMCOh]Ć^\MK;4B23P!"$a<2HvdLdvC +OfE>x^S_h]_wZ+\abCz|) +.H~xp~8ldCcq'{paǶP8"OMt1玉W_7wV &E +(v!Ϗ;%oI FVӞ3>J#br7xgbX<$!Xks :/G -Pl%Nq*MnnggTGH8>Os?W!B .SB6Ў擾)~9ȺSmH0FifKhc#4=X{l` ]m΅8/ޗs}I 0 uX2{m{I}ݑdpȭ{osFXgqY-:'UV|8鈭@Z`EQ s= KT9wD +%rDB)"lf5ꣾuu*7g8-1msu:"=Ic<#`k,,A +3U"-P&ݚkȐj+j_lЫé( L#TKL$`Km8|4#o 6HdE7XW=6w{b4XiOrF/)+xԎxD,P.#QT3= kV6oZ=ȸ,Mi^o +"ϲV)e),׸Q4o-/|b[P=ojJ?`ľ;}*&x׶-x;:ϭ!̜D*ՕB ߎZ){X$"fH3o7_\ٰ4f("f`-/=0otf Lxz"`YS^23#"ɩ1XPe(Tӑkck[]Q;li EPr=gsVTK!zTpmmD(1yHD@ڟˉ&M5{ +n]lE߄݊ "U\K*8%6>9nA 4Aa;Y[$/զ)Fp "iZ\CEut%Bs,$T4x&mQ;46ְj[5{Y<éXd~{"md*_y;cq?ǯ,o?/oϏO?~ǟ׏??Iӟ?S +~_7d ^]O(k~^ |<7v12nH`3I! +[|A3k?U͗"_PX{bWТ/r(*i31\lf6ܬ0l4VdK2ͺF^2{}(D9T'J2GhP 4v3AvA~eQmXVC%]fxUal3$vJ><> 4E|odNF b,ĕ͘v=d +01V9l!yXΟ1 !gg;ύ\{W] Vמd Im5/{|܀ƕ-C) 88%*"40-trpA?;Np:93eHH@M X? lФWjه6 +":wEϘz %ݯ RoL G_ ,?&-:t(q?bخ=#Q/s=pN VZ08ޑvLYZZ + arw!w/ؒ5&߻Bj bs߉|!oUfwx ]4[9GRhğ(=f(g֨zwkTu:A7dEl.RePp8 |;trطMHl'olʖ/E]e CHU/Wn eܒ{\FcoF"@w2E\r?Zm3sgn83LL69 Ph">3n"2S H\V4pdž6e8k\cKmakA)4eDXV0L`/Fs,Bg:DT)d TyQC_">%'P < H:tEIYFMQhJ8`Vd58k-ԍ[Mkc)j,Hv ?J TvK/ʰ9ni[ W=-A6 \S],:-sP>lHЀZ~Jh{iĮ +c`2,% +łpcD]|n!JSA(N\w@gE栏+|EFN{LnضJZiCm\Q9RdBu\<9KUȘ**64 * HZ1" ,d~9eAُzoJ?bSA~m`n}2m4 `|>܌ؾ|} ?~c*?ԇg!*n6>k$袏|+5Fީ¡93 qgU|}}R>c*wٟ﫼?hrIDvt;JP!x6[93O(FBe@wS%?5,~`~VePcl[rda֝UڸJ5j ^L@oH- SJ,tD#9>oYU*4`1wP%+ |,il$ƚ`!XVIŬmО0p=;Hc*kee5NOX1o8 +κtu.c6 djl1}9Ӟ"`zl/؍`JGd=b؛\$ 8wqMV!; ̽͵͋QU#Tya:[ϣMy!V?q9\qqPc@u^RWTݬc]tAiH- +\&%GV㨿dyY?S*)ܚi%mCSR.E. 'JUum&V˷0!H9-,D4#Ř_4C>&}mrmApS\CB2' 'F{saFz=!wo(B*T#iĖN(CU +?ؕh' ,?ptD /R4cM OۆϰaJX-Pgpb>QOGCPc5$4X}1~h)66q8y=\} +wIƍmrW 9~A/v@䵍%Hhhr=o]s6'ICPzSI"ww2ԟܴ^R4_Ls4ISu'gbfR%ԗ'sl\b5Z#)>ݨ=w k-ʯgѤ8 tZoEV7L6~nƻJ*抳ЭAy6tMp|(ri0s+g8RNxm$l@CS0HH/^譝 65mV+x@΁p2;?#8XnQ2VZMEc7/|vBeFay\ؙZw9\1"zCP۹ng8 Ɣ,5ܻB5ﱕkfL3ʶF+փ'z ꁜ=҃j趬wY)ah$08f9MGok/kbQ!5͋SıJc#,`^;Kf hq~; =VBJ{ +PwI9Hn@-*]bAYɛB7$zF6WFQwR"/Qk {O;)SsbJ^ks0WT־!*eL\Xh`q!Exf]0pҮȻWfi{Џ_wfS%W߮Y,Zi_=7.<ʼnQ#16ghVTvMWICPo9v3T"q"m6‰3@"FfiC!bnHC9ə9d fsP|NOpmW=LT!(5 ,LdQf2qsBy! . +;RfJ7s/Xg`Z$.7 dngoyH+a0@ Dq eU*[45ZUhpo +ڞF|*?]*`6^{ K zRjl2sGY?V2F}mX5.O0dc5ޢ_2|wV4 9 ]Y:vv@ѡn<fj) C Z?HxyrXWHa< RUoi5,WfXs[bC-( jvӛFOlURB~ݓat+D\S=07K(yzliL) ēpάo+2~ε7h̫[Լaxn浶ņ{U;RĜl9ح׈:vkAJzQ_Wb"GA"\*׻19tr4@k$JkFBf*bUE`e:QbQq֏RY%&0%P"1 Zm NôЈ\۱E #FC֛㘮Q3^{L%ɘ4 `5ڞ(6L@+q3i2]{bͮ,Kr^z34({ /AnQ(M! 2dEuvXFdFx}?M ocSrVI3KP l55Hp,/KwnzVW띊iVvgGMƆ&WNZ!.vlo +ǰ h +vh* >ݫ<~^a*GuxXMׅCmK?L y%΃:ybCDوLuI8Pb?a$vhYQ#}zQ;mYD0+mu~Ff0SwމRU&K{u\!@oq;?h[aЁgcEi$ AexB<. **Eű!Z\H-ҜH^<7 4뱠-OjNDI}\ MJ#=ofa7=EGVЮ!gljs;b^LDX5?V00sDr&qI@Y f08*+*0J]c 1 IJ"jʕ7^BhkSRA:Fpl]cƳ5'QY͈8A<5ޒ*DEts%%?I +&VT誧f.!*YRxܳ K* @`3o-(@>1o {12튅H:09\,с)xZZs]Ed~5St5e *ʨ :˙.Ŵ̻ ߵ)0&#/=qⶀ AǽaCxRGm uNmNpAږ?좆^֭?Գpt?D MN4*qyn2ѧˑF8U\J0Ol[BNnP#5u) 0T N\la|RIʑP;F}Z|L|:Ty--hO?)U7I&f.Ϟ2Yא/f6*'!3IRcV ԈW saZ8ŧBd0$rDͳcH @y[r/ѝXQ,Ҏt|yv~с >wKQ(˗CheSj=tGU(s֔XVtm[/u?b|oH.dqXGF m-Y"+ԥ;,tdO/B>]`@;4~uZIޕEĠy917%Ha@ߴ + ^TpN)xC +hCd0[c=D^O}gq?ގn ?0˓2$` +`. Qo~ľ~,>*`qxŴJ 6[ڲ-˫+-(r_ +U5p9# +O*#/Z/hܠqӁt߷҇c_N^ZlAMoHko-m֣&-@(_nK  +u^u-tamwQ.B$'hHTx#-{W +-tp\Lš5/>ywQeE?oJVy+v>2RQ~ת0zbߙTp +`Ik?,aR0ٯL0†E>Q;4Z p}Z)WT’ݷWzG9kr;k)z)QAQ xd AɽJ[ .?{Ù%jo|\ +_g /(Z5SA +˪qF]qh̿xi6Ɩd2\HmK5gLKpczƗ@PCa޶Y1zKZ/D~b!Dn;ge|D%eJ7뭠 f,L bԩ5zx+{̽4r4e;. ![q#] JJO lEp/Y|NhIB.+y{*B_K}<j-i+O%Yrh^EmMY[2ˮk\Wn&GXåO7g#j!Aji+ +Ju+W뜢+vA%!rDSS.?H:R Q{pҤS(ciK[DRGi$}]҇4ׂ-C^]a8`YxbuYPj +PcOMi?[}=z// B W)idfzk6ǻh}F} `C\lrHU>}R˺L[." I^,fOurGg,QbP.huSqN%hJ.H fpJJ#7-0r\S%C"biԽ}}X`uʞ|AVmK:430hڟ\]-Iv8GqF=DhDRxxE_ +B$.^IFf3Q2ˊB!uꑓN2b~dlApi_z7T8JԣdRO!EsM1+=H TSzntkTӞ >c oWlH,O,"Cz +1M^J6oBBk#7QviăhɔN Ԍ=Q]؀R`NjBԥ*; ,#cHD?l_S':JuUa" +}j; 8W>CX=v1UqңYkCes"W={gSΌ` QjHL:X ܏hc`\5q9L([Z6Ż=n(kq'G_> +`A +Yb,g'v]h@Dō2ti^bGOw[' n-X'q(~n; +NZүk +*qqBd + +J]yzzS$VÕQ4vtYrát\QP΢ Cd19>T_G|k$WiB)fPbMMu%t$Z&2tr-OP{_M:@H]ҦzR&;aIVD2gȎd%ttX+P؛P~;^Ut̼e ֬/Q{˺4FDC6ԅ Uv/6+oAЏ?G_m/(^ +ղsuaZƢL:TЧ+*>qS~M%B8W{Wx wTG8U4 + ]4 *Mn|EІN5B%la :B:0/vXzm?#K@J!iNNj]q{ M`Ka =^Xnz$Tz^b qc UE81it-r\v%|`ԧc2o?\ TERy`u +)oG}1; 2יP֍vC~F] +fH*T в2fX:ۂLrHA[Poi!" H_jxK;аg}=)k7` gĦ3Ob',>2&|xj@qh+BǑ2QLVxߞxQU;*>{ +#+TMԃeTa Uh);GCkMF7Cmlɻ r>K9#vͬ|+Z U,n+Zzܢ|=/' O?ߙFu5/z`ۺ(")mSПWqQ`<% ;$t K& +EO s&Y :XSA1t? ~'s^3TG)J| V{|5z;['͵{?e5 6=,@8̾зQVH.9kC~Su})q) +]ZKӊ0r哊#H)ۘtȁ }=}9~.ʬǣE8puA>?֬,2]FOO`C +^QEѩ¾5s:9#A&MqF0`OxT8Dw+\;U͞Y |<_a~h ]:VZIeaa !dqnØѦn3ĞfTJg׎%|jsLCң*]3Q] *+;AJҍ|Hq% TpjWK~NpOlApNC+ef27*pձ>7mii2y>ռC<ʗtњW"%|Ye,1Ԋ +|X/WXHh?9g`GEW_YAe ӺVbR ,Ey +QP:YLiWhU{ +W+Y/>(ջ[ڒD.htΑԝ֠LE |wC)S?r p#Li? h@ޢdW_-ҞTu,gqڛn;a_A=:W#J"jyqa#n))<J[ʓD9~1ЯEWt8;9CȏB-j #칇L̰h 0dn\D/B׋<; !uB_.ºe>*\ wZsT-U:+, NlR!ss[.u\u +v قp0[ʧu5PXxֱrU?͎=6(9Y80{%AQ9) +3 J|b^(-%n?gSNqگG=?Y^`~ Y  3jGЬ+{Dm@l 4램qptYS,` 7a iE[a=P5=xבS19gHHsw ~.I +2_.=t=7D,P2UL T`: +c7_r⃔f?Ңu <njYr$vgy꧋RP١vKjkR.}l+wAӲ lāqI3BѳbddM +(ڵ!1K}t㵠ɚFlV;>Bu촔}&2uETLj /Oz#+P ԔE`4 6=^A/A@Ñ_n @p|F8%#[ͧ0=}*V½/B9xN'4kҗC㕏wZhqE I ]|c8}i6hWs?41-D[6 PL]=/L6 endstream endobj 77 0 obj <>stream +~w0Mhfc'FWWك{POmfNQ3u97(O5_5Kcv䫗pOyn\-%[dfRbCc8~_>z4aeAYduh/<u9Mk6{۷+\BK&Ʈ] ks Gъ +r<?C\h[w٭{]<@pә8 E.yrXctv2HL&?9v:\!ZZko@Uh=2Je,'aJ NVSܖ:e#8^Člo۴9yP=P0`NQ~Ȏx;[D(xC-Q3G2G|7mFA'ɢ-c9";š9$¥-R9 _=cG|A/+pڬW0BɌrh냫D]-lfC/5q_7vkCQbQO!2K+Y4ByAV|j8oO<N<3"1bk-T|JǽnG)-+u*Ib-fGT?; + Q#_yaU B;Yiϑj&C +\bz?)>îjj&|np`lc%j?1Ӣɴ +t֦t`Î{OCFs@유̬ ,vΥBE( l՘tUW ڶ 90oYd<_̩maxOơEQtܮJ7E"G,\LG/[=BDf,TDnQgٟeԬM!#,d-z $p"K +zlg%/5Zt%:+ WG+ʡNk)*X=\hw$_V` wIW?:e.fKCWc =@yǧDvqK`׻t5,_Yvvrz`= b޲p12XJ!pii#>>%GĴ)D2|sJwV=z{ M[9F ڙM\OظFgjȯl[̟1.l0o*o +#?iU ^A:.͜^6cNM +; KR*[Z87|IynCG)$s`/ +}CAکԀ%ޓ9g0J#aq'"?ӀA7/0ݢY2%sשIL%'@Y'S5YEJCHPbCQ]`4ߞOA'c* d>:wc?]T=`(r,!8 +{S<*9`ED(7J;LՃPDž0Cgq9%T8r +v7l0YG|گ.|"B )ӕsM]r~,x7?Do>'XZxpO//3ukZ]!TxGŠhC, 9dRBIj$8 `D4LӏWuEvȻWLoH\8 F8C}~:}i|xx Z@;l!% F2{y/,+L}ivuVʱ7$Dy`JnA#v K i^ N̝E#ZR!a#̀ߤ|~sB}{~?B\)XE`+!@l|V,ݐBcPkcpusoryZ s$OPģe t7wSi8_>8RhI~ʁBrjzГ{;Xv?8N~~9KE#e3#1yQZR6 +\ H&Nk.Z%ԟz|zdxXgB]Y-_ʶWhw|}nFΟˢߟ׿YZ>:Ȥ544MJfEC+ L1PhpCZ9ft4HAo$B}l%|d [k辶?w????????q_/oОs+VzA~05W8< n0( X*FΨv&˖T+T2} m A}:v2hů*ٮnͷp-K3shnFeD3]z># +?І8/7Q-SI9@T@@ |G|˜{MB-@g|)dom .[!Ѱh!ag' %]U!%JD+V<)HRd[9%E?!GF*;!Jv D|5 7ZU8^1bjzG-3ׁ=\@՝?Wv!c@]QeQ/\JŚ#A j5䘩Vy\9TF>$aՆ^2#Imڴ-"ݜQ՛yVfih*b1V7"V1CYښ0*@IJXtb-jB M=>X̱<=•,ZdJK$%c:ߜг;6{1KyYJ2EE̤Wl)D[@3cb cB3Oщ_{iz@[`~է"SCDfph+(i0^]Щ!Cb@NGY<U<t߻F,U#4AADID,)ux;-v8EI(Ubw-0׹RFh%"_.#8f͹u8rF +JZ2i$DsA>5.ОZZ{y0@@C-'qU=x +W+Yz}սJ/s4˞)xΒѬo6$U.N$囥x'W}^b>H5 #bg>F5^laƚx}+s$;RzDF{$`X$o"W@knz>R?C!buD"᎜0:I?{ $- +=(?f> 3 T<;HiTn5]%;c`=J0Kp^=SBa2hy۳Kx,{EeJST2bѐ_<AA[SUĢ&_t\ J6N&?7"?uHѕ!}a,Ec $nJQO@­YJe֑R +6$i+QM;}ySY)hZ2b>4C2i~8I'c%%g?}+\Ghö0ݬH7|5@X]TLwAK@i ͑GJ=ǂհO#fCp`/^Kh[yzU<7 zfHP֡Udb:Q/v'ܰ Glƈ{ BFh߇I^cJDT ;;pq3Օ=Zsh!sU5>^kk腯@WHvD9m *ޟuw"5>x)?#YOH`2lQ['utXXbѾ>Uu=piJ+ﳧɽkMqNJw +E==0ePIYrGؖ(XùҸy{l0`)=?_s'sj2W q>!*WU>%Rh +)]9VjLZe 4+P6ODP*T,*\zwT +(5KPN}k#Xi `NG :)_sƧ3p\z|کxd=^CN265 dFH1m%Z|=BD 4 U +h*RWFIp q}'0_hbYP$L U늷s8> P4u-dȐTC +Lv଀Qh3Id'$q#Ÿ=[|Ӏg4*Ue~iѥ߿ϯsVCGêWa^ Ӂ 4oc\0sߏ{d{ +~`{ P EA<(uP@Mi`{}DfM)h4!jCum 6`)Kgj͗V +Gk'{=;#xš{.9Sj V żFrSao[B6s0[r"lUevD-Ou`iuyCDQKSհȎМQ$dM4ǻ W0^Pp>$+^ p?w3: q+g/"=gCOwhޗ +8+vl9 %vMbq/݂$tq +Bb_ro"fH>*_JbĐǢՏNF͞;jЅkeq_ͨ ֡{=Egʵ eJ{㞪[|BޗaN SQu'jYKεk)`-"X.jqJ13ykp2~21X}b +eIObU8G?F:/ZЊjEfF~.N1S],(pkS'-qe +#jYR#A^IQi9p번oV՛J# El!oշy۔jo/ծ+NBE#U֋dU{W([uJWP \n|"c阧e ǎh*8_=?{}7Ža[q^LDvV|̏F1}Љ-2!Tz0tKDuk\~}*}AArC y;,sZ-7e#%[̠ހN΀p.D)K8N +hZ<Ib\\f=-/]ԍ~(7< VNezQݙ~dL|B$ՌJ$嫫~bʫ`QP"!X@e$}A} 0+@rb܁FhsTauEκO0qԎ/vZխ@xM5SBdY (MSPk7A47)MQwT:O-XPt2NDf1B^Upz[l^p%}m*~ܽ (7fj0'E= {Oq@yB-чx)Q0UzercWF-ȵz1qgdT5L'uX-JF0.j bCe?+滰E3bp4cb$BUvS3,Mdx]"I +Oj9"Yθ4>ߏ7 +UgnGğNքŮ;=E~sb/OJe+7;8o#d ]&ON2"֛ʤ,﷏ׄceAȀ~hj9_"ڞiِAte{^e 7Zm qucGZiAx!RW"1 Ō}nE@2y"HN=|" i)ځI~%wP +R!Ud#*=E +z[׽o"*P=jşQDG;Qҭ^ +0->6{U3 zdxQלbO<0"1 (|-EvE&h7-+`i|G,Vԫ [IiyYQ%GTԻ er0PN8~q}jN_DsP}Y{A+0]v6ueV>"EѼ)V[B"?h?/L/8V uʝX~H@Sp$ (]BQق6# OJdsU +TPh^E1f\䍠TgH_)YqJ BS*3* ]Ug tTZ_ӟPڨB!=i"3Q351"摟qB^M=8YʪɃf.wS2F:p3v: +3eӄNN/,rUD %W (ęY8&٣ VZeb%`^xGgQw#yjC'hGO6 FPnyP.dv_@h'ƕ 0b䬧,"=`ƪ3qMFD@u׊:$L-8MP9@c +2y-CܱE J\@qg[tY1YQD;恀b!bI_d DQ#(G)##iIdT݈-@؄E!oZ@"WD%FnV@Jz}(cNn-a?NUŀ-Ur`b42_md)0ײ9!"X]*F#-D)7~i%!ʁ:@,8U'Rl|-Ԏ[Z#ܒ}k7LrdE tR/TЯ6y5e{K- 71 !ds"@.[DɐVmtDe JNߏp0ԵljDDa-Č2B߯;,!ႹA3^ͦ++3(tN2v`iâBľG >+M#@gRKZ}8H 5*0 +9t)?Z4k[{X bO?0ϕ|5BlbWq@LM3vBӀ08d'9 Z +*w&:VP%R]Z4&n)-W + +ɴp%,enft2A$|x_ ďU\˩PBPӘ^ E#NԚq +Sw_^ {4м*߀-cexoS ArJK +G޺ײPj2TvbTDQ'8@4B?z $&==p3 bPv))g_%D< FA + ^ +[81!_죅23HQU3>4k[|,`sCMe ,|骅Ƥ{ˆ鉂mԈPۋt2ֽp_q#hvx/D(*}IyxIȇDhHK:ԍו(DtW:ߓ@́j8-"&^gH[0%4%PoJ)<5U'=щƂ6 xHtspE }څasdJT7i'H SKBKH_BSYhg>۳):3|Fl΁ p:ݔFY8 M (ͪB1!G &#等B)ޗωvd|l>7=7Á3\33p췻 +pR I%f0!Z8ck̼ +Ii^òr;HthALW{"PVbQ؄@T^fUC)Ւ҂4.VjL"Hzr)|,:J\UhS4"G:mN(E]`tK+EeGZ{N'ϳU ߣ3#?u'm +ZQ9}`ƃ= PoΕ&EFZ+KL'c!!p9I@ݝ"'Q[J8Pbe.y={({Puq +@Ak{I5.|,!Dx)$ҙU*NVl#*N@Gxqb;?iZ4LjhSmxP8[DPrU:?8PǂvNzQbvi+@_d=RkG$JF5#ēTx5A=3=GNbQG7GFD{!򚌢JQDӬ+͞^:pBDH(l"Ў(\V@'XBĦmjl\H-/ׂ5 t(bsPQ"/$("6 + +I>qN y'C4}bюvI0؟7R Жh؋{tL}DepIJHp ͮ+:cb{zC #޲VK$ J $l.C?E/]ϰyΩD^z.?q^%iRpn#yXzA$QVx0MqLVTd;+>{UZ +CWS%TbcgL}_Y!2> @o^D$p'XFD%^C ì#yMkGBpCG3UI'eެQ''*f-ejAB=+?5.fZ;O֔l3cz)eӥn-*}n>odyf|ȱT`;g:dY,xAxGv+㏌QZ6XCGS9B8Jitcf ҎB(>`@CMk+p"e$58BJ%J~=G +yw=Z@0$VVvlDh:(x@|m}8YX RyC, jhgV$O[iTCHM/Fo9-T^##Ek${&ɑA@0 +X|:%8<{DȜ%o!MŽrEDL("Zv"J$,ׅ,OHg3=*R:Tl g}" 4:0Q2ܪ@NGFgfo\HG`0ݑi\F"m=T)v'oC\eJjx6v;LQt鵥-_x t ¬c#^M}KtN"hm| 6 mzD: +{fY"{@:5 uEðnb`1Zij;<i7>; +F>Fʲ FY~$'=dp$"J[?|"&"V?^I5 +cANAb"".ۉ*+ v +l6F܈~D\yzܼu {Yi I)PSƔfDKCҗҐ㾋ӲeD|RR0p= @RhgxbTbA#ޠ,U(툄ԧŘ}|3dmTX4`0R7 0YY + +\)](%.h߈Y<+cАKf.me¼gAPmG1o[:pֽLz ߚ*O YB4=饹TzhpEGxNtH#8Ht}_U^WLa R@;n1Aët>s +tʕaw\^`ǞcIS* ~ΧBOfg(g,`|x%4X`\}ֵ]DrqZzSIcGI W|❱,HRzH.PA {")S ņC\-wE?(Q+plf0JhKk@ͱbWE#P;93 PN!DXx"͕" e&YrBgRۄPCT +JqUTةJ_HK-r +~^%$,{J vB+FʔP5jHDӒ"1Hi_ ]>=U](-Y%4Ucy@ϒԔx 3ñ#r5c/0s+!D[Jq7)*]C"'2x`ET&e)$*2N L,Hol)(@M2Cp0h{ &ẖ@SCЙҲZi*X>՘@<$ 9@v'{Y^~q>z_Rˊi*Pė1WxYfq!>r6V6;B&=TfH!T4@rv@Nߓ `#V|MKTJMMIz$cک O᠑MCw2㱆ϐ6FߓNkI*l>$vW/ D!jC KUty-uJ2(ڃv@);<͌(f8v7&p%N;DlŇQtzAȌ#ѡ`?`xƖӬVKI ++yoVVЫCY):v$JS^ [ёuewemq H).!>9^b+#fR!ֽw66won#ў )uj!!>K+QQCnT$?YٳE \w=T3lAQ! +R9JijpmK߄u=T\_2NN v~tK17ʎ@L&@o@@q)뢿O aNJvP٫S̜p?*QƵ|T`?ƼI]''"N''{n8ۋmKmbB36mڊw_jj1| ގ3#GD?a) 3 B)R؂UlP/4"2=`?0ܝ1)X_ ϨrA}Ardw.: TJ +8'b!}XKM206ݚMw3X蘺YyfE`>MW <(D-VHb*Mϖ'*7`"YJ5I&_k돲ȬDCDGM Y] z^sO~AXZZ›g5F8)c?::ei\]p{5O9}g$H3!_:3{QE ǹ%,HBT:bM+<yL*-DCdD(x1BIT:A_C#ۋ"|_hf>d-ſu= #cz+hq@;JHHJAH{F:Tu#BO犌24s0\ mBXBI6L'とUZ=j7 .R-0Y!qNHOW᷿ Z۟vz9ȫR=uH܏bSR6˔jPv/OYRK=*o4/qutBtM A#D4A%ԦHRRI^*OjX' k-8V' +SP|H 0(1U`k6 pF#7( R&ur}}(vCMI . ͒fmTjFPfllشv'D.o2qtf?4q4pO +ŕBDʠo +0'4G6*lIt \'<EEۡA\s(_]3[UVhWz9ZZ2g`@kv$! CڿVʲ{w +4+wR+ >֬oȚBGԡV +RM30?xG[f%EMB#aڿ;l6@9ɤp`0Rn~I6>Ȳ\j^=Y4/Rf}k Y%tB,c/)s_EӭYԑN!Vl5sHU_}<sGb6Tgһd5ts:.#C+i +; FLf{D^q9o{;qB%Ͻ[A7z>71]7mӅ'M,t-2}~FTK SElftl(C]*sfy5c + xҊ"töXi-%^yM!a!'FXj{`F2 +?ƩbW(gq`bq}feqp76{Lx0aOȱCeJrGrP66¡`YJ\l!NUio/CR+>XC[ 9.iZm8h͓jMT6BlhB$U Ό>d9VoB 홝 EUՑqxx]Kb{£Km{Pgha?a:#NV9tٯLd^H'm>Q+qU[}]<ͽj2dk.<|G׻zoeAj;6$T8 +Ao_MmSBGiتGp/E՛A }JZ!`X{gpQHDDV( MbMF1%%@&Q|f-Z{+ԃss-'{l>RsYو&K Z{WB͒JP  O9&(IsU>$ѦL" XF侑 k%{F,~V?ϓ=!$eAg΋9 *\{y-M>F }3u9YC[o/ZN]@yP*k{PcP a.SUWY ~'QBlR;;8]As>au $cY`F9䐑Y9uNe:AR&< ('`WRUQxRԲ V4 mZD@BݾϨ!'߀cBPQAXzГEOL:R,1sP3b7ҏxTmX j WwNc#W'Rn:CXU[x"%H?Q +)0vNн祌B%FȽ--Ц +GD`ּ۞(eD{Ȉ*hi §)Oŗ >2-Y'Jm^!XMχ~;E#Dmj%3 1103]_+{}R[wd{ğnOMpUgKmU&DjRu (+ep$)UQA;G\vHƔa/fWz$;ϽsP>2AaaLlBKՂ?ƒ̡?aۑ*E+e &5g/s-`nyW4/ OCŅK֓>A3}R<5L06D6EP?g3xVSc{R'5&*G|&A %;M HY.rRNU|y@P-~# ֖@Ov7;O[/%<T%D X17O(Taey wМksC &Z9vIS'XQ' +8x|@#X_C_{HB$F/urMUVֹqk} V58 +ZU3a#X%RLjEq +AA} HP;ӟxnV/`G}=r\>ʠ#B] ܰ񟏯65n ɪ/8-=ACBC)܀<"psC"JQ45.8YP2c.b7?P\ + +1ңrYoH=)Qo9ٻV5 @tVdͬ;i'þ"Aݺ3c4(E #Ek5hiO<0^-Ґ؏Z"f@ammYϟS˟?~!)}"LN"8h'0P jdpR(3)F4뚴xׁi Q>F^9p˧|wLV0|}RZ*J_hY7!?.xaݯuv1Q;~qRjT9:HGiV^d- 0:d?d[†l' 94m2u]a@+}~mx˻0@ᨆ1ϵGy'|ƭ?:(E sy~DwϷcl;`I7BrG=Fa_q_gH*SyP໰,S)).+хǩNf Fc`ZG1Q~ ˉꮢP1k"ƈQ7˔d|~ºl0s=ѐ9Glmfzm̕ +_$+Wf`G 9,=Iql?u>%1s1Z>A՜j+MƐݢ*MigVa]LJ ]"is'RsG h!S~"j57ܨn遡G@+5?|D)s~AeKq#Pk}$ޢ>i!ـfyPYgN5_#^sfaHCم8Zzp#.pfrWb^m_ݨv%otH!9oiP$B3" bT}i}+ -qR W!zPc$v M&"n nUoz'S44JcԦc^yF-2&GRݵanbdl6loVۊl ]dCxh*(&b+"oGEA=H(! + smBhLAjtuCo >?=xzXz>: uoĪ'ߜo}^kQ+ғS:ƌ7:tz*<}l?_|q!\ÛVZo1m+D$O@96P-rmoE+Jm&˚G'F{l㓌=yp mJAۡ&?"H5E\ Xn$9f3(ҳ=4 +Ez{ )Hߢv`ũ8)vn%? gD yGo BXJ)R\hSZ~*% - +#X]1!Y@Rf/1|EF55/vZӏDب%ƾ:Iȕsy * [0)&1BB׊M&L}S9?T= P+ C"rh~e޵"PSlmzQr'K\ br >ٵ;:bopHbL AYCU+\6+SʚS +weКZ}<`#Mݟ'#e+Ov4K7o~_??owwoO!o~./wogB$VdV 4,}T|e++h()d<>@U6*+N}XBh[;pږrxLu.luV7oQ] d/8xXsL3b촕yEDXBh:,{nE4I\ +dIl3E1> f1F,ebZ9ulQOoW"mKYs@Uѻ ՠVuu*Q+]Wb HtyUM<50$AҫZ+È"멎şE (@DzJSuBČH95nSFp:QAbQw(1Q8$EkGϣaҀg ^Wh6(bQr9 :vA9yU l) YygbY4=Y=ufIIA}г=ZZg?8<-z4t4?z +׸SY%\1ЫF4 =&xv?>u'{Xzfs ^Jh"uS=Qھ}qSm} +-H0ψ99u6 VL[]S;Q;ҚEqX D f]p^瑼GV#ZʩAS8ΙCWl& &ݓu;g1_Sܠ. ԃMA0i{w#ZHh @9c$=]Ɵ}IZ29HGݡ!`=ݹoD)B;gvsݷ#HW%7ct8e~-:[PԑgW`1PpQ{D6(%v$y /Y7iY6_n}Oƚ'-^QR@AIO|"+NC{ Ȃ"HPݽCYp(Djcx/1@O#H.9ˆ>#]Z>4 ( J_wn~z>V `0yr#+@zzPc)GJQu"~Z8L:1+_v@oW++tE<3y4%I:gGq#(>aʕ,*4@kg /4}\ꜜ(1r=r?עC+p*.coמX5mmxy 8!+5Fk27ޝI&XtYx +S 5OYk]H0&B2;FP31`㹟Rҁ0{lU!ZL`O#"V E79?n]չߡo{z DأH )tF0~ ~8^dନ?K[h}WeA˸tĴ r6Q\Yg3z!0H| ÖQ8XƤSAC5.~?^ix%p!a_vK +Uv7Gv7=I};p/CC6 ;Mު\#h9>'‰#3m3Djvuz*|F߁rW8 5B[؎>AƃYz5weCwm d^xR;HQR =;G:X)١;$ ֈBe= XP ԕ?@̤5r|\ڣJoCߛ(Mv]E9 *,/ +AHckgCw"\gJJ25+`?DQ&@ n$zLjW#?9$D2n7{ 7 +G57ĜwκWw8_nϜ-޵m>87-ϞLp^W!JbmZ7Oj虶`Fj%QD!kTx˳ۙaͪm+e'@vAalZCx 7>YFPO~xD1g'3z*f0HwA0=<={o"Ez> -Cj6a Lt$Y>>~:mx־9} \HFʰπ$# rkTZtۋ.S7J%:[FQѫꐧ=|٩ǹBG4ZjW<:1>Zun7P?#ubKȂY54GEKgbKzd8 .]-5&7-ukRuޣDnBOV<9k!)vg3N)\yFL-XK)'x5y곕JF1 IeR@ ߶o$ٔ,8Uۚ 0Qӌ}.du%JBICzxaܝ4JD5-'%qjxʕlV3'xHcWhYWGUs܃Miv6] 9ϒ=.띑qě8Ao DK˜LIEJc֏X Uߏ^ f4آο:ǝ=7.kmL{.|J2]iJY](Vo%3y5SD:oGۻiM͟WU`8lF01vjJl. g6`HBI_H6:6[)b`x s`C'uaNd6hД*񩰮 3o)ZURVب1)3;:+`P@+E-i +a27Yd[9(|5/6- +4}D|&~¶BajZJ$_1ah6z4x%v˾c::j0ėQG!vCMM*Q g;VwooW){0,s%9}cArYgCZ'=s#"\éW:@-!D=Syg#u9"p>WR8E>5ǽOy|+mZ#HY=֨̕ +@+Ң)wP?~2+nbǶ>>ӊiTT0xa7l]y q\Șh]%] +U3#]!?H՘b8B]?n0Ģ +>„1l<*BѾ3O33h ?U7)X詉OH;4\Sl<[xWuD)_l%>䎈 9TBC b<GzЪd Ժb4}E(iADcB+Nb-V,z{dK~+݊aXDzMaa\!HnH ef(GږHUD+̲Mݿ3 +fN.'[mZ( ꟼ2k3jn,F܅oγ6p?A:ґDG_8c%[4 c(UA01q#y}G/70~ 淀L__,(a=gu8eH׏8Q0OBDEfDH@Εinz>nՎraizArJ}ެ1T:g[7:{+0,d\ꛢ9K& t7DX|׾+Ps~G/1N>}hy>#L{+F$ߠVn$g>і 8b(o~n#S˔)y 7q &VFJ̅)(3Q#Coj7 `tk8G@Nsx,^^WeJK$@# {i9\{T+m4@&K%EI/:t +{D=h/aqӱ.e+KbRJ@ + + fG @FiV) d"b62o`><( +~jSܾBў23%1X3\ XƓ}d|8! ]׃v&Xhyfv}s ^{|l~BSټi.iƷAg_f%Gics: ~<$5:"Y}SŖB mounIi +u\I4P-7Z-O[hiZ/^&}QN= +aI r3)t?gw&'tQEQӵ< FEBCY*p\r TPe7&Aw= ¦]nM`EOBPjTKYdAﻇ;#(Z8"W ]& E3OL>.L`]Z6koZƎ [hPx >z _rH ⅽ[}FG_)c5`>5 a{IH- +*ذ?~en޶i!\݈؅x9Op%`q,(q⧩ O/$C+աyK4(oju?_ǛFņU!}-|`[y&;D-< jᚶMc(_(sgSP#(O +AB0 ׁ JY@4Fs_)ǵaJC16\W@)"jbn<^Ja+?=uv^C1DίbEx-<ŋ;*@jYxIoIE +P&j*_$atESc(+AZͪ ;0o^D.lmM +T-seuU%Z"T.h)XFW-~`~Gt;٨ætuJ%.o]G/^X^NH9H1$ vӇ,+tTx*% a !ny2B1LhIL` 6Ou6df^ [(눉 ?7gQ5h@9Eek^JVtM bz$_GUu-[Р +/0B" { l\9u!l]f *%d~6[$Še += s0[d\omJ/.QqLf_&=̚ul hx2aۻ_r{VjRar[O|+;Q*T^EwPq{wmMcev 95i O(ª%a46A;/Zbn8$WgPl~ +LQI]HO]MGOoDOdeW0`臍03ҦG Qt;MÁzo4MZ<<'}㼒i ϶ TXiPĉƈ)וo >7=.l.F +":v4#M̊%]9dg=u:d&/oI=:f[Y'yǎQ&i %5T CEԾ7v@I~Xf,0vV[-N`* ]a +zG5eg?8JcTS +G&}#uN( +0#9- `A$'XETme.d]mQC%ڧvI:6akHweH% n ï? 'DL*EovtEGNi tB9x_~< rh갂i7m`JejE +a@mH9v;Izu㉻keޛIn#VGD}@# >|}KlaO{4!m:PY +, +Rm;f(fH']TVR-j%#زCDnsR(gJ~8H`H +~q?n.+9RGLh{Sut:KRˁfs~Ͳ=9i8+A"/269en'Єzf#e]Q`%m]v{>:'{18A#yts9H"yN'),>Cv j<%Q[ƪҜ(,*3c߄,9vPc[iuwG 29N1vT6J)6,o=ʖr%2^ysnN]׈dm}a+׷'F:}[fQ]h7J$Mzk./k2Q| +4ZU=fv/qgN˰CKc> ++D([3vb׈k/-cwTf@L&7Iȑ;l;?\ d֙zܪS2Avi'W܊s +os]#"Tf'Ni\Œ 0]U}5F688m([9VǕm 6Pl(H6|A0oص*exoF5M]WzWv>[A/ E޹Ik&;@JD0B}sA֗?Z"]Νk^;_]J[4xPɐ^5)7c[K RuWjs|x`;5m'٢ +^[@$ŝoMڤYs{en234z`FkN:761v~Bc_IN#anH}2Jȱ]+h|cjd5bhz+M+#r +N`0sߕ!LX?Hqɿ{3MuȴѰVT*5wpP꽌w +Wnc ;q+Ձph{Lh7YϢ.c`-8H52{%FgyM QwMƁP5Hl!k|K*da5]&6s~!S,BD^+$JyjWm;~zxP.>m6 VR+B(b{~s"*lEd!YZ@膓 = @mXێֳ5^ /J}jY3\i2;b?,J/B{`Xz7ɫl00fQ~E>]t+]Sh+9t:t9nZSHHzUk3O2ڡ[26kΡ(FFqaH d>b0 +G}9 |89/ebBe`;2@`㷪ԟuDC~b?:Δp&͎c,LT;IؑnUY5Y%8!ad#m*E`FSk/ a"&x>W_Bvj}nw F^gu$ B`%PNe(#ۢo;{ Lj%$߄r ٩q_h+y`G +wf7B~3\,bb7W&`3\=# 2"3e;: +J禌`7NF\\`0Ug3e-66.]|'&˒"N9E UN&H'GНa@,;-h)*a +t iE!\5^:R.\Qw |z +xf%8R[,8ކmpnT2bTGy8OtY4]=6YuSr᩾āIIF]^YY7884uE"vrn!Sاa"6sO/~Md)QeU҃^cfk!FIi w)6]Pil׎|#%"Ds~ynƦ?2ew(3q+I2 jppl~~m s>)6j A SȚ*N+Y%\I lqRhRhr_`o[C~w#.M$TMe-jʥ7MRpU@cj,l5v&jܼ&o,2ke3MP @C7XsT I[Qd +[uUgh|n/,coέ|j[=`Rߴ^^WK;ŵؾW43q|cRF'x Mcc3 ;~ʹ%H)<&N*bS|J|0K@BW!V0×<(]t\,<Iଁ%kٺlXpş,`?o^AX;LWraex6;Ӗ鈦[HX\E=٬@DҵGȟl)3xDET?,ķk d(q%H=pI ։YBDlP1!|,(겷 ߔi{@/j EA}! z! H * U-ҹ6ӤbaUY G~ C^c +dDYo"KvF1ZOp,ђDbT;8<%0XZ~&ωY~C>-;;wi{Ew6R[k_[foy(YyNWH$ENp@@ivW%{"2I9 gf0%RtlˣP${u%iZxafEӡv'3GTI^Ձs9GZąYd>&]< jHK oMmnJ PՍ{ +m ;Gx.ey=jw8}#b>u|aShAԥِ\/(£^ BGA*\ʖH+phv: + ^d a 'ţ[cdfB 䕈q~C]u~T3rwp(rNjwZqQN=_EzgtmPF:u$Mw*Yழ.2OKHgICInN=ȅXāʌIg$V Q|zP?7"Ɩ'v#N_+?տi0ַEI{VjWo(1sE/q.\:zC}FX?$g0yV=,P.MdG +A֩Ia)+cL  h%.Yћ].?} !c+y2Vy9dN*ʣ'ؿwn̿;/;} XְMYAtQ٩h`_s9GK[}5 8$y,fJ.qh>(CNIQ\wtո[y@vc@}WfEI6UvBHm( se݃3:U<x)6yJN;\$Qz BF5&wi¾ rG'/Wuhȉ b!J%J)3~!VԋC֛QZ aS^/T˃.ZMV˝ ]9N"A\6n#7<;t͆Iti~:}.un~a~3Lw5 +6]P2ԐԿ ;}P+3/͚5LHVB6ց(Ͼv> rj̰z s54%RUx˂qwa\hF^y':ΪhDzj0?U8ٷΈ 挆{U֤Ǿ=80"p*[X8 C/s٣dw0 uv5#:Q52g~PKb-@ގׅso> ҕ˾=n)'}i}FI/Rh|5Tr1#*xߛJO:iK2{z+OAB[_V>< ΦgRVIG(=T掚u.baLQMrgk K\s:^bߪ8m^_F7Ѽm֭v15nל{~y&jEv{B#6 +!6hi5珐޸a~o_IO:f?ֲ}aL#q?6h\vP jW +uQlciQETn\A8vSQf1uW _NFe UUï9Nrt5Q 3 ~M@v#YSuwQ4D#"?Nv_0yLƆЮ3aCW2L=Dۦm{7؂ܧrC%+3lɈHձ|mRP'Ү_}}O̎ :V=@P1Nz< \`ƀl~5% `$({Fr!3+VQ'6_ESJϲQZ5}X9rK3 A +4R Ӯ{I}&Z8[TEOZo.cgustQ ?қpo?7;BUNV %"D\|V7wF\)]6FN pOivԾȽ"ᠫy Oqi?QK54*1(y/;LmQjuT>PA nDӛ}IyO~LZLǦM23P;lw>~tNK 7 cd;K,gķk{ JR>R uCcGv tx1P4?fFZ Hҹ_<\zw͈O_q>,(~avOw&+3J3p%K"G?Jۙ +Jw})q6CR{c^ɨ yE5 j#2شώ kOYcXO#5U'r63{Ni$5(Z"4rc|7 ,Hlw^,ވ쁡z#`lC_,X\#9KlP"9U5vA>}߶ +nb?cgVơR1"Zlvym?MnHL>uf>;c pE{Jo"Tw"1Uy%Jez*g[q8CV45/hӖcre :3uc҉6 &SW=S?[NX_1ժ9`tlj(7 +uo;J +*E;V +CQ)I̴CT4G4f(Qf`gJ::Qh5o%F+Pe`U ˞m9Hx2; uC͜HŸ}[jï!e|yAJC +7OG@g Gd:X+J}afsbFe( H00vԻdE(B\J=+MI;\"7WbV豍]pEs\)8[ȑYTf)pM]GMy@m "[7uWyZ/7wMݳ~TP=_AHN|{BM Uu8nSxgQxO~Ni72-u[wyO2|{o>>gLTcxbi[/ Hy)kIB)k*d$6 &JI*{sE_O|tE]hvIiV<UhI29A)͊\\Ф 灮8#b@;Ѐ>_kh i +1yo"|#qG)=J=ā_t5ٞhqϸ&Sل5/^yߣIdҠGRI;{D)EaAYk-57-X +Gĸb1DA.'m'Q3QtKA(2dgY/M7x$/zH|%h㩇2-k.]Ǹ"D/ƐʏvK)kFzb|Hl]vLӜ1kt*mh~bёj6#3"cj:bRf+c(:fn)sn>"BM,A=pZsmƳC>$%'c'HY_36^-sN4+J!!\e )G'pN>$S'.* sI ;{Mk!>@[= G렱kZ⇭<߸0tX{\]ce'uM>C @DXCl:~}:C6(JD_}汝VߕJ8k=4yN8/jFгabeO80UX2Sί]Q/!C(!驼T V' ]egkk25Uib YbWg<~X0X0-~Nt`)G~Mٜx RN?0ӯܯADc~u +q™) z!5rM~h(!W}!cari).Om]YՁ{xMr 7-_XqjnoaC9s5 ifcAZAz%J<;'V|[b{;^b~Ml^awN<فc%珿7?/V~?~7ޯ3?0ԘSZd1j6NXs٠?d)+k)*tQ-tZ"lr׿N9n4&(? 7yP)6[8/#z&z-%&T55S= a}1-l؅Lj^9Pfnޔc X\R޺6A\YY)@Fnf/;s7y(«7Db]Axx0CjڟxMnR)jmCऒwo^-OlxYQ[Pֽ׸l&Q(AJL OE\:]ͦ%iO;\X#-Pzx?͜.΋s@sL&p͗?=LDwK|UOU8ͿfR_A ׁZF_{ +3 +_=u48</7qR*[Fʝ=?@JVnj[ 7K#&i 9:A{|~j[u;on~ +=tf^S)v|5k5Ʊ&ck43,d$j2Q$6\>Agt⨔&e-g"\ o&D <ސbI)׬tqk+}^r%DB`D 1P^+;q\?ig>ՎmҌ,&̢NSPk6(J{itU{KߗL®' +_81A°=Ssmyi+ MYs6(0 YُnOI}4F'+5a\C+c Fv1yLAN8#pShDXW(2Xc;3.ڢЃv|^&i⢢`my&I_E4$V2HzbsLrI B *z-8[\ܼt4c7!cdqU3"eRW*|(gNlA֣o"!u*fʞZլA8E +a 0hi _b>f>aEQZc0]}@Re|vF6vF&kd^xkYqvBb|RbOeK E5yP~=c؝_T`dK8!=nѪ#{*3HYArQob> +hD"_rp$Nt>>gK"ftp#IZգ/70=с4\kP4LU2j3p~i;?~nmEIMOnDeqZB%2wqZc.Op~Ƅ >Ϙ5Ei<6Ա"^Oݏؼc$̴ pGVBY|:ZpΕ>J<l°)!l , HL>[=GkΞuOlNaɴY;^ TdbǠj1lzKhҚдc*L+@3z (i=O?Z*l[%iƃoɵBL gsډpVחv}F[xk"6֨uzP+N sl&:r$O,Zc\t +XˮPO_CYm`QvuVW'S޿>tn-87@`@a]'owM˧V3o9П)s'^ |J3qgP|;+8`((:># BPMEYЋo:i1{ݻ +Mc@|#D@+ |VUmzb:`*?5 ÍzOwA)]بGDܓvrK.l]l݋R[7Za[yEkRmZZ~ EӦf$I(!!u +Yf=N +Ox*,,,L5S'- +SE+}7EPiԡ{{Z)1.kV!Q%bA:t\>%IH6,EA^2 D^W4`I[S-feI`ocT8;Iu9(|Gpo,Lzpr*{;t$cbačZFU?a_ɎQ~Vb1htcUFqAvnms:ǷEBҘ[bjt,A3 s!\Ȳߑ/}| 1k"ڟG`5wEG~=ꖭB8]!]|wL*>Z%O?0-oF[{ߗ7TSypTy-ψs#}#?poa]Y)^)R'Pe"l!}qky"gL-&BXI>x5?(Zp˛؂}kcZhpa)#N&Hk~g'~GxVޭrQTÑg#Tc Z"0,I*Jt'Xņו޸#)|Oo3S!hʮ^M)dYD\rY:rί;uMAK\xmJz>?# +\&BSmw?"4y;˪JP1U6o5k.~yi?فxI}0Ƭ uŤK + M+Xw2Q`:c+zA=chВޥٞ_em:=LLpF~֍()At:ߩat_HԱm<4?^PX OM &аyԽ?%aѷ# \^`,܄ -8`'#s4` wŘ'X33wSxa~lЩ.Q:e̯֕u{~D<%%}S^9y휁?5CHz^7Vƚ ȕڿfÏP9qp!iC?Ÿ~=ϑtN,3Bʪβ6"~Zq7(bz:ݟ~8$3 %=:bk7_9,sWWH*A0}\j-Й2ZAU:Rg_Z &&upAq](l>?dlP`0q~s~PBM]s!~F/>G,ZMbMGV-Ԁw(l'9l②قv +;M-X)1V' ~7'T\af")o +} +6);~z1~0U=Hrr4qe^z]2𢖼6GiXy6.wψÏlR8< ,1mnܥ{t2i5?ޏ\vÈ +.nB#ꬿ*m`%f.f^A G^1*~$m~R\X0^#u%Հ\eN}@N3ȋDյUTO&ALcEakKgu7]Yt떷Baՙ;e,H~X8ܺ#7w0vdv'c1mmRiL#F޾snnU%Kϻ:uA:jRZ߽yoU9{嘙eFF~^ Q>RWhB2OФj/t6zC~}P8vHe^ozO혉tPi‚1\U'v7 "LEOpg&Z:Zj +KM |Ao +RCbIJC,P%jB6cU( QVM/ +.oB[l(P pdc#%gU󻦶S%għ+뎍@Q&1B*qR9O%F@k>>_JAFz6Ñ:(29H0ظt)3> ؾH} "J\Ot+[SysMl">UqZ*VȔt!(^uy`{hYcxvwNh~:(\VцJ?n>|eC\H!g<ʗh?,xwG#dbS%3T^ax_5Wb'(;"~I`/X2爦1`eϕ /vaJJ*,\h!^Z<>dSeyQtZ`cBmoۿsTc*i|-j!jE^T,W͕Wx^ǔ% m؆ G-p׵Y0fWS7uBq+uzcE+g扟j3,P _tU6haK^,'Kxi(]l2]XaѿW4R-GvED/ ~[jX;WK钎C6@P9' +.Ie&~7-)'ƳQtsH/0(>@3 *h+sl`dMe"v|ȭ(Y2k&Q97.'_71LI|\M.4+)L+;?iݷd*Oq +<|u{K s OʠG +WFO|DAqP8.d=H +k-%6֝DفosK\YG GvX\Vפ弋&uѓ+ntdLihBCCH)TXOw'$=۴cX!`o0٩r١(C@.b)s-OȁrmE.JI&yC2OŒ +%Ԝ/^D j-ۛ\ mc)iqVly`&<yGf^R։Mn]] 22IuغۖVmQX_N~~{^5JYfsT0#QiH, +MgcH㢳YO<+:rM81J!8J*Rqa(9]tco4(ztZV5$FY5g!1y=ҿI$1])AJ?VC;iq@=UoُVDl&X'Tm6Jl60'tsQmV|z$8>',YĚQd&M߫LA>VS3dg H XY=i[0y&2Tתq2sZ@OoaC w +0{ԮZq+'݇a@z )`&`c`Ap`,:ot'!ET~G4x1d.gB2BSlSbgO-;eǷ{ͫۗBcz;S y<}oྐ%`B)LlŮA)v~]o*ހ>BTVՂ3B{Ϗ#FH/hƓ78"mHzpaJ5=qV oetDӏEsDntW@A?7Aa7x|2v;;r OFyokĬbuH$ҠbS:~EzԣEs Z3N6;m/=8$MOҷދR@::՚"okI}&8'% +{=DD[3R7׊ٰe``|`ScFp>t|-H;!'wHͷ<'f"eY"DP.xPW8] +!hXoAXx@QRd voj'^Eoz}(a!EW-вNc[a p3HԀ6܍*8{/ȋF㈘q(oVZY~OYɎ=õD +)) ̍"bJ`8D_߳b:"6C.qܢzU VSLkuL[ұJ[nO0Ȯ|Sa>PmK\ud9ZJ{"tA<;sB&|V EMoQ"QJS?ĺI+T͗0{Z"22=4uYxt(5"=p]z={Pq:[uad2X#=#lx,DPBX<$Az9{GS\&"uUwLj㪡r7w"rutT7i5"\pb\ ۏlS2e \Di"|- В-7 (EከM +xTRC]&Epb\x8S3)5!EiiێinOE*( Cu.Jm]=@Պ&zL"jh[]5nkyן@/ +BR%Q|EI"0CjyG;[ #/4As!2APc^oA ԋG}erx%dz,Q]"7PxI'yP{Xe]ۨ:H2){2F.WuEր#l0l*h<4Ut)KRD=|W٠c W$;mE"{`ӷ*lZ\™TV%Y9ʖ~E]1 (UV)EĈ!N+_I4]U[h==E.@xv{`,`;fQ;f3 +oIVDg(Wx0Eh\5r]dpHՔ7 ( -F}:K Q^iA5\[%#A5 h:\k3w>5ɽa ҝ}=:)cg8:ߊ3(9{jF(=&DDFK$I|DurU޳'8AI_Dǯxkw;͕iDbCV'5JjD!Jq胨L{X-}t #!ۑ}Uč#/aWY Ox'3:\߾zKeԒ3ޘ5G D'^NNПSk|~2$:W?43{JQ)Cu%'X +s s{ ?ɼ"ְG0b;d}7v8T?>F_!& +7~[щ耒yF6uOKP- c(LB%U%}x +kR#Fw@&4eu ;rL2r.o-,:Od]B0{iOVD?i$lz-xѼe{͟mK#2)l?.ރ U 2OM.*as|7B`;g$jj$2B}S5s{U٘h5ڍ&k#O?Wfzp/@*)I(%<wIgI% +Q3q= S|DC㪹RusRpSDYBJGH±u7 +T2M -Jd hOB]\hMLϣ9hiꪳWA:]$+޷YJtE),|`R{єu*4SBs%!X7^3LÔkO)L?Ere2tZ7]"C[VF?.釒Q[ҩ#[ ]P :n03;)dd]P)GB*xG= ĆXXֹ7m[<0|5OxOAr]1!+5qDbNb\A`9 `Ge_9{1`VmM6ݲiq7EC#ܠ`=U}ڭr0& 9ɰ:ȎNb3>Gry^Ra55M,Z"y|=h3>D,nIc_.vu[*hTPnSUPvE-dŘtX"qe}<_2X;GrKE[W<~@c2Hsfmal􋮰%0T|״/saimtLhA7u1&:EMh$*b6{=#Am"ihDlf:+mm/ʡT^Z3Q$Wk-[D83MϞ̲r\4%ך^@n)fRVۖ/(ZJ4ٜWFUevm B^HvoآԒMrB&J1^J==w|hzj>b4;O>فT(ݾ./lP[y7<_0'S +%3OR:+2vxaQB(sFרrgku.3qqLe:Uh;<^5ÿ|̙gҳYd=4fg%JΙn#7ICHDG~f6𙗨)ŮxB z&@h"|._2ß['@IVZaCtj"-/ton3+bU~2];&O"@3Gar㛨ۢ4b3Ds/QʢHh +lPMK}u^@~ j GU">[/"RӾ?GװIFk@";,n@(#clvDM&` _`moF/`[fL^ @` ru`(B*}zʍպw_vvUDGEw>3z"A#k +EyI=DU/<:4,1OT<]vH~Zqт^֣$C>MX$cXN+=K%hSgL!L ATz?$Yzet4I1WY¯Tc(_LfM@ +Zܛ`^UV{j"23ayR_yǾ%z%yB!? +KtDuCwZ!-]=[DQCřAb"\/pa3WB3BJQ>~*)#MEZnn^OnA~MDg\ 04)~6nBZ8O^jA'7+t\f6d,YߣLzջegvN,SHQb͖gܖ@!n-:! a;#I_oO 3(iPAsM:b)dwp2mdGj36~x{èi [Ky!Uh%ny57dEE#8J"  /`5^% +֐?{z!\j$b:Z(Fg ˅YЯcnq&̞[.\;.nk(% +?i~2d;Ф|[̽Ty}и5 Ա1= XM\oѣ~FI) CzP-_O2>#(= ګ +3/ԤCu +4\U(K애8\WLHFyB@RYۃRŮ ǵs +_s.@  FCᩘ0QcwX1a59k3J9>VP=Cs7F̠:evǂIX-<`M*$E*h$qF [P<jQF3.SM+'_Ȏv$8fB4nXnN/6cs2Rfuds >HݨҝXTEy:mb0 pލ*+ l{oCRْ䣬~F?cٴ'~U$KpSRXNWpQO؎UgɃi$A!V,+ r(Gz@=Xw4WOʺܛ! 8ddaHx_L7|6'(} ̄(9yP00H5p{q7)rMKN!O!*OdiOج%g`?Fx Мa3?MdċFZmяrO%+a]l1D"'ʅ7KcSOmyYa#[{mfFNΠ "c(ɕM5 gQD%VPzI~=pt5sX a&93AP1bnZ;XW9i>WI<糱urn\yp9zw Oz/rHDTW%P/%WOß-_idì{Cw$NA*svea ASݫJT"5.]8B FF"b=bnh UWB,UMzB})9M?Xv ܥd]˼ ~N{%K:9p rλDP{WLk4 1IcQ$8N>׈f/Qf#chl~(%1A1)Ξi cX4aJ[ f1w}ZIwd@-D +Dv1%gB֞'ԇ/쐳_|{jkpSi,H^r:[ )rze`:rs N<Z׃& +GhJ&iWh `Lu:qR4߼mF=c#E~5*[wY^u{OEEPùh\B} Q:Nz=:KJd56>=bnԓ55A]CsHX@r(V#G IE(ʲx}˦s0((߱A\`%s:>4ea|~%M%/^yl,o +“5Ř~jLq]svY|mA>aozwݻL ~dMWjZݏb׈Dm4rQDe8i$ڸ\ۘ|(t8 ZhKo 5sF>l.YWJKvC!{- D\& +EhQhtRO$V8-a"!ws(%>I:@$kA. e/Bre}3)cϻՈ&]j&J(EMI57;@ݼ$:(xhȈ?'UW>=oYoF0>y,G$Bjp-rEyld!6S⪤ hDf{l\Dfw&Q97rhiKjL~Y|ר@M m=񤃼haG +xҲZIRPQ(kH#Qׂ׈bE@!6zQntE_fl z]m)$ۡeYKW+Io42PT~0w<؈BF^v%ꋖ*Kdx <} 53KE|Aoߜf/QY< L"5i=̀?WL5( +ntUG1]WѨfGA❏E˕rBEk#˼νXV_!\ǵcB~?@b{xPrOG}Yʰ6ETQfWT[&Fh|Ș:p_|}w40bjG+,r}gė)  {o &8,|h5#ӷ8kscGO +zX13+sĶ(5 +b'`&t7)Gq/2>Y/KuQ/#Ӱ,>ω{SgOzn5/DW0ZvD9I{\5) NBJdQ42W + +KoY7{hyS]\q0GEN]k9ԩU0P{oD'X>gx/Pa諠jăcJY\_:+`WpO1 +w%Bry`9x%^˜#D]{?qpAo*~L<P0]IjiahsJ?GwwqW/q/;@K,f7QxhY KgtX9 YU"9mhZK\ +dARЅ]w3bN|D\M"MʺX,NK{ <&; h=݀-*E3*$jz_%a,j3mՕFq`Ok+]'OⰂrE5/ڑ8'7hABp(i!v"r:ԏ(Q4ޙ׀R<Nnp w(uLTC3߈+ʒ[Ijءp/rW{sOI6:%EǚDQR0qf_sݳwE7n,r;#P׷UנX޿o]kP +Sﷅ;y]a˟b۷wk4cxTb O(c3^ꍈC/TKόT+0&I).$C}g=A LioKvA9_x(D,d A{k5);@P FIi?:ZZ4@_"7K\ߪ7QL{sMUJftam-ʼn[F@x`%"L#j' iYtv;nh)LF\[U +T؁Q{Z I:z&X)tA\;w 0g;['/(=O6̞{l +Dz3Ќ,EI_0S5F5yTR@{I 4Crs+'ёt?v^k1YbQcgnBggs~ "J9:[#Q0pY͞iOmLe(앆Y.^.-y”y]E쵫gM rl23tx,Bۓ8@֖Sx}nFW&ܙ%;1ЕeD\씱Cs*h쬉թͯ2M=FcVmQ~^@PH"0νvi G#N/E z6DڲrQ4v, /Aeh0!*xa']$ iWqp^R5vPЮD0B_hS ?aobyEh" A&@r*o nFO*/q'R8>yUF3gm=z+#?J0jMƞeң-ݝDar֞cX^ңt6` *Ӂ4lP d 2Yb4]%E`\8A¼pnO7*gL}ZAiCl~3*=.LST]H% mŏ$~= M/΋!~_vU3XskcS4GL^E%)`Z)z<{'zL ȺoÊk9>78Y삧>M %(ݻT`?ؿ5N8!ZXTro#UUǥ Jg 0'FHa_>Go%(zpx2r}T|n?6Qī}spoxnįulS5boOk^]}>5Rx0Ԓn6aυDV];Q gOv~)UĀ(y={_z=t+zfH[n2Iz]lܰ:'#eH3.wpDQ@ZfɊ\)W67jMT' z7!;S ktL=L!%3 d̓l4#U$o''%lVnZF<kYC{j͕u>stream +4 |JIǁ,@3!uC_#藃zcL]n~"$S-ɫ3Ž{l}Jj> >;ϥ;}(w+~lQm V{s֜9> 뻠Jt[C2IW }giBEk?uCOldlߜkRu+; + &G9wpILŃzOAZa1yJeCK x÷/tE{?rKb. WGMЏ/)}8B +=n^喇, ^^K/`c`k|sP0AcyAr!hH+oL"jޛsE %:bcr?p!n Ǝoya9xDpF£[+3H˙g(]"dȅG'%kBl~ڬ =I)f”B)=e v"#R݅ۈez;:_9/?'9&U7mB]F@OJU"#s2W7+.2%+&Ӏac4c䆵x׈50"c Ղk ?+=֭Aw zFMEq[~"ѿYm$􃩾K^ᛇo(S~ L0-d44RHb!&tO2ׯyb]5oߜRPC߱kt~2X}{{Iy&8rp-O?GcG Ow; F‚kgydUd y#⚶'dRFt0})aNv_DoMEρFWvLIAk:暫wp xcB6`.co8,N_&:)ˆ=c'kޖ9(Q^{?:2(ˎQ%9oMBʊ?Þa +k-SvDP1#ªsD7% +6x'AHN{;uRqF" +#MVDniQ'"hb\MJ&3i\<|"Ôi8,@7x4B6xK@cta9P@va@Dlul {]Aػ{;m{޶p ^h"ڋNcU7BhCeĵpC* 3:rKg`o?o-#+eQ_/k jf'yxIfi^Zj+2>_[Մ} PǼ?4C)|]B~ᄿi[٦As6GԠ Po#ku`X;Y +p$WzT6a It ĸ],Q  IT҈*{>ij}9`vF5$ +|m[9Ss8Xf-?d/*{ס6C B5u#&:6a׮& p\ 4ރ kU$҉X։l̎0;(fӨԎ*b^3v<,qoM5}@ ֲ@Ho,t14jp-}9Xt4{_r]90~dV$m'Mc fH/3rdgYg;c.|c}R3*Zz`Q¥y$`uJkkD^^;Ѿ;O4|( f7pq94$6{#Hr\z|uͬJf~ARѡ3zACüҗ.XDݙoμs7a:.1-D~h!ڧSNa-D`lL8<lpld.A?##s L m?%1VotOK:)4>7L% +-~T@/~b+lRB^+.;tUӨ=NEHNv}xlt'!gA4؜JY,;D=${ +pZ"9'Bx%*"4t!=5kgR4rddPsUYjTuwo׽AqZ8#j-8ňBf7(RF{uG(\(iQ䥂HU 3̿UpO nڏy[! > 4,]?ޤ׫ 4)xSnԾD!E#+6N`qs],6 /v-!ÿVI> 6S7d k9>w\A w,a=[`$\ Z\3 E<%cܽ-kF+#JeQ aCƔ9& 5"@ Fb5*+fL/ B`i\Kԣ.Z[`?0;(ahUk!LDx YCcs0`끢^aFܩC䡝2Iמy +Q ڎuzNBG8-˲wf7YFab/\[K4ɇ`&EN*o#og7#REC{y㘝 +/('bi)5"Ϫ%S|f7'x`ۡrWJ+7Cz$qb`FDҟd ^ SlWj[߹N<`VF%* >M&ca˜ oaOvP+zt^0$=7zЁx|^9g!|}$'ىc} OvsX[# %,!J`H!v.痸 rLI+w2fa\tzyJl6-HMlidRlJ?9DfIW;IQ;I1R5iIXZIlp® ܛ~`rx6R0O'Sڛ1-.*c;l +·@A+VLwR C&P> oJEL̓'HDQx64)֯Q2OK % 0 -ΪcCk'3Pg"tOR@0 +h|8jSI&JH®}tHZltλYI72N*-'KC8Wl;r74A8MDp%sAX5+&]I&S_l[yv6\] pvݒގ_~MD ٺ}D$o14z{۹K9;;zc KYY.2{{0ÞGzBE1?ۇjoU25RWD@tf\aX! ?4g& j(N[*P9`ky[OFFp_%4v=hJ&y[mÖHTj{&ȷƂŷP͓fBE+x.eM]qG=<FظdHeq\Me}nCD<.U»B ݶNI).ܧi0[`MN>-{ c%Z"VK }Sce?٩wǵRpfg}09O6*Oi+6+!쉝]ѧsUATN6A)GOeHWI|d^}vL/$HgSX@Cg{ͳIDثG + T偟&dvH;ζ[K3m\ dq*ɽܩtοk8,ƢbͦVx +Ji)us]_;#ߖ1o=1[@T$5!ێbӰˢs+?O+aP5c."14-#cNlY !κ8Ȏ(1RbFJPo&R?t%X0&WzmH[VuRHgDKp[Q֛ ڹg;I_꣦L(aGZW |\34BX"><,蘁8к!0o+bW$ `F!\%g="\,0rÝvc1 LR(J?-5$l&{R): +FKBtA+R0u`w5 DER-麈㩫ëGT~D%Jf'Z6A VV0#H8h|!=A'7s%k"(^(#s/n]UXjK`SOmocg(Hj59{F_jGTItcpqŒjs}92~. ?!,/UY4cDQQ@D<fQRDYGh)CDNhJSd3߲Q =Pd@}aSHNO iOB*dWv8_Xw QkgӞr뚲I-u~jڂMi"n@ls`ܽ63A_u`⥦Fe x܍CAd/%3[$D{ 䌎ՅNxTZֿm#: [$xз>0_a ٕHA7/Aw|nzBi먌zQ4ר$$ q [3)O}AF$.YnU@̈*M6JWDbP(XH5P +Uo=k>lԦlߢ-`R+2  =Z(YU 3P3ot=Q)ދHd%F͹^P`xu}8y%Mj$hΟy2E>Hr hR|Nw\2O H !h57$b̡*8eu^?ҟ:-)\O#X>_f ;k+~R$#R(Ӵd=G݁}%G!*_}DŽ!f?(kAde;Fw4>HvO՟knW2ɟŭUW9Dӿ&Mh!lL!;EnS OH-Xp1a [>0U9}|{?[G-2 J$Ws DHԣW!~$]1_q㗫5Gus}~Zu/.4nA–\>lhbvgPPЧ; a& &/it\ $Ȟv+~?G!HW*Ū~Z]O;yVr.M5khHQ4Yji/I2b?7=÷{_53TgqS&ZH;sIw^#Fjn}h8:/ujjVO_bN=MvIDd@}NehǩQAIGsב/#Xt: ? O'GC=Q,'pwTQU Լhe3KPunq.ЭKUHBPZ/Da1Ǜ&qQR\b9evwN9{Q@Z>!2nmThZZ` ׁ\'Ƙ #ddVaT+CKuLj(%s4ˉGV(YMy*T~ApP&+H᾽d_rpT\w!/3Lp/2S +Ʉuj-,>9Q0< c|?t`FJ"̲NP5O6,I>̥[nek4 +`|:m1&8 +A>s^s2pcv* F)(szݸ>Xfq}D8]|P۪H_l[qd07Nh,%,Lt@:ౖ Bls:>L0~- l#5`oQc5x&ܥӾ}j3* ͼr?=ج?zʺSYpf1aQ(ZLB=υ\Tvv!N[XǔC#O2 "<(^y2@_ׅNDڔuY J3qe^Vtc/aF*lg_b(zqyU# B%N,-'@WR8e=6~Q6!gFf?¯˝N>n+=%f]Ӭ`{Pug$,`!A%IE~9ZsDj]GJ@ǓdcAYP m)3Me"C􇽩Gc=B_A&EKsFfq4VhZ@t"PbT B2Hb+`:m@cDM֟lUeW4ޭu=]ޜFP0drܻ{ctpEx:AVO ` +Gצ$u6h5T;OB]d5*!lԔ8SJ:0)_c>W'<'mce :kƺ 09Gs%zn?`daI˫Nglψ~2>et_zÅJplâ1Ri?Idb6y+322QX(LbCA1ǥ]05?C{q/x^ZCHðk@K3#v{TT{Lrw |#rwv"ܒL,JgT)5sB$~[xV:L V3FʘvjDQ8ЫU^bK=D) 6$負 =F9];&;HjTf$֬+[+ l~QVBɺ^Q(S$hg MpwN5a/jQL_+&$BTd^rhG P;M@Ⱦo +½SLZ2#ֻ@)@>A+|RJLHQ =tTT;+2J{D/;8Xp͞j0Cdo?R#+' y{eX'm=&ʁS<ƖVp\G Ī- z(!ΖVZMMfk %[nl@+aslfZM}t}~_GBi+C k?8 1&80^@StpVӦwYw0&{"< cCعf6jrzPmzNl/[ݿbgW/}/~k0ˆjn jsv b q6D_fZ%0G~eE(FיLŇe֚o0s&־;;gQ7jCaGʝR~Ų>s.EbFH_TA^N.x?(MW2,RG|TE&B&"3Xɨ!.վX!': JD..n`Xmu4NB{1 P '6uUxp]&BC QQddF 3Z kRg=30r}VyDSdŪA0Mw{Pq~Wb:{ܠ3Ŏ=S;)%nc'D|~JGKK߯",ʕJeusӂ[i13)R*텤ڬ(籮ǩWqn'3H Q.0kpanlںӉ5w1즆V湍^U{GGF1y +h"n1R +A@}[{!JwxO$p  +Os*Ӂ6ځnzɯQhN܁cĖc`^ aѧV+9 ##87ǿ_ +_دiØ*q~]Hu<v័w-VP$vd0l@SՔC-~!!(+oM966Z=)Ksb|bV!,v"z{lB)SqyED(D:yL{Z4`M3V /dR@P(?Vi3_Ǹa=Bv Ygkr@6ǔG.MlrnRu9v;UOˣͶ6-.s;Jl kUXHLh>?WHHR[1?N샥6iUgz?*~T\oJHQ ִNNd'oz>lNuve4lnRA+ՠPPWi xeT4aGy<3X5 j?X8>{h^ZN Gɐ%ČTQo*$}&It5J1*u=x3ը`ԎnND7*%t \Tr_Q] >=sܽi89WO_>RD?6Qs^G^J/:WN ]r"^Yxl̅Q3334S~PG_G.bY fB͢K654î Eف_YMp\ PDEA @ڱ )La"~! KA[Jj +p=MJ_f~iDfurҒ{[#pzo-K p; V3%H)۳uNcZ%d +-̮j"H} #k2tvD;:/Md{ep )VPoD3?W 5yݨsx6RRQMyϏ rwōVh_patNCV'ʜ0b9?zq(ˊǶKuBLt; - 4D('Ll~5 Z17O7bL5uO:h3:8 #o71:a?J+Jy,E#r\RI؀KxRsX˗D'bai-lʆ3K$T:u]Yaig3cT;#})Mc%PK0=[&zO `9&ڣ>B/ri68})iO):|ٞ_&өi;ce7GO'ַJ##ڹ%j @$k.lޮkGSVP;ߦHT{wØRSuݴPC>݅3L(KkkTZO`vucS@؆$b(4iE6[8vӘc:RëLgʇgU>y4 6RC+})Ƿ[%i;^T`uKs>ZȒͮڙ|q3e/~xgwZ0oW += dͦ\&blk5wp\39FS5xkpwSgh`׋?ɐOZWA:cݥ%OeˈZeWP5DxD3$!62C5C{^GfgAqZk# .1!9^G}#hwh&)!@jDĜ~Vu=m/"c^fNۻ[nk{:nECC1^_Z#ϣЫWom2[IoQjw)WH"?:xCiq9~ɥ&Qh2]& "@w<.vQR*MAU;P#֨V܊Txψ4M1Sp">qax)! yYqr-7wEgMn б=>5ClA)[t."'rE~ +iUYC\hsKe,L-9fk=2gr綕P}t|Pj U xU<1DP.-YpoJ}WaHEwtTZDjH:)>޽[.4)bKۅc]?M[}N +0I_JkDԺqׁ٦D]yeiQT4.x3An[[z(\rw*@3As+%Ynh-F`7ݞҾ~`ׄh 5㈽@jӔl6VN$B>#~t4 o3C]^"mvn|BuZzTQ 3U<a VF|UYy>{dK\֚ttZѹ~2mܣZcߡ #vq}#V)vͳ2B,& `Pz} :4D S*ޞD5Lr#t!]G6WMG~;KKKFh]\Iz[ %,Tg+XBS-%75POpc{gPJ"(V8Tb_ݥc*TP9wcoWal>/jl=5IWG*)1[/~2BYM6gt+C8˪4qSw?l8MV{ >4h$v>)G,?'D"Ew9mpKc}DJ;cG?*5g4VMX;RU9<OFRRE7uL'|=d pk@:mSOge :e5f1^n[1*W+ѨA!\՘&M EX!18 @4d3HJVr"姼vD@%"ʂ)nS;QS ôk+5؜ vʚ̩0&3"t>(%XCl ~hv%ZPǽ6eQIVlrk9: ӔJ*+dMU Γ$Kii1<$LhkwgP#le1ƻƒFc%F֫YH +!+GT;JG!Yd)ϨBz~`&e.'F#M+ŪG=sjLN57),S +5]badˮ)w6׊d:$_l@!:~ivǝ:? y#k +7no4<M.)#^c[)0ZFLF4dw96EZcs)ܯ~bw`% RdeHW\N։ +&ylXQ=3"<+r7%z+iuPնkPXa%6TCLY<5# 8gԒߣָc5oWLx (zЕfnӠoOǂmQ,z{K$sb:JEŵר5 ]/PI:qqq$(tkY{F:;WuthvIwCB"j̣IxtX[/0񠘂݀Ǫ= +ڕԘi;B{A_wC5^/ jTѫ*e)ѹnŞ\~r:SRguz71=lD/>, _Į_Y1~ſ???/_??_?O߭Ctr ~E,?PIVv.ɽtd-\ˬ,\{v Fh)d: >R*e_U(XSoO`Ug5Z Qb){|FUŎL<ڱ#X +54-⋑O!TG4oWDkb}(ek:s/*2&:ibH lDh)_z"}0V}]RyZy[Y,6\,4~ȋ]"XD(a5{:d6g,+2#+dB4DOE +q ?ɊӦ4WUl.y +(P8tNoDDܵVvCyktm[NƺE o:&.DuYP _JQT>m蓐Y(>nA>D/O5s^w4FL-@ZTR9O\tXK U΀)pJ:+-]x.yU}Z<^e=z]%4Y/]Y T:>7x_E=!l#pnCн/1tu# kEf*Ӎl>g׭hhWd:Љ׾6mCnHKXM%TIND1k}H]-o3] 0m*w0R YA8T!L>(Mz$W߈)^5XM§{GBgُ?3Lctj&#!37gR;=118țH;=APheBFQK֕$GӓT?y6)e<;70 _7 F}(R,[̍f=qAh"Tj_´ ؈:0yn獇˽֣(0.pE먎]1]=[s~F8x[=~*%saXu^ܬ,>~S#PUk; +"N}T2w41t(%o,أ@(+NP*&:6mQ:i[D_"~Y3U\'`]2nׁ[1qD7+v++/O]P-+ln}-F:=5|{x +K0no+!_>{ڟiEff5=}Djak=-VLhݷO= r=1gev3{s*][GE_*-֦hyLq m6?ӶW!ͮԭ?7pfYc!V7wK;Tj^^{FUɍ #f׏o͈SNA)"Ӂ5lٞ'P YLsSk QBB'Vq[De I>y[F&0T{iQMaDG5PϕC= M̧AcGo=7t} ˣVp!aE؄gv.|4Wr959I$<˵嘤ލ0̂i1ɭ@ɚJ_\wAu5>+uA }?MT}-.k î*G@/690"tA +{iM837HiVjR~"hP]Ģe53SFʫ;5ce] I`l- Z1Us1ހoy $u;{e`i!ѡ1FE tdJyHT"XwJ.~gBR9hdf9pfwl-#S5tV"ԧd !׃y#NDI\kcZ +PBN_So] +Wz)f?bb3XΡ$ۚ2-Vu>`+erdiaE@DSEb'A)B;Hupa ?g38ka|F -^bocߌmMuFꈸ xHmu ,od.g(&FiH^ˋ]m"R}(1[ :ǸuaWZ^ bx޷a!rf?7$KO& E,4c(0qYy* 8M7=DU:] 98xF%Nw'̚ +DQ b#HY}EɜJr"{,Z *E(?b=_T9M7?oJ9JXCcr~0cʻgQoZ` NWF#H'~qj_3"1q~ϝgθ9T~t3}(vOk{}HBGQCa<b,Ixє -?71]bŀj<%5Qc"u:B a;a="RKȫ!M9_qԬN +V_ۮtLoˆgch"|ۧf*$Қ;$j9gkKŠЙ l1mn2޷V) \SaP9)z*`!*觑ŔдC#A584n$=g.R yF^ QbͰI*!,As)ӋB?כ$vOYkuFD8(5)`G'=շ2Bv;ҷ;"ُ(t^VKM"+W:U;Hq#ut%{ӖMv}DYsKl=m)4zƀ#l] SυW]i\5`XYvYK9NSc]i'*&|i9])lφ~6M h5ms<5O3 ";9z Ba|1Hvr%Gķ{TM.%xk?dQwKvԪVJlWnDCxm}c>݄uU-lli-9O~CMm)PXYLokpTkkb d1̀v~m'xˬ@-M(tZI1R4/ˍQe +??ZOD6 `5D)BS]? Mz[StIGo9't&trgdZ6[2GZIz^*zR볘)Jh;#ΏT ?y€cVF&4 +=I + +:uԩL/H^Em[SO1P\;xC%M\O? F~ =~~ +?D'$hR9^ܰN9Uf3Djw]2F!bOmNG u;h[weZ~+qU.@eR@rd+ȼ4(9UoW֭0٘%=|Onw=ywtQ"g[X'$` i5DŠ4K1h]I:{W}I:8"yNQuݑR;둇=7s}l*Hl2QX)Dt5Yi8 gT#H9>\:Tz6ş$j_V> ĸ-Wqnf+hi+Wrc:XL\ύNI#1Nq{]Tnn5L.ۈ *lޱΠOkTD1&a3*gNG ?J`Q"G3rZt +L2|_+2isٟѰ"IF;B0fw%|kSDȤwm۴neh7Me ƈ`ſ[k>(QOI4R"z߽e(d5]S{~d}FἥmD{*JؖSKK]A,A^LytW=ݹO(u`([7 +.1 :EAݬAb(i򠔶Ň)%+uqAM^.+"~s%O! L~T0r{*Ii[t-kt-j8oZp܂ߠo@Xcxx&V`QJGл2,Ng3npsX`q#z+ 4vDP%fbV8!NuXk $a{Oϰ&[EN9$wJ u3>}xV37@1)Yx0НݘztО]i8oA9^csEvW + ^zYllOȣro{];DQѥҏ8tRY*+,{G$05kZވA5&!+(Ḟbt5%K2rzcN\CX5KR|-W|T$[DOsC˪oSOW 7(\v[%v uBq Ab_- "{'QTGPƃM;nFeRb / +i>:4Պ A~ O,6+".#kN#(U Q"xͭE@1ħ>@pGc1J~s4U70|!}̴̤'~V @xiU\)=3]cVTnq{}>v>0CnݨRc?Jw7cgDŸ&P?ʌ#':7u,xb}'EnY?L~(ފEgtSCu95ְ [( !H`{dH)J6;/ I#(A@e2d 9TfH?@#fHTxmaQnMiKyZ'@{*~` +m|#TUQ~zӥc5 9jFXL؅oo"p}ׯSg(m]93hfVGh&V=ew}}V Z+OvǯbpO\_mAV&q x; "JY;d9=ݐ.dfw ^FHK*:(6)'v[3:ѺA $./ GҴ0/kzYVeW +zfTӷ~|h2C^R[JD?%{PX"L@䕫39}L(|ն:!?LG?yE9B5Yhs +PN*@ |SNƬ.m'"ɥ5:K#c +JT_84m` rP]N1+ ?7De]$8+CKR6y4VUr* It* tتOfԱ7jFei=µpk;bC%a˩C#tNLbȺvOܵ}⎾L(= T6x3*jɻ>X3(43%Pl\06 Q)NVDwttޮ +*Fȇ^zs#B.êtɻR=lܛ]ynv%/Kz*zljੂSԒEEhrW- k ]^ˈ>!#RltހLEwh!\-I 6$5YR jZ%7Oq_NnHljʷo,Ե5Q{Roe@u0yv{iLA&(a/$>$S,sׅ[-}u$XP>^m|'.nwnʑ&H VeuL}}M3|i8Xlr&'R +ܸe8&3 TS9"Ĉjl'r)$h/DblE6ҝdvIj[')ԣw,U5[,D9'Ր{>@{hsE^Qѡxu' ;#0bK2vt<F/ ͩ]q \ڋ)'p[&T̃:#ǀޟ-.]ZPLK\]G{G3W?FjO@&ʠ6ԿQ}Pf6P 84îECV~pԖ7 7fHx~PS2*QwQy*R$+b%Wax]}ׇzoT z%vmB-t $#o sUu/T].[ʤe kpLŃ9|%^\W0J~$*c5$VY9'0esuĚF({ٛ"2ò j DF#^!:[[vT~^ߜK"~`y +n( i.۟)ۛ^q^{i@?'vR{6ݧh@2kI}n+hqtɪ%Avwg%ǩA}nY8erXD6fY|5;su7礴RD5UgM+B8P3KHo)^ʳ=V*T”40d j9P\̀=.EI (͟_=V]QXs@gP+u>^`si{l*4BXV3Ə+s8Oh<*eLXE+\H#>Xu+Ӯ]EΈ@uSL,[yo+g3"ƺ7ciL}1Ilk+LcPKBxEU~9$4bC8# &Yý :4h5\.zdGNeH}}}i@V9g:-!xeC'/񼉠=:;tc̤۩m3iu)B. K._e'ߟvn-¸Rhˋ5Kǹ(UX$Tf!(Z>,JSmz"(MQxW/[cNap=D"!j7Cac&M11R ͔T9]V֫@\.04Z0Y pD[;isqF 6(1(w%yLD,I%B2/]9TkNeTRN]հr߶ +!VI >M/2/GHgEz6nmЦT0FfKn.2IRJ|=}?B£UBA\#dELpEF"ta +|y0Ļ5tgQX Wobyc#F*=T\kfJOU3ʼ<*au'F{@\vyō ]\)IY/rn%+-fa|k + +I5sR`M<]T>`Z%dbN^*T˂_hx ?T@FGjG3QܒJs)YFYR29ul]y5'ŦQM=9c4[(>{W']Zs7ʚx \Q=vo-16SdzƉ=+G i=q;\2?S8_F += +#j"(&h{mqʗ)ݾĈBYyzfԅHݲV|9S#\# r q)3f6*ְ{ŴdߕEKt}"h<gku|E:S RWrNF4v\\\u? .:R%1HkC%:P5 K 'lk|Nt&`2?aT:7rKS}zfFAS ' ܗ9EQ%j^|<<8cĚYܺtבfl'¼=PU5j[bhpCf2r^_(w_ňWx29 +`z#ZH&,AU㞏$wKL{>;=Jי=[jjqdB'0#qwD= UU{R@ u5|7)T@m-M==Nȭ ~۰ƈ:hH#J\{@Y;ߺ&V&Br2jM= 3}~Pҷvj*ZxVGD{ _uidꠣAVH,2Ybj<?([fp=%o;̴+ב$PvH$]4i^@%H0΍l$MT6u9YL$ԯqe7E:3*{*4xhʨ;҇ʊR(]CgIp@^ǃ{ڡjcd\"O=4gVnSc"#qbt < PdKMA\,6w)&vc_%A)ާx(9E"$” zNfէ5wpƕVbrN$JͣG Xf0x[OE>׃]Y]->b6KSܲyɛ+#-Tɶ诟-J;^fD3*L҆ +@ޝ*3ՋO(K|g83" Yؐnjt[PĜ6NhM-g +&Wq eHb(5 +I5ױ͎1=u*u tDs=`E9@xeʩm䡊890Tpc!(0~C +Gp2FL&׮{5*Tmh,<4Edؐ܎Dik-kS(`'Mڑ|XR۔H59RX=(+66gj"6QܔaYGrvQՋe;Cg {ŅW + `ŌZ2 IsXxtҎՊ:M4Qg )ۛUdTM| d@&άQJWB~:&V jETf^ME:|-P+ke?[G.aK`h0};G{9P&M^{yГFP4 iXHp]Ghݩ*n]ɰc0JNEP3$}[ϭ4GSD\qk(2\_&&'7~F%-y'UCB6y:VpZO!zvAqƵ6`CQl,?8Ty7oMGWF%`Ӻ !$*cZ+ў'JjQpJV,Xj\}MxըGb!,,NgwXGPP[H<Úx&Al>tx5b ۆ& &ٯcϲHe\et)%1@2(qہ 凙 I1 MGm'_Vt(TT<V#@RS*n0gDnIW`؊*z˴5GO1*3!O w"079\ޥ9x"Yn)J$ti (# &])OX?@2&+ʎDXtc:Mh.pe*X7z=DJsF$q4YE :}hRҏSox,|X9VVr]jKIq˹]W_'DCۓhFEP5Vj@j 8Ol(++@079A0Q(rspPy'|*ƄCرFzG$z ˆ"URGu + nopQtz)%LO +dwWw)߬7_Gz@c9̷Ԛ3CJ*,lb5@݂a&k{2 rH՗ }R9#>>L1鞛|b dhƨːwo}!E6%\G-mS'Yi{_שqœ+v>Qo0 4[_: T[Sɨ.>Y˦8k%K(QO2djGjoxgkC ёCs6-㪞38+y!A< +sGLt+Q[z$y'} Lva,d3_åVDS%Obռ6 uMqh=vŜ0dE$dOdAhqJ2I=}&|Am7 \4ʄvD +˭2 ,_Pʋfe6dH +M>L.Bqy֨娏[M +S +=P.exZq hY1> +W(k#.f,ok,"p3{u:ף zld$+]Dr$bʥF5$Ϩ0Q{f d/<84Xv0>\l][ZꀲvU6^O8wME +aC̱!c/dVtkmaGT+aH.\c/V7+唊0h2h-$kkӭ5FZ~Z%'my"@N{, +IBLJǣGR΢ղEigfalNR^_(҂VlF+@W<:Lfʂ7(y6z<;`4.s*;xK}i[,HmMo܋K@9Jʴ}q +Z'\ %9mx  (\'3`r0O9GF@~R|SPGI"Ɇ=0yh_~WmnyᗾVDxJhfm]A@ǹ5nk]`)&\:o G" FhbHw~"RGE-Tkr7r~.ukv!aj0X'UG1mc-\gnCJ=7~pfoHfNOtN:O^VFm bjOkDnEnQQ*UJZ7,]9>!unn ZJ˒7*F!ۨ:749l *4χF0M^´* ȶ +̂ r`~ӧo^`GIV!X}o, -ž}F*FV&M;EL +%q8ȭe(}9KUnTjx e-ME9XqP"l39T)LJ7-w0#2mj]kFkR^H=ë^JZRe’t)s$IiǃhZ6+JQG +<-EmxG>:犘>jlYZ].;ʔޫ=܍4#e '1ǮiwV-$LtI[+*'rw6Y˺ +5WnXR(\x3Q4CBĄޏ5YI+10́Jz贓#Jbap}Rgg. 71:{l0;0|T][;Q`RRQ!>?Q &ٮQ7Qrq +'!&C@͈@%]DHt&GueZn_HƉ. H%ddzu?,=\ѫ qLm1v/ +pONp:Udtn +Qw"my:$}DTwGOv~99=_3 D"ѣӼ[ɢRApm@eE)6H֩'~cu@m$uh #dHGHљuOW`)IBZE D)FP!rJ@JlHb?2ҵ(bJ=,|ͩ]o{%2h5Cm{iNd1BG͐ToO#>'aanRq(z¸Kc<]DAZMQrF]n3nU#)ƨ(ON#rW'l#jJIQu$pL|PQcI9E4 bERf#җ::xYaWh~n|{Ħ^֎SϨccXTȱ) +J"o/k^6>6A޹Ƚ֏(4ef,JզQiNyS BΑ&\Z} @^LJ"|`aC-fpfDuyY|z~mgNbN*,/78$:W bfԹrF)+j8"{Zg:CBLnu PUT"Ʋ(m%Q,\ei&m +kLuW[zdD|"ѾuW{J-34V0^Ͼɜ7e"z O:@5\0YU97~='s.*)ﳾjP 8­{ @h;m?*(d Zj_Eƾ<W:cوdW<ݏ1c~uC7DS*QkFI>H ܨkۯ08q>NOq@1 c/`V,TH>DS|;y+4:0<V~wgn/Х rFf$ǙQL7#*ٵ]z&ʡ#DBG^DZ-liOuiW+VITèETǦƈ5КɋԷD@Nt\Lh}hk[= Lc'$`QsG l*@W 35 +l֬v\q,O7my7oAT/8f3 8JGP(›8V ?z?k9X.xttWӼ2E*JO5]@ GE}3YdLXd=gUUCh8Y:%D)#J@b +e} +Qz9qVM +pL T3Nwy]mIPb^J}K + э@nȉHģ(P^Ni VMqGJzwQ&jJ,PaAD=Yr\n4Ro..E,*,aPC@iY|F]v29e|̃/b0q Ug_Ycwj͚{=#<ȍdzܮAp9XD$KmSqwlȩ|i ,п>,]:Y wJNQ=QCz%Lj` YdNlh_ķ‰xw߱ZwLRԳ2,NȒwIy?噹]fq.9De$ɁZEf{s qREIh#øAzdWչ(DO {GD2bD'/[ޑ|l"6N/~D m AU&u7[@KpuE TY35AZ+"6Z]#:d](xiS> "M4> 0EEz%ktȚ:O#YM,'Q <5@8x kM>~xW uX>jq+&(?Сb>rj8mEyƴs-) rj* >Csmɲ$wu#sjXa҅zO]`clj_fn m8_]#F]{-|n[؅T z\3\rRqɝHQ%\f÷  eFN&<0cq +JdF*AzD 8РiaZZGqD J9Zx8䘞zy0m7)fz75g~m }eOKFĈB<Q^6{< (X,a8s.u0 =êGTV TxAM",H+߰WH](cQ0PlOG=cX葀Cq$jhqv [Ej@-"o4Ua{Ȇd g]"HEykCO1 +gE3uCA s7YT RcB񋛜?Id=OWeڭ? +mc큲ь G-T%W ^SŞ1/APC) }]D,UH}a ] xai.(G P +-t`J%- Ej9FcgBa\\N\.Ժ?"jB\9Q,6En̍ȼEN4* +E_4C5^fY5fpqZ*7:!fwE Y BA}bl؜[t*sxH%C7Ș۟k8UP9=Dtĕ<r j*=iL3X!;Vxij*i&}bQT=b}AoD1"sI긘ϑ@'xNҗL!#U%2Ujɟ(D\~ b޴!^A]vq1][AU~֔gm޽b ເ]^wmCCU]]mrt@T_ q@!bu)5F4!B4#^6O"7UQ{ G3 +c"6V c,$A$! %)"=%~䑬6Wj9BT,}^┱FC% +B#ק7b~J 8tF55( Xs;ޭmllA [jiXj } TxD[ :[w#@?9zPnjDy}A{Q-dK\Ura!;sJ r i`Sks&$QP;W4ЫBT2:Զa5gvmRзIvdQT˅yʄt)-\%S[#FK-V|]ߏ@x:LTߊӝŶh(q^q;?@Gt]x~жFf踇i4U#~ ZpGa +p[ f?THe ڀ`WLIQnSDS~]ۓΥ7Vþ@;yIn^MyYwO!Tu~:ωk;;0¦c`ǿ/_Oǿ_ۿow9?7[,1~PjCJ%6WxGuCw7OJ7 ʎ_KQY׃ČTx,f.8QMK"ooEwAU$O'(/yVktZpcr9w_ 9lhw6p`7mS@*?)} [/6?r4uCkB1RMG=J1i OA9 Og>$_!~[ҵŋ*9,9F DD@_]<=cGa#Jv7FuCw)c d!ˋ6pތXCH;MbMM?shs"r`vU1C͒!zv7 +^mc16iå&fnkZs2ACĹJsCP|ls؋$,6ԗ(ŃaBW)̇I) L'Y}{}Tth :1Jcf7 +M\:PT+Fm lƱ_ZywZ )T=.e6A%gW5H(@|W '߾G0G9X4zd!혿c|-2$5XJ]"np^l۝haƆ<[+|HŧO+[u"7NJd^ +nMcrHQoj8?ܻqM``|ݙF1ǩ lf\{5 N[+ ({Bkj==gNvOOwaѱN0-Q_+d3l'ºl 92vI"뵂^3HxL1_fZX~dZiH"J`(V 6yrQJXgSDQv}c 맟j W?*qDZyogv}4_FNز_ fEciPg{Y8K U89kj޼VՄCg c= ;*W:Ieez +(dz\c7?ɩ:bcξXXԖElgw=z6ekQyT i mv@EƠQߏ۳f~iQ:I5":~{yk=zssuM'axD_M ǿ')7'ݼp6\{lF< +N-~ܚt<ܳD)j=2Mo;\ܔ7O&Ոl볬(N +b7')3 !C:yHk^2&|EkLp&QkjXW': HnaW( FI"'9񀍬h8` k +u>7*ҥY~%8?Tڵ"M#%GnHwԄei~r袥j{vMYF y3"VW +[Sgu@n .3gvsҴ"kw+s).۽Vv Y_Ѿf^& ̟\9J; +.f_+( غRg}!6͢)Kݵo/do\jc ߭ځUq(r$ .$xI{F"'cC NnD}ǂ$#DhDwӈb+:yD0ܱ$L@ 8n9G@ Sb k|75G /{^g@;(u.g2zzge󻀩'㍖Oy*Qo7 +t1g-deܟe xP:7AuJm(SI)-J!NSƃE} (__πSte .:^O=jrEdY9n޾>vaOZތ!47G>Q% +G)))6fg}ggȼh.1AY(1\)6,?"Aew{btmAɌNjLI}"P:ڵY-.KAX:ppY~5F× `Xd_N`cW說+'w!<-`j~F\Ry%`?yQj!PCg:ZJ-DJ -W~ɐW AE~>Iӵ522?Cە"rD;z$n2cZ7 +6ފPSgZ q"XX!=VK D:鱃k](lCq +AU)ۿ rڶx޿Gv~7U8,T6§H[.Cn7j Bsrm  |K!,IׅPRN w&RFųl TR>D)OρJ1;Vuo{Yw |/éXS<Mķ{vֻďXEK=6vi4UckIwk7=hνN!mK!7d3 +z1{+VJ +PY32WWn31N^0j6"ʢ kcd(@@z\sЭoaYVи @l ΰ cohH_8όgo*4~#$26J,6XcEDE:0`4޵jt20+؝WT޻6[syaI*>(Vъ-UʅB"* +纟Yku Ҡe^ft? *IX<"F"Q (+E#%UR#N^8o)X$-gnt(=ʺq~AhN'b5h,!Oz"CT$LFWH{9kK@&DhTX=:&.PRn\58YwA0G 0O Jb rz:@Ɯ71‹_OǫL0t['.-)2ĩ!.$v'~3OvK!'W.u~iE[b:Ÿ+PVSh~t-¤'v+gdm70prjlqEt[K7Tw;HT#ג] L: ] &kh&0BآShM,]MGF)Qz$X4#Dk$6bw `cy +U[hEܥ]sެ'Ӕ#hD^blB39R8WQvThD@8b2inmb屉C "8_Ѹ`msK(iWڕ2ȿ!)ڇjSQGY),^h1<^+iV,HA|L& H [<f䟞~UMIӏ/e]y[6ހղ1 +n,vD T4#s +yX*ߌ$tZQ0:zPvT4fm$L5M[/mÓq/@Yc1oݎRGaMgbuD` jIS4/TFLut@ߦQ$krS]O9*$k8CgKkD܉b>S 3mhWJ`/3oo(a<*Y&*lk8xKm+hDfM_gF1:N5TpdW ɬ2^ 1J/xFMZ RRi0HKl@ .>UO%jo0ȦiDM;yETLqjR SdZRS;f|ih=,a}ecSdgK"ě qm h$%ADzedRo^@sۆ@+׀/ pďZYtJSG(^A@Se쥊 x.z< <.{M_Ԋ)Y~c=U4PbmFHs[@ugQJ3>h|Dw>QaFX2Lj2@ mjM&|ӌ`]e1Q7DF;SmtHĥ '}9zЯjɉS(VQ5 %@WMDm\xG9iۮÊMaJ[6"x3S (W<>T+H,G$2kO.jdTQ6N_#hGAFHf!F`S#(dكFa S_x}pfY2pjDg @A&7|FM0 /Nh 2V z"K{u(bChigAyx$UޠR+'GiLX>d}ȝ TeQcޢ+&r!R>RTq +#=î4ez6 ˾yP9Ǝ7 +A]eu3@N6~#u.JZj H~`RŲCuϤQ"pV i_Qӈ㊸4i HCm#DsIC?S4@`\L}𴲟A(:}ƋBU~f8#CDM,Y}bv_ltC,t>-I7iE?Dtyr(F|?­JҰ"Iϣ,\hQt,8lFvY0 cGb$Pa;B~xx%QQ^R9spCDFJJ7[~0L#^+RgCx}هvbTƇ,S?+BҜ2G>U(v9J8ZrpO!0Fa2dZPf{ +\c8#ME|!S$cAsr.Ec;_3g<A0Q:mKd=Vȭ[){`4W/f2*9v?n&Mebd5U~6#Re@$6=z.MG.EC;Gr# +_4X>bcBN +jԿ ECүSpwe0s&8(e+W͝8;q#Iغ9p[8KH jtUA$ťA8zu*e΀i2dh-#!!rRR:F>nC;捎Fzgk0r%(4Uн`Z!8r~&Oj4 &wB4Gc~4:x@ +1";L,:C)xv`hLͨQc(!g=:?Fd t[ҵDҔ8PvT$zPtuDGHC{jc0 $x:zH!He7RȪAƈ]F1jD?F@{4lmXaH9sᠪC_"tKxNNNztQ|1hIZ)s4;Krh0kP8 vlӊEzhzd6M l7HzNɪ3p9I?Z zmEkUUe6S)$$цsJ$pt/] Iu|_wjwWBQ"Yִ;]`sd6^ ^`*$E'UT'KYg+jgl$sYRte1oas2<5NM# ?QXt%^)I萇~'0Ә}B.QDL_d2(Uԥ1wZU۩vNYKh)6$?a5K=8݄@*}+@L"EHT)bF&K.t:u==0R_!.{G6iP8N֮EbAF8޹uSAbWwY.]YfѓioX%紇F.(%y]`T[ڰۜl`AĖ\~ :Mj#yD~׃p[6E~.,`4mJN!s!> 6V4)Ń>'A9Yxb DJ"f$~$T($Đ"s] +UZ_c,\wE!ǯGBgwIT(TWs >yeE=oّnHtеk rlVˑ+%(2DR/ԃo@oԪfq6?]N>-3?lO@Y>T@ @Qr*)"F.# zʹd%A~I~^ʚxu\,? +?y&Kzjpm*sd]pFrzIAĐtɎ8\ ks iy.;5%" e#Kio~69" d@$NBo*%;KWׂԖͩb Xt:dI@<qcXCD Q1+H1HRDؓI?PU,ubLKDz4m0="ǖef= +ԇP$d+}R>Qve=v,|@v}fiв'V Nd)f M<ܱý:ـùD|eMfJi4[ m +Jr6>}agq%aWv N]֑J@Г_=ެ3BJ*#D2kx]&ű[Y2ByMҖ=SO+2Q}(=,m#6唝Q2rVFg񲑰LABe!@bIsEeuTB[ ov3Ir#,+bSfwP9 b!>T^@ϱfJٿXK J~4gAE2Q&WK@^# Z+EbĐ%2PmGzv/3Jrp!csEJY@n4P(X|ti  R#(AY$@Mm؎Rh^+b!T(x%* 7MK7|*>Iu]"(Hhd +>tsLr!2[o(Em֓D[8_;DUIuO~w2m=r:#CX5C9Bb _A(%*T-K0T,$ Y*%.~-Ew[vūNCEK<I~īUS@o uLӁ&-jsf;!<=3|Ō(5k3b5B.Nf* <|!z%)\=",Y2W,U<I';HMj˪^Q84zl˚Z((f-[)T`'*tad~;0*j9>fU& IVtMI[&p40JPYukıim04l]ld6Ԡ[0J[ "talٵOEeAmL&ZYWE(X裳@*`.¸ƁRN >+YL5E jPͺ IxB@2*=4->UC Q QZFL־)?'b tgLU#UR*\쀞N=?feTE5ןh*s ]HR./H02 IR5hUO[VR.*$i,J7 Z,OU]"Pҷ9a*iQ;`͞q>o̊0} Af5µ H^ל#X#X$ܪ-7IA8ѳcLoS{Bx# S)4kLEU6IօS"IE$|*h rK>JH$zq%#C?M4?؀JY뀑dc98Rf%p/yޝ0D+?w;;=cU8mNw;),5>Z[n{eF@F!\%/F!'K'C]Nwe48 IK9̀pi@ +°ZAjBh k2P)K д+() + YlF܂L N-b!K\+(c:!n2\-lvhO殙0:U5ГR$4lfb˟8DPʥ,Q^%)~Q5-]Ժ;st;(PM "@S%@+EbcIE $o'\ yϚ&9 ""J%\D03=%J'fSka!d7, "i>PyRV@*dEJu +jWLDOB{ =dƻoT8GĦ݇8DW?UIsU j0.jŪG((]ҶC3lq_ ǧv+zITEŁ;P%!jZ\~{!<8h +4|'I*2OIVbSXV|7%a"]b>t?5M)C]_|1`4`w9`H!ez!/pz_f`gwzGs~)Yfc}I +w4wkN 0c8Q8[cd/g՛QQOȝ$ADl7#~E# x@=Ȗ{Y@]4ʍIowWzs `UOi9 ":!hNϰU)Wy0"܏E3OAN&O#h :]o6Hnө&$ 4E/t1*j'.=p1-Eu, h[:V)oH)2 gbW=.m8dW5a1cǁ$m#H H'45N)87e,54L^lBc ʩY $lA{%e`]:(MvvQ9$+rG :z$Βj5;6gN0@@='{L4_tcf$<=@Կp΂4o<KMJ9"^0I ζlxFz E*ZAc5L98FB[ ý!FܐFx,ᳬh d3]b%#^onYеp@FɔFF$Q3-cW'}VPQ{g0<]bݾ拻9szANo}1;J0њH=^X>תaZ 縝0*NTU~,^ g(@RMIQ-gABH"euBx@6후.y08@fPbE$c]YG~^}ʚڇ) +T \sՕJ6'zfM6VfGЕ +jU_h@DI2$"ƝnE8Uld1"X>!KśfY2 +@tcN x1 D`RI1Ji#9YZ  QU5#JhӔR<.GӦ!Хr[A\$hǃ3=Sv\sD8Fk N<2|sҼefL7å=AmЛ I"ÁL?<\Rhpa ]Qb1^@%ܝbXu)MS^P)r7=d鰱DS{8Y +5Y16Ud+}d] _z 㠸CxY20Dm쬔v8 s[ᶚ ;/!*X+uxY$O͌“ + dFP}tIZB@$ꔉ~ՅȁFEAje ,rF@S v`$>clLvz켓t! kE P<|altO~v}5Z6_Ir_k)fKyӉ^tQ"wwdvq=`9I, Ib{`:(>"8LEOÂBԺLF v4R9dЁ0H$e| +)>uĜP7L+H*irh/70(64b,&lmlō"i -O8FBiT_(7sz(A)A`&q+*  }/C'L1baKE wI +[ B X2 + +qL(zs2 ;mݲ`8# N)Yp%-@y 3)*)ʇžZXFQ+r#p|Ȁksɯgy Q,N +su*KFz #n>.h|.\O]fPOBRuI[C1BrB +sɩ}Fzmh>Em Ȍe g>.QU[Ѝc@aXT)$"oxrM!5;q=dkE"~l}¢AY&/d-+(6tqZT4E"zzTc<(%yNXr0(#(rKRdEzD {t3BV%) 5 ,XlpTG#-cȤ]4bkdimC.^:QTMJk)*F@Gfu9_;{f8Jk 80t12qsuLf#iNJ(`#HGL *i!F6DlPO P4{?ܜ8@Gl{Z bArJ +AUHG3 +A\"vUvTT +s&ɁuLTQ@]j?4* +X=;p0 Xqňzx*K c,oF/sT(\)ktcC"&TĂq%Qx|vjϡjOo/}ACaDqL_p.9$hZ2z;wE`fy ZG7bSfx= ;dh )f/aL;9 DXϠt"3uV4:'Y"ۈ + BaOݻiB'3*Y*niDK#jD)ε%:Hr;OIεa% n$z#VyuD'_y`G9=h`.B%Ft4}ds b704:thS'";x_kSIFXNSѶmJ|4iO걀p VvHy %@~G}ND;^B^>BϵsmP@P r\gCMNCk0 eauA !E8id,5Ȁ:j K +FJ+.(!!b &!P +T.ߐk=MO{Eу#hKp!>: XsaiV{&X +)>\#Tn/ )G5H#4/88/kw}$N=pW_ +>`r-_^/K Bג6"LZInQwfvƵDFLuSj(mZvƓcWuQHcXG|zӄA!:8!^Uiak<LL؅ZP` T/ ܞ>&H7(w"#@]kS8i%m3=oZG14 +"mEd m&D ;eQp4Q\92 .m)}M6/3N3t1]>*1ʢ_9೑%"<%C(mw$(I6r}q0àBt)8=#iW.ĨWH5!/RQ܋Y^ya3F>}lAum^2!NH.NXtL~c>9um5h]4=B].6:[$KJUa ~IKrϬR-tyes"&ſWY IpBX4F-CmI,]cZA\O @+1=exu@_aB@m U"t",_"&5B1Dc>sxM;& +"e@W'j8#?d.P-_,o??}_|}w/įǯ>xWpW_rB~|~|/~_|h_/@9S77Weۯl}yvM|OOW_~wnw~?c-_??~ӯͷ/Oo7_6'7*x?UP).&K@i8a@Xѝ|^_mgKW_)^dB>zYEQW~P?[[enlC_a 6rs*5 T4J"3Mp+Do +vm@9z:>hLM=$ݖBQyDGb Gy5N,Oj|K6IXZt^$Ί7|pHUHva!YeP蒶vzHp -`2\ye ظ@8u4 +F, ѷwߌ4`TQkXtn/B|E+EϚ-@q +Dp)`%'NS:)5K .=گn1ZlTX-EJu^UYqOځהHp0$6X7vYWD @ bsYZ0n֘9,@}@9bs +ii;jT4!v h +'q}Q\?kro^'xF**E{.r}HXy@ {1 +0EU7ܞJУXzj`d]/)^R΁ + uJu'&*YNXV]0#yQK!j.<ܐʎ +qp)G_Ϟް:\ Gfa+],T$ +vgrLhJ 8~yWgVY3>T6+, ʖyBJQAUrxvxC%C" ]W91óB{Tug wm%CS(=x%zՉrg˺-"/~i~-!MC2EԵFRϛvM^PUɊ˭˵dtp!ED 4$@P ey%@6WPd&O@1y^cLH)rUoD`G>hlcgĥԻz@U%Q0īrtREVKxbaM@WkNM[0agJZ6"yЋ+=9AO ]h}{ >[IW(~7dgo`%#1eAͽP+D8'l,(첹;>I;*zEPn@׊fjڟ\DiJ8ϳ@:@tvzkOgdH~ KC-|@֚͠VMOYk> B?,oЬ CS?uGR7%}fQ 6Y>ijQ R8ܐ҃MOg}}|E+J޹/?ෟ~_1oЈ-껿$w_"YwoMq?%g0-VZx  k!Crwn{_sS*#e"xԨA7i^Ϯ[m} Xi&lpԽꀋAXr}Cqƃ K>Pۧp!b2 nekX$: kVCUHN6z\ah?v3G:^'M ip[U4SEô=N.ڶit F[#qC\)#E'7mM$$@,U:Z~vGH=!h߬E։0؁_-&H5V>TٟV<*\648$4G A_+Ea~qe.,;mpyۃ.y҇`G1U[F|g٠S`q&b +i 92UX8%BDB<8]s +P=Lٙ\IteTӡjN,r`JϣJ/pdA&*JCfK|:' PG劮!NUXɽ@,x0/ןpkK3ohF$ng7JitA~DSq0iZO{ؔ(j k@s\40"L刴.TxʜA4ܒ8cgL,[O*c1F1=ɓ2df@K8myQc-N^K(zí1`*+X gknى +#8 -V/p,ha֨et_0m?j&S:%2s,Ъr;ԫWVtHJ}ojgE63gGWdL~;|c?h]Uű E/RҞb4>#z}MJC:(BE@$1E,…6\9M$mfT5<^D_9ǩW$t^icm`39Nq_T@uȐ^YM!Zsnjђ#kef|Jh)0o˜*E~ft0v[qD>i:bmy^r{ۜt).z @^A./,@<@QR/v n)h +ljz T \v4gDmɅPM%hY|L_]//R㡯~tzZLt ՎSGL +6Ynd8p2`=G t6Zۧf1L¥Y,q͞km/vYS?USҖ>P[M7»CW[=W^=j I]>GbrFuP02 |'fdT)*IACDu [I>]@ooQU cC8# 3;YwnYgFjC#UFdEy0nPj.;~) +؀6 sq)UcHq4O)Ska#҉,u֏GqFoD5h + %囆1Տ;!} 3~x0:(*[*$y}|ˎffMcf3,ᇳG{zAHD0dFFՐ$$Z"]1K~`T< &%J|.4l"hBεf{)$p|HS8p&EOʑPѣ<,%/WnTJM=^[̋EWm!hH@:¾@<Jv?< 5"V&,OmU;tJqGcq߻]leg-1f-==Πi/)P)dMF4dk)Uk(2f<#X(^f[&ykF¦cL7 {ق~)-dôρYTIJxmajY/ cTRXH-x\^L8uC)G[7%3k$H tDTάc@׊ <>VOVFcJl 1j1kok𝇤|[cry;fs;㭣z2lZ;[5y_sm۲uo-s[|[*Gnr`݀v,غvη tNx޻wƺoH-|؀"aȆ3™Lc6mmolqDsmgwn0-l.kA1m=mK6ՖGl(-@^9͆r ^W6V@[kV6VM[En U6ZɳAʑ z37V"j޽q7P]5xCR +Aߊ޷ߊ݀pL?6%6f؈ Wvnښ9w-Jԟ{[KH_-&*=bIMתS6[)Z__| HNyk5zt#zq9a,Hyo BheZQƂ {֡݃':kS9$N /m*AĪ/=ZŸ=:ZTkxk۰۹_ק9q׶ߦflnV+*YjOī]xq0o% 6P{dt#MقP&@lÒ 0Օ}# +h]Fw^uAC;O.aV0*tc0wv1bt2{$3#|{;v`cVD{y?ӯ2Q#5I ф"ۨ8q KW듨IU9̸mr_( ˫8 +d QЁyx_r0$ךD%ws^g3Ţ)vOc#j ͡o`GLfw&*D>3HQrs3v\C>}= +?Kl\=?-[`%k9ʼncn^* |]z|jVY۸/o_}8YLx+!քzy͗bH&(u}T9=uPEFkV$=O98 %veT8+iS̈́>/x><0Eʲ1&cfJ;>R0Sv 8񨎁2(hq5%)ǰEw0=+6*0+Q]OE">wD{Q&k{$2zR1 .;ZmbJkJ8{bu*hc $Hn*,WpP%1o\ȁ]U` | 2GINzԦ[^hze=Y_X +-anRֻ¨"t ,_l-lW||AӍ\gC؋eo$Rޔ҆I2,§+T]R $w[{Իw^ӕ,kA9c)RB8Om_ez 7jª1 yrK$20H ֧w.oٞ{oƯ%&Zo@.A{Zрuz|hY_.-oy[2|a}>}Φ}\g&&[b{Ud}ߏhދXZr O'rC=~E/o%?~Cf$4 +RtM':R7/7Nfѿ_٦Ho!||$#1mTBhJ<H#tQcTm"z%XqAPk;*RՂSp +Abщ b1 +v(GJ YATPbZ;7B~/ÑDUQ[6zg/U!ukYd_['ypHi+OhkڇaiW$9b e`y8 ƂE:58ڌ}Ej#ME^DOn K|_C™Ͷwڳ(ʶodWXGhs4-KL*J@mhQ^ *7 m*+N endstream endobj 79 0 obj <>stream +DWz$tfJR'E<<x4jP +E%G@6I G-IZ嗇 Aj5yʘ* G?{g*fyz(HEgђiі0x9eFrY˰Cve +{ß[<&XaB;mٷqTȀLĶg{%-|3iw67A97B+an73`"p(gk(h('OsC]m&-@*Ѽ0͂6zۍPJ/$/hy.eyK+sB$[-Kӯ?M&9O W k 2iKާA? 0ߕ6ܲw' ϳoZWެv{׵)mkus/{7u|7;lA"?$Ʌ bVq'ޝ61GߠdsצiN^ xfZîM諏aidne&QM!#MO{'򮧭Kƞzvin$w=uUF;"ڽz6?s&'E?ல89t,^>;#3ВlϦD^.mi=fGHZU9%$E-  g=Rf;i<@î ѝ"^g2Wj[iQ2 |eơe rKCE 爖:%0[>iH> 㥢 $KH.V|S?l=Sm'01S J)Nqh"dYmpPQZõ%mS,#T>tmHBv`GEu7g%Z-wp>^ԡrG̘#7DsNx}܁mͥr"5[H1؆+s em2l;Q.ӜjYwϝwa wҽܡV5**.;-Oj x B3݉-t' +7y5bpodw;Q= +!p5*PU<Ժ bergY*?rpfv»%OaBvrp;4,\!2ҷC;E3[,vat]c+[qCa,Z{U:+9l:T hw1 .ާ8El TGp BKҁ!+pZR3{2X-MiĈhswb0nl`5|׬\:1YP{h֯ oY1_B[> dbQ=>L1l>t8-6x/}\e+g#~҇Sp}<އዔTXu>/LY50r/~axx0lL=޵a ata`|0?C048F 6 ^KV I' #ll,lZQ_ƶ$s\Hi7?O4_hIz/d{75IrZeWad/h"1rk[zQd '|*q"Yet;‰s۹WSS# `3\Y>a4Eyo4S@aֆ0QþDTY'M;?p<д%ªEIU]#RY^Y-+n8.X +VR*ʰ \^[Zz-p[@dg[]j`C&Kꇛ z펞0xbRuWܕ?ld.C'Pw蒗0<Ǥc屢 u*Yzf ?E^z!q2Cx;SYaNA]MI>=uҷjm ,q'j~E=>Y9to!xzb ]jWuY} PZ>Tt;5翟uߦR僛k)[Υݐ;g՜$DtTp}pO=mF){LBtC3&͉ V9Kid d]^1U5 rg=Zu>;C0cٽ~"WV_Enx@Oٶ·5s0(yM{ t%Z{=5k#}iAr !4PakjdC0wi$f̈i"[6.Q}6#+4ȶ*R`p:'ҧh䒢o+-WeKKʠt{o jhS(ϸIs=JKv[f;藭Nua\DNrjêގS3 +jf`5_b1|? (ޯUK.ZzHOVa=nDD *'ڏ΅`UK.yLTlP eZdWɨ3hL?13,j nQR!:fal {~aqovzA&y^ +z< ` cp0u}xrRBnZk3])Jl:},&J04ƾ:t%x>vhyu:{t٢;}ɋZܽkSp_vSUf naRnk YӮt(Yn_֋^lX/UJ{uKn1{oruswsSśɔқͪoUw~s>i=Vzpnr%o$Jl[ r1M+pӪ­Mr6-лě,!z3FQfԢL:K}EҬ;}Ԫ;MdvRnj$gңM8wTw34{g.ݭƖN-ؒ)t=4:d][#t_+/ږ޼k?_Iʱvf]/Ykk[ٶjn=%wm "*Nءݾw=mq;m}ކgomzJB =w}l-"ښ#Za֦߂? pkg +s"YlP=]Q[(" xcW}BGcM$eq5CZq/{ft'}+\燌;Qkx)ݧ+i? + fu[XQZWQauv_XQe{}d%\6VZ}[!kG6ZNېvrV6V\ї%7V0w p:[7R lמ67vש>Kv?ΆWc +*"ЪwxC~1{SD `cډ6U)$}d oAfiW#\j>OË~Cg)EyFO^r)Z7߻rGs)j~\}دΟuwpwn/U9_)0vե}3$;Lo\+Hsyc2Q݂EgzJo.1MfOY^?~]E;uNlUnkNJ~ݞux6=m+붥Ύmkضnsη{ܷd m/l6hzP ? O/ʹo unE[jn%_:N-MVY$]G~G;HB(vsaW{L˫V$9V TouJSz댒7|FU+[ap^ձIv$F{5IeK7qSk. @VM`iuI6{@?A۰Mx4ʺ7LcSRG<1e-7;_tȶw#5vj7܆!"6-b` +8^M)o>h_?N'yv/WII?OtQާ*BϨ;1}b^wN{{Ӭ/~)~ݑmmYo2>mv[ٱl[ٺos5?,RJ\q\|FYlȍ7RKPt׃ NrQ&IE'`K@NSƶmmw$͜#frKRȏ*XH_osIMʍz7.Iy#/ew.I)BDy%o*O$c { y%Rȍ7m.ILܚrIB&}Ȍtc67ؠTm9Q0H*JZ +cIː(X'llw_}i}y- ;Iz)vsˍw|2$%Ւ>$ {'B 6;I\`,KU@4 }O9g$>t C p[rto@!Hlk他3?w;}뷟~Ͽ?W}c}aMum )1u[J9bo}Ǵ BRaEEcBsv0)rMA@11QgDȗ/ ѕ8آJY ϾFrxuwf J+8 ; d1;KpXzD' JZ61ٴ0+YX: m Zk G.s1F2p!~7Sm>V %r?M(6v@w+}䱘D"-6 lrM2`ؒ.V#9å4 [Yۈ:H`P "]^ѭ0Tk$Z)G 7NB0Mtp$LO`R["FMLa(>kf&qdY:ux(x!1dLek #4*8gpHe;];Nف鑆"TґP=}0PQ)k9U0!ay~=@j亂/uK@׺VGJ: V[b&V\ӴhGxu9ƝU'P-ˀnDEy/Ik Fb&jQH^*V` }.j_vJmLܾkOXP QGCv_f0bɜ.D +!N+ר,0-̞YeU0^EHP +mm$RG d5T/+$B_Rg]T#$A^Gj6C3b-8Zߖmx7~E%(43G|Pa7~lLxӃnvt/ׯ^3!?^m(3ci5?|L!x*[x`摀{I2sVd qbcQU$m90l &ދ=Ŏ`S+|'t mi8KPwA)m l͖$T;09JR\ {BdN!Wrρs;uњi/4@Q8ϙ(ik(^0vT; 3-8RXm1qO 6>Tvl +懽'2h$GEن"ۖV r<'bvۛ((~v]2fb# &,Bv::&VM/0ѕUs*}&qcKNH%G@{V,ՓĬ-[X;n`<[(;v5HSj&8_:xlO፸+†ɦT/t;6$kL86{Nk hwO/eZ&,s˗LGgYtM|x϶8Fis:i;R_m,Ps;vyX!Xs)GGM >mB]SUw@2;TK@#BCˎ4ÄF}*r6r?5:'gJLm?v4fTY5Ѯab*w ܊ZQrHUQٸd~ +G@L.նcN8@ôd9= 'Xfh7&=e\њB)KPF8D{{3@zM7 l:Ѕnu>gNKEdͦFYPA$V͐19y"m2͚C/ZM:J:n[Q ɀxF:~59E&K}I쉡| >^ "M)PqfJ6ѻplҲc;=C+Svw ++Y:DGvm4eY1trH>MrQ[U:PdvWS9?{ќDe_`)vaPP|`Q ֻKV{hZiԾC#tb.erU̫2+wJ\B7٢ d2mdsPeg;x@?ak~& Gƺ9fD m6r]Dz36'Df#RebjK IԨu)st#_n9yg,#wql/H3:54joa4_?՝B!ϗ7GR Wu*>¡ţ)}EPo98[,(+P GD_Ef j7^1ՍBT 7Т ![7TÅt5NX# ԉixw$QZkHKq w즍GpEH%C?=ooB,֘ >jT}AU9@Hݠ@Si6Jb6h!B@]Gp@:BΦmQɄ1ljȓ"%,3@ H0xx5@Km>5%j'n#y<֘4=F+B>؆>C$Nӵ$׎SGbb6+MkGC}<1Jr_+%=\ԸA!DE&[i C/X n&'y0HY 49 -D+Q *`Qp7&trٓ<]K෕G<@0ڦH(80jO&rtxhY7$!ɫKeħx=nRL0Fl/L>kFYG[7 tck]I٧X_纜@i[ +l,|<ɡv S4JieWcƅ%v +n>00 +8fޤv(dHHxcN%rĞ u26I#!HaQpg TL}&m7{*ڡRt;bqɶ8/9:Tba\bz:o0"wP.w+ JDIP07*Qf3H [;Ӟ41]^N}?ivk0fU (U4n{V(2eHz ,u0كj46˺4`u[WL&_ȺZJ쾛R驄(cfaQ9X -s2Z@P)H<.Q48.U6ǮҫRaf oft68^lVh?e-lo5y_)&KO۪9*0UAWႨڠ*36Sl594j +JU +Z}HAW/^=v̳Bk + ?X32"DbTl$ &l)dvL,F!դb,*,&9LđS5uM n5963ʮƤ6 >5˕QZ1J׉QF۴:N'&5\Z,(ΦmljE +y +p`# j޳+ 8xJ%7s8hraiq7p8&pZ/.K q>1禇1AiM3؉/ Bas W3JZbG ̍ |YZn"#Unb66pC0ۤ}-/!/W`u_&X mb[MWdUk>>`MOV Ii$7+s ړ+/մ{sǙTNM\"0 w\s76yS[S8ta+7sB;|Jc7xW55wM[N3*aۆu$N‘ BI.e'B)*B5Mg+jC%O١h +PCFC +_BSQjBUUЙ2+PUۡP,PlZfmkڷ`̲` 7T vX \ڄ1ؖ12*)*2[}RY: PHBAj7BQkYBm sys+\~B܆B/c_oZP<|u)k-{UĚMC$⇐K(߆nBc@ނ5&Pa f MhZhQ"{qd! }'!zWehF:C+M.j;3bQhmH94)ۡ]j$mW!f>{m],$ BYH8Ƶm">g=B\Hλm%4Ml\r>p:¡nْXk[X_ZX0ULuO[0hdޯ953>aMr8N2$6shfLB_a~S2:`kCo&<=l/PxĤgZjZD̛v S3"oP6Y[Am7>g"oY3a$kB턬8k]=4a}Dk?n]@mkAذz!جf +%@-,<{]q_NJ ƾ0 o'%N(>M]78>a_@v,'us@|PԶv0NcU􈏿6p|zup9q`<ը7N ͅq\0dG e +ޛm L/Ž +} heϛnuf')cm wpGe}eHtێhd"EVfy/>g-[/^D~ } 07szkY듸x`fC(h.蟪9x~L\}:Og*c/;H㟿SȠjvaGvͶqô^߼a|woռ=r0 PܜҞNw'1<%Lj}"-ؙ~y=8]Q&U1^D\P4ՙg:H 4CH$=&A,jeOn.00柟BH 괧N§LAG&XU8ʗ!Pohi<p;=9u픃ht[<JT/G$C>Pg3w8i1V PLUp7:05J$Lf4QDɑ;!KR)yQ7d%R#I$Hmc~-Oa5 /B p)#d[@lf +4g +{2Q;.^c_uNP7ےjib+svaxUSMĺ?Wo<! +0 +;pl']1|;*Rgy] +6\#;h=>-DI.1ϡm|tP։BS2$1Z<7 so2vN%n3G It4$i$: d i8oq R/^e- 7y% Iw}^x'LD %G|7=WQqbz +YϤA'ld$R [pn!kV@,/!ށL^ RU`7 0A +`j`N@,NbOj蹏J}<D6`&z u-]R5uH \ȁOEx":m7 D4CY= Ck#h@ԕTevHA[bU (FܠE&¦N *4?GI(r|G%)6nSAMܑN8웯& > Vgl lylv 4߇-80M38*)%7<\@#BMWcQZeWbf.)4c$)26РILޓvH{%%#'EN[\ <} 3'c}`*+Ea|KpHc})|_PbU>j:3+aIʭBՖYl'L@6Ci"I-b9jx zG WK#MXW.&\ћ6~zQȗK0O!q҂`Q96mGe$f SkTQ*vQE~ǐnZyՑ|v^[G熗}剳P(*o~~P\ +yb}1?{qnM* vT]nfΔw*!? v#jH?w +Rcp~Á-%}wElS6;&a`؃bgb}蜀~ {NcWS{`gwCr*L!d>s5.bb@>h>tXa*%Ƀ7ə`wPW7 +Mų5u۫}&N)ۼ}Z[P=?\$뱌o^~3J8ڮJ|aq # +߸͢ _wF,;C52HG>'VJ^)|#o~h(~e+=w]YFO<5 OȻJg>ͷ]G_uڇb95 JOٗ 13;XIWުf#83@]X7՛Ҁ6 EKԶESBK١O~8q:Eãl،fSdqD)4^[>؇=ZY9Ǫ*%:ÿg1sڤ);j1jZАiE:nqĝ #D1P)\4a 츢5 +}RKMSl^|֧R)0Oʩ +"eѢ{:\"oӦ)p/Rňsa#9,_{.ʋ +ů 3lfh Mwv3,N,(AaL){648}msU {Tz˜Q~lМ^T'n {~TejO)x aOBC""eȮ;4oG)F[ SE^>PVǐt\euad8"tO> L6^kҔ5ֺ0bHoa Q%;X47lu4P nԖ}lՐ9Gws`Mٴ8DP[av +M=ҒMܵQ[IeP[*(Ֆ䔺 EEm)T[L tlU$ruEtmGGGm'/\>~1'. v7hd;~צ (Nj=]Qh˰Y8=)3A ZI*5Em('=:Q/CFg 4kƕURA$VdpIК|fg]hpK&8 [|eNR X%_FmxKiʄPrwwrh'AHK%Yn )9Aa?OIoN +ZEM*V14[eRPճzFԌ|+%]*POӭ!GgMP߄smqMBk]G$?-[[9v`URuNs1[0IZC>8 A\ $bsl!6Tux-p|v'tyA²7N N?X5yR<@`N @x&qپTyKt_V=\.*S,;}݂eJ d;OL0Nj;˲wpi;:V; >=<lwǟ8b8#bӡTV"C3f}P/"1&ы&4PӋa=U"[œr_Q;Eߍ"!2xRJk@L%o ^TfGhz~Bͤlp$s;Y +cfQFrR7tL3 0E2DD HPdБ̀ПW$" 2띩<$8U>{(ys|@l5{v-kZ"[=蛈{kN9QN`x@ wJ޶n<4.@juhMF7@聾+&W7R<ͫ3ɿ@pKѕ Gν +Ql_JdO"[~.k S@n#gNS^lg @;g2'2þ 4dq`j 06 \CRp3QK2E!sSw@+Sܪ)?{ ϟsʳr蛧C`jlˬ*H3_JnApIl+߯0馠[ڔ6fߗ8$pm21i; ̎ջ:Zx\aTШ6+( ZQ FF]J|WƓ0OUR]?' )Ż/i =uU7zUL*! Z&Jo{O@嘔sZ @{ KG?Lxn9-?ؽ XyP Tg&?ueB5E?;*nnT2"Ԫ:_J(-yOTS L|xRsA9:x +0-B<Nuj%&3:[G@ΰZ΍G0V%U3_F5Vp&S{/;UhQaAYHE" H!~ }_ԬCpwκц!_p[PZ6ep*M%! /,/@{".uDr?ٸlDJ(LЁ&mn +4*1m"CFYM_f 4wDK6;Ba@9Ո>m޴M[Øu|tƴ5 ]<paM[SLxtIާ[Mjl5mx%kޚS0ykPA4!ծXNE&o m8Sbyk +I#oM.68Bz`[9ZH`3%~ .`7 쭤)3_{ +B ;kD_26&mVsE]8s \寿 l$GDB=EQ*0lZ!th ñ7QVV/TOPഢ`:N:'n97g|| [h6o +DMbiO@2֐gܧ m>A47q0lvmvL]XW {٘LYYz +P8yro/1P$^ա$aU׈}ʣO.J<ǽ#'dJwHj47ETFMȧ)p*AkVbO ]3T +7DnP";G=U8@=>o)\J= WI*-+lǒ@| +dV,q`hl@i7e4p߇KR@uv8uEpᐬ]/rٙ} +y4h #aG9c:=&GiU#MsZ׊x93,X;նjOEpr[ G&RW֍=P区 daV4`2G ͔ +l3(dc|I}BJLcKw(}}ݎr;!q¯X"wߗ~UxGfԨ31p׈h?4c 2GS%0} HDJ)q՗P ]`CH-C&Ԫ`5w9.g$9A `4@vZelS )utHY ؄J~v$m 3h[l^seYa[R7wC$2' -,6j +!ҥJM&ĂzNw||39NV`G"jd4]RWxbq/=$ tq*! +4 /L)Mߊ~3Bb9nAh|KT$39W#2AM򚱙E,D<μ'KQMU El +`={XC| +K͆=CYϳ^eoݙ4է d>4Pws^[[OB3hg2 rt!0V+C N/KDp:ty)YGp8ԢglFG.謹a&jtDyCވiUfZЄa$Oru#[S = r +(˛tBSA EO:E݇W,MX>@]y>ʦK + jv6D'3Mdas< W}h>lb=g>"1.*E\G"ɳ]`jrg։aLkd:ϛEip]aܔa&!ӀOpW1݌r+җ${ެ}$%DJ`B㐑E-*YhܫHL) +8E(J#~›UHz=A9t3Ykv۳&q (II:e2{aXhU؞- +oW\6*JoJs* 5` z8B +|"uny*Ńq{ckqQ#5Ĵm}Mi( ^`tE~%MKVhgku񜛎L]&uI;~ P:VE^ƒ*H Ym{lH\RR40h3ʩzfQGz .,b껞|:ba muA{ED#pPB\HQxTxoKVMjSņT|adz u8VH]Č[Jvک]of5!vă>X;n2QK$sVB(#IP}D,;scZRE$XP% nd[몘ސN^b TeBBabFBSU)1By@ݴՍQn7N7lFM/P^ƊO +yy!Ҽ#cl|ՄqEKM8 Fm">fy0j=Mo:J8z}QI,C ՆL@%D%f|;TJEtp-C=ݼfHE [cLţfi;fPB% Y{*), 3pHp u;U "NA88/Ⱥ%&ȠJ@t ԓ0B۰BJܣJWM͋ rIF=m!sHi nh%7haR/kD2q??׶ OFUk7Im |;9%LhlrJ pSDc>FM0kOiN[F1 Ao3223Uae ROYjܦPXiPoF]n ÀO{8^<^ޅ N$3@$>XNu_a73QveZ#A8uy) e_ôAPݴgPkj(Z;xPiQPIdFkzk^ +O itU 81ٝGPL#[+23y;,R",N4y)-1jR9 3ݷAGCx$ N%?_Ee\VKDlVkΆgﺱ +E2;Ar}zY{IۧT6Į-UIQQj%2 lj05gj{GD--AxkJٚ( +|$lZKz@x 1s\͊L4B[[ +52Aܭ6[ +v >AL_KVjޙO[* EWA_⭭ E`AB`z&D(g H( VL(ZC2/S/d&pkح( Eў\]ͮH22ɿw.3١32tg6"z5[&W(w*ܲx݅ 㭣W5@kqg9wg_kȣC("oC~ ĂUL0B`U} (0WbMk-6f&C(`1Y#Ee\]B\3ʄhhyZ ;!2~f,w +h#n5v13CUmx>~$[3#miY39nz&]$6Yfrb.#T *aKfIkt)aZk6Ŏ&pXk T\ Q$b@u𹊆Ćk-&{rnwwLbcϮYie?jƏP,dF%(\jUͶ ٞ5 0m)kr8~ɚ`#ZmgfMx?eMǥ]3%Z \k2ijDU|1y6B[w>.-PZr.ЀoW(jqBJ慭(S }gZ@w!?3ɭ1EǨsUԖ*vx₆ŒX4 @ v6Y~'73x]ĿjT Rmd3*7+M*s&5G~ܸ}#Fn+U7P,H}_]3ЄFۀ ' ~ܯߏI8dEyBb9lŕҋ^-|uLʑ(6 )e9}]HV2`]㒲 ~bDԯ@ $J<.JxBvUB)э8Y%<%N">>[w(M uS.Jw" jpUL"AYA̱@ VKyw6Z6V4aP$g7JzB ATbi{w~ 5Gx@]'";=g* (+Ai2 TX 2*vCjQs}m)-B+a1VPnZ,Hޤm3hP4©o1+@Q!HI v Ts#s̴/,K y]!Lz,:snH@6SrǨc{ߎW窼MVy~ȧ#MS(>,A6 V̀d9yʲzzMC{,LI0G(j⦹7U + uE𙤯?lhW1,f>ma +]$fǤkݜ4ase]7|(G,}} v{9:˸ۀ:rrfn1|B' +2uHAho6u/r1>2 vw+8on Q*Q:Ywԧ w?%|ܑ_`HSF,)NsSJP޴.ъK\H ^.)8pVn%%@jMl$o8`ݛ':+#ϝ|djJxvM +_)u23ңe"QJ}ժMv VFS9|Ax_dv SyB?eP5YuPXUM +4l͠ `Wt{ʏIc<^~_AQG Pm~Al`$ +|7+k'`&z'3@o:~@ 3b:WlP + +Ng@'N'C -Ng8+~ @[0;'~ [NR? mH-Pg<=~ [;~ [΀;Wlعb\W΀;3 Ή?q:?8ysрfLt%AǞq߃;`ʸK=mLOjdij*aǵgMbx2)Ш{&2"x#o4 nEvaAr7Ql)jܥ[v)# i=s+C9NiJ˷ 7x0rXߴ!01 /J 6#/]0vqaC 4UO}NjVijme'-m(w6Qw;M+ /"d"=9i"[.T$oʊAZxyiVw=|S]|ѷv ƒ2ɚHaͪ-RNVyML=fݽ=:`Zg1MTv(ⷜМ=l~qfǟndO7/_B +^ OѶ@iH"NEFUEFUFɭ AMFɠVJɠTsIrJUͭAJɭ AErɡNENUENEEJɝ.ܒ;mI&WmI&Wm&w.M.N'RxSxD}y'?G;Y^޳%}J;ى8O;v>ؗQ7zC:IM)GgG#ϑN~00'f3*90NRh*;*p *ʚ0NQp*-зm\7DiT:MslPLiP웽ig -%H3# I3Mž4FBtFTݪvt^R_hc`4>\~4R+ȕ>GH|o6VeJʠ~ +&UmˏVxѾrnSءkiWҴ4lbO;Dz2:;nxǓFSP˞'͛7!QtxhrD!"ճ 74_Bd'aO ]/> H{:"S̅v2J9%~F*'z` bfrGT$ uN>.kCU鮘ai) (NdW5첊yJk_wiJ :²I9zNmUr_y$ZV^Uy8o??0 Aʄ j$Aꅥ 3l()Ö"֟35FaҜ>;b^eq!F|>dAݔiwpi5tWS rBEuݻ [Ua.#$;MDf8(&b>Q$'z6 ?EP("rzΨY/b#ZRE!mY.ÓvT"]A EA]խ*H +G#K9A)7Sr q/ xg"]E; $wDkga@.cr*ep?vo=E| &\@Ǚ?wt6VU~-5-%МRv{v|Gsb]?u9oupBzJ l3j@l_W_)oyEw!+EznY4!YL?d90(4a/`f̻c$0Ckb YR6iఔ)S H#s`:8&Lu&xJNf28NepCgDŽxdoqA)]` +lr;J![43sx keDo?=2J[iԔHtD1>OR&8!XBwo֬DTpe ac-L!Rhpk6 @m&!vꞪ]6#4#LAadJN÷uI% +UMb EFƯ UQ.& |Bf,#gG`(IUNlxD Q10 +^V\[. w#h +M5y|9'Bv*)alS)N]dwky U BP464{D .? v@ڶϟLxSJթ +^Q:p/zGNcleal[r>;LSi `rBH" +O>,U1z[FCP^~Dan.ТeA\E wvZ@Pog^~F|g +qRuq: + +o묄jrLX7if6/J_5Is;J8IqccJƾ&yJ9chq%^Y|ZWBM ETrӻ 9c|Hљ:RmK2Uɮ&d7!l3rPY3F&n8p%gے;l-0جxd']'UgK# *~kRܧNP%̂7 +^Sꢥi\{31$24 !@xa\~Vo.3nqZP9te!9 lagӡ&~CbMPMY1 !Oa]U=Fs%9C>QwD@}L55qUOR)asZꩿV.6 lӞ޿~ [st3*Z+@H۾Ho wl +sPwCfKwSiM5Ȕ7m'D;z=rvJBH]60HPhrmvt wc^s#3`!i:ا>ա~xrnbO<<y= z}@ $5t|r*9CO*xQ kuo  +jVuMh{ Zm4/2"cqhm A IV/by /H$[a@($S6|mi9/8PB}#=*``U zeAh D96d_D@y\ PHB]&2C1a[\SKO[9 +'Ms_7C-.;0={h,t,^m4 +Y$j۰m7x? /ːϡt7F (oJ^@,<p|kľ5ͳ?; f3aP94G~vjTG3sfli(%&tJ30O-S@O`#&fG k[-khةǦ +8( n+j:̀pC`C(yڊ'k`w@-w4G|s:MV_/JY )59#"`g걓uU~d 6N4M;9`au{ayN -|yh$;;c{`giAğr\; |-9|Xܖ +T>;4 v]/u 9:ZU.-n H޿ j@'ttl A"UhDB1"]@TVo;L0T04,]T  مP#u}ꃯW :Ő]n #%cZT&oQA]Uf^ 2༢g0uf5Q5ҶGFzAfDY%kUYK0VbČd Î +a`B"38c*X[p0sk\J[6Bib4 No`8%rr%%Ȏ-z,<)q!f~&]dX +\=f%z5jRe#R?[ `b%ЇZG5'H 5S)s| ɒ=Y3P[1ܬY8kv,KRkJqdܙkz35M?%k55aݟ%ƚgdo֚__HR[RAh)gM["D2j* +%[MJ)" AE!AozUㇲ[JdJm7P'XD'Sk G K ePfWNMҵ,+u4ʻM:ԗm PP]dnRw3zѕzBZK +3V&1:kܱO]T}FWy-ݻkj|ZP"u18Z㻏1ʍChfZFxF +14PZkwŪ]<-\(\_#z} u!Jgr--. k\44l!egCm8tarߘQ U(!HX1}3!n нhƱ."N7j&jLP>ğ'`Ho0vY{U<>*]=ШiLxTehW,.|`o7k1-Ee_knZgw]Gg dI:>N6dMO491F?)EPVu@/2fp%roXzz,o(N8.eFM1P$0OR%ʐfyg@*pN=:Phq{8r@Ag@, + EKSh9 JD@p5w#6f=U`LMU8x;-t G +9ܭY<&SiM$z#a~0a\ROFypJ޲Rn'/8J&@M63W9T7aLIVA"Mz^(D +//Lcggt[ÁK5B=a; +KΘCaB v&!]C]Ut8n/vO3}Y)+'MUD}ddU8]pRS7o* =-()bNR4:.&\NH=p^@i'}~K$T}B39\< +3mM_dVHyb2. ?HN-N4jK(N8=1=)ftGTug'PAI<[Wu0PxD5QM.lÓRɁl=9FN3SvR;U)]R"chd/~ B4IqԒ1в+JWl)=9T~iD)!R/QQ ?cj/A•(Ndg +da + eTUVc,wl*ec;FeTaҝFVl\*LY䰵>=81⪜cJ?L; QMe߇>ꟁ)n`0ޤi#z( &ҠyU4_vv$К-_+SfrE2feV\wS8\% M# +mL [aɵ}ndQڡC2I +tɍpf]x'[u)*pLyBx $@z<3>]vv.U YH +=6) +&ă񼏒Q +*eD +f()Rz|A]<1ܷ067_g㻿?_ꗿ[@0L{_ gǿ^ݕO?_7㯿?oloտ;r_~yG_/l҈ _v__?ksMm~kk ovwm_|uڂtdA- M3 WMvM4`BK+j +GƙV_>yc;skǡV"gZMPZ~<亮a<&S>_ۿ?']? ʨMvg,no'ӟވ&,fH__xc<Xm&Z rL|\R~Ѭd^;{L~'øKk YvG/T1}|0NyBP:rҘ=.2סc2>^G] 9NyeR]c砜 Xj%2]ֹ!^/`IB&0..|Lxv=y13q=?h{[ +~7;GvxH<9qf1!nP9'پm|F>ȚXS˭61ʹ΋=}u^3tv{#̽}p#%t" po?/M-#No6X#'h 9ks)!x6=;<>suyƐ:91p9Va\.>Q'ImgyyeRh~9{DW(X2ߌCۼw{v/:DLGzpk~͉㩩))mjC۠6rWU0;>{+9QJ3gMtEDj}'lxZp"c#ם31*ǙJ y퇽~=&X}݅q/ڑBfq_Ǽ^|ٝ!p5g8Q0:B{y i'3U:IGbȸ1j<Cs7mS+:e~LkC2%JQ\6RxݷkD^H(wSKй^~WwXm0Uw fOP~ֺ~4LÔ[_KwB56,~6lZ.:yCiV7Mo&7ӵeǚ2t|Ys}뗇Inz5/^yTq's~1Ŗ~|mʩ4Qcgs"i|g\%щ5ihP^;-gIxT~#~BIT4.v#O%w_sK\w#o$o)7u1slLj>;\< {=:ef͡jϋ~_OK/[(Cq߽Z>_66)X2:Q~ndDy5|LIVœ~]< +5HUvmf[Dy4^h+rBep 3UZ}aKye*,49x-~A|E/qn>Jֹ\%o*,S`,}OӅifǙj_jeǞΏ'Ah-__pOuo>MGCG^4ݞ5;Ms~n)'nr:g><6 a޺%sϋ|c +7G$LCe~Ӑ/~f^h^le*Ptg288ޞ7qaW\fܴW7`*uBO,(y-\p בΠ#ϺlCe+c&a~^:<=ՐRuQb_#`^G[v6F1w` Meh*ܔ'ZȢ<ް\ V1s,sg5 +i>$pP?=ejaSc(O3_d1v\.#4s>tq⍃sMh +A?-*V~Tj:O ~o\f.᤬qxqKvtUd"3fO? ߎ˭q]q\ln *5u4=_/Àonp1ϏB_i3B5򓨴=eqQ 'P-? +cx󱀣͵=Siɘy0/V) /ZRs ]quD뼵(b_E}tk}nqQxHrlT%xbqv\>m^'@drՃ_{_I$O;K7tDj'd2Ԏ# + +~gD&D5TD嘨Aq&6u uf;rSXgg VAg{KfHU}DĪ)AhAp] |OHY[Of ZyV !izMSCo MҤSK(ms̏^*ExJ"v8%(-vg"jMjNೈ /|:L*Ԍ8u\4V Œ 6jaGY1+¯HFep$ +MFT}{ՍFXC ^4pЏ&Џ#X2&ɊdgvF4|y8Nd#3T-F5gwpƐ?GcpצvTXv̓qtT) ?Yj&mA4:q>#T &v>.FXH-3bT0ee(KS}z[m5f,È&嵦>(0!t}omdB/So ~t7SĶ=icn7A%<1h&$[,њem?K՘+&ȉx$lB"g eD'RUUE䉻'կxSq5#UP}oO4y;eLNF_XbFS~%'bkAMK1%l#MdLHc֗ź<ԘK@I,`}+ē"OJ;$Rvcl\G}w&Gi&MYY_C"/xC S=E{d[pS˂b%'sn"3^<>=v207Ch`Q>~ѡ 8/"ƴѱ&߃U-Bx4dŘ`ڡ$wd@/.ZBya}UnoG5Dj8+bT1wVX6_%4%^A5PWP8EexKBSw_U+)]KƠ/yO73'[fyXLL1Q{q-D"k!r'UqS( Fh +2 3)ߦ'ZB p- 9QRn|*6mt*"'}2'^SHKj8(cD.b8 F<8-4 噪⠦_zJZanDk=noADb8eWT5@57t p֖M ~lixZ$7tg}';P~{ O=;`9͒7*4j*NjHr{E/EB8)랇EIhd{a)I"F3Ld/ )xle5'߯I~{; +5QJiוֆq4anH YCB6Y2X5UC>#'us(BYo )6YK ͇dž5%8{oL*g߱v5 +Z!W¨cX,ü Q2c""B.!_*ȜF_W`Dǐ/Zys2C<c£o\^GU~Ԓ 'm:(fDP?a'%2k('}"E)2бx 814 !倨s0 7#S#nh~ |CV!G\㊊>u9, ^ Zahj4!’ Z7%ؒȈ&bo[֒~'g*(@l GIOK䀧Xo "ô0 3YdQ885u\k7 Kj\DŽF6N{b +m]S<2{sOM 2IQ~rrי}lTIx(.bPsqm{=OungmM`Z~ ;8H$::j :dbZ<0\q +"1 5>h{?Hgr!1^_C!L7ZFTЊ壟022m9X7:Գ5w,j(  +gY9"2JH%JDͅOd +͊C21_]Kb1O// X*J-LC+C{B6}!8YQ6طhp\[-JY\L$vA:a.+ _ӕTD:i㳖9!S îG,YND[ݰUY +Ύ 0rˈBGUnlZ'زa˄uNX)@0G'[!VUuX\!1):Ÿ;2 eQ0E "Ұ UA3,g҃blKQ܍0E,'o #Xɓ(6~U;Fؖ"LˆLa|r߳!f5"OlI 3Ѧ-ڸ-Ȇu+Td *2Uc1aaXȼW#:(kcD*ԟ`%#lqenM|˿kdlYKϖ)2Q~D.Ɋ@VĞ`BWL@&2+LUmuA,4jlpɚ|ԒB.6b:i2na +*˜{R({4d2zsӯNƺ9LOX3:آzIp"'& >'ʤE] 6-ܒZwi\ZM)xtwi0ܥ˂[]jV$:5%`,׭D7+>'r 16RVdɷn(Br9 iW%$RĝѿƬ#+yWXjElXT}"Ǘ }(DruMEcVWO[aJɆيi.hKXٶdnZLJ5LޖsUXBQ 㷂 Il?%?XLz(V"B3FUI闱eN@e8k8'YYK$sɔ4: Sv6-@Ip c':X俜L(2 7uaQ&"ts1uҠ.Ҙ dKÞu:$P]qXSD4PY5Gdb0֛Vv3Kjx@zw\ZK* 1 MYnc,k7-@dnndkCN&O[UvE$~F$-lxeЅ9MTblGeBm$g*AK1aI# `MUr "e -beޠ<1tfKNl` N4M{Jə'igX?i +BӔ&K-i|C>w]=I['Rsa8Xz\?Wq!|d7+teV s{?&o-Ȋsy*cdfQݫ)][7Ӷ߰죪EmR2ʒ{Dz!ZI5e 7`x.ȷ7R&J|f'qqYQ*ۀX ވX$!J[:F-CcI [D\ѷyՑ&oo)"kqƴhgeܒ<66a;e1KaenԄ@Ys6%(sq{@$)ii;g;[NNv=vE.SIE- lPYezP]P?h1U(-:Y]QOhhKC2,YLc߹qfqMQ6͘EEd;1[[ϹKDleC$>lXFD٨A"&NFmlCgWJG,kxɄ ZM6kAĬ;%˙ms#26eT~bDSmk9cv1,R noTݎ@o/S0JTTnaSd[Žb|VZ*x-Ϻd]bcQ9 /+4B4L`_"#GTnU]酾W tOHΔ]Rس/¼~,p/>k&MT#J[z,]DPFTP.G)mikN e +'!QACNBۍdÒ4l@!r b=VCŞeMpC*a°9} +j z&m)‹eФ-^TD[ӬXD [.ZؓR&q];ӻ(GK~!? ]YdMDYGY,J姙SGuT{aP{С!Tf)pȇJ FvKm?)@TMh4aL|TѰю*'1!lDlzFhh))Ȟ:bȦ.rـhV?ln@S 3C{*Rk6 %pL1R^~e.cD3/,d٣¯D["]71@r݊M-PNk%x?#~CbX}pڰOf3H);X0m_qY-S!g@%xCL*>%;^pnʂkQؙsP3&$-+[{Q3ހἰRlA3TAԧ݋U,;!1ϓ b7ɢINMYMH?Ke [ ة-@ : >[V#3,F3EK#h~2{6&?_YˣbTP80P&t#n-^r~6 j7Vd8 *eJO2\~,Qɋi1eYT".D][,O i" +;Kz {Jk iDu N -D%5Ӑ~[YP(yN{\q|O7e 1&k%e)ba .-'<Ic>y`/mlL9HWtV}B~9}`DS2̩є O-.#4Mʄ_7)ia.6b7e-xQǮ(<1!KDTDǔ^A IV!D2*z$$%ϓ#E돕kJ5DaslfLZ!sMӡ oD i2lݘ(e{ئGEkJ nm'ć%' +YξJƫ}>QLX)d$l$POc+ +}$IDA3 ijü@T ڬ2_-X@ +^Ql%;`?X$j#hb +Y5lP)4t![8*}{nVsΪs%hˢ3X.!P$~ĄQw"&B.b(Q{ +#/*t4TXKo`3fЖL6?6e"^_N5,h6d]Eh r~u yHo&8Ldt⪡yl]eií 8l="oa극G2HNPnA4eDL14~X7%OQB\³O,mv?Ru#W^SŒ Dʁ:o  ~2,{el+r%SZĒ/W}\J'VH)dϊh:'{C6Ph$e[3q*js*Ml(S ;I~^bKAz[0ܬD')Vȥ73ŅZp3eA)+~̐5>CƟ1ԏYyy6ooQ1[M,8qfo$%'}:u|ToȖ*&xXuY\b٢@$ua8V- [6 ٫rO^aM^iɑ>p\IQ_ς5Ku<Fy^amD3 +dJu?xLRM$~4}.K~!c-}bEے &,BS#ax`ݏl[yI,ٿ)&:`7i<{4&RbIǯ_3v%@FPMlΓb[ƚuHꚭs&&׈rWn6%`ʪLQ?țdid>+i>}S5YUἼu seY&+5`YôCwlPr3_&El_Fؗh~:vþ,LF#*]DY,Ū=V` S(67D3]J<ى!dXq/Ȫl1*DQܹ*u 8`ro[/VnVBpt`b.6GY3* +t +IJ#0wu8G3v^DN)rOySCbQ m1XHEcj,c -yV`=X뚆{|c +[8XƋii npne>u3FO3dTFVkʶ#.^aja&9/~fňw]h 2UV/h5ߘe=umo8%+Zשo vVsޅ-lm,U~F2ZIDe|/a"J}Ͽn}! f+Z+gwj~ ܐ?5^1peR>z4Ӣ$_@nx?[t'ݙ> Ǖwono^~ۇȑyGF[&Nggu\_$mX@s,\~`wkrCW7,q=s1+*>QE%i(,KB_ f:2 ifDNf[f]̨cE>pp.XMX1v:l `m}mzcb^eag\>??(oT݇pa, G4蹐N=K2BEQ@7wHf]M !XzׯKYYmq3/|2EDp/6C0 g/p"Ȣ&>}gDӷ8`[t.X4_n>Z, $,gV2>7_667?.VaZ} 1w1L:ȏ ~b^$fŝ>czigx չ?Uzk7_r+A]Y mQes6/3OV Z"]rX+̻_B0Io`X7O_٩6E0V>}{a0yIUՅtg. iVŭNeyB ihS)4wltLCoxU_ֹ<3j'm< s$Me4ʶvQFkQ} WgoZۭ [&JsvDGyڛ(x8c|Ĩ)A}Va4Ra5iyqc^4ӮLZ'WVo˳Wr;vɴJf\/hVu5߶c< .Ksfډn< h檻h-W&*L;z5h♶ۻ̷Nv-jV|1֪L'W;,\VBje;Y&i7۵~jTV dGj~D*0Ttg#%8I;W?.4ϔ(ƓXi,viWvЂ5aK^"8l)NĪc; 0Iea`VLg/ZK:Ltgi2lxzM}v5t~m\4b" +9\'Ji;an휫nypmז\7lme;.uBT]@FO<iIqZ)T9߻ [=$^ ٘UK)g2Ӊ`ًrN<LHf'ێg#VSu-i\{p:w1c @>rc;J]}^+Ed h4gwG#8i6YI?aw-8_;Yŝt%>64-Kg[QjnH+,h'gIdZG=0X䞳H$W@G:hi Rnw @Θ2͋3+AYipI@+A*7np;L Kv י +] he%7ε.Ru0Cf=B1PV5h6d@g->HFFi +W ima\)ɳL[᷇\Nf!2] Q&ZعiT_|Sހx7)0VUJ! +"i |)hxarWjԯ˳ $Ewkio/]1ܹV3vLI}'jՈV D!iX&t9@< +Zi7qnFHo ЉGl"MogfAHgG!#m#%r < I2e /fHiQ\{3`齴1̴˓WN:j3,&rOCV`6߹JA]]lW@Qw@OgJqoe*y Ҽp--\>]6H3隕P8\u}2 N" fr +`{/k' +]ql.}c+IWuyS. ^ϳk8;oZ]iuйuoh>}yߏξ -ӟڧ?7r׻FT⮔28+i +mz38DQ҃?1 KOZ<>UZum>NR8gϋs8O(`kn<ʇ̈"R f3bANjKNP*Vt"Vc7]؊gMost9r0UdܞV7vXwp-G&șhf/%ܘֳ +*? g@m aXn'YL#ZM.oiX*ؽ(y&j8OSdVӳ 3@PE}X~\| *Sw z{ @{yvsX| S[hF΁?Hǭ;]@(swz3?ϋߦ!ig{7- uV#o bvtӿEjg9@N?i?J6N Em0<ؽHfyaAWfo[?ו7/W[i }$*p2HxҴMǴyri, l~*|b|m.r 'qPOG6"AӨ̅T7f g0P>*W;M>Ȩ ,0Ti?]J6ǐQMBVjRha'fSl+ $J0g[l?ם-Cz=xAB?ftP-$lڎ?aQc:sPON&ܙ^](AHWaZ~ʴ8zifg Rf,N`/O?8;կG߃v 9o Iy6yY)/+)ͻGoCv иQZv\~~O?xW0L<}U_} Z}SʵN@GID-ʓӫ? fwfz@7-A{~ՙT/*^:gwh_,=݋M@ z X^;"u3՝ +4w RTOfwVZ-E?ҁ́ |n=vR݂W~ى6Yq֚"V'jřVjM-(GVUrÐZhjLc0aLϮeN(/HИ4Y} kSNH-'Io?Y9n?$L.HXoH+ß$(pPeў=ҧ!k;YMPݝ4"?l`{ ?ͳlL-M@k~v8:݀+tڡRZ.vVvb+0Ûh䭒I +R; g#,t/hϔ*U/^yeOAw_-|CN}^gڙ^;0j6e H9Q6 ͕l^X]c6iGH#&r={v2hl:M1(/+ᴗ"m؝ʆw[R>2 +;Y1Oc1F Ȗ,p!#a1`8ʑE4 +;,\: ruNi?_;/wSl @ZU@f#Q)L@ V +J[q pv/ELN@Nt@`/n_?*;-7LM&Dӈ[ݰb _8&0dVPsqZh|4aG&׾P+}ʷ0W_ZǕ٫| +6(xax>YUu"8=Iigɴ" pQe8(KE.iV?t.ݫUwrGARϴɻ]8e= ]P +\ʁ 9Kj~T\tIh㤲8zӡ\:DO^~p`\-a/‡?+>&zvvDDج’u8#%?Iȴ,ޤi'9L壘\Ӎ"`+e栋C~$YKdި:MPJe+VFan\m˙D7J)WH{ZJ39#S0݉jOf@qUsP82i3*u@n'O9L`Z<ai0RzW Zu ,xبa>^4%A~:!LpXvv2^3]ВUYNik :~?:͝d)V JnexZjYOv®UDq ol4L  [;XyD&\iڂJKL"}qZ}?UOۥyX,v<1 +0Cg¤϶Md 9Ņ^T/nst%5؋fb Չ-`(]%3$p.@& + ]ڀw٠RH0"wuPp @3rI{DP"}U0`WOp´ru+Mg@*4vS'_+iA܂hLi܉CJ-iʂO~mU#Tq6a{0 ` TJLWtGtw$bdSee 2O`LjNZ0I w64l {ӞN +S0ہ&1X)8t +Dnp8D+`aAoQm PYOgZIڀ3Jq> ,f݉RT\)4]kdhsucz7i_%.N?xv2R*e{WY},&ɠؼ#׃JTކ()d♺Z) gLQPSZ+/pO^Z]ʴv-eY^:ObTm:Ogz:zN~r_{P$sc(%ʏ?S:Q!n'vqZ]َ98BAf4˔f<{%hϧ԰⤬&lzP>` |?t),"hb}4@/O^_AºL9yT#jI/4<Q5lmGir.8v +X>ĝ8c=˩k+Nj^e{WjivlaE|TWv. me`xS4Ke7+.rW)U`΃;&swtzy]`vNP<ˋ͌qu]yWUV̪ºf `@/=_RELv-ҹ Øc: `Y{54̕_VHB+ ӈROzInw6IX4g!Za{ۍe#T)Bq,3KrkG` .k83s(v+mTbT(2a 〈P 8*< $ qL:G dhGYio7H96&Pj^^gk+8}iDp7 kAIڋ +$赠Z-O!? Q3 ieг&aw aԛ7B9ᇍkw1׻^Rd{|4߾R.u g DA<\2r`yԪ-+ߤ%l΋Ç-^d]ųVIf`!1'D{0J,wtlab0]<^"I{Jsz "F%:%M7w!$g%ɢ=8,ӀZI:*$0j `%X8 AWڣ}r6 Cz+d3ۿer{Oc6اZYwZOʳb*WVd_ۏ(a36Ǽ@{Fa{Zf wO8cjWN 0`OvUY*;Lej~^<Zg)*`<׀Qz]}=?2CQ`Pf|JGo7Y2~eЏUP; vx&rV#UzɆrz <\6` OoeroUi(\t'ICk,T;ݫl&Y`!t*^+X3v̌O~:Cey 34_ԙ=@ =6ug0ϣxv`:g_c/n'Fuz.M4*XB6f7,:ۊS@QΏi$_M6X[|@+Üϖ2#-?mi $s`Re8K16Z;J-jh?Iҙꆴnڊp9C|R(h*j;Bc9`l$D4vaa+VaQ+z2jW&JA&@J1 YN_$2àވgaԶS} +lނK^<哀gcF9ҥZQXCy; gj (˲.´ +Tf'At/0  M +lLI>;"YNC&T`XUU;XSkZm>8Ny[-8Q'= +ZȊL姴qQN~tv4l l'U|! +/!p'D@F`* 8Dˁݥha`/FŅ͓BV3j?j44 <@\I+O;bdීp63Rn^,|Hڍe}T1^+EiapV<10S=C2hiθvf)imKAV,j:F8tXh?Mrz=aw.!0+ڤYh.r)⣠O-\L]85!j0"Hi섉,ހpK@w: ?/ 6~f;Xu}'Ucψi jzZ0ʋ}rvu{y1 +c0gLwm0@w8 d:.Tv*zzLk'`>U@&ta`ػҊKzR#i&`T&[c!@RL>ﴲeQ +3R993I +P ŽD1c;^+-G1˃KUZ6Hv+ىfIi8$DRܨg+XIM<1Haii@<@^P1ў6?l| bٽxq/q(eW`}ى`Y=F iGܞrv؊dl5Zgd hOceVw]vit~uF'I8ͣ*׻hU*$FUvW& \6:3=TN=ɷ4oeWVvyo+XsR=3,ʮ-uv;5j-b"<^A$n%\@6 @zK ~y(gX= + p#Xy}h>Û*$2\" k Īe[!.bnf=I;ZqVh'YUG\Nʡ,*L: ,;p-0aˀ&rzqblI! .߹1Hze'Q1#Sfs0Kd] Y՝(3QD5{K>!šye '`O aOBlpm}( ݺV9}ח/ҸxS;niY|"0iwO]e4yJ*G&YX T`*8h֒A@˜vdfc*y.ÁH2~V&*+8J: ( 8uϋ՛vhԏ 82 xǺ7J35tq +ˋta(1Aq&M Ҥp֪`%^Z(iEv ~qwFܓh\k1[;,mi|>{cyz}<;'qaT9l /9N _J-+I:߱lЮ'wbU&" 6۠lʛ=WB6]uwVꝬW_j)| fAi'ഔ3n__54&ں4N 9TamUfg6U_8>_WVKNluOpg׏k˯kkw`V;JpyZw /hasX`q$b5ӫH8ʋl6{U_0je6R^}q`:'4ޔ^K䆙:<錟?S7m-:{Lc;y9zҜy+ 0޹ :X(U0\ +4c!g8ԽEix7y|:Q,VӆJwÛ^gY= +۠23P:Q8zvm Ȯ(8n,_vOn^gqM\Oo|?(,;gr_]\~?Ó}uPY=4aoGys&vci3HV[|wߟ'l29-On*ӻG)M4wk냔+AWVoI\u.~.OS'[g0/ uV/;w<@q7-[KZnlLQb:n_8|]U8)710ݙUa*(_%s}8f0ҙraD}ݳo,W}'H.I؝ܹg_wf9]׊-Y%Ho~7?FWc7zӻy7fum73+Oݝ\7u۟hթ7랼_ԿRquL-j,닇\88{㿖';y^߯^7K; 3-g'磌oVyt;{2߹w.;}~xU[AgV "g?/7ߞ/?fp}wg_~j,\V+g_>yzM.:VWo+7w^ypk`t\K+Or:>17;#TBJ +B9Ft΁l6EREeYql%K4,ʶeY|9{v_hZMֽ4xd#WSSgSԩ[&L)Y=):&3jJ+tuJT6 6>[T^.]\2}o9.M{W}U#3EGej":b踙+U69U^;&z<TLQў+6lөypU1X&խPtn͟ ^wxP\*,^,L򒑊pf̜+,_M7ksg;P>ب\kDگlܖ:ܡn8Y !3es Lv6X_5x#^`im06d/ z2R\j1!: e"S- +.xG(.xssJ6}xjifa~m +UX/N)^Pa>(Q(Hs'X]+[HD 3P ,ވ;SXP6Fx +.]Lk+S[abb3<+=̤\kG+bg" +n&ۑ{r=~gfB6ZZں?Qiw -.KFE ÞP"|fZj[\V66 fc900@$ +M%j˾6LIM[Q.Nl­`4%0T4Jso>OQ^+Pxl.޼쵧`ʍ%U2:w#Pޅ 3Ru-7{uOSڹk +@.UڍOL=ͥJZ,:ľѮPXNMolݙGK5;K|iElf)A]a]2FjR ]2b֎['GX}=ZK6 S@)f•puK,9ÕheayuS +U|bꜿA&ܡ=;s'tN"`hM''wFo7~8lswڍK7 q݀7CC@i9\[KϜvNReԍY'(-,6S+L|ҿr,uT B̗Mq@a^L59;J$` O90J+s*&>?`Q BnYz5ϛhjy3_4hag\|0]R\,I<@qjqO5 +&Ң#@~%UjޮݛI4 +sr33S'T~SA{ʸk$cfҖNŧޥ{Pcen{ײ70U靓J#Fz䁄(Aɗ2gx#y7{2@5. \*Lo,_vDm!PظG ֤9wV<¤x 3b6t;bmIԻu)@#]W6bTx~́Ms2l$C\f<77s&=EJܴT[uvCGmrGdligz*vA'Al\ܛpG%;8nvaykݛα0;Ƅ [E&:Lzv) ΎMBN/W=m"C;‚75ONz l{;X$-Ȫ&& Ze3TSwns +^iHفڹ _ݤRە17g&cU4Hf8rs /x3 ԾTtH1GK"!27o*),,d*zCrL$7PCͲKH' +3͕K|ne_d vT#,g0mnF-PV$R* I; +7O9`H,P M'P&t5 +Y=YXMefn +V&4f4N9iq(T{'؉u/9*Q=@1\^SF& kdlBJJ!*Bp&LB͓v`Uze[\ɴԌ. >Z6̬XNNzW/꩘Kȭ-&JDcK-$|4tm5Woddy8P9,dKvX'9U^l \ʽ0 +l +q?p|_03RUYJQ#)_  ,Lc<88q*1(6_vjNh5;>&3q  rMN.^2u:WHܡ4 +3B ē[<wmTn# O8GNec#JDJv P<&* +5 poaJ%;(0 zrlb:ZMc|Ni'\WXi A3.P%٬T?=s;nejqJ*y얙;qƟ'n_  o-dB%P&*;whP5%PCgq{'7²1x9Or^̭fJ (XP* y!HbeJ&F5wbaE0HETezsD<"zle`Ҧ/*hM-:iY-"%0#XG G-BS*6b$@ Э();B5*abd@Jċ EGHc&ҟJ tj!4iP/%u TCj;˔WX 3B %xbLmLtBna&‚$C{&ή_9ʱ1QPh Twߓb>´`6>f@MHΈY'AA;;3ɵve%$= GG4˛YپOte\/"8!`> JOjPZg\,VڤT:͵3 D 07)HFEFY>/Kl f\l ںP}u_,u\sr'd(7i{"aFI*4n%djFOq_D,vDBT H{ bs V0iVFfrZ%;/l"(;'тq1P!ISKm2YҸ|dNG;FgtH+L&rL(.]4P1qe%2揌nJh:$;2`>3Sj焬a 9*^N$7qLf;!w( +ftԈʮRDס*$%ks/ݷ|[󋧮MOG~TbujzakԅsWzW_|??Ͽ|?y7/FkjL#O*ޘN*텍W.߼SW_#Ͽ?GƏ_?~yח{Hebgfsn3=ҫo+˷??A~?q:g}R"]lL.kn}g==w}'_|~ȳl_/pq9;#PiY 6#s}o~{~>ٯ?ׯ?;oۼpy6tYOVsι=x }'}_~|_ _}+?ӣנ9fpBEI16gVO]+=|ǿ}'w>?/?>7/ dlc:a!$Sօ|ɏ~>}O=D./?}HbA>XHg͹B7sʝGO>_}k߿aCU+qZ?/Xw?Ͼ͟;M>^u +)s{\5{zo>;G?>Ï?zr;Y0Rٗ D&WYX^C8~͗__~>x嗟{ՅӗP +XycJg99O=Ͻ˿?嗟~Ko}2%-&Biu$"Yrͅۏ=K>[?{//?{???~}Wwb@sa>E)1 fbwv/>/׏_o>?{?vVg*.NQ٣6 6RA[l6~z77~_{{࣏y WH-VY\.TcLub|cjbni[wn\z~ܙX6Ay+Z =B15"ӢV|D<_,5*Jgv{[.&gX)=ӟWZd'vYݼ8r*Ӊٽ}#oO>>_d*BtE=L`eTm2Q5ԩSO??~Ï?{'oW_~ŧxזW7r)2;j;\j1A|,^_W_~7|~w?>p\ZF=~x[))gfΝ9<̓{__|_'?Ke{ǴġQq1Twvn3.^z˯=^y;ݼN-.T(CP0a endstream endobj 80 0 obj <>stream +Ŕq뷟z慇֥+7}?yyv/.`f.v/-\p,vcO>>s콧wAQZq >2kL4IZLR|}1bX5.%7f ㇎-kvxuVʊqفcY_(:1[u195@ #cq̈́2Za@(SKDЛ[,d\ NlT̀FU2$3 G. #L" FrhT"R-2\QoKxNk99`Xa;2::kw#Dx1!ERX}:Ib(FB6UO)J +X.h32qLio`坾㠢w'"$5"ةN*FJdgUfBf t 1*36c@P;eu_RGN+|BaڀȨXWz7> )cz\mGԈ`ۛPQ'axqxZŃ#::e +TerPf1nH8` +LM6# +LSF&X\p5zV gFT8d:NhøQx!̀brF5u*x=Ѧ=)3Qb 7GC?1f6FW%mLNC"PWCH7Oy&wf3dGNLJlA9ͣ + +iN2;C*A+tKM1ac& OOFFMk`Lspa+>0\_Zp\|"6r(!C wed$rZJMΰ >+GradïV-v`4cbZftk~ufKaqie26:A=R +ȐvH:b2s̜1zFm>T;}\(<66s0 0FU[F4 +&CxRC'H_kOQىau%[<4l鉻NGԨŢW + lq(LQQ'EKkA3*\lzpʁBvHС+P8snPTV>*+Ru- +N㡖#{zۅi0|r2#FC}e2a&Sw`;z䊚\M|)hO&K@EG娠 A +dhNt +d4AK׻AM|F #z;֩@*2 2\O1*Ti崈WG(lQqM( hՄ9WqKu\(ZY8ưKA7XW,ɍ$N$׏+O[6` Yd7&k,. KOKxKzs& P͈K'm#*B,8W*if\F԰QcFLά>+abf pHmߋ& ɨ %>хa8=1R MZt Tc~ē4q+ +yW"r/Iwғ9;OmvKFܧq }Lmdef v?LpyKN+gҨ?i%3jV&R/|絟,-1̇YB`q-b9ZY8JJ`;❋lzNzgC-28!RISv4wEOMMGMF=9 Tc`\VczfL7=! X _vIhuM,.青P  +`E(%˓JƮFy2TDŽR=<4?6n9Olcz + v>r#@|E\e+ +`tǜ[,rJǸq@bBh &>+;%;V>ME;_@<&TщNVd b:L؃ro192Rz|\c0q+0GHFR+,9:)|G <6h1uxH>l奈IZgXMu`ibm.#BMJyʍg +gJ׿nuB 2 +=nvef+xTW,. +y %'6o.d`wťtk۟ٹƆv U䌣cst +zQ>Kvϧqy'qEByB*[5|Z\G5Lcbm)6\:jpLɂٝ/ ÎLNWfV?o&+SԘK+N[\8X9 e%%ܟ5Pf3313=wA|*įo֓ tvIG%u-BƦ6rPM*-Q΃LIx(XҢ0&.'T+ԉ6v5HGFLz" v{ F'raN$jIfvpsTCrq dq-!7vOv6kuEuֵG^ Beٻe"uK|fldۻTYz6@ uyh~9n_*X!8^p"2Rg]_qMPbܽB_Xp}#T[f4%d=>-2 [:Lv߰`:Brfco{@q@NĚ勻W0Ki֐jD$$.i0 +eƭM+ً+v&oEkZhR|G'&Q_)T^MwP +9>_a D5@ dܒ¦fdS<.ԘKT/ZP}颍Odsg?OOes{z~6ғA-R )0ҿn9DHtȘeL6A; .ʠ!T}~ 2X1Ac$4V0?39l 4bب3XLjQ>d`\Bؼywt +|dc`+t 6L2 9>%rH9].wİrJ([76?5}0wNXย_ 5xxJN+AB]'8zRw (V_ͯy kB~LhQkzT<2GOO1?B9`m~_qBW_YZm{KDqBѡݓٹ>K;f u?DXe79 FO>gؿ;Ƨ=6q.jfvSCՅ…YRFlmf& %1C0p#Pbe- w +I03VwJOp?;~/1#eEԊַ{_{6=sJwBPߘ>"z<NuHɁPr ӧ=૫_ +CFg5Q"lq&_mDAG`S۹κdS=_p2:s%F QwWT146G~xD3ܱ)ŃN90zb\OMA2!y`83CV3<-"|Fi"MC@MOdRfTfUio  ZI%: "ެ3X!C%oA¹wvO{pӘ~;_v)ٯ]56 qǩ\Qې tCCu +(4PPqg K\ViFKkY)PM^2>.wσ6OP߄$F N@GoN/z JLzSRx*gz bn TցA5a~̪BA<)'$Fר5X{}'{אلxL:UEK[1ˑJϷ 䈑 +7y*:t +8PvPnBG,l/-^zB Guv +(uwä첉Ih~aZ eBҁ3uRytX{hH;Chqv/ߋ4gHђZH"'(G'54[2QؤJB/I#L +1,xH㒛y=*X6:˄d:.Gʋlw T6a.ޑ*`szV,3:K(8԰luP2a~U\mcp˛ Wkkʟ\$'Aƍ;*Gq~Rគ[ѻ55I056VdXn@zv^ ř);J+ nm!LRefG5NGF  R4Q_/[9I7V I)0qTsl`ckcF]ÖQ ׺m:ĊPZ4Oxr0J8BU."|2Ms̗11O/ +JEJ;oBhPC*;T,7z.@z1Ɇ0 O<=p%X!ٙlιĒJWX2b7T6b܀QBMA`1=qc;G4رQCmi쟡:gRJoruwwZ=bu@S6Q/ +Q:F"CuZ+?:-jpTfZci !Q!/sx4C(ӡJr>Xr3E_b +4P&=nJ87 Fu a@lmjauv!͜n#dK:Q/Ҹ;n{> vz@[\Jk3.{啍KON :* ̌i8Q1q@Nv9Yg.<~W3!LXujN4-f@/ʌ٣#Co蠴dzqdxxP;((!`-n̟2JԫsDJ’T\%5Vj4qri&B`Jw#ƓV3p}CJ1&k*3c6H +e1o&p3!.*Q!ހr&\:k`w p;6j >62KESuczF}ե{zBn')=.a@C-~+F2%|r u׀ +^'6K +sp/s9ˊ; +sGV/>}S\$t\NG' +=!t xHֺT&\ɀsH.ΝV<XXO u&|zC&nڽ621>:u剙mfWӥJEMF7=yD&##T&fXi9>(;\Pids ʾ77oRA>kbe`׸֭ +BN[tGe(%3iam`̌v:_?2#'6C)Rbq5Jăi"XcSb{.Lz!3B=>=)NY_͛bgņtEKV&aun #*Dma-F0# +tL| ^Sqݵ39'#"G%uwm˧a3lf {_Y2UMCa fIψh$HH+iYu_<8Չ4/'?dgJwP!*VM=PRfX}p&9+$' L$ .:lLIހ.[G'; 4sپ\^ъ÷>u6[;C!;Ƨbub`!HA.~9S&$1[;ÀZs &ra:ۈ6=\TL-B{~>KkU\,NLq1]cIDS!8yi=b͘FFZP0SBXk7?j[>xZZg볗7deX,`RK&:@7[=Sm l#3Hx]>}l];'2JT:[:@~.oow0)g.2" l@f_,KOړRf؊7^Skte%"Dǫ΀}{. &8I;>a3V_hԄ耾]¤%Y>٪n6<}Xn-p!*f`&p +!/Jf y`y҂/84!ijF3ag=dR#U'&qIqq妝RR^.A8P +ކ}؄$p |z߹ XS$gmH _p~x]Jq˅;oqTS.2C]6|iyQRL$fza}09JXWr[ļR\j`Ί*NP}PՄh VX0B1vը>g$ 1NƜPDO(Fz}džiZsA +2=&mCD#b0԰˅ǀt6}?qL +h LmX Bm.hwnv 2V{T9gP<8 8;uvsXpYn_<~cˏx`2V]N]RR.$.\crNOZ /YG]fm&;icϦ72DOM.޳kAZkޚ jcGB/cg+>K\Kv+'^zv~h8^Å̈:5Gm;m;6xˠ_V<ƜuHMcy_FB-g;ֆUKjiT+Xuyv{I"A+ KNf WwE c0+$xrӗo>/Mm,˫ͤsսH0b,R\oƚl >| +k ؉蠰b=W -Uz*KEThyP8]10y~vP9 h-.:e6< cAMM +LqpDwW)cW Z8|ɋ*D`.gp&'>0}esaƦFlؿ:5ʨ{؈L(_v#p ƻK7>/Pdcy}oV˳x/R;_Tqh}C-b}{ 1d_uyՅ Bb ܌߹}m!ߍA{Zu8{G[1Ɏ n+p&!i:1 ⨓1O0kEg$g2 +܎\OrW*ׁBoXXJʝk/f^JtDZGq".B| %@$5_0F`s X`YLbEPGN <B)J!V[ܐB_ܿCNyj{%չ7XEa,= 6t;rq5=6.~k;[ ݭ;[!_\ ޏkcn1߄;DGg?X8;^[`B-hXħgiO~XˆH^^mܾtBK&9=b7gO]7>ǀJQq+54inf.4 sqR$i9 գwuP/n?qc>isseDB(8wN8a^+%CIEWnxv;Tr}MϢjm09ZLJ cd3Zs`VJZ%T*C<ĥM0۬ziEJsQcQ~zVD}z~(;-͇Jc' + ֩,4 (e&A6R#E(-ׁSc^/he4͐4a#h݁vэ߻ZO%;BBN v3턏+B8a.Fm  (`<#d(sFWoNZ^*\~1Xe:ə'+􀭌NGG] h@ brы+w_\CsSW:pQ+aR%5&|.)BҾfG䗇V\~\ZN"Bi-19Jlb)z: ė}lO'0]AHg;u2b\A+&1#yrzuV =C*R~.\XY9P})׻mnS)+jZ + #9m3x9T +'a# NP N +q' bPi.e:[s:[OV^/ɹ^*§J+V򱆏jDc%|IJQj׋z'Wt0ѭjXn1qfDJ>-\}79u$k#N`+d'b>.iΨJgr j)%{@GB R6R5$&㒗M0zigA`ǭF , Ccx(N$:W/s`@)e +DK0"dM_ f]}FFܧ]u8dB:flKGV7xEVú9"ùy!qJDf Z^I.#|Ž\#%?7f?;jh 鴏LL2\0\HhsN19$޼qI'JJqU)oz^*("\@fmsIV@("I5lfPN܉ȆH44 >ʅLqz9ӚQmZ/\'=C֝՛`$Y9Ӛ^<+mތVb tPX:t*,TBDRwQm!=M[}пt'ʆ־RXzv ysN&< &(¼zF\츏7Ĕʝ;8[HWxm dkoforkoF + F\F\V/,4n>9*}.8{NDrÓwT9dr1Lć kw^ΙxҐϳ`;'":͌. ˃KHmebL#VS;\=?JL`ո*m`"1'uI`_E' ^Q +r~&5?js~vXXsvaԢ XY\?b,h(q`C2C FP-@ezY0RxCT Ǫj 1OPbqQ(VSM>vlNIi$?)O8 [vȍ ND"&Rq,vaw@:xĪbw3+֦i© q\4c 9?sX$dW^%.,k7buo@Ndj77+b B)s/^  d(>#ehQbw @ D(=Ps@!&慙饃 ເd?ÒBn܂j*n{F/wj3de/ɥu9 ޗ7fBO940ju7|Dюa*'jnLct>/?-y"De `\ +f6o`58lN(@sV#\Lo];~>Sr6u[L3N*c0~B &nvLcSh p1BrU3*9IopF #q@xh?lDh|l`C\LQ51Fe15@|}9Q3Y6XqـX4iqsB4F-Ir,V8afLr>&Q`L^?=<'{p"e>~-`3aA&m8"$0 n*np|Ou-Q +)g`Ӽ #F;JpQ-ݰyqqa d:#80Ln<26p&}t VDBqq60\qM|I^>c7 v4 t܉+>20b3Nӹ±ͺ"NqÌ-d\LQFAhv3~R 2΅cfgH&Aȧ갘 qB|n=ZNT3澘^K8)u8 K UMPHH=|߆FD/~ +!&mYa NhC88xxp>VLO8DrHrኘRrk^B'FttmI?w1+,&`kKv\/,=?IX؍G&]A);.Xtx9_8$SǬ~xҚ Y]惁Mf!o@Q̏0`tG~:u<QQۘD>vGDSs3X=cf/Pӑt}YJbȔN/aWcHnu@ R" Bkq&-N9\;E볆s@aPR:[1x>38j~ eh0˅1,EKG_zy`!`c6g#IMɑ,+e@H;<4െ'/2yȘh1ZwAkh>fLSݘntg/Z^9?I>\:7lLZq@I?*Ac>l@< !(@)Mƕbgh d&E~&hqV?j8ZE%I\&> NhxYpNG= mvvz„ DgXr4b1;E>svىQ[ Fe\LK<Ñh&Kkj#N k= ;xԘS]V~gs'O`y:F08:mf9/ϪK+yݸu[o}720l4ƌ."8xI,Cufǟ\ʽ`o8/>7?~7׎U~_Օ) FAQKg. Xo4HDYPXҞ|ɭyӯ>xf&us;J)8P0PQA7VxPWOO˿g߿_?٧׶g|' N y-2i릉zw=ݫo~~ʟ~\ه߽S]XE51X( +H#٫}֯zfD'NG!걛NXx'؟O-ֻlA狏{Ϯ=}pSS#6XABǖyzɽϟ_~FOϿo/ (G ޼NK-hV~/>W>}}돮{~y\:$)~"$$ of9.}|_^_<ǟ생O\.[@0[Fl,^|do?kǟՋ7ww~b+yMFF6ǃ$J˲$Z;ح裃zw˿/'OVwJϵQFE_}|ᄐ>sg_7߼Ϯ}vf+TAZNqr֌zwyd/~x?o>>{tŕ <FᰚVf dCs[;?'߻/o_x7_G;7/7?{AN).Xb0O)9 v7|cY9П>{9O_7W]_G {1Xv5d&Kvć;O}bo?w-/M!"fX14 2KX=>ڇz?z}]KՍ~+'"T5DZ񍎾==u\{{w?}+OOv*ז3sp> aqJgr[O,}y~O?y/?/Nӝ,{F DT>XQMiГ³+?Zo???ǿᝏ0J0B)><9V|-Z"ݘwJZN==6n߽g~ɝϞnar/1% +"pBdF0^**P{V`poڕksm5FxM@GG8< +`$O$>!RTR' gdwO֣w甓l.#v6i^ qE̙BpAYd?O??Ovz6Lr!=D QΪT=-);|f?}~sxDӘnJMK \-_vvxk`޻ҎVR*"/G'p>RZ*j,! ˨LkL+oո F.bAT܋,b\<S wgzq~O;/,U^x/"^\1 OEb[K׿|v˷<>z DE JvBEKL)"՘ȄfZǥN%w{B 2A6gG|CA\Nih4QX"q{嚀~ dZ g`Ӆd0MuW꽼Ʌ,әvr>/.^&8|vdžGn3Dzɫ8k~.??;q}VkUPp̥G0x R$-pA`P粩ׂqBPfyOrv ^'FĒ!3,@DR`mslN&.bԂ ' g%h)SA> MXVVgͅr'5^ pBNO9p;TfE ã&?^ BT"T-3WXjFgJ WZZSlv顉I`my屢!3cϥT$21ַ\O\~pcr\TylāvLw3Nhr¥>pXHX!Z +v+Gƽg/:֌^杨Jڝ7f3z SCH 3 HZ\,'cR ƻO;gE0!"%U!\A$B2üы|PB(?n ٜcf/;G/{< ϫp Fx`O``FL05n(lw'/QKVVV(˄"{f1bpI0*|lS۸ZNz(MM>э8i6L:.lƎ(6T@"mQ'=];er(Zc|8^Ÿ(x)朸&X$)Xի##3Ò +usDCqJ.HɎ1DCۤ r)7̪NW\/\ʐjeGeГ&#neX 6d<a,b4#:52h@T +0_2B!"ް5:!lXLe02Nf1YF$mJRNảXc3ؤls eSૃYT k|v[85L}jPbyS)͟rX\섍Y E%ȔYc9:nJsWLvLZq7&Rb#I<~͍9 OȂ&D\fJ#Qvj 1f'r0.O"A#C)&rI^{ kTʵw+k\(Gz^.kʼntלdPL+uRC53"0 +h[LԪm9J.iɵKBy#[`bmLgp`tfMI%D,Z1OĪ 9"| P4vQ1Ppsaxրh. /h#XCy*3dLH@*V,] +yP +岛: Ge;rDe+谅9L̛[ٯqvq?Q)Ao &Ϙ`٥H0\>Ħ-4!c2C 917oK.B+|fIj3I'h E;dS^XE bV/˪e:D] +VqGȍ6LXd Yh39o큈_*zL$$ 6BM94P`p..$`AgJˈdĦ<` hF,s/$~6f#F,3Kg'{bĦ.R$ ;lj.1u|mn{᪑L;F=lڮܼLD꬚}\":QLXX3}֥Aۨ:ss9Z{E'KzR}iᱞ~mnaJbfvp-?n?}'}k-ăUzJ9mT h}/Uj'DB- 56LgAWL}PpDKc$6a hG$:+_8ZZS.N̈3Lj9T&X>k/Y \(VқTݸOK8$cZ;ڿ_{I'g'!I).uupg' ~n(<(1f(8d:k=8džHfD15q8knnt}Kv1 +.*PQZtur/fTTXcU0OEkDr(ǔ?\ :Rs^0tIt4$1}P&{@zj4%Jspzo*Dɩ ]F[_&ƀ7^zF~^_wREtK[I-dۍ'5qrɦts.㑮[ +gTȴ\It,d,|ƽ@ںXTe7OO#D+&J+?꧍db3Z_pc B|-:n87 +-[[}5?.aZe&X!V >]~ni 66O&5l +[[w$|zӉ$ռLb5=ϟ5QILm^JѨ>k@!pRXKW\鼅RW/]0= W[AtJL`Ɉ(>c#6"jS(9^gUF,mtֱpk|z&Lw/ +.*K{EHmPAai¦f#Ϲ(vju/޻u,Zb~FilrFl6>[naXH7JzRي5+g^\k6NL9'_\z W)\ajBDǁbS#l/jkw;+>9ELJGzscOO jTZ#m9ϛ1$:R(,mlhyT!gzV\Pv!4`n^,me"6ٛU*1&f@ }XTcM>/.߉ux֝`AƄLf(=s9LL_;.\DwX^>).IgOp󢍃C9 *ӳ\vN9#iCuY_>k7gH"R=4Y5b_OrW\l,NOi[O™/(+Ť`Lk X(洞ig@j^;n=JMq)"`_vJ#M݌4T\&j"MNk;bm#FuvzsY+fWӔ\j{ +ˇhm>?u.jzc6B5c_*peN-@BY2=`*^kW_WOΣ Z +"NQe\E&.foY=v$앪RsF=z5-/,>ZeK(sw+Gzg+^[[X` \cJwVqUru Q{v W˽}/X ~aCĪ^,~ j6\?g +| +&P&@$Ay/g!4O0CXs..PJL5@pU">ʄpZ~s5뺃1ɹtK*%$Lo?jl_C#5;f4WhNC-k%T.z(Mդd%Z p k^Pox;]rRntmD˅KB~IIО? +fӱHH,o+c2 hͩze 8/ҳtOn]}!/G_Ͽ$Su +XW ɓ7./~nL.m؃f +lX_{'/~[UU6~-4zW`_[?(]ڝw6_GZ'"ŷUc/ԏmۧ߄;?/7b@i_oNnngQs>:2RvW>g7l|J fjS&z(~}{֞f Y;8zΚld6>|'AxRV^(CY&/7`V1nv8o.4OqwG`:= ~]iҙB +Ip-3׺Q-uz9wWwé7̑*6 Ӓj+Ts!n \@Ss8۟ +T:;j/_CEi3Vpg_U{MFF4p'G/"zsduV檹]?~hy37gy( ;?yћnKB7Y?.I}TMV[gjM*FӋo@"zU`u[{^J HY팯o״;:3u[z xzUg Qkmmꋢb>]|Y3q f a0~2:r;951_Xm"\fnJ4=A˺#5W?njsx]!RTms3F%:8|͟V (s hfbeooavSؐV[)yt$V&iHuQӨ6s߲PPk6b .)ol5`,-K{ۧ}{Vޠz]f_y,̦E.@‡pÛ";ba !`e.a\{%u&bttNj'8^Zí (]Ic*:iEò2J#ꞀBKb8z9*p`{E2gW0Hs^XnB@h3Bx?|])=8| <XRi]ryL]~Y"BT!ZyOy*?LCV h̅AmF7Vwte#/3c;1&a2y9>Mr S)8~K#JczQ(YB8*_ckLlՐy)" 7svsk:<"iYp]ƨ*7Y +.!?y>o9 +.s>;K~  OY={7MsmKI3>ZVڥyJ™ݽxb4G)H! :i.4gR)*|c$~DYÔ.7;x"ᴖBODEMUۜ]/%$OTF)^AFUbN>>y?%hVѾ M_ˍ(y(3e5isd !I/8e>\v KXw5VϕAꇃW?#:M.ϲ)#uDh-w7Wߋ3#b4F|F2g1pC%Z}AӸ=rF/[vNDkơj>Ɲcoz/`n3A?5Y Y_;ܥI4}X=\4/ǯ;Bm]%Qkzז D,nppmĸdr;Ej%IXB^|?Iֻ/}]5޴{:F@d}N#JQQ̱fL$=R3[sjJ*nRQ6[cEsj퟼}匮@%R@Aí~xoG@NtjMiXWB9vxhPR4'66AKJKkl6~w?$J4Lʇ+uwfWoZL UA;o)ks^fAͥx,zEnٓ*`Hk U =/TvUĘ<8j)ITⴏJ m_z{_Pd{y^>Ѓ]yޑTv։[ G`U!L2mI@iA%Ppf1*dDuafXymghǵK{xS[%xOEyKzM4fυ5Ərb,%UDIL#V?[g+ʟ,PZc'bTw͓F㠀Q{?|n;nQI>j΅֍ݻczw/xi +AcJ2j}i4j4.x+9 Oƚ2:g +vu@up ڊ0R6WRҟs4K8OPCa%N_;HP^5HΔh oZGKn`0b"!hW@q "]JzMoKm sGN.ah@m]+ai!z6lxwƷI|e2 ]۸ ;7\_R meph_;cJo'ŽZk?Nn! )4ǻU 0m!X!HUͪǑDE&<P`,g_5gUf0!…nEs|uN7îdSTI0J٪`6;bFUd(R=L p!Mbg+du@ WdgRbrƛcvAu}.{Ydb-ћ3ě~} +.piO8яUT9mu({#1\LjO fj7Y"`+B-6eb j}mwNA-Ǭ1 hTJ1pV Ȟr/- +1V5Ja+,U)ϐpSzĄ o(EL +8kX|BDڽjLjO(.LiUņѾ𧯽?73dEGئӿ ϋl}$)'GXeM_ ۗ c0ime#JQ @Vf2; D}P3 +( +ɒRueڑk-ʿ)iۍ5nt!I)(I|SWӋҘ'QGE&K9_J#Kpwѡ))(a}yi>e'2<%&D5t R>N_7I`8O0`T@ETBR-wΞ5V/1ZěiAlH6 bCB*9z M] q\lFVN - c3Tr'vbo (wqev!ܣMI\Y"abx:#LHxqz}6y{eAsl>+x0ɸ`J#"W))!ٺH#͌HM=I$r lnKX2 i^hcV =387IJJ@@a[&6„ƉU?bNX^`{YfU!LH`t+'dD07!JʣTzZ1 nN]URiae \ѹfRl|K Tr+b0GvID [(ᒳF%2H%f%x5fMLBּĴa0N[%o/rDnjeB" tD=|Ԁ2KELWŤj|MA:w8]_t^W iUգ1jU!Js +wFrƤ@i0z%tu4OYy5 3cƦ,a # +Yr1$#AtQjxj,=|;" )ʜ QҘ138}?rz[P>nv +u2Wš)S+l@*, aUR\FN& +Ά&< ww~^(ރ$ IYgoճ$SnxB|=kkΝ&mt>j'(J9Z=ۿvIh=5j5TnW:\(p9 ΝLJłN0Tki]#=TpJ} \D=o|ÇpNِ|ǺC +F6Zv㏟ J##y'S΢B4谹~GY$Qۂɣjp)Eֻȍd\d]Z`Ty P6rˇ w] (m-]DO^S7z\ŝ_c%Q$,qx_@phSF p1`ڔ!͟zwNu)8!)# HIT\Q@ŕ!> +L.e.%P 0R+j6U\ABy9Bm^{Ba*.:m_!!2' +|mt/~]*`9oQ렙@ ֜~v +Th $C]\|8CARX/&5| A|R (cA[KC(!_' FdIm6Z%tp^2 LiE l S,a-Ф@Ũć> iv/aDɒ7q #_ -r?+ + [iMTmņX;RJMB.J.h15U*gC!R b9=—Sꀏ.5)y,i`Zbm ZDɲg2 +_϶%glcwu(?РLJl:2Ɯ^Iǰ(Cb^T2g:R,Rm>E"8{d6fsi4aYwKNIC.`7Ai+q,cZ(!AQ'q{-CpOsu^'iڀ<`jgLpH+XeƲЀIG4p܂,:$l\T.Bdm.ޭ^2$ނnϹڦ +/အƤ6t0y(gRFT~$ M^g|pX@Yg %4goueBZ[!]jb 6gX/M[7UZZWb,τd>嚐 =`o ݔ^b\X@pğ!N0҇YSjGE}U`[]op~C8\5΁1P3hx>< oGߗNUaJ?My[1YN~59XON|\C`ԪC>:(:`:@AT˪ԑsj쳇?zRL%ԎJmRQd@ Lqwf ̂( +EDY379 W @秪0:]zܗ5e\(YwU__QU;&菭AkU kZmM(pF +eVj@Vb&գ;gD IJ%\6v "f1IULe0(9 ErI"؈ I}w +_ 5[a`oS r&@.yR+Ӹ첳.4I!4f=Hy҅(= G)J{"6tqO!`=xsX?gI‚HĦ=6QuizTR}}팟ɝ3p4 dw]U$QZpg# P"XøBt") ~}'W 'ϴ)C67s0QJ>״5Ad&T@oC#5??I +WXƝ2rAcF^ o! [kvyY$,@ nLW5Lg"Zȩ.5"xPQ;>,˭^Y~#H(W3{q,[O׮4!K3SFr=| >AfH~U_pw*vZCJkp-B|yhɊAtը+yU$rL _U;T;W3.Fo$أezzJ,q9/9]0| 7JR?'>,D +/1V;)?ś |WWPDH1w7frfhY[SƠ"rui.H_nƌ4Fuc¼a oeE$1,jx+r}tgBAT[C68k׬)s>-WQa!Xr#[ Wh^n!'UW } +S%GYr zaPnaQAFfw3WZU /ǍٿhnkJO\XCڙ0<[%p^6@ i죊:[>_$0 TDpdo/185굣\)sYltnކs MD]s4 \AG]%BHޚF9.]<ܭz6foyvwN:|7),V^bpW1h{v߷~C8 y1g_`{2)La.H(FaDzF~E惡26.8 ~\ qs->4~л7 Ta-T]JBO;1:)))̊9ym>aW5RngIQ1e6ۏK[%qa+>,P_u8KQ0գR8a#'.ca,pm`[E?EFQXTJ'BZd#!"&\<bɝTaƹ;}mow b5e)k\Yjrp pEbl ]F\q'HܯT)׍`FS[c :99FX0{WM7yyw^䮵ܵv?r@Z]kk~ w䮵ܵv?r@Z]kk~ w䮵ܵv?r@Z]kk~ w䮵ܵv?r@Z]kk~ w䮵ܵv?r@Z]kk~ w䮵ܵv?r@Z]kk~ w䮵ܵv??m3iz2W&WO'~4Z\|}?*WdrtJUO/V'`m69ZrT+]\_J xTdro}|t B4IiK7/OVpǂ_6VnyhA׏?2{RTfH'8?DP25BJea5VzZ?vgV!'m󿨈,iSZVEh k*]-hkLf('C4^Eʡ&kh Ҟִi K{Ef/OPj3&ܐjbM)0ΠXg)GGZ3esD !a QQnonPΧz 9g`4e{VOZUm*SĜa%a4娍{L])sD(zg}T/(QW"4etcUE.s6.JR/Img)G=Nzh}SLf0'he۽w,1>eQ`v򤗣\cƤ+Jђ[+5B_Cd<fI7K81ipj~ad_˴sID.N,f3W:(a*j7G;9&eu'/+Cʜ9ybҨ\dk5k;Izo#L׸$uҕõʔ+\f/E6$)e0."E<.zD9U}ҋ z tU)!cq 8pzS"pUOQmcL\6V7x\,6Oygjmf\Hk,9mfF%?C;S:W{s`uPKbjQsZj0y+1c..I:[9v'ǵa6vYFofQfc!TɸlӸɲY1=٪?!R y +qv}$(z1+ag--OE&J"oD  liD"y>O?ݯlg2`rW6zE- + 3!҂E SŌmWC~7%8OeYoWY8(~UFMHޟsΤGߘ~Y7J*4ޭ}R&JHsDlFkVKƚHKpV-z=G/h]\nKq<])*A +^YpCNm̷P)C=`j#zE!7ǿ֯* >ђVUs"kwNqgꝧ:hoUVUcćS0ZvnY- qTE{"RA$a.dvQ"_NYyfMvJY>Lϑ6Sn5N 9 ,<0EmeGY:Ye͸"&ԎkʱSCD RgqR OOP$/ ,pG>N*{0XXТ<*!E{&SRf"RBTd5,< [/ +ȟ8,l\[,pذ,ԉnɼ(v*~U 9S)\3>+Z$Q_`tUp\ƊޣgWh:s.m=D)1u^TnYd'P#EX?LG4ڔuHX_jUE=fܾG%4O!包`9stpcxȭn&P  " +ﮝ+$fB4x:%)s )^^YJi=%a2^E.;E*xx;O%8SJiDK!~Aqʯd΋E%#cE1K>J~LTd8&aXkLu!l - -LǁGh DC+lDR~I y"i>!up%{S面{e%eK9J\Vi<ƽ2{E%Uu!\jH2AA$-qmT;0ѠaӘ80M䄝:*R(Cryڊ 3q=MU`"W%9 + *hlQlEUvIxP%\5w!hv%8<qEI<0ڧ֯ȝv!SМ69٧nt(}1^sY2$]6o:'o bDX#_XҞrᦪ Aep8E@}W:lo' MGc֙Q\oD'7ϱtP%䩶s6X'_18XAU!9(v@Td@,%H:qk +8a [w \l!ݽ yވS+CT7ɑ< DY`FUh >)}#K[vRpU};>L`Y+(VN@AUԸH/H{5 D/B A]1Q%?ObA2Bp'!?zuA#b"vJl(I +0AVbN-!$߀=x̿ !X_͟aZ; ?x{Zq98q/ +@7J:F//_7"):O1Q^hV<7zO#rGi L,K" pyˊ%!Pg̓RL_EЄ'SSjFqieU (DhTCƛ +"0ysδ +RKi[`ƸY%vnӤ\Y ;*ӊ>W lD#DjY @ZdbpTUQP/ U7f*M9)1^k o`(ZkA0ErJLw&rp`u&$T \{/bd̃ Y +eGhg `NQ? `FB-0:Ġ*+Tj:(^J`sYaGXqX$&+ڵ!`ڃ4 omDT3Ntx%ʋ.Ne0>OiTQ\0^Y-3<-%϶%F}܆(IJ(?Jbgi|,aR 0' JyV/b' D0e&LGIb(cIQ,b7F\M(D{,=?LTzid˜lB(=W +I +Oct~a uUue%HDGuiV.4UdUCq$Ekѯ(]ܜfxgyQh`Jt8;YdZ%ֻ.4_$kѷJ2X6X~B ?k*ѱݽ^ս%nwQ RٛhM՚RE>H y2P}#fLy>jB%1 c.a47[&MnO@`X"e:#3z+fdsHLbs$dsço[P_ 0d[q\ h(V:\V $ + Z!Q 7Z77a*[@F|s!^ +DsN8,mxU.,@m@T `C50N΁rLL?A)Mب w06|ZyԨ59pp9SW؂ibjRÓ.`Z_;6&FnJCPavXXM)pn6$o͈=J6BK*q/"@1 n:I%lx̊ED51B*ʅe4  n$ ͌#w`@-ZߤSfods+[#Fmk" Z8ӂׁpI|7DHVix԰ExdN! Lc Pσ`F6!!|^LC1 6aDHh&>PfRsi="byOL[̄.4zA; u'- css5bLúM:e_>w4a;waڌP;f%A\Pu@DU_4 aHdTrysภmuawBkz2z +Є Z-3%6a + +4a>W*쏌[C˘Uxg>ibDv &;x`7b&Œ8/rU.yʌZZX( +Z5MX܄ltO+\nFtC`#oxň#ҁB뼂K|/UZ䐕rr9>ƴe&'ῌLulM2HqNوB%qz" ؈[XȘ}]k dhpъQtOʘ;ŐT7;83r> N" z&p/C._$Nh𠦁tH:_Jd\L ~Ih +#V`!BvP#q)2ց7mޠO 1EK@c<< av" +tM13ntfpc(P\ vnlYZ尙2@ְ7{!ٸ1sBtF!t"g-#vӸG`tNaB FM:1 .29`AgA t0i9ݷwxԢrn;tB!9ui/ +jy< P`jv̳ Lz1.d!^:-X,A uN-D UBBDUN6d!츚94x#Tt.^nHR̃@N B2 fp@s @V88VۅG]`H`l' W/5"{+0 t:ÍG}l5 N*14>0538@ lSfk8[t#?㫇t:l7'6jeؐigSTI;b`;X&X7nuPNцDXW P22᝴ttZﰙ 0BX}AL_.(ftL=Uհu脍2wYu39s+~xDet.*FdPz6,. V>")#`/H`KP&=a+>b%bјGڅٯU;10jgG(.W ȍSc vNP$N +Y417Z^`@CFb I\pa + 9v"&'#&y:6+W1!#HUNcCFl˜!lXZ +cD1 "RA N6AFR(5~yNM8F!J +[c`mT Ր7d$PlPy]xat9nB5DS2cMv`D: [`F #F?Dcq#jp~Vzg8CfwΉFh +tȄC~ejav CȈh4$b7X>?r@ 9ŒY PAj'4ꄰ +8 荍xȧF2*'=Ahg'l)6! lT#mM`MTB>4ŀLxȿ' KBOйƬ 5Z[jH !B%X 㘐;`c HD ~0KEDFLZ + bI0a3aδK`MMD3 u؈ea!`0;&cJzgC&qۈNhсӶv]21!Q!HNXN uS N1`zHa@35BDT0CM蘙<8?0iKD ,yp6y˘<cXj~J#Vb~ˈ\dy).2OƿrP7 3#FbHB;X0WѾrH7B4l@+`ՀoFsndC:`5 i );Bc&'wcpj#FB, +sY$XEzV.f@9xx8<Qv~*?YOvz5vAU\t`;;xD2Q&T +ޞ rF':e ĆLldA& (V?Տ7[^ƙfLA2&$llK[h"jNC3X': +`8p3)"\"D~!pa=jMSMt F2eBv HUH ƎFQ6cpƀ|H6.R32 @#P}7]лי&@l0V) v>`?рB7z/ݘq ,M_=d;$v48L@J:a%O7țA9 >=KǻTɦzn!p&ܒT\1y3ѯ@62i Ĝ,tn ǹL TuypP@2\ՎO bMg?z7H2b1"50ɐ|\ @>V +zRLJ 4mq  &C_q +Yč !+hF. 47CHsQh+P1[4#aCmypU؆"tJAftn6b*O1ftU ~x)$æ6@a&V;d C@˅'-CLde!kDmx8pݘ0aTK$шSҘS'Bc`I9Vs +T͕LSƢCzx{ggFMFkŒͳ{D)AMPTc5lUh} +wX&fge7XR)\P-j%U#8< TxKӉ+46*L5'<"Cs f@O(eϭD&N6xBIE3G"azڶ3"@| Pp%<֢Sx5'Q5$cTa8ٌW%-Z}҄OF^7w*:\o^b'~*mqh= +6ޒ\Ck6C7W,SԺ\ƀEg,`: j? XيPMDp r|@ !?FLjZa:-#rTkƺ"-\J9?G: 0BJ6@--;4 4\X˾p REEdԂhʥzlrw,tr0h'RhS{Lv-:9CI.8*^$d +n!g@>)-Pq)RZN6`*T ``&!q8#7c*x`;T9 +gXgڡeh#z/禣LΧZ\)JC H́2TH2yT,;F +X.4TrY_D%Tb*ZtAxKx)@\r6\^IvTۻx)`sZ{7p&x&`]9ӭ,.J| qDMtPI-,8LkcJK.,e]13lJٞ1dnmDۻPBh|bjcvjbfMupc;V]o&z@J3y6 E*VLfJgzHVC%>7/Vssg#`n:-\@uY,s+~wNʪGA +9Hu7?߿Kb~Nc͍hkS(̩urn>嗳|ǥgRSG]H#dGMZ|yC9*Շ_2a@,imtV]8*0z삘_76b-!t h"JmxHw sȱZN)IHu-1ussTw -K%Gs,? */"u>7Ǥz\fx` נR߂͝& X͉Y(-K[[s{w{A&zGw9sڭRějc S3KZg|Ov˷g-4%2.XHϝ¥icR(C '撝]ݫK'pi&PYk?ԢSHh+L H +v#/#\VI5>랔˛RQZJMH/dGNܻy)"ގVk/n+-nn_t:;>))̤G`"3ՋkŹ㽍[NK(±Uw//t=(JeNԜF;\~1T +SRa0l)!;㏔t0'k+W}cHyU(< SԶӹSru%Vf,}ؒ֠pŹS ٓqOk­T +ΜJMv뗧6Li +^rXn4F"PZ[3J}U*Eʋ٩}&1*]U2xc5,.Xm5$bXm-9,"-!?ӚkduZ[,/`+;{ SG*N͵O\OmX S LQ 4y09KuhۍUṫby >'}B-r @0`v'XJvV ҙŷa}t,nU^Vھ9W_=ٻ~ocjs뚘[8v+O&cR#VSGOW?]>o{dw7?6{۟Y:|Ӟ=[;ODk6b16w˗O\\gHMś;@.?]Y8}qq6*V'ۀ \xdc}a~ `^#!,:gw/3K۷͵||IN1%T;*N&)fg:`{X?ssKǯZ('"j(]:|rG*uUC6 s\q!> Kə[C?o̞u J.gf'OxNf2S'[=~%S Jc|1;&tNn961,- H}t6ٞ^;~Z]<ũklva3iP7驣nwz17IvwN=u pu=R]M9`yj9Vjׯt0DsS+O:^!%$TNtjyVp`/ A(<"Jc UuDW:X8'*'k_i!b99s>H4WZJUFk7XBDk7\Xt11&^2= &;+gNΒjqHsb}Bmn8ݽsoܑ&,xmQrxڝͻ4]lo} CBLwK^xuPlZ1A#5{wJJ֐P#H[/%G=E%?PP.L%gp5vaCXutjZo.{ 7Th1Qk[3JE<\no#tw0}LMHu`[_tM|4do??6=s!B6-@Lΐnadf\9zE +ʂ&TnmJk{ HuԽb~)aRd>__?,t -jbrZ?W^:@0mDI'gFNeOokRqND+ٗs˾` jB613h8Pw36  WDGHMp%=ݾַTNDʫVR ۧVr"5*-ީ{⬛Ғmj} (|~0ߘ?[Y䴘4L)4*f"`~:uT&ܑ_&:vB LnV/t7Xdiu;k؈}lƼtG%hpz(8q;Q'`lCk.'Rs1;aB<{**-mi,鐋|N%(t6@ԀHuCB,z BV +W4k܌^ݿcjLDX<\h :926cP󵙍Sw%f<::ShVc]%ł%'5yY2 ޾Z]8j䣭[Xd@ uК%U3"B@Jq\( +ȓbu-O 8KRq_W)fP͍) % OՅ|ilwZkjo“.~I*gxqNDsFrQ.G+tT* {[vӪuBi7;:MXQ7 +6¥Mw7 +$/>?faaL hL6ke3%"\ .AE0HW Iy$ {!3¢n)4ZqJ& @X&Z ;pRw⒍nszp"ZRM;ϬY04ܤsbfS-x ,إԢh>;&sGcBqG^8{*.,Q 9LNETOLө9s";z+&*`p +J(DL˄\ta `{0̋)*waãڂ~jDxcEmo%4T$,RfNL:lTt T/.qPN56Fm8sӹ06D.ZР!,R8giB}ReV"93:0ysx!\\0)"hELҪV^"U\H1"@4{1 w2|wz<7|p}Ŧ&,gJe<\6xi[z6) do)9X_9rɋl.Hfy;&\vRU>SK4fO\yAk#@)v[ւG3չps`D) '!ϝ˫)IJZk^*vB3l|ԯbͬz#)RS>X4lp]i DFb4F :Nky{R,|LLܼ˙|ФcED-)8(3-D+@;T99Lvpf&@0lo@Xƕ*@AT-͞o!ez:&\<рVlk L+3ʷlhlG +KV+C[] ИuDxd.̷wR-r|~o?x}s~</t$nŋ].͹3㵅^کxşG7n-ž lULB+[~.wL8\+m;jc.]^=y]_yٗ?{Be"@Bpц=Vokթ|_Yﯟ9wO_;x߾`tBK`큐`X6 3ڜZ޻p}_y䅋koċ~#%*Yb/V %B\=~[oiunk|˿za36j}l.[NvnIo']p"nB I\J'KO{.O}js\i8GLM.FZS+['k=o~>7Ň|o_=«+oMqPIƒP4̔ݹcNv=>?o|^?G?ܹplkp$]SL5~{|^|׿O?G~/ WZmH$DP,Yqԅk=_z[O㛏W}_'HHKJv>К Bymw=x//ԋ|?z?//>w֎ Q Źpn_[??w>L}~/S=l䤅$#TYml4g6O]ʛ~'/>/߽g.p(=EE$LWV78uw\Ï=w~ѧ^~W.mjHaK'DJ]>Գ~/0xՇfUfXYv͹Tu*Ql.mo^o;w>/7(ǻ|ٯ׿g_|֏~|g+)N-ѼNS+;G^?}~+~ͷ~|w>٧}ʛ=Re5MXyijÏ _[?}W_/_~/>W_}׷\-OY Z3Es=^~o~_~?|姟[o?sRndm&@Z>uO=+w~_/_?~~_'/~sWMTHƂF!ipϴ׏\7?go~O~睟'\w5FZ? ^L8jͬ?ww^~o|[?/?__~G/ۮld{~X[3TTZ9~{k^5_+J`\փKFatf d5-twzfsGs}\p;=zj(Ybp~7s)Ho_; gwCO<~GϽKKKDVJT] +ޱK/]-[ӧ=o?7_{swXE~. "5Eٽ(*\fgswꫯ?]<ќ%]&8`X2_mWW.zyg~g}sf͋^2 +fbF ȸ UŵƑ3zۯ\vo^|yo < ZfM^䂩:!%&LIj4 ++O2|!Wow#Z2JSr9$}MF%l(?:f7DYmRD+bZ\]tjRӟru$)'0)%b;f߸=f]̋JX[Le\;;^.fj>;ݟsO!И}x 0WlB̖+ܾ'*Zrf/ LCT a9C@b 1^%P򼔊e;\T޺Y>'D2nG(t^xp@6sԜN͓΀g6D*SL8K҅D*$)Lb$C rT+DCLY/"i6޾yv`8a=0n;lMX0/&L0*-P!='ҹp'WIq䣭ɋ2df/sxj AOR@V >3Vc!.ac|8ށ[CBLƥ.z)EfvHgp90.f}L U2*Ƭ8aO+b4aBj(%cL܊t.fF6te3{xG2x6"nݔLmvcv2H'aT033nq.v\ù77#Roq"vgq6~ho*H\o Ed@d䴔[R^i႔](!f3n,tibpGMΗgЄg͖TgN<@udq0cN;ࠝhȅnLʙz}192RVBNϥj˔R&BeiT.n$mxӁ B&@'` +Q>o:G E>5jSD#tֱPq5{'l~'U7b-9Q@mXEilQ jGx-sac:'2mݸ*1V̊Q>LMa׎F'&`'\5"1顢F7uӈMoJBCFdoqq ;4uQH;YӡܴZw2nD0FӛC#Ca1ac^tژ%I140؉9Y9, +.&t/FLxF~?/5wp>9]M⑆S 岐g}"lBJat 1\j͝Q;"d1ȄJA [-v|f鴟KiTȹT@. (mâʸ?PstӞ"CБL 9l6TP;ҳhff,>b!,8`3qS8;dYP>;T~A\k~V*^F2[L>g7\Z=aEyx*&WhWZʄMФkNApiML/l(;#V@#LQ$b8/6r~ɌP_5 DˉPN5(X`]\* :{W~w E)=mFiL܃np 72Lx'- Jx } |zyTwBo1@B +v,ѻ~D^7a^lY)=A/cbm) '[BE~.eJ.RwˆO l,'ZB?LEz7kpy>jMt@7w#d΄Cwʣvu[۽ݾmAN@W##ZTZNw#.1C";茗+PўУ +p35DpHEtp-XcP.z3"H+&)rNPV򚃎ٱʧoq{@Ah ASNrŽ[/":uVSp6́E|\/]Tgu26!րJ$:n Ra N9y]-\:k=d6h@C0HNk!Bjt. +*"ThxߺĦvzz$ed7ZXF?J`w?t05JSV,< +[Р_,fvx{<Gd|š *',aZ݈V7|N uSS 4!a,T5ǃE"> !:w띴t+NژI'7y2l"Ƨ|A0{p 66AD'b/B9K9);kAr!|D=Y7N]TSt@B9Rr^JTDxp > 2ybuQOB%B:(UtNjӊRL|, [ £n:aB@ +_s4'arudQ5Z1E*>.e$jmOdԹˏJۨ u` +1I?5f@5(*6R:N81Q.<Fri[@t +~& &e;zdpY%齟I4B{$wYxp  ${PuMLs'p \rGH$݅"dBE+1Qo~yҼ +s%1:pU&s"9;=y6ӨHC΍f0 I:|s.TAD =\KXꓲ6J +KzqR]ǥC?RMGTK(sѩRI6DyqKX-bbhs˰w7ں=Je:Ҋ48n9sDǦWT\wPDRjg=7#5&DBE>556?v٧" +r(Ċ'Q1"\v $ a-7b9' u` h3{Z}b? B 8s%{4h wL]"#UΛn1B<"Br ׼\UTGP0>fXD5܅ 1|hE rnER Fp~E>=B*."&3Yaqqq'[122nL63(h/w\j Hqz,dxˁ|GGk@=TLIpf2@81IBJ1T?KtzڵsF-' 8ܴ/MV4 Z}+Rq>H[Bv׷͕)y)юWɌ13.eGre.X09., +7PL[ T*oBy$'-62~-^J.v[ 7hк1C޵'J'ED:^gV~fb̻.(ս6oafkxAJR{zũh0 _,2hػxUh63 q9<ޓϻ)H +T #6щ7de-v?$I Ul$?ԶKqbv1\XEt$VISPJTNRցds8dfܜ6@5h_C%TRLnтIL6OS]4\ۗÓz7g e*hI9IV-U KuXoq^F'ϿcACTm:V{9VC,}N0fwyad +\76\rSNMX78]z.g V_pvhb߹tŗ?*#xz8l_pрjNh}U[<j%+,ǛW*,hd:1u\ԩ'-\Ll*]+!InyZcva0տ.a2&$>㦕i;&ÛIPιXӯO{HΕڽCvJ'Xw"qzx}mK |ع5p΂Lhc@ƔR `0| +V>3JrKڗ~xӳPH ~2%'ˍ=AT(D&x̄hQ`i,rU`+Ѝn!?NGɳNAqL.ʅTdHk˛5ipe ,朜R$BvL4b@'[յխҝK.VC*1h'RnP +!Wu9;.Fh夒%)u^lR\ЛT TZkNq|7w9WnxI(Ko^^_UwߦSKqW6'nRi@S#K@:k !CTeD(X 4]nl\}-Ȑ/͵믢9$[Fk̹̄0YϏ`*eD.!JM/qV]qkg-!3f_̃ uBOzByfLr.1\s|ҁTtʳ'->V"v: +b J*V4rjdȳsmyjnJjK)Hu\iN9LE~BX|+O]Y]mBRC+ +hO1@1/tdLdɄc\mS+-s\X&#T 7omWV")vwhl>IOkD]!kҘ =\=~gŕ۠tMNȎFp֌ϺYҁȸurr"S܊dV6߼ǻO]J\I;5x 09ZmRjTyZ1HU?BdmOД\_:#EFp H^(.?ps(d&g +:eaNDٹklf ]~XИ+L&H(Lc-/fvA &wQdOp_*5 1{8C |+.,tzw&3{mW*eFoqi{ lsVs^fxK`1 Nku?B HA}I_oמBɟddZ`E}0DyW%k+'k7ۼ#FyωHEE]lvqtcwh3 \y;`d1A.(4 Yiն VҍBF^ٙ\1x1Z\zxBڱ1Ƀ H +v a0jQY:޾j4Do ?!2GK@`6vԼD9݁7v4ն GmPC\ Bߺ~ =c͸Y+BP޸7gmf7oyy*/U +S;Ƥd 7H%2lߺ 쑔uPL&lz$7%3zI"A H PHt95m;7:=뚲'zG@Q DrMZ]ML.+ ?8o5J΃^tbalCE J0!>zf4;!@<:LXyכ^R P(sI)amf/KԗB2[c+n&=œ6lb&F0.*}|686mq (d밳[|H/0y9;P>/;5m!PTjPs1z9B.!DiN-KZ| .ۨ*;6X[\Aż/ g='p 'w.􈎷TSkx^^! bo'7 +b2i+juAdpn]آѫ tOVT!VU?kM؟p ^O@0;'gWJ%B-#b&E{jm0wtF@.LBWH( eLV/!#{'>! ^ax'>+ Ihz+5,`qKDDKGRΚ|1N3jy'ghۤ<|$")Z;+OǗ^}\<|2[[8R6r0`|3d ii'2hRS Zp +-!GƚBoo\{j``'<3-W@/kx-Ԡ6c6Zp>2xYKxe!#բCm`CAIX|,ςTME( +ʪ=KtGjxM.љf"P~qu㪜Rk X77M,rY9^_޺=za)f0:*ur5#E?T"h=Kv$q3vb2> -3Z}7vҒ\Z)-g;1h{0_2Bҹy +(-3Xɳs33 &q{C0$t7bx}; XƆ [|7/Qxq;mWgm$y7&bNJv~CDԊ{ʄR'\X!\Gi6/!V2M 1qR]>3#=<:Qq(%ZnA B @3sn#$,]n~Ak Rbk)'g Da.xV-Ԕ.Z4\Pk QZK^ +pY<ݵa6N_[aIB ;8 +}p%\qpҍvZ9ֶHukrm~}2-X^5۾R3L*rF|2xK0@<-|8l=HwW>aULJsC!n)/\NLم!7Ѩy$& Tqif2 ה7m $))9xa ^+,;%$:U Kh`gM=4@A>ATc[ԛ-$H/y~xشLN&\'PuF`bF >d60C+u6Ƨ}Q`SxP*ԂMJ(z_lȌuT 9@Ņ@ͅ ^!R\vxzu7ީ.VWouGEjD,,Rнh +>-l I}i9+8xG,'+6$0<|oxmn Z=>b7au( %ziS&∐ҼhDqϤq?357(eAɉhZ$ׅx8jn?]y"arxN-P2?޽ +b!BdCčQp;2 (@0%dT %0Lmu}@\O!|GbY'j(9+ +D Kn$taBx\LZ ,4X#-T\4@ ѐǻ&(~B5;9+2e.$~uf̔uڊ8'&囫LX9gCC\_R[|ha'?' 34UWH|z);.*v~>mt]q @BVh9 |\\Re|%X𝫏m$\V.EJqڃM>2+hƂq.:M+qzv,j~ mΘ) r_t:cb)7%;xzޓdR~YHvXRyT(6lHEhH/!F0BY;q Q`vT5w0%)0V.:;ݍ{lm5S_qRNMd #tPߨ@!OZGMG!Id]:YËD2W Ntގ:RҀQ:3:0YƲ+D\:[=~rR*BU7Zؼ&] ;2JtIe,AjtMNwLNӼ(hXTrp0BBO[kkt^T{H'&/tL.ЉTZzmyr WJוҊYԖyU#2Vs3g $Xq;x H1jx/H)\fbH1&xEu95̵-Z Xi q / ~OtP:裡/o߫8..G['[^7nʥ~k6wP1\RK!zU!H7˓5S^O l{=#BM;Y'd脍7p9_U{+TlEC>6"A4BH$#N# M1l8"4K+w}>w1 '3-o0l>3, df7q!a}䚏j\}lʕGu@r)&;5l4* '{ICz@8k' _v(_3+ ;;y3$QJEN +"/V7-Y۾qq DTYT*jcgŤ3 XN{p8m%#reKRn8;5F?sbaRY-o 6F +4ѻ0Zgd +#!@好bwv2S L PZ)K+g:['o< Q+چރCe!vBu*5Pp H8Y\:crٱR$;Wܔ^`+`|)XHn ՁHZ+ NPe5[= g|>: 9ܿClrr,ԻT +fx/%eրl'kT \s8`|o .X/bf9ڏzͅˣ[ͥ/)x(n]*-\U|x\Z bH(]ZΚ >Ab0p6e!'=)3voLy,~E.Jto>),!#2֐K˩dJd{ZVA 4~ OOfT]tԌ >t'#Dg/պTfl >stream +)WvN7!K7V_-h]. h{st8ݺ*F6Li4iJq&b-P= ť?KG潜WlnJ^Zk@=\r=qઓ7&AAIP8,`L$^zWZ~{rR\wu9 xJIK +`Vv`@U0VxLV~?n>^}YX_sˏSKڏG~K|FNX9]1qff"U"q~܌I <X)e:#c:1KX%:"޳X͌xsT)bJ51dNхvo\)mtq;e.m'w8si J/̻8c>}'Xn,ߒxݏZ@j^L/C ?=T*Dg|2ߨ<қ.*QʠdO.1E>Fhst T,g6"9DOaRJ.ˋ7wŁBu|6 #յ;-o閏S IobcE*WPR &ҕE9va'88>rf&@abu6VM7;Ɩm<~/F~x#ؓF?}z|esqȬ\r.FSCO޸Εo" 4_~/ڎ)/s?̧6^0#.$T'ۻv҉**˅Pns߻tMDɩq={x-\b:pvs3n@8uSNg@&7cFoBTr_RMvUV)*ךwO{;ўT]~W?^z%\PQ9 1^\֒: pg&ZMGG[B5ڹ]Yj=BۓS\bqljp-AQ[WrÌ^Hry-*:r4p +v)}|Tol^t_TVG&з,= rgy{%&H [7=T ƪ[BjHb1G8=Rtۑ)R>sUR) A?~ɣ2A>5YΊ ҙV͏ n̬f " +-A :Dr_4{Xsۍ:,U&'ԓWuW@`L* 5IYn^01䪚j{эR>f 7f$?C .s!蚋frĥ!B;=㱸Fo뛟9;A/[fi-1j1E&T(,ʋGV]|ʓxZZb=XV}ဋ''< ܅oR$H+0e[w?]rvrɯShRs0{{̌d,TZK f,]xKʽow 7y_|.G+o/^yTZ^߼SZ9њ뵵k7߹ ݝ'zk/++2NU .JHGB%"ڴ\DxBѱ+Sv4WsKԵBZkkBf X^" Jn2^Bo"\*A}zPٴ?u ZAjKݭ{ `#'t/bNL=fYa7i',؉Hݾ[^<+~1opb{~Fb ocBƆHɣļvYً3Sy;#R0v+;oL;|N. +gA-"hufy|r HIM2踤zcD2zVX5EHuʂp l@M ;qF(\ov}q[wھ7-)Qӝ|sus1;PK+;Gp~&k<|ECe.5R˛KK5 ?W&O?}wb۟oCT޼|}w1΄u0E+"[Oz4_<NPa!Vitq}2jZ8^]}*n{" >=f- pj[H,97ItkRv\A¥U.&:VqYh Zv ,EI9KEt'R@ڽja 7ZIFepxAFx 8:c]-&ڤR)`SAKi \xIP6uA^NƊFd)tҝmҀTJ'e@J +VY&B2DžT_*l8J8[0弄B%huţT4`"Z* .{<"մiv6niQ:8k"BJdX^8Kr\׊H\\ eG͕ntwIDNvxCȭ ę"GJc*Rbg}x & n$ؔss &qX&N T\#>cVE5q#R=KA5˷TÁ +t?38NvdW {;&kU5QzF c|a+vBVL'J+1Q)a@ ]5's^q`"R)% n"K91VPh571Nw8QVp<=FNI\T[*V_ڛ }ԾtUp^TkdPr/˙!x+@!eu?Ǖf^,_}P),'wy T>Q}yWwdzMi.k_)/ݾtXuMKw>ф6Иpޣ/v~7\^/6L{rt7X/ey?Q]?3;?w^:Kduy/(NnGHk\fY*l,|uۙxg6 t4\3Vb{ɝ󖯝3S3>;g£*=JzP zŌ)BVU7r2,PoW{K)J8?ǬL>qX}990VLV7j(/9Za^UR~d姥jue T57@YZI9a2TԫhZn6Ɂv<2@ J8 5R"H5nŋTЌnbŃG[tG?$)|OD0ח0 ,/G=B *?abnҭZw@Ó~FA%d- f%j>:BeĴ9 GJkZmSJ'{.Բ}r(VR5Sɼ^i+n \.YXSFQ;Z +0.,n^PPPMNòJ$MM#>ys,̸V*h/Ov㭣SP!6m DHʹ>`A IVJ WUr&ZǤ<.pD Vۋy!C~2+8uG;kŅ^WKrqc`(e/b(|8 M JˍM0ќpf&ì T[`,N HRNRX؉j0qaQ@„Lʈ Jr TvX&wO!1F PrVQV@CF[$,nHU?ze)r1V+ X1J RziQ h|y;`hN\܃n}6@"LD$%eh!e 6xթYlGP"Hr,QVAOJ@d|K6\g sam_ +D/-pL[Nq1))AM  :GFDO#+` 8 eU9Dkn<,)ͫ'Ox-ZU+z'ja#=0S,HB* +Y&"ł [?sӪ =F^$xfn,n K.\!w )f#|,@J).˹ᒇPeN@]蘚[w` J^-%NMκ 0c.4 +X$@ +T]KM[.%CN'h/xGvapdXrvl1fM.c(F +Dz*"Rx0e!8DEgltx6e60D8|40 SXP[H׆ +rm~>Tyz=kFdڌ^E&ǻ@IJrJ jHvS7xhB|rg Ry&ؼĜm{NW.ڠP X!;@s%綸X & .r 19oGM`q#MB>^T MN .| g!8S"LIb}P-T(uj':ѧΚLVdCgf.ڧfFh^pp)_rF;X*NҼ%$ڑЃaZsY3y;!a=/JĤMY\ļ 8G%OD \4=߸h33B$w ey/BW\#߻|/Jqj܌cbBTJ"ϊݣ;㝛v6,0*)l(Me&\Dx*ɫ~"!uq@lqp0AFIkf/l8ENXŋf/ehrtVL  +N0G zc".Xp9`rrVJv6Hx0!щ-fuy8N6_ia1>QlEr@a2TOrj`V"qp !^j̺A`8 +Cq`^ыF]Svۧr>,2ˌXs3|pgN6X *RB RDIAI{<ZsfSy#ds1@Fj0SI0aC^w)ꄅ^j {K|H +b>B#wJD(l}Ah ndVPI.CRI)Oq q JDHP8DI"4 7م>U<0yi?*„ N/E$xtl.CZ>1ë/ln/kB GP9/O͝[QaEE1. OiChI!Hg.O;s2=L8,)碑s(#t0-0?3 ZHi#`.$ 5 /Kd*4j+'뛽J%^.&DRTAf\0L' \xܙ^TCNTPLc`,.JbWvo6ܽ䦍i @A £*tAUQU׏>?}RlPP>5Y<1l4ժn;n2LiN<.7J40;Qg^x g/`(bR1M7FU+Ók^?/osY%~S-aԓ|9U311˕;n#[ț/^卷޾76D|i"~~_{uwOow\^ˢ rGcN(M FBt$j|K[v^Yws]>WDw:<̼=?  ssCNH`Ȕ&7j,H,Y̧ \~k'?޺6L&(ZlNDxmI^ƻTįV+ujﭻK/,~l??[?ݽb:v͇!"PCC:X~vX.??ɿ[ѝ76d~V*dť +2r?:H_i}}w/m/6٬vsԹiHG8W5u Oy~/߿>bY..tW wqeb@{ryp~y ?^W=/}Ͽy9XAY^RScݣsR'o<}??~/~_GrJWtHM`F[6rYzjǟ/>[gw՛?Oh2xm =+1U$\!4,OQh%Ƨo~o 7P%ewwM'\N~'?~Woƥ&YQR EhZ<(K>o[7_=޼ZHXbu|'j>"식׋߮;ᇷ>_/z_엟_/.'?NO:A(4/kkJC?|ql|?|to??o?W?|Ϯo(l7܁@Y_54_]u G;;ꟽX+<__߿_|ӽF,?I<#&f$|z1齷YtUh G$A"G"%J49"$8vg]h{17{ob"2:4}} RϹ +i???ɻ?߿W?y~?hwZwZ9VX[\zk- \lR@/Ǐz}?_|g~ǿvG~qTN.uhRTy|4{[??W/__ѫן?zgGFɊX@bRIѪ:M{So?mg?/޳߹El岐$:'{`̯_~͛g?ٷ<Oo6H +!$٬hV0Ulߩsڭ>?o}v>ŏw޻?i7۪] +D$b Gq˵\PipmU=Ha9F*9F`:޻'w᏾O_㩸ƒSl¨tw?_</o& O,60":Z.MEђhUm?{8,1'&w^~r܆ϞmU5ES7Ήf12hr8t˶Rw~bq>m&Ҡ书D`%DB($H&YnXO[wK(?Ɵ?~}ki4g=i8C'gQR}9n{/ ?֭_ggr K͊B$.թwsP6ن'u'5oTf%N[{;͞,UUp - 3 Iܭު㶵Snݺ)EWD) K]X]cIerՒMJ~S}ίsiXgl]V/^4EUVQ-%O-q&ʺ824YIZ ++yZ^Xic-q b助;<+qK`$K!WCd-d'vEFN^@0D`29v zP6")Ҫ#bFsVOvZ^ 2$3ijUa}c׸8WG<'O_Zgۯ7V"aV;'gYC"jPR?ɫOw{WWDps ڍfZ[Q 0\YVXlWkW8=R.$WtHIer$h<-60;N\ ˉHJŤ.Ŗ|xJ( m~Sq{3_ PQdF wm52iږ6P(H+ ɇh&"ݯSGV#{ ʹ\a´OA\hUxi#aҎ–QAJ(h|1M:7my,h{IgBgrZBqFdIV2`٭Ip=BP-*֌Ѯt[{7^%nJ8 e̵ʙ-ƙcr;)Qى.l{cCĠIЛk1¢z8d;%3F;Vs)@cb>+!<1&G=Bk: +4)+gI9Jy Zqkl5Ft,7S|SQ6:SBOq48U7OMll)Eb8qNH&vtW"1qs@9[ӏaʵMע40L>QcZq65(\8Klq) Jz&c >492٤\Vw;ӹƋmzm'cPzV}?@ƚT/!b }8K &m{r팲Sϋ̈́xuGG'`dݻ"7nO'9q0t _ĕjWe9)mhJyTGRIэqn\jSݏr0ftw%'*w1cDv"Ee퉹 ety3q#>˶nl&s6on_a*׎1~-DĹ\2X}?n,B-n'(0`JiHC󥽌3 Ry֛gJ,Rq1 bE̽iN3p#ƮEͤ +}ƒWCo]-K(OJmҊ^<La {M\$\݉Kyjޘ"tVcuW,6q)jW*= pxL_N|8|?*C NPD}{*I}j-Cؠi:ǟw7zB5@)o})WbP,swgMr-w^_Sګl=rP.m3-ԎX<G/0@u+0sYE~jJ0Ouz20]k'> RA(Ro|'\M{[wZ7?+Vtn:'%? hS_B XLWЮ3kgW|H¤x1*gK 3%|hunb-;SRhJ D,cZt\a4}90c6 8 Em _?dj$?y>Uq VÍ>b 7vjeto֐+JO^|"Rau8 ecou^~t+)x+Ԣ6A.Oy[ބS$[-̞S&777 PF}j5Ry)pGWmS2eWfHzgMY>ot|_ދq%+B8;x\?x= Vr]ܞo_v_^VpCzSGsPA%ѝؽ{l~MXo-h~yLev׏n Q+9̟/?bImuo&7x[XOK +Qӹ9 JZDK[^~[qz Z;{5viaIg1cMZ㼲ߜo~Uݢ-)?k{ɝam?cb (tXMAn|ʹRsJ;WOHg;w?1[{1+{N/NKәkn_=>ww|4G][Do&P)*;^g"ln5G (v~֧Pre|= '~:\0Onofx.ì>`ìMy-L#RF!x(TohSyc8mz'Bn@USfϜ7uz5(ٽWOr CN}Pޓ{`xֶ{w?"&T7޾o>vuqT)!P};^}Emeuiyy+_Iqq\y;sNc";Y)֌PZ;Pb ,8 Y[ +`RqDr z +)?y۽y̘qs@)J=voC/Zmw-͏w?n?Rl ܇q Qy77y.) rP!re7;0wXh"vb2{λ{nxqZP=J;aW\<ȗZbjл]=;|Cr,VZR(vO]ȦսQ7Z@b?4xoyYuXG~}a}g@::y99yiA–^-|}^(c޸wbx#}x=?c٣O͝(.x nG͌Pl7N;;Os3kݳwIwg5Ao19ጃIm6D &X51!.95\9p +A;-U\)Ld3j}1?7oSa{OP#w;šUz{Vlk)J!6|$;K[ZhZ#>1hoGV[7 T%?SP\+Ο/=g%_9*H+ny'ɛ>4-9}@kjncxg?S0[ČT;~!}?lp2nyﺣ(emմT t;ͽ4'm#lq7YauA\ATOnyj mRRY K3uf^& +7,%.7#Yor>Ld=N^7^mbJ$}ȭb藧w=`$RmZ.0ᨕ]/QF)Q#%&^}x|x]sb@.9zO+vNnerQ4o9[okBqG,#Zb) j+?< E|珢B]ܴNjisf${?bqm[#{f;8/0 + Fbar+Vyqk>lqڊ4euIgZE)&76^R&jN6D_7 +[}7.>#tQzS?$XچG5Nb~k-&Ndwƹ< yƝdRI[}{|iv-j3VU  +oRVdJI΃o'i6fJnv$l7zn&,0$kWTozu@Ō7JPZuNG>09T*Cjjb=sz1Dlq}t*0I*6YuGçVhPZm %a{ϙQ(D%/  7O){2"-xU{Է#B boua(#U1o6r@GZ;2ܸ9]MCX`h[^v/grV|rViD +li3qk3"$T&i2fV^nFU&VI˘=L&:"ڎK-W! G0}1;HܼYq) `RX%27J ְZ+oWRuW4 Ebe׏@(gf1 AgV0}Ƞqa1cX^H6u3~"hrb:>&ϸc!1ʺ)K+F^3[UjGT!pz6{…u줵(KKY7kRa`C 犽[Riࢤb~ĕ6I͍B}~ I:&"xlr[Oi] D$]HЬq FݮocR.ΘN5= b! ߄Ѥ)nl.q$NZ.\B)+lwj2Q+)P!A G*[}fj4ψl?ދ[a<*`6aIVU87:Q߾6*!ތE0UR˻?lnS+܂Bɘ}~e=R.zjqդP]ۆ$1NZ}&? uT3n{*Kk8 <ʖr#—`XQƱ + 8O9+VO?[!\P/M zC,ð.'D5,@^ 1>Ĉ ";uڷKn슟L3j{=!Ҫ3%oݴn}&P՘@M4[R9RVB?fuתphݔJbfNu%DzP!TC?zp H ] g)תGuf^it~=nĥ{eUJi7xګ$ݍ@[%h#-.bRJ#D A 6Lk(_]tp%PۦjF\V`3 mFƧ#hwG/8FohaN0D8ml?TFpQ"bPc~}QalIpO=! 9Zbb4LEH;t6:i +t%!1{mqNV;9JL|k5u՟yqP?{gJM$櫣s8@4H-ń(U,Kg7l Duxv0ƗxGxaJǏ6rU) G"8x +GrDDt~hFjm7LlqzlBoBVu|>{\ Vk@dG"0 )e|9\XOf +v=@ fgaÏʥ101cu7btr/n"AKS|6OZ[H˭u$ {Du\,\Dj&*)V$Ud[<4g-r#Fys-H_ Ϩg +qula1{ x osQ s! +$(n{Q)֣Y4'k~/!3//Ø0V:D o-%FCu ofTyD +[ӻ,m"DatT0yCI'M3JQ1G]A`d+dqy'J OoMN^ O?AA|FDH3FZ@mhsڙ3N0% V+#ChWI]DJ]P"RwHP: % ;|` U{8}1YyY#hC)Ρs O߹z(f~8=y726H2z$z5-A ōm@0n:g=ڝaR%$nj ,q6i wJ:hv'P!~<û48o +)JOk6j3jKPw1\)mmZT/kƆm^0+ɭU E{*{|*%Bʯ:#㑌_]M]1q7},SHPFp&oN!=,^-einT+e31Eq-HaBK6 շ4Ÿ#%9ğkyi)Jȵ0馄j(:H)M1l!Ȓ |nȍŚrU*[dvj$IsP)j3$Hnt 13zU=gvvخ'9=yvN00Y'auqJwڧ<;%=?Kkr fRIpUTmDR^wD4V:aW5Z_ܺ"Tߔry&´0^ +OS6dE'xRM3er7Q7W›+X́Ci] Q’l&T/6\y3/'>KLTZ省 Eˆ4%ֳR4–l1a\_C,*0xcJnƷJ{Ju(1-l^^vKg8!fQe;gwGC)?D$kSV+) ,c< _oxJ B-f.[K(l^aպ12[Ipˇfc $V֢-h:gԏ"5SR +D \'TV$X+ >H)ݥ^(B֩P~=۫1H29u㤩/]4oP?X?%[RWH|qph]r#J!"HZHFQ?&vɵiȐz;LOIЫ^PVz:BJUmʕ(EP5jXF"[۷jV󄰆1vi\ -UrMKq%V] _H| 9KZB[r;y(8}r&_Y_ 0I=&o_.[qVw/JސZby/㌝ +6kH-b*2K yxR-ITR' ++M ʝA*78=H*BHЫ;l9-DŽWP[1*!jZ;5AJ\$Q*ƛq=|b'b-BqP,(sDY܍[II}ۆ$դ@p›1!lR;ZIom ;J|Cnc%,1DB.[Gkޏ=w3%ت8,LqCth$ri-YVMF4jTyHBugv>0.ouϩlE1՗'ak͟Fp?ZLXKЌs&QQBZ݈ AX +IQPJQFǹPnj>n c\z\ d6"$%ɿZbaqGZ;)`X&7GN].&H0!ENIPY숹V>e4(&y*4B|Z2Z4۴;$[$͞XکlG\7 F"^)4-flvOO ǥZ+#*7xVHn_, +5ÙLry5T0c* }=eaBTHN}u]MpTzwv8̗VW@@Ǣ#z\v*PTJBd[Ji>{Fٳf_ҁ]\!m |ZY6xA Qn\3\OKAZJHba{%|.Pʀ܌1n9@`WZ۫8x=] _Y +Y]0f MKP]Vo,T6XMZ˾O*XXQX-b;؀?Y?Znr&@&$Tc$BUÆA]Yw1ORb5 Dvg8*1*De?"G$Q7S,l;Sy@Z$lB~3%AmS +"Tb!#z>D19_7bu$_N 0pDY*;bt$0zݗRDjT-J,H%B HWbKH@RFH;)U@&D&Bn13kB/IBŹ"!_\  ^ + 1%UEoNkF 9L x ௅X7gje/x NJ(SN \K1Yo UXF,z&## %'_dP ǿ\ڞ^qQ[ILr&yO`h5Wc_ cVі G,Rif7.o !j9b%JB48ே$L$23[o 3JS))>ԕވ)2[7IZjR-ŗVk+~PqGHDDi +ൎjKAj5C!I%8 rT%`$CBATrӴT2 t$k!ʟ2r[Plьfq9P44jD"eRTx"+*!Q5Z!AXX דbv>_KIUH⛨~)P#% ho&tvnϯ%?()IkYoGȃW)P'pQK-Ny0M6o?s(_MiҌ{oHiQJX=mń틥@#+4# bQ[ݨΞfJ41c!oB] 26Q{W7]b\0 +)Xo[ͳ0x9b O0nJK`ʸN] 6R ^qP*R0:`8W VXuS*DRmn(,G PTPv/A-+` a Dȵb) klntnj`e#|rvm^蟁G2(m֋ +@))P Dl08r J%i! +3Zl\^.;Bk5Q:iC'C(Q\tpc cs_I)RP0>u=DC/ / `VށPr[ P3E=%ݾX@ܖ 8e\,%6 /\pKL3RLt0USrϓBhmɇAsWBLF# ct(_XH_JD2 bR=*Ûz +K;_f+ s0Wޥ~^i+@{}{>HUd.HxI!3Z:1:!45^sZ2Y6%u͔L\DWD,q+)~Ƅl3,XF + wAH12 A/L-0V0r +Izi=#)nvZl09BbfK.e1W܍be ԏ))a9;dh&f̶Z;I Mi4 Z"^?OPՄ`R&FY `wA fZ9i`mLUZ/z7^+k4R"R:VRL)74KFRF(n%ŅR-QkWW6˾0#ה~c"&yHN E7ZB$"(t!WKX#Lkorw;" ( 뀑H̎vrQn8X+LPccuA߸[c8""kP SmB+e~&—$Jy32 +JCc,?!~J(sajCs2 b&pHZZ0.ׂUBv.#kŔu/9KUƚlѡpvo2WBrUt{۽hi°^ 2KA.p1zZ~ ,vxgL5̮^IW#S*\;x__ZK xv 5څ_j ZBrQo=$M);PٺS/ `FrRPm,=(Dߤ;NL>NWcr~)\BZ>C?^”\*_ Ƒ޼f+ nT4{ZǴ5Dµ:wZ+ #zFf|yi#& Dfq/BۦA\re5L'(~y|SoHQAL#gx\<.pJxQNW6$f8cF+u?%o,Ǘ|8EF혭qɟY`\_H *H;c&b=ӷ68S*GJ&Ҵpo\o$T;~fX9"g3l*|A*ZZf8fkGɓλFb%. G~w R^d)T)߆Hd,Tfj0QZ^zTI6Z=9?CcnrLЪN,qI\i$ԦP>(vz%Ji vJ;mQ8dF,?y>AH.tZ1qʈTOC2bMH&޽Ǥ7XbRi#J +8CĭkA +ŗt4lTv IMLF˛F\ c8x ;~s5+A_ pUYFmF2'=ٛ~Z*@]EEޥ@&@{XvY0o-QRZ\zs%KPA4K(ara&6GI}V9&e +; A +%l$%8ꅩUٶGpl*|ZBWR-ѹ]vL aqx|aYERYqXŖ@HTDv49cJ5oN{;Z,BL&&VaŘctD]vcJ EMB{Od&VJH+o|tDŽbLlnRMLd5/:ۻeZk~BE.,4|)u~ NAo.3*g? Sr}7jiƁ<3 Y +Pߛs.? +Q> *֍ʂR ŠY\hɹ 0ӖU[O>j0;)@ ۄ‚:ޮBʌJwWf&UAR.M:CZ:˥ D Kksm?mqQQYqk1f?r eĄjL <X=! +%Dk頋wD;l^ImD*o&aqQNrxR2N\$wFf SI`EkM +az/I|tp0ViTLAɯ̈́!2ATQF27"zTZX%ͤn߈I3o5O1^NJo7?psuu Le1?XM`6SX{z{W8(]ƚTg"B:L('@ҍeچz+D׷kSjrm 7mrm 7mrm 7mrm 7mrm 7mrm 7mrm 7mrm 7mrm 7mrm 7mrm 7mrm 7mrm 7mrm 7mrm 7mrm 7mrm 7mrm 7mrm 7mrm 7mrm 7mrm 7mrm 7mrm 7mrm 7mr'2rkD{mx2a}3D/ OG>щ,Gkix +I`Z45xZh1_pg^KYd ]C>qIST%PDf5"0ECrm{J( +#1%ph{9C/? MQ(^>?E>If-^k!*y +?c3M2 $b<-Z#I{?}YOAy!d"׺k?ތk)%J}08GkdO"%W粤V&SR-) c@#BkaBO~˹)kha40dM5骥P2ΘG9`h:Kr8#4B)n_,.L/.TF) 9eޝ~LZTlPS[q&3 mNRm!iTɇpኂ;2|aFfᴃH#J6pyf#j#iW9+}3KN(F;\O~DN0ʻV!0ba& +) :cvpM@!J;d7S7iWOyg0afwFڊn3,gvcD3z'.B:1&grt25^Jl`F—QL]8TɧF02gQ&] tчgEn#)2f DBLSc D +=BRR L +ފ1.BX~T߈KtP;)EitffU_ 5ɗY{,\v"$HQA*-Jk-9;F98V)+(mId;L2팺v9"1ݼrP(\򰎽T~mq )|A/3qA_x{f:QSVv@(W\ٟ26F|:mLd4B UB~+ӹ*&|pٱTpfj cBԫ1>jEiI\ZU,LҌ-P'Ysn}u +Ra Q[S;l%m T&m:*y;RK*PJMڍԁX9B*C2Hv/* l4c0_lFT،K 1ґaEy(*x~%^pQ6Dڨ :3gߓ%_Np\aJ-L kq`Wq0 #"%i;Ԋ҅#>o+Xג/`b M_|ͭ\ѻ\j2ZG_Z,.XpOjJRS: c0QoclzTMK&I>䎔:#F r:  ,N^ )aX(nWWC0^G%!\s)JЌah;G~"1 $2ԁvt jD ZCk; +cfݽsLL0 .@1~{b5Ͻ2}oT` +c:t)^T$6ikկ@ ļ—2דFRx'f8rb0f0ݟcB"O`Z˛I-#wfRP? 2A8KxLl?E:iҽ£@aGh!F9)|q鞟%H#4,@_J,Jz#1ˇj!"ʭUSz-XG*oz=J9ڤTJ l!\Nqɳ_v,#C%V !VRwYk,fnm; 1!Gd,ہ:)۽Z,JP[BH(6;I51? 2y GĚs-ƝYWepVCw>K[fi_ɍ:"rQZlf$:cx*%erΜ0Gx#ЭbN!N.ZKlP3BlUr&ݽ6Z/w8)֠AQz4KuZmj IÄ-`RྍG ( M\rJf\idqnS`zPE܄CGZIpf%ވI19)BAI&a>@[@pc :0QR@2JԺ)4v~5LHBz3 Y̴.RVc0:)hתrv_Htf+¸p9p!(i92 $7v}\=y{rl~/20H(.q (B)Ra6G(|oEoec:L1̀wihwbVJs17Bk^?q\ힿ=\I p&w* .7%ɸ޶-pa 7B5A6Z`i=vwP' m]L(Pb3W0!-\ 9sc +Q1 +Tev=1 + e3l&<ps=ί(JXXIs(_Jvaڅ9j=%U)HY~D +%pAtm&@R$V#Bpd+!Ld~$\=&S +䶉B$1H+qz0?dH%=wO +RaIu^ufʓ+?Pf"=3mo/8zUʉXؗʇ) VI2AJ+\h쾩b +#0S~JqZj_YcLsNtPZujf/A:Pj6:E%f) e~T굃R?*N4!71jP~D6RjA-0F>b"#6*Wp&hc'rIx34RJP(|rG6Jbte@ƃ&99 +p:&@&(Dz\Ҍ}T!@RBƁI) iJ {*4Bٸ\)0o&f\Q tl%0 qR>(ɖ@al3zz?tY ib%xEՠ(#J( +-.fQJlaڎwv +h4H#~2K\n#4L.FKMϸ#Do'V;hlU`pk;|~.W.]ׇ݆ *$βT*s;9Jc>L%&ǔ*eкI&1u +6_f'31.[M AhX8>5tz0&hVg%H1 |nÅbdHn,p( lHJg@a@fHpC Ɓ{$LZ3N۟е( %dWK tB>xOQ֗]% \ +,B;=c*0>:x G(zLQSp28i%®ňKn0 _ebY)"Z[M&! ~(+ 7m>)ǹ,X-?&8NxwI{-ùTolbbwY-C>? JB :zШ3}?alRR,&R(#_+аi\,j]vU3#0;yɖwclCB.i+Τ)_9erv$ Q\ eo4KXFRF:9&3[gby$A[;ޏ P~}+Bib/~\E#3)+$ Hi0]Fj.tk <JHyKmPfBә0oҬZ>056}%"¸rSEaxf +QB)ֺb~'HfMT!:`)h:w?ȬE?F~!2^+j%UCAS'r{ZP~pJgXQTP+jzzO*P)Huw?LZ0=g U>CJqA60O aBUmĽ-dE;0Ii-*3 P:^9IJjME(wtXRRoNcmobe0*{ @N?HkqŇ`btN/:Sl3=f uLXM€ R2~Zz#Wzu;)B +2%pyV5"X(@YH:ƺGQʍRkfBLmPJ#RZP!(繧,c@$i+ʺ`{a='BkχS$L` Fpp-Lb9AeIIT.Q09%) 4&"A:TtAY?")fM$wrq>g݌Ao"*PG}"#H"\2 ՒRv/g_2$,iKrz<עb1՜֛WR="Pz=!Bit+<3_t zJKȎLvAM]#^χiN2?SOD5@񂏃R B@W2{PRv&Pi-ҧ11)UB)\ectwI'TJ,L_ $%tO +44 18xD@e0YSZA /&z/@p%NFX{-4ImBB)[vzVuJO.wvN ⎠vLz6DeWrP<~JE`.*"|ۻX02Bf$vx-tPvc-.xV5zN/W%N# +O⁐[֍EўoA;)E2i@!BkFJzwI[w:Fe%DgJ+ji&vbdso=o#\^My0t!)(v.Q:s|3!Aׁ +pj*!Abf委Q_Cd`Lɻ! BڬRO+u 0>oA8mADJ6X6XqޗI'[FdwHC}? 0e1}ST1` !TImBiJkLQ`]jI0sk[IUh;Aj5b|'ע^o/'Ds6m~gRX"Jy(*hmY&ZZ=\J2Z dW׊Sl ;l )BM3ťJJk{J]Evpi  +ս wg1eSRZzJEZb +P,Pia:O#u8OIi%'Rz06)/(ҙg,Ť*tl$6lt1*H(#ФQ&k1f2 .|TPq׏Eҫ8Hg˒޻ +ާ{Az#.{gV!"=NH Z%Ai$p=cVƝN@_uD~eBti jdG %`퍄`v:!ʤ:kҙ8U*ISzۀ|L\ #Q4]@:BE!vD(l#b# &U 0 f+1a "WḦ́TD=j&*a1ɂɇH !m1J1y "paܦ3Ll i6c^+P] z2R%ZT^֔[FB ѹ^4]+)(e@@(å +ԏIF0.QV{ H# +UTlzWmIK;> 0 +[x2rFB݇eنhhĀN讟'7g~/70dG5X͸s]0%jp4Y 20´U$W 0jn&wޘ/a. SuJmw 1T)N_ӄT'vi{njaKrT[XK{JJ1%YyfQ68[Ș}'XD{q !n$dH `)X);}jوqmLp= ik?8ri/!Q5 +5 ``} T uQ|N ҏw6q(`p l)'L+ȅ]Rm.G(𧛘*P")=I\] 6͈}`l# b#6@y\ǩ<@9 mDP?Yb%]%jLOB=l zdg*VuF :ASR|KP3 PADS +zq'42f2d,j\yVH(ClP*.8Xc`̓½hz5)ի fG`$.u̘skq:Ƙ\"v.]RIr '+Ikx2=&yg؂`R*)wcD(͠r͌SR-%<{QHHӯ|0jT\7q>.n\,QJu? + :JqpU/"TVD+Q$P' +(mw^HN.(43x|V뤵7B :T,!\.t 8WQ &+d<5ԣLK;AoPwdzIxPU~$AWZ\VPJ4 r1a-UychqIk ٮQ:Ό3`B !Ì 1u@#bh7߮H ~5^YgX *ȄFH +E\k兘ab2rd\) +!K ` +`iA:)Y\Q7b/Ck5vkGʲ!<063BC+an-Įka/Dq5P t]_j= 1LJÌ?)iw7CFRvKXz?E؍} +<ڧ+]@gQ XCjwB[VB頗 {jl1l`ޭePޤE(vِ䋘bcгvO(θć$IuxxWP}xWcL%~'+}(xԈ0ŏ7h5@aBRr PPx!o:Np٩8PK8;١2tv +k=}]"j'.Vb%΃\TrŔ&8\or0:a},֌1Rv5d4A? Is4sŊETMchORWjP\~fpl" bj# :G= e/(&UFpyln׏yB,r ;X1)TI:d6P &LXq&u݂=WYq8 :I(_a + ~|w4;T60a*Iś1.%^gc\%@ TkpASZ̻場prZFbG E]ZP'X狋QX  {)2qv6GKe|W>P +مUiIa (V*uOP-=#Z5jfmu'1a1m#4!\ʁb-m{aZJ.Je-fW+3=P*c >ʖ(k@g&)MVJoFC%5RKe(QP$ +kw)>:Z,9편GlCLXk2Ji ^?*;5!F}>[V$ӅpN2;|iBu3<̴|)43z̲cRџbM .7OW*KC:gB,ԦRZו5j0=dpeiIgeCF/HȨl7f׹ѕX Ӡ3-Sf e3,>P(cS}һEVw]ݮطXT5ZUeX. 5{z{/Ӈuܲ{GR~PJeiדdf0|5>278Uk;l~fZuK-+x0e +rJytOβk-:jByW(ng/ڎaP\xvGMv1.”N(<1swX>tO n@lEuR(ڠ\=)>NAq$7ʍbtPhn_.va K*C-[& mv|k<0uٕV[mc)aXg D.wqJRU*j73(ZS+AauMX1ۨVUV_&gONGvUwb\]#x>cjs#)fRI.>PN{uE,~RZ|vh?Nv)4`( ]7w?}wr'X}U]aiv9:zGwLfڄQO-7/Z{޳_^>iwn珍=y".| {X{**{WhcsZ^ug<"iUh"4:7ʡU&e254ɍ.*g/L ju7>-^6vFO8@Xv874ڇj}GoΈ- hmu< I).ib `hsiO7^w^,>xmXy>{_Lsg @yoo*h8e}@Q}T[<}?{y7W^:gt8|[z?hCgBp9zNwzmO/~^=Iڝ+tni0v,m<.o=Nmr[SYL\oC`^eOYַ_7v?|hxX* /&?zO'fXxBgZ~}}>:zv᫝/FF/O:'˗}m6=:Ni;'3htOZ}lstʳgUX,p`B΍vߵ^y{T?*L˧go~;@K0i*͟)˟rJJ82n74VzA\×o3ĕgfg??9ts3 ,]_6wzefZ/nq|^=} VfRaPY>Zۥ-$vK W?v>TGRim{뿪N16׃o׿iDE0/g/ +˗#wԘ]v`d B, s]aJSmkk1ovpbmRF6*E`N fJoo~;uOk|YY<>tyʐtB-_8: Tv8ww7<'O*1G6%FutOZ;/᎟Y$]̷˳PJ+esueXLo.G_Iؾ +Oξ.Tzgfc߾&k=js㽋N.}0k߼@o6_T;χ_>Wk'~+6۫n=̎.sޛ\tϖޝcJXZ & &:{XuWYk[p_y=s;zc>kBi4N\,a:?gA{QVg=zVSNɎlWjyh6w25[^݋Ra>zraكwlc?߇Ia8鞥5Gko|>0᯴<9X^|]z(X$2:nZg4)I[pkE(Mvu7*Cl; S}RѮ-Go/>0k;>- X%WHsT~sH.&sX9Έ0;@ngqwG~=?}:~6w?>fK{x8yv0،hl=+58jr<|U> ÇorEwQynw)cdk}{^[̷*`*?4ԊY{;OXCj@@T<{Tj|JkWe1"UѨ"Tocp9*L*3xLVw|&Һݹr`?+1M9`3y0.ίk;N4՚Z !'9G(L<GV0rnLގyHk&n( {'X(Nj#gpY]__fԬVit)J>o`J`Xp(ftΞ;0:4lg|&G罣/OڌsQ8Q.P÷LFu\|A\Ff<<0 ؙ;4c:! +kQaxe3=Xwkѳ@åRTncaLU_/I\GV&*'@<8/CH, UJ-ٮR9*˳l1NT$q-3MH9G,UˇF{- II<-*(*k 6E>y"ՖŋW׵^3ٿ|K[Ilv^N&"HZ.:g Bv|?;xa ?^(+w@e;ƅb +Q0FDR{JxyGe:aZCObn;hpP$MIYXm8u4~eAi=8e.XTfݝl@ bch2gΉ+0jli^`cY R2g1Nb*wqFx~m's(r:~N^@ A {>#f4H^,K-rk8v'N؉{q99w]kֈ~7O| dPCLJyʟC<2M h]c v -! :n$܁`<>ԟ|/R5`TlpsTBSHSTw[ThU 0̄LDdÀ;;tfD !&L$KN1s ^fSܒԚe 90@ҝm\IxI +i񮍊lQqNK@ {&=Y$e+#*PB*܀Ը3[ ctĊ Z.PSpXIqnb{cI,f=%&mamPpKQuwŁTV ;' !7ullxĊ "R^No(\Y9L3tTym؀Y2.@Kn:\N,qm?95žqP}ϰ f>6DeE.,!ܨ5vZ\,Giݧ8`_Q*3KU[YOLB9{̵xͷ~ˏ?_NB Sr45Od*|k[Z8uCOyY=߱Ĺ{鵷{ډXu$mT.ґ +2Di,O]=s+wxٗo%[|GOw_ܼsg{dۗ~敷W]zHn$\L6ͳٵ玞v?_}O+LVÃr~Uifɐ4¦MXЌN:0ppdoս?r/TM7 >3BuDxr}zfg_~'_}G~g?OϿ3/lOlp $tY:zة˻{^_鯞~Ǐ<ʛoO|͟oǿK?~3oX}O|so|O>ꫯG}eHa/`tu#UK^,T'윽y<cϽ_O'_}?;sW9$"'\|ޗBsnr囷o>Gx~gx/׿o?ϽpqFau1P9VL|kvcy_?ݛ?埼|OW:{_(70AV1,Icgw;OO~xW_?W~' +ݵhu~6lTt`e^.B=w֣}?/~~O~_翿?}Gyb-.R%͙ţǶOp򵫷~?Ͽ7K{/M-?ٲBF'Elu[n=zcO~~?O~wu^xl/f[!#ƪRGCR{jeny}ym҅ ?g|_t_Wooj/m:%f@ ʑ׏Z<~Wx7}xO/>g_|~'/SH7 CpULt CjKz p??7~_^x^~ui")2(VO4jКZX}}^yӟgϿꥷ~S fJe$uv֌@HW=K>~ǟ_埾z7~'[?{z(['QSPF|0Zo\w?wŗ_~׿}?/zz3׻ 0A`XaZcD8Wnm_ ooޯOyg/,mcDm +VTOsIQӓ +/]u3'N&)&uIZFi@DmB(+ +TXL&Zk kݙW;{/rޅ,NRB֗RN ʎNMy|f׎Gb62{>?ɏ?w~g_| o9]bL(z-8GzCkGliLʍV=?7}ѧ~퟽߿_՗_z'n?p4 rCTЀ k []4'ѕť^y_}W_{ՅR/VmGiaO<.NJ٥;<3OWч_~_~'|L)oEV,̰D **E)ɓgϟx/O˯{7ﻶyd3*;2P6"gO0X\ټpޝGsҵG}Տ]x~ĩJ#g[-.ڼ;t`4F +QDayy/J=;wgsBs蜜HNXѬ e̚ n:[c'y(Qm! Wd0|,'D>)i#Firۋ~Ѡ#v2d!1 zPWa;5I+Pbxow0IX$4:ɥU!h 1:\jL${ʄg@PB@ Fp"/TyɑJd8gs(g'Dqӛ^mY~>ZȖRT8(JAqnaZͧj. 163 +*(1 +CJ۸mD{&h>X!ϞxL*VTrB{iVɂ +iCC#F_!&T8 %$+mNHSZcќ0L8ao)H cv݌,Ī )_:ؘXXfH;Bj,"R,f:ӻ׷GN":e ,G!9ƇWCE>Z/p|nߐzPi%8˟z5-M0vJ=!V7 #}ú*ۈ">s1q'IbL%1&iaNƊpvCJBlTY= 8(+8=)M.^a ԐT6Ji! Nv܀hʂA.LF8KYq \>f`dt:f#B0c&=EGЈ¬ڕjRc6 NLЁ0ڹ11 +*̸|k'j[aaV P4^X?%EsJ=H'%_a8v]c + +ڥ4Q:Ox@-3VۙP9TX` NoVZG!=x++pebD4OcF'<ħz<&Gtc}H5hczeTyG,# +k,ݵ}=+b%S14b#>Q\FgBD[[$)͇UyHm1D1&rzR#q>r+d%#6oJuH[}#~+{S/pGxuvXaVH7[TG'P:smPmAFrlr +`e69< KlK[WxPRaB| +31Aq@ +2K/1pǼrVYGjᚓI거)!fJ3;AݸjR;\A'jZ;y=dP#:߈ptI.) wӺF#\|Bvͮ>Ä4 ZatHόHC'xЃ#f z4vmys:'a6R؄T:eP AX0]ZAqa_f<.jPN$[E' Fevڗ.wNXPqߠL^ jHk8DE.'n&e'[Ra+cZ84VA鸫?ݴ;x`nD.Bcf.%JV0pq\(D_^pp@ ib5c'SQ3.|jАa@8uڐ?7I8f:kWv|Pi8L8v:fBB|R6aeõ@rRk*!. ľ1 2<]| Z78tJfeͷ#f,8j pTN28Ycs ܂J59M%s07RZ[iu`qh @ң:bH^38N8뻥cvp"rߠf܀7:D5`QtV@ᢙ|636&NӫV.^?*&jǯr@a6T[ 7"""Ҷ3`vϗN4^=7/Bm t +3VO-0r5v@ieC,)%π&Brݝbjf&AE-̃4fχ:/;p &3~ wĕLhD\s\PcF|HAMfrzMQoBf>B sjf2=E9dگF `@ +5OI 5N|((Y62+U46I>ݠay LBThPP[=8Yp`eMS +v# Tz҄$(aBFF1-2nΜyRnQPߋdm2*bOaP-F 1UAėQCŢKLSnvLq );'l#3ΫaӱtmY-X huşN=h0kmz'S'`uNo\z/=V\ <)\ZkFWxXG)<8 c9.` $ s T{;jl)peX'UYܽxuS23tj%w/WpBp5uXJu@te UwoH @5Du*`C` +:l܈P4qO͈9+)VAfjP +- (E8_"/"p V-x 6O +Ļ_B|9o ~'+4l%f;$܌Jpx*'ҹ1GFF .Z,jܿ?4jXN#%PɭD(`́Q͘Ü^ K&'DpNZDǟ##-.jKמ)͟<?o瑉LĘZUC\'LO*/E=9#l{6wzv&E Ebzuꖹd/+ ʧҽ3=~q-.Hi W4O`_kXtg[ +>;^^<ĥ'6N^}: \l)3.-Pq33kg5Û\:]5.J-G;۱֑;rm.'&y+$ oN E+,0{  -::'Q6bffBK.s˸Ă'WVhӂ8IH P IjCk#0PyorʟWpG كv  l1S2(AbX~AL +=R?6qmU&Rq/i;1h40 $S>5Fs<(võqoH LTPB)NzGȥ9'/P":R=L'&Tnb!XZ5H/3kś.`][jn\L5a˜2f2 +5͉|KCy+;MNxvSsWO( Ԓ˥M:ps9*X\w+KƘ7bVٽ&{$>>Ws\=YY>ڊsGȣx-3֣\j>98;c&ƽabXr|fWZՒ6Tg6.Cd/ٝ޹gfbU;ĶT2 ;SBƈ'x3$ `\VOzUNKGksK7Qlo&3|~MMB%R]OwNpIRp/Pp6E5#AQb6`Q baE(qY|F.HDgnTp$pYrcQ\M[؈DT4ޟ7]Hu5ҡx ܝ[i +R4_嚝M.ݗ եԘ4= T;!&|kȢ#|spOy=<_;ugr'jp +lG-ț 5!\ o 6uOGG'Ln֡cH )FG*D-0D(9QG6 ADty^K3(/ o DSah^6D2@|g#\sPA;拖f[WOYڻ}mJ(ObDM8"քJ{pN3f?j'$&(q=6`1 <&\h`I>)ϗV.8y3ldZFpAegG; }}Ewۉ H`$V +X@v.X\,L﬜^odb +`9P` +.4ĸɅвf^#TZINno2V &T65Xgvqiȗ7 +qyy/y@i1{(8 "1}H88SqGz}JXWdOTa3ʍ&d\Zc'tqI3&@BOwE6j!JoԄ\A9J,qJaݡ1QӐY='B'R䧅\uMN|> R V"4x)#*4 [H ǹ4̤A."Ԡ `(@Gn |1cpo$OGAt[ӱr0[=)@lԟkGp`Re54ngL +DD;ěBد0|kXc9. \c*ma|oa NJ@iާWX6sXBHF5'pz#DPsvtN8lM!Na*.U?:ƻdNZP‚l9NG3VoF(O_rV(+]pßZl,RCi s(d鷉"Z$jbe-U WlkDa`BLOI!Bm_]ÂB&|n!3Rytw|,u&Bq1 CfN0Lb<1wFew>xywj|'3=T8Y5%  5VӞ@G2t8&7~m+m_3+rmnv{+soTH +MfNf!5Q0fd[[ŭbNDi q +> baHBU6RKחNޤؾ.w) &4z*+֒?bVi*bdɕ|{Ca" +R[=;zC/OL]P=F߂(L bl dS: ݜ>2T WRs; ?͛\V׎^xrS90B$_n%ye` p@V()33bjl<p YC@Hh@:SHuٟ +7@F'P)7۸4ƭ +f<D-1F19#0.VO] U%q M$.,i/k!_WO\ 7fs;Z}5HYVӡ;X 'SZC;t ψupv`4qׇrٚX<3j%uhLE dWBpyJDeQ5v7l7  LŒ :fǽ).C^+)>@ť1鈝t6ڂ@xBC +۩K(M&cwTus:X&#-.ҒR|5gi`qٕ$ͥT`$BͷƭCFZ:?9i#&R8}Czˆ?#R-P\g^ꯌnjI'^;9ysܓ[W=OᾔMȣa=vh2vvH:ģfɭ@R ;z'8VܟgoO74& $W5Y?mP֘a"pdA>~kA(MWP&n9T<@0< +$+ 8"p8rHȜR#ZdԈk;P`TL H.؟q;CH=+sZqr|8wZ(,`yBmx c\;\K*c#j`o2TY9~'O\s3T$lO[{ %3ͣ:ol1z4̆v*=æCZ xƛWwDbt`dI~ԍ`umBoe*\0oSNT|ѺkSʄ:0̦NnLxuNIqTԘI*g6+AtTK'T  ]2@hw hqxXip[agcՋ4 0*8@ ͠yS&31;.xe`* 2zwL"ftrf707 jniTk@a1< +*sj F1a!WA팩2 ڈi!%C!շ!68}4Ή )C,)7t[Gk I9>; (O;|itpD釕 Qw`OݷQ2d;Z-%*/:~6^`aU-&vZ7+KӧhKJ]& JȰO,GmRУA҈7jPC,>=%gHvbw +TK[]2}kV{Kϰ\ߊ=Y`@Q3[l1IVWX pyzLHQ5$wMx `o RFs|w_(LWNl_پrBAɭ̟CUK;I"\+ -}Rmp`QkV6wfwZNM'6` +7vрB<͜j/33$b_tAœ%m66i@+>m2w `"!KVfw DrtP>X^qdA'kPXBZ\wXTmW:8&\RU.HtH +S7[\lR +3J񉾦#l&@LP)^wGPildagwgtLb\^6?A<<֐丙 +hLk̴ d +x7@vO.8X;rmⓍ[ Vfg3{|eݟ\O..?)dM`alX,7V.}|zX^d5;-ZVK_CqIX݄O7g1b!#& ^tBeO/5VKe+_8bQ6*B-!5LqZMoPBoUsE&!—l,e{LTFjƙ|oO!7ME&\ʓtܟy7`& ~wq hD|v}'']/Loo~5kKf{4W/eGn>Nt/7kON>*G{[@?n)~3rzRrS.fwKgs'Bidc[{a}_?`av/NR"JYAU$*mb|VuDJ&?nA7#CwOVcz:sL#SKlb+72)+EhfL'l(P% ʆBl#eDiz|dMwbmx)oeuI:`+2F'Dsr.?gg!oZibAO@LY;2Yo 9KqirFzŽ W;Zq~ϰ>l$D-9{ZP+B~nhq\Sr0r"$E9'ĦzeRXC%Je:0Iֵp='e1ŒfqxT 3E@\z{jeܜE0qnjك\jn=_ȦtC?6B$/@lW^&e."( 8;F2bj7^zo]+}x=rۍZ7$R^}EdʇʖKc{4<|v1=x(*dR֮ؼ^nJ2/yۛ VE Jq +@tj6ݻ P3}¬i׫tby xP `. Y>թoܺ ͥ83tqDD~ 5pO#KRq,\ Z歹uL-$VhVrfͧ^%s_Ĕ6ۗj;N0QA9;!LZJΒ+cuBan^R6fw~x+ˆ~|>V恽tŗ~|wSq 1鴇dӫfz쭏ꆑ} >7}cYhmw3]$y"0ȹK/Ic㎘z+Y|j&Ldτ4*fw6.|lf,V/m73Ka̼»WtAfy 9J sbra\?{fOt=1y6h_ep@hncj=dH]JVOQ߭,_ +aBu*kr~ŃOYGi?gJ&\~eWa.r|˺ 7Fe5zyt7[@YN&b2.&"CeAE5/"'©eP`U7@ʳj cS>HZ"ݲKo`51%&k{rc{Jn):B 8D18c,S.W%0,Xmxbe%Qڈ 8nVUho!mfm|-?t"O))R( Q B:B~GJHk!iub^0jb_N![Gw|TS|{/MSF}ߨlI[_iWV-zb|h) 0#Lr!/Â0i^-srn\z2”ფ5gH0Si7b&.$A`oHj .*N6԰l1@ adG\Fٌ+Bە`` i+6*84Bi(g "6Eq!0G VDMwP$*jf}j +Za+FY!1PAHjCQgD  +D/} 57̅-a88?:F-($Q I 7sfTd}C/܊ p4nN U4ܲYރ6-OD^+|3 1PPi?^L/cRJH i0D3s_ N-D)8HDqif1"e+3ZCqlpKS4q s6 (`| B.C 3'>u;`0%2 sVE8v49xf>|z7aLO-19%dEJ `ŧNL|(%Fqq{ +ِYc0qz19op./[ž`U"`ވ+D!,fl/t'>CqDbrJLV[BG S-ăDbʍô?1rNH#7BAs^"TT-k8%If;*#Ӂ3 p<3gsaޏ'1Y])$ ̊jv6J rj)!2Κ(oMY. .alz! \0F40lA ^H:@s0vXaAN +$Qgƃ<5wǖFvAdbދxx02F̻`1C90ʢb /<<BʡBvq'wԙSS97H^-Nn3Ƿ5AA/\H!qf1&zze4Q]3"~<1 +!8fə("\ +tYћ΅>;ԔdPFQu{-.pw gPc38d+_ED7OL=3G(ZH +ZZMA߿pkefO/DCB\0HDTƔ\D+FMR(B h !9 w{MTcBG1Fγzpr! 98&A`ZZ #Dnl ( +WVɊFiv60FDd|03m<B@Til/-LK:;zn ()0@bVBJ?IDLE_H/݈ '\'O=*OX# #sS3O *J> EP|B,B3'}Y"gaTɒAHbZ ']x{f.Dq~125s# Vp!߳9 iBlOiC֋q\wb&1vÁ(Ov(psky.d+T.Kh4 +WjSSA_UJ<ȔM5S#^ HNq^,wƧf=3,i +/HTQD1iw{l[s{GL=aB2<ΉPxU$V gn1..|aF' ;&:eV9I +2"" wJF̛E6QĥB h`gx g 8g1RD*zIp q$f3<,PE"0ESQfðz8{EQZzgzhpK/ & Ăڇ}brEb(MVY)E@YI(<ڲ^EӞ'~3I"ԩ'Ϝ {0p{cd QB(;`~$BO^sC0̅Cq׍cAMY~ꥺʩZxsvRŤt xvP(&2K*ȸ+UmIgMLhK%uԵ>x…;7>w6_ɝb$'dT9DN91^ʶ*#xgyoݟwV6mXKM6EMIVlK(HwC@PJ\jnn{\C45Z=ϟ =8٦Y*3d$ E&HqRR<Jח-kaAD1JqP1Z@P&ip8ϗ̈́1+{+FQo;]{tͫANZ !dPhp(ö}4N=W{Gɷ?e#1,rG`8եJZ\jsKjƕw^{ppx^[IP(85 }3'g}~?y +OJV^db>](,ӱl:B )lB 7;w/|woh+ރGqg>k ^&ZA/YWw+vԽ{|ystu{=sJJ)@1 9V7,}ϿOϿsW߹O?}_է_uqN;1 G X)KdՖq\*`FgϬ/~跿w>xw.w_7ՍrG]ï<޽ݣt:-ii9ibd|ʽ~k k_|p?|W7~^jϿ|孇璆莝 C$Nˡ?.K@__* kW^c[J2N}nx_|_O'ه`~/7k7wVJICA3RK$T1Q=nO>>}q?oo>w~Wn2B\Hue%˼guoͷo߾?}_/nOtO/ݣk{r<H kZC_t׷>y}w?/|/޹oo?_/}\'szfb00"uyKK|˛_w;?7w6S0%i9[n NN_/~uG|}O?o>كU;3{mЁ^ +:7[ɷ/?~~|_W_xf(LpuN$r +;bܻwq_/n_g{w>{u+RFF(E76tayj7vWs?_Wy;o_>QaNI.ڰuat/߹>KM1<򂖓:Ǥ%x(_)>W}pXW/G~GWq7=:תd%,bbe dJy0pSWR_~/߻7?xG[;nA"$%4I|TS*U|飭/^__|Ooo[ǟTxTD +bTSپ Z +UDMȍR7_/~~??`sZcMLJLh:)lZݝkW/tow{{Ə.dK"# +Hfj&"$u"дͶR>_٨?n~mƭọn\^\Dǒ$ RԼ(% lTVO-v?}uW^=7n|7_>On><[Z+K +808RQB jDaUu^9.}/oW҅qSJ"Ja"  ҸvZ</m?Ƌg?~|;k7= Oy\Ao3K殑sD%eX|ΐƋz+UpR-M<,˒Jvi2Ed %kE7ް/gzL+c[PcP6a|HDv!ٯe|߿7}h[7޹޽j\IV2B'!t)(FzƱPӂ:ezo~O?^1rIi9"la0²^+֓2ըgzJh0.YS,Ю 3&OS 38E ۺK9TX)*pEKȘLA,{G|A\H gtp)./w;+S^-'mV7+Q`)Q6J1\v-81g@X(G+^#񍕯>a_hDH9QT M{YSEIeYQJO[X.Ӳ g )S.(W(5LA"]^1‘%`Ų9M1).a"jևM{0J6*f91: HA0Z^oX16^ D^ A*W5ҧ]ӳ8>fjJSWrr;s^%VK׻fKv6S S3)/`LPʣHhZw:׏^}xԨYHX P!" aGyY:R&_vq!gjtK+A?I3Љ3i7Gm7J()Ƣ!(Fg\d$16.w0EXwbD"Τ-eg'ܮa 2d-4aV-#`BqNML"㨄ʼyf*8?{r|,R 0r +EE4&QqT1J sPL Kc endstream endobj 82 0 obj <>stream +)'0ǕgY85ZQ +#g惋(c}+*΅#fٓ bq#&093ھQZ> + iD+GiT!啋Fĸ i/{wokv.ԦrL@bɇj e&ǷcA391iv i^&"UԒZV+¦̒%2k4jHyq 7*7Dˇ*1NMD3,RIز|y/̥Np$"|’zDI/q1E+. IO\ Qs!HV!!,TaXi5?aOwZZ䘁*ekT7>iaq+1턋9cx/,$5P)`prXƵ: ‚Ct>Wt'lNSqΚ0nXJT*IeS!=SQ#Y*=K;b~|ǠR*4"3>4;@LOLybjهYg|BLCn. f3桯OPި"71 QҜsŁ.3+dj%&Ǎ.72n22A0v6R.bT[qY=gu/&mc5qO#ht>TiAiT + z BƹC.ՙGdnG@-`\r9 :ѐ#K9!];qån*pOń F"VEF; D E%{ZuG)! W?j3X^-;fDO-ȭ>\DWBI)ۻ/$[.H׊꛷ãGlnswE0дփQ͇$mn3  e6Yq6HiP{BqʬeWnT6tɬ斮I%>"6gu,vSKuA ++>50[*Ŕ NJfy:"s"\C{Qm]xу'< 8 [^}:~n1{)5~rn[[Dt i6$XB\Gg@ح rag!${!/"My@N阊}ku|e*|j!t/fzvO dϮ뵽8;et/qYX.cfN2kqҥ  6ա&i7ËrqLx)UU̯CJu.BrQk= qLm/@ +1YB65n6_2KsRnJCdK_"7܄}~}fm|2;1d7=AMәUK/nY=qD9dG]Hju޹^u_ ǜ3뻅uyvw_Q[)wmL) P\눅-*9 (\?Ĥ޽5-Inq;3Ӏ&f =*󔗈9V szXzo [ly_3f}nص e=KdRyCc;c!I޹u6*dWAUzU˰n:7j;҃bf >vFIFaf~jvt=@go]!-DfW6v6V+mܐ +kbi+⤛ ,Dip 7rޡ͞`#“S `ʰT[Gű;?֐ +v2!c: +gRå×˗2(cX__ AfR=y\X];zm1[6!7J9 +Vw/ +Qsrvl};gɅk{KV;Wظ/9ppW%ޠ>Do"j.W(|aK쥗]s_[?~};nBe6/dqGjţo5nNV;2ڀjajGbZlK)ɦַLds9yH Q#m̨'vݿ]+|q _dnw1Qݑ@q)ٺۺ/1%%?J567/|'sv~@N;^z)ail)!Z}&$щz0+WV;޽`v!fL&j\ƕ?.DH7a + Z~~vuRoH礇v&q/v9E( /KIyHQvL*7MF*RJqlPV88`,Y~vB+7\èTL.KIrc݃W[xdHHcN 3tƍZt[5SUM4Dޙ Up1}dҖZJq uΨ7ʶZٶ8F.m\ + +d82n2EsQ.m]|in=Eħw/ȕm(JG_+Xē^* mSy|C`WҭyԌ+XsoYc?n(e)9Q@-уѹj{|E 1AmG4PYyfdGvת˭Zy˨TJշ2,>ot> <洟\ +R#3jZ;@JMݽ[Q uy>Q cl͇qEE\D Yz.ӹF& \Qg6Iv#L3i5AyPy0XM:ÐPRNs(Dh쪕M9xހ͖ U_YDR@8g6U\0tW72j5B&,6!62٢͖Y'R~yBZìN)n/E:FRn`4Z}#7غWZ=^Jytq[ILmfanp JZ}ʇ,Pkp/~RL!!=$|.dzNu\?w,.{$^[l Q!gF-?So.ݒklzˎcr Νtc /Iu=ReZs`W׀xOK~zA+oEt{x_ƒbL.+dQ?+fZ{~cXTHRL]/Br1ȕLa +SNku3DY\dM9 Fs*,).Dh0n 1E5񷶏_xz:"r1(-P71!eK r![9tV-o 8wncfD,"7n׶2He$Vk[T ѩ0yU Sbn:+{+^._)L+Ʌ0ةK\Em(&i-c1L5WH_2뀊IGgF Q)t$gAТRd^Kd=6\pVVbgGpڧI/3S\^K0sVݪo4֯Vׯ뵍ILri!&)p^="n4ukفRuG-$Ը:_ܚ$?"zaR2 ]=i_ȌR )G/$/`{`6tڇ*GNeh#mF}TݸϹ0g.((nyxʸf C_WÄ_vwY +1Y[\;t2!ɋQ9ȤiM3׃'8#/SӋqTX;5`1V$C|0;^vV&IO׊WfkT%e\KvBB \ha)/t^*_XѪktfdsb $Q7Tr w6l{Wh'>ryPIx.=`qu` :gfjN&Hdj D?eE8;XS1<&TX؀J% \RZTjE\-DyZ+je>Ֆ3>T*ds&a;%BDpmEH+8PO}EťKۤV ]_vsEP Q gf>Qjy+ۿ;}M{Jԙy Gv2_:)qq)RA䦲 0WςbwDǤ1k6O蠺ë|fL]F*2m(X/y:7U`B^I))]Rv4:_^>rJ.D8$5Ow`B*XHȇZge@N1X,bzS=3 AJwxlLOeBdBzP`{zqɃ>\['"\Ios1֩rM%@ȟ 15ȖD߬dXLfgAlφ؅J0ԣRi!HUNuË8"{!LX\)+?#g<=lGz~ՃhU@zcόIgN]N6@{ 'D0eQi[$p!Dmu\mƘdKLi/5<Գs(]);3#<jB,W&5E)p;̤vT  #hg@V{:A5 A!*+u&&Uѩe&τhX p][(Dy=V6 +ok4(Zq4-  +/0YN.&;n!Z3sip* 2Jq<]d7"U`p(esu }@dj>"Ř$fbfZ?s%`mt0(dW >]4|1p&,ɵP [Jԙ)2*MTiS>f&m` IBE +jCl"JaL$aIF*7HN1:}6FLvb·i’sklr0\:KwtGxV ֽ|nr9fP146b|JHh_` Rv}4 L&ٕk7KZ'S۵XGݺy~CinEHsa6cv0/.٭\dk+5p:"&_H."ZVMl~&ăy %΂2%qth VAL-"qB9 aMF}ʋQyi޸1C+uX'=5P3@-XD9q\H%,VqO 頴7] ©vΊ!"D;nk,ྸq&~e:rڃ" OT^]: ˌg#<&*Q +jp׻ܞ7YfPޝ'OD}xQ91\qVڜS~8HաNJ!:Y9K!Ŭ 3} n !%B g0&&{ +y1# f<>o\\HZ׏,iw//nOs*+ oH}yoݧrw]a R!B?Iz IB +:NUVϼz|qkvO.7}dn;ߎv/1U)39ZG W=g܅:ǧ~n~^,њLބó"cj.%b%.Ԍ,iהӏZqoM p?S)!fk~Lҫ9fi:н om/Y8=3guk.źf \S35gV9kZ>R+ݢ\y]a~9΃rgڭatpHh_eݢk_z1Eh{TՓݏ맿J/AJv{ܦ?͋N,8Mmn~ggu)#gp"E3џ%xo>ӟ5jJH9+TR_W:=\Hk0 m{p'˟'W'sZ8h5K#֝vٝc9>z*%5W׷$J:W׺eI vO]!9Q@52(RN#BzuguY"mjׄf;П>:z뀷G{X#JjU%no{㏭ΞZ[2;^gw[rrfpjp5棃]-9jT,hM8}*8<>.fUqa>)e |rh|I`vnˬ#'Mk!4w9<{%}5kł7R?:ƧEO5lϟ %fTSKͅ3/3ц P;`0vlu/eQH78mLo~/),+j<$BsSv?R^Doe@ՇӿqWܚQ5JR[jK'e)ʒ*BȈ^)+'KRsU&sgbWj}~};!—U~ Qomiz".E2Jn*~ZYs"$Ekr+EO Դ:_>x IjV +Fxr& +Uhy7- ީqVsze5!^I(-ZΨX(ѡ޻4z|pT iXۉ`GEFEzEV3~璯r2lD*&`\kZjMZ8;S=~bwI9)3g}g"_:#an}kHcOxDSNpu{XD̞Ҕ~?hA 0B|kjxEaZGƧd̙?WM, jojRNyoSU'+E;K5SWFj 5 ,Fጮdu _4L*IK gwͻټAH2X8=S['9g>*P.$u).ѽP |BIu&Fq!D`xo|#5( {EILFvis>xE*Q%qg=]߯N^i@Z=oR'G_e)ZmSF şI+D^Izgh *B!u)igHm8Fs5 d\mk?3{RT2@ zx+D5:RI9؝# Asz^yygHi-BmFH DD}]??ڃCآy]ۄ o⎮RNjf?m~,ph믣{gp YUU{ؐxhK2T4N㪹׀]*+J͓e<{AJ-?QO@&{-uҝ5l&ettOO$lB>Ƞ1^_\IrJ,D +sw-03L<0a aMOc)>漵:jXҳ*B N?ĒS((aiƇG P ]<Ѣ5B=KB7!LITz{m}4Sb`[sp_)R~WBɩ?Ai2ICjg^} /б޹$模){Z34d +B]ū}kibB 8 k&Grs'UNr|aDOp!G[}tp(jWٽp2,Pi"'6+^isP4.Q(%xc\õaV{'?wBzJM֝Vok9‰׵e4hyTWu >/,e[9ZV= hZyg*]UneYWKέU~5Iwr#DvU@ܲ`tV+͡Gp y6&do;C.ʭ`\lCGr%3;jr%WZ֔B"NIH*xNI#[ٺr'p3*2'Ij**ܜݟWe(k*EGٹ@[ǐwg=5-r0cFԮ=Tg>H]pu]EN +UmqHѲs uH}IśWտ7R}$c[Xm-3ƀR5E]rU[tדxSWk̊ ޯNek!Xbq)d.%D׬8[H?vյ?mk._Ic$ܨٹw#9v{:?ωWZvq^P7Nާ)mwqC09BAߩ JC\1%OٹF*;{Unܩ?ms[opWSf^Ü4}2bݭ6'yihbYs>XwNBPre8u=0.i ʱnUtOV`1ڀ0çZZmc!P5FT'NTVwլKЇ$PDdJ)NN[3{?{'USQcshtϫJh>~k6^M.16c 2ig6e17rϐz6΄n|rό;肋JLNuD1}w̘2Wa!9k(d*>|S{{1[WKz~ oH5fX;mP۝럼"9 +b0EiÛ9mH(hWp&Ãn_mΒ.Q(gʆsp( /`:dH,#,9gհE.D3nzo=TTɟ9 + +ỻn:&5@* ɑ>oׯ.~?H@;I4y!7Ƃug6p~ìU|a._s](Ѫa I{G?~io8o w,S{.eݯպW\dJ{Z8#i)&m`/G:9D VDxhycJGH(c!6%whlztXfL] MFVԾ%icNYj2  }`.:۷oQ5 9'-rܭ.,iݧ.'>s ]❒ܐ^U^ +vp*3ƛ+o_MgJNJNdqKMfR*ٽqOQ JRHIwq?ؼ6^"vPHČrg)(/(AﳌWxD7Fr//U==<('jkM=h7~j'uLINa5-ޭ=WÅ͌2\>w<@6T"pιMߥ;{NpU6kty^{5R|LKS]}'<9vru1d~SY~UDpV: +[kp-D[RgIh MC~a?Lalb:'F=yGuDfI)s hJչOAFCP"&Fqaxx =?>]+Fr=lͮWWI)ViOqEfM49R +s\֔"CY? NVZ.^ObEBA cMNƯ𨦏*+c[̷QO1`9u|W* l[AU9]|;:{c\8|[kx}%ŠĻVzy@T`UV83=}c5[?3 +J]J=8WCO/^zacunm$ >[e|ά&FfuK}~ww֜\DB UW9Fr|CsqWl['UmdQ9atLw_H +0?3'rt&VA WmnAy7?Kv*NYEuS։7zsРcçTtkB9uW!-ڤMJ{BfVD֬5βbX1zϺ'|t,G`O"!Z>V(LzM| :PIQ}Ø ;ESsJ^uh+e4{y[yCY A;QY+gwzC O8Us]7z9ƪ]{QOd!(=hP6.cNb*t8gʹ<]l^I= ݅dOPvjAjU9*^8^x"RvN;yLkūMԫ|4Ț9Ϛ\rNEKM &nEa1;'j~Q&v)Kn oۺѯq!8,jTp~i{˔i1{<?ӿSzhͣrE嫬ڋؼ+wp~`7B D^ oY\mj 'ڜK5Wۜ;7Ӌ_ӂE㗿pQ1(6w)EtWh/6_.\a1{vriIsZ͏iBQw, R\ٝ^]5Z׭Gs^ݺA]fM)7~z;s`[(S ʚzWo@jmڛտas|55I[S1X;^aO:.gLZC2Bb|RX_ڇ;3~>zSu;GUYb51n_H_uKk/_7i0hsK*W hF +~R󷿗y,962e?;=#P]¡~}ה1~ϗ$Z>bK_ŤsշbzU;U<>䡵yh@Z<>䡵yh@Z<>䡵yh@Z<>䡵yh@Z<>䡵yh@Z<>䡵yh@Z<>䡵yh@Z<>䡵yh@Z<>䡵yh@Z<>䡵yh@Z<>䡵yh@Z<>䡵yh@Z<>䡵yh/u2PN×_̢/ +v዗Ͽ|Qؒ2 +ːÛLA;9<>9dx2t QYEF`h礌(=fEZhA_L)W2;̛ΛՋKLtN1'IӽܝaYMY21]o24igk*s>~^9V D?'ܧO<^| +T÷bSބ_Adf/)^?}kJuhIH~ iREiSwLDBSV2bX{\[ -xS1&1)>c 9U)ZF$U9&G=&D'zkΌީ:#.㚛=(Mw%kə; /6gbq W3m 2Hm2RZHSw&4EY(?m{}tOޭ(?k|/ֻbUYI`ɺӆ-A 9DF76ދe];5zstsrm[79,Kr;.)=[1n֑.BRbBik᪽xw쯊WժB.wr@9z,(}HC_rfUg\XCvMJhkG1l(<|RvZ MmCYb\RuqRVYa9c _bC/J;[ת|Tl"Xk!zy6÷»>Tc{x|X]tPμ$K\$z aipQ:%1"D.p~|)`vO39>;.Qxk\o9{"|鄱g9.c\;=vOW1ۆ影;gkWÓٷY%4g.]j\tʤ/;RM;,h/GnRf'"B3'%5sF=0G)om̳޽* qV. SP5YhXٚkXвC%Xej: +LU۫e!־rtjwUUl ,-Oڈs7;W LLC p )@P<(?sE"WIܭn?͒fl1',tg.vv+rhm k<沷raQ6րY>"qO8]v|jH[#)ݑ儴Y/pARr}A+ƛg"~ Uk{xύ).ѿWך$gFxGi#u: B2|T*ʟfEK޾#Ti 9g%GKu 5KctCy3or ɺ~}GƝf0.(N]1پH6Fgm +ߧbwtsՌa/ig+EH}u/lOY~})}!92e/~ .kNJl߰sWbBȣ#ҕmQlfm8DL†HwZ lJR C!iIAqU)A<)SV +oXO +bC`ؕy?w;G,(O{eI %ϬyELu/0N-˼9/_3YqiUс> +R\~œRXZ D-ƝKտrO~ aUJo2;)a vIjt(C{gdrgNnFon6ix޼tk +XMB/sLܨsNYIX.eNֹhGRĹswtlNM?ppK{v(<2[rJ) |"uq +.l5Ǐ\p: 9aUjq]^M)ɍٿ77r4'@&O5%GE笩.%wA) +@ZUڗ%U R,4Ic|Oմ))([Gxj%ؓ%G%"VO*f 0vw"=γ5Sa4]Nˑ>\5;ړhv+֝Svol}YHJ U9+ 1l?gsQgູ|19_{ [{v/a֑ѿ BTw # 1vivsIU>.恞+H$ 6oI]ޜ=JkwOnϢ]qȦEE$CjJ(tO:Cm96XiH@6[7 qBhq/ *A.NE6"mW:`[R rUAS`B$%G89ҩK ȅ }(ԄVv+Fn7MqEJg]k tF-@ +GEE|R A{U^9>T&⇷f(OVк{ƞvN""VIFJ03M{;K%HcN~zW;?!XJo=~=N7 O o[g)άyYC8,:ۏ_ntr+w9:ޝ>+k5a7y-m,6w> hSPw*+)B^3]zbbh짭?y:ٙ>F׭+昀&?8, tol>MٞkgP!)8h}$dBB?Xg%~3>[;5#C8%5WF9*$ 䓩ix֚f5}Ge]D;9e [YDx2PڠHGe&p(0RlvDH~JU1쩑bJ7GXEkH\AT@u %lHnUC-2ncԾlSw^I +1ʱmPv3Ik(nn5A..sGjv(3=@3:\hl/En +&hcUF B0RZ({=9㭜QpXwS/a !5&ҹ#6<o繐rs8ce.'vFeW-g(wFy x^8V{՜(IYjֵN]↵#}CRU0# ysHnI(1g/Ν_Jކ3f4U`NUy\*reaVPЖ,i"` s%\Ì0I{35!Gu'kj⁴Ǽ0S#9J-P0s!1FGhoQ-<@nn.!S$eV}Xq+1qovwjSj#/%L;CX>)[/q5bڰZƆӇ񑝜aUISFKNhcLBo@ZkO36KƀVY0Wdi45(+-888pQkm6̾7u'O(R;R(\~>IަHIά+}JEx˪)-=sl;vIdIևF ihr_6wvBGzruϋr0P?dwf9Zx1'py +]C>bű:`JK,R{HԇTVUla a#x`TU=K*ݰ tRP #̆Ԭ~lmQtݪ baq_DX{2Kޔ㊘BsONIԌIS Kk"i$$EtTmN »W/LbJO$oTSh +҂nQ6*–)Y`!k%uR䙩E*lnvɟ_!=.+ZBno>xGڦ. K_"Q~/>~~wR3ݲhk[oN,E:!%o PU} H̭݃=G%6|c5b~ͯ:XP_5 ׽DB&`@Ui4>bD;e"֧b}%xtKo­2o =!'I YkE>N`*87:z47Xʺx(vpk+r m$zk(ݣLcDOЛu}Rscu.}8Ɣ7y{FKH~."BEa8"O*DΖ&e|S}D\ǔ'`qwߛlڃ1Gv*^'qnMmnz}r?5:Wm[7gZ J;9˒T$uÚΐrF5omUJmsiwf|:R:r65Ҫ!vi_~RU cK*=R0ݼ/sD|F\*rM8H lzS1f(:,QAXu35 ݨp%"MV`45<I'0Qhf+hQ:ҲSu#qsĊĎIy@i5J1\kIثȄ |mHG%q2zW{L- ,2aRZBm-XLjNlzA%K}$0kkKvǹΙQ^l('<-fY{$s̳=kX#֛Uxne}t1#yQ%g,κ+)>';|nWEέ+`Jl\<<_ +Oh<' +/)󙊘JX6gbHIM$A- +0XuYTW=TaJT.,zCHk_=F6k7Rں]ڌ5F6jQVTRht=cM5~IZFeL#&SUq@Hiа-ldJB II6*F7`/*..nVz8+Z(&]ZVa]R:m/Pw&![SYbTUY % y^9=#m_rzGw9~USz5]m.;o5e*0Ѵ)EvKbz[aVNkNjcaOT6ݲJёڹy==S 5PFKy˜3֜ _PO˔^.)ObfXgL~U++Y)KҜsʈuֲ! +( ᬩվ( +%H.(5 +KFү +q&  Acڜ \XQaԘаdGK 4 +QCtʒ +AX +"ITXfppKd#%PTp!BJ *5x <)ٚU,$+as]py-gM:B#,k{Ijt@vg0:w)0A{ctX,ƞ;gȚ}523~C! k+û To e8~z?nhֵ2jз2+C)Nud;Wஒ*Hvis +ogLâa]YIsaK:Zzl4N6=ziC2G;*_3Kf` &H,Gz W7*H1%Nh}D:"WyQAV؈{>c4 +qQ,QӻG7LO$2,G,>(r\lNY-RZ{eƜ4Ԕ=҂Ƿ?/saCBU`)+{+y3 .=%hkuEHOZ$%M VC 4ѷ۟Bȃ3#M%O#jO(tj&~njjׯrkf5CN0u':,cUw CVNjt/bSrݚ ]R9MJ \nM3 z+0%pRjY8sJUZ* s Tms&Y3%Ś5<SNMiWjtPK%ThhE{ ydxf)N!WrtRWYS%=\l)`D(ٚk$jj҃~S}*kڡhn?bZ̶n>čPzL]-ٺh8bJIE~0Hȧ@Xns,̂HQC  `}:nhUMHm5>P5$]yJ + (1Oѹ|g2 4T#x'e*F6)}'<(cOf R a4lOD/C=\b(*w|z^Fs#?ʑ6cMȇ)!$%(fN}a֡ty&Z֌kƗ2[jB`t!6+x@ekrW2AڄY]ܗ|CǝU&Ձ`$+;S-~Ω9[K/ꨆ _VSQAksZ!j0hU-FU%=tϙ> +?)6{-Oyl>*>PZVYhlh@5LVYn4Lkr;v),7.!-~::MF?{(\(+(0y4n,0㰟eή!UU=s|!x\=c;Ê6 +Nc]<?G{5%zd"9L ֱDۀL$i9oa/c.*U٫JH0PWH܃y2YjI8 +@l̓>Rf3}6 aUH:TrTXnE˔ݒSR|éq,@Fz58WHcLu#\ |M?Β8xyjm&—;WU53[y\}[ΔEXBz]!]jGe-KV?yݲRJgvo(ˤ!8KJi@}Yȭ#9>h g?Ӻ'y& %JSҳQt>u,~x7=}s+٘uĸK_\ц[G7RMYY0soy.RDj YCe9s5('u{nE=z`{g.LJ3E{\dM(}Ȼ ]R֜б"~*/%mKH" mץԀխܦ34!#HՕ lT=T 0 S}wNBhI{xq۷3E15;7rU(T +B +99f7$DD00VlAc9[m˲39{vОӧ 7|/8:pШ- [Q0o X@Ⱦ6;E'5x-x;m"#:OÝG(0for n݁i﬌TՈ ܿ8ꄼ?f_^Sq<hEmP2Xd`՗ @ZB:D$\70|GFlfv?D l y_D iP`HKLK9ؼiY` 3N#P^F>y_r?x/"370i :{; 9uY63H"a bb wn.O;zL&ļ5b?gRIP`#,ў7ȔOYʨCa1`=h!< 35 +~|IJQ;3b!md \/IuTOh!UOA;\P*Ux(\6l&:p¤> ^و4` =B3DLH옙zH6j͗k&0FoL*CVa?ѣJBB#.(=ܘ褒D$Zd +4!я9%+1 'HZب[ty-i2cV7Ѻ9+!;I+-7Wg,d ڟ"8ij, b{X\h9QX4x (7b2A%]lVLOGj4G4m?9ɤfl\8  QH@4 U5^lLh-5 NӉYp9KƧNSJFzXeT=wPn@iĦ,p[Ypy,IHF,)&TDheqG+⡂/RbqIN9R E,d_M +j%ڙtFzȪOl<`l +*4aXXtdyBa+m@[L]J*Re ihsW'OS"Zvr+7m}qg HXkDfRr҈)zO,[(ӱvFo@U\Y*VllNʾp]OzLtEDjba)=sP^W]D1` +L=C' xiHc3>Oϩӡ&`;E"荻OJ7ܔsJ@gT>knn7w:+ҢX^]9_YN&-jE/ H}+&[;;>m'HW[//z],҄1aȂ[~}Jnb3Sl \~ާNI:1*.&z{2n0a("L*ӉPe3ص9\cQ0 6Oڙ$\xɨms@~L|avHgPb +NĻBaFXEGɁQ&6ڏu#-ul] neenlV.77no]?jx$ ؿH;3}Amյsri`QZ)Ս̙~=sVl$r^Υg) "lrqTV^vuz'&LfK6/uYiu)u6=)VB ^P +.0RMey_b!Xg@{kLjj:R?mNMĚ['o-]x U|abeRybzTijmfiܵǾ#WWmLO#MHw:7wv-i,BLnr~UnAm;OE+B 獄db-, V}I`uԩxghHv^~Ja#H0g&`@e>oR{~ʪ5\.3ɞT^ z9{r #aRݽAmH ,O)/\cA(@"ދ7¥ՓWJwwuḐNҩ9=XgP4CaR@qR~Jx}AŠ +t*.rA Sg}f0?*-R0?_].=bF񺔟Lnv r`pR ,J A.*-U[OWn~ggمPťk:}^cR"fa|^mf߈4֖R[4;7zj|vj̟CżWk1NI̅=<;z1@z6}nzX/#J #f dJ.&O[|`cT &qx3޹p řSv6뜕+P)xb ˟Pf<$$;Rqzu=7w 6vx L';y*3um@ㅥ`qٟq@3[`."Pit'WO_ĂYs/.\X>x]؀  ԅ@=rfcm4Zr˕Wx[( +ǟ]q o<3sU?L&ؕj[$xu"X];uߥ^+ PBe]@#@r*J^Pg×(v(AHTPCDs+LWJ38)bX\^#c5vu Dk Bq)5s>ئS3TOfiJm~Қ?MRri͛Worsݻuoo+kfv;+S7\*\Y[P[ۙLr,sDJ5Ps:Ғi%V*B*n ׄ\f 8Oə .6AFkv8QRaMF,(t:Y?+BNg"pit1g2s\"ek mr2A"Z]ݹ[rrͥzg3*\?d$'zא f{^b?Ȥzz c :c aMh%ZOv'<#r@݌ndj\ WH]VmTX3sZĆ+{7:l܂\M\*_'gB$|Ra}列1Y)-.Z'2P"`W읆N{Vv撐m#BzW&$^'SD/;U]J` zTr*u(K(pu4w.3yR)ϑ(;5n'W*]:#ǿ$U.aRJkb"\\?Hu6/0V:`4MHHv c7D-o+WOFLbF,'KhZQe3@Lnqp:sX=HБ:,!".!PqV,3N6 Ɉ\J6LlPldH+*SS-0Fu%jKmmAi f<噞:(]⊋-h0 P'_ UVe3KHGᆔ3 $C'8ukL" 5AGO̭^E'F._пEDCˌZ:lO6̺ҘVSB{.Lq6n6q3a w3N2HSXMHˇWinȕI>UM ^/r].^6݌d.{Y2ɒKRu>!Dlv~YnYQHb'$X tw Z-9YTJI.U-Ϭ6vt Ѧ_Hu?R/M1dž'):jłZ Y;= IJHW:d=S6*~tv|1l^FFޯv0SbvU'`n~jwRA+92^E +"eD ҝsL1 pQV3]^@J>uk.Zl"e;B'8<&7rB9=6bXXJTV#e${&\31f9q\ܖ2veRTFoignW|ާ_zoß~}'|*;IuMFbV*T+zOﱵK7O^}pSw|7yLnWg01i#CR1DmήLnpw?_ݻ]x_֫{~m#B)3.hˋr(U#J(](O-uO7Vvs]?k6TSggt6xXNue1yq.^Zt؍fv~[߿>KZ7opq,))' 'l{pj[xϿ/w}'nΟRK. vQb'4c|&lHd{#J ?z|=_}c/v׭.:'tV|b,Bf4s1=g?7ɣPyu&_33#z|M\0Q%X:{7z'_\9u4{6̱qkGL8%3'O]<#O<}>'~o|G>]jkӀ)D +*VL(t]>8y+7o?o7؋}_ן\=X<_܌fl,[->|^ywo>z_/>OϿ}S| ٠ʖ[+X;v#Ͼ~zowއ/_oxv?Zhe╭'% ɥ}goӋ<+oG}_}O_}ŧ7`qF^!ϥZ/4'W__Ko?y/^R`1+e@'r1omcWy⟾Ə/>ͷW|??Ͻś\ aB{1!,ĒTy1v⥛|WO~7_??}O~Bo=V]# m|6ϐhGH)U+KW|_y|_~_ˏ~ߟ7}:Ɨ~'_OAw^z;/:g*xéRgzu~ece}w?/w_|go}[?,:)e1Aqtޙ]ڿqΩ+o[>ݻG?>Ï?zz;\pj03ʩ\ _[?}__~˯«/Dv_ȊK|!&b{zqc#O>˯ڛ_?o/>?Ͽxwn?Lj¤139n$tv"D{gyx'__'᧟~?}/~?_|[lcḡ2rC{{}_/_:?~=[kT8A`nZcD\[nt/oo}'??~ޯޯ>^yu]>H68!^(z"OBZjL..\vփ7vaD>ňN\a 0./d\iZōlw:2=*I2=2T4I{hGR]s맢d1Z[]8{{x>}g?jӁp g]]рc@x}Lc:Un۝S}w~·~Ώ֛<^.4fXP4A (5az[]Zݯo/Ox_SkzC-Vm5fr<^\LPIJ͹gN?C>w>x/>_/ӏ\:)孈 CNKr>$[g\tוk͗_;?x^z^7olReOԺHAd{q THI,\~^z|?{?7/?O3q DH~FMB-)%$!i~qZͧӱj.hv3 +գZЄĘy`6bfrT$^HKWɤJ%/tZn& &1ZA#2nG0#f93D6I r*340J4'0a&<\,ҡ€PfD*5ɥ3Yф BcAETtґ|}S0H4Ģja8ۃ{)? HY>\bum˫-"TǬ@&'^>ni-Hb|8|Q!V`@C;N莎5n+¡T,B˨N*?Č W2a9C(ϴnG'Zp~^>ivPÃQk<ݳb;,zl+R%[>0h#ΌF'kB$[[I{tqd|txl<0a1AzvQF3AٌQ??2Wtcw 2.o 0.EEyxvtH\B+hOh{lr|ҥUħ *_Ը ?ag DBJ}J.٩$f\ݷv*fR8HExfP|VGӧdt@uRiJi˅u\ k#0hpbq|brݴ/7mP.Q\|1l}u +hd*" (-*qryLC4 %?t1;3c2!Ivx1qF|ύ8ro *@A9+.Y etKZτh gb5^&)%!Ӑ5{yqy:: Jf:젭xȎqbRF4TiO  ̯ Y +2ݬMⅢ>n"u&?8[L8F,>3bpac_3b@e_/fQsӍ+ tkw:J+THh`&0hF;6JV2a!T7R=l,۟DYOEJAc#f*7b`~@u5#ի +8LXr +czذupy~j`c 80>3b&,,~L|eB%Gw 1=4c02||9a06U)И`v&TY-JT, G6\9>&$%qF[:=O{̢lOO4B w7wq!OH5))x +-Wڦѫv_ + (u>Xa9#`{H|Pէ4\^AA+0Jrs)U< +:ψc@:Ĥ +2V"rhrt1b&O, P&Zu7,?0n3:&|\>2b75zu. +K2jJ DnXSrv$dgAwQa 7B_̑Z'?h,NA#B%`r+Ֆ_96nWҀAVRsfH}.'mpϕ霌nPyd-:6Z &l:\~Kr)"=rY#5)f;lah]Jy'6g 1wL +ԅy>FdXn>`_kT DCȶU!7eÅlkrM<@C Lnbrc[g?M qLj蒃*2+Jy/fR(:a!AqFsgk /<oM.fN0/VbݽxoxhvE+x(oeqv&Q f$GB1 (-ϯRJ+la3^@EJe5-EogF Ny|#$5DС I:F} +| 9gB|ў6![8K6rad XO@LkyhxX:1l;n"4]4?ju[^Kˡrm̹{ěԷiJms hn&(P}8T0)۩(7TB'&TzQpTV㍭py%܎6̜ <6 `b9[nn5:m37 UvZkdKv+>wYI9h7ڿOywL`a>TX\\)M%(Փlrϑ:MZYN57Mq{/R H6s +Wl;SYލ*QsA3!Уlj!=PZHwDW,6Vf6 -ᑎ8\YʖִD.=۳P@rJ힝9hf9DG4&b)b3 :+"e$z^j|}vk ϡ!GvƬLK'.#T3 C9Wq.eDq+ ~l-}VҨt' ͈XXd Z9 =v\2zǜ,LRP!+df5Ra'wr{8c=N8Q ;l #i4XV7}65 . +zHfc?4jA/_ +:sqLDKR2`AB0Fk#ջB*__94v,Nn30nwI"Z)?MD:pBA~!bP Jrna1KR%IMQj˜=pc@R~~|]m/.q=6=\^9D[P0c'#`ڀ ~x)H=H8 +/D|Cs/&OWWa;Pe3XL]al{|,p]BGp ;beVϺ}I񈤔[v ^fŧ.=YKR7Ӟ?+|&Ѫ 4VҔbH$14f!GQkm+mB[ +gFqL{6Y;y.^V&,?8e:7p>g#`(d%X_Z|:|+C߾U,ﮮnwO1`n J$DRJވw~)s}ec (81Kdcs*- CԅX#\۸+cuyLU*'=oa׸:"pRVwpq5߿XZy*/vg6nX$QҤt"&$@6%닄fH]goLoez+?ި; 1o|{;Tt#"RJ7Kci!gU`G$pN{S.~)Z~C`E@H} y2$59ӋZZw2Jz<ɯ:&!D_EN ;q74?4%V.NKf pVdW*xbT׮N3vg!.EjUD`5dY?TGCH)zƽhซs Aვ0$pTէ"TP sJa0sjnԦ󇼞"1@|a- Ё2a q|{l9lƬ#bU\PVTu1;!ZnT7h Uej3U[zS1p0{1$>O0mJw +.fx=xl+j2fmf\GV/FQYM6rfAemZ4F3݋]FzKQR~!{ʄ1r.Yبk-4i>j?i3F)9)Rz:e֘猃33^.4s -0"2>Ror~`ftBlvav~wT $]xѐ ;1[|ˆ#.f|JR&L~K/UmBXYOC8d`A1g0(y^~6N΋P+UHJ)J^ni26r5~u+ZZx+RRL 9s"NϬ^2Ӏ\jC4!⨐q#3 Ã|L"SC>dfww2#Ap᠎ N$%Fi%)%5u[ GVAM7(ʆ',z6 ,R)q;Ncj _0peϘa 2O{F(0*N$$,B%PR/FyfvxY+-cr6Z쳑x0eÀ1fNHY?mm;@KM~{Gt2og|{bS 2T3=17K\{']-j 5磓v~gy‚:^"&fJ:QIMy'k<-w7FEbr F#VcuMN(O @䂃FmNĸÀHKTfU.t{(c$(f:n Bd |sɁZ3~`B'&u|쯏;cv()9pJb(ՙ"ATSіSklw7=򢒟'p.[$#'GmCvn#!KuKGq$2ݳ^p&$Ά +awQmVe2ꩩ;d8eF9'ewlhx78 3g,%$)9}ۢ#%)3X%=}rw{MOHy!"uT[g!ȵjN\gB]ޘ! J~lLLlՐ41-TbFr?,~ [{V(dJP\u>6874 IѪZjo: KWh{xq$f :.3q2fC)@PJI,nrkhc)]Tbf'?U<3=ᤁC4Psdkҁp3#f'$/"jbNXŅK]# ETG !R+GoMziEkIyvYqzpW,5L zψHN 2H`.;!ī ֊X(̴lhvH3h4GmPZUILgkr 98C.JKnrR1/ύ}.,d8ejڅՕJap}&v2ie2TRH~+4`), lfEP7s9\ #6 `Qt}z'_ʔ{dhA>6ъ6' Y;vB!a!zgL(P{6ugm>u1PR /c406@T;5$2bvS& ^qЁ|3sGY JX>opA S!7!\ƒ*`Ϧbr?N1w@`APȗM!)@=Z;eFl3:ZRb /1a\}n[[G~) I9F<.rP,&;Cd0ߞo݀䤅)e.ъspg Wh5ux߼@UAo_ZS˽'>M;j%U3΁#]1yn; fi~0vrN^])٠"TkmށRmnAxA! fe+"!:Ƨh5aç>ұIׄ1W+gcxkEF飧]~ + +4+Y)S@]f%Vc7&$pKw@7BLMm'Qۜ}$ +ӻb=9(|? ͝2Tc;gvzW|sԔU`&8[9q1V/ >wN yQ}̸nfmu#bnv.13|2ctTIľscsNBq +$XX5"#"50 D~@K:H|k Zv,$>.f`ĤdVT ?^bwa|•hl{çsKrN|fBC*t֏d㜐YQh8դ;6G]B8?ţTh˙1&Hio溇ɩK`Kzu hs);9piqSF@@%@zŞ[AJ[[ 3[wW./}˯ 1˸\&Ԛ205R+B`YG~1vy{;w&gS/'{qpx[ ׀nP +'<LJ:f:1 RLlWPH:DEŦpA/́`XktyuTYoQZ FlPE"<3FOPCVtر<BTsqn٫/w7n[^ {n\5{:W..#Jaǻ@A17i)p[H-t6&lPX3RO֗xds-vBjTWXN6nO_p!o`)x ;1/<{p/Q^9ʀv8{6"Dʊv4u;W_gXlqvmAsULrS&tTXZ^MNDZw$z=Z^#=ue{ +}6\9cNM"* L+%fl2 j:"a1Y +JĄ򕅋+W_K"%2\RYѳ/;+W\Z`Rl^j0a:92S̘c'Vh+n#XXk zOWo[ZVhۭh_ +WSWڦ]ٽ|PM:w3a+ĸ/@>*l l ӊdB٥wPKXk0~gAeM@r7(Dg/Wr.Zw6=;|9T] Rr=+R]Ii%KJDU?h6gq`k~ȱaW#U6RN6W[7ښ6V}dQ]N_׶c>L;8=dVY.>Wfz}_; ݝ;xOl8xW' ĜZXGS& KS損p @#U%RJ^@Iv]x܊kw-_*"Xe }bؐ AU*u;g'ܰ uM[UL0&x+L"jKAiB}/7ےrW^?|W@X;U\\Qt|hLq&7=^/g,~hWd~zEH5zWK#M%9՜h%6F5\J̈́Eb7Jq)a*f Jj\B f[DG}|8Z[l=lo?,-^LuoU-ݚ=/f|kAǤhe)OzHyMHLk\TS  %o \hyeҍZ ûo~#Z獪pԩttMB2U_KU޸<6wn< l[N Qe*}!=mz/Ֆ/JːT^87KRމ^T8S_le5{%D;Ll +UZ~KwR6js3PC%Ɲ }5MpZǤDݸ$jW >>w0^:EZf!¹Pcnֲ\ "6'jP=Mo91^϶Mo]-xj9:ցoTgvHu0EyT1', )5"@|,j\ރopůSxkwjhƛSW}Ȥz",,%Υg]xsw~e' 2 N@0~k_ޝy\YZ~s/ aqp+?^pE-`l'w,6ݤ$@P]1VD'ՊfT䛋 ϟbU=5%!5(5X,|ƃ)gE UG>qq0U  h !f?v zNIw*s|It|3/^1#&Bql. 6pW~/}}{jyI--مh}zo{S;OPJ*ܬVP=\.n)-Oj&fʥ׈PFD`~}:ڱN(v8,QJdcT6LB}vv2`7a„&CE*\c5B̓@y3Q[Hk.L3& Q猪0 ft?ا"m,$%%!..5OcMBJ6ҁj'F JtK.zړ^~ޅ\򠻲{+Q[X?m5g|^m:,5W 5;w5=)%zqQduqf X5d4kBqԂNfj 6{'#NIZ#iDWKKrc.k?`HM8<+gpG&'juv0 LIB2Lt0ɀ\EA"|~5b]Рi'F^Ip`bJV0' Pz:Y]S.TzQdP`~0\F9 vHC0Z@spdָH`H"%W6Yl29tkuSVdxṵk +WSDSų{7PΘav7 T\~%^H3X32Dv??b}2f#ݰ S0b"N|̊#' <2gC6ɉcvB(n]{I R\ +pq`8dckƋVfĘ%XCm07d=ELkp8i9F*k~$hnu1GHY44C gM~䅝~\T_ H:ͪ.AxE6;z"yx%q#1ק,@a+zӃ9 ۙ1S%s) a3(a dKwz8h:'ː2z =Z&'M'X&VFq"M} +bs3iɸßqA>\C w +x0tuFp&M.` "+h!Dj%xM&b!5f1( &z==3%9^ʏya !Bp:\Ni$*ɵ~Vpn'ãzn X,$qZUEE1cN O0bpQ9TpS玏;is8򍛉cgϝvLpNI(I=Ĥ:>dB0{=n%piaV x"*+˫R(cz,.jc'O@bO# L 8Q晈! +l;ztc݃WVn]?-e&CnO$,P*h<*ҍ!6= Ϟ]߽/>} HeDs͆Hlf=Vx̠88]nYK|}>tfׁ&4<+3:==9~@HPȧ1_ R~j+Ii%I1%@X ŀ#gHXKEĔϗv6ZRV?G^ܚEcF=݅#4'E xF1T+z|vͥx7?ޓ{{jQ$_wQ(%H& +CR2N٘f o\^{|;rՈƬvۄՇQAlr_|n>9΃_~q_~/?Ϯׯ}rʹf2Jr)-5T)ѵ4=ۊwSS 7_ܿyv}Hbs.D<5xĐb +q%d8B{(H͙/?8tk׮w_|x3_Nδ7H J؞nTw_>}vwϟKӟ~rmw!0>mxatBBuru<˯}}x?}s+4ngL&ZRgZ ]( WV2/_{vt;ճ?GaWv~勯mtl Z=3ඡ^;t9=\)n ӟۏ~r 7FDdq<2V/oߘ>?wAow~յ~!K +jz& tb6w+ Ϟ|'lՓ×7ŭ.bAc 8|>'d-RiW߻?~柾~_v~{iX |$滕vr]Z4w問_^O_߾y_o\\646nuRan.X}Uy~xx/?_?~ʿᓟ~Rۛ\\Tn$ +>/?_;ӏow|W˯ݧ>|zi+g"Xb\ ZFQ'v{kӋOGG/??W>{ҽN{!& K c +`/Kw埾z9|l12N0A2r(qgAx&o~??^x^K?ݾؚ堞e @$bbsXB"qjk:;xjo/ߺ+;_|~^Z~.e> +Qg(!Q*V~QUO7W_?_}z.H䶺`E/']Q2/ɊD}WfG'>\~_~ڿᣟGO6_e-s + +-#Ajh%^jpֲ/No-uOo;>|陂BNfx̃! CnfxTW{Rŗ.t"v':SGQL0AIQJX.D-T3ؓO^Z'O~-|xh3qw1rtP *Q8XfHHoA6g=^ύ?ׯ`*$#a}7s4jdo>T]=9xzsF䉆ۄmT<Hзf,6S~Oׯ\X.ϮO%ِbLĉ]iJɑr6nh Li]IRֹF/-:T#54 PVmpSh.wK뫩w}lW}O?{K.!8aabi(@ecj*e=uhD,&>yo\z~+^(6N"LJ*jL] +iɇN.JSA?smsz_E\(h!cqV1grj*^["PHƺzs_me!9EjU2p` +X +`Ae/rHF咓0|B.F.m[^޷ 7ژN$h%*҃Ų}<ZIup` k r\ǔ"5",㒨ZKрvB|Fl0+s2T$N"a~f҈MfP݌P3>4'"Z8 ++Jd/$gq=k 4`+"*Mj =&Aw@;ei&FcJHZmɚ4)9Ȩ8H7&:؍7 $*پ[m f0ID&Ml &nĄkrvւAi1~RXӽV:fvH +כzkF)TG*m%h5%?9)35IwhlTm,"|kcjΈ%xk?1u%3w=6uH%nwc- KݍkG\f+dovE0:д m^6t{'9,_]!>(VW!FeVzm,}U{o C@ g cj E/X""q)b2yXJ1 RPZWqy8/8Bufhu>ztKWig+QJc%W?nfcy5y6*WBi`zwJx:S4RKwww;K|,(SBi BhK.]uu/ïm?dOV|n~oR߭Lo{'+͝;272ǗӘ]˵cwq]y~[xg6/xW^:ϥ (9Fg{}O s/NyoO[u_t 5i7ӷ99 +嫤n0sti7isaF\\)sO0(cPY5[Oiz=ʮQhB)šڐ0&qwYrR2!@ujvfFқ?ZJuX<v#4c88{ôI]ow]mzNnʢ6{uNJ˗sǙ֧z'9xOO<ߛ<=rzuF__~{vk{77iΣܙX߃(_(+Ҟyó?XK7߸}@}ouOW;z*[_ٹ}8K{k'VXk( +Xۿ|;wUexTyK*-f_8Ki(_NSB`cEF 27Rbpi0@`j t2<`ֆz.Mr[=RV2Kppcu0|>x/6F/\ _I)ct'_n}۝g-7< +Axr}svKo-O0ٳK3oN9T7] 7:՛4վw^Gf;,om&a/懣wԿ_?/mP1Q=%'㟯cu2˖9ojQq 7'<<]}ewƕ%`PWJmGGr/:G>Acz'v {84Ct<FZuaO_ۓg5*ӝ'?6Y1"iyEipΔ"Z1.PEi9:خ?oem|ADL@^OgnQ ΡR Ff)-aAzQ q2ҸHle!J+ڪ^%.@_{ cpvOޱ3>[y _1([j$A"#1}YTȀy1^iοN1e8sJ_@> +gߎ&1+TQCYH I>'!i%vhܻ]">LJX{+wzGjci2R?+5gOA fq!X;.hӠ>}Ny-\ɷÓZR &iMCy9 t"/ WFPݱJIM42''~=kHmcULr Z*)c|#/up; D&nROXb +wJq:<AƧgu|=^P6'۹XAKc"594)ܚD /*=VE)7ZEexQd1/ZGeп9Qx W fҔ8HʒZmVgiʡ!0[c0"s5$+L=50.pYMugq}vCfqZBVL*ML3^1 d`ʬ1Nzʢ[]2&5nE5OW#9ri D 7/Y=k^d$_RTߍIRl=ͷenGq՝Ԇ Y!L Rk#diWkO { ch.l4ؤڗ11+K8gELhfҤ[Ԍ6 vyty}wA%6W7{6U5( 덬P⫻jΥMgZD1ʬ;BZAXY,7),@ehRThai79ԙ]Z]n /xpУeu񦨎`S[Up59<6v1U{^) +k}ƿ2 Ɣi{W>]O E8m--oW­q0ǀM.k<㘰+O3Ty')v݈P#y=zk,lF;^3cژz9 X4]_! +HF X݇aQv4:gYBFRiY흹wxM˜{eB)/*o'i4TlfVR[yQǨOD}meu\s[O-z~#o#VNޙּ϶ٟ~ PӇixir|(7Dǘ$JF}\YQ6(v)|`ݙ8fP6OVJm_8Xc4.9zsw'v[Ɲyf30z?ty\7m re$ ^*bTn51ak@!f\y=A +j꘽ %޻ g<\P`\ 5iwS ݿ3-ô.0lf8f%soHRp s&N#YP_eV(MU05ڞ!f,WŌ =zP}!k</*,a +J7[xEFӓrz#CyrrOҊn$/'1;A&ʖ#i:r礽̉HP êuo4+[9?@AQJO.-9I!Mopc̾'亿 c%PߧؒLڞ>+sN'X~43zQ(8c皈d:~3^^&H K)chw VF>bKy7N@ڀpQhQș@VIS5`>'hAtBN`Q;/hgb.f-Hg&ݏcOcx j'KZmqLvR+Ƞ8e*r<6;ӟ3H Nmq lSô:c E=[)UҚa kGE}=JD +2x^Lռ ϗ$myHQP|y4#˭4`Y@$'n'@O$l{(BOs0bn$'Sfuw#Bzo@d׃zȖ(k1Č#z,'e)71TmD0QǔΗ'vq-*6("1.U! BߧWo 1 oNʮAR5PDIArKgxU8s(BnQ; bp%"B^ 3s|q̆ȋ8B`U:ރG7דl0'AI<pԥH4]u"j/{Pe6Sl)X#H,y7Nu*" @LjQ"᷸jI HKvf?ݭ4%U֙8E.8(n=H1FhA:KQt{= A&h(1Ըc\9LNtaT[p>>!>stream +Q^H7ϕ1ͻ:ϰY4ΪPʰeDj,u N5j +>%Ä~ aYzBm2ybA2&IV6Y #L2Q `b)KYy!`%ZYzj$6 F/Ina6. +{ A9ZG,RL8 Grvw1} +/Z`㠫 i@1[PJ})MHQ8sx3~<\ǛHgb5_$o2z,KDCō+G.w<}}33`ĄfAh8IA3 g5.ȭPAjA S*]ȓ0fdZO)b?JQjR#NX }lE-/HpBfQ@vQcP*#{_oNRu1kJ+Gq};CրT;g>leU^ +Y0Uy +b-RNq9lW9 Vv`-vf=r;J16<ƗZdJ=4[T,zLiZ+0sa*9$al? cL:(HsCX$aA ͔0mΊBww#E'li0!g.uLN7b0.&,F_O9A#ʞI}"krbXFcJ4k۠m###5Z2R?#_C- di1^lLPAhn[9gY B}E8 E0,~dKk$-t" iвl/g Q0CJ}Қf@lK{˔c Lrd+x*mX>=F\o<ƏPc8$nj;Iq 9|-^:]END qh{`{ƶ4$v.}_1qF" N1D$Kz$iH`v' +j:W>!(VSg27Υ}ĖV L}Ƿtb|`;gt΁P3hxY:㧍$S<@% +͍4lԻl~=Ξ .9nIH݃,G`:@A'H,[jY g3ͅ>H2;@(q\qj%lݼ>(C}>^D@~$,>G'ZmYU Jm1 $/\gE#K F;rVY =ꩵ;Js{t[}U +P)F>Ϋ~eb2T՟g/FW?0!VLP,\}Dx It7,+(Wb!6"Pf(+iP@5!(OO&I?ɓ8잗G1f8*ՙ}{u\"`zB?_.r&k.e4I F Xb&!yXK|kvh}ڣsM-`IkV  +gVcK*@^dW;{W\}M%>@0u1 +=zi/4֙:#xygXҘP9H XTG㷓ǿ*{ D0ͰjspJ1k/6bVO:XLkI03.W+co\i{5ƞ3\|;һJq(^*ʠsyZwfVdHKpnVA C8sSLk$ bi,'1s#ZL^ߑk{\e?6.@rVxVya*bevy+ 4-ub!K*d~J $(7GI&/S=A23P fe6XѦ%m.+8G#)>C@uօ +zoq'9x?ˢAF)iekq@T@0f& CU"]LjFWA3TfG%PIEi'myABAɒ\=(_ҕ4J%M;~ym| +ZzPyl>"5(0fiR=+ӥ,E/X9/b #sZ(+g)냜X!Z{[] -@03ӇQ/*-1ac1M67@Icky GckHZXVr]gRb@ K'yJ`sHk^>U) ZFaŲQ&q N){ 4s A5u1TvÔ.͌2|j ,4Ā>|!r;FU_>GD +/ +9VfV$o6| rǿwƊga `6FEKтf\m H;]CT=T r;7&pƿFje(OTa4"1Sc74pGHT鄰>)BҦ\;\]4Y"ł%ھq/9oAdA_)(iof1ePiy!3D.R^p~^=si.Ἑe,WҺ̈ݵS|iX'9.kIp^@ 0*ox[M.+*"96[GtU쩍j=IZ4J&J @>uf~.TjEQP1($ "0J}qȃ f[40[9hⳤK)ė=.(DFȚyqd̓f$T~\2Ř5@?s͌ic1Wv +jO</֊d<]Kj-\'Y|~XWZ%Rk]|+ Y$A4&Zf$R@ZȤvd\2$stfm??ˢ(|*Mdǭci#ݏе`hAT\ոe0#d«`t>V3?j}MbǂC$HvNRɼ _G2p‡ͮ}x>ŵ|M>)YDP-y+ejrbQ9&K1ǘCVtE=}4L9TE(T ͹ڰR3摢7ch4w)g; ԘdNqNQ%BpJr/E +(5b+i:*W[K~f JI!$CE-Iq̉mD +UJ QKr0aPzWB%n/R+Xb3y1ʉ[I&)B/_L1Yi F5#p`YCVV?*I@"EƄ PNĤ \#i1^4pe4 + Z5c-Y[i1ScE;IRD V1е0bl9DP#%A,ŊfV$VIaFr0y%~ȭ'`^3Cd%9Ѣ9y+%xq (2n.{PK%L29n9)4LW/# |sf1LMޙF79A82(E93ۧLe`;a<38KvIku +؍nE5TCgG¯bD92zoF-XnLi]݃W +c +n 1z&4s('==zKLKgRQNdh&qCkQb=FmavJhĨJjjC ~PA @oF)(ʉcz(/B$DWi)ڡZ݃z¶iN 1"Nu\d;#P#;Y9 !|ǡŸmg!3bǔ:c'At;)DfoeVAhgAH`FJs0aZOʡYym `0 Q29B@ #Tꪕ?|'"9,/ j/?AoS(kD,"Tey-IҼY&$5(T%JVRrWqT:JTImX_TqUkugI.p5KWrR?`Aյ8b!L=Nx9o i (a& +Wٯ,vrg1sYy'3uZܪ̓UǦ`fNS|;+ۖRo`7RFJH~`F4n&YL+j zT0{)晰?P+KQT?cE#Sbz܈ ѼFZTςŵ0 jQІ'd:ʷXcXr-Z:bu,GףD9AU2 D Z(%1`q+oO +1ąi ,KΔ3 n+-o`NI1Wh{*#FOUvDŽ1I-?.<\` B 78% +ii#9*5i(5Z4sBz@hAqQTiۘG ^}Ǘ%͜-ljdwX1StUgsH:Œ)NR$Z@AJRUҘ 'rur4F,W{zZʝIԦPmi& (m-_dDXߗ !f7E6SR`DZ +0(#h(gV2LPU@P4qa'Bpd `VfJܷgD魔!+g>L< >5 ]FH2f i }V j&?Wg> ףz g V @ |FOރɍJlD rN:t98`r0IH,YqV夵eV-r\}ui +55b8y~Owc )ؖro xArG#;8eaLXP*N`À!Mߊ#F∁rѹduwfm0kbf CEɎ?=ppy13 2XJj>E$x'?_J|f@Zh v DIyZ-$;I-p w 2 *ڹ"%Зzput QCOy:xEL(7dSҦ/bՃ! dn@젨Pɠ:O7S&DRn"VA6DNl`#M NȮ(v7P'F/{Bq 85Stu=6`G41wBj~; 0yyF]@Q5a@RƍԸһ%I;?j M:u΀ i=̀x@٨lr^6on`N.`wB%_>Qe L| ؜́yt8T6TN'H +a3أSsjl 6&$5kԄ!ye> H0?lk) ]4E)7wXio!lr69AftdcVB$ hKZ@rh82ǧ-dbĈ7Y,+QXI7ew3 |;+pD)WsEYψ { RP <|U NBV:d) o4vtȍ +lDNA'fbHB0 n`]"HzЙ={DӨyDڼqhY=2#qGԶATn=IAZV>)&VI*Z2^naV 8(z%65 7\t (E)8 U~*AMT 6_Xcck<)) j(ۉnj.aD=2 a/ +4FF'm 0ϸWX(S5fnycpF(B :nף@fPeC<# "\flŬި 3L?(yI3op4w+O6\3jGa#'W7x@v7a!h +l=̠z VFNf ӻ)V#_£Ӂ]:ʤcBRĂ[V68`0{ s"$-pR'vmq=DAB]|69B5*P.'WǍ&l6<#a0,haPu2uO0\ nơJn,/<@bKy ZG2n9<wuy=ԢlT + npdO4G,bQKݔ{^is`1JBy}0"GO)ȔFK62vXv0q'`*9(l7ǍN+NqGڃF_ܟȔb>AoOML` +v*La7;8ρqE+ߴc1^w0)y'`@YK02$_B@LX;YpP),62aƢ&_HޅG[LѮXXv +(wFNSnww>h.XW9>jlb.[50;u01` o(؉;S. *`uyobf*n!T~'V3-+.,y4N}fkś(w"j,O ֢F4 䉘(ߔfods+C*˘mAqHF_ ӈE뀣&$Q*p„..5b&1A'8SDJ"< p#Nc)3at.O >7iTr"Ep4ܟ&2aQ[(sPYPixΈј Sa bDC7k2ВN࿴5CG# #:+ѠRshi4dP|a(*7nZɴa3v:i..k%RLೣ6~́rB622p@mLZPxvuyK̘̤NR¸R6&nne$stlWvZ h۔MT; IU6qˤyH8vޟlIDt:na)pNE!,)T7ɨ'ƨM!.h(xcDѺa#X+b hu JCmA+n[njc mu4Bq )=IvGt MXGa5 H˗'-섁$I@Èڣ3{̀*GVaFq9`]0*=VXt, Hu׹]^1Z})3U>[11иPÀ7 Cep1#aE!.ͦP.\zϚ䰉9;=ŗ.y"f"eaQqѹPqLB% MChU]\tLfxgDԢhWMjJ3P@0thc!3zL1-(`Fd-ԭxچ'_Ofl\brK26*#ʞzG3f z6E qJftHN`[ ]2 릋FojR0HKX-P6!VULgO6á[UV(p[Uv0,MHx@j!k['\MTfVe6?/P>guKOZ/TȔ9M8O8t[& FAMpa}#R/ +-2(涽.l=t:aHVP]E}b'\L H"d&xh/8`KF" n>a?Y &: e%Ӹi L%dbd盧`h]Oǭ[IRSkcMN!Sq-u@l`ÀƔ`a;2VOhzLL#Z`< &ظ1xz KQو&-4,BҁEeu +HK[=2h +pC)3CEz'42ٸ 2#fW U&Zx(O6nU2uJZԘ7Z7T8ѡ)ψU#SÓ@~ArC*ۨ 7G4Ȅ W<L@qV6AJۉ? M|z +EtvV+h_R] &mG@5[1rmfvR{ՀWNHY8P?;[ǬʥePNQryO`2 &_Je@YEp]eJb#SPFY8<:[P{#@A+/=lx Tt\L'X"ﹹ<46`H}YoG,5^ +۩ *tv8'$ ^Lz[ "VT⫓C6&f_AgtLddtlJy1o`JK8,ޭa=GfkXڈ@VS +Cu\CUW]>XP4N/TEE6AuΠӺc&BD픴VP0Є FvIHUHƂFP&:RzwNUZ?:!(wP0ʞ`~$gܒP\7y0q' CImDRܐCTupyb_o p"X_Ae~ƂLc_.o࡚QbQ"35dbn6I D$jq3tZC،_Y(ɛ'@M4T#<4ԟGy#yCuǭh K8"L'!bH7߀x +0wrUЌ~蔂ڨܔ;?HPGeQ1f zQ׆njJ3M 6Z dƎ:/KZq7 R齊e8D(B.6cIHu*s#7!i% hMH2&¦4 J1 0erI 9V90젃-Y ksP jx TV>j\vP~^Lz6T^ D/ٙ<#O#~П)*UP5ZYHe=&[+D#=L{Bm+[k쬅> +Ld-VP|ID:_J'iPu<@٢C1P*?C<4 oFH4\WtE;"ɺ ġ\OSrB@$&$/$=\n[(7lmQiPtp q3b35$Paؘ sMni-"k\bۨONjx_W~ł'=| !xt 88E/0aS*^KMo3>$z*ePq +\66EψYtԌHQѲt1qT,8h<2 'N61j‘仔 jY4ҤS3ܜ/Z"eDr-XX Wp9?EV*  VadԠԼR%RZJuwҌDK‚P\vHv2b%"FLFU6cDct"-Xt Mܣlnɟ_"XO)42[Rdb,dL A;|AKJKrcS*.J+Z J5,$$P;El'{XɠBOa&(BiDGzUh"> , +&ݳ ? tl,fhUh joR.QӉB=(gv[XH\l*)|ͰR -T%{!5.Tj)5}"?S\[;q'X;RY޾ںx}{FsǾ츅l0HuD +g׊s{͝ ݽq&X\=x09OÕ*Q1qyOo2%N5V/fO{>nkn!PPhk~yz+ON [WX9] 'ז \_ +sbvzNLA@GK^7,.hm5ģhm-9,C->?śkDnrmx +_*e{^:4Vw/$< |k/Zj%D>Q`.[[kZwCXːa-8Y]|9:D[Rq>\Oo}0ErB5"ޥ#bo7ZYR:3/5vey%5*jݼK8{[لefϦg.yX@q:Y6µP#Ͽ cLsnx4֯BIq׳C\}\gпͫͭk__YZ\&Vp)9wF8 fw -7@Gr{+˗å5rƟ`4T.τJ|utg +nC?Ht,tEǀ{7+WL@4ݺ6xn6nUNF]TM&,h`f88q &IY ;ܡ3VvSsʂ'2RiiPc@Iv.2x@JmP6 B nYE'1AOSOH*s|vN;7ϡ۟Ug}>@%|3U_#Dv|asGob68uwj"ʩC*Jpi5Z݅_d"zCAW g ^-zkr4uGm6bӅAm鼝N BKπAё +Ș1r4hEo.Wr dnt"雼 A@"!enT̗v76_pN=ڈ08 ęX}#V52SX"m*@نJ-DȤEo'<,;RzA4V +_{I$),m"xW1XXP* \ $ [eGIs]";RAڽR47'd/sIXs3t1 Cg"ZE[9v%rh3n>*G5lXȄrDJ3&o@_g[-)ߖ+z*,M M}B.69!iL6:E6̷wR-,PP*IEHuX1`#8[X1D>b#l7y|u{<}OW|?~'^Te)ו8gr{6,n.Ÿ \/JzЯ7W[Z;{vo|_/|מV0j)7 S]CXW`B%L,ى{ILH'KcO}'_>}r4{-#vWNk7Ň|o_=+I'&Gm)OfJ篝rǞy;?z?{=+oӟo_/}=΅ƲlwELU2}kO>s/w~>z}ǿ(Ͽuo}Lb5c.\gko>}W}_?}㕓wS=و)#N +jcќ](էgWvWo?[?}?O??7{ꃥ:Q&Hve?KxZn~Gހq/O՗__~_~>x嗟խ3Wt R V|"Nw~c#O>_~7o_7_>//^z}߱mx$Y[GO>3ϼs}'_'᧟~?~/ѻ':wDeeBLb?[>x'?Ͽӟ?~oݟ?KFq#nnmZ._^΋o_'>z~ued(wl54Ĩ͙免.=w\tmZQ4k2NLYq3q/.lhg3ͽ{+'~~ w{U)Y``~5k߱w:/4*ݝs^=>}g? '/].-Y!QBtNRbK/S-[`v}mg}ǟ~߼_՗_z񙧾w{81+Bvp>ܺ]oOn4{FM:N*e8#Dju3_g{o?>.+7k.sa92k =Crf7/qڵ^~os+/?vNUxكd~s|o>yG?~n{=ns{== j 'L6a3+W}׀x?7ʕ6w6 ΘF-B;JoWgVdHa`=lpGZ#I* +^2!+Eӕ`@0kGq `%xh҆] $tTću͇;¸0 ބc:Ms [lMvl:I0!] Ru\H tH, G#r,$\Y\œTݝ˒t{9.!Y)? 俪~QnpR)+b񘼶JL?a yZp 2'tέs6 ^3WT^U._r1;nWkٙ\+bxB@m ,#6FoW>1 !RNjl91bp<]Frb[xAHR(%3j&? ц?Vpށrf;lTٺY>LJ23 +yQ"ctbPE(ϝoy&iFxeFTHeҹ  AS*J(gMʇPno1Vu.P;{Y*TOkĂo@ U$6_pʌ 40ݓF |&*%P>Mc6JI+&BMfM Bx9,Za ^XR 9"Xta!!qlnC?>*Q2TIgR03:-Zc&DR)P :7:iNA +t2%2ٍL#齛Ht/c[H $'ER*JRvմcckvv؈*{@0(2<*E)s^}g!k6 T~BT4,[KywV|.7D(gq"أ%*V/]bm#Ng,'6-A aHbI-Bn&Ja +z F罱iRfcKvyiF1&I:k[+YXjNՓB>, .7]QoԪqBglcpk[Ĝ7@Äf56`f=%$E9WLg\AADKrE QӬ%48cA#jR((nz.c)7J%ImOnV< E d2XQ} [^"d6+&U" +su3ynlDYp#8kxkז7g7 A&))51fXgV`Hcέ"IJlXtism :0pӏ.G]@3+.hMM)*T+@x斏b5I+ |!Jۜu7:K-!՛+"58~BgzPx*ΦD7!Qh?)D›T`>?u!/EdjR~ 勹3 F8A,k1&-TR^ +^ oۏYZy#HW"a\KiOH.!fQ 9D] Q*7یH\rEgnT*?zg*&2䣁&hpNHJAŒW1pIe|2R!. n_ZQDa%*Eu6mqЏ[>TTgJ՗sT'Z좼^B`o-G@5V=C/Jsx_B (+s+Q,ą2~^qn_O^]QK 3|yO^;rm6[/HeD\FSKÕ5!s^PRMzZ^V,L+jL.VMaN !8a.C*%1v\CDĠ|X:f fASDb𑙈Pc tgG2D ^jYcq:Pdw#rdُQ%FYaN(Av-"RYtQ&RKΚ zƹ\/(Y'%7-B-_YN||W(WU4e:nEB%UT0f8?~C}jk42K!|9Qa\fчXcI7aT($R."3y}Φ$kmsBz\YAHk+ѕ0M@@AKKv)C_͊!eV1q}}u qW|+!24{h صuпEr)+]$䒔щY!7;fy'S ׃ )G9Rj~{]M'>@PaFlegE~~~z槈\_՟z!%ø$0mzǨ7!HsiW6TuLmκ\-w  '؈PB"58SFS-N#|bMgQ#~܀͇c&jiuJ.3JY6dj HA\yb"bT,FtB,`Z4!:H 2V¤"nG3X~\b)\RdzO| ] q!•6g ܄MCj0 αq#(vߗXy{ΨV`Γ 1Iy޸HkUȚ; [\KImp~`ss|%ElRƐVQ6Me?o EgIMi7.(@Y/V<fkIM*KRYnL6FgT-.\k08uz(/ك","T̪Xڷ:+hkhC#PQu)'<jjg? >>m+Ug]**LVKb;&@ل^s4%`2!7..iP.h(ٓt^.0" )?}9r]s^F2:MHU걹 Ą,TXCp{;HټA_(珱PlL!RT};GI9潺~7T:CN{ƵB(]cfPg₣U6KFuBoaVX(i1$S5\&סXSVK*Zmhn%Xz;y[|Nfƴ= MV/1Z tzOrV.E 1g% +>wwx}8Ý˥UgxRXXx=|v +&L+.1K!rUn`n! ZtbRʭJ4*ע%LkuB3鶘ra -AD^u0aH$:'8Dȁʫm],$!AX* gzPb@,f]Rn\\QϮ./O|FR&=QhgG޵Ǚpɳ'^wFwזּw+Xjޏr *P@")ȈV#bH*N;ʛn{ş|DM3NwR͏{aҭTif3fjO.<PrBQ.d'_Teĥ\Z^<CknJ{Vg3C^;'{cFnp_cJό |nuj\\,G+Q!eg{<ӚVO^ַ2"{(g.Iz_[},8bg|sOA<:~u3{l?݋7`pCl֟\җoy>|!¹iΦK&ۘ\h՝߬>+ Kh{@Oqy3)y @l&tO\?0[:/M(mG qqGA+S(pBXc)̸\#Q-o@Շ:?6kfz2|E WL[K!"|F4m\}MZ༶XnKvuhT@ EI+^u%e[={T38bsmqv_.kӣ_\'Qmm .=|klelHo2/7|I;鎉qwfsq'P!"aRHH5 +ョgq.d/@FyguB"6Zk@l0Z͎X+[AgyrG(-YC0Ԝ]rk1p%d7–T\lj\zlp7|=|t +˶jؼR>+`R*xzc!W f ΅ٽHwP!mH|hCy9C4W>Dl^v#k=D6F⺟4tˏ(5ΙR5\ p`Rk֮jpL[+ˡ[~̇L_ܫn= SvGnO~?~_Z{9xW炴PZg^/ZN&ӹE8H!nN5֞čTy*^Oϛ;ۗ3)7J^sX pD5 Nh>@ٕ3)c U1! h? eZw^?پ;!YMKdԦre#HZnDbu@"L?9Ј0',&3ǻ_޽( +A*B8WHUJVZǃf[ )q'DfԻP"fcӨP]JyvGwW wÍE(;Ϯ/ڊF*3M#TWo=1Ň>Tsylol&,=kG|aF3"xWTk@@LOqh +%hgKKq V:2fwRo8 ^ N^J!bffdrwylKY-L@4] ч;SIZ=@Ecr3*t<C]>W?FDZۄP2rjX˛R2ٽdltC .4;HFh{7 +`fQ_{kgsDV3WTZcd&@ށG  Wh63t_ͯ?sܐk>X}J[ a ̻ ͇mT=X'!߬?sye9j]YB9ydr͍,FE? W .wo(oAJBG\w + +QR[ MD|Rk2ɛJJCپX qn#j RP 2M>tB[եȼPBI[d|11b~dv~qR$ G%3)ڬQ_s#&"b.f\ %Nk5\A.D,6: Cx/jF'ڗA1[R2e{88)nvQW6r;4ƁݿK{Q]F/G8a"MJU;Bm!3B?YpM+Laa`| L{Zۆ +IH;fK[AvG.cvWbW+NHT1QbRpz`PG;Lۘ'Z\aJfpĸ v t6H*ViJzVޅպIMS=s3bnW ++̵G;6q~O=LϊkPկiC$#2&7<-hV W˩Fau[޹\Z )PfMQBaD,x~ܗa~֬^ÅJᬓV#JsyG_?x-Twtmc 0ŋ8f~ _5Ѭ 1oh&w_ 7]Yݡ1Y1Tv2ܿ7={q}98|i.rݝ8Պ\f@m$2( &9lRQ%Qk, z1P C6:9{5owa`gez6] NV 8(bu§2Vf2->ۭ??Otlͽeyt֟_۽bl_%gvc4{B卉~rbdч볪3?X=z!.iw.9c? +\^F=X`(u>JZ + `ږ8SעU;k(ť<ځ#R`}cnDŽw⤎9j \^Aө=:e|_FyUjKזe*\fsrK(Ψkv !-OVaɗ`RCl&||I|^s~Vf8$=[=sXn=پ'{O{#*bJ%Jg!ԍ؂#RÔ2X⥨gu֮6o?wx ı{Z\;'y5YCR&jG7|nm9"%45i)Piˈ/WB{ ӗxxzrdzt{1!^]WWGq!&U)S<~k EI3Hdd6H#HR[𢋳v| ׼Y%T݄M׷X}ݸAqI} NqbwXbܜk^T髋9>oO3]1gwbM/ӄRP쟪biG|^N\!r<*!Dd >|ɗlw'N:Q&ղQ>{>mC2g@sSR.!FOBKE0|n)洶lۇqЎdlF)Nԋ2VG_o~"1lzWKk/.UꓻѹRZlκA26"7j (vDU)%e'Bjv}/~'Ͼ ?>mo]|vϵ;˃Ta4^D$ÕjVLB|9XDODPY&3$' )%RAD̞QPe?>F !K)_^[6_!,%u8`?]^HѨi48gvI}Emٿ/@Cvghʥd5Zoٛw!ܳmp0JF[Lk[ѻ_)72qurݝra.Oe3e)E\lO)9S^ WBFi{1ZJye.7l\ٶVs??ONO~vXH̶bJR m 59 grnsdRBd2rԐ}4cҬj*xr/Q9%=?@XڛBIQ{εX()ŨwO +"z[Ndiyk1J{w JjI %?VKK函jd力/?o;ƒ# +o􄱆٦h:;O V|/0-AYńL7i#k)ᎊ ƕ8ƄBo= ҨsܵNwwcSIkYѴ;}OL7-x;*@agBos !ׅ[-*HU'vguQ%,Q +hEMrV(WG']C?(gPm9&j.ʋq u!jujNiakɓo{GύxѯŵTw^Wܝ-pcGPo"KuZ.إ016{<&{Xy2X[תEo>n"!*)@!<ḌPiy/ ^L7#|㝵ޫ\\0mCFaB% +zykŝ7A8oDpd:+6#ZM14k7w>l/~_;Ĺt'PrgSRġF ZrzKIY4|c#QI-y} oLMU)ʚm#?L "d[݇v~=}rPr/jVG +5h ߺOo!& wo wICjv;{d˛[äg2gӣO]xP_K!ҏka1+ՇJq3D;Wb!̄\L(YJoY5YִҐ˶㓣_}{jgGK"L6䂴k:]w#\ǍVA<3fk>:_}6lhWg-} tiBGblֿè +1WgWŖBT"\Kꮤ,8]G\?y_*s1-`i1F `'f7Z{|t7J~tu!9KwA}BT6`7T'CB/w΢ oOwν/O;z}#S8T~( /KGJq#@@3+1際ZpJ3y~+ GQ伾vY>K ζ{PRa^*(+Lg[fńK*u/D $ =ɧs)'oG/g.Oӿx%Pw +,HoRafmyww/?<_=lѷOk{jݻ?KЖQ3) t|fP7-c|+\XLHF_As ]lqU&;ST6Ӵ;ˏZ/Fﳫ]ݺx/AlVWg2݃M7=);.tLu;{vynٛ䂴qH}M_b6ߌ΋L0DJoj &3Qʇ)/'$wBLJyWl{48JaHȹ褱qvnǹޑdJÓMOD4[~pe|[ۗө2X{YK(F~U𒋠Q!g9.M/o&2pT|sKt-1r)8kZq3('L ҬEYSvK!==zlʹ\ 3'OÿLJ%Ii@R & 7vs9R͕(g7]rE%n r(v HpǯlIJb·{ng:G/˻/^:}{/ڴvq| +ݘPY PW7\H!\ƟQ1OY-61Z;wloLJdzDڳ[gpa1vXI**-Wh{ar%\J ,0h5/X$@,VkpqUl Tr٫v.ɥ!"Yhљ.aa((BR{("DSt9Kʆ)۪mG#I!g{bSO_8;8z?hVR57֟Zi׍ȋ! +6gsMfMTIu{8y@Ʌgo~qdHdp?= Y~={Fn܋rql-/S|!Ȅ 3fLϨ索ۜQ엯wFi-J٭Bt~쾠E{C+Ṷ7o+ԙ͇I%[DE/c -GQRX&wKvdp׿ScBo~/q_^|\Oʭ_յD +ov ʰ 8GE u祍O/pe{iv|n/f5Ǡ\jc+(؈^ kx?jPtnd:Q1ftۄV`UR.bzΗOso=2~ܶZ;_d' X7OYݓNj~~D%G/)l>vˍcT39"ިhq_oX;}v\/ +Nv+;6\QRctl[R %eyJv0f7!g7?{NBIs$[| QgUOIcٻϝqt犮ĤȚ9/Jq_鯞Տyɋ__BKΚU˔\V-4k5d([[wΎZ&7_xںi5w*Ռ°yOfSY'Ey%DEpg;`r>UNޜ|_t.7O?4k~[^f {Ӌzr΋F(olyP>ly;Oӿzo[͹QcI1=*WV}\>yͽWͽ{d|/GP_|wOm05٫~rTE.=P +hҙAYތ~X>*D +kX>sJy0"j2?" !% 6TN6 +JZ10TȄ >DnTV;ײ3Hp5gܑATIUg +&Q=Q.)A:]ON?im_=T㒚n[UwXJPs#R)p-9[z@fXBE͇W,B[IƤ2x+7B¬+&x#,~s©vz/UM4rzP);->vOz~L2!ݙ +N( 16I$o^u7_]6?nק/~{щqm 2{Wo!6 |cݯKUw:޹/?zWڴ0<;|۝gWhvZswGO_az;z_Kr!.~{S73I7$gG~ŤҊC46v?K5Nb\@R*;!+u)cVVJJs}Kr&V6Ckti+St'mF͗܉Ka "lN>vX%<[FN5Lف ^er*dۤJtkneT'~\+ Nv1{ښx͇LJT={p~Wx_bߞvO O?l\|( o'B8?:~yG,R >o=5 fwnaro{O~6Ͽ=T fpkzq' >/g+ ڍ1k Xt%7]=zf{1;B~XZ &)I֬õqiL(qՓj3- +=n3}9ɡQh|L-9o΁]?qQ=L?\ãw4\]ܹF+o| +rsY DiBprZ0_~_[Cv w_2Ag~kզ0s2+(_b[>nOy7!LMOnx"ƨ xkEgD-ܸ0̈jYI.wT*JRRvﴽpVJf׶lQ#Qh9'hG0ZQcrQ"Wd;v{xջ7X3wFrJT +'u&p:Dgsvu)DA*WB"t lG059&-ØdLikL vGq\FEw{}KcjTt (mBmo\0bf +-&S\fSuˠMxʖQ}tD賧g;ƚ f1)vы*K!ժ"¥#AE^-Y .7&tkճץsL+ѽ7Ns +n&݄Rrv4Y_ +$uTtPΎhZwq` YeEuIPJl?: +Z݆͖'x@MӭO?ݷ?0Jr1xH'i޹>Jej?Ab['Cb,+eP4p`T7UFǘR`?THF(&xø&A" $V*=gIMIdgVcSpzfch%F0%8JI6KV52B,)fKkyIy;a,c|k}rI0B+jؐ*1F3jō#g*`2c\)XC8$_̢$50acR9Bf +3g•j45 cBʃ +b*9=!y3I"Ds~:ƔT .:)(ٺvk]eUQ$LRPJI`RdsV(҈R QT[!T!/dYj<ɣ8+*)XI#D˨)(kfy]T{V(pR1LE3+qBxP*|fȨuuz~rV^^7B=_cZXʇ!\c2<.gQ{ƮQ +ތӖ +Vu3:ôVі@,/EQFRktF%tsCaQƒ ǹs`H|8c3(Z!t+W^G(+iqx);BBt`#;G:)n $cK(ex,ݕDke/ @LDR D8v7V=OrN9I,=EObћ$$1m#ה*Jebr|i t)> Dm9bRu)OIٞ;B2 +2#gj\cM͵"+SRx~?} =_IK. ސ)޸Ÿ)>P5!1&}A ./̹pBUy\IiXBpv1I w~̙gwziZ.BbH:E#]2t0C=k.E=tkn!b$oQi,PwAH3Bڮ ?5=w*.E>*^L! ;+揀xrK(NsMpQȥn\q\1szWD"H"iZ|j9ȕC'EDNPR"N[^z_\ +\X]wr(Ul;p˳ "jYrd^9ܺ|߻kTC) Ovuơy)$U!!)Fg A@,8rrz*vQNc\8λԜ SNWT2ًQ:7xYw#a\u +.o +2,rvɏ B1R`aT@Hod&'$+"x b@ BT<I(\>GF1=jdOׯڣKc#(9p}8]3g.^4 G$ӚPEPsx7߾ћW'˧fUpA8kl* +G\͍AaSXwݽ7x_k֛fy: Ly=AzΉ ;SSK^ xMd ( D- +fʶ|$F?w~ G~ BR/]?=9ڃqk7ǯ~[{C۶Qu"rb\h]4o֯sz6|>opT&1ǽ +cS"EXeG=ښjW.;W>|ug{~Ͼ}~oOha71.aA2Rˋh5RWkt+O uN~_|^}`$zt~T>s߹sKD2JLg:디Qۂ8\~rWo>}tor.orzVXJ@)ʊޣ|O?vdw?|_;?fNeA_ 0 (x ?*?7>ݯ<}?ů?<:W3fe-$ æh+߬ v o=ʵ}xW?zG݇w~>W҆pE/̇\A`` !dlqXbnnoVG̓[>z7~o2EE #Z V+>͟|7 Wo+*iCbXQ324IR3vu4^?)}탟|+?}?_/[r,@O(ZQWknv[;go?}ߺ=?y8oɝjBI4fKO˿?˯oQ}qnFʲ2Mws?}t9ڭ懯|Oɧw?xw?z_~ɏvk0Z Md) נ>;w{}ʏ?~?}ڕRH {<7r m~gO~ћ?ν~_~yvJ21ɤY{~_FyƐڣ}{7?{ +ONӀĸDZT&NF{G;럾|^'w;/pHta2GZQ WO[yow_g_yz5`bHfjYV~rq_>xw?7_͗\yts4nԫu(j"dR:M W~>Ѓ)Zhf\*IyX*NW'~w|zRV$ 1ըgQ2U%Ɇ[֕7n߾k˿o?w~gOvyEK\*F%K)fz|E:ܣ⛷O-?8}>Ǐ?}[/߾=_:Ҕ R4I$wZ`P]֝;ou븟:YN^[uu :8`~FPbVL%9] )5qj0OOn߼o4z0VAe*x!B[/AH<PE÷2x~͗~7ޯ?O߸qmUT l8@3_1^^lNە?z;o_{˭>sy ΀'ʧ+.d-c\^yQWG+|ǫvL II?n{?㯿Ow^7u\ek^F4!xQn.KȫL9)KV/sÓj+ŖtٔePqY55^̔!8hҵB.g2Ų%Y/FEU,j =Bq1]@BtPYW{kQM٩壕vM۩kj,kw~b*!ՂXrj6'gf=Hi[jb?7}J)ɲZ*a\9Fp,IU+Ŭ) +(&9|ډ*(k.@z,y]^9[AC`*MMм?Hy/>Ct&Y50)%QL4Bl;֚ zAɊ7u,mFoFӳywYDFK^+Vӭ~druky. +N*Y) rfz~{f;!c V+YNXr2c{ӻ'>RTR7Tގ*%\ɭ_WY= YTFeX%gյ\vR\) +AH,sLVNb[JJ!RŋiKS PV-HȍTMV7d +k|f%Q^gN(OiUhU2=0W##dWHR۸O&;^LvZ\v%!+"`%Wj> DISN5kZ%nBR=tHc͉TB2ը(&]!9k i'0G1:~(r* OsxjQmIxfܨ'&4008TZS !GXAj&*lG7'_Y.YWLFHU=Vi Z{.p`F@(K:;*{Rҹ%bbrjn,r^, 6'dT,JU)/PCVT.,"_ublpS"TjYC>NgרZTǍeLo%Kk{\T2$05rɏm*ji7NnNnsZtlF$\n巢j+`6kE}˜,Am82SnT%M1?J.۝cuYl+OK6˽WZ/[mL,NNrdrsJ=\kG +'aT~k hucN"V.o'[Pg +6JE*ytHXmD,_W˛!3f/c3jS'h|ޙڌ%zdz  b>DAk\JKA6kLdz5{yaXL:7){HWzہ&&fW| >`X-XfsEش5*A(K5@Yj|gF>e'+ M׺ ~zK-d;нg_<~v w9\Z@%Mj^Pi?mC1Ltsb/ ,Z@ FZ,+1- +iulQ*N$[Jq݉'axi{(Wޮl!v~sE'LTlѽfh8n4i%J:{jy$JRae|էeZla+"U˽+gB,lڽ{+7Z@qwtȉZy{p\a +?ZP0hZgIcڋI+46au|RXF:ooz`FDXޣs{'6 ++4I&TzEȯImp`ݔJw^L;J SktfϬGն34lX +EnPSǔ=9{7fL mG蝣;_z>~5Hk%3~vC@T|PrA>erP?VR[ +*$AiOkFXj[_]Xq݃#GRB 8€WFra tW0dׅ&k;O_s+b\!RXU;x*Tv`y|WW+\z7Jj[af ɥTf$Qv16a-׷^\>|#r)ncF'$zfx[QQzI.mu!Q"QՑzbXn׎^^?~r6,Z2z9xCTqx'˧ ?WL/?Sr;ᕷ[\l_K74Qc6uToѩ^TXC7fm n@k_xoNh{JikkdvACl^-m>]Du +[SnՅZI3 @>,m46)'¬wSykߑREgL.ƏƷ +^(Uɯ:1݅bOgtIVn`x%l_:zPɚ`wF4^Zd=۾``&bq3|ՈT3;7rk/_FTK֎_j~ {ZcxR]=~_Zjg_ܼX:mTQ\I]"Vc|4;^:=m +^-_5)Ɖ/+wbFA݄gbeVLoNLo^3+-=LoXSǦ:%j+4ִGWz V령qz:g47V{پ׺dytt!b@}wD˪O((+.gWn}wT+nnּ n6]EU7w Oi6OvdsD ;XQqdnkNTmWВ\p"m7ޑ޼\M~.T鞗plZNqRϮ{_jnc?ۿ!l\.vweP63k!Z޿]]tZXs9Z[3AI6d:v++RskMvZk7 aS1kf[Dqһ~>f}  CЎ `ɸ\, H^ڊeZu[ʏdOhZRmv!:zn * ow("ɥRujr~ƿїt7ZՍ[Hcqv7@sպD(g%]δ6&t7lɒUې'[Q*^V#?F򽯬xG]J.*v+۷A"b);Z'lah!"gPkJRL+7?ri%Bit·ݧWwE,bj^]}C-ʅ?[X%RN'O֯hT7[rn-z"y斯e(7;%Dbr%K1wUwh\bKȘ>j)"jm%#TElqx|yp)/ScѾ1,(0*0HPEl>XIDZu$5"D;?8. `$\.H7_‘ _}!bv6@z ]Fua!|vS ֛KIJˮqTi@`=̶v!{LTٝWkw# )w?nڸl,OUOi0N>_]{ Plҫj0|hHhv6/sZs\=>NVr3Js|QgKKe+*-3^h4jA Dfz3K,DV*obϭBJQ oP܈dJr@<NY]<KXF6vc^S\%iu qR4ۗ 2%ֵ=U~v RZ] K~ NPA:lCͶ)jAx +5+ҩ&P1e:T8&Ӎ^*y(ZLBձ\ZN3TOCR>;\~}Au!Q{EY3ZeW _D<' ]7#˅0P*.:'nD+z4Qǒm/u|2m!-W1'J~a媟1tǚ'y)PyfA=DKί\]= *NTBkmxtja3֖!b1&g‡cRL=p<"(3y9\es03} KLv/!i bO{G/QKhKd(K|v :dxM-E%Q{ls*@m%%)kUctwZ~Pjn8#.8sdsnšN6ъzqÍj@z벐[G&+s3n!u%݂w# +"LVQ[M5gDqj($􊛴D[)nv-\\B?Y ^< R~ V&'>F.ZjZI(,nK3! b84"bY)#i/smLmq: ^c'˦Ŕ7|q#HD#"!OLn&+kTaTH)my?7>Jyj!lYݾ;ba);\H i ybDn!E iJD)TlB-x?yR)-YK(I"Fc̺Ȍ ࡌ3"L0b~ `O Nh4$DV?dED=ē!&Td8Ɠ0vPW  +W!Wړh^*nri&e^ cTd Dqxs37gs"A<r;7:~~BP!dhk9%WU9mW&gp2yN{Ũ={TL@.{H-iklU3iV/. Q٣ 3,k16hm7vëAł^Llzd`m5!`:>ۈK XXjjaқ އfljeu%*AKì]^D|4 ȅP!(sRX 7 Ms^!-T O]pkrmL- d߱, IVC/Ciy7;C򬏝rz}F<;}Ye;̴)(zZ͞ωzbLDj j 3侹0% >x1υ_q"#F9+>[}͉|Rފ9 + HRFdBihRFgW!Hq^M+ݽ M! +^\Rҫ0JL ]+,pz-.݈DӃQ(֡\rvk;*q=6$ܵd%;(Z]*^)Tz_yCVck)cڲչjuۋ޷[DZ !jMpPּ7.[)tk/8c:*7&?H +zP-NHs%!8`"DLZWfO9c igM7Q.l2ғ3rQ,NDčY/$,BmZh'9^@(׸o +mW†+ns^-7 +dG7\ʚ P<O_KRjPhB`J5R \yVY0ӾX)Xcj)9ȭ할Xf+-?AIXځ4Yr!Ƅ<EdA(!Fܴ;̬Wqa5&TWb#-O\UDƲR7c;b`؍ɲ9n{LT,-D;Ul9hʘM6=3*/ SDꌏ;N9q!ʴv]4;YJŴVet{3^6f{+Wݘbv]o0Vkɧ{ZeCgbLpetOmG|`"<㢃|M*/""t{v&|v! PZ睸0ټ !&Q\ %P7L{꼗v_NG S#Q:AiĢR,1Qu)oԶsˇQ~D*%F:I}Yln( p1ʇhk!.M` ?e1Ng)3>09Nךt~#(U͓64xVs}'\B%$ Aٹj0[0V - ;nxt]|8@qJ0_n܄^@2>23F~RXjN?"{.J$rZs%Dq tc; +S?ʡT= + sddkEw`#ɕÍD+>Lvc@yG%?arSZ1 \{0+ze# +R}\-B1HV؇[^DJJ0!kzi]bzϕ,sn,҆ıd+h]fp dKWNR_L^ +ND `zsD([k?}#R~rbK~bV M8$(˅ c9L+m43N|_`q:<YriH./Y)g"6$vA7!+e9' OrJHZO*j +<:>K#\jQpV\)Z42skBqۉD/2rSyɊ^Uhh|@(y|"Ur?xN Bl`BHu?U DaZMdİd?vP7_\Bd 2PjS9Cg䲇̈́8 exA)$H!/~CtTIqyx0ΘqE:#bH7QtO;"bl!ȁ4A7a"0ǔd7"Qjy),>#r^T7&ugTKf#JEC|ׄ3$Fq9:IE@ )tb U.1BI& `\ R[9uƔK![#<Ѹh= {ÆVݗ !<}|H|H,aa1@{A yZA" +V vv>ޘ%Q$C<䢛8C(Hb$qfɷO.$XR@ljy\ yb3LsqqNkM\?v >\ +g{>ESqc)pk՟sS.|!ǥZ=@&䂟 S:V,v#BJa67s`h +#d0 <&*U|!&G)1gB=0g χx/i1 EH⋈zƅ.!0W䠏#EݞSPV.,_>٢5]NtaqK"RKtz7)bztکHbXiΈSRn8e@'[Gt?W14˜LsETh92RRqxgf|G9? y킋:H,co_Ľ1 j2B2`^իf1 [փbvG[3~O)n"BCH0Fؘ<=\Y1! }=dY t /q LG&x#B<atWK 4 ӄў KPHcb|f{׼)J~ *@>f.AG 2Y~ Qy>M9(ards(|႗rĽD/D bXl0(e֦b\7WQb~2L-D..aΰLD2bR +;˯v 8;>K*W=L{Ljm'#J57xϖ Uif݊+-0?֑i/n%e:e0Ys8 \%ù +\Vs@TqY4kR4i!:ȗ?eu& 1"Sa\*YbݍZ3#".Q." ~Ik"Ba1"xhNcL4 -w캗LL6YVK1),t80A*iڵq.zBA+n3#p"b9eQy>(}bqf1ZgARrRO `mT'_6.=&UW\'xHat!L"Lv1Aĥ"hx(87 Ys ٥y3fKR~$y?O'!RjMlDJ:N;F +mf}/<2 k RZZ~ͥt {L\[R~2zIڿ`lir5~5z}3=ٕ R迺8FIp!W矍/-h]>&?ű 8Ly"Y|՛Og/]]35ivrN5z+Oom|(M)MZςOY;p|u+Eɖ2q0llr2qh,/۟ߋJ{w .P00˱ȅx;nnGy9!@NLD^v|!W2Xyk3O!Wک` {n|kC. Y"9$̃hWS=<< m~ool9, O> &_{JOW!uW\6S듫oח/-/oxu +I~XxWR7HȠw|{: ritk5A -]_x\_j;37}{{_YO? C/5׿Tt͝Ֆq|8űs "l3W_DNsgwySr ( h/%w[חƣ_wSWɾm4Wyt)^Z~ftg'9)ٻɆq_?34"Q9gj:\Ó|z_V_x+GL7v s_X;"*}2Ɉ}> nYkߐFK#󹞾 z"35ǤP7^wU7\##hyԚݓ_"Ĺ+Յ魭;_.S+;dЬѨ\ۥD7SW_}?;fyɕg ?X[ÃxpV&KNB[M=[غJ 5Nww_'ܼumՅ{'Jw "$2J'`Z? #Bpq薾~1"ݷJI*ε[-u>O9y\Ӽ6|x.l޾wG$ɽ=OFh${?r#{F]^ܽr< ¯LG%"`Wf~s[>w/g\[oWX&VZ~7I`#Q@Zrej/hrsW׶~,ѓ/ˤ~se}7~;y4;NU:z`Byi|F?3_+ؿo;|y4ϴ +K;7V7_|6~Kc Wڿ{zw8,#s⼞Zx86{o4]8ooyxן^;׼`H'Ui3&\Fmrߦ_Gm]_=blۏz[5d缈f6㹭;8s0{|ۓ͵=44H WwH~|!N'mrN`lW⃃G©;c"΍5Z8 +grcv`be4ʵOL&gbd/ovvfL5swo'7ߌ-&IBrb8blu*ip~R{;Owui<)_ٶ/__i޸sa?}w}v3X#~ş[[P_x׷^̼v5}:1gD:{N"a|d'}n^%3>vc3Iv'V_ ==v)Y›Ow+!Wr'76oo>o.]#ECZ\Dc[UWW.Eho܍o>B}ޜl^ +{7f6G.YKW矄?.~mݛvη&c/}p(ah+s#0({:}Hgzb{}0:y.^DC53}Fx}Ս7W^sJzd'N[ɇ_Ok{4N84Wo=>ooTI|wme7^ޜo>涉wԍ{w\Kfݿ[mK7nos/R&m|u/Sķ?=VOl ^_\|6Z˫w>1ģ鵓frէh"8jѹd᜙M_Jokoo?_<[KWW.~go{Gtc4Ṣ/|9f6_/^_Knw O~;qe0_lvkj^< 2q,ꩍ+2ؙBkh|&yXZ +7S,=^JW>5"OȠ}jDS#2hAԈ ڧFd>5"OȠ}jDS#2hAԈ ڧFd>5"OȠ}jDS#2hAԈ ڧFd>5"OȠ}jDS#2hAԈ ڧFd>5"OȠ}jDS#2hAԈ ڧFd>5"OȠ}jD=#w<ܞ:??rn}Jm>i,{zedfuwtu}*6+kyA5V^p߾иLFjߏI7CmThG7b4 B6a&:҉1AU/E1L&IlEJSAEtQu#FGlѼ%7wWNhJ||tzwxwbtTSm#˯ +͹ٽ}+KGm|-,;k`~a=s~u=*]>nwݸrWsW6Z\(^vk\ݏ_xual.lJw}t:8{]XX?ɀ }44~Tm{}wk۟#!8<.R϶۽- !G_o#ygBz{m 죝}Hgݻ}Fnflя`_a>|xzu<}tdwƯx +ɀ~ݫ`ٹc!yϐO~s@kh귻ufÞ ^9j]tXn A6zBPA vcT=)"G{'g~Xe{E'::*:rI>)pXܥH L;Y{k0|Bg-=2tyGD :;=h&Qs(e4wD OΩ+ޫBǏ?O1,>~L} /7' +ĝ;#a>*[;w&;>:ڟ:n9SoAv jxk{MS/>h_ۣr3"=;L3\ttjhE&-gPIfۙ6wv[-H=o? K10zv*xk-Agwcv.OA8,ܺA ;5E3 s׆3-ӻ[~ՏS{N|(?>_cx1%Շ 8b=/3f^jڇ'K[O'=} K1IvE9; hiT^o{ֳ"tH׳+;beއ=[=W,Z:4wrAS|ѫ4N=,WBVs9|t܎>n oIl n"[9_JŻN!OO~?EA=3v}SL?n:3e3c2,hR hHdXfZgl>'N"{oXΔ;DEА覺p.9}$[gpwLEKa|L>pΜ=u433S8;&"~3R8Ӈ0$o gZu0L"зC"~!Cd)YabԽ#~qc83-#'o=-O d=7$͒nK3C'[o|*vv[kZKZҍ[mҭnt;k-6z_r=#dp*KX3QLgk&D{ߵWvA:>a{.Q)cWJ SOK%CnSգ'tP?h;;F?4Zv{gIU{d);NAOj Wջ;lŔzqKPòO .9=^&=d4DwgwQ13֗z0k™ks{Y9dp#5#>tAuw{>] Y*}^2{󈄧ȇrDU:<ò.3 ƙ ?3Qsu'@`/ RsssuιQ(<9odA }3,go݅{>ڳ(sCWohQ޷Tt<8}tHaU}{^{{BЮg4˷!:W-2># =wh~d츽=vtuDgNu'4ӍƸRIޜ˼HtzƩOqjџ=vVNvfFEjzׯ->17˛߽"kѱC8[YX:du!+`N̩9u0 i t#N̩9u0<+UudLk:3l**!nϱw 3әޙb݁g+G 4]9zGdrd΀ +[ =3ݭ>Ȇhݪn./QS!@wXju&Znm}[ii5\t ˢ~0(sڵwQeJ+`һ> E gLvTe|L8}Gݢc Ꮸ Z?L>䬄?zG|t)P?Πhgf]ǀ?ĝlQUpCµx'h7oڇލ]ã{AyWcKតa8,^O}NX[>:f;[壽w=bi4K E+Kk㣃 tB~nTv~)h|QPF<vJCND9~f8~hCu!5GeHB;!ulԠǀWggr8:)ԑ۞υB?KWOɔ}0W{}k/=  /gנ /AN56'n`n`=3ɀ }44ལ[kj?]g1ޙ{:lpR _Ȁ o>¬/dE~!_}z9ѫWHX>~xjhKޅgξi~TOeK_ 6$fo.DgX\O0 +|=[AowZp+t|AAǃGOw_ޫ-QvMH=ۆ)c?3TسaM Tsǩ>W wǩZ3{,ILfD^-:>ۯgO&[Wo<~ݫ`ٹcgG[Cb SSm&q;N/OczG=}򈄧fњZ*pA&tFOSn W_Pu}|>H6>>_ir@áh.'!Q=R۷ +w/%6,r7.@(8t3 +n)r׎.=ƃކ,况XgKO͒]aC\͠z?w~yHRmceﴏg\q/W9l P9s֌AAns5>_p:BpO +>6-&6gbXܼ!p5.09,:e?>sTvv@Gn2*#˯F~ZsF$y3ҩi=@_&з XjJ(퐏058xEƆ3M`b0 "l,0t"c )PST㦰󘄧&9n+ G6S q%l7PXt1 wĊf`$)h4#JK@%U3@AĤod@ V1km-$!56D .Y":7ZrMH3IoJcIJ& ֐8!`Ib&^jH 9B/9UlIB$X5S'V$tshbX=UMbX)q@ $^,W "E +R\ F|r%״1ӗJZw&65L.QNc͑(5tcٌ?5KVEFsKDB ~i57@90@a)Mj +etBO3L/U<4Kȃ*Y͒8R#"IG%17 XCǡ1J 0(`&0E4@^ʑ+i * endstream endobj 5 0 obj <> endobj 35 0 obj <> endobj 44 0 obj [/View/Design] endobj 45 0 obj <>>> endobj 18 0 obj [/View/Design] endobj 19 0 obj <>>> endobj 61 0 obj [60 0 R] endobj 84 0 obj <> endobj xref 0 85 0000000004 65535 f +0000000016 00000 n +0000000173 00000 n +0000042259 00000 n +0000000006 00000 f +0000653862 00000 n +0000000008 00000 f +0000042310 00000 n +0000000009 00000 f +0000000010 00000 f +0000000011 00000 f +0000000012 00000 f +0000000013 00000 f +0000000014 00000 f +0000000015 00000 f +0000000016 00000 f +0000000017 00000 f +0000000020 00000 f +0000654119 00000 n +0000654150 00000 n +0000000021 00000 f +0000000022 00000 f +0000000023 00000 f +0000000024 00000 f +0000000025 00000 f +0000000026 00000 f +0000000027 00000 f +0000000028 00000 f +0000000029 00000 f +0000000030 00000 f +0000000031 00000 f +0000000032 00000 f +0000000033 00000 f +0000000034 00000 f +0000000000 00000 f +0000653932 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000654003 00000 n +0000654034 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000047596 00000 n +0000654235 00000 n +0000042672 00000 n +0000050591 00000 n +0000047908 00000 n +0000047795 00000 n +0000046600 00000 n +0000047035 00000 n +0000047083 00000 n +0000047679 00000 n +0000047710 00000 n +0000047943 00000 n +0000050665 00000 n +0000051017 00000 n +0000052453 00000 n +0000066435 00000 n +0000129158 00000 n +0000194746 00000 n +0000260334 00000 n +0000325922 00000 n +0000391510 00000 n +0000457098 00000 n +0000522686 00000 n +0000588274 00000 n +0000654260 00000 n +trailer <]>> startxref 654498 %%EOF \ No newline at end of file diff --git a/tests/dummy/public/assets/branding/ai/Ember-CLI-Mirage-Logo-Stacked-Color.ai b/tests/dummy/public/assets/branding/ai/Ember-CLI-Mirage-Logo-Stacked-Color.ai new file mode 100644 index 000000000..ad31f4721 --- /dev/null +++ b/tests/dummy/public/assets/branding/ai/Ember-CLI-Mirage-Logo-Stacked-Color.ai @@ -0,0 +1,2802 @@ +%PDF-1.5 % +1 0 obj <>/OCGs[5 0 R 35 0 R 60 0 R]>>/Pages 3 0 R/Type/Catalog>> endobj 2 0 obj <>stream + + + + + application/pdf + + + Ember-CLI-Mirage-Logo-Stacked-Color + + + 2017-04-12T20:08:18-05:00 + 2017-04-12T20:08:18-05:00 + 2017-04-12T20:05:03-05:00 + Adobe Illustrator CC 2017 (Macintosh) + + + + 252 + 256 + JPEG + /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgBAAD8AwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq7FXYq7FXYq7 FXYq7FXYq7FXYq7FXYq7FXYq7FXYqwjzv5y0s6TPYafcia6nPps0RNEQH4qt0NQKbZk4cJuy6rXa yHAYxNkq/k/znpEmk2tneXIhvYQISJSQGoaKQx26UwZsJuxyZ6PWwMBGRqQZhmO7J2KuxV2KuxV2 KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KqF3fWVmge6njgU7KZGC1PtXrkJ5YwFyIDPH ilM1EEoX/Emgf9XCD/gxlP5zF/OHzbvyeb+afk7/ABJoH/Vwg/4MY/nMX84fNfyeb+afk7/Emgf9 XCD/AIMY/nMX84fNfyeb+afk7/Emgf8AVwg/4MY/nMX84fNfyeb+afk7/Emgf9XCD/gxj+cxfzh8 1/J5v5p+Tv8AEmgf9XCD/gxj+cxfzh81/J5v5p+SpBrWj3UghhvIZZG2EYdST8hXfJw1OORoSF+9 hPTZIizE17mI+dvJWkxaTPqGnQehcQH1HSOpVkJ+L4dwONa7ZsMOY3RdHrdFAQMoiiER5O8k6Smm Wt9fW/rXsoEwEleKAmqgJsOlK1wZsxuhyZ6PRQEBKQuTM8xnZuxV2KuxV2KuxV2KuxV2KuxV2Kux V2KuxV2KuxVCarqtjpdm93eSenEmw7szHoqjuTkoxMjQa8uWOOPFLkwiT8w9fv5mXRNK9SNduTI8 zb9CfTKqv45k/l4j6i6o9o5Jn93H9K63/MfVbO5WHXdMMCt+0ivG4HjwkJ5feMTpwR6SmPaU4msk a/HmzmxvrW+tY7q1kEsEoqjj/PYjwzFlEg0XawmJixyV8DN2KvPtTszrPnl7G5kZYEoo49QiR8yB XpU1zn82PxtVwSO37HocGTwdJxxG/wC1Ov8AlXmgfzT/APBr/wA05m/yTi83C/lfN5O/5V5oH80/ /Br/AM04/wAk4vNf5XzeTv8AlXmgfzT/APBr/wA04/yTi81/lfN5O/5V5oH80/8Awa/804/yTi81 /lfN5O/5V5oH80//AAa/804/yTi81/lfN5O/5V5oH80//Br/AM04/wAk4vNf5XzeSRebvKtjo9nB eWckgJlEbK5B3KlgwIApTjmBr9DHDESiTzc/s/XTzSMZAcmc6TM9xpVnNKeUksEbyHxLICc3uCRl jiTzIDodRERySA5AlF5a1OxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxVzMqqWYgKBUk7AAYq8 11yT/FPnSDS4puWnW+3ONgykBecrAioqfs5mw9EL6ujznx84gD6R+C9Es7K1srZLa1iWKCMURFFB /affMMkk2XdQgIihsFLVNLstTs3tLyMSRONq9VPZlPYjDGRibDHLijONSec+W/MA8p6pqGl6j6kl qrkKYwDR1NA9CRsydfozMyY/EAIdLptR+XnKEuT0bS9X0/VLYXNjMJo+jU2ZT4Mp3BzDlAxNF3WL NHILibReRbGD2v8A5Mmb/Zf8mc0cP8dP46O9yf4kPx1T3zH5pttFMUbRGeeUFhGDxAUbVJoe/tmf q9dHDQqyXA0ehlns3QCM0TWLfV7EXcAKDkUdG6qw3I29jl2m1Ayw4g06nTywz4Skh/MLThqX1X0H +r8/T+s1HjTlwp9n6cwf5Whx8Nbd7nfyTPg4r37mVZtXUuxV2KsV/Mf/AI4cH/MSn/JuTNV2v/dD +t+gu27H/vT/AFf0hPNC/wCOHp3/ADDQ/wDJsZnaX+6j/VH3OBqv72X9Y/ejsvaHYq7FXYq7FXYq 7FXYq7FXYq7FXYq7FXYq7FXYqwH8xLy+utU0/wAv27+ml1wZzWgZpJDGoanZeNcy9OAAZF1HaM5S nHGOqfeXvJWlaJP9ZhaSa64FDJIRTehJVQNumU5Mxls5en0UMRsblkGVOY7FUDe6Fo18zvd2UE0k go0rIvqUGw+OnL8ckJyHItU8EJcwCwXy7EdE/MKbSLZy1pMGUqTXb0vWWvuvSuZWQ8WOy6nTjwtS YDkf1W9IzDd2we1/8mTN/sv+TOaOH+On8dHe5P8AEh+Oqe+Y/K1trRikaUwTxAqJAOQKnehFR398 z9XoY5qN0Q4Gj10sFirBRmiaPb6RYi0gJcci7u3VmOxO3sMu02nGKHCGnU6iWafEUkP5e6cdS+te u/1fn6n1ag8a8edfs/RmD/JMOPivbuc7+Vp8HDW/eyrNq6l2KuxViv5j/wDHDg/5iU/5NyZqu1/7 of1v0F23Y/8Aen+r+kJ5oX/HD07/AJhof+TYzO0v91H+qPucDVf3sv6x+9HZe0OxV2KuxV2KuxV2 KuxV2KuxV2KuxV2KuxV2KuxViPnryxfai1vqWmf732gpwB4syg8lKk/tK2ZGDIBseTrtdpZTqcPq Cr5S13zPe3T2ur6e0CRR1+smN4quCBQhvhNevw4MsIgWCy0mfLI1ONebJ5WdYnZF5uqkqnSpA2H0 5QHOJ2eft5685BiDolCDShhnr+vMvwId7qPz2f8AmfYWm87eeJVMcOjFZG6MIJmI96E0w+DDvR+d znYQ+wph5K8q6jbXsutawT9fm5cI2ILDn9p2I2qegHYZDNlBHCOTdotLKMjkn9RZnmM7Ng9r/wCT Jm/2X/JnNHD/AB0/jo73J/iQ/HVOPMnmLUdLuYoraxNxG6cml+IitSOPwjtSuZms1c8UgIxtw9Ho 4ZYkylST/wCO9c/6tX4Sf0zD/lPL/M+9zP5Lxfz/ALnf471z/q1fhJ/TH+U8v8z71/kvF/P+53+O 9c/6tX4Sf0x/lPL/ADPvX+S8X8/7nf471z/q1fhJ/TH+U8v8z71/kvF/P+5N/LfmPUtUupYrmxNv GicxL8QFagcfiHetfozM0ernlkRKNOHrNHDFEGMr3Q35j/8AHDg/5iU/5NyZV2v/AHQ/rfoLb2P/ AHp/q/pCeaF/xw9O/wCYaH/k2MztL/dR/qj7nA1X97L+sfvR2XtCF1HVNO06H1r64SCPsWO5PgoG 5+jJRiTya8mWMBcjSSp+YflRpOH1plB2DtHIF/4jln5efc4w7Rw3z+xkFtdW11Cs9tKs0L7rIhDK fpGVEEc3LjISFg2FTAydirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVYPa/+TJm/wBl /wAmc0cP8dP46O9yf4kPx1Zs8kcalpGCKOrMQB+ObskDm6MAnkuBBFRuD0OFC31YvU9PmvqUrwqO VPGmDiF11Twmr6LsKHYq7FWK/mP/AMcOD/mJT/k3Jmq7X/uh/W/QXbdj/wB6f6v6Qnmhf8cPTv8A mGh/5NjM7S/3Uf6o+5wNV/ey/rH70ReXUVpaT3Uv91BG0j060QVNMyALNONOYjEk9Hm+iaPeec9T n1XVJGWxjbgsaH6REngFB3OZk5jGKHN0mDDLUzM5/T+NmXS+QfKskHoiyEe1FkR35j3qSa/TlAzz 73YnQYSKph6zX3kXXzCWa50u4XmE6c16Vp0DqR92ZFDLHzdbctLkrnA/j5p1Z/mppUs4S5tZbeMm glBEgHuwFD91cqOmPRyodqwJ3BDM4J4biFJ4XEkMgDI6moIPQjMcinZxkCLHJfgS7FXYq7FXYq7F XYq7FXYq7FXYq7FXYq7FXYq7FXYqw+306+X8wJbowOLYqWE1DwoYgo+Lp1zTwwz/ADZlXp7/AIO4 nmgdGI36u74qX5hWGqXElrJBHJNaopDJGC3FyepA8Rke1sWSRBAJiz7Iy44iQJAkm/kq11C20NY7 1WRjIzRRvsyxkCgIPTepzL7NhOOKpd/2OH2lOEstx7vtYW2i+ZDr5pDKLozcxc0PH7VefPpTNKdN m8bkeK+f7XdjU4PB5jhrl+inqWdS8q7FXYqxX8x/+OHB/wAxKf8AJuTNV2v/AHQ/rfoLtux/70/1 f0hPNC/44enf8w0P/JsZnaX+6j/VH3OBqv72X9Y/eo+aYJJ/LuoxRirmByAOp4jlT8MysRqQcDVR JxSA7ki/K+8gk0KS2UgTQTMZF70cAq36x9GW6keq3F7LmDjrqCzHMd2SFvtJ02/MZvbaO4MJJj9R Q1CevXxpkoyI5NeTFGf1C6QHmLQNKvtInjlgjRo42aGYKFMZUVBBA6bbjJY8hBatRp4TgQQkn5WX c0ujXNu7ckt5v3VewdakfKu+W6kepxey5kwI7izTMZ2bsVdirsVdirsVdirsVdirsVdirsVdirsV diqhe39nY25uLyZYIQQC7mgqegwxiTyYTyRgLkaDBY/zBiPm5ma5b9BlfSX4dgQK+pSnL7X4ZleB 6P6Tqh2gPG5/u2d2d7aXtutxaSrNC1eMiGo22OYpiRsXbQmJCwbCF1LzBpGmSJFe3AikcclXi7Gl aV+ENmNm1WPGakacrDpMmUXEWEH/AI28sf8ALb/ySl/5oyn+UsH877D+pu/k3P8AzftH63f428sf 8tv/ACSl/wCaMf5SwfzvsP6l/k3P/N+0frd/jbyx/wAtv/JKX/mjH+UsH877D+pf5Nz/AM37R+t3 +NvLH/Lb/wAkpf8AmjH+UsH877D+pf5Nz/zftH60ZpvmDSNTleKyuBLIi8mTi6njWlfiC+OXYdVj yGomy05tJkxC5Cgkv5j/APHDg/5iU/5NyZhdr/3Q/rfoLndj/wB6f6v6Qnmhf8cPTv8AmGh/5NjM 7S/3Uf6o+5wNV/ey/rH70dl7QlOj+V9K0i8ubqyDo1zs0ZIKKK1oopt9+WTymQouPh0sMciY9VfX r69sdKnurK2N3cRgcIQCa1IBNF3NBvtghEE0WWfJKECYiywz/HfnH/qy/wDJGf8ArmR4EO91n5/P /M+woe91jz35ghOnx6c1rDL8MzrG8YKnqGeQ0A+WSEMcN7YTzajMOERoH8dWZ+VtATQ9JS05B5mJ kuJB0LsANvYAAZjZcnEbdnpdP4UOHqm+VuS7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYqhtQ02x 1G2NtewrPCSG4N4joQRuMlGRBsMMmOMxUhYYFH+X0f8Ai5oWgk/QYX1lapoaj+751r9r6affmV4/ o/pOoHZ48aq/d/jZn1hp9lYWy21nCsMCkkIviepJO5zElIk2Xb48cYCoigh9S8v6RqcqS3tuJZEX ircnU8a1p8JXMbNpceQ3IW5eHV5MQqJoIP8AwT5Y/wCWL/krL/zXlP8AJuD+b9p/W3fyln/nfYP1 O/wT5Y/5Yv8AkrL/AM14/wAm4P5v2n9a/wApZ/532D9Tv8E+WP8Ali/5Ky/814/ybg/m/af1r/KW f+d9g/U7/BPlj/li/wCSsv8AzXj/ACbg/m/af1r/ACln/nfYP1IzTfL+j6ZK0tlbiKR14M3J2PGt afEW8Muw6THjNxFFqzavJlFSNhJfzH/44cH/ADEp/wAm5Mwu1/7of1v0Fzex/wC9P9X9ITzQv+OH p3/MND/ybGZ2l/uo/wBUfc4Gq/vZf1j96Oy9odirsVdiq2WaKJOcrrGg6sxAH3nBKQG5TGJOwS6b zP5fhNHv4if8huf/ABDlmNLW4RzkHJjos0uUShG88+WR0ui3yjk/ioyo9p4O/wCwto7Mz932hy+e fLRNDcsvuY5P4KcR2ng7/sKT2Zn7vtCeRSxyxJLGwaORQyMOhUioIzOjIEWHAlEg0ea7Ch2KuxV2 KuxV2KuxV2KuxV2KuxV2KuxV2KuxVinnTzLqGlzW9vZURpFMjysobvTiK7fPNV2jrJ4iBHq7bs3R Qygyl0TLynrFxq2k/WLhQsySNEzKKBuIB5Af7LMnQ6g5cdy53Tja/TxxZOGPKrYofPusjVT8KfVf V4/VuO/GtKcvtcv45qf5UyeJ/Rvk7b+SsXh/0q5vRM6J5x2KuxViv5j/APHDg/5iU/5NyZqu1/7o f1v0F23Y/wDen+r+kJ5oX/HD07/mGh/5NjM7S/3Uf6o+5wNV/ey/rH70dl7Q7FUh1fzpo2nlo1f6 1cLsYotwD/lP0GYGo7Rx49vqPk7DT9m5cm/0jzSEa1501w/7j4Pqts3SRRxFP+Mj9f8AY5g/mNTn +gcMfx1/U5/5bS4PrPFL8dB+lVi/L6+uX9XVNRLyHqF5SH/g3I/Vko9lSlvkl+n72Eu1ox2xx/R9 yZQfl/5fjA5iWY9y70/4gFzJj2VhHOy40u1sx5UPgi18m+WlFBZD6XkP62y0dnYP5v3tJ7Rzn+L7 mz5O8tEU+or9DOP+NsP8n4P5v3r/ACjn/nfcm8cccUaxxqEjQBUUbAACgAzLAAFBwySTZXYUOxV2 KuxV2KuxV2KpdfeYdFsSRc3cauOsanm//ArU5j5dXih9Ug5OLSZZ/TEpJc/mNpKGlvBNMfE8UX9Z P4Zgz7XxjkCXOh2PkPMgIT/H2rTitppRYdt3k/4iq5V/KmSX0w+8tv8AJWOP1T+4ObzV51J+HRyB 7285/wCNhiddqf5n+xko0Ol/1T/ZRcPNnnFRWXRzQd/QnUfiTj+f1I5w+yS/kNMeWT7Yt/8AKwr2 E0u9LKdieTJ+DKcf5WlH6ofj5L/JMZfTP8fNGW35i6NJQTRTQnxoGX8DX8Muh2vjPMENM+yMo5EF N7TzLoN3QQ3sfI9Fc+mfufjmZj1mKfKQ+5w8miyw5xP3/ciNQ0rTdTiRLyFZ0XdDUgivgykHfJ5c EMg9QtrxZ54jcTSta2ltaQLb20YihTZUXoMnCEYCoigwnklM3I2UJ/h7Rfr3176on1rlz5705deX GvGvvTKvymLi4+H1Nv5vLwcHEeFMMyHHdirsVYr+Y/8Axw4P+YlP+Tcmartf+6H9b9Bdt2P/AHp/ q/pCeaF/xw9O/wCYaH/k2MztL/dR/qj7nA1X97L+sfvU9Z8xaZpMdbmSsxFUgTdz9HYe5yOo1cMQ 9R37men0mTKfSNu/oxF73zR5pdo7VPqunVoxqVSngz9XPsM1ByZ9Uaj6Yfj5u3GLBpRcvVP8dOif 6P5J0iwAeZfrlwN+cg+EH/JTcffXNhp+zcePc+o/jo6/UdpZMmw9I8v1sh6ZsHXOxV2KuxV2KuxV 2KuxV2KuxV2KpH5n8zLoscSrD69xPy4LWijjTc/fmDrdb4IG1kudotF4xO9AMeFn528wfFcObO0b 9k1iWh/yB8bf7LNf4eq1HM8Mfl9nN2PiaXT/AEjil8/t5fJM7D8vNJhAa7ke6fuK+mn3L8X/AA2Z OLsnHH6iZfY42XtfJL6QI/an1rouk2gH1e0ijI/aCDl/wR3zPhp8cOUQ6/Jqck/qkSjMuaXYq7FX EAih3B6jFUFc6Jo9zX17OFyf2uChv+CG+UT02OXOIb4anJHlIpNefl/oU1TB6ls3bg3Jfufl+vMP J2VilyuLmY+1ssedSSw+T/M2mktpOoc0G/phjGT/ALE1Q/Scxj2fnx/3cv0fscodoYMv95H9P7Wl 83+ZdLYJrFjzStPUKmMn5MtUP0DAO0M+LbJH9H7Ens/Bl3xy/T+1PNO866De0Vpvq0p/Yn+Ef8Fu v45nYe0cU+vCfNwM3ZuWHTiHknqsrKGUhlO4I3BzPBtwSKbxQ7FWIfmLd2raXDbLKjXAuFZogwLB QjipH05qO18keARvfi/QXcdj45eIZVtw/pCVweadcvLO10vRrZleGGOKSYDk3wqFJ3+FBt1OYsdb lnEY8Q5AC/xycqWhxQkcmU8yTX45ppo/kNBJ9a1mT6zcMeRhBJWvi7Hdj/nvmVp+yxfFkPEXF1Ha hrhxDhH4+TLY4440WONQiKKKqgAAeAAzbAACg6gkk2V2FDsVdirsVdirsVdirsVdirsVdirsVaZF anIA0NRUVoR3wEJBpvCh2KuxV2KuxV2KuxV2KuxV2KtOiOpV1DK2xUioI+WAi0g1ySLUvJWhXtWW L6rKf24PhH/Abr+GYObs3FPpwnyc7D2llh14h5pBJ5Y816PyfSbszQ7/ALtDxP0xtVT9G+YB0Wow /wB3Kx+OjsBrdPm2yRo/jqlNx5s82ROYZ7l4pF6o0UaMPn8AOYk9fqAaJr4D9Tlw0GnIsC/if1o6 wsfMOupX9MoyHd4vVfkB7xKB+OX4sWbP/lPt/Q0ZcuHAf7v7P0pzp/5d6ZCQ95M90w6qP3afgS34 5mYuyYD6jxfY4WXtfIfpHD9rJ7WztbSIQ20SQxj9lAAPwzZwxxgKiKDrJ5JTNyNlVybB2KuxV2Ku xV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Koe906xvo/Tu4EmTtz FSPkeo+jK8mGExUhbZjzTgbiaYtqP5eQ8/W0q5a3kBqschJUH2cfEPxzV5eyRzxmi7XD2ueWQWEG Nb846EeOowG6tht6j/EKe0q1/wCGyn8zqcH1jij+Ov6278tps/0Hhl+On6k80zzzod5RZXNpKf2Z tlr7ONvvpmdh7TxT5+k+bg5uzMsOXqHl+pkCOjqHRgyMKqwNQR7EZng3ydeQRsW8KHYq7FXYq7FX Yq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXEAggioPUYqkepeTd Cvqt6P1eU/7sgom/uv2fwzBzdn4p9KPk52HtHLj62PNIH8peZ9JYyaPeGVK19MHgT80aqN9+YB0G fFvjlf47uTsBr8GXbJGvx3810fnjW7BxFq9ga9OdDEx99wVP0YR2llx7ZI/oQezMWQXjl+lOrLzx 5fuaBpmt3P7Mykf8MOS/jmbj7Twy6173CydmZo9L9yc295aXK8reeOYeMbBv1HMyGSMuRBcKeOUf qBCtk2DsVdiqEvdW0yxBN3cxwkfssw5fQo+I/dlWTPCH1EBux6ec/pBLGNS/MAO31fR7dp5n+FJX B6/5KD4j9OavN2re2MWfx0dph7Jr1ZTQ/HVkOgSavJpqPqqhbpiTxAAIXtyA2rmx0pyGF5Pqddqh jE6x/SmOZDjOxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KrZIo5UKSIH Q9VYAg/QcBiCKKRIg2EmvPJnl66qTaiFz+1CSn/Cj4fwzDydnYZdK9zm4+0c0et+9Jrj8toa8rS+ eMj7IkQMf+CUr+rMKfY4/hk5sO2T/FFS/wAJecLf/ebVaqOi+tKv4UIyP5DUx+mf2ll+f00vqh9g d+gvP1eP6Q268vWb+lcfyur/AJ32r+a0n837HHyj5uudrvVPgPVTLK//AAtAMfyGol9U/tK/yhp4 /TD7AirP8uLBCGvLqSc9SqARj6a8jlmPsiA+ok/Y1ZO2Jn6QB9rI9P0fTNOTjZ26RdiwFWPzY1Y5 ssWnhj+kU63LqJ5PqNozLml2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Ku xV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Kux V2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV4v8A4581/wDVwf8A4GP/AJpzZeDDueY/PZv5zv8A HPmv/q4P/wADH/zTj4MO5fz2b+cvg87+ammjU6g5BYAjjH0J/wBXAcMO5Mddmv6nrGtzy2+i388L cJobaaSNx2ZYyQd/fMCAuQehzyIhIjmAWC+SfO+oT6sLLVbj1o7kBYJGCjjIOg+ED7XT50zKzYQB YdVotdIz4Zm7ej5hu6dirCvzA83XGmGKw06X07xv3k8gAJRP2V3qKt1+XzzJwYhLc8nV9oaswqMT 6k28j6nd6j5fiubuQy3HORXkIArRtulO2V5ogSoORocsp4wZc2O/mD5k1vTNahgsbpoIWtlkZAFN WMjivxA9lGXYMcZR3Dh9oanJCYETQr9bG185ecWHJb2VlPQiNCP+I5d4MO5wfzmfvKpB5/8ANltI PUufVA3Mc0aUP3BW/HAcECyj2hmidy9D8peaoNftXPD0buCgnhrUUPRlPgafRmJlxcBdzpNUMw7i Es/MbW9U0uGxawuDAZWkEhAU1ChafaB8cnp4CV20do554xHhNMI/xz5r/wCrg/8AwMf/ADTmV4MO 51X57N/Od/jnzX/1cH/4GP8A5px8GHcv57N/OZj+XOvavqk18t/cmcRLGYwQooWLV+yB4ZjaiAjV Oy7OzzyGXEbQv5g+ZNb0zWoYLG6aCFrZZGQBTVjI4r8QPZRksGOMo7hh2hqckJgRNCv1sY/xz5r/ AOrg/wDwMf8AzTl/gw7nA/PZv5yMsPzI8y20gM8iXcVd0kRVNPZkCn765GWniW3H2lljz3ek+X9f stbsRdW1VZTxmhb7SN4Hx9jmFkxmJou70+ojljYTPIN7sVY55q86WehqIEUXF+4qsINAgPRnP8Mu xYTL3OFq9bHFtzk89vfPnmi7cn62YEPSOABAPp3b7zmXHBEdHTT1+WXWvcowec/NFu/JdQlY+ElJ B9zg4ThiejGOtyj+IvRvJHmTUdcs5pLu3VPQYIJ0qFkYipHE1oRtXfvmHmxiJ2d1odTLLEmQ5MQ8 z+bvMdpr99bW960cEUhWNAqGgoPFcyMeKJiCQ67VavLHIQDs9OsZHksreRzV3jRmPiSoJzClzd7A 3EFWwMmP+etSvdO0B7mylMM4kRQ4AOxO/UHLsEQZUXD12SUMdxNF5v8A4581/wDVwf8A4GP/AJpz M8GHc6T89m/nILy6QPMGmEmgF3AST/xkXJZPpPuatP8A3kf6w+97j9Zt/wDfqf8ABDNZReq4h3tr NCxosisfAEE40kSCXeaj/wA63qf/ADDSf8ROTxfUGjVf3Uvc8PVmRgykqymqsNiCO+bJ5YF7V5R1 5da0eOdiPrUX7u6X/LA+18mG+a7LDhL0+k1Hiwvr1R2r6pb6Xp099cH93CtQvdmOyqPcnbIQiZGm 7NlGOJkejw7UL64v72a8uW5TTsXc9t+w9gNhmzjEAUHlMkzORkeZepflmwbyyAP2Z5AfwP8AHMHU /U7/ALMP7r4sX/NT/lIbf/mET/k7Jl+m+n4uB2r/AHg/q/pLMvy//wCURsP+ev8AyefMfP8AWXZ9 n/3Mfj95QX5lPpf6BZZyn17kn1MGnqV5DnTvTjWvbJae+Lyau0jDw9/q6JD+VNtOdSvLkA/V0hEb HsXZww+4Kct1R2AcTsqJ4ielI782f959N/15f1LkdLzLb2tyj8Vb8rJYk0e7Duqn6x0JA/YXBqRu GXZRAgfezT6zb/79T/ghmNRdnxDvXqysKqQw8QajAyBeW/mp/wApDb/8wif8nZMztN9PxdB2r/eD +r+ksy/L/wD5RGw/56/8nnzHz/WXZ9n/ANzH4/eUv/MXQdPl0WXU1jWO8tip9RQFLqzhSreP2qjJ aeZ4qae0cETAz6hj35W3Eqa7PAD+6ltyXX3Rl4n6ORy7Uj0uF2XIjIR3h6lmC79D6jeJZWFxeOKr bxtIR48RWn04YizTDJPhiZdzxK2hvte1tI2fldX0vxyHoK7sfkq5syRGPueXiJZcldZF7DonlrSd HgWO1gUygfHcMAZGPiW7fIZrp5DLm9Hg00MY2HxR11Z2l3EYrqFJ4z+xIoYfjkQSOTdKAkKItbp+ nWen2q2tnEIoEJKoKndjU7mp74ykSbKMeOMBUdg8b84/8pPqP/GY/qGbHD9Iea1n97L3vZNO/wCO fa/8YY/+IjNdLm9Lj+ke5EYGbFvzK/5Rh/8AjNH+vL9P9Tr+0v7r4vI82DzqpbW81zcRW8K85pnW OJagVZzRRU0HU4Ca3ZRiZEAcynv/ACr/AM3f8sH/ACVh/wCa8q8eHe5f8n5v5v2j9aeeS/KPmHTf MEF3e2npW6LIGf1ImoWQgbKxPXKs2WJjQLlaLSZIZAZDb4Mw84kjyxqP/GE/rGY+H6g7LWf3Uvc8 x8m6NFrF/dWUm3K1kZH/AJHDJxb78zc0+EA+botFhGSRif5qr5U1ify75gaG7rHA7fV71D+yQaB/ 9ifwrjlhxx2ZaTMcOSjy5FH/AJj+Yvr2oLpls3K2tD+8I6NN0P8AwHT51yGnx0LLb2lqOOXAOQ+9 A+Y/Lo0fQdJaVaXtw0r3HtyCcU/2I/GuSx5OKR7mrU6fw8cb+o3f2Mx/K9gfLkgHVblwf+AQ/wAc x9T9Tsuyz+6+LG/zU/5SG3/5hE/5OyZdpvp+Lhdq/wB4P6v6Slml+UvM1/YxXdklbaXl6Z9VV+yx U7EjuDk5ZYg0WjFpMs4iUeXvUNV8peYNMhNxeWpEA+1KrK4Ff5uJNPpyUcsZciwy6TJAXIbM0/Ln zJazRfoc28dtNGpeNo9hLT7RatTz+nMbUYyN3adnakEcFUfvUvzZ/wB59N/15f1Lh0vMse1uUfiw zSvLOt6tC82n23rRRtwducaUagNKOy+OZEskY83WYtNkyC4i0b/yr/zd/wAsH/JWH/mvI+PDvbf5 PzfzftH63pHkvTb3TfL8Fpex+lcI0hZOStQM5I3UkdMw80gZWHd6LHKGMCXNhH5qf8pDb/8AMIn/ ACdkzJ030/F1Xav94P6v6SreW/zBs9J0W30+S0kleDnV1ZQDzkZ+/wDrYMmAyldstN2hHHARI5Jb 5p883muQi1SEWtmGDMgbkzkdOTUGw8KZPFhEd+rTqtdLKKqosh/LHy/PAJdXuEKesnpWqsKEoSGZ 9+xoKZVqcl7BzOzNORcz15M+zEduk3nJHbyvqITr6RJ77Agn8BlmH6g42sH7qXueb/l5LEnmq159 XWRUJ7MUP+1mbqB6HSdnEDMHsOa56R2KuxV4n5x/5SfUf+Mx/UM2WH6Q8vrP72Xveyad/wAc+1/4 wx/8RGa6XN6XH9I9yIwM2LfmV/yjD/8AGaP9eX6f6nX9pf3XxeR5sHnUbok8VvrVhPM3CGG5hkkc 9lWQEnb2yExcS24JATiTyBD1v/HPlT/q4J/wMn/NOYHgz7novz2H+c7/ABz5U/6uCf8AAyf804+D PuX89h/nO88/8opqH+ov/JxccP1hdd/cyYT+Vf8AykNx/wAwj/8AJ2PMnU/T8XV9lf3h/q/pCN/M 7y/xkTWoF+F6R3YH8w2R/pHw/dkdNk/hbe09Pv4g+KWfl55f/SOq/XJ1raWRDUPRpeqL9HU5PUZK Fd7R2dp+OfEeUU7/ADZ/3n03/Xl/UuV6XmXK7W5R+KL/ACrYfoC5X9oXTEj2Mcf9Mjqvq+DZ2V/d n+t+gMf/ADU/5SG3/wCYRP8Ak7Jlum+n4uH2r/eD+r+kp/5L8y6DZeWbO2ur2OGeP1OcbE1FZXYd vA5VmxyMiQHM0WpxxxAE0d/vVvM3nby8NHuoLe4W7nuIniSNASPjBWrEilBXBjwytlqddj4CAbJD DPy9t5ZfNVoyA8YRJJIw7L6ZX8SwGZOoPoLrOz4k5h5Mj/Nn/efTf9eX9S5TpeZc3tblH4ob8vPM WjaZplzDf3SwSPPzVSGNV4KK/CD4YdRjlI7NfZ2ohjgRI1uyr/HPlT/q4J/wMn/NOUeDPudh+ew/ zkbpnmDR9UkeOwuVneMBnADCgO37QGRljMebbi1EMm0Tbzz81P8AlIbf/mET/k7JmXpvp+Lpu1f7 wf1f0lH+V/Iei6r5ftr64eZbicScijKFHGRkFAVPZcjlzyjKm3S6CGTGJG7LE9Y0q98v6yYZKM0T CS3kZQyutaq3E1HzGXwkJh1+bFLDOu56b5d87aRqdnGbieK0vRRZYJGCAt0rHyO4P35hZMJifJ3u n1sJx3IEmR5S5qy4giuIJIJRyimRo5F8VYUI+7CDSJRBFHq8R1XTtQ8v6yYiSksDiS2nA+0oNVcf xzZRkJxeWy45YZ11HJ6Bon5laRcQKupk2l0BR24s0bHxUryI+R+/MSenI5O4wdpQkPXsUfdfmB5W giLrdmdqbRxI5Y/SQq/eciMEz0bZ9oYgOdo7y7r9rrmn/W4FMZDskkTEFlIO1aeIochkxmJpu0+o GWPEHk/nH/lJ9R/4zH9QzPw/SHntZ/ey970mx86+V47K3je/QOkaKw4vsQoB/ZzDlhlfJ3cNbiEQ OJW/xz5U/wCrgn/Ayf8ANODwZ9zL89h/nJd+YNzBdeUBcQPzhlkieNxUVUmoO+TwCp009oSEsNjl s8ozPeeZ1/yqjUP+W+H/AIFsxfzQ7nbfyTL+cHf8qo1D/lvh/wCBbH80O5f5Jl/ODv8AlVGof8t8 P/Atj+aHcv8AJMv5wZz5k0mTVtFuNPjkETz8KOwJA4yK/b/VzFxy4ZW7XU4jkgYjqkXlDyRdaFqU t3LcpMskLRBUBBqXVq7/AOrluXMJCnF0ehOKXETezLZI45EKSKHQ9VYAg/Qcx3YEA82ooYYV4xRr Gta8UAUV+jElREDkx/zl5Wn1+K1SGdIDbs5PME15AeHyy7Dl4HD1mlOYCjVKvk/y5PoNjNbTTLM0 svqBkBAA4gU3+WDLk4jbLR6Y4okE3ul3m/yRda7qUV3FcpCscKxFXBJqHZq7f62TxZhEU06zQnLL iBrZI/8AlVGof8t8P/Atlv5odzifyTL+cFSD8p7gv+/1FFT/ACIyx/ErgOqHcyj2SesmZaB5a0zQ 4GjtFLSSf3s70LtT3FKD2GY+TIZc3ZafTRxCooHzl5WuNfitUhnSA27OSXBNeQHh8slhy8FtWs0p zAUapi//ACqjUP8Alvh/4Fsv/NDucD+SZfzg7/lVGof8t8P/AALY/mh3L/JMv5wZD5O8nXOg3NxN NcJMJkCAICKUNe+U5swmHM0ejOIkk3al5v8AJF1rupRXcVykKxwrEVcEmodmrt/rYcWYRFI1mhOW XEDWye+W9Jk0nRbfT5JBK8HOrqCAecjP3/1sqyS4pW5WmxHHARPRZ5i8t2Gu2gguPglTeC4UfEh/ iD3GHHkMTsjUaaOWNFhUH5X6xBfRSrdW7wRyK/Ilw5Cmv2eJH/DZknUgjk6uPZcxIGxT0rMJ3jsV S/WdB0zWLb0L6LmFqY5F2dCe6t/mMnCZidmnNgjkFSDB738qLsOTY30bp2WdShH0ryr92ZI1Q6h1 U+yT/DL5qNv+VOrswFxeW8adzHzkP3ER/rwnVDuYx7Kn1IZr5a8rWWgwyLBI8ss1PWkc0B41pRRs OuY2TKZuz02ljiG3Vjeuflxe6jq11fJeRRpcPzCMrEjb2y6GoAFU4Wfs2U5mVjdA/wDKqNQ/5b4f +BbJ/mh3NX8ky/nB3/KqNQ/5b4f+BbH80O5f5Jl/ODKNS8rXF35Ut9FWdFlgWIGYg8T6fXbrlEct T4nPyaUywjHfKmL/APKqNQ/5b4f+BbL/AM0O5wP5Jl/OD0vMJ3jsVdirsVdirsVdirsVdirsVdir sVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirs VdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVfJnn385/zI0rz7rdlp+t uljZX80UFv6cLIEjkICGqVI2od8yYwBDUZG30r5F83WPm7ytY67aUUXKUnhrUxTLtLGf9VuniKHv lEo0abAbT7IpdiqD1nV7DRtJu9V1CQQ2VlE008ngqCuw7k9AO5wgWr5Hvfz+/Me98wSXEGrvY6dP c8orRUh4RQl9k5MhOy9TXMnwxTVxF9iZitrwD/nIn8xfOnlfzPptpoOqPY209l6ssaJGwZ/VdeXx qx6KMuxRBG7CRV/+cc/zC84+ada1e31/U3voba2jkhR0jXizSUJ+BV7Y5YgcliXsnmq7uLPyxrF3 bOY7m2srmWGQUJV0iZlbeo2Iyoc2RfHv/K9PzY/6mGb/AJFW/wD1TzK8OLVxF3/K9PzY/wCphm/5 FW//AFTx8OK8RR2l/wDORH5rWMoeTVEvo61MN1bwlT/so1jk+5sBxRTxF7n+Vf59aN5yuE0nUYRp evMCYouXKC4oN/SY0IbvwP0E5TPHTMSt6rlbJxIAqemKvn78zP8AnJk2d5NpXkuOKcwkpNrEw5xl h1+rpWjAfztsewpQ5dDF3sDN45qH5t/mZfyGSfzLfozGpFvM1sv0LB6aj7stEB3MOIonSfzp/NDS 5FeHzDdThaVS7IulIHY+sHP3b4nGF4i99/KX8/rDzddR6LrcMena64pbuhP1e5YdVTkSUfwUk17H tlM8dcmyMrevZUydiry78zvz68ueTpZNMskGra6m0lsjcYYD/wAXSAH4v8hd/HjlkMZLEyp4Hr35 /fmhq8rEasdOgY/Db2KLCq/J/il+98uGMBgZFIU/M/8AMZJTKPM+qFjWoa7mZd9/sliv4ZLgHciy yvy5/wA5HfmVpMqfXbqLWLUEcobuNQ1O/GWII9fduXyyJxApEi+n/IPnBPN/la019LKWwS65AQTE N9hipZGFOSVBoSB8sx5Ro02A2wn/AJyJ83+ZPK/ljTbvQb1rG5nvfSlkRUYsnpO3H41YdVGSxRBO 6JF4B/yvT82P+phm/wCRVv8A9U8v8OLXxF3/ACvT82P+phm/5FW//VPHw4rxF3/K9PzY/wCphm/5 FW//AFTx8OK8Rd/yvT82P+phm/5FW/8A1Tx8OK8RSX8xmVvzB8zspBU6tfEEbgg3L4Y8gp5vQP8A nHD8xP0B5mPl6+l46VrbqsRY/DFefZjb/nr9g+/HwyGWNi0xL6wzGbXYq+b/APnJ78xTNcR+SdPl /dQlLjWGU7NJ9qKA/wCqKO3vx8MvxR6tcz0fP2XsH6IgggEGoO4IzBb3y7/zlf8A8plpH/bOH/J+ TMjDya5oj/nEz/lIte/5hIv+TuObksH0D52/5Q3Xv+2dd/8AJh8ojzZl8D5mtL7I0P8AJL8rbjRd PuJtAieaa2hkkcyz7s0YJO0nicxTkLbwhjX5gf8AOM/li70u4uvKKPp+qxKXis2laS3mI3KfvSzo zfsnlx9u4lHKeqDB8wwy3VndJNEz291bSB43UlHjkQ1BB6hlYZe1vuv8vfMx8z+StI1x6eteW6m4 47L60ZMc1AO3qI1MxJCjTcCw7/nIrzhP5f8AIElraSene61J9SVhsywlS07D5qOH+yyWKNlEjs+V PK3lzUfMvmCx0PTgDd30gjRm+yqgFndv8lFBY/LMkmhbUA+tPLP/ADj9+W2jWMcV1py6veAD1ry8 LNzbqaRA+mq16ClfEnMY5CW0RCUef/8AnHHyfqulzS+WrYaTrMalrdY3Y28zAbRyI5YLy6clpTvX DHKRzUxfKoN5p98CC9te2ktQRVJI5Y2+8MrDMhqfc35c+af8U+SdJ1xqevdQgXQGwE8RMctB2HNC R7ZiSFGm4Gwxv89fzHl8meVAtg4TW9VZoLBtiY1UAyzUP8gYAf5RGSxxsokafH1paX+p6hFa2scl 3fXcgSKNQXkkkc/eSTmS1PpHyN/zi7osFpFdeb55Ly+cBn0+2f04I678WkX43YeKlR8+uUSy9zYI M5f8hfylaL0z5fjC0pUT3Ibb/KEtch4kk8IYX5i/5xW8t3NzFNoWoz2ERlU3FrPSdPS5fH6T7Orc enLlvkxmPVBg9s0+wtNOsLews4hDaWkaQ28S9FjjUKqj5AZSSzeL/wDOV/8Ayhukf9tEf8mJMuw8 2E3iX5MaFpOvfmVo+k6vbi70+5+s+vbsWUN6drLIu6lTsyg9ctmaDCI3fUH/ACor8p/+peh/5G3H /VTMfxJNnCHf8qK/Kf8A6l6H/kbcf9VMfEkvCHf8qK/Kf/qXof8Akbcf9VMfEkvCHyF50ZW8466y kFTqN2QRuCDO+ZMeTWUPqujalo8tmblTH9ctoL60lWoDRTKGVlO32TVT7g4QbQ+xPyX/ADBXzp5O hnuHB1iwpbamvdnUfBL/AM9VFf8AWqO2Ys40W2JtNvzI872nkzylea1NxedB6VjbsaercPX00+Q+ 03+SDgjGykmnxZYWGuebfMnoRE3eranK8ssrnqxrJLI57ACrHMs0A1c0owofoTppB061I6ejH/xE ZglvfMv/ADlf/wAplpH/AGzh/wAn5MyMPJrmiP8AnEz/AJSLXv8AmEi/5O45uSwfQPnb/lDde/7Z 13/yYfKI82ZfA+ZrS/QDy3/yjul/8wkH/JpcwjzbwidR1Gy02wuNQvplt7O1jaWeZzRVRRUk4AFf Aet30eoa1f38SelFd3M06R9OKySFwu3hXM0ND7F/IS2mtvyk8vxzLxdknlA/yZbqWRD9KsDmLk+p tjyeY/8AOW9xIbjyxb1/dql5JTfdiYRv8qbZZh6sZsc/5xZtoZvzHupJFq9tpk8sR8GM0Mdf+BkO SzckQ5vrDMZtdir4h/Oayis/zR8xwxABWuzNQCg5Tqsrf8M5zLhyDTLm+g/+cYZpJPyy4MarFf3C J7Aqj/rY5Tl5tkOTyb/nJ/Vpbv8AMZbEsfR02zhjRO3KWsrN8yHUfRlmIbMJ802/5xU8t2955j1X Xp0DtpUMcNryH2ZbotydfcRxlfk2DMdqTAPp7MdsdirsVdirxD/nK/8A5Q3SP+2iP+TEmXYebCbw H8ufN0flDzlp/mKS2N4lj61bZXEZb1YHh+0Q1KepXpl0o2KYA09t/wCht9O/6lqb/pKX/qllPg+b Pjd/0Nvp3/UtTf8ASUv/AFSx8HzXjekf8rQg/wCVW/4//R7ej6Xrfo/1Ry/v/Qp6nGnv9nIcG9Mr 2t8beYmVvMGpspBU3c5BG4IMjZlDk0l9AecPy+/xL+Q3lvVbOLlq+h6ZDPHxHxSW/pgzR+JoBzX5 UHXKIyqRbCNnlH5O/mA/kvzjb3kzH9FXlLbU07ekx2kp4xN8XyqO+WzjYYRNJv8An7+Yy+bfNZsr Cb1ND0ctDbMhqks1aSzCmxBI4qfAVHXBjjQTI29F/wCcdfy9/R3le/8AN9/FS81OCWLTlYbpagHl Jv0MrD/gQPHK8st6ZRD5qzIa36AeW/8AlHdL/wCYSD/k0uYR5t4fN3/OV/8AymWkf9s4f8n5Mvw8 muaI/wCcTP8AlIte/wCYSL/k7jm5LB9A+dv+UN17/tnXf/Jh8ojzZl8D5mtL0+2/5yN/M21s4rSG 4tVigjWKM/V1JCovEdT1oMr8IMuIsX82fmZ5482RiHXNVkuLVTyW1QJDDUdCY4gisR2LVyQgByQS SmP5X/lVrvnjV4ljie30OJx9f1IiiKo3ZIydmkPQAdOp2wTmAoFvtOxsrWxsoLK0jENraxpDBEvR Y41Cqo+QGYjc+dP+ctv+Oj5a/wCMN1/xKLL8PVrm8l/L/wDMDWfIuszatpMNtPcz2zWjpdq7oEd0 kJAjeI8qxDvlso2xBp6B/wBDWfmH/wBW7SP+RNz/ANlOQ8EMuMu/6Gs/MP8A6t2kf8ibn/spx8EL xl5f5s8zX/mfzDea7fxxRXd8yvLHAGWMFUVBxDs7dF7tlgFCmBL6d/5xd/8AJay/9tGf/k3FmPl5 tsOTyL/nJmwltvzPmncHhe2dvNGfZVMJ/GLLMXJhPmyj/nE3W7eLU9e0WRgJrqKC6twdqiAukgHi f3qn78jmCYPpPKGx2Kvm/wD5yo1TU7PzBoa2d3NbK9pKWWGR4wT6nU8SMvwjZrmiP+cVNT1K91Dz GLy7muQkVqUE0jSUq0taciaY5hyWCc/85X/8obpH/bRH/JiTBh5pm+e/IvlK483eabLy9bXCWs17 6vCeQFlX0oXmNQN9xHTLpGhbAC3rP/QpnmL/AKv1p/yKlyvxgy4Hf9CmeYv+r9af8ipcfGC8D1f/ AJVjf/8AKnP8BfXYvrno+j9d4t6dfrHr14/a6bZVx+q2VbU+ONQZWv7llIKmVyCNwQWOZQan3P8A lsiL+XXldVACnSbEke7W6E/eTmJLmW4cnyp+eP5f/wCD/OcwtY+GjanyutOp9lQT+8hH/GNjt/kl cyMcrDXIUlH5XeRbjzp5wtNIUMtkp9fUpl/YtoyOe/YvUIvucM5UEAW+2ZrSG30d7O0iEcMVuYbe CMbKqpxRFA8BsMxW5+fWZrQ++PJRJ8m6CT1/R1p/yYTMKXNuD52/5yv/AOUy0j/tnD/k/Jl+Hkwm iP8AnEz/AJSLXv8AmEi/5O45uSwfQPnb/lDde/7Z13/yYfKI82ZfA+ZrS+rtK/5xv/LS90WzuJI7 xZ7m2jkd0uDs8kYJKgqR1PcZjHKWzhD5+/M38utT8i+Y30y6Yz2cwMunXoFBLFWm/g69GX+BGXQl YYEU9M/ID86I9LMXlLzJcrHpp20q/lIUQMTX0ZGP+62J+Fj9k7dPswyQ6hlGT6YBBAINQdwRmO2P m7/nLb/jo+Wv+MN1/wASiy/D1a5vP/yU/L/RvPXmq60nVprmC2gsZLtHtGRHLpNFGATIko40lPbL MkqCIi3tf/Qqf5ef9XHV/wDkdbf9k2U+MWXAHf8AQqf5ef8AVx1f/kdbf9k2PjFeAPnn8yfLNh5Y 876roVhJLLaWMiJFJOVaQhokc8iiovVuy5fE2LYEbvo7/nF3/wAlrL/20Z/+TcWUZebZDkt/5yR/ L648w+WYdc06IyalonNpY1FWktXoZAKdTGVDD25Y4pUaRIPmDy55h1Xy7rdprOlS+jfWb84mIqpB BVlYd1ZSVI8MyCLawX1v5C/PjyT5ns4kvLuLR9XoBPZXbiNC/cwytRHBPQV5e2Y0sZDaJWz19Y0h IvVe+t1iAqZDKgWh71rTIUyfL3/OTXmXQNb8x6UNI1CDUBaW0kdw9u4kRXaSoXmtVJ+RzIxAgNcy nf8AziT/AMdHzL/xhtf+JS5HN0WDIv8AnK//AJQ3SP8Atoj/AJMSYMPNM3jv5CXNvbfmzoU9zKkM KfW+csjBFFbOYCrGg6nLcn0sY832B/iTy7/1dLT/AJHxf81Zi0W23f4k8u/9XS0/5Hxf81Y0Vt3+ JPLv/V0tP+R8X/NWNFbfCH+HPMP/AFa7v/kRL/zTmZYaKfcH5eRyReQPLMUqFJE0qxV0YEMrC2QE EHoRmJLmW4cl3nDyN5Z84WEVjr9r9Zggk9aEq7xur0K7MhU0IO46YxkRyUi1DyZ+XPlHyat0NAsz bNeFTcSPI8rsErxHJyxAHI7DGUieagUyXIpfn/8A4c8w/wDVru/+REv/ADTmbYaKfcP5epLH5B8t RzKySppVisiuCGDC2QEMDvWuYkuZbhyeDf8AOUmlapeeb9Je0s57lF08KzRRu4B9eQ0JUHLsJ2YT RH/OK+l6nZ+YNca8tJrZXtIgrTRvGCfU6DkBgzHZYPePOSPJ5Q1xEUu76fdKqqKkkwMAABlMebMv hf8Aw55h/wCrXd/8iJf+aczLDTT7w8vKy+X9MVgVZbSAMp2IIjXY5hnm3hJvzH/L7SvPPl2TSr0+ jcIfVsL1QC8MwFAfdW6Mvce9CDGVFBFvjnzh+X/mzyleyW2tWEkUatSO8VS1tIK7FJQOJr4Hcdxm VGQLURT0z/nFe91CXzxfW8k8r2cOlS8IWdjEjG5gpRSeIPXK83JlDmnf/OVemale6h5cNnaTXISK 6DmGNpKVaKleINMGE81mk/8Azi9pOq2fn/UJbuynt4zpUyh5YnRSxubc0qwG+2HKdlhzfUGY7Y7F Xxv+duh61cfmlr81vp9zNC8sZSSOGRlP7iMbEAjMrGdmqQ3e4f8AOM9neWn5dSxXcElvL+kJ29OV GRqFI96MAcpy82cOT1jK2TwX80f+cbIdSuJtX8mmO0uZCXn0iQ8IWY7kwP0jJP7B+HwK9Muhl72B g8C13yV5t0CRk1jSLqy4EgySRN6Rp/LKAUYe6tlwkCwISVVZmCqCWJoANySckhlHlz8sPPvmKVF0 vRLl4n/4+ZUMMAHj6svBPoBrkTMBIBfTv5LflDP5BtLye+vlu9T1JY1uI4QRBEsRYhVZgGc/HuSB 8u+Y+SfE2RjSR/8AOUljfXnlDSUtLeW5ddQDMsSM5A9CQVIUHDh5om+Z/wDDnmH/AKtd3/yIl/5p zIsNdO/w55h/6td3/wAiJf8AmnGwtO/w55h/6td3/wAiJf8AmnGwtO/w55h/6td3/wAiJf8AmnGw tP8A/9k= + + + + uuid:e4d4e5bb-1cf7-e542-bf3f-b9911c13fa0b + xmp.did:3b81609e-aefd-4ee8-a794-d6d24a4d8ac6 + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + xmp.iid:d6f6ba12-a5c3-42d0-9afe-14c7af2144f1 + xmp.did:d6f6ba12-a5c3-42d0-9afe-14c7af2144f1 + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + + + + saved + xmp.iid:48fef565-7731-4c49-bee9-dfbb0bfe5fa3 + 2017-02-28T19:39:58-06:00 + Adobe Illustrator CC 2015 (Macintosh) + / + + + saved + xmp.iid:3b81609e-aefd-4ee8-a794-d6d24a4d8ac6 + 2017-04-12T20:05:02-05:00 + Adobe Illustrator CC 2017 (Macintosh) + / + + + + Document + Print + False + False + 1 + + 300.000000 + 300.000000 + Points + + + + Cyan + Magenta + Yellow + Black + + + + + + Default Swatch Group + 0 + + + + White + RGB + PROCESS + 255 + 255 + 255 + + + Black + RGB + PROCESS + 35 + 31 + 32 + + + + + + Mirage RGB + 1 + + + + R=39 G=50 B=73 + RGB + PROCESS + 39 + 50 + 73 + + + R=110 G=116 B=125 + RGB + PROCESS + 110 + 116 + 125 + + + R=54 G=181 B=192 + RGB + PROCESS + 54 + 181 + 192 + + + R=112 G=201 B=203 + RGB + PROCESS + 112 + 201 + 203 + + + R=255 G=147 B=67 + RGB + PROCESS + 255 + 147 + 67 + + + R=254 G=201 B=78 + RGB + PROCESS + 254 + 201 + 78 + + + R=214 G=237 B=162 + RGB + PROCESS + 214 + 237 + 162 + + + + + + Grays + 1 + + + + C=0 M=0 Y=0 K=100 + RGB + PROCESS + 35 + 31 + 32 + + + C=0 M=0 Y=0 K=90 + RGB + PROCESS + 64 + 64 + 65 + + + C=0 M=0 Y=0 K=80 + RGB + PROCESS + 88 + 89 + 91 + + + C=0 M=0 Y=0 K=70 + RGB + PROCESS + 109 + 110 + 112 + + + C=0 M=0 Y=0 K=60 + RGB + PROCESS + 128 + 129 + 132 + + + C=0 M=0 Y=0 K=50 + RGB + PROCESS + 146 + 148 + 151 + + + C=0 M=0 Y=0 K=40 + RGB + PROCESS + 166 + 168 + 171 + + + C=0 M=0 Y=0 K=30 + RGB + PROCESS + 187 + 189 + 191 + + + C=0 M=0 Y=0 K=20 + RGB + PROCESS + 208 + 210 + 211 + + + C=0 M=0 Y=0 K=10 + RGB + PROCESS + 230 + 231 + 232 + + + C=0 M=0 Y=0 K=5 + RGB + PROCESS + 241 + 241 + 242 + + + + + + Brights + 1 + + + + C=0 M=100 Y=100 K=0 + RGB + PROCESS + 236 + 28 + 36 + + + C=0 M=75 Y=100 K=0 + RGB + PROCESS + 241 + 101 + 34 + + + C=0 M=10 Y=95 K=0 + RGB + PROCESS + 255 + 221 + 21 + + + C=85 M=10 Y=100 K=0 + RGB + PROCESS + 0 + 161 + 75 + + + C=100 M=90 Y=0 K=0 + RGB + PROCESS + 34 + 64 + 153 + + + C=60 M=90 Y=0 K=0 + RGB + PROCESS + 127 + 63 + 151 + + + + + + + Adobe PDF library 15.00 + 21.0.2 + + + + + + + + + + + + + + + + + + + + + + + + + endstream endobj 3 0 obj <> endobj 7 0 obj <>/Resources<>/ExtGState<>/Properties<>>>/Thumb 66 0 R/TrimBox[0.0 0.0 300.0 300.0]/Type/Page>> endobj 62 0 obj <>stream +HtWId ܿS a6a^۽wpI YF+DqR_Oq_\N^?y~u{JQ7z߿>_~]؛9;f}_]n)Q;kC«>Qqw zWK Mх7,Cu>n2vIsu!ݏn2((q=Zs{qHG6 yx)R+cT 3Nrq!;UW{<\]V~zm ^NpWaI x487l"Txq(yZ {#*͍:e1p%\ (z߲# +:8_KU\R؜Gx!xܲܐcK 7*!v0N CjT|UJjի\ĶϽph'o;@P^ʁi| +%1~Biˇ 0 !#jаqiqI sUݛ˽ߑ$Iܱ<F#@K/"'`1YG#fq$aҞ*06u|B#5 H%#ڹ 2s2<[Z52]C䤣N:*ւv+Mjߊc%+wqPA# rquf~ԏ#/=W]DžJ.Ɨਈ/h߶&IzRk?f m4^~\z+^_m].ŢMU+Z._6?6砹]Q+୯ zSգb}6W.i8c (!+y6h#@dJuF椈6'á fAl2SA;" Eٵ*I E @pn{q ùA쟘F"ժE|oW]$p. 1jPWSNpAh8~ i$ + 2 hYBBŜ՘ߌ=)Gt82PT0L a^\h +l);\22^tbm)ZtKJy 0D-"W⃌2ۼVR84 DS ZY ,>4lj,ZI{[gO +I2l fV\ɅNHEL)*,*%;ed+:xf:$<k}Mb`r@! `m|TF&RRQ6jL@n ok)aIxLSE--+T.|Uuil\ I7i!r<5['(rTyNn;>#E օ]AI1ӘK\GA-&‰PuHR!|k|HRbBA:Ekc@ /)Da˦)V-`TwGa\n* 2޶ywɲ Cs ,q)\YDWX|OhZO,1O iK[f^m |:h^ ϑ;ݚo3^qoZ&F*)9ls#E>*A;/X/_e0~mr\CU:'n6jhr c@)‚S-`.I̘a3y "dm&4BdA&#MҢa2{K!kʋw4w']%As +刿ima#36Yn@.Bͻd0g%`|.B|A-*Gb@Neyύ`Im //F zfWA_J* dxXc',.VRbGy8Iu-@ +}r,!gVqZ`4$Q2 .ɅB D F<_S;Lv^⁻e,!HΰZ*FWnRGm#G Cgfnn[(261o@|nuH֮ia ͺ t%x@xA^9M) ?vIY30ǂʇ1 +C1 t&9%G8} +0g +R@fy/9!O m9\. "9㰙+rZ}ɼ%&pWOpRGI_|EeǙ`+*?K5`؟I-aJ6WQ!#*m1$# +V2%@5Hq:Kuc%*B?xZra51d*!\$%9vT>?5C1ѵ6U f|];m}|ڀfpMh4xS?#`dc & y8NDmLS;Ȅ{yqut LQ:uՠkfք1GѼ4%'zf^:y|W+ >O{Ed$V=5]k;* oK9dPȺsSivta$U:_U%:q&$x.N sIPX(]m14q!2b(dȏ`~,F. \,h{MӜT&JirpaõuJ ޕC{5)A̬On~vUTjm +ϫ|?VYT6dXKK4L>K1Z.% +7l4~tل_?:ʖN7fhCV$;+H::m-)RT</%O}| n^}OJM̤Բ1sEgitP,hr +20Om0 ҨfBgg6]+b:, `Y;ʠk +y4+[f2VD? "kw +6s:J6f" LŶҖ޹sY@)|fcW/8, MIaN$GӵX4OJv0jXϼPt#B# + ICPSÆE}8qC^d݂0l0q] /a`b KCiwc~= IDŽN&`/,F +Aa*N O#]]|arM 46g͠1H@ʤȈ PGA OKs#S{8pxQ0!&",WVox{HqĪc*.c4f7̬ +ĭ03{#2` \]kcN?І2>W'+,L#J}025@`ֵ+CCwx1>\BcxM'44]4_J=Lum|i;W endstream endobj 66 0 obj <>stream +8;XF36#qJu$q7'E�s!0X0P?XuMBN_7ra/*s>PHgJ5Wh!lWD(LqoW7k4"t,;k>QG +Y3o2@50Z[qD$!+Ekj4DA:8A\+.@OJ<$rOEAem/maS.sYT.Zl1A0]c2rK-K"ej#ei9 +-I\At.@!j^MnckS4)S\ endstream endobj 67 0 obj [/Indexed/DeviceRGB 255 68 0 R] endobj 68 0 obj <>stream +8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0 +b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup` +E1r!/,*0[*9.aFIR2&b-C#soRZ7Dl%MLY\.?d>Mn +6%Q2oYfNRF$$+ON<+]RUJmC0InDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j$XKrcYp0n+Xl_nU*O( +l[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\~> endstream endobj 60 0 obj <> endobj 69 0 obj [/View/Design] endobj 70 0 obj <>>> endobj 65 0 obj <> endobj 64 0 obj [/ICCBased 71 0 R] endobj 71 0 obj <>stream +HyTSwoɞc [5laQIBHADED2mtFOE.c}08׎8GNg9w߽'0 ֠Jb  + 2y.-;!KZ ^i"L0- @8(r;q7Ly&Qq4j|9 +V)gB0iW8#8wթ8_٥ʨQQj@&A)/g>'Kt;\ ӥ$պFZUn(4T%)뫔0C&Zi8bxEB;Pӓ̹A om?W= +x-[0}y)7ta>jT7@tܛ`q2ʀ&6ZLĄ?_yxg)˔zçLU*uSkSeO4?׸c. R ߁-25 S>ӣVd`rn~Y&+`;A4 A9=-tl`;~p Gp| [`L`< "A YA+Cb(R,*T2B- +ꇆnQt}MA0alSx k&^>0|>_',G!"F$H:R!zFQd?r 9\A&G rQ hE]a4zBgE#H *B=0HIpp0MxJ$D1D, VĭKĻYdE"EI2EBGt4MzNr!YK ?%_&#(0J:EAiQ(()ӔWT6U@P+!~mD eԴ!hӦh/']B/ҏӿ?a0nhF!X8܌kc&5S6lIa2cKMA!E#ƒdV(kel }}Cq9 +N')].uJr + wG xR^[oƜchg`>b$*~ :Eb~,m,-ݖ,Y¬*6X[ݱF=3뭷Y~dó ti zf6~`{v.Ng#{}}jc1X6fm;'_9 r:8q:˜O:ϸ8uJqnv=MmR 4 +n3ܣkGݯz=[==<=GTB(/S,]6*-W:#7*e^YDY}UjAyT`#D="b{ų+ʯ:!kJ4Gmt}uC%K7YVfFY .=b?SƕƩȺy چ k5%4m7lqlioZlG+Zz͹mzy]?uuw|"űNwW&e֥ﺱ*|j5kyݭǯg^ykEklD_p߶7Dmo꿻1ml{Mś nLl<9O[$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! +zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km endstream endobj 63 0 obj <> endobj 72 0 obj <> endobj 73 0 obj <>stream +%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 17.0 %%AI8_CreatorVersion: 21.0.2 %%For: (Lindsey Wilson) () %%Title: (Ember-CLI-Mirage-Logo-Stacked-Color.ai) %%CreationDate: 4/12/17 8:08 PM %%Canvassize: 16383 %%BoundingBox: -130 -1073 143 -796 %%HiResBoundingBox: -129.654645872944 -1072.96321614583 142.577776002053 -796.918294270834 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 13.0 %AI12_BuildNumber: 242 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%RGBProcessColor: 0 0 0 ([Registration]) %AI3_Cropmarks: -144.666666666667 -1088.66666666667 155.333333333333 -788.666666666668 %AI3_TemplateBox: 306.5 -396.5 306.5 -396.5 %AI3_TileBox: -282.666666666667 -1294.66666666667 293.333333333333 -560.666666666668 %AI3_DocumentPreview: None %AI5_ArtSize: 14400 14400 %AI5_RulerUnits: 2 %AI9_ColorModel: 1 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 1 %AI17_Begin_Content_if_version_gt:17 1 %AI9_OpenToView: -3343 223 0.3333 2549 1289 18 1 0 5 43 0 0 0 0 1 0 1 1 0 1 %AI17_Alternate_Content %AI9_OpenToView: -3343 223 0.3333 2549 1289 18 1 0 5 43 0 0 0 0 1 0 1 1 0 1 %AI17_End_Versioned_Content %AI5_OpenViewLayers: 7 %%PageOrigin:0 -792 %AI7_GridSettings: 72 8 72 8 1 0 0.800000011920929 0.800000011920929 0.800000011920929 0.899999976158142 0.899999976158142 0.899999976158142 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream endobj 74 0 obj <>stream +%%BoundingBox: -130 -1073 143 -796 %%HiResBoundingBox: -129.654645872944 -1072.96321614583 142.577776002053 -796.918294270834 %AI7_Thumbnail: 128 128 8 %%BeginData: 13896 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C45FD50FFAF84FD7EFF5A60AFFD7CFFA86035AFFD7AFF845960356035 %6060FD78FF84605A605A605A84FD7AFFAF355A84FD7DFF845AFD5CFFCFC9 %A0C9A1C9A0C9A1C9A0C9A1C9A0C9A1C9A0C9A1C9A0C9A1C9A0C9A1C9A8FF %FFFF8484FD5CFFC9C1C2C1C1C1C2C1C1C1C2C1C1C1C2C1C1C1C2C1C1C1C2 %C1C1C1C2C1C1C1C2CFFD4CFF848484AFA8FD0EFFCA99C2A7CAC9CAA7CAC9 %CAA7CAC9CAA7CAC9CAA7CAC9CAA7CAC9CAA7CAC9C299C9FD4AFFA95A6035 %60356060FD0DFFC9C2C9FD1BFFCAC1C2FD48FFAF84355A5AA98484593635 %AFFD0BFFCA99C9FD1BFFCA99C9FD48FF853560A9FD05FF84605AFD0BFFC9 %C2C9FD1BFFCAC1C3FD47FFAF3560A8FD07FF843660FD0AFFCA99C9FD1BFF %CF99C9FD47FF846084FD09FF5A6084FD09FFC9C1C9FFFFFFC2C2C9FFFFFF %CAC2C2FD0FFFCAC1C9FD46FF846035AFFD09FF8435363584A9FD06FFCA99 %C9FFFFA1C199C1CAFFCAC299C1A0FD0EFFCA99C9FD45FF60603560FD0AFF %AFAF84843584FD06FFC9C1C9FFFFC9C1C2C1CFFFFFC2C2C1C9FD0EFFCAC2 %C9FD44FF603659AFA8FD0DFFA86035AFFD05FFCA99C9FFFFCFC99FC9FFFF %FFCAA0C2CAFD0EFFCA99C9FD43FFA86060FD11FF846084FD05FFC9C2C9FD %1BFFCAC1C2FD43FFAF3584FD11FFA83584FD05FFCA99C9FD1BFFCA99C9FD %43FFAF6060FD11FF6060A8FD05FFC9C2C9FD1BFFCAC1C3FD44FF5A5A5AA8 %A8FD05FFA8A984AF84AF84AF5A365AFD06FFCA99C9FFFFCACFCACFCACFCA %CFCACFCACFCACFCACFCACFCACFCAFD04FFCF99C9FD45FF60603560FD05FF %84356035603560356060FD07FFC9C1C9FFFFC999C2C1C29FC2C1C29FC2C1 %C29FC2C1C29FC2C1C1C9FFFFFFCAC1C9FD0DFFA8FD38FF848484FD05FFFD %0984FD08FFCA99C9FFFFC9C2A0C9A0C9A0C9A0C9A0C9A0C9A0C9A0C9A0C9 %A0CAFFFFFFCA99C9FD09FFAF5A60355A3584A8FD4EFFC9C1C9FD1BFFCAC2 %C9FD08FFAF5A605A846060356084FD4DFFCA99C9FD1BFFCA99C9FD07FFAF %355A84FFFFFFA885355A84FD4CFFC9C2C9FD1BFFCAC1C2FD07FF5A6084FD %06FFAF3560848460AFFD48FFCA99C9FD04FFCAFD05FFA8FD10FFCA99C9FD %06FFA85A59FD08FF603536355A3560A8FD46FFC9C2C9FFFFFFC2C2C2FFFF %FFC9C2C1CAFD0EFFCAC1C3FD06FFAF358BFD08FFA984A8FFAF843585FD46 %FFCA99C9FFFFA1C19FC1C9FFCFC299C2A0FD0EFFCF99C9FD06FF843684FD %0DFFAF6035FD46FFC9C1C3FFFFCA99C2C1FFFFFFC2C199C9FD0EFFCAC1C9 %FD06FFAF3584FD0EFF8460A8FD46FFA1CFFFFFFFC9A0CFFD04FFA1C9CAFD %0EFFCA99C9FD06FFA86035AFFD0DFF8435AFFD63FFCAC2C9FD07FF843C84 %FD0DFF5A60AFFD42FF35AFFD1FFFCA99C9FD08FF84AFFD04FFA8AF84AF84 %AFA884355A84FD42FF846084FD1FFFCAC1C2FD0EFF843560356035603560 %84FD41FFA95A5A35605984AFFFFFFFA1C29FC29FC29FC29FC29FC29FC29F %C29FC29FC299CAFFFFFFCA99C9FD0EFFA8FD0784A8FD42FF846059605A60 %84FD04FFCAC1FD13C2C9FFFFFFCAC1C3FD5BFF843584FD0AFFCFFFFFFFCF %FFFFFFCFFFFFFFCFFFFFFFCFFD04FFCF99C9FD5BFFAF60A8FD1FFFCAC1C9 %FD1DFFCFFFCFFFCAFD3AFFA8FD20FFCA99C9FD16FFA8CAA7C9A0C29FC299 %C29FC299C2CAFD58FFCAC2C9FD13FFC9C9C2C2C1C1C1FD04C2C9C2C8C2C8 %C2FD40FFCFC9A0C9FFFFFFCAA0C2CAFD0EFFCA99C9FD10FFC9C39FC199C2 %A0C9C9CACAFD49FFC9C1C299CFFFFFC2C2C1C8FD0EFFCAC1C2FD0DFFCFC9 %C2C1C1C2C3CFCFFD4EFFA1C19FC1A8FFCFC299C1A0FD0EFFCA99C9FD0CFF %A0C299C1A0CACFFD52FFC2C2C9FFFFFFCAC8C2FD0FFFCAC1C3FD0AFFC9C1 %C2C2C9CAFD3CFFCACFC9CAA7CAC9C9A7CACACFCAFD24FFCF99C9FD08FFA7 %C299C2A0FD3AFFC9C9C2C2C1C299C1C1C199C1BBC199C2C1C2C2C9C3C9CA %FD1FFFCAC1C9FD06FFCFC2C19FC9CFFD36FFA8CAA0C299C199C19FC2A0C9 %A1C9C9C9A1C9C9C9A0C9A0C299C199C199C2A0C9A8FD1AFFCA99C9FD04FF %CAC999C1A0CAFD36FFCFC2C2C1C1C1C9C9CFCAFD11FFCACAC9C9C2C2BBC2 %C2C9C9FD17FFCAC2C9FFFFFFC9C2BBC2C9FD36FFA1C299C19FC9C9FD1BFF %CAC9A0C299C199C8C9CFFD13FFCA99C9FFCA9FC19FC9CAFD35FFC9C1C19F %C9CAFD21FFCFCFC9C29FC1C1C2C9FD11FFCAC1C2C9C1C2C2FD38FF9FC2A0 %CFFD27FFCFA1C299C199C2C9FD0DFFA7C999C199C9CAFD3AFFCFFD2DFFC9 %C8C1C1C1C9CAFD05FFCACFC9C9C2C2C1C2C2CFFD6CFFCFC3C299C19FC29F %C29FC299C199C2A0CACAFD71FFCAC2C2C1C29FC2C2C9C9CFFD77FFA8C9A0 %C199C2A1FD7CFFCAC9C1C1C1C9CAFD7CFFC9C299C1A0C9CAFD7BFFCFC2C2 %C1C2C2CAFD7BFFA8C9A0C199C2A0CACAFD7AFFCAC9C2C1C1C8C9CFFD7BFF %C9C299C19FC2A1CFFD1CFFCAC9A0FD5CFFC9C8C1C19FC8C9CFCFFD16FFCF %C2C2BBC2CAFD5CFFCFCFA1C299C199C2A0C9C9CFCAFD0DFFCACAA1C299C1 %99C9CAFD62FFC9C9C2C2C1C1C1C8C2C9C9CFCACFCACFCACAC9C9C2C2C1C1 %C1C8C9FD68FFCACAC2C29FC299C199C199C199C199C199C29FC9A7CFFD6F %FFCACFC9C9C3C9C3C9C3C9C9CFCAFDFCFFFDFCFFFDFCFFFDFCFFFDA3FFAF %FFAFFFAFFFAFFFAFFFAFFD05FFAFFD15FFAFFFAFFFAFFFAFFD09FFAFFFAF %FFAFFFAFFFAFFFAFFD05FFAFFFAFFFAFFFAFFD16FFAFA8AFA9FD07FFAFFF %AFFD0BFFAFFFAF596035605960356059603560AFFFFFAF355A84FD0BFFAF %603584FD04FF5960596035605960598484FD05FFA8605960356059603560 %596035FFFFFF8460596035605960598484FD10FFA95A60355A3560596084 %FFFFFF84603560A8FD09FFA8603560605A6035605A6035605A6059FFFFFF %A8605A60AFFD0AFF85356084FD04FF6035605A6035605A60356060FD05FF %5A605A6035605A6035605A60A9FFFFAF35605A6035605A60356060FD0DFF %AF84356059605A6035605A6084FFFFA9356060FD0AFFAF5A605935603560 %5960596059605960A8FFFFAF35603584FD09FFAF35603584FD04FF5A5A35 %605A605960355A355A5AFFFFFFAF603560596059605960596059AFFFFF84 %5A356059605960355A35605AFD0BFFA8603560355A35605960356035AFFF %FF845A3560A8FD09FF84603560605A6084FD0BFFA8605A605AFD09FF6060 %5A6084FD04FF84596084FD05FF60605A60AFFFFFFF5A605AAFFD0BFFAF35 %605AFD04FFAF5A605A6084FD0AFF8435605A6084FD04FFAF8484FFFFFFAF %356060FD0AFFAF5A605A35603584FD0BFFA93560595A5AFD07FF84605960 %3584FD04FF5A603584FD05FFAF356035AFFFFFAF60356084FD0BFF845A35 %60AFFD04FFAF35603584FD09FFA935603584AFFD0BFF845A3560AFFD09FF %A860596060596084FD0BFFA86059605A60A8FD06FF6035605A6060FD04FF %845A6084FD05FFA9605960AFFFFFFF606035AFFD0BFFAF356059FD06FF84 %356060FD09FF5A605A60AFFD0CFFAF5A605AFD0AFFAF35605A35603584AF %FFA8FFA8FFA8FD04FFAF356035603560A8FD04FF84356035603560A8FFFF %FF59603584FD04FFA86035365AFFFFFFA860355A84FFA8FFA8FFA8FFA8FF %FFFF845A3560A8FD05FF845A3560AFFD07FFA85A356084FD0DFF84603560 %A8FD09FFA85A3560605A605A605A605A605A84FD04FF84605A84606035AF %FD04FF5A605A845A6060FD04FF845A605A8460845A605A6084FD05FF6060 %5A605A605A605A605AFD04FFAF36605AFD06FF605A6060FD08FFAF59605A %AFFD0DFFAF5A605AFD0AFFAF59605A5960356035603560355A59FD04FFA9 %355A5AAF356035FFFFFF5A60358484603560FD04FF596059603560355A35 %603584FD04FFA86035603560356035603560A8FFFFFF84605960A8FFFFFF %A884356035A9FD08FF845A3560A8FD0DFF84603560A8FD09FFA860356060 %5A605A605A605A605A60AFFFFFFF84605A84FF855A6084FFA8603560FFAF %356060FD04FF60356060846084606035603684FD04FF5A605A605A605A60 %5A6060FD04FFAF35605A848484606035603660FD09FFAF5A6035AFFD0DFF %A9356060FD0AFFAF5A605935603584FFFFAFFFA8FFAFFD04FF8435605AFF %A860355A8460355A84FF845A3560AFFFFFFF5A5A3584FFFFAFFFAF843560 %3584FFFFAF60356084FFA8FFAFFFA8FD05FF845A3560355A356035603560 %A8FD09FFA860355A84FD0DFF845A3560A8FD09FF84603560605A6084FD0B %FF84605A84FFFF84605A605A605AFFFFAF356060FD04FF84596084FD06FF %855A6060FFFFFF5A6036AFFD0BFFAF35605A6035605A605984FD0CFF6060 %5A84FD0DFFAF356060FD0AFFAF5A605A35603584FD0BFF84356060FFFFFF %5960356035AFFFFF845A3560FD04FF5A603584FD06FF60603560FFFFAF60 %356084FD0BFF845A356084AF8460356035AFFD0BFF8535603584FD0CFF84 %5A3560AFFD09FFA860596060596084FD0BFF84603584FFFFFFAF36603584 %FFFFFFAF5A605AFD04FF845A6084FD05FFA860596084FFFFFF606035AFFD %0BFFAF356059FFFFFFA9605A6035AFFD0BFF605A603584A8FD05FF84AFFF %FFFFAF5A605AFD0AFFAF35605A356035605A6059845A605960A8FFFF8435 %5A5AFD04FF60355AA8FFFFFF84603560A8FFFFFF596035605A8460845960 %356035AFFFFFA860356059845A6059845A6059AFFFFF845A3560A8FFFFFF %8460355A358484FD09FFA8603560356059605960355A35AFFFFF84603560 %59845A6059845A6084FFA85A3560605A605A6035605A6035605AFFFFFF84 %603584FD04FFAFAFAFFD04FFAF5A605AFD04FF845A605A605A6035605A60 %3585FD04FF60605A605A6035605A603560A9FFFFAF36605AFD05FF84605A %603660AFFD09FFAF6035605A6059605A605A6084FFFFAF5A605A605A6035 %605A6035AFFFAF35605A356035603560356035603560A8FFFF84355A5AFD %0BFF84603560A8FFFFFF596035603560356035605AA9FD04FFA860356035 %6035603560356035AFFFFF84603560A8FD05FF8460356035FD0CFF845960 %355A3560356084FFFFFF84603560356035603560355A84FFA85A3560FFAF %AFA8FFAFAFA8FFAFAFA8FFFFFFA8AFA9FD0DFFA8AFAFFD05FFA8FFAFAFA8 %FFA9AFAFFD07FFA8AFAFAFA8FFAFAFA8FFAFAFFD04FFA8FFAFFD07FFAFAF %84AFFD0EFFA8AF84AF84FD07FFA8FFAFAFA8FFAFAFA8FFA9FFFFFFA9AFA8 %FDFCFFFDFCFFFDFCFFFDFCFFFD91FFA8FFA8FD11FFA9FFA8FD07FFA8FFA8 %FD07FFA8FFA8FFA8FFA8FFA8FD13FFA9A87D7E7DA8A8FD13FFA8A87D7E7D %A8A8FD0BFFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA87D270528A8FD0FFFA828 %05277EFD05FF2827052752FD05FF52272728052827270528275253A9FD0D %FFA82E28052700270027277DA8FD0EFFA82E28002700050027272E53FD07 %FF28272727052827280528272805282728A80028007DFD0FFF53002827A8 %FD05FF5205280053FD05FF53002827280528272805282727057DFD0BFF7D %05270528272827282728002EA8FD0BFFA852002827282728272827282727 %057DFD05FF520028272805282728052827280528277D27002700A8FD0DFF %A8002700277DFD05FF2727052728FD05FF52270528052700270027002805 %270052FD09FF5200270527002700270028052700277EFD09FF5327002705 %28052700270027002805052EFD05FF282705280527002700270027002700 %277E0028272752FD0DFF2828272805A8FD05FF5227280553FD05FF530528 %272828522E52272827282728007DFD07FF7D002827280528527D52520528 %27282728A9FD07FF532727282728052827522E522728052827FD06FF5205 %28272828522E5228522E5228522E7D05052827277DFD0BFF532727270527 %7DFD05FFFD04272EFD05FF5227052728FD05FF7E520027052805A8FD06FF %272705280052A8FD04FFA827270528007DFD06FF7D2705282727057DA8FD %05FF7D59007DFD06FF2827052728FD0BFF7E00282728272EFD0AFFA82805 %28272800A8FD05FF5205280553FD05FF5305280552FD07FF53052827277D %FD05FF7D2727280053FD07FFA82728272828FD05FFA82E2728272828A8FD %11FF5227280052FD0BFF532705270528007DFD09FF530027052805057DFD %05FF282705272EFD05FF2E27052727FD07FFA82805270052FD05FF520028 %0527A8FD08FF7D002705277DFD04FF7D0028052727FD13FF2827052728FD %0BFF7D05282728272827FD08FFA8052827282728007EFD05FF5205280553 %FD05FF5327280552FD08FF5228272828FD05FF2828272852FD09FFA82827 %28057EFD04FF2828272805A8FD13FF5227280553FD0BFF52272727002827 %2752FD07FFFD0427002827277DFD05FF2827052752FD05FF2EFD0427FD08 %FF5200270052FD04FFA8270528007DFD0AFF2727052752FFFFFFA8270528 %0052FD14FF2827272728FD0BFF7D002827522728272784FD05FF7D272728 %28520528057DFD05FF5227280053FD05FF5300282752FD08FF2728272728 %FD05FF272827277DFD0AFF522728007DFFFFFFA8052827277DFD14FF5205 %28272828522E5228522E52287DFF52270527537D0028002EAFFFFFFFA828 %052700845227052759FD05FF2727052728FD05FF5227052728FD07FF5227 %05280053FD04FFA8280527007DFD0AFF2727052752FFFFFF5327052700A8 %FD14FF282705280527002700270027000527FF530528057DFF5227280084 %FFFFFF5905280553FF530528057DFD05FF5227280553FD05FF5305282752 %FD06FF522727282727A8FD05FF272827277DFD0AFF522728057DFFFFFF7D %05282728A8FD0BFF7D5352537DFD04FF5205282728272827282728272805 %52FF5227052752FF7DFD0427FFFFA800280527A8FF2E27052752FD05FFFD %04272EFD05FF52270528275252532E2800272727052752FD05FFA8280527 %0052FD0A7D2728272752FFFFFF5927272700A8FD0BFF5300270052FD04FF %282705282727002805270028052728FF532728007DFFFF2828272753FF28 %27272753FFFF530528007DFD05FF5205280553FD05FF5305282728052700 %2827282728272728FD06FFAF272827280527002700270027002705282728 %057DFFFFFFA80528272753FD0BFF5227272752FD04FF5227280552FD0AA8 %FF2827052752FFFFA8002705282E27052705FFFFFF2827052752FD05FF28 %2705272EFD05FF2E2705270527052700280527002852FD07FFA827002805 %27052805270528052705280527052752FFFFFFA82700280028A8FD0AFF53 %00280052FD04FF2827052728FD0BFF522728007DFFFFFF59052827282728 %007EFFFFFF5327280559FD05FF5205280553FD05FF532728272827282728 %2728272852FD09FF272827280527052700270527002705282728057DFD04 %FF2E282728007DFD0AFF5328272752FD04FF5227280553FD0BFF27282705 %53FFFFFFA82705270528052EA8FFFFFF282727272EFD05FF2827052752FD %05FF2EFD0427A8A8A87D280527052753FD07FFA82705280552FD0A7D2727 %052752FD04FF7E0028272700A8FD09FF5900280052FD04FF2827272728FD %0BFF520528007DFD04FF53272728272784FD04FF5205280553FD05FF5227 %280053FD05FF5300282752FD04FF7D28272827277DFD07FF272827277DFD %0AFF522728007DFD05FF5200282728057DFD08FF5327272852FD04FF5205 %280552FD0BFF2727052753FD05FF2727050528FD05FF5227052752FD05FF %2727052728FD05FF5227052728FD05FF53270527002759FD05FFA8280527 %007DFD0AFF2727052752FD05FFA82700280527002E7DA8A8FFA8A8522805 %270052FD04FF2827052728A87EA884A87EA884A87EA8282728057DFD05FF %A8272827FD06FF7D05282752FD05FF5227280553FD05FF5305282752FD06 %FF5227272827272853A8FFFFFF272827277DFD0AFF522728057DFD06FFA8 %280528272827272728272805282728272852FD04FF520528272827282728 %272827282728272727052753FD07FFA8FD07FF5227052728FD05FFFD0427 %2EFD05FF5227052728FD07FF272705282727F87EFFFFA8280527007DFD0A %FF2827272752FD07FFA8520027052827270528052705280527007DFD04FF %28270528272705280527052805270528282727007DFD0FFF5300270052FD %05FF2E00280052FD05FF5300270052FD08FF2827052827277DFFFFA90528 %270559FD0AFF2E00280053FD09FF7D28270028272827282727002852A8FD %05FF5200270528272705282727052827270528522E527DFD0FFF53522E52 %52FD05FF5252285253FD05FF53522E5252FD09FF7D2E002800A8FFFFA852 %2852287EFD0AFF525228527DFD0BFF7D53272805270028527DA8FD07FF52 %522E5228522E5228522E5228522E52 %%EndData endstream endobj 75 0 obj <>stream +,!-y+m  ei !q-O JC?"hE,լ!tw=e +%B=&Q1%hIDɉe,Nvkb0==-s㉋(7Ĝ# ,neN[#]g:5h/Ft ob0&8dՉ7 dNR&wpLSGmX;& "JS~"]Pk'E  +!9&īxS&+zc0Vha&k)+/֘uJTP3} lT"(ҏ4)YD6噸DMʻIܞHqiM`dUPi[[MECwiп12lM7vYiC+G>^3aEnۊ1Y<G+8S'{ +ۇ 3zNb2E4rpS6,$AG׋fHvH+ 2IYX;E3S O*q=)VPӚl&Rt]EybVF*QJثKC8`&Ȓ'fPiʻy^T" 2C]l!įG*fZ=SsGrlvGAGQP}3AÕH*ū*F*QʬFD%Bl5:1D"R`Lh +@FJJk)EHkL9O#"(MSo m$ hضa +eY?Y46,C{8! Z cPmWwM5IbN +]n;}fH5WぼbɆu[BTsE} *tZ 1?(ʡJ8f{"v ZWx|m])2fb%,+AqkW*b9Ƙ1e% xeŖdz6YbÃyb M.2*rꦆj|؈#2LP4h|³vT/MJz+;fJ%> 5M,6g Y8+yOQ!?8 1R%NbD#hGCV&lOPINueb3* l(p?hʬ# +&;~aŅ64|O EHX0G +%1{69tʐ ;^shO}JM@s@D,A"X((QrO%Nۺk/.< 9Zy9.[V"-v=N}АfK@{Mݦam&Ljʣ{PӝJ$ ,Sr+H,r&Fnw#쒁 3N0y83+bM' c.%&难PMq(ed%JOKqj}oH ~$•)6Dȑ̠#rc4#f+'%s.Nf/ ]6≤iNq>&hXABD;8b Ŋ% q A,Hb2 B¤l؅bx1)-q +*隴VNl$88+eAUJTzn j,V kh09KoGVpz}Hi;&0 b9G=eG$@AF)q|Ē0CJH"G4͸̠!;a| .-9e7ْ~Oι#@,b>FlMLx/b/:bs<3i BL܉m69lR^ KZY2aHf*p3UoCFc5D k`'RWI+%}Xϊ8^T\i'$ĺti֖kRAvrH3G<8v"10y* lL2*L,a%jB[18 PB$@a7JVa)NXM)KGWʵkquI .)+ vϱdq w ҩi!1uMolĥؐAC+9J1,{L'cudĕ2ލs*i,6s Ⓣ9&"e䁟8GeO,*7a#[]BLFNܙHI S%+=\\XƑ ̶WTR#s|Y M[J WJed)h7SfC$1bL+SKF<~R#:5a/\lD2lϓbG -!%[BEø``%Y#91!Ft-۸\V.3 >3jH(cY%WxM\w'Ó.~,lĥSNy[ Jڢbo +@mJUR[#rNt1gDo̹pQJ |܂*9 E%Ә3\R63͉P/hb " 9>`}IDrf w{ 9"H2;AMh>}8H +>yDˈ#.7/9+Oj@[O'.>`bH65\WXG$<eH0]R_J +YKTl@6ς، +9[2RpB Q ?FP) TN9%MXf^3'>#DEa oGTci6(& Wa˙ +81 8$nT]ҪD 0a7&ilX'I5'5RM[^]lJp%Sl\ XMJNg)ɒt +M&d_%=8)Gb6`%][Najvb)?5%iVF$6Vs  zD#TW*Ј#d]P'[Nɶ]^j.'Th*i6.2H%%F.X->JUM&[#Q +w CRAHAUSq5VK8ǫFj$#yϳvZ#G8N\ -PJ9R =H̉ ]Пe/GxJ.1oh"'NS~RJ-ZK<&˯Sݕ(J&6vjk*el@AE*X% Xi>ظ0eYnT^QYA(+ vt||p:Oϰ@!r0R{og,p,GH㽰kk5NG(+HdX%)P/$GGqAb0fQPTɱ–#8r3(PI9 /tFO9qZz$eFByH*vOˋpWnͲieD jy/59W]sd!UrXDZsd4٩ιP^0(6:(;m/2k#Y>q2:A HZ RJ*00v#]=&n&_QO'bBx(9W<;FʓYQlŕ<8WґyYbqkp*.  26f1Oxxyz/|%0OV( +٤0oPab;{#Qƽ/4|{nht40}E,:!Ic9!%Ŀq;Di o"o=%rMJ^AjG@;!,."kS2{Kh@\*=: O)a$b&lB]+h + ?͖,:1GC2ߊޝ r'dTE*g"dN-jm"qdΤz(;8DO*w;7.@~كJ8ľ}+)m(D*`.KsbJ9Ͱ1*{~;CvkA݆P짙]4\ٸ`ebй_cS_wo.J^'Ccj1Cri Z gfMx=lg%ǻ8O'x2!鯄7Q;=(< s]fw !4pf Y];]uH#[e .omHb%g_Reyr˴ `A U\8½u[PB.<9ʀu*T0uaҝY* Cj\{w' C-*%++ D +Ud=QQoV@Pr`3HRg7;W.#Q\bW>zB|Rc9w睄Uoʰ0,3̿Y}.T8%k%&eV7; MܖS\bZd˲W4%y=d4k@ۅN;C$Lѹ_f.yfpMȊuQW;/\ݡ<_iW$7St)#g^::.k9t]!]0Ÿv`븽X9:x"#oe +=3tH0R,"pz"){|AF˷V/YRwW69@t{ss_xy>8n}'&,~2QA# n$Meqh8+", $tPp^2Hsx0q4i(LS8{}J +K: +-A6""U=9$N0ErpZ_!嫠|G0!F'z4Gg"O#oa"gC# ~}4ɏJGzclMXӕGB &0ᳯLkR5l$ +%Յ d&HɀtD:ېHmڒF.* N/x4Y|uH}/@&=W.uEKkGq5.}GЄ#urTGoWer!Р a'4C}/f?5ٛĔ#gɏsϟ2ώ˓JE8$W8&OGS_X¤23ymJDcQ >N&,8Sp)2VYR\.7*iQFdMtč{Sa4Nx{CB} è}q}M٧S?e\dF[߽><::b}4.O9@+}~n~#=H~CԢҧڍFl~5LM9 +B 90=Lb̌T-_|E]^Vh!\23B.9[!do +-=8ܮrMuf]RyQ~]ZD:#{m>MDtOT QIp֩h * ]>J33_]{sr@K.6SjUs_cyNw-=sIux&'b'ȽKJ)1Ƈہ6 + 2&OiOeD}{Ky7O +?ܪz"h>uM- +]E4G!bpσ{F +G9^gˊ +^XlhmQaRqEmiY #KIwJM UR)4m%^vN Ǒ0uߚ~?y~-m:{Ȇ(.]1OϹ +3 VYq^s?Δ3?7(CܘPߺ-bCBУ9q5:Qvo]; -!ξk̃F;0cP9*<^}CcDYNlTw5j6m˚ 7cR8$]N`㔠[ЄqHM +Z Ǒ砀F/#!,b!.H_. +" %HH㺚q.jaဃAqQp\EDZTB^"zı'TX,j4*NwCR݌g-1rFWZ$B2.a- YAL.j9U#=7aHL+v`!26%Ӓ\8,Z&p'CTLNc1 J8nXJ)ڕMáxBMNFq;(8]j_?(9 +yKԇZ=1׏v^6MOOZopsrWlnOtùfeK[ǭ;G>l1Ҹ;G+HHM^3MQ՜pPj!.; )j1hS; H\xBƹ(@H*@sFs0|R-4]ܔ WQ[9s? + :i>M gϹr=JU4 =Ha 5Ą\ ¢uCt6 5($$v-b]sY mď"\"guvQJ:>l=w#g44l8bqAI#FVʙvQl] J@0Q "aTȜT5&ȒJ N(Rd%jbCTvJ-( N+EzW{L+HHKrWb92aU RD9z4打 IjgL|Zȱ +'Kʇ|Vdp%,W'kTU)u.Xkx6faPCƕ"oRa>{H"{{qWU-gaoqmt$Q>DR$m -?0Kv38Rs؄RB"ƮPe)(kjBvEt4Ա%G&WU\-RBU\kelRpBs 1)؉:-/]4RH#Q/X(ȕfFnMEϪѝ$|D|q(O0dnb-#Lj  'Πq'YP*C1i,*CPǠ#Ɇ(Y,NtodPtt. 4aP*V;*isECpNNs Rϙ&@p'"EK*F@VjU䓙ʱ]ls +{+tpġ4NØwwYKTʏJcಳR}Q&ϳkjCql-;ebʝR +eR6F g\e2B5E{ .U:OnJDpDHƳRj,2Ps@oQڴAJ ÿ"m5?C_:QY*"REUאaB +77gJDaԩ,-HV"ɩ/&FuW"G9R'J5uG7Y,;$8#ˬ;{Fq8ז)qOEKU@\/ ޫp%1&2ЌtXPYVkd x+ii19A}y]썅H\0R*)&4+RwĨyf%8T,l4RՏP p'L>—NӉRzR>ط׿D# )\3CֳaYlB>I + rQeTR\BIY扤O1r߱\4NZ;tRa_ $/a33} r)\WLDq{d+Q, +!Ƚ8ph;aB&DԘg7TC,R(a3Q)hQAd1h̒$2.(>y`e)!Ht@<ܗS[|$EcZ0D?|E5)EPKp&0WeP J=H ];.[ϰ5z|B ׀Z0q.̈́զ a P)Ys]VbÑ^]l[iz|V10իCᬲJO"A~KXaʠjӏ*MPΙkm$ĄJIJBqcu@g}> uVLZh72 HB)fH+{"SVa#ID4N~=L &ypO .{[3nʦ>q&ՁCΔY;HwL`-VL*.NĘAI9yjjD91HlWejas5P"Γt3B\M/ʌB2\ L6Þwq"adH'X$Bn`PڧkpK @1ؔK] 0b߭{l;]WS!Dvn)}[^6E6DJYa3nM$`N0(vwVaaaxYԚw^CжQ!9С󌺀%4qGR)+N ̈k^<eU^8y|*ngf,w^W+w4K&D>wC/s7Ovч(lHe/zmŰGp>uE⁙v 'qmg + +]ey+%VKH4+K\3amƉ>84vn%+ ̭wވkϰszw}KZ`u%.CV>\Fe/ +m 8[ +gT+wIz60a'5ƬPL>}q/?~oyT|mjg)qhwuMѹowwn|5lNfZ")7SN?'_ssсd!Br(H)2nI>8cDtI-ד"ř5 U~oxI(\kT')Q_D|(B D1Lio$Hh&Ѹ0"s;9R'q0/~ƔYGfE!NA;b}"C&BZi6֛ܭ\-1fkyG R]fs~G+n&#Av2ܜm pD]m)^mF˛>EnG'TdT]F+bs+̘t)=/`-*@Nysu2]8("șqIMyGATÜX/MPhFΒ*&aБd#)|śω}/_R r +ZS9k._A43u4LȢ%:]G>FXզ33=ill3-5OP{'tM=P@&d 6䳀 ( ֎8ai0HoqRN3grp7S{G_!]#1cU77b^90w4B8ƥșb aWu,5qd³X}ȳ5Qs2 `尰(rtN /7 )/3wM5#npO{P4% tK722O^Ǧ:4;8wgdrfyS)Gi)\I΂TXTn2UDi!E^`'$ [=} -vSB"nyd”Ay#fHBxoL21Z9#).l+ db*@( c`L9A9LpBdce%HM9疙=-VvXIeHtUX!*Fҡm,G&J%7E?KtHn]n9l{QeXiNWfjA'=E8 ?j,fhA~pĿpӜ˺zWK:vs炋sNp1>h]դYp:ݑnWSNŷg +C>=,qs޷l z3(PI.U…r*%3Ur|Q(#Z4 + Y9ߊ2~v3טv$\vn$~QRN/zd̹{NN$ceS 5Y=)fzU_+ =G͢Ux9\Qy0zm09V:*RbX|Ak[йSMO + c@}ߋ#8AZxA(Ge KI+]3Ye|Ȫ2n +@M2RMB 捏?t>tNN7d=Y!\id}`((:F:D2gzg oSz޹]JO0{d:?F!r(Hu3W~RLi <0SAqJjwzEஷnd)#Oʃr;'L@l^c. T8lWHNJaGg Mnda+.PƩ9[yH>l~'n9ք7=WG +D~C>YX?XunIݭ2Cu\U`l#`8$+ʉl\تm2`TT^>uVn "WȉNˉWV RI@]fW +(PEIMY-|tιdӉ[bР&ƈք;2 KzU,CZU!*WJrWrL`E +e~W +0)Ė0s7H:ҘFc?$uYU;m.2kŅ.nٻ̯r!4_\ئ!Gy~;sq!Ao(:H@prPQ(ǀrHwʬd݁y&%+悀ٔ!i ;#OƜt`_@ yA^q5R4XMJI@LR\߃㚿9\+$lj3,E +e1^>%C2^&lC/%ׂL؟VXU 2w0+8u¸[$5¨n +ZXyK ]M0(plnѥGÝv\R&?:qz1A:WvaVp:(AZrOnE,i +_c`:vW^ s'z'>}Ho )ct*,k߭}V]JÀrQFDa 8 H ; QT ea-dpаaM/0eذ 00@,i˄@X0E a,kaȔhڑJb8 " AhIP40 a0MBK: "!&s:oa +w^a \40`tuA[a HAA%o@( @x6Y"UQ) +[Ȧ¢t 2tC^I ZD"&s |4UJهQRP!if#&Ѫ.=eELtE1T]~42i;>0\qh0,VppK)ϑjz*+ +r"7QPt>0y$!UL}>ʊS0/ ^ifwmpQ YK=;=0Y'*&$NľcQUPZ{`XXX@\x,]A\!|yKhݷ-Ɲ~&9B<{`'wX-%8΃*~U b6dpJ& w!.'{`,}S[a?JGY0sнJܫ HſWIEM%￰T{~|2(tR24H +&0I]`yySУ\/nx \7+Ub 2~R.ݬ 䛅~R53&d- P<v_T,–HQO8{*5* ++ 'V +fWȪ OZ~TX +N\ !4IBTH$!QFCT9D:' s48&'14~Z"K 8O Ѵ8Q XG*IT3zKS:¤"YM +6wi$D5k0azHQ8β! +vzIT9 +%67 Ee*kDc @]lIbYfkPtb"=S>͓džq*.P2kՔ_VL )jo;(|AO|ɕn-Wh|4~+mEN`BD /4u@~`\TUdbYbH" tAϏX/GrQ jZtc5Jd_^D +}P5PEYb L_RٳLrC.,? # +tKUC$e|D*9YH$StMaBNSn`ua.,\2Ӧ]"%ijl{ /ơ޸dXlyC +1#*{uyNE!$s#sPB3ix/2RBG F4ĥ??L]lT +>Y | JrEVy0-D %PcX +a4t$SH>(_$// n0!$r0?=%oFCU?^T9Ldq\r {W_nF +yR`Fݲмuׇ&2= #[UȢ$x ξ2d7R']KR{560TρV0kF61#w2ER?ЃcW ǘ)%Ug_JsP$*'7b]T1~߆zE?P|5%?cMoLч9l>PIJNɱ>`u4%<2PBX&k.RY(kc8|=P3XU7y  @`MT}xDJe= aT:lMzK 06ٵs{TÚCx'!*:hpDDEA里$ހ%= 6 PZb v%$>ØP p(PKHCa@7 i8Ƈb"(cDACm8ڇ퇘??)IY4:Ot0H<.e:|:bPdƖvX2ǥ^4ik{sE61(*VaYlt^ ukRך/[ZufVNo^<{ٷFU/4K&j.nuzҌ:VV +7ƒs뫉TU *YH$/aFN w+_LPp|م_NbJ +w}z7#Xx< +{5LU|2=V9T(s |OBnFGM +NĎQ5c+v +(5tn;`da|n ]- =.3rKͤC``'SRO+8fRH5j +)w@'C:kxYlX#ȁb_9H eU`+˪)ah#ri}:Hŷxis(jo&kxw4`[tM珌龁TF$7^ٲm&slڔ6aw1!XtQ簑C,r]0C\^{f$e6flJ^g䙪5Y[(ci<,By<~岈g#ctcfc847a:<l$wWCL-W6l[e+   ^Al4Vd"۬TQ\X}D432@ccE^0/vj*XKY}ZQ{O?n309 r@S`,)F{_/=hf`X@4]`vi EH EM;Gmv+FáeXSh3DŽV8&]$D8SapĄRbXTζQ5 jq6sʜH jUKg0L,dpf3,FxX@3y.`d&7 @xe%g::xmZTeD("KS|6Sd@Fj|Rt 6@b1:T?@VE`*Zy`@O g26E۠\ Gd(eCnBu7:4 &SSE_ ^,hc"`MťMGQp[]VwY}[T`ƂmA0eݘ lp66#n(7+*u4*b2K%'I\)HB\JhLKj|M9ٱm(ꠘHlV|v,M'{9#+bei樇`3JNy8Gݡ~zpeDa: V4#BK@TD82:`@"09:09+|(4P]ryy̟?@r`h\QƸTYi CASPfz .;\MFR􌂑B%[dP~i6#:2$n\GÂk"$5AЩsJΔ>*b80/sJ6l&("St[ +3\4YTK&# b1F%!wqRi&]6+PQFL6s @u;K]7k,C4Eb:a$i3 w ,DoiΎ0Ry?Ve4j$P%IGh06#7蝽eoAt+cF!F##I亦X U74Ƚ}KT|h)Sܡ<3!TX l ( LLBr%ש$I_^:h,0&Ry!"$ +xU45P/KLQ8I"uT 㸠 bKeP  ( >)\ +a[gL$gy< +!c1:LMtG(|o%&4{8*3PP#p]U F4]zD1ǿKoƘI ^ /9-s$@a$~- %r=gG()R %<VIP@u1h`5 0'e?-1x)FC>8?ȟUKx-Lч r;fۓ.]K?0.iEU#4T)U ;FD():ż aA<0 و 8 9bqʳiDrJ|ͪP9M*_ΓUL %e3gtاW*(Iy=*κic(/=>Pl$>E*E utŀ'֧ zx h"Eg-,J c5\(<%i>Lq15~WT;PwpFLKRxx"r^ᙎ+ŐukDH"4\lvGz 8 vB IxNWOB3y8QS`'촗vX8o u1qV@ Q] a,;M~ީ +d+I票v8;4 +sU35$qi +ءVn)<]6 +UeTeF㓣y$t8}jѩj0|)p[f tJ4,=F!b cƦs Q, +eLAoc b[z`{ҩ8:t=*.i2,Bƪ袃pO/əH ,vȗHJ4[?mkt.b 8*G@<^mtųt.x|hᩐu E'X3uAjU210_azJqbIDCGa)H #7f!^ b,&ϋdl):ra |4@iaT.Y%4 +12:~пϰkL ZRk:Jw*BntY$ D}U=7JEt+[%TcB >*8n_tC<`t6 +Fxc ZEK|ءcu-:D> jP[ر=F:͊\tDҩk yjUl&zaots@ nT@d#M*=ίmKXcB㷘F>Dl(s4I& Ka\U:b!p */*Z +{d¼Me=tbrJEfv' ĎrJ4H^$*ΧX4 w&sO% %AmHZсr,|JpsZUZv߬ƺkt-?3RS C1]+CրGM(RҢ.JX*V(_pįTߨpV[T6/YkμRci.f8H?Ӫl| I+UbVc]g@eYclQZ8c j3cV2l{`lSB-h6K b_`IKTj)FOvXC?):na?OGɱ*P;F{:&DCNkP] 3wf}pMSbNt7iK: Qlk")[ q1cu4PbxzBS Ӈ : k"Jÿ.'dP8J,^EZ(IHPbQ,\ ޷םXk~m1f d!2YK?įK9ku!XzcX%yE.ko`gR;zȖ4Vگ>te"t\r޼BGzuu`wUZVGV1Ƣk⹕f9`8(A 0T]U13mZ4" "߳PY"J>6C#%ǎ]g?0 RX +c+XR:+1ZiL`ta{zs4$Yt#qdNb +h@Zllr٭; T͡ۮs#^zQoV݋>[,֍{,X:WT^fKqOo^t/^Z%!~ENdˀI{X<06ӔVoGg9p_#5;*sBEw C']0TͫqT_P~-ǰm,*ޑq].BZY&|vSTj[@ե~\P c͡j +¶]z֋2D I)}/d؂:_0jO=zT~`[Ͻ"w{A?&%-/0ixttMIPp\'ݟbUA6bw>]iuҥpKPfXPM,y +wME< V덴>C}}Cۛcl.|mZ^79 F8_N;{-U[6O? +@e93VdFr05|NLqf\793fNۥZ L_UK^NfRzgzk;袠k-'[ fkk쮾/=:^=ue`jQ t8MjOB8;f3eRoJ[i9i*f@Ѵl3ik)Ć*S'U9EWcNבa8 Gi +{&b#P[hN)L5K2qs+H^;bId4444EHOIWmGg*U㘡`l%l 0 3ɮY6_-@ց:*b*" +2uCv1k.R0 V1 _YIT Ӵ>m SHfNnh[5"vyq:]4A[ҷO?ր7T,<^aF&,M!&&\D̸z5%쭚)S>$LriVpd"<4M JS b qhJOft6HÜrĴLGME&0+bA\QMV5L9 6 دݧ2#]ds5U6GW1445d45U r@t +*]wQNW b(J"geYm 31h+UT`rľ=0f` uT22Ťt´X80:ᐃI#RZl@\æaih@:` \|*Ek3I\ +6QVzNTFiї^\q E6.@d\&ep;ps:&LRt emo2baCr,|u#K’z#n0k`3;*J F%jTUz0a%)DFS{yBCa@U1H6"u$lZ53ql(kݍHTBT$K,>A@IS7$w$H(r̆ɃErZW#x t@ pQqa]&$$!J0 AD:}Lu ad%Zr`8t /`GǂFN : ?#sk@!8A CQ( CvC#S71sy/$ "3B}DTp 9:] M`f0` PU +WILC~1;nb2o +3{)*CݟWBAx0e9ۀM#)]TĒa7*^ J͗:K`c[ZQkz^5vԁJXx?Jn.ksSnQ+[Mu^4MF +|ox^+aCC`UK֨7TH逶t'/ժՎduD4+3/NwE +-WTXQX5>nۿ:V`ʛW dDrYX Ǚ;E|>!$Աk=3}O:V˫Vr%<;@$Yt Tc@_A.M[&slV#SypJ5ZwtС}fY~4ۢ$؆ZCg&jiiM >ZR0+F-Ұ=:5-?68YߩxYt8)L_m)C~!+u^h `?m~{|VQs%?ʡʵƼ'5{^^|ΒkXpaZ]*= YPfoZu|0G*?FZd#,o?fJ?z6v֨NW)sGOJR1U%92g\8= +es辩.U9!m*z' KZ7RԠz!5nZڟqf'ZRx=(Q՘XUmK=/V;Hؖi渪Q\̩Q |/ ,9d 7z4/y躗5W ;HRvTW9t{%׏+^19WGWy49a5Ĩ~ ?`\ioֺ`">Ӭzkn;Y Jg,UvMCWh?= I|vg^լJ,)y-c}zЄY \l5{S$4GimwZ, 00И_mQ07I:jJ ,wL14#R.W7v A.}~h0zz6i<(O/VoV$n29%!zg&7nTlrc_T-b^㠄0 3dY>hcU7`ƇIfhí) +75;fA3>Cip&W}> +,=.yƏ2|VU#çA+y+ZaGd5e EHFyŧѐ| E{NSFX?F;`]ֹ5_Cy\T"K~y@"q>8ibR A[\t=Ƅcc~ēj+6@-e۶3lRj5`BCKZ%h䕰S0 AQϸݸeGi2ف9'z\F]u-8Y>j:VkNop q3ϦVz]g'{vC} x 0“ӷ9+#gsQ:rDKH}WcnV +"D+KUJ#狏Cس::ȷ~m{{5YZ6"\n am`d(ZKKw U8rKHcQ.̊yxTA=ׄ}tt*O0EO,i8Zyzi,cb޾L*zosjfvԛ=~9+I嫟@ɡ7Fҕ߷)9}aJ6Q6q;A~>9,m?[ͪ4byl^ c +Xbl;㪲5՚o`k2ns<Ne,{bUƺ¬kƺ/5P1X,N. _oKۣÝ}kcm0ub[pfݽ`Zh 7mZcvQb52Jz^m 7 m_y4A!4nhM@>̮ _7 ݙrT!i(m"m|v2/ƪwϭk +eD Ę 2R׼Ca s 51P#$,VbIToN?b3Ԋٚ0k3g{q4sz6R^gRVu-Z)ݝ. 7{WbA;paL)J75Lo<7W4\ُwD^edsrJ>}jzbb_RFk9.[Sbޘ~^M$nyhgӶl_esу7Wߊtc![s{!p<+=<{~ϦәTTO$ܯɅJb$sj&,d6sŜן_ܝz]TJoPxe#RԦkl=1,3g38͕W}"a\ofʒݸ[RYt*;۲Xv/lg_Ju[*kԢ fnguꪰ]ؗ[kjεV/ZyꞺ]o&`Anɭue4Nٷ9+Q󲺯SL1𥃣XBU&JyrǠ UiǪ O3FԽV Z~esRz@;O;ʚ|'pL@Mb%Ϡ23?Alk%s^{/JY|q\ϜVzA\a3~)\?m}1 [ЙSOwņݴg*--O\ž'Gu2k\7; cjv1k 6o~q!r /\Xj"Ou5gK~֭rks79AI b;q,;>epꟺ^19Ӟ˽Z_ +eeu>u:wOVqW%l[M=Rv>P콱9zsϻ\qCsleUз_>Za"[o :YE+WFUbo=Yv݅0n9W,䖩cmnjg;XՊ<J>C:XX+}>ïc9{/֒E축9?hl^z"|p C8c-_ÞB}F @R/1ٻ9kN$$.~_isYw I<ѭVaP<¾^X_t5sj'U\ZSՂ9GZ^曬f"[UҸW}FmؼҼPf=avo\teML} %p/ §9ڈb*c"8O_ +VQvAVQho< NzQh*LeXVE`(_%(cvCj;ZJ6#U~P\=@ePڨ1[ZZ|K &ʫ߮ 8_ȡ9Z 3[B+`ĪWeb|_TYe$ ҚPnHkn&Y&kFnK˽] />8(]eH!HB;H?/udXoo|ІK!4Q4=gO \[)^} 垛ifN_@kGFrYTշVb3iII$Z|o(eiI$כHa i`eYPnGZSʗbF%; 2&NkW g#nȣdi"si_M7F\`|vn3G10\j(jaJʆR8wӰ2Nfd>VpoʂؾKCz0r@Bؙm_{{RPcMގ7FB  +0,Q11Wj-<7/Ϋ'>pr@?jY> +0wdYX?`=`O^nrKeWa8l7@t10{pMA)t3)MdQ1< :Xo^T](>=h[Aۓ]Ha8V>/\ks@Tdeaum]Ňbnỿ8tؕ&q M"srxvYUf_>VF/o/׻4`z/vs@iyȾik,WuT=Dh ` [n;}qYzۛ+{7`>}eζ_a_:Eܥ=XK5Q~>&'Tatq-^i"H/ŹJ1o~o{/u/Qov njjs/έb3]|{_^^'gOn+9՚b^6AC#{׿OyYX!*YS{my|]bny"A{uڦ%k*I{ؿ/+y}O5oLa;? / 6 J>|H[-Tsu{&_oPItx9D2tS_MnvRn?s|t\{paǯa_$%yPP.+KAlK|}?^3NV/yl1cbE~R;ZЅ/_qʇl<}֗n6Wڮ:4^jIk~d%\|Il1Yo|I֝)GkG'u0 `OUohAܘjkbdmX[冯Z\ثm~rz5?LAx('ƾ}Wq%obmZٛ<_ {΁:T";{ZtsӉGByK;y93gǩ3X]kB>Axn +|r"|fg!d^* w#d{܃s |,xn>C6[-S8k&7bYuŹ^fFJVՆ(Y̒^˘pՔ(?` w5Z3$C#GyˇSմT>'˙IWIKZ1m3S'Ox`s4ۙ baϛb|~Q۸PdH9f\8LO8VɝF};*Ί{Գ_2T.mosCGJ3[,J}Ʀ2F2{QHvH( Q.*{Ѽl9TB{aE|~KWZtuغw_R~vsT:D=<ȧ^W%][E #fW|(OZqLӿȨe%tPnA8\'3)[+>KQj/y{a σ5uPRƘmR(t;d~o=>LF:" nZ.|5u.>SY<|g0# c͛W[癫9Sp/q KiƧh/&t{]}/f7~+w=Wr|mby'PYeS)ғ "E;b?m/ K1sٷWP"=;WNO&\q Xu9"qK2E洵dϽ&38;_Xςoi9K{W)PcxO># oO>޳4%N=ħU⸺zXLIONgE^V bb^W+|yi[ :>w|n?d9B?m箾R|\\Њp?O,z;)L뽻;):`˻˃`!3߃V"0݅)Sޛ.TʋUEpm n#k!Ogs#XURL+ɱ^dfes"k7w˽Y}sIt +W[TBqfk\GJgKڭX穛/Z!.6is@NY5W,WtI݌U _sP[oU-*ǎf7wo%~#o䎤`;Vv;/UnjׂrWu$M>x6zbVҕ t +|a +XQN ֯۵_~Wk=nj:աgo`̎z6&Vԥ:ukJ/` B~Zkw_.3&'Rxk +4H+a3i~͞ˍw\i;i)[ĘJ-)Șj*bpɵZQwH:Hk +Ow;dY>-/MڀՈ˟ꌇH1tH-8)Fe-zҘ:=aHqɘ;vl'9}KI +avFGj#񲛮z<dj^k:QZ i?#JCHcW^9kQӻ\ـ}7qP"4Wmb:N4Ry%@w but<1~i&ðp/{C:J) }G5 RVubRc6X$M?=?1CN"8HFXjGR;c?dxZ{\}ẽ-J{GSO0%v|M T8bޏFBm[/Ӊdj L6SF4>O z8j] wIQZFvUP^Mx% kOt aȤ_|BDN0&]+o?Jwq6{x2|8c%1i.(}bse(>yCh(޺jA@M!LI|NqB=>oѶR,%:kٳ烩}}0\)ctsh֊w;G7WrS>Ǔ /ĵɎ +;T: +OIP?^Jkqaf~/~XB\,1gRǙnXk}<|K{}@Fѳ _L_~oKgӝ/ic}AD]<͛ +_;I#Bk(ޅe=@[Mԝ\9z_vNڄ-ٓ G;L[ٛ/L4e|Zau=oZVB#3WZ~u ŝ#ګ~ҧ_z݋/:#.V/Dnܭd.|y.fqiyEd6+;BYYgna'.dS-֝ś!u=[7KYcdFoeׅlA{ʨ>-;==8Xn) Oͩdx<evrn9jn~2>wx_v i_=~*&[u/lv^)O/ǧimO@3kG&첲OnosV|~o%_8/.㩻x/J$vm/OzŠ3qkq!nyݢ_?W*ء̕__=o\7B<{==,>;;ɣ1yZ?iN^.'o.S|˫z&5}peN.vצ[wKӥ烽鷧nJ'+Dbp?ПKfe3뉬|z=yM%ffwx'_kVq\iī%cfz2ig {refX٬e-ro9s>6d_ON[mm~[OfZ0[vz]{_Мdy!M 㪉DBUԵWu-[Sj6/{-ik zPr7|zKsfYS'=g>]vvWw7/1yuL$^nX[gݛIz~gx7]Owͅ^ٓV.0/JE1mk~>a9ӶU.YgV[͌=gX;W-}o׵鿵zvm<\z7뭙c1w rmMjWkGVCS={{^\>}Y5*sƺQ7Nky3{o.V^n7 Z2nZ]uyi ܮm{g/gysxϿm\>6Vo+'nU3ŭ뭗Nۻo/_t;1A^9w^SQv~\tg^9>yvӻEewMk\3KWNsq~#H{{r?r;=3Iea/oaǨ~lUs'G^8=}U<6Wr{σ'Ix,N\4~2kNN/i_qm\sg;ŻY~}p~}) /핋F}).˧U~1}U˼^\]=TTzqw}}(^ͫ^8-4n7s~xR+w/rx?pu9X??xX<;%GmoUY罣gp9/~*W׃ׯ6XoUysݜxzR8gե͙ٯFVzzy!~ia~ש<>{ºj3N Vi5P>u +rvg̪ʋ')Cÿkik;״|,ԊЩHfک7=w3:MeG+ɤ[ڵ}yti:s=))݉|niqi0l߅%r~)4n~e~Th~nv:mNa窜wUwO{s?LlAy)u +vZsm\7}^T)cL7ue}Eu*?uI(-}ݒNCX7vc:^HG;Λ+RN/x(ݺ;׎0x [y tSdLЋmvrn\hkřN_envҏN>[L؋Պps;+N@s;rN*D#s溔Nzw`=i8m,=B L:vftj}#m/.||S+םCtδ#WZV(H׃-x8&vZ +L:it +Z˕ҩ銸]b:>:ărnӝJTy40T^ +>כ%B?iuFB[DsNc+ ^$KNA/?'Sm&AOUh`ᝢd<;>NyShF*Q>xgۭT}Aߩty_cn)`߅tz~)e5ΕX!i6}X^Cv'S)4oO%\*,WkBZ4-- ")o,]6-27H| g +5]?M|vq U׿S 3#}:!6_28 Gt f2ޟOضI+tL a/G^y3gN\솋@ɋg~7(ߐ!͈' oMAOhŔ`} 0 揧i=X9DVVwP0]&ѐР Օ{Qd X73#BV41bX^o=P Ę89IĘ<ll|q}h$:ϞgІɱJ: '>WVft~,qcF÷Ǣ#toO +sD9xh]3e³-a(m9@(Nb|A6H:miSzfd/khσh0ܰ`m3Թ0\Cu<Rpl!6 77+k]B:%V#TboMGgC +gC3B|rVt<ё$ TBd%bq>1Vĭ>DHs#مlhRa-6$B/XmmqC]4: 6`\q,XɘtsbKC,6&'3N-WWOBf$񇴂3d +/CIRǎxDFlc1V^!<ګ{|(*z|5#g1_rmMJ FeON¾Ue'b=݊ #sta.͆ a.Kmx4)Tzm/ByX l3 mv2,bQN-JS $`pަ +{x}}08^"RƜ!2_ 0YMMV-=DzyO&܋.%7i[}LZ<#AbJr>l[hlVd"$Ddg%,D\J[XBD G +fHAabb\-p!:߳U.f(Y ۍ85tt #EWY;EWБ EWGKe&SC]A.Dj+ՂEWƨ$ڟFݯIHk'v]xy ɯb ]O4OHAu?dXN7O!msptg)dO+>ZIVw׌DU%S"WC /Ͽ31H~h.lk dd4ʩM}^J'ݛKńaj Jb VJX1NbCU?6rĄo8D!!)^~26} +0B21EV 1H&~_뫞Y?pՠJd+a[<ǣ# Tū= X>/$#9{oĊۑ>qvG1G1q~0 rp}>=v=ȰAcCqfᅣiP̎'r,.3Ze\*3ԠȸCEzA {xJ y|#2[CEd5_->(bz d9 bvĩy~,C;OikĈ SehFdHu?"v]bԡsRd򜡊sp. u$MX[nf TU=aF^8ȍ_G" )t (u!Ht0yd਺@,׺6w=%!bb nD0m=G=?/^Yz&Tg%qFeb%dPM^U:z8&Q ]痖a[瞪Tcz =ؔ+mZ/6FN$c[b٤r"O<7z|'ߣrzA G4'V&1 DW`3F`; b"%u>&dN>'Ȇτ,dl8LNCX~4d2)6R#Ѿ:>!0(ޫ0a\θG]V0L{mװ("YΑXՎ13C+R~'R*N"Uf1*Ri%Uz?MPtm.N"tBH=HE)hKP_0h_'(P!h:V`Im'[ +ge#DMnG(s66R8,/E&_ +gJi_ +0Vw"<1'N@5޺@cxÉ0h/)$3B #pDQ?#bT{8.9+`+ӥ|禑.7Җk<=vVVz~X?x9.3`moX}NqO_hU()҂ɯ;[.\+.I!j33'?anv[TݿݣNĭǰNvl5)S6"[VtgV)NvBvC:%~J7augv}%]4x_7W괝 RM5z]:jt'.>C;7_-j37X8Ŧ;^,:ZcLQg '<Ұ~K/6p߂]{Mz_E!rK{&pl$nY^҄nr5 +WO"B].N^_oD.4yڵ .ި/?/kk *>HOJ_cQd4i7j:vw;g1j:^wDx!gɓcV@xtag݌^M7 l ҆K(+U AOKۃ%n!) 竱AG:HĶ.L_xyZ:2|+pg +2O |>ֿm ܊1}kv:3ȳlƉk9w6I6wcoG)i +pCh3#)7KIz%{e&2ݭN$a's"c]xp&(|vA;v[1@❺V&:#J>f(xQbxՉ0'cJ# gr~PٱD!: n7UPX\-PٹfD ƺ2b C:_FLZT&ߨޏn/1G *vF{6E7J _ƹϛΆ +/:*ɣ}HgCqW{_~I(9Qb~SGoJId+ڕ\*D +o+"n9ƽ~5Ox; :ʽ~r\aR1[kIKP6{-~l{Q#N_t+{s$.|wwƼ/:͍ +E{j\ss_|k{Q$w_tu*ঌv0Ui{`o -oO~_ddHSa.׌o 6ZA&^_M wΨE;Ԯ^?~[`B{ICҼ{o9{o}|qUI/7޽~N+*ܡr8%+G/޺/i{B4}_^[v2~ѷc,Y&jkG׏;$;m>~AÐ/Vt{8 KT&4Fe~=6~Z4/|Q^I@3ν~.ro ˷^( nq݌JZ2]ڽ +F$[qKb1̇dss-l bF_k6Rzq~gG?6m-KՓ\:+LNqcaX]a>KVhBl + 5w(K}y(eh1 +G+Ó~+t~fӕp-\gfK+fݟ\Wgz朤fR񸹟,u[d7Wޞ{%)6쭔^W2{;=]]0wdOn,.-@Evr3-.>*[a*4OBk{7NH%[䏋˕rڪIl4*">a vK<.d*m0Qnݘg;g\~Kl"^.UnmUk +/4qpsӻUw}zzSgM@?ms-Y0p͔,ϩ^kŖF3T ku6 +V/hy:oRlt6p4WJgz_JU5x; >spNU|(/n4ߞ衅XJZ.xOBM\[ylmyYʃ}"*j!q%*6 >uB6( g {=) {iI%b׳Kt#RXjI^ܤ[+v~3\?5iuC67aAvҬ y(*M*Al9t/:$!o8=uiESidL۾.l*յf0C~KP_spR{N(79Y 䐂|~#7g);yΒ֒-PYsDя r9+ہC(-1-ʜepf]M_G9Ov6+gx_(rŏ)HfV_@/:Hwfrzv? *Z#4C}cIU2mF}퉖㭅<.e['9Vy~k) v׍J}k[VKi:BWGYpw [Njq{8[|7m"K5hlS&yn[-*+kSw6ET|{byJ9\ |liqXPMͳ:6~kAL`$*sYyvCu(.-%$aޞuvֵًByg1r(ưOЀ򛨕KMdphF|!)Mu|&j"AqHʻ?] C4&~jBhT2(J"i?X/.{/Zp7у(; 1iJy<:YƥKn\Ë^vqk1?&&ӸчCe柗+㬆jOjċ&Nr@k1uSk5,H*Z? s7ڵcMcBu!TƆr(h^"Ml(5L 9 +xcޱVqV/'-r9θCZ# +ucozp[Njuϖ%e-,_WV*B󋔿8\?_?n։#TT1G,]'jJwj׮;8xO}kKvV3ืNӟŠ%~ٱt4OVRW˱WN-/߉{'_(yl.hh.f= s*9s^Sx0BTW56 G2G4~D +1``x@?;=8S/'Ex|(!+drhV6H4009|[ LqP!$vmoNH2ZӍ۞5$g[\Y]^G]LyNO7'd$KI[䵗 +x^v[\Wv7ڸxmc%;f^ *t^nD(j(#O+V)pDNɮ7~O@c.GnÅ~Mn^\1}S\h[+g J(Ә77BgHrVv5!m';r%F9li3Z: U/XVe,mt z4r*l@$5db><| Ǫl@$5ÀHj>2Iʜրaqb-svh =0-)HBhʒ#7Va{byi>G6Ql{6O[fx-ƾ"R"aLj,'U.-dO,0H!mc^x9Ѽy9dm4;Yf9Gv\}|ET-Yٖ-B>R˾)n0OatY.`=v6[͒b9vEPQd +/kaϪs JJrS@&[t'tՊoS+wNW6tC'C{❡x/-fWh,5x{$ɋ4kbcnەFX'͓5Bە:X"~**3X#LȁFVȕ/GoWLkGDuyߺo#o)˞`A.󵋧 e߭w/;-BN=gRWW\{(^P.GP[1#:ЉNe45I5tH +Zp]&cNK1|5؜4;IQRQX~NǏJ'龺ߛv86vί\=Id0.}Mcxi74οCŇiJ[pvMe5;HEf8rGRVU4$?R84z,o8QM7x,&Cbjdf8LČ")L+>9-R= ε/M}}qR7r= .H2eAYz9۳@ vB?b +f9'-ךshz9_jyVx}gBpC*/ݽٟ޺{xdTFkq7 o]TըJɊbB;!U"5"DBkDHǤDBkD^&UIe&X%Z#LJ$F$5*_ȸU"5"IVֈ2D]emfdЉxn5rMߒTs;¥l k3H!n̾ۘŠl7Hj*ɉ8ǼmTB0uI@)wI2Tg1BL+vO'hvf͓1멵ҋ,@֛t(5Ekkkq$dQwz}^J_qJ)IU”O4~*Mվ?{|VzS l}YZr~}-ڿ^`[)qsVT~{)2ҩk;u=U;:1)aj ;*n*:ʆ.*"hO e]MuIMT *`lhDd]WLUtI_" aStCEYTń'AW`lJ}JWe >L09L ,iꊬ*.MDAʲ'2MY(E* kj T;τ @j USfAieEg:L. J4˺(KIG /Ȋ.T3ze5U߹=򠌲(¢h^ᑡXò2< Mq{@ rYD]DCRUXq &BJYVM2x tFjJvSPB ONԿIʜNO~J/ij  Td]:lTn"#Gʤ8!kjnlK +(+͇Iw5`t-RlH)OK|~@T +1 " nI+.pak̃Uhވd= X܇xU`B +>DL&;RT0y @{ l, (2,ˆ +0 H!ÑxH6,x% +v/ 71(ST-OK* +V ]9~JRʆCASRDW4hK@aF`a. +7 %lPHx*3]3 UӉAɚ 4XmiAǔv 00яfr߀TdoX:`eE\ d]F7 ]3\sPFh; p`i=eT0 $E&Mʜ/5îx@2E0\RUM2EpB@S0h2 !l=)SVAx :P+L0hT C7uTMfAI$;ւҁ v@ٸkH1TG Ұgŀu@ ,(H9tÎC֬Du c +9M F ێ^L " 5$Wİq; '"8ުX$/ۣ64ɥO.P@#xʚRZ!cJ0ܱ;ӝpjr 32HgpI$9"%#G̲bD%REpU<]" fYI.O~ Y1 mC AUAXb@A+ Ew1Xf)`.x`Кa/ [T4{01"S<0DI@yP`tYuIR@arR(pfau=Q7O]GI &- db0 JSR'U'>^,Rb()2!=& +!Q5nauVLHM6_|hnATAIJ|k*0t +4.`Ig(ikB Q$`S++E4 j&4LEVU: + ̥A@P'Bva,i P9:XDJU&Ja@e0aT`m) 2kK" HHE@bA*Dp}m&P% YB֨֠n ; +T@9B(΂P==CAP.{@p7779PY*ħ"F7X Ɵ ś \>Se H V;]vXXy@!]"%#lSAGjDIɁ8f+&MI8\AߺZ+Dxh Ӓ +;<+O)4lĈYu +,H2t 3 +PtCVU1TPRh|hҘ"@f @{6 +2L)h`U1 A2ImGw(YR ;k`/u%l6ZJ*:js8ߚ.c$8*Mޡ G*] +tLlAePAD)p @Ձ>p:h`p@Y:A;(\0 e`n+1pLpLK +u0 @ x`ֈˀa:R4'1,@g0+TGذeS2T7d*a겣|AIn-B5Y.20<24 CONTY:3Wq@fa860Z]@C7XoXnA0tZM0܈'g +Ԩh'+Pd 1d2_& 6Ub0'1i"Qn$)X^`?am6Cg2QapX(TD`LYTX} )l 3  kM ]Ή`GW}ƙ@FAUߚcq0 +LҐ@g66ā(=FD鬈B8Ce%)8ۚ.kr1;NZ޳`אR5 Fy7Q Th mX JB+:QF3% c`pnZy \? Ӳ+p>M佫hq c]u$NAh%xBMD )&*n?H6duI(Њt$+lm\Z JL8ATK)`^rZE856 A"^ + ~!P혔7P +lIZ+Wj@@oaHqLeF/%WkB=3ݳ &0L݈l+0*ncJsF"'̴!,m1)-ƣ|/b0S׼c)(-҆o ,@l28 њ@KN#bR&Bx86FGtȘw .gxF=M`ޕra>][0B=!pD暢l JFgLmAJ;`8y![^/BYl Mt: (tSR g?%id!=fxc b@0"▽nnKx$iS T] +)K5tzf%kxNl?͋4"eb+Mute;=H@%-P2{? +[aK 0E+4C0 OSȵ(&1gr8Ǻ QHcGTp"X;ExyP#zn}M;V`P`A}DGPߡ5E)9^"hI ye1jM0~@hŎ +[t {1 X 遺40Hty "]Ie/nHB `ҍdp&L  =nAd0/n*ۙ(omPjT)&~aI$v1ȱaQh$UuH'>dm0:GZztA:c!,rk`'=%AeʀH F#Ph^.CyIyxA#,?Pt&Ʋ=z`T `EF9j+̟[M(qS`Ah04a74Z۲Ȯ'5 EI +CaF(nM#tթ0dde!/YvN![  23رK飅 @ MqĿ,W@?` >D+FUI5r +Q%9_D5R2!I{ =20+Iek^V0Giabw~_LP|SAHԭ6ЙQf DggA΢54XMrHCX%!X bdC7P-pLTOp3L0%ba 0g$;225I2@)$N'9@d1@x"AtL b4ϑ9;hM``Ɓv*ș 0V.(o;m H*pŃbQE&U'(8; "n$ƣCVց0$ +nJ]J dfsfD0-8+%~ZrhG0ؘP J;;n)°tXG86İr`4fRqafET"8DmwB, _Z80E5@% °(d9j,f I50HpA@A FXδ8K 'J.Rbf_]fbI!$/səg!aIq(4+cO{d/oX>{Z3KN΂`d02,e *0 g99@, ,gVeph%Hb9LGM u#pT*> vYPDuD;߁H]`r{#"t xq\e +sd7m0t}U%"i2m:x_`=)&>JPj\v5]qAÈ2 :݀u +Ɍ$8pvBf +-3INf +@Hi8nb+QgNgUKu/4}&Af$X41LR}9KQRy LUVqԺıSu9)TJe2Gz~7SϽnN_O'x&k/ % endstream endobj 76 0 obj <>stream +%AI12_CompressedDataxk9v- ?`b*|3ҷva\*kTPgxs2ZvBC$sͿ~՗o/ݸ/^x/wvׯ;~}s݈F_[ÿ{WorxQyϫWovϫ?}_޿~wݗ_߼z/?/ח~y|AqaKM˱~ֿx?Cˡ|wxo_ݗ.1Nab}9Ռ&^p׻bLƨ]-;wi'vW]A{?%Dt}z͏߽|~0?rwӋ7Y߼_5xL_߿z/w.ׇ_ _-׿|{<ny_*߽+M+^u߽x?exėQ]X}26-rn_cØPof9| Hy1eB^߾yio}WtbGi5w{ j7o}_VqOk=?6)_K 榯7ϛׯ?Ul7wz/C>FO/Q4Cq5>g?-߿|o7~oIĄE[,y +#wW^}۾kǹSL٥o`)Y7_AǷq@n|V7\Rl`ݫ7skՔGTջ?~7viڗ;۩ ߗw? qG___.;m߀g`}}n~7xT=pwwqư?|U7//QtȆ/zĦC}l VUOыv<{\F'>ׯݏ?o߾Q?g]*^ [wV7j_[]o؜\ߩ5x]3|ͭ?=w[~oA_}W˧Ќ߾{`?{WC3DrЯ~|~=Wz$H_~rywxw/}.o߼yW;pK;|; %$x GPx?UN([(e:dt*C?(v?L*%DQ~܏멞zD u T(*ƒWѤᾜ1}J.tS8ig<=MjCyLtJ* :K +xc +Ctq p P 9xy{_!`g<?3^ޕM=9x?v1ౌӘFgԃn¿3_hEd?Q;Vyߊvo<\}3~3dģæ)GʹaK).D`TEs?X>~ +XFiXPju;Oe,]KKX~JRqX$a9k&Q84AOOSBKo7#J!|L4)rٟ 9ӑ!|LtptDqBxxbEA]0{mikS;IzjY4O1`6 YCGG?ypEb,zqW%lVL,'d)ӪMߔf`/U9ms.FˠMPW%oˀeS7)U9-e|>/)TMyZTB}_;k tiӦOSqhjzud;:Ȗt2[*)^(STnviTnjiR=4 :t5hӟ]n긓q-4\g(Ѓ4ìAKm4e͕֟b mMyyayu??/[Ц٦f ;Q,.M ӱ>a#o +^!Zye`d=(ڧO 6\dcV)f[ed;dФۄdD$jj۬ڌlL, ơM^Ѽٜ|v F/1zI?4@d"ޔ澉A"mfMĐ]LT`^WW FjL<25gSͭboUie{vݲbyl~lhRWe*U9zeJ)gq&gʩH5l; w vi¬o7z[Ma3_6 ^/I8>Z#nwhFn.O+eat ^B؄f( kchj~l2s]͇&9OX IYdv,J!* \qxv*x+YiŁuJu KU ^@;I.*)O.ĉVra@?!MKuTbKʡ\z#(IGT6.8b7#h6t*fqҬGk,g4&[O:Fq ;%Iz0e%;0)dS$qS( %G6w3ϧYM_VA9JY6 3#MΌuQ,X وde oۋ{V""DIA]89cɔ,*)W\yޤK," 3YLV\8JTtjfcI2p2vw72Í88) ^2=z-/R)]Y8;)mvMwr(bJۼ2[tf85N{v6A^ؓ&?sC_RYZ ʰQ]%H4*ihΦ\uhYke0K3Gڬ!~F e8~H3,4pRbO%(g~c86n\>}w# -[hݶ\"lQ^L͋ z1LeŐVe|mm6oMk#xߔ`yQn?@ٯ˰s^,kKDh0euXµpk$4f(<_a`XW֩Mxvn @b+!iБv`ͼ&Y/ǏM dr |Y" iMZn@õ t-\>Cqȳu"JY.~[gbY筷~z3n"~)_eUppCF6j-m˫ +Bw7Dڥ.`܃79V;Wގ?-ܤW\ dIxuG l2r_w#Ӭeo&Y1ZT}0Ş21<̮΋Ņ 7+(f#XiLwܬNqt@n*|7GnL1ESMڒd2ܾ~G|n>|]5[?jѭhw女z+37lcB"AZL@k]/8^|ޭwEFPG?PFO9!7ƃ P@;=-|K_Cٸ#,qz չ]JG\r9MdTK1`:u¢kQk=rwW!RrˌP,>,yl)B&0,c$>*<_{ RlPu=%|QŰ jX7]]quy{赗!wfeү3n,T&ڙRơY%ؒY%&-eH$_uT W8{7k6 ~l4[<͂YרM +[#3Pkf{ WE9(燡( e 0O+Co]vYXZf2*} 9Iinr)،(7a9LbGs9972.gN&`d51j3*{ӕ*g~F&Ags'ivCzyVjM~i5ű +\(*k'M]x(+Ќ +prIJw ~Bs1OUL;O?+k:~ jav畓|j?EJ71t4O8kO"`foN֊(nU(ULvCv[]K{6Rx4 ;GAyTld8 ,;oqxs^a7fH3,9/8<5~,š, C3d,ͻLFf0zd4llFHr$l@:5n‚dA +l챟I^_fxߚ`lUkqXqx\o 8J|_?Yvš+$62pt (8: OŰFA԰SKL޲nL1Rpl:5yD:F=\a!3ӖKt^5~c>5qź[n=)ʼW{Y}ּq]go%, 27>u~t.pէ?"Ec^1gDq\0q 5H<0#b u^wk]w2T~ =UVo~.au!>sP]IwhsC7\<8Tcښ]iB00L tkPP 6ųmCgU2F ߔMG~V4/ke_h6/l +-{OKs䦨d(CQ~3׾2Z%!^ek:# ,qP>g9\':=YOh@qr]Ќ5u+o,*Qg1] V:q|pHCt,Q1Q'!U19!!Iǃ/ŗcOx|&a6(j2-<N찱JM[w@ٴv3\OiJJK ls +[ydX* ŹUݦ5<+ D{cn>[_ֺ@i`9\0.q:-v+H:Nb9Jʷ8*O>.t+1G(2:(L>g'y 7egtߖ++#|݋4ʟszA !} E kUJ *~:”vst^.xwI<[ػMP}sm빷șmrvOj>zF po=]k@%ptA.xڑ˧%% +05aS:Lut7a{0Q+pY>˱ e'Fpi?Iuf[ݷ)b:؎#/81|g;9g&bXvs;B'r2obzΝknH'b)E5KB43ʖCWQ+ɋv]?ʣ2Ch_[pv(o>iVo۔>|ɞ~nhX*bm7ƆT+㡹z6 fIѶ1X Pݷ=Cֱ[~ђ툗]g\ [ 侙]Qfg^. {-6^(K]eWQ%ZL^gQOU&^n2obm&߽̏3Cn t;E˟V+_c;R|}[J{j;x)=tnG馦t%D ehe ]%5ܺ%Sa^MI79Ԧrl>i7y?ԩ=ֳ^g>N;vr,JǬv̇٭[h9nhg;ۮ)&~]h*:aGn*А>~|?eQa>p~]r^2~1Cׁ@9 \H~-Wbb7%B v!Zlƹauoa>|36MT#Ås"{lsbmGPVNX|ː?q}Lĝos0Go-?4LtH.xKW}3L&a_paiߤ\V%&ݰEEfRԷيɶM.jRGWq\[)0oz繟cUfFl._g_^H[LuHVAfLD$آKKZBJ'oI m~/(߱I4KμBtZu3$04%9}x=C9<~@6dZ07Atv!c@u{LbST|bUKy]'z*('p%: مb=VUY +pM p&+PZ9f":`$(e26UY)IL%c6whqk'amlc6;z=Tu3F&(lc 7 6 [gjL!avBӴ}QP&ש$~P +XcXXF4;,ncb$|n"?|H9s={9s9s={9?I:|9s9s={9OKn.^t_s,%_Mn՜PO)W +ʰ +KUœ.%]j>w2ؐ/~97 !`̅ۑyȭÜEbGܲH,ݷK%] Tɽ@疚r8Ĝ?y Gn<q{cGkfs;<Ůew={amjׁs/Vq?^e`>g .}Cw 6xxc<.>^6fZ2n7܈Xߞy·-~co pY_VJ jmk:}vqoFpI + EIH!Oʽ)"?R;Nܱqz:fDIguy ӗ[*}F.bo ykpC z(] vlV2cd8-cXټU 7J|//'xC>KT6Lnn% Spy? hn[* kt74,ǒ WuR-fEr pMfN!\iE~2iZNc뼥v|KNq$~d'XsyuJ;QeqJl$'S QYZOŗWeuiC.[oDފ=>j +ݽ]zn^|q?~t>kK9_[oxUu[C')}u\f@VaR.R)Ə)5g::̳R\d:guffhh ~p2nC`n6㦙WGgmO<l?\{&pyئe]:e y]N2\~#}R3[ڊ_J'pv؛ܙ{WMFwiv>@~5˰O.L>kgclũ|vL<ɥҸOkcO mPJ-iP/r`9ȡh5]N0]w-O5]uqeiz95MF ^n߱I=F/cSECK:;C9-%sL`9a~~e4^z**=11ţ=]8%Gn;!KM+g{bc[uJ"@0tUP&9@صcǑ2&l +`nlҩU: +rWrXsdpNgɅq2zU +R?p1~|Hዯ߾{7ZW =k/߽Y͊ov5EwDa<%d-F`'iΥPsT~/ߏյ4'/ g?q];w5[Ch[׷V7r7_}ݟvW۷w߾zׇ+f߿z߽wFK4`iV0Db|NR}d(I%1y`epy_`q +zS|𫦈QX9\ +p=BpYbUܨ+0 +4}^59Hs.UԑvUG9B/؊wu THFI0"e7$,OlSEx7bfX ŪaډcQ9sYD=.!y,/e[\ح 7X P wY)XM33 b]HMo#t!`bI&i?j*!w9:tfڡ;05.f&;t~g@dcYb1ςZn +Lm\ +9pRToךt*i_dk}Q#>}QCiMA &F4Lѻg5[8Z7<OJYLFKk11ނ(}QQx)?AyH +B Zʏ:]y[X{{6aŚn`bLVyQ:l<'wZ׍;܋TUrOnJ)95+6zG(Uxh-5%rBS$]\TO@ek&G +y`EzgY48)Z0 }m)[6 I`Y*Q.5T=e062asКVV<ÍwxhxAo{oStV:dqc,65W2w?|qx0<^aJm`+XdTA}!l\U9Ayˋ7!yx*K )xs sŭDm6#(wfl zȎ{)s`/9XVvMh)Ib {=l X,5C,h*l| hZ߃j^ yOFVL{-]{hE.V֨V'h2QՏ7 V'S)j* {oCvy{۹[A~8ȧ#wZX:ܡh#NN@}R5S`NS e0[`[a/&IQFQ`ID f%7+fF&eO +=(ē?Kp<ፁfޘI#̈́y&,N \W̄O<얲Rh R\ ٌ:"4bģqP[pѠs@6!cLڝV[/[uN9NdkpFl9.݈YOFՉd PX‹I[{2* wH(Nb|AF\("XGB7ܕE %4J2Kݔ1qn4',3y=`_ +LX1H* +yP +B%u#K-Qa<B2+"!Ҵ] +qˑցJ-70huC-pCg2EM,6weA(i7 e:I1H3 MU[@UH˙9=GL#T6*< +0 *+!*(<wSƙx$,T{XP[Y S2G1xjl@vA҉ +t7B'&\^ GTg"mj؏ϣ`I{^ÓYe%X*1 IWiKUj9(&4;9ZiiL G1J=VP/~xJG!ē8(>XGaʮRբ= + bF 5Rjv`4,!"AqB!\UERFԮ*G hJvVPɘV^a'V)N[ПۀKqWum6 +,Z1zPsn{`Xo+Qt 2rT݊$0iCӓ9{mm(iۧ&wtZ +Vɾ] x +u2;8n+)hҩ\2g3r*2B!k1 j +T"=TL̈@δQyųUqVBƴhI{mâoݵM~G郍ѳnGbn[yV UW49F{ eTf[rSb!f%f[=̺ &݋Atrxبv2 ! +4{u`LYOE#I <0(*xd~U*=9O)8bH۞^ukuԑ-'A30!"<'=xtpN>wd +6hX/xB9={U$Yyfʁct&{.MآE,7*oRUuV4]U"nh1= Q;)mɸ +ٵ2oMcG=AqD}cF)}m Ax-}'X0 NQ`\0]t^:biNJl4B* b't^UgZsG 2P0tbwG\!̒s dgyn$;2IsM 2b;v:b"(y-l*1Kxui QMzB@!@AG/(nfZi@ˍD]V8ht;T#k*5=_ A3O{g*Ϭ'@5\ZqcЉS+ڧcPa`fniiT]"Gnu(swxzԲrLNW@^zVB"B!F'i y%\6dp:yx0qmcU +31- +QNq"냺gu/TuG,@Sġ8ZGxfJ!nSN5є/YFIVA8+5r$$^G3 +hV m#m ^TjAM芁=!c@8Đ.\aB0Uk"ekAR&Cgz ݗ5rD u`QuXC[{oTc{o]@I7ž'NJ* *ZE "CSc^',ܵ7 _M5;v@bv+Dtd҇JP+2WGΫa'BW "9CW433.*bDR<4j +wMDj +4z$8gPQ*h8sn56&<'h{hMoeHjtKR\u5Ӭ#-V*ײ|n$*Uf%X1"QIR_`&4Ա%XAuͬBxM*ZŊ,;AxcNB,<Q)|9 H~B39*NYGA'"*ڦP¿icƭBi|ơ>X)ņsI'Nt&+*aNnt񂹸sc@ CEܗ"1:=1n 62l ?U#fo$괅VzzDc# 1'Si/~M̦s+0MA\@G}"h L>d !ѓO3!JLh22jgMw>QI5*%_BaFCTYBZˡE5>f '6dE#ĤFaghECLdD\Ԃ፪ wJ2sgE׆tGTDqL!0y ЇXЇᙚ @D)iSi-H>qYl"I\L-" );'[Ѐ ȸ$jdK?.(XfE=Dk홝ZN}!bQQ肣7By¦5igyPSlڨ@ {S&!QRt7Z|2Nt "fq*^5RWe?JBaj]r#S%{B>}, +2F^r +u+O &B$o24nR I R8{TЪh [rrl1%È^`n H|lJؙ(;K$֊i؊Vt-e Bٝsq, Ԃ2 ^TTVhW!N +/Jw8H51 :Y1ZA7%Rj&HDG.VNG*-E+e4Q,8Jѫ~j3m1,|h5 sb =Hi"ȇ",~@T=L))r&^>4D\6`cuµR].]/$ ^1N+) sFf&-("S^c%5 24 g.SA#-nAvb1lZ&?17j`z爉!S#`۸nU-"i̽꧴ЗIgR-,deKle+37l&%FTAŪZF!Mh7A hܠԡ>涃O3DNOe Pt|Ms6(dhfQigDffl}鮯ŗЀDl| m< FRӁ*)AO8cMF"JW(3bH$v K( phIKBo 6jg6/v#ZoE `A#c&hᯛb"LnK< NU3)4ͩک2Þ#5jH-F:\j$^iPSSZ,Gz:rqC&ZSy]wV#'׵@rɽV"U:뒭)<'yMȔ_70_-´'PHB+B˭E:gÍU :pMuЭM+҃MƘR[++T 7P p)R)c}*ȈEC}Rdx03^kO"9  ȶkXh +QE֝ Q@+s;6 @QRJ:<Ҏ$m0^\5H_(zS1$@$ +eA892(X.~.INxkA~ɘ5 C֧VO.:)\Xd@h*M LV`NfZLw `0Np: Fk鍊š3*T/$4[5w^Toz6^os>πF.Tm^P61E5S<2A$2 !KheT拓G9Y_ wkӼH4*Cө7WM?#B;0iIe@BL QnJ"cL[ Nl ^Q4A +N UlFSdQno|ahmVV + +\݈0ėxЀO4tO)ʻB=-%3w6mMro9d{$,lB bIge9;~$)zk=/bPQ/z NA6z{FO:L_|V wb`Ou/3oBR$W8BwN6ީ;ڝ"q%%LgToe?D0)kn%/ESmJt S$m"oNLair `"3mF7sBfM in%P8F8 %&e 0&Y5IROMH| `_~ݫ7p͏l`!{sW g'R0صchT {ÿc"| LE1w-PĪ-YxU8:gF3_ T5+SF VLY 5lemc:S To['ZL)7 h( A mBh.e(D2+x2x&wh)eox =_JLȸ4j(T@EX©~O\Ke蛘B!{8ٻĀ +ڙȘMN&tIi+A |`]%LDaM _9Ѥ]k%-JSZ)cGMísRi˘ @]zXm&RbX&8`+Щ!P)e OLřaJr(x)7=ru`$uxgCbOK }GE9 +y,@^I +e\'T䯄8ͮe 2'|L\~;LIC4PZMLM飭+.u~O=ldF;ލ Sm-'wdHRAݳ(qvVe +RB!c`IDAqߴS4 +5t[ QhP{m.IF]2b6+mmy۩=!F/tpg`pi%Da)om(&͐w唦qAwHPJ4օ,^V12%ɖ#o H!%m\&TG82|8%X.<@#(új 2 {EEo97#Wy*'9(&AFU> l Y2XyƖB|.$V̔z씐2oYт$q/a,I\K2Q`d5*.ZxIF4dFtxWXe,b(JTfi^tw3և#WX:Α0C?tBC9xr9f!JN)_FiwhKM4R~˒?V"CLM4:|1R s~AaقWf  "x( +-Ȁ3'+z4?I0*羙%8z$eHfrJ5IF38FyR/S+F$۠WaAr²KE@sG[ +/W*_z}#B)M\V|gw2F,Ƹlsi/"*C]y QFŚI'Hh-X -D /|$Ɩ +fK$]sTj AG^W)#rV+$!b-S+/MP^fBt;pD֙ފ% +J pze1JEǡHⴢ̺aGd,97@<sEj02F|LW 颻 aIAO.APi/śkrZXKB1i*,MPŭ,51H_f);e)P٢ d= -Ə,oF-F83$fC(хI3DR1܄Sht(S]f6\V2+T+@U3$fP&;+an(+"$t<Ʌdj+e\mҠlySi>h~,皽: +wD]Er-rQ  (TwIl;o"%Ս:6T9#ÌXr0,OL@;B$܂dN5h lRa&@iK3Oh<)s2H턓 &#BQq%o"NPT3 l~`0LUX +ؕ@UV3}fW(%5>ģAGU5yKh0J&D@6"N -Dk< Rc +&^⍘T`oh`2MR]"YA,+!bh){ +1t#L]igo9d]̣G7m&kltQ BvA30@A8A3 {gZHEQ@wd}es`1@;A!I#V/"~gJy;C=UFIxTPPt&b|3#@^^#b%dJJQYA\UVU26Xd;$z +Co4M2ޝM![b ziW_n%$sRhK F#vfR*H2bb"L qۼR L9!([ d_㈸ )@%9eot7HEUi?儛@WHd^˄), +p/~ +p&VCf5PM RhRxZ0GQ(RLC#hK'QFl)XLEWu0$rdq12\pK&49¶GQS +Pޙ '#$k1@T_r"™D1pe! $ԊcV-lHIbT`iTVf%J@/[]F>Td֩BDo* +l m4ڶ]0[P)V܈|¸؊l%K AG,Z0= [40d6568u)4R Bz0z@@ə!fL SBtZFݳ,EɌe5$0DUiD*q=LaM1Sx'!ĻTQ<%[+X= jC DkJDs&4m( +~%Qҙll G脬, +#)v55 6ze|̌h~!NV) m0"DQ]rA _/3Dn5'j +=)z +tjčQe9ׁVpBF? ڕ'KJ|!ӼҔKLSPt"H&t0eH-H@(^h4T 9Q65DfdٽaXQBAµEԉ^- tˮ3v4D*]R%-YJJ +n|k%q5#Y'UBl˼MC L5/^2*ߟk]Rg) +(S# Ag0ܤ\-ZA#xa[@ 2Q V9sBт"9l5ZOgɻxeJܓX8s4a3Id h cc\ %|81ǁo'Kg*_1DۤʢD5A&/!EhqMĖ3'2מ(1ߊoXLbJ#VlecS{FR +Tg&E-N"8ϡcV +ʿqtRFp̎TSO75)O"BQ^ D'隒_GLU@ˍFۍ |4%,kRA}EJxI=duxOs%,ORy7ُIY%IWǖkfQQ?5YqhYZ2p?h=~qXĬgciіE[:K~AĨ80X5!(WUF>kA:<.e|YqYsK-SԤLD¡F\t->@G%2Iv!}rZ:H8eEK< X[GbXWɻ.3}RT +>:q c-'C6E;ƆGe&JQ9+uQc>%L ڒBhn *E7:)]@,( &GiT 6{~BFbS5bEf% +2\Of +3 +O) [ibg/BDܖZ:|Y#[QH#LsJXA +Iʅ GV!Ljܛ! } +vOIp_*BnE]'kF$au৊`K)2>LK@e@x`>EpILEV Hke %&UHRPwUbFH6, 9d c3&ʐ^9(3hqԉ'aH+~@*4a,KbijJ9j6yK[^JF2x1:aK2Mw#6 +2:H =HN9= +H8v(gl)ai2ϊ[gK=HJK-<V9\I}6ҩX|e+9>y i6)FF^'&6vs + VFpFQJ⥛h Rj$2iN18TQno Uw,hR_8VR U +:%RѨ#>sI;W_s^M3 Ԇ@1!^ٝ]̿C>]|@D'x Ί +1 J! ` d}<{˂v]U]"zf]b#c>ߺM1T-7(?ٷnAFB}hǤ/0R5d SbmM3.η}ee}5ǩ+8E )PXgWxCT@oeGg:ȽlA݀U@Eb3h`(gE?kG56$ +B bͿ3j5@ͣ!qU*`<w'qT:!7^ EaS;t k@dV'o="2ދ0I  4dy-Mi,ktN:xHg=_tWk;#Wz4|U0zxmT8fwr"Jm?O++0RP vE +ӗ %x-H.I@bt1Cl1;_0=y^}xzIH:Tt?9CJ㧝 xW/W:ǵ#@͏(')}Џz\'h/gt] l(F頤^]e39S A"m + P0zvşCUۢ!U Xp榛QT1F]}i fQK =`!_CCYwn.Jzhi8ack>^p"}z-8B/vlB _MԬs_4Pyj Pb=)}F^,UӠ, XoUx>"#qz`Pt蕱&(To G5o_:ҩ)(X= #R2붎.F03W3Д[QG׳&k(d%R^Y/>L7CIb7*W&"ʯ0#Zd*-ኯñܸ N;/qFZkTs+Z:2YVX1/JkHQ''Wﹿ1lE̿5'!I8C o4?Vc<<&}[ +h܊{0c>)HW!.A)ˀ +CVKcO_Դ3"ޚr#\A +ebQ n`4T 쯔P JLdjP̰@YֆW{E'ʸ8@q=۴C}^y$2dv+^h=!e8) +\O$*IAf@D~ A%^*<2Uʼn Ž,w2NyI%h޾bY1pI,-_`{$$۶ ڳ$P*td`}!XncW#.bd  ArHqȌvb"*|SV9sQ9Ԍ?&!_Q \5zWjrfqcy^Jyy+57& +8OMCYADT;C{Cu乴wl Ek*w; ONeEacƂ&TVS DҾwB?Pr!dgSU&~Vs߁0#L䂉҆PGĔN+/"Ѓ&[AaNJ^!ԑx齆L>QDs8o*9[s,=*qY>קC{ȄеM' ̨"k/uz]0 4Dr}Ѩ_8/ pTݽ<-j3t%b+Uvfd*RdsdڭYzβYQ ŮJ!yj\r^ztJ[Mq(n9vh̰wrm|&s35Ã7nG% d0͛ +H]؅w% [ EvE$FB6%.tVjbt +pѷ%Qs?%OIO-qQ ȼ zu'_ᜑ(њCBfC t,u\YqDLrZC%RSNNWmZ 到O|K~HK-;`(>EIC]<pM(PƙS&L)FIo!5)M{8] >˼̷6rT(FrT(\- 9y2ОKC;z[%Tld|C+nh$$jCqsl2yM.undz5]Y`*jWe-,(/bj2p9g ZpnI{ Kr&0Rٸl[$ +pЏiB/`PF;AI%Ș>(ֈyWTbO}kG+=@,*Nh{|I4="NB,G&vEs*/C`p7VӓAzvn a_7a +C=S -I +jTG/wr9oߒۓ3JeRu:c&3*Ӻq$gp e|zYMp+S>zr/Nh/͐dfCgi>VR.ٙ紶&ǣyS$1ާ.>AMbKݔ'T9O!$j\wP Qz]G]J0$g }In ). +s!ΉĸII] +:JͺW艽5| "޾ +b;. +ÛD^VkD1x*lMN1PmOf~+"rB50ˑ)mUWrS{"f>?=kX^]p/BB#&a&+",%Z bEV7$/G +#BgCsx[ Lu܂0"@]M|ΟkOt|mju@-G]*,yePy̒)4 +Fr Qh~Vj픋xjkuQ1 ,naZ'YOޅ+.[kVc"4QexDN{r67ϲ'~˨Wh\ԗ/idB*_ysY:Mἦ Ӿ^5q<'6y2L&- fX3~J쀆Ci5X}C? +\ 3NCDg!TENƒVBj@^ܨL&<ʒ>Q?DŽoX Ƴ$"}ɹ%WAj.2VՈ5VD;[ qkN96U"hGG: udql4FM#?,A`I=DQ7o H~C VLmoYD\'l´֣q%tB*+3lQ^-SRa׈S}Hk[p ȐIjRneʆ37BUw]Z?U[hcVaPfEu`GقkFK)'rޒ&755U@lmx JBvQC9\>+C @G9̧K"bsk1g;:vh2C1,paB+ dϤnoI[ mWT/'FN +K=既ǿ???__㷟~so?O˟:/.~7X`wOdB%)*hᇵx +2i9)=; [8\%%S+ "-P4 +@ZD4`ҫB169! 8.l4@lecjXKfW8M g(PV`q섬e25:amfS}kavc!W`GDn.Azt$d +KPė F!0UD2Wњ@"N[(T`ʂ!^M٭/Jm +-6 ;^H}BA)m^0Z׬Z+*dT +1lO5 %6Øò c.tؘS~&v†N "!h~(=C1`F2T;"D(U̍>`-mSʵYR(7Ç[a"҅ 6ÿu?(n; jw'WU5@E:?2'@hH<۷X׏EE Qn4d&.{f.( 0񊯇UWS<+p63Ӑ{S5{[*HFJfG!ܣGŻ'Gy@Gё*i_(eƙ%!R#vg02 +7Z% p0~I3;(ۣHƜw^͊t&{]&4Xа[v5ZaF^7X2Izju H^iѕ7`CME7ߒY >uBPsGwam&FSxFmW_3grMsڍ+H^!ȈW36B,t6FՏuו`7*;ʬGzE_^`4 (ԆF9[tj0OCu@BE2ZyZ,&_c'z +fX2{>ydE⡄:t!@(`࿗Sp/Z$ʔtZ0 Zٸ&]yWm -|p"`@,q̥udk]8tc< b 78FptR\A^rknaˮ~gd| +)5-xD>5P_= Հ)h= KwKj1}@ЩrXpEls ]./g(x5{/mAiRodZDټz<a}Bf^zx#?ʸ:/.RY (0WVm:vꥠ0S +]VMZt=3*q`;֗okp`tg4Q|m5m~hN*2׀ƥ :2dS}5FOCܺ}vnjR,   +[ƖTUv97RZ)a $ݷHT&[e/JX{d=upllф[-lx<,JxS"r, _fHN1wAXQ8`dn0 +pbmk onZa.}~yΪT$m- vɺx!0yT>7ꭁCzmEl"!Đq`U;4h8g~)6eXA"pS{?ZRlx=v>]@v)VZl*w +䭳$ +<{C#̟vƦ3Ik5` vĸhMbEi|v{㸎Z Pk<қ8qk&i+a4T w0J3t{S@>c3n~`Z f2^}Q6#+ TqAWJLh(Fj 7gBc}^Ny[ Vwd\ׄRCdOE>$ +EeOoS/:YUO _0yZ:ޖUa"߅,i{ÅNKdzoΖ‚-p 5.5%WV: +Zߵ~)E/U9eM$7UekV\^`َXHPB/} C+5*Sy8! @V؁,wQPpɊV RS׾AL2Dh%2k/l .8a|8,f֍kv\a5._g8p!TfT!P#{B9e JQGނ U[Q\*DrQU80mˆ w +IGv^ N&+oԶ7FTA*ˁ%"tGqs& Q= %;lt{Hs+}q !X)$z 랁I`d9Wę.Hv" E NNt6P`v]Cwέo-N +|9vhPzja#67hZ2[J}[$TlR@(=DkO +wNa8X% + w @"'Ae'>xZgv_ETOqFj]dɷT\f;;fl{(ύw|=DH'3sjJqo8 +Z;e^{]/LpG&4]EMevW#?(*op7קY}ՅA(FTL lDF<'RT2sn|=A(Q."lG']&5[_ +ãHۜFXC_Zlj`{^<"/' bWvu"a=3P8puC3zjd9Ee3 1^=SK 2R$`DpE2`^ЈS҃}ǻUXdPbf\7饘um,k/U;fkR,1SY?0IgpČ vDI$\e+SC~ +ͼ&W@Jf'9-l)an FO PRI늞<ka AeJh~}&/T6?0H,5xkf@/Ok0}8R32 ]‹Uv5tt"{q^g|(4_ +$O ZL 0U\mts6<VI* Tf^_Ż@ wķnu+Vy׼y8',T*9L=!i +FIrUih(%U)zA]@W` c-D@!Mh) "Q6mmUQA +EЮY"N[j8h0ʚw5d Cj$4H$pWks +"鶸LQ B횚 勷^[,ռhø^|XOʩU7jpOw32^չD I\>MKP@zzN푉suHuN/%cXOa$S}Ÿ'H;E+odQUϡ CPST^6S#'ԥ,ժ,P@Y w߰N8fF׌IhݱT ă#<Ժ zB h.?3Kֱf +&,RȽR PFfҟ,{1@P6. ;kYߑO[RH9~mM?DޚDckԔ˲=W3.CLHtŀ'ۨ3o+(b{޵/Dx:@B#mȴ{u j$_unl~!QePGGPU+gRSFjzV>gK&}P#Nd{Z)VgU1[` skb&_1Er2mGc_m0kϜQ6Qǚ\ +>%p+H$~'b"Zܭmy0[dD2}w+<ፁCˣ攤|Եg+ʙxl[eoy+|V>~j)$U:A1)rF< fE uH^no)GJٙey7x*kSCK"qTL'YI iYm"!㬕oD5\F߹Fz=+@ k +mr*R\̈fӥr%l9=KФbr7j7:.EP $g l׽KZō Pp +NT7TĦR9 M҈dUV k1 FZ4I:[YIbJ4;DrfFFOFfc/i'=7O `1k:0Xso`{"ґ?qx9^l.k.Ms)rE}?1Q>h;ab +!(fHE +;Khel\[19`M4ڱUQ-^ +b>Xb;b-iܬƛm?_KYd8/&{zS7*e} < +lO +Yْ(/T!{\#[ o&.3q`I; !]25 t ^D.Gu? ASӀ<=I0YB{yp#eIe^H+3A1Jh!Pymx*,E$ ڸ`BxCمՇ5|5 G+Rfw%hA? da fCa3 +͵֯nN*"V]NCvUUzX0ޭHVװz ^•Fm_ʤ=`!WEqo\s"v8tbMjWכR{v,iuGi ]vzByyk;T3@nF$Br}\OW^k![T7,7 q,$JQ&*$~7x);+ +LʒF_=,0:,KlTdHp +QߢΣWR +N$:U+s u πT[;䝛z'OƊEZ)TYrkVv!1{R"[K5 Vދrˈj(K^€8ŠcjD!ŀ }8iۿU=VJ;yH K>jEj\UAqʁOZS.O5#`C@}"?D $ T6EjZ|Y?8< cJ^#2¨k<5SD4H=dTZm{5WV#qFes*3JN:"[oX(BdLT 4u(CDooc/2VzĎ^ +@P5l\kc.=x2S`W0aͥDd4f.ydB*t_n7l- + L7!^5G\v0ׯ<'3]p}d/ "&vrgR\YPbc.[%đ_Pfs/ݲzKnL%$'ѢH|]#ٴ6◮` l 6lZll<;$B%1j{g ɽ' D~oۈ= BxGQ'݂G+"SΑFilJ޶ϋ0CB(M@nKX$&WT+ʡ Đ]!d׆$F!J(/b  Yr cu9QeP\Fm$`.?lSl8¤4ZNnG4¢AE!~6ކ70%bۨ"8l٬:y#1h’-@u\" !#<*`V>95%l=! /H5v ZC1g>jDIi("!cY-@mq$*Hv1\HyS^F0R'oܛ@\AHHrd2~k n))LOW|bC u+j]$_Hi +ugfm+8Y3Sx`1Y##kKxnG{x+_2[!J1F}? LH2aLjnGp@Ti'݆sX9J4 "/U]sG/$r)7ZyxE:l+~.C^M*ܮvJяTnTNS\YngE8F,*ƆT._͂ĝ\l6d:62R3z=$Si8PYfrP\!bMwY4#}(%ja9 ׼ȶf$I@4S((?Qpv*3M4({Ea.HE$+ rsҥfFwx쯆(G!Ӎ/$gHOGCD-׭IםRd9h0$l=# +eYo)_ةan09IIJXtŦ)ՑZFuo!d^ź $a#%Te>|[ k%@>tiڻ% V#69Au5A<axiNWzVW޺D%<@--(yGsT-Th|^U) + 7 +;7Bѩ Da^E Zd.( R#5ٷXH'[< Y!{8F]m9Ƅ; $QrXK?9*k$f(]-NYDRGf +"I(K7|g*A :9>H~L[;eDd ݱ(8ȉv6)A2YZ$HS=;,O[<7+<;v -B*0+D+0cw?1vA$݃}HD,μXn Eut5}-^CzV>NDag&? R~)fPʽ=$t#4`̓h::B +t0gc׍a Bt8IeK@y0+P{Ԡf)hP%Mp0LJ縆1a5]'dZ:脱-pPM7W&|Nd +sSRIZQswP%] qB_tl}&,j+9b^ 9(>kf+ӛ\a !}%D ed܅"1K-K1K+;cC_C2?#Kd9 ,+p{Ls.B2䖚oJ eܩ`}_-=c^$CO@9_[lz*8YIY-#H%[kX>$4>:J&IAMm&`٠]yem૩r KW]J}Rkm8k2jhY,FUC[ϻz\ qld 5iMCM!E_ͽ${>\s1Ȅ|GVʽC,;I5&$(༦&3mR7^+^ΠS v f`Ő!8)]30U8,H+iV3@!eVSEz&bő LLSPgtrv+NM %ܵ/آ7;Azd HAΈȯ(Z?,dyAp D~ů*"o݌#|oItϲ/3)1C3(鶡}wJ3 Ns+WDATH +F}:GOQa_`dll[sG!IMBh6^ko>@;!!WG*ORjISCNB:Wܪ1bS,%`MQb Dz] t +bL[^Qb"?UL,G5%1"VcouA$\*p$kaFG3Q >?d45q z@0:) -,Wauf`עCEUUv*=P,xkﰳ*VhXaO +ڊ^؃dlA+SdRE)PZfҁL_QQ\Jo`^4)#SW,dg@Ԑ1㵅yZm]oMs^߆ixIVb9gtT>ejp̀G X+5 d k~C)+DLѠIioze07MҀ>ҐV|YVQ9jn0žFx:`A(if2~Xwj֚BH@pm>RW̄~ |mbԃB-^,TEĖ4D(q=[ܢ][s %TG4{5z~orPmFDk 343'Wi=!Mݙ0KI41f9E@|s@EG$GǽdtNjVlZ q$x'A;r}ܸ3[uخ jsW 23Ҟ*O[z, Bϔ +)T D97uuucR۬cŹ-X/~wlUK8p/@F^R쩌\ Qq^kdF(!s2P0[ +&'ka_;]aD䄰M5SRuR6*863#-ݬΓ_@"0f[ NJKYɥpL54?ԏjORn)_Mh2n䕿miuJ`EfFLG@('@apdkPvGUrD : ཐfk/NdG;\3h|~/-;'疯g +fy9^3e24kf %ck8 wT)EA!n.؃(X*s#r]ˬBL'P3'yÉ] xphv#. 6ќ\\a 1 +&2=س0{Y[E+S39v[$0鲌JYv@eO羬"m6qɺc|\I2#äѠFbTx >HB>'+¯i9#1~t1$VQ^\.gB4Bip7Ԥ|* L5`|k˱<.v߯(4]V<+HQƼe*yئ3Lf0D7ծlB8Np.l ]?ɦ +iX F'pyim{nUJ'-}hG KlȰƺ h)7(2AZ<}rHJ]C- ֧'܎mE3k\Ѱu\磆IuxR58o  ZEEC_祾-o*X84ʾTTWTew*Hih]Dl4{vYrQ?jfĠ;@h>us;crZ;2 }A.2"SA ,C l4Ķ={3#ia%3G%JuV:2{sQ^8Ӌ]DZzHf +^Ű_$;f Ie], NOoMHǒ$X -?թcQ-tx E5*(ФLh1j(H"m,01o>66mjoSHVTBS͸u²p| +)7p?DsrSE=sn2[p̿Ǒ$ ++A:s$ + +^S=v }p1@c[\4y6 z5tV +{Mn.rIPSaPҿC`f&u"hon@L%ܷql5E]a%KyjM(cګF6iwTеdyuC hVh(RtG]>kxKƳ`+ *w,ՀqGqVK_t`<MZGΓe‹2) WJVƪQ +޲9 x; P)9Nnz$Иg%)W"SytIʿ=KeoLxW& NY)WG3a)rJ`TY9D\{ͨ9^MA+|?ﴂ|;ΆUIk7pb3ßGuאb LN.*m]"-C[3g E.hCBP[ ,޲T(pJw_ +9;<]sFvd9S4%w 1]:^ u.y)n׮n{&?13GE+ 0z,lՈgIgXȔskn\o8hP07QVl, 5u#ܢ/I"v:צSRHQsυ>oD" 2%cJ07<HƇ s xҤml6b@#VT4X#< $l/V;zZʺ"N˙h.[1yi݆~9[\6KNԨPa^${&q݆V" |XhD( ykB!a{zOѰ TmZkrla5~o/a M؈ O6(3+2I5ݲ+}z-AcKa92z@̮C1r@3AW㬅%LF{Lxb7!*tϓ.fsYӵuqk DvgX׫<ȷ#y(3daK@b4S㞃>5+a o}G=m.=: HW5 k|:xpI/b#T`*VaBYqG{>_l/IFMOS0=qώ#ڨWcs'S(0bϡà;^%!K*[δW%L2gc:2^;4I[K_;^Uҏ1h.5qOɪ#7yj y{w-x ed^sw4RDSYaů8(&e;KYb16zI6|Hn(Uyc=ƶNիe NmV6*rk("mĉM_ӂ݁+x&b[L +d">.&RMh~ B{ F@Zz%+8FPRU%ׯzu'y3`FD b>-@o.;I9GuǴN(HEZQ6\{ Jg/ 7WxW9 }M//q&3gR3vTyF {(~cd^5qQ}Vz{ls +ORX053J}kizG/gwidsdVUFF!)4sTW0eu=&w#6o57ŃxI~:-0u8t {lSMKZLGy!r&{M2GVͺRA&M;]v7Z΅J\&$V.E2F(z8}Hm/$}E ot9"Ԅ7sW@?bD$҆"/aѕܝxtst&e1Zv{Ӄ8i[^ԍt$qVKAS^჏ +C2C xƂ dz0eF.sݛ)HcA1*@B9i#I R,"ZIGBּJVlf^ұ\x_7鮉z2ǚS9~g r*ƈ(k}EGu_vq9.`V\>@T)@LWgp* {2Z ەwb0[rfSBiw'k"=$P2;=HRZmb9h:!Z2 I1äz l$ۙo]Mp(C[}sjUfML\ \r_I#(q\ t>ElEtC)$s9u"B˃(dGDf7 dVc_W5fhߵuw 0RȅHpQ+6ǗRYDm7A gGF64wJpl %C)D罟#xxu#xg nkRrmG-_{rD_ Ո+ XKX^ܴvIMe{4sb(25.d(j>黛'!>);ՆCmНm!6Va>"OHS%7A\b}Yغi:רܗ4J[ +P]׊ #׆7IG[ܚQL?'xiU{٢sRele'c?ή +Vx1wݳHcpJ$?Pb/G$oΊ!-f[> *XWr^}qsƩ8WaЮ#Г43vBkbo:S%2>~ Ѻo Э껆 ٩oEpYv] T0@zϸT`LfV9Hs1oրH+xmNVq3[({cck>~!Io$g!XNGj͒ ;E5zvae o֚ +]Ҕ` 1,n{_ +rEr(.U,SZ UgAbYLH=6{DpW +bGv %#FܗK liGKym[<>߂IR])E + E"b|غ(nޤJQ`U^M_JݭH/ BPUSbK ODչ>Ej;ߊPmr*\ndg EUA;TTGN^"1BBE(jNCcc UX~}ALM f6i +ÆMIaE .Nڬn(R],o<!LTY5*jpNk4uipT|n]lWdĻmT6#EL,j!QuɃϜjP%P bӹQHB:ɡ#@NB槞_6l4OKFo(6֗J+-Kf3L͈k ݰ7b=O}h)fMB.(wRc*00zVE>gחyW.3(?<`y\o(DNtjGc Tn +5oq>b$T417USS'_lW=o8ֹ%7_L6kyL<]TKe$0@G.:S&JUEBc CUPǢFj a^zI+ +ӈ42ZVYF( @PV4 hz﬛HWi?i@ܗ3^ VHV]ИttNփ,nEBsgd"ܛ

4Rac'ʜÕy.W{ Ex0=To%uXIIH$KHc0]J34Pc !gk}I y05)$3a(|q2:l7vndrvB)B5rFl2T%X]v™R9;n@G@l"eISG0Z^WA@^{HiXz+^P>)C˴ /j`E,lpLG]00B,R? ^&JFٵƮu}@:=[v(0/XPSXo5 )(<` #?q?r{Cšd_[.?#h:or_䕇1$vZaY4DFzuoiŠ8k.,#C JUzEB~4 "kvZfXI<:=* CaO@Y~~cLnߙP& +Ix֓-Vwk#O֊W *߱5~nU=g vGR&e5{L;Fyb2zc:x\+1Fzmx 45С+ u')#y45VCBO瀋&bcCњgէ@~d6+aP}ՐtiGD^X&S5Wjg3>F3U;4b@w/G0s%Vm*-hob^FyaGKv^ ;1=oo-\sfj@`UZItH'30 {՚%cu"Sn.1EGrUџ!iTECVtLdzD %Ul +8J<|$>S o ϙ\W/^2J}Wmb /aNGEKpD|F穱VӻkN,RӸ< ^[p/*}q[C<ٶF")6?rY3.޼8LL˫D;6OdkPc% !p{Uzwd[ڢ2%F4-ԩCbCnz넊mߵEE"~4]Ԥ<3qq*`^\YUKjó2]z@U8NvdufvAk*})< ]N.(mHp!-Ѷ!%oHJcHt)\;olp.$`zV`!cknseu'>P-%bi&@ Jͼ7C25'F~v.1sUЁHe>?=2Qĥኛ +b[kgFh/'튼~oH,_Nmv;Uyzr̭#Qqc Q9#1ixFfHnפqŚX=ȝs_`83JA%G 2j#8 $bd="ĉ;c)C`6$_vcK5bRsOvek+3 >wH![" ,й#un>9{3žFH E2y+ zÀKv;g# JNP _"5jN#P^x Fiϧڕ`%'p|“T#Sۅo s'5r"q&H[b$+vl4PMS֠ Y ![k@HY }0%vDD E$E{q\fg2lZox,v(##,_|.*ƩgÙv{-}uvX(5]j1qMBEtb٠<! 7}'`UC@`#MDcYٿFa4G5;NZK8#oa2Db**J_4㒺R=Z[2⍋42!ucX[4|W~gPAH@!M.yp1zj2?1PHP@)IZtٵֱ$, ׃v`/ f ZZaAo\GÁ>46l[zy5dkGb'-ƨt{P4`q'E&;w(+o%n7Kۆ%)QPTC6+8yAY-U A:'ygUHsϐCaIUժ񰼡mWoaȫV2%*ȏu{OsJ{>+"Z]C|e&5GE-6Jrig90)j ;6^% 3.=FB$u:5Xzc sRwq&)@dz-@(VXI_0k kh%6n(>YbSn/~E 4L hΕh[OOn;"p}m[=dk8 +5TI#VPSJ- yh#\[278V.ӵ'&ކ㭷)9+$%(~VpA% K5=ċ)ͮ,Kr^z34({ /AnQ(M! 2dEuvXFdFx}?)8ީ&`ep&pMdlHiqU2hp +01hӽJr[E!t];ж4XpkX<;ѽlQ w*6DTgčs%樊zܱFI@b51ڧӖ5OVgl]3uG{靈|X.eQhTW3O) M?݂K}O ^1 USb.Gj}!נbQjh! +=B̐{\A5MӘx2^; ~,@ixAϣ ,@X¤ rz4[5ˆt-ɾl@)or +a^-}ʊQe];(ƀ +x2Eʈ&%]Z0gJx8_FB{YZ8.):lO^p ^T;IK +:*0ΩŅ'"͉(p +@ +ےvZN>`{D=BQ@fvӺ_PxD;a% x}xy p=#e$MفUKO+ۯrmglWL;d 1``y;{-۲A"_UP #9pT2ux| Zpi:@} *}88TAYաZT_`T񆴻v8/Nֲ>Va=jrނ ־d0^[9PТIǬvy)D~D>"!2 {ũBݟJǥIX]~.~U_dsdſa#s.EQEaW.qzP. +'Iא MΒ!.,lxYD,OH%So +OپqoߧrEuA/,}{Gyx.'曢ŀG(Oܫ7Y2ջ@E} +(yQ\8Ejp9jg4HKfclI*D0ܶTAzƴ$(, G9fg| )^51mEi˸L$o~'zqIr@6#}Y6oMXPX֫}S +`x̒<^)FZK/1(AS&r.7% VC=(QJg \| zÐwo:wLVQ:]̗vўDS)λ=!*Dy(;Ү ǫ"h~sX~)fђƺTϤf#3@^q^X#w{JqUԆ݄z)슰ufr%:\ts?BLiL ΪTooZ~r )ںbĿ_')O4=eCī#OXW 'M:"<ƙdEM$P /uF%}Iz-2k1#V5 -X| 5[t(ޔ@٧ѣ'r +}5b/.NiGF`sK 0ZgFo9&׈XAc?' $e1!"iUbx{4X'wp*vEF_7G+$\⬌t" ܈x`nv?:rk"- , :P2$*ܑO(Vn̷QdضC3C쟿 Cɥ"ԾO1aGXx}!gDCfA$Łb/!h^h5*;`7%TXV{,&3sعڹҎs%m,Q{5m&ݤƕh'-טiiQf-]k\s|O(!V? M ]=ɔ1u<}WfcAn=&+pO"EU&^?bTR-DxT DM.nUe-N.W֩@Ð6x ,08͵`k xx X =?~?G,("LE`*,+f?ZYrp%Ӏ#**׍&6'~BZugV=羈^/7Gh@1;upФÉWD%@ +6qSDe:8..cf=O @H(-c }䁮R(IU=]]*9+)$<`3jZ$#~{~nⰖViC/+dL3QR$8zǙ??"w»"" *m "LkTEMcI 1CY[%ڌ C)@x?R9Q W x^#1cSa.J (DC.ŔR@6lh31Nx wEBӈK&#Mtwr`缭x4Gp,OODg6]0Q9S9 KV)0SO^\_&wEr +Մ$(,"A_C2F/GxmGD@ICa-J@#{&fŗ?3&Sd0ðkix=-'8sZJ3liá^y$'df-֒.ݻAwtiGgt)GZ9 ,Zm>HXl<dd6%c)(dR9$-G6n }A܍D=J i/Z4N ٴcңN5FJ5@3KazŖtb,b)>Ùd+$DA^?plFr8 +D5Q*x!A.D YWv*Їܯf }U3.cql߾ X.=j&=T=a۫=,O0͝y5h߳zɉ>bJo宦L4jͤs6 5^Wkԏ%8nS놲Fqwr郮vk?/W Bb*؅܁.D;\܈.*L6%ytpxVL~)ޢ}2ֹc % +W*t@Iz`i@Ie?w0N@ba5\UAcG-8Z,L'1ɥ,J/̀=Dfy@nsCuTGXK}.bl/fдt_W/AJaa;kk!,IG*ޢ +j:䁑 āu.m].,er)SiEM-zHVBg@L_Սp5z#M XeO[`*~l!MGcDz09to,lL]8Wn@P%hbB&ެnXdx 8/sP-;8 N|!X76kxA(ye@]`,{Cu}y7ݤQbX-c@q\ .quO.`?|GqQE nARDW mh4_ 9Q0{+$BhU>>:ML6Kw y{0$ $`+GNU-:PE|`+XcFA"L?ͥm[!}~zF}Q1&37&ʵᑠ +JlQP 5{Vvj S{eh7DgdUy`[BP -)c-8TlQ/$5Z"r eDCQ |c zvXa pKPpVHl:S$}~"8x)Ca;+c‡ JA wځ)t!\iEw=qZGU룺0rbHKTM=X6@J^Bs4fitX=;V_ɖ++#9sY?iͷH Ⱪ\/ⶢ95@-߳_ypd󝉋k4xXWL:'ּ;jYX}A-2;pX)]I2JLOk a jS$!BUb/-D3fk\xb&5!8`*tnK#;<=Z{ 5sn6 +yvz +CO}0d;7Y|fgA5iNx&ZdB # ?N.% {/VD-GNbpmNxB0p R\ 'P:,aYZ2w**Y㐘i0[<[|7T0:s-8wi"a;P k=9_ZGR+@ڥxieh8X ,W>h8ڽOWӗSz삋XNpv1`;EQ**^13@YT`y`T@m6@aiOtv([lϧ6Gy? ,=XE;ե٠롎$84YP@U WqMa 4+`y4ؙA\m&#|͡r WsvV_);+SM pjS;qPmN=48ө|yOy|(>Q"G[±#JAXrf{X{vO~TtUTF=k%&^ӑD vFY帇 ,U^ R-9))4x"B`E/l:Z*!NkYe^3O(Y#p{?8,T #sVb!DžɊ +nz'ZzJH%AhѶ-ՔVKT֑$ +A/3!6Gi)ȦCTrOI(Xߞh AȄQl+|;8c*G;$Ѐn-JƳ0qey0ET;MWk'—]1>)TwDBJDL5@|^~j JI6HJ  b}ڬm+P9K]$i8|Y lOS/M/Xfdp9Y/A{ѿg?M~@db;UU)ݤz7t'+J:O?{OKePmF;.WjB>Vji-O~*rߣd%p5߁3l{ ۥ8k|UL ot]GƼH!cVPQOE5cm*t)F6B2^8EQ\v${kLۑqmzQ"ZP ޠ1F` {?~;G=Rw %*Q'[` ڐ-|ZWg,YC(c2s'QTәR;Cݠ'BhR0s;ɻ|D1WЍp ̀98/vzgM PĖ@J'%<2zfY +2+]PӃw9E xy(|9;ww`zA钴(Bܾ߳HsIRx E[ *,!QT1{̀aQ1:P?Aƭ>v%*>H9/lC.-^PyK`s̘-Gbwؿ~/+E`j&vox;- zk0FGпϟ4#=+Kh_Kd{]ϣ}t@h c \K,'1 !t>юJcP0ع&}94^8ppAQс^7o+ۗfv5ASBUz9H:nM eԵ3bidCl iwC9fKh endstream endobj 77 0 obj <>stream +l?bpEq=%f1h>qT%<[(^g![KssRT;A^$=0foGz dhH؋uR Ef&%6h:ڈyE)QM#Q y?GX|xNW>e9O|!{wgN{,2#z/>-)C"\R>,8S=FOP{wg/*~#)$(>L42)f6 zQc9}co>>5!m/T"DiH-L IK PJwy`mAw +<44m=T bKk\*|*]VZMW%.p5z!m;o) +1S(EcΜdJsduS˪QEʮT +|{X$~DbtB#Hi͂_(Nk@Eu)PvO*2BhI"'tvQ~REWMpuk: r 0Mpu* .ÅNqO`5p'A z!=1Sb0>D)*/59 {|ITȺkG8`m׹{vK\"uegG/ga F"- ݽMAalQ+Su+@&K0SrT NL{L$çj>tgE;1wNA@_a,T`챕gm$x̓d&TC=GJY d^)>>9ef߯ u贌b"{(ipR ],KZ}pFeyG+[Œ#M!GE3o?jn)=tfn&}Fm;'_GkTX%g4jFhD飆ˆE :& }0y<ցQ[Z\T̙ek~! +Pq"ӯ< t +C-0%,_\2wښT~2ZC١ŏ]T8%6āeFc[pR8ҐNV~Os1+E*IvAB(Qj-Al_s7% M\Drsn(3iʴ]=^xu\:Dq=SBSY!ٰbw#u}pD˧W!]>/"԰[q2=]9U ǂhqCH3~BI2SV\E +oAGxlnj!F9;>βC,%DDFBɈJkLԊN4zK_]dG x搫%I} Y`m1/ޛa9{m)V]^n%i _f>DP9jkPŇ#%k>Dk/+#0^h, +!Rxf-lw;`bP/yj+߯LNDat# +c!|g (>>\!s?)YGR(Al_ف&>9B̎bjgl@U휽 @%gIpЖڧc/)^ʪ"Z| ޲>C9hhTVxJ;ѥ3m"8O@wėyT/*ہt7BѶ f")@ vv(P҅Q" _Hdb5$ACy]RmD #:d'QaJHW3pUZHIΚs>n +9e'GN@|Et$p(Z5.VQ&p/MD=U)B _\PT*xxA9vȃZUW1|hy 1Vv?I ,V'|=?|nރ *%Tpe12|!EXa[9+YFQSHjUǕ OAhCVm8;E=>N-/3Z1BA+IԦM"8Q)7jeq1"(V?cu#; bo=YBTUL'֢&p|Д\Q3|1!(\ҬUMDR;y +={m~;a#:YJ^$3\ĨZLzf; NU 93& 2&$~;xެ_} +-25ěHdk*kN /ݍpJޞ2$Itcpl/XcA{lIJ΍_\5PLDTȘDLYb#QR%vG2s+eV" 2bc Kh滿Kޜ{Zp^#Wi84u))֙hLJB4ASY< ˁ7  )|o4Ԃp™MWe= ?נpUw .WݫR>Gi@,9~0fz@rYz 袞MQY +W|r%FT8"vca[1uj^߷2G㊬~)ōjOd$G%H+y _L#X (j 8"V+O(9$\@ҢЃBS _ jp0@ȳFQe`/Q3 C9?+Unڳ=%!=0]ạ+6gl' h%~99 NBTp Q[o*٥iM=&Ïz٨qhE/_懝ƻ )W0B~*CQhQU?9Bl[v5N!G;F-?-=3eU2' ugN<&55lA<(CYM%$9nϳaap"8 +x6`']aޏ!g8A +癿G7O bsY't;b|(mXJuqD{3"~Sğ}$%piٯb8Ȩ-9xSAF$Fጩ=9iQLNf6Hy{13(K s(Mluxply]ߋb߾_4 +X4E(# /45UuM,jREŠtOidRL~#BZQD +o]ۇvAiQ4A}x-y +$ETVj)5 ;mCrS +:Їnߜ<Ş%|!{A3@0]!7QȊCb_=VRrCݷu$ Ѝ:l ͊~#o˧ZNt H}TCJ{,X t:h6DXl/+{ _[Wӈ~h䨱oZI(EbG!qk 0*q{X6iq8iw`.,T(*i}85KDpG8S]YE962QUEˏha^ +d}ňToG#9B8)`ZW0>L~g(Rʻή3by ݍt@*ɖj%P|RNG-%6+.PeHP׃&?>{ܫDH鄠̮t-QP cq^ ip%wĈmb58AL1+g=N5w2/sB.xe^Ӯ[K +ՎVέ`yauȤUfpIK2ntIU +8HR cL:&l?JBd|êw'AK庬pR{= Dط6≕)qToiۿ5Xa>g|z?#? WH`LG5D a\@o\́ +f^%h79ד 4OPQAS ^ީ*|o4_ x:0yՎ& EjoM~ـX廮x{k<;EASB J54mgM| + +V(:Dv{J>"I8So̷8 xKyk[NZ7]{\?Ga5d:_~4z{P2PJL63A{'P'PT̃RE|Д>Gm۔Lsh6T&i `"t}Fܡ6|i;y|v@Q`ak=7~*R{3-٨`R̻l/7(d3%'V%Z6`G@G}X1ygXF0v-0%5;< 1%.fUIT:XĖ2V}{MRzp*tZ_[T;QiHVEwwBy+X]?i/|G>fnǞ(2y*Zv@@z숦Ÿp#xycI(옺I~ă+efPJݼ 6b*.;czJnI`%sV0)u5IbjZ@mOk3$]ZgğnK愠7(k/#&^TՕfm GýKK}8@۪ l㊾n \{  JM-j ӞfGCbj,PеSsgT-!#1lb)΢8hjOi΄Ⱦ=a$'Bu,*lͲ]0WfA1*Aŝý,"(I{-",py֝-0?mOxG~ךިuKr{g#^i8[Tsz .'1,vBn#]1)!0js>JaUXko7ye@ 6/ +j=zɈCحrS6YɊ/ {~ Kriƪa!d-uo]:bnIgr#ϓ`ktN_]UmA۝O'*|LR͈4NR'Vlm, V >*b+|0\FG=p + $'hĈ6GAPW SNOmY +Ԉ4\c[(0%DYՀ24 +vD3pe qG5D ЂE'xDdV#oZμPW7Jv|B~o~aZ±w*}W_n<EJ?_ZW!g=viģo' +D8Fx +1.uDLsگ£У<%A;16@P)I 'L_>Э/r a%[G`~f(NW[;ݫex&^Eރv+CCQCy&9:3$0~~jϓDlX֟+0~ v[XܾFOQcOO3"_PMM y1fjAK$AegEA; # L8T:YD8A_uHc@54OzDvziTCo[(AoGjh[_WpĤ<=8$#zSFqˏibd3L ޹~Ĵ}4q$ *4otWpQ+RV>;Ed{qʴ 3Ogeq`Q&<{"; lL@(!Q'<0%thS-@yHQt 1Bgnۙ}TB);CP4r3 +M\j7@yJFU#t_W!Qd>j3® 6YC잼j [4#V(Ho{@3V -L"t]e753 + iDiW U~(8C+K#@ySpQu6DdMXS7)XYֹr~ӋSX .~?Be,#`yL)~xM(0V 8gsI%)홖 MW-u]vpSƾ "W_7vP%@2JP u%BPا\a$a!?p=p3 '8@&ztwiPy*RE6 ?sX x7uݫZ&R +UܣVItDs%jCisW0Glu)fos.S§߲n[Th]dxs2}y{BJPI}9OɢnY_AzKg`^pDL9X& +5]qT{Ч*N?%9R H1#`egSWf3H.Rd͛me%Oy*{A(rQcŀYZ%G4'J,@K€0zŞi.4-hj`3nD6h.P@ExUcEJydE% 4=]@GJ=`*ޓ&}<e?YS#bi*T !CEIhypFϏJm(PBg=]mtqz"4؏tst^@. 2h vEFiQ8ǧg4ټvqV^-3Hׂ%GtmՀ"/mXq̪%]9RtSېV4ypۈ }\Y*LIv;s;p(1,sQE~7R +?=6DH|Bvx(ln5QBf[ vk\` k],*Jzb9.ya<3ʉm=d*kDPwCQts%:c_T{:hHˍCDuTk> !8yڍbJ MXDh1*lEThLj87ݗ2f֢TuYqP 2AQ:,/K#FAYS|-+O@"յhbh=rOb.p,ᷱ;j;NPO DrSu"3lagp+5v9W\wO 8W +tm,ؑ' $=}gX0TԢPӥ@\|K-=qbl#[V"A#Jg̛?(Rb,La蝆57jIbPE [MPۅm5Md(jbDԐ^j;` +jH 6+ ^D.}I oָ)"f5U|SP&"hM2B#0Wܗד@-P,9/ZC!'oMITRISr_-Q=QT/v$Ewڂ^@wj&\5-JT'I)3ପYadF+h@C}c0PSFe/)vB5- !YZ(;(E Q1CՌ'@ 60TXR1RW9ZhL I)(8[ݖ{IK%Hw ?-#i 7fɁ:HTҗꞇ!$|:H&DCx]io@Oqq=Ɂ 49~"hx։ + cZBS2,C_ӽ^+8m,ngA7'g;;+i_ԠIާ]6nLvXDyz3vR .@KP0$48*\0e@Uv6铼=283^iaM*`4& MY(t׉.n +e%*6MDŏjev~Q5r~X- i(*-HCb%F*' W'9jˢM8#0̼ςTi@˔^\H@eo{^EVq +cjpkj_ #^E ط*@-F?sDK3R/Wmш=E78G +o4禆=.Eh3?(fV43 +%֡ ~~((cCI/pL/a*§ - +~ƀ$"y#5mv0O=YLp ([|GTV +' Bo=캢:f-f*]=@_^!;}h-[*PkP`lnKH۠Lb + QVKp98;,S ADwNj>KT9P z<̺>ĺ! 7{d:0Z^$}RX{rRjւ0\*41c-3^k3oM6;^M^:]F("ƉJ\#V@ƑGHaK_Czc_HKł4!wNkB`9ȸema:$~>+$o*aM7fy,(O 4+޴B j'((;19[6MJ\#T(Zs@ wף t +Cj`e Fo7m5 < ǣ*mp4 HܟuG9P2Dw be=*o[G~mXYq!3Fy(YAئD~WjԮSa `;3Q&v ;>j02QCj|\DEk ng3Q?-2$=_1cu^C#sOUÿ(aJeݻ/JAi6 <]Њ ߪy>(ɲpK:vl9z@dαV.L5=܏r?n搃KR(I@%A9JlI~?J^:RtvJ¼gD  +Χc]̳wn]zH Q҄!(7[D ȄB(rYj7)Oґ|]Ht6ӣB.կCŖ|'B íZ?qп tdlt pktՄGhIWm.'m06G48#wlU!d!񩓩[PW4 &@.=z6^AC fX}CsQ,`nD,[yyߙl`D1a%Gr~C'K"@(#ˋn۷&i<3v3D#@3FÉxQGcː .]CҤݳT-h &rHՂGR0vT6gncҿavTvvNŔ[`.YY'owx 6pGA>GDPyVŧ +k&Z,mF[(EہaPh%.,R'`ėeE~]=m)1Zr 3DK +"}3,lҾ8b!MzyE\jOr[ԄloDݝfu54 ;J( L[ 3IѝqkG*6uy^U pY@$K%{" +ǹ:q.*2Co!T`A,n{e\?=,|$r٫\?lژXlf/tej x0Ũ,{\p@pcGv:ý3]i:tdɳꍰ_x@Kneuɔwo`P (=lJǃII :]U,3,r`O +bSE^T:A4(&r,"`Gj h foI΍oK4ϕ [bY +: +5eLoI4D)}. 0!nO;-[FDxx!% 3 K$*F֏((F%4 *|_׎HA}X9X7~OK;SHֆ`@GECc u2U"ۅB^R/蘅`= h\)̋pvVe W +hݛ y$aoPԀ0%Dxx~^Hю _ztIA=?!9DGah~X5uV 5 z# +U&h77BkwG3/qs{g($lnCvN3@(6ЉB,̱騉V}̪.DгsR ƈv"ReU%g;ˬ[JK!=MfbVMFD%D4*@1gp(σ9B D6bg 3Vt,a(~7 +%* /Q] RٜbN!ΝaŔCwzNEBY2)~4`JU}2y#fIg%=TTA2O9SR-Q <(R?Y(LZ ,˚FŮBQ`I$:\R]8YwG\v< Maa Š(h\71TGqd T# `Jǫ\vuo?@V]|0=ŪA|*$4{j|+r f__7_B%l7{h]ۅ@$XZ74vpU'BZ$$TnLͰw*/(`2Eh/YlX0="m +}׋=QQ4[e) +P\JfahFֹd߱+fW43Q1j +,DBu)\ *Xf%w~)$=0{X*UM( xI=$Aୠx?[E\T"ǭ_B²dh'hdJ L UFDt=-!3]Oo+sjMS52ْUBS +@[5D,IMw:9.87?*\3 3yJd!g)zʘ?$r~ {"VDeRBZ.d˲ +-z.vk_fJ2 Tz(3P=`k9 89)-ߑ^ C 4ox%G<7ì*E ؟Xn^"~ E|Sye#jal#dmqAetm(HEDQ/gwN=yـP +6bTpkd;NyԔ'^M2 Tdo1t)q.Sh?k ic=f,k\CJbwKؙ@PF0˰TEW/MX$Á=HqhGD?^̈b#joWxp`_HĆHZ|̎E8/ +Љgl; +` ߑĩfŜa +~>yxUkgI¨;+ K(Y}^YvLP`%&jͣɍֲ n70L)-Lp[ PߞݬtD,9| {tlv902.h_3=d3S{7}h沄H\dc$ +p㔼~t v_0]umrY7cϕzv,ǔB1tLFDy  lTJď<ʚy:+:΃"_CI*ZӃۏؼgRQ Uamkdr +PZVu"%7a.DQKSi +l#RX0%Kf#LfJ:yP[ =>Q$K;Ա؍ltCU7K .q(C=õV//h%dt|k?Zu_Vy!r #/*[t%hJ.~༠*Yas~ , XW`DViPdiD ;W,T%⋽$ 7R{/0N$)t(~1%e3L e%hJ,3KJHQQ'@'D'$ 4Id@sY2AmdjO j T"N$֋uؾ@ւ Kaux@<=j1jI e!B29U4ЛkIbUq[QV#0TUGk90{D w3\";2Ա`ĤnƽWLG!UG'Yn|ot >?uF8]xMޔBh+"8*3ݗ^gNl:UfFg+227jW;\Q=<ૹ*'(R@7l+ߍۘR"ᕗ{LLNr`GJKa*S@i!֝~r۽/+gQw~/kD; 1;tZ&4.g/ehcCP-J v˅ЯvYr0 %(:;~ g5`q ;D FDfNIf#h8kk I +-yyψx$-l@\:MHHP{lr4^"S]4W3 +Im$RPQhD +*Y" y?gdgU<)3|rYLR`p8Рɵc7+Zi1qOؕKdiߜ2v5 ̀"?尾Y%Uw%&)!;4WV?v{ny9IV|~Bn7j)-g^x +A.%R K=)`]  +佷V=dZf{P{<{pdc`? BH9fJp f+јC}EjS!TL-uocyrVye)Uej~(UL- YyoEЦeMD*jr <&-a +L  =YDdS/Us:5+v#ωGՆE:pud=v.+(z(~8y}"妮s8\'R1ckp^(TAmD}oҲmz Ș}D>HoͻRF"Fz |T|i`#SnےԶ5Ք|(9:H{3P4:BTP^r~9 nO:"{׽ _(>m|7HG64WyFVUMh"kK.oA&URB \HRTs4edLibւ2 0E(G;bҀl>85ٍIQ"褨̴cjko+=^o(A v0Ȱq&G %jAn ݟx7*sKeݍnTm$3`ĊԻ)ŰLG?3Uf߃0hcS޻aCG@E詐QU䆍||pqXqcLV`~1qo *0Mi^zQҧ٨(WDtiYF(ςߔs#f u\:TPMԔzCzNz޵6&V&|mU*'#mfI \/8f?= MyE-jAD - +_[AK{Zj~z!6 +n#nxZ I#(i^fJtA;YG`T[$rG!I1XפۯLC6⯟Pmρ3^>Vx 'gRԚTV@3%־ q 3n~3T\R㤧:DtKp@>JNs'ko%)]&J6d5=ODHȹGn` +B^ks_ޅaZG5y|<~ o;x7n% A(*|sO=# +.}cޱLU;Y7/ ʈ?DRɞJ[߅eJ1HqX.T@=Nu6h0;s:7qňbYNTw!tX94FQD\$e뉆q XT=G $'=TKX1FuK l?[A#JS *mE\+ygZ3#!Ms, p>}4;:sC0 C.yֺ׳S'pAw3۽knzhF+QD@yK'Hۇ*? *榒L ;-^9Mh\(tb*u#s_h2Yv#`pP=w,_`z ;Q:#6 +xwh3ZGnG19Btd p cȶ!`;8(<s(Vtfn&C_P CSG17+$XPu~ <ʝg,&p@B QP,ɜkBc R {=E Tz[h](+TC OŲ-Y{#V=<}%36\K0]|g5fסSct9޴zklt(X%"ybyGl#eh O+,_AW + m/5Y<:1se#%d艨ϣKxl۽W2 5NEJ)Jg8*t#1AQ=u.SIE5+-N}FI9s/t9>#remxsl>"UU[RdRJ Ttuaֈj:@(*D}Lj;tL%J> ّ%]cʉWw_E]]JUD2Tiuy)r~md1RnʪqjuGPB{T)hhQyz &(5ۖg|ގ F -5<|eӚ~L%EF-1@0-]ۮUH*F<HPز N1!ڷj%Vl:6aꓷ!UBY\a"<\{԰6@}[/=񀚂`k{BC=و\ + +px Nh8>YȮi9X}[s@DcDfZܕ\ႴeO]"T֜S+SAo"8?,+_y_Ypbǿ/_O_Owwwu_} ~Cg!1oXD`ףSXƝ4X *:^0)n1~ K';3k.C$^Rz,w|E;|]=H2艊ۜӘ Hm; WhAi~FDɩH+5l(-5dzfG= *꟢߹VN +ܑ.ݬ,ÚM%zU\0"6Fڼ>='DRN Iwδ:b3iV73G)?iuqhl +I#QJX%@B'>3o$D7KgE:ugh$湋?yBP ]"<0P8(l;Yh_cEusleT;ݏ %Z)wYd08͊XⵯDa(K3,g,zk",(Ur4/gh5y~w»Ct!֒(t0ѝ;1 +#OҞqv< LӤNkHpv +$hn睘P Ŋz;<Ba`3VfV(30\g޹t/KZ4Ems*d4}`z9ZlA +,@I̛mϛGΏ&'?Jwl+.ܞLJ TR@DB@රO{wO %k 9)=-xMj'Ո*?)3ڦ4Pg^oթUp[QێbuĿ),M2qGNTHaGa+,Q=M# aԯӠiV֣c.n7h}#J9A".;__I(kْXeLL;# +#A)A-S%olhx}нOȲarSL~20d\?io NzYqk@!@"oBdžCq0eu$TdzYzXAtq]6 슖t*wE Aa_V" vu#Ks42lA+qm4^#Г Lam?W-?a Uׁ/&~0O]<gD~SZY+o؞ɖΓ)I9;sޞGqlSUd78Ua?GZ;[xzV6D頜7}WZI\Uq{[<\ŪamnS/E T6\I5Zk%褜L=0SjOx͊X@O71"zlQwDjٛeZbr{Z( ,踿9yq:E-||`ߓe & +-@J(LȸN@m[t5̅3f`1"gEy_B ,` Z#%I| Κ> F!4sp$:Spu{l-um?hydj%5HSU VkӺHxR+Eϴ=3zU+" +Q]\[ nVum[,&=8 h +{|]f;0N)͊5r}z;$; +|?>S%5 E .דA0OhR3 ޿d[ %U[lÛty#_:E5R|$I[wТ^tQ* 2 +rH^U6U#vZMro3bjeDP.ZrN9#[UVR5YH:( +"n_ |#I̦|صdfs!EW+QJrDD

GڵוdZy$ٜuQǭ vԅé 0} +'G6:S㙬: Q.&7b265DeW3"FJ:Ci୙38B*n.qH+}ѠxpI)Pr'5b//k[g GߛM4Q+fDZ9Z" jSTɌu^>E]++o~]>녧_o44ڏŸΣ@|-+%G~n5@+݊uJ;ۦJ"(LvUbs90h87@JFѱJk؞c:+k@vz OG@(A+TOuMfHI~HւxFUIYė\)m)-O3MPѿ9%ۚAxiQ#5#E=STҏxV"ݝ Yŏ$ #FH{w̧+QdW[U1QI$8 +jj8PčJ=۱K4{Jك9Hd}u,!i{2~H<::)NE@ }qzw>n i&*ʋ<wĽ)-rqi<jw\omEzDطFe{iTeMZO[' H\q;MwVUHjO !`+QJ%omYpjeON0u&euGUN8qHڪ+ܜ9&l#`ܧJ^& +=T٢I(h[a$fAcvXpp_C5"7>8Ǭ ۲L*L7X%[Yr u?#P<@ܛ 5QSaɘTL;u$] rF%uᙾ4F@+s!z9dok ,ƙ:*.RZL ~J>O[(%ADm*bp\VA<é\GuBUmlnHi-Y|q'}%"Ձ^5%PF67FȉYZ@1B+Ў'kyŤ殚F,Cgp\#ʯF W RGܿ7y=0O\Zj/ﯽkUcms>8x4K-c" PPq?ry?|?ʲNq~nz.ޤ_&Dxt]VH-u@R֜"E䙝予~GTSn Qo~3G vJ[_e?4a0:CA1Rg7.6  %Ad5fBoTJǦh]W9wj維>3$x~ɍ9pC87 ` Ϋdr{?((X6$2uK'A>dܥ!M@FysZLKk@'5锷2w5OPb.L@hIGl}V!^1?wOK\g,Sr]2&RgkO;ޣjl]ih%2Y.)5Mzѡ,W%tM~E6A{uku)[\jRRP]lu4. h5{8j2JKJXXl('yK-DQS?ͨU 2E1,qڞbM0 k YXX3D\l8HgD.0;7 \cBŝuNs/H6 RŸ?j4W.4~ 8bL[?%OO< qD!.ЕJk\*,w_h|sKJSJ·Jnټj!}B;Nz7r +QKeI8pnOS5>Au-*YPW04r(= *R܄+pdM*1 <62Pun+z_PZ\ʪ%K=ع$YFѺũjU72)|btifY{cע7vt^pB##ԣ7LtE*o&_XD/z]3B?ʬ=Oج IsLBzmQPĆ((. t{tZ㒥WQlDY/yA:=D l>C‰[ח.뎉Y}OZlϧ[~A|NOŻfL ׯ7X dC v重&g +PLZ]&}J`(!ebNB.D+1\=?ϫ D\n[0hZr%MDۮ`=;3w#u;!oL eBtPag ;sB`n7AVLMHc2O,d45m&kA+u=kA'ѮlǕxh\|%7j` +Uu'X[G#[2{G%ru~(r{|nၵ(^9WTOR}CO*R@7yVSy"o ++"C\ JLֺlV٩yE:$"peˀomWd~_)£ T~.Q9;(XU-@Wwۗa=FKbc4 }W`$3j +F[GLTDO9؀a }LDr)*[XW;oX#u<:FboA%=߂]6Px%YhKeqׯ e6u.\TT-%&Cقh'q/5,SahR'  G}۸lVqc2pT6U5Yf֬eg[@۳Rە x2^  Q,L&A $0#0J"3(@6vunK2c5:{<*x.t<HIBIDrh#|G؂Ǥ$?)u9ݨj޷:,R 4?.c߻kk+cq4OyFYVe/3Bi}s!j?$Jg{UeNBzBpmlP=z|#z'+cC?l<6-p8j܌~oLh,x P^VJ"N7FL显duxc'1តv`sQ4Ryթ4i"fV, !?l !5y~K1RG̲=;v̏5IlH.9 ]2/=֧jMƊ7`jvSI +U;B)< 8*(c'jַT84QQsRGIT)[D OR)NMn\T/HY}dB=\Q~gmDZy-O~B>3@ sa\ +DUJorinX-NzŲBt<;i5:pS~lë =ю AbnCEV̫-RTay5h"<*"lې-p!#ԔBulw8*>^Kұ #|][G ++dE*fpkXׅ~9!bRX/e~?+:rjH] ZIFSNiW(Pc.2Tȝx^8x@hGȱCHҫO]X;.+Lu T +?"i[ZMeڣ iՁwz@+$Ç@ZkyĞxe*EGɎh W֊2^^zrb}R#c"[ ط<(]@f#=!mC۵c wfp" +Ǟ~HjRk9^KəfQ`Q`jӘ0C0CB?*BpΟmQ+z&rC PmDQrgBcGYR\4 ۨmGɹ/O3Y ~)s[?&ԋ7s(33@g.)n9[je+v_R~Z5Rnb u%؎"dSۅ%гdۙo#"W1,tŲLguwVSaNMGVO!^:72䳯J3ny3 G فqR(WH}0{qX&;CuXj_n?-VX$BѴF\{iI|4b7ᐸIBGa9 $u] $VoA :K;JVDРUxs0) ׅlF `IgQu:Qwjҵ_}:~8 um2evxB +1'[hEu6٤0)^kNޫzei࣐F "6=!wJ]fH iFP6YmDF%dI8lReFAτ~ŮWE({3o'm¤uڼ+;B z1=O(ʐ΍܈MZ3عR":g6>[~r\u2UޢċJIQ/}ZJN{W]RS33ީow^j2ʟ@4" |*_u! +@W#^U=NO6x!갻S|;l&tӹ=Up:CUǽq@Q [Uk (jovOCbTxlgcL]DI$x^ggsCmA4EZ)ѵ؃-1?Ӕk8m|4 +v%Ab ]3[&W!k 2# b1ʼ] _'QPVSrn;=OrviQ|B_t@ِӏcdUa4t4."  Z׊LPE7\Ymnv̰}godxQDS˂дJGg%N˔iN4dQz9܋c[L^e#M1ST+*ԯHz[:F^)ϡӡqCjBRGeZ}Zm*i0_wE1Z$XL6 C\ +3V?;YW4gɮ!xi(.ۑXU@̠ʹ%܏u+7ivcaIŽtc4*>ςaD* #OlS,C0Z3}Ipg1L+Wss[0? [ WHȽ/+lztv*CyۙSW'oaR+^.&&TV0KNB[Qȋ;RǾ3CPsb3!J5꡷ag\);iyXVH?T87eQu2:"鬚?I.k餰q*;Yd6Y<=nv)Lr2Az=T6P8RІ Z`8fIܡm $FLU ~(W3oN36. + +|ґvኺoE֖T0ţD6[,Y濖g6 4nks:ZtŁ}? bh 걉̪Ǖ O%DOJ72X(z8ǡ+sWov > x+}:~tl&K,3#^ I6Mu辸Oo+HdJfvD Hq.PGa$+{w866)MtM$S?@19[IQC8ؤd&nhCTyHUsFOO@Tq^r/*Oasv7BB{"|0ӏԽyplzT'yh*#mQW.h:&@琂/S[ea3Q565|%f鈐Y+i͕ \lx:MzӦ*5LhTMʈ'SZͨ: E䋴PTt{qd l|\7{Kvn@˵U|BK5|7-v򺒨uXrީ.ܤ:I!UD "4:[h+%[aS΍-AGJ5qR ߜdS⃑x~X74%Lz58@2Gb5 (Mg =/Y ֕`ǂ+%ey" Z ؉eҾ +(c_6ĆI{sycIyݦxrG#9S%ٙEHG4B:,zfEme%"ݕ=BdCMi#*a ]!C ؈+EKZwd^Nn"zd dFQL Cb~Wk\( +  Y@jPYجMuom0& J2H@?*[Sh' |-(??EP\д3LzzfA4"._1s x;: +5~v J@ZdhG?6΁Rúr +aI!Td_c}px!W8KxQ,6^H퉯lQbjCI].Y"WIR-ۊE{%(rې3Pf̨4f) +ҧ& ~}pG*Hϧuh[OqnXJ5H7'B[Ӊ X. +g ɸy{3>R.MRO0i#gS +#iZETP=;KOnFQ2Vb!X6!F%-mG}k9rѺyh& + -) +7xNZ+OoٹK[/sڂXںn7Cx{K >EsRVF"17-rzOݴ*c$$NH=3) +_c["#+IK cE5+ʝeT;JT~AEJ0: UPD:^$xC;Y<>WX$1 O8)瀶&3$DCr0ǝAcFsPӺ7vR*b$ۘ>k/=xkZ6֩o&i.UI%w6vy]B:>#LJrsA.z'-UfLO>Y#zu#> _XGը=l몙A,u  +?dϧtTtaDŽ$GtBW`Ϯy %Ahh ӃB, !N#؛{&"S5o^Ds|F9Q'/F\x AkBOǮ3@)W +9) +qTtfֿ9#Jo7QuK3J*Gn|Tm+1 9mGlK}(0 ʱV YgķC#fh@ګʑ7* @Av/E)m;<~4Vf\{Ek[zs B1Ֆ8)qX=H9},jMx޳R~;} /?NG,|Ds@IӮ7B_o!9WBjFY+5 $pЁYHSev9"A܎cP05ү'7gNe0=;w=p|"F#GEN; T/WJCI^ +d*(Ԛ^h z ]ڝR5V"h< h)j]$pIՊnZD-MM/XqYX=tuCޡk6Ld Mp ot %`-;=D eOQ湾c!Rbz䫩y]T`}l R I>[YƔz S[ JtzbQ@m4֥xEm>p+uq^*v_=R8v9R|"C5^ZT k4-诏 !8#@*=CJXj4\fhIKpoQ#E*ne֦'%}+E*/qDWQ!Qm*q)d=OW>mpQrlE sܮFf%70 iFd*ڎj[=D߭&*Z=ִbUT vʮ΢6g/ +tm5ߕpUX9.02*Pz݄䧆xeP=E,黀Z}Ehٕ֬g Z^5k{v.ܟ~i^ }vK9`K3=uMz*G㣬頒#WI*,J4ۺA(h0í¯y)R@+5]­q{jfQm./~&#Пovcĺ9jT^k> +87dϹ=bFmvWNOIX0,SH|mZgAX>É1Uǵ7(H)F~W۩y,ᨌ6W:Zت8# +s%Jy궧!Byi\{BڤTqTh]\kes(Ng?ĕV)I/CrsmDm Ղ* y )9,`mm~q/pf 58W$4l݆9QT}:7v)-cZ mSNt"Gz}eSVו wUɴETj|ґH+u/^)d_ix_ +t$5DNxt6]xe?J:@!5wԬMDu8 cKgo*8m]YVh|N6¸9nn󌱖9u3Q/311TFKY=Hƥ8|x ~Jz*1SE cqA{抷%5PU8b\vkO*rP =Oı#r7CQ-%8tu^6p5*(#]x~ Ȍ ȹvM^I3m:{vȚ7-/ wfw qb߷)c66 O veqg|0$.8W6m;ݻ>*$]`KF@E:so땂B?v,xfv4o`ֱaBQu*Ѓ1__E3dy(w=`#E3{ϟ5\2g8-Rzqe eɔ_ݟ^ WUIv4o~Hx0ɕޢ-B~z Tt,]8TH4/{x!nvߜgRwb(Y&ĭ嫰z3JH\O|y6*wc|OMD] ]->Hx§}Ktx^YUGA{|ٹgjیTĭr +Jm#uT@1LjZhuPe srhoV\/0-rs̉b1>*0ښSÚ1Fp)QС}2ZX}Dݐ;uԭ XYa5(8?z6ܵn E_$8vD!Txueg/͑yUۑˈ(0gC`ci *bGa<)F * /2<_WJuQcL}7|(׎$3q@0>[RC,.iT뛈1$DNk>(AGA.Wx6\yji×Zeq"'R # t#Kb{޸`҂dr=6mi߱gwZY89}=\#YjLlg%?#]#ߣXPb2@GvJb8_ۤ6^ky73b@ʜ-uJ #%kF~ +6z 1deF^ {jo0Y!Q[-_>"iW?>ΔUPzw/]@HiZܛn?JF^+ox]6ӄE2;M>ώVI,gԹBAx+1r^*(Ky_dmDFZۗ9 +h|G*+g +hEW#tTވ]~ )OEx BXUڶ'x%MX)x=b<9"ZQ@ 3˜Gw\3.^FIG +S,|`$+BBVRQ\iJZJXؐBmb /J*_U^OG̺ŧ2;xLk:j2e2n4 7_ݺƸzo?z!U]/走Km\2' Dt:6njݿG`Rq{8S{ p +O+XiK:k|ʐ۫xq8>ghTChOz]X@2dL]4NJYmΟT'K%O)L0IWOTٛ/zR[.rD,MJ≨zZCBTK˳/q$k(bWn~L*fSxZuBt \j[CH,4՟nF-%!v릗mg,|QVF׽g,@„T0DZ.-6a#g@yh쫟GtD^@1sMAsXjb<UuКk#0-@%&yu/9;Azl3v)]AU + /#\hH>J>>It Pf g'yU4"r~BE B MO入 +_:Q<uG(c>\[GJ˅CeDu>nǂǂn s;[F/MA5<mWGtѽ$YU~oe\~ "ҌS4M85MNk Ѭo0GC j&& @K[,HA%ݥtyjʂTgăh +cP9n$Ssk_} y.gH3F +@ך:Mt #v-T~9PE9C>nbS s/)߬8ſ??ǿ_??_]~7ƴМ"TqšI%{HYYKW8l<a˖woVq|90XF m? σJ)mey3vn^.1/Iia.%dEPSZȁ~2uDdX\ֵ 2Jy4rp7{ٙGA(λ@^y$ +@CǓw)Rh^khZt %THQk̤´'̄{ n}ReˊL凂eV7E "Pzee,fnx/)n6M-I{ontq^Ӧ&f4攅k\a"Rd\2~z5э o53o +- +M}0Ϙ:SfwxQ$Pխ1x9ۧ@V`M5VVʶBp;TbYp1I[9:3SJy{pS8;NZ(quYfY>ŷR +H_X>FkBI "jc1C"G^<DZC|ʺ!qeX~㙉MzJ~9eگ=' ٧^tvW8D&Vw1|{k ed9(d?];1Ъay8(Z4%O`'>@\e1J@ۊBõQQ;g$W9x _KP a2f- T z|j=ԝvAlh/O.?EGkDaxB? P߾Gc᲎g˪~*@b*+lɾaFGB̀@M]h@er;,}!,#"&@daJxa?FNXgycZ+ {)+I?(D.6 0z{TQx7*Glfh.ހ:tŗ(o Mlvϳ>"I#0ZÌn ^ Wv9b4Htt @i5߁# JCDTcZWCb;{ZּcD +O'C">d(ȯxW@gظx +T> -0U`v*Œf['wא5K6bA+|D!)j ̷4x!̷C EX|S\1SٿHВ<&NL]K'73btwS^eװFZqc3ё$b!*S-Zvz'dΊmDl;2u:1)Xtnƹ +(w:o?@_> ՞yρ0ULӵM8]S{ TI_8nԆ֐#xJNF>n'j̶+ST]ra4hu`^bܺl +mL߲ /ZjJ֚c,."67'0$ 0#IB 'WPҨ6upRxS@dda=g:h)TP*Z+(J[DwGiz{8~0Z(4ȃZn&lЪ0Bv"&Iq] +Qv,jWס.IBa, +"琉vHhE ҠiKߒ|Om0+wWOC}*>kހLtE0;Z/܀ ~e9-e҃SAݠ#9C#n2 JvLj`D{8d5 snk)΃CJk$|~Fi x5͊H!zEHf:)*g W[o=cZm1!:Noū!~FтX[ffR01: fn=E +AyiJܨՀځ%&'с#f3 !`E1۸'N ᠑AJ[32"u/IaPe ĥsi3QJ-QH;Zd Y)oܭ~Fټg<"EEsx!#QзcMzL9g%)$o# LA6( Zc~!Lv)06e< Ha.z5 (uQi>/n;R<Ka!OTQ;BLj(-6ՕI{j͜|{G VvEJlJ!ʇ'inׅt~ݩs^Fn +Z70hVzD+&hTIQ|2zhx-EYVFVGԍa}+]sOK~ Ky7fN2~o)CR6>OF6)(1E 4"brs]DC~SSQFL9SL' &SǨ AS%+kĆ׆8ֆMʃGus~F~d+Zy4?a`qlu. #Ia~ER+b mTpqzUgUisle[-L-1p7GX j8 +QAU%i(-v tO'?(a'Dح*w”pjT'G^&J ů +x2Y & d+ C^k\:bG{\)`AZe{f9'=lxlMdq6su|] Qn)#4YL'hRQ5 f:T F!DqRvv,Yz֡파<7QӔ Bn7F~jU+/32b# xΚf:s=c&ҕ/CU BdOrYrV1ߴ'0=dxvM늼=@0}ʞkaDh )p/5&*J @wc?׃ ـ׎ǏBT*돢0DY6B((fa 9oy@6-WeܟU>DLqB*;6jEқ=H<ٶ֗f~) GVnȘn#`"E(^hth3b6"1JXDV+q?3El5M55| ViXa#S҅@Th{Q%^e1ݵ[;+oAtWz2؅MCo*)AZģsOxi$_N!߇EE,G hk-2lYE:oΑS]r ih +#o< {:SQh^^4W#\CkySb0 Xa&^>bfH@]Mp A{ş rfӇ'~Ͱ8 $C6|UZ*q/eo{4,]Ut-Zwb!FgaDD^uHG{?*6{al c`x_Z/K:: S،U6rC|+$tFub*"|0D9ϱuV6O!:dH$Gh8P| H35~'q}45SЬ0}8|uJp{<) :4I*Z--x^6s&႐??+)\=mĎ,%Ax +DZ].J5GO^.ё2qFu + fS ]gs5# PQ`=}ZlӎaXog6eL ejHϵʓ>!Y&+Y&l(? 3g+h̗Psƿ8z1'P"悶losw.eZѲ Gc\:Bn{I=X'6tMwˤ&. `n[ZEc];omP5{m(e98PeVTDr# +7;"SfU>cpP[7ۿR(Y(HDž  ,v M8ӀΦiYADLQǢf՜H&!t_5u(%X]*MVe?s[ͳ}B`P(Ğ́GiXeX^詓lfWkN>DB4""3ZMv~ȳ' Q.`ewnȞnS^X_i==V- vܩ*k}Pjjtjn>ow@zti}:%E1[-ʫaO1 Tߟ8WR]AL_N!OQ'=m0P6n_ + yO5Dك S1BoDzn ;[l.2]]J"I4vxSYU =?#TgCOJ D4U8 mi*ykYQ.h=.*M?RMWv]UGӖ+f*ˀG-t< +|F6Q3 +"K~SPP8L S}2 k8%\`JҒ 7?H߾z/JQFW26hVkڋX$9ਞl*m!H\+fd}\MA CL<8_!5oif@iGLEe]b8K4ţ{ozL@J +e{ْ1ӳ7 +5j*AMO/$QYý"AMxD}6C(RX!WRjs@mK[s>t;4e G-Y8pݯ1SB}~[6Zf`$X*#!䥾qvMho`]/>R)hv* +tyfQ<@Շy@WDh_ vI+DT8Gac5F9pK{6Uū{B_*~Bˊ +;*Zlmz' mR_،r7TXd8 /9#b~YWPYie9v/`qLJ M=yW|Ί-Y,)Fj1L} gU65F${5DDC*rA5[ch e>8SRsfN^УWoB0{)sW5-3]b3#zÖ _.rq9m)zc誽uv`ZJ'8x&Žy%ЬRY%)vO+%N>uug>EyÓ +b MqšԅT6i#r`Fܩ|]DPPקՈp"x*Vjp1n?޳OɔU'pru:'K 0XV@7CKV(pހ`ц+F;dp4^_+1RK u,^ҥ|33q(,~4=c|tfB+xPJ<[¹Ϸ=`jl)Gx4EtX Bk)ry- +_N@p`</ +n;ʧ1?>?,pn (=mwsU+d@"^^S1Wmt%v8^NEc&Z@Gә{d\hz+ JD% aS Jl1 +ӜZ΅"x0CWyj-SR/sa~ᕐ7tDYwm&@%Ac5u oo[4N!#tE5:/姏Ȥ+n؆kxz^h$0WICTw>)6dLJkM +휑<M=wUqfcΣ9h7~\j<\W-½XLM'8r;['@%(`8D2L5#x#:5! J~ϕ>J1kL=e b(! I&4#ըTE}9{nbDv =3(a鎠fD?Q3ڝwĻܻpJ-t?爟PDDb{!´A'C("<#ƒ8lTˉ +S!hi +(_ݛk1O @`^1nhȶC  +e hV=qI+P<,iPl(GWæ{W +ŝ1:}# +iCA=MjRT@;)5C0skU<[yy] #=18iy답}׸bFlյ5"(Pt.V7-,lRWjl+-= usg*5'3a> +Ev\tV`:x~gE*զh.L1#I[FS֩L ϕ`x-80 S=06ɉ~Djtۊ\ni[ `J#FnIlx{d t!B2|踥kdz̰BwwCUD S@:caY4mDE֨?Y?|DuADŽXk9qo@/= +Q_(ŬY7v˦FbN#S Z6&pEWŞi0Pr$#;^x:y\@ ZzI]`,6kEhG$}nRBF|UsLUBcz`)ǁZ|1dD` t+o-=Hn]I} #-:!Jj/–S=^~6̅qU. +1Ţ}C!*ǘ87@=8d]zDBqL0NvyGy@*PS hxiG\'"l}4={3?qT~\kzLre*K[m[ hRnj*Nds^UΣVGw2y!'qP bRK6 (ZĬ{)YO 轉偤A;P1Sfa%8Ѧ3}gݞΖU˾Ш$2i-sml WϨJ]hլQ-j^gHT*vzJ +FG! !̡;VI<:(lvFegMO[1ĥ1Pl@$>9d +>Pq8jvֻB5goUUoпD3+;LQ+`T>IصYsgG- +_|X))_~S.޻c 1 +gY{u'nJT"FY,ݓz;-> ˽*hV咙NS EKƈbwg)άfM%m2UK3#(DjpC^85u̗{N)"&f}\7Br`4nEIra0_N靝"0x/Nw vDM*n|p VTʝ׹?ό"JY1T l{1gIrf5ӘY( >8g뺍0$Q #ig^\ 5虴@~Ʉ^nl?L9&傖[jb5}|89!ͬw U9 KwG/k8?tɝJonO싁{M=bϕD]+v#*YC5A,Mm~sz=./jU~|nlIk(HM*4yRR_ÊVC\&IVpV94h|\?=Ms^m&2M{U2$85Z.@SgQ)7V^|~=AV}u݅JΜ~)l%D_WOXаafEu\&\e S~1]\ϛ5)hqoyVYo;@uH9 |r +I@ȗ) 9X(,ҭ;$j kDjAtS|=.!pד ^:,N,IUɅ6Z'h} HKۗy"Q9Y/v3]^;zthyQ];neuJ @:]`C*Sh@׈iֻkI "57j0\Dv2 O}zӤE8QOGukgvpy\): y(GDpRTG4*iuZy=9OA5?s%DФJ iE*p2>WG#Nӣ,Wf2 ,Kp]E0# Ieuo K./w`v +1j`6| +"7` Qb´GaYt&omר@(ɦw*pXaCj C(1lJSm &aM5D*tO t_ Okъ2l$B\GAOL8Nw6*C!;[nڑ#ZѸctcy:d{xcBJMyAW3x3"}Js:t3KwbS5s09Àz7;MJufKyH@C+Q#RاgӞuWMH/AM`K_`9]aG=a;V {Jg'+X+LbO@9LJJPY5@b Ѵ/^7rh?)+Rrohf'‖ T ٢}1} +R/ۜhKA ը5-9x6S|/k<F?=uy׃H7?מ(,90L>OdOU`>g)~ oec ضy189.8V`NC +$W7.zMFs>sG=hWjXA!Z&y׃J r`% Ds<A|O%çjbw_a縿`_E' +:KȹOO#Dr1d<} Q5_ d5B(@\> r|[S zg k=I:n +8U| UJ2adѲ8 h_&zFsόߕrP;R%7$!suCٹB.-F_cFRn+sZJRڹM_}֯MK41ƞvL>}d-ܯѥJhn0R_L6~w0gYXەu'Lsw*!RXolv=T_ (W-7UN 9s 6H`Mj=2>[pcuy/&09p/ ;1A:A]b3@ s&(" ;  ja7<Hh7dA R]@<@J^VC %ģV:NWD},Kl441W/Ih6o@r d%lg +$ +Q[ +ywxj30l߄8 0ϒ{fȧBmOqGwk݈v +S_; 6Q'$E|88L_#Dݶj:Î[n\單>8{J59`ќ*m⃘qܡi%>ܑ#1*ف^l +Y{&"RCΖ~͟M (ʂz˹wlÃd^*ou_G%t8Dh^*+%}D`+g> e^e(71h<I|Ndp3Ԫ4nA!3gyz}<CB ƣq 1D8m,)qJմTQO<u !ae_C;Q0O[7$(yX(y.~sTo]94kx}䱱H+Lfk~ +Oc1ue񡷡9<u2/P6v5Sdb_jv?Q_#.|F%*l\pkXpmcD,430k/U&̍mt`d_i?+c/f eƶ4<q(YE1=wK>e$"ΒXt?QTQQ8ϛ`k];fDM*t9Cs4*ƞߑϕzx[&!Z0ЖsqȝqTKMpl>^>oTOT#"t;*A5%@B_T;ejRv-P`_)j@Ft%A)(S>Gt>jڕUP=6E*P["--[PSSDLQ~9$P[ U!`t]E>"*Bw>"j@n\-Wb">ʡ +e/:bA[E~s"{I]AA?g+Jl REO_ybSanߛcٺG ֢5"c}"ۓ[/[}oKM_4T?콡3@X<kx {fՐpTL${̍Ic?*q`cPX~ۊ(Lc{sw~,҅*ߜĽD\:_"ˠCd/QWEq2 NòhD>'M?ɣ{Ы ^hae &sրGP&r5#FX; }v+1YkDѤ{g_)( .e\J4BLvq׫ƍ m9uPV.FPBՏtc ⅺ@[ +kDJ+dqŎ~謌R _=*ܕKTj b╨{% +c;s%wk7L<[ BtV\d"UV1@ w%qJXJ%*i7aƱ+nZX_qn_/9HZm+#gh(vL^ӔJxeyyyT msʲߠ>K_~Jx)@﷥c8d\FC.?@j u6g*R{d(HcԞXTIvVTlx>$< +/f64Vlk.;# G s {A*4"תd +Bs*<مUlcAw?_XO?/OOE??}?s4 IkHc>ƥRJC.̙{ʌ!`$*}r=GsHLe*7ao,4CL4w:pFR5ЪЫ~!l fTWsSV}=Et< +}A׼hGJTt\ߠs jf؉R?Dv&ӌ{g_J@8 C`A0 9?=& +83Q |#:fl*Kso%aJbtJȅ^m B=7v'FkEIHę}wڛ!ߴW_#I @ ׻_zW_b5{bvA)Ohur SvWT;- 5oޭAӸ[Sڃ_5x>e DxEë7"Pex/=3SVFL"& Q&2itu. yeEr/eB˯אB[B%y&hi$}x,Mr}D15U)U҅Y?:{ 'ng 3$_1} MρF{lB@st7{1I4^WfAxv\h Su Txj׮~ 7-/ɘ]aoO[[NE>ڣ:^v\yhsg/@W^QrSAULjWPt&V6sL6^ '"`x*{WZῇGyB" FĞ~8vE/8sKu4/D7TmYKk&UD yڲH7"}è = +cv~|R^]yJ9PAPCAJJFh}9hNRPv/)  ɩȒ)©2<=܂!-~>Դ̟ݨ15j h@2NSwݻ+#?,4hf;/އi عKrVWGhc ŮaL 1 z-j9Z35 nJ}+mxkdͳ w4-Pz[2VtRE_`;#t +*jMbQʝ ++cݏ(VU68(e/`€ 4!Ie!? 8Nlڗg_? o QQ:Q@؄澞_"RDfyY#M,׈uɃ>Qx tq>4y+HлRK|n+=Yuj-F7ģ⟟q@c?DjMc eTߣP}zlb&ҭi],"n) 'uKq꜌'"uRw!Eiu'+reʦ^܈e4S4TnA-uA؟|Kt͘*>uPMNuAqK͒q{( οCty>G5Uvda2ݻPPrlr<"UA @V>@u\Y[M$,SL~FVIG 䲒L݄L7 @AJ1kc֒2u:Z l0TS 7!2OdkNpVu违Vt[i Xe a5W{ckG/њBT+,.|<"WΖ*9d_[O+zqr5hj<].?+*Ԭ/&%I0M qyUqKr2kx15etJ,K{Xa0Kwf7':egu ;.f#wA|T?/te1wsr}";(:?1& H0Ӏ@z)% endstream endobj 78 0 obj <>stream +.+N̈́D :h_AN0uyPOϏ$;~%+v#< wܽGE2LGjXMv?\Zs<$#*Yr:jn ɔ&].yIX%K?B%}syK ׽DN8+0ptP'1zs=6iD\*=Zz@VI-5oi/5v54'\"@7A?8'%TC+y^.(7{xy1.ADay@ bʅl^W!#m0{oJϙ5b;y)%<;be]JXq +n}ds Q6.gNOsS+wj&!2E Ih2$ S +@8U6؉Hun#Yxۏ|$DJObTNSt p QwA>) Ty~`D^ݐ@˘j_#鮘oNRӌ:J_#"}F.KT  7Xrt5śDzmmk>LFd /v{o +Oce_ NU/Њ3H"!A8>N\FuU(}sJA }Ǯxbuu'Iust>O1;3`?]ܥr + j摽JTyMB0HcA@kB;Ws,#K1K`|BfqP;A:J9f5 u]DDdM[vHlyE+Cfl X-/p{}r?B7Ju:k#ӶjWJou_ r +7lo"`)ثWOyU; +W-s#,9oV[#r{וd\YE;&ޛ(-6z5Q,y@]wE}Za2ad}#T^=_39`< ;# \>>wgk _b3$ak-b΋ EۀٺHe:⬲8 §غ/3Hԯx[jBDynȌ .;EGKw (\)0h:lgi.e}ЅXCڳڅUia4wcHз9>xڳ.xj/F8IPVl ME4 + F&t"x7ho@P.=[) % f>}PDp~Q 7 n9% wx]jQT|oUEC \ owy newOwYQ@]C<"icg+\Qte'Bu}DsTNOT&$SI#6j{z ADWODOmi`׸( +R%oO`6ӛd:x]z kO"0 +hO,(C^R4si,|P{ۃ}"NVDPJ'bY'W1;BwM*R;yةzJx{ +ǽ%6yo (X!DTR!H}lbivr`=7}uC~]IZ\Ξ45!aw{W@Pˉϒe! 4y=sKa 2h1EHn +@(y)ya"{=ZG<ј󕢘>@$k6}Dťӏ#r5+5&> VϧQHDXA!H y8tEѝ ѬgbsF[+e@LM*Ji4؟r_D^\``҅CE7}=lẙ).{b5 % DrY!dbJ /IzGnǗ?^l^Prĝ),>EW˴Tb_"PyotŸ( iSa[+#8?poOPNI +Loy}C}[VofR7Ry-][>@k@c#c ݠH ]AsLۧ G +"QW97|C2V/r=%i?8~o烴0D{S@F~td{^.WӤ̇k9OλQtL(ڴV:MÃ*Ev3dbdصL2{7_ z[$9J`Lݐ1C̯J si',`}lsp6hr @"k,`$+0sBqz(!$G% S\$׈3m=Lר v0\z3] +mqs/Q km<@NWc3僯d yzLpv &Q8^{9*F94:FKj;jԑD: m,޹d9%p]o-jz'] ֒ރ^8L0j9ѫx%K q-~cv*w׈I{!-DɰM-`4t}/8۴yqWMR(QH2QPQh mW +9w?Sd$-=)AӚhN +ů{L.I5L` =Ut=pF}'C{{[_H -irtg(nM` +M=?OY'TՏbZ4z4weCu;N_@A_R{N?(><;%B"ߤ鑶p=7 WrB~{7=Qu\ CWqYh,dR V{Q|lv\a\w*j0GXPq4I#.9+@b>¢8uPGoaA +P*q# +>^I U<%nNa3X}G\eyQԨ'j;a 5DLBۇ{$5aJ8n6g{4.!,|ڟ&0T7`E$(ﮝ~顔mmw +>eBȞau!bʌ`oF,߸"'PFCFI3[r" /C>2pR(dVN `djohhz)H;X19H @T&Q+AS15`#MDdpdXvFTx$?-I$s#/D,ðT.:fwI][@a>Ia]70PHM%G*= aN#kٲ9>g%V;p.ՒI6^vWVܼQ [6FϏÕazȮWGD4v_$=L\@O}GGLVw3#oـr}vhXwK{;~e 4I<.ziK6l8bd/(qQl~/@d1D,UlLbLddiKd {w =pHoW(KIO\ a9p@òBS"rb';Ь7,8bXl@Q +95o>ilh)m:ǃ[N2"Q  ZC7OV#_b +I>߻h25 tǩ'Ȯaj!B]C\@Wy +~҂* t:%7,Ocosny +6;q +7hU~X /%hOM,Od&oJ +>l<ب>BLnԳ'vRvEUQ9KlZ8)ڬa=! \% DJy)F"p3 |l May5&uRwa9+PyNl~!`;nC.ʹs )'Fpҁ;!{K^5v[A"+(uu~J QiTE(%jPThP;x6"3S0#\hwܐΕHx9Ώ'uVEc-SINMg?a pzh9}QE&эrlj +3vjMQZ4 TTehDAEGWDۯV{s6ؚEFI͊GsAfIW;=+MG|F$B +Fw\gxGL.#8i¯?%xM>! LS>kd_H X~ b5D^9'N{Ckk*'\Mi n7*JṔrhG~|1qSg45q7u?dn3:VXWW8etR kYYgʢX3leB|9,dW"iA1US +i82EY[_H{p֓$B]7lm?AdmrVQ0#`b7t^(]m:Ae`! 4;C9*TQB=pLF:R}YJ +4H$>j ԢdUNnCcπCDөDx/#R5BzAe5򸅁CWID;Π% Y2j3쿆3ۻސX1NFmuxH 6\kp fw?qy`1 .Zk HHtQ|QEiFdfsZ + c>UWJzt]̺"&VU^M41»M }9u<4mF'9ջ}Ge']e_g\G,d`H,|k[x,>0> F,GכBW QGU5S󮢵Ls ,YdC2qFf5ǹ@.-ҪFRև4jȨ׻jQij61\zp0cvC4YR JB/1̙/'Y g5PYYzB D"}ɹjQs݅@3m!$\O)T$שPR`DzXF.(/Ӂ]X`I7LIEx$)[죎H]WQ)i! +Fz7~GDD덀AJrVoJHKJ_FԛQp5 UraovRzaM^gTL-r"iZvG+n5nҬ$ +{Б_.Ň A*8xH+2:;Au n<ݞ&T&0ni!8 +KC(ТП('Dy4 +k˘RY#$5~<`$ +w`͚v!wb^Bm"Ń^nő8YJX[Hʗ2=!t,w?To¨,UIH7ȳtxc Y<=%:=j`Q+yLٕ_q/ L,aAI%qq~L L]^S21 +Ps"'ǂ 4,6,޷+ :$;؝vۂ^[8ڪ4CWv}uMAX~ziv>'Q%4U=V A7E Ԕd6;Kz"%gWe4D$f{1 +FKi3_!MV_{1Y.=W{ev=.& g&"D ;}2րUtD,"#=tj/ٚU.! h!j9EBO`|RRI1A_&B *VEb4󋞠2TKfcL!6Q! +\d4؂Z*3 9r"ld3\!:L0 BԀ" ̿FŞj] Ԍ㙰sOb3g̃_ͨ34^Pb?4Fg")NeMΛńqDh 3 +_ܲN>rQA]$>B7;z@oubSY]2sc+x%>$0C!Oh_#3^ꊰ[:җol!8QD\dFұ{8VFrs +f &T52$4޽R2n\Ӕ>gRaL@e`p(i%c6RE\Y9fgU*7 8j\^aK጖dE\CT "JVSHp/w +8 K:>u}OjB>6 wmL $y:Khu)1ONeG<e B4s|>Y +vdNc|)#tFA.Բ:Ziѝ@QQ2 %ZȂ"%jhcSϳ#WQv4Y TUJ]xH @wzs :T@FMsRi zpi¾bV$[U>y8&.p'*]ZRxl٠hRy< uըQSdOU+|Ä|\ɟD_(SlG',_zAn3ΕA nh5&',*;G>?#%DΧ*^~=r*a± ."K^R' Fm`=0 ͷb>+:JwtG zǽyk ""{0"/ZǨ{~#IR5R1==7͎EnۉpK24*+ CQGP)R +vAoGYI23X(cک`GhC_ +*WɃ{I/5=T'/@،˂^bBC,tDT uQ9[kHQnXna$lEY &:zE +ˣL e&H)#k79<;%'F1- +D9rR ~Ó^l{ɍ?C-&B=~|6Y)#}k3(N5fxV0j#Xl;"N8nI)2!E> ++΃QjVlRSxJ(O#bNI6{_ yӒ4J$fD$ݖ`9(zOw@[Zqq#$B&8[Zi65雭q7rlINf#af۳i6_~PVV}]U + -&=T\T. $ǘxUBXO[QO +]gпǪ쩯(v T_ ?tGcBۨ=BEy:m=<Lo +w_}`J?$ +#"C?'Q,#y'4R_V~H6Wi_](Y]gj09zwvs:F~8;Zk4ϙ["[ `!FuDЫ5Pk:ByUR*wJE r_eA:!}aGP=Jy9׻8d"4]u`OfdHaܓS cnd 9c@$bTTj`$*BUںJcј: }X4`:B͎Vmw &q0pDE!UFzӏz,Tz"h.ǣYKΌRSY!>O 4wE@e;sO]MH_rZ,;zh|NQ +\EAA5+񐅠sy9Pp%E~6ȑ{_+?MapM,-~ +W*}tO FlQ̤;Hvk|OǺ^?'At"-FʟìA-"9iO'"xcԌidưZ6z{W%!}=K)y H*mu(=[sd*<ͩHOf@h"%Fu;q{\[N"y 302*FZ䀠':,盃t7f~z*| bx cMwM"H8:b9BѶXAؑ= Lc\WS:6W wG)R꯫/i#j5D&٣mw\ru4ʟbLWb!s0Y\"!J-oS +W'8ؤUFhAPqy~Og*!E[:Q:@9ՅڕQ ҈boAJTV6CAU^^]/ _''CjX 3S oDDR%"'=b(ŨET)R;"9ݨ"D-pQ}"D!v1{q\1=.2">|3DJDzy*\9[.tEʉ`"bzeI1?3 +G-WDL'Bw}HeYۛ 5k/ נo$ ~.e~e-:4q5C]qLmk6K(2S5j&&.m#Ho))gXG7)}֚5m yrsKK% +g#lm@$_e/Q0D׏6X}{XZϔ lϲmf:i)~2 !&@ꎈgɰu4T텗1[A\)\Ԩ!wƺϕHIyF5=?697Z}=y]t|;I>OY(søsSUg!kġ.+۾/Q 0_ҭ$O0U3>}Jנ#,hB_.q3"h&xq1W!9/3mՖ%;}R8d^څ1ؾ*D K%o>}Hk Jb͑9#Z^hĦ +@2c9/9͈Ϲ7`***R?:j(ҧ}{M6R/rLG}^ho3mnӕqS*Rt}= 5#Lf۱ŧS]0vn@LO>oGFsKAׁH\0\-]׎4;wMϑ81-ri|( Q5gP]%,k5ׄũ&ҧ/& IPi~Pˋlpl1tWD}ϔ :"(J#}2 +i|SmW-S,oKXvvX 4.׉|2h%Û]y3f^4 }`5߮,z6:MgލMو.%j4fr] +CMk +9l ֥!&7d5tƺKK*o˖ ˮlk"g +H?Bl +ej.b%đOý=JΘnF@\'b$BrNkF?p+АMnSnCԚh9"TRCT198vGQ8 ii?bl29ҡD|ʷ<7uSCl"tdue[,oΚ [c{}j؂Ri#\3E\1Oڿ`ӺzyVfppS8˂.L\*׷Mo"rJI7fϣs{ҭv$["]!iz%dm(ŵv/ Vx#"-E+?#}D l9+!aYpգ'Z r"Cz^/eκ(m+G[](m3JxBkcjJ]Zؕ$cEÐ +訴xi\f̃ﷶ>P(Ujן#fWKZZnDSӻ=}v ?Ў'5j{Z)lέH|FigƻE,2 v73fx7:9%m YcM6J}xaɸ.D5=G5(+se6G J4,zCA7G?FXS-gehYMAҏLXt&h'2A&ΧT60y3=!k4~Y5GPClcz;W#F=w뗖:к/@JBYWp4h[0Jnj3FD"Pp4*KOTv}4Kݡr2RM}_Cz-j^ \Ud?S1bX_W?amem.W_pUi+Av[Tq4Y|(J諧vpu2JY!iV#/k9#5S7a`MfD}\QJұ(M ӳAZ^>J{mH8&su"-)TV"LM +V5`?N'I v c|yI8z(ΠF6bpsw?%}Ǧ5Kr]қWc/0]>CVv ]CϟSQ? 1"ML]NxF@\WU70X{T=7"05joRXH>j$sȆ]=(_Slt6HSB,uݙL;uxYFnh2ly\SG vǶRaLiۃae +yN] i2Tw5-t'Bm3/$Fm,unYUdJRo hsGS9bЃܘENż'e?ǥfO9P3B3§G{ƉwgOI*a(V~1h1@M3+2uN,KIWX{, gkRP`X<]}9nn75cBt(E~#yM^)i7-{ + L96^%T%+^#6PA $"xLD;;I$s/ځ&kףxJ>Ȣ +("M?ޅ|j (NVZ x}3OC 4N4rt׸TBt7o41=:5>Ax5MX_:M . WQQP#DFdWo  AZo1ot-t!l9 ̲TT`~FZ+щ]W ],xH<Q3 @v6(M#mPhz_3>%//=.p;bPG5UHߣ+Y5rQ#}>,r.C4m +S_fRxqKnɚ]񑮸(D{]M(ذ +zgD yWoKV꠪m:Jm,ܩ>xjF.p)qyC!k8uf5D5/!@e%R+5=c d(%1fhCU-G@ VEbߎ,ppn ;9;JC9V0KO + :~r<8aٺ\\9ɘ ykOmw̟-=֯R >q>4Ҹk4S3pʤ]?#Gމ"i8(9RY6~@+SyZ@)t&/ޗph#xcQG+r# {+khj/b[#jCh߮֜~%P"ּu}q72^4Td<mMtbezA؈vSf#ſgD5]hewaYl,5YTi"!`E@Qjt^9 l%+jYWdFVȺhܟXZi_k!kMUi >+\XPpJ!v%=?Q߈.=k / +*ʱڶxep=u)*tNM@]P,׳YrՕDM|r'!Q5ZP|ݐ+.@q| _Z1jFthFZ,Vsz-@-S?S +8t"'{W3Zi-\x2uáGekѲ*, +k"S: +|z|x{4.lRx`)5nwn`XnzQ[SYP$X/{@L#!vDԾƷ#i!`}=!'} uaD{GAQa\5Qb"n{* +p-&{T7K$c91YY|~FT 1oFw +Ddpi$y'5YG2I7i^BAB+`ֈqk-~ukrAo F+nK +gpv4x7qX3bez_N?ʆЇ1ޞㅫ"vux#Sk6B2 )o1?PBa[w; +3a\oવ~]qz!58Ӊ O׈GSMc ŬfaoEEoZ3@xhӿVDudUD۵P>U+UwL)INEJZ+WhG>Ak.'oӔ }>bD2JQXKYG*QWNTŕg Ltl ۬BuҶ \ +(Ddeg:PNd +bbڛ ߉ oV0g;BW]W_4"ZW,Zu^{ k8WK`,VB2}4?$Ћl7̦-$j{ +:^#=*#J{ZLљкoeN{'R#zb\5-~ f{UtyL8?3 }[UZ[M[9ʁmjmk+B]["o4>+nC1ovB$c1btWg3F̮JiRDmkز=OAąN3 #S &Γ}D#ƷbW'L]Ia *k0.B-#2Z+E'{!+7dkOɃf |5z+oQ7=GۃYK,7)B֋ ?]~ @irkrBQEQI +y3ėk1I ac[5JN2 9rk Z/|VN@Roz (K[\':v~]U^lrҭaD> 84\s҂qgn,ܭjCդǡ'8D8Ѡ E3~[kyء!_?P M3y8֣r.p5 +hvlG3Z+To2'$Y豨Qz OmGt&l y  KC8'FrBE;Nj% +mHvY\F= 銊Z>ʈrV:#&)H+4Zg#D\% Z`1fM]Cg(~kF; qAndBO=*|@1g(8&9|W?wjLQ ˺9D;[b8綵cHKvP?C$C5csb7-,ɔ2#D&B;]jG[5:6(`[;rѶtsZs!2bZG>$kakjˋDO3B tFfyuKƴ +o +8"$f\q|Z^?h|Ǿۚ-LrqA:W gYT;\\Z9QL(E +HQb tN;Z1q®oB +y?=+9lo0F|=`I+ !ȟL'XhTaQa'PVGCUWqo5i1ztFhs q8K$FO5| F$-9H9@EXnTQ~z{r(N/}=&E3"O)o~4Џs$鱆Ɣ.` +w%*?'&GN g+ٿgDYcFw;-Μqs*:X.f(HoQ̓.~"*Sy"HY|)"Z~nbz%?ĒxjQ3Kj E;t vhR{Dn٥ +W-*?Cr(1j۩Yߩٝ<j]%*ބ{Z&^

 vYUPCXBRco17I2ݟ댈pPkSXɓ>N_={{oevowlEX#*HQx< +& "(DW&NDs-֥ƺNTM*1`rpR`Yp퉟 lV;uZjkxk-}f@D:.7wr4AbPKo'(\Jv$~.ɀ+ +vU ܈PI/۸L| '&r[ϱ*[s [K5 S51Fz[TPygQ%^&_bҙVO-YZ қP贘(b6Хh^ja5Sg0~n 1&+1#mj1^R,b@擄޶sNMDȴqm*e4>( +7Tg1S:uvF~+bF8Mi*{VuԱSh_xحbws=#/7J(t>Az8F5NIDroa +=rf͉(eC /^ > "AvѠf5 Jwz+V>S㈫V;]̕;ˤ69ȠWy=hPs>xƯ +2 [/%`6+1=bKzܲz,ߣE6Z)ݷ(NI +S@hk@Eib4ѺuxHx@`Q}4tpD#w#{nQU4e2="Fe̱S"j>qF+G(ꑂs|@tl?,XOIV!Pn}q[NZW*[ $KWt4j޹J=GFc?םv5Fmj(\1#".TL!cAyVFu^Y^H8RW '+ύV@ͯqTgdNUk؅סclx~u?^(~muhЃJzك2,^>4G[{J[ msϟphxJ6L.s-<[ӌH@.+bM!fu^u9"*k7ԅ~|ṟ@($<'dH]VHe~?a D Tw`8J, I{4FU۶iWEo%;Zۍ .U.3|M<ىgT|- =`c>Xzs.\Q"Nq!K{ AQo]b uY5**F=PӘA)mSKV〃"]W6yMrr(zץP\^.@})VMXT~g_qIDEA_q%pŸX,HNFW:i薾q><}"OՃ41.N?("^v}&sͶHS؊%.3y}qw j*RbJX#ndf+A3!|D~J*C7$OA@" +`ZQW'T ӶZZ +Ղq޴X7A898z8M >|{1_w_eXzg-'QG Vh.술@KJŬpB>=4BIv})#n)aEe1L6r&IX@f -}3% gn3Dc +]S$`$;1 ġ= ҂ qނ-r؋TJ!ye@"(`-FP@))En[Eb>O}(0cЕ62>66%hpoL `6C =#i3"IO(*Z#R){p3Ss*Qk arQ +6 0B$`512cɐRlv^BMN"GP9 +h~!ˀ#DY Ϊ^6QGh%ҠSӴFk ::U XհF$̼VMxѕ=uYPsq$ +\QSS,h(Havc%cW GygA^(u2D LD6"*Gjluݑ6R5bϰ,yy}EkHwYmLN2с" ++xWF5yYª Kѩ{,xo_5_nlzqXfu0ThȧvSSD^? RIo=$P|-O?6Co*WT€r9Gvr ZA'=jI9T•lp8fW0+,yKD }F>]!T9փm3*F䅮]̇Uaw9,{:S7J^$TGԆS%zТ&[f#C +rƗ}BF60R 2~7]oN%\C"B3빲/[ltIj"^JXoR6㾜2Tݐɕo.Xk1j~<` )SJzķM Qr^H| +gkIFX [fI|gNZ\8@'?+܂7#M MD0=@f|p#.{ bvMo9+9Ntqm( pMy^frDNRnEH^X؊m;wgL|Yj}NSGY7jXHs$O!F}> XIhk%FFuag#CZ O@vvG`9d?x29^" @Sf_=SN8L 'uF?![b]>*ʹֻ,55!fʯ~3~ԞM(\q A5lpBe Rl+t+ph]F*z-o@ n +InabdT7 +8jUT& I2VJNPŻ"7XިKڄ>[IG v@(j8?@!]^d: +l]hUI)LW+4l=* )Dr)K('aHUPj8Il( rOGa~=5#3P7E@e~eAF$B~uˆN^*yA-ztv4p~G籝ISf0R*\*$]HN?Zqq/Жc+yTDRʾ%խ$dȕc dk[*X9;؀]fՌXsBqH..kÚ%0eUOy +yijIYHz?% vJ/$7L~!l2>Qb8Qt1K|o=K$YJdH_:rq@*6|睺ūamtC ;@|_#d_L2'MAϊmfUUM+#aFɣ< .]Jet;?;zw~. ] G*+PGȱhE /`w!}ko 7飰6FĂF8Tz>+lE ͔|+$d#ӗ)g]yyTO V= )x`12 d7Ty/SA&OR +͌%P(@NKa/ik!s,ݣ` ͱ KJs#yy"_q" +H)ƈ5¹u'霯# e_Q͢#Ny3z!!6jԶ !‡ d@kFQハ[er|ZLG%L,YE=I"˷|wx{TZ3{0V ʑ}eO`F0{<ױb)5Axd=VG{CR@E ~Z׮k(=QDVypۥx)/6P;1FjvC0IA))3i&N@EאA\|?kMo>S_́6Z{z[PauiuѐVG%#vu9M(!L `lQe U{ufxlНoWsj^ f~gkӯ#zn5deY PȮeCNڄbu ]zU6g924JlzSs6c/ Gϥg,Fnr/>wj|b3%)[!! EUxbl%)` l]6YS+|< 3z%o!rT𘛭#hӮAGЃYd<: Ȼ1fxF9~%QVJ{J\F1 Cvni#W2#IDw]cבHi4ӼJӁamEb[IDEϩlH*F1r&=ǡLI_=ntfT\5Uh@Q%2@wį3P *,xぼ  C1`EzzhL0!ݦvEEFX@x'(ޛ_1B 4XlTR6M*0% +cKRyOPhs DI)4ٽ̪O3k#+/>"|'ΛHG1#`?6񶞊|wa-5[v}\A{.le/7WpeG*Z,m_?[v˓iegfTl 0$`;U\gxЎq:m$Vǎup_QCh`(@.Ps-_Ja;,#~DsOS^*ػ +FXIV|PD1pgD6R;E95!}g\,9mE>[,M4F!Y'$JjC8Pjc{k҇ccV{>UA[!A z rʈ/Sn2C}qra?BlQ@a>d'*M]kTȩhYxhtM!+(ּ[$?PN3H#o~ ԋ?)k5R?\s@{PW.Kml|Dmƹ)ò :LP9U rw 1HedruuLiT@R79Ȩɀ(MYtM':ViԊ&s= .guAZՅW~Xh ] +˗%`fv!wsL(=V+'W\i@ҰH 4{Z(""SyU:8ݺaǼU'17Ca' +g)puIH[i[i$޹"eOj-QVebL0FM On.K +/25ZN)Ї4<lPtԑ0B|̓*~k' +m">٤Y~p4'±nvQbћ$JeЧuB4HTW=Oף:#:rYXղ;Qa"=B`YX pϨﰎ1j y45-!L%F |kr- ML6_,63eʸ-ˮ%RJbdQ@p`P0WmWajor`JQ +JWbOT 5oc4I5PEЙ$ե.pߏ&(6&RJ*$=&#R% Yo$qso 5qg^ՕT,YļkH?c遺MXe䐪/taG;rF}|"\c=7B9r Q=!@%". +C| UlKnZ۪uNUC15d/4SV'W*}n?3ȵa,X?pi-NuJQc]|MqDnKP,dzԎPVDtג#PmZrU=gqV"Bx"֙V :H#l9O s£YfK:8K.8zjym o%A +sz:L9)`ȊHȞɂT⊕* dzs!i O0[e"AYJ=6k mȐ8Eě|c\2Ae QQ.]Nz\@вb1 }bQkGj7]!Y8X64Epg$t$Ga-:ZIV$4'HĔKpkVm'HQa ^xpi2PaOű}Zٺ8ell= 76~q +#F +pcC^J9װŽW¼\^ +E=7ԭnV)Xad2[5Hn[o9jlTKN5NEY& G郙pEe*'~Pխ5پy`[4Z"^RyvCɨ釺zb)B* ;~T>_E=[1f,X9ATtP,ӑދ#JRs>vcJ+P=Nga, +s` $x=<400&D,+һ+D 9{`(2F/_B3TM/}Lԕ?2\ۺ"0냢sk׺S?Mt#ZDA +8@h9DJ܋bs+`][L4nqyic](C( 6+0a$Ob[݆'{oސ09]9 PuƵ#?ƍ}݃Ԟ>{݋֣8>UDùnXRs|JC&xQ !|%3oT +`} k Bh!2UQAuj;voh +sT99 `uUh$w1aUݛ6*iU۱AmE,?#NxO{qoխC)|S&;Y0^[}H1*T.RM&fwR|K&.p[!zE5Qsn>(Z/&#ЋrNWD%p+ذgr>9ZR=v &nj[8`GJeX֬!)kTz(W8`s-Q%#˥5SH/9ӎz lV\E@xBKm[*tVs=u}&u1[}o@\v)W{͹hiGz39Nbr]/3~ZJ_Iґ钶VTUr9N,m6 ;LDQE]1H˴:>X]J`~T3>5Yz烹W[Oǫ6l=c^NBt DTuHXH(f7)sFs{XfnSh[E>GyEE!ۀˊRl2u'SO35vǔ=<"H#ЊgGɐ3+8$#VYS[㱵@WS,(L?2C$:#$C-䔀1xؐ4ŴdkQĔ$zjYS)6J$ej[%)pCAC9H&HuTQfuU;n,aº4xF3]F4+و#z87Gw_:ܢ.e1Z@[is+_:=&gh5 +BO7E"PU~[58~vS s;(+ӷ)̪ZǷ\Pv=y: R֛tyn[a*? 7֝>?Ii!}y\MaSAcK +if`jۨ=mFoᰫ:TBM^k2!/gy2wAtKfv8Ref͛֓`ip^9&D+Q$<[>4D j(q+X11a8 +SRVuHPglh KD +Oa9xTJ>b(C_9_Ճij:k>,鶡3Bwf?xȩêdP m(~V8w@X˭9w!ma9,Nݨ@3". pghM)ɘ@ z`Ϫ@χp:puKD;+KDRG - ź[yM3#n?r 42 ©f# ?{(/RQ/)Kն=A6 +(poq竅ecc*Cgk;eXv%e(Q L3sѻ*:_]rމDH?_5zr<@⤊GGqŃ Xɮ sQ!fE;eOD_&KS#؄+#Dm4=%;+_BΉ@Ãn۫bM`n0PŁ`TE +%gjWDlFtPӦ|Dh}`> 8K5uAFgTOYNxQk(qR+"֚|J/|)6b VLP~|C|p +԰9pA!"qGiZS^,T +A|.:ےe R3IF:c԰b `;ڟ4F3bRڨq4G"S [ =_7fR 䒥;őH-&KFoAxAʌ vҹMxaN vtVtɌTpޡAG-#hE PDS%r,p1=k ,`B0oRL8 nkjqA#+vϛZ 4y<5lܑ1y0P.1BS?Y´q̽D\(aA{r닇U;DSB/$#EXVa!=FPd)a؞*9{ư#H._FԀ'5Ze)&;y! :"ѐX.#u5CfX*U#>_ۏievzPA@ S + Ew +Q5u~,3!{(S[ 9VG2h1;=mk*~!|Dިi2 8R4 +Q9=v%?7P4jżig?$FC佂+b~79F6*OS)2{9,t^w5#Ƚ\/RW/ + P~8,-a&',C_Rvk 7iFg'OtEZ7l NdžY-/I4IB/@J5JRE{N5 K<R<6#Yl3"VsXff?)chh+FbyzR(F 1n$ytчMR'BL#FtC -hmTU9v4< ?b'EE8\zc%7e3C~I'n@ +clӆKMKܐ6&j1\;eR zsC +1٨;@I%XU+m0/QuKiÄpSЙk=ÓRNT7)^R@$ucؕ<(ob˛trkXW\&@ cS; +(/Sz]HmvKήj(Б:?Qa]\?7⛭O<}+`ˏrh>3 C 17[dAI,?ik D(MqT;-Œ yέ +8gWOUVE:n+.Q!厑bWbq~wk3bӕS;{>W8(͸Dk:V+PԅZ7S;z2{d7쾟"|)¢c%a[VAh1`݃gHNur@e|Ek.=Hg,"b1$ÿ̈60=VP7no6h^|D% +Qx­ɢO>Gfq51 B"(P!50r;Ki9Y| t#?6NcRsJ+!ᮗ}R_EPҍ"+J +ˡzX .~#BElg=wݝ׽Q_M 31kp+V@=jI$naTqd|+{52@Ӳ9s"EQ W*@2&j:b{L/H#:W>> pTV:} nGCyEסnf%>:e'H#ЩHŴd@RF\.7Qt:*8谣 (ݏh`t; ])Csߥ6>R`..z0dhk"p#[Hcwi="޿p +kƁ¿u46lA#jJb6@dJ'>:ڼ-*2A_;uϯtׂ|J?2Yuí67mBO*(콱Φ@+O?~@}U₏cy'L΢c=1=i%Y&Eϯeq6z/ԏӚ2d[pc@,pw5 r#$y -zzvTu\A5Qg˹n~2Su}y-}zuv&<Öx@h7M{/cODt4}5JP{*a~Huz.o7P١i;7-vi9٩|vRj:dEj?GHyۺ!C.b0~b$*)%nrQylgm"W-1 Ult(Y?ul5Wjb߁4uK_6i}m_4ңW9O5'LNSI v˅BSA9V7W#"=_D"NrY3p@|,]Io"'T4K JpD8GkE,eG'܈8IIF6Ј`Wtx +A#`c#: "I &Aqr%*{Ɂ03<2 ^LWok_πw@-Q]eΠˢ9, wSO-T4>I#oV$bZʸ?#r@troC75'ڜQPsq7;$S٣[B: +;(mщ;Pԧ.!o'ϧj 8]Uu{Ԍ劒rܼ}3fe} žChny}HKvRRsSQ%lTΐyFy+W]| cPf1cNS +i 07mX E <7:ŰڂYԘ8qE@ڥ=tkZ\p?Xt=.³(5uk/>ة .DƮ=MCWN#CxZ$K~֟Bj t(Z6<TZ4o/!DA.|ckk8d7dn4" ++Ev w6HqH6dƴdχ9nly7δ8i+P+{EXm)ڱ<N_qC"({zwuc +P؆v"ũ +R(TmA:/o6pYlO<\*>&Bmo۷@! B4+Y Op JL̋g#>f#3H||)Sebv^>S2,ԧx +ꛈo'(5wi=Fg62m{lZZiMnzO{BۖCFo1%vgЇbVi*gdЯfc(`!`ԊmDEA[NQ)+Z漛[5/峬tq=z=5؝a;О p8T(Ci^Y FHxͮɉ u8⎡ԜCu/sݺ*a ̋ -ĊJ K)ҝu{(S/sqS_o}8elY0l&'kR-1ua3iAk+#T5dBaVב q ձ;;xI-IX{ Rw~5"ʦh]^zRR:]9nwz+p +,-L?޵ٚ<K(W'DqPVlR.@PQ0e +j:X>m CDʫH3s]Mu?/a r NL.INtgȟBOX4!]hAxr%pr rvKR/GuQӡu<*"?P;hۈN&0R.A}j1*܀N?FER&_2 d_O@4Ya:z:c:~3Q 6B8R\z(I=$Y3R +40x#mt UIrX΢<׫J> 9 ]6i8.V!|lԷ6=u?Wxa7ZINV*r3forIGa:, (ov7G%t::&A:L VL`E5"3;㛢XЊ ֯/RK YO)G~ +`fsB)p `Ogx-&eu-('t5Zy< mtG\𛮸CB NE".ZJIo@1cV4]؃0'.޼U#6@ݡyi,DE:)dH2Iվ n`E6;iPm[m.j#iw;@zK{0'+l=?'%f>'aF +07JC=,uT_UkFpB*xHI!J];jяySU#ā &:Dg&Wce͗!OZE!)/h4H +ݓ0~d&*6.ƚ*fc>Ec:p*;Qtوa>Z626D"iSp,M\u_>_7 vdP(tjDc͈v(>8E!dt}6P@$͂c +lAjLA`{Eq|p!EdN>cE0jqۑ FqۂȗQҮ,ٵ+)dQ+B|SD]S +YжcxYat5]39{4/i:?d4Ǩѱ`)ed`Z" +6HMEga rDO. +'&*qh;l6:ׂ3 +- Hu:@_0&c+_OƂW +j @6CQFѐa*g"8 hc0CCW4 rlDOi8M%<隞 7QL]SUp{~QSp(oۏY51&uFUppQJcZi߲ `u|xĽ +WnY"P9Mh@`ax o+A/?=/lu ^wFm9ye: խ@d +< Nhx1BnqL<;Ƅ!t6 k6/CIpJVX\Pe9[@Fg:G0q@QӎG{nɒtx0< iEo!*ͯe}'lecܰY6]iG"U I,(tFaubi :Ij8 %`_V6 '_*ֳ@E_ic޺z3 :'%n6p9!!Ւh^ڹ8jM CIRrU$/ԭI.p%1210D}<|jg4ЮJT^fߌQxTXMmUؤ׸qQ(VTш$RT< bBaNu̝jh/ʩ66$h ɮh=Ye&"Pc^(Ra.{-ـ]Y}J"E$~aMIӈTwTҩP+RӥQȴҥvzY~8?ާL' +D67AWHI-K!&>ɤ ߼& )ӷ W% _@µõO5- 2 Pr? K\50y+x>]֛< ST!6.B{h>U!;Fی:XGf(\ٿ}|ˆd*M9d@,ڊ=՚LPb46mycnԉMv$h# `6RKyN=x=r_"S? PVOk$׽KڸzQ$6r"`c]1K"Ô\-'lDf(Py }}a",SW&Y</$Idׄ]ȢlFЎ&cCFPTÈh \~a-%oer  ԈD $AuLnNa^ԝ.YeBE$'7Q ;އ ROaMY΂>xHXgAm2V$Na#|Bb;_kˢ7`ǼEW6MB6(}r!NC\gA7#FZ-[{ ]i9m/A}d r8 Boqtݵ4 C;`">Xs&d"ȴ M=!LqFVB9H΃W]Jv"=Cvgx$y8TB>\9Q(9Aa I> #ld/&Ǡ3cH +<;Z~*:R)u]/< Pr~Z*5Bؠ24ߤf gd WJDq*5Zp$.O\3[G_~ķM3y}`f}.?uN!ۖz[cuSh^ O4a%eTr ~L*^rgHk +NgCm0F&a-ʀ>IImz=]1\<Cwx +F*)*Rht7!|ĄDŽ!@UA_"* +XOM`2Lp81P,aMG]V2*;qw`SG>us!2ɷS)!2O`1U\^dPhK{w1c,'zշSݝ $tmS23tz{$`B)]V=lҞӡp]`p0s1r%Į*>P\'̢'߈;!&Ki]P6KvC^DU8:aշ9h-)=NudÛHsRFR"Pl4\W/YRn+hX39N=%-9CB}l0)&iDSI}t N#rX1%RxDHtItQI!WE治 N Y`B_^J*'ﰓP. B 7}=,S, Azކ#yYݐ,k~3-mM?!ج&#WJ>$Qdz69uȒӁy 3dmp bV$c*k'Y9~Z%< "?H9 q1YVy񙖎eui6,P`zE-L`Ƀ{0#cϡxI +3Ƞy(Ztt7?(dN_\hBi QyIhC T"VhBT $/JiC.4V~)H +'^s=9FYR Gzdr$}Y)zMo:۱[B1N–sxd-oIp(":t=EK,Ib_ eղ꧓>.ƫMEAswM1'8 (\fzM),p3`I5N(vg1hPc4.G9yKiVpXo t\ +~H\`D '7db!U(@~53,֎.옏t>z2,l%gѴL: L.^\:X>٣ƞ/٦Խ{!?ݬ],ީyхHg%?bOĞK~l$uX@D +E6HIhPo&!(C ϑ</Y%QNCƟH yʼnu^xЬu_s] +Qҭl>{6/p@ķ:xFx% e4f:v~7*Bl70髺$, ?:B'[qoK? Ju?'ȢGL3*03` (i@R{~|] Uf90O#$ !͎(_W{4ӈTFz}OEfW]~Od*E F$U "i3/[rƹ0!*E!0Eސ9@~\$%)CI!̒ +ýs>BAM2`*(v'^t0v|$QW|zX*(MeO +="SH%(p@j iW+.+eL 4FAWĈ!Kdڎ^(L+gI#{BV}Ձ0݂iP"E/(| 0 GQl6 &ҿI-6-4Ѽ$"!V6 +-*BʻQlJŁqUAn"o**T|! DPx z  }NCdb'~[ =%r>p30-iƫ2- ]n)s^~C|8w[DN6bd: z,uFj:s0"ekԿŃPKUZf`T-YHrUJ]ZX#7nWHa-5"xOU1}3, oыW/m%dMZALvByz&geQ,kNf( ZkR\ + T x B0J\1'Sk{D'BYOA=dƯX Yy6W?PsNv:}fՖUjq'Jg9%!h%?Ի5-QPZtU98R$NrSUNvFaTr|̪]M0:>! XLſi`*(@,",]YQc+:`i٨7zUmؿA`J=.Dvz0Gk5 +,HA8ۈL Gd+nPGgsT ]6!Py9q}/WjdA +6 uCE+ ,9=eT&"`W{iZ| n%4R7}S,~O&~ ==,. 9FT>=w "z~ʨLk?UpUp*aAx^&m +)kXjl7}\ %Hˌ͍f5BԹK*\_ 8\ CNOip@ !raX^Ԅ@d\ISۡiWP"(R.;8 ~YGvZn B-8WPj5uBdd6CO[8DQ9(ў]3katzk'm?M[#5I|U5i4> ?qBtiK=X] b5t=J(SS)h##pFX"Ɣ1 2Dl CJv#'ܧeg#sqNy«Cufyb@u4ۻ5ONO3ŠA| 7T^ԬL^ߌAZPP^#:T)Tt@^$LdrkQDrPmI+":|J[ͦ.:BBoX@I1tE(}F:,P݁UȊPXbY+pqY@{DɌw qM[q> +~Rf3a9v]ԊU< +j "S,޻H/birBBH__@)޿X)3"΄(JR|hԱEa<>C$fq pƮ:B_ /^7 +;mi㡹InFpy|>hӦ+IXm^`K$B$&??BĎdMTp@A(cLA؜n'3r +2"UP `V Jpr]F(9 5Ʌ7g8. + +HS4K 뇅|: FPځ4{x-p**Sij4@75/:rQE6tC,@ќ>ȟaMch SaD#&ɹ8g4yL)Fwruһ ĥ-la-0)SMH$xi^gc%O;TN \ ={4bZXmX(=(˷u81 %& #*Sߐ5Sd9@P͝/L/{]$ڴqɮ*kqb02JקIF̫A&Nhtm'jRbKS?qonaoYMkx̮ +pDX ++a= RHSCFUuoÐ[vt|9x3K{DNo"YX &FoS2Zu`"@DF`mP]VCnSh'li{l +q6QFI@T< ABRBT UL f+mh}R\INҐH"J`=|o^`^MR/­or8 Z](3pDT8l{uAllDcHJU8m%ݱ8%Xj`,9I .(#U0=5tiiaHOiu{6sJUgn< pclF `!N +jXGYg7c$a \ *r!@C8ev.2d*fBYEōE]O 6~-HHoar f@ƨ"ûAvd:Toq'CF 2V~$UI9e(GQUTy8|qM#T-諒[& oPge!`IQ%4""cl 85 +Mkׇu;ִ Tu*[fѳ8_\,LUyQ su0@uIVCU#>ǝ%Y jwlxH3H) +׋|`:zjOi,#= <(Iyz;iy\sE`ȓԝmق-QlaATjrp{C܍@!XgY#d(@gUKGݲFUk)# HңfD)#,[^N(B"j`96wEWy[,:}ws|UBcwX%/a5{rI}U #q; `U +EfUY*@N)Qh47e6ԣZMV1pDD B'] +l7 {]&apE,>^Iƺ5/5St ++J lN͚,|7 cm̎)+x4NMeS)ID;)ܸ?p1٬jWcD|B7e!pWXO <0!c7YEAc&&4 +1c.'T&*Gr_0F4j4"FЦ)Ay ]NMC[KBɷ::H"ЂI?fz(p[6q?0s 6yefyB7̘nJK1z۔7;$Ey:>i >|޻B@}cJDk5;p Rڛ*ؽ"StoZA!zac?Dp8R3pjbl"V Nk"V"ȺAzHHAq7x!Se`Y)pq,瀷m5v^2#)CTW9I$8('&ȌlG @1H?)> NK r ! +">@?)Dv<$P.:g/g)J0r;jS%;H֚DfD0:HmHЧ8V!yHvxi~=&+YD bVMAU?ER*/TSD ;Hc +\Zm: ʇcJ8Su_ڽ5[CW F;Ʌ2>]^)1'8Hw߳!p kǁӡBI ;DSqQ"[%- ?_7n> +&JC;y*ң,zV{CAxBq?0nT[/pq*[D}$Pck98IP}TNg٘:.(cy'5JC׊tyR4 7]j>|_l&G๥+$&R.趑yN= !)*)*)}.ƣ3Eؑgzs!Y20t.7Y=K)#.p;HVtP w'oQ|Dp; l&u!& +Z5]iXs]%$b'aH|>O'R|D)4c 9ѡn(SQWT6_n,a .QlhZYMvȋ;D@Zq;Ҩ%MP=o$PReL&."WT14^NnO+3_cĮÖ4[wpط*5~/g)el?&Qe"vۈe{U*Dq3Fh!9sAr2WS-Jp[A*4 gSTvw%R=&V(PGn=_ƣX*"D$UvlߍzG|\\4̠ODlR23Nc> SM872|DA˂A^H}8]Kηǀ$>-P1-SH .Etk ڿCjVw4)zȨ׊D E߇!6L^[VqQFm&&h_'SE!Vק(x:%AQQdKnձ<taPF/PRȊ5lfJ Sk@X0!f + ᨎ<GZM[Ih|bbǻӘv\ t +#.";RTHIG#ߍ|r4jw(pqրAq`\bd,FӎQF; +>TT =Cxl.6ظ; +^*^/,v' ivG9q*f8(]Ń, D22B%V5EL2ɓ+.7똢ũ~iU\7#/zva=NURq͗$Y v^樢Q5 RVzrI$U-дee":wAXJAµoŦzw0JkS_DupKdwr *_ADf겭 itNDҷ)xƵME} +A"ʟw O +f%T r@:C.30[q*Xk0e?!xy^Q&2(  Q(E|t +=V\QCBHL|C &ȩ\!d{{@s3eGт'B|Suhp"Nˏkb LxhnSQJ>]SF$ Lp\ޠ6=Όa'BFTTݨ-ȝϗ77 2$$t4BsS>"3 +ф50< o_2N9@=MH9],AbD_8TG`lEJV=]mDȊ +j*i uCh2F*)7w ?! v(> +TL@U$:rP(T9AˈKA $|S|ïӹNGO^RjFi_ +%pq^$&Hz +}_Z^w$B%%m>#D*ܢ"Kyka>§P>' Ǯ96ԇ -BtpC-ӎx:8ߙ +@ H80_ =}xrGcI@1n;+*uΙa:4`!9I"4a&wa,*1Is6Pe,bh"bU|ߩˆNSQ6$N,T]a $,S!N(&G%V#I+,3"7_' ѥ(]ŢAӸtolP;d93|L8{%ov nQ6zEF׻>Crx:"ooᛯ{`y_پ3욾ѿnc\Z{7wO??I_o_緟~om-OnU~T9pR\XMp€b??d!;<ϖR\B}nރ~ŗ-&> ~߿َd}2{lұ+T(jhDf:?qR VF'JR *r@-p/rt|> zDI2x-MNF jY# +:/m".?6IoޑTC`&ˠ%m1۽J5Ze6*' qp%4i9,\ VY:o޵;u h@ +ke^ԍ +W5[09''*%R=*JNƧ00JuMSjݗ\z_ bب[.bhz- 㞴)z`I6m|Q!n천. ڵaJܬ1is[Yb%r 3S?:&wԨhB9@ +NO2 +޼$O ycUށMGU(*X]Lu=+r<c 4d_)cd`o%=; V'G!'(Ԝr-' +<%^Rr +%@->bOLU$(a G1p#8HuC\:y!7/",*SBmˏ8=au/TWXhI^ۙ%ϔmDWzKF0;b$.d3{QVLqOXQ es_w|2vTD1>Ё-̰?Ӕ&q*gRJu( 6 ,4$(R%' |[d5U;A 蟲|TcY>Y-pzo뎤n(Kܣmd} ,*?}[pf! V0z{U-:0@I O20"W`\D )\Pb_!+繣( SqHaٱ9jP*~GRz +b@`\xHb+9:b-A+UUt=ŪH_/7B rPdт i(h`7.S0JʳD8z '4WC_-Z#P nAd^U^+tNMqVuC !J$hn28tXUPYIU#z/`wwZfd˺ :̢0K +!Fs`-[Ͽ͸TfEG}ÔDǮpRvSl|d!N_Ib\Y !mr IԓT0kxv!sŏSH2n{ǔn f&rjhI)\c!OLnC=:Ԣ%Gh%/8R`&1UBs1̺`6|0txQ7!9+R\z.ׁ$@]^YPrx;9^8(R0q5Q`0@"^5^hX?βے hKЬngv^^3KfC_*f*TQV(m.p.d^*z +-@,l㾱=ڸ_:0~-}H^QowNz 5zz, +@ʓ|E@cga>&> e:N$<$(:iRUdEtI,zuѷ} ܁:n?ߢ$<lcp +GNg>W5wn 6ܖ m!ů1NOFHj+Ɋ`ҡ;]fwSmR, +5ǐhSdVG%!8XE⌼j@K"/7 /cmwB"@f$}sCc`ra2tQT< U44I/D'%<7XgXg29`fm!98p۫!#HH2E,l}bV/yv+fpٓLJĕR\hDЅk SH/+2 qLŋ#%2uGy4X 2K_iӯ[ +u=ו.%zڷe?V۶CАHqu}y+ xٕy7A=kDME \Y +K +w +VEwexs{w-3 (i7@[bZz{A^,HSn Rh&ȮR +3P(A ejxFQ;ͶLpn=Mn"8\R3[Ɇi{%Eqem&2%Jڧ+_\Bө1?Z$?5pS^#sy(o*h2|yo[J3&{Fr/ ~wId>Ti2  ۚsJXdlr,lj8:kQ]S #LwNz?7)&@Y@ @=>!ҜmvJ:ޡ;dUC\g'h3\so)n3BH4NPKB/=0p8Mf<8ͨuv6pOSSk(.>|RnJ +gIR鈨)Y+*x|dEkAǔZAbyR?BBN,R$eACqlz%PvqzD5TqKME->h/4TjnU1R況r~vEϵ0N&b婝AR F0يtRe)T֒x"\zBY .*_jp\SnkW%ksR|_K>\ާYj]JKї6pT:ķ4V502 +fgPmxdD^h- ШY'+q4 jlo{y՞ &@GX_^%[1safpY0 9n]0MS)9ѷGY,sGiޟ{7 Qe0~ [Ow G}vc~s;I d6)f3vN2Gwt[Ge+vrrkvڰeeZ.O[{[~T&:5zo+ 96DXuo@;X7 xwpuߐ[EnÐ g32 r?m -3#@7߆ȉ E3`H[;]ւb{" -ulP-PZ[.ns #Fl˯wy>jI&nKWm +ے CF7{nT7~! v]-љ8Ɇ-lҭOr^}*"mH׭d2ֆmݭ{m>gAq4ߕ#7@,fn +:׷Eb'{+nj(7S {Co 07m1~o% ??඙|mJl̄n$/b܊5s4Z"sHF<_TXU_zZmq{tD=7hOV󗷷amYsm} =>OsmsmM &3`{7&HaV|)T\ԞW5`4#J(l2 F,o)"Mh%`Ы+Fd]FDqw.' ]=(.!p`T?`T>bp+=dZIf]G]v έ<_d;F _k#^£ 5EQYuqb,V6qS"'Q7mPsrqۈţQWqHn'6HvF`0H%5kRKT?<ܯcgˋES$ KǖɁ+G‹C!:h>Q.LTX|fUf츆l/ |&zfzy?+X_-γuz~[?J/r0bU =ݼT@2߳ηqu_޾q WC ߳]ν/Ő LQ&rz렊DTIz,rpJ"ʨpfWӦX14 Q]}^ +9A|:x`@ecML5v +}`;qQe dQkJRƏa92a X{WlT`Vh!8=D}G%s=P'3$MH"+e1RՇBufO c\4^ v*ڰHݕq3!TJǶI^=:UY K c:߸Es8tj%n,#d ;2&Mdt zl *{Zݔ!,X ?wOQE <Hme`@jO]޲=?ތ_KL)yV d0Jߣ͟kɛv Nꯓ>Ne #?.C>-S~zVX`K뽟}]e8%{G7QRв=f]$o/n[l߶-e f}Fu7 oM}MȷM|}?8`}}aѼHʓOz1$@A!^9SfKn9mHi:lF:O*7u!n^n~M B` UI@/Fb&y&CpGޣթ +\%DZy +7K;xvT +pŨ^łcPd&̡Ĉvn^j# #֫lΈ_BH峀!C> AaOTfV{E!mÈӚHr:AX +  pRy~ +*۝4{ TE0KSE7ʹv7!OJ6)B_a51Ft 97u/t8 x1*sk1e'nS<4G ?-&Dε )O~Ț79ۉ~5 >B|v 'P0DR:qW~(iL#D?@@֦V{hb w7hmO/>zjC[mh[~#}싀W-du?k,p>6G;W?HQb`7-'Jٽ=2'3mgPpme{mȮ KhZP-8T4. ТTn<0&TVG;<HVr endstream endobj 79 0 obj <>stream +o,OdyyP1viՠ>cAJlL{4[/A@=ye#j{j1Tr~"TT/.5f(P%>΢%Ӣ-Qoar˨lEa$? xL+J„zw#۲o;&"`m`K6[~g(1blzqosnVnbygDPlϒ6QP%` +9Q$KO͇v'MbY[*Ty9`a =m _%IV_] 4\+V爅IRc/Z_'!~Lrv30;6-AdҖ&!O~?`+lDeDOg}IkYߴYWkSּao6_n:ovXplE~Iȓ A$lO;qmbtAɜ.M)uFJ"}(3ӷ]OW>XsӶ hɎݤ|MABF6 +3NZ]O[= 09IPz3HvD{l~& +LN-~1]e#p0sX½|vGfj%.M(-]>B2zR͎v5ʑM qfs^KHb[*h`e{v.7y]5;;EŽώe,X XSճ%b|Wexh# oCE;96ޫA尗L-uJ`}}@OKE I=]" pL~طzSO `jcX; +IE;RPѶE(ࠢk͹KFۦXF5=4}h;#;Di *nLJZ|XCK厘1iGn眠nEK,+K Dj'b W.ڌe=w\9Ԑ;޿,{CKkUT]tZA|ge[*Nnk*EtKALwz"?Bj#VUjyuwˁ˺tGT7-}ݝ5~wKݟ\Ä(f;D^=v SٳiX +'xCdovfX@Ža.KmW,;+.; ܏a.Z+Ya0tlWmsA؜uf6,VS+9P{(,s B$e&`}g[wœ-* AS;|"{HSSoez\ DYOz8Kz|hYr2#8C{;𬡽9>{j3רGnӈyCBiܡ>FWֺȆ`6$$$I3D"l(#]lFW\imUDgjIuOXcOcѨM%EI?"V[ʖ*O'A9 Ђ Pq=z&6.v/[5n^U{= / "Af0&%F?kZ^b3r) +1~: Q|_㭫\ёz݈C7THO + +u?\. ؠ2`!ɈQ=>f0ј~6bdgX :]/ *ܠBt5@&7ZvS}Lx'`w\#0)`:U䤄ܮ fsSDAꋷuYLali}]uJf|,vtEv4vj-Ϲ{5-.ി숧$3(A Nlk#4]cr P(D6xƜo둃3!!#mSX%o0?$_#Q>ÞB%H ϸ^T^¶i찺Fc䅄%c}j]Oݿ?Ǵ+\:FP+Aۥ1y3epǧ@uPܭBM?C>Kψ)> Xʚ+?2o"  @t:~z[`;\ bvǛQ:3s# a13SZUafd\MzB18U2ۥ__= .ܻPV%F.H+e zvمp4]UP_JXfy~VPb]Tb+XPffn#\[N_RIt#yG\:AVjh(0]ԯ=HXtcwBw\N (mѼ9^mװ]2ϷY̫s*}~/ɸ5ɼjnGcGF#c.*5y<]m57>"Wo&5_Mk^ׇ"\ +v nJ5f0kѦ}6֭4_v^lc5+&7ccQ?q77)77U{oߪ$)}p{`7mKI +D0,$m[V~+^m5Uحm[ nU_ xw[oˆ1Zq5ꕛ'Vv[a+n^ +{vcG:w Ruiv%ۈ_ZZ)-]!/m}z-iu8ɺF6Vn_-ykCgy~tc>kһ_׶mMmznwKֱٷExUmǙȱCm˻}mz/]wԭ _uޚvo[z'[6:[D5G6oîMm[Fy.bC\1Eؠ { yQEc 7؏Ta)IrSmd{&V=mKָͱm{fܝo'o/ l/co_-`wc%0byomb)Ağ^iݢJVB!-)tLZ4ଡ଼ٳH$:*bw$E{jQJ®, #WhIruS딦%MotV4ἪcHK<k>s`I-˖nkwO㶧$*]@v,>|3뒜m~aiuo=*L{ybR "0ZovFmOsGtk6n%< CDlN[p$R|h&޿x7N~#V^~ޟ OUzQwb\Eɽ +kƝ@Y_Rw'b#ڲme}6sa&nc[[ogٶFou_0kZBYCik{#boNWa&78䎣Z=/8M=82N$m.I +9G1V +9?ޘ#U4,!7͑ <~{/o\JF^\ +SKRTП7.IDltKR'XQo\-:5 jfęMb&& mnAr0;7$`T%v$!Q~NEO;[8wR'eIRK%#)|V=I ;v3N?N@lwXV}'i@(sx:I},.@.ÿ:G@CjQ'w-g~,wo?ӟͯ ôߛL#.Sbl5bD r4iY@Vh́*`XSH=5"nbb" vBb/_& +qE=ݕ&}3 /匵n-V4pvbvN,lbiaVHqM%u ygYq)]kbbe\QC.0oT?(ڠ}Jv#~Pl?7!6Vc1EZl0, (e%]`FrȗKi'@ fu'AUEq۽[a$FC#BIR~ 2Do/ +aϟͩI$UϟD8ҍ +hKQ|?Mf*ɲt$QB9cʄU!&< FJiT -p +vl-ۻuAwP&# #D#{`jRr`Cn {(lgu5'۝?pAՊ `#x/MkN{h*k#T)#/uK@׺VGJ: V[b&V\ӴhGxu9TSj3E`2%]{Ăl:Sh2|[Ot'R qZF%g'zlF>nM [g +W:6$7p7{-@HC~ [|E3B"i'΁`c(6^ h(-v+ȝZ5p]>}5chNs(] Ji[`n&)8QJSBm%v*aS}̘9 L{y,p4@!M]C񒇱Ii>Ej{jcsU0?G=IAG#f>Zw-6ٶ4gwfs`?a[`DqFsN 1sIF7`鿘4ٷouRS) 6bF(9 b$fmٺƊq}B\uHD鷻@R3 'WfF~2g o]6L6xLxٶ7]%)h^c‰s\іG}|"} 7w-S:05aQ\df:?žlMK;(|g1H֙OTljc)ԀY +򬽝K=:nl"9gܡZiNg]v\Y&5SYD밑99;W`Mm[1ʪ1v X~Pc`_VTԊ搛DUvO0:ƅ&S8(-b&p=prm !Pa84Cq4/MYBbw500 %ڛܛ +&[oidLׁ.t8svZ*Z&(m65<@BRfH<$jQwhͩϣm;iz逽 lYU}eqۊҗOH3u9u/2l_PsmObO {^PUhN0 LW ޅe%gGx&*\L VXɂN!"8p>n3)ˊQK[Gi*06*%ҁ"%~@؋<&-$O;.ce]⃤n^*C@J %ݕuy/e^MOYU!U}(Ql#(=I3\Ўn0I=21#i{b&כP[dy Q?.\MBF3}G' A9ٮ`%4!.SXj(M +FKr`)CW>Ce.`lcxIFY0udЩiU{ :< +wx\96x%=DSyU-M+"|M y02De EQXh0="R*X.BH5faW;ݣг#޵0iJ 1˰iKuor[ۓLVdAI] QZApnHuj%e\BM#PvIXn!4ٵx?h͢=owQS)6;z7hLEGӋLo q5 ڵNƔ#_^NGj9㤍itڈLVpES +`M6rFDGKֽ(&2$c㍮jU*.)M*LRY +Tm5Vd'uD(E_ ڌo<0CO?jEt[j&v0M-*{9q!{Vwل~[dXM @ؘ,7M(d:C蓝lwPPD˟`"<G)ъk8^0h :A EIb%FΪ +O|Ltmց-9. og5}ǝP4FvY!.bX +|9V49`.ziQп:8`x/8n|jtOt@ݺQ2.$ pLNL;;v~`k'R]CBX#H|Og7mڨ1UZ)Zpl +!( +6J'tAz nGt3M<ẼAȊ̽i`h&b_!RVA[Itv74gȞ~'Zp>]6@Bѷ Q{2 qSLN7}b6ba_7:JI]> =uzNKܲV_g$`M #Om @*QJL/36.,@TwW7&Cg%CB +cw}tK,$7N8\LIwqG +@ru%EvJI;]S5ݬ:^@q~v۫Bq)[Dcf`TYMG8-l +:`7B}_>Tbݔ +oOO%dE#(m=Wu0 mα:wis^!pLAb9piMOOqa>v^ۆ6_'/}#4+젛bE-ܮha[};HJ6Y|tVQAJDŀU}V4gsiQNVPr4wRU{FH ʼRp챫=`(XU`f&#b#aw_0d[M!db97 & eQ f1a"ݨkZp!ș -$Wv5&mXҊQN(7Jݦq:69XzbAq6%mcS,RPkTI V]IT* Ƙ A MQk15{zqY*PMq)>7=ɴGVJ3oN| ^X +7nx>Pa +zҟ@޻/w~Ԫ";a(uZ+ApⱵU6wH3\pp +}-6V{y[$HgШ,ab +Ң+/j*x|9%MkȧRQ6ߨp6Glwh'1T||pjOp 5,;JaVIi8[Q*yE@S؇7"T  +P[] YA݆bAbՂ5k[C$Ծf[(TݽB^B_B& u%, fWIPC`ϢiBҭ +RZjcO(]]PxΛw^,4ZK:6J;zs➇/@COYkC"oB^O%?\BA6tB(a5a + k0+4GpXhFBFʅً#a; л(C 6ZiB4tPgƟ۝Bk,8tmCʡI)D>R yh +а5kb!YZB!4m9#:B$tmS//dnb󉽄Qvg̖Ɗ=XߒYtb2}b݂A#~ͩ o!-w!!aC6g +ۀ"I_^ӌz3Qd+}{'&=ZfW"Leܧmܘq=y2 4ښ8T +Vm9k9~˚#Ym'dMy] &^SqJn[+† a߿-~f-'o|70Y):lfB=8uRl0ILx8q/qFemUmA jEe9yϯS+ek_oqVG|(;| ωt]S0F]8um.!;.S@l`,)]?UX ~.^`G(x|w37;NkO;/3K-GڤvD#LO,6CS|9$ob|~r$,EnPI8C}^#\{6B.@A wDT=ycy >+P1g6~8qoDBUEmg}=U˶π(?hd@$[?ϗ{~P0HK}mdZ&@(t;)aRw|0idm̓ﱔdR 5A䬊"?ӹpEZ*DҶh%1IbɄW;.|zt+Et1T4Ej8wV=]uZ>gj :2qƪq(fSt`1zC|Oin)aoGCuxҰ9lP +px9%):sIZld"0'T{\tׁIW$a"4s&JN aOXJ͋l`?&( pMRW%Dj#Kky +IX_"|=hDHu$3Bb3kTOi?Tؓqڬ;pؖTnOpv^ 5jZ&֍LOWz80=V@< dGP؁c;Z3V! "=, R')dQ7E^o!JrƠxl#ЇN,(!Y{Q$stl/q#!|L=bOG%Q8 I#qGEma'IA&#$X&s^+RvĖHË;ATKVΧgOtAK$]'}j뫆}'6YaUn~M=FhQvPTNuQEo=ǁ +zPwG:Z*DkV韛^J7OIʉ LG ʤ\-qm&M;+N* ܅%<&JG)QgwɍCs4Zs-:Lc^( wrTnXWu{qyHz*.n`gpɳ(iNڼHM ³>aj%R xg؎(9鹊Sz&:a+/&#|5:N̈s Yzœg=8M~d +n? :O8 UHtSsbw:{RC}&WR%_ c+5TK{h钪)HPE\ФBx**p,iI Ҭaj]A*sTE >Zf@Y5H,5E6utnTq1=LEg3=(Iq<jEOt7}?lYDLlZEQ4?Lg.qᑷuFRJ'n҇(cnge7wIIi LIMMg4C+/9)ܷw*zJ]Sk1?A SY) +'k_EM *Q#թ_ +VO"Pnewb߄h =ɟf"2HHH"hQcM;*mฺ_wiºrQd6I޴Ӌ@FXxdȎ+{ʡo?8*#!o5Z":V/:W\pDWʾTM9J꼢V0qin :d|²w9}l]^(W\E/ZZ*}f}ʈLÉs)e1к*>VuV)a4>ݏ3&lNQlWԚM+-wˎC$L!Jy O`VZroZe0>PJIyRNUUp)5й]ڏy6EPL 䆃}:(F̈a"OsQ^T.~e`0C[m WaqfA ++g|O#|@xiǽk󝫚HMأJƌne:qK *S{J_{~ +}I,{mEvU)79m}{?Mi]6l*m">\=Ll(E %{I`dZK5$'mUcF:Mw}8 (-gh,Muc-w9~;kͦű'" Sh}o宍ں/OH/R57Fy ԅ=(-jMEubZ8-`*'A(+kpmv>RTW?:?Zwl;>!Eu}zOy=#wYG# P6m@pvR" 4֏F[^Ϫ~YO_ZlJ^W) o@9z5:`Y6ʕ +"tG'K֬] c$(5;B[]5ɟWe0ܪzT|q{AB+94ݡ'" tL)4$(C;jAu$UULMTQ'4WYP*b'rӝĞb.@=Ӈ kJuHqi;]>f)93ΰpJuB&y>D;mknkLqҢ?hEtTz!wpJTIO#%xk? +4x`F/aW5rM ..*Jaa +x5dƂOSDy]{܇͈9SUgz9M|I,hS"BP=pId5BgOݰH}MNzD) }N]5+u2o* 5zl_`OS&tސC; *@\.r#lH +K)UCT;r#I6J6ޟ ~LsT:w.jzV&@OQYL* ήՓ4f])nU2~Rnݎ =>KĶn%h&<-k{k^`<") h٧bIȠ{ UڨszO,MUwPpm|2L .Scyk΀3< UE )tfpLwB Īs gss6%wGX5ǍH=̫w]ŠrrQjנ`QQ,kM͍8Pb K ybP'0tTX{PO ֱ +m݁Hٿ<0w䁼`k/8;|iԽI/4ze=0^4ٜ^ z,$7҇O)ng RX#z(d4.98>x;ee*T6; +Dj&ecg&3ڠU3V6YSf4Y((!"BL4F"ed +&LaA'XL-=$ũC͛ d33n؜πEX?FD#]{πwr3* 8SuqR#DhZ-5z/-̅^1Xi^Ȕ쌘L-G/[L8wuƦVbGP"} NK-pa\{o^FPzr=[t7`>Cf 259AmoRcik +Y|-0r[# +2 5ov\u*j7yki3[3& (TH|ykm(, Ƽu9$KZB)qI`o%LSZY#$` \)6m5T/ _&c2\(H`# ?U'/ +.ӌ>Py0hgcDcJD>voz֠}V!v?p2ԉ8wC^Ϲ]nn ᾉӇ0PfsFo@=ue¢b$` +STǗ!På{x鎁z}$% FS=b=uQ9p>!TCѲ!{ :\<g~%d#&^=sE˶Q!{O7ў[ ٛe:ⶏ'@c %$/d'l^B&DKgvr'Rh_[c>auv!<}>m҅ٳ4LSg7QwĿ)WBy~O lW es:_s{:`P[ a'JVJ[ĆUr$jIAueͶ#P!mMϵ{e:`c#SlcMv2xCn2R[삗%$ ͉̊nA;qN%}mޔ.Mù3/+fuƖoL 1tCp0|u~lOjw7۞D Baw5B+3Ln6 icTpdb^[D9D轄KF:,D0gr&sYf'&$ŹLqW0,B2jTl@>%Li3T *,X "85| +\ǘB]Tп!zpN9y;*xLWfLRhYag;E?U d"}S#A ;K(i|79J޿o*cSzd LOƏ#;\Cr&Tö%al8hqt̨GB` +.r8 tߒ"ᖡ=lXXA.SŠRÒS\2n6z"-{x μ>?X`' Aլ +Jފ$PֿF89m ス^i2u_B'`I˻MÎ`UDؼ<"XV 4եs<`38r} Oo'3V֠%CbFL2& {&n}ܖ & "f8lnVF@!^ޤ;lOj(z)>GU ^go&6CQ6@_T]Ts,!:mb7%qNCa!8)HvV(g,:*I}Sc%=NLc_# ׹o~ބ8(2 L7; +㦔31}|f<4^$f#)a'R}@6)j )dlhYh i9X$QQgci H,jIVB^MD$ngjHQ)JDQSެBʡAZSܞ]5KP$p EaO L)+ D n]WP_|#rQQW|SD[WAfx4^RtϳU){ _Ŷ&mThP$HC!mECG-Sh-1hZB;[t g*]7!+4H#xhoұ*j5WAj2nKgv%حD⁶,o: +S%(*؆0>Vo>$0݋!Lcߘ>srR8';}u=L)^/]sy?T 2,n'd2po`+a綅G sWp-8#&p2q_meة+TX|W:\r`9ʠ 2U30iJ +9DPWN3:> +gs@dwaP K`wm;DP SE-$ѝBc{^*jRR-6U k E@"fߚDUNxF5vAl ;'12q +X"JոRE1I+,Op&bYߙ b4u-%5Oǒ*Y\p,%˄BXW}tkh, +3:6Jj̓ꦭnrQtQdw-0jzBx6V|Wͣ ]di$`c&(J_ doI0ns1k΃Ԙ@T!m} Qѻ싺/HeMG\6d.@$*1sG]ݡT.Pk5F/c*5cL1v*I[TOafC[۩jq +ڈƹxɤGgE-7FuT xL\fچZ]TUrjzo^lMM0i ELcfuW\U@+D j~Y#Z[}/5]Mx"4_Igl9.a4uFc.[Ufc"1ohgY7|Js0v2qH(Ox!G1GB +k&XxpzʲLV6ZJSz3rX5xړƱ^7^G7.t )5$A94rN>}4Ir8Դ~. # N^.=^SkGi^މDԍJbN"7^s]^>PRxJHc>j!L>ZbZĔ faqrKiQ X :<b-y|z^.goпvN +ίmPޢ bMzޙ8UPN-k;SILBgX0Q$YHu +|pU/*.#Zb8&`%Zs6$?|׍U((iؔ 8ޛN>$vnJVJ4oW+th`W\Mɔ>`V 㑫O va-쀫+TWPcs/Ѷ Kp(@fࣺ|, urO+ + wg*\F4p>,hNym[N>Cܹ{Og% N}(_#('p [} +sj!y 1!uǚ'eC$" .=P ՔڂH5ܡ6 1BcGL@~k8 |ŝ2OjS [Z%us? }I1Ƌt=qJNHԇf#q%eg}J.),.jrp$:C7wt_1اc^#£bb);H%XVWc;!һ@o)&)^-pS~e4wQQ-*S9?-C} D9RLM &j!n s\VּG] _DV#|f֚\3.chpDjV`R)1ltN%¦鬶SUu]yL̓LsoL," x2?ڴTRzaPҝTޛ5H^.a^y;,懴Kf5}VBEp$K +Nazi1T cPkF;GfY[[ܲN"F1>S;XD%"Rf͋BC5?ǺaTյJoa! qbBÖ|sH@?ln1 n͓ Z oaF!.Z1*kAqkBܴk~ Bÿ +T +PDU nJP3n b: mZz*P,}ڪP95^( +2omn( ; ԣ5!B9[@BI\bBiy +E} 5[n--Fa(JZovE 5LSuP;{?!Fcqݺ0V6B6SwŻV. 1oP:w]>˹>ZCP~B}kh$ԏJeB5턆 +RK@1v +WlXh1c 7aFcI -*ۈ⚡U&FCj 3cWhFk9v+iǞ56ڮBX=om ,Dc'ٚ!iLC|Κqk#6'YoĆ5w:mT[2K.X[NZ޷9.v456ê_SeBzLR$m$tU4d&6^k1ܓKtc{v:N-ȸ0V3~@e$0*@i%RheNXX`oDnՍOYKsњn;3k5],k=.횹v.7Z@7Z!&" [ߴ ں+qdnҒp|GiVPGT",6/l@M; +~!Inǀ) +=FO˅T$wvSnO4fI0z/瘍8-ϭ"WX +%m#CiV^oU3)9"]ƕ?~7bw_zdA:-7FM84&4LȌ=a3~~$MO&+za+^:o >7߽_ePD؀I)ˡG]=?O(_&~=<a$TqAVJ P +OYn:-)qb)YߺCibP<r9VrHPb H +b5?_Zʻղ)7/\X?ؠ "=aP"D굾l4]SO3ػgxϮ<D?9SDhF_JiBΌn` (V߸G?PLx hۼOh"] )u+jevG2&h@RFNv8xY ?@O?Eq>?Şhʹ%f%xMdP_*f +a&`љs Fbh>F%$v +>=WEhMĶC>%i$Eg Ig<&&X?= ,mC=fhKYƍAd6sˎ8PC +B{Sϴ9\{;9aS]yTtF6Va%בmȺ>!)C/XDڌG\2bIq:0h(/tReuivV\BjM wIϖzov(Y-Ps8hb#~×Q6 tx|7;8pH}RgH[Թb:Wp Ng_q:[?q:??oq:~\Lgbv 9Tg@Bu:~ i3@o:9!`gvH `gvlعbc` +vdY?vNd͛c4e, >`{V]YlcxzV#.'U;=nÓIF3qyqow, /g3lOV#.ݚKP\X'M3(w(ˌd\)wtJ#W]ey>*4 .8waxQR&hip_]Gz";^R&m+;iiC̴ȽoZIx(']ɁׄLu96Rw"yx lxTV :Kk5%絲7ļ櫟*ۍIwD +oVd6o5rצ +kf1#me'-⟴=i#Em攼vaӠ3;4uK%~=|M}yP]:>ޏOCv/2J/2J/0Jn5_` o2J7%j.PJ5(%L;5PJjn Z.PJn\ .Ku8%w.rJ.rJ..RJ]\]\uYiH2jH2j6vmrvwrw??›M#;9-WNy]ߙ≮̌yIjJ!o< +<<N~t9$6iWuWɴG=qFUQ}KSQ|%uJ҄Pim[!JǧiĘ(ͤ`?"eJR`읕O; i-A aHl16.@V:'ʐF˿#B 8@Z@m?Dr{q~:(SRU64J=l[~ƛsÏRu]Kaˏ&}ډm%ңQ>H1w;4z2^EϏ'Lƌ7LֻpfI`W˄0 1{8~q~42NyT}a.p DPʉ.3R9&Sec6ԇ;OI{VUW`cݞ&-lV m,* "l4އ, OԨz +v+8njt43nbcϠh  RIBx8zHB u$a&X\C[gi$;4,E>ɀ})ZX_ 1Z7n]է,&~/Gb‡BO~q)>fq>׭`pj*(3O}umv& y~3llj~iBPԿnT.F~ +\.nF}B{?$!F&ds +qQ@'fGXHw,uKKa@w 3h=taUSZ{K{eWJAMMBϱsjo#Ѳ2Oz g|ATiR&LeV% R/,ma{D fwMd昩1 ++Wvف.gee|a4z)$ L L묡(?mت s!i"2A7A2&=ѳY)ZF1O܎sFzQՒ/P lRvI麘Z?ѭ-nPEFRh-=Iv^z J3[xYM> I*qH 1Ž]#Z{= R_vk5XZS=Y +2:hhQ2xL9JAtJLEgSU2fp:x. +9Mg*LM/!UmN*_&}UۖVGoeL( +ޞNpj^ЀW=GzLh $SE6;:?z3S)#8{[Q-z&c0):TA;_nqoq,洕۾<%\xƏs-;VlpgQbkֿ8dM+߼쏿~_毸=/t])ӄpʧ1HWςdJA'نAEѧ K~3c+&AfZۄ[ȒIOZD2 1f3 \ǻVr29p*;崇:;&,-#~+NTDdQ!|ߪ&@.); ^е]+w$%2~tQ*LLF* #ð)29Ȅ{f]T$̦j+[oAc3L>z n0@8bfS + h(1Ѻ˙Qt>|L~jw4m'ij>'t)؇=0s +.}z@ݯ}fiL*r{ٖIգ(rL!ߑIQlYZ+2ǣ= Ua|rPzbl\dPQYyfjJ:8(ͫDq!wbCC8( LH a9  K4;ڂ%A[?d"BXfj3!`e]PT욼MM)f\ +t&S}PB%wpW#H*WzncP(b44~er)5iLo'u'2e9;][FOztb;T&g"\6YGdUjroNAPnq'9Z[VI~cJqr b&[^^`98ovõ'JpnC жc›jPNUҁC~>w8c+ c ܒQ̯8EdBJ`BPOPxRAf:Am2#n'ss- >*rvn;z;맽b3?SW +3TTx[g%$VCp&4fĺ!L3/~QQ?.H۹T25ILR' ;P25kUȑS%G(ʲjo(#mȉ%GC1zl[ה.Lv5!s .f;j{:d1upGl}Tb'aߋhC)16u@}G}UU`6x["|+v{NbϻQؼ&P tt'-
dުW+m"k|FxV¥avK@${iTn3t|VBdfvR rƧR b'wU +mݦ"^PT>Tfl"Լ͚1 +0qpǁ#>(9Cޖakqf%eT#=::^jADXP m_>euu +=.,f](,WR-Mݛ YŔ  %8 j}svu;}j̱( !.kN`{;%5U=F7}ȠmjʊHy +04Tu.i$&(ẖ + ciᎫzJ [Tp:^VO@Zwi`Lj)PZBE|Kc;pW/;`^1밂#: aiƺ,@RϭB_v#}ۭOG7\*rM=oAy'l{t8d%ܵQkVdGT fndq +T%md  5r$ZQ*10FzF DZ}ȹ&Wn Rl<Һd}U)ϢcI` SqY}_moN.;k|~gfRbP6f;Z`6og=0W/Mج۔uc@ ,U9TECT J @!ұlC|‹Y 1 ժg׹5"%g +M&\;v.ga\݊ + ;T+b| ^,̍V;g[o0{ep%m:d;?sƥ 7OrgvLaM!\ͭ0 G"oSG g0txCTgN:(oyjrt@A $bMA\PL,8:Z*Q4bP(Q)Cȯ[£ 3DLfeAF6)"FYg|},18vnXwPYGFtЈM?rф@ޭ%jFu1DRBmKK d Jǟ1 ΗH Iӹظm>ݟ+˯&sk~y{ϧ왐}`>gL@-'%9Y SzRJ`^m} _ /X]1W'WobuGMВlۦy1X @kt}┍^Ob} +| ˳dxAle6' BG F'kkO3|ye|"ڴQSL+{uTBy&/șއ&+θ&*/b!BT2a9;r50iM(lNM0s~ G̺^WO&:]c% Xz1P@<=ilDHRqjqw1!ًWup@Vzx}N?O4 dg;MѬHq6i:`S@FE qvsX=FCkwa٠cR\l)UTU~P"@dV݆E=nS iPq]Lt|q $HE0A!xSbAƵ3[ &i)i0|0Ρ9S7:3cKC9(1W~T}n*}HǤ17;jXj@^CN>6W GahtM\ViT̀BBxVx:ʐ?A YJsfHQ|Κ؎)fͪ]sVg텥]ϞXS-&\ӛqwi)Yӭ x`/(6t8K&{+|*BJ=͐JݐB;TL1?k +ު!*QTQ(jPJa(:4Tul5, + z;ԓ?lͅPP"PjƸ :" +>ZkX(= +\(_ +&`( +7rheYyW Dlԡlk:`ƇZ +%s{b ɨՋ ZR2qԭ9\k$Zܥ3k^PsB]a1671}`t <CJ|YuޣyPQUFM+(fJ}BΈ,C,e!/v$W~Yam(%,"^sʥm>{÷:8s] KAx]75p mzȉ6M(jڭb~%]?1?KG(}sߍ@`yC.wu u(3rMElA"i~BB.V49c'|0߽[HZݞ {˙@PTx +c#u¾[i+mob(;nt7?}u߽9u`'#|LGκ hK6Ouˀ +K8)aw|0syA\6{o_0TP,!S2 i|{_\ӧ=Dpc_F"7 t q-sR^ŇD!M?2*\éCDP + q뀎<D )v: ;/@RsсZDێC)͖L + > `Q n,JX$FKMu`W JRިy<7'qm.`nfkhcGwO8Rn1n&Jkw$ {PDW㒪`|2a'޲74qe"GBoWX&p YjC䴝~ NֽTaّ\o$gѯQ3ŁPDSت@G;up Qvy`~j&4U"ws-qP3Y?&Wq@XցNj፴_Qzn=vF\W!5>t҃P!je$fh!lA*l鞔np0pTHgSݎ(9!S҇\~%Y4謰%B jxSoET!06L>2P-%g!btuWhL_  |z +izZr^c3$c0]Tw Ar5Eڢݱj<}5Rj . H;P Rp͇HjQ;Kj͉pj'dHϪ#sj{q|"XC;&x#f >>׋SM >ڦ =\au @.*$<7->_b1g#a= 41sDx0{m% .hx>\QXRvwys\TYH표hAIsbq1rڞGcJ;9["j1yWi N/mJ$@2ȃ$u{g!FLubhqQ[BFy uѮXN1cc<"5J;;A:*wHB8<#:`5jra3EN<`1tJ/ کL2l>x|/gC#{)[VIZO]Q߾f3N6ȡ +KSm'lN zY W D@W{YDq';S &, XTH(+Bcq`V)1*|$De5bRe"'WSfݑAu}oz,>/HSVОKn4338I޲NQczQssdv~`ic0}V-6 :vBvr͓VLg9(^f?=Ve;T.V$&z;sNLnScH1yE2i*;U&]QC%`umdOp]spjLLm/(SvoTg߭}~v{ߗQHQGy_OX{?!\ sv-x Kb Qn6UaoFm}K/g6'WgN۾\|v׿ͯ~m +t/OLGǻL7|o~wC???_}_F(2ɛ_>R9>|ǟ?羅鴹:37?/?Wn_r@0<aCwo7_8??J_O'=~?7W_◿_c|_|cU?xcǯFd?jKR_>^_W_oj87W_ o_Kp|添k㷿|C4ýD$ j!XoJoRnh[j^*\iTS85ΌVޙX>"t?ǯrŬMlA$_>~/ 7jWI?/ËFzȉs4U|\-iuOT?m3@֔ǚ +g^n]4E\iew^iR۵[ygUc7D/I{a_p~qMmjwwz:8GyYsO ݡ1Q3ɏruL1=iLj; /0.B ث_%ZEq0ǒf<%潷۳~y4%b:;_ hNOM=MIiSi~ ظ=i;]99R܌瘱nißb~wϜ]ב,7`_s&(2)Uʰy}];%*BB?|tZR]ʼ>jȼ{\1{ +2wu_#gZd ~*徦Z򞏼m܇Yeo?a[/ϸgE(rYWסuϗJ0nz3/C|>֔9˚[*NNCڱmn?ENƻ;_LBtXy,p6py*s|_={y|P'|L`g>FY^PƸ9/)33m W{^|D~Zz|Bmв9ODz=y֏~(t##s,cRDNjƶrl#qy'? 4eB9ԡ\>sЦz{S{Ǐm3]|hju|y^TM!Q9Gqv~Xi<48T=\GK~ +e >f9UE_k;0"%0.ל(λB[_.'cj'|rs[s-Ta\(ycnGĝ=.zi3wcMTJ*%.6Sa#Vff{.lH{4; $=VP+;t~< @slz|b.4PD{i?jz?|$埏=9nrs}Na>qwqp^#q?u>}>Qi -}^ԯf^SS9"7gz*{kt|V 3z/uGb+U,쇢#?#(9ʼn̾ 2㦽S"}bAkK_04t~5e3/~X3I _W_,m\#: .S:Cyag$ɷr馡9|273 -xޭǾzokzGKWpp0hW$CRab32s 'eߎK_ʷ%1{tX@v\n:bs->wLVg0W񮩣Ezu]}s y~LRRNDI-;Pq?aVBhQ}̐㞏m_5>J{oL,yy.vOixђ:.0f芫#XumgF*b[s[_FJ_f*#Kշ baH{})̹Sꓑ#`-刏/>>Zǎoj <"̔/c4EMϋtIxXC '1n&Dp\~ܡA/Ľ$I'@Z%L-C{ʈZ˧{Uj5=zgqD{yf t[EzxL:hUΗ`+]# ࢙AFV# % W?I:O"Q+h|lQLƆgS-YGc}/|Z>713U$NNl bdP,~݉OTX/8pNdiT?t9[<#U;I&xvtxTPs?>;$*Wv7!|&/D@ 0ct`0F1b-_?; +:[B4Gd$"VLB r{DB|2OnȳbIS h*Ezs H8n&Z0GzY~Eg@0*0Hd]$Qo0CT~/n$HT5Zp~4~1NVL$ƈ>3ۼq" x8dEj1a4?0鼄8bͬ}6iz=W i.I )y²ul<0אJa^R 0i ̥ +MNx60yw1"2EJn)S,GY;ۂl+5gF4,5DQ {o#zRx{ɟ %%I˴p b,`G?g5 $bA4,kYJ\xF5 xDNģ,&a㱪 ,1oG &3UPE|=^M@lgɱ|Ұѽa96/"@7 wke|)孞q\ݏ+35( lkY[sC4̇|-"%cb"sfD@?&Nls-m9J*nN{e\DVU9f/c%>uE("O?~Ɠ4GQ{|۱/`b> w +E03 63(Y??9+ U |@8R()T?+䳥KgU/0gy*ߪeXP9M4a m$z~>}%cDMuЉuYKdg5 jZ2?)a\i +%c +`G,\jJ +e[!i|R߁ ʰd<3.>J3iutyY\b̟)'%\C|(9s&<c|9+ED9UB#Ì"]Xu,yaL6e0AjRţh?$+<ն%T׾#Cz@pa?ʃhv{;4 DTl]²] ,h)p +)긂Qu.B-%]r +Z]1Lz}g^2Exs}}~> 6{γ>dbz_ڋ{m!Y 8⎛BI0DS0\L6 >}haR|OuS8,lS9aL)Q~hPi(T5nȕ5+U`/] +s'b]Yvk|~ N$SA-%dfl_ D/֘- T?fKB 1F?;YȆkxaiV!US&v|WCS/z-OY< . M2@#3 KM62f"{ lLc(߯9Ѡ~MJT۳5T RJ46s 3w4EJhfΰ=΂֖bY}P<C9z[M@%aZRlh><6l) q5O{+eR)L?QR 2F~`%Eu\ .1"&viRGDh6տ&:|"LϛYU7ް|W}b:' g\8?9nguE@1Ð 3>q-YKF9YMP@,5dOqT%=)dž{hQyo)D݇gȘywC3 +=WTqaj +[EU+X 4m fТXA( @F4{*@ذ;k#n2K\F带@$љAPiչ $8!S5_ L_ D L@:Ci +Qe 0V(\$Yv)~o cQCi@(W8˚,) uPB(iW%n.|"hUhVX@eEyt4~y1NRQjq.`|*]D|VK_'R OɊ׵YǾF{غlQ"f"u5M5uYYȠe ҹO1%)fv=,~pf1rp"֗RpvD&gF+,_Ft:rcӲlԿ?< _&s²pM19"=ٺV rW +L( I0_a/) +NTm7ب + Ee?c[n(b1?I|[HLD1bǶTeFd- C A4[6Q@~ldKᝉ6nQD]}mA6,[&Q-  2@-tYAY 7'RD,f+s3l^X#cZzH s,$vHV%kwFb +2Yal` b]ƘQcTH䣖sq|qUMqt STrYYc=WD g'b{Lye_`L.%uI<'3tCsC L42 y.ʖU{ٱKe6sRX%~O<Xnn6 L)XװvٓE`c!sh!0֛~uO45aez1L91aZ K,&ilNPcd=! +d'fBi0a,? +2+ K5ul<' Ű\$5u34Fǚz ʪtt<%cm6液Dv_ZW cwK/׊e^RY^8IoutEgYi"pw$^r2A`|+$#4'oa+ˇ.ymf#Hg;-[j&Yn?S *^2ō KiLMEK_l2ߐC!,[\L0en/-M3[v4d[piSLp2IOWP 0Y"_nI[t򉸳I:K|Áƺ ? M1@@8 #Q\A4-÷ߣ1yl,FVL 7KLV'k4^H:uZǿў58`U]G-j1m\T ? DMJ)ffusFŽ2QZ;`N6;A-?5},zRF7Ƣl]' QB1jObʤ ⊾-kѤfg4wYL;Z4AX}|Kq^CT4E;>K(斬'ѶY u,5X@ -s&LϢY/Aㄭވ4X8%II3N9يpZTvd+j_vO*goYpfH2ϲdf/ӃzZAByh1ɒ"̍zB˖Fs]bo``>ݵM6lDhi(","ۉٲܢ~έ^"f+ʞ''le2"F% ?61,S ZY+w+doqXVXz˾q2ld:W::,edYþH&'jPeY "f)Ylq?M) -#$n[=qe\p{Zuv+ GV +MduH'rv,mTRny֍M rYyY4aw8ʰ0v"J/b~Btž~ci{&֧^CW54!o UڂL]`IX"z2ry2ˆ,2K[F>TόToh4ҵCvt]*lI!0/]RnB c⣊vTxl= 6~ yǰfK%b3DD3LyHA @6 tDC1esʜhFسTZ۷a(gscC_τ.vy#}g'~'*AMUVlor-'_+A`Q:O'?o׆ߝR6D%M]hȚ_l +UL%8*!]@>O]5X[b|et[|[dMt6U7xVk>m]0c~{Y*I.M(]B<Z"ՒWO NQN<8Ӊ`>O2$+ +4 ̪.5ˆL>NV4@"{?g x%lxR3s`L2K=k+mIE*&%rr}ۂPQ3 E,GƏDaPV&1-psS\d[W 0!AmYǮߋ]^AW Ub * J "VG>%^iv + + Jm?cBD(s8fm 8H]LF)m6WtYir~ؽ10ݮb Q׈A ~|O)TNMrjʂnG Hl^ +(NmZADeN eahzl״E$i"DJTn-9eut2? +#2On=XEh3ö00auVQMFؤ0g=+!K;e>3jp3̀b~D0Us%X"_>ձdmgP^ui~v3䘺2^ +k%L3BE-rE`"(D-\-Lweuيf7p&f.ZAK1joZ%* م2)Uqk*oP۸"SW̧di\P)s~P d*,H^L)ˢ"Yw'& +ڂ fyoHYT ؐY'cFxUZ[M%Kw°i&B,ԍĖDϊhEYsߋN{u/Kh6Y{,)La~ fpo9HP뿈l G{oceDDs # enזĐ`N'dP}hApirU&FHI Ktp-{m:vEq Y"BZ%:<jH!1OWы%!)~.^]S' +Lf3cE4 ѯ'k͜vXx#\Oe#DY=DDE,[6=(ZSM?uhc-?Q%>.A>Q`tU6^dZ&0LI #Qd~L$& +~[U6_P00#L$ +aXo ]wT55[&}jQ0ɍ.Z"Q1*E#Z( $!`.d/zbqmsD,c[u 6l(fl %*QzRǖ_%(@6wC%bf*l"RWBU*`K~8, X"QA VȒueJ  ɇbTYc>ރwDԕůuV+AXr"&&S0rCr,SyYW@?XzCuS1CtdQ1-LrBa F׵!*BEs]`͐-𛬳dC}C|4lDZf"$CMW m͋f(SHCn LuaO9|CuS=ReAr"v )$dd1lòD5yDV((x}dxo˰l7 fXȼ&R aknv`a+c\Q+'})ZU>JEJ!{VD9QG3%)ؚSQWhbCjI[b= 2Vf%:IB.ME1).ׂ3/ MYKEgH2~Zco$>~ |ˈl"gaʼn{4{&)8y[ gJ|;GW1Lp "(cd ñ:hoز)Ug^D;~: +kJKq㘧JzE]03 k#U T)XHdj"wY2-lc("ܖLͮ`0Iİeq}Yd~DfKBlt`H1ֱ[IߋF 1DKz?~+2jb tGmݪ4ԏh{@JVlՔ31Fbu',+h,UVeA$O&+Y &O9`훪ɪ[}~80N],R4YRLlgx`U2)ez.p0lN6¾@&бSda2Qq}%7e+Vz]ҟ^G!ZR +G䱎N 1&DNJ{AVeUԿU'~EUk۟zr[…ӥty>ʚQQ@WhE S>';X5 jwBpO {BOiˎBz/u UeahɳsZ4ݓ7D[ƌ. ,k,YZ_LN}tm?.>nasoddѭRk4HJ"g, M6C~I K]Q"[}uAO%M6[A<^=ST3Vcl57K/=УM&iv O;|9<\^{s?}O,]^>|@LN//v8u;j5_T(4_~GUv:;Ce=?"i^ cA/-]mͿ"9g/)_AVaw.B.I@oTMEgY(,4m0)M`M0#t2k5oؒ5bF+3wnR0'ank+kk*, >,ʦf¤'N_ziWYBo9aS4Ýb;x= (b8盓=OXPL%a[I\gLyvmWDqw҇Zz&~0Mzp?b~2HJf +R7H9Jk6[ƛ7׈;tg5R?uMd9Qriw/xEy>cI>d8O6إAυtAXZ*Yo|tlٵcy|C26jjXU,Ի~(|Xr0-n4ן}9X/'~)n=5?{mdD5X;#ʼnۢs"pbi$' gug8+ƻ%le|f׃][ z7`@lc*#|y\}~ |Z0׷ZigbGH_p{Ub =ND/A>s_Nⴕu̮.lo;tafVOH,/(n5 wv/R?HL;FJqcÝ3LeozëBQ;vnN $i,Q}\wse40l7J\P-+o:{cOn]h2GV[#R?&|G)ų=#FM +ee5 SŮYHըL˳7/ove:z[j|iHmUW7KzAT]i@u]3Nv㹾^^ oFk7WEk2yVa׫AϴeukQ[gYVMe:AgިzrR+۱\j%h7IL߮XSrjl&3}%?R#R9;4V,i'NڹqyF `4rOcLjck^6asOq"V~#]YhI*;5Ld:{\̬^Iew;K|ieoۨl:Q=́:QJ u7n\t˃kah, +!I(2N ky1Ȋle.+𱰡i8h^:݊҈VVsCZ9 gA%8?N":N E"?N'A?A+MS(2t'GwPuƤ|i^ٞ^ U8.JdOZyWwnRAԨwuer]^Us^? мδ=UN@++quq2ҌA%R=wniA02J3PXʴNHпo Jy^(Oe'Nj6=|w7 ٍY4MBĻLAh ʮR +5PLO+NKA 㔻RKǤ~]}H U/rۀ^M{{εqT glM;lTFJ0& +LO/Nz}7abQOLԎCv+7Bz#lNE8Jem¤83vRD:c8 ~O;5*jwYuN Unӛ!Y ^z +Q(9$`dT gFJf5%vbVt^pj-TVx@:n55Bɝg՛O?^<6I8ۻndΨ~A۠S-/R;pzG7)LQ:нUqog /j7E"7 2{:!߿LJ 8M @ QA3}}mZ?3&Hgaxl`#T!6X#lv$>zM]>u :NFd.1n8<ViAF%l@d)Հ@JRA YLj:֏@Xd1a+yme[gji*^ɷ^{mr+0L_1 @#oOV7UQe,= eYe{AǴ}TVҬ<}9go+~Wkw2?vn܆磴 tKg:}9QK凴q&`,AO GJylo`L;B\7ػ픷ACe+mavFyFw8] ilV6UmޒQ)y<_6Bm_ۧ ;2ZkTe2:^{WA C(T&qЬN8H;HXpZ?v.Ay|M_2.vI㬶s^-/Ӕ; +z}L9U,Ӎ-YR`RL^UB +N2G'%oz!~,kejq {> X6s}8; "f4)I @=f&(%H;)y`X~/Un[)e7]R=0S$iD^"F1hZW*["--7 +kޯv +m[$ +PJBʇxՒUtNT+x5 v=IQ{w; hL~ e"qH-< +Oɭ+r@nz\-xĢF=gPTnA>?jaz/Y]F /9RK8mӼY<>׹ +Y`F 8LwIuҨ8ML/ igbۗ(邖LTWop]Hs_(l-@qn$KQt+U[%ZMv5o߬ 3fxgyUe,]GLE`Jݙʫo'2aOlV"\*xd6裸ݎ۠~`.ú`y`ňQQYOZ=&x f/l").Szw(^Ĭ6kNhDUF0*a&iO.s2Yw! g_q +B҆{dӾK2{'+€Qz?L[n:Rz~0Js& +X9,^\~/sxa6.ыv~VJ 5|/Bqqumcx ! +8`B֬~ˏӹrzנIxy[:r?ߘv Brq?yurA~qP׋# r`QPݎ`v1pR*W +(+bZa_4Q +_OB&\֚A"ۉe;)PLD2X[ !':OvT`. Ly1jFgc6Rb38z't%; +(/[~#識} 8şuw?FtO枆 hOON*?^e+Hޓ wRh0J &F;W wE!Z z(jg |:JوPC|)0OЮEИfi6N ?:f~Lq_[ &s@[3Is- pqbՏ?'ms XwUp/ ݻd0I(=P:`6lWF H! XH)Ug8;xeꏂmUZqPx{JTklw-wJK,y˦=0lә~:;kouz〺')D,T~*  + vc8!erҮv4& b5Y4+֏-߫.A{>ധ'e5dՃ9c8| KdDAsy}i~4 j}}mg6AVӠQKzqe ᙝ(* ak;JSp`v)|=-?PA$^N\[vrUk*ۻRKdd [/J{TwH ta o+Û]]j.(Yypi֖zmOs-(}1.`s3(ms]!]^,wmfk=u4SBȴbV-7#&Xm0zI*lEM9~Q_Oۋ@咭©1Dtؾ3z $*XFǵ:C\p`؝wb6"8,QV5 +Y`F[oNqg;|X+ +0vYu dL;[!^e-kn*E3 ÒFuuhN=KEi7k:ƳI8M|D +hL2Xc r/ TXf; (RNBj%tѓp`r'aoZ`0> dqyV*Iҷ` @X@׃u ) +} `Ny D~ϔauM{82KSQR1@/K9Z]#Y4Ϊw˴;NzeeTV \_{?&♾Tz0]<T?S(j ;;gv4D-R@ekM@LvY6UÐϲ[]$XYf<"LwEZqp^@F~Kr O9 Ѫn,JMwόc^:]=kP^05w]Ù9@XF[iNjxG8ĬcDZŹU9,uoY Yk`=? +h @;? +x2M{I7Fy6 (R:[[H$*'pHXh _?ZO^rh^fo >X|*J2 ֎A=&KfQҏfk`X[뀹*4fHUV1*)i2}4ܽsQ&9+I ؆`NQtս'! Q.ř?g2`[!i\Go-3C%{>ʺ3 +}RW1ԝl'~@=Gۘ==3 +2c`{ǑXW?lwbX~ ůD-Ra*;U`p:KWѾ +4Vʥ 8z"p`,~20`H63Sgp4-Mo<]xl0x+{dLCExT<|PlZ;I5Z^cL^e7 sUMEXdf|zVm_-3C_h!*Xmaq;S݅yųә={/7xq; x`47zvi_EͭT*@z1A<`Vڽt~ H8'BnߊZ 6~|)iyhON ,*Y٘QjQߝ͖GI4U7wVD㬐f:B)@S9TKd'q&Bٶ ] +Zԣ]}'ƐWz0Q +2Rirh"F<3=*U`^X +EL0-`<3.Պ2I=U]ؠDGXvaV@2}5; { hM|50mR`{fOv2;̭Ƃ]ӊ=l<im|oW_it͓ljqZ8遜WH*@Vf*?Bw;4eg`k? U %? 8!b50L7?ϿsU]!Z.uv~@ |mx1ڍ,. oGQiWs\8̨aH*X1}ZI 3i4`/irw/w_bEnD5/So'㠲rX)E/H;U /d1ffGK\uƵ33NOlXRM,w`Q+1r$Bi"8 spUsAYF@&Z\lGsH.u8}jq`©И T FJ8e'LdtDŽ[4ĽiyagTA5 pUI/W>G`~F 7NkUQ^՝ۜ+pp3V9c(m٨+ ]0$F5d?w SxfУVcZ;12 tGޕV\r_I6 +0< bx%,Rʱ̙IbT(%t_el9YX^b8D[N4H:OÙ'!HF=[]Nl:q@ߍF` K]O;O4.Ҁ^ta+Hŋ{qs@)˭N Y57N@?T[V$fޘ*H?#;HG{K-,ڵL,/63ڏ(2>Ԩ~i~<:"Y il8@,w_nv"TeJ o&vHr]@w䃵^c(OfXWA.)wORë9 L@۝j%0^ٛ-dn\V/K;wpU=7kv$ӹzyP[k}x$]3=8L㹁^ۍ|3k`E}fV:hutNK[R?\\,.;<=O1[lHq&9dHeE!>i>Xig +<]gW +8!C͛G83wO@e9p؁ o ۽XT|m7ӋcN"7Y]8tֈ@+; ގ瀵T͍ wH0],T+)X bܨD h՘َ% س]q )+g<!|rE +l LvЬkA>9ߎfb WGA+c,{k:MY k彴=jI<׽쟿//*Og:&ywo2sVm4OAJe@|ػ V~^W/3`?xWy{mMiܬ{Zs {mgo3DaU0to!|缾|ƕśvsFҔ}N4!zW?x_p:g,߆=~\[~][/^RQ"ׅ̃ {nxC]=X~mCw'^M懀=@ڨőU^d٫BQ+gy*2\ 3~ 9q<7vZ"7Kg* aMm>mqt9}XwewՋT~\Y5gBl_W +̀?Sš-Jû8`J6 wT^tO?>{씶OQtiUW?wϾ/҉u-׳kK@GvDqc{uc48&hl +}xCEF̷eqx94q x@N]}Ϥ}*gjyP fy\_yW]nzϣoV7嬀Mus&o + :=yq?^&7?_ ;_n~7VceVg:^=ͣ7/huAez\= |߼Yrg [/f/ㇿO={ or9z[Y]~σ_{ZZy^nh ê=GG< /zPYշ=w@2-ӱI(f젎 gܬ3C52AΝDh*msXݗ9#!h,+EG&Hk#T[M K ߆ZaR}:R>?gr_P^NCˬ' *J:by55u&9onLl$kHIAչ3sINZlAꎉ]+7/=)6pq"ݻ/-:B-&b#`L&'b +«u\ޡZ+=:sgm&5Yj2T +OKH}ushKr хdTaJeFaՇ/tԛh*kp ̹UY;޹rFeP$]ijqKsK\f5dP}=ܢD{_'BUWiXÝh3NvrB?MM4AA6ᐽمhTl E: \lMm_-Z}YX8OõMʼn3 *% +%mkR~:e8c4e@gF}uFh $NM.7C'T7Z]ŃUp1(xf2R[ gI!oĞ3\ggy_g{buٝ2zx;\ +=/%ThvS|6َ֗,<ϖW%5.3c}θx lq\w|5:: +A'3w|u_e×_`N0m츍0r&]ྔT[Ԏe*w^OjrŒ]ht +Eldi톚.L[@qN۫>6̏ٻz[ML,7W^RXJ&6n]~eZ1#Vr:[w':;O@ $be9Th]_SR^E}Yb* ˩ۓgOLufv.Nvpiٙ|9hA( G`0cgRMJ4qZ"3WdSw?:ebA'W S߫.4ׯeffeQoŸj'Ng&2D#M-ZEecӓ+0XYϞ_ؿg[@K8k|:޽wGgVwbE3U<:II\ft"mr%B(097!?{Wv觉Nk|eV'S,#\//q81wsuD7Z[ONgϷv\bN( Tk-\,LmpRD*P\##Xeay5=)`\~^:mPҔ+\_۽{G I+榓b?twH>\<}vv}z Bo}1p7 pu=XZ3bӸXY:up⑂PcÓffcƭT;1U_9:@Pb&V0/" 7Ts+\j&5y21up,0*"|-Q6[W7sEN_{ .,I',.{]-iWFCD[L9Jmr۵2Rs0w.7>S>n.{•k>;׮|F*xs_ĔۻϾvn) btu" ?LUz∑3y !uP_fhy^a̞ PśW7ot/;T[{&6w%oOKkbqE ^WVOtXz3=u%{ؠMÑʸİa"dd: \ar`YV6xw>ݯ]VbUYJԭF#)_  ,ypp*Ub|'Pl'7Nh5+>&3qf69xɛ9XS9*, +]ThXX05Ԟ73GG!`JzgDnX\a@6p@=X7fV/U, +2Sna|M8Ī zX/,mnR<ۜ۹+X!Wpf l7vO2HiJf4ī3dgbb{ jA#>C-ԝ\f<%Mk4ؓ+p@sZ"!8xv. Փ:ec#JڡJvE d8QNAq`y/#JMvP.cqK&Zzr4n&1.yx+B׻]J*ڵY[(,z*tܕPeUf i1%3;q& Hm?K JKwJXh u4T[Xݿ_eTkfO e6#jᎿ +a8Ü'9/VR%ArL,(< qBeJQ&$jX.H0HtezsD<"zlg`Ҧ/+XK뙈%X#ܔ?^)b^ԓ6.-qҤe ,fΦ& *\svv./,ClSO? _xIarx +R_Ku&Z*kvo5GP[(ok t|HP4+[QeSvw +e$78jU vS*](!@~/-0I ФA}PH-tdP6ҮP.S^ƻ[`ԘN(w:Hr[n ,@Rg9 +E+SA;&3jVZ{(*LKVNqq/Mk|rFH͒ + +1\kWVB]rtD;}kp CެݓE4̧AIJ+lЛ':6)Vls6<& 4mWh ';Rb2qF|k}1{#V+΂8!C}L- m6Zq+#BoR3z:BCKe:Q1gBN2"aҬQDZ%;?b"hWb +B͡|#SKm*Y8T:F26nd i&JL9 x].T DQRf q|Xvh̯0cfZIIH +`m_nzۨq'1q9x#8NKWrȈL{h2;cue@I$[g3HmjƠl̗jC4p9"Pp +yH}!X`%> +dgEobrHa#o'TU#F!}xi)[@ܙ!c@f;|v_c;G'/7ԂI +X$}h֙ߜY8~_~͟O/w?ڿxzbs[5NH )H|;?v?yx[>~ƣ/o]ٝ^=-Oa <.!'3o=ݏ_}O=k/7w:g94;p1 UHHfvb2R_\gN]]R]iFVcxP҂ h'Z认 o*S3Wwz'{G8{w~)*l^#;!H_ݟ5;.^2xngO-]s>[O~~uVw*V{*++3Q;yjGfMDOv@g+}}O]\y~g_xw}IV6*Heo|/+z>?y69{q3W}OO/{{1a$bT(??WӇ~izbD=닋d^:{u[?[?}ǿx>o_~ o/𗷟~}inhXVP:.vffO;w}=/;?|_37^_*wS?}﵇^x?ǟ~~ϼ}pn٩$Kz`=|"W_?}[7~wg_|g?}w?~ٗ{8gCMHmO&7v]{G~_7tO/DO*;(F8 |$ۜY=uGyJDjl!9Q"΄PA*sVo~ܕۏۋ᧟~k_}̫?͆`ǹj}zf~ckgKW_o?_+/|era%yM#]>OHg +Kۗ}#7x{᧿'~_W«o^n.)>ZڡL5(ZKŕ+.}o}?OϿ?`9?>7o6DS/jkzi}`S]7G~w>͟샏?_|gG|?8{V>k! tejFE1*L|_qϽW_W_}?|ᥗ}镅ӗp X7^˕\srnugǞ|慗}'?OW}o}'3%-Əq 41:,G|W~w?諿ǻ|g}?/|{c]LWqoDniQZxB@؝]vï//w{x쩵7;Wq>wBeQr bbwpCϽ x?/㏟~ WZᢹb3]ƓĨs7o_x3DVZ =B15"ӢVQ)/Fs~emnu3]v^ۿ|eΛ.&gX1AӞx &Rk&Mvjw.řSx"fw}}я~O>'_xn~er+c,lܿMJZٚM:S?kҋ/<syu#WbN3Pޓj5ȨSc{K/曯/ΟgoΝZ]+Tk|وƴ6+/;8+ɡB}ffܙsWy{/<+/?ܳO?_޽7ooFSXI6~ VHW@/m^v endstream endobj 80 0 obj <>stream +\rG~GBىm6RrhB5LFŵW~W}zg}z滗/՛_r% qFie5ʬ1z+iSLczJjٝJSn"`$/㇎-kvtVڊyfeGHLlZPF(OQa=zdL5PDvYjTYޛXXGcF5E5Q=&fTGsr(4}@8XTz1 +*t*թCYΣL7T2#y'r\ %1 7X.gH^b9 aeHf<93h3Nq) EsX))Z-2\QoKDNk99`Xa;2::kw#D8A`1̌(l2sTOJ40n0 FճB$32!Ӂu ; id#40f? 5Ю1-zTĚ:D<ڽSc *UP[[B!WJFWXn(QnXɺbq%9OG'~`G #TKgSfWȠ~pMv X! +׃_ +ffĤ\ jLGmG"[I&>6b>:;69. ZobvoʗbBNa\ +eSzG@-2TKH[A-ab#c:%gIUԛ"^ +˳6V:>nAi0e _[*02 30-Ψ;T# *%(b*ha2c&πҮ|c:wPAT6#`uEvDˍo ūA*ZF5IOo,fc >9|M'L6\W2G]" ȭRGuP *'z(=C( WL\afǕcf=,,!Nq`|UDy2kfRp(o"RSɕ7L'YlQ*+j%MOR=29rpC>R;thJwU9U7xeu(*+fnl[pDG=>WBKjln`s9ʌ X(L ՝Cm:ڒ[czHXQ;3frFQ6MΥ=і__b+::!Gy WX}'v:`t0A= "ոRlvEotEl2jѓXA8ꖨH=1uNNWJWt?|ʬ@8ƀШyPMm~#Xyhcؼi#R8#!ځuHThy\ybܢq`f2xBf\+AX" Ɵ +hL@OFT Z * i\f\Fݩa2Ǝ7YV*MY!J/V?"&Η8 =qMZt Tcē4Pq+yP"ͤ;{ Ɏ'6D#aܸ9ۨh2G z{&DD\MN+gh mIP}=P^qY;Z/|՟.% _KWrq')a+lzN zc-=d 0Hlh[*]y<{QfcSӔ4ش'1dy7՘ǃ7r{L@mk3Hb-V]KzR]j`!s̒P߱%{xyRi(G_J|g B#:6A0``$_ź=P;;FW V\BTګz;0nXܐZM>!޴Ý؇V&;V.M:W@<wncNVh :LCr1`E1= @C1޸v?#e$#j_ (b FHm*;[OF +yx o.Ѧ3fzD tQ)/^ta1B rtA:BΈaeO“ +E>?oEwn|UD'T\J+{mlDmpO8;6Ag p1^{>5uΛzgL _.\'IJœy,qfeFK7VWch uL=ڙkO3A 5#U0ԢXa1XIppte`c oba2uzH9RiD;B \VJY `1q;3f怢G$qįB=%W`K::.66)skbivEeG Nڼ0Hjo@%!P+- +#arĤ7ճq' wb`a B=ྂT"l A@1]+Ɗ;q-9Lh +S(Xb=+!UnuXiA k;u&73TsgA$:X6^Μ)-OMnG,gQ&ȳ?<#|'U(+͆bcjk]]:iTxʭ/ERXYs+7J bb ?{7N0&\{:d`+T^wG@Uvl5xr9#ąݑ6. 퉷Q6{jfj75y:\]h,\(͜ +kHdk33JL(4B%v\`pZPᯜT +BIq^w +dg/\{EW4f @X}wϤgC[(.٢31Gd!KQ?9:j;5na=xe򐑵s3FMXHqЈ-ll~ԑ3 +U N)8I6CuA&ӗuNiDf3 +68:f~7a+>eTx蘜#A)䕛 DX޿a?,-"d(0A0#8_aNΓ _q2Js]lzj~"3P22{ (M~{Hh ;N*aWDeP +|Ja$ʳʋX+qw'($$wghJ(7w?ݑ:%D /Bȶ 0=LsC ؽ/޽0>ZW +R_jt&=l:J *2 =!As4Phl ...YY+gB__7@}SqC~yw&< 1j }^ ?:t_rg6f rK>G +cV  I~^j'ޣw%&͞CfZ{I3 \ +V!*m;G,GN*e:?b6P#F* )|ʦCAe GR[xq%y(T2XrEXǝg&wLbYѢdo @}f᎓ʣCC@#\;+\e^$&P.@̔BAp. FU.6AB] ^M$i-Y!xir3q`GFς,N$ b47]>Lě舕u 9=+\BS԰l%(%ACYS?_yRlKE*۵] +M^u''Aƍ;:ڱq~RគW;55)˸m=.hl4XD+A3SvV6BIՐF5+!3)wCU*D{noaL4XZ; +'1ϯ ;\b+ͱ EB}w [F5D2_S +*|i%< ~dˡts* ^W@igWT6`$:Қ^tO5+ʅ]ݍ;{.ϝk:(LOQYgzNc$: YrbGXef4VϘp8D6:t|`2$+g%LlߗO)i:@qTŹQ ~hP7Ԩ@e7 JڨVX dݽ|vz?XX4si^=YZDb垃KBݬ"XA{ԙ?ۿ:z⭸sƥ'V$B#V#Hp9%L +·8 Ԩ5aJGjr#DŽz@@zP"PrKwA0iؿ6քOohN`v ,ϓFMTҭӤRF;+ZPZ~k^4xʍAMeZk|wrZ띺 +Q6L^8ep5 +$&Ί6!S! 48"(#ž`M''IOO.IW %br}&5u ךE6:OMZĉq7:'̀Tۣ>QSngc2FNܡ2I9j#4UۏfFmb<,x6$k1>r\N\uǹxԕg6qWOK(3a, +]zWl0bj}<οCpS2۠`T(@ySF&f( UVP}g}bخ.^97v]4عqcDi8d2X#q'S,|';{O[pz5wjcFĚ[tn9*2bDƾ5IQ̕wV"Ny Ңj/l_w(/|5hvWs*)tk'vOʴHot\ZpH*+;#nկ f2 +~fHfҗeB-S0S.uRNyrgnn͞Hz+pR(L!0qL47]nu/: +2.(R Ku bnBGmtԄbD6Ϩz|\GLa":JkJ&KU}D}x'X+ 8ǵ.=T&~b-C<*G)1L+lcf3o摑o9<8KoQ')ʥPMNds3m_iHT:6e$6 Z\i)D/NiżᲢ ˌGp8kԫ-$6_;6$,6RdB%*Yݒ 'r] #*Dma-FGB`%kgvcsO^GD'w#R{LKݡtIWz8\;Hݍ6Ȱ63LHッtuڡ װ CCP3$gDr4f$jv/qND~}[`N#Ф{9'b7I]DE瘍tB8 Хxq'4?#u.ۗ+Zߝ~&tk';}(dg_N ,)ȅO>Gҿ>3t!I֖ 9.s >ɂH6\usv +b3\'r0/G]H +f`r٠R(3kG{OKWt}[?̘L*cDݕTckgʷmvp}T /Gcσm`Z&BJgK%& PEF@T1;H [A` ?P{R [fZkjmDĂ #xP=tϡxo҄22i'lx 0з+\Xd8'[Օ͓ٝGs˭."DE~!Q=7uEZi =!,OZ0_ec'㳀z.ܴS*1T\˥]t2A00VdprOT;7k^ !w[a Ts9>ٯK>x}t_6\4 >΂jBb*eSfٸƚ/:/XP3Q@jL/Q^>/^1c&gCJ.^_^v}WZmYQ  D_ + F;=u;n5Ĺ>ܩqۘs + H}[0MKvN|9(д^s\@mhqX̶`·&vpԕ敻o?I k AM~ζÛ@`*<#, +>gN"c~N6+S[o,>soLƪ٩^*B7؅VrBNI+c>+sz좍vd'Ma]PS{V4nʊV"Rֽ~/ݿ]T)~9h ޷s6R͎їW/a*Z?4Z]*g7#hu5ݹhJg`Ksn2 +t!/Dj/_0 KEP}̰bti_0qf 2}'q ?^\kvm[!V]m?{>2Xp{}~Ɂkns$V݋U/3Ѯ kSƐȰ3BɆ33n>?XnOͰhAޕv~W=LMVH`BRs]+6\٩;K!~x|M4bg` PION,`b,A['[|Y\ݹ4p+5{xz^n/<ĉT 5W)Pl t԰ +F{fqzSg$x<r%R'_&HJLzY,3 #Z)R_6N+.ӹK!! +5\CSM+c?aN:ȅY0\?{zZk ֎|3T,ۗ 3Gg] ??b&or4` +ԘP50 )~2UVcLw'ڐjyI--j%.n0 [4he7a2i ;havfEt;Zn祩MEb3by5?޾ѳt2w AEXuCۇ㕵3!Pam;R +DsJoC`0 +G+F=2\~Ԇb9 ac).*y,w +Dg_=yUsC%3Ƽ {.LԈ W^uIe+Pr3r| xw|*ll6OoWݿtʵpyxPjrg6.1o@o$C3.PpXar;w-仑B?hOT^Kghu+&ٱmeNd3>M'ᡒXu: f茛LF@񘟋^nJe:pq q1]m aT0__vkRiU]pZkT2RDEσ|f &wlb ,^ȩ!'C(%R)jKryAw~ȩ9O@v:W돹!3Žڹ&NQzG.&%֯|m@x_$RYu{K7>kDqcQxͽ2p茐] g'|V_0kL l09ɽo\{k +ۗ~P| bӤ\t3G 6GPyb0J7n& P7>r-Lڅa.NXc3ރ2-s|prd\zޣ.?nާ"xnnP5⢌HN 'z(ip@pcʭv׎sJ}]oYT f5Gr) BI#Vwl|y֜lQk|nLJ V^Je( fQ/V^in]Ovv +зOe\Pi❀V:|ՁƝD;H0FvD1h:pJy~vkQ>ё&l;P~7q@{wٿrCidr\Hԩt1xe9^Z6Eۨ#a`< |,%un(W W~ߘ<KQǝ=9deq(k|AVn"vrŽVLKFo| W E+Cʷ+\v&(ߧ"%9]OWg<4 otl; tUk~&nqdČ[l[FL =pq_zd#f//XN.XQ{`Ša' {HEυ 8+G/z`r* eXM+QA9rD8#-z/b +WR$4l) +I;?D ʁT 9/f'ŽLgkYg2)z2~!hµr(&b$ӾzoXq5SѮ[{FܘZ_일Lۥ_~7Տ޼?oP( y65UjKV}zJD(U6IoM*FLCi2!diLOu`&q-^yUDd̊Oz4zJL V/,ҰsXur&X۩T19oE]h8o^* L)Bد<F<\=`D* \zJ-Ѱ A$Ep8ùlpCF cl +E@FZa7R91 Z0 ƒN"#f$tB  vx=V_q5VPmTH&uܜ#A5 ht$U&ҳ A녓S7΍9O_pa,sa2("Ͷ?LQ1+#9 ]%ATiªU>1Q8h9IP4JzQ/d2&\{]͓mVf/my{מt}|Z`ՕImHzh=^+АR!W/{WP2{!>Bhl_olw(6f?tl4B'򽣅&tsmsD3`Rl5Wn@71dTDֆ_怟Ą4v\ &Z/_;x>H`u8bEshB%©68D +s 0u3L^ hI&AL B_t+H@7|ۈ԰kLBLMuhȊq90g@Bt87V6:bRI՘h 1X+;eYYQ bdpgG0`a? If& Pmщ6&ě .2D BI)*A+\E6BȬ Q`.5\Y?领Ͱj‰;ِ棙&Gp2[)N/gZ3jME6ՐKds`ܺz$+aZs"ËGb͛`ՠVR}>!պP +[nBJ(h^n?_~\-ɠ~޳\W +O/?Tc3xɄ'xS9^Rc[>ؽFR~qõr ݷAl=M.>sHaԈ׈t1ꅅҍ?~?GCXSTϥgZxcω(Wsxj1?g2yCn"IYټU+93/^r`ypx|gVC\G`¥dyp)) LwJ~jqKgC ,wVbZC^$2ؠq;椣.6i,KK3JAϤf^mn kcN1Z+kGlB3LpHf5҈1â +V/ASBoȃXUʹ!F| *R,^޾X: +r'-))Һᑀ' G2{ 1@BP@6y>:n<~V`XXLnf%ڔ2@8p Nf 1gc.\$ؘjcKyE~sF ȉLmqt%ח\AY en\b+r=!7 g6T[쮁5%J~(?ļ03t[|,0gXRȍ[qPMܭw>Nx̸_%.ԛ֓L!Ǹ_11VD͍I@4|'[姶%/\3}A,ᒟKl LX| htY~KwaJntnV23|fIeLO`N҃)cl*m.1FѡT<ߘjF%!; N؈1Sr$75n#M C/l ;z&fh7׹,/'s&7 x v\7"."&-nNҨ8I0T' I$!* Ax.B <3z&,Ȥ _Fձs# B8+R">pĎƼ;qG&YlQ`]X|:7}X][Z86Y7"@D 3nq"})>^c5>ʈ1nO|Aƹpq C}~8Tv\!N-]^߿G)rf6ӋBuxI'e.Ty bDi + phOXQ#ޤx9+,Imq(JҼwPցVUW.\SJn@h\hRsΛN_^2g."f€ŤL"@u-~Ɏka1Ł;'8 p Ȥ+(x/ ^Bd +TvSQZ! 1|0𾩢l94 h>*bqorQΛ'N7vpa6cS?W R9xqya2nah94zB$,D򼚥CI70oL28XDPFa f4rTRJcV.L_:7fh(NLU.7Q +ōD3c@`$&-`H?n.Ξ3ArH@Cq[xnu熟RLNUca8|!/. wOFLqcnaVdqtCNGduPJ'+c<7o^;5dHII[|-FmM;1bp(pԍ^:3daŘI{v.L&Ą >BD Ñ Db(-! %:C ۜD QFB$jC 72YJQR n܄}0?g4;VhGD3PX<8NkE;&YM/'89;j2jBǎY|HhJtpngz·~:/K6P S`)U0jI֭.H:A +^"Aa-Nߤ)G{Gh|}p( J܃29Y':`5'5a (ŠɸRl m#!5,Ԥh-njG'P$pħxz }/  ሢ'u=Nݸ W_5!8CR( :\nt] P9K=__ٽR)2˃]@p?a&`>&%eYPgZv508:Xӿquwn +%54p؇F,f1b^h5gN9;1F&fӘAg/鳗ehK,y{~Go?O߼ӓ/b1㣜nVT LUޘT('oڱۏ޿2$zh06=;jyaB덆|i(k5V4Sڳ=?7Tcn~B) +**f[[Ujj7_=qw_W?lV0E&m4qc5W'{;O^_Ϟk??w +ӹ&b Sr?g]y[>\şo~'{^W<ٌs~ith [=vi`kzWݝ?|у\zٵnjj#=K"HR4r>/wWo|/>/^6"s(Aܛ4|Eʏӟ?[gzʧo~ѕ_|/o=>KG$Eb\OĔ5;ǥ/^[?߼k'ӓ}~پ˥t #y~8߈͖+L퇗?{mV7~ÿzqΏ?\lE Ȩx0$[`YvD~}tPzW||oٟ~_~xcN鹖#Bh`ݗ~on쓛;_擣ٵ޿l + QS#NQؚQN:_ܙo^ǟ?}~G|ooޘq\ܛWa'Hp VsJL7T7uwn|k{k[h?g=_7>ʽ(B80`/dݎpӵ^?~߾"P +&CRRt&cAT&xV>^^G+<߼u/r"$@$b&ґHCk:ѷѷ?yo_|o~Nrf' ,.ಢZ L\^.tkş/oݏ'7~?_~~v`hr!h|+)u4zWxvGK}߿ǟ>_/?[F(Ň:GJEQnT[˩ƍ7/>?;\%DA@Јpk0[Ejz/J_}~m㹭o6u(8c㉤'Djݞ^D6>}uᷟ/죣~nzryĎp&-ۋ!n9"2Wn5;+w{߼nXƀ5C"];䲇$*Y'%eٛެ|`go@b3ZIӕ9ޢi|TޜߚK]n׮oM,{WJJREZ8XaΧPJKTEQ @%d>!sWRByitTA1ԈEL8h{[,~'tj4W/.O>8{G?zœܛq?Jo@ċ+;H5QQ}kuv4wϿ|GR$ހDNh)EBTB$0Lkԉӻv/WVȴTA (`Foh0S#IB>MQ=t5ʓKx:r"ar\87L ,LqP &cTWB3B>xy:NŅ˄2jFd,ÆIǣ\msB1y5|8gG7j +j!<TρQ.(P +\6Z0R( +,/IΎs#6k1ڈx9т{yXs9d&(HBLm͉܄EZa$\X-R`*G=> lP. Z\1n'b~lаaxG4AU|Rw +KL\_IՓjBKk>=41m?ot2d| Tq1j!0pZA8멓n_ZO*80Վ)nAMNT]QN IR"+]KSnE]ȸEš+ܼU`b^1pVAbjya`;I݃dTjx ~`#H&R*+>VȖ\f{#z*AǍЙ!UTb̌wqyU>4HOx ` Ј Ż\e;x)ѪҪъeP؜yό9F1&CMtqjW+#Ie''-3f^BDžņHĿm=GܸsZEkǫ/ ŜWdT""kzcsbfX"a_vN&7h7ԝd1ZIթP ?9kl};pmnl +|u0֕2ja._t &7X4OJC,o*u633C1=k;;3k3B?g@ǭBiN?ÎI+dVʓ\ld>ir{213 Yp݄yy{Bi$^:Nm;$lZF[I$h8($ZN6 kqj^^Z]ył`- He-81X`㚓LjqN*`H`Fd@<m ZuQPWp1Ge"-vI(or L1Z`iQ8;emq  Cy+7ajP)[1%.ם\br)vm?l@>iشf5d Rf3!'3~E^6cţ\b:iPt[`0655bmh'l˗|B`DeYLGPKJ84Цp| A9 mFu>c3M=K%\`)TF) + Ne,7_iQ:bvq’q,ؔL=҈t b~/lĈwA{wϙ^@LX<4"ǭ䤓&y A^YbcT`S=;R$B&eC!L@- PHZPjڀzM%ϲsT=m/\5 `'Ш-Ѿ\ەHURKV!U" |\?xֺt2hU^'sn.=S_k߹$pI_3#=<ֳY>ݯ܍T7 ^I̷'Tdowx02дƒXPvS)'jճVr>*WHeflw_=I*.6qyLBvm& ^(]":D=| GK||jɔ]tI- +[7cq9=gM; Zj^zW^}zidLkGk7$$)%N$@ďV '!W% ~]gG^QrɌ(ffC#v"nT3gsRqm͍oN2bBaE%=t!J+WŬJkl +h=Up^eR+<[\j27"u0j`WdX@oR-f2Vi.NT֣KcZ)5=S=ug (Zjt P+r{Sꥱ ?gJ65ֵC),'wlDF@m +eWS7glʨ:3zO$TYÅXe |R ( Ml97N{SX@(M(g- ^ڡRZIO_U*[Vckrkmo҉i>dbK/*=LZȀ5R8Pl}*ݿ^]bMZmNsU}'7' UhConɀ^IDJkD `ZOv.kPzK͙RZa~GeZMo_FfLK1lөH(kB\\eҋ\~-6uuꉘyTZWK2Z)*,v㝫7˳ǃՎd#RVj`.ZH5Wx2ؖm)IŀҖod¬VߐJK%! 0?j Dk}u%տiб(@s5`k^p`x\<2@dͧ充SL~幣}2XwpH`kk+R]=6>qv KvL*n>J}[n!joΓjuٯ0lX+/R͆LO*2SPh#7a03h , f(ky.хE*|X)>3 Jħ^B+Otb]w0=<9εwI0GWSkhf'́F*"iyE D3R~d7.ᴖb͋v +-VR2oBnY hv`~I/@U:)@l:ֽim}L&A95^@,~f֭8V]3:]_zSXQOMSvMfҘT:mߟ޼-fj`HeLY8^?ٝػyVtwU oo\7}eUVuv=3d93K.w%. AG:FZI 謌Ȉ9gnNsp916û;Yo2\qDn*13Z>Xp_;yg&;5\n|]'V@6f>.Db橈ԇQg I$ʴ_fiܭpMy^S:1yy~v/ gh]jeIy.^;c_sòg$F v@׀{V2܁U'x\$^|,OCy؜vw*yg+~l+Fk.rYjcFl^n"m7o*'{DH嗣@#IhVdȂp@x/xpU%3Rcgp]>xo+DXgս6f}Tw?W_kkx+0~߼=[t??߷E?OPs6Nm;gD??/7Įڹ +:'5o:|/_|\-s[(oe)n1cRVR8:|BkIԨCů9< b^~킔Y&jރ#i;?|O2VQ,+#ԧӗ3W`Vqauy!o%ćM88>;%)n^1Tޛp2^d)H'[9^Lh{﮿7ë 'E3rU\LjhiX)טjcU#FIg pw՚kPjT@޸zu5CZћC[or]KJSEʒy?rG{y&$58=Zn_ū9/2>@e j"Ҩ /MEcZ묬s{z.|D=Lm/ m?%`JnT_c^}͘/ 0Swޯ &zЙuZ6^Qy :'˯ yg.7O1 'F㧤<~yNatg-_Я„>dA>.>nֱ>hNd޾_!|jҞdhkҞ2$\0_I}2Ը ]m?vr0I-Hk[sL8 +?Arox7{nou|.pݔH<:|x҆ kzW5FdxxԀM?tau/sT¹^_%]u$Zڔ'n8O(YL[Q1mAN8{$jׇO)hl7pUm=F+wg5cZdww"CRZD;ׄ3S)o +ftyZVEQ>Yfjԅ'YN(}Ez[7_| +/-DYd/=dhO.nSE`Cњt++dj,7vGD'^4nEX: 7>ޞ}aOQ9(PYEBI:Y|d_/Ii1FUb`wSXhwx%K) _οVMkF ꫿y?~nB&4ZŌ>@1"?̯FD| :DGErzs:cAP l_`*N@Unuq[[G[9I506ĝYj3BK<7%:^NE=/ywjrT5ǟ[[XaAy@x7gb|?8z]h3;~w꧳7 wl}1=}@pԄUWo;_JJCkӗ_N5Z'H-8s@N9@ +W%s_.\*\Z36^dr3&![|tw.Iu9og&]ᬿ?yϤj ֹހO߫iO,g$ۦq&5PA(%\i|ϮKoOѾӘ8CşFg>y[`0qgE&Q;)DI6q: hᯬQߕ1LNQ>CtCtV)HiT"Nm*с`bw$sZ +c%C2m'{e4N@.+NH>\+py|/ +lUN=螻[N +8OʾWvh~?~9N +xV41 pﯿf FB1 N}"O8(c}BYC=q*[u+a5fX +fIY&ݓoѭzo p}/LLj'wFL| v/Pήf=| mneX`5Y;xg85:1jۯBf*#cP h"j*hgno RFwr1G;SU"z{Fl 3A$9M1\dup;3LnW^E+F@=^Rw zem ?KC*I/;%5Y^GGiCƴ-^I, a"o%s炘l@|ߗ,1\}On BښYD;W?LDQjs@o)h`֬ӪKJkuZmn@aF7R +9&* Ϟ +djR)-\goEEhV(یIU*I[5G7˔9Aws؃ JC}S?%jjbx?$H}'K8m{bt>_^//~j|u^|^b«(Pz(:(, &4LIگe7KBe ns ФWrBRvxSRowh$%t1m6} O Ɲ^^i=rc}Lm% 3Aepd;8s&/cK FqfIAg_wR1*Y D=1GR0w:vk8AްLj׍} s#&zELsz|5vty%7% ZigF}B2HǬ7OV)Kvsۼn&*Or|ѻxUASM jD:)T hu+on3֤*wu +*v?xΠ4[P1v[^Λ@)s21|ިࡔ*+5/S%;)ц֯r)lQȅ7Tw+w| *6J}nߏ~< BnjόwoEH! Z ߝ)iT-S Ih w1>ӲX/qc*8EC;^W9o q-UQS:n#sʞzUL 4*O'_=wZA + F;G᫿Y=,3J묞R'׮s){f%STE-#xri:3TRUز7,zMp1'o8gI )X"bDZ z9:QAT +9Fi}ݢRz@{`v5'7aIAVE*i>F;{e}B3Zo2\u<(aJ ނ[[VSdY }8kt}4m@ k&ĐŸڠ͞XͥO$K(Q%Juϣs.<"RP\' 櫾&o޵ܺ=!Jrz4s0`h%x`|-RLJs5^lt@KDg Nqk-)(1~|tOE6C=Bu"G]IPiv.|-b2]*ugn?ʍ2د(e-~|6 H(4rGEs*?e -P6vrs"8 uii|LYz?@=Pє'7|iTr*06GhW EfȀFiWVnh)}?(cZXksU&F֗9w H?\ovfVx*xN UeqPAHc pZ;U3>ڗRiD8EYC ҚF)}û?#9IgV]`|H`hisK6D(l+'EBXg<Ǭ9P)K9|/WuTAt$7O +^I ++66+3OwOIˌh9~XrZƄx+Ϥr +@[E22~?_9DBYh"|"T+5E&%3gji$@fI?6_*I%,f߄x۫O +rUݧG`V)'=pf* zw m5:`!ȭ4fH?EӈQTo+T+k+bH{7ܞeB%9mOp;Ku*Jj|Xjw +l {)AMn/>`5.:g [UxE5&Z礹zO_ctyӘ\^C ֮.R3zuT QyRLU挮< uxl^E]SdC^c6e6:#yXǥDn)㮁#Jt] $#uArI\pxj*;?˜!) Y܄}X uLĒ/Gn;e{zc+P ^M) 5.nuǔһS *{HSLJ!kv~Q,S4 I_أGoՋգ4[Rr=eϛ77K!K%:(}IqYr~w?UI&͙. :ҩIm5uPs7B`~/d@@!+c @/1iɭE^"Rir >arofdH4F䳛`]"|\]f@*;jKG{h7hn +N(-9>p/MMi">RAȭJu U`=!ZzVtF[Գ,`v.b.s}f2((\ˮI! ԦX/0nכ&Q7+='Є6 "c9\K#**:~ ?EVQEfAA fؘ[Bn0Kf5~q +!>(d?|W݋/e>#6Zt_YsFHc,<mV\wݯ3~ '/+B4H9>dLeR NrW:N'81^ @rnvW st@ i4"!m.{r0ĨlSۄ9뷰Đn5/VM>pa*c)>.0%RW0`!޳p%(]v4f#4at gk1>euS5fJuEyO +ր?z Ӛ@dU)Ooo.t`r 򅠻džǘ h>*qE\TZ4Lj-ċ06ό匶+R]"O T߀֪qoj$;"E]D-@r ( + o{Wv <1٤4OB`NYSƼ3Z-4@uczB1ZEנε< #ճR;۠ӄ[ᖣ<9Xgо,Xjrm@ +@0s60wT?/ѓ:B'@͠(ZP:*Awur>r|p!Mx;eJ*rf T^IS ,Q `)S쳇(?zRL%o%JkF/RYfA)on ʃ(eB۲0[W5C ,@Ϡ0_IzkCT6E^:nl>ī/U)-s/Ax={K68ȅL n/򐱧48#Oׄ*|xWR@ a+Svs\ajr{R$,RK\?sΜfjVs8p_ !+֚~~]$OJ\̇x-xLM(Q8Op9W {weLYRvݔve\v"AxT>_ 2>gI]::nrz?z! H%9\( 9pA!pUe-VFw 4»n)+PQl1QR +Gj1>qm?1*vRz m0 m[;_ +0Qj=Z7=+@d jYt(GHjc-J>?IU_X%ܪ:rAgC F^omHJus48|U&m@㗥6̳lZy6.1c ADOTІ2ֈ1VEi]UvA0{L^ா$1$@zؼYkdkW%%9)L#h9֙@>WJ&|:נsټnnp]T{&P)vӘ"&9ɢ&*$`zw:BLHW׌;/!0xrWH^s޲z` ybV_;-&w L$DZt~;u-BAoqk + U``s࠹~gNG*ۀl%ECVDJuwEk!<`Bh}Lj 2TM>&(sE1< dO! +cAլ6[w=ȒGYQEâЬvjžO, *XXOVLX.'[COPWְg| +Z'yr 5FHiIIAVrmTi sb jxf 'z)AOvvqHVP^ cK!֏poM.>/[Qf2ݳ/^7z˴UhLƙߐnQfY8z9_i;xM7J|ƁyA2R7ʾ1`]-4\$m ȝrVP'L'Mu8UU`Ơf|Hd +G56~4z TBɝC)^h+b_{)>ߩN9}c^T>i:tn*ӄnO +BiL>}<02SV[WoymIg䍞btT뻘5Ge6Ϫ&jArFFe^`0G +!ZddB4p,%oZS=5SvA-I9JWc'ly+-VNAdu7j)cI0kNʴjin~ɇ0Ҥ8X?ev)jf + e-|"7Ay\+2W?O b@8QIn652O??|Dr@[{}koa = 侵ܷ0r@[{}koa = 侵ܷ0r@[{}koa = 侵ܷ0r@[{}koa = 侵ܷ0r@[{}koa = 侵ܷ0r@[{}koa = 侵ܷ0r@[{}kHr_;]:% xzuqYVg[4vxg^:Qy) K(*mL S{_co_24%>nJi Reڥ xŇKʙ 5&w2W +u R +FE)NNYwXꜻRc}!L-Dƈ4GJt*rRYl@3Qa#ޝs.\0K;1. >7Rj-}Yӷ\㬢tr\]yL^hk}a 1~Mi`+R2K LmU%x/Dlg(/Ky6])c*uZ"Ӕ[Q#ORI0#ΙJ/iD/k c (mjOrlw +_76DOcv+\Im*RAMHoQ`ƊL<昷g^=,>ʱ;ei,Ub҈Ri۩܄H&vYbt̀U^v +l3NQ,! jbPG5cqkld1{.XoL"@DIE /SͫFkY?Me.mq!{"W%")zL19b=U!9|*5OqaGn|XB>8tsL8t%,J-Sk~M)'r&;%>>X7e91xa3'>\_{ Ӹ)G=zY ̚:d+lX.O`R.,V) +ImX]zEYZ%UUXA3&Y*)!%,aѤ"YjBTb,n-ZC Uzй[gWYf,oGi*hE"O4]\*UӋWf#TB y~4RxTOğPLZR%,C*ZOv4d+BָIn`,# +@ v*fw!JKb we> r7a +|ƅѺW1gWIWIaOҘ1u(~O/G5 w>bU fU힨 1\gvv}Bg(LhDk[~2.6GȀτ6dCx$+BgDtI{!F'j|@ +xW9.>u"i$yI2XWn_ݯ +RX}۹{ꍞfRR,OUG> ?f5` TYC+u>K&tƙ;~N_WB1_YoPmEWcgNDtXn,)gn9%@ +O2^Ak #c?-;%5O5hXefoB5TlJTz:bv5YbvJ򓂸_5+:V2]oٽzIj$ 2ts7>I]vhP0Yyw +NAʡnif 2?Qد}Ap\RbU 7 n){;x%?ݫ1xU]GEPٛ2`fFE{nwk3LԔnDڔhNw|]F/Gp1pǯkL TU @UzEy1 RvKnY..c +5ǝ8oD 1^MK +,B1^ ^^K(T9ѵ[ReX4$(GN~B'1ؔ="k2mE +DD<`Mn,fH +MX ^;K1<$6@> MƁ?pvRh+q-gbh㏮Sj{UsEWT8XU6.W[f95]AXg{$=>L3ymWQT&iBnxUSz09_ZuAn#gtS껈^[~DvjJA-P8 [ZF*5J +AE8VINalVRB|,x?֘ӾYR}moj-"Y~-2^aT fZk &N"waRw0E:-Z$ݢ Q8n(IqM!*v2Q@!L꣝(K=JOtsUaҊ8|%)Ղ\ 1cgV@ +ư>y.7zFaEA- ^РNruQ4H#__⛤1#֟a*"q SKr[mwQg`PsR\\tx`Yʅ.%WY͘CS`A!b#j=Fҩ=X\gi7CZ/`힔 + h=>(@fHX8>vtZHVqO#**9Hu$1r)4GI.`NY? 6`FҘl06¡l"ibg j\b@'e*a~]3{e@"8.8waEU"Bs09f댵@`|Qu5/m1}*,Gt3~#CzˢuD_2,m(I}Ҥݕؼ7 D~p- +[J꤁]bBvR +iRD=꧐UK"Ŀɹ36X(Q샹NUhZ⅁.~v[56|Hc:Li]p=2&aUۀ9I]P~U;GYl"᭲Q,=I{eM]WO +ܧi{Hul'Rmt~qi7(3_gz]DXM\n; ?=ˢ +獪r#O ; [!|Sm)&<&UdӨ\gT 7O%m CȝtMLԓ<AuQ DB4 1q *qAboYҀnk@LC­, a헥 + HU._y\TMͳ[!TwAo +_$Ovk>=fųVw Dp5`r:F[NDΩ9@h4ra901IIQ9UJZɲ夵eV-r\[u +5"s}BF4?8n4=X+V?"E2ze'S6\uq3z+n`簑f>>3IiGHߢG(`x`vې64|zELc"d@a3ޅpu \6 Te%=}Mu2ឰ x!pb  #9nR(в}~esRPWf:GSSH˅qH@_H IB  CHU:֕ i9ݬM|'P7Nl~ȈyiCmSYBU3W0b\AEswbΤW8 93q)5?}i?pÆ 1;{H8RfAk,+ZQ0ہɼX8~ 04ZߤSfods+[#Fmk"! Z8BׁpI|7DJ. +a i,""chQ3>f'̘i )9\4{p=b"`Fz!>ZJ.6b^!AR\M8j 9ꠝ2Xi4'#a:ѱN(oi+݅a8'd>esl|U`&\4xXIsC As2&ln;S dV(R .]:sZIX +2BUP4 aHOdTrysภmuawBkzŢ2z +Є ZU HÕN IRtCz_-T*Wƭԡ ev΁Fxg>ibm/Mv4reDZ=A{C`87@!= +IƇg ; ! 8Hv~LS| <>x`7b&Œx/sU.yʎZұ<Q&TykMx܄lLAH+|nFLC F#jX( +a'>> +YTK6kCV\|ז.26*egaֱ17 i=h;K +c;4F5P +D01P12V,dhpъ<C_*;1 v!mnnp(f)M|RAdTg#FM^̇]IX'lAMtH0:b%3.hkd +_4zEX+{!n;Q\T +u` ~7hu fRo}lтi"DN=|Qڔ\3FG`Lny| Ѝ-K+9l 5,^&c6~&Qmb }Ox؀B&ș:˸gĈ4X2SsPQ398'`vN .rpp d}lt +@ش[ep^("](=t`H`]˦qZ^.&B#t&*S^qO/Y$?RCйlflӤ:ͤN2JZӈFBBDUN.d` KsP7+>yY~y)ȆLⰙCtu&\(3稠vQR9 gpKM.HG6 6.E'otuGQ dkp`6̈228zq)7k8[t#?㫇t:l7'6jؐig'RTI;c`;X6X7nuP΀ :ïGAee;i a3 `6j (\!3"TyVԡ6/TXwO\lḼJA}ѹD31"Cx`q.OJ5,X6LhUO [E@R6-+ĈeFc@.~R)yQ;78F dMFn( KvJ5't0΢2CfH cm'I8C*@zoĊk9q! A?d2>\сup/_9Gna&{` ǁYSiXuBXZ+:OE n2"z_h? B;=a/Ĩ%`*X1:T gͤ 8.6c6]b,a#aW# 9`vlϥL-#21:m!'\_9d3GCt_C„ uS N1ࠆzHa@ԃ]bFFJkM-l0bnl4pÄ %+AH-c2yN6, +QLSTC!0)#,o@Y` N8:m0=+d{te5PI; &J\\wHAfBX1ǐgEB>*Bo%$ +ᳰ,6"K^*=$.:LĨ1cVZ¸'[72n 8ԈE V>džuI3S'&13ctP!mMG28jFv8OV6ؐ ~.4fr78=.`e6X"*"гr5H}!$I1؍ އW}I'E`/| +I6s^.%k=f#NY/`vf5vQ獸 *wqw>d{M=A䊍I|uu˄ ٬٨M8X;?P^~Dł7W^ƙfMA2Q&$llK[h"j@3hNubP,q fSd+8D~!pa=jMRSMt F2eBv HUH ƎFQ.cpPF >C|Q`cpWu} +Tnu S݁ieଜ`J) (}gp*ҍIE1%髇lvn IXt1 7,ұ&żW* ;sKRqdJjF QI#srй-Bs,Tu ypP_, D 0j ɀ&Lc_-oJ2b1"50ɐ|| @>VzRJH U68wpO +6C_qYč !+ h*q|B!L0`>?ꐀD#`e|2Cѻf$ SD s7ι +ې N)8MF\i@`?c9.€$^,ipFF>hiB 4\gqY,,0;PrqyNcJPS4T!jM`Wzk쬝̂_kV:哫X#u Z)ՈGl+:Lbe% SCE33 O,gϭd& ^b6xBIE3G 0Ik=Rma >xۄK,%"bSx5'Q5bTa8P%d; @ n. +d2629sAxLiC;ǠrFo"*xKORS\ވ@']-d3Mv֮7X>ڊ4N~DgJt +*Vm*Ud| +DGp`w RYrLjDdP +4NQ˳mA|˒jwD_ZgWi,BnMK%c[.SH.ۙWCK&f9&{h+\'XڎwN3i$h(oE_ 7].1E@0k.H%gxMsst7擡pzBfuNZKfB{y7eu! +碍M]tJANyd+3EFRd5`a%QJu\hPNtTbQp-L]Y`py%=޺Sm\1i™hsKvLpt*s Y4X&6S.⡒ZXpI;b-2#-wvtgSjպJy%ډw}ԄĔ섛i.Ս7KZ{ÍXu};虰gS\5PXu+T:Z ܼ\Z͝w|{|pQdp[ȭi&W+1+"n'{;&ю57M06׫ۻs )=>=:>.(%97km CeT~ӑI bILfgNkӧCPqMõ5!gxc#?*xK@j <_z' 8tZWk}럨-CvoD_-.ǪK^k Tʂ ~onf V}JKf-k@vJ-OJs^Tk #*N͵O\OmX @Ah`ruhۍUL̇@y%*|WHZ6alٳ3 <,N8[ +Jgn߆3p~~<WxZijvC\}\gпͫͭk±s^y5 +:R_8򩇟}# &#wҹN{ho<1@E[^4}-\쭞""eZȧBfZpF܂ LI-X1Prhep#̈(*KX>˙sZgu:o3Rf¬Xڹ nZ5=:@L7=> 46cⲘ9{ߩ;ҭQ7%%17WJKg鵳/SZپv֑{G^9HkN;s۟u:hfzG*sgdw3[p1NM WוzṉkW̱'TH CM47tS|-AMD7R^-/ +ea"%.iLZߵQ'ڹHsi!rs Bh6o+̟ʫ-onbcl"fztMvV !-쯝̑ʭ͕ӕp{|烹#WMxJ=ZR'bRa/S/~']ǂڝͻ4]lo} CBLwK^xuPlZ?\W*5{w0jh!G,J[/%G=)N$?PP>L'gp5vPa&BXutjZo.{ 7Uh@ֶc gJDD:h©Gcna113o +4zken{h(Q+~~lzCl4Z,:1 +rW +ʂ&UnmZk{Ĕ W\{@~ )*Z Vb$>R秶x0[X=Xn,_.e3\wPqe'WvӋ•M="#t  +*U^>__uw$!bM,-_n] +hZ;uVuZ]8}Bo%Ϗg#ˑZ 9H4,Rй4QJ|utg +ir+Lt줊lnV/t7Xdiu;kȠ}lƼLG'hpz(8q;'`HѦWG]N*!cv҄y **-mߡ4L%hn!mbzN t6@Ԁ=!e!`=BƂQ1D +W4k܌^ݿcjLxuxz)s Lr#f`=S5(m$Ǡ" ;r+k3J4WDtuȤP5RZUwa,KN&jrT8}pG[k:D-Ȁ"`@b V͈h򋘔 X\q'13@..[蟊ApHin*Gf9`\3^>]-w DiylB36BH JnX}M3}+&;I>_W.RP1) % O|ilwZkjoÓ.~IE@!1E8,2(R hڿRNM.Ϩ T\``_:6aED(w6V,FF y 1 Ldx`u^.LʅRTtaXnN #&amD%XmtwSMъGDW .*Ak25!ٰ3qG"Nd#C\m//HVT3gcC 7\ 3ϫÿ"Ukjъ0|4߹v8{TNEs#gowy:.,ѡ9LNGTHL39s";zHT>2,rхG' ^D0HMѱ e#T#7V\^BCMN2*iB(*e&FELM@e:J~qp Ft1j#p>M!rт-H‚(C{/W/Ujm,T @̙΁kk *yN8HVZZR%̏X#bqQD#YHսָ i>RQ`KM:9XdeDl26 z6^Z,ϯuI. +X f$pY\<P>NJL;T򩪐%'<߿Jb8l-Ix~4S g:KITJ09 L2l,bG*415gHJ.V*k[̪WI$aҰiFx vSt,p$&X-/fZ;@bt_'M=V$UW%09'{"zW"ϚH„X1?◊z'7s{PT cVT6%!k )px9u#BkăpY_FߨɯsnF)qAvL-ɫs{璝Ev6g;V3S2L$H TDfϷV2=`P.Zhu.u +je6^[O4Ҥʐq.©);4f,6T}V'̘0Q*Z=` [P<%W^YLh.[o_?wW~gkz?~'^QZ.Qw +8r{6Y\=yk!j~AZu*Wfw}/=׾/}'<_;kPE;2#"}¥baf?^Sk{?=]z+p'^xwx}t}TdC%+"D Q BfCzЯ7W[Z;{_㻿__>Fp،ZSr˩ڮ- 8D%w,$t8z^OKۧ6WΕf򈉸iŊZkjyeıӷ]|}gw???7_xu#:!X擙R;u‰]'{;?z?{=kz?÷g?›;3md+rW\x=‹/w釿~_-Q} L ŒJkzi{GO]vc77|'_|?᯿xkt}APTΧۻFZw6y{奻zG}_~ǿ_~ŧ7;F(5Dj\87U-l9u>>o~ͷ'}۟_}_ _|k?L6V ^aNsR.52WzcO7>y_Gw>w?O?o>ᵷNvO:MHq7)XRl-vOvyWO~׿_>}O|^HQ$Y9I5Fsvmū?|_/򷯽{SҤTeu؉S.qǵ?#o}w_O}{|_x^S +3^&BbTjjsg䕻'}g׿'_?`:_/٫nldsT؜]Y۽zw|g_oPw?_ϾnxEb8QOͮ={y㧯\7~oy~?7g~~+o~KuP.Lvbe<Vֻ[=؛0o~_^~_}})B5|/t7f6O{/}?}͗~/?Wzǟw\jt&'gCd7(u#'|^y7?/?O??~Ϝro2* B]UéZj!'zI`t5v>yͷo/~~GʫgouRp$[oTSRujbk}ۯ]:{|(E˻0CHFitf V{;=wdco~e#_rxG{i5,J8?wy +`㷯N Jqwg܅'~?^~ ݥ`"+%*DW2C\0w w{KVoffv}mc??|Ï?췿yGo_}y?V-@;He0h "\fgswꫯ?]<ќ-]8.e"&b|_]ݺxG^} ϕ5/!x(a;8f5 &O*Vk#gn˷_vxW_/ګx=)P!jx.!lө|H+ 1oϽǟ;?=w<}O=6SsLmd(ӿq:4@%L}kx JO=죏?ҋ/ڿ]rnަ w"T@*r_^äݔ` AjGL C~&$VJ)X +np1JB(Zʄx9KxؘC&'Ay W ))""sΦ ron~久X6c1 ڊlps&/)`NJ Ӓ‘XTsd;늖LT\Ia&ª g`cv/ !TR"zYqUk۝NTtSZ.d`'uVt7nj>Kp@Z-BrʝG/SvV۹B姆ƍtV|h><\+ .!E̖'>Dt=no_%)·Fn܊F ^'$Pэ +e;|T޺Y>'*Q"t^x@6s9Ǜ'X%mUp,J T&IR)eT+JLY/4ov<aw/eP~&&F )G^:"ELX;Lhd}lU2*Ƭh`0-Vhv-n7† ++QZٸ \$0=l6z+ndmdiy-S,d:N^i033n3q.aa;ù77#RouRrݙ}[y_i+ma9YY19-~WZ e&lJ7y41EX֦K3gbah3afK^:~`3aM X5udqcN;`hEnLʙz}1rRV01Re:R&CeriT.n&mDӁ BctH˨7r#Ca`QHp]:*|f$B\X]Xx%'*6T< 4͓&9jA툠z."lpvPU6Z㢭T@e^&ŠY *d)49lQEzd +v*U#Q:jt7X&pюL3*jE$/xgLPI&x~b NEE!ge&7NrjeDGLȸYMoMzM䄍ubHzMhc 6rh `Q3] lX$t/ƌLxF~?/5w!9]MJÂfbFB~,DAR9l"b`cBB#F$.zHTdCڀLX[;1tϧ *\ +KbrFﱑaȸ?P=15G+CT%)V-ܸ hOM)x}XTE54 5f!P |Mk\k!̂:/~2Z[4bPmN?y +* VqD\2R&l&]vM Kk&ˋr3b$qM:&d`:&':ȄЬX,ʁIjrM=EwqTui;zRz6Q_%mFi\܃npn:d<8bsL$&)WrQFt~Z`c9тaZ)ݜ[|sRnTF(΄Cwʣvu[۽ݾmAMXW{T*-Z{W CD";/^ G# NL5(\$":l1,)l9\ +Hmw|B +⤜պս`bv\A-z53kh2ab^mZH.}†;pǧbХ:{` b^:Iu2@ÑsZҹtV=T6HÁ`BԐ;bt.*ȋՈpuKu79rIn`'~Pw`j:e"e^[( +`A@6S[wA`mf?=\`aTup,ju#Zp 9/lcMOV.jӄP֜^ފރVtޭw2f_DMD,t@}wWͣ2ӘPq}vP@!E ŨQ.X4ȴG`h-|\^b $:˻Wwx%|BHvr4/!;C +驹S\q˸klkrnꘚn@Ej:>=æg)vYhI'H)m'9ྲq4P^RjNZPy聄ܸhC,pFFО쬋՘XӉ[*XHՊGtV,Jk%9/%N21jF^kP! Um6; $upc&\o\D +lǦm6lM:+wЇ3,܂V]8 Ŋ:;76X)$#Oh =mۄKoL vUWngg-=$k䒻556?v٧" +r(Ċo: bD#H4BAZn(%PsNf0I6-~p c 0JZ8ii>%D-G +Zm`ϻKf@U,\r9TS.mB^6ZV'Z.DL^g@ s@/Y.bl0ƀ#X.*PILt!7 +{茛;qWQ wcl FA;O(xļ"Uk@BGwtCŔtO +gg-sĎHY)[ TzIaJ'.Zͭ>];o{rߠ #qzoM[!LdX@CPaշ"Ս#J(%dGz}88j\9~H~: Rv$W֌psҭpyHmf GyBbS\-s\ribo(pvKh?T]{Y4qRDj~-ljlvP +o!8μprkS+`6oNf魭85:?→Np\=<Œ/6@ gPՎFm):=y |MlFFT@N'.my'0|'Hj2eÀ%A^*"P%{H} Rj^r +L$(%d֯p7?Á'7gYiSd[%H(#WA#LNjA_D\+j},Z5:<}m "hm;ُշ݃Dg?TXqj0R 9IRWKݽ煥)pݔKpuM9 7'chwX}.a~_r`}ES+:Vm0o^Pbm ,tc3ݛsQgf&x p2YD{$ekۅţT \Z"eLH{M+vLʭ%7Ӡ>s5#JD:Wk +e+bWT,fw -y`by 2S&KtbCÌ)Z(?-j; P?+#!10z +.7K@ZR <1GG=Y?fOhnTAsB7W ;q%:Ic@1(Sg +c}.o׀MuR>BfԂ-dHsr40?LZKɆ1)lVVb:Kw.X [FJ@)\8іJ@k/@bHe[H?"ܠ5ZOv{wݾȹr{Ɠ@Yz`_~Y}N-A\jEc|.^ٜ7I X9O,1`XsRq]`&Аvq|"CP*J67׮<neq22d=?*-z8*(U6fǑZuKKY`+Bf}ꒅr +8\ec.09 gO>]8z^[/WDu2*5!*!$%U6h dp OܔՖTSj{ꎟɹ0:rLK&$W !"R4BVL!":I9cJO .c6_$PtU ڦVZ83h-LFan|- i[:7D8R^|WUӉ%;!$x(f~zsV>Fp Sx ִEMH.WxEkw60zy1A{z/+AّS>u'rq@EFUhGl.qՏv|'\o]o:vvF@%0e^`5A Fyekl(.x0# Jmo0%]RIÙ=l^pgf= Jzg2gچ́xERfh(V86n5e\I՝dv2^b@rKZjL %#&4 ^.:>u%ýbw'D}x(Y[>YW/3j{o|FD.*bhG`ss@C,Y W&@w) jMty@fςHD}}mn7NjËҎňI\@BUw}T WՍWh!&z^ D?ZZU ;e]$T]8l +Rz&o ZUuiv?T>3YoZ1p2"y|87m3|o{P~ʧWo47&&MD@*Vgm`Beb 6e#!/ļ5TL 2HDj@:pFϙi9k)+~zWp`!@)D[)/T])sJV<5>ޖӋNL8{X &@L^(tgTF*y(xy1z9B.!DiN-KZ| .ۨ*;6X[\Aż/ ='p 'w.􈎷TSkx^^! bo'78xĂZ14Bk LN8.ellZU N'YQ+Z+IO3B^OJ/'VK _+vD%1ʎ=[|o#B }GcM&!f$r֎lW_05^BY/G(=VO}BƝ7}ZX-/"aVPkX`Jq/QM/![<ɳJG:k)m0&#; dm睜mTPjv<<^~[kyd<9q*lO`Kg01n,C2a N8dtѤ@dA&]~C5D+ڹ&N|yL]-&M^IuzmmpsL#Mx HCE9&VzeE z^عopN8 a +%r!".@7fXSoV Psōk?B-1ldާ><;-W@/kJ"@sAm($l|A>e LhBGE!X( +!4 X6¹Q./*U{(dJ\3~E$p!Z09 U?U9Q-T;qAonXru{Sga.CuT3^kF'ˋ~::9EP{ ^M;Iygd&|< +K2Zfb|{g?ovҒ\Z)-d; h{0_2By +(-3Xss޳3 &q{C0$t7bx}; XƆ [|7/Qxi;mWgm$y7&bNJv~CDԊ{ʄR'\X!\Gi6/!V2M 1qR]>3#=<:qq$%ZnA B @ܳsn#$,]n~AkK Rbk)'g Da.xV-̔.Y4\Pk QZK^pY<ݵa6N_[<|s'Gr,#B9XȺi;~~6>aIB ;8 +}p%\qp'vZ9ֶݓHukrm}2-X^5۾R0L*rF|2xK0@<-|8l=HwW>aULJsC!n)/\NLم!7Ѩy$& Tqif2 ה7m $))9xaL ls dvϪHnQdY`X/y{Li?9;/}." +9 ƶ7A-M[0I_8'Pi 2k 4>rъ`BiZ993g ԁǫFM^^MBURR ~6mpt(U@8v9W2#3VtIX&R)^4x4.xKarl{p޺[]Vp^/X zp !R#ow`O~GGl|{O{s17X(isLHB }[ܓne;#ק]筸_nl*b>^ puEexiiEL Ǚf(K&2G E$`Սk~&iiF) \NN4F".,Qs  toWvV ""nt=ʅM;\SBfLEPSV.y DL§|*눐!xp¨&2iO@ĜFB.Ť-ATT6T8{If`ΠźmB)Z>5FىY) p!WM_;7gNYqrlRLs64EZH%UF ;?ٿ=!*@JKPކHqQ siBmBBY^F'䊐++͇o_}n#br9RNo6Ԗnɾl\yDE3sqh2XֳcQ Nh3Ь7t֌M9H]GHt.|;;<*t?BŚMbϣBY'fCB.B F|||71R,ډLS7_AxSrc墓Lݸ_V3E?'t8ѴN@ +9*J' +Jo p2O$uDt}t!KJ589Id+\}D# ( # [1j,۱BūՓg+/z Tuө鯓,4HT[ɢ$KtA9[P`ɋE%.D!sP]^#xLF2[>6ycrNtҲkˣ<qпRZV"`_9;m!qƊA 줐7v?k@G\W.{F@J)Ņd瀉C fƘ\0bZhcE"N"5_8T,2ZE'\f#1 >AlJT(}:zo vl]{Y߸);+WTApJEj,WrALLjZ`W3!+ڴuAM>OnΏNx gÃ$R2ث/^"e+ PA ¦@u QqzxAoʌg#91_Zo󩾋I8 tiy`9Ofq'dh #6) WO(hI[G\yz_G(`#0Y)f=@p_M +fqR>LeY 9ROQ/Zs~G0CbqTDK Qje~sXMĚ~)KE"!;6{VLFt!W2{V_ >ZrdDsZ^-D{X(g{NL1L*˹Hay:zWuցYIJv;R T^{,{g i' P0Djqm,n]lpP +nѱrq΃Om=8Tv1/p2n'tPiʺ^]919jՔ^1&KgMn111;Vjd犛٫o| O6T m7:Uk)LVb9Nno<.ﺂY&ދ7voJnwᇥ5 AUta'5@ 9Yδ^s`tt뷿tX1ҭ˥0`/q5:Y [\ Kˢ96C==&ڦ,`'e.2)ϹHEɰ`u';drDri9՛L x{֢mn6>Mzx_48&WAM.:j†klRc~j]. ]6V M`)rϦNLN+JgDiH KjE$=oN +D ڟ)WvN7! endstream endobj 81 0 obj <>stream +WN^-h]. h{st$ݺ*F6Li4iJqs&b-P= ť?KG潜WlnJ^Zk@=\r=qઓ7&AAIP8,`L$^zWZ~{rR\ַU9 xJIK +`Vv`@U0VxLf~g?n>^}YX_cTr;*ѶVpxW6nHՆ=f_;k>?AEg!55VaJNXN hI,Dgv$;f3#-7;}zURML*١dta`&W +ifxb'3hՕHu1^]:zt;=Lkz9XP,f( VnE\2x7L(3țRvzs^e\Kcts WHP>noGWHi%،7x3nm?l_sST6iNVu^4tIb\Ds +[//^b*ڸ\Y}[_(O Dryacyw[LAXy36X/*7C.Gjԫk8c5?@(hmN_4T.z_J-ঃZ-ݛx:*d1)y7Zk+7njkTc(qf[>q;e.m'w8 si J/̻?;k`sa1,\@QAkOI03:ڼYe~K{g>鬜=}'Xn,ߒx[@j^L/C my 0q@blWT*"ŵ+}TFzit2=Qc'ۿQ[y7w]T&A9qɞ]b|vк.U @d /Y0hy3l +Dr)¤\o47O l@GkG;w>\:y;R-߸ƊV%5T,L+r?dOgq1'q|;Llnovi-_8}s)^эF'>~ƁpRgdYP]΍G8q+_މE@in=>xڎ)/~s.?̧6^4#.$T'ۻv҉**˅Pns'߽7tMDɩq={x-\b:pnn@8uSNg@&7cFoBTr_RMvUV)+ךwO{ўT]ɋ~W?^~%\PQ9 1^\֒: pg&ZMGǝ[B5ڹ]Yj=BۓS\bqljp-AQ[WrÌ^Hry-*:r4p +v)}|Tol^t_TV&з,? rgy{%&H [7=T ƪ[BjHb1G8=Rtۑ)R>sUR) A?y2A>5YΊ ҙV͏ nf " +-A :Dr_2{Xs[:,U&'ԓWvW@`L* 5IYn^01䪚j{R>f 7f$?C .sKfrĥ!B{mcq7>Y3rn28^&}5 .ZcԼc2=WL,PY }$&ѕ'ýO$z!One OxcA* Ϥ1IV`>[~pymdaO?&_-'dplG[o~+YX\.Y{wo*n\05V6 kZryr5kk:o}π;O>k^VVn)eBIk=+< D]T4dKDiC5J<6c_hL_S.Q +BkE %Tn bs\jiPnLb񉓅,eD$p%TLi'n0D/bՖN[xFN; 91bg-䦝`'"nwnyD.żÉ`b "&g}.N9픏PBHg.ح3 >w~ϾR]S*kb~Eo7l|pԙphEd I󫕕rq9x*,S*N6nGFr^R-BkG׫Cm/[ϧnj޳Nx~8KdbR!ڥWp0pKU\d sQRR2-5vk@hÍ(niQz.^wQ;FC9>;NXh1MKiK +'(O6@Js~PFR"jpR@'wzM9KtXш7#eBNat5VJVHI0^^*D(Tt>QK R)Gs P\drs."x +}LPK*Hϳ-RM˙fgV%XiHyo."JU0e\$'kXulnPv\^3Vg|٫W+G޻'w͗_{[ܽ|mǭgg[Zw^{ :$p>wQa| Q.-'7WX~ +0f꣧SJQەy yb4"Ukхx9IQ%$L':Ȫ _3C601WCu?Ǖf_,_}P),'y T>Q}yV_wdzMi.k_)/ݾ|XuMKwg>ф6Иpޣw~'\^/6L{rt׿X/ey/Q]?;0w^:Kduy/(NoHk\fY*l,u[xgK6 t4\3Vb{靷 7k33>;g£*=JzP zŌ)BVU7r2,PoW{K)J8?ǬL>qX}990VLV7j(/9Za^UR~t}c2*,?朁0*u4TPq-7@E;\uaDx hyN)\ M*hF7p1BrZmp{rn`aH>'d"X NYQW0 ,/G=B *?abnҭZw@Ó~FA%d- f%j>:BeĴ9 GJkZmSJ˧{.Բ}r(VR5Sɼ^i+n \.YXSFw[ѵXe(?*a\Xܼ6޽ eIF}g6X:;q &LuU6B{_ [孧BlEq-S s}~l{g6$#LIy\Lى s1BJ'Gd!&WpNvŅ^WKrqc`(e/b(|8 M JˍM0ќpf&ì T[`,N HRNRX؉j0qaQ@„Lʈ Jr TvX&wO!1F PrVQV@WIX4""8YT~.c8R9QbV"CN-ȱb0A$#B N?@.h`w8X= ^': x #(Ul)D<IJʈB>mSХyَDfX, +4*!l +Z/2'zq ^[4Z˙nbRSF06 tVԏG(VNqʪrxXR2WwOZV\)NF{`` X +T LE+[U{(ՍzI.`CY܌\jC@$R̀GXD}-R\sc)9$%z#l15+R'͙67I1ZJuAabǤ]hdH~xP]'h1Fg>@vSf?/9~24o"xfU,y0ftI S4. (-N:L]>Fpv{2 uKq0;;3^TAA/B bmaW NqgMyɆ 2cΘ@8@DDEpΏGA3 scщ3~RL;P5B`}.V7\2: K(O|}!^񊏔>Y= /ɰ،;ct͚\0Pe ^UREBIY,#%t ~aʶCz$qp7 +l8'F>2lva6ph8`@0:(*R 1&@/"C*|m=kFdڌ^E&ǻ@IJrJ jHvS7xhB|rg Ry&ؼĜm{NW.ڠP X!;@s%綸X & .r 19oGM`q#MB>^T MN .| g!8S"LIb}P-T(uj':gΙLVdCgf/٧fFh^pp)_rF;X*NҼ%$ڑЃaZsY3Wv +B`{^hB(V7eq6Ҽh>7HrI6Ҽ`|//8@wJD߹z' n罔 +<\ pp|_ńD#w;77mYɩUa[\Á3LPBtzӫr'873Ҵ ( Ɓ݃{E/uyp7gOn"lXH0.3`aig!]u9g8dP2nobH<%JbJA=֚3_`0e7B6'NI*,dv(Sq?y S6Eȥ99`qXP G3Nc!n?O G2$'Lkcƈp<#&~?W\f8 *$`'$\,+ɋ9',BKJ4Kɬp2 vXSUYE/R2 rar$P]9l.dY $ Ó~t^RQYP XMPKz->b-ro\ćs>{ȋ]R 6YKaoi@A vGbN%/"-MA ! +*E}S*)I>r!R +H!If3ܧ8 /GEP~弈ounrHT'FָzpxuŃe-As*:gřsvb>"5(~ cͰ8)9=)99ssg/X硙G><;=s}~c6es\8.Ѡp'q&A )>7m1`少rVzLF-qestc}WńH*ً$;2˕z(‰i ťRIY=}||ƃܴ1m<ȓ aVxTN9<ȶ*J2B]ᇷꟾ'OWW1 ʧ&1Z5mg\T擉8 V’Xڣ}'Ы !BsE XT*f _&jxtzx. O0rr2 tz2/Ǣj&&fT|{r36Ռ9?/oᰡ' yP@I h2A8A[Hګks͗G~b^ ;cu@ibp6#9UKܠ__޺{[/<|^qg<hf0V,d/Z_4. 9!!Sܨ" d1.rXRgs4݅X~7{t9FC-Eu=\|uѓ7;o_g/l\my,T<\ɊK-mo!1( e;~fu7?O^^mYFŋn9uNkpV!{?{_ǿoӯ_{wW2rqAXܻǧɛF}ku㏿x߽ϯ7=Qau{t:Rh>dcbV*­w^?n~O>O}z`sJf~!|uu:^\bˏ|/OOBr",V*Uz߹/?z~^ϖy%t;^9sStN@h$ Rh(1ؔ-UY%K[i7Ss?vu;}߳_w?_럽/ŻdwgZ9VX[]zg-;\bZD/&ʋ§?|sWo?__?|}gpEp> +\lo]O??z鯾_~\?y_OŷwEYbkngN{:W_Wwo?ɦQΆ%y1&pnE߹?|?~͏o?ǿٍkpI!$UͪF4nu>W߼/~{_w'<9vZթz"dxz>_TQ3/)>;,֫;o?>?ٛ~u*i1v9VDUQq\$K蝡Y;>ۿ7gGn 8H8e,aѤE'}2*mݜ՞w>={Sľ;w:@tZdl5_/W^1^N<ճϿ}o~W|GG7-U'$g(cDlҤM<&h/?<莛%(q>J♤ƒESlz¸܋w?Oz_OAX,lQDt+[S%t=yrhTfl;=w{uoI>{U,M 87FZͯ MpLc銣WI~ƬUòEC&6 Z,NbLFgQv2k?+wW/˳?/&O=K̢$#qLù<ʸ$"L-_ >xحhyTwo~~/펋fU/Lp! N6zyMlӗ*:װiyY|[}nuKTUbBI~5,aLE:G4ceVF*xEe O1D'WVZ)$lNJ|c= 3'Jj}3m~~~9iwmc6읆0j(Jb:S֥h6XImO-+ش,'{^{GݛݞuD/An2FI>ାlw Z^ Gr$7i8EjWݝQsc|p49U{X뾛Hf/-ų"[+(Ipjrmʳ!uG(DIƵO_g{+ M"8I%iw3+ iuX{{0\YVTꃂ_8=2.WtèicJ,dSh2M(dG 铼R(L!@Ks|wGjy;X +,JhnW8b8i2Ѥ򅮮0~y9ܜPو䛫x{}eAr{Y0C ,EgѬB *S9PlC-BZiaP+o+Z') <{71&YJ|wz@/o֒iʾTܥ&WYݹx5DO2B9Yf0]^B'l19$pzV63J+J^_+dmR7f+xYH]NW)MKJq(aI;s2\1C \heXչQn+G4(f+ˡD0wJfZ'+ג9#4xoF8[Oy,!Kf983A.O&z'i?k-NQguMBq7 +fuw5L&YFpXG&V&5 ;rqsiq^ VOqdJj ɗq^szkjijz[zl%k$/xhٸXwbri7//b9X +"w-Ɲͬ~5DmiR92T0diGڼRZL#Y4 zV(lŘBv@i#Z{7^6wnrqڼW q%դ,-WI[w7<Cϕ=&*aWǒ櫬-w̻pH!̈Nvq- 3BQ+o~h3z`hE+ui 9aJ36e'obz +ZNk)/#UQ=g9K ig7I&ək)v#Eq3یɝpZfDf7N{v3G9L@Eihn1vF(NVi"RBV"xSL6&u88U\iQfO*7rS\-+\O,k-.Ynf0F;kt#f +Ck!FpRCidKJLݸVcj0ap}~N9)Ȓl6v' ֍:eʶۿU8ܻ 0w>?}P~&8C2 L)%TݿϜޘ4ڄ +3v#DrWB%\Eq%SFV [@F)*=q%`68WbFw\$\Cf.avA,{}1?n@8n4o؝s}c3΄wh{ +s5&F^?Ƶ9t~'g X)Ug—s,LXn6OWSPz)CK|.$(_,nk-/f M}3G v-lU;н߼y;@F2mI=o`Zb hvL>8w]/ n daunR*PV'<7խ{bqk?ʀTkj\$6g^𲅹\;켚ya\*['/l>8ACg͏emrNP3dSs7PT~5{bڨmzUZoVS.voI]~La75:~ɕC]IŹ;|B];%עd!#6ڙֹt٩>,B8KzR@B~@Y;Ͽßywz5.nokzX= ۽괞RdJĸ2ԏ?|)-`1Q\]@*bL{\N_ Ҋn4'|-p/ʔʑս*ٷ4_Hus;#Ti-ҝqŽy4jsp9c0Hk gia0{ԎPӓbQlZ7? 1{Q߾Vc\aF\iOj`zl3.[՝훟JS2\oQuNs?n}PN +:(8eF+PsǴ?eam r-6Z70PFcf<2j/߽޽OBfd5_o~)/0kLj?>|O瓋/~+KR)ͯ'W'IwKZ=wSlpgn~}{uLj#!\֟q}ˏ_A~ӿv'ܦ4_zXU;)JSD,Oo\×)q)D0jt~wYw-&:孇PL>8x5v*;! +.l1O~w~ے7quc~Ra+ӻG; PAk Bȵ[Yf w?o?%ݾUl'_7Ͼ:{w:Gnw~s!n^+MM?<|]ۚ/VnC9sO){(c"kԎPNϡ&ѻ5fzmo9Lt>BybqR\YқÆY[lq ZF*KdHZgf88I,O4jzcr3x'YPkhQV[f._;rȏ/nUӻBe_AaZj0ZRxǿ{ݳ73 ޛ'4D8)d{/j*{/\&O3+٧ݓ7ǟt%Z+F9jPiÜ88@W|*@gz)]Ka:VIk̹Sٟ3 `B)Ldv)ޗv 3|*!N灺3R0j܁^9GὭ[nXv aEࢾ~~_X37B=0GwYhWLBu?7Z}Opz'ǔ;gϾw7gw?4$z;?9{E\a5`o~h4vM~ov^fލ9)3<AySlӎ|15$;/GsD.ފ@K +%P  N߱z7JF H Atz?}Ϟ>O]0;:~ 7Z,=/Mٝ32ͩ+j^rDrOG/G?Q: sƝ?ڍcٽ^ݕWR*g:x췺w&}gxvW:oO(Ɖ\L0NW6XbQ)\p!̥eS0}YQΩc}DmZJe d:wg7Gwo+ J:RJYL[[yGޓ8۟O|v.%yUi|0$М97(QYAo u+I4:8x/oiSufvDso<ھaox*1oudziE~w^3UN}V@Rc' ~h/gIGfYӝ?j~ +qџ盄w1o*_)G՝gf:m Pim(Ɩ6qȳjc험; :kA* zz{ s"woino˧rV,3sn ;Vk;Kzm,Z+ +L~|0{d-0qf:?}<|)QTvk"R9"HcPݫm߫#jgbt8G_^3JiKI:FYryZ7F'Gww;Q:/ʩX؅!^ƻq&gJ붻ֽ'vu!/O!G" Ëh?CHqwo9ŴCuJ?'?[NRև'vB(v=B^Z#Tk$Vi+hgW)#o +3LnnY_R&nD0[|7.> BtQvmorY,@J0Ƶ6Rj7g ]yh@<#dFZnt{__K0%̎=EF+bNy[R{ffayfw+;ORB4Z}g3$H/;uR:Kp^0N7)`d mn\y*Pk1&J(ZBmA[[,qn?H-4iZ7#-d_8Kz^s/JkdIJ8;%S:ŕdVz}/LJ b*w8D8i5"ebC;7ˣG^"a)3DH CB}g[C:s@Uo'?Vn,l$e=?im߇.N A04ꇵGfm?M'39)9}nìX #UPRՒ|ƒ?pSl4sw?ۛqv5gURsf{iHu+`Q+/ 0}1;Jܼyq`RXNe2?Nɕ0ִZGZl=PGRmOCx!1zV(F^K3[UǘT%X{4;?fvZ܊sǔ d%l8ʰٳ m<_MqqȰ bJFF!>!|y\iguk}xx9̭g4\%j.$wd69I4v0)d:MھX1>nh w&kKE7MRk W PF-*[;SRnFFnH Jn\^˭D\Tps5ʥآ< [ﬤnQT XGO] B-jF,-T%f@F7V35Z= 魧EV=l?0Je:Q/ϫ[c8sՃH΀jn%Hq*v;vy{fnA!|~z@ )#4FZZBQ匞΂p] CSE:$;ĥZg+I0(Z)J)WkuqxZ @X.(33bSK0)zM kW#L1BgnNy_ Y&_݄^O  pIF^Vmlgv9V$UjB^ũkA]r9Bbg#{ioI=t13!Q}bv eB. /mjFn e z=E_߼e7rA@骕ف$/Io#.V{)z3Fi/0gҌ&HP͇Wrz/\q'Djki:u(S3WGG՝5BۭF5:Kqx-ɁћsZئ!V5wHFA*G-Z0 4Do^Vxo8m ^z 2X9H0͌#m *iqݏM6jiR?+iaoC. _.8^mvsD ~,4[-Bz_(ANc/6 1҉nVA>]IIQL] G Y\ h BlVxM$kJi R* i _ҋ yfgE<FDo]zC"v5N| %怶 p=HarjiLBYi1W3+᜝3Н2ѣѸavns&_9;QUj|aKv?#I<ӔX-ȕ5jbBm9NghU4+]e!AOvfq |w4'iV<}tFJR$#V(gJ[^Z9NpIXy--MD'qaHfq|SEi-UX_-3yުM?OUm08GĢV'wYgP螶PUy +i<ڮG(!nB" , |QS3 ^gFR^VnsE +hi/H`YذGaT +Mjfy*]k)a5JrZUvCsߢ>.7ɹ;^pI䫨Xw,Ҋߵj{PZh1P(APZ]KAkuv+(a=U2`J$ZNRr1|b~N<)3Y}@t>ϐ2"at!>& >fZYB`G8=k.NFGES˜?jg + +vQҤy1n#[#K;8˻qXxzszztP; .rJ5F ӪB~Fkޤy83`sR~9Fp4zQCĚT݃^eB)LjT䬜ޥm(!%;k)W$g >G"̉?|89potN[1\7 +sDywLJ c9V'ЭYj,\.n +Fq=/ތGi`s2M LkPҩE!̀ +Y9#D\y3HOqɩ`VP3sVc\)bNil+A"xA77\s(%hU9\hEp(Hn5snp. +3ٟDS-E@tTa5L_-ցjzex77|{Чb`=#4v2ڄ;tޣb!\uA2d9PwV߆% J\c# [)%PeB)\? 4Yr#cRo#rs\SjgJ6iZEs:i7Rj0cRwGޒCDsfNoޠjt&Z].4 g)&˗d!Ja5P +n2T,\` .GnWCJ\/HaTY]Lcf+1[["riOstq7BceK!rBY[4j|aۗlJGB͔JV7ߺ^\dJj\۽[PJsͬ,cJo3mRjݛ d(:E)aW7",geKLrbQ) UW*N<]ީlWj@YB}{x;;# kJ1ڌ7jȗoGRai֡vZȧXX";ٺ}8Z'͙=RZv~q z Ү4D +v. .Ԇcڔm#9'Fqu 'VFxEHzJGaWЋQ:e罓P $|(I ޕJNFj\ bSr$G3Fq\DJ0rJ1 Kh}L'HD;QJ^삂ʔkWR}u&WCtNc29J^YS%Mr-BdT9a4-Õ9g[I*-Dz*' ,.robkY oHpm-HbzBl\:$wm?+QxCFjX΂.N2NV(NWp;U'B6Ële6X +[:N—KE ]ʛC*/8=XAHݜk9{ՖB+*-5YJk4bu%)ƐvQƛq=|b-FqPuw9!tFFCJʯմB@ jZX +!PBTMb_w6)DXCD끡 Ӕ q kZ":Li)/*1 \~%1x\^Upу@Mt&.PgDflw[qL % +EZ fo>Oh֒4cΜ% F!6B1`@*3%I.+40c׼"WBII`o.gVbX\ܑO(wZ\ 0[N h=+)or7.btPK[PXL~B"(5b~Uv8w@MʬFI}|^E* iV#Mt)͖H/wZoq 01^2ҏ0Ō^˅Tr"US +MEfVb4g"U/&WV7 +&wLu5g$[&a*ч9^ǭooK8 ]9lq'Q:']!7ojգ{ZJJYףT#r[)4)gœa:U6}=*KFJOryȃK +5`xْKi~) _@ 3H,@#89@qx`#-0NV+r{g5"'mOpNnYbФY ui%R$KٹjzZR`Z $x +RZ`܍{%Q@&dG?ӷ7_2 i6 *zyz2kI H Ǹ)TNPv@Da̰r#u!iu ͌(PlB;#(4{-q[J|(:#SVN1eM){ińXVaF TT//J,J%F0Lb[,JPZFH}SjL>Jkbf׮EJo+_bKrE#S A3@NCVJ6itd`(Zbl4^|6<~7-L%-7{=)m"z +Pd-T]LbGtZ빜Ԉa&P.SBJ})=e=ymlB5.MZ $%6j!|ׯ&u=Ŭ-+93Xa^"g]@#r*Cji=hVi\_H6HfI SKar#%攖RڦN+3eoӬDz/ֲWD10\1J 6̈ULkՖj +BJ1IFmH@BATT3> t$k*rrPleqmhh( ;%04*KuDWT@jj#(K1?8-!j7QRFFCL GY{n/$ (&IkXW(WE)P'pQGC/NyF0M[w۽QnenZi=? e,*r\,B)[;1T]1Ok먣oOisi%Ι \K7ޮKT(q}Pd .Q0FZ,vjLJ|C1GJ'v7~j|%:ťZ8c\YETj i \C (hN]~\pNFp+I;TaӾ%cT97Q/JH(('͗!]wAC(EWbZ|h Su6?q)Mr y] +(m֏ +@))P D8;Nq + ôRJ=q6A/LWyI% Z@Ψ\eat ! k(=`VxV1fLyd|)(!!G0MBSDp `9έ%}S\J D]h nK!ኜ]:W.Ÿ`.puxjBhm)AsW"LN 05tԇ(_\^JD2 bR;'[_v +LJ;\fv۽(WݣA'Rƽ?gHUd>Li)rZ:~N@/9 \m@Ƈ^,C\р(se| nV?șbG03M;iJ4L2pqoSiE)\Dڍ^?Q +gRBq3M/G6D0#JͬeQ6O@Lp)ڣ\;J{1]Y,1%#Ubl 8& 7D՜QGbi/- !d`[S7r#%pw5|z2IgVBq]P~yC!)V}Rv4P6q×oE5[[(c)wbJi%( e"PHL9ɖ+@j[N!vTJ E giRʪk1wP6)% +:gϝ]^߼ zg%Ψ/?s7Ykq;6 |,P~~7 ƖRl:Zz'%R +fJ3b $dQcl>uSċ:$,_ &)WrzVմhb*YH]aI>(FSB޶z`b̊Atq"!N2Ƥ}gD2 pL5bh݃=Z Kk7J|!%GXcLlr&M]'c (낑EH'vrqy#-/RE'D]P'X ɮFb5-Ԣ,G[iJEo C~e3+ GI2ZZy9N}`0jD+t=SⷮDˆJj-\n0je0 0fd:r-L^ ,d:XLY[Jz,[cFV]C8};bt kF LjY +s -"k`9.˻J#CDjz%%_qZϨQ*r4c|c "Fdqo@ 0j !\葵J0i Rv-*2 :wzg_z _Œfx6X{8Dߴ;IL!IW crA)^BdƙZ9 ^Ɣ.\\ ޺e v/q&Ncf1m pBXV5/mdVd4g,=h۬:L + =RFBدLnu!`;0bR%A O=op]Ë(].Z.&ъ}e$rr)@SԮپ%9Jk[zkaU,Ʌ롌 +aq 1l"Xڇ=}gO2EznP8((@{Zr#js9g 3Gfvq,LL- Rɔײ(s5B')ϮWOkA-L1fP\aB RSښP.ypkQzzRk6Js!wڄVuC(@`+LJ3aeT;Cx8+QJ[v2b7/0l_QaiaKl%N)yL9 {7gL qI.V8gya0{C\kn&N R# Ɉ6Vb?p'6­HTJPVZ&0n] S/mlQ ZX 7$x ӻ~{5+a_ fpyNmr 'y}ٟ}Z*@]K%EޥP.AgXvY0-QRZRz{%ȨPa6K8aQ5icV=!6e A +%1n%$řUݱpl*|ZJWR-=~B $aqx|aY:RYIp!X:U:h{eJ0c{_D<.t^'Y8d beOok(6u uq@ZESD.7I:VZFlC8NѮnf&B~F[11SP.c(K.Nkj!] +?_ r?-A7N8ov5CzcFk6@1@"572Wq >"ar6PhZJ00(j&Q#ف[F_3;xgi'm9?*Bi uB[ku-.nV#䂂͕60c MLHu~^XK 5h( n \^on`7J%)F`9TC?BVZI +|E,\(=J/YбCžI3)n%AQn%&'䵸-.$87 LePBZ=Dim8/{v1@UќFh5ڬJ`/vӗ|6A7\~Ӄ9-L[{ϫ[Eoq^ޭ؀Dl9>p{t-mą@qB:jC\ .; #J7-rƤpT3`in N .<})U!tN:U J*Ҩ ҫQz0 TKr%"IHg02u\){\f ^+yv6$@ep^U?]|Hw *"FZn{1YwZ= Dt-!,6݇It?+ny;p1V'ƸlNCҙqarvA~AYĀZa:XIMHsR?uۇI.d]?8b񯳽 X'V@×)h͸ʧGgdJi;F+-`86 @e/<0j Қ@Rݬ,8! 8Ŗ۩o +S?m۵5Za M,,h +-4}W]|e`r$PJ((.4"I\)l zt_^۝+liǏֈ2Qh52|n았XIQf/_IՃ Ti쵨nV/!r]/_]%:Ν\F&am6$'*)i9Hqjaj5)R,hY!H +%o.*avt<2P"D:1LPF[X + 6m11dMgnݽn}! ,ÌOfʖ o_oYY6PؓU[DY'BD9(.@1L;h(77||{q?1{_@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nڸ 䦍@nDFn/~coO4OJ'~R9:b%KZO\A5):E%PIAh_(N`CQ$ ?$vQD0CQvc8`"8E^>n'{?aBFRP/3;SOTLx$$OiROޛ| + ']t EH[yf^K,Q5'~9z)C?iR28%:e6)kINz [M9g@۝Xnv +T5!J30e2cր.l֗}q&FZܾT\%^\)Znʂ;J;fԠ2LkŹBLcjzӪ;Iަr&-/Ȫ "R0+č^7ShQ ^?Lw.:!%vJ0`lTp)B5gar=dL.Rz&kuZUz L~܊ +A„Y=!3"Vt`ɶ>jF187z)A‰D(B6p8Oɍad,L6J"lчE~# +e DBtӒ D6=BRr LY +ъٍ!l?jl[ NJnQzMt6<0%2猕CB#  j3HeM-d(ӋsjE\BIXgL*5 `U(og]ֈǸva\GTܲgJu:"",SuуXH +1 DŽR330e)oTB%Η)s#mDf#!P!ҝImRG4͓>'2fw~usuL.I[*l"=!ңXL=0b-&l%ocXFV\&ZB%&Ղ"A S0qo;(NII+Q<a&ʕ#uIu=*2̈CmJ=Y eƙl/jj )Bu*P~2Y+Sə$ܽ@(9;zA:M Hrͤ4@o vtJrLb1Q^$D+CvbTTѫ?[ +rAD(4JTᅮ +e!2!Ku+LHLi$jLP.lc&GvNX*pAX]X_&3*;ji  P{rq H)BBqU0C:z@=HX jL%V=.l~QzW^ +4Js<=ss֜=qڇao_\rsT[ajRDM@eoPʼb|IP>2IQTz6*G^@ȳ_IgE VL8i\ވq`!FfdgȚEϯصB* >sƞ*=9PYRmx _vn>qpPӎQ;> rvqȭ(]Q9R V3Ii-iRLAIOr0t/1F^MFСkX?_Yۅ͘PIJUr9m,VRAo+i$)7R7ܑ݇Zy[g;HDiz'øiUC<7s4%6-5q(tiJm24c%@!ډH"m삱;Iu ,n8+;kzuuraLt8}i&z?&lbr{O湷9XWa~XGԀu11 +EJBijz +@ +{/|)k=m$ \i`_Ĺ,"Tg^N0fzLLT ԃ0rOn&(~S@*ā! T &Hgৈ\'1:@WxT(B=ĨLJ(#\~#/.SqiPyZmZŹAIo$5?fP=DQźzP.Ô{qq=+!*%ՖߋP*3et(OHuD +Έ5Q(iMڙ]`Tw\*b@0Z1@UfR6fR.cJ_B_ k14c eKR5L0gBk׀2*)ۏh~@ +.̈́Hj$@jP}94!7VσǔzJ6@4U$&SjNٍYBI +k9LIaR.,i.QyrG١YY产B~C  Ϊcr"ahj#; Pq\m7WLaf2}C|).Rz[ 0k;)񙁷##^ݷgKaj=TVmCnYJk{BbFxvwʛ5(?p")-D9mM8k1QjVeUk  SZB9u$EEeGŵ2m*&#g-ʃkMu)=ԏYk">*IuLjMPqH3QG0KavZk &^48*At'J]t8LT͸ +U8n3J `:<6‥*|P+8ø"o6P~ Wlt9!iqY Eݢj j( -.VQKl2`\A+м,H#~23J|n#tL)fKMϸ#h'Ժ^;hl`p{2:B~T.]ׇ݆ *$f9w*jRBI1 +f.iR)}Lps888h DoǪIuCt:b|v mс8c1h &`& J[q΂{y]́axЈ M ~*䜵`F"0#a|^Лq̇E9($ZJpI Xn|Xr$ (*@0ኙ"t84gXƇRDuu7@[1*`N&'3~D^p`12[ ,;.4GXG"\HV$0ab%'8p3R܉#2;A&&% xgFP@`DXQ=4kl' TNJŤ\ +p@e*4lvzeWxUj?N^r]oX;ېP~fݙ\=*TގT>mv YH*P3@8ϤFL*Aw`d[pG|~`qrE TZ!`cd:aau" ) ˈPEat&B7ZB;E6G++9ai LHq:&ie)&bD$Z_bO֣r5 OCa j(ezW0Z6esZT_n Eb ih +_RC=)jL>a~RiL.vg;חJJ FoˀEE-vy%]-Oe*'XT+~~ä Ӄΐ0[a\=TDd"\&Vv AB6T4;ji)}۝ޢøX 8 ^*3x]ΎrQdsFlF thg ,,Y_􃔳W}(FnuJZa\a똶IpDTOK[oqgʨn'B!ARz\_ATB0<={ac |(fo&$6) ըM{{2DB s |8B)O´k!]րl@iR*'? l)JL /SJ1Al"2Կ/i@EIz#bJl0Jv'w6*&pa}T'1mR%Y@EtrRB48C&1%a92I!rs-*+N]i}+#l iΐf7ۻd󋟮U.[oCiQ?=-Hq;kDTZۋ#T魓tiϴ@MP0zPUD !90))VZg)f bLPj5/;oX ;]*%a&/z~m wj'G_ ՎHPQZPY<T[ϔV,pM(+Az|F`ll!),v.Q:sIB3!Aׁ +ipj*!ARz秔Y_C`Lɻ! B:ZgպdS` 6 "'H,cvch͸KK-IvCv:E^!꾟؈Qr(w)J)65ka&~Ar5$Ё&* 0 +kQ7»v~gZsX"J +y(*l mY&ŒVZ=\j2[dW׋Sj ;l ))BM3JJogJ](Evpiս wg1uSSzzJ̀a7Һwf"2tTڠU¸OjV>L׃;v|`Ek ku4h,tVDŽrL#j׬gόD*j #LP #?j|+ko$d Qm9ŦGfT$jRImhB_ 3s-VGQuT>BCi\XFFL4BJan+A;U(sDDG!R zLU5ca:Cq4cޕbp[%BNADM'HI5"n@Wh$d&6K)VCFB ѹĵ^DJJ2F/JY#+`{ncJ3p.gB #,BeKaԠ^$btּ"PJ 誹-bq/Wv7xLJF;@v+/Y&z\Hwxb+Ҝ}|MB0r3S:'ɍ $Y(eQ`3.y*DLpIBm\0x 0u"ɗ`p 1x7Ji?KXztKÔ0@]39w@o$Fif~@AV./iBJ3cfX9Nj-X,LiH=~Ǽk(aF+Cd>,"8W +Ӆx7IrTpE1وmLp ik?8Ji/!Q2 +5 ``} T!uQ|N ҏZw6q(`p lLwL/(]RkF#MLOL,z]rg$MF{fDd4> +ZPZgr <.Tc+PNv?wC +'_$"+6z-Ƥ4*\)PaAvb(Ag?w61(pFBJh`l 0 + 0Dt~B#Cm&,?@L>V2~FBΚCbZ֎1OjRkTwI­82C<"H\FH1cJ)˻T}97r[qѻAXOI $V+q2=&{gR)wcD(MJKSr-<{QHӯ|0ը'nBSJXJ|&V"w6ઘ_D4AW H0O +PP9q0]p+Q0ga&4B :"KA@;8r(Z!- ȶF [Y1+Af#&{ gIdsqq5)OP o,P ƎS&Am~ԪRv(3.@;l#IJy$8\@Z3}/D$FnH +:!5D,ui|v`rC0|tQjPdIJ`W ar!». #81cNFm&L%بA dLqvc-.34a-JD5T:iX1wF + 5h!P )?]<,+fd 1j73y7D`CP?Y ]GDI>8SdJbf|?&܍);zb>^ i+C@qŠ0K(tǟCB׀h%`BLS#j=ddu[\ |<; \-tiEpzqn7n\H 8D XU0VyכPe@_><0#L!rq6HwD킑fu q5!F5P͘}u +LhXR^H&(s([Iƥ@R8H 1ZDF% P@1i#&\c6{[,]S s"4TBJ] s|? 0mlCł{ww}h$Ɛjs3)3䋲 n$AŁZns~(ӋpQi#*C;xOWBk! +߻Ρ| Ի;ؠ {j\12l`ޭePޤE(fِb2#ġgX3HRF.t<_y/Y)=)72#LkSFқG,ECiH)̅Kji;gP +Qy\mrNd{Lk̽S@Sp荂W3DO@ + " kmDnbJp,i?r38l" LbZ# :G+= e/(&5Fpy\n׏;ybu܄ M, ؘ2d.P &Lq&Iu݂=WY6tJ[)Q3@CPhv.\k&aT>[1>%^gc|%@ TkpASZ̻塴pZFbGE]ZX'XKQ\  {)pv.GeBaT>P +مUna󰂄ǴNB +av#J>TxwHwڮUI @XALHj!&Όܴ0~7w 6;!$3{VznvYw)XJ:(K t +d!fkˎAnpzG/mgl>)ܨ8`AL,az̸ŽXes[cuylu.8igDBZ]!?I(\ +yL˄P)/ƑZ݇ZAV- Hi=D䊟|1ý.zZ00iF<)!pm4t~&`5#P&Vq}8WdGVND.CNa)Kc%$&h^3`{ OMD|>[PZ}=&^փRY`pptgϨ/ʸX킣r% nK2P?kIp, 5Jjq^.eAGK=!;gH7SMWi=}('ba8-4.L/GRy.Gj~}.Z#R41 TZBA5}+{-&ŦRBB,qQkryPk^89t`S(h3}jw}9;j1Z'A.O}uf#GXmT)C\ 2f#?-M\`rD(*p1 #TC)J=mPLM.=badzPFmq: 1Ϻ#>;Ƒ+ې<9;tg-ekre&"Ҭ5_|yΉT^f].6ʳt{?!Rj;l4,+1&)p(&({s3t~=ĨC}&RJkem~]_S@ t78tfD4 MWSsc}BTv\m<5։\˻bq;>~v| g6˶;nZvq1 B-hYgztOp:e+FXGٸ} LHl]?o|^]鵥\_N6vf _ե^] +n=N)5TŹTs{}Y^\aUkZe<(̟iw*fu+>T$aoN+#~`ڇ_sLkn$eLR.);85GN}yyj;l] ˽_ *Ԗ2gwju4<'6:jDFwݿܹz7vg_ngWC{X]ξ޺6aYe6v~}Ek;{+2'Q[89r&O֡R߅oQ%$5x/Ku]}y]e;s{Zu_ulwNӫ]`zH)́qyy} +T2RFgɗL GJ [nBy/r'lf l@`ys\Cc4ghmu< Ʌ).i `hknO7^w^,>J{mXy>{_tsg.ߴTq>evx68oG )gPuUmqi}1jv R2i󧿜_p7ݿ3j{ZxxLXwa.K*tn8?y\z[>\kٹ,.8G?'ҽ0(:on~;}q7[U^L.~O|W?KeNr9=|tW;W__.PywNzg/_;jl{ju+RyatNɣ:>).mv{/=t:G?+Ϟv],rc8TJSaM97~}n{UQi0j,-wvz{4Vv_/*E(Q(? zl۽s({s _QSHWY<= NZϴ6t|qtyZ^)n4yyP*ΊufxFV簽2 .O'o!n{oX\@Z<{R8m?\~}ݣ˳Sދ~_Xx\lOJ7{yb~]W^_*[lgriK}zǟ&HՄE<2{Vkwqzq{_VϦ~u2~:Aiz??w^}FuWjc_<,N9ݣl89 kQ.ϞP,~~듧?UCx{mj~zͣX^_iw,,>|=&?}ų?s,kmuj.G[O~RZnOd3UN_ LzPySZ0[ǠڎO[OKW@!&y>%fu鞴v^|S?aU$DCʷ˳PJ3*esueXh.G_Iؾ +Oξ.T{gVc߾ߚ&aսLj&頋{5J]|/Wazeyހmln]7wϿn}ՖOjW\Wz\{]F7/?!=[zw ֒"(xRiLLAu2.(nԶp;juN {5%vƒO}\)$vir +)XڍŗC6?gA{YVg=zk^S>U jkZNk:2k˝7¨|vӿ +sQiuq"=c5G|>x8}ax_ xr8L;Q&  HdtŇ?ngxlvˍAW4O:`.iuܖ9n=͟Z%W[;Հ5gJ@̎=LΆ)Et_UvفN%h(/;Go}w1kyVww/t{Qq!g6)IۍpkE(Mvu7ߪCj; S}9%S[v4_:}`wB[[=mKlV=&pt7vp%ƓZ].L@ps2#绻q!\<}ɷwZs~?pAovxQq׍gÌ؍CPR&>Wc0|Q>rPվH.j;oҽm^1>eR^:stk˗CLGƻݔVao :P#%; ,giқUhFcKB~j4G{G18\vut?fT~<U&Wy,yt.JLtb o^,+eVSr\k$$ SOѶ2LuLo'yHo&n, {'X,Nn + >jjl ̬ٵSs}4BqPf\鸝=w`v)n+XM!7({G_N7XiD9'2LƏA\m_{G5>3cX#]=yT.d'PVJ3.dFuaշ1ZX>4y ret:78O%<}W"X貲NY<}JP*O{{KGݣ Ͼ/ڞS +, *g7sLhtngr~ɝ.PĻ<ʠ{O>,~d3ѷbqHLthyZ*e3. njl)jb\'h)7sӸf0R`]!"g4rt f4 .Y 5ji]wtKgo?iZMOοn=jmK*L[/aE&gN^b3޿z<.KjsGyqt H!Ox??{uϿ+};>B*NjLL)33VtݨNaV +Vz෻!ۗCg4h&8Ny(>o=m(~kU&4{@ P4I1헓J~YZfIII9LT:1!t NOMQW?ԗB6+kY#%Δ'WޡUՙQ9 +8.IAsv=T1\fRp{\cw{2u;plae2yDʃ2;>DRQ6;~UeyWl&Ss;V{)W`Ez0Iwt2ҪA1KUCg8=x +CiV(k+ +*c5YjOB~bzzI22 ?)S5JӅroXOW[[go>>إ[ޚj̏i̗vQvp6Nbl1?zʃS?<}΅޽ᝫ/>o}/~{ ,9 !:\'&BIJp!lf 3g39sĥ?x'??x!V8i\62Oc&'C6aA3;0D7Wvݽ}=tbiz' ̀ +ţG=wGx|O>?W_8_7a " + +HRxѓv.{Ow_z?oOz_şחOf,V-LjӬfݙ?>+?~痟O?ӗ>? ꛟKw&(©ly|ri <ot㡧~ܫo2-7l؈0ʼ\JUgR{vakG|_}ڿן>O[\Kכ3 Gn:}kWn=?~7_|o>|w/\\\ euNu'H\iym[n=rO|w_}ʏ^yŝlk#dX5Vȹz(UjO..-\<G?~'_| N~_滿tV{qO)1C_(]?vƱ W;}ۿӏWŗ_~gON^?ݜs yU!31 R*W-o?KϾ&RePKϾ_/??}go?_}o\sلJ32:;kFDBkq}G|W~}77>//O_>>߹p=Ǝ)M(#|r>-֯o{~{򫯾>y痿x_}G>ݍKX8A`XaZcD8Wnn윻r^koއO~g.N/ncDm +VTOs Q Ss.^uwO$)&uIZFi@DmB(+ +TX[ kW=sS.| NRB֗RN ʎNMy|kggVEb6/?{6OMNzC1&utE##7N]4&SF՞:vSO=o}_okҋ?ﻼvИ•An +Pp 0zD諯~GNɔVm +MA!}HP(Rz;՛_>q̹.]|[?镗ܳO?_z6oDSe;uRFl2  ?_#_?yYXZ;rͻӡ]@ FcDM/\+Oܾsg}z.\]XI*pFTFBv fl(,6gƧW g@p39; #Dj w@80f'1c9!II1BNE^ČQ! !ZJQNZ{c pI"\.mL,E+LȰѩZWkgfRe%I+P&d'|8#b0xRpHTjl&1>mF9;!lKķj͊E7BJAQ +Kj>Vu)^!IXQAGGmHiTLn#3AT' +x܅ˇldRzNOLH `T 6_TJ| 1 /±L('YlsR4/E +@<*S椇a‘痝Wm&~+'O E:X@,fd!VIMҙԎ5[-D,'RcA@b1١Ψ;bt=,Od9 H<0> 'b*Ѻx`t{ՇVPBMx7u]ޢ$#adþbx;3; k`+C=QoJ9wx"$f|Ԅ] c6\A*Kdg8=D$!KJECb#B6WX5RpВF)-ɎSY0%x9|)+3' BlDrl|V5ZRmVjf;Y :p&Z;7j"F@sTbDcZXmq+,աA3k'hnL'$+;KTBwt@a\AP&J|_eCj;* +,`vJZk7oee VlP~HǙX\ Wİqt,2w-|TL̴!OreXaVqn)0!> ꌸHd|wIJ%uc^Fz#5p$Xvߠ΀f!ݘjR;\A'jZ;y;hP#:߈ptI.) wӺ#\|\vͮ>Ä4 XaatHόH'xf z4vmy:'a6R؄T:`Ãc@WÈE5W9x"]24 HI vO (/]Cz'3)K{"xfXs@#cԻlnIUj]c`P~H,L] }#v#wN5v-Qrݟt6iBȸ'v:<lPu8ɨqTۯ5;ֆ15/wO H(g%D+o1Zm!raT}6!^ި7YWB.& @1Q3)WKґD™hCډLʈ +LlbH АNKtψsJTpzt .¤!͞i +3?fĀJSЀoJ;.bD*3;Ml #V9 +GTB-.6}"X4AMlvO$j`l@&̞~"&W+[ZX@ Oj0fZ]qB0/\E*P(YmeL4+O 1*?TC>ܟ3J 1 ,;?pPьgИَ6x!1h6rtf@JKR0jseeA{FRI<РcH ŏ)M9=^- `w N. +R& "\q؟sǺ|~Vmn l#R .Any߿ŴwkT @S@Va=A&w鯺*%)j'%>V.}X`@.\Y=zUaӊ W3ID)qyn5jF`+PtEIIeGޯh&U; 3!!Ts4)MizZɰZ 9yGobϨ; +W.>C-;8tJFe<ͷf,8b pTN28ZcsܼJ5>E%s07RZ[ioq` @#:bH^83:>/&<wwwK{GD-C1jX  րE:Zf&ne̴S(ژ8N\\>#[;\'`fv];Rl=CˌWz#̹x-gPm5\_HĂ}=W=R{߈Kȧ 140+t)X=&8Kvw 岤P >kuw50JШ?^ <`L&PΈ aW*b3uripqBC@:$Po6Sfoz@~0ZS;}0DA-A^4l RyMBQvr;FaFza x]-M r $DjR k08!;,qp*@pa#‡T4!!;I5J9" QofTc3s&pĀTbQ=_JXS=p/A}Ԅ*Au,xtTPh:Bb3STL<(c\BJw} *{Ѐt,][V h'c@!Z]'"Փ8,Z y8X]+7_xݥ5׊ 'Ś]XBKxm +;=Yx4=e dy.R3jyG!¾,* ;ΝUC} +\fN͸%3~J.YUZܠK.ȁ5N XW7ulPr,XrH1ӑ&.Vi13k%彣*hLRJ JΗ0K6:e"ĂU;^*͓B5TGjΚlF¤@M>YM*بΉxB]'e]/!7҄T 36bVQgCnFy%8<ߘ#c##c-_h, LߑV"Rf߈faWRVflez\b-w͒pkONPtܟ7ȃDiy|Lj-䎪!CE|I_'₃ YLrMvrY=5u"u1=wl:cu\N߀SԮ?\B@_5O y:೭tkl_+/]OB \jRC'<.6lt pyKȂÎ W +(ΘܹӏŚGM,Mmp?%זXxiR +gg7x +gAuQ |_63i3!x%X e\bi+LixP[vf $ou($Ρvw79|+#Pi1xr@J6 +X` P1@,]|@ &m)Կ8T*8̗C4 4Uq`ׅG^JbmɫxcMğG%;Kpm}0P/D臓2ri 5TO(/щ F*պǯ?A|XcáRy$8q-}> `W,3S-pDGt0j B`ec|:PyJVJ&Zoѥtp[=aXc0:%7LivFŽ1bɩ!^aF ϟx0;\\=2'cS:6l"Q&., f$Rgb]ۯt(-+!wg$V:AF3ͅchfegm,huqnv079j%`jb(%7Nȴ t7h%(zⓞdO,gOtn~ dM(yӀi~.[t +CE{ܚ'ڣ&q'5~3*,i!"lm! ‚ [:Qԁ!ݷj]Nu +Q)*RÂJ * +;5v+ 8(Cxh.HΥlXQ([~~1TiQM5 h'+Fw"\[IۍSZ/gV[˳s!=F/m}/ME!Dr+XS2 @ 6&MHՑ0ۗ\'2v8x2s׸xno&z:26r~aPN3jj'$&(1=6`1 <&\h`I>)ϕ;y3gZ'FpAeg~@; }}Ewۉ H`$V +X@v6X\(Lm/^od| +`YP`2.4ĘɅвf^#TZNNlo2V U65hgvqjr츼×ܧ=Zpr\:tҩ͸>jl,p+2N'*uvf2rPt~:AR'Ļ_{%Njs7jB}. %t`uϐiiPhc BWPc!\|SBq6:&'P>)^考x+| tvDP\f Xfo `(@Gn |1epo$OGAtSSR0[9)OClԟkq`sRe14ngFM +DD;ěBث0|gHc9.磵 \cɵK$*ma|o ! NJ@iޣUX6sXBHF5'pz#DPscvtN8l(M!Na*.U?:ƻdNZP‚l(9ˎG3VoF(O_rF()]pßl,RCi u(d"Z$jbe5U} WlkDA`BLOI!Bm_]ÂB&|n.23Rytw |,u&Bq1 fN0Lb<>{Feсs3FJJ R`$BwƬFZ:?9a#&R8=z8F(#Z#_Ԓ~Ovwbr'6/?7sAԟ})'4!GCzeHi숑t `GQ[o*Y ?!핕$Oq,-Ǜbq?6ohMbH5r1:bø\uNd΀/F`vI +)15E yHe>{Tp=>SaqkL}Pm7"¦OUrҐ#l`jXA4ơ2HJ3td@;AWMl\ r'@hz2q;ΡĀ!|EW& O\aI_$ @6"#F\/uԀbB|h@r@ɵUFn^n.MWSBa|*hn+ƫnc:\\ WK77UCx}/?uמv&d3&EUj6]fq.ix `ףa6ܵS2b_3޼#å#PNt7/]K'owozW[kpLNqb+Q]ErMc* 0;1393&AT }CSc&@ۈ)>R.SM7vGo$vvHKm'8d@vamڟmV.2ЀpclGTQKf'V^6"M9 a661wߣ,LQ-əa37AJe*dT(KΩ*DŽ\& ̈OogL{aFtT *!w j 8tuVL OgIťLo7:ҝX}n^hH*)@L|K`#3&"tpT?4M ,|辍q&۩Jw4Q9uֱ: +bn15ZYP:D[RpLhPD-~b9ZnҸ *l mo4g9.9M/T\٭[WKv63\z6PVi;rmĈ` b OJ0΀˛v`2-D!kh {c`Ld +7 *cl< 1aG(~ST8C@HP?obp̧("@&h+Ë+NoIE^<0"cziQb(Z{f?eM,ESeTJMP7py|qo1 1'gC@Φ4ȿ)[Y+":Q1ڽFi3d妥ʲ\l\|0Lhnr'&&Q[O@*^+Tց}CjZLivbuw,11K5dk.8X ;mBuDs\#2K259ZX4⢙7jo&2bVvRؽBDZ/G犝uZ.SV~zzeS|n1sZ" EB,c&t ^ygݶA6Lgpi@1 wd׀Nw{ʟvDsB{h )9fb-1>Q& DŝB2j31~Ё]f'! T|{Z3Gon]aRBǬ(oplrxVPQt< +>H. w`H(_z 1q"LOqP€?鬬uxRtxHFy Ba:jz}: Jne4B\eL8XkQjZv{6}׺D0ODžTjj;8KT }vΈtmd{ᬘ&/>Bs_kG .9Ȍo O_(lCFc ^23X8i [\FV/< PiA;}y+d +qDZ0/u_iGyvnC:Psnʬv*MHc#8j&d9չvS@3*=6uی \8+ Z+ 0aߨNƁv(ڿ8&&nI*<u6nrfszkcΆAaUd4>Q\i71ƫGWNߙ?ԱlE/&9G*BL +h +Lѣ0e}ܴW|gzPa7[a&DobMtF l]gVH Zx.OXpiovFOo\xrkAl&_]پ "io oܗP@an  kq1޶cb^XrIU8#]`#'Xԓ*Oޜ[nq =+̤[*I؛Di3`Cxe-fK3; NvB9"X!Yڹc/vI62qy cHCcf_)*Q1&4K#X* &[=U?cz O4fo^||&X).NL5z|ic]@m\r2Xi;9(*l'Z@! +D0!O|~JOq@i福UVKruD[gSTtIRAQ&t,V|[p@L/?yp8)6ua8Xz汩[by촀srkaZ=,!| %w$^cuC>ߜň${Б}f; +=bX>'UTxny;LwNF+\|Zig w5V7 @LvJknbL[GO ވDK\zf|iՈ BxצWO+!VC~&6-6Bp6w@#e>3KM|j3}̸H/Ow1x3coP27 +fR4l(Sa5tBD[B]AKxxp*Tw +';kǯ\e+lxw!o\JG}TkN +](\aR*ɍxw|&jӅٝPcMj{33p?9nOY@0B1:s2XN+p=̶ebNF3A<~yFalVɭܤnju':n +ub锕lPqup_iX6Sg2taOŪLd܀j'kX]ʂ Xkfe=~S质Bl[46qwE!V=w㱓sqi'Q8%WtЁ)LI[ ka;@2[a䪌/=OFaQZn `bmj҆~{+2dc1One:7ZM7WGtO{x +)*2|VؠCTϣ@%̘3^K(.@+N&KK>1qzif{bn'?tt,Dkk\m޽;պB\},9qfv\ʏ~n=sVBݧtL O)/˧n)֕vx~@ns;Ii\ ++e!&BUl9㥩9F:p5wgܡz% ikL͵6i!>Q2g8d:&t0/= ?d7hv\p8AB{!#&'n `qJ`fl|×p9!^ӮqFS|ur `-5Ȩ_Phc* b O +Ljpcngri{l;Gn.>:}d}x#]];yݛl %ڒ?DKlG^c"þ4 +ũ;;Rsb޾/ݎ.ߺ}$gw$ו#n5m|z {L (eUXU4EHQ5RԭQػ֝;~'5k8gw?/">~s^[[VjeCȯ[->uJF.XY(4_UkWv(]L:&IU^ں,Z,VןaȟKPvY-lP[pO&.ҭ}B-{PKͭtNv&]hMJd%Z'H&T[ PMFQԳV݋'L𸜧:_X9ZN#aGrit֮S}0o|\EBjڕ-_ S;z{3a깈ҰX).][ష{jO zN^qC,oOjE!!˧:[Wz8OG#@x>H9/5X*@YT`l_/z DB; LJڙ 0q8<?B}40n3ѧ#u.yă\zI*K4A5"´Dyj}jZ̷TËrYtRbTd"OOϸQ\f8+c|Trq%(1#br15ԺY;k6Mz^("bWK@f9ik@(;E퍱 a2L& Rd+=JI\ZVesjBkǹF{0CsiFR0*(g11t}ܝTkxUY2c%3`N21ԭëQBզ\^_|Z1sߏ߇Պ7DO63<0Y1R*0|f`w+JPʚ_eVaO"jJJ# +B?%1Gk帐QZnHZ݅6ڶ5Ɨ{{ӽ}64h,HLw),JJMz%OPwL9979 )^Ikp|@kʍYYʏiGWVo((f'eT/} }ħfbS~~>nǔQ7*[R"׿9Th>Z;@YF%t 0(>`Q #&u7,PJbR^P МG8&yn{W*(kt{keڮUf4ZJyB7B˩>e LW˜/76׽0e i!@M5b|ڍ IZ6JiM!5,.jQ*lc jt\p2BhniՔlg}$Eą>Ā،?$OȤ 9):M@B|)gAŵBV؊QVbA "Q\YHz "P\(ܒ/T39()f ?y0 +7_s{P4ml2*;ON/@aDq /L xw Bm|*&c#MAͻaSS 1La 5YQ'h?{fӡ3e9JI&Q\vǞ8ťk6$0>k;L^>qrøC8KV/Xx"ج7 +Q je;-;O-gP"(Q6"\1jÔmKv8 r0q./ 捐APc5,j NI +"|t&\ILqVWJ- v=]0hgZ +`b&[oA y!yw^,x±8Ѿ(  +hrD@Li)3DXwrӳ~o|=o1 OMyݱѹ{"!~z6AE3P},(!@ .O$rcA]y72u&pT` Wh3[L8kyPo('aHYɶ`" o;}i׌2'OÄB+@,7rr&3$0qas8g=59QT޻xK˳„T,:8fSLVyF/Zٻ  $Li81R",:1%ƊQT9-8sr:0(c!kNa^/ESj2(QA+*\GNvָĀDwH.QBC/ʂUQǟ AQ:9 Lms9vK 璅Ύ[d +L+9ժiaҭd㏠@)F0$|ax6RK7b(;u? ~08crHB}Ԍ:BF5ej0|,{gxr(H@&(UF$EҡBg=垙 }(9D_L܈'HC%w;qEF¤~r7[qڐb~zjIvLp +ē]0)\Ƭq 1m=/ƢjUZlju!2bfysSȴAB&s|˝yYF j B(UqLy1ۖng{9S(ĩj OvuAs*'^e#1@[K|g);FX=8 'f~厉1:}z>x.5uNRz:ȝ&%c/fMq)1%^D!B/w^Qk䰖Y^=\o~#\X 0JUEA +GQ?bi$Š8O|QĴ牧zvLpj(2?u*3gB'ޘ?B)N0G$ɧӧ sPuXPr_j;+zrj<ܼݫTr1i$A{7 s +2JU[YA$Ӡ8ڴRIu퇷p΍ϝWr缧烡 'U8SNH,w޹y?MRsQb)ǬUn;n +$-]?ER-6^{;x!MxzEV'gCO?}"@iJL6C0RT_RenXl=QRTL*(Ie3eL!JfA/?k?`аV,C7!4#A9-8\7Jmw޸xů~wGzYH Fܑq&3B3eus׫ZR+ڽqe\z.^WV8* +N!jƅ<{&8B9̉Y}ASҨtO +9tl+N.PCC +.й_>ѿ䥯>1pEnzi VЋk֕ +8u^=znn_w޻A1@^Ϝ;F +P b`@:/n;K/㯿wnO_n]oN fQVʒ+Yae,' +rjdQ3K+{_>/~@.O0@'9p-l Gg.>{ ?yuoy?zǟG7߻׺{TSN%--'4͘BUxb۟W_>_|R7+o=<4Ewl"qZ'v _BFVyh]XK=2/oJ`& T!vskW>|r??>#z鏿_RJ"\" +>wcxg/?~kǿ?|}yW_}z!)1, DOZ^WV{[Wެ~|q~?x/>wy(B 1tܯmtk FG^諿|_}'~|~puD Yw  + RÈ5wo/}w//o~o䳻??}o?8hN”lwj$8;|oݷֹ}r/>;?ۿg蕽|'o{u0UU3JX$&ɔ`-v/_w;o~`KvD%ЃEHJ,iV&T*+eAG[?x_Og7/?0((t`Ũ}A$/ۑ#ѥko_݇w>~΃Q?+k 5a2Q(uD3%rꤰa:hww]<н}/?O}_?:].):P$* ԉ@"6Jl?ez_~3s={ +rK,`~ZJBZP,d9SjZ=u\:?H>_}z~G߸k|ah?ºli,)XH>Dً>4 +X4ᒆW.woy +ǿ_/_֣KƵN) ׋(aH$(SXJJJkux\Qz\/7k_8#ۅfr~yn; _s[/oÛw8oxzsQ($YHOfBM _G?o_{J' +I5rzXOlVJ6UbBNFd +[rd +dIOB̴<1O-ϔ" 3lZ.Sc-Q#c +3\aq!Y샜c\<]TLyYݬHGŃFE۬+r*jovڵ + +.VBht/FaXRF{n\.7V ~բ)!DQ)7P69gN%eEIR+R>mdl)c L2'(j8O@\<3AoKwyt +GBO4d(@@FY6T*Q2ۨJJ*3 MhzFcHzT%_{zzq.Dt\izCHPJvMz)M5R^əzu>stream +^Nzk虹Lm>ʧVp + 9J.ԖH9SdQFx`-%ℶ胟L(TkqnS07#bNVCNȴ1>h0iE(51)^Tc o܈Щ0t0"ERΰFU tG2q#QFN$g\n6H>;yr&8"lznH3IO~IsK=dy2&BD2HnD~jf:^gQFL$0MʴwyMRZ"T?jPZB0_rBjH09~VNˏ*UwsRadҋ1RRzR9UZĞ^@T[,K7? vQ֐όIØ`HK.XbF0¥∶Z6%g.YWDoϫɧTYI$Z>TvZlz&aJ˃{a.uڇ 9.Ws\d+#NzX-Xq!fLzL ~D +iasuL  ڰ + T)\ :.IըXi'\9{ƃxa)@& LC2yg0QʄVioe2xbCĄ^S>:#bpsI0X<5}څ F!͏^X+d p^!S+1lLM~S^X >x3A&,!"j5 b~Hj͏@h{De{>$RFD\C$㤏R؄)qN:"כ:5 +@F[G.Y}7P@+mM@X*A2~>upͥ>c&{ȦVىk5#;{OXIϓ aZc,yRiRL(mDZGNsBDHzUȯy+e@Zm4-r<"v;j䒋fЉ^޹ǥlp.m^wSx*&Ԙh_0zdG*ze7!J-*Ӫ;Jq 14mTcɭG2bgoiޙ0C$N|jFn%2JJa}!:pAVP߼U=bs0k-16_L<6l>$nv넟YHXu.AJZ;Tf-rOf5tNDL.A8dZjo܀ R@\ٺ@V(4]p"UW21佘|~GKdh‹8!O \8a[:;ЩosAKsskw"mN!">:n] ; ! xiuMTs]{+SS {1x2He\%3|v]-DI-#̤#|AG\r3tj_ޏk%5?.=Anm7I^clM:b~Rsq%ȥ Z#cj xit0<-V/1vyut"YU ˧rW*g-%_ၛ㉮ݹTݮu:a> T?cEբvp[](t{F+,(5*vP-oKg| W}<H &9დ m#Kۭ1w0tOR]Of{k||Oǯ0o~.|γDrqDG&,+ V7kى %A-jRvάb_}v#Y&=BBP+w1d–R+ކjZ+7~~.t>T6~w~ +! G!ҌS>,]h6s]qgRa0;65Qrvمn̄AJ4MrlnGVsvqO$*V +޹batEoj &3 A_KvYK+jܪ<ݹ{έ7JmpT^>朞Y-tڕ׍J޸eG ncJ9gZG,lk7jKQɉo@ &X_FoHzpKu|71knLQ%D1vjl~[.hi -b-L+ŕ5;v)\ڔ'<Z HWU! + +PEO m +&9+͈P" =:|(q-Ȥ@$$GTذ 0[Q68j.=_$早DBL6ʝd9k;J6AQ}Q }S?h}Q(B\g뫗/9{O.X[\_µ]عƕϽ1=YKv.,/aA $G\~Qvy|t@Ѩ [be/|};q.wb-~!3[=R+~vsڑP KT =Xd[%HI6 ug"cT΁^Nϫ@b~6icF=ܷ{d +^K&vӽꎔKM~I-)Qyw=qbuwfwNyKdkOɭU3!NԃY__ڹWsd1ke:0Vc2Tq!B޸ Ul/z;@:'= 6 }!)(hG\xD\*NCcRf!fh5R)Rfckg pZ:F`rP^uLG;_“ cW@"@uZ4kU76nbzj5hA% +veULILSc &$^PsFuז/!UʶT0zui*PPH'7Ƒt(VviNs('>{Al˅DaTj>'_"RiXmkuxnΣf^UeWqC/K?uXBo@=oW+Rf h<3ӽ%,8øV._nmېXFRa@7ys@ MM1BT@YWTl:?䄏ZXҦ^sfk>((#tv6((:e"ZZs52NV7mD.8ݰI}aI ΃ȃmrCŸ'FcWl cl\׸"EE`^9CzHz٥cfQ2aWA(!m8YߐsJfuBNv xd,a 0psQֽyXBS>dZ\#F~bz u!s;fqK$`se* 93oɤʈ}s\;d+\vkv[{TL8ٗ*ײ\o~Z^Egt'mՓ Zy+Bã|ۍdrY)'Y13J%BR%w7bR=R}|A` + VZvZ;!"hY7Wa40Oqfg&8@kuv_)}ӑgPDq,n . \ npN+IJTϩjy^vK4#b1, tu NHD*%^ۂbNT\[=\s#~_)m[zvrMaZI.,GfN0_*hCI7Ih!6`*BJ;YTL=:3JdmG&!>  X*&[YBô;;>Oz_ʀiV}~~]mL*\fK 1HA(Vgp3~^ȍ'N3>j6 e<$14ԣ +I`uLU?Gfnx0|INa4>z|>&|ۛ3>U?r*@i%6~΅9sAAIv#ňP.0kE-&rNRqϪjl= +@1I^DA&M[nN:sae3s38gA<{0Pt6iG:%SK$)+ƒ̅lI7 hP*V/႕"բrT+jm!ZQ+,󩶜1Ņptc CS#J'WBBy.">l +ݫnGw3nz6"#J}&ȺbbT +6 lk Z40 0\J~K/1U'{`6 ("Ҁh-B*\"\~+*.]v0&^8ޟ(-jrE\(>3qRU[mKV΄OC^H7 .=ۗ9LAޏKZ%7ᇩ5$5zS&>&Ya.~B-տ^3`2W1ihG~}ko6й'LHO풲T&`Vr!:$!q ~}>7 Rƺ@B>@P:k/uʍbӛ$YH V[gfOf0~*J>&"M=v&fN:?8=,.ԋKDB<Jr~KN8k(B\A&f Ӿ`v]Ģd2> b{6.DEXU1J A?t^TA Qe:JY fEN9d-?D+{|fM:sJg<Drb?'i( +Nk*&% jSίj3N/ 3^,f:gO{ ?塞CAJٱ㉅ LV{˜5g 2)Jɇa& (OA;*أ։% +QIwTl\35rN-0y&LE[U\"eK5DoG-$~wvt\y_\;A׊haHX-Pt|ه`ru19p њ!6',K+P)LU[э\"cu1C)ˮ: Sɇ%@l/$1;N3+k#E!1lE'ra;^ 3apHE\RL0a%TiJuFQO@03ifFHj-?=⽰'J+]q {~|&=59'≹XuZnxuǍ|zxr>2Y1 r!*!S^bҐG,G5PAЂ$)bHAsK)="Bca*!jZЛ9Ôƴ:= Y$`P'2`ON2Z'Z֪tz0),ĽDNAB6*gȈD#&;qW:w4/WoeD6xD~pyWSː0h@<1o/];$:F,=衉%q^n)a8ZL)MvS>n>F^sZJuJ,ec LA} +DaLoVi܍q)ij31fYQFөm!.9S- Ai;!AZm8T.*dVb6b[%\cVT(3ZݳbBhiq +^PP%!D¥NH9ezYs^sX,Ӹ6mO<&NPhƥʔ ɾcA*5i +vMϏ@h_^D]aiϜXr)L<AGIg1ĝZD +,oL 3g&9/,5HiD3}3Uk>@|nӅ|\(Q䂤(cTsZf6j'@ KnUPbQR c% N F0R^FMvGIM/nw7bBs>L [cˀaY;³z%'<0Es#63WjD܅DK0[\e29Ȯ\kޟ_B*8خ/:uօ+/U7( hNuӮ/B\D Eg}qn [\ 6ErRt爰hf3!c\,q X.s Cd7] +"dj3Yk5GT^O#.Hƍim\B%<) ?j"́p`@(e9[Y-JqӅ.`w=ଈ"R^@t3&N&gbW#=+HZDեCBx6i5\f/n x~CeƪՊݩxt@~܇# i͹(=凃NZi?R +^̊ 1 +ƀ^r.|IcBi砐;bqK blf?1LkͅňlcJYHxtJ $0g~dI{A}!,w{SUYmx}DFFz{s>wfwvfK +K"EIҕIgH$$@T u|}DDw9vt;}Ja:l"9./`>>~wp`fz&Tu)>.qQfdI;_,.~U_=W nJlgHQ7[W`z^M5MHЁu/gdxfo{]Q<9[u1.ֵxp6;\條=#rY{D>u]EJORψw<;cn 4EB*K_+ֻ-2EˆoG'W?~\?U} JT;6o^7 pdCoroow?&?M9),{`|uQSJGʑ^sZLZ9}wuGZÆ1hhCރ>_<3%>:=Gi]w߰֋'uhP(q6`zշ/'Y/%Pv^?=-6Hrv~vN,}zr|'tErr#{'?k#iVc&5ށչ[=SWR赨*)uwvw_Ux[lmpڒ:+؊7W㯭5 +m%U"eA`nSIqA4 IY(mu瓻DKwp_f.vg.}*(a{_(H 5cp\j.ExL!6lȄJNM~Cagf}i/JGrHOYofztN`YQ$!9д{W> ظ +,d$zEu(> Ϝ3BYgVRX^pp=)KQTBFJ\]k?9x_5*6ܜ;å5R;({х alH`t,xlH{%>;uIl7.Q&vkUaӪ-!)\spu]d]):'F +f NYƛnMR@UE5“W/7YT"HFϻilN+ *\LDiJvF5"@ޥѻ惣iHN<?*%6j.+<|lf ^W0ZRۅl©9l/<KʩO?k;9 cwX_6@s%?u'wݿh^oߓF"05e֐6/Ek~Z&XTok, + :2>]E̔&co2eLV{Su{ح=_Y+YĬڽ27Uca(V(1;~uLJswx[:9*Kj2]f(\HR%\!Jғ,8C3MoPZ CHIP8s@jl1ŷ7IMO ;j__ϝݓb4c]ɝ 1ĕOMV dߥ\;CJkj5B +f ">Xa|r&D6XxwttP;7]i` P-PE{^-;;gxw*xÆûhFk_╡uWE<R\QVj4/ Rjvz2k\ͮa3)-{|:&`e5AH +Se'RmN۽d>BHjxэY}_5@Aa + H۫h닏'\ۚc5\"?.H> N&NN9o25H;Ei gMRV;[|- 4G OӚ1إ,eĦ'NTp xW(^[HpU'e)H=X59=9uSCD'%z 9Z`;CQmzAd(O;=Aqf_O쮞epB)U#>@Mo ;1\CX6g`{Ujz.^Nu(F.Fȣ2kyoe (C^·]xO_Fsʓ<@Pr+˺ZrnMz0I?Θ rLJ9? ޓJWY ʀk,~d.1:Um|}[W$ +o"Wwhk_CsuQUٛ`դ6\p418uoN Vzڽ"Ǖv{U@5FZROp⣊CwoN !@pGjW[YƬMkQ$TH +W|h^t BԵ6oQkB]X¥z[pFݎϾ~ ᝑ΍h6:x P wSHvTA_ T +wʴx|$?3lFK0OCmyLnt/c+)^[;59G .!W'gF3gtY?#!:D*60Nq׬;%NgIAPA *BY|៸1XN%栦r%=5X'_n<;@]ȳA0Y'{\MrVnRe: O,ўٹT+)8ݵݽE)wvJDRl?ěwJ!ĄM<^f/7Q ?KRVQ(o *{FYS): +ǧ:;cn 0ڇX,vE8YEꂫrL.rW(js@7f?oCZKHr/7J#kNߊj4eMmk1ح-꒛5";\ě_gV4o~Dw .[K&p)'rf%8ǙB* i]sJj#F!αg֡-yNL*ԲmJ?p 9\6k46oӓq'o⛿KҨ;:~Cg|쭔`Y"$l(x8Ih9fef |k]3$73Mx/pcRiWX@9,ȸӏ0/2~-ݒBmԗpz?>\KUwlFS}fwo~ǿF_R.ޅ=UElVԚ-$qRU۬?#?9}Hqhp- B}ggU+˲ZN 8C ͑N4͛XbktIh +JP`nn]y{@}1B6o{?aD%V!tp.jӺY/? AFLxBFc{x;אLM).L3ݾ8 w{KX]_$iM-nh8S;8힑F˷a){;g590gEi7*b>Mmsl8DŽ9ϑ +NUPzDFB.y5R٫t3Ni3z5{g +tanֶ9hNs LE˚,蝘pZz f/>PaqIkQV pm{߶6A4.>zj h1r"Ɵ>qtSf]>Xt$\/$"SJvrnƋzw2 ۽Z߯ jo. o8oQ`2|p` оғ3#^S6}{Դ>,ټ✡;=|;ꝊC{^U:$ XE[{jrsI5&H[}%D=)3a׷wOW~5 v&t˟?O~f9@\Tbpگ%[cYw Y'E!۰P)Y䛚#,ܢ^)wjOH N]љqzCzO\Hwk-:gxC 6ChRi 䅚_]|]5$Q-J3_OXe9o+@*UE/G3_vo{?vp F9S6ܘ{Di0$Cd)a9sw ,r!Oq+ЫOJ\QP} |pH1WNHq~~wc AZҠIN yh0,=f5D {psWNBV cH3}>ypKyKc9݃xv98}o/{'~=ֽ"S˗vj|yHN5i9ɇ!i'z|K%FkTx/=BB<`, )C `s|=>֣2ezMh2*(fLkwWyHOwپ|kʬIAv9 i8kFxP*WV8S)1\ߌo~{o:VrTrz'_nB0 T3~ZPbD`O=ȵGe%f;{|pOh@0uxA ܾ|eF/ŋ`&Z1#xy?`%-TYM˿8'ʌ 565y8}r @A95P[kAӼS{\?IspgJr +o n.hf]׵so"V.srdžضYΣz;y`_8ŭ,u )m(+$hv΢."s V88Zk!ڒ8KB\nRnc cD`rc[C9'uL76+5>#2KJFP guΕo~z2R=:u15 ;adԵZ 7akvHJ1vH{*+ 5kڠ p aRЅ3沦 b9nhwZ||:vM~- +Nhlt5~ŇG5}TI]3V?buzii#RI`pZ| 9CZ{+,%޵بʷ*\ę>鯜5WPjUJ׵*xzڟۧ Șuk#Y/{wf5!0'|0]Wbh[ `̑诋t'h& oPڻU2 'Jfa]luwÊ+=c9:/{r0 Ѻ,tɰ*@a o 6X<ցOҏ"Ƥ Oh0)zWzC]ه.˃:xj7Xځ%b \?2h|1VMڣ$t GFkT5BqO`psRU9SΝbt\gmHm0 ? .$xr&Z(3W R,QdzwoQsYHcZ`|/^רoe^CE͑>xпHwU]Nv*J]j"Hu5_7w+7 9I/T{O42KX7v{gxk%֍~ݜ~IdTۤ翽OۛwXL@ݻhHm?Ns Gk6/*_e^,_K4WeY@!c8u*jsTӇ5e!dݱow՛ݯ9®ŀlUݯ1t{v +/G0[Z|⯼K}%tF[R*\xE5zW]eQαٿ-`t6d|틿}̄'1>@բc^J,&o?f\/݁QpE0\dxdt__i%SCU3ԧfh(2C<'eDQyQde2%dQ$QbM }2EI@1xY4+GsMnb/LMGaޤtޜ^\_bJps9O.oOO2 ̒gooNxzL;\S̱! +9>?zSx74+ +&N__B'3|ĝO\VϬ3 EcLBWOH2,He'R_ +zFjhm\t5!)H-cMΩHъ0U%6!=1$?[kwpfNֱqھ)<rxg&[4AIl:C-YPOM0}!D9['hdnhoHwtGjkΗFrN3(-fFE)7o{ʝUnEI]|M5WJ"K֝6n +M'7I^5-ܩi=֛c;h{ޚ)gY96(paMI:apwQJ[ W #ueUVZuӐ;u'Bt GCZJ/Ր5JaC擪Sղ] mZm@ +rK|BWkcLbxQWٺVgxwZ (#%K}X22r%]"[ }L+.) i]m1FI.9onUn +G}_;uT ,_ސF{Fm]T A[5)QEL$ ~G mX`,2XK033Շg&nUmjco}|˷N@ +r~s]O7yDCdCPZ/i##SNm鮷 M9& aLH{Nҧ"VVEK\ZMlfP5 hu؝='Z S@9K):5e̵܈ϊlАۤ9b40ڽkB=(rL%X[ɩjIY.R~MH?QݯʴJ׬>ثvsU`\@Uf"$RšS&DA},G/p?_>Y{1>(ѧ$դvOH{b$9oqQ2[}x#h)O'=#qݘpջ/c+9W/p['fu3Μ5~Ƈ uQz&Bb sB6~:|'!;~:o6.މ>8S\Н^Ͼ*A=wR;紷S&}ّnaI'G{9ڧt2<9)309zNy,mcUIf&V*u׆ҮB֌\Â,ԅ**STd^M- 1mϴwI[ˌGk_5 =K2u &tϚi |ƙְ6ՏTCI,'5Ͳ~ ҭ# \1ތ V=+\'_s|n Npr$=3zgkn-`U(0>mu˘cUf{I;[):@t{{g}͒>gϘ[ M# I&(3~tYsRb#BFiהnb6lġ&b6D{aSZ-eMIOO +J .X}HR|zRӈUŮ9BHgIDy+M^(ɭ7~f+b{_vnYQRo΢KYW(Z +2z|Ӛ!j1\O7uxxR\W:?O+$9O kKZu/VC;&?puW7:|slO[S jRr|agzFm#wwbvJrź,u)sbϵ΅Eg/~7gM%w) JWE,Ҫ +MԾ,խUeO5}rI̢>в!hB =Ǵ#A˘Cgv+JnevKXu\@>)wWIIAJ> V , .>*ir|P5k{qxVvkrr]f ve͵䪹xמ\F{>X{c}LB7WJ ^ALjd1?Hׄc=ٷ_@)ު { loXKЗi tOKr"Yw6XA"$'nykvNz漗QO__sr6C6%' v(*" +PSz>G9{Gyjc9wBH3GE:6ZIoB}YP6u0v*bi*D5JvZxX{Шl7" )9ɑN]J E.oE&[12u !ln?l+R>^aXtE6*Pn*D8O]9..䓒 ګBW7?5Cy3u0sJ)N2P݆dmYH-!Dc-wջܩOVg O> J Wz0]v֯ lq]8~^xf>c%Mqfˢ9g~rv_ɽ#YY4 -ɳhfMM%unc)!};'yEES)XI蜱+G`?m5nm^05AdY,Ơ9ئ{cqn$]8CM +IAc&q'y:+9ک)-~4Q&I LM~ּ55G %<* "ja)cL@7 '[E:*3QCY5It`Ǵ#DS +1gOsP9*^C:5l(aC@vop6ވT@`ݝSJJUQh!-LZCw֨t+ rAt[5>R[G3Fg95 @f{)v+=V0yF#$4r }\:1?:Gyc,Ήo3&Og׿vW\t+{n[} Wх)m59ϕ 1x;υ>[,u!>{5*so988kD3[±ݫeEIRuZ7S*ꯂeiXx}ΛtHD`uvKB8{wR61˧YcvU+s0dI ~k+f'e>qNj]ݛ7<9R%>_S$=hYUj q1*>BD{x nY|\ru.v $l(kb4,[V{˧SSxTUVxA(aªN~ӝ5ֆ*06>ԈDOJ2ZrBczwZZ[LQ\j<0ςɽ K['AYiZ$laѭ;yFڑGO6WN6 EJrf_W*"[VNYlA-u`pK,$Kڴ>4gPLC9CvаK?ғ#{^!0W3ċ?SXDd+ՁDSZbCJץ>4m-be;ڭYTex%:,wZ\]a6fuEufkJVM K%'5s}Y_f$4WxtvJrfhO +l^ZI{$!)Kj3t:g޽$~gR5T~z%y"m씨BcHWX_tCjV<5LyiP"8ïo e}cor]CLxK-q>c32`V cRV (Ck \g'&5cXR:E|) p=-Jq 3 ˆFw-ږ8pCT:ඵx%:v/>c3n"5?5^kyRִmJ6iSvXu #4^Ĥ&E9ϑڙJ&j#\)xJRTS^,brޭwIE +U!Ie IhW0SsHiSʠ&vr h2kQ?Oj2"zk=ʱ;vtFeFY_}suQ.Ja`{N(yAC*PEDK&Ƭ_,Jd6 L,RaCw[Kh/y~#`0@dnϬ9*`W?\c$$T _No~-懂"G<.9DOP_% +҄5aGz*H#)9 pۭĚ1բSX-i(yȣ@P݀gTOʌD7nmY>.[zn xc$GN)` 9A.PNZҷh7X{,!(upSQѣR\+7Gyഃ_X;WXkh;% 3\GeJ#zެs#]Cv65&#5ZB&p]L,&g 5yRi5&r,6)sk%s&*w,=>w`~clM"7m݄$!0:pTk©W%D!&f랊4C٨e9 +"Ī3UmFFSTS.Q!İlr&7cy H: fF3+^AґŝQE G%V&v| GO;L;TT +`]K^E&dp`Sl;>FJ>*{u_ڃ$fjigQ Jmk5}vhgP;tbԻ*)X#)Y[\;ΝpD b7|g,@9aQmQ4s#)cYެ"usd/͋.I8du]I9a/3wp *rn]iUVb2YIHVxG<_I E 5ܓ2#MLёlrN'OOPhٔPxLTLUB(͵?MEJjBP$!nQB b*i + T"u(X`J@ZEe` +1j9,XEf1VDBƧ>kjHҚ<=6*{7`AH$<.0WMsB*wHm'ED`#SVwZ0OJRaGV1"!{ VpqtuV"yXQԚD W5  rm23tT1 ݚ:@b(S5X(ͣ`=%iC>z3ң)bJ,n8kRdq`r 4ȶ\4ϼKw+ _Szw*ŸFѓUY'9&W5d7V 1`!w.gLbQF?کlUA`b]2Sg0Ab9k(UA)uB3 b!sr Fc Q0b=Roa~"f9f1@1M͖ װXfpvj_8<.0 ?y j&H@\[cuiHu9-0=UD[sv.FzJԺ%',ij_𠡌GԞ.h*~Q{zG VǬ5amsSS5~o~_[{5s'rz/XSg=g +KrU{Yd PEiDžlRJwkzgx|[)ކge.R;`ǙS"PaEu/UokHhȘ5a"))֬.*8*m̈́pcaDBbȘ][Ӊxpt+F˯jrEj%tԅSR ]hE }"7OE={ak?)K_U0EI$8IFCr7npvBHpGwd{"}r@USˆ=>09\`TkBh]D>lN 1 .A0cvr3 ͤL΃6&"f_3PȐ٪Vs Ya\ś*[`) & ܭ:2!`#Y$]ٙjSuN)b._zQMUG5bxB +Z: WFx?j96*願O{i]VN5߫hyXeQEz@cCar3gZKdAw5iiO7Y.CB\!Dϣ3wtGe!,svMzp9o a碏f#VV@wH湠Eq@=B߫)#V`j%d"Hy {xivs!P^U"D9 x E$̻/0-1hRKP@ +Dnff0웯iXBWQDªw+ZLE7(N`r7ҫyv +FciTik +@q#Vl3<)нٚtS +r,* rtT?*kY:*;얕R:{@8_gGY& -]bG WJR3BnA9o=3n(1P֞▞4,f$[uĻKş[#]Rz6ܢ?l̲ς{ˋpѐ"Rkgh':,]ΙgEo=ۻu$/E)ԛ;s9>/" oBC]p挽PyG'?N~.yo ]Bah.|n6` I4@Zhv ČO`+ꩰG` ޝ#sUEGB+jMhץaUVzIYH ~\roglbjvnP*TP B!rΩsnI6I1")aGadْrd+ۖe9g潝s=ODn~_@{AHU T):بs|5n9?g pv`!HOh1}HZw e'_ҁƙu`|@>6:i#s<,'fT> Z)7Ox5ȸu'4L70Z$l񥜁 d'T fLO9A +}.*%ič^uƍ%v>g@_c21-4*:@⩣.#a̍A EJZ,FxF1@˄(zl"㮾dB@W! +$qກ t;2bU5#!L@N alz@yd _-(LBw$7B:>! ɴOADZQUOXh,o!xStq35d iaȻ%bMHCpp3@"X'gM_r wHK p7G͟0Qm'{$'ᆙN!i4̩"|.wqD2 ktssy:{e26I%歁9 Ji-0gP6`F}RFS A PO Wp.;K5mT䍀^ڙ i#cZ4 |IR{ +xB ژԄ'| +&7P#G!D4a4i$X&eF5tP7-3иrprv_OOK%65ͧgĜCgLB0ba茾 F,DdHK@ +J*u?Asq9(\2sLb6L∑wI^_ AJ_oYWB'$tg + ո,6]&*d:5n?&c1!oO! &QK^BFT21TSkry@uCB0cvƄRY(-HDduYf̾Ԑ(|r=ZZsh3bI\;@i&3scv?(+kKxዷ\mD@|RyM_,.,ä h4cşyKBeްQlߒQYOϜ3Ӹp +E'%RqE**-t1Pt"7T9&)Pr%FXt*&SHΩYLi 0qz$G-?b%^|r KLr!L>(a,b!m"TW.Τ6ң|EV}$gUdSPAF_Ʀp 2 &*[i +޲dT:\fVmU*kHOCre->yZ:- ղ[hc;DĂ'\#57FL{ž` VBٟ5C5:֎Vxcr̊UfcsTzB#fBc-"R K陃u6W"qW HP`:9gcǴLG=zN6,7FoU|,WPᦔP*:+EXts㾹S77W/Љ7\ Ju:5iaT/}mG[֎?5ڸ'ٱi?A*U +W|Eab&S C%:%wCSrMbSm<\>uO҉Pq1 @tCaRNL*Ʈ=A%쌂I>7oȵ y2?u$ +TMFx(h[uf8Tޟ >Gd <s Pu" +0jG,C@OWB A>3Tڄ.xUVrIXXӝ͙K1hcG*oxfyLy D^,.՗T#b>uNĂ?v/x3T-dLx*UcPqN&j<6Pi y2u43rmץTfjMw͵s aד3Hujec…Dr|>3v5&>r wgf.--T/ZZH5nv-@@h`rGb&X fg 5:W^.3=(OdBڄ:i@HՕ\(gUݍG^xG rVix|rw?=_-̝.\-.]--_<jX|17 {'Mj3{>FHZټ~Sg峫Vc*r_iuJ*ef.N>8}٩=DSd鋵\gvb~ W7THe1/m Sbv95y+b0sWdEś΅{_(ΜX\(._JK ]J7!!ّK빹Dn|sK( f:Ssh/,dKM sJ@/=<=r~j"Ÿ+|qC&<N@Xw-WO'.'.3ElpǧԂ[fBByOU="\\8}靫Zig2ƮT'ک._ixT]*Rm'xj.SVz>WDG) B*-&[fR?hI9m':嵳tv[H%Z_ K6{~-7DHOSj/̦ՕinjK/olnޘzۧo$ xh}+\Y56si\^>RJ܂mo_ $gjc#Z.[i; ׸ ,k0P5? }J1ۜT{x0w=S=mqyWݢN |A/KqPˏ<|Hh;ߝ_ADLmRY$D L>sl.i݂ˁqyK5y;PIʦR^72TDJEaF@CIuS:b-b z n2',ԠJPm;ۭ,_<}IO!\*ޏоɽjkףhm-fԖpXJlt @s sg'hY*fFmyc];dl $-_%{? +r'$P [+*2Mim9XșHl&+@ܸ+^)\O㱦Z[ۼ Cjkѩk\vihe 2Tf\aRwVgz#WH1w3^sAy&54vԔ-l]픊I0 isJm[P;BW&&Lju)Xu(j ;! L(=-Z0VnC:U큼DdHnHF[~w +iH\04)Ta2`'oV.ɅEؽHmvwH#CV$`? +הƎWi98`|W̘@Ģ[Apx6b!-F {l4^,f` pJǺd,aҢQ;\5ZHiN~$>E* 3@ 9!8 lOu|661QϜt`n.;ޏW) +Dǜ!#9aлL8@4݋SE&{8_n[ slB+z=Sf\vK%TdJE:D׶j+ץ +ؕ\$z$6T\ٻ!a;nzRi?9& +{7TnjJip1:)b4Tv30RtdX8(5`-2q)/qrN*n&vx 6<Dknr}3Pn8_lPW[g0pef0s0s_w'Jۋ{Ksؿu8ٜ ֠^qJxdiWӻ.ҽSg`d@ "2܄wP.&Br*5kgAX ,o=B9j!͞ )'GG}Pʺ~S1+M6Lx|<\"C@=T9);rq65ַ Pй9bMoDy@b +\%y3"8LTҵHmc 0pF +q&TX T0OK:ӟzbv,:餓IV=AJ\e-'4bī}9=uM\ؐ "t˗!0TF<^)PJF?٠ԚGIA#M.6vX_,cC8+>rs0h[W%ZwY?fd2UDTf@kbyR{-(U!5CYB[sɓJy@Lݩq;Wұ)? Arq RZAE}qրI,%16oBFDBd&ny#]z28ee#6g>\B Պ +(2?erQ@Ա`܅q )uNReٟvIMFTdRdbztf#KEZAPo1`v_4R\LX :b}bn}z(Z>1pP}(p/"2d$`< \fչf|eg֕ƴRڛg&ww(`Kp񎛉[pqA2 +*lFFrX>\으Hs@|Lj(ONz1rʰf'wtf`\.TI\!Oer{GlBF64sd8a'Zإ{X0f'jʸTJrjyfK+F_6jF6!N˹Y1 &'i`Ϥ +B5? led!SBqxYw0on:Ԉ86l8OQ+:cƀIiH + VB߽<$,QQcafJ622l~ U:sWgͯ Z1=Α*"'<~W T!,#B mHv&+]fbaۏB4J"TEXs9Zf) >9=o0Ե'R),#ܐ;0xEƘ1ⶔYV?./4zK;sg/ܸS>S}O~ǧ_?S-L*}n2KRV2o/Uv7]Sx}]y ~gj}v|:I" \ %nsvezu{37ѧn?޽o]}>^޻~VoJqA ^^CTBByj~-7W~GޏO]{w?Y*VֺyX|`!HHAf>YHT\=Qnf ͅSgoz|wǿ{?=yvsZpiz;a@77acDDJO%|Wʷ?ϯ\+=wcgy#Ͻ/{ᵻn=v^9ôR`INwXJ6ͥ/8so/>/Lpxmʫ3ژ{L.ӈ?m̨*yc=ʩٳ.d#_;b)\]>}Ky|o?Ͽ|?zWgwR[L RPbBKs^yg^GgϾ^|}οo|>`f6dcronn?s/M L'Tܚ^ـ{y֣/7>G|cϿ{¤/xE+klu8)YN.mx훏={^^y?z?/>wws E6 +y.z9?w??ҷ^z{ן}??A藟7sY)"8|{nԕ7~O~o_w???o?v/ ZXcf a!3/|ϼ~O~|gßo?Og~zCOz*ihy4(F+?"DJ\X/흿ʛO>[_~_߽S~1zsvni˗ݸ#[?~˯rH'VobQS"/\iuc=x[??ß? y>Y>mPKHN:ӫ++kW/_w᧟}tO?o/я=`gyGHI)C S6vN]~7~}~?ෟg~~+o~悓D8T7pPN +嵵|MhǏ~{W_^~^}}&Z"@V\ 1QӋ{gy_~o}o~_~?嗟~+osgrU&q#ͨ' +O<+??y//o?y???|_'_>Sg +g8=c&s\$6oO?'_ +y?/~g7/\åq wpeu#r{~}_~o~?//~~G=ʫ.F B-\}bRkfrquҵq׵ $)F p",3f@ Ȅ u~)O%Jj/o.nf{'7߼x\=˕9VI,葡NC<>6v[?M$كcoO>_ܽpPL8,Kvndөr,Ϝ:쳏w>~w~η|W^~橇owv1Â9|2d@5Ȩ [4-$}~W__?O ϟX[,jjè1Ma +"`J"Wj-?sGz~ç~L)oE|VfxDw:P^!9L-,n>s⥻\voҋ/qZݬ+] e,''vp( 424+a'<8lAǍn;0 +RVpGd.VvN.KAkԂi?j&ƭHevI E8!(JSIPN-D+z6aQ֎K?&:@6/}lbl)H)!II+j>UuY-@#=IX:&l'cψ5K"BR^rN&W*|jv5Y09B1#)% '?hHZNTT֘i4)Q < 3qT`2;}>&WI.ilTgR|l&lЎ ("b{tCF Yp.Dp$U yKd@kX^m׏8>f +59)0wKpo@s`$dܐzqBwt6q[bpr^FuR$fl؄ S a6L:sۼZcEX; +H0KEJz$iWv_ã&To!NZc3n8AJALFåq/'996h2:9'Тz'cp҃QFk0if;JY 91i q7qhߨthh1 ōsr,72!ӁtG +CƁ spטԹ8="@{6{v&\C7}F+Qko D=\d|\بPa؈RJQR^OO0ADxmv_?2>?тLJ Z 1dc X*܂A vf5:Y"KLcݣ##cc :hg촋RD7 f,ް:CįcP߇wyX q/(,ã  +|6!Q>cBxg n6ulv|:s6['IJIF->;d¢^v-^ƩdaBQ3>wꌘyB,*z<_1=3;:n;yJnJ$ύٹǂcfk4w׍ۀn7b3[cѰޭO4a0yDHQVmIٞ+qyd}1ݝC#7D!:eF C:G o@r^ZGkB`ucc'.">e`tUA-M8 ;gh7 d'BRSbvN%6vؘ8Sq7t@*3G=Ҟ> zRDOSJ[.BeXAC#Uoit1x݈^>cGaS@Kd''3PaaU,X@mQю0e: h(aɘ !OʵcӀ6:w|n7{gPy +YqɊTO(X<ϝ:}&$F9?+D 21N)SPK)W2Shї`mCv< 2AJ .bȈL`~ hXZWM(ǐf4n4/ t0 يGtd1b s(*}Q7n\_s1 V^bDBf4Gc6zQzD ZdcL$Ϻ}*B%TR_1P3?`͵=;q06^V)e*X$ŒLXGdžc#Se 31f!56`c.*=c Fq#;Fݠnkj+uƍ\4TsncRVRkgBY9<2b1z'l(4VzHIe#d"С˗j|h1a!81EQ=X9ݥcc0PdfTgf]Qpuf'MTJ}JÖPf뽨/Zb'LC D;Kj}[JVNPX ֕fu29G;v&{>#Q(q>ac 8?W6S:c2@txG@²>lce\@y.{Zbkf&A%[ +6k]"Ya^ (? ȧ-P0F\lrLF8HAHѱfr9>Gu.ބfoBf'\I"tdz@Шc@A@k%(>|FFnF(rEcq:rÄ1q-t +)O3 +oTbN8ڰq0!a/ 52ҹ!#7 kvtt +\@s ` *XҰMFe\)h%h)>d1`]o؂.mc.v6ef/f/E=.uP 1a?jxV'h'>h~z` e~zLn+/7ƏVָV, yBIHy#Vh6^RXEd.6he &њ 6_JRusY&MU^}pׄOҩ9oK\r+ l7$%0f˩)F勀4%>7T4 +B Lh/\Q{N U^yF*&&UԬCÖ3y|=fa0(_)$Xƕ'T` 5J.ZaqĄ0) g3s!TO\BQ{PB\ tSPJ$̘bD4 e%; ܌ +cмqbT:yhȐEcat +*[񰨶r!Ͱw澒,d Kt]63EdKt<mUWxpȘMdu#mёְZp/6`#\Ld0[zHy5٭fcFRz?9 3J.~ IB X`'Ce ` `R X{LC׉q'dqq.6͠Q#&\Zkg| DL-H+/MUj#.n@v3 0@PBI壟HiNEDtɦ:1ȥZog֋åBol+veX'99rsVfwQ'8lPfZ%$\./XqJʁDvo\~2?w#c&eRJayn1{e '4NsBY;#Xm!Lsi :RsihŪ g妇JM%#ͱIȴ "^hDȻ[,R4 s<9sXSd!C#Z.|Fm sTlM Q.&f@y3>yc3Jy->sÅ%pSByfےlf 5| (V'W̾Ԉ%O?QOWpđ1nvF@(QOn#G5 zvye%HhvFA biI/I9o:,`VF _!ˡ!+$V6蟸>b=C!^D̓Z aՅՕK61 1z1rف/2#O%{,ß^XDsFi\'#FDef$Cv+͵7/<|{%#]YLʚR̯f{k6_!TIL1ȕQ=fnm2BU'Hhyzu.Qlfr}_\3P/jƫGX?N"X};r#1j%:Pq0szÝ6 [`PnV.b1y:b@sI.&' \ Jָ7jf>{rOrrرǜ\1Ң0 pHuȘ ݄s?o[`:qT6젮܄:ٜ7\k\^z& J+TI@vɟ_2@̄r^ |J 1'tGMLZT}m~St-4+dh]Ir"$E' Vƅ4Q:mDeF)ŊFAJcn& `@ O!y} p~Tm^щhA3xu%^XZ-:1>Sj[\٤9BS'|fDC64}H(p~5|fXGL/j{H 76I jWml'4Εbiczh:f1!w-lt3Zs1с:\*uNAѹXpI$;Q# uuӑq _ ݟ =B6,yBl$|g[6t%_jވҽٝy\ѸD0IVmb ;G"9n01 9bĎZGm[i[ںW>3zEKd+{?uou\ߴ2di)׹<(_)=lF$M.4~3@D}+{9`R{>qi#@|UK]jhxo z/F$%jFPgFҌvwfW3koݻqS`4e|}~4x3غ1cuyLM. +.&hfj.QϤwbnpr^ٙtSვHi0X^4{!\Z_nmݜp.X0 Ҵr#.&A6ˤhCmfogk?(8BYM4nu]:6{lQZ-\kɥƬp0N +X8P&)0ꖬ>UwI0DOx $~bAsBbH] 4c}J'TZv^ ` hn"y@NXAu.zܰ ++M9ʶ݊WƺRYǢ]Qՙ^&vډY̧)9Ff\4#ÛX qTO .8b>4)1j~7__@ZqA-.ҭ`DGlǺP:Z}FݣVx>*ڕك1/m4wQʬGfmXUg5X7x*͟L$yRVNKD@ +zY ᘺH9[mPQ)!4/)ZrӓSIe6ҳ{6/>vךa~ {FvNMI *TiXc)H:2Y|6Z8hc.|A֭Ap!׫(U(UT)ÙpVG9ݥsO0%KQG#8421 i`<츛uyPB̙3^9hű+qRPBeQ3#썻y"`(mxܯc'{ ǎ:,(έT{cf{\)%;+&;Jsl܅I|$3~,`L`bB5wPFAwXd(I/,JΟ]yy5 @xv5̎=.0ׂѧ}b ,^Q۩idxӀϜXW,~7F, kXb¥I'~r NGX1kp`LyPGNP`'PbƤ9w4@M7+2E}zA. r9 pI'AZ_peN[Q:"CNNzǝ0*n4$}b'1 R/b僻Veq|Y/J.VpѲzqu˂1aGA9l?k@K-gP@Lxo|l/a1TdS+ŕ{R~3^-z[w51BB|&\\vzۏ+ DHϬCEVw&4\Ofh">!0F}1_;$g9H+;-r.ًˇ/nf ܼP-6m`r?܊=`@0;r |/iN>5R*9c~`2!* TCڄ1-HIWn:ڍ\TSJa';:Jrw(  IkVsZ98: KNXч{x:,ea&)I:@A9HP:҄ rbjʹmEfe|`c U5rz&:x7)L{k^~ѺZ\LvK"XHy$3G6 +HNUИX0e2(*e3\^o܌w3كLgXJZ +pI`'7ҵ\vKb3:\ljGT'<ʜL"Dڟ.W[B5t_:zBcbeH#ғO-XKDzT(<'&vL4Ih0ǦĸGXn>mV\pIʨg;Qj/TцQ[Z|ډ."R\nm|IQTXPY껉-ZS0szuRK_wYD1ˉQI7f㳌шWV8i%:%m:>gDEFyd[{!QipTX&#ssSzĎMyY'3Fe)\O/>8sDg3^.}"4o8ތs+*L( M@F:bz5Rdq?|@ͤ [b+&`Z\o'\\2fm3TsoItpcӨ3)JH@t cs7vrN*,3ū޽bX>stAūgJkSݫR)_L7NXQPa=,$9Rk1 )<\%F +GfP!\zAFT.XON9uCF5tT RrJT} K׮F+T죣8qo~]3b|KSs+JMx86d`NX=bJ9GD `88t{՛A> vztkRejzZVrK;l^&gɦ!63jǟuOGlABLzTB4r7r?^-..OT.Un* Q DW,0y!B u +`h%贜3H)LNAiRc:pq i=_ peygڛ G/kkBuB֮pтӉHUˠ+p9Ty^Mܘ,.< =7H5@96 q8LE+z{Q2ߗR5KKZ N܏GW[j!'flbs K7_>{y., Hqw7W[."7>թb (BrA+nbI FBDk{APKEQ_ +ei5{tk/~[M1}l *D:.WPfn~Ԃ Qᖣ ~2i.Nuv3GVrX^X}[+W@3x']Z^9xQ&BJ ᪑hԀW46v޼U_"ޑKjNA +kG*ћg=j݂|R0[ji%naFRFf[„$,B$V}|=;{h6L{RK݇Y6=X6.{)eF+brx"61%N[S j6]'x8-44 ofoF(5G +Sl4 b*HV#:60-FA„Ձ͝xh}꫗UX.o{O, +e0&i`O KA:mC[}2Gbc]6>=ٸ›Iʹ /]ù>/t3/@֜ ~)ZQMֻ1 r|t>&zzv)!psas\M2>BzapX?)uޛݹZԋ L 95Ѭp(2DpnDrzCZx(3ڸqKGs+?ZLEg7ꜹ]ٽ;lo#Jr\f….Q?s{;_:)s*NCSlr)[n4NqbmZqX\h]ݼ0:ޕ\x\^ }866T2ePE:\-5(& ތ~}"t!_|fR"PH%Lzq׻H`*/ 7px*R +ķkW6`#.1!ȫnuᨳqC58ᜎGa+eTK4P^aC`AӝZX +H)//z`bZ)L(Hf vDN 'OyvM8(?I?1N[#5 7E) khlВv^$.VHj1\քXՍxk A v4P0%l>i bPeW.o|];*-_x2hgϴ6xUMsǨ^\^on(.Qf.}Wݴ.ɾ^Z_8zupjљ䋟=x-I4ׁݮ??Ǘ>rK}o=WRZy'Vc\ t~~ކV8^>%KbUf6(:l3Ibhkd8+JrIBbev + ڃ"gL V'zs|Mi%!Jv;7wOx2nb + DNfpx +4~mLW0ґ׭$\*Ysět򴔢'DnKv +RREjU@F0xDi(L( Ñ>Nq164cst(N7LLURhٮJ͚eHLV ,b'CpjM>BsǟsJ))B/gmzJM7kWR?QG9S6$:U2M6ZԒ.ƛE5QMTjcCDcC-̇2̶6ۃWXt絋޹仗ŷ֯<_x⅝o767wV$gB"l^訋Ĕ̓2dY%uRjG4S~7k9w eX!zM8liAFL(B6X4"S^dž -)MuVFs-1Ywg9B-@+ zҁFEl^tr々1!pRA1Nk9%Nv e@VVD5h9"Y嬔h@(*zwsy%Ō'BQr$[l-T7 +<#$Rcݕ`wΛ37AOJFb>Bt(οq;Α^o,nң6bsk/9aYqڞ;pyV!<_yv\Eh%^v!dp(^!bJL9?QZr8j/_$WӞ cs<4D_:Sr~!c1Z1 G/uWnꕭ)hV=1@TP!VYEC/eYpJNTr u'nX2++ yHII=jT4<G 5ǫեsw:WTuL`h |8O +l =mC_?€0%@i>B"2g!M:` LJحhY[k2|Y] =6cd(T$(8(9%LJRzOKP W꺜wn0kd +<&pq^Nu,@1u#6T|VI/ BEHIQj AoliJ!Z^ʏ)/ oL5? ii9 itwgcQ8łjͨmP$zΔ<>Ꝇ`ai>;DQidZ* Dj_yn?Z'g3e;a&R.%=0kq!6LJSށ0\{S8ot[+{i 1:J:($()${\JJ+W:+d>p!3oKs>2Әؐ3)vWd4{N{Iԗ  :aC~MpJVW@֒Yt')ۆPn,8t&%D̆R3Zq` GOCb <QG_Nكav#W|gcAw"G9HҼW6C$#'c]O.0HQs9l^8^:x %yӋp.#B3"Q.Ai)GHG&Aթȉ1Ԅ@P95eʋ ‡F@d +BGGNX1[*p^Xz4yz2.pGBxsjZդPFwDK `7C0Srkz Zzy{jz~-Ș^sBhK~Rы0cb4I)GEno_]KDKCI; +ø`ٍv8d ND&48yDi5U[V…E5;R+&+?ճs,@h9g3ƀ +`7b0Ӄv Ifc괇FwŽ9q CU;Bz/(=swX\ شod5mGBZ$"ZEA>a=6yn;6Mp& q{'z\֦܄GXϜrB P"ڜYIfO?1ۼ ʃZ J,r`V{l c J4C,Z9^i.tSCTdԎ};(pJVbqcvpiT8E\:1P4 rϘæOD7'Ԫ`vB)V^RC(@.5l$gpd h bd]0|N+y NXC4@sf7hJG4|zٻgExfĨgX).)-eXV/cFu. "P 2T%=R$# +J +B9wRDA1ɰOz ,> 8%LJ;.XSh24!Ht+H |Qa7,<(jF6nIϔg"Mp&d.K)' \IկpϷ7@e2tLHzMf϶~H:i0!D%$|F2}t%c 'mF@aH'Јۋ) T5Ii Q+(a)tЏ./jg&TĴR6sF( AZY;m.~TG');X2TN;m BO-AXC 02lw c#O  O2$/tmaLg+p2!W tLQIj ,h̕ +U-NK(ѲGD"[ZqR{qvt񼮫$yU(˓v `,\Vi>J2<׆LdM&+F Q/g?*TsY>Z(^'mdS#Au6,*b},T ORNŃ͉)Cx,LJD#~T)s`r|gd<#(I $4hd{T<' |Q2 r.㶻NYxT.Ϟ<| #tyP*2>gƏ8l. +h)`tESEBB $KB3N,SEW99x#p#ę8-&FN;I@z)eęVb0_+ɬVϮ_[]f7 I.;999z2LJJ]q]fX(KFMX;7v=ye3rvd92 y4'QTv)8iDmԍ܃ͫ'osyqģBry.eH2VN+jd#4/^Rd\)4f +wm\(bS<bySOb(FB:!؍ /Ժ=47WlBIG`.dT4 D,˕=:XtJZ]ݾ7_ztŝz,n0E% %(.x>!4Kz1oSvOoۏ=wv{sV+Iq1Ahbp&*YCV̅^v[]\}={pVqSp9̄ }n 'NZOOnrA"C& ^͇UQB.gh"ffs$Íwѻ{[<[7zν~x_~|G6VfJrVi&|wSx7[( ە28.wn>;VWoRtL8"h  t-w_ӛ3>\7?~'L=̷LVۿկ;>9$zns@NN91Y| &I s0n~#Rc{.?kW{/pPun?ۡHTDQrwƸwؾWۛQ^h_}ͻk_<Ͽ߹_=*!͇`CP +vgn}_'o_~NV;ӧ?O?߼~N~esT*HeDZxe-U?o||უ'_{7T=xzg$x!wr`>DCl=;Z+må }wo̸ႨDVcij__1޹1/|t??/=ǿ}}ׯn qCf9I7 Ehly'\Y2^?Ż>~eo_O_>ݻo>|<0!6 ýevg/߿^~?O;~iT%\ {ՕNj_Z`?k/~sOտ?|q{qGaĤ )zPtYVV w_X?'?}?~/_?|YsRKq3)$Q߽凗[?xcv{o}ѕ7~ɵO޽^)٨2Ĥ nn>ۑ/$߼_?W^|!GH,5nhVx篟ɷ/s?+֯}x'/ ^VL!?,1!EY+碥Hȍ胝ӋOnG~_~|ѧ|ƥ{׷IlHŅ@=F,YǏx]߼/6KQ% 2UYMK +!sp}r/W?xeg߾[͝jT 9ND,6(f&'ewfsɋKׯѯ>{?}e<:۸QXDY`=fn6XZLGdTrPRn>~wÇw_~_=_a~~(0d QIfzl,QPU+*O.5wW>|d󽌢G>Б|- B4D$O;MFgo[?'?AfyEԀ(P4LjrV*_zm{~'ۍU@G4|rխz]) +Li{)4vW-Axׯ]Xn$ lԍE<ZSJ.iɢPCr s~WJwf:f"I&~p> \.Wϭw.|w_X{WΕ5> x| +$l2M ē+W/m*&(D +ja9׿I$ x^rKX(mJaUAR5!Z`6؃CD`c᳼B*[A^Cd2Y]r2Njx|'8̤w>&)u\D(r *Ś ED^b-7zǝ,")gmv7K ^IJ6RP~R֠fGJ9ӡT?\X3+[jqc,-NcS-h}[J Ĩ,'='-9%%vԘl䴛"Sc9=eH2'&!#cr>ϲ)h *.: o\#2Gj!z ћ䄁%kgjEG!ݷ/7Ic$ Pю:PԤL?ZJ4b-lwfQu^{X ۿM33۾e"^!BϬDH}2fP'Qfs`eO8pUHw=l KrΉNLSՍL +n:)g’O0= Ό-٤Ѫ)8׫@ܰ$u!%ccZq=Rٌק2ctrP)8dBͯ"R8щY*>VTn +y~(fqåhN&ج^\T!: | :B%.t5O9?!,W~btƬדg/D]y2+L7! 3 g1kgwc +]iBR?I}PHA1@wWb ʕ|m_mK~kBk'p JmT)8y(5OQR7Qvos~ZSty=o5. t|?ٻ?ÿFVeo|䷝yt+GNႾg +J;# +w+iIvZ*A̦+{Jﶺf 1n)/B+AV|Km_'w*#RU{)*w0MC'6NZ{&=k<*/J7o6g\eNFﺾV^8BYyqG;g 6:ǀcb}vbDK|>Vmw=A\[wSYRҎz;vt)"{0tF{YZIz;_<}s E-]^ ZOh4vhӵ$XAFL?l@٢,.^$c/m*|ywww;/'OsbKv~QolԜؕ[Wŗ>WѝM. B=kjo&g_  ]M[LЯ|5=R-^#+x;6_<m>&%n Ruï)9j]UO_D@fjtru'XV +nּO73J꛿+Id+A<3z_}5god*D '4rB<}w}juٷ\i֗Vﴽyu+w~˗#XP2b2Ѻ絝5,] M_z_1;~3:ɞ9?߹_K[NWϛ;wny_'ýg -f D9+w͖7᪋PFĮ~x[IsfO,|wDy7RlUiwE)IwTs3ajGV|uw}doe/91k Zٻ2ϼm^1tKPKsÍrTkA_> m g/~ߞ̓z ?'rAj׽oo'sb7sWI>~;ar}n 0Ö޹>RzTş`PI)֡Hk 6z ]]ۋڧ9ЄPS5G!aL)K$dBF.̌ޥ7̙ "ꢱxѻGBipp>iyٓeoҝHEm2D뜔/3O-N +Jsڛ=yoW7{'ry{ 댼ۿo>̓Jon^.'TӜG39PPW=g/ BV&{LyZ?vu~UJi=.߀NnK} +2ovqRc4fWW~w)U˧Ƿ sq0;^Oα:Q  4s7wΫEyTZ̎dqP*:8,=eoQ=:7`NhNAle q=#xї /!]Xz iev#T8Ba 9}^l^4*SO|;=[[%ox)TǗ[`g7ngޘsn4J=ot7wyTHeo;9U'_ћ6Fѣ*J}%˷E<|_ڙ#un "E޿~c}~i /}ߧ2Gyw2Xo8[K M^G_(]czJVO?_}e-[#sawբEoN>eyxotWr눮sZ {|An_YEepV^ݣaPZ!˙ [^Δ #o,c—sjv(qU-'}{D0{s4c $oz3B'ctN[Y^oZ32v*4WSZZPffdzvϲ|-+sy0so`ƨxGګg\oߍd5yRUrר\;I|>)O8˫7EX(#])SDkaNc닛7ʘ}47ӷ6 4_CQ&Q@W&_^A] Rҿd:gJ}E#W0&(?^dJsT#Ztۓ_HOC@k"7([?a19q{_ .?~/ rqf(9H&:1]IJ՜It +r'FT 48k57?~P*]uNfmHZBջ3w[U,Wb8C_hfZHKF+ Urvv|ޝ\ e~ 3 +Pe/g?[==߼Lҍ@VuV$ɖrB #ĉ2MօڿFq@"R#zǭ%X ߲7ly0b\x~7꽓?ˬ̰ z`-emb|;<#yͪ _@ڐYchλ)Uξ~(HuYͮYTz~I&6.#MѢbuzJg&SDHhVƩl`drf5E>ޱ\+߃G ;_Qzxͽw}ob; $5BV^i1UAk'ǵ;AK]B힨cg|.r9cPD3'H{I΃ +m/oEFc|tc<bp` 3ӿ|N1_;|cLbVJU7V1`37|NhCKBBiw8}EX}™XY$VTElae~ W^kΞ`A26*Ccv\ІTA}>Z"{o' FMҚr3E=Pje/EI_j-;(=cuOy &^*pMEbu7V9=x ^ZU~_E}xuͨA}hpe}4Z ij(5Wj}/C:XR@6x74OsemhRFU> +Ӽ:H +mH?ƞp@.3R3TÈI^s{oڇo),>1cZ9*Y +~W8N윥(L3}ieONzx|a6H.$ʙז_t~م\Z;T=#k3zq<,M}/%ø竍Z]sBP^ymZ8_qy{ . /G؞OZubT Uf߈F)An1Co5jn/putb^w͛bZ/`qsRf>В5\?pBM#^)grqv +j0f'/K8iJNe]H!8S> q3 sw<<܈b]=֛{"%׶Ӝ!ޏ`"$-jx3 nfl-N^ Yj"hs;8KU\,V9BE+/AXMR%ʞ@uBɐ+G|+ R븃kvL.PVI‡Z>;bcuNyw+YZԆR?>Ǵ6`)*{_04'4( $nAJc3fiʕ9An ӌhv,4(}֞ z)6TSh;%F^w,/4M ֟{>&#Dux2>~O8P#x*0 6Fa9YU҄Gte:xo~C&WRu;Tm+땽)4mR{GU(ngՕ^cu^rg9ց +[{Z + xHA"ԶT;ĴsP)`rk;E|̤)qG-BI%c BҔCYC71`;f<}y0aD +瘽okHVjřzk`Z\j +.l歼TlfD vqckr=YcvE;ɷ +d$Lj|7"EjxSkhSFHsJm N|An^{ּȖI%KBAzokhAݎ; A>t-B?FҮ<(M@Ѣ]"iI/c<WKcV8#m'8Vڇq'϶. +aIk; #l>貵BJ,m4aol|7kP, +B YWw-KZ?b +"YwȵP-=X\}oSY>ʴ&>-Ec-nNsL3Z #^GMQo#-[)jvrxm[c!`RLjCe#e@)΋P}9ԋ^[%q0[ZN~[`%Y\&y1akWg:U0NSJ$FS{YN)Lev(f(=81rL@i B^pWAf{viixuβ 2y%j;s{'v9 ʄR4_RUNҀi+ϳӭXYQPKk286k-[FF23y+m?=AT) BrQn\ n1I[i3*\'mP4ST׉*M3qVIlH5rھC q&1Ti]4s2*6>NΙz;9Nf$`~^ +c/!nL8['_uʰIP$UXgź jbr;hC̚ 8$S "z"&/"1{A8K8~w@"xrgZAj3@ŕg[;i]eaHqK`<\Q8L +F hPwak=CE*Y#{B<4C7"x4#_T:Yˆni@;ŋ)'?ſF('*#8c96oAH^Nbv(+L--GtaI{[ &"U?FYiWd+rf\Zs^C\$pvA5ǘ}OuJO)%(=}$V=`Ny; igQfq\u7583u?fxڽL<1C|Sx) 93j|^6og%a>Т3jBeS;k|0NF'6` +v^h"6Aѥ]Z*Lȟ`A$Nڒ 9B,VAqy p,Tڡ5xlv.&?7;gڔ@J)i#u?xǖDy+%zQR ૤5@׎@NjzdX?by /k3D=H򐢠Ri +:H#Fj[8iDHNNЁ$,H{Q0Em%hPJ;aHp?YO05F, +߀"-J-ȮT-Q~7=7bGXNRnc,t_ +a)s=;/OfmZT,HmP&1DLc]BVÁA^Oc@(\o] α$18k +2q;7aQT܎:&w@Ă7KHDHfZytM;"5@ErHTܸd]Kp1SyCu+pc (*ORje %5"ueԏQ0ƙ>#.H&Z"߹^-f&Is3EHpN-/6þ"S/\I0@.i,`NGĮ2dQA͜f@=T69Ex友˟!0˷m+[y5P"xob,Z0E @ +&ʮZ^rR}=N~hm/= 7#VJ +8B0$@b~۳ӵ(byd1gn!iM`vRx82Xp9]`)v;-*ÕN+ns]܂J"!Acd~dדLPPo8ϕb+q(y9'Z纨pJ`A$T| q\ct0n'`N I*yK#\iSjD^(m8"SZFlY)nVT4E0-@DUR'oq f=Ĵ[i#Jj3q]pQz$c=0т u-8z $M PNc]q!xrrf¨p}J }R['C@yS+ [J]Ԝ 0+^h:Έ~KwAbcx-(9b{=sYrrI7!6(b#d*W".X`Z5x(wV̩ r+{&?R0w&M0Tpu˸9G< ې*hG~RգIn+cjw endstream endobj 83 0 obj <>stream +ua[ ūiU#aˈ Xtd9jH|J eȳ.iNe_ɱeLr;loٳRGeHD)61@ R,0R%CKHu`*Hlb^]4BmB]2rƵPY2q)b8"^0AWށb 5<yTkJ1 7/WK>H&ː3_pUAlOA%)7ap[O˓_7R63z67";Yj~ Pk1 ^H9"s\Xbt5? EڹZ>7ݽ4jG)͸=*uJGcl9xi+m *e5=}!%ij2g@ur\-xjjj!N4H J;,l+ tu5AS.b+@."7cX)E8WFX+Gὅo 0WY+Yw5Ӥ,%FéH +.gE-ꁴ 5ZrB4'*εwfP}X  SaJ;٫Zrl5M Awnr|.'[8 [ r7z8wblRo[[y./E>:ɔX{h" +Y Vw)a `xAT3sHjQHKia#A@$ tHQ S.If#΃0)aPڜ.FeO1aBp]R*ՙRn`] MX֍$sbG=EנڱTaƔBi.A AQ +FFG5Xkϵ5d~,Fʿ6 Z >n/1c +  ٘+P#a*yQAE"] lgӛW6Isl<8lۿ,-`a@":j@<[<ס}r&ϲ|c+w7FqD{'`XH0ɀwIZDp,* 9J4ec_.Aأ0a045  ؒj)pA 4WU(ۢ}{ [yb"EqJI v0sso[Lsui?F@ +0M9 0miH,]d;)(cEAZcjI\ I O@ *uL|CQ 4O!"doK-v-o"2'H0'w4+%_!ftOIyJ*i~#jw{=}( \sݒ:Y*֏t$YO +Yι `)f +^} +d*"wPD|չ(Jy}P0r}ڽH[ 2YTY}$WPO: & @0 kQ"WD)02(k+CPڟџ8Yi4}Bv$Ak#|i +-X_r+NH4 M B{;%mR_,-mr;CͬzA +v<#{X!v0o>LH< <ʈ PqioE.u/cdu+'ohf9 a-}R +Mv;ֻi 63,DK. *}_r*o >ɂRQHbMUy B@ fU#]{T5\0y3zY +//=uk)>E]ҔO Vo%qs]0֒4aTl=\WZyTD9sl1XS'5zӵh8'.TM*}\ԊbQ I@Ea,B#rA̶'.i`rgIR/-9{]TQ҉R5>ћ Hu;jyѹeZ1k~dӆ/Ǡ7b, g3LyCΝq<V0H P?Jsܚ@WSQ^ZNS<Y+o9fY.S\-'2R#DA[~Wh)(w2'5t$P'W;Y3I79J֒W(V@H sd&IR~EQ)d,<)U(*BI[GG9kZ̓G!܇q_ʎaFɄWH%|8v%vf~\0;> HZ{-Ly/eS]mm}8Bk N}TS SZ 7Wr|#M7c1ȭ8鄋zhr$zQZs'=FaAdf#Ec3ohϱ%LRw1* + +kqJ>ܕ^Qk0;Wl-/uUV dt>C'I^iZv㔙ۈ'6ϕja +u1(K^VfbLS^9bҴDjFp;J,WK1u~&Tl3q++E:c *HIBF8bhRh'&q Z)A(jP3Z R//B'÷b Ɗv("bkaLs0c1̉FqK$YͬI4'ŒaJ %Pu=4[O /#fJs V!'4Ec=sVJXZQ;Ee)j\ J:dJssR0 ai^ +F +c*3-Hn +rpPePTy4b +~_UQgANf˛.|r(g&O.n:v$,Seysgp aB>j9%ܰ1S j +~ώS_ňr /me߆/(~["'[#Һ* occLhQN!b{zu}2Jyڹ)2%XL6N1a!֢z²5ЈQ8USOqA9B*ߌ,RP2P^ +HV¯"$R ++YCy0m%؇bEl)$<%vFFwlr AB"{'C?Bf6)uOvR?< )Ts0`ˆCy4NW8A:4adsT=GU+{7ODs7X_^ '(";[Y;@ PֈYEp5e ZUy)6γL9MICkQũJf>m/J=uD&Yڰ6ʫ9Β]jli~ +R% ;kqb3Bzr\'Ey9>=Ҥ*QL0_Y|nc+=" NJNJgz>U!M3.̜vV->5n iL)W6=BL'aS 3a-yu=9V60ƊF$lyVE! kaA SÍ9LQyX<[8^r4&̅\?KZɲ5880 ^x3fv;I'=˴t#т纄o=A%͌,,h 'MX ,| +wQ OuoPǰZu$X pGrle@ЇyH8]m\Fu St[{Ho|-#L-ǷʊRyጮTLIw1$楫z퀴SfOe\gFb,o VN !"cڭYʲ*7ZQ1Y^%_+ˢޣa^o+{g,ye;'B\F4O3s+`JW$vE+MU R`Y3E)]pk&ejix-I 8D^ aL [qa U d1f#[)Z.h[e;0 ^i@4mP Ong? 94 c`[~\x>%n.qKRB/ \QGûsTj$qՇ8Q +#jh愺 Ђ̩\ߏg :1,@ߏ/G;J9[4 Ʃ9/~(bHtsS"WI1O]ipYΕ޿7;ų/Mf$L LP[JɈ9/B,x/V|n&!3ZmpcZajQ|=GrQ_QiPe(`i6Hq#Nlg,!\ɢʩ ̲yo=>[)i+)BjE#W&"?}x7|04j@dƧ1|=A v3L*2L~(|*G(L d+I7  #dUG*yd=ܸHN htNh98`r0IH,YqV夵eV-r\}ui +55b8y~Owc`Á!Mߊ#Fv1duwfm0k_z6&chgT +)N !E$x'PJBf@ZSDJS[H6w6O=7R_Bm4܁Ȁxko DZBF:@_nWn)SHDDmL˘T@#Hu!1#WP]El*7R&iq}ܐC7Iu vPTdP'ߏi")7mWA6dl`#Mĸ NȮ(v7P'F/{Bq 85[tu=6G41wBi>;<'P Tws +j]~;¥7h +1qJhp@͆^0I+ 1h) odBe:+1 sDtOyN?1+페HX4?Ӑά+* b@?K:oF+Q6jم`ʱCzKL8CF<< UUJŜ| f.gSlr6=}I ^}e-*>EhqA$.'J 26 ,B&ԀUvɈX  &,IEV2sdGLf!Bb]1Hj0<`̨B'2y@ZDoâryٌV,fFuN؎ 3y|d9#&͂ed2aQ[hsYPixΈј Sa bDC7k6b h[\z_ƊE͐HN)1e#aJf4snZ aF&, EsX L.=cgv:V +.F!;j<('yp[0q+en> 7 dƦ5JSN+otIJcVfmLoc>դ{Z'6e$*}Xeaț ֡2vjR(U>DgMTrDٸˁB_ce&'tLYuTx\L.T#f"maIalCS.7wU_1<@3u#(ڕ1y ZҌ&&v ݾ*X^9S iKvʡ<0su+IS$N+h-ԈQ-:i;d"2vĵ. \QG`!BܶR)2Vk=fWd ¹7zZD)$‚',DPWU\gM6á[UV(p[Uv0,MHx@i!k['\MTfNe6 P!guKOZ/TȔ9M8O8t-m„-71,p*#drʂςAv3:1ye¤)[綽.l=taHVP]Ť1Z.6?f*HN<[A +dmp%#G}>aY && e҄l"& +PAXiPAXp%X0OxݢC4 /3qu0;0hŤoĒXCpyJύXM_}XeqHLyȿ'mKB'*fc\r&ޕkkWPH8B "x rCfF0/br`ԸI7 1Ԁ(%U|ЃfZD=ڴJ43R:+#毎ƴ^S옌%jMC12j36S.Wt*?Z*{<I)/J882lrQ7ШJ ڽ!ADd !5 P !K +)TݭH7Н"nti:`v \pHl1qj;C pU͌;#Oͻ8k]0q3*A$66n&`$Uv~ a#6=Z}_B2)  `£v6K:Di%. *w:u Tzd@I3aD". bSn"J$sС`zbLOLPlnpeL딆Ԙ7 Z7THQCS 2G<'}(6(WӑTQ-01,5?n"h y Cjm O1 2WѾ2Q L('Q7ڎ*j 㷪c*0L)q/~v4qYKˠ~.W%=6"*/gE<*+Pr6+OE57 TreHHXjer..b3dƃx!93GrD>78bjWNgP d'zjHOɻE؞ N|u~hČLdJ@& 7^?:3 BJ֓z$hVN4 m5e!=1W'uꊰ+ a +p0)"XB[4D~(BдQ s3ʥ&jQ&\TN0@MBB54y 0ֻ#v2z։ iGԈE1쾃.huIȇMPXi0e|s*ׯ.ݜT??u| +k @P.*i,J t ޸7ӳtKEl. 6lrF-u37 y8F&uި @8;JU*!Z}Wvg蔂ܔ;dZ$(@Cuٙ  +k=`¨k#bFzo|ÂMVC q#zD eǓo -CTzb?!TrjH$$q:\U4 vv4&cTRI3pi.1 pRhLYu11j8tp%+Ȱ3]u:TYXrlfXOdzX0eeL CujP#R[a3}HCl PѦm f4 znTiPO* :sJv6{J=;FmXS+12r&c#TiEX]rK +j.Na$d +3!gbzo>*-ɍM*&k1vj0YIH6*vL1'AŊ#M$PBӈ?o Vq4,T*t&Gl+{|W#g1⍵}EY$b`eEr3b /ΓPK'X H + ٹHyx|.T^b=4@6`uC(m:䌕zEhksEw +6]61ME0k6H&xG9*Sqz|fvՖEhi\0:jsƦXXv: Lbv6|eF`$)V ++N A6>JTK%#-.,2R|VRdK΂+]r{5%\]8[<inɮ?ӭ,.J| qDMt1$lTB&hp_Xb]_flٞ dPy%ډwRHĴ,23lo/J6{STbIͳIčmªɌHL')ST^sjnL{j;ɷ7܀"6:|n%ONӉ\Yu +9t.!fg~qsɗЉvim +9^]޽+.8ŜOyY>҃qqafqgdǟ򆿾CfTiSN~%1s:>{6689-ת Iԃ5>e|Xc#?*܂zV6MD-pp_~!>D@96^PADLRr=T]KLǻ9D,+rIGsUw<ڤ./|nItfspn4iɰ [(Aw,p.ښۻ%*mmn?z]L5()Sҥd[[o` TԗOv˷˧-EqIo UnNE{JnKZ0Qtp0i#\ڻ{uw>.9$*kע}ZtjjYٜ |9'VMKp}; d}Tv֗VΉ5>7w9ĢZJMH/dNܻy "֎Tk/n/-nn_\:o;;n1* Rݣ0ms%Awjw//tL_peNlluT +Sc 0Sۉv6ԴxBe_n&Pk+Wb}/GˡPrtdmesS\GuxK,˭H}#+]>yOo2%N5V/fO{>nknPPhk~yz+ON [WrD#b$N- A*B>.V2Xc7P1 nX\8ǧjIDZrz7PYvZB~.7؋7H9eby,Tw\_uh]/,_HL WWIy6_>DcJD=߃om],]j aM.C"fuHX{ilIts=?a$=0ErB52e"bo7ZY&3/5v}ey%5׺tq" c̞M ΀]8tkmk+*GBGh_“k~gss{*wB666r +br >Z_8򩇞~-߃(KvwS٣ҹgCy"Rrrs|iCK*,[ܹ[=˰k":{GjB X[b6d劑VqጓU+.3#dK=X>Hxgu:ozpa:…Y6sypzuyZw=$BhypxNXf/ w^c{,Yھw;'PK[; ӗt/YXo?{=kfKz޹_lؘ/;vx_ـu7&2D=ghgޟ U!39n +ޱʥ6SBn9"57c٣vs$L 3}"2\wkf_wr.X@Y\B}zO T_)-MtgξO86ؾv}s{'݀7MLhebn gu AfN,] ʕc$G]O!&LR\-BMD7\^-/ xYXF\*TVI\F"b/=]YI潁bnlz\nBe=l~X]L5n BBLAwK]xUn)v6MXՠpEr:\-5D*8jKdkCN8?Ұ#\nJj03c%Khutjxo,O8Idh_#׶b݃3E3p2n_:T]2ϭVY:.>":r}%ϟMNљ9DFr= dԟOf8 ;,TT !CpkSSH鱐wO N&EF9(pN`B??mVvcrv,纻G>ꛟP>!`eS_:ބ ;U^>__YZ\/Sr}ԍxqAœřr} $8?Zo̟fV/Kk/= i,\P;hԗ 2rW.X+XnV/t7P:3tj.9vy%*OD0on%„T&e_cIKk RTta#܂~C|ƊPFDx;I 1eب(Lg?_T>c>jlq<fr3`lhDFaĠ=K꫗*gmT7 ,3 7;ʋU(q egeodKj΅"16CvҊ^6ip +*#1|wz,ݚz|`]9Ŧl,gJxuf/l"Tw+{Rrz<>8zɋl, D,&fNƂ(@-\gj+/P-V` Lu.m&&Q1ʫN1DּX숅WΙ'+`J$vâỳp`vST4"JrMT3񼐭r!X촖wz'}}nn}T4!xu%R) +D]b<\PEQX1É$$}i5~GRQvi N^=zQ,Ɯ @AչrвKmOHO"5)Dk'Kv䤋0A.5e<\2"VK[wjR.Rh@u6 L+3%re6V[O4C)aá ;&悩iR4nENSZe:)ҹ#F 6E+_HH.[o_?wp+=u|7O?w?ɇni4:y@. Gk>η|_O_xo|_o_OO\yv:\!%EW2 >)5s[Nvʍ{׾ O/÷g?;˶ GW\x_{{+??@~k~x4`M+}xl;u}<^{o苯?wއ/_᯿xt}I_)Owt܅rYĿ|w??z?Osu .ƌ.L Z-ힸGo??w=T}~/z&ﳑSF%*j;Fsvmū=/|Oѯ7^GxCRz +5I&<_Y<8q¥;vy?O?{K\]KzE'l^eF"J~W'_?`:|/٫_:Wl Ѳdst؜]Y۽zw|g_o~g_}[?:.Lsr`T]9vO_~+o>߾oo>>쳏?(GD ى1_%bC_x//|/?[g§@x3E`icԹG|/+o{o|_~_>LcdX3wRg-_l=<ҫϽ˗~xG|ܕ{i&1"Nj0UeZGkoO?O7'_Ow?G/;#Ǎ3p/%k]/x[oO/}K/PzkPiNKQ3 ;뗯]{v xe:+n^/GB՞ 6n̟ͯ8{{+W/uﱋwVdVy.ְ"!K?~tШww]8{؃'}̋/tHdD ѕ8) $.pOTlӧ}o~W_~gߵP-KhŬDh +)\fgsw˯֫~?_<ќ7%&N:+Fju3_g{o?>.+7k.wa=2k =!Brf7/qڵ^~os+/?vyG?~n{=ns{== j 'L462+W}׀x?7ʕ6w6ɇ Θ-8DάyEɊS7{y#>z8dFԅI:^*!J0^p 㵣p_F"4i#.aN&v:ކ!D.\7)E)0etZo<ܴOk'm^2:XeC@N RhDsd;x2JӕrYn/ $ Vz,/7x +gf1_LxL^tjRӟ0Hҟļj-ڄN:Jyb*[/*uxnLv9<6a*Ȥ ەOlBb2[Nk?p{9_8#\-K(&y)5ʟbh"8@y^LEhj.X*l],B_"8ktPE(ϝoy6iFe FTHeҹ(Idh*J(gMʇPno1Vu.P;*x}Y:TOkăo@ +U$.,8e]d؊LOGI#ƒ $:\J9TH+ATҊˤXpS٣w&%,b= W,ꡀ\ldZ7qUqXֵ5lnNd^Ɗ]IzBL,86iAܗu3 Ls˨XR *ZQߤ3uM +#Pʏ11"(&i5&NQ +tP2'2ٍLU0:8F +S6EJ#1G{7f_b{fKH $'ER*JRWjSwg'5;{ol]~=F Eos獣Lj+d0x ey9ʹt "b`WfV1=2݋9/b+rq+>vOOƼHR_sO;Z${zR[@rP]K BMI^*oy|!AD^2&RTiI%v} \wnx"hPH5E4iFj(qR e~|`BAc2Z+OԊrkaBgLk'6GCf5`K]%S'Da:ǤFν(&`Ga"a8D]Nf3TPbḞ :Äh*P.$9맢^/P\<11L"{g7@]]/5)&=HV&M%׿CJ16har%DZt1bg=\ z/-CS02spT]BN;`s5"bEM2]R޷ 6/"p.a-B*puTʮ1F/DeKMJ u9.3Ɨ\18GQKJTP$.uc)B!8mׅ}nyQ֫P j)VOٮhy'&){1w%W/Xt=hkKq73XLE.-,EJ3BL@p |98~q5H-%]snn-l7o>6,qQL>Ɨis$Ԅx@PtBJ%12myZ-D0-&+Q[-6E"7ºdfyW\hti1^^D#tNuV1j|Ó3qPQ̘NBճVJ/9 Gqy/zm1 +%80O.iS6q#I\kj}Y +1xD0BޘgB<+5̴Rzwۗ(wiƻ$,]]0Pt*"ɚRv\.JON^mӵ=>~5Bnv3΅LTsv48~ +3jfk738s+ws 67AB0= jCMmz$ͅi_tBR-&0%;kraM(7\Q , c#B +Vv{5HO0 6~5D䲗LpJbx:އd((%9i ! q厊PQSq1iUhR_ 3 >KZZ &cGp̓%qLH%Y7| 8k fl +Ripy\y'q.K׵{޸JqFw" `&Q>3Ixb"U kBƪo{la.%ip¹Qθ&2 ZcBHD,7}RLa&5UXbM&m63*p|$ + Ad1L2(&՘wcj#ZJmNۭ?o=7V*f wBpPfb,Ja |Dn[OƬ:V+[t 7Z莏񳯼-hrA~tPfOyYDg?A֎҆ڣB 9.}=9Jw[|G0&3m4yg8;8_’>K`PFaNFjNgspDRaU6Tڐ`%lF2vnt+Y іj&1Vh|YmnElpY&3N(%˓Lw?&efXG?٫OT3[y#7>n>l3ZyS|z\vS|1^ (5l|ִҸwuz[o쓩&~o"9 ~niv-E?LROMS2~O;PZ,=޾Um7_9Ws׼\s% ҜN:L81*s+φZK hkrOM\1y3)W~ Gl"twL?0]:/M(mG+1qE@+(pBXc!ĸ\%Q)n@<=6mbZ2A娶Dx~(V SZ5?8k>RKyqt3,ڸ^3{JezYuVBt(o+u"=yViZ'VTR6jNv=9?O~v㓏p7X ljzMo}w6}9xT|to +ӿ˴jFٜD<:K@B77yrmחg} f 9OOQ&mEIlpMθ/E4W^Dlov!t{m5iҩ"ZQ32E,-p!~ҁ״]մ97|3T0S|%ƽgߍh=w˭h%7O4G8[L}pBxl8O=]u0YT5ֶ.rã'RvW*{ɝ] +K($jWᬟ!h#6Dg"8XbbBLQk}NAJ7ox+.XN{{zs]wB2 -\P 1:Da&lY/Ogown.5hD|J/#r' +gYQty)oVpFAӭGt1ܔݾZoi="=N(RqqD,EU4wWwͅ)= +ڇW?0:biJìs{ "f=>wT"b\;]dzq>b`v!0gS;OLl#?/p!zy!Ī9i؜\l@Ҡ6>m0|TtB̴;lwQ6@mwVv?N?Cy)1r\bj+D.nVPv^&4B%ճOu컇}yrxŏtfaHVtx:.T?\DB riCW ,m`1n117f \ws +ӛ~,kOͣtpˍj?Kŵ^&@f)n6X}MC:X`^}ھ8y ꩹G|֏rn5؃kNhk<` !9A˜y Rv礼q +UYqDžߵ?-o=EK (B;ǏH#*E:N5W-bLZ+֖Nxv.Lf0:~uw~8#R|'bq]*͛ZEy'|L2 zOuQ+vim1|y!< 맻ƕ`2ioemWX7HiA*PLH6kT(nHۏHeB*.W!"TVZ`!PK-xKK;Mg+5eRa:T[_KC=W +6$|tGl,Z0#fGz@+8+n^ZL,pyk&GiaD2wꫳ eP/O8| Mp1R[ {&Wt軾z|,ԺiBDP e6p8뤲ݕm_?_ +m -U]߹L{^L{"错iTU4k,GF~BشvLOc,ĘtT[=ݙX7{><19_Loj?.VSȌI/d\ s cFtuZ1’0ǨUM V-˜YdJnP>;0S]8ӵ*;rfTlr<YHAR}JoМ^srf+Q}qkS#(i(lW)T1F"-%LT^aUַhj ?/9kW0pF r}{Mo. tj9&.LEJn ' $ EЄRg3C6+2[{8+lXy-djԀXC 3▣bBh,#nhaeq#2Fs|riwf1Z]Bt5oT-KOo)"٣ Pr\\pK!rw>@O;SiL+1&TGo#&0FcqQ&wWw.dM)=Y+][®,LAhy⼏2bK~kV/8?iF\˰^sI39+E$7y^ln, +>A.E(k@V(1:)X-)N5ihYo.8fp)?.E$X(!ff1RG,cX. Twv2N~wO˭ڕ *Jk6X+WT0e.1>rx9gggԴLlH&ҘTq),oB4׌'9cپiOWF}.|yoIB'+Rȣum1:F}0x!","*X+͛O\8qtmq>}@-#p%[Qû]] Kq*Ej b +T"bk9a k֍yLfBIjQٺI}vLNNJɍV\j۩6o/Qnƍ/"@xbyߌ޷'MQwuSRP蝨NbiK|NN5ԍXU#f7/خ :rGENuxD%4yvۆ +%삦g'\Dh `xdZ*4̙NϮy@|quփ흖Jrl1HQ I H.\ŕ""H NewqoxQ{:3-/"(@;xdǪ[!8SLȄZw|q͍_ở:"0+lWok۹R\lL2dsk> +5Dmz;Zv&5vtg'G6?]={g[TkQ2?t^/dJ%iK;1+B(_~e.73!TѣTeY?x瀄\nՋ&ͳgE\!b+(pKͻ7?<t  +JiMR:{7_/G\B[j+?N Sꎲ@EE,i_N,y@B;, JiƝ"((myBuϯ?7W|xKJF KVAR4*~"Iuim}\|V]qܻhnmTHVFKa6s}10 +z„k FBI8 h)IefknoRz=ݺjUV.VϾ~*Wk6]RF3^(08mǓ 9dVѭs>*v.7{9ڽgZuGɏLԪt+*A-H? ӶZ1&1LF/+([Q&|D\-X<_6;{*g(KyZ0a\=lܺ2 &(LIFbw`I,-UoMV0>WnmV{!b)@ZA( uG3/RywnZ lG-_Ysypw\>3?ԃf{QCӒ( ]5+&T_At-]1N#ROV;#C5.7;v7\8\[zl6vi 3L6I!;KVmS!:eT[JZQť|L.#ju*lڹtvq~s񣯻Oho_jPVMuX*r݀oOLy#'ĥwB}>}n=]](f{^k伻uM5}DstE cPLFެj/az6jcEvxK.\!# .dr g9M堌x'O¸`:+6-Z 10*Wm[=T#`bgSB,ǠF y=r M X4|#QI /yuOTM)š-#7 "[ӝv9yPr{LժVC2i <ϯҤfc&Db.EWHFeobcG{\.#ADG@T $LWL#PKO+Zi3>yQ)au`Lg4v ++ӖON #bv>:!T]2WET\C Yp:bhTkw*7:/ ngb 9:]d&*NLo\ L#Rnl5w2݋Q_j>loFhb;w.z8ɷ!S1Ω_9yW\º4Fӥ!g֗}M/F4?$F}w.Υ⒗2#b{Ym8yO6mwVǤtT +RVN76L +Q.Pj((,H0@zOea:C͏6_O\}RTmZo3f/  '0љ Zm+*O|l\Z;~rڃkWw?Z;7K-9fRXMn\YTۏזbWC\\H[~/lr&3rT6ݰ[ې͍NGgo:'o3+Һ]<޽NtV)cu>)+&TTvۻVi}n>fU~|NX߃Ҧ7>oXA{Yy@ 7"G@wHc)z7:+t+.&@rrLk߇J~@~zjf{GLNE[4me_RNA*N$o[hb +HXG + փWu7nZUZw>óoetԚXsIs(JwQ^!>*N.7o&"0vip':\cSLwf 71r!8Za#N;ŕJWˤY{B}|>nŹ !g]9|JnҚs.bb%KgW\חE?Ha2C(V`i^:x +ww>hOHvۇK;όޙ^%i{*!Z H6@XraЪgHYR+֓G 9޼6dS?l_|"Y>3ha`((Lbk( ä@~t9Kʄ(۪n#W# !gb]N^ڽ?|럴l3!dOkOsB Pųә&&*WݹYY\ߣW} @G/2:!:.T=. la<ٚL0clMwnO~`W#tފN6?3jMG^Tk+spVJp6J(ʦ;,{(n9RC48U\fO[Gg߽Os~o.>_^|ݿo~*ƥ/" 7یD8e~^"8ǽgJi~83:Gjm #P.lDD:51zʉu:;4dt3LG-B0*)0A;Y9||G>ԷUmTolY͝ѭ2BiMp@Oc RXu57"㒣G>pa<BTέ'"Q1Qҏr@o~'/掜PuЩt>qXrYQ: -!d`JgSTg<1%|TZӛZw>p%VYwS bjKW޸Kਇ"&Ѷ +VM'N(U]:q0=Ț}J1oGCBIΪUM&lV58m5`r(,[kkW7];˿J>&l&/v+_o߃lօKH҅"6ӭѫn>h>G'OyA o|?ltn'gk9Glu*rSFN͚0/E f\JP _RkFWJۄ&)Wb1~iixuq@DĥRᇸU""ķͅ(?B:Dq>)5پ~Bx? JWcQ4ɇޘp!L Щl|Qs¨jT*P$庚Jɏkz)ȅ1ru&re6`J0&_E \22b'̲z)! 1jǜj ++w !հCØL87 4a)RY/11Kc81ABvlVVno_E}ޣony(\('X? Չꓧo~s_l#֭ů6/~U7_׋wNV'Wo??'_1fk_:ã'/~4^׶|ŒIEب$$=9͆쌓 03ك_34€OX/7ygşP$hkOߜ%IVf3@~Rx W܈[azڅ&A\Ĥ4cTK7\1 دW>F.݋P7*D@MRa P:S9Iy%!꼟%䢚2f(ld- މ6EN/X(әqs 3%BHŅt,ۙƄ1feE+o%%kڡYt\JaUϡFl,ǥ8m f\ a8f& "hLn>zXE>zFULʙ1ny|"dZьtmNiT>\V}ܜeKhջFwT5ܽw?=G>[=gϾ<:ɻwg̈́O}ã׽|!SJz?7C7v;뷿}CS1^ݟwPƘŭakU6WVN +` ѣ|Z#J_r1jitBIܠzNZ~LRMYkRZV +GKk!y6#*X1^NW'p:'JeO6c,0u] `& Q^M56T"ăs`*@rDsxC඄^YD8|U7`2rqu":#fV WRYK7swe{UTJ$Z\Gw˫hrҰVq3肟&.R_9K(9άQaT.OX cRZGh9oj@Lfwk˂h1i6F UЂBaw 뽈H &$OsiT=+ +(hJc:ng[9QcSY] 6o~+InQݽ[ +`d~51;p(̾^;([΃/VN?1k[b2o;f;'||w' pRq;3~~O]}?q QݸLޝ?̓Rd+>_i/~k\YB/!Ka1)o^ +F qk WҎV;~W[_̓7}wVuc>'!E65}ɭW_|Ĵ{?˾KHsZk!m6sct3#Zd%T2׎Pm`JQ)ݓZm3Κ֮^ 0eVnD] >Dd" hAEwDK\aiۭíVneO]q>J(J+9@K)Йdizڕ58 RL RVЁDd l{R^2TazA>!q)Ce)>غz|L/QS[R5FΣA )R=1aG?ˆ:ʚqڂ" $˴%;HrMP. +6v+StƇ!OfvvWoB*d`D,YVVT +JyhUֹؓ0R}sVz;WN_W0.ׇw^9-Lg;ƖVvJQ}rs>ʟQS93Ղb䪝)?5gGT~B)buh%.*jizV45M5?~7_Ǵ+K&ѵgv0w1wTo +⏲CMAQYڸSaJ^rk{=?P)>%*" ˾X$N#ab~< !yCflw9NRM)L6&d2u&M\$3?"Sy7,B3qc>pXOxB7tGjRɇNk3\ +!eD$KU32u!G^+8qB(nFNT.p#Hj1҈UL 2]IyV+05KWg3K'F&-v §GG"lr)epQ'Yѝet.z<8y=xDU6 >R4$.ٜU5JC8ԼbHVUH1 p+HK(ΊJ#)V2#ʪE9;BY;zplW!UnmU;L&4TSƌJ0&20j !tݬ={"kEp= S~7‡0-LY~,E 1j 3 (vwsT}Ǩlj5Fohpzz~qpibB+h?IZrfW"Rm!|1LR :YcsPuCd*9`0F)cb\ُzP0$q>iI.yd-!ôibJ?R&r:[xjDbh1\2 ҕ?*DzF<#\ W;dBxR%8'eс\pBn?;>IzNmzs{e>r}10]KBO\ 2ɚ%TWLqv΋^qxIFf[cz9b'&[Ƹ;H"LD5'"r4ZP@}Fp $U1V$p/$pU ZdR!:.]u}O/Dnf#.?$F YY/oqJ͛w_RQJU"L8-yfn*p */x_-(\YU K~bf)'0: S؇3޿2PRJ4̔sEi.G?*YPJJHe0z/?y g/9*<}9r8o1%&\=:!f4UB Y/F 1R8M8y7s-zP(-U)5aUg ZetfCHl[IJ!t""J'()Lm/R/-...λqJ`9NTAሪJb8Y,X2m.9ՐD"DJ Ó~qt^J(IUHHYC*P= 0E(] 15”LbEŪ-^VAAHWEz(g䛫B%˄](rXA#dR#",'s4I = +#E!v~u< 9PE2pAEO#7ąbJ(y>$QLٽ+kH1J xN&g#Kn q:0I⴦$TEE9| O0Q4Y^FYSfyqi.0=Y(< zLpэ|TABI̢9wɱBb1><.hrVzҴ3D>ܻswrV3崑E 2;'J,$y*:*uK9QALʔ*/^{xoZ҂b @AT*U|uSVVOӿkYMY,#r(lh6Swۅi/I7ZhlɏL/<^1ُ s(bRJ9O`x24/k7o54f!@ wUj*DöbJjӰqpm _{7Ö6a$D=~% d1dު裮u:>x7߾ћW'KgGfUpA8kl* +G\͍AaSXwݽ7__;֬7ʹt0z}v&0O9O-{}>$ 41VbT*)2̅%hX/ y,j +2Jx{胷ok///o>~oڶ8~B5y~uǝGo<l_?w~r6<Wd(-= 'Wry[?K~݇sw_~G׏٬q 1Z^ǫZ[yzgW_;ͯ?xG ы.;Լ%X"Qb:9_ѪWzG'z?=,W |n"/]=:iowq/?||߾O;̩L8 8X%G%AϿ~Ƨ_ǣW߾?o^/ǝGjҲ٬edaؔm5n6^zrG7?藟?w?ΓO=篿JP+H w<q-Kȼy^ܛ<̴?FQBȽ?ʭϾr'?|FwJڐVԌ M2 b]6OK}'w>yʏ>~wϿ>=zV)- Vյ<ڡ7?{ko[~'og͓r_;sXm/QDx^n;o=Yo^ݏ폿_ۯ~Ͽo?kAEܗ]h4J,;(-#|7k>yg'>/'?[Ѫ]q5m%KdOg߹{_={W~oǟӏ_|ן>](ܼ3s!` r,ݶhx'?o?z߹o]/oqc=P)bQF1&4vo/ (_{򽯜?[w٣_|t|_Z{Vf%4 1.)Q+նQ^ɱ/?_~~K8B$d/L󑖅oTkCճ'o~}ο_}x/]^ QL [٬[-W_>)}G|i/|ΕGW;FZ" "A8/>]|~gO>{o\y^yk9Y+z0EKl3K%2 :kUq7vٯo~?ÿϾ}?}_~WONKÊ!?L~ J$bV޺ƍw:~w?_/Ow>zA^ђ8QR'|J^ehkj_0ŧ~O<֋oW+Ρ4%DHfz.t6ɝ}V=om_:kugs[o:NWjz(3EINrBJkf3sZ:L}{/[7o{d/8ʼzrP٬*cq8rzЖËE42T|?޷_?|ŵ?__7n\7z,@UC(p@WL7qv+^9yyyc.{DT~7re+۫7O9xZo=dNiuS551)_<|GL)47Լ!Maܶ6.GA5/:9@RǸ+^o(afΠvu=܇/n|?}qw|ޟGpT_LA4BRt-66c=uo+[Go͟~{_Z/U^+2ʥQr3pyXB^eI_z9}㯭;U[)˦, 43κd pEc2v9fFe-Ϊ|ٔ4*bє(U}H葸6zˇʅluu[jN}&__/kN]_+'WfYNG0S ĒS?90;C +MۊP3qUn}oox28MPJIVqt2x0c$'8NDZ)f%LQWEE5g%NWD1&XsҋH`ɓB=S(/hj?D#'L{Y73ʮQIy^/ᬎbf1DNgi֌ zPMVaܬc!Hl\m3zKL60Zuλ8̠RH01b̈IBln/|,'ڜȏu5W8fQ)Ƙ !H/C7I<-䦡?zfRN-k+֑]sEAoX\ _O-a.ϥWhPc1^p>P\}v٠GEHCk[ 8$.EYΈݸvT)JniP̢Z5"(ƚ-93]w JQBb`rR_kfgY/,&N"U4-=E۱emܘJ iKxpOPgVu섹[[VVh0Dd}?YhcVdMP゗Zډn,zdz5hbjv5ȗ@PŒe6O \M[C;TT^_ȮFGHOX|fs^vr/j{qbH{j p7c!kE Tڤ%-6Dg:v!,f1.M5Zfͮ^VNLoUH/`Rq25&RN< KC_߿ve󣕝.:8Adb͌5NDqI[=(QVSc$Q ++[o>,:b [ +^= difV6Oܠkӝc'k͝78$bصU` дˍWk/$ZbӠۄՙKa꼽v:mCG6kj;/LVmVn1i( L֩_Jۤ&7)w"*ԕ:Ymg,iٰ`eO({!sFi}+n̘rS":_};w?|"jJf|C@T2|PrA>erP?VR[ +*$AiOkFXj[_]\q݃{++]O.[Gv(Y3RT*X3([/,]AZ}G1Ktv=3-W(Q,6λ((Hl1,k/|6,Z2z9xCTqp'g ?WL/?Sr;ᕷ[\l_K74Qc6uToѩ^TX#7fm n@k_xoNi{JikkdvACl^-m>]Du +[SnՅZI2 @>,m46)'¬wSykߑR%gL.ƏƷ +^('}Uɯ:1݅bOgtIVn`x%l_>~Pɚ`wF4^Zd=۾ ``&bq3|ՈT3;7rk/_FTKN^j~ {ZcxZ]=~_ZjdO_ؼX:mTQ\I]"Vc|4;^:=m +^-5)ƉaqKʝwi7aeg۸9ӛtf󢇌 +Qfxv+^V{ZuOR˴vtOZ~|h栗{Vjh P(Ymy-9{gbam +卻\~CoAŔ^8yKTcRqs/}k;m)7@{qbF&{ō~&v[aD|~vkIcqa,ٟKR\ڔ*;|i3 8'l,TmM9c=ؔ \1h ai?0!TLmjLn8b7+ TLu"Ҷ>^&p|fCLd J' +KQ1YloJkVLo챩Nu*D,'gZ + 5q:hnܸ|cլwo}yp+u,xy~V\o1j >;heUǧOƁPڕjջw<ъ[g5/?MGwQs+k]SZ{\4Bju\\>]?ںպd[7$m>&oMw7/gW= 1 U,h&GV5Sk`@޾l'{r~z~ͬLkgq[[G/K J-xͮbIsfLPfJTl@eMBb2 {N!hGByd\.OG$/mE2a-GX'4J-JTk6H[}v * ow("ɥRujr~ƿt7ZՍ[Hcqv7@sպL(g%]δ6&t7lɒUې'[Q*^V#?FWVo#.'jMP۠Mi}UWKHD(Or5vY)m&K_9]{z'"[k1s5kg|WV-Fw Pӗׯ`T7[rn-z"y斯e(7;eDbr%K1wUwhz1Ç%dYQA1"\8|dK/Xi&+;zi̧:A.J'8TEBLެ_PncAa38c& b)*5HTl2wnL #'= +mGx6ꎸB$Fk?QQc^,qb  .1 # Q=H& ʙ^rTk\.TIuRq-Wbr\̪AI%Y2),5cj0VTw)SFYknZ+cV]>ɭd<N +5% K@8ra 񒏒#DH/](ww?* ý.5s|jmNwl7!E' WVdYV 3?յBTzUo)7 ;7ގ5? ʵ3Dj%*7ClAϯ4~\UٽM\)ɶOqq;&VB4l6BE|wSc~AȬ^>{l$ Q,ʻs`T=Ta (7z'Y$;x!üSVOR9$Q }*WAIbZ]o"r9dB\&!Aº<*ۏ׮_2VQJaɏ!ة*RǒM?c6e4P-POSA|EC:*>[ +b;zK!EUz:Kk{&jRǵ].D{\ D/ ctl]=q(ʦW +HAϩTvۅef|ug#f bm EDzet (fTU?u3^*V2ux([B1Y/@U Nh#cuv{Z~78q{! DjDir]+n`| kCΪm=}!—@\D#tn1({P}1,c*cxS\ѳ/"Z1Qָ4 1_i݅8eW1S'˹S)!;ߧ):&RiT-|Ob>TmL.Wʕ-.ִ&,BԀND']-/cGl/#Ɋ|vTۼ 8Ys0Zy ٍDI6&Q6e.S> V5{YyE<Tڎ Nvk \1nŤzDVLWily) +js.9#"( BHu6"(՘P4B|6]1b 6Na6IksH2Hf LR.gD`0_V6o{`QZI/ =Z 1LsY/Du7?&/z *ۼL"A8a8ս)T%El\.D̀Pqy(?l{٬7C||ȏn h)u_=}m{La' jC?).9~RuT. k08Q + 8$ݫ#\Z[rW' + Ie\oS05MLsO0sĊ"TJf,3u P烧%=FE/-œa/1Lt^7M +ǹ5P|j{>-EdG,.IYڌȕ]mPERDsZUs9qс#sltяV\׋nT[Bn)ϸqԕt jލ(0YG-nM4לƙYl+nFmE$Qpi PFwpC/i7+RnO.vrW) >kOQ+^ +.h%'8#{Hg6Pk=Rōi AA:(M6)׮0U'̅ PY'b\*F\.mWVzg1nezG{m$QT ͋^+Sˆ4;`JvPYS0 Bn5ٹ]Bv+H3g" XV˻{u\ƴFZ  + obXImGTVfx=z7<6rv4.BPf:LzO.Gfqw㵨X IJiWL{Lmcj!_;Y6-A2M&t&(xbrk,YYs +k-ZJiF3~GTS (gki$dG[HT&HRDHÀd,##83 1(Z_MSr&JIbjgCEw{ΐJi)L^@HMm?f_r1Dcօ\GfdLeaVx2h@wBˠ&i,'ʗ."' 1DG"kH1l#hP( +Ҟ|Gbq㾗+N0)Z^HJ$k Ûk7Y]?c '0_߹k%G[a>G},bm,o49#tv/FUץ8dzriCl&O[dLBIzqyXmETn(Qnf\͌ eAm[^E *.g4f [k䦠8ӁMF\j020RTS \>܌U6;N֕- vixכ~:k$|"B|bRZϥJa=,gܬgh&7i|zHP',wv3!* g#Sj!6{~>'I3-@t>ϐV#|ʼnȎLhpfnftg'7'QJEx+&+7 IaFJ +"§IIZF:] ť{6Olwt^{.40v\*xqOJaK(25tS鵸v#nTMjFPX^s9L٭s Prגk0th5wT{)Pa~N{7X'WV k'wm/jvw{ߪo9i!,.Dm6Å2BY޸lu +gЭ jܘ" +(ALc?;%솸\Py`1j]N=%Bh51DTXHO>̈UGD9:7fLkɚؖ|*<cz+{j;B(k9KnPyAog}3 1Һ}.f!ToLbD|bRs1@2Td(2퉪^vI|9M;/LD|κcU=KDեQ-Sd`:oXX]bNID$e>fm}л.( Bt6%Ť:+'(g8i\kTM6O3ۈBk[Xr ՗]gfFDco5X%ӉvuƕjX(|qžsa9g Ћ*k͝>ǁ$Ӎtc+k +L+GR8,Tju&$[. Ln$jgXaڴsGB;"7.  Ҋ%?nj݃_!+3Pj(.duO,}EP\dqfi.w\">“T. 4-Z+"}Iɥ`\Z?5HrEl4׹T't+=GS Nj:fRf:@+湙=ueD m4TKbI5YJ+)+ZeN" @ynCD |%!>C-.FChTb&M2[z!0Z#.WZ<ٞ(~.d +7ջhR0ٹq0DLb +Ƌ%/L9/BAՓljHh=B@.(限QM[\9⦜Q(!TȂX;Ĵ.Tڞ , AGl;Q nh$ıX\6.zYGTe.sN- +SZLzc&(/EUhebnVȧD4Ŭ6$Ũ<%C\6F*0Q/ ^r*bRw"JӃǜ#EZsɛRfhƸ6\ >:\\phb&D!\.L `"\9h\r3'/g&ȒK;Djt'}B-ΗdwJ>cD& a-\)ٕgO?UgxSD|zWTHTy^ +4V +vJŵ[+oܯn?NT$z$ᖛʃ4MV*FK@ B +x &HQ(̌tj +g&BRLlP't:n" $%QjyT'KlAUCʙ:&=ln&q( $ṫH(Ja %A +YΨxKbMʍ;1tƌK.C%7({zc Ad#-^2Q:.k&W!1kqL*2EnH\ϥ3]rэjM5I( d$"ȩ5ܬ_ +1EE@! <`ً6ė\Q+BBGCbe K] +Qs>b +"OEUZP4(%!ԧg\\@.]3P$F|k"~A-6^F_ɥ';ʴ~v>::.inbC!|K!Ulb2@3n,4n-3.bʅ/T#BRԕ\aJjba7"TfsA᩹ȳM@a& ' DJ/Ĥ2"f,TT + GELF6$PrLzJ>.dtM8B\\,j "d5N57l2J(B <`Tc6eɧ& %M17f3aI|QϹ%$Jb$3~q0g3[ n>,NyIDjb_O&C<1ELV\;)[ +TѓpQ#tJ dK*5sFv + ;bRC*].oZ܌/6g!oB]tQ 7e P 7Q S&BH٫zu,D8qzPHpk≚Mߌb)\SZpy⒋G 3jpR\JX֏u\ 07H#*)cܦ9"bz̴OX ET/a_|"x}k.: L7M6jN/JyOQFQe>6A&jQ@).de>,#kP*ޘ2&b-:T +iCsaY`C&{U@:n܀|GxCόvj-~;J&߭0*r:Mߏo=_y9wm}jprb{{ov8Km$?bWT3vzS_GBһ􃫫{v!rht㜚 [|,x`j}z蛋")swZ!]+l{X|~ĭ赍3zq$ \'$v+ &w[._SgFv~wa<)/_ -ۜ]tv╕/׿&NoFvy!y:q͝/ό4Фe=~ٹWw7_/"yMܽgS{DۤQ:/K+n=w~o'C!7`4]!abWK/i!H.5 #E89Nu.楄"-:m"HUL@l?_}L|mNoDwiثw_2aHMdPE'7}p6$" ?^_}56AJkdL,>,"+7\zLIb>OR_eקV[k-_XޚXyyesSG+=A&m+K_G [MzrNd?ӥ$s>tmqpmil̙/7w?Oz>)}AN]knO™.$6e$IK/noߍ] Vpu|GD4`ͧ^߻<$1v2sw4/;?wfDB$h&W`?SӈXW3j&\|z_V_xdǦ&L \_;$*Rh| 4g־!UK3O =s^ NEjjr[H] {ɏ3in\JJࣹQyZxw?\$ ZЬӨZۡD7Gӫ;WN_wm坝?CӹS+p|M,vۭjfi,^Wwv~:uŭ,]x7yuCL}L.df}v}R--l ]nk"}1Id\_yqf4ߜK`bNWo][XY~ݝ?^_z~.>-nܺ{_Dɼ=GJh!{?|=F!.7w._{.O/"+|t#zHBߝbƗMWnm6m{KrYb$%W7^,*Y$J6W=yf|>^&,fm>qkh"w4uҎgs'Vq~G.|6q꽋Vڿz_y}L8O9=5`|hx Ysկό^=;v Icf7^O<{Wm2f_هdm][ݿr|½[~sG5+ 缌f7y?:pb[ۻ$Oo='IV6jN0|=l_w8:~p)}!&ܘ]U~V8Sskn|~x )?OFEX_$qn sDՕsf[Ǯ,^Y\y5urۈR͆u;7c.%andk5Օ'3~ޫG_rH婻k_^]LJN8A I_/^YW4};Dܽ4y.>拿҆">6͝&79ܕ =y-oH4.w3ڏd+}-?I6΋o'V&+sws_ٙI,s_ f\GmLܺOo"xDꅤ9rٺtu$8R_ݸ|m=zuF}}yr]YzN߻Ml۹{]}A?=y?ܽ6Oz򯢛[.3o>88o.u'Yܽ;/&Vƛ/ŗW1C;uKu +5M‹tqgrɟ37Ex3xy7[RK~so΍ +Yxщͳvq14X33wiV___{m=GM7>\w_n=/jLs"+ݽ( 1K!Kg;8T_%x`HL'\X}->،y!^-ffn|C8fѦ؟S+O7_7.o/5n!Bp}o^|7}͑q)i,Asrsnp[䨯}Lƥ vͧk.]sm훛O:p.ߜr)IDBJgU`tՕo9a]"1- +O/MܾtmK4>;W?|Oj3KLpaVﻯSl~ftO~=(zYۥqġyr9{\DB@3+/Γ^}kcwg6uܝh풙x0wwoWgͯ[fG$ImXM+ RkSg _Or3L>Y;^z7Sk?fE8 ~Ts&g\:sbzw6.]Un{w.*^.]xe[~vo>w&p:}^h\:d`曯m ֒[O|ۯ3v]zWb٥3cSͯxn,g';syh+R?4yˇo㉥-;O/_ggC3o?N~MXW;/tƿ2=.\O FDx$I7 cta{?}/Ɵfy"xo2j^,'7[0{f;%g'=S#2hAԈ ڧFd>5"OȠ}jDS#2hAԈ ڧFd>5"OȠ}jDS#2hAԈ ڧFd>5"OȠ}jDS#2hAԈ ڧFd>5"OȠ}jDS#2hAԈ ڧFd>5"OȠ}jDS#2hAԈ ڧFd>5"OȠ}jDS#2hAԈ {J>ˍSΞq=u5roaM^zs>Y9nx`c4.]X9}{@^|]:N }?2'a<jD?d a`6qIDG:1&HE{(&I$M]i4c.ng푴q|ݑ76}1MA6OVvw^ +xMSad5~Q9?5}|o|¢ƹQ7XZףݽ~׍7;z.8{qy`Euzʕ[|T<ON{qowwzF]1tjS+^t5_[ӇoilӇ^0+K^{.ɱ:1Ϸ޴߼mzg6>9>:X{_=G{^_qҽ"tvur"vBW q|wF;=bO,o݃h^ONgr}u|x3B>9VoZ;:3sq{2lEc6d4 +1{6k ?N=a_mѻw6`m6`m6/E,X`2v9v`8 8~[>Գ.x{nw v3DG`?i޾yu0eDŋ7}Hgݻ}Fflcݿg}Û۽Ã7[o' ߽>|)eAIb.}D8ePxLc +=KWpD<"j譣qab=R^NNbzG$:#"txòKmWNr~&GS#ep2H¼ýv0nh{mm}Jt{TRN{FdXPۻ{[v3pޖ^Yr 8w;uN/wyd3&FOOiÚg fз{л2VW;x'[wbsfn]렄* "jZϑz{=a>ꍟ~_} cx1!Շ8b=/ΛS'fw߼jK[O&=| s1NE9; hiT^o[fptH׳);lXeއ=v[=g,Z:=4wG'Lş^Z@\ջY>A޽VǨshow} {n}3)g?:KM?>]?<Dz,r_̃ +w@l{{${&מeuΨ w֩Ia F:mf@]"Ú6:Ei3u"×7;5 b8S}(@C"ę:qlę1)Շ83=HÑ8s'δNML '$Ψ_KLÐNiՉ3Ð82 OC CDÓb}dB֋Q׎ɎԔt<ϙד8go݅{>3+{ p+4Ьo~74|}{{˝c}r=Yv.Wdv?HG8i݃ݗvGã:k]wt?RWw7J%={~{yS{Oļ?l4!N8wfV짦Cz7->17߽&m#ɱC8GYXeu.+ҴkgN̩93vΜtiu#aN̩93v<-YgLk:Syt*,!.ϱ{!1SS^d݁gӧ*GhrȀW8խdN[ =5խ>Jh]ݪn&ϯQS"@wXju*Zlm~[Tהs`=a^uOo^x>؏}ϰ^ O?k 4"=7K X}>u ˢ~0(sڵwQeJ ꓐ`һ> A gLvdezL8}Gޢcqv Z?SM>䴸?zGv|r.P?N!kf]jǀ?`oUpCmµ$h0s[osGo޶Z+i>9ǻǭ8F7Ǒ=މqX_ioc|r^mѻw{?#7ӧL5p/.%^' Ku;KX폎{'J:)($USrJu5_Ɠt{XKS}8]j7O)RgOGZx xZp +3ih2:*!Ƃ8ܞcڶsа{RekV`_㨭 +uq?̰{dxH+Z:|=J78uW؞÷p™ӴN)~T;OK_lHԈ!oogy}3,|뭭>=,kZۣ[vo:]6ӠҠۃ3o>ԉ/oՖ(~!=iDZm\籟a*lWv'G*T{+bT]f~BPYWMO뙣}'/7{}x,;7~r,?w辵8$ +b==S<ӋXë=b['?#Q!bC9dp:3_}<"7~3lzhxgG ab׽oI,S|WtS[Z<".B?JIշ#2b_vk㪮J"//7# n ᫀkљzFxBHA3̵7p>E깦0 } zg!b7pRt:T9gO "+x詩1ڳmz< kP7z0 +\!c*Fu|Mn'OnܦO8Q!suE.8Og jIM>Ƙ3o='71>i i/1iauv +8ZYdy|xJ*n=0ao='|~$hL}/푷#{k}0Acj=&4t8*i[AF2!Pv_7X΃xVF@&Jicq8Ֆ5 0% MFT+% ҄!]`@Q' 0mUv,5F11!71z["maZihJq(n1}QX'ŌA($c A'ic)mXل±001 Q9jXZMExP2c&I6̌,SqGX`цIPXlgڴ9BkԄ_-A1%JiQfFhZ=@Co ]D1M5 8Fhi؆iD?fXkGXl : +hLhHKIC&T$ +5XDEH k"\ vi @j"IcCϙ{016A1?ݥ$Hl'T#SiqSyLJC C+ G6S q%l7Ph wĊf{6HJSM;}XilwB(-_/Ҙ"("&}$^t{A* b-ͷsb D+dY":7ZrMH3IoJce+5&c4ZCv&uA TdBBa)mAМ*mIB$X5S'V8tдay8Tm#GW& +OM Ib{'Zs EC@mo@.D5-DҀ]Mp KjTg1Hcތ?5sVEFsK.%\$x-Bkn,6mș&;s $S@> endobj 35 0 obj <> endobj 44 0 obj [/View/Design] endobj 45 0 obj <>>> endobj 18 0 obj [/View/Design] endobj 19 0 obj <>>> endobj 61 0 obj [60 0 R] endobj 84 0 obj <> endobj xref 0 85 0000000004 65535 f +0000000016 00000 n +0000000173 00000 n +0000044291 00000 n +0000000006 00000 f +0000656362 00000 n +0000000008 00000 f +0000044342 00000 n +0000000009 00000 f +0000000010 00000 f +0000000011 00000 f +0000000012 00000 f +0000000013 00000 f +0000000014 00000 f +0000000015 00000 f +0000000016 00000 f +0000000017 00000 f +0000000020 00000 f +0000656619 00000 n +0000656650 00000 n +0000000021 00000 f +0000000022 00000 f +0000000023 00000 f +0000000024 00000 f +0000000025 00000 f +0000000026 00000 f +0000000027 00000 f +0000000028 00000 f +0000000029 00000 f +0000000030 00000 f +0000000031 00000 f +0000000032 00000 f +0000000033 00000 f +0000000034 00000 f +0000000000 00000 f +0000656432 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000656503 00000 n +0000656534 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000049722 00000 n +0000656735 00000 n +0000044704 00000 n +0000052718 00000 n +0000050035 00000 n +0000049922 00000 n +0000048646 00000 n +0000049161 00000 n +0000049209 00000 n +0000049806 00000 n +0000049837 00000 n +0000050070 00000 n +0000052792 00000 n +0000053144 00000 n +0000054580 00000 n +0000068719 00000 n +0000131658 00000 n +0000197246 00000 n +0000262834 00000 n +0000328422 00000 n +0000394010 00000 n +0000459598 00000 n +0000525186 00000 n +0000590774 00000 n +0000656760 00000 n +trailer <]>> startxref 657001 %%EOF \ No newline at end of file diff --git a/tests/dummy/public/assets/branding/eps/Ember-CLI-Mirage-Logo-Horiz-Black.eps b/tests/dummy/public/assets/branding/eps/Ember-CLI-Mirage-Logo-Horiz-Black.eps new file mode 100644 index 000000000..935db9a21 Binary files /dev/null and b/tests/dummy/public/assets/branding/eps/Ember-CLI-Mirage-Logo-Horiz-Black.eps differ diff --git a/tests/dummy/public/assets/branding/eps/Ember-CLI-Mirage-Logo-Horiz-Color.eps b/tests/dummy/public/assets/branding/eps/Ember-CLI-Mirage-Logo-Horiz-Color.eps new file mode 100644 index 000000000..d5a3d6b8b Binary files /dev/null and b/tests/dummy/public/assets/branding/eps/Ember-CLI-Mirage-Logo-Horiz-Color.eps differ diff --git a/tests/dummy/public/assets/branding/eps/Ember-CLI-Mirage-Logo-Stacked-Black.eps b/tests/dummy/public/assets/branding/eps/Ember-CLI-Mirage-Logo-Stacked-Black.eps new file mode 100644 index 000000000..4e544f0bb Binary files /dev/null and b/tests/dummy/public/assets/branding/eps/Ember-CLI-Mirage-Logo-Stacked-Black.eps differ diff --git a/tests/dummy/public/assets/branding/eps/Ember-CLI-Mirage-Logo-Stacked-Color.eps b/tests/dummy/public/assets/branding/eps/Ember-CLI-Mirage-Logo-Stacked-Color.eps new file mode 100644 index 000000000..d73d2682b Binary files /dev/null and b/tests/dummy/public/assets/branding/eps/Ember-CLI-Mirage-Logo-Stacked-Color.eps differ diff --git a/tests/dummy/public/assets/branding/png/Ember-CLI-Mirage-Logo-Horiz-Black.png b/tests/dummy/public/assets/branding/png/Ember-CLI-Mirage-Logo-Horiz-Black.png new file mode 100644 index 000000000..79e95020e Binary files /dev/null and b/tests/dummy/public/assets/branding/png/Ember-CLI-Mirage-Logo-Horiz-Black.png differ diff --git a/tests/dummy/public/assets/branding/png/Ember-CLI-Mirage-Logo-Horiz-Color.png b/tests/dummy/public/assets/branding/png/Ember-CLI-Mirage-Logo-Horiz-Color.png new file mode 100644 index 000000000..53684346f Binary files /dev/null and b/tests/dummy/public/assets/branding/png/Ember-CLI-Mirage-Logo-Horiz-Color.png differ diff --git a/tests/dummy/public/assets/branding/png/Ember-CLI-Mirage-Logo-Stacked-Black.png b/tests/dummy/public/assets/branding/png/Ember-CLI-Mirage-Logo-Stacked-Black.png new file mode 100644 index 000000000..df4758072 Binary files /dev/null and b/tests/dummy/public/assets/branding/png/Ember-CLI-Mirage-Logo-Stacked-Black.png differ diff --git a/tests/dummy/public/assets/branding/png/Ember-CLI-Mirage-Logo-Stacked-Color.png b/tests/dummy/public/assets/branding/png/Ember-CLI-Mirage-Logo-Stacked-Color.png new file mode 100644 index 000000000..5082860c8 Binary files /dev/null and b/tests/dummy/public/assets/branding/png/Ember-CLI-Mirage-Logo-Stacked-Color.png differ diff --git a/tests/dummy/public/assets/branding/svg/Ember-CLI-Mirage-Logo-Horiz-Black.svg b/tests/dummy/public/assets/branding/svg/Ember-CLI-Mirage-Logo-Horiz-Black.svg new file mode 100644 index 000000000..01db46789 --- /dev/null +++ b/tests/dummy/public/assets/branding/svg/Ember-CLI-Mirage-Logo-Horiz-Black.svg @@ -0,0 +1,49 @@ + + + + + + diff --git a/tests/dummy/public/assets/branding/svg/Ember-CLI-Mirage-Logo-Horiz-Color.svg b/tests/dummy/public/assets/branding/svg/Ember-CLI-Mirage-Logo-Horiz-Color.svg new file mode 100644 index 000000000..3c3ac1503 --- /dev/null +++ b/tests/dummy/public/assets/branding/svg/Ember-CLI-Mirage-Logo-Horiz-Color.svg @@ -0,0 +1,58 @@ + + + + + + + + diff --git a/tests/dummy/public/assets/branding/svg/Ember-CLI-Mirage-Logo-Stacked-Black.svg b/tests/dummy/public/assets/branding/svg/Ember-CLI-Mirage-Logo-Stacked-Black.svg new file mode 100644 index 000000000..83049612b --- /dev/null +++ b/tests/dummy/public/assets/branding/svg/Ember-CLI-Mirage-Logo-Stacked-Black.svg @@ -0,0 +1,51 @@ + + + + + + diff --git a/tests/dummy/public/assets/branding/svg/Ember-CLI-Mirage-Logo-Stacked-Color.svg b/tests/dummy/public/assets/branding/svg/Ember-CLI-Mirage-Logo-Stacked-Color.svg new file mode 100644 index 000000000..0d70d7202 --- /dev/null +++ b/tests/dummy/public/assets/branding/svg/Ember-CLI-Mirage-Logo-Stacked-Color.svg @@ -0,0 +1,55 @@ + + + + + + + + diff --git a/tests/dummy/public/assets/favicon.sketch b/tests/dummy/public/assets/favicon.sketch new file mode 100644 index 000000000..b5e8d548c Binary files /dev/null and b/tests/dummy/public/assets/favicon.sketch differ diff --git a/tests/dummy/public/crossdomain.xml b/tests/dummy/public/crossdomain.xml deleted file mode 100644 index 0c16a7a07..000000000 --- a/tests/dummy/public/crossdomain.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - diff --git a/tests/dummy/public/favicon.png b/tests/dummy/public/favicon.png new file mode 100644 index 000000000..2b348163e Binary files /dev/null and b/tests/dummy/public/favicon.png differ diff --git a/tests/fixtures/config/environment-development-disabled.js b/tests/fixtures/config/environment-development-disabled.js index 7a0482a4c..a776409b6 100644 --- a/tests/fixtures/config/environment-development-disabled.js +++ b/tests/fixtures/config/environment-development-disabled.js @@ -1,7 +1,7 @@ /* eslint-env node */ /* eslint no-empty: 0 */ -module.exports = function(environment) { +module.exports = function (environment) { var ENV = { modulePrefix: 'scaffold-test', environment: environment, @@ -11,13 +11,13 @@ module.exports = function(environment) { FEATURES: { // Here you can enable experimental features on an ember canary build // e.g. 'with-controller': true - } + }, }, APP: { // Here you can pass flags/options to your application instance // when it is created - } + }, }; if (environment === 'development') { @@ -27,7 +27,7 @@ module.exports = function(environment) { // ENV.APP.LOG_TRANSITIONS_INTERNAL = true; // ENV.APP.LOG_VIEW_LOOKUPS = true; ENV['ember-cli-mirage'] = { - enabled: false + enabled: false, }; } @@ -44,7 +44,6 @@ module.exports = function(environment) { } if (environment === 'production') { - } return ENV; diff --git a/tests/fixtures/config/environment-production-enabled.js b/tests/fixtures/config/environment-production-enabled.js index e559f626e..e3c3a91ad 100644 --- a/tests/fixtures/config/environment-production-enabled.js +++ b/tests/fixtures/config/environment-production-enabled.js @@ -1,6 +1,6 @@ /* eslint-env node */ -module.exports = function(environment) { +module.exports = function (environment) { var ENV = { modulePrefix: 'scaffold-test', environment: environment, @@ -10,13 +10,13 @@ module.exports = function(environment) { FEATURES: { // Here you can enable experimental features on an ember canary build // e.g. 'with-controller': true - } + }, }, APP: { // Here you can pass flags/options to your application instance // when it is created - } + }, }; if (environment === 'development') { @@ -41,9 +41,8 @@ module.exports = function(environment) { if (environment === 'production') { ENV['ember-cli-mirage'] = { - enabled: true + enabled: true, }; - } return ENV; diff --git a/tests/fixtures/config/environment-test-disabled.js b/tests/fixtures/config/environment-test-disabled.js index 9d82ea3c4..e3dd76972 100644 --- a/tests/fixtures/config/environment-test-disabled.js +++ b/tests/fixtures/config/environment-test-disabled.js @@ -1,7 +1,7 @@ /* eslint-env node */ /* eslint no-empty: 0 */ -module.exports = function(environment) { +module.exports = function (environment) { var ENV = { modulePrefix: 'scaffold-test', environment: environment, @@ -11,13 +11,13 @@ module.exports = function(environment) { FEATURES: { // Here you can enable experimental features on an ember canary build // e.g. 'with-controller': true - } + }, }, APP: { // Here you can pass flags/options to your application instance // when it is created - } + }, }; if (environment === 'development') { @@ -39,12 +39,11 @@ module.exports = function(environment) { ENV.APP.rootElement = '#ember-testing'; ENV['ember-cli-mirage'] = { - enabled: false + enabled: false, }; } if (environment === 'production') { - } return ENV; diff --git a/tests/helpers/.gitkeep b/tests/helpers/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/tests/helpers/destroy-app.js b/tests/helpers/destroy-app.js index 116141188..a935b7e33 100644 --- a/tests/helpers/destroy-app.js +++ b/tests/helpers/destroy-app.js @@ -1,11 +1,9 @@ -import Ember from 'ember'; - -const { run } = Ember; +import { run } from '@ember/runloop'; export default function destroyApp(application) { - run(function() { + run(function () { application.destroy(); - server.shutdown(); + window.server.shutdown(); }); } diff --git a/tests/helpers/module-for-acceptance.js b/tests/helpers/module-for-acceptance.js index 76996fd04..68cbbdeb8 100644 --- a/tests/helpers/module-for-acceptance.js +++ b/tests/helpers/module-for-acceptance.js @@ -1,11 +1,9 @@ import { module } from 'qunit'; -import Ember from 'ember'; +import { resolve } from 'rsvp'; import startApp from '../helpers/start-app'; import destroyApp from '../helpers/destroy-app'; -const { RSVP: { Promise } } = Ember; - -export default function(name, options = {}) { +export default function (name, options = {}) { module(name, { beforeEach() { this.application = startApp(); @@ -16,8 +14,9 @@ export default function(name, options = {}) { }, afterEach() { - let afterEach = options.afterEach && options.afterEach.apply(this, arguments); - return Promise.resolve(afterEach).then(() => destroyApp(this.application)); - } + let afterEach = + options.afterEach && options.afterEach.apply(this, arguments); + return resolve(afterEach).then(() => destroyApp(this.application)); + }, }); } diff --git a/tests/helpers/promise-ajax.js b/tests/helpers/promise-ajax.js new file mode 100644 index 000000000..6b746ce18 --- /dev/null +++ b/tests/helpers/promise-ajax.js @@ -0,0 +1,11 @@ +/* eslint-disable ember/no-jquery */ +import { Promise } from 'rsvp'; +import $ from 'jquery'; + +export default (options) => { + return new Promise((resolve, reject) => { + $.ajax(options) + .done((data, status, xhr) => resolve({ data, status, xhr })) + .fail((xhr, status, error) => reject({ xhr, status, error })); + }); +}; diff --git a/tests/helpers/resolver.js b/tests/helpers/resolver.js index b208d38d0..319b45fc1 100644 --- a/tests/helpers/resolver.js +++ b/tests/helpers/resolver.js @@ -5,7 +5,7 @@ const resolver = Resolver.create(); resolver.namespace = { modulePrefix: config.modulePrefix, - podModulePrefix: config.podModulePrefix + podModulePrefix: config.podModulePrefix, }; export default resolver; diff --git a/tests/helpers/start-app.js b/tests/helpers/start-app.js index 83f842c52..9f6aee596 100644 --- a/tests/helpers/start-app.js +++ b/tests/helpers/start-app.js @@ -1,20 +1,17 @@ -import Ember from 'ember'; import Application from '../../app'; import config from '../../config/environment'; - -const { merge, run } = Ember; +import { assign } from '@ember/polyfills'; +import { run } from '@ember/runloop'; export default function startApp(attrs) { - let application; - - let attributes = merge({}, config.APP); - attributes = merge(attributes, attrs); // use defaults, but you can override; + let attributes = assign({}, config.APP); + attributes.autoboot = true; + attributes = assign(attributes, attrs); // use defaults, but you can override; - run(() => { - application = Application.create(attributes); + return run(() => { + let application = Application.create(attributes); application.setupForTesting(); application.injectTestHelpers(); + return application; }); - - return application; } diff --git a/tests/index-named-imports-test.js b/tests/index-named-imports-test.js deleted file mode 100644 index fc237be7b..000000000 --- a/tests/index-named-imports-test.js +++ /dev/null @@ -1,39 +0,0 @@ -import { test } from 'qunit'; -import { - Factory, - Response, - faker, - Model, - Serializer, - ActiveModelSerializer, - JSONAPISerializer, - hasMany, - belongsTo -} from 'ember-cli-mirage'; - -test('Factory is present in named exports from ember-cli-mirage', function(assert) { - assert.ok(Factory); -}); - -test('Response is present in named exports from ember-cli-mirage', function(assert) { - assert.ok(Response); -}); - -test('faker is present in named exports from ember-cli-mirage', function(assert) { - assert.ok(faker); -}); - -test('Model is present in named exports from ember-cli-mirage', function(assert) { - assert.ok(Model); -}); - -test('serializers are present in named exports from ember-cli-mirage', function(assert) { - assert.ok(ActiveModelSerializer); - assert.ok(JSONAPISerializer); - assert.ok(Serializer); -}); - -test('relationship helpers are present in named exports from ember-cli-mirage', function(assert) { - assert.ok(hasMany); - assert.ok(belongsTo); -}); diff --git a/tests/index.html b/tests/index.html index 5209b8523..6d13069ac 100644 --- a/tests/index.html +++ b/tests/index.html @@ -21,7 +21,14 @@ {{content-for "body"}} {{content-for "test-body"}} - +
+
+
+
+
+
+ + diff --git a/tests/integration/database-test.js b/tests/integration/database-test.js deleted file mode 100644 index cbe06c26c..000000000 --- a/tests/integration/database-test.js +++ /dev/null @@ -1,39 +0,0 @@ -import {module, test} from 'qunit'; -import Server from 'ember-cli-mirage/server'; -import { Model, Factory } from 'ember-cli-mirage'; - -module('Integration | Database', { - beforeEach() { - this.server = new Server({ - environment: 'development', - scenarios: { - default() {} - }, - models: { - author: Model - }, - factories: { - author: Factory - }, - fixtures: { - authors: [ - { id: 1, name: 'Zelda' } - ] - } - }); - }, - afterEach() { - this.server.shutdown(); - } -}); - -test(`[regression] When loaded, fixture files correctly update the database's autoincrement id`, function(assert) { - this.server.loadFixtures(); - - this.server.schema.authors.create({}); - - let { authors } = this.server.db; - assert.equal(authors.length, 2); - assert.deepEqual(authors.map((a) => a.id), ['1', '2']); -}); - diff --git a/tests/integration/factories/after-create-test.js b/tests/integration/factories/after-create-test.js deleted file mode 100644 index 3a999ac24..000000000 --- a/tests/integration/factories/after-create-test.js +++ /dev/null @@ -1,53 +0,0 @@ -import { module, test } from 'qunit'; -import { Model, Factory, belongsTo } from 'ember-cli-mirage'; -import Server from 'ember-cli-mirage/server'; - -module('Integration | Server | Factories | afterCreate', { - beforeEach() { - this.server = new Server({ - environment: 'test', - models: { - author: Model, - post: Model.extend({ - author: belongsTo() - }), - comment: Model.extend({ - post: belongsTo() - }) - }, - factories: { - author: Factory.extend({ - afterCreate(author, server) { - author.update({ name: 'Sam' }); - server.create('post', { author }); - } - }), - post: Factory.extend({ - title: 'Lorem ipsum', - afterCreate(post, server) { - server.create('comment', { post }); - } - }), - comment: Factory.extend({ - text: 'Yo soy el nino' - }) - } - }); - }, - afterEach() { - this.server.shutdown(); - } -}); - -test('it works for models', function(assert) { - let author = this.server.create('author'); - - assert.equal(author.name, 'Sam'); - assert.deepEqual(this.server.db.posts.length, 1); - assert.deepEqual(this.server.db.posts[0], { id: '1', title: 'Lorem ipsum', authorId: '1' }); - assert.deepEqual(this.server.db.comments.length, 1); - assert.deepEqual(this.server.db.comments[0], { id: '1', text: 'Yo soy el nino', postId: '1' }); -}); - -// test('it works for db records', function(assert) { -// }); diff --git a/tests/integration/factories/helpers-test.js b/tests/integration/factories/helpers-test.js deleted file mode 100644 index a038d05a2..000000000 --- a/tests/integration/factories/helpers-test.js +++ /dev/null @@ -1,83 +0,0 @@ -import { module, test } from 'qunit'; -import { Model, Factory, belongsTo, hasMany, trait, association } from 'ember-cli-mirage'; -import Server from 'ember-cli-mirage/server'; - -module('Integration | Server | Factories | helpers', { - beforeEach() { - this.server = new Server({ - environment: 'test', - models: { - author: Model.extend({ - posts: hasMany() - }), - category: Model.extend({ - posts: hasMany('post', { inverse: 'kind' }) - }), - post: Model.extend({ - author: belongsTo(), - kind: belongsTo('category') - }) - }, - factories: { - author: Factory.extend({ - name: 'Sam' - }), - category: Factory.extend({ - name: 'awesome software' - }), - post: Factory.extend({ - title: 'Lorem ipsum', - - author: association(), - - withCategory: trait({ - kind: association() - }) - }) - } - }); - }, - afterEach() { - this.server.shutdown(); - } -}); - -test('it creates associations with "association" helper combininig with traits', function(assert) { - this.server.create('post', 'withCategory'); - - assert.equal(this.server.db.posts.length, 1); - assert.deepEqual( - this.server.db.posts[0], - { id: '1', title: 'Lorem ipsum', authorId: '1', kindId: '1' } - ); - assert.deepEqual( - this.server.schema.posts.find(1).author.attrs, - { id: '1', name: 'Sam' } - ); - assert.deepEqual( - this.server.schema.posts.find(1).kind.attrs, - { id: '1', name: 'awesome software' } - ); - - assert.equal(this.server.db.authors.length, 1); - assert.deepEqual( - this.server.db.authors[0], - { id: '1', name: 'Sam' } - ); - assert.equal(this.server.schema.authors.find(1).posts.models.length, 1); - assert.deepEqual( - this.server.schema.authors.find(1).posts.models[0].attrs, - { id: '1', title: 'Lorem ipsum', authorId: '1', kindId: '1' } - ); - - assert.equal(this.server.db.categories.length, 1); - assert.deepEqual( - this.server.db.categories[0], - { id: '1', name: 'awesome software' } - ); - assert.equal(this.server.schema.categories.find(1).posts.models.length, 1); - assert.deepEqual( - this.server.schema.categories.find(1).posts.models[0].attrs, - { id: '1', title: 'Lorem ipsum', authorId: '1', kindId: '1' } - ); -}); diff --git a/tests/integration/http-verbs-test.js b/tests/integration/http-verbs-test.js deleted file mode 100644 index fe2d1cf19..000000000 --- a/tests/integration/http-verbs-test.js +++ /dev/null @@ -1,134 +0,0 @@ -import {module, test} from 'qunit'; -import Server from 'ember-cli-mirage/server'; -import { Model } from 'ember-cli-mirage'; - -module('Integration | HTTP Verbs', { - beforeEach() { - this.server = new Server({ - environment: 'development', - models: { - contact: Model - } - }); - this.server.timing = 0; - this.server.logging = false; - }, - afterEach() { - this.server.shutdown(); - } -}); - -test('mirage responds to get', function(assert) { - assert.expect(1); - let done = assert.async(); - - this.server.get('/contacts', function() { - return true; - }); - - $.ajax({ - method: 'GET', - url: '/contacts' - }).done(function(res) { - assert.equal(res, true); - done(); - }); -}); - -test('mirage responds to post', function(assert) { - assert.expect(1); - let done = assert.async(); - - this.server.post('/contacts', function() { - return true; - }); - - $.ajax({ - method: 'POST', - url: '/contacts' - }).done(function(res) { - assert.equal(res, true); - done(); - }); -}); - -test('mirage responds to put', function(assert) { - assert.expect(1); - let done = assert.async(); - - this.server.put('/contacts', function() { - return true; - }); - - $.ajax({ - method: 'PUT', - url: '/contacts' - }).done(function(res) { - assert.equal(res, true); - done(); - }); -}); - -test('mirage responds to delete', function(assert) { - assert.expect(1); - let done = assert.async(); - - this.server.delete('/contacts', function() { - return true; - }); - - $.ajax({ - method: 'DELETE', - url: '/contacts' - }).done(function(res) { - assert.equal(res, true); - done(); - }); -}); - -test('mirage responds to patch', function(assert) { - assert.expect(1); - let done = assert.async(); - - this.server.patch('/contacts', function() { - return true; - }); - - $.ajax({ - method: 'PATCH', - url: '/contacts' - }).done(function(res) { - assert.equal(res, true); - done(); - }); -}); - -test('mirage responds to resource', function(assert) { - assert.expect(0); - let done = assert.async(); - - this.server.resource('contacts'); - - $.ajax({ - method: 'GET', - url: '/contacts' - }).done(function() { - done(); - }); -}); - -test('response code can be customized', function(assert) { - assert.expect(1); - let done = assert.async(); - - this.server.get('/contacts', {}, 404); - - $.ajax({ - method: 'GET', - url: '/contacts', - complete: function(res) { - assert.ok(res.status, 404); - done(); - } - }); -}); diff --git a/tests/integration/load-fixtures-test.js b/tests/integration/load-fixtures-test.js deleted file mode 100644 index e142ee3e0..000000000 --- a/tests/integration/load-fixtures-test.js +++ /dev/null @@ -1,58 +0,0 @@ -import {module, test} from 'qunit'; -import Server from 'ember-cli-mirage/server'; - -module('Integration | Server #loadFixtures', { - beforeEach() { - this.server = new Server({ - environment: 'development', - scenarios: { - default() {} - }, - factories: { - author: {}, - post: {}, - comment: {} - }, - fixtures: { - authors: [ - { id: 1, name: 'Zelda' }, - { id: 2, name: 'Link' } - ], - posts: [ - { id: 1, title: 'Lorem' }, - { id: 2, title: 'Ipsum' } - ], - comments: [ - { id: 1, title: 'Lorem' } - ] - } - }); - }, - afterEach() { - this.server.shutdown(); - } -}); - -test('it can load all fixtures in the map', function(assert) { - this.server.loadFixtures(); - - assert.equal(this.server.db.authors.length, 2); - assert.equal(this.server.db.posts.length, 2); - assert.equal(this.server.db.comments.length, 1); -}); - -test('it can load a single named fixture file', function(assert) { - this.server.loadFixtures('authors'); - - assert.equal(this.server.db.authors.length, 2); - assert.equal(this.server.db.posts.length, 0); - assert.equal(this.server.db.comments.length, 0); -}); - -test('it can load several named single fixtures', function(assert) { - this.server.loadFixtures('authors', 'posts'); - - assert.equal(this.server.db.authors.length, 2); - assert.equal(this.server.db.posts.length, 2); - assert.equal(this.server.db.comments.length, 0); -}); diff --git a/tests/integration/orm/all-test.js b/tests/integration/orm/all-test.js deleted file mode 100644 index ae287adbf..000000000 --- a/tests/integration/orm/all-test.js +++ /dev/null @@ -1,41 +0,0 @@ -import Schema from 'ember-cli-mirage/orm/schema'; -import Model from 'ember-cli-mirage/orm/model'; -import Db from 'ember-cli-mirage/db'; -import Collection from 'ember-cli-mirage/orm/collection'; -import {module, test} from 'qunit'; - -module('Integration | ORM | #all'); - -test('it can return all models', function(assert) { - let db = new Db({ - users: [ - { id: 1, name: 'Link' }, - { id: 2, name: 'Zelda' } - ] - }); - let User = Model.extend(); - let schema = new Schema(db, { - user: User - }); - - let users = schema.users.all(); - assert.ok(users instanceof Collection, 'it returns a collection'); - assert.ok(users.models[0] instanceof User, 'each member of the collection is a model'); - assert.equal(users.models.length, 2); - assert.deepEqual(users.models[1].attrs, { id: '2', name: 'Zelda' }); -}); - -test('it returns an empty array when no models exist', function(assert) { - let db = new Db({ users: [] }); - - let User = Model.extend(); - let schema = new Schema(db, { - user: User - }); - - let users = schema.users.all(); - - assert.ok(users instanceof Collection, 'it returns a collection'); - assert.equal(users.modelName, 'user', 'the collection knows its type'); - assert.equal(users.models.length, 0); -}); diff --git a/tests/integration/orm/attrs-test.js b/tests/integration/orm/attrs-test.js deleted file mode 100644 index dffefdb17..000000000 --- a/tests/integration/orm/attrs-test.js +++ /dev/null @@ -1,30 +0,0 @@ -import Schema from 'ember-cli-mirage/orm/schema'; -import Model from 'ember-cli-mirage/orm/model'; -import Db from 'ember-cli-mirage/db'; -import {module, test} from 'qunit'; - -var db, schema, User; -module('Integration | ORM | attrs', { - beforeEach() { - db = new Db({ users: [ - { id: 1, name: 'Link', evil: false } - ] }); - - User = Model.extend(); - schema = new Schema(db, { - user: User - }); - } -}); - -test('attrs returns the models attributes', function(assert) { - let user = schema.users.find(1); - - assert.deepEqual(user.attrs, { id: '1', name: 'Link', evil: false }); -}); - -test('attributes can be read via plain property access', function(assert) { - let user = schema.users.find(1); - - assert.equal(user.name, 'Link'); -}); diff --git a/tests/integration/orm/belongs-to/accessor-test.js b/tests/integration/orm/belongs-to/accessor-test.js deleted file mode 100644 index 1b9774fe3..000000000 --- a/tests/integration/orm/belongs-to/accessor-test.js +++ /dev/null @@ -1,53 +0,0 @@ -import BelongsToHelper from './belongs-to-helper'; -import Mirage from 'ember-cli-mirage'; -import Model from 'ember-cli-mirage/orm/model'; -import Schema from 'ember-cli-mirage/orm/schema'; -import Db from 'ember-cli-mirage/db'; -import {module, test} from 'qunit'; - -module('Integration | ORM | belongsTo #accessor', { - beforeEach() { - this.helper = new BelongsToHelper(); - } -}); - -/* - #association behavior works regardless of the state of the child -*/ - -[ - 'savedChildNoParent', - 'savedChildNewParent', - 'savedChildSavedParent', - 'newChildNoParent', - 'newChildNewParent', - 'newChildSavedParent' -].forEach((state) => { - - test(`the references of a ${state} are correct`, function(assert) { - let [address, user] = this.helper[state](); - - assert.deepEqual(address.user, user ? user : null, 'the model reference is correct'); - assert.equal(address.userId, user ? user.id : null, 'the modelId reference is correct'); - }); - -}); - -test('belongsTo accessors works when foreign key is present but falsy', function(assert) { - let db = new Db({ - users: [], - addresses: [] - }); - - let schema = new Schema(db, { - user: Model.extend(), - address: Model.extend({ - user: Mirage.belongsTo() - }) - }); - - db.users.insert({ id: 0, name: 'some user' }); - let insertedAddress = db.addresses.insert({ name: 'foo', userId: 0 }); - let relatedUser = schema.addresses.find(insertedAddress.id).user; - assert.equal('some user', relatedUser ? relatedUser.name : undefined); -}); diff --git a/tests/integration/orm/belongs-to/belongs-to-helper.js b/tests/integration/orm/belongs-to/belongs-to-helper.js deleted file mode 100644 index e1c709632..000000000 --- a/tests/integration/orm/belongs-to/belongs-to-helper.js +++ /dev/null @@ -1,91 +0,0 @@ -import Mirage from 'ember-cli-mirage'; -import Model from 'ember-cli-mirage/orm/model'; -import Schema from 'ember-cli-mirage/orm/schema'; -import Db from 'ember-cli-mirage/db'; - -/* - A model with a belongsTo association can be in six states - with respect to its association. This helper class - returns a child (and its association) in these various states. - - The return value is an array of the form - - [child, parent] - - where the parent may be undefined. -*/ -class BelongsToHelper { - - constructor() { - this.db = new Db(); - - this.schema = new Schema(this.db, { - user: Model.extend(), - address: Model.extend({ - user: Mirage.belongsTo() - }) - }); - } - - savedChildNoParent() { - let insertedAddress = this.db.addresses.insert({ name: 'foo' }); - - return [this.schema.addresses.find(insertedAddress.id), undefined]; - } - - savedChildNewParent() { - let insertedAddress = this.db.addresses.insert({ name: 'foo' }); - let address = this.schema.addresses.find(insertedAddress.id); - let user = this.schema.users.new({ name: 'Newbie' }); - - address.user = user; - - return [address, user]; - } - - savedChildSavedParent() { - let insertedUser = this.db.users.insert({ name: 'some user' }); - let insertedAddress = this.db.addresses.insert({ name: 'foo', userId: insertedUser.id }); - let address = this.schema.addresses.find(insertedAddress.id); - let user = this.schema.users.find(insertedUser.id); - - return [address, user]; - } - - newChildNoParent() { - return [this.schema.addresses.new({ name: 'New addr' }), undefined]; - } - - newChildNewParent() { - let address = this.schema.addresses.new({ name: 'New addr' }); - let newUser = this.schema.users.new({ name: 'Newbie' }); - address.user = newUser; - - return [address, newUser]; - } - - newChildSavedParent() { - let insertedUser = this.db.users.insert({ name: 'some user' }); - let address = this.schema.addresses.new({ name: 'New addr' }); - let savedUser = this.schema.users.find(insertedUser.id); - - address.user = savedUser; - - return [address, savedUser]; - } - - // Just a saved unassociated parent. The id is high so as not to - // interfere with any other parents - savedParent() { - let insertedUser = this.db.users.insert({ name: 'bar' }); - - return this.schema.users.find(insertedUser.id); - } - - newParent() { - return this.schema.users.new({ name: 'Newbie' }); - } - -} - -export default BelongsToHelper; diff --git a/tests/integration/orm/belongs-to/create-association-test.js b/tests/integration/orm/belongs-to/create-association-test.js deleted file mode 100644 index 9421ec9c7..000000000 --- a/tests/integration/orm/belongs-to/create-association-test.js +++ /dev/null @@ -1,34 +0,0 @@ -import BelongsToHelper from './belongs-to-helper'; -import {module, test} from 'qunit'; - -module('Integration | ORM | belongsTo #createAssociation', { - beforeEach() { - this.helper = new BelongsToHelper(); - } -}); - -/* - createAssociation behavior works regardless of the state of the child -*/ - -[ - 'savedChildNoParent', - 'savedChildNewParent', - 'savedChildSavedParent', - 'newChildNoParent', - 'newChildNewParent', - 'newChildSavedParent' -].forEach((state) => { - - test(`a ${state} can create an associated parent`, function(assert) { - let [address] = this.helper[state](); - - let ganon = address.createUser({ name: 'Ganon' }); - - assert.ok(ganon.id, 'the parent was persisted'); - assert.deepEqual(address.user, ganon); - assert.equal(address.userId, ganon.id); - assert.equal(this.helper.schema.addresses.find(address.id).userId, ganon.id, 'the child was persisted'); - }); - -}); diff --git a/tests/integration/orm/belongs-to/create-with-association-test.js b/tests/integration/orm/belongs-to/create-with-association-test.js deleted file mode 100644 index d9d9afffb..000000000 --- a/tests/integration/orm/belongs-to/create-with-association-test.js +++ /dev/null @@ -1,65 +0,0 @@ -import Mirage from 'ember-cli-mirage'; -import Model from 'ember-cli-mirage/orm/model'; -import Schema from 'ember-cli-mirage/orm/schema'; -import Db from 'ember-cli-mirage/db'; -import {module, test} from 'qunit'; - -module('Integration | ORM | belongsTo create with association', { - beforeEach() { - this.schema = new Schema(new Db(), { - user: Model.extend(), - address: Model.extend({ - user: Mirage.belongsTo() - }), - foo: Model - }); - } -}); - -test('it sets up associations correctly when passing in the foreign key', function(assert) { - let user = this.schema.create('user'); - let address = this.schema.create('address', { - userId: user.id - }); - - assert.equal(address.userId, user.id); - assert.deepEqual(address.user.attrs, user.attrs); - assert.equal(this.schema.db.users.length, 1); - assert.deepEqual(this.schema.db.users[0], { id: '1' }); - assert.equal(this.schema.db.addresses.length, 1); - assert.deepEqual(this.schema.db.addresses[0], { id: '1', userId: '1' }); -}); - -test('it sets up associations correctly when passing in the association itself', function(assert) { - let user = this.schema.create('user'); - let address = this.schema.create('address', { - user - }); - - assert.equal(address.userId, user.id); - assert.deepEqual(address.user.attrs, user.attrs); - assert.equal(this.schema.db.users.length, 1); - assert.deepEqual(this.schema.db.users[0], { id: '1' }); - assert.equal(this.schema.db.addresses.length, 1); - assert.deepEqual(this.schema.db.addresses[0], { id: '1', userId: '1' }); -}); - -test('it throws an error if a model is passed in without a defined relationship', function(assert) { - let foo = this.schema.create('foo'); - assert.throws(function() { - this.schema.create('address', { - foo - }); - }, /you haven't defined that key as an association on your model/); -}); - -test('it throws an error if a collection is passed in without a defined relationship', function(assert) { - this.schema.create('foo'); - this.schema.create('foo'); - - assert.throws(function() { - this.schema.create('address', { - foos: this.schema.foos.all() - }); - }, /you haven't defined that key as an association on your model/); -}); diff --git a/tests/integration/orm/belongs-to/instantiating-test.js b/tests/integration/orm/belongs-to/instantiating-test.js deleted file mode 100644 index 655693f6d..000000000 --- a/tests/integration/orm/belongs-to/instantiating-test.js +++ /dev/null @@ -1,101 +0,0 @@ -import Mirage from 'ember-cli-mirage'; -import Model from 'ember-cli-mirage/orm/model'; -import Schema from 'ember-cli-mirage/orm/schema'; -import Db from 'ember-cli-mirage/db'; -import {module, test} from 'qunit'; - -var schema, link; -module('Integration | ORM | belongsTo instantiating with params', { - beforeEach() { - let db = new Db({ - users: [ - { id: 1, name: 'Link' } - ], - addresses: [] - }); - - let User = Model.extend(); - let Address = Model.extend({ - user: Mirage.belongsTo() - }); - - schema = new Schema(db); - schema.registerModels({ - user: User, - address: Address - }); - - link = schema.users.find(1); - } -}); - -test('the child accepts a saved parents id', function(assert) { - let address = schema.addresses.new({ userId: 1 }); - - assert.equal(address.userId, 1); - assert.deepEqual(address.user, link); - assert.deepEqual(address.attrs, { userId: 1 }); -}); - -test('the child errors if the parent id doesnt exist', function(assert) { - assert.throws(function() { - schema.addresses.new({ userId: 2 }); - }, /Couldn't find user/); -}); - -test('the child accepts a null parent id', function(assert) { - let address = schema.addresses.new({ userId: null }); - - assert.equal(address.userId, null); - assert.deepEqual(address.user, null); - assert.deepEqual(address.attrs, { userId: null }); -}); - -test('the child accepts a saved parent model', function(assert) { - let address = schema.addresses.new({ user: link }); - - assert.equal(address.userId, 1); - assert.deepEqual(address.user, link); - assert.deepEqual(address.attrs, { userId: '1' }); -}); - -test('the child accepts a new parent model', function(assert) { - let zelda = schema.users.new({ name: 'Zelda' }); - let address = schema.addresses.new({ user: zelda }); - - assert.equal(address.userId, null); - assert.deepEqual(address.user, zelda); - assert.deepEqual(address.attrs, { userId: null }); -}); - -test('the child accepts a null parent model', function(assert) { - let address = schema.addresses.new({ user: null }); - - assert.equal(address.userId, null); - assert.deepEqual(address.user, null); - assert.deepEqual(address.attrs, { userId: null }); -}); - -test('the child accepts a parent model and id', function(assert) { - let address = schema.addresses.new({ user: link, userId: 1 }); - - assert.equal(address.userId, '1'); - assert.deepEqual(address.user, link); - assert.deepEqual(address.attrs, { userId: 1 }); -}); - -test('the child accepts no reference to a parent id or model as empty obj', function(assert) { - let address = schema.addresses.new({}); - - assert.equal(address.userId, null); - assert.deepEqual(address.user, null); - assert.deepEqual(address.attrs, { userId: null }); -}); - -test('the child accepts no reference to a parent id or model', function(assert) { - let address = schema.addresses.new(); - - assert.equal(address.userId, null); - assert.deepEqual(address.user, null); - assert.deepEqual(address.attrs, { userId: null }); -}); diff --git a/tests/integration/orm/belongs-to/new-association-test.js b/tests/integration/orm/belongs-to/new-association-test.js deleted file mode 100644 index b2ef7593d..000000000 --- a/tests/integration/orm/belongs-to/new-association-test.js +++ /dev/null @@ -1,38 +0,0 @@ -import BelongsToHelper from './belongs-to-helper'; -import {module, test} from 'qunit'; - -module('Integration | ORM | belongsTo #newAssociation', { - beforeEach() { - this.helper = new BelongsToHelper(); - } -}); - -/* - newAssociation behavior works regardless of the state of the child -*/ - -[ - 'savedChildNoParent', - 'savedChildNewParent', - 'savedChildSavedParent', - 'newChildNoParent', - 'newChildNewParent', - 'newChildSavedParent' -].forEach((state) => { - - test(`a ${state} can build a new associated parent`, function(assert) { - let [address] = this.helper[state](); - - let ganon = address.newUser({ name: 'Ganon' }); - - assert.ok(!ganon.id, 'the parent was not persisted'); - assert.deepEqual(address.user, ganon); - assert.equal(address.userId, null); - - address.save(); - - assert.ok(ganon.id, 'saving the child persists the parent'); - assert.equal(address.userId, ganon.id, 'the childs fk was updated'); - }); - -}); diff --git a/tests/integration/orm/belongs-to/set-association-id-test.js b/tests/integration/orm/belongs-to/set-association-id-test.js deleted file mode 100644 index e1c265c9d..000000000 --- a/tests/integration/orm/belongs-to/set-association-id-test.js +++ /dev/null @@ -1,46 +0,0 @@ -import BelongsToHelper from './belongs-to-helper'; -import {module, test} from 'qunit'; - -module('Integration | ORM | belongsTo #setAssociationId', { - beforeEach() { - this.helper = new BelongsToHelper(); - } -}); - -[ - 'savedChildNoParent', - 'savedChildNewParent', - 'savedChildSavedParent', - 'newChildNoParent', - 'newChildNewParent', - 'newChildSavedParent' -].forEach((state) => { - - test(`a ${state} can update its association to a saved parent via parentId`, function(assert) { - let [address] = this.helper[state](); - let savedUser = this.helper.savedParent(); - - address.userId = savedUser.id; - - assert.equal(address.userId, savedUser.id); - assert.deepEqual(address.user, savedUser); - }); - -}); - -[ - 'savedChildSavedParent', - 'newChildSavedParent' -].forEach((state) => { - - test(`a ${state} can clear its association via a null parentId`, function(assert) { - let [address] = this.helper[state](); - - address.userId = null; - - assert.equal(address.userId, null); - assert.deepEqual(address.user, null); - }); - -}); - diff --git a/tests/integration/orm/belongs-to/set-association-test.js b/tests/integration/orm/belongs-to/set-association-test.js deleted file mode 100644 index 0b36a2310..000000000 --- a/tests/integration/orm/belongs-to/set-association-test.js +++ /dev/null @@ -1,48 +0,0 @@ -import BelongsToHelper from './belongs-to-helper'; -import {module, test} from 'qunit'; - -module('Integration | ORM | belongsTo #setAssociation', { - beforeEach() { - this.helper = new BelongsToHelper(); - } -}); - -[ - 'savedChildNoParent', - 'savedChildNewParent', - 'savedChildSavedParent', - 'newChildNoParent', - 'newChildNewParent', - 'newChildSavedParent' -].forEach((state) => { - - test(`a ${state} can update its association to a saved parent`, function(assert) { - let [address] = this.helper[state](); - let savedUser = this.helper.savedParent(); - - address.user = savedUser; - - assert.equal(address.userId, savedUser.id); - assert.deepEqual(address.user, savedUser); - }); - - test(`a ${state} can update its association to a new parent`, function(assert) { - let [address] = this.helper[state](); - let newUser = this.helper.newParent(); - - address.user = newUser; - - assert.equal(address.userId, null); - assert.deepEqual(address.user, newUser); - }); - - test(`a ${state} can update its association to a null parent`, function(assert) { - let [address] = this.helper[state](); - - address.user = null; - - assert.equal(address.userId, null); - assert.deepEqual(address.user, null); - }); - -}); diff --git a/tests/integration/orm/collection-inflector-test.js b/tests/integration/orm/collection-inflector-test.js deleted file mode 100644 index 4d1a521c8..000000000 --- a/tests/integration/orm/collection-inflector-test.js +++ /dev/null @@ -1,22 +0,0 @@ -import Model from 'ember-cli-mirage/orm/model'; -import Schema from 'ember-cli-mirage/orm/schema'; -import Db from 'ember-cli-mirage/db'; -import Inflector from 'ember-inflector'; -import {module, test} from 'qunit'; - -var db, schema, HeadOfState; -module('Integration | ORM | inflector-collectionName integration', { - beforeEach() { - Inflector.inflector.irregular('head-of-state', 'heads-of-state'); - - HeadOfState = Model.extend(); - db = new Db({}); - schema = new Schema(db); - schema.registerModel('headOfState', HeadOfState); - } -}); - -test(' [regression] collection creation respects irregular plural rules', function(assert) { - assert.equal(schema.db._collections.length, 1); - assert.equal(schema.db._collections[0].name, 'headsOfState'); -}); diff --git a/tests/integration/orm/collection-test.js b/tests/integration/orm/collection-test.js deleted file mode 100644 index 59751f77e..000000000 --- a/tests/integration/orm/collection-test.js +++ /dev/null @@ -1,86 +0,0 @@ -import Schema from 'ember-cli-mirage/orm/schema'; -import Model from 'ember-cli-mirage/orm/model'; -import Db from 'ember-cli-mirage/db'; -import Collection from 'ember-cli-mirage/orm/collection'; -import {module, test} from 'qunit'; - -module('Integration | ORM | collection', { - beforeEach() { - this.User = Model.extend(); - this.db = new Db({ users: [ - { id: 1, name: 'Link', good: true }, - { id: 2, name: 'Zelda', good: true }, - { id: 3, name: 'Ganon', good: false } - ] }); - - this.schema = new Schema(this.db, { - user: this.User - }); - } -}); - -test('a collection can save its models', function(assert) { - let collection = this.schema.users.all(); - collection.models[0].name = 'Sam'; - collection.save(); - - assert.deepEqual(this.db.users[0], { id: '1', name: 'Sam', good: true }); -}); - -test('a collection can reload its models', function(assert) { - let collection = this.schema.users.all(); - assert.equal(collection.models[0].name, 'Link'); - - collection.models[0].name = 'Sam'; - assert.equal(collection.models[0].name, 'Sam'); - - collection.reload(); - assert.equal(collection.models[0].name, 'Link'); -}); - -test('a collection can filter its models', function(assert) { - let collection = this.schema.users.all(); - assert.equal(collection.models.length, 3); - - let newCollection = collection.filter((author) => author.good); - - assert.ok(newCollection instanceof Collection); - assert.equal(newCollection.modelName, 'user', 'the filtered collection has the right type'); - assert.equal(newCollection.models.length, 2); -}); - -test('a collection can sort its models', function(assert) { - let collection = this.schema.users.all(); - assert.deepEqual(collection.models.map((m) => m.name), ['Link', 'Zelda', 'Ganon']); - - let newCollection = collection.sort((a, b) => { - return a.name.localeCompare(b.name); - }); - - assert.ok(newCollection instanceof Collection); - assert.equal(newCollection.modelName, 'user', 'the sorted collection has the right type'); - assert.deepEqual(newCollection.models.map((m) => m.name), ['Ganon', 'Link', 'Zelda']); -}); - -test('a collection can slice its models', function(assert) { - let collection = this.schema.users.all(); - assert.deepEqual(collection.models.map(m => m.name), ['Link', 'Zelda', 'Ganon'], 'Starts with 3'); - - let newCollection = collection.slice(-2); - - assert.ok(newCollection instanceof Collection); - assert.equal(newCollection.modelName, 'user', 'the sliced collection has the right type'); - assert.deepEqual(newCollection.models.map(m => m.name), ['Zelda', 'Ganon']); -}); - -test('a collection can merge with another collection', function(assert) { - let goodGuys = this.schema.users.where((user) => user.good); - let badGuys = this.schema.users.where((user) => !user.good); - - assert.equal(goodGuys.models.length, 2); - assert.equal(badGuys.models.length, 1); - - goodGuys.mergeCollection(badGuys); - - assert.equal(goodGuys.models.length, 3); -}); diff --git a/tests/integration/orm/create-test.js b/tests/integration/orm/create-test.js deleted file mode 100644 index 08d7f2ed9..000000000 --- a/tests/integration/orm/create-test.js +++ /dev/null @@ -1,50 +0,0 @@ -import Schema from 'ember-cli-mirage/orm/schema'; -import Model from 'ember-cli-mirage/orm/model'; -import Db from 'ember-cli-mirage/db'; -import {module, test} from 'qunit'; - -var db, schema, User; -module('Integration | ORM | create', { - beforeEach() { - User = Model.extend(); - db = new Db(); - schema = new Schema(db, { - user: User - }); - } -}); - -test('it cannot make new models that havent been registered', function(assert) { - assert.throws(function() { - schema.authors.new({ name: 'Link' }); - }); -}); - -test('it cannot create models that havent been registered', function(assert) { - assert.throws(function() { - schema.authors.create({ name: 'Link' }); - }); -}); - -test('it can make new models and then save them', function(assert) { - let user = schema.users.new({ name: 'Link' }); - - assert.ok(user instanceof User); - assert.deepEqual(user.attrs, { name: 'Link' }); - assert.deepEqual(db.users, []); - - user.save(); - - assert.ok(user.id, 'user has an id getter'); - assert.deepEqual(user.attrs, { id: '1', name: 'Link' }); - assert.deepEqual(db.users, [{ id: '1', name: 'Link' }]); -}); - -test('it can create new models, saved directly to the db', function(assert) { - let user = schema.users.create({ name: 'Link' }); - - assert.ok(user instanceof Model); - assert.ok(user instanceof User); - assert.deepEqual(user.attrs, { id: '1', name: 'Link' }); - assert.deepEqual(db.users, [{ id: '1', name: 'Link' }]); -}); diff --git a/tests/integration/orm/destroy-test.js b/tests/integration/orm/destroy-test.js deleted file mode 100644 index bcf6b4388..000000000 --- a/tests/integration/orm/destroy-test.js +++ /dev/null @@ -1,40 +0,0 @@ -import Schema from 'ember-cli-mirage/orm/schema'; -import Model from 'ember-cli-mirage/orm/model'; -import Db from 'ember-cli-mirage/db'; -import {module, test} from 'qunit'; - -let db; -module('Integration | ORM | destroy', { - beforeEach() { - db = new Db({ - users: [ - { id: 1, name: 'Link', evil: false }, - { id: 2, name: 'Link', location: 'Hyrule', evil: false }, - { id: 3, name: 'Zelda', location: 'Hyrule', evil: false } - ] - }); - - this.schema = new Schema(db, { - user: Model - }); - } -}); - -test('destroying a model removes the associated record from the db', function(assert) { - assert.deepEqual(db.users.length, 3); - - let link = this.schema.users.find(1); - link.destroy(); - - assert.deepEqual(db.users.find(1), null); - assert.deepEqual(db.users.length, 2); -}); - -test('destroying a collection removes the associated records from the db', function(assert) { - assert.deepEqual(db.users.length, 3); - - let users = this.schema.users.all(); - users.destroy(); - - assert.deepEqual(db.users, []); -}); diff --git a/tests/integration/orm/find-test.js b/tests/integration/orm/find-test.js deleted file mode 100644 index db9d775b0..000000000 --- a/tests/integration/orm/find-test.js +++ /dev/null @@ -1,48 +0,0 @@ -import Schema from 'ember-cli-mirage/orm/schema'; -import Model from 'ember-cli-mirage/orm/model'; -import Db from 'ember-cli-mirage/db'; -import Collection from 'ember-cli-mirage/orm/collection'; -import {module, test} from 'qunit'; - -var schema; -var User = Model.extend(); -module('Integration | ORM | #find', { - beforeEach() { - let db = new Db({ users: [ - { id: 1, name: 'Link' }, - { id: 2, name: 'Zelda' } - ] }); - - schema = new Schema(db, { - user: User - }); - } -}); - -test('it can find a model by id', function(assert) { - let zelda = schema.users.find(2); - - assert.ok(zelda instanceof User); - assert.deepEqual(zelda.attrs, { id: '2', name: 'Zelda' }); -}); - -test('it returns null if no model is found for an id', function(assert) { - let user = schema.users.find(4); - - assert.equal(user, null); -}); - -test('it can find multiple models by ids', function(assert) { - let users = schema.users.find([1, 2]); - - assert.ok(users instanceof Collection, 'it returns a collection'); - assert.ok(users.models[0] instanceof User); - assert.equal(users.models.length, 2); - assert.deepEqual(users.models[1].attrs, { id: '2', name: 'Zelda' }); -}); - -test('it errors if incorrect number of models are found for an array of ids', function(assert) { - assert.throws(function() { - schema.users.find([1, 6]); - }, /Couldn't find all users/); -}); diff --git a/tests/integration/orm/first-test.js b/tests/integration/orm/first-test.js deleted file mode 100644 index e1367eadc..000000000 --- a/tests/integration/orm/first-test.js +++ /dev/null @@ -1,24 +0,0 @@ -import Schema from 'ember-cli-mirage/orm/schema'; -import Model from 'ember-cli-mirage/orm/model'; -import Db from 'ember-cli-mirage/db'; -import {module, test} from 'qunit'; - -let schema; -let User = Model.extend(); -module('Integration | ORM | #first', { - beforeEach() { - let db = new Db(); - db.createCollection('users'); - db.users.insert([{ id: 1, name: 'Link' }, { id: 2, name: 'Zelda' }]); - schema = new Schema(db); - - schema.registerModel('user', User); - } -}); - -test('it can find the first model', function(assert) { - let user = schema.users.first(); - - assert.ok(user instanceof User); - assert.deepEqual(user.attrs, { id: '1', name: 'Link' }); -}); diff --git a/tests/integration/orm/has-many/accessor-test.js b/tests/integration/orm/has-many/accessor-test.js deleted file mode 100644 index dff326347..000000000 --- a/tests/integration/orm/has-many/accessor-test.js +++ /dev/null @@ -1,24 +0,0 @@ -import HasManyHelper from './has-many-helper'; -import {module, test} from 'qunit'; - -module('Integration | ORM | hasMany #accessor'); - -/* - #association behavior works regardless of the state of the parent -*/ - -HasManyHelper.forEachScenario((scenario) => { - test(`the references of a ${scenario.title} are correct`, function(assert) { - let { parent, children, accessor, idsAccessor } = scenario.go(); - assert.equal(parent[accessor].models.length, children.length, 'parent has correct number of children'); - assert.equal(parent[idsAccessor].length, children.length, 'parent has correct number of child ids'); - - children.forEach(function(child, i) { - assert.deepEqual(parent[accessor].models[i], children[i], 'each child is in parent.children array'); - - if (!child.isNew()) { - assert.ok(parent[idsAccessor].indexOf(child.id) > -1, 'each saved child id is in parent.childrenIds array'); - } - }); - }); -}); diff --git a/tests/integration/orm/has-many/create-association-test.js b/tests/integration/orm/has-many/create-association-test.js deleted file mode 100644 index 3be825869..000000000 --- a/tests/integration/orm/has-many/create-association-test.js +++ /dev/null @@ -1,42 +0,0 @@ -import HasManyHelper from './has-many-helper'; -import {module, test} from 'qunit'; - -module('Integration | ORM | hasMany #createAssociation'); - -HasManyHelper.forEachScenario((scenario) => { - if (/^savedParent/.test(scenario.state)) { - test(`${scenario.title} can create an associated child`, function(assert) { - let { parent: user, children, accessor, idsAccessor, createAccessor, otherIdAccessor } = scenario.go(); - - let startingCount = children.length; - - let springfield = user[createAccessor]({ name: '1 Springfield ave' }); - - assert.ok(springfield.id, 'the child was persisted'); - assert.equal(springfield[otherIdAccessor], 1, 'the fk is set'); - assert.equal(user[accessor].models.length, startingCount + 1, 'the collection length is correct'); - assert.deepEqual(user[accessor].filter((a) => a.id === springfield.id).models[0], springfield, 'the homeAddress was added to user.homeAddresses'); - assert.ok(user[idsAccessor].indexOf(springfield.id) > -1, 'the id was added to the fks array'); - }); - - test(`${scenario.title} can create an associated child without passing attrs (regression)`, function(assert) { - let { parent: user, accessor, createAccessor } = scenario.go(); - - let springfield = user[createAccessor](); - - assert.deepEqual(user[accessor].filter((a) => a.id === springfield.id).models[0], springfield, `the homeAddress was added to user.${accessor}`); - }); - } - - if (/^newParent/.test(scenario.state)) { - test(`${scenario.title} cannot create an associated child`, function(assert) { - let { parent, createAccessor } = scenario.go(); - - assert.throws(function() { - parent[createAccessor]({ name: '1 Springfield ave' }); - }, /unless the parent is saved/); - }); - - } - -}); diff --git a/tests/integration/orm/has-many/has-many-helper.js b/tests/integration/orm/has-many/has-many-helper.js deleted file mode 100644 index 5e936ff54..000000000 --- a/tests/integration/orm/has-many/has-many-helper.js +++ /dev/null @@ -1,200 +0,0 @@ -import Model from 'ember-cli-mirage/orm/model'; -import Schema from 'ember-cli-mirage/orm/schema'; -import Db from 'ember-cli-mirage/db'; -import { hasMany } from 'ember-cli-mirage'; -import { pluralize, singularize, capitalize, camelize } from 'ember-cli-mirage/utils/inflector'; -import _ from 'lodash'; - -/* - A model with a hasMany association can be in eight states - with respect to its association. This helper class - returns a parent (and its children) in these various states. - - The return value is an array of the form - - [parent, [child1, child2...]] - - where the children array may be undefined. -*/ -class HasManyHelper { - - constructor(opts) { - - let { ownKey, ownModel, otherKey, otherModel } = _.defaults({}, opts, { - ownKey: 'homeAddresses', - ownModel: 'user', - otherKey: 'user', - otherModel: 'homeAddress' - }); - - this.ownKey = ownKey; - this.ownModel = ownModel; - this.otherKey = otherKey; - this.otherModel = otherModel; - this.db = new Db(); - - let hasManyArgs = []; - if (pluralize(otherModel) !== ownKey) { - hasManyArgs.push(otherModel); - } - if (ownModel !== otherKey) { - hasManyArgs.push({ inverse: otherKey }); - } - - this.schema = new Schema(this.db, { - [ownModel]: Model.extend({ - [ownKey]: hasMany(...hasManyArgs) - }), - [otherModel]: Model - }); - } - - savedParentNoChildren() { - let insertedUser = this.db[pluralize(this.ownModel)].insert({ name: 'Link' }); - - return [this.schema[pluralize(this.ownModel)].find(insertedUser.id), []]; - } - - savedParentNewChildren() { - let insertedUser = this.db[pluralize(this.ownModel)].insert({ name: 'Link' }); - - let user = this.schema[pluralize(this.ownModel)].find(insertedUser.id); - let newHomeAddress = user[`new${singularize(capitalize(this.ownKey))}`](); - - return [user, [newHomeAddress]]; - } - - savedParentSavedChildren() { - let insertedUser = this.db[pluralize(this.ownModel)].insert({ name: 'Link' }); - let insertedHomeAddress = this.db[pluralize(this.otherModel)].insert({ name: '123 Hyrule Way', [`${camelize(this.otherKey)}Id`]: insertedUser.id }); - - let user = this.schema[pluralize(this.ownModel)].find(insertedUser.id); - let homeAddress = this.schema[pluralize(this.otherModel)].find(insertedHomeAddress.id); - - return [user, [homeAddress]]; - } - - savedParentMixedChildren() { - let insertedUser = this.db[pluralize(this.ownModel)].insert({ name: 'Link' }); - let insertedHomeAddress = this.db[pluralize(this.otherModel)].insert({ name: '123 Hyrule Way', [`${camelize(this.otherKey)}Id`]: insertedUser.id }); - - let user = this.schema[pluralize(this.ownModel)].find(insertedUser.id); - let savedHomeAddress = this.schema[pluralize(this.otherModel)].find(insertedHomeAddress.id); - let newHomeAddress = user[`new${singularize(capitalize(this.ownKey))}`](); - - return [user, [savedHomeAddress, newHomeAddress]]; - } - - newParentNoChildren() { - let user = this.schema[pluralize(this.ownModel)].new(); - - return [user, []]; - } - - newParentNewChildren() { - let user = this.schema[pluralize(this.ownModel)].new(); - let newHomeAddress = user[`new${singularize(capitalize(this.ownKey))}`](); - - return [user, [newHomeAddress]]; - } - - newParentSavedChildren() { - let insertedHomeAddress = this.db[pluralize(this.otherModel)].insert({ name: '123 Hyrule Way' }); - let savedHomeAddress = this.schema[pluralize(this.otherModel)].find(insertedHomeAddress.id); - let newUser = this.schema[pluralize(this.ownModel)].new({ [this.ownKey]: [savedHomeAddress] }); - - return [newUser, [savedHomeAddress]]; - } - - newParentMixedChildren() { - let insertedHomeAddress = this.db[pluralize(this.otherModel)].insert({ name: '123 Hyrule Way' }); - let savedHomeAddress = this.schema[pluralize(this.otherModel)].find(insertedHomeAddress.id); - let newHomeAddress = this.schema[pluralize(this.otherModel)].new(); - - let newUser = this.schema[pluralize(this.ownModel)].new({ [this.ownKey]: [savedHomeAddress, newHomeAddress] }); - - return [newUser, [savedHomeAddress, newHomeAddress]]; - } - - // Just a saved unassociated child. The id is high so as not to - // interfere with any other children - savedChild() { - let insertedHomeAddress = this.db[pluralize(this.otherModel)].insert({ name: 'foo' }); - - return this.schema[pluralize(this.otherModel)].find(insertedHomeAddress.id); - } - - newChild() { - return this.schema[pluralize(this.otherModel)].new({ name: 'Newbie' }); - } - -} - -HasManyHelper.forEachScenario = function(fn) { - [ - [true, true], - [true, false], - [false, true], - [false, false] - ].forEach(([useDefaultOwnKey, useDefaultOtherKey]) => { - - let accessor = 'homeAddresses'; - let idsAccessor = 'homeAddressIds'; - let createAccessor = 'createHomeAddress'; - let newAccessor = 'newHomeAddress'; - let otherAccessor = 'user'; - let otherIdAccessor = 'userId'; - - let opts = {}; - if (!useDefaultOwnKey) { - opts.ownKey = 'altHomeAddresses'; - accessor = 'altHomeAddresses'; - idsAccessor = 'altHomeAddressIds'; - createAccessor = 'createAltHomeAddress'; - newAccessor = 'newAltHomeAddress'; - } - if (!useDefaultOtherKey) { - opts.otherKey = 'altUser'; - otherAccessor = 'altUser'; - otherIdAccessor = 'altUserId'; - } - - [ - 'savedParentNoChildren', - 'savedParentNewChildren', - 'savedParentSavedChildren', - 'savedParentMixedChildren', - 'newParentNoChildren', - 'newParentNewChildren', - 'newParentSavedChildren', - 'newParentMixedChildren' - ].forEach((state) => { - let title = `${state} with ${useDefaultOwnKey ? 'default' : 'non-default'} own key and ${useDefaultOtherKey ? 'default' : 'non-default'} other key`; - fn({ - go() { - let helper = new HasManyHelper(opts); - - let [parent, children] = helper[state](); - return { - parent, - children, - title, - accessor, - idsAccessor, - createAccessor, - newAccessor, - otherAccessor, - otherIdAccessor, - helper - }; - }, - title, - state, - useDefaultOwnKey, - useDefaultOtherKey - }); - }); - }); -}; - -export default HasManyHelper; diff --git a/tests/integration/orm/has-many/instantiating-test.js b/tests/integration/orm/has-many/instantiating-test.js deleted file mode 100644 index 3316b14ea..000000000 --- a/tests/integration/orm/has-many/instantiating-test.js +++ /dev/null @@ -1,108 +0,0 @@ -import Mirage from 'ember-cli-mirage'; -import Model from 'ember-cli-mirage/orm/model'; -import Schema from 'ember-cli-mirage/orm/schema'; -import Db from 'ember-cli-mirage/db'; -import {module, test} from 'qunit'; - -var schema, child1, child2; -module('Integration | ORM | hasMany instantiating with params', { - beforeEach() { - let db = new Db({ - users: [], - homeAddresses: [ - { id: 1, name: '123 Hyrule Way' }, - { id: 2, name: '12 Goron City' } - ] - }); - schema = new Schema(db); - - let User = Model.extend({ - homeAddresses: Mirage.hasMany() - }); - let HomeAddress = Model.extend(); - - schema.registerModels({ - user: User, - homeAddress: HomeAddress - }); - - child1 = schema.homeAddresses.find(1); - child2 = schema.homeAddresses.find(2); - } -}); - -test('children have fks added to their attrs', function(assert) { - let newChild = schema.homeAddresses.new(); - assert.deepEqual(newChild.attrs, { userId: null }); - assert.deepEqual(child1.attrs, { id: '1', name: '123 Hyrule Way', userId: null }); -}); - -test('the parent accepts an array of saved children ids', function(assert) { - let user = schema.users.new({ homeAddressIds: [1, 2] }); - - assert.equal(user.homeAddresses.models.length, 2); - assert.deepEqual(user.homeAddresses.models[0], child1); - assert.deepEqual(user.homeAddresses.models[1], child2); - assert.deepEqual(user.homeAddressIds, ['1', '2']); -}); - -test('the parent errors if one of the child ids doesnt exist', function(assert) { - assert.throws(function() { - schema.users.new({ homeAddressIds: [1, 9] }); - }, /Couldn't find/); -}); - -test('the parent accepts an empty childIds array', function(assert) { - let user = schema.users.new({ homeAddressIds: [] }); - - assert.equal(user.homeAddresses.models.length, 0); -}); - -test('the parent accepts an array of saved child models', function(assert) { - let user = schema.users.new({ homeAddresses: [child1, child2] }); - - assert.deepEqual(user.homeAddressIds, ['1', '2']); - assert.equal(user.homeAddresses.models.length, 2); - assert.deepEqual(user.homeAddresses.models[0], child1); -}); - -test('the parent accepts an array of new child models', function(assert) { - let newAddress1 = schema.homeAddresses.new(); - let newAddress2 = schema.homeAddresses.new(); - let user = schema.users.new({ homeAddresses: [newAddress1, newAddress2] }); - - assert.deepEqual(user.homeAddressIds, [undefined, undefined]); - assert.equal(user.homeAddresses.models.length, 2); - assert.deepEqual(user.homeAddresses.models[0], newAddress1); -}); - -test('the parent accepts a mixed array of new and saved child models', function(assert) { - let newAddress1 = schema.homeAddresses.new(); - let user = schema.users.new({ homeAddresses: [child1, newAddress1] }); - - assert.deepEqual(user.homeAddressIds, ['1', undefined]); - assert.equal(user.homeAddresses.models.length, 2); - assert.deepEqual(user.homeAddresses.models[0], child1); - assert.deepEqual(user.homeAddresses.models[1], newAddress1); -}); - -test('the parent accepts null child models', function(assert) { - let user = schema.users.new({ addresses: [null] }); - - assert.deepEqual(user.homeAddressIds, []); - assert.equal(user.homeAddresses.models.length, 0); -}); - -test('the parent accepts no reference to a child id or model as empty obj', function(assert) { - let user = schema.users.new({}); - - assert.deepEqual(user.homeAddressIds, []); - assert.equal(user.homeAddresses.models.length, 0); -}); - -test('the parent accepts no reference to a child id or model', function(assert) { - let user = schema.users.new(); - - assert.deepEqual(user.homeAddressIds, []); - assert.equal(user.homeAddresses.models.length, 0); -}); diff --git a/tests/integration/orm/has-many/new-association-test.js b/tests/integration/orm/has-many/new-association-test.js deleted file mode 100644 index 192bd4763..000000000 --- a/tests/integration/orm/has-many/new-association-test.js +++ /dev/null @@ -1,38 +0,0 @@ -import HasManyHelper from './has-many-helper'; -import {module, test} from 'qunit'; - -module('Integration | ORM | hasMany #newAssociation'); - -HasManyHelper.forEachScenario((scenario) => { - - test(`${scenario.title} can build a new associated parent`, function(assert) { - let { parent: user, children: homeAddresses, newAccessor, accessor, otherIdAccessor } = scenario.go(); - - let startingCount = homeAddresses.length; - - let springfield = user[newAccessor]({ name: '1 Springfield ave' }); - - assert.ok(!springfield.id, 'the child was not persisted'); - assert.deepEqual(user[accessor].models[startingCount], springfield, `the child is appended to the parent's collection`); - - if (!user.isNew()) { - assert.equal(springfield[otherIdAccessor], user.id, `the new address's fk reference the saved parent`); - } - - user.save(); - - assert.ok(springfield.id, 'saving the parent persists the child'); - assert.equal(springfield[otherIdAccessor], user.id, 'the childs fk was updated'); - assert.equal(springfield.name, '1 Springfield ave', 'the childs attrs were saved'); - }); - - test(`${scenario.title} can build a new associated parent without passing in attrs (regression)`, function(assert) { - let { parent: user, children: homeAddresses, newAccessor, accessor } = scenario.go(); - let startingCount = homeAddresses.length; - - let springfield = user[newAccessor](); - - assert.deepEqual(user[accessor].models[startingCount], springfield, `the child is appended to the parent's collection`); - }); - -}); diff --git a/tests/integration/orm/has-many/set-association-ids-test.js b/tests/integration/orm/has-many/set-association-ids-test.js deleted file mode 100644 index 95d0d0933..000000000 --- a/tests/integration/orm/has-many/set-association-ids-test.js +++ /dev/null @@ -1,52 +0,0 @@ -import HasManyHelper from './has-many-helper'; -import {module, test} from 'qunit'; - -module('Integration | ORM | hasMany #setAssociationIds'); - -HasManyHelper.forEachScenario((scenario) => { - test(`${scenario.title} can update its associationIds to a list of saved child ids`, function(assert) { - let { parent: user, children: homeAddresses, helper, idsAccessor, accessor, otherIdAccessor } = scenario.go(); - - let savedHomeAddress = helper.savedChild(); - - user[idsAccessor] = [savedHomeAddress.id]; - savedHomeAddress.reload(); - - assert.deepEqual(user[accessor].models[0], savedHomeAddress); - homeAddresses.forEach(function(homeAddress) { - if (homeAddress.isSaved()) { - homeAddress.reload(); - assert.equal(homeAddress[otherIdAccessor], null, 'old saved children have their fks cleared'); - } - }); - }); - - if (/^savedParent/.test(scenario.state)) { - test(`updating associationIds to a list of saved children ids updates the child's fk, with ${scenario.title}`, function(assert) { - - let { parent: user, helper, idsAccessor, otherIdAccessor } = scenario.go(); - let savedHomeAddress = helper.savedChild(); - - user[idsAccessor] = [savedHomeAddress.id]; - savedHomeAddress.reload(); - - assert.equal(savedHomeAddress[otherIdAccessor], user.id, `the child's fk was set`); - }); - } - - test(`${scenario.title} can update its associationIds to an empty list`, function(assert) { - let { parent: user, children: homeAddresses, idsAccessor, accessor, otherIdAccessor } = scenario.go(); - - user[idsAccessor] = []; - - assert.equal(user[accessor].models.length, 0); - - homeAddresses.forEach(function(homeAddress) { - if (homeAddress.isSaved()) { - homeAddress.reload(); - assert.equal(homeAddress[otherIdAccessor], null, 'old saved children have their fks cleared'); - } - }); - }); - -}); diff --git a/tests/integration/orm/has-many/set-association-test.js b/tests/integration/orm/has-many/set-association-test.js deleted file mode 100644 index c99242820..000000000 --- a/tests/integration/orm/has-many/set-association-test.js +++ /dev/null @@ -1,124 +0,0 @@ -import HasManyHelper from './has-many-helper'; -import {module, test} from 'qunit'; - -module('Integration | ORM | hasMany #setAssociation', { - beforeEach() { - this.helper = new HasManyHelper(); - } -}); - -HasManyHelper.forEachScenario((scenario) => { - test(`${scenario.title} can update its association to a list of saved children`, function(assert) { - let { parent: user, children: homeAddresses, helper, accessor, otherIdAccessor } = scenario.go(); - let savedHomeAddress = helper.savedChild(); - - user[accessor] = [savedHomeAddress]; - savedHomeAddress.reload(); - - assert.deepEqual(user[accessor].models[0], savedHomeAddress); - homeAddresses.forEach(function(address) { - if (address.isSaved()) { - address.reload(); - assert.equal(address[otherIdAccessor], null, 'old saved children have their fks cleared'); - } - }); - }); - - if (/^savedParent/.test(scenario.state)) { - test(`updating an association to a list of saved children updates the child's fk when ${scenario.title}`, function(assert) { - let { parent: user, helper, accessor, otherIdAccessor } = scenario.go(); - let savedHomeAddress = helper.savedChild(); - - user[accessor] = [savedHomeAddress]; - savedHomeAddress.reload(); - - assert.equal(savedHomeAddress[otherIdAccessor], user.id, `the child's fk was set`); - }); - } - - test(`${scenario.title} can update its association to a list of new children`, function(assert) { - let { parent: user, children: homeAddresses, helper, accessor, otherIdAccessor } = scenario.go(); - let address = helper.newChild(); - - user[accessor] = [address]; - // The address is saved if the user is a saved user. In that case, we need to reload. - if (user.isSaved()) { - address.reload(); - } - - assert.deepEqual(user[accessor].models[0], address); - homeAddresses.forEach(function(address) { - if (address.isSaved()) { - address.reload(); - assert.equal(address[otherIdAccessor], null, 'old saved children have their fks cleared'); - } - }); - }); - - if (/^savedParent/.test(scenario.state)) { - - test(`updating an association to a list of new children saves the children and updates their fks when ${scenario.title}`, function(assert) { - let { parent: user, helper, accessor, otherIdAccessor } = scenario.go(); - let address = helper.newChild(); - - user[accessor] = [address]; - address.reload(); - - assert.ok(address.isSaved(), 'the new child was saved'); - assert.equal(address[otherIdAccessor], user.id, `the child's fk was set`); - }); - } - - test(`${scenario.title} can update its association to a list of mixed children`, function(assert) { - let { parent: user, children: homeAddresses, helper, accessor, otherIdAccessor } = scenario.go(); - let savedHomeAddress = helper.savedChild(); - let newAddress = helper.newChild(); - - user[accessor] = [savedHomeAddress, newAddress]; - savedHomeAddress.reload(); - // The new address is saved if the user is a saved user. In that case, we need to reload. - if (user.isSaved()) { - newAddress.reload(); - } - - assert.deepEqual(user[accessor].models[0], savedHomeAddress); - assert.deepEqual(user[accessor].models[1], newAddress); - homeAddresses.forEach(function(address) { - if (address.isSaved()) { - address.reload(); - assert.equal(address[otherIdAccessor], null, 'old saved children have their fks cleared'); - } - }); - }); - - if (/^savedParent/.test(scenario.state)) { - test(`updating an association to a list of mixed children saves the new children and updates all children's fks when ${scenario.title}`, function(assert) { - let { parent: user, helper, accessor, otherIdAccessor } = scenario.go(); - let savedHomeAddress = helper.savedChild(); - let newHomeAddress = helper.newChild(); - - user[accessor] = [savedHomeAddress, newHomeAddress]; - savedHomeAddress.reload(); - newHomeAddress.reload(); - - assert.ok(newHomeAddress.isSaved(), 'the new child was saved'); - assert.equal(savedHomeAddress[otherIdAccessor], user.id, `the saved child's fk was set`); - assert.equal(newHomeAddress[otherIdAccessor], user.id, `the new child's fk was set`); - }); - } - - test(`${scenario.title} can update its association to an empty list`, function(assert) { - let { parent: user, children: homeAddresses, accessor, otherIdAccessor } = scenario.go(); - - user[accessor] = []; - - assert.equal(user[accessor].models.length, 0); - homeAddresses.forEach(function(address) { - if (address.isSaved()) { - address.reload(); - assert.equal(address[otherIdAccessor], null, 'old saved children have their fks cleared'); - } - }); - }); - -}); diff --git a/tests/integration/orm/named-associations-test.js b/tests/integration/orm/named-associations-test.js deleted file mode 100644 index 33b8a6802..000000000 --- a/tests/integration/orm/named-associations-test.js +++ /dev/null @@ -1,246 +0,0 @@ -import { module, test } from 'qunit'; -import Schema from 'ember-cli-mirage/orm/schema'; -import Model from 'ember-cli-mirage/orm/model'; -import Db from 'ember-cli-mirage/db'; -import { hasMany, belongsTo } from 'ember-cli-mirage'; - -module('Integration | ORM | Named associations test'); - -test('schemas with a single hasMany have correct foreign keys', function(assert) { - let schema = new Schema(new Db(), { - user: Model.extend({ - projects: hasMany() - }), - project: Model - }); - - // Fks are set up correctly - assert.deepEqual(schema._registry.user.foreignKeys, []); - assert.deepEqual(schema._registry.project.foreignKeys, ['userId']); - - let user = schema.users.create(); - let project = user.createProject(); - - assert.ok(user); - assert.ok(project); -}); - -test('schemas with a single hasMany with a different property name defaults to a foreign key named by type', function(assert) { - let schema = new Schema(new Db(), { - user: Model.extend({ - specialProjects: hasMany('project') - }), - project: Model - }); - - assert.deepEqual(schema._registry.user.foreignKeys, []); - assert.deepEqual(schema._registry.project.foreignKeys, ['userId']); -}); - -test('schemas with a single belongsTo have correct foreign keys', function(assert) { - let schema = new Schema(new Db(), { - user: Model, - project: Model.extend({ - user: belongsTo() - }) - }); - - // Fks are set up correctly - assert.deepEqual(schema._registry.user.foreignKeys, []); - assert.deepEqual(schema._registry.project.foreignKeys, ['userId']); - - let project = schema.projects.create(); - let user = project.createUser(); - - assert.ok(user); - assert.ok(project); -}); - -test('schemas with a single belongsTo with a different property name have correct foreign keys', function(assert) { - let schema = new Schema(new Db(), { - user: Model, - project: Model.extend({ - owner: belongsTo('user') - }) - }); - - // Fks are set up correctly - assert.deepEqual(schema._registry.user.foreignKeys, []); - assert.deepEqual(schema._registry.project.foreignKeys, ['ownerId']); - - let project = schema.projects.create(); - let user = project.createOwner(); - - assert.ok(user); - assert.ok(project); -}); - -test('schemas with a single hasMany and belongsTo have correct foreign keys', function(assert) { - let schema = new Schema(new Db(), { - user: Model.extend({ - projects: hasMany() - }), - project: Model.extend({ - user: belongsTo() - }) - }); - - // Fks are set up correctly - assert.deepEqual(schema._registry.user.foreignKeys, []); - assert.deepEqual(schema._registry.project.foreignKeys, ['userId']); - - let project = schema.projects.create(); - let user = project.createUser(); - - assert.ok(user); - assert.ok(project); -}); - -test('complex schemas have correct foreign keys', function(assert) { - let schema = new Schema(new Db(), { - user: Model.extend({ - projects: hasMany(), - tasks: hasMany() - }), - project: Model.extend({ - user: belongsTo(), - tasks: hasMany() - }), - task: Model.extend({ - user: belongsTo(), - project: belongsTo() - }) - }); - - // Fks are set up correctly - assert.deepEqual(schema._registry.user.foreignKeys, []); - assert.deepEqual(schema._registry.project.foreignKeys, ['userId']); - assert.deepEqual(schema._registry.task.foreignKeys, ['userId', 'projectId']); - - let user = schema.users.create(); - let project = user.createProject(); - let task = user.createTask(); - - assert.ok(user); - assert.ok(project); - assert.ok(task); -}); - -test('foreign keys should be named appropriately for multiword properties', function(assert) { - let schema = new Schema(new Db(), { - author: Model, - post: Model.extend({ - wordSmith: belongsTo('author') - }) - }); - - // Fks are set up correctly - assert.deepEqual(schema._registry.author.foreignKeys, []); - assert.deepEqual(schema._registry.post.foreignKeys, ['wordSmithId']); - - let post = schema.posts.create(); - let wordSmith = post.createWordSmith(); - - assert.ok(post); - assert.ok(wordSmith); - assert.equal(wordSmith.modelName, 'author'); -}); - -test('foreign keys should be named appropriately for multiword model names', function(assert) { - let schema = new Schema(new Db(), { - wordSmith: Model, - post: Model.extend({ - author: belongsTo('word-smith') - }) - }); - - assert.deepEqual(schema._registry.wordSmith.foreignKeys, []); - assert.deepEqual(schema._registry.post.foreignKeys, ['authorId']); - - let post = schema.posts.create(); - let author = post.createAuthor(); - - assert.ok(post); - assert.ok(author); - assert.equal(author.modelName, 'word-smith'); -}); - -test('foreign keys should be named appropriately for multiword properties and model names', function(assert) { - let schema = new Schema(new Db(), { - wordSmith: Model, - post: Model.extend({ - brilliantWriter: belongsTo('word-smith') - }) - }); - - assert.deepEqual(schema._registry.wordSmith.foreignKeys, []); - assert.deepEqual(schema._registry.post.foreignKeys, ['brilliantWriterId']); - - let post = schema.posts.create(); - let brilliantWriter = post.createBrilliantWriter(); - - assert.ok(post); - assert.ok(brilliantWriter); - assert.equal(brilliantWriter.modelName, 'word-smith'); -}); - -test('a model can have multiple belongsTo associations of the same type', function(assert) { - let schema = new Schema(new Db(), { - user: Model, - project: Model.extend({ - admin: belongsTo('user'), - specialUser: belongsTo('user') - }) - }); - - assert.deepEqual(schema._registry.user.foreignKeys, []); - assert.deepEqual(schema._registry.project.foreignKeys, ['adminId', 'specialUserId']); - - let project = schema.projects.create(); - let admin = project.createAdmin(); - let specialUser = project.createSpecialUser(); - - assert.ok(project); - assert.ok(admin); - assert.equal(admin.modelName, 'user'); - assert.ok(specialUser); - assert.equal(specialUser.modelName, 'user'); -}); - -test('multiple hasMany associations of the same type with no explicit inverses throw an error', function(assert) { - assert.throws(() => { - new Schema(new Db(), { - user: Model.extend({ - mainProjects: hasMany('project'), - specialProjects: hasMany('project') - }), - project: Model - }); - }, /multiple possible inverse relationships/); -}); - -test('multiple hasMany associations with explicit inverses sets up the correct foreign keys', function(assert) { - let schema = new Schema(new Db(), { - user: Model.extend({ - mainProjects: hasMany('project', { inverse: 'mainUser' }), - specialProjects: hasMany('project', { inverse: 'specialUser' }) - }), - project: Model - }); - - assert.deepEqual(schema._registry.user.foreignKeys, []); - assert.deepEqual(schema._registry.project.foreignKeys, ['mainUserId', 'specialUserId']); -}); - -test('multiple hasMany associations with one explicit inverse sets up the correct foreign keys', function(assert) { - let schema = new Schema(new Db(), { - user: Model.extend({ - projects: hasMany(), - specialProjects: hasMany('project', { inverse: 'specialUser' }) - }), - project: Model - }); - - assert.deepEqual(schema._registry.user.foreignKeys, []); - assert.deepEqual(schema._registry.project.foreignKeys, ['userId', 'specialUserId']); -}); diff --git a/tests/integration/orm/reinitialize-associations-test.js b/tests/integration/orm/reinitialize-associations-test.js deleted file mode 100644 index 1167cc291..000000000 --- a/tests/integration/orm/reinitialize-associations-test.js +++ /dev/null @@ -1,32 +0,0 @@ -import Mirage from 'ember-cli-mirage'; -import Model from 'ember-cli-mirage/orm/model'; -import Schema from 'ember-cli-mirage/orm/schema'; -import Db from 'ember-cli-mirage/db'; -import {module, test} from 'qunit'; - -// Model classes are defined statically, just like in a typical app -var User = Model.extend({ - addresses: Mirage.hasMany() -}); -var Address = Model.extend(); - -module('Integration | ORM | reinitialize associations', { - beforeEach() { - this.schema = new Schema(new Db(), { - address: Address, - user: User - }); - - this.schema.users.create({ id: 1, name: 'Link' }); - this.schema.addresses.create({ id: 1, country: 'Hyrule', userId: 1 }); - } -}); - -// By running two tests, we force the statically-defined classes to be -// registered twice. -test('safely initializes associations', function(assert) { - assert.equal(this.schema.users.find(1).addresses.models[0].country, 'Hyrule'); -}); -test('safely initializes associations again', function(assert) { - assert.equal(this.schema.users.find(1).addresses.models[0].country, 'Hyrule'); -}); diff --git a/tests/integration/orm/update-test.js b/tests/integration/orm/update-test.js deleted file mode 100644 index dfbf0c80f..000000000 --- a/tests/integration/orm/update-test.js +++ /dev/null @@ -1,88 +0,0 @@ -import Schema from 'ember-cli-mirage/orm/schema'; -import Model from 'ember-cli-mirage/orm/model'; -import Db from 'ember-cli-mirage/db'; -import {module, test} from 'qunit'; - -module('Integration | ORM | update', { - beforeEach() { - this.db = new Db({ - users: [ - { id: 1, name: 'Link', location: 'Hyrule', evil: false }, - { id: 2, name: 'Zelda', location: 'Hyrule', evil: false } - ] - }); - - this.schema = new Schema(this.db, { - user: Model - }); - } -}); - -test('a collection can update its models with a key and value', function(assert) { - let collection = this.schema.users.all(); - collection.update('evil', true); - - assert.deepEqual(this.db.users, [ - { id: '1', name: 'Link', location: 'Hyrule', evil: true }, - { id: '2', name: 'Zelda', location: 'Hyrule', evil: true } - ]); - assert.deepEqual(collection.models[0].attrs, { id: '1', name: 'Link', location: 'Hyrule', evil: true }); -}); - -test('it can update its models with a hash of attrs', function(assert) { - let collection = this.schema.users.all(); - collection.update({ location: 'The water temple', evil: true }); - - assert.deepEqual(this.db.users, [ - { id: '1', name: 'Link', location: 'The water temple', evil: true }, - { id: '2', name: 'Zelda', location: 'The water temple', evil: true } - ]); - assert.deepEqual(collection.models[0].attrs, { id: '1', name: 'Link', location: 'The water temple', evil: true }); - assert.deepEqual(collection.models[1].attrs, { id: '2', name: 'Zelda', location: 'The water temple', evil: true }); -}); - -test('it can set an attribute and then save the model', function(assert) { - let user = this.schema.users.find(1); - - user.name = 'Young link'; - - assert.deepEqual(user.attrs, { id: '1', name: 'Young link', location: 'Hyrule', evil: false }); - assert.deepEqual(this.db.users.find(1), { id: '1', name: 'Link', location: 'Hyrule', evil: false }); - - user.save(); - - assert.deepEqual(user.attrs, { id: '1', name: 'Young link', location: 'Hyrule', evil: false }); - assert.deepEqual(this.db.users.find(1), { id: '1', name: 'Young link', location: 'Hyrule', evil: false }); -}); - -test('it can update and immediately persist a single attribute', function(assert) { - let link = this.schema.users.find(1); - link.update('evil', true); - - assert.deepEqual(link.attrs, { id: '1', name: 'Link', location: 'Hyrule', evil: true }); - assert.deepEqual(this.db.users.find(1), { id: '1', name: 'Link', location: 'Hyrule', evil: true }); -}); - -test('it can update a hash of attrs immediately', function(assert) { - var link = this.schema.users.find(1); - link.update({ name: 'Evil link', evil: true }); - - assert.deepEqual(link.attrs, { id: '1', name: 'Evil link', location: 'Hyrule', evil: true }); - assert.deepEqual(this.db.users.find(1), { id: '1', name: 'Evil link', location: 'Hyrule', evil: true }); -}); - -test('it can update a non-existing attribute', function(assert) { - var link = this.schema.users.find(1); - link.update({ name: 'Evil link', evil: true, reallyEvil: 'absolutely evil' }); - - assert.deepEqual(link.attrs, { id: '1', name: 'Evil link', location: 'Hyrule', evil: true, reallyEvil: 'absolutely evil' }); - assert.deepEqual(this.db.users.find(1), { id: '1', name: 'Evil link', location: 'Hyrule', evil: true, reallyEvil: 'absolutely evil' }); -}); - -test('if users sets incorrectly an attribute without using update, it will still work', function(assert) { - var link = this.schema.users.find(1); - link.reallyEvil = 'absolutely evil'; - link.update({ reallyEvil: 'a little flower', evil: true }); - assert.deepEqual(link.attrs, { id: '1', reallyEvil: 'a little flower', evil: true, location: 'Hyrule', name: 'Link' }); - assert.deepEqual(this.db.users.find(1), { id: '1', reallyEvil: 'a little flower', evil: true, location: 'Hyrule', name: 'Link' }); -}); diff --git a/tests/integration/orm/where-test.js b/tests/integration/orm/where-test.js deleted file mode 100644 index 19c89e962..000000000 --- a/tests/integration/orm/where-test.js +++ /dev/null @@ -1,48 +0,0 @@ -import Schema from 'ember-cli-mirage/orm/schema'; -import Model from 'ember-cli-mirage/orm/model'; -import Db from 'ember-cli-mirage/db'; -import Collection from 'ember-cli-mirage/orm/collection'; -import {module, test} from 'qunit'; - -let schema; -let User = Model.extend(); -module('Integration | ORM | #where', { - beforeEach() { - let db = new Db({ users: [ - { id: 1, name: 'Link', good: true }, - { id: 2, name: 'Zelda', good: true }, - { id: 3, name: 'Ganon', good: false } - ] }); - - schema = new Schema(db, { - user: User - }); - } -}); - -test('it returns models that match a query with where', function(assert) { - let users = schema.users.where({ good: false }); - - assert.ok(users instanceof Collection, 'it returns a collection'); - assert.equal(users.models.length, 1); - assert.ok(users.models[0] instanceof User); - assert.deepEqual(users.models[0].attrs, { id: '3', name: 'Ganon', good: false }); -}); - -test('it returns models that match using a query function', function(assert) { - let users = schema.users.where(function(rec) { - return !rec.good; - }); - - assert.ok(users instanceof Collection, 'it returns a collection'); - assert.equal(users.models.length, 1); - assert.ok(users.models[0] instanceof User); - assert.deepEqual(users.models[0].attrs, { id: '3', name: 'Ganon', good: false }); -}); - -test('it returns an empty collection if no models match a query', function(assert) { - let users = schema.users.where({ name: 'Link', good: false }); - - assert.ok(users instanceof Collection, 'it returns a collection'); - assert.equal(users.models.length, 0); -}); diff --git a/tests/integration/passthrough-test.js b/tests/integration/passthrough-test.js deleted file mode 100644 index 285137d5c..000000000 --- a/tests/integration/passthrough-test.js +++ /dev/null @@ -1,239 +0,0 @@ -import {module, test} from 'qunit'; -import Server from 'ember-cli-mirage/server'; - -module('Integration | Passthrough', { - beforeEach() { - this.server = new Server({ - environment: 'development' - }); - this.server.timing = 0; - this.server.logging = false; - }, - afterEach() { - this.server.shutdown(); - } -}); - -test('it can passthrough individual paths', function(assert) { - assert.expect(2); - let done1 = assert.async(); - let done2 = assert.async(); - let { server } = this; - - server.loadConfig(function() { - this.get('/contacts', function() { - return 123; - }); - this.passthrough('/addresses'); - }); - - $.ajax({ - method: 'GET', - url: '/contacts', - success(data) { - assert.equal(data, 123); - done1(); - } - }); - - $.ajax({ - method: 'GET', - url: '/addresses', - error(reason) { - assert.equal(reason.status, 404); - done2(); - } - }); -}); - -test('it can passthrough certain verbs for individual paths', function(assert) { - assert.expect(3); - let done1 = assert.async(); - let done2 = assert.async(); - let done3 = assert.async(); - let { server } = this; - - server.loadConfig(function() { - this.get('/contacts', function() { - return 123; - }); - this.passthrough('/addresses', ['post']); - }); - server.pretender.unhandledRequest = function(/* verb, path */) { - assert.ok(true, 'it doesnt passthrough GET'); - done2(); - }; - - $.ajax({ - method: 'GET', - url: '/contacts', - success(data) { - assert.equal(data, 123); - done1(); - } - }); - - $.ajax({ - method: 'GET', - url: '/addresses' - }); - - $.ajax({ - method: 'POST', - url: '/addresses', - error(reason) { - assert.equal(reason.status, 404); - done3(); - } - }); -}); - -test('it can passthrough multiple paths in a single call', function(assert) { - assert.expect(2); - let done1 = assert.async(); - let done2 = assert.async(); - let { server } = this; - - server.loadConfig(function() { - this.get('/contacts', function() { - return 123; - }); - this.passthrough('/contacts', '/addresses'); - }); - - $.ajax({ - method: 'GET', - url: '/contacts', - error(reason) { - assert.equal(reason.status, 404); - done1(); - } - }); - - $.ajax({ - method: 'POST', - url: '/addresses', - error(reason) { - assert.equal(reason.status, 404); - done2(); - } - }); -}); - -test('user can call passthrough multiple times', function(assert) { - assert.expect(2); - let done1 = assert.async(); - let done2 = assert.async(); - let { server } = this; - - server.loadConfig(function() { - this.passthrough('/contacts'); - this.passthrough('/addresses', ['post']); - }); - - $.ajax({ - method: 'GET', - url: '/contacts', - error(reason) { - assert.equal(reason.status, 404); - done1(); - } - }); - - $.ajax({ - method: 'POST', - url: '/addresses', - error(reason) { - assert.equal(reason.status, 404); - done2(); - } - }); -}); - -test('passthrough without args allows all paths on the current domain to passthrough', function(assert) { - assert.expect(2); - let done1 = assert.async(); - let done2 = assert.async(); - let { server } = this; - - server.loadConfig(function() { - this.get('/contacts', function() { - return 123; - }); - this.passthrough(); - }); - - $.ajax({ - method: 'GET', - url: '/contacts', - success(data) { - assert.equal(data, 123); - done1(); - } - }); - - $.ajax({ - method: 'GET', - url: '/addresses', - error(reason) { - assert.equal(reason.status, 404); - done2(); - } - }); -}); - -test('passthrough without args allows index route on current domain to passthrough', function(assert) { - assert.expect(2); - let done1 = assert.async(); - let done2 = assert.async(); - let { server } = this; - - server.loadConfig(function() { - this.get('/contacts', function() { - return 123; - }); - this.passthrough(); - }); - - $.ajax({ - method: 'GET', - url: '/contacts', - success(data) { - assert.equal(data, 123, 'contacts is intercepted'); - done1(); - } - }); - - $.ajax({ - method: 'GET', - url: '/', - error() { - done2(); // test will fail bc only 1 assertion, but we don't have to wait - }, - success(html) { - // a passthrough request to index on the current domain - // actually succeeds here, since that's where the test runner is served - assert.ok(html, '/ is passed through'); - done2(); // test will fail bc only 1 assertion, but we don't have to wait - } - }); -}); - -test('it can passthrough other-origin hosts', function(assert) { - assert.expect(1); - let done1 = assert.async(); - let { server } = this; - - server.loadConfig(function() { - this.passthrough('http://api.foo.bar/**'); - }); - - $.ajax({ - method: 'GET', - url: 'http://api.foo.bar/contacts', - error() { - assert.ok(true); - done1(); - } - }); -}); diff --git a/tests/integration/route-handlers/delete-shorthand-test.js b/tests/integration/route-handlers/delete-shorthand-test.js deleted file mode 100644 index a9c7b3201..000000000 --- a/tests/integration/route-handlers/delete-shorthand-test.js +++ /dev/null @@ -1,91 +0,0 @@ -import {module, test} from 'qunit'; -import Server from 'ember-cli-mirage/server'; -import Model from 'ember-cli-mirage/orm/model'; -import Mirage from 'ember-cli-mirage'; -import DeleteShorthandRouteHandler from 'ember-cli-mirage/route-handlers/shorthands/delete'; -import JSONAPISerializer from 'ember-cli-mirage/serializers/json-api-serializer'; - -module('Integration | Route Handlers | DELETE shorthand', { - - beforeEach() { - this.server = new Server({ - environment: 'development', - models: { - wordSmith: Model.extend({ - blogPosts: Mirage.hasMany() - }), - blogPost: Model - } - }); - this.server.timing = 0; - this.server.logging = false; - - let wordSmiths = [ - { id: 1, name: 'Ganon' } - ]; - let blogPosts = [ - { id: 1, title: 'Lorem', wordSmithId: '1' }, - { id: 2, title: 'Another', wordSmithId: '2' } - ]; - this.server.db.loadData({ wordSmiths, blogPosts }); - - this.schema = this.server.schema; - this.serializer = new JSONAPISerializer(); - }, - - afterEach() { - this.server.shutdown(); - } - -}); - -test('undefined shorthand deletes the record and returns null', function(assert) { - let request = { url: '/word-smiths/1', params: { id: '1' } }; - let handler = new DeleteShorthandRouteHandler(this.schema, this.serializer, undefined, '/word-smiths/:id'); - - let response = handler.handle(request); - - assert.equal(this.schema.db.wordSmiths.length, 0); - assert.equal(response, null); -}); - -test('query params are ignored', function(assert) { - let request = { url: '/word-smiths/1?foo=bar', params: { id: '1' }, queryParams: { foo: 'bar' } }; - let handler = new DeleteShorthandRouteHandler(this.schema, this.serializer, undefined, '/word-smiths/:id'); - - let response = handler.handle(request); - - assert.equal(this.schema.db.wordSmiths.length, 0); - assert.equal(response, null); -}); - -test('string shorthand deletes the record of the specified type', function(assert) { - let request = { url: '/word-smiths/1?foo=bar', params: { id: '1' }, queryParams: { foo: 'bar' } }; - let handler = new DeleteShorthandRouteHandler(this.schema, this.serializer, undefined, '/word-smiths/:id'); - - let response = handler.handle(request); - - assert.equal(this.schema.db.wordSmiths.length, 0); - assert.equal(response, null); -}); - -test('array shorthand deletes the record and all related records', function(assert) { - let request = { url: '/word-smiths/1', params: { id: '1' } }; - let handler = new DeleteShorthandRouteHandler(this.schema, this.serializer, ['word-smith', 'blog-post']); - - let response = handler.handle(request); - - assert.equal(this.schema.db.wordSmiths.length, 0); - assert.equal(this.schema.db.blogPosts.length, 1); - assert.equal(response, null); -}); - -test('if a shorthand tries to access an unknown type it throws an error', function(assert) { - let request = { url: '/foobars/1', params: { id: '1' } }; - let handler = new DeleteShorthandRouteHandler(this.schema, this.serializer, undefined, '/foobars/:id'); - - assert.throws(function() { - handler.handle(request); - }, /model doesn't exist/); - assert.ok(true); -}); diff --git a/tests/integration/route-handlers/function-handler-test.js b/tests/integration/route-handlers/function-handler-test.js deleted file mode 100644 index e822ac9b7..000000000 --- a/tests/integration/route-handlers/function-handler-test.js +++ /dev/null @@ -1,180 +0,0 @@ -import { module, test } from 'qunit'; -import { Model, Collection, Serializer } from 'ember-cli-mirage'; -import Ember from 'ember'; -import Server from 'ember-cli-mirage/server'; -import Response from 'ember-cli-mirage/response'; -import FunctionRouteHandler from 'ember-cli-mirage/route-handlers/function'; -import _uniqBy from 'lodash/uniqBy'; - -const { RSVP: { Promise } } = Ember; - -module('Integration | Route handlers | Function handler', { - beforeEach() { - this.server = new Server({ - environment: 'development', - models: { - user: Model.extend({ - }) - }, - serializers: { - sparseUser: Serializer.extend({ - attrs: ['id', 'name', 'tall'] - }) - } - }); - this.server.timing = 0; - this.server.logging = false; - - this.functionHandler = new FunctionRouteHandler(this.server.schema, this.server.serializerOrRegistry); - this.schema = this.server.schema; - }, - afterEach() { - this.server.shutdown(); - } -}); - -test('mirage response string is not serialized to string', function(assert) { - assert.expect(1); - let done = assert.async(); - - this.server.get('/users', function() { - return new Response(200, { 'Content-Type': 'text/csv' }, 'firstname,lastname\nbob,dylon'); - }); - - $.ajax({ method: 'GET', url: '/users' }).done(function(res) { - assert.equal(res, 'firstname,lastname\nbob,dylon'); - done(); - }); -}); - -test('function can return a promise with non-serializable content', function(assert) { - assert.expect(1); - let done = assert.async(); - - this.server.get('/users', function() { - return new Promise(resolve => { - resolve(new Response(200, { 'Content-Type': 'text/csv' }, 'firstname,lastname\nbob,dylan')); - }); - }); - - $.ajax({ method: 'GET', url: '/users' }).done(function(res) { - assert.equal(res, 'firstname,lastname\nbob,dylan'); - done(); - }); -}); - -test('function can return a promise with serializable content', function(assert) { - assert.expect(1); - let done = assert.async(); - - let user = this.schema.users.create({ name: 'Sam' }); - - this.server.get('/users', function(schema) { - return new Promise(resolve => { - resolve(schema.users.all()); - }); - }); - - $.ajax({ method: 'GET', url: '/users' }).done(function(res) { - assert.deepEqual(res, { users: [ { id: user.id, name: 'Sam' } ] }); - done(); - }); -}); - -test('function can return a promise with an empty string', function(assert) { - assert.expect(1); - let done = assert.async(); - - this.server.get('/users', function() { - return new Promise(resolve => { - resolve(new Response(200, { 'Content-Type': 'text/csv' }, '')); - }); - }); - - $.ajax({ method: 'GET', url: '/users' }).done(function(res) { - assert.equal(res, ''); - done(); - }); -}); - -test('#serialize uses the default serializer on a model', function(assert) { - this.schema.users.create({ name: 'Sam' }); - - let user = this.schema.users.first(); - let json = this.functionHandler.serialize(user); - - assert.deepEqual(json, { - user: { - id: '1', - name: 'Sam' - } - }); -}); - -test('#serialize uses the default serializer on a collection', function(assert) { - this.schema.users.create({ name: 'Sam' }); - - let users = this.schema.users.all(); - let json = this.functionHandler.serialize(users); - - assert.deepEqual(json, { - users: [ - { id: '1', name: 'Sam' } - ] - }); -}); - -test('#serialize takes an optional serializer type', function(assert) { - this.schema.users.create({ name: 'Sam', tall: true, evil: false }); - this.schema.users.create({ name: 'Ganondorf', tall: true, evil: true }); - - let users = this.schema.users.all(); - let json = this.functionHandler.serialize(users, 'sparse-user'); - - assert.deepEqual(json, { - users: [ - { id: '1', name: 'Sam', tall: true }, - { id: '2', name: 'Ganondorf', tall: true } - ] - }); -}); - -test('#serialize throws an error when trying to specify a serializer that doesnt exist', function(assert) { - this.schema.users.create({ name: 'Sam' }); - - let users = this.schema.users.all(); - - assert.throws(function() { - this.functionHandler.serialize(users, 'foo-user'); - }, /that serializer doesn't exist/); -}); - -test('#serialize noops on plain JS arrays', function(assert) { - this.server.schema.users.create({ name: 'Sam' }); - this.server.schema.users.create({ name: 'Sam' }); - this.server.schema.users.create({ name: 'Ganondorf' }); - - let users = this.schema.users.all().models; - let uniqueNames = _uniqBy(users, 'name'); - let serializedResponse = this.functionHandler.serialize(uniqueNames); - - assert.deepEqual(serializedResponse, uniqueNames); -}); - -test('#serialize on a Collection takes an optional serializer type', function(assert) { - this.server.schema.users.create({ name: 'Sam', tall: true, evil: false }); - this.server.schema.users.create({ name: 'Sam', tall: true, evil: false }); - this.server.schema.users.create({ name: 'Ganondorf', tall: true, evil: true }); - - let users = this.schema.users.all().models; - let uniqueNames = _uniqBy(users, 'name'); - let collection = new Collection('user', uniqueNames); - let json = this.functionHandler.serialize(collection, 'sparse-user'); - - assert.deepEqual(json, { - users: [ - { id: '1', name: 'Sam', tall: true }, - { id: '3', name: 'Ganondorf', tall: true } - ] - }); -}); diff --git a/tests/integration/route-handlers/get-shorthand-test.js b/tests/integration/route-handlers/get-shorthand-test.js deleted file mode 100644 index f16af4dfa..000000000 --- a/tests/integration/route-handlers/get-shorthand-test.js +++ /dev/null @@ -1,219 +0,0 @@ -import { module, test } from 'qunit'; -import { - Model, - hasMany, - belongsTo, - JSONAPISerializer, - Response -} from 'ember-cli-mirage'; -import Collection from 'ember-cli-mirage/orm/collection'; -import Server from 'ember-cli-mirage/server'; -import GetShorthandRouteHandler from 'ember-cli-mirage/route-handlers/shorthands/get'; - -module('Integration | Route Handlers | GET shorthand', { - beforeEach() { - this.server = new Server({ - environment: 'development', - models: { - author: Model.extend({ - posts: hasMany() - }), - post: Model.extend({ - author: belongsTo(), - comments: hasMany() - }), - comment: Model.extend({ - post: belongsTo() - }), - photo: Model, - 'project-owner': Model - } - }); - this.server.timing = 0; - this.server.logging = false; - - this.authors = [ - { id: 1, name: 'Link' }, - { id: 2, name: 'Zelda' }, - { id: 3, name: 'Epona' } - ]; - this.posts = [ - { id: 1, title: 'Lorem', authorId: 1 }, - { id: 2, title: 'Ipsum', authorId: 1 } - ]; - this.photos = [ - { id: 1, title: 'Amazing', location: 'Hyrule' }, - { id: 2, title: 'Photo', location: 'Goron City' } - ]; - this.projectOwners = [ - { id: 1, name: 'Nintendo' } - ]; - this.server.db.loadData({ - authors: this.authors, - posts: this.posts, - photos: this.photos, - projectOwners: this.projectOwners - }); - - this.schema = this.server.schema; - this.serializer = new JSONAPISerializer(); - }, - afterEach() { - this.server.shutdown(); - } -}); - -test('undefined shorthand returns the collection of models', function(assert) { - let request = { url: '/authors' }; - let handler = new GetShorthandRouteHandler(this.schema, this.serializer, undefined, '/authors'); - - let authors = handler.handle(request); - - assert.equal(authors.models.length, 3); - assert.ok(authors.models[0] instanceof Model); - assert.equal(authors.models[0].modelName, 'author'); -}); - -test('undefined shorthand ignores query params', function(assert) { - let request = { url: '/authors?foo=bar' }; - let handler = new GetShorthandRouteHandler(this.schema, this.serializer, undefined, '/authors'); - - let authors = handler.handle(request); - - assert.equal(authors.models.length, 3); - assert.ok(authors.models[0] instanceof Model); - assert.equal(authors.models[0].modelName, 'author'); -}); - -test('undefined shorthand can return a single model', function(assert) { - let request = { url: '/authors/2', params: { id: 2 } }; - let handler = new GetShorthandRouteHandler(this.schema, this.serializer, undefined, '/authors/:id'); - - let author = handler.handle(request); - - assert.ok(author instanceof Model); - assert.equal(author.modelName, 'author'); - assert.equal(author.name, 'Zelda'); -}); - -test('undefined shorthand returns a 404 if a singular resource does not exist', function(assert) { - let request = { url: '/authors/99', params: { id: 99 } }; - let handler = new GetShorthandRouteHandler(this.schema, this.serializer, undefined, '/authors/:id'); - - let author = handler.handle(request); - - assert.ok(author instanceof Response); - assert.equal(author.code, 404); -}); - -test('undefined shorthand ignores query params for a singular resource', function(assert) { - let request = { url: '/authors/2?foo=bar', params: { id: 2 } }; - let handler = new GetShorthandRouteHandler(this.schema, this.serializer, undefined, '/authors/:id'); - - let author = handler.handle(request); - - assert.ok(author instanceof Model); - assert.equal(author.modelName, 'author'); - assert.equal(author.name, 'Zelda'); -}); - -test('undefined shorthand with coalesce true returns the appropriate models', function(assert) { - let request = { url: '/authors?ids[]=1&ids[]=3', queryParams: { ids: [1, 3] } }; - let options = { coalesce: true }; - let handler = new GetShorthandRouteHandler(this.schema, this.serializer, undefined, '/authors', options); - - let authors = handler.handle(request); - - assert.equal(authors.models.length, 2); - assert.deepEqual(authors.models.map((author) => author.name), ['Link', 'Epona']); -}); - -test('string shorthand returns the correct collection of models', function(assert) { - let request = { url: '/people' }; - let handler = new GetShorthandRouteHandler(this.schema, this.serializer, 'author'); - - let authors = handler.handle(request); - - assert.equal(authors.models.length, 3); - assert.ok(authors.models[0] instanceof Model); - assert.equal(authors.models[0].modelName, 'author'); -}); - -test('string shorthand with an id returns the correct model', function(assert) { - let request = { url: '/people/2', params: { id: 2 } }; - let handler = new GetShorthandRouteHandler(this.schema, this.serializer, 'author'); - - let author = handler.handle(request); - - assert.ok(author instanceof Model); - assert.equal(author.modelName, 'author'); - assert.equal(author.name, 'Zelda'); -}); - -test('string shorthand with an id 404s if the model is not found', function(assert) { - let request = { url: '/people/99', params: { id: 99 } }; - let handler = new GetShorthandRouteHandler(this.schema, this.serializer, 'author'); - - let author = handler.handle(request); - - assert.ok(author instanceof Response); - assert.equal(author.code, 404); -}); - -test('string shorthand with coalesce returns the correct models', function(assert) { - let request = { url: '/people?ids[]=1&ids[]=3', queryParams: { ids: [1, 3] } }; - let options = { coalesce: true }; - let handler = new GetShorthandRouteHandler(this.schema, this.serializer, 'author', '/people', options); - - let authors = handler.handle(request); - - assert.equal(authors.models.length, 2); - assert.deepEqual(authors.models.map((author) => author.name), ['Link', 'Epona']); -}); - -test('array shorthand returns the correct models', function(assert) { - let url = '/home'; - let request = { url }; - let handler = new GetShorthandRouteHandler(this.schema, this.serializer, ['authors', 'photos'], url); - - let models = handler.handle(request); - - assert.ok(models[0] instanceof Collection); - assert.equal(models[0].modelName, 'author'); - assert.equal(models[0].models.length, this.authors.length); - - assert.ok(models[1] instanceof Collection); - assert.equal(models[1].modelName, 'photo'); - assert.equal(models[1].models.length, this.photos.length); -}); - -test('array shorthand for a singular resource errors', function(assert) { - let url = '/authors/1'; - let request = { url, params: { id: 1 } }; - let handler = new GetShorthandRouteHandler(this.schema, this.serializer, ['author', 'posts'], url); - - assert.throws(function() { - handler.handle(request); - }, /create a serializer/); -}); - -test('shorthand for list of models with a dash in their name', function(assert) { - let url = '/project-owners'; - let request = { url }; - let handler = new GetShorthandRouteHandler(this.schema, this.serializer, undefined, url); - let models = handler.handle(request); - - assert.equal(models.models.length, 1); - assert.ok(models.models[0] instanceof Model); - assert.equal(models.models[0].modelName, 'project-owner'); -}); - -test('if a shorthand tries to access an unknown type it throws an error', function(assert) { - let url = '/foobars'; - let request = { url }; - let handler = new GetShorthandRouteHandler(this.schema, this.serializer, undefined, url); - - assert.throws(function() { - handler.handle(request); - }, /model doesn't exist/); -}); diff --git a/tests/integration/route-handlers/head-shorthand-test.js b/tests/integration/route-handlers/head-shorthand-test.js deleted file mode 100644 index 2bddfa21b..000000000 --- a/tests/integration/route-handlers/head-shorthand-test.js +++ /dev/null @@ -1,124 +0,0 @@ -import { module, test } from 'qunit'; -import { - Model, - JSONAPISerializer, - Response -} from 'ember-cli-mirage'; -import Server from 'ember-cli-mirage/server'; -import HeadShorthandRouteHandler from 'ember-cli-mirage/route-handlers/shorthands/head'; - -module('Integration | Route Handlers | HEAD shorthand', { - beforeEach() { - this.server = new Server({ - environment: 'development', - models: { - author: Model, - photo: Model - } - }); - this.server.timing = 0; - this.server.logging = false; - - this.authors = [ - { id: 1, name: 'Link' }, - { id: 2, name: 'Zelda' }, - { id: 3, name: 'Epona' } - ]; - this.photos = [ - { id: 1, title: 'Amazing', location: 'Hyrule' }, - { id: 2, title: 'Photo', location: 'Goron City' } - ]; - this.server.db.loadData({ - authors: this.authors, - photos: this.photos - }); - - this.schema = this.server.schema; - this.serializer = new JSONAPISerializer(); - }, - afterEach() { - this.server.shutdown(); - } -}); - -test('undefined shorthand with an ID that is not in the DB will return a 404 Response', function(assert) { - let request = { url: '/authors', params: { id: 101 } }; - let handler = new HeadShorthandRouteHandler(this.schema, this.serializer, undefined, '/authors'); - - let response = handler.handle(request); - - assert.ok(response instanceof Response); - assert.equal(response.code, 404); -}); - -test('undefined shorthand with an ID that is in the DB will return a 204 Response', function(assert) { - let request = { url: '/authors', params: { id: 1 } }; - let handler = new HeadShorthandRouteHandler(this.schema, this.serializer, undefined, '/authors'); - - let response = handler.handle(request); - - assert.ok(response instanceof Response); - assert.equal(response.code, 204); -}); - -test('undefined shorthand with coalesce true will return a 204 response if one of the IDs are found', function(assert) { - let request = { url: '/authors?ids[]=1&ids[]=3', queryParams: { ids: [1, 3] } }; - let options = { coalesce: true }; - let handler = new HeadShorthandRouteHandler(this.schema, this.serializer, undefined, '/authors', options); - - let response = handler.handle(request); - - assert.ok(response instanceof Response); - assert.equal(response.code, 204); -}); - -test('undefined shorthand string (no id) shorthand returns a 204 (regardless of the length of the collection)', function(assert) { - let request = { url: '/authors' }; - let handler = new HeadShorthandRouteHandler(this.schema, this.serializer, undefined, '/authors'); - - let response = handler.handle(request); - - assert.ok(response instanceof Response); - assert.equal(response.code, 204); -}); - -test('string shorthand with an ID that is not in the DB will return a 404 Response', function(assert) { - let request = { url: '/authors', params: { id: 101 } }; - let handler = new HeadShorthandRouteHandler(this.schema, this.serializer, 'author'); - - let response = handler.handle(request); - - assert.ok(response instanceof Response); - assert.equal(response.code, 404); -}); - -test('string shorthand with an ID that is in the DB will return a 204 Response', function(assert) { - let request = { url: '/authors', params: { id: 1 } }; - let handler = new HeadShorthandRouteHandler(this.schema, this.serializer, 'author'); - - let response = handler.handle(request); - - assert.ok(response instanceof Response); - assert.equal(response.code, 204); -}); - -test('string shorthand with coalesce true will return a 204 response if one of the IDs are found', function(assert) { - let request = { url: '/authors?ids[]=1&ids[]=3', queryParams: { ids: [1, 3] } }; - let options = { coalesce: true }; - let handler = new HeadShorthandRouteHandler(this.schema, this.serializer, 'author', '/people', options); - - let response = handler.handle(request); - - assert.ok(response instanceof Response); - assert.equal(response.code, 204); -}); - -test('string shorthand string (no id) shorthand returns a 204 (regardless of the length of the collection)', function(assert) { - let request = { url: '/authors' }; - let handler = new HeadShorthandRouteHandler(this.schema, this.serializer, 'author'); - - let response = handler.handle(request); - - assert.ok(response instanceof Response); - assert.equal(response.code, 204); -}); diff --git a/tests/integration/route-handlers/post-shorthand-test.js b/tests/integration/route-handlers/post-shorthand-test.js deleted file mode 100644 index 37d592678..000000000 --- a/tests/integration/route-handlers/post-shorthand-test.js +++ /dev/null @@ -1,80 +0,0 @@ -import {module, test} from 'qunit'; -import Server from 'ember-cli-mirage/server'; -import Model from 'ember-cli-mirage/orm/model'; -import PostShorthandRouteHandler from 'ember-cli-mirage/route-handlers/shorthands/post'; -import JSONAPISerializer from 'ember-cli-mirage/serializers/json-api-serializer'; - -module('Integration | Route Handlers | POST shorthand', { - beforeEach() { - this.server = new Server({ - environment: 'development', - models: { - author: Model.extend({}) - } - }); - this.server.timing = 0; - this.server.logging = false; - this.schema = this.server.schema; - - this.serializer = new JSONAPISerializer(); - - this.body = { - data: { - type: 'authors', - attributes: { - 'first-name': 'Ganon', - 'last-name': 'Dorf' - } - } - }; - }, - afterEach() { - this.server.shutdown(); - } -}); - -test('string shorthand creates a record of the specified type and returns the new model', function(assert) { - let request = { requestBody: JSON.stringify(this.body), url: '/people' }; - let handler = new PostShorthandRouteHandler(this.schema, this.serializer, 'author'); - - let model = handler.handle(request); - - assert.equal(this.schema.db.authors.length, 1); - assert.ok(model instanceof Model); - assert.equal(model.modelName, 'author'); - assert.equal(model.firstName, 'Ganon'); -}); - -test('query params are ignored', function(assert) { - let request = { requestBody: JSON.stringify(this.body), url: '/authors?foo=bar', queryParams: { foo: 'bar' } }; - let handler = new PostShorthandRouteHandler(this.schema, this.serializer, 'author'); - - let model = handler.handle(request); - - assert.equal(this.schema.db.authors.length, 1); - assert.ok(model instanceof Model); - assert.equal(model.modelName, 'author'); - assert.equal(model.firstName, 'Ganon'); -}); - -test('undefined shorthand creates a record and returns the new model', function(assert) { - let request = { requestBody: JSON.stringify(this.body), url: '/authors' }; - let handler = new PostShorthandRouteHandler(this.schema, this.serializer, null, '/authors'); - - let model = handler.handle(request); - - assert.equal(this.schema.db.authors.length, 1); - assert.ok(model instanceof Model); - assert.equal(model.modelName, 'author'); - assert.equal(model.firstName, 'Ganon'); -}); - -test('if a shorthand tries to access an unknown type it throws an error', function(assert) { - let request = { requestBody: JSON.stringify(this.body), url: '/foobars' }; - let handler = new PostShorthandRouteHandler(this.schema, this.serializer, 'foobar'); - - assert.throws(function() { - handler.handle(request); - }, /model doesn't exist/); - assert.ok(true); -}); diff --git a/tests/integration/route-handlers/put-shorthand-test.js b/tests/integration/route-handlers/put-shorthand-test.js deleted file mode 100644 index 3fa2bfeaa..000000000 --- a/tests/integration/route-handlers/put-shorthand-test.js +++ /dev/null @@ -1,89 +0,0 @@ -import {module, test} from 'qunit'; -import PutShorthandRouteHandler from 'ember-cli-mirage/route-handlers/shorthands/put'; -import Server from 'ember-cli-mirage/server'; -import Model from 'ember-cli-mirage/orm/model'; -import JSONAPISerializer from 'ember-cli-mirage/serializers/json-api-serializer'; - -module('Integration | Route Handlers | PUT shorthand', { - - beforeEach() { - this.server = new Server({ - environment: 'development', - models: { - author: Model.extend() - } - }); - this.server.timing = 0; - this.server.logging = false; - - this.authors = [ - { id: 1, firstName: 'Ganon' } - ]; - this.server.db.loadData({ - authors: this.authors - }); - - this.schema = this.server.schema; - this.serializer = new JSONAPISerializer(); - - this.body = { - data: { - type: 'authors', - id: '1', - attributes: { - 'first-name': 'Ganondorf' - } - } - }; - }, - afterEach() { - this.server.shutdown(); - } - -}); - -test('undefined shorthand updates the record and returns the model', function(assert) { - let handler = new PutShorthandRouteHandler(this.schema, this.serializer, undefined, '/authors/:id'); - let request = { requestBody: JSON.stringify(this.body), url: '/authors/1', params: { id: '1' } }; - - let model = handler.handle(request); - - assert.equal(this.schema.db.authors.length, 1); - assert.ok(model instanceof Model); - assert.equal(model.modelName, 'author'); - assert.equal(model.firstName, 'Ganondorf'); -}); - -test('query params are ignored', function(assert) { - let handler = new PutShorthandRouteHandler(this.schema, this.serializer, 'author'); - let request = { requestBody: JSON.stringify(this.body), url: '/authors/1?foo=bar', params: { id: '1' }, queryParams: { foo: 'bar' } }; - - let model = handler.handle(request); - - assert.equal(this.schema.db.authors.length, 1); - assert.ok(model instanceof Model); - assert.equal(model.modelName, 'author'); - assert.equal(model.firstName, 'Ganondorf'); -}); - -test('string shorthand updates the record of the specified type and returns the model', function(assert) { - let handler = new PutShorthandRouteHandler(this.schema, this.serializer, undefined, '/authors/:id'); - let request = { requestBody: JSON.stringify(this.body), url: '/authors/1', params: { id: '1' } }; - - let model = handler.handle(request); - - assert.equal(this.schema.db.authors.length, 1); - assert.ok(model instanceof Model); - assert.equal(model.modelName, 'author'); - assert.equal(model.firstName, 'Ganondorf'); -}); - -test('if a shorthand tries to access an unknown type it throws an error', function(assert) { - let handler = new PutShorthandRouteHandler(this.schema, this.serializer, undefined, '/foobars/:id'); - let request = { requestBody: JSON.stringify(this.body), url: '/foobars/1', params: { id: '1' } }; - - assert.throws(function() { - handler.handle(request); - }, /model doesn't exist/); - assert.ok(true); -}); diff --git a/tests/integration/serializers/active-model-serializer-test.js b/tests/integration/serializers/active-model-serializer-test.js deleted file mode 100644 index de7d21691..000000000 --- a/tests/integration/serializers/active-model-serializer-test.js +++ /dev/null @@ -1,143 +0,0 @@ -import { ActiveModelSerializer, Model, hasMany, belongsTo } from 'ember-cli-mirage'; -import Schema from 'ember-cli-mirage/orm/schema'; -import Db from 'ember-cli-mirage/db'; -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; -import { module, test } from 'qunit'; - -module('Integration | Serializer | ActiveModelSerializer', { - beforeEach() { - let db = new Db(); - this.schema = new Schema(db); - this.schema.registerModels({ - wordSmith: Model.extend({ - blogPosts: hasMany() - }), - blogPost: Model.extend({ - wordSmith: belongsTo() - }), - user: Model.extend({ - contactInfos: hasMany() - }), - contactInfo: Model.extend({ - user: belongsTo() - }) - }); - - let link = this.schema.wordSmiths.create({ name: 'Link', age: 123 }); - link.createBlogPost({ title: 'Lorem' }); - link.createBlogPost({ title: 'Ipsum' }); - - this.schema.wordSmiths.create({ name: 'Zelda', age: 230 }); - - let user = this.schema.users.create({ name: 'John Peach', age: 123 }); - user.createContactInfo({ email: 'peach@bb.me' }); - user.createContactInfo({ email: 'john3000@mail.com' }); - - this.schema.users.create({ name: 'Pine Apple', age: 230 }); - - this.registry = new SerializerRegistry(this.schema, { - application: ActiveModelSerializer, - wordSmith: ActiveModelSerializer.extend({ - attrs: ['id', 'name'], - include: ['blogPosts'] - }), - user: ActiveModelSerializer.extend({ - attrs: ['id', 'name'], - include: ['contactInfos'], - embed: true - }) - }); - }, - - afterEach() { - this.schema.db.emptyData(); - } -}); - -test('it sideloads associations and snake-cases relationships and attributes correctly for a model', function(assert) { - let link = this.schema.wordSmiths.find(1); - let result = this.registry.serialize(link); - - assert.deepEqual(result, { - word_smith: { - id: '1', - name: 'Link', - blog_post_ids: ['1', '2'] - }, - blog_posts: [ - { - id: '1', - title: 'Lorem', - word_smith_id: '1' - }, - { - id: '2', - title: 'Ipsum', - word_smith_id: '1' - } - ] - }); -}); - -test('it sideloads associations and snake-cases relationships and attributes correctly for a collection', function(assert) { - let wordSmiths = this.schema.wordSmiths.all(); - let result = this.registry.serialize(wordSmiths); - - assert.deepEqual(result, { - word_smiths: [ - { - id: '1', - name: 'Link', - blog_post_ids: ['1', '2'] - }, - { - id: '2', - name: 'Zelda', - blog_post_ids: [] - } - ], - blog_posts: [ - { - id: '1', - title: 'Lorem', - word_smith_id: '1' - }, - { - id: '2', - title: 'Ipsum', - word_smith_id: '1' - } - ] - }); -}); - -test('it embeds associations and snake-cases relationships and attributes correctly for a collection', function(assert) { - let users = this.schema.users.all(); - let result = this.registry.serialize(users); - - assert.deepEqual(result, { - users: [ - { - id: '1', - name: 'John Peach', - contact_infos: [ - { - id: '1', - email: 'peach@bb.me', - user_id: '1' - }, - { - id: '2', - email: 'john3000@mail.com', - user_id: '1' - } - ] - }, - { - id: '2', - name: 'Pine Apple', - contact_infos: [] - } - ] - }); -}); diff --git a/tests/integration/serializers/base/associations/embedded-collection-test.js b/tests/integration/serializers/base/associations/embedded-collection-test.js deleted file mode 100644 index 7cc1d9e35..000000000 --- a/tests/integration/serializers/base/associations/embedded-collection-test.js +++ /dev/null @@ -1,168 +0,0 @@ -import { Model, hasMany, belongsTo } from 'ember-cli-mirage'; -import Schema from 'ember-cli-mirage/orm/schema'; -import Db from 'ember-cli-mirage/db'; -import Serializer from 'ember-cli-mirage/serializer'; -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; -import { module, test } from 'qunit'; - -module('Integration | Serializers | Base | Associations | Embedded Collections', { - beforeEach() { - this.schema = new Schema(new Db(), { - wordSmith: Model.extend({ - posts: hasMany('blogPost', { inverse: 'author' }) - }), - blogPost: Model.extend({ - author: belongsTo('wordSmith', { inverse: 'posts' }), - comments: hasMany('fineComment', { inverse: 'post' }) - }), - fineComment: Model.extend({ - post: belongsTo('blogPost') - }) - }); - - let wordSmith = this.schema.wordSmiths.create({ name: 'Link' }); - let blogPost = wordSmith.createPost({ title: 'Lorem' }); - blogPost.createComment({ text: 'pwned' }); - - wordSmith.createPost({ title: 'Ipsum' }); - - this.schema.wordSmiths.create({ name: 'Zelda' }); - - this.BaseSerializer = Serializer.extend({ - embed: true - }); - }, - - afterEach() { - this.schema.db.emptyData(); - } -}); - -test(`it can embed a collection with a has-many relationship`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: this.BaseSerializer, - wordSmith: this.BaseSerializer.extend({ - include: ['posts'] - }) - }); - - let wordSmiths = this.schema.wordSmiths.all(); - let result = registry.serialize(wordSmiths); - - assert.deepEqual(result, { - wordSmiths: [ - { - id: '1', - name: 'Link', - posts: [ - { id: '1', title: 'Lorem' }, - { id: '2', title: 'Ipsum' } - ] - }, - { - id: '2', - name: 'Zelda', - posts: [] - } - ] - }); -}); - -test(`it can embed a collection with a chain of has-many relationships`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: this.BaseSerializer, - wordSmith: this.BaseSerializer.extend({ - include: ['posts'] - }), - blogPost: this.BaseSerializer.extend({ - include: ['comments'] - }) - }); - - let wordSmiths = this.schema.wordSmiths.all(); - let result = registry.serialize(wordSmiths); - - assert.deepEqual(result, { - wordSmiths: [ - { - id: '1', - name: 'Link', - posts: [ - { - id: '1', - title: 'Lorem', - comments: [ - { id: '1', text: 'pwned' } - ] - }, - { - id: '2', - title: 'Ipsum', - comments: [] - } - ] - }, - { - id: '2', - name: 'Zelda', - posts: [] - } - ] - }); -}); - -test(`it can embed a collection with a belongs-to relationship`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: this.BaseSerializer, - blogPost: this.BaseSerializer.extend({ - include: ['author'] - }) - }); - - let blogPosts = this.schema.blogPosts.all(); - let result = registry.serialize(blogPosts); - - assert.deepEqual(result, { - blogPosts: [ - { - id: '1', - title: 'Lorem', - author: { id: '1', name: 'Link' } - }, - { - id: '2', - title: 'Ipsum', - author: { id: '1', name: 'Link' } - } - ] - }); -}); - -test(`it can embed a collection with a chain of belongs-to relationships`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: this.BaseSerializer, - fineComment: this.BaseSerializer.extend({ - include: ['post'] - }), - blogPost: this.BaseSerializer.extend({ - include: ['author'] - }) - }); - - let fineComments = this.schema.fineComments.all(); - let result = registry.serialize(fineComments); - - assert.deepEqual(result, { - fineComments: [ - { - id: '1', - text: 'pwned', - post: { - id: '1', - title: 'Lorem', - author: { id: '1', name: 'Link' } - } - } - ] - }); -}); diff --git a/tests/integration/serializers/base/associations/embedded-model-test.js b/tests/integration/serializers/base/associations/embedded-model-test.js deleted file mode 100644 index 1e01de488..000000000 --- a/tests/integration/serializers/base/associations/embedded-model-test.js +++ /dev/null @@ -1,198 +0,0 @@ -import { Model, hasMany, belongsTo } from 'ember-cli-mirage'; -import Schema from 'ember-cli-mirage/orm/schema'; -import Db from 'ember-cli-mirage/db'; -import Serializer from 'ember-cli-mirage/serializer'; -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; -import { module, test } from 'qunit'; - -module('Integration | Serializers | Base | Associations | Embedded Models', { - beforeEach() { - this.schema = new Schema(new Db(), { - wordSmith: Model.extend({ - posts: hasMany('blogPost', { inverse: 'author' }) - }), - blogPost: Model.extend({ - author: belongsTo('wordSmith', { inverse: 'posts' }), - comments: hasMany('fineComment', { inverse: 'post' }) - }), - fineComment: Model.extend({ - post: belongsTo('blogPost') - }) - }); - - let wordSmith = this.schema.wordSmiths.create({ name: 'Link' }); - let post = wordSmith.createPost({ title: 'Lorem' }); - post.createComment({ text: 'pwned' }); - - wordSmith.createPost({ title: 'Ipsum' }); - - this.schema.wordSmiths.create({ name: 'Zelda' }); - - this.BaseSerializer = Serializer.extend({ - embed: true - }); - }, - - afterEach() { - this.schema.db.emptyData(); - } -}); - -test(`it can embed has-many relationships`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: this.BaseSerializer, - wordSmith: this.BaseSerializer.extend({ - include: ['posts'] - }) - }); - - let link = this.schema.wordSmiths.find(1); - let result = registry.serialize(link); - - assert.deepEqual(result, { - wordSmith: { - id: '1', - name: 'Link', - posts: [ - { id: '1', title: 'Lorem' }, - { id: '2', title: 'Ipsum' } - ] - } - }); -}); - -test(`it can embed a chain of has-many relationships`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: this.BaseSerializer, - wordSmith: this.BaseSerializer.extend({ - include: ['posts'] - }), - blogPost: this.BaseSerializer.extend({ - include: ['comments'] - }) - }); - - let wordSmith = this.schema.wordSmiths.find(1); - let result = registry.serialize(wordSmith); - - assert.deepEqual(result, { - wordSmith: { - id: '1', - name: 'Link', - posts: [ - { id: '1', title: 'Lorem', comments: [ - { id: '1', text: 'pwned' } - ] }, - { id: '2', title: 'Ipsum', comments: [] } - ] - } - }); -}); - -test(`it can embed a belongs-to relationship`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: this.BaseSerializer, - blogPost: this.BaseSerializer.extend({ - embed: true, - include: ['author'] - }) - }); - - let blogPost = this.schema.blogPosts.find(1); - let result = registry.serialize(blogPost); - - assert.deepEqual(result, { - blogPost: { - id: '1', - title: 'Lorem', - author: { id: '1', name: 'Link' } - } - }); -}); - -test(`it can serialize a chain of belongs-to relationships`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: this.BaseSerializer, - fineComment: this.BaseSerializer.extend({ - include: ['post'] - }), - blogPost: this.BaseSerializer.extend({ - include: ['author'] - }) - }); - - let fineComment = this.schema.fineComments.find(1); - let result = registry.serialize(fineComment); - - assert.deepEqual(result, { - fineComment: { - id: '1', - text: 'pwned', - post: { - id: '1', - title: 'Lorem', - author: { - id: '1', name: 'Link' - } - } - } - }); -}); - -test(`it ignores relationships that refer to serialized ancestor resources`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: this.BaseSerializer, - wordSmith: this.BaseSerializer.extend({ - include: ['posts'] - }), - blogPost: this.BaseSerializer.extend({ - include: ['author'] - }) - }); - - let wordSmith = this.schema.wordSmiths.find(1); - let result = registry.serialize(wordSmith); - - assert.deepEqual(result, { - wordSmith: { - id: '1', - name: 'Link', - posts: [ - { id: '1', title: 'Lorem' }, - { id: '2', title: 'Ipsum' } - ] - } - }); -}); - -test(`it ignores relationships that refer to serialized ancestor resources, multiple levels down`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: this.BaseSerializer, - wordSmith: this.BaseSerializer.extend({ - embed: true, - include: ['posts'] - }), - blogPost: this.BaseSerializer.extend({ - include: ['author', 'comments'] - }), - fineComment: this.BaseSerializer.extend({ - include: ['post'] - }) - }); - - let wordSmith = this.schema.wordSmiths.find(1); - let result = registry.serialize(wordSmith); - - assert.deepEqual(result, { - wordSmith: { - id: '1', - name: 'Link', - posts: [ - { id: '1', title: 'Lorem', comments: [ - { id: '1', text: 'pwned' } - ] }, - { id: '2', title: 'Ipsum', comments: [] } - ] - } - }); -}); diff --git a/tests/integration/serializers/base/associations/many-to-many-test.js b/tests/integration/serializers/base/associations/many-to-many-test.js deleted file mode 100644 index 8f04023c6..000000000 --- a/tests/integration/serializers/base/associations/many-to-many-test.js +++ /dev/null @@ -1,78 +0,0 @@ -import { module, skip } from 'qunit'; -import { Collection, Model, hasMany, belongsTo, Serializer } from 'ember-cli-mirage'; -import Db from 'ember-cli-mirage/db'; -import Schema from 'ember-cli-mirage/orm/schema'; -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; - -module('Integration | Serializers | Base | Associations | Many To Many', { - beforeEach() { - let db = new Db(); - - let schema = new Schema(db, { - contact: Model.extend({ - addresses: hasMany(), - contactAddresses: hasMany() - }), - address: Model.extend({ - contacts: hasMany(), - contactAddresses: hasMany() - }), - contactAddress: Model.extend({ - contact: belongsTo(), - address: belongsTo() - }) - }); - - let registry = new SerializerRegistry(schema, { - contact: Serializer.extend({ - include: ['addresses'], - addresses(model) { - let models = model.contactAddresses.models.map((ca) => ca.address); - return new Collection('address', models); - } - }), - address: Serializer.extend({ - include: ['contacts'], - contacts(model) { - let models = model.contactAddresses.models.map((ca) => ca.contact); - return new Collection('contact', models); - } - }) - }); - - let mario = schema.contacts.create({ name: 'Mario' }); - let newYork = schema.addresses.create({ street: 'Some New York Street' }); - let mushroomKingdom = schema.addresses.create({ street: 'Some Mushroom Kingdom Street' }); - - schema.contactAddresses.create({ contact: mario, address: newYork }); - schema.contactAddresses.create({ contact: mario, address: mushroomKingdom }); - - this.schema = schema; - this.registry = registry; - } -}); - -skip(`it serializes manyToMany if properly configured to passthrough`, function(assert) { - let contact = this.schema.contacts.find(1); - let result = this.registry.serialize(contact); - - assert.deepEqual(result, { - addresses: [{ - contactId: null, // side-effect of having a HasMany on the contactAddress side of things - contactIds: ['1'], - id: '1', - street: 'Some New York Street' - }, { - contactId: null, - contactIds: ['1'], - id: '2', - street: 'Some Mushroom Kingdom Street' - }], - contact: { - addressId: null, // side-effect of having a HasMany on the contactAddress side of things - addressIds: ['1', '2'], - id: '1', - name: 'Mario' - } - }); -}); diff --git a/tests/integration/serializers/base/associations/sideloading-assorted-collections-test.js b/tests/integration/serializers/base/associations/sideloading-assorted-collections-test.js deleted file mode 100644 index ea2b10a51..000000000 --- a/tests/integration/serializers/base/associations/sideloading-assorted-collections-test.js +++ /dev/null @@ -1,62 +0,0 @@ -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; -import Serializer from 'ember-cli-mirage/serializer'; -import schemaHelper from '../../schema-helper'; -import {module, test} from 'qunit'; - -module('Integration | Serializers | Base | Associations | Sideloading Assorted Collections', { - beforeEach() { - this.schema = schemaHelper.setup(); - let BaseSerializer = Serializer.extend({ - embed: false - }); - this.registry = new SerializerRegistry(this.schema, { - application: BaseSerializer, - wordSmith: BaseSerializer.extend({ - include: ['blogPosts'] - }), - greatPhoto: BaseSerializer.extend({ - attrs: ['id', 'title'] - }) - }); - this.wordSmiths = [ - { id: '1', name: 'Link' }, - { id: '2', name: 'Zelda' }, - { id: '3', name: 'Epona' } - ]; - this.blogPosts = [ - { id: '1', title: 'Lorem', wordSmithId: '1' }, - { id: '2', title: 'Ipsum', wordSmithId: '1' } - ]; - this.greatPhotos = [ - { id: '1', title: 'Amazing', location: 'Hyrule' }, - { id: '2', title: 'greatPhoto', location: 'Goron City' } - ]; - this.schema.db.loadData({ - wordSmiths: this.wordSmiths, - blogPosts: this.blogPosts, - greatPhotos: this.greatPhotos - }); - }, - afterEach() { - this.schema.db.emptyData(); - } -}); - -/* - This is a strange response from a route handler, but it's used in the array get shorthand. Deprecate that shorthand? -*/ -test(`it can sideload an array of assorted collections that have relationships`, function(assert) { - let result = this.registry.serialize([this.schema.wordSmiths.all(), this.schema.greatPhotos.all()]); - - assert.deepEqual(result, { - wordSmiths: this.wordSmiths.map((attrs) => { - attrs.blogPostIds = this.blogPosts.filter((blogPost) => blogPost.wordSmithId === attrs.id).map((blogPost) => blogPost.id); - return attrs; - }), - blogPosts: this.blogPosts, - greatPhotos: this.greatPhotos.map((attrs) => { - delete attrs.location; - return attrs; - }) - }); -}); diff --git a/tests/integration/serializers/base/associations/sideloading-collection-test.js b/tests/integration/serializers/base/associations/sideloading-collection-test.js deleted file mode 100644 index a51d01057..000000000 --- a/tests/integration/serializers/base/associations/sideloading-collection-test.js +++ /dev/null @@ -1,212 +0,0 @@ -import Serializer from 'ember-cli-mirage/serializer'; -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; -import schemaHelper from '../../schema-helper'; -import { module, test } from 'qunit'; - -module('Integration | Serializers | Base | Associations | Sideloading Collections', { - beforeEach() { - this.schema = schemaHelper.setup(); - - let link = this.schema.wordSmiths.create({ name: 'Link' }); - let blogPost = link.createBlogPost({ title: 'Lorem' }); - link.createBlogPost({ title: 'Ipsum' }); - - blogPost.createFineComment({ text: 'pwned' }); - - let zelda = this.schema.wordSmiths.create({ name: 'Zelda' }); - zelda.createBlogPost({ title: `Zeldas blogPost` }); - - this.BaseSerializer = Serializer.extend({ - embed: false - }); - }, - - afterEach() { - this.schema.db.emptyData(); - } -}); - -test(`it throws an error if embed is false and root is false`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - wordSmith: this.BaseSerializer.extend({ - root: false, - include: ['blogPosts'] - }) - }); - - let wordSmiths = this.schema.wordSmiths.all(); - - assert.throws(function() { - registry.serialize(wordSmiths); - }, /disables the root/); -}); - -test(`it can sideload an empty collection`, function(assert) { - this.schema.db.emptyData(); - let registry = new SerializerRegistry(this.schema, { - application: this.BaseSerializer, - wordSmith: this.BaseSerializer.extend({ - include: ['blogPosts'] - }) - }); - - let result = registry.serialize(this.schema.wordSmiths.all()); - - assert.deepEqual(result, { - wordSmiths: [] - }); -}); - -test(`it can sideload a collection with a has-many relationship`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: this.BaseSerializer, - wordSmith: this.BaseSerializer.extend({ - embed: false, - include: ['blogPosts'] - }) - }); - - let wordSmiths = this.schema.wordSmiths.all(); - let result = registry.serialize(wordSmiths); - - assert.deepEqual(result, { - wordSmiths: [ - { id: '1', name: 'Link', blogPostIds: ['1', '2'] }, - { id: '2', name: 'Zelda', blogPostIds: ['3'] } - ], - blogPosts: [ - { id: '1', title: 'Lorem', wordSmithId: '1' }, - { id: '2', title: 'Ipsum', wordSmithId: '1' }, - { id: '3', title: 'Zeldas blogPost', wordSmithId: '2' } - ] - }); -}); - -test(`it can sideload a collection with a chain of has-many relationships`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: this.BaseSerializer, - wordSmith: this.BaseSerializer.extend({ - embed: false, - include: ['blogPosts'] - }), - blogPost: this.BaseSerializer.extend({ - include: ['fineComments'] - }) - }); - - let wordSmiths = this.schema.wordSmiths.all(); - let result = registry.serialize(wordSmiths); - - assert.deepEqual(result, { - wordSmiths: [ - { id: '1', name: 'Link', blogPostIds: ['1', '2'] }, - { id: '2', name: 'Zelda', blogPostIds: ['3'] } - ], - blogPosts: [ - { id: '1', title: 'Lorem', wordSmithId: '1', fineCommentIds: ['1'] }, - { id: '2', title: 'Ipsum', wordSmithId: '1', fineCommentIds: [] }, - { id: '3', title: 'Zeldas blogPost', wordSmithId: '2', fineCommentIds: [] } - ], - fineComments: [ - { id: '1', text: 'pwned', blogPostId: '1' } - ] - }); -}); - -test(`it avoids circularity when serializing a collection`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: this.BaseSerializer, - wordSmith: this.BaseSerializer.extend({ - embed: false, - include: ['blogPosts'] - }), - blogPost: this.BaseSerializer.extend({ - include: ['wordSmith'] - }) - }); - - let wordSmiths = this.schema.wordSmiths.all(); - let result = registry.serialize(wordSmiths); - - assert.deepEqual(result, { - wordSmiths: [ - { id: '1', name: 'Link', blogPostIds: ['1', '2'] }, - { id: '2', name: 'Zelda', blogPostIds: ['3'] } - ], - blogPosts: [ - { id: '1', title: 'Lorem', wordSmithId: '1' }, - { id: '2', title: 'Ipsum', wordSmithId: '1' }, - { id: '3', title: 'Zeldas blogPost', wordSmithId: '2' } - ] - }); -}); - -test(`it can sideload a collection with a belongs-to relationship`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: this.BaseSerializer, - blogPost: this.BaseSerializer.extend({ - embed: false, - include: ['wordSmith'] - }) - }); - - let blogPosts = this.schema.blogPosts.all(); - let result = registry.serialize(blogPosts); - - assert.deepEqual(result, { - blogPosts: [ - { id: '1', title: 'Lorem', wordSmithId: '1' }, - { id: '2', title: 'Ipsum', wordSmithId: '1' }, - { id: '3', title: 'Zeldas blogPost', wordSmithId: '2' } - ], - wordSmiths: [ - { id: '1', name: 'Link' }, - { id: '2', name: 'Zelda' } - ] - }); -}); - -test(`it can sideload a collection with a chain of belongs-to relationships`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: this.BaseSerializer, - fineComment: this.BaseSerializer.extend({ - embed: false, - include: ['blogPost'] - }), - blogPost: this.BaseSerializer.extend({ - include: ['wordSmith'] - }) - }); - - let fineComments = this.schema.fineComments.all(); - let result = registry.serialize(fineComments); - - assert.deepEqual(result, { - fineComments: [ - { id: '1', text: 'pwned', blogPostId: '1' } - ], - blogPosts: [ - { id: '1', title: 'Lorem', wordSmithId: '1' } - ], - wordSmiths: [ - { id: '1', name: 'Link' } - ] - }); -}); - -test(`it skips an empty belongs-to relationship`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: this.BaseSerializer, - foo: this.BaseSerializer.extend({ - include: ['bar'] - }) - }); - - let foo1 = this.schema.foos.create({ name: 'test foo' }); - let result = registry.serialize(foo1); - - assert.deepEqual(result, { - foo: - { id: '1', name: 'test foo', barId: null } - }); -}); diff --git a/tests/integration/serializers/base/associations/sideloading-model-test.js b/tests/integration/serializers/base/associations/sideloading-model-test.js deleted file mode 100644 index 8496f47a6..000000000 --- a/tests/integration/serializers/base/associations/sideloading-model-test.js +++ /dev/null @@ -1,231 +0,0 @@ -import Schema from 'ember-cli-mirage/orm/schema'; -import { Model, hasMany, belongsTo } from 'ember-cli-mirage'; -import Db from 'ember-cli-mirage/db'; -import Serializer from 'ember-cli-mirage/serializer'; -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; -import schemaHelper from '../../schema-helper'; -import { module, test } from 'qunit'; - -module('Integration | Serializers | Base | Associations | Sideloading Models', { - beforeEach() { - this.schema = schemaHelper.setup(); - - let wordSmith = this.schema.wordSmiths.create({ name: 'Link' }); - let blogPost = wordSmith.createBlogPost({ title: 'Lorem' }); - blogPost.createFineComment({ text: 'pwned' }); - - wordSmith.createBlogPost({ title: 'Ipsum' }); - - this.schema.wordSmiths.create({ name: 'Zelda' }); - - this.BaseSerializer = Serializer.extend({ - embed: false - }); - }, - - afterEach() { - this.schema.db.emptyData(); - } -}); - -test(`it throws an error if embed is false and root is false`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - wordSmith: this.BaseSerializer.extend({ - root: false, - include: ['blogPosts'] - }) - }); - - let link = this.schema.wordSmiths.find(1); - assert.throws(function() { - registry.serialize(link); - }, /disables the root/); - -}); - -test(`it can sideload a model with a has-many relationship`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: this.BaseSerializer, - wordSmith: this.BaseSerializer.extend({ - include: ['blogPosts'] - }) - }); - - let link = this.schema.wordSmiths.find(1); - let result = registry.serialize(link); - - assert.deepEqual(result, { - wordSmith: { - id: '1', - name: 'Link', - blogPostIds: ['1', '2'] - }, - blogPosts: [ - { id: '1', title: 'Lorem', wordSmithId: '1' }, - { id: '2', title: 'Ipsum', wordSmithId: '1' } - ] - }); -}); - -test(`it can sideload a named has-many association`, function(assert) { - let schema = new Schema(new Db(), { - wordSmith: Model.extend({ - posts: hasMany('blog-post') - }), - blogPost: Model - }); - let link = schema.wordSmiths.create({ name: 'Link' }); - link.createPost({ title: 'Lorem' }); - let registry = new SerializerRegistry(schema, { - application: this.BaseSerializer, - wordSmith: this.BaseSerializer.extend({ - include: ['posts'] - }) - }); - - let result = registry.serialize(link); - - assert.deepEqual(result, { - wordSmith: { - id: '1', - name: 'Link', - postIds: ['1'] - }, - blogPosts: [ - { id: '1', title: 'Lorem', wordSmithId: '1' } - ] - }); -}); - -test(`it can sideload a model with a chain of has-many relationships`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: this.BaseSerializer, - wordSmith: this.BaseSerializer.extend({ - include: ['blogPosts'] - }), - blogPost: this.BaseSerializer.extend({ - include: ['fineComments'] - }) - }); - - let link = this.schema.wordSmiths.find(1); - let result = registry.serialize(link); - - assert.deepEqual(result, { - wordSmith: { - id: '1', - name: 'Link', - blogPostIds: ['1', '2'] - }, - blogPosts: [ - { id: '1', title: 'Lorem', wordSmithId: '1', fineCommentIds: ['1'] }, - { id: '2', title: 'Ipsum', wordSmithId: '1', fineCommentIds: [] } - ], - fineComments: [ - { id: '1', text: 'pwned', blogPostId: '1' } - ] - }); -}); - -test(`it avoids circularity when serializing a model`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: this.BaseSerializer, - wordSmith: this.BaseSerializer.extend({ - include: ['blogPosts'] - }), - blogPost: this.BaseSerializer.extend({ - include: ['wordSmith'] - }) - }); - - let link = this.schema.wordSmiths.find(1); - let result = registry.serialize(link); - - assert.deepEqual(result, { - wordSmith: { - id: '1', - name: 'Link', - blogPostIds: ['1', '2'] - }, - blogPosts: [ - { id: '1', title: 'Lorem', wordSmithId: '1' }, - { id: '2', title: 'Ipsum', wordSmithId: '1' } - ] - }); -}); - -test(`it can sideload a model with a belongs-to relationship`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: this.BaseSerializer, - blogPost: this.BaseSerializer.extend({ - include: ['wordSmith'] - }) - }); - - let blogPost = this.schema.blogPosts.find(1); - let result = registry.serialize(blogPost); - - assert.deepEqual(result, { - blogPost: { - id: '1', title: 'Lorem', wordSmithId: '1' - }, - wordSmiths: [ - { id: '1', name: 'Link' } - ] - }); -}); - -test(`it can sideload a model with a named belongs-to relationship`, function(assert) { - let schema = new Schema(new Db(), { - wordSmith: Model, - blogPost: Model.extend({ - author: belongsTo('word-smith') - }) - }); - let post = schema.blogPosts.create({ title: 'Lorem' }); - post.createAuthor({ name: 'Link' }); - let registry = new SerializerRegistry(schema, { - application: this.BaseSerializer, - blogPost: this.BaseSerializer.extend({ - include: ['author'] - }) - }); - - let result = registry.serialize(post); - - assert.deepEqual(result, { - blogPost: { - id: '1', title: 'Lorem', authorId: '1' - }, - wordSmiths: [ - { id: '1', name: 'Link' } - ] - }); -}); - -test(`it can sideload a model with a chain of belongs-to relationships`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: this.BaseSerializer, - fineComment: this.BaseSerializer.extend({ - include: ['blogPost'] - }), - blogPost: this.BaseSerializer.extend({ - include: ['wordSmith'] - }) - }); - - let fineComment = this.schema.fineComments.find(1); - let result = registry.serialize(fineComment); - - assert.deepEqual(result, { - fineComment: { - id: '1', text: 'pwned', blogPostId: '1' - }, - blogPosts: [ - { id: '1', title: 'Lorem', wordSmithId: '1' } - ], - wordSmiths: [ - { id: '1', name: 'Link' } - ] - }); -}); diff --git a/tests/integration/serializers/base/assorted-collections-test.js b/tests/integration/serializers/base/assorted-collections-test.js deleted file mode 100644 index ffb101acb..000000000 --- a/tests/integration/serializers/base/assorted-collections-test.js +++ /dev/null @@ -1,43 +0,0 @@ -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; -import Serializer from 'ember-cli-mirage/serializer'; -import schemaHelper from '../schema-helper'; -import {module, test} from 'qunit'; - -module('Integration | Serializers | Base | Assorted Collections', { - beforeEach() { - this.schema = schemaHelper.setup(); - this.registry = new SerializerRegistry(this.schema, { - greatPhoto: Serializer.extend({ - attrs: ['id', 'title'] - }) - }); - this.wordSmiths = [ - { id: '1', name: 'Link' }, - { id: '2', name: 'Zelda' }, - { id: '3', name: 'Epona' } - ]; - this.greatPhotos = [ - { id: '1', title: 'Amazing', location: 'Hyrule' }, - { id: '2', title: 'greatPhoto', location: 'Goron City' } - ]; - this.schema.db.loadData({ - wordSmiths: this.wordSmiths, - greatPhotos: this.greatPhotos - }); - }, - afterEach() { - this.schema.db.emptyData(); - } -}); - -test(`an array of assorted collections can be serialized`, function(assert) { - let result = this.registry.serialize([this.schema.wordSmiths.all(), this.schema.greatPhotos.all()]); - - assert.deepEqual(result, { - wordSmiths: this.wordSmiths, - greatPhotos: this.greatPhotos.map((attrs) => { - delete attrs.location; - return attrs; - }) - }); -}); diff --git a/tests/integration/serializers/base/attribute-key-formatting-test.js b/tests/integration/serializers/base/attribute-key-formatting-test.js deleted file mode 100644 index 863ebc029..000000000 --- a/tests/integration/serializers/base/attribute-key-formatting-test.js +++ /dev/null @@ -1,56 +0,0 @@ -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; -import Serializer from 'ember-cli-mirage/serializer'; -import schemaHelper from '../schema-helper'; -import { camelize } from 'ember-cli-mirage/utils/inflector'; -import {module, test} from 'qunit'; - -module('Integration | Serializers | Base | Attribute Key Formatting', { - beforeEach() { - this.schema = schemaHelper.setup(); - this.registry = new SerializerRegistry(this.schema, { - wordSmith: Serializer.extend({ - keyForAttribute(key) { - return camelize(key); - } - }) - }); - }, - afterEach() { - this.schema.db.emptyData(); - } -}); - -test(`keyForAttribute formats the attributes of a model`, function(assert) { - let wordSmith = this.schema.wordSmiths.create({ - id: 1, - 'first-name': 'Link', - 'last-name': 'Jackson', - age: 323 - }); - - let result = this.registry.serialize(wordSmith); - - assert.deepEqual(result, { - wordSmith: { - id: '1', - firstName: 'Link', - lastName: 'Jackson', - age: 323 - } - }); -}); - -test(`keyForAttribute also formats the models in a collections`, function(assert) { - this.schema.wordSmiths.create({ id: 1, 'first-name': 'Link', 'last-name': 'Jackson' }); - this.schema.wordSmiths.create({ id: 2, 'first-name': 'Zelda', 'last-name': 'Brown' }); - let wordSmiths = this.schema.wordSmiths.all(); - - let result = this.registry.serialize(wordSmiths); - - assert.deepEqual(result, { - wordSmiths: [ - { id: '1', firstName: 'Link', lastName: 'Jackson' }, - { id: '2', firstName: 'Zelda', lastName: 'Brown' } - ] - }); -}); diff --git a/tests/integration/serializers/base/attrs-test.js b/tests/integration/serializers/base/attrs-test.js deleted file mode 100644 index 9d52e39bb..000000000 --- a/tests/integration/serializers/base/attrs-test.js +++ /dev/null @@ -1,50 +0,0 @@ -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; -import Serializer from 'ember-cli-mirage/serializer'; -import schemaHelper from '../schema-helper'; -import { module, test } from 'qunit'; - -module('Integration | Serializers | Base | Attrs List', { - beforeEach() { - this.schema = schemaHelper.setup(); - this.registry = new SerializerRegistry(this.schema, { - wordSmith: Serializer.extend({ - attrs: ['id', 'name'] - }) - }); - }, - afterEach() { - this.schema.db.emptyData(); - } -}); - -test(`it returns only the whitelisted attrs when serializing a model`, function(assert) { - let wordSmith = this.schema.wordSmiths.create({ - id: 1, - name: 'Link', - age: 123 - }); - - let result = this.registry.serialize(wordSmith); - assert.deepEqual(result, { - wordSmith: { - id: '1', - name: 'Link' - } - }); -}); - -test(`it returns only the whitelisted attrs when serializing a collection`, function(assert) { - let { schema } = this; - schema.wordSmiths.create({ id: 1, name: 'Link', age: 123 }); - schema.wordSmiths.create({ id: 2, name: 'Zelda', age: 456 }); - - let collection = this.schema.wordSmiths.all(); - let result = this.registry.serialize(collection); - - assert.deepEqual(result, { - wordSmiths: [ - { id: '1', name: 'Link' }, - { id: '2', name: 'Zelda' } - ] - }); -}); diff --git a/tests/integration/serializers/base/basic-test.js b/tests/integration/serializers/base/basic-test.js deleted file mode 100644 index dfeb3e255..000000000 --- a/tests/integration/serializers/base/basic-test.js +++ /dev/null @@ -1,86 +0,0 @@ -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; -import schemaHelper from '../schema-helper'; -import { module, test } from 'qunit'; - -import _uniqBy from 'lodash/uniqBy'; - -module('Integration | Serializers | Base | Basic', { - beforeEach() { - this.schema = schemaHelper.setup(); - this.registry = new SerializerRegistry(this.schema); - }, - afterEach() { - this.schema.db.emptyData(); - } -}); - -test('it returns objects unaffected', function(assert) { - let result = this.registry.serialize({ oh: 'hai' }); - - assert.deepEqual(result, { oh: 'hai' }); -}); - -test('it returns arrays unaffected', function(assert) { - let data = [{ id: '1', name: 'Link' }, { id: '2', name: 'Zelda' }]; - let result = this.registry.serialize(data); - - assert.deepEqual(result, data); -}); - -test('it returns empty arrays unaffected', function(assert) { - let result = this.registry.serialize([]); - - assert.deepEqual(result, []); -}); - -test(`it serializes a model by returning its attrs under a root`, function(assert) { - let wordSmith = this.schema.wordSmiths.create({ - id: 1, - name: 'Link' - }); - let result = this.registry.serialize(wordSmith); - - assert.deepEqual(result, { - wordSmith: { - id: '1', - name: 'Link' - } - }); -}); - -test(`it serializes a collection of models by returning an array of their attrs under a pluralized root`, function(assert) { - this.schema.wordSmiths.create({ id: 1, name: 'Link' }); - this.schema.wordSmiths.create({ id: 2, name: 'Zelda' }); - - let wordSmiths = this.schema.wordSmiths.all(); - - let result = this.registry.serialize(wordSmiths); - - assert.deepEqual(result, { - wordSmiths: [ - { id: '1', name: 'Link' }, - { id: '2', name: 'Zelda' } - ] - }); -}); - -test(`it can serialize an empty collection`, function(assert) { - let wordSmiths = this.schema.wordSmiths.all(); - let result = this.registry.serialize(wordSmiths); - - assert.deepEqual(result, { - wordSmiths: [] - }); -}); - -test('it returns POJAs of models unaffected', function(assert) { - this.schema.wordSmiths.create({ name: 'Sam' }); - this.schema.wordSmiths.create({ name: 'Sam' }); - this.schema.wordSmiths.create({ name: 'Ganondorf' }); - - let wordSmiths = this.schema.wordSmiths.all().models; - let uniqueNames = _uniqBy(wordSmiths, 'name'); - let result = this.registry.serialize(uniqueNames); - - assert.deepEqual(result, uniqueNames); -}); diff --git a/tests/integration/serializers/base/full-request-test.js b/tests/integration/serializers/base/full-request-test.js deleted file mode 100644 index 773790297..000000000 --- a/tests/integration/serializers/base/full-request-test.js +++ /dev/null @@ -1,163 +0,0 @@ -import Mirage from 'ember-cli-mirage'; -import Server from 'ember-cli-mirage/server'; -import Model from 'ember-cli-mirage/orm/model'; -import Serializer from 'ember-cli-mirage/serializer'; -import {module, test} from 'qunit'; - -module('Integration | Serializers | Base | Full Request', { - beforeEach() { - this.server = new Server({ - environment: 'development', - models: { - author: Model.extend({ - posts: Mirage.hasMany() - }), - post: Model.extend({ - author: Mirage.belongsTo(), - comments: Mirage.hasMany() - }), - comment: Model.extend({ - post: Mirage.belongsTo() - }) - }, - serializers: { - application: Serializer.extend({ - embed: true, - root: false - }), - author: Serializer.extend({ - embed: true, - attrs: ['id', 'first'], - include: ['posts'] - }), - comment: Serializer.extend({ - embed: true, - root: false, - include(request) { - return request.queryParams.include_post ? ['post'] : []; - } - }) - } - }); - this.server.timing = 0; - this.server.logging = false; - }, - afterEach() { - this.server.shutdown(); - } -}); - -test('the appropriate serializer is used', function(assert) { - assert.expect(1); - let done = assert.async(); - let author = this.server.schema.authors.create({ - first: 'Link', - last: 'of Hyrule', - age: 323 - }); - author.createPost({ title: 'Lorem ipsum' }); - - this.server.get('/authors/:id', function(schema, request) { - let { id } = request.params; - - return schema.authors.find(id); - }); - - $.ajax({ - method: 'GET', - url: '/authors/1' - }).done(function(res) { - assert.deepEqual(res, { - author: { - id: '1', - first: 'Link', - posts: [ - { id: '1', title: 'Lorem ipsum' } - ] - } - }); - done(); - }); -}); - -test('components decoded', function(assert) { - assert.expect(1); - let done = assert.async(); - - this.server.get('/authors/:id', function(schema, request) { - let { id } = request.params; - - return { data: { id } }; - }); - - $.ajax({ - method: 'GET', - url: '/authors/%3A1' - }).done(function(res) { - assert.deepEqual(res, { - data: { id: ':1' } - }); - done(); - }); -}); - -test('a response falls back to the application serializer, if it exists', function(assert) { - assert.expect(1); - let done = assert.async(); - this.server.schema.posts.create({ - title: 'Lorem', - date: '20001010' - }); - - this.server.get('/posts/:id', function(schema, request) { - let { id } = request.params; - - return schema.posts.find(id); - }); - - $.ajax({ - method: 'GET', - url: '/posts/1' - }).done(function(res) { - assert.deepEqual(res, { - id: '1', - title: 'Lorem', - date: '20001010', - authorId: null - }); - done(); - }); -}); - -test('serializer.include is invoked when it is a function', function(assert) { - assert.expect(1); - let done = assert.async(); - let post = this.server.schema.posts.create({ - title: 'Lorem', - date: '20001010' - }); - post.createComment({ - description: 'Lorem is the best' - }); - - this.server.get('/comments/:id', function(schema, request) { - let { id } = request.params; - return schema.comments.find(id); - }); - - $.ajax({ - method: 'GET', - url: '/comments/1?include_post=true' - }).done(function(res) { - assert.deepEqual(res, { - id: '1', - description: 'Lorem is the best', - post: { - id: '1', - title: 'Lorem', - date: '20001010' - } - }); - done(); - }); -}); diff --git a/tests/integration/serializers/base/override-serialize-test.js b/tests/integration/serializers/base/override-serialize-test.js deleted file mode 100644 index 349bae98d..000000000 --- a/tests/integration/serializers/base/override-serialize-test.js +++ /dev/null @@ -1,52 +0,0 @@ -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; -import Serializer from 'ember-cli-mirage/serializer'; -import schemaHelper from '../schema-helper'; -import { module, test } from 'qunit'; - -module('Integration | Serializers | Base | Overriding Serialize', { - beforeEach() { - this.schema = schemaHelper.setup(); - }, - afterEach() { - this.schema.db.emptyData(); - } -}); - -test(`it can use a completely custom serialize function`, function(assert) { - this.registry = new SerializerRegistry(this.schema, { - wordSmith: Serializer.extend({ - serialize() { - return 'blah'; - } - }) - }); - - let wordSmith = this.schema.wordSmiths.create({ - id: 1, - title: 'Link' - }); - - let result = this.registry.serialize(wordSmith); - - assert.deepEqual(result, 'blah'); -}); - -test(`it can access the request in a custom serialize function`, function(assert) { - this.registry = new SerializerRegistry(this.schema, { - wordSmith: Serializer.extend({ - serialize(response, request) { - return request.queryParams.foo || 'blah'; - } - }) - }); - - let wordSmith = this.schema.wordSmiths.create({ - id: 1, - title: 'Link' - }); - - let request = { url: '/word-smiths/1?foo=bar', params: { id: '1' }, queryParams: { foo: 'bar' } }; - let result = this.registry.serialize(wordSmith, request); - - assert.deepEqual(result, 'bar'); -}); diff --git a/tests/integration/serializers/base/root-test.js b/tests/integration/serializers/base/root-test.js deleted file mode 100644 index 604a89834..000000000 --- a/tests/integration/serializers/base/root-test.js +++ /dev/null @@ -1,52 +0,0 @@ -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; -import Serializer from 'ember-cli-mirage/serializer'; -import schemaHelper from '../schema-helper'; -import { module, test } from 'qunit'; - -module('Integration | Serializers | Base | Root', { - beforeEach() { - this.schema = schemaHelper.setup(); - this.registry = new SerializerRegistry(this.schema, { - wordSmith: Serializer.extend({ - embed: true, - root: false - }) - }); - }, - afterEach() { - this.schema.db.emptyData(); - } -}); - -test(`if root is false, it serializes a model by returning its attrs`, function(assert) { - let wordSmith = this.schema.wordSmiths.create({ - id: '1', - name: 'Link' - }); - - let result = this.registry.serialize(wordSmith); - assert.deepEqual(result, { - id: '1', - name: 'Link' - }); -}); - -test(`if root is false, it serializes a collection of models by returning an array of their attrs`, function(assert) { - this.schema.wordSmiths.create({ id: 1, name: 'Link' }); - this.schema.wordSmiths.create({ id: 2, name: 'Zelda' }); - let wordSmiths = this.schema.wordSmiths.all(); - - let result = this.registry.serialize(wordSmiths); - - assert.deepEqual(result, [ - { id: '1', name: 'Link' }, - { id: '2', name: 'Zelda' } - ]); -}); - -test(`if root is false, it serializes an empty collection by returning an empty array`, function(assert) { - let emptywordSmithCollection = this.schema.wordSmiths.all(); - let result = this.registry.serialize(emptywordSmithCollection); - - assert.deepEqual(result, []); -}); diff --git a/tests/integration/serializers/base/serialize-array-of-models-test.js b/tests/integration/serializers/base/serialize-array-of-models-test.js deleted file mode 100644 index 4e15c949e..000000000 --- a/tests/integration/serializers/base/serialize-array-of-models-test.js +++ /dev/null @@ -1,30 +0,0 @@ -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; -import Serializer from 'ember-cli-mirage/serializer'; -import schemaHelper from '../schema-helper'; -import { module, test } from 'qunit'; - -module('Integration | Serializers | Base | Array of Models', { - beforeEach() { - this.schema = schemaHelper.setup(); - this.schema.wordSmiths.create({ id: 1, title: 'Link' }); - }, - afterEach() { - this.schema.db.emptyData(); - } -}); - -test(`it applies correct serializer when the response is an array of models`, function(assert) { - assert.expect(1); - - let wordSmiths = this.schema.wordSmiths.all().filter(() => true); - let registry = new SerializerRegistry(this.schema, { - wordSmith: Serializer.extend({ - serialize() { - assert.ok('serializer ran'); - return {}; - } - }) - }); - - registry.serialize(wordSmiths); -}); diff --git a/tests/integration/serializers/base/serialize-ids-test.js b/tests/integration/serializers/base/serialize-ids-test.js deleted file mode 100644 index 45d392cd1..000000000 --- a/tests/integration/serializers/base/serialize-ids-test.js +++ /dev/null @@ -1,87 +0,0 @@ -import { module, test } from 'qunit'; -import Schema from 'ember-cli-mirage/orm/schema'; -import Db from 'ember-cli-mirage/db'; -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; -import { Serializer, Model, hasMany } from 'ember-cli-mirage'; - -module('Integration | Serializers | Base | Serialize ids', { - beforeEach() { - this.schema = new Schema(new Db(), { - wordSmith: Model.extend({ - blogPosts: hasMany(), - specialPosts: hasMany('blog-post', { inverse: 'specialAuthor' }) - }), - blogPost: Model - }); - }, - afterEach() { - this.schema.db.emptyData(); - } -}); - -test(`if serializeIds is 'include' it serializes ids of hasMany associations that are included`, function(assert) { - let ApplicationSerializer = Serializer.extend({ - serializeIds: 'included' - }); - let registry = new SerializerRegistry(this.schema, { - application: ApplicationSerializer, - wordSmith: ApplicationSerializer.extend({ - include: ['blogPosts'] - }) - }); - - let wordSmith = this.schema.wordSmiths.create({ - id: 1, - name: 'Link' - }); - wordSmith.createBlogPost(); - wordSmith.createBlogPost(); - wordSmith.createSpecialPost(); - let result = registry.serialize(wordSmith); - - assert.deepEqual(result, { - wordSmith: { - id: '1', - name: 'Link', - blogPostIds: ['1', '2'] - }, - blogPosts: [ - { - id: '1', - specialAuthorId: null, - wordSmithId: '1' - }, - { - id: '2', - specialAuthorId: null, - wordSmithId: '1' - } - ] - }); -}); - -test(`if serializeIds is 'always' it serializes ids of all hasMany associations`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: Serializer.extend({ - serializeIds: 'always' - }) - }); - - let wordSmith = this.schema.wordSmiths.create({ - id: 1, - name: 'Link' - }); - wordSmith.createBlogPost(); - wordSmith.createBlogPost(); - wordSmith.createSpecialPost(); - let result = registry.serialize(wordSmith); - - assert.deepEqual(result, { - wordSmith: { - id: '1', - name: 'Link', - blogPostIds: ['1', '2'], - specialPostIds: ['3'] - } - }); -}); diff --git a/tests/integration/serializers/json-api-serializer/associations/collection-test.js b/tests/integration/serializers/json-api-serializer/associations/collection-test.js deleted file mode 100644 index b7414c8bb..000000000 --- a/tests/integration/serializers/json-api-serializer/associations/collection-test.js +++ /dev/null @@ -1,468 +0,0 @@ -import Schema from 'ember-cli-mirage/orm/schema'; -import Db from 'ember-cli-mirage/db'; -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; -import { Model, hasMany, belongsTo, JSONAPISerializer } from 'ember-cli-mirage'; -import { module, test } from 'qunit'; - -module('Integration | Serializers | JSON API Serializer | Associations | Collection', { - beforeEach() { - this.schema = new Schema(new Db(), { - wordSmith: Model.extend({ - posts: hasMany('blogPost', { inverse: 'author' }) - }), - blogPost: Model.extend({ - author: belongsTo('wordSmith', { inverse: 'posts' }), - comments: hasMany('fineComment', { inverse: 'post' }) - }), - fineComment: Model.extend({ - post: belongsTo('blogPost') - }) - }); - } -}); - -test(`it includes all relationships for a collection, regardless of being included`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer - }); - this.schema.wordSmiths.create({ firstName: 'Link', age: 123 }); - this.schema.wordSmiths.create({ firstName: 'Zelda', age: 456 }); - - let collection = this.schema.wordSmiths.all(); - let result = registry.serialize(collection); - - assert.deepEqual(result, { - data: [{ - type: 'word-smiths', - id: '1', - attributes: { - 'first-name': 'Link', - age: 123 - }, - relationships: { - 'posts': { - data: [] - } - } - }, { - type: 'word-smiths', - id: '2', - attributes: { - 'first-name': 'Zelda', - age: 456 - }, - relationships: { - 'posts': { - data: [] - } - } - }] - }); -}); - -test(`it can serialize a collection with a has-many relationship`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer, - wordSmith: JSONAPISerializer.extend({ - include: ['posts'] - }) - }); - let link = this.schema.wordSmiths.create({ firstName: 'Link' }); - link.createPost({ title: 'Lorem' }); - link.createPost({ title: 'Ipsum' }); - this.schema.wordSmiths.create({ firstName: 'Zelda' }); - - let collection = this.schema.wordSmiths.all(); - let result = registry.serialize(collection); - - assert.deepEqual(result, { - data: [ - { - type: 'word-smiths', - id: '1', - attributes: { - 'first-name': 'Link' - }, - relationships: { - 'posts': { - data: [ - { type: 'blog-posts', id: '1' }, - { type: 'blog-posts', id: '2' } - ] - } - } - }, - { - type: 'word-smiths', - id: '2', - attributes: { - 'first-name': 'Zelda' - }, - relationships: { - 'posts': { - data: [] - } - } - } - ], - included: [ - { - type: 'blog-posts', - id: '1', - attributes: { - title: 'Lorem' - }, - relationships: { - 'comments': { - data: [] - }, - 'author': { - data: { type: 'word-smiths', id: '1' } - } - } - }, - { - type: 'blog-posts', - id: '2', - attributes: { - title: 'Ipsum' - }, - relationships: { - 'comments': { - data: [] - }, - 'author': { - data: { type: 'word-smiths', id: '1' } - } - } - } - ] - }); -}); - -test(`it can serialize a collection with a chain of has-many relationships`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer, - wordSmith: JSONAPISerializer.extend({ - include: ['posts'] - }), - blogPost: JSONAPISerializer.extend({ - include: ['comments'] - }) - }); - - let link = this.schema.wordSmiths.create({ firstName: 'Link' }); - let lorem = link.createPost({ title: 'Lorem' }); - lorem.createComment({ text: 'pwned' }); - link.createPost({ title: 'Ipsum' }); - this.schema.wordSmiths.create({ firstName: 'Zelda' }); - - let collection = this.schema.wordSmiths.all(); - let result = registry.serialize(collection); - - assert.deepEqual(result, { - data: [ - { - type: 'word-smiths', - id: '1', - attributes: { - 'first-name': 'Link' - }, - relationships: { - 'posts': { - data: [ - { type: 'blog-posts', id: '1' }, - { type: 'blog-posts', id: '2' } - ] - } - } - }, - { - type: 'word-smiths', - id: '2', - attributes: { - 'first-name': 'Zelda' - }, - relationships: { - 'posts': { - data: [] - } - } - } - ], - included: [ - { - type: 'blog-posts', - id: '1', - attributes: { - title: 'Lorem' - }, - relationships: { - 'comments': { - data: [ - { type: 'fine-comments', id: '1' } - ] - }, - 'author': { - data: { type: 'word-smiths', id: '1' } - } - } - }, - { - type: 'fine-comments', - id: '1', - attributes: { - text: 'pwned' - }, - relationships: { - 'post': { - data: { type: 'blog-posts', id: '1' } - } - } - }, - { - type: 'blog-posts', - id: '2', - attributes: { - title: 'Ipsum' - }, - relationships: { - 'comments': { - data: [] - }, - 'author': { - data: { type: 'word-smiths', id: '1' } - } - } - } - ] - }); -}); - -test(`it can serialize a collection with a belongs-to relationship`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer, - blogPost: JSONAPISerializer.extend({ - include: ['author'] - }) - }); - - let link = this.schema.wordSmiths.create({ firstName: 'Link' }); - let post = link.createPost({ title: 'Lorem' }); - post.createComment(); - link.createPost({ title: 'Ipsum' }); - this.schema.wordSmiths.create({ firstName: 'Zelda' }); - - let blogPosts = this.schema.blogPosts.all(); - let result = registry.serialize(blogPosts); - - assert.deepEqual(result, { - data: [ - { - type: 'blog-posts', - id: '1', - attributes: { - title: 'Lorem' - }, - relationships: { - 'comments': { - data: [ - { type: 'fine-comments', id: '1' } - ] - }, - 'author': { - data: { type: 'word-smiths', id: '1' } - } - } - }, - { - type: 'blog-posts', - id: '2', - attributes: { - title: 'Ipsum' - }, - relationships: { - 'comments': { - data: [] - }, - 'author': { - data: { type: 'word-smiths', id: '1' } - } - } - } - ], - included: [ - { - type: 'word-smiths', - id: '1', - attributes: { - 'first-name': 'Link' - }, - relationships: { - 'posts': { - data: [ - { type: 'blog-posts', id: '1' }, - { type: 'blog-posts', id: '2' } - ] - } - } - } - ] - }); -}); - -test(`it can serialize a collection with a chain of belongs-to relationships`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer, - fineComment: JSONAPISerializer.extend({ - include: ['post'] - }), - blogPost: JSONAPISerializer.extend({ - include: ['author'] - }) - }); - - let link = this.schema.wordSmiths.create({ firstName: 'Link' }); - let post = link.createPost({ title: 'Lorem' }); - post.createComment({ text: 'pwned' }); - link.createPost({ title: 'Ipsum' }); - this.schema.wordSmiths.create({ firstName: 'Zelda' }); - - let fineComments = this.schema.fineComments.all(); - let result = registry.serialize(fineComments); - - assert.deepEqual(result, { - data: [ - { - type: 'fine-comments', - id: '1', - attributes: { - text: 'pwned' - }, - relationships: { - 'post': { - data: { type: 'blog-posts', id: '1' } - } - } - } - ], - included: [ - { - type: 'blog-posts', - id: '1', - attributes: { - title: 'Lorem' - }, - relationships: { - 'comments': { - data: [ - { - id: '1', - type: 'fine-comments' - } - ] - }, - 'author': { - data: { type: 'word-smiths', id: '1' } - } - } - }, - { - type: 'word-smiths', - id: '1', - attributes: { - 'first-name': 'Link' - }, - relationships: { - 'posts': { - data: [ - { - id: '1', - type: 'blog-posts' - }, - { - id: '2', - type: 'blog-posts' - } - ] - } - } - } - ] - }); -}); - -test(`it can serialize a collection of models that have both belongs-to and has-many relationships`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer, - blogPost: JSONAPISerializer.extend({ - include: ['author', 'comments'] - }) - }); - - let link = this.schema.wordSmiths.create({ firstName: 'Link' }); - let post = link.createPost({ title: 'Lorem' }); - post.createComment({ text: 'pwned' }); - link.createPost({ title: 'Ipsum' }); - this.schema.wordSmiths.create({ firstName: 'Zelda' }); - - let blogPost = this.schema.blogPosts.find(1); - let result = registry.serialize(blogPost); - - assert.deepEqual(result, { - data: { - type: 'blog-posts', - id: '1', - attributes: { - title: 'Lorem' - }, - relationships: { - 'author': { - data: { type: 'word-smiths', id: '1' } - }, - 'comments': { - data: [{ type: 'fine-comments', id: '1' }] - } - } - }, - included: [ - { - type: 'word-smiths', - id: '1', - attributes: { - 'first-name': 'Link' - }, - relationships: { - 'posts': { - data: [ - { - id: '1', - type: 'blog-posts' - }, - { - id: '2', - type: 'blog-posts' - } - ] - } - } - }, - { - type: 'fine-comments', - id: '1', - attributes: { - 'text': 'pwned' - }, - relationships: { - 'post': { - data: { - id: '1', - type: 'blog-posts' - } - } - } - } - ] - }); - -}); diff --git a/tests/integration/serializers/json-api-serializer/associations/includes-test.js b/tests/integration/serializers/json-api-serializer/associations/includes-test.js deleted file mode 100644 index e6c2b9aa9..000000000 --- a/tests/integration/serializers/json-api-serializer/associations/includes-test.js +++ /dev/null @@ -1,538 +0,0 @@ -import Schema from 'ember-cli-mirage/orm/schema'; -import Db from 'ember-cli-mirage/db'; -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; -import { JSONAPISerializer, Model, hasMany, belongsTo } from 'ember-cli-mirage'; -import { module, test } from 'qunit'; - -module('Integration | Serializers | JSON API Serializer | Associations | Includes', { - beforeEach() { - this.schema = new Schema(new Db(), { - wordSmith: Model.extend({ - blogPosts: hasMany() - }), - - blogPost: Model.extend({ - wordSmith: belongsTo(), - fineComments: hasMany() - }), - - fineComment: Model.extend({ - blogPost: belongsTo(), - category: belongsTo() - }), - - category: Model.extend({ - labels: hasMany() - }), - - label: Model.extend({ - - }) - }); - } -}); - -test('includes get serialized with correct serializer', function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer, - blogPost: JSONAPISerializer.extend({ - attrs: ['title'], - include: ['wordSmith'] - }), - wordSmith: JSONAPISerializer.extend({ - attrs: ['firstName'] - }) - }); - - let post = this.schema.blogPosts.create({ title: 'We love Mirage!' }); - post.createWordSmith({ firstName: 'Sam' }); - - let result = registry.serialize(post); - - assert.propEqual(result, { - data: { - type: 'blog-posts', - id: '1', - attributes: { - 'title': 'We love Mirage!' - }, - relationships: { - 'fine-comments': { - 'data': [] - }, - 'word-smith': { - data: { type: 'word-smiths', id: '1' } - } - } - }, - included: [ - { - type: 'word-smiths', - id: '1', - attributes: { - 'first-name': 'Sam' - }, - relationships: { - 'blog-posts': { - data: [ - { type: 'blog-posts', id: '1' } - ] - } - } - } - ] - }); -}); - -test('query param includes work when serializing a model', function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer - }); - - let post = this.schema.blogPosts.create(); - post.createWordSmith(); - post.createFineComment(); - post.createFineComment(); - - let request = { - queryParams: { - include: 'word-smith,fine-comments' - } - }; - - let result = registry.serialize(post, request); - - assert.propEqual(result, { - data: { - type: 'blog-posts', - id: '1', - attributes: {}, - relationships: { - 'word-smith': { - data: { type: 'word-smiths', id: '1' } - }, - 'fine-comments': { - data: [ - { type: 'fine-comments', id: '1' }, - { type: 'fine-comments', id: '2' } - ] - } - } - }, - included: [ - { - type: 'word-smiths', - id: '1', - attributes: {}, - relationships: { - 'blog-posts': { - data: [ - { type: 'blog-posts', id: '1' } - ] - } - } - }, - { - type: 'fine-comments', - id: '1', - attributes: {}, - relationships: { - 'blog-post': { - data: { type: 'blog-posts', id: '1' } - }, - category: { data: null } - } - }, - { - type: 'fine-comments', - id: '2', - attributes: {}, - relationships: { - 'blog-post': { - data: { type: 'blog-posts', id: '1' } - }, - category: { data: null } - } - } - ] - }); -}); - -test('query param includes work when serializing a collection', function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer - }); - - let post1 = this.schema.blogPosts.create(); - post1.createWordSmith(); - post1.createFineComment(); - post1.createFineComment(); - this.schema.blogPosts.create(); - - let request = { - queryParams: { - include: 'word-smith,fine-comments' - } - }; - - let result = registry.serialize(this.schema.blogPosts.all(), request); - - assert.propEqual(result, { - data: [ - { - type: 'blog-posts', - id: '1', - attributes: {}, - relationships: { - 'word-smith': { - data: { type: 'word-smiths', id: '1' } - }, - 'fine-comments': { - data: [ - { type: 'fine-comments', id: '1' }, - { type: 'fine-comments', id: '2' } - ] - } - } - }, - { - type: 'blog-posts', - id: '2', - attributes: {}, - relationships: { - 'word-smith': { - data: null - }, - 'fine-comments': { - data: [] - } - } - } - ], - included: [ - { - type: 'word-smiths', - id: '1', - attributes: {}, - relationships: { - 'blog-posts': { - data: [ - { type: 'blog-posts', id: '1' } - ] - } - } - }, - { - type: 'fine-comments', - id: '1', - attributes: {}, - relationships: { - 'blog-post': { - data: { type: 'blog-posts', id: '1' } - }, - category: { data: null } - } - }, - { - type: 'fine-comments', - id: '2', - attributes: {}, - relationships: { - 'blog-post': { - data: { type: 'blog-posts', id: '1' } - }, - category: { data: null } - } - } - ] - }); -}); - -test('query param includes take precedence over default server includes', function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer, - blogPost: JSONAPISerializer.extend({ - include: ['wordSmith'] - }) - }); - - let post = this.schema.blogPosts.create(); - post.createWordSmith(); - post.createFineComment(); - post.createFineComment(); - - let request = { - queryParams: { - include: 'fine-comments' - } - }; - - let result = registry.serialize(post, request); - - assert.propEqual(result, { - data: { - type: 'blog-posts', - id: '1', - attributes: {}, - relationships: { - 'word-smith': { - data: { type: 'word-smiths', id: '1' } - }, - 'fine-comments': { - data: [ - { type: 'fine-comments', id: '1' }, - { type: 'fine-comments', id: '2' } - ] - } - } - }, - included: [ - { - type: 'fine-comments', - id: '1', - attributes: {}, - relationships: { - 'blog-post': { - data: { type: 'blog-posts', id: '1' } - }, - category: { data: null } - } - }, - { - type: 'fine-comments', - id: '2', - attributes: {}, - relationships: { - 'blog-post': { - data: { type: 'blog-posts', id: '1' } - }, - category: { data: null } - } - } - ] - }); -}); - -test('query param includes support dot-paths when serializing a model', function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer - }); - - this.schema.db.loadData({ - wordSmiths: [ - { id: 1, name: 'Sam' } - ], - blogPosts: [ - { id: 2, wordSmithId: 1, title: 'Lorem Ipsum' } - ], - fineComments: [ - { id: 3, text: 'Foo', blogPostId: 2, categoryId: 10 } - ], - categories: [ - { id: 10, foo: 'bar' } - ], - labels: [ - { id: 20, name: 'Economics', categoryId: 10 } - ] - }); - let request = { - queryParams: { - include: 'wordSmith,fineComments.category.labels' - } - }; - let result = registry.serialize(this.schema.blogPosts.first(), request); - - assert.propEqual(result, { - data: { - type: 'blog-posts', - id: '2', - attributes: { - title: 'Lorem Ipsum' - }, - relationships: { - 'word-smith': { - data: { type: 'word-smiths', id: '1' } - }, - 'fine-comments': { - data: [ - { type: 'fine-comments', id: '3' } - ] - } - } - }, - included: [ - { - type: 'word-smiths', - id: '1', - attributes: { - name: 'Sam' - }, - relationships: { - 'blog-posts': { - data: [ - { type: 'blog-posts', id: '2' } - ] - } - } - }, - { - type: 'fine-comments', - id: '3', - attributes: { - text: 'Foo' - }, - relationships: { - 'blog-post': { - data: { type: 'blog-posts', id: '2' } - }, - 'category': { - data: { type: 'categories', id: '10' } - } - } - }, - { - type: 'categories', - id: '10', - attributes: { - foo: 'bar' - }, - relationships: { - 'labels': { - data: [ - { type: 'labels', id: '20' } - ] - } - } - }, - { - type: 'labels', - id: '20', - attributes: { - name: 'Economics' - } - } - ] - }); -}); - -test('query param includes support dot-paths when serializing a collection', function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer - }); - - this.schema.db.loadData({ - wordSmiths: [ - { id: 1, name: 'Sam' } - ], - blogPosts: [ - { id: 2, wordSmithId: 1, title: 'Lorem Ipsum' }, - { id: 5, wordSmithId: 1, title: 'Dolor' } - ], - fineComments: [ - { id: 3, text: 'Foo', blogPostId: 2, categoryId: 10 } - ], - categories: [ - { id: 10, foo: 'bar' } - ], - labels: [ - { id: 20, name: 'Economics', categoryId: 10 } - ] - }); - let request = { - queryParams: { - include: 'wordSmith,fineComments.category.labels' - } - }; - let result = registry.serialize(this.schema.blogPosts.all(), request); - - assert.propEqual(result, { - data: [ - { - type: 'blog-posts', - id: '2', - attributes: { - title: 'Lorem Ipsum' - }, - relationships: { - 'word-smith': { - data: { type: 'word-smiths', id: '1' } - }, - 'fine-comments': { - data: [ - { type: 'fine-comments', id: '3' } - ] - } - } - }, - { - type: 'blog-posts', - id: '5', - attributes: { - title: 'Dolor' - }, - relationships: { - 'word-smith': { - data: { type: 'word-smiths', id: '1' } - }, - 'fine-comments': { - data: [ - ] - } - } - } - ], - included: [ - { - type: 'word-smiths', - id: '1', - attributes: { - name: 'Sam' - }, - relationships: { - 'blog-posts': { - data: [ - { type: 'blog-posts', id: '2' }, - { type: 'blog-posts', id: '5' } - ] - } - } - }, - { - type: 'fine-comments', - id: '3', - attributes: { - text: 'Foo' - }, - relationships: { - 'blog-post': { - data: { type: 'blog-posts', id: '2' } - }, - 'category': { - data: { type: 'categories', id: '10' } - } - } - }, - { - type: 'categories', - id: '10', - attributes: { - foo: 'bar' - }, - relationships: { - 'labels': { - data: [ - { type: 'labels', id: '20' } - ] - } - } - }, - { - type: 'labels', - id: '20', - attributes: { - name: 'Economics' - } - } - ] - }); -}); diff --git a/tests/integration/serializers/json-api-serializer/associations/key-for-relationship-test.js b/tests/integration/serializers/json-api-serializer/associations/key-for-relationship-test.js deleted file mode 100644 index 79d17d1c7..000000000 --- a/tests/integration/serializers/json-api-serializer/associations/key-for-relationship-test.js +++ /dev/null @@ -1,55 +0,0 @@ -import Schema from 'ember-cli-mirage/orm/schema'; -import Db from 'ember-cli-mirage/db'; -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; -import { Model, hasMany, JSONAPISerializer } from 'ember-cli-mirage'; -import { underscore } from 'ember-cli-mirage/utils/inflector'; -import { module, test } from 'qunit'; - -module('Integration | Serializers | JSON API Serializer | Key for relationship', { - beforeEach() { - this.schema = new Schema(new Db(), { - wordSmith: Model.extend({ - blogPosts: hasMany() - }), - blogPost: Model - }); - } -}); - -test(`keyForRelationship works`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer.extend({ - keyForRelationship(key) { - return underscore(key); - } - }) - }); - let wordSmith = this.schema.wordSmiths.create({ - id: 1, - firstName: 'Link', - lastName: 'Jackson', - age: 323 - }); - wordSmith.createBlogPost({ title: 'Lorem ipsum' }); - - let result = registry.serialize(wordSmith); - - assert.deepEqual(result, { - data: { - type: 'word-smiths', - id: '1', - attributes: { - age: 323, - 'first-name': 'Link', - 'last-name': 'Jackson' - }, - relationships: { - 'blog_posts': { - data: [ - { id: '1', type: 'blog-posts' } - ] - } - } - } - }); -}); diff --git a/tests/integration/serializers/json-api-serializer/associations/links-test.js b/tests/integration/serializers/json-api-serializer/associations/links-test.js deleted file mode 100644 index c53c7ad5b..000000000 --- a/tests/integration/serializers/json-api-serializer/associations/links-test.js +++ /dev/null @@ -1,74 +0,0 @@ -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; -import { Model, hasMany, belongsTo, JSONAPISerializer } from 'ember-cli-mirage'; -import { module, test } from 'qunit'; -import Db from 'ember-cli-mirage/db'; -import Schema from 'ember-cli-mirage/orm/schema'; - -module('Integration | Serializers | JSON API Serializer | Associations | Links', { - beforeEach() { - this.schema = new Schema(new Db(), { - wordSmith: Model.extend({ - blogPosts: hasMany() - }), - blogPost: Model.extend({ - wordSmith: belongsTo(), - fineComments: hasMany() - }), - fineComment: Model.extend({ - blogPost: belongsTo() - }) - }); - }, - afterEach() { - this.schema.db.emptyData(); - } -}); - -test(`it can link to relationships, omitting 'data'`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer, - blogPost: JSONAPISerializer.extend({ - links(model) { - return { - 'wordSmith': { - related: `/api/word_smiths/${model.wordSmith.id}`, - self: `/api/blog_posts/${model.id}/relationships/word_smith` - }, - 'fineComments': { - related: `/api/fine_comments?blog_post_id=${model.id}`, - self: `/api/blog_posts/${model.id}/relationships/fine_comments` - } - }; - } - }) - }); - - let link = this.schema.wordSmiths.create({ id: 3, name: 'Link' }); // specify id to really test our links function - let blogPost = link.createBlogPost({ title: 'Lorem ipsum' }); - - let result = registry.serialize(blogPost); - - assert.deepEqual(result, { - data: { - type: 'blog-posts', - id: blogPost.id, - attributes: { - 'title': 'Lorem ipsum' - }, - relationships: { - 'word-smith': { - links: { - related: `/api/word_smiths/${link.id}`, - self: `/api/blog_posts/${blogPost.id}/relationships/word_smith` - } - }, - 'fine-comments': { - links: { - related: `/api/fine_comments?blog_post_id=${blogPost.id}`, - self: `/api/blog_posts/${blogPost.id}/relationships/fine_comments` - } - } - } - } - }); -}); diff --git a/tests/integration/serializers/json-api-serializer/associations/many-to-many-test.js b/tests/integration/serializers/json-api-serializer/associations/many-to-many-test.js deleted file mode 100644 index eb7a26353..000000000 --- a/tests/integration/serializers/json-api-serializer/associations/many-to-many-test.js +++ /dev/null @@ -1,155 +0,0 @@ -import { module, skip } from 'qunit'; -import { Collection, Model, hasMany, belongsTo, JSONAPISerializer } from 'ember-cli-mirage'; -import Db from 'ember-cli-mirage/db'; -import Schema from 'ember-cli-mirage/orm/schema'; -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; - -module('Integration | Serializers | JSON API Serializer | Associations | Many To Many', { - beforeEach() { - let db = new Db(); - - let schema = new Schema(db, { - contact: Model.extend({ - addresses: hasMany(), - contactAddresses: hasMany() - }), - address: Model.extend({ - contacts: hasMany(), - contactAddresses: hasMany() - }), - contactAddress: Model.extend({ - contact: belongsTo(), - address: belongsTo() - }) - }); - - let mario = schema.contacts.create({ name: 'Mario' }); - let newYork = schema.addresses.create({ street: 'Some New York Street' }); - let mushroomKingdom = schema.addresses.create({ street: 'Some Mushroom Kingdom Street' }); - - schema.contactAddresses.create({ contact: mario, address: newYork }); - schema.contactAddresses.create({ contact: mario, address: mushroomKingdom }); - - this.schema = schema; - } -}); - -skip(`it serializes manyToMany if properly configured to passthrough `, function(assert) { - let contactSerializer = JSONAPISerializer.extend({ - addresses(model) { - let models = model.contactAddresses.models.map((ca) => ca.address); - return new Collection('address', models); - } - }); - - let addressSerializer = JSONAPISerializer.extend({ - contacts(model) { - let models = model.contactAddresses.models.map((ca) => ca.contact); - return new Collection('contact', models); - } - }); - - let registry = new SerializerRegistry(this.schema, { - address: addressSerializer, - contact: contactSerializer - }); - - let contact = this.schema.contacts.find(1); - let result = registry.serialize(contact); - - assert.deepEqual(result, { - data: { - id: '1', - type: 'contacts', - attributes: { - name: 'Mario' - }, - relationships: { - addresses: { - data: [ - { id: '1', type: 'addresses' }, - { id: '2', type: 'addresses' } - ] - }, - 'contact-addresses': { - data: [ - { id: '1', type: 'contact-addresses' }, - { id: '2', type: 'contact-addresses' } - ] - } - } - } - }); -}); - -skip(`it sideloads manyToMany if properly configured to passthrough and include`, function(assert) { - let contactSerializer = JSONAPISerializer.extend({ - include: ['addresses'], - addresses(model) { - let models = model.contactAddresses.models.map((ca) => ca.address); - return new Collection('address', models); - } - }); - - let addressSerializer = JSONAPISerializer.extend({ - include: ['contacts'], - contacts(model) { - let models = model.contactAddresses.models.map((ca) => ca.contact); - return new Collection('contact', models); - } - }); - - let registry = new SerializerRegistry(this.schema, { - address: addressSerializer, - contact: contactSerializer - }); - - let contact = this.schema.contacts.find(1); - let result = registry.serialize(contact); - - let { data, included } = result; - - assert.deepEqual(data, { - id: '1', - type: 'contacts', - attributes: { - name: 'Mario' - }, - relationships: { - addresses: { - data: [ - { id: '1', type: 'addresses' }, - { id: '2', type: 'addresses' } - ] - }, - 'contact-addresses': { - data: [ - { id: '1', type: 'contact-addresses' }, - { id: '2', type: 'contact-addresses' } - ] - } - } - }); - - assert.deepEqual(included, [{ - id: '1', - type: 'addresses', - attributes: { - street: 'Some New York Street' - }, - relationships: { - contacts: { data: [{ id: '1', type: 'contacts' }] }, - 'contact-addresses': { data: [{ id: '1', type: 'contact-addresses' }] } - } - }, { - id: '2', - type: 'addresses', - attributes: { - street: 'Some Mushroom Kingdom Street' - }, - relationships: { - contacts: { data: [{ id: '1', type: 'contacts' }] }, - 'contact-addresses': { data: [{ id: '2', type: 'contact-addresses' }] } - } - }]); -}); diff --git a/tests/integration/serializers/json-api-serializer/associations/model-test.js b/tests/integration/serializers/json-api-serializer/associations/model-test.js deleted file mode 100644 index 75a4b4770..000000000 --- a/tests/integration/serializers/json-api-serializer/associations/model-test.js +++ /dev/null @@ -1,472 +0,0 @@ -import Schema from 'ember-cli-mirage/orm/schema'; -import Db from 'ember-cli-mirage/db'; -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; -import { Model, hasMany, belongsTo, JSONAPISerializer } from 'ember-cli-mirage'; -import { module, test } from 'qunit'; - -module('Integration | Serializers | JSON API Serializer | Associations | Model', { - beforeEach() { - this.schema = new Schema(new Db(), { - wordSmith: Model.extend({ - blogPosts: hasMany() - }), - blogPost: Model.extend({ - wordSmith: belongsTo(), - fineComments: hasMany() - }), - fineComment: Model.extend({ - blogPost: belongsTo() - }) - }); - } -}); - -test(`it contains resource identifier objects for all a model's relationships, regardless of includes`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer - }); - let link = this.schema.wordSmiths.create({ - firstName: 'Link', - age: 123 - }); - let post = link.createBlogPost({ title: 'Lorem ipsum' }); - - let result = registry.serialize(post); - assert.deepEqual(result, { - data: { - type: 'blog-posts', - id: '1', - attributes: { - 'title': 'Lorem ipsum' - }, - relationships: { - 'word-smith': { - data: { - type: 'word-smiths', - id: '1' - } - }, - 'fine-comments': { - data: [] - } - } - } - }); -}); - -test(`it can include a has-many relationship`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer, - wordSmith: JSONAPISerializer.extend({ - include: ['blogPosts'] - }) - }); - - let link = this.schema.wordSmiths.create({ firstName: 'Link' }); - link.createBlogPost({ title: 'Lorem' }); - link.createBlogPost({ title: 'Ipsum' }); - - let result = registry.serialize(link); - - assert.deepEqual(result, { - data: { - type: 'word-smiths', - id: '1', - attributes: { - 'first-name': 'Link' - }, - relationships: { - 'blog-posts': { - data: [ - { type: 'blog-posts', id: '1' }, - { type: 'blog-posts', id: '2' } - ] - } - } - }, - included: [ - { - type: 'blog-posts', - id: '1', - attributes: { - title: 'Lorem' - }, - relationships: { - 'fine-comments': { - data: [] - }, - 'word-smith': { - data: { - id: '1', - type: 'word-smiths' - } - } - } - }, - { - type: 'blog-posts', - id: '2', - attributes: { - title: 'Ipsum' - }, - relationships: { - 'fine-comments': { - data: [] - }, - 'word-smith': { - data: { - id: '1', - type: 'word-smiths' - } - } - } - } - ] - }); -}); - -test(`it can include a chain of has-many relationships`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer, - wordSmith: JSONAPISerializer.extend({ - include: ['blogPosts'] - }), - blogPost: JSONAPISerializer.extend({ - include: ['fineComments'] - }) - }); - - let link = this.schema.wordSmiths.create({ firstName: 'Link' }); - let post1 = link.createBlogPost({ title: 'Lorem' }); - post1.createFineComment({ text: 'pwned' }); - link.createBlogPost({ title: 'Ipsum' }); - - let result = registry.serialize(link); - - assert.deepEqual(result, { - data: { - type: 'word-smiths', - id: '1', - attributes: { - 'first-name': 'Link' - }, - relationships: { - 'blog-posts': { - data: [ - { type: 'blog-posts', id: '1' }, - { type: 'blog-posts', id: '2' } - ] - } - } - }, - included: [ - { - type: 'blog-posts', - id: '1', - attributes: { - title: 'Lorem' - }, - relationships: { - 'fine-comments': { - data: [ - { type: 'fine-comments', id: '1' } - ] - }, - 'word-smith': { - data: { - id: '1', - type: 'word-smiths' - } - } - } - }, - { - type: 'fine-comments', - id: '1', - attributes: { - text: 'pwned' - }, - relationships: { - 'blog-post': { - data: { - id: '1', - type: 'blog-posts' - } - } - } - }, - { - type: 'blog-posts', - id: '2', - attributes: { - title: 'Ipsum' - }, - relationships: { - 'fine-comments': { - data: [] - }, - 'word-smith': { - data: { - id: '1', - type: 'word-smiths' - } - } - } - } - ] - }); -}); - -test(`it can include a belongs-to relationship`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer, - blogPost: JSONAPISerializer.extend({ - include: ['wordSmith'] - }) - }); - - let link = this.schema.wordSmiths.create({ firstName: 'Link' }); - let blogPost = link.createBlogPost({ title: 'Lorem' }); - blogPost.createFineComment(); - - let result = registry.serialize(blogPost); - - assert.deepEqual(result, { - data: { - type: 'blog-posts', - id: '1', - attributes: { - title: 'Lorem' - }, - relationships: { - 'fine-comments': { - data: [ - { - id: '1', - type: 'fine-comments' - } - ] - }, - 'word-smith': { - data: { - id: '1', - type: 'word-smiths' - } - } - } - }, - 'included': [ - { - attributes: { - 'first-name': 'Link' - }, - id: '1', - type: 'word-smiths', - relationships: { - 'blog-posts': { - data: [ - { - id: '1', - type: 'blog-posts' - } - ] - } - } - } - ] - }); -}); - -test(`it gracefully handles null belongs-to relationship`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer, - blogPost: JSONAPISerializer.extend({ - include: ['wordSmith'] - }) - }); - - let blogPost = this.schema.blogPosts.create({ title: 'Lorem' }); - let result = registry.serialize(blogPost); - - assert.deepEqual(result, { - data: { - type: 'blog-posts', - id: '1', - attributes: { - title: 'Lorem' - }, - relationships: { - 'word-smith': { - data: null - }, - 'fine-comments': { - data: [] - } - } - } - }); -}); - -test(`it can include a chain of belongs-to relationships`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer, - blogPost: JSONAPISerializer.extend({ - include: ['wordSmith'] - }), - fineComment: JSONAPISerializer.extend({ - include: ['blogPost'] - }) - }); - - let wordSmith = this.schema.wordSmiths.create({ firstName: 'Link' }); - let post = wordSmith.createBlogPost({ title: 'Lorem' }); - let comment = post.createFineComment({ text: 'pwned' }); - - let result = registry.serialize(comment); - - assert.deepEqual(result, { - data: { - type: 'fine-comments', - id: '1', - attributes: { - text: 'pwned' - }, - relationships: { - 'blog-post': { - data: { - id: '1', - type: 'blog-posts' - } - } - } - }, - 'included': [ - { - type: 'blog-posts', - id: '1', - attributes: { - title: 'Lorem' - }, - relationships: { - 'fine-comments': { - data: [ - { - id: '1', - type: 'fine-comments' - } - ] - }, - 'word-smith': { - data: { - type: 'word-smiths', - id: '1' - } - } - } - }, - { - type: 'word-smiths', - id: '1', - attributes: { - 'first-name': 'Link' - }, - relationships: { - 'blog-posts': { - data: [ - { - id: '1', - type: 'blog-posts' - } - ] - } - } - } - ] - }); -}); - -test(`it ignores relationships that refer to serialized ancestor resources`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer, - wordSmith: JSONAPISerializer.extend({ - include: ['blogPosts'] - }), - blogPost: JSONAPISerializer.extend({ - include: ['wordSmith', 'fineComments'] - }), - fineComment: JSONAPISerializer.extend({ - include: ['blogPost'] - }) - }); - - let wordSmith = this.schema.wordSmiths.create({ firstName: 'Link' }); - let post = wordSmith.createBlogPost({ title: 'Lorem' }); - wordSmith.createBlogPost({ title: 'Ipsum' }); - post.createFineComment({ text: 'pwned' }); - - let result = registry.serialize(wordSmith); - - assert.deepEqual(result, { - data: { - attributes: { - 'first-name': 'Link' - }, - id: '1', - relationships: { - 'blog-posts': { - data: [ - { type: 'blog-posts', id: '1' }, - { type: 'blog-posts', id: '2' } - ] - } - }, - type: 'word-smiths' - }, - included: [ - { - type: 'blog-posts', - id: '1', - attributes: { - title: 'Lorem' - }, - relationships: { - 'word-smith': { - data: { type: 'word-smiths', id: '1' } - }, - 'fine-comments': { - data: [ - { type: 'fine-comments', id: '1' } - ] - } - } - }, - { - type: 'fine-comments', - id: '1', - attributes: { - text: 'pwned' - }, - relationships: { - 'blog-post': { - data: { type: 'blog-posts', id: '1' } - } - } - }, - { - type: 'blog-posts', - id: '2', - attributes: { - title: 'Ipsum' - }, - relationships: { - 'word-smith': { - data: { type: 'word-smiths', id: '1' } - }, - 'fine-comments': { - data: [] - } - } - } - ] - }); -}); diff --git a/tests/integration/serializers/json-api-serializer/attrs-test.js b/tests/integration/serializers/json-api-serializer/attrs-test.js deleted file mode 100644 index 465a95b44..000000000 --- a/tests/integration/serializers/json-api-serializer/attrs-test.js +++ /dev/null @@ -1,103 +0,0 @@ -import Schema from 'ember-cli-mirage/orm/schema'; -import Db from 'ember-cli-mirage/db'; -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; -import { Model, JSONAPISerializer } from 'ember-cli-mirage'; -import { module, test } from 'qunit'; - -module('Integration | Serializers | JSON API Serializer | Attrs List', { - beforeEach() { - this.schema = new Schema(new Db(), { - wordSmith: Model, - photograph: Model - }); - } -}); - -test(`it returns only the whitelisted attrs when serializing a model`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer, - wordSmith: JSONAPISerializer.extend({ - attrs: ['firstName'] - }) - }); - let user = this.schema.wordSmiths.create({ - id: 1, - firstName: 'Link', - age: 123 - }); - - let result = registry.serialize(user); - - assert.deepEqual(result, { - data: { - type: 'word-smiths', - id: '1', - attributes: { - 'first-name': 'Link' - } - } - }); -}); - -test(`it returns only the whitelisted attrs when serializing a collection`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer, - wordSmith: JSONAPISerializer.extend({ - attrs: ['firstName'] - }) - }); - this.schema.wordSmiths.create({ id: 1, firstName: 'Link', age: 123 }); - this.schema.wordSmiths.create({ id: 2, firstName: 'Zelda', age: 456 }); - - let collection = this.schema.wordSmiths.all(); - let result = registry.serialize(collection); - - assert.deepEqual(result, { - data: [{ - type: 'word-smiths', - id: '1', - attributes: { - 'first-name': 'Link' - } - }, { - type: 'word-smiths', - id: '2', - attributes: { - 'first-name': 'Zelda' - } - }] - }); -}); - -test(`it can use different attr whitelists for different serializers`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - wordSmith: JSONAPISerializer.extend({ - attrs: ['firstName'] - }), - photograph: JSONAPISerializer.extend({ - attrs: ['title'] - }) - }); - - let link = this.schema.wordSmiths.create({ id: 1, firstName: 'Link', age: 123 }); - assert.deepEqual(registry.serialize(link), { - data: { - type: 'word-smiths', - id: '1', - attributes: { - 'first-name': 'Link' - } - } - }); - - let photo = this.schema.photographs.create({ id: 1, title: 'Lorem ipsum', createdAt: '2010-01-01' }); - assert.deepEqual(registry.serialize(photo), { - data: { - type: 'photographs', - id: '1', - attributes: { - 'title': 'Lorem ipsum' - } - } - }); -}); diff --git a/tests/integration/serializers/json-api-serializer/base-test.js b/tests/integration/serializers/json-api-serializer/base-test.js deleted file mode 100644 index bc17f14a2..000000000 --- a/tests/integration/serializers/json-api-serializer/base-test.js +++ /dev/null @@ -1,68 +0,0 @@ -import Schema from 'ember-cli-mirage/orm/schema'; -import Db from 'ember-cli-mirage/db'; -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; -import { Model, JSONAPISerializer } from 'ember-cli-mirage'; -import { module, test } from 'qunit'; - -module('Integration | Serializers | JSON API Serializer | Base', { - beforeEach() { - this.schema = new Schema(new Db(), { - wordSmith: Model - }); - this.registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer - }); - } -}); - -test(`it includes all attributes for a model`, function(assert) { - let link = this.schema.wordSmiths.create({ firstName: 'Link', age: 123 }); - let result = this.registry.serialize(link); - - assert.deepEqual(result, { - data: { - type: 'word-smiths', - id: '1', - attributes: { - 'first-name': 'Link', - age: 123 - } - } - }); -}); - -test(`it includes all attributes for each model in a collection`, function(assert) { - this.schema.wordSmiths.create({ firstName: 'Link', age: 123 }); - this.schema.wordSmiths.create({ id: 1, firstName: 'Link', age: 123 }); - this.schema.wordSmiths.create({ id: 2, firstName: 'Zelda', age: 456 }); - - let collection = this.schema.wordSmiths.all(); - let result = this.registry.serialize(collection); - - assert.deepEqual(result, { - data: [{ - type: 'word-smiths', - id: '1', - attributes: { - 'first-name': 'Link', - age: 123 - } - }, { - type: 'word-smiths', - id: '2', - attributes: { - 'first-name': 'Zelda', - age: 456 - } - }] - }); -}); - -test(`it can serialize an empty collection`, function(assert) { - let wordSmiths = this.schema.wordSmiths.all(); - let result = this.registry.serialize(wordSmiths); - - assert.deepEqual(result, { - data: [] - }); -}); diff --git a/tests/integration/serializers/json-api-serializer/key-formatting-test.js b/tests/integration/serializers/json-api-serializer/key-formatting-test.js deleted file mode 100644 index 62c60791c..000000000 --- a/tests/integration/serializers/json-api-serializer/key-formatting-test.js +++ /dev/null @@ -1,79 +0,0 @@ -import Schema from 'ember-cli-mirage/orm/schema'; -import Db from 'ember-cli-mirage/db'; -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; -import { Model, JSONAPISerializer } from 'ember-cli-mirage'; -import { underscore } from 'ember-cli-mirage/utils/inflector'; -import { module, test } from 'qunit'; - -module('Integration | Serializers | JSON API Serializer | Key Formatting', { - beforeEach() { - this.schema = new Schema(new Db(), { - wordSmith: Model, - photograph: Model - }); - } -}); - -test(`keyForAttribute formats the attributes of a model`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer.extend({ - keyForAttribute(key) { - return underscore(key); - } - }) - }); - let wordSmith = this.schema.wordSmiths.create({ - id: 1, - firstName: 'Link', - lastName: 'Jackson', - age: 323 - }); - - let result = registry.serialize(wordSmith); - - assert.deepEqual(result, { - data: { - type: 'word-smiths', - id: '1', - attributes: { - age: 323, - first_name: 'Link', - last_name: 'Jackson' - } - } - }); -}); - -test(`keyForAttribute also formats the models in a collections`, function(assert) { - let registry = new SerializerRegistry(this.schema, { - application: JSONAPISerializer.extend({ - keyForAttribute(key) { - return underscore(key); - } - }) - }); - - this.schema.wordSmiths.create({ id: 1, 'firstName': 'Link', 'lastName': 'Jackson' }); - this.schema.wordSmiths.create({ id: 2, 'firstName': 'Zelda', 'lastName': 'Brown' }); - let wordSmiths = this.schema.wordSmiths.all(); - - let result = registry.serialize(wordSmiths); - - assert.deepEqual(result, { - data: [{ - type: 'word-smiths', - id: '1', - attributes: { - 'first_name': 'Link', - 'last_name': 'Jackson' - } - }, { - type: 'word-smiths', - id: '2', - attributes: { - 'first_name': 'Zelda', - 'last_name': 'Brown' - } - }] - }); -}); diff --git a/tests/integration/serializers/rest-model-serializer-test.js b/tests/integration/serializers/rest-model-serializer-test.js deleted file mode 100644 index f8e1f8b9d..000000000 --- a/tests/integration/serializers/rest-model-serializer-test.js +++ /dev/null @@ -1,65 +0,0 @@ -import RestSerializer from 'ember-cli-mirage/serializers/rest-serializer'; -import { hasMany, belongsTo } from 'ember-cli-mirage'; -import Schema from 'ember-cli-mirage/orm/schema'; -import Model from 'ember-cli-mirage/orm/model'; -import Db from 'ember-cli-mirage/db'; -import SerializerRegistry from 'ember-cli-mirage/serializer-registry'; -import { module, test } from 'qunit'; - -module('Integration | Serializer | RestSerializer', { - beforeEach() { - let db = new Db(); - this.schema = new Schema(db); - this.schema.registerModels({ - wordSmith: Model.extend({ - blogPosts: hasMany() - }), - blogPost: Model.extend({ - wordSmith: belongsTo() - }) - }); - - let link = this.schema.wordSmiths.create({ name: 'Link', age: 123 }); - link.createBlogPost({ title: 'Lorem' }); - link.createBlogPost({ title: 'Ipsum' }); - - this.schema.wordSmiths.create({ name: 'Zelda', age: 230 }); - - this.registry = new SerializerRegistry(this.schema, { - application: RestSerializer, - wordSmith: RestSerializer.extend({ - attrs: ['id', 'name'], - include: ['blogPosts'] - }) - }); - }, - - afterEach() { - this.schema.db.emptyData(); - } -}); - -test('it sideloads associations and camel-cases relationships and attributes correctly for a model', function(assert) { - let link = this.schema.wordSmiths.find(1); - let result = this.registry.serialize(link); - - assert.deepEqual(result, { - wordSmith: { - id: '1', - name: 'Link', - blogPostIds: ['1', '2'] - }, - blogPosts: [ - { - id: '1', - title: 'Lorem', - wordSmithId: '1' - }, - { - id: '2', - title: 'Ipsum', - wordSmithId: '1' - } - ] - }); -}); diff --git a/tests/integration/serializers/schema-helper.js b/tests/integration/serializers/schema-helper.js deleted file mode 100644 index 25c533daf..000000000 --- a/tests/integration/serializers/schema-helper.js +++ /dev/null @@ -1,45 +0,0 @@ -import Mirage from 'ember-cli-mirage'; -import Schema from 'ember-cli-mirage/orm/schema'; -import Model from 'ember-cli-mirage/orm/model'; -import Db from 'ember-cli-mirage/db'; - -export default { - - setup() { - let db = new Db(); - this.schema = new Schema(db); - this.schema.registerModels({ - wordSmith: Model.extend({ - blogPosts: Mirage.hasMany() - }), - blogPost: Model.extend({ - wordSmith: Mirage.belongsTo(), - fineComments: Mirage.hasMany() - }), - fineComment: Model.extend({ - blogPost: Mirage.belongsTo() - }), - greatPhoto: Model, - - foo: Model.extend({ - bar: Mirage.belongsTo() - }), - bar: Model.extend({ - baz: Mirage.belongsTo() - }), - baz: Model.extend({ - quuxes: Mirage.hasMany() - }), - quux: Model.extend({ - zomgs: Mirage.hasMany() - }), - zomg: Model.extend({ - lol: Mirage.belongsTo() - }), - lol: Model - }); - - return this.schema; - } - -}; diff --git a/tests/integration/server-config-test.js b/tests/integration/server-config-test.js deleted file mode 100644 index 2fa87f687..000000000 --- a/tests/integration/server-config-test.js +++ /dev/null @@ -1,252 +0,0 @@ -import {module, test} from 'qunit'; -import { Model } from 'ember-cli-mirage'; -import Server from 'ember-cli-mirage/server'; -import ActiveModelSerializer from 'ember-cli-mirage/serializers/active-model-serializer'; -import RestSerializer from 'ember-cli-mirage/serializers/rest-serializer'; - -module('Integration | Server Config', { - beforeEach() { - this.server = new Server({ - environment: 'development', - models: { - contact: Model, - post: Model - }, - serializers: { - contact: ActiveModelSerializer - } - }); - this.server.timing = 0; - this.server.logging = false; - }, - afterEach() { - this.server.shutdown(); - } -}); - -test('namespace can be configured', function(assert) { - assert.expect(1); - let done = assert.async(); - - let contacts = [ - { id: '1', name: 'Link' }, - { id: '2', name: 'Zelda' } - ]; - this.server.db.loadData({ - contacts - }); - this.server.namespace = 'api'; - this.server.get('/contacts'); - - $.getJSON('/api/contacts', function(data) { - assert.deepEqual(data, { contacts }); - done(); - }); -}); - -test('urlPrefix can be configured', function(assert) { - assert.expect(1); - let done = assert.async(); - let { server } = this; - - let contacts = [ - { id: '1', name: 'Link' }, - { id: '2', name: 'Zelda' } - ]; - server.db.loadData({ - contacts - }); - server.urlPrefix = 'http://localhost:3000'; - server.get('/contacts'); - - $.getJSON('http://localhost:3000/contacts', function(data) { - assert.deepEqual(data, { contacts }); - done(); - }); -}); - -test('urlPrefix and namespace can be configured simultaneously', function(assert) { - assert.expect(1); - let done = assert.async(); - let { server } = this; - - let contacts = [ - { id: '1', name: 'Link' }, - { id: '2', name: 'Zelda' } - ]; - server.db.loadData({ - contacts - }); - server.urlPrefix = 'http://localhost:3000'; - server.namespace = 'api'; - server.get('/contacts'); - - $.getJSON('http://localhost:3000/api/contacts', function(data) { - assert.deepEqual(data, { contacts }); - done(); - }); -}); - -test('fully qualified domain names can be used in configuration', function(assert) { - assert.expect(1); - let done = assert.async(); - - let contacts = [ - { id: '1', name: 'Link' }, - { id: '2', name: 'Zelda' } - ]; - this.server.db.loadData({ - contacts - }); - this.server.get('http://example.org/api/contacts'); - - $.getJSON('http://example.org/api/contacts', function(data) { - assert.deepEqual(data, { contacts }); - done(); - }); -}); - -test('urlPrefix/namespace are ignored when fully qualified domain names are used in configuration', function(assert) { - assert.expect(1); - let done = assert.async(); - let { server } = this; - - let contacts = [ - { id: '1', name: 'Link' }, - { id: '2', name: 'Zelda' } - ]; - server.db.loadData({ - contacts - }); - this.urlPrefix = 'https://example.net'; - server.get('http://example.org/api/contacts'); - - $.getJSON('http://example.org/api/contacts', function(data) { - assert.deepEqual(data, { contacts }); - done(); - }); -}); - -test('blank urlPrefix and namespace ends up as /', function(assert) { - assert.expect(1); - let done = assert.async(); - - let contacts = [ - { id: '1', name: 'Link' }, - { id: '2', name: 'Zelda' } - ]; - this.server.db.loadData({ - contacts - }); - this.server.namespace = ''; - this.server.urlPrefix = ''; - this.server.get('contacts'); - - $.getJSON('/contacts', function(data) { - assert.deepEqual(data, { contacts }); - done(); - }); -}); - -test('namespace with no slash gets one', function(assert) { - assert.expect(1); - let done = assert.async(); - - let contacts = [ - { id: '1', name: 'Link' }, - { id: '2', name: 'Zelda' } - ]; - this.server.db.loadData({ - contacts - }); - this.server.namespace = 'api'; - this.server.get('contacts'); - - $.getJSON('/api/contacts', function(data) { - assert.deepEqual(data, { contacts }); - done(); - }); -}); - -test('urlPrefix with no slash gets one', function(assert) { - assert.expect(1); - let done = assert.async(); - - let contacts = [ - { id: '1', name: 'Link' }, - { id: '2', name: 'Zelda' } - ]; - this.server.db.loadData({ - contacts - }); - this.server.urlPrefix = 'pre'; - this.server.get('contacts'); - - $.getJSON('/pre/contacts', function(data) { - assert.deepEqual(data, { contacts }); - done(); - }); -}); - -test('namespace of / works', function(assert) { - assert.expect(1); - let done = assert.async(); - - let contacts = [ - { id: '1', name: 'Link' }, - { id: '2', name: 'Zelda' } - ]; - this.server.db.loadData({ - contacts - }); - this.server.namespace = '/'; - this.server.get('contacts'); - - $.getJSON('/contacts', function(data) { - assert.deepEqual(data, { contacts }); - done(); - }); -}); - -test('redefining options using the config method works', function(assert) { - assert.expect(5); - let done = assert.async(); - let { server } = this; - - let contacts = [ - { id: '1', name: 'Link' }, - { id: '2', name: 'Zelda' } - ]; - server.config({ - namespace: 'api', - urlPrefix: 'http://localhost:3000', - timing: 1000, - serializers: { - post: RestSerializer - } - }); - server.db.loadData({ - contacts - }); - server.get('contacts'); - - assert.equal(server.timing, 1000); - $.getJSON('http://localhost:3000/api/contacts', function(data) { - assert.deepEqual(data, { contacts }); - done(); - }); - let serializerMap = server.serializerOrRegistry._serializerMap; - assert.equal(Object.keys(serializerMap).length, 2); - assert.equal(serializerMap.contact, ActiveModelSerializer); - assert.equal(serializerMap.post, RestSerializer); -}); - -test('changing the environment of the server throws an error', function(assert) { - let { server } = this; - - assert.throws(function() { - server.config({ - environment: 'test' - }); - }, /You cannot modify Mirage's environment once the server is created/); -}); diff --git a/tests/integration/server-with-orm-test.js b/tests/integration/server-with-orm-test.js deleted file mode 100644 index d4ae226d0..000000000 --- a/tests/integration/server-with-orm-test.js +++ /dev/null @@ -1,33 +0,0 @@ -import {module, test} from 'qunit'; -import { Model, Factory } from 'ember-cli-mirage'; -import Server from 'ember-cli-mirage/server'; - -module('Integration | Server with ORM', { - beforeEach() { - this.server = new Server({ - environment: 'test', - models: { - blogPost: Model - }, - factories: { - blogPost: Factory - } - }); - this.server.timing = 0; - this.server.logging = false; - }, - afterEach() { - this.server.shutdown(); - } -}); - -test('a single blogPost db collection is made', function(assert) { - assert.equal(this.server.db._collections.length, 1); - assert.equal(this.server.db._collections[0].name, 'blogPosts'); -}); - -test('create looks up the appropriate db collection', function(assert) { - server.create('blog-post'); - - assert.equal(this.server.db.blogPosts.length, 1); -}); diff --git a/tests/integration/server/custom-function-handler-test.js b/tests/integration/server/custom-function-handler-test.js deleted file mode 100644 index e55dd6f92..000000000 --- a/tests/integration/server/custom-function-handler-test.js +++ /dev/null @@ -1,103 +0,0 @@ -import { module, test } from 'qunit'; -import { Model, Factory, ActiveModelSerializer } from 'ember-cli-mirage'; -import Server from 'ember-cli-mirage/server'; - -module('Integration | Server | Custom function handler', { - beforeEach() { - this.server = new Server({ - environment: 'test', - models: { - contact: Model - }, - factories: { - contact: Factory - }, - serializers: { - application: ActiveModelSerializer - } - }); - this.server.timing = 0; - this.server.logging = false; - }, - afterEach() { - this.server.shutdown(); - } -}); - -test(`a POJA of models defaults to responding with an array of each model's attrs`, function(assert) { - assert.expect(1); - let done = assert.async(); - let { server } = this; - - server.createList('contact', 3); - server.get('/contacts', (schema) => { - return schema.contacts.all().models; - }); - - $.ajax({ - method: 'GET', - url: '/contacts' - }).done((res) => { - assert.deepEqual(res, [{ id: '1' }, { id: '2' }, { id: '3' }]); - done(); - }); -}); - -test(`#normalizedRequestAttrs returns an object with the primary resource's attrs and belongsTo keys camelized`, function(assert) { - assert.expect(1); - let done = assert.async(); - let { server } = this; - - server.post('/contacts', function() { - let attrs = this.normalizedRequestAttrs(); - - assert.deepEqual(attrs, { - firstName: 'Sam', - lastName: 'Selikoff', - teamId: 1 - }); - - return {}; - }); - - $.ajax({ - method: 'POST', - url: '/contacts', - contentType: 'application/json', - data: JSON.stringify({ - contact: { - first_name: 'Sam', - last_name: 'Selikoff', - team_id: 1 - } - }) - }).done(() => { - done(); - }); -}); - -test(`#normalizedRequestAttrs parses a x-www-form-urlencoded request and returns a POJO`, function(assert) { - assert.expect(1); - let done = assert.async(); - let { server } = this; - - server.post('/form-test', function() { - let attrs = this.normalizedRequestAttrs(); - - assert.deepEqual(attrs, { - name: 'Sam Selikoff', - company: 'TED', - email: 'sam.selikoff@gmail.com' - }, '#normalizedRequestAttrs successfully returned the parsed x-www-form-urlencoded request body'); - - return {}; - }); - - $.ajax({ - method: 'POST', - url: '/form-test', - data: 'name=Sam+Selikoff&company=TED&email=sam.selikoff@gmail.com' - }).done(() => { - done(); - }); -}); diff --git a/tests/integration/server/customized-normalize-method-test.js b/tests/integration/server/customized-normalize-method-test.js deleted file mode 100644 index c96fdd996..000000000 --- a/tests/integration/server/customized-normalize-method-test.js +++ /dev/null @@ -1,107 +0,0 @@ -import {module, test} from 'qunit'; -import { Model, ActiveModelSerializer } from 'ember-cli-mirage'; -import { camelize } from 'ember-cli-mirage/utils/inflector'; -import Server from 'ember-cli-mirage/server'; - -module('Integration | Server | Customized normalize method', { - beforeEach() { - this.server = new Server({ - environment: 'test', - models: { - contact: Model - }, - serializers: { - application: ActiveModelSerializer, - contact: ActiveModelSerializer.extend({ - normalize(payload) { - let attrs = payload.some.random[1].attrs; - Object.keys(attrs).forEach(camelize); - - let jsonApiDoc = { - data: { - type: 'contacts', - attributes: attrs - } - }; - return jsonApiDoc; - } - }) - } - }); - this.server.timing = 0; - this.server.logging = false; - }, - afterEach() { - this.server.shutdown(); - } -}); - -test('custom model-specific normalize functions are used', function(assert) { - let { server } = this; - assert.expect(3); - let done = assert.async(); - - server.post('/contacts'); - - $.ajax({ - method: 'POST', - url: '/contacts', - data: JSON.stringify({ - some: { - random: [ - { - format: true - }, - { - attrs: { - first_name: 'Zelda' - } - } - ] - } - }) - }).done((res, status, xhr) => { - assert.equal(xhr.status, 201); - assert.equal(server.db.contacts.length, 1); - assert.equal(server.db.contacts[0].firstName, 'Zelda'); - done(); - }); -}); - -test('custom model-specific normalize functions are used with custom function handlers', function(assert) { - let { server } = this; - let done = assert.async(); - - server.put('/contacts/:id', function(schema, request) { - let attrs = this.normalizedRequestAttrs(); - - assert.deepEqual(attrs, { - id: '1', - firstName: 'Zelda' - }); - - return {}; - }); - - $.ajax({ - method: 'PUT', - url: '/contacts/1', - contentType: 'application/json', - data: JSON.stringify({ - some: { - random: [ - { - format: true - }, - { - attrs: { - first_name: 'Zelda' - } - } - ] - } - }) - }).done(() => { - done(); - }); -}); diff --git a/tests/integration/server/factory-creation-test.js b/tests/integration/server/factory-creation-test.js deleted file mode 100644 index 08c3b88e3..000000000 --- a/tests/integration/server/factory-creation-test.js +++ /dev/null @@ -1,96 +0,0 @@ -import { module, test } from 'qunit'; -import { Model, Factory, hasMany, belongsTo } from 'ember-cli-mirage'; -import Server from 'ember-cli-mirage/server'; - -module('Integration | Server | Factory creation', { - beforeEach() { - this.Contact = Model.extend(); - this.AmazingContact = Model.extend(); - this.Post = Model.extend({ - author: belongsTo() - }); - this.Author = Model.extend({ - posts: hasMany() - }); - - this.server = new Server({ - environment: 'test', - models: { - contact: this.Contact, - amazingContact: this.AmazingContact, - post: this.Post, - author: this.Author - }, - factories: { - contact: Factory, - amazingContact: Factory - } - }); - this.server.timing = 0; - this.server.logging = false; - }, - afterEach() { - this.server.shutdown(); - } -}); - -test('create returns a Model if one is defined', function(assert) { - let contact = this.server.create('contact'); - - assert.ok(contact instanceof this.Contact, 'expected a Contact'); -}); - -test('createList returns Models if one is defined', function(assert) { - let contacts = this.server.createList('contact', 1); - - assert.ok(contacts[0] instanceof this.Contact, 'expected a Contactl'); -}); - -test('create returns a Model if one is defined, when using a compound name', function(assert) { - let contact = this.server.create('amazing-contact'); - - assert.ok(contact instanceof this.AmazingContact, 'expected an AmazingContact'); -}); - -test('createList returns Models if one is defined, when using a compound name', function(assert) { - let contacts = this.server.createList('amazing-contact', 1); - - assert.ok(contacts[0] instanceof this.AmazingContact, 'expected an AmazingContact'); -}); - -test('create falls back to a model if no factory is defined', function(assert) { - let post = this.server.create('post'); - - assert.ok(post instanceof this.Post); - assert.equal(post.id, 1); -}); - -test('createList falls back to a model if no factory is defined', function(assert) { - let posts = this.server.createList('post', 2); - - assert.ok(posts[0] instanceof this.Post); - assert.equal(posts.length, 2); - assert.equal(posts[0].id, 1); -}); - -test('create sets up the db correctly when passing in fks', function(assert) { - let author = server.create('author'); - let post = this.server.create('post', { - authorId: author.id - }); - - assert.equal(author.posts.models.length, 1); - assert.deepEqual(post.author.attrs, author.attrs); - assert.equal(this.server.db.posts[0].authorId, author.id); -}); - -test('create sets up the db correctly when passing in models', function(assert) { - let author = server.create('author'); - let post = this.server.create('post', { - author - }); - - assert.equal(author.posts.models.length, 1); - assert.deepEqual(post.author.attrs, author.attrs); - assert.equal(this.server.db.posts[0].authorId, author.id); -}); diff --git a/tests/integration/server/get-full-path-test.js b/tests/integration/server/get-full-path-test.js deleted file mode 100644 index ec5b2e5d8..000000000 --- a/tests/integration/server/get-full-path-test.js +++ /dev/null @@ -1,98 +0,0 @@ -import {module, test} from 'qunit'; -import Server from 'ember-cli-mirage/server'; - -module('Integration | Server | Get full path', { - beforeEach() { - this.server = new Server({ - environment: 'test' - }); - this.server.timing = 0; - this.server.logging = false; - }, - afterEach() { - this.server.shutdown(); - } -}); - -test('it works with a configured namespace with a leading slash', function(assert) { - assert.expect(1); - let { server } = this; - server.namespace = '/api'; - - assert.equal(server._getFullPath('/contacts'), '/api/contacts'); -}); - -test('it works with a configured namespace with a trailing slash', function(assert) { - assert.expect(1); - let { server } = this; - server.namespace = 'api/'; - - assert.equal(server._getFullPath('/contacts'), '/api/contacts'); -}); - -test('it works with a configured namespace without a leading slash', function(assert) { - assert.expect(1); - let { server } = this; - server.namespace = 'api'; - - assert.equal(server._getFullPath('/contacts'), '/api/contacts'); -}); - -test('it works with a configured namespace is an empty string', function(assert) { - assert.expect(1); - let { server } = this; - server.namespace = ''; - - assert.equal(server._getFullPath('/contacts'), '/contacts'); -}); - -test('it works with a configured urlPrefix with a trailing slash', function(assert) { - assert.expect(1); - let { server } = this; - server.urlPrefix = 'http://localhost:3000/'; - - assert.equal(server._getFullPath('/contacts'), 'http://localhost:3000/contacts'); -}); - -test('it works with a configured urlPrefix without a trailing slash', function(assert) { - assert.expect(1); - let { server } = this; - server.urlPrefix = 'http://localhost:3000'; - - assert.equal(server._getFullPath('/contacts'), 'http://localhost:3000/contacts'); -}); - -test('it works with a configured urlPrefix as an empty string', function(assert) { - assert.expect(1); - let { server } = this; - server.urlPrefix = ''; - - assert.equal(server._getFullPath('/contacts'), '/contacts'); -}); - -test('it works with a configured namespace and a urlPrefix', function(assert) { - assert.expect(1); - let { server } = this; - server.namespace = 'api'; - server.urlPrefix = 'http://localhost:3000'; - - assert.equal(server._getFullPath('/contacts'), 'http://localhost:3000/api/contacts'); -}); - -test('it works with a configured namespace with a leading slash and a urlPrefix', function(assert) { - assert.expect(1); - let { server } = this; - server.namespace = '/api'; - server.urlPrefix = 'http://localhost:3000'; - - assert.equal(server._getFullPath('/contacts'), 'http://localhost:3000/api/contacts'); -}); - -test('it works with a configured namespace and a urlPrefix as empty strings', function(assert) { - assert.expect(1); - let { server } = this; - server.namespace = ''; - server.urlPrefix = ''; - - assert.equal(server._getFullPath('/contacts'), '/contacts'); -}); \ No newline at end of file diff --git a/tests/integration/server/resource-shorthand-test.js b/tests/integration/server/resource-shorthand-test.js deleted file mode 100644 index 0ecc1eae0..000000000 --- a/tests/integration/server/resource-shorthand-test.js +++ /dev/null @@ -1,379 +0,0 @@ -import {module, test} from 'qunit'; -import { Model, ActiveModelSerializer } from 'ember-cli-mirage'; -import Server from 'ember-cli-mirage/server'; - -module('Integration | Server | Resource shorthand', { - beforeEach() { - this.server = new Server({ - environment: 'test', - models: { - contact: Model - }, - serializers: { - application: ActiveModelSerializer - } - }); - this.server.timing = 0; - this.server.logging = false; - }, - afterEach() { - this.server.shutdown(); - } -}); - -test('resource generates get shorthand for index action', function(assert) { - assert.expect(2); - let done = assert.async(); - - this.server.db.loadData({ - contacts: [ - { id: 1, name: 'Link' }, - { id: 2, name: 'Zelda' } - ] - }); - - this.server.resource('contacts'); - - $.ajax({ - method: 'GET', - url: '/contacts' - }).done(function(res, status, xhr) { - assert.equal(xhr.status, 200); - assert.deepEqual(res, { contacts: [{ id: '1', name: 'Link' }, { id: '2', name: 'Zelda' }] }); - done(); - }); -}); - -test('resource generates get shorthand for show action', function(assert) { - assert.expect(2); - let done = assert.async(); - - this.server.db.loadData({ - contacts: [ - { id: 1, name: 'Link' }, - { id: 2, name: 'Zelda' } - ] - }); - - this.server.resource('contacts'); - - $.ajax({ - method: 'GET', - url: '/contacts/2' - }).done(function(res, status, xhr) { - assert.equal(xhr.status, 200); - assert.deepEqual(res, { contact: { id: '2', name: 'Zelda' } }); - done(); - }); -}); - -test('resource generates post shorthand', function(assert) { - let { server } = this; - assert.expect(2); - let done = assert.async(); - - server.resource('contacts'); - - $.ajax({ - method: 'POST', - url: '/contacts', - data: JSON.stringify({ - contact: { - name: 'Zelda' - } - }) - }).done((res, status, xhr) => { - assert.equal(xhr.status, 201); - assert.equal(server.db.contacts.length, 1); - done(); - }); -}); - -test('resource generates put shorthand', function(assert) { - let { server } = this; - assert.expect(2); - let done = assert.async(); - - this.server.db.loadData({ - contacts: [ - { id: 1, name: 'Link' } - ] - }); - - server.resource('contacts'); - - $.ajax({ - method: 'PUT', - url: '/contacts/1', - data: JSON.stringify({ - contact: { - name: 'Zelda' - } - }) - }).done((res, status, xhr) => { - assert.equal(xhr.status, 200); - assert.equal(server.db.contacts[0].name, 'Zelda'); - done(); - }); -}); - -test('resource generates patch shorthand', function(assert) { - let { server } = this; - assert.expect(2); - let done = assert.async(); - - this.server.db.loadData({ - contacts: [ - { id: 1, name: 'Link' } - ] - }); - - server.resource('contacts'); - - $.ajax({ - method: 'PATCH', - url: '/contacts/1', - data: JSON.stringify({ - contact: { - name: 'Zelda' - } - }) - }).done((res, status, xhr) => { - assert.equal(xhr.status, 200); - assert.equal(server.db.contacts[0].name, 'Zelda'); - done(); - }); -}); - -test('resource generates delete shorthand works', function(assert) { - let { server } = this; - assert.expect(2); - let done = assert.async(); - - this.server.db.loadData({ - contacts: [ - { id: 1, name: 'Link' } - ] - }); - - server.resource('contacts'); - - $.ajax({ - method: 'DELETE', - url: '/contacts/1' - }).done((res, status, xhr) => { - assert.equal(xhr.status, 204); - assert.equal(server.db.contacts.length, 0); - done(); - }); -}); - -test('resource does not accept both :all and :except options', function(assert) { - let { server } = this; - - assert.throws(() => { - server.resource('contacts', { only: ['index'], except: ['create'] }); - }, 'cannot use both :only and :except options'); -}); - -test('resource generates shorthands which are whitelisted by :only option', function(assert) { - let { server } = this; - assert.expect(1); - let done = assert.async(); - - server.db.loadData({ - contacts: [ - { id: 1, name: 'Link' }, - { id: 2, name: 'Zelda' } - ] - }); - - server.resource('contacts', { only: ['index'] }); - - $.ajax({ - method: 'GET', - url: '/contacts' - }).done((res, status, xhr) => { - assert.equal(xhr.status, 200); - done(); - }); -}); - -test('resource does not generate shorthands which are not whitelisted with :only option', function(assert) { - let { server } = this; - assert.expect(5); - - server.db.loadData({ - contacts: [ - { id: 1, name: 'Link' } - ] - }); - - server.resource('contacts', { only: ['index'] }); - - let doneForShow = assert.async(); - - $.ajax({ - method: 'GET', - url: '/contacts/1' - }).fail((xhr, textStatus, error) => { - assert.ok(error.message.indexOf("Mirage: Your Ember app tried to GET '/contacts/1'") !== -1); - doneForShow(); - }); - - let doneForCreate = assert.async(); - - $.ajax({ - method: 'POST', - url: '/contacts', - data: JSON.stringify({ - contact: { - name: 'Zelda' - } - }) - }).fail((xhr, textStatus, error) => { - assert.ok(error.message.indexOf("Mirage: Your Ember app tried to POST '/contacts'") !== -1); - doneForCreate(); - }); - - let doneForPut = assert.async(); - - $.ajax({ - method: 'PUT', - url: '/contacts/1', - data: JSON.stringify({ - contact: { - name: 'Zelda' - } - }) - }).fail((xhr, textStatus, error) => { - assert.ok(error.message.indexOf("Mirage: Your Ember app tried to PUT '/contacts/1'") !== -1); - doneForPut(); - }); - - let doneForPatch = assert.async(); - - $.ajax({ - method: 'PATCH', - url: '/contacts/1', - data: JSON.stringify({ - contact: { - name: 'Zelda' - } - }) - }).fail((xhr, textStatus, error) => { - assert.ok(error.message.indexOf("Mirage: Your Ember app tried to PATCH '/contacts/1'") !== -1); - doneForPatch(); - }); - - let doneForDelete = assert.async(); - - $.ajax({ - method: 'DELETE', - url: '/contacts/1' - }).fail((xhr, textStatus, error) => { - assert.ok(error.message.indexOf("Mirage: Your Ember app tried to DELETE '/contacts/1'") !== -1); - doneForDelete(); - }); -}); - -test('resource generates shorthands which are not blacklisted by :except option', function(assert) { - let { server } = this; - assert.expect(2); - - server.db.loadData({ - contacts: [ - { id: 1, name: 'Link' } - ] - }); - - server.resource('contacts', { except: ['create', 'update', 'delete'] }); - - let doneForIndex = assert.async(); - - $.ajax({ - method: 'GET', - url: '/contacts' - }).done((res, status, xhr) => { - assert.equal(xhr.status, 200); - doneForIndex(); - }); - - let doneForShow = assert.async(); - - $.ajax({ - method: 'GET', - url: '/contacts' - }).done((res, status, xhr) => { - assert.equal(xhr.status, 200); - doneForShow(); - }); -}); - -test('resource does not generate shorthands which are blacklisted by :except option', function(assert) { - let { server } = this; - assert.expect(4); - - server.db.loadData({ - contacts: [ - { id: 1, name: 'Link' } - ] - }); - - server.resource('contacts', { except: ['create', 'update', 'delete'] }); - - let doneForCreate = assert.async(); - - $.ajax({ - method: 'POST', - url: '/contacts', - data: JSON.stringify({ - contact: { - name: 'Zelda' - } - }) - }).fail((xhr, textStatus, error) => { - assert.ok(error.message.indexOf("Mirage: Your Ember app tried to POST '/contacts'") !== -1); - doneForCreate(); - }); - - let doneForPut = assert.async(); - - $.ajax({ - method: 'PUT', - url: '/contacts/1', - data: JSON.stringify({ - contact: { - name: 'Zelda' - } - }) - }).fail((xhr, textStatus, error) => { - assert.ok(error.message.indexOf("Mirage: Your Ember app tried to PUT '/contacts/1'") !== -1); - doneForPut(); - }); - - let doneForPatch = assert.async(); - - $.ajax({ - method: 'PATCH', - url: '/contacts/1', - data: JSON.stringify({ - contact: { - name: 'Zelda' - } - }) - }).fail((xhr, textStatus, error) => { - assert.ok(error.message.indexOf("Mirage: Your Ember app tried to PATCH '/contacts/1'") !== -1); - doneForPatch(); - }); - - let doneForDelete = assert.async(); - - $.ajax({ - method: 'DELETE', - url: '/contacts/1' - }).fail((xhr, textStatus, error) => { - assert.ok(error.message.indexOf("Mirage: Your Ember app tried to DELETE '/contacts/1'") !== -1); - doneForDelete(); - }); -}); diff --git a/tests/integration/server/shorthand-sanity-test.js b/tests/integration/server/shorthand-sanity-test.js deleted file mode 100644 index 9d7851870..000000000 --- a/tests/integration/server/shorthand-sanity-test.js +++ /dev/null @@ -1,145 +0,0 @@ -import {module, test} from 'qunit'; -import { Model, ActiveModelSerializer } from 'ember-cli-mirage'; -import Server from 'ember-cli-mirage/server'; - -module('Integration | Server | Shorthand sanity check', { - beforeEach() { - this.server = new Server({ - environment: 'test', - models: { - contact: Model - }, - serializers: { - application: ActiveModelSerializer - } - }); - this.server.timing = 0; - this.server.logging = false; - }, - afterEach() { - this.server.shutdown(); - } -}); - -test('a get shorthand works', function(assert) { - assert.expect(2); - let done = assert.async(); - - this.server.db.loadData({ - contacts: [ - { id: 1, name: 'Link' } - ] - }); - - this.server.get('/contacts'); - - $.ajax({ - method: 'GET', - url: '/contacts' - }).done(function(res, status, xhr) { - assert.equal(xhr.status, 200); - assert.deepEqual(res, { contacts: [{ id: '1', name: 'Link' }] }); - done(); - }); -}); - -test('a post shorthand works', function(assert) { - let { server } = this; - assert.expect(2); - let done = assert.async(); - - server.post('/contacts'); - - $.ajax({ - method: 'POST', - url: '/contacts', - data: JSON.stringify({ - contact: { - name: 'Zelda' - } - }) - }).done((res, status, xhr) => { - assert.equal(xhr.status, 201); - assert.equal(server.db.contacts.length, 1); - done(); - }); -}); - -test('a put shorthand works', function(assert) { - let { server } = this; - assert.expect(2); - let done = assert.async(); - - this.server.db.loadData({ - contacts: [ - { id: 1, name: 'Link' } - ] - }); - - server.put('/contacts/:id'); - - $.ajax({ - method: 'PUT', - url: '/contacts/1', - data: JSON.stringify({ - contact: { - name: 'Zelda' - } - }) - }).done((res, status, xhr) => { - assert.equal(xhr.status, 200); - assert.equal(server.db.contacts[0].name, 'Zelda'); - done(); - }); -}); - -test('a patch shorthand works', function(assert) { - let { server } = this; - assert.expect(2); - let done = assert.async(); - - this.server.db.loadData({ - contacts: [ - { id: 1, name: 'Link' } - ] - }); - - server.patch('/contacts/:id'); - - $.ajax({ - method: 'PATCH', - url: '/contacts/1', - data: JSON.stringify({ - contact: { - name: 'Zelda' - } - }) - }).done((res, status, xhr) => { - assert.equal(xhr.status, 200); - assert.equal(server.db.contacts[0].name, 'Zelda'); - done(); - }); -}); - -test('a delete shorthand works', function(assert) { - let { server } = this; - assert.expect(2); - let done = assert.async(); - - this.server.db.loadData({ - contacts: [ - { id: 1, name: 'Link' } - ] - }); - - server.del('/contacts/:id'); - - $.ajax({ - method: 'DELETE', - url: '/contacts/1' - }).done((res, status, xhr) => { - assert.equal(xhr.status, 204); - assert.equal(server.db.contacts.length, 0); - done(); - }); -}); diff --git a/tests/test-helper.js b/tests/test-helper.js index e6cfb70fe..4efd6e58a 100644 --- a/tests/test-helper.js +++ b/tests/test-helper.js @@ -1,6 +1,12 @@ -import resolver from './helpers/resolver'; -import { - setResolver -} from 'ember-qunit'; +import Application from 'dummy/app'; +import config from 'dummy/config/environment'; +import * as QUnit from 'qunit'; +import { setApplication } from '@ember/test-helpers'; +import { setup } from 'qunit-dom'; +import { start } from 'ember-qunit'; -setResolver(resolver); +setApplication(Application.create(config.APP)); + +setup(QUnit.assert); + +start(); diff --git a/tests/unit/addon-tree-test-node.js b/tests/unit/addon-tree-test-node.js deleted file mode 100644 index a67b22968..000000000 --- a/tests/unit/addon-tree-test-node.js +++ /dev/null @@ -1,67 +0,0 @@ -/* eslint-env node */ - -var expect = require('chai').expect; -var EmberAddon = require('ember-cli/lib/broccoli/ember-addon'); -var path = require('path'); - -function getMirageAddon(options) { - options = options || {}; - options['ember-cli-mirage'] = options['ember-cli-mirage'] || {}; - options['ember-cli-mirage'].directory = options['ember-cli-mirage'].directory || path.resolve(__dirname, path.join('..', 'dummy', 'mirage')); - - var dummyApp = new EmberAddon(options); - - return findMirage(dummyApp); -} - -function findMirage(app) { - var addons = app.project.addons; - for (var i = 0; i < addons.length; i++) { - if (addons[i].name === 'ember-cli-mirage') { - return addons[i]; - } - } -} - -describe('Addon', function() { - this.timeout(15000); - - afterEach(function() { - delete process.env.EMBER_ENV; - }); - - var treeForTests = function(name) { - it('returns an empty tree in production environment by default', function() { - process.env.EMBER_ENV = 'production'; - var addonTree = getMirageAddon().treeFor(name); - - expect(addonTree).to.be.undefined; - }); - - ['development', 'test'].forEach(function(environment) { - it('returns a tree in ' + environment + ' environment by default', function() { - process.env.EMBER_ENV = environment; - var addonTree = getMirageAddon().treeFor(name); - - expect(addonTree._inputNodes.length).to.not.equal(0); - }); - }); - - it('returns a tree in production environment when enabled is specified', function() { - process.env.EMBER_ENV = 'production'; - var addon = getMirageAddon({ configPath: 'tests/fixtures/config/environment-production-enabled' }); - var addonTree = addon.treeFor(name); - - expect(addonTree._inputNodes.length).to.not.equal(0); - }); - }; - - describe('#treeFor addon', function() { - treeForTests('addon'); - }); - - describe('#treeFor app', function() { - treeForTests('app'); - }); - -}); diff --git a/tests/unit/collection-test.js b/tests/unit/collection-test.js deleted file mode 100644 index 7cf5e8bde..000000000 --- a/tests/unit/collection-test.js +++ /dev/null @@ -1,64 +0,0 @@ -import Collection from 'ember-cli-mirage/orm/collection'; -import {module, test} from 'qunit'; - -module('Unit | Collection'); - -test('it can be instantiated', function(assert) { - let collection = new Collection('plant'); - - assert.ok(collection); -}); - -test('it cannot be instantiated without a modelName', function(assert) { - assert.throws(() => { - new Collection(); - }, /must pass a `modelName`/); -}); - -test('it knows its modelname', function(assert) { - let collection = new Collection('author'); - - assert.equal(collection.modelName, 'author'); -}); - -test('it can be instantiated with an array of models', function(assert) { - let models = [{ id: 1 }, { id: 2 }, { id: 3 }]; - let collection = new Collection('author', models); - - assert.ok(collection); -}); - -test('#models returns the underlying array', function(assert) { - let models = [{ id: 1 }, { id: 2 }, { id: 3 }]; - let collection = new Collection('author', models); - - assert.deepEqual(collection.models, models); -}); - -test('#length returns the number of elements', function(assert) { - let models = [{ id: 1 }, { id: 2 }]; - let collection = new Collection('post', models); - - assert.equal(collection.length, 2); - - collection.models = [{ id: 1 }]; - assert.equal(collection.length, 1); -}); - -// test('collection.filter returns collection instance', function(assert) { -// let collection = new Collection('plant'); -// let filteredCollection = collection.filter(Boolean); -// assert.ok(filteredCollection instanceof Collection); -// assert.equal(filteredCollection.modelName, 'plant'); -// }); -// -// test('collection.mergeCollection works', function(assert) { -// let collection1 = new Collection('plant', { name: 'chrerry' }, { name: 'uchreaflier' }); -// let collection2 = new Collection('plant', { name: 'vlip' }); -// assert.equal(collection1.length, 2); -// assert.equal(collection2.length, 1); -// collection2.mergeCollection(collection1); -// assert.equal(collection2.length, 3); -// assert.equal(collection2.modelName, 'plant'); -// }); -// diff --git a/tests/unit/controller-test.js b/tests/unit/controller-test.js deleted file mode 100644 index 395fca1a8..000000000 --- a/tests/unit/controller-test.js +++ /dev/null @@ -1,128 +0,0 @@ -// import Controller from 'ember-cli-mirage/controller'; -// import Db from 'ember-cli-mirage/db'; -// import Response from 'ember-cli-mirage/response'; - -// import {module, test} from 'qunit'; - -// var contacts = [{id: 1, name: 'Link', address_ids: [1]}, {id: 2, name: 'Zelda', address_ids: [2]}]; -// var addresses = [{id: 1, name: '123 Hyrule Way', contact_id: 1}, {id: 2, name: '456 Hyrule Way', contact_id: 2}]; -// var db; -// module('mirage:controller', { -// beforeEach: function() { -// db = new Db(); -// db.createCollections('contacts', 'addresses'); -// db.contacts.insert(contacts); -// db.addresses.insert(addresses); - -// var serializerDouble = { -// serialize: function(res) {return res; } -// }; -// this.controller = new Controller(serializerDouble); -// } -// }); - -// test("function handler works", function(assert) { -// var response = this.controller.handle('get', function(db, request) { -// return db.contacts; -// }, db, {params: {id: 1}}); - -// assert.deepEqual(response[2], contacts); -// }); - -// test("function handler works with custom response", function(assert) { -// var response = this.controller.handle('get', function(db, request) { -// return new Response(201, {some: 'header'}, {some: 'data'}); -// }, db); - -// assert.deepEqual(response, [201, {some: 'header'}, {some: 'data'}]); -// }); - -// test('its default response is 200 if the verb is get', function(assert) { -// var response = this.controller.handle('get', {}); -// assert.equal(response[0], 200); -// }); - -// test('its default response is 204 if the verb is put and the response is empty', function(assert) { -// var response = this.controller.handle('put', {}); -// assert.equal(response[0], 204); -// }); - -// test('its default response is 200 if the verb is put and the response is not empty and no specific code passed', function(assert) { -// var response = this.controller.handle('put', function() { -// return { text: 'thanks' }; -// }); -// assert.equal(response[0], 200, 'Returning a non-empty object changes the default code to 200'); - -// var response2 = this.controller.handle('put', function() { -// return []; -// }); -// assert.equal(response2[0], 200, 'An empty array IS NOT an empty response'); - -// var response3 = this.controller.handle('put', function() { -// return; -// }); -// assert.equal(response3[0], 204, 'undefined is considered an empty response'); - -// var response4 = this.controller.handle('put', function() { -// return ''; -// }); -// assert.equal(response4[0], 204, 'An empty string is considered and empty response'); - -// var response5 = this.controller.handle('put', function() { -// return; -// }, 204); -// assert.equal(response5[0], 204, 'If the response code is forced, that takes precedence'); - -// var response6 = this.controller.handle('put', function() { -// return {}; -// }, 204); -// assert.equal(response6[0], 204, 'An empty object is considered and empty response'); -// }); - -// test('its default response is 201 if the verb is post', function(assert) { -// var response = this.controller.handle('put', {}); -// assert.equal(response[0], 204); -// }); - -// test('its default response is 204 if the verb is delete and the response is empty', function(assert) { -// var response = this.controller.handle('delete', {}); -// assert.equal(response[0], 204); -// }); - -// test('its default response is 200 if the verb is delete and the response is not empty and no specific code passed', function(assert) { -// var response = this.controller.handle('delete', function() { -// return { text: 'thanks' }; -// }); -// assert.equal(response[0], 200, 'Returning a non-empty object changes the default code to 200'); - -// var response2 = this.controller.handle('delete', function() { -// return []; -// }); -// assert.equal(response2[0], 200, 'An empty array IS NOT an empty response'); - -// var response3 = this.controller.handle('delete', function() { -// return; -// }); -// assert.equal(response3[0], 204, 'undefined is considered an empty response'); - -// var response4 = this.controller.handle('delete', function() { -// return ''; -// }); -// assert.equal(response4[0], 204, 'An empty string is considered and empty response'); - -// var response5 = this.controller.handle('delete', function() { -// return; -// }, 204); -// assert.equal(response5[0], 204, 'If the response code is forced, that takes precedence'); - -// var response6 = this.controller.handle('delete', function() { -// return {}; -// }, 204); -// assert.equal(response6[0], 204, 'An empty object is considered and empty response'); -// }); - -// // TODO: Use spies to ensure get#shorthand is called with appropriate args -// // module('mirage:controller#get'); -// // module('mirage:controller#post'); -// // module('mirage:controller#put'); -// // module('mirage:controller#delete'); diff --git a/tests/unit/db-test.js b/tests/unit/db-test.js deleted file mode 100644 index 13d9d43b2..000000000 --- a/tests/unit/db-test.js +++ /dev/null @@ -1,597 +0,0 @@ -import Db from 'ember-cli-mirage/db'; - -import {module, test} from 'qunit'; - -let db; -module('Unit | Db'); - -test('it can be instantiated', function(assert) { - db = new Db(); - assert.ok(db); -}); - -test('it can load data on instantiation', function(assert) { - db = new Db({ - users: [{ id: 1, name: 'Link' }], - addresses: [{ id: 1, name: '123 Hyrule Way' }, { id: 2, name: 'Lorem ipsum' }] - }); - - assert.equal(db.users.length, 1); - assert.equal(db.addresses.length, 2); -}); - -test('it can empty its data', function(assert) { - db = new Db({ - users: [{ id: 1, name: 'Link' }], - addresses: [{ id: 1, name: '123 Hyrule Way' }, { id: 2, name: 'Lorem ipsum' }] - }); - - db.emptyData(); - - assert.equal(db.users.length, 0); - assert.equal(db.addresses.length, 0); -}); - -module('Unit | Db #createCollection', { - beforeEach() { - db = new Db(); - }, - afterEach() { - db.emptyData(); - } -}); - -test('it can create an empty collection', function(assert) { - db.createCollection('contacts'); - - assert.ok(db.contacts); -}); - -test('it can create many collections', function(assert) { - db.createCollections('contacts', 'addresses'); - - assert.ok(db.contacts); - assert.ok(db.addresses); -}); - -module('Unit | Db #loadData', { - beforeEach() { - db = new Db(); - }, - afterEach() { - db.emptyData(); - } -}); - -test('it can load an object of data', function(assert) { - let data = { - contacts: [{ id: '1', name: 'Link' }], - addresses: [{ id: '1', name: '123 Hyrule Way' }] - }; - db.loadData(data); - - assert.deepEqual(db.contacts, data.contacts); - assert.deepEqual(db.addresses, data.addresses); -}); - -module('Unit | Db #all', { - beforeEach() { - this.data = { - contacts: [{ id: '1', name: 'Link' }], - addresses: [{ id: '1', name: '123 Hyrule Way' }] - }; - - db = new Db(this.data); - }, - afterEach() { - db.emptyData(); - } -}); - -test('it can return a collection', function(assert) { - assert.deepEqual(db.contacts, this.data.contacts); - assert.deepEqual(db.addresses, this.data.addresses); -}); - -test('the collection is a copy', function(assert) { - let { contacts } = db; - - assert.deepEqual(contacts, this.data.contacts); - contacts[0].name = 'Zelda'; - - assert.deepEqual(db.contacts, this.data.contacts); -}); - -module('Unit | Db #insert', { - beforeEach() { - db = new Db(); - db.createCollection('contacts'); - }, - - afterEach() { - db.emptyData(); - } -}); - -test('it inserts an object and returns it', function(assert) { - let link = db.contacts.insert({ name: 'Link' }); - let expectedRecord = { - id: '1', - name: 'Link' - }; - - assert.deepEqual(db.contacts, [expectedRecord]); - assert.deepEqual(link, expectedRecord); -}); - -test('it returns a copy', function(assert) { - let link = db.contacts.insert({ name: 'Link' }); - let expectedRecord = { - id: '1', - name: 'Link' - }; - - assert.deepEqual(link, expectedRecord); - - link.name = 'Young link'; - - assert.deepEqual(db.contacts.find(1), expectedRecord); -}); - -test('it can insert objects sequentially', function(assert) { - db.contacts.insert({ name: 'Link' }); - db.contacts.insert({ name: 'Ganon' }); - - let records = [ - { id: '1', name: 'Link' }, - { id: '2', name: 'Ganon' } - ]; - - assert.deepEqual(db.contacts, records); -}); - -test('it does not add an id if present', function(assert) { - let attrs = { id: '5', name: 'Link' }; - - db.contacts.insert(attrs); - - assert.deepEqual(db.contacts, [attrs]); -}); - -test('it can insert an array and return it', function(assert) { - db.contacts.insert({ name: 'Link' }); - - let contacts = db.contacts.insert([{ name: 'Zelda' }, { name: 'Ganon' }]); - - assert.deepEqual(db.contacts, [{ id: '1', name: 'Link' }, { id: '2', name: 'Zelda' }, { id: '3', name: 'Ganon' }]); - assert.deepEqual(contacts, [{ id: '2', name: 'Zelda' }, { id: '3', name: 'Ganon' }]); -}); - -test('it does not add ids to array data if present', function(assert) { - db.contacts.insert([{ id: 2, name: 'Link' }, { id: 1, name: 'Ganon' }]); - - assert.deepEqual(db.contacts, [{ id: '1', name: 'Ganon' }, { id: '2', name: 'Link' }]); -}); - -test('it can insert a record with an id of 0', function(assert) { - db.contacts.insert({ id: 0, name: 'Link' }); - - assert.deepEqual(db.contacts, [{ id: '0', name: 'Link' }]); -}); - -test('IDs increment correctly, even after a record is removed', function(assert) { - let records = db.contacts.insert([{ name: 'Link' }, { name: 'Ganon' }]); - - db.contacts.remove(records[0]); - - let record = db.contacts.insert({ name: 'Zelda' }); - - assert.equal(record.id, 3); -}); - -test('inserting a record with an already used ID throws an error', function(assert) { - assert.expect(2); - - db.contacts.insert({ id: 1, name: 'Duncan McCleod' }); - - assert.throws(function() { - db.contacts.insert({ id: 1, name: 'Duncan McCleod' }); - }); - - db.contacts.insert({ id: 'atp', name: 'Adenosine Triphosphate' }); - - assert.throws(function() { - db.contacts.insert({ id: 'atp', name: 'Adenosine Triphosphate' }); - }); -}); - -test('tracks the correct IDs being used', function(assert) { - db.contacts.insert({ name: 'Vegeta' }); - db.contacts.insert({ id: 2, name: 'Krilli' }); - - assert.equal(db.contacts.length, 2); -}); - -module('Unit | Db #findBy', { - beforeEach() { - db = new Db(); - db.createCollection('contacts'); - db.contacts.insert([ - { name: 'Zelda' }, - { name: 'Link' }, - { name: 'Epona', race: 'Horse' }, - { name: 'Epona', race: 'Centaur' }, - { id: 'abc', name: 'Ganon' } - ]); - }, - afterEach() { - db.emptyData(); - } -}); - -test('returns a record that matches the given name', function(assert) { - let contact = db.contacts.findBy({ 'name': 'Link' }); - - assert.deepEqual(contact, { id: '2', name: 'Link' }); -}); - -test('returns a copy not a reference', function(assert) { - let contact = db.contacts.findBy({ 'name': 'Link' }); - - contact.name = 'blah'; - - assert.deepEqual(db.contacts.find(2), { id: '2', name: 'Link' }); -}); - -test('returns the first record matching the criteria', function(assert) { - let contact = db.contacts.findBy({ 'name': 'Epona' }); - - assert.deepEqual(contact, { id: '3', name: 'Epona', race: 'Horse' }); -}); - -test('returns a record only matching multiple criteria', function(assert) { - let contact = db.contacts.findBy({ 'name': 'Epona', 'race': 'Centaur' }); - - assert.deepEqual(contact, { id: '4', name: 'Epona', race: 'Centaur' }); -}); - -test('returns null when no record is found', function(assert) { - let contact = db.contacts.findBy({ 'name': 'Fi' }); - - assert.equal(contact, null); -}); - -module('Unit | Db #find', { - beforeEach() { - db = new Db(); - db.createCollection('contacts'); - db.contacts.insert([ - { name: 'Zelda' }, - { name: 'Link' }, - { id: 'abc', name: 'Ganon' } - ]); - }, - afterEach() { - db.emptyData(); - } -}); - -test('returns a record that matches a numerical id', function(assert) { - let contact = db.contacts.find(2); - - assert.deepEqual(contact, { id: '2', name: 'Link' }); -}); - -test('returns a copy not a reference', function(assert) { - let contact = db.contacts.find(2); - - assert.deepEqual(contact, { id: '2', name: 'Link' }); - - contact.name = 'blah'; - - assert.deepEqual(db.contacts.find(2), { id: '2', name: 'Link' }); -}); - -test('returns a record that matches a string id', function(assert) { - let contact = db.contacts.find('abc'); - - assert.deepEqual(contact, { id: 'abc', name: 'Ganon' }); -}); - -test('returns multiple record that matches an array of ids', function(assert) { - let contacts = db.contacts.find([1, 2]); - - assert.deepEqual(contacts, [{ id: '1', name: 'Zelda' }, { id: '2', name: 'Link' }]); -}); - -test('returns a record whose id is a string that start with numbers', function(assert) { - db.contacts.insert({ - id: '123-456', - name: 'Epona' - }); - - let contact = db.contacts.find('123-456'); - assert.deepEqual(contact, { id: '123-456', name: 'Epona' }); -}); - -test('returns multiple record that match an array of ids', function(assert) { - let contacts = db.contacts.find([1, 2]); - - assert.deepEqual(contacts, [{ id: '1', name: 'Zelda' }, { id: '2', name: 'Link' }]); -}); - -test('returns an empty array when it doesnt find multiple ids', function(assert) { - let contacts = db.contacts.find([99, 100]); - - assert.deepEqual(contacts, []); -}); - -module('Unit | Db #where', { - beforeEach() { - db = new Db(); - db.createCollection('contacts'); - db.contacts.insert([ - { name: 'Link', evil: false, age: 17 }, - { name: 'Zelda', evil: false, age: 17 }, - { name: 'Ganon', evil: true, age: 45 } - ]); - }, - afterEach() { - db.emptyData(); - } -}); - -test('returns an array of records that match the query', function(assert) { - let result = db.contacts.where({ evil: true }); - - assert.deepEqual(result, [ - { id: '3', name: 'Ganon', evil: true, age: 45 } - ]); -}); - -test('it coerces query params to strings', function(assert) { - let result = db.contacts.where({ age: '45' }); - - assert.deepEqual(result, [ - { id: '3', name: 'Ganon', evil: true, age: 45 } - ]); -}); - -test('returns a copy, not a referecne', function(assert) { - let result = db.contacts.where({ evil: true }); - - assert.deepEqual(result, [ - { id: '3', name: 'Ganon', evil: true, age: 45 } - ]); - - result[0].evil = false; - - assert.deepEqual(db.contacts.where({ evil: true }), [ - { id: '3', name: 'Ganon', evil: true, age: 45 } - ]); -}); - -test('returns an empty array if no records match the query', function(assert) { - let result = db.contacts.where({ name: 'Link', evil: true }); - - assert.deepEqual(result, []); -}); - -test('accepts a filter function', function(assert) { - let result = db.contacts.where(function(record) { - return record.age === 45; - }); - - assert.deepEqual(result, [ - { id: '3', name: 'Ganon', evil: true, age: 45 } - ]); -}); - -module('Unit | Db #update', { - beforeEach() { - db = new Db(); - db.createCollection('contacts'); - db.contacts.insert([ - { name: 'Link', evil: false }, - { name: 'Zelda', evil: false }, - { name: 'Ganon', evil: true }, - { id: '123-abc', name: 'Epona', evil: false } - ]); - }, - afterEach() { - db.emptyData(); - } -}); - -test('it can update the whole collection', function(assert) { - db.contacts.update({ name: 'Sam', evil: false }); - - let actualContacts = db.contacts; - - let expectedContacts = [ - { id: '123-abc', name: 'Sam', evil: false }, - { id: '1', name: 'Sam', evil: false }, - { id: '2', name: 'Sam', evil: false }, - { id: '3', name: 'Sam', evil: false } - ]; - - assert.deepEqual( - actualContacts, expectedContacts, [actualContacts.map(function(r) { - return r.id; - }).join(','), expectedContacts.map(function(r) { - return r.id; - }).join(',')].join(';') - ); -}); - -test('it can update a record by id', function(assert) { - db.contacts.update(3, { name: 'Ganondorf', evil: false }); - let ganon = db.contacts.find(3); - - assert.deepEqual(ganon, { id: '3', name: 'Ganondorf', evil: false }); -}); - -test('it can update a record by id when the id is a string', function(assert) { - db.contacts.update('123-abc', { evil: true }); - let epona = db.contacts.find('123-abc'); - - assert.deepEqual(epona, { id: '123-abc', name: 'Epona', evil: true }); -}); - -test('it can update multiple records by ids', function(assert) { - db.contacts.update([1, 2], { evil: true }); - let link = db.contacts.find(1); - let zelda = db.contacts.find(2); - - assert.equal(link.evil, true); - assert.equal(zelda.evil, true); -}); - -test('it can update records by query', function(assert) { - db.contacts.update({ evil: false }, { name: 'Sam' }); - - assert.deepEqual(db.contacts, [ - { id: '123-abc', name: 'Sam', evil: false }, - { id: '1', name: 'Sam', evil: false }, - { id: '2', name: 'Sam', evil: false }, - { id: '3', name: 'Ganon', evil: true } - ]); -}); - -test('updating a single record returns that record', function(assert) { - let ganon = db.contacts.update(3, { name: 'Ganondorf' }); - assert.deepEqual(ganon, { id: '3', name: 'Ganondorf', evil: true }); -}); - -test('updating a collection returns the updated records', function(assert) { - let characters = db.contacts.update({ evil: true }); - assert.deepEqual(characters, [ - { id: '123-abc', name: 'Epona', evil: true }, - { id: '1', name: 'Link', evil: true }, - { id: '2', name: 'Zelda', evil: true } - ]); -}); - -test('updating multiple records returns the updated records', function(assert) { - let characters = db.contacts.update({ evil: false }, { evil: true }); - assert.deepEqual(characters, [ - { id: '123-abc', name: 'Epona', evil: true }, - { id: '1', name: 'Link', evil: true }, - { id: '2', name: 'Zelda', evil: true } - ]); -}); - -test('throws when updating an ID is attempted', function(assert) { - assert.expect(1); - - assert.throws(function() { - db.contacts.update(1, { id: 3 }); - }); -}); - -module('Unit | Db #remove', { - beforeEach() { - db = new Db(); - db.createCollection('contacts'); - db.contacts.insert([ - { name: 'Link', evil: false }, - { name: 'Zelda', evil: false }, - { name: 'Ganon', evil: true }, - { id: '123-abc', name: 'Epona', evil: false } - ]); - }, - - afterEach() { - db.emptyData(); - } -}); - -test('it can remove an entire collection', function(assert) { - db.contacts.remove(); - - assert.deepEqual(db.contacts, []); -}); - -test('it can remove a single record by id', function(assert) { - db.contacts.remove(1); - - assert.deepEqual(db.contacts, [ - { id: '123-abc', name: 'Epona', evil: false }, - { id: '2', name: 'Zelda', evil: false }, - { id: '3', name: 'Ganon', evil: true } - ]); -}); - -test('it can remove a single record when the id is a string', function(assert) { - db.contacts.remove('123-abc'); - - assert.deepEqual(db.contacts, [ - { id: '1', name: 'Link', evil: false }, - { id: '2', name: 'Zelda', evil: false }, - { id: '3', name: 'Ganon', evil: true } - ]); -}); - -test('it can remove multiple records by ids', function(assert) { - db.contacts.remove([1, 2]); - - assert.deepEqual(db.contacts, [ - { id: '123-abc', name: 'Epona', evil: false }, - { id: '3', name: 'Ganon', evil: true } - ]); -}); - -test('it can remove multiple records by query', function(assert) { - db.contacts.remove({ evil: false }); - - assert.deepEqual(db.contacts, [ - { id: '3', name: 'Ganon', evil: true } - ]); -}); - -test('it can add a record after removing all records', function(assert) { - db.contacts.remove(); - db.contacts.insert({ name: 'Foo' }); - - assert.equal(db.contacts.length, 1); - assert.deepEqual(db.contacts, [ - { id: '1', name: 'Foo' } - ]); -}); - -module('Unit | Db #firstOrCreate', { - beforeEach() { - db = new Db(); - db.createCollection('contacts'); - db.contacts.insert([ - { id: 1, name: 'Link', evil: false }, - { id: 2, name: 'Zelda', evil: false }, - { id: 3, name: 'Ganon', evil: true } - ]); - }, - - afterEach() { - db.emptyData(); - } -}); - -test('it can find the first record available from the query', function(assert) { - let record = db.contacts.firstOrCreate({ name: 'Link' }); - - assert.deepEqual(record, { id: '1', name: 'Link', evil: false }); -}); - -test('it creates a new record from query + attrs if none found', function(assert) { - let record = db.contacts.firstOrCreate({ name: 'Mario' }, { evil: false }); - - assert.equal(record.name, 'Mario'); - assert.equal(record.evil, false); - assert.ok(record.id); -}); - -test('does not require attrs', function(assert) { - let record = db.contacts.firstOrCreate({ name: 'Luigi' }); - - assert.equal(record.name, 'Luigi'); - assert.ok(record.id); -}); diff --git a/tests/unit/db/identity-manager-test.js b/tests/unit/db/identity-manager-test.js deleted file mode 100644 index 95cb37b8b..000000000 --- a/tests/unit/db/identity-manager-test.js +++ /dev/null @@ -1,86 +0,0 @@ -import { IdentityManager } from 'ember-cli-mirage/db-collection'; - -import {module, test} from 'qunit'; - -module('Unit | DB | IdentityManager'); - -test('it can be instantiated', function(assert) { - let manager = new IdentityManager(); - assert.ok(manager); -}); - -test(`fetch returns the latest number`, function(assert) { - let manager = new IdentityManager(); - - assert.equal(manager.fetch(), 1); - assert.equal(manager.fetch(), 2); - assert.equal(manager.fetch(), 3); -}); - -test(`get returns the upcoming id used for fetch`, function(assert) { - let manager = new IdentityManager(); - - assert.equal(manager.fetch(), 1); - assert.equal(manager.get(), 2); - assert.equal(manager.fetch(), 2); -}); - -test(`set indicates an id is being used`, function(assert) { - let manager = new IdentityManager(); - manager.set('abc'); - - assert.throws(function() { - manager.set('abc'); - }, /already been used/); -}); - -test(`a numerical value passed into set affects future ids used by fetch`, function(assert) { - let manager = new IdentityManager(); - manager.set(5); - - assert.equal(manager.fetch(), 6); - assert.equal(manager.fetch(), 7); -}); - -test(`multiple numerical values passed into set affects future ids used by fetch`, function(assert) { - let manager = new IdentityManager(); - manager.set(5); - manager.set(6); - - assert.equal(manager.fetch(), 7); - assert.equal(manager.fetch(), 8); -}); - -test(`an int as a string passed into set affects future ids used by fetch`, function(assert) { - let manager = new IdentityManager(); - manager.set('5'); - - assert.equal(manager.fetch(), 6); - assert.equal(manager.fetch(), 7); -}); - -test(`multiple ints as a string passed into set affects future ids used by fetch`, function(assert) { - let manager = new IdentityManager(); - manager.set('5'); - manager.set('6'); - - assert.equal(manager.fetch(), 7); - assert.equal(manager.fetch(), 8); -}); - -test(`a string value that doesn't parse as an int passed into set doesn't affect future ids used by fetch`, function(assert) { - let manager = new IdentityManager(); - manager.set('123-abc'); - - assert.equal(manager.fetch(), 1); - assert.equal(manager.fetch(), 2); -}); - -test(`reset clears the managers memory`, function(assert) { - let manager = new IdentityManager(); - manager.set('abc'); - manager.reset(); - manager.set('abc'); - - assert.ok(true); -}); diff --git a/tests/unit/factory-test.js b/tests/unit/factory-test.js deleted file mode 100644 index 183e12f13..000000000 --- a/tests/unit/factory-test.js +++ /dev/null @@ -1,347 +0,0 @@ -import Mirage from 'ember-cli-mirage'; -import { trait } from 'ember-cli-mirage'; - -import {module, test} from 'qunit'; - -module('Unit | Factory'); - -test('it exists', function(assert) { - assert.ok(Mirage.Factory); -}); - -test('the base class builds empty objects', function(assert) { - let f = new Mirage.Factory(); - let data = f.build(); - - assert.deepEqual(data, {}); -}); - -test('a noop extension builds empty objects', function(assert) { - let EmptyFactory = Mirage.Factory.extend(); - let f = new EmptyFactory(); - let data = f.build(); - - assert.deepEqual(data, {}); -}); - -test('it works with strings, numbers and booleans', function(assert) { - let AFactory = Mirage.Factory.extend({ - name: 'Sam', - age: 28, - alive: true - }); - - let f = new AFactory(); - let data = f.build(); - - assert.deepEqual(data, { name: 'Sam', age: 28, alive: true }); -}); - -test('it supports inheritance', function(assert) { - let PersonFactory = Mirage.Factory.extend({ - species: 'human' - }); - let ManFactory = PersonFactory.extend({ - gender: 'male' - }); - let SamFactory = ManFactory.extend({ - name: 'Sam' - }); - - let p = new PersonFactory(); - let m = new ManFactory(); - let s = new SamFactory(); - - assert.deepEqual(p.build(), { species: 'human' }); - assert.deepEqual(m.build(), { species: 'human', gender: 'male' }); - assert.deepEqual(s.build(), { species: 'human', gender: 'male', name: 'Sam' }); -}); - -test('it can use sequences', function(assert) { - let PostFactory = Mirage.Factory.extend({ - likes(i) { - return 5 * i; - } - }); - - let p = new PostFactory(); - let post1 = p.build(1); - let post2 = p.build(2); - - assert.deepEqual(post1, { likes: 5 }); - assert.deepEqual(post2, { likes: 10 }); -}); - -test('it can reuse static properties', function(assert) { - let BazFactory = Mirage.Factory.extend({ - foo: 5, - bar(i) { - return this.foo * i; - } - }); - - let b = new BazFactory(); - let baz1 = b.build(1); - let baz2 = b.build(2); - - assert.deepEqual(baz1, { foo: 5, bar: 5 }); - assert.deepEqual(baz2, { foo: 5, bar: 10 }); -}); - -test('it can reuse dynamic properties', function(assert) { - let BazFactory = Mirage.Factory.extend({ - foo(i) { - return 5 * i; - }, - bar() { - return this.foo * 2; - } - }); - - let b = new BazFactory(); - let baz1 = b.build(1); - let baz2 = b.build(2); - - assert.deepEqual(baz1, { foo: 5, bar: 10 }); - assert.deepEqual(baz2, { foo: 10, bar: 20 }); -}); - -test('it can have dynamic properties that depend on another', function(assert) { - let BazFactory = Mirage.Factory.extend({ - name() { - return 'foo'; - }, - bar() { - return this.name.substr(1); - } - }); - - let b = new BazFactory(); - let baz1 = b.build(1); - - assert.deepEqual(baz1, { name: 'foo', bar: 'oo' }); -}); - -test('it can reference properties out of order', function(assert) { - let BazFactory = Mirage.Factory.extend({ - bar() { - return this.foo + 2; - }, - - baz: 6, - - foo(i) { - return this.baz * i; - } - }); - - let b = new BazFactory(); - let baz1 = b.build(1); - let baz2 = b.build(2); - - assert.deepEqual(baz1, { baz: 6, foo: 6, bar: 8 }); - assert.deepEqual(baz2, { baz: 6, foo: 12, bar: 14 }); -}); - -test('it can reference multiple properties in any order', function(assert) { - let FooFactory = Mirage.Factory.extend({ - foo() { - return this.bar + this.baz; - }, - - bar: 6, - - baz: 10 - }); - - let BarFactory = Mirage.Factory.extend({ - bar: 6, - - foo() { - return this.bar + this.baz; - }, - - baz: 10 - }); - - let BazFactory = Mirage.Factory.extend({ - bar: 6, - - baz: 10, - - foo() { - return this.bar + this.baz; - } - }); - - let Foo = new FooFactory(); - let Bar = new BarFactory(); - let Baz = new BazFactory(); - - let foo = Foo.build(1); - let bar = Bar.build(1); - let baz = Baz.build(1); - - assert.deepEqual(foo, { foo: 16, bar: 6, baz: 10 }); - assert.deepEqual(bar, { foo: 16, bar: 6, baz: 10 }); - assert.deepEqual(baz, { foo: 16, bar: 6, baz: 10 }); -}); - -test('it can reference properties on complex object', function(assert) { - let AbcFactory = Mirage.Factory.extend({ - a(i) { - return this.b + i; - }, - b() { - return this.c + 1; - }, - c() { - return this.f + 1; - }, - d(i) { - return this.e + i; - }, - e() { - return this.c + 1; - }, - f: 1, - g: 2, - h: 3 - }); - - let b = new AbcFactory(); - let abc1 = b.build(1); - let abc2 = b.build(2); - - assert.deepEqual(abc1, { a: 4, b: 3, c: 2, d: 4, e: 3, f: 1, g: 2, h: 3 }); - assert.deepEqual(abc2, { a: 5, b: 3, c: 2, d: 5, e: 3, f: 1, g: 2, h: 3 }); -}); - -test('throws meaningfull exception on circular reference', function(assert) { - let BazFactory = Mirage.Factory.extend({ - bar() { - return this.foo; - }, - - foo() { - return this.bar; - } - }); - - let b = new BazFactory(); - assert.throws(function() { - b.build(1); - }, function(e) { - return e.toString() === 'Error: Cyclic dependency in properties ["foo","bar"]'; - }); -}); - -test('#build skips invoking `afterCreate`', function(assert) { - let skipped = true; - let PostFactory = Mirage.Factory.extend({ - afterCreate() { - skipped = false; - } - }); - - let factory = new PostFactory(); - let post = factory.build(0); - - assert.ok(skipped, 'skips invoking `afterCreate`'); - assert.equal( - typeof post.afterCreate, - 'undefined', - 'does not build `afterCreate` attribute' - ); -}); - -test('extractAfterCreateCallbacks returns all afterCreate callbacks from factory with the base one being first', function(assert) { - let PostFactory = Mirage.Factory.extend({ - published: trait({ - afterCreate() { - return 'from published'; - } - }), - - withComments: trait({ - afterCreate() { - return 'from withComments'; - } - }), - - otherTrait: trait({}), - - afterCreate() { - return 'from base'; - } - }); - - let callbacks = PostFactory.extractAfterCreateCallbacks(); - assert.equal(callbacks.length, 3); - assert.deepEqual(callbacks.map((cb) => cb()), ['from base', 'from published', 'from withComments']); -}); - -test('extractAfterCreateCallbacks filters traits from which the afterCreate callbacks will be extracted from', function(assert) { - let PostFactory = Mirage.Factory.extend({ - published: trait({ - afterCreate() { - return 'from published'; - } - }), - - withComments: trait({ - afterCreate() { - return 'from withComments'; - } - }), - - otherTrait: trait({}), - - afterCreate() { - return 'from base'; - } - }); - - assert.equal(PostFactory.extractAfterCreateCallbacks({ traits: [] }).length, 1); - assert.deepEqual( - PostFactory.extractAfterCreateCallbacks({ traits: [] }).map((cb) => cb()), - ['from base'] - ); - - assert.equal(PostFactory.extractAfterCreateCallbacks({ traits: ['withComments'] }).length, 2); - assert.deepEqual( - PostFactory.extractAfterCreateCallbacks({ traits: ['withComments'] }).map((cb) => cb()), - ['from base', 'from withComments'] - ); - - assert.equal(PostFactory.extractAfterCreateCallbacks({ traits: ['withComments', 'published'] }).length, 3); - assert.deepEqual( - PostFactory.extractAfterCreateCallbacks({ traits: ['withComments', 'published'] }).map((cb) => cb()), - ['from base', 'from withComments', 'from published'] - ); - - assert.equal(PostFactory.extractAfterCreateCallbacks({ traits: ['withComments', 'otherTrait'] }).length, 2); - assert.deepEqual( - PostFactory.extractAfterCreateCallbacks({ traits: ['withComments', 'otherTrait'] }).map((cb) => cb()), - ['from base', 'from withComments'] - ); -}); - -test('isTrait returns true if there is a trait with given name', function(assert) { - let PostFactory = Mirage.Factory.extend({ - title: 'Lorem ipsum', - - published: trait({ - isPublished: true - }), - - someNestedObject: { - value: 'nested' - } - }); - - assert.ok(!PostFactory.isTrait('title')); - assert.ok(PostFactory.isTrait('published')); - assert.ok(!PostFactory.isTrait('someNestedObject')); - assert.ok(!PostFactory.isTrait('notdefined')); -}); diff --git a/tests/unit/faker-test.js b/tests/unit/faker-test.js deleted file mode 100644 index 78bfa36be..000000000 --- a/tests/unit/faker-test.js +++ /dev/null @@ -1,34 +0,0 @@ -import faker from 'ember-cli-mirage/faker'; - -import {module, test} from 'qunit'; - -module('Unit | Faker'); - -test('#cycle - returns a function', function(assert) { - let callback = faker.list.cycle('first', 'second'); - assert.ok(typeof callback === 'function', 'result is a function'); -}); - -test('#cycle - cycles the passed data', function(assert) { - let callback = faker.list.cycle('first', 'second', 'third'); - - assert.equal(callback(0), 'first', 'return the first result for sequence 0'); - assert.equal(callback(1), 'second', 'return the first result for sequence 1'); - assert.equal(callback(2), 'third', 'return the first result for sequence 2'); - assert.equal(callback(3), 'first', 'return the first result for sequence 3'); -}); - -test('#random - returns random element from a list', function(assert) { - let callback = faker.list.random('first', 'second', 'third'); - - assert.notEqual(['first', 'second', 'third'].indexOf(callback()), -1, 'returns random value'); -}); - -test('#range - creates a random number in a range', function(assert) { - let min = 0; - let max = 10; - - let callback = faker.random.number.range(min, max); - assert.equal(callback() >= min, true, 'result is higher or equal than low value'); - assert.equal(callback() <= max, true, 'result is lower or equal than high value'); -}); diff --git a/tests/unit/import-files-test-node.js b/tests/unit/import-files-test-node.js deleted file mode 100644 index e8112222c..000000000 --- a/tests/unit/import-files-test-node.js +++ /dev/null @@ -1,55 +0,0 @@ -/* eslint-env node */ - -var expect = require('chai').expect; -var EmberAddon = require('ember-cli/lib/broccoli/ember-addon'); -var _ = require('lodash'); - -describe('import files', function() { - this.timeout(15000); - - afterEach(function() { - delete process.env.EMBER_ENV; - }); - - it('doesn\'t include third party libraries in production environment by default', function() { - process.env.EMBER_ENV = 'production'; - var addon = new EmberAddon(); - - expect(_.values(addon._scriptOutputFiles)[0]).to.not.include.members([ - 'vendor/fake-xml-http-request/fake_xml_http_request.js', - 'vendor/route-recognizer/dist/route-recognizer.js', - 'vendor/pretender/pretender.js', - 'vendor/faker/build/build/faker.js', - 'vendor/ember-cli-mirage/pretender-shim.js' - ]); - }); - - ['development', 'test'].forEach(function(environment) { - it('includes third party libraries in ' + environment + ' environment by default', function() { - process.env.EMBER_ENV = environment; - var addon = new EmberAddon(); - - expect(_.values(addon._scriptOutputFiles)[0]).to.include.members([ - 'vendor/fake-xml-http-request/fake_xml_http_request.js', - 'vendor/route-recognizer/dist/route-recognizer.js', - 'vendor/pretender/pretender.js', - 'vendor/faker/build/build/faker.js', - 'vendor/ember-cli-mirage/pretender-shim.js' - ]); - }); - }); - - it('includes third party libraries in production when enabled is set to true', function() { - process.env.EMBER_ENV = 'production'; - var addon = new EmberAddon({ configPath: 'tests/fixtures/config/environment-production-enabled' }); - - expect(_.values(addon._scriptOutputFiles)[0]).to.include.members([ - 'vendor/fake-xml-http-request/fake_xml_http_request.js', - 'vendor/route-recognizer/dist/route-recognizer.js', - 'vendor/pretender/pretender.js', - 'vendor/faker/build/build/faker.js', - 'vendor/ember-cli-mirage/pretender-shim.js' - ]); - }); - -}); diff --git a/tests/unit/inflector-test.js b/tests/unit/inflector-test.js index 8c2e91510..1114302f0 100644 --- a/tests/unit/inflector-test.js +++ b/tests/unit/inflector-test.js @@ -1,17 +1,21 @@ import { singularize, pluralize } from 'ember-cli-mirage/utils/inflector'; -import {module, test} from 'qunit'; +import { module, test } from 'qunit'; -module('Unit | Inflector'); +/* + Keeping these tests here for now to avoid accidental breakage, but they are + definitely a Ember Mirage thing, not a Mirage thing. +*/ +module('Unit | Inflector', function () { + test('can singularize', function (assert) { + assert.strictEqual(singularize('tests'), 'test'); + assert.strictEqual(singularize('watches'), 'watch'); + assert.strictEqual(singularize('sheep'), 'sheep'); + }); -test('can singularize', function(assert) { - assert.equal(singularize('tests'), 'test'); - assert.equal(singularize('watches'), 'watch'); - assert.equal(singularize('sheep'), 'sheep'); -}); - -test('can pluralize', function(assert) { - assert.equal(pluralize('test'), 'tests'); - assert.equal(pluralize('watch'), 'watches'); - assert.equal(pluralize('sheep'), 'sheep'); + test('can pluralize', function (assert) { + assert.strictEqual(pluralize('test'), 'tests'); + assert.strictEqual(pluralize('watch'), 'watches'); + assert.strictEqual(pluralize('sheep'), 'sheep'); + }); }); diff --git a/tests/unit/model-test.js b/tests/unit/model-test.js deleted file mode 100644 index dc3877029..000000000 --- a/tests/unit/model-test.js +++ /dev/null @@ -1,32 +0,0 @@ -import Model from 'ember-cli-mirage/orm/model'; -import {module, test} from 'qunit'; - -module('Unit | Model'); - -test('it can be instantiated', function(assert) { - let model = new Model({}, 'user'); - assert.ok(model); -}); - -test('it cannot be instantiated without a schema', function(assert) { - assert.throws(function() { - new Model(); - }, /requires a schema/); -}); - -test('it cannot be instantiated without a modelName', function(assert) { - assert.throws(function() { - new Model({}); - }, /requires a modelName/); -}); - -test('findBelongsToAssociation returns association for given type if defined', function(assert) { - let ModelClass = Model.extend(); - let authorAssociationMock = {}; - ModelClass.prototype.belongsToAssociations = { - author: authorAssociationMock - }; - - assert.equal(ModelClass.findBelongsToAssociation('article'), null); - assert.deepEqual(ModelClass.findBelongsToAssociation('author'), authorAssociationMock); -}); diff --git a/tests/unit/reference-sort-test.js b/tests/unit/reference-sort-test.js deleted file mode 100644 index 2ea753bf0..000000000 --- a/tests/unit/reference-sort-test.js +++ /dev/null @@ -1,38 +0,0 @@ -import referenceSort from 'ember-cli-mirage/utils/reference-sort'; -import {module, test} from 'qunit'; - -module('mirage:reference-sort'); - -test('it sorts property references', function(assert) { - let sorted = referenceSort([ - ['propA'], - ['propB', 'propC'], - ['propC', 'propA'], - ['propD'] - ]); - - assert.deepEqual(sorted, ['propD', 'propA', 'propC', 'propB']); -}); - -test('it throws on circular dependency', function(assert) { - assert.throws(function() { - referenceSort([ - ['propA', 'propB'], - ['propB', 'propA'] - ]); - }, function(e) { - return e.toString() === 'Error: Cyclic dependency in properties ["propB","propA"]'; - }); - -}); - -test('it works with no references', function(assert) { - let sorted = referenceSort([ - ['propA'], - ['propB'], - ['propC'], - ['propD'] - ]); - - assert.deepEqual(sorted, ['propD', 'propC', 'propB', 'propA']); -}); diff --git a/tests/unit/response-test.js b/tests/unit/response-test.js deleted file mode 100644 index 60b0576c8..000000000 --- a/tests/unit/response-test.js +++ /dev/null @@ -1,19 +0,0 @@ -import Response from 'ember-cli-mirage/response'; - -import {module, test} from 'qunit'; - -module('Unit | Response'); - -test('it can be instantiated and return a rack response', function(assert) { - let response = new Response(404, {}, {}); - - assert.ok(response); - assert.ok(response.toRackResponse()); -}); - -test('it can be instantiated with just a response code', function(assert) { - let response = new Response(404); - - assert.ok(response); - assert.ok(response.toRackResponse()); -}); diff --git a/tests/unit/route-handlers/shorthands/base-test.js b/tests/unit/route-handlers/shorthands/base-test.js deleted file mode 100644 index 1c2e5bc0b..000000000 --- a/tests/unit/route-handlers/shorthands/base-test.js +++ /dev/null @@ -1,145 +0,0 @@ -import BaseShorthandRouteHandler from 'ember-cli-mirage/route-handlers/shorthands/base'; - -import {module, test} from 'qunit'; - -module('Unit | Route handlers | Shorthands | BaseShorthandRouteHandler', { - beforeEach() { - this.handler = new BaseShorthandRouteHandler(); - this.request = { params: { id: '' } }; - } -}); - -test('it returns a number if it\'s a number', function(assert) { - this.request.params.id = 2; - assert.equal(this.handler._getIdForRequest(this.request), 2, 'it returns a number'); -}); - -test('it returns a number if it\'s a string represented number', function(assert) { - this.request.params.id = '2'; - assert.equal(this.handler._getIdForRequest(this.request), 2, 'it returns a number'); -}); - -test('it returns a string it\'s a dasherized number', function(assert) { - this.request.params.id = '2-1'; - assert.equal(this.handler._getIdForRequest(this.request), '2-1', 'it returns a number'); -}); - -test('it returns a string if it\'s a string', function(assert) { - this.request.params.id = 'someID'; - assert.equal(this.handler._getIdForRequest(this.request), 'someID', 'it returns a number'); -}); - -test('getModelClassFromPath works', function(assert) { - let urlWithSlash = '/api/fancy-users'; - let urlWithIdAndSlash = '/api/fancy-users/:id'; - - assert.equal(this.handler.getModelClassFromPath(urlWithSlash), 'fancy-user', 'it returns a singular model name'); - assert.equal(this.handler.getModelClassFromPath(urlWithIdAndSlash, true), 'fancy-user', 'it returns a singular model name'); -}); - -test('it can read the id from the url', function(assert) { - let request = { params: { id: 'test-id' } }; - assert.equal(this.handler._getIdForRequest(request), 'test-id', 'it returns id from url parameters.'); -}); - -test('it can read the id from the request body', function(assert) { - let request = { params: {} }; - let jsonApiDoc = { data: { id: 'jsonapi-id' } }; - assert.equal(this.handler._getIdForRequest(request, jsonApiDoc), 'jsonapi-id', 'it returns id from json api data.'); -}); - -test('_getAttrsForRequest works with attributes and relationships', function(assert) { - let payload = { - 'data': { - 'attributes': { - 'does-mirage': true, - 'name': 'Sam' - }, - 'relationships': { - 'company': { - 'data': { - 'id': '1', - 'type': 'companies' - } - }, - 'github-account': { - 'data': { - 'id': '1', - 'type': 'github-accounts' - } - }, - 'something': { - 'data': null - }, - 'many-things': { - 'data': [] - } - }, - 'type': 'github-account' - } - }; - - this.handler._getJsonApiDocForRequest = function() { - return payload; - }; - - let attrs = this.handler._getAttrsForRequest(this.request, 'user'); - - assert.deepEqual( - attrs, - { - name: 'Sam', - doesMirage: true, - companyId: '1', - githubAccountId: '1', - somethingId: null - }, - 'it normalizes data correctly.' - ); -}); - -test('_getAttrsForRequest works with just relationships', function(assert) { - let payload = { - 'data': { - 'relationships': { - 'company': { - 'data': { - 'id': '1', - 'type': 'companies' - } - } - }, - 'type': 'github-account' - } - }; - - this.handler._getJsonApiDocForRequest = function() { - return payload; - }; - - let attrs = this.handler._getAttrsForRequest(this.request, 'user'); - - assert.deepEqual( - attrs, - { - companyId: '1' - }, - 'it normalizes data correctly.' - ); -}); - -test('_getAttrsForRequest works with just type', function(assert) { - let payload = { - 'data': { - 'type': 'github-account' - } - }; - - this.handler._getJsonApiDocForRequest = function(request, modelName) { - return payload; - }; - - let attrs = this.handler._getAttrsForRequest(this.request, 'user'); - - assert.deepEqual(attrs, {}); -}); diff --git a/tests/unit/schema-test.js b/tests/unit/schema-test.js deleted file mode 100644 index 28f0d340b..000000000 --- a/tests/unit/schema-test.js +++ /dev/null @@ -1,36 +0,0 @@ -import Schema from 'ember-cli-mirage/orm/schema'; -import Db from 'ember-cli-mirage/db'; -import { Model, belongsTo } from 'ember-cli-mirage'; -import {module, test} from 'qunit'; - -module('Unit | Schema'); - -test('it can be instantiated', function(assert) { - let dbMock = {}; - let schema = new Schema(dbMock); - assert.ok(schema); -}); - -test('it cannot be instantiated without a db', function(assert) { - assert.throws(function() { - new Schema(); - }, /requires a db/); -}); - -test('modelFor returns model for given type if registered', function(assert) { - let db = new Db(); - let schema = new Schema(db); - - assert.equal(schema.modelFor('article'), null); - - let authorModel = Model.extend({ - }); - let articleModel = Model.extend({ - author: belongsTo() - }); - schema.registerModel('article', articleModel); - schema.registerModel('author', authorModel); - - assert.deepEqual(schema.modelFor('article').foreignKeys, ['authorId']); - assert.deepEqual(schema.modelFor('author').foreignKeys, []); -}); diff --git a/tests/unit/serializers/active-model-serializer-test.js b/tests/unit/serializers/active-model-serializer-test.js deleted file mode 100644 index 439757f41..000000000 --- a/tests/unit/serializers/active-model-serializer-test.js +++ /dev/null @@ -1,70 +0,0 @@ -import ActiveModelSerializer from 'ember-cli-mirage/serializers/active-model-serializer'; - -import {module, test} from 'qunit'; - -module('Unit | Serializers | ActiveModelSerializer', { - beforeEach() { - this.serializer = new ActiveModelSerializer(); - } -}); - -test('normalize works', function(assert) { - let payload = { - contact: { - id: 1, - name: 'Link' - } - }; - let jsonApiDoc = this.serializer.normalize(payload); - - assert.deepEqual(jsonApiDoc, { - data: { - type: 'contacts', - id: 1, - attributes: { - name: 'Link' - } - } - }); -}); - -test('it hyphenates snake_cased words', function(assert) { - let payload = { - contact: { - id: 1, - first_name: 'Link' - } - }; - let jsonApiDoc = this.serializer.normalize(payload); - - assert.deepEqual(jsonApiDoc, { - data: { - type: 'contacts', - id: 1, - attributes: { - 'first-name': 'Link' - } - } - }); -}); - -test('it works without an id', function(assert) { - let payload = { - contact: { - first_name: 'Link', - last_name: 'zor' - } - }; - let jsonApiDoc = this.serializer.normalize(payload); - - assert.deepEqual(jsonApiDoc, { - data: { - type: 'contacts', - attributes: { - 'first-name': 'Link', - 'last-name': 'zor' - } - } - }); -}); - diff --git a/tests/unit/serializers/ember-data-serializer-discover-test.js b/tests/unit/serializers/ember-data-serializer-discover-test.js new file mode 100644 index 000000000..60000ce5e --- /dev/null +++ b/tests/unit/serializers/ember-data-serializer-discover-test.js @@ -0,0 +1,29 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; +import { createServer } from 'miragejs'; +import { applyEmberDataSerializers } from 'ember-cli-mirage'; + +module('Unit | Serializer | ember data serializer discover', function (hooks) { + setupTest(hooks); + + let server; + + hooks.beforeEach(function () { + server = createServer({ + serializers: applyEmberDataSerializers({}), + }); + }); + + hooks.afterEach(function () { + server.shutdown(); + }); + + test('it discovers the serializers', function (assert) { + let serializer = server.serializerOrRegistry.serializerFor('address'); + + assert.strictEqual(serializer.primaryKey, 'addressId'); + + serializer = server.serializerOrRegistry.serializerFor('word-smith'); + assert.strictEqual(serializer.transforms['blogPosts'].serialize, 'records'); + }); +}); diff --git a/tests/unit/serializers/ember-data-serializer-test.js b/tests/unit/serializers/ember-data-serializer-test.js new file mode 100644 index 000000000..331cf8d8b --- /dev/null +++ b/tests/unit/serializers/ember-data-serializer-test.js @@ -0,0 +1,146 @@ +/* eslint-disable ember/avoid-leaking-state-in-ember-objects */ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; +import { Model, hasMany, belongsTo } from 'miragejs'; +import Server from 'ember-cli-mirage/server'; +import { EmberDataSerializer } from 'ember-cli-mirage'; + +module('Unit | Serializer | ember data serializer', function (hooks) { + setupTest(hooks); + + let server; + let address, wordSmith; + + hooks.beforeEach(function () { + server = new Server({ + environment: 'test', + models: { + address: Model.extend({ + wordSmith: belongsTo(), + }), + wordSmith: Model.extend({ + blogPosts: hasMany(), + address: belongsTo(), + }), + blogPost: Model.extend({ + wordSmith: belongsTo(), + }), + }, + serializers: { + application: EmberDataSerializer, + wordSmith: EmberDataSerializer, + blogPost: EmberDataSerializer, + }, + }); + + address = server.create('address', { + id: '11', + street: '123 maple', + }); + + wordSmith = server.create('word-smith', { + id: 1, + name: 'Zelda', + age: 230, + address: address, + }); + + server.create('blog-post', { + id: 2, + wordSmith: wordSmith, + }); + }); + + hooks.afterEach(function () { + server.shutdown(); + }); + + test('it renames the properties', function (assert) { + server.config({ + serializers: { + wordSmith: EmberDataSerializer.extend({ + transforms: { + name: 'externalName', + address: { key: 'addressId', serialize: 'ids' }, + age: { key: 'externalAge' }, + blogPosts: { key: 'blogPostIds' }, + }, + }), + }, + }); + + let json = server.serializerOrRegistry.serialize(wordSmith); + + assert.deepEqual(json, { + wordSmith: { + addressId: '11', + externalAge: 230, + blogPostIds: ['2'], + id: '1', + externalName: 'Zelda', + }, + }); + }); + + test('it embeds the properties that are relations', function (assert) { + server.config({ + serializers: { + wordSmith: EmberDataSerializer.extend({ + transforms: { + address: { key: 'address', serialize: 'records' }, + blogPosts: { key: 'blogPosts', serialize: 'records' }, + }, + }), + address: EmberDataSerializer.extend({ + transforms: { + wordSmith: 'wordSmithId', + }, + }), + blogPost: EmberDataSerializer.extend({ + transforms: { + wordSmith: 'wordSmithId', + }, + }), + }, + }); + + let json = server.serializerOrRegistry.serialize(wordSmith); + + assert.deepEqual(json, { + wordSmith: { + address: { id: '11', street: '123 maple', wordSmithId: '1' }, + age: 230, + blogPosts: [{ id: '2', wordSmithId: '1' }], + id: '1', + name: 'Zelda', + }, + }); + }); + + test('it honors the includes option', function (assert) { + server.config({ + serializers: { + wordSmith: EmberDataSerializer.extend({ + include: ['address'], + }), + address: EmberDataSerializer.extend({ + transforms: { + wordSmith: 'wordSmithId', + }, + }), + }, + }); + + let json = server.serializerOrRegistry.serialize(wordSmith); + assert.deepEqual(json, { + wordSmith: { + address: '11', + age: 230, + blogPosts: ['2'], + id: '1', + name: 'Zelda', + }, + address: [{ id: '11', street: '123 maple', wordSmithId: '1' }], + }); + }); +}); diff --git a/tests/unit/serializers/rest-serializer-test.js b/tests/unit/serializers/rest-serializer-test.js deleted file mode 100644 index 60a852285..000000000 --- a/tests/unit/serializers/rest-serializer-test.js +++ /dev/null @@ -1,31 +0,0 @@ -import RestSerializer from 'ember-cli-mirage/serializers/rest-serializer'; - -import {module, test} from 'qunit'; - -module('Unit | Serializers | RestSerializer', { - beforeEach() { - this.serializer = new RestSerializer(); - } -}); - -test('it hyphenates camelized words', function(assert) { - let payload = { - 'person': { - 'id': 1, - 'firstName': 'Rick', - 'lastName': 'Sanchez' - } - }; - let jsonApiDoc = this.serializer.normalize(payload); - - assert.deepEqual(jsonApiDoc, { - data: { - type: 'people', - id: 1, - attributes: { - 'first-name': 'Rick', - 'last-name': 'Sanchez' - } - } - }); -}); diff --git a/tests/unit/server-test.js b/tests/unit/server-test.js deleted file mode 100644 index 16ad60bd0..000000000 --- a/tests/unit/server-test.js +++ /dev/null @@ -1,1278 +0,0 @@ -import Server, { defaultPassthroughs } from 'ember-cli-mirage/server'; -import {module, test} from 'qunit'; -import { Model, Factory, belongsTo, hasMany, trait, association } from 'ember-cli-mirage'; - -module('Unit | Server'); - -test('it can be instantiated', function(assert) { - let server = new Server({ environment: 'test' }); - - assert.ok(server); - - server.shutdown(); -}); - -test('it runs the default scenario in non-test environments', function(assert) { - assert.expect(1); - - let server = new Server({ - environment: 'development', - scenarios: { - default() { - assert.ok(true); - } - } - }); - - server.shutdown(); -}); - -module('Unit | Server #loadConfig'); - -test('forces timing to 0 in test environment', function(assert) { - let server = new Server({ environment: 'test' }); - - server.loadConfig(function() { - this.timing = 50; - }); - - assert.equal(server.timing, 0); - - server.shutdown(); -}); - -test("doesn't modify user's timing config in other environments", function(assert) { - let server = new Server({ environment: 'blah' }); - - server.loadConfig(function() { - this.timing = 50; - }); - - assert.equal(server.timing, 50); - - server.shutdown(); -}); - -module('Unit | Server #db'); - -test('its db is isolated across instances', function(assert) { - let server1 = new Server({ environment: 'test' }); - - server1.db.createCollection('contacts'); - server1.db.contacts.insert({ name: 'Sam' }); - - server1.shutdown(); - - let server2 = new Server({ environment: 'test' }); - - assert.equal(server2.contacts, undefined); - - server2.shutdown(); -}); - -module('Unit | Server #create'); - -test('create fails when no factories or models are registered', function(assert) { - let server = new Server({ environment: 'test' }); - - assert.throws(function() { - server.create('contact'); - }); - - server.shutdown(); -}); - -test('create fails when an expected factory isn\'t registered', function(assert) { - let server = new Server({ - environment: 'test', - factories: { - address: Factory - } - }); - - assert.throws(function() { - server.create('contact'); - }, /no model or factory was found/); - - server.shutdown(); -}); - -test('create works when models but no factories are registered', function(assert) { - let server = new Server({ - environment: 'test', - models: { - contact: Model - } - }); - - server.create('contact'); - - assert.equal(server.db.contacts.length, 1); - - server.shutdown(); -}); - -test('create adds the data to the db', function(assert) { - let server = new Server({ - environment: 'test', - factories: { - contact: Factory.extend({ - name: 'Sam' - }) - } - }); - - server.create('contact'); - let contactsInDb = server.db.contacts; - - assert.equal(contactsInDb.length, 1); - assert.deepEqual(contactsInDb[0], { id: '1', name: 'Sam' }); - - server.shutdown(); -}); - -test('create returns the new data in the db', function(assert) { - let server = new Server({ - environment: 'test', - factories: { - contact: Factory.extend({ - name: 'Sam' - }) - } - }); - - let contact = server.create('contact'); - - assert.deepEqual(contact, { id: '1', name: 'Sam' }); - - server.shutdown(); -}); - -test('create allows for attr overrides', function(assert) { - let server = new Server({ - environment: 'test', - factories: { - contact: Factory.extend({ - name: 'Sam' - }) - } - }); - - let sam = server.create('contact'); - let link = server.create('contact', { name: 'Link' }); - - assert.deepEqual(sam, { id: '1', name: 'Sam' }); - assert.deepEqual(link, { id: '2', name: 'Link' }); - - server.shutdown(); -}); - -test('create allows for attr overrides with extended factories', function(assert) { - let ContactFactory = Factory.extend({ - name: 'Link', - age: 500 - }); - let FriendFactory = ContactFactory.extend({ - is_young() { - return this.age < 18; - } - }); - - let server = new Server({ - environment: 'test', - factories: { - contact: ContactFactory, - friend: FriendFactory - } - }); - - let link = server.create('friend'); - let youngLink = server.create('friend', { age: 10 }); - - assert.deepEqual(link, { id: '1', name: 'Link', age: 500, is_young: false }); - assert.deepEqual(youngLink, { id: '2', name: 'Link', age: 10, is_young: true }); - - server.shutdown(); -}); - -test('create allows for attr overrides with arrays', function(assert) { - let server = new Server({ - environment: 'test', - factories: { - contact: Factory.extend({ - name: ['Sam', 'Carl'] - }) - } - }); - - let sam = server.create('contact'); - let link = server.create('contact', { name: ['Link'] }); - let noname = server.create('contact', { name: [] }); - - assert.deepEqual(sam, { id: '1', name: ['Sam', 'Carl'] }); - assert.deepEqual(link, { id: '2', name: ['Link'] }); - assert.deepEqual(noname, { id: '3', name: [] }); - - server.shutdown(); -}); - -test('create allows for nested attr overrides', function(assert) { - let server = new Server({ - environment: 'test', - factories: { - contact: Factory.extend({ - address: { - streetName: 'Main', - streetAddress(i) { - return 1000 + i; - } - } - }) - } - }); - - let contact1 = server.create('contact'); - let contact2 = server.create('contact'); - - assert.deepEqual(contact1, { id: '1', address: { streetName: 'Main', streetAddress: 1000 } }); - assert.deepEqual(contact2, { id: '2', address: { streetName: 'Main', streetAddress: 1001 } }); - - server.shutdown(); -}); - -test('factories can have dynamic properties that depend on attr overrides', function(assert) { - let server = new Server({ - environment: 'test', - factories: { - baz: Factory.extend({ - bar() { - return this.name.substr(1); - } - }) - } - }); - - let baz1 = server.create('baz', { name: 'foo' }); - - assert.deepEqual(baz1, { id: '1', name: 'foo', bar: 'oo' }); - - server.shutdown(); -}); - -test('create allows for arrays of attr overrides', function(assert) { - let server = new Server({ - environment: 'test', - factories: { - contact: Factory.extend({ - websites: [ - 'http://example.com', - function(i) { - return `http://placekitten.com/${320 + i}/${240 + i}`; - } - ] - }) - } - }); - - let contact1 = server.create('contact'); - let contact2 = server.create('contact'); - - assert.deepEqual(contact1, { id: '1', websites: ['http://example.com', 'http://placekitten.com/320/240'] }); - assert.deepEqual(contact2, { id: '2', websites: ['http://example.com', 'http://placekitten.com/321/241'] }); - - server.shutdown(); -}); - -test('create allows to extend factory with trait', function(assert) { - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - published: trait({ - isPublished: true, - publishedAt: '2010-01-01 10:00:00' - }) - }); - - let server = new Server({ - environment: 'test', - factories: { - article: ArticleFactory - } - }); - - let article = server.create('article'); - let publishedArticle = server.create('article', 'published'); - - assert.deepEqual(article, { id: '1', title: 'Lorem ipsum' }); - assert.deepEqual(publishedArticle, { id: '2', title: 'Lorem ipsum', isPublished: true, - publishedAt: '2010-01-01 10:00:00' }); - - server.shutdown(); -}); - -test('create allows to extend factory with multiple traits', function(assert) { - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - published: trait({ - isPublished: true, - publishedAt: '2010-01-01 10:00:00' - }), - - withContent: trait({ - content: 'content' - }) - }); - - let server = new Server({ - environment: 'test', - factories: { - article: ArticleFactory - } - }); - - let article = server.create('article'); - let publishedArticle = server.create('article', 'published'); - let publishedArticleWithContent = server.create('article', 'published', 'withContent'); - - assert.deepEqual(article, { id: '1', title: 'Lorem ipsum' }); - assert.deepEqual(publishedArticle, { id: '2', title: 'Lorem ipsum', isPublished: true, - publishedAt: '2010-01-01 10:00:00' }); - assert.deepEqual(publishedArticleWithContent, { id: '3', title: 'Lorem ipsum', isPublished: true, - publishedAt: '2010-01-01 10:00:00', content: 'content' }); - - server.shutdown(); -}); - -test('create allows to extend factory with traits containing afterCreate callbacks', function(assert) { - let CommentFactory = Factory.extend({ - content: 'content' - }); - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - withComments: trait({ - afterCreate(article, server) { - server.createList('comment', 3, { article }); - } - }) - }); - - let server = new Server({ - environment: 'test', - factories: { - article: ArticleFactory, - comment: CommentFactory - } - }); - - let articleWithComments = server.create('article', 'withComments'); - - assert.deepEqual(articleWithComments, { id: '1', title: 'Lorem ipsum' }); - assert.equal(server.db.comments.length, 3); - - server.shutdown(); -}); - -test('create does not execute afterCreate callbacks from traits that are not applied', function(assert) { - let CommentFactory = Factory.extend({ - content: 'content' - }); - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - withComments: trait({ - afterCreate(article, server) { - server.createList('comment', 3, { article }); - } - }) - }); - - let server = new Server({ - environment: 'test', - factories: { - article: ArticleFactory, - comment: CommentFactory - } - }); - - let articleWithComments = server.create('article'); - - assert.deepEqual(articleWithComments, { id: '1', title: 'Lorem ipsum' }); - assert.equal(server.db.comments.length, 0); - - server.shutdown(); -}); - -test('create allows to extend with multiple traits and to apply attr overrides', function(assert) { - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - published: trait({ - isPublished: true, - publishedAt: '2010-01-01 10:00:00' - }), - - withContent: trait({ - content: 'content' - }) - }); - - let server = new Server({ - environment: 'test', - factories: { - article: ArticleFactory - } - }); - - let overrides = { - publishedAt: '2012-01-01 10:00:00' - }; - let publishedArticleWithContent = server.create('article', 'published', 'withContent', overrides); - - assert.deepEqual(publishedArticleWithContent, { id: '1', title: 'Lorem ipsum', isPublished: true, - publishedAt: '2012-01-01 10:00:00', content: 'content' }); - - server.shutdown(); -}); - -test('create throws errors when using trait that is not defined and distinquishes between traits and non-traits', function(assert) { - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - published: trait({ - isPublished: true, - publishedAt: '2010-01-01 10:00:00' - }), - - private: { - someAttr: 'value' - } - }); - - let server = new Server({ - environment: 'test', - factories: { - article: ArticleFactory - } - }); - - assert.throws(() => { - server.create('article', 'private'); - }, /'private' trait is not registered in 'article' factory/); - - server.shutdown(); -}); - -test('create allows to create objects with associations', function(assert) { - let AuthorFactory = Factory.extend({ - name: 'Sam' - }); - let CategoryFactory = Factory.extend({ - name: 'splendid software' - }); - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - withCategory: trait({ - awesomeCategory: association() - }), - - author: association() - }); - - let server = new Server({ - environment: 'test', - models: { - author: Model.extend({ - articles: hasMany() - }), - category: Model.extend({ - }), - article: Model.extend({ - author: belongsTo(), - awesomeCategory: belongsTo('category') - }) - }, - factories: { - article: ArticleFactory, - author: AuthorFactory, - category: CategoryFactory - } - }); - - let article = server.create('article', 'withCategory'); - - assert.deepEqual(article.attrs, { title: 'Lorem ipsum', id: '1', authorId: '1', awesomeCategoryId: '1' }); - assert.equal(server.db.authors.length, 1); - assert.equal(server.db.categories.length, 1); - - let anotherArticle = server.create('article', 'withCategory'); - assert.deepEqual(anotherArticle.attrs, { title: 'Lorem ipsum', id: '2', authorId: '2', awesomeCategoryId: '2' }); - assert.equal(server.db.authors.length, 2); - assert.equal(server.db.categories.length, 2); -}); - -test('create allows to create objects with associations with traits and overrides for associations', function(assert) { - let CategoryFactory = Factory.extend({ - name: 'splendid software', - - published: trait({ - isPublished: true, - publishedAt: '2014-01-01 10:00:00' - }) - }); - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - withCategory: trait({ - category: association('published', { publishedAt: '2016-01-01 12:00:00' }) - }) - }); - - let server = new Server({ - environment: 'test', - factories: { - article: ArticleFactory, - category: CategoryFactory - }, - models: { - category: Model.extend({ - }), - article: Model.extend({ - category: belongsTo('category') - }) - } - }); - - let article = server.create('article', 'withCategory'); - - assert.deepEqual(article.attrs, { title: 'Lorem ipsum', id: '1', categoryId: '1' }); - assert.equal(server.db.categories.length, 1); - assert.deepEqual( - server.db.categories[0], - { name: 'splendid software', id: '1', isPublished: true, publishedAt: '2016-01-01 12:00:00' } - ); -}); - -module('Unit | Server #createList', { - beforeEach() { - this.server = new Server({ environment: 'test' }); - }, - afterEach() { - this.server.shutdown(); - } -}); - -test('createList adds the given number of elements to the db', function(assert) { - this.server.loadFactories({ - contact: Factory.extend({ name: 'Sam' }) - }); - - this.server.createList('contact', 3); - let contactsInDb = this.server.db.contacts; - - assert.equal(contactsInDb.length, 3); - assert.deepEqual(contactsInDb[0], { id: '1', name: 'Sam' }); - assert.deepEqual(contactsInDb[1], { id: '2', name: 'Sam' }); - assert.deepEqual(contactsInDb[2], { id: '3', name: 'Sam' }); -}); - -test('createList returns the created elements', function(assert) { - this.server.loadFactories({ - contact: Factory.extend({ name: 'Sam' }) - }); - - this.server.create('contact'); - let contacts = this.server.createList('contact', 3); - - assert.equal(contacts.length, 3); - assert.deepEqual(contacts[0], { id: '2', name: 'Sam' }); - assert.deepEqual(contacts[1], { id: '3', name: 'Sam' }); - assert.deepEqual(contacts[2], { id: '4', name: 'Sam' }); -}); - -test('createList respects sequences', function(assert) { - this.server.loadFactories({ - contact: Factory.extend({ - name(i) { - return `name${i}`; - } - }) - }); - - let contacts = this.server.createList('contact', 3); - - assert.deepEqual(contacts[0], { id: '1', name: 'name0' }); - assert.deepEqual(contacts[1], { id: '2', name: 'name1' }); - assert.deepEqual(contacts[2], { id: '3', name: 'name2' }); -}); - -test('createList respects attr overrides', function(assert) { - this.server.loadFactories({ - contact: Factory.extend({ name: 'Sam' }) - }); - - let sams = this.server.createList('contact', 2); - let links = this.server.createList('contact', 2, { name: 'Link' }); - - assert.deepEqual(sams[0], { id: '1', name: 'Sam' }); - assert.deepEqual(sams[1], { id: '2', name: 'Sam' }); - assert.deepEqual(links[0], { id: '3', name: 'Link' }); - assert.deepEqual(links[1], { id: '4', name: 'Link' }); -}); - -test('createList respects traits', function(assert) { - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - published: trait({ - isPublished: true, - publishedAt: '2010-01-01 10:00:00' - }), - - withContent: trait({ - content: 'content' - }) - }); - - this.server.loadFactories({ - article: ArticleFactory - }); - - let articles = this.server.createList('article', 2, 'published', 'withContent'); - - assert.deepEqual(articles[0], { id: '1', title: 'Lorem ipsum', isPublished: true, - publishedAt: '2010-01-01 10:00:00', content: 'content' }); - assert.deepEqual(articles[1], { id: '2', title: 'Lorem ipsum', isPublished: true, - publishedAt: '2010-01-01 10:00:00', content: 'content' }); -}); - -test('createList respects traits with attr overrides', function(assert) { - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - published: trait({ - isPublished: true, - publishedAt: '2010-01-01 10:00:00' - }), - - withContent: trait({ - content: 'content' - }) - }); - - this.server.loadFactories({ - article: ArticleFactory - }); - - let overrides = { publishedAt: '2012-01-01 10:00:00' }; - let articles = this.server.createList('article', 2, 'published', 'withContent', overrides); - - assert.deepEqual(articles[0], { id: '1', title: 'Lorem ipsum', isPublished: true, - publishedAt: '2012-01-01 10:00:00', content: 'content' }); - assert.deepEqual(articles[1], { id: '2', title: 'Lorem ipsum', isPublished: true, - publishedAt: '2012-01-01 10:00:00', content: 'content' }); -}); - -test('createList throws errors when using trait that is not defined and distinquishes between traits and non-traits', function(assert) { - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - published: trait({ - isPublished: true, - publishedAt: '2010-01-01 10:00:00' - }), - - private: { - someAttr: 'value' - } - }); - - this.server.loadFactories({ - article: ArticleFactory - }); - - assert.throws(() => { - this.server.createList('article', 2, 'private'); - }, /'private' trait is not registered in 'article' factory/); -}); - -test('createList throws an error if the second argument is not an integer', function(assert) { - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - published: trait({ - isPublished: true, - publishedAt: '2010-01-01 10:00:00' - }) - }); - - this.server.loadFactories({ - article: ArticleFactory - }); - - assert.throws(() => { - this.server.createList('article', 'published'); - }, /second argument has to be an integer, you passed: string/); -}); - -module('Unit | Server #build', { - beforeEach() { - this.server = new Server({ environment: 'test' }); - }, - afterEach() { - this.server.shutdown(); - } -}); - -test('build does not add the data to the db', function(assert) { - this.server.loadFactories({ - contact: Factory.extend({ name: 'Sam' }) - }); - - this.server.build('contact'); - let contactsInDb = this.server.db.contacts; - - assert.equal(contactsInDb.length, 0); -}); - -test('build returns the new attrs with no id', function(assert) { - this.server.loadFactories({ - contact: Factory.extend({ name: 'Sam' }) - }); - - let contact = this.server.build('contact'); - - assert.deepEqual(contact, { name: 'Sam' }); -}); - -test('build allows for attr overrides', function(assert) { - this.server.loadFactories({ - contact: Factory.extend({ name: 'Sam' }) - }); - - let sam = this.server.build('contact'); - let link = this.server.build('contact', { name: 'Link' }); - - assert.deepEqual(sam, { name: 'Sam' }); - assert.deepEqual(link, { name: 'Link' }); -}); - -test('build allows for attr overrides with extended factories', function(assert) { - let ContactFactory = Factory.extend({ - name: 'Link', - age: 500 - }); - let FriendFactory = ContactFactory.extend({ - is_young() { - return this.age < 18; - } - }); - this.server.loadFactories({ - contact: ContactFactory, - friend: FriendFactory - }); - - let link = this.server.build('friend'); - let youngLink = this.server.build('friend', { age: 10 }); - - assert.deepEqual(link, { name: 'Link', age: 500, is_young: false }); - assert.deepEqual(youngLink, { name: 'Link', age: 10, is_young: true }); -}); - -test('build allows for attr overrides with arrays', function(assert) { - this.server.loadFactories({ - contact: Factory.extend({ name: ['Sam', 'Carl'] }) - }); - - let sam = this.server.build('contact'); - let link = this.server.build('contact', { name: ['Link'] }); - let noname = this.server.build('contact', { name: [] }); - - assert.deepEqual(sam, { name: ['Sam', 'Carl'] }); - assert.deepEqual(link, { name: ['Link'] }); - assert.deepEqual(noname, { name: [] }); -}); - -test('build allows for nested attr overrides', function(assert) { - this.server.loadFactories({ - contact: Factory.extend({ - address: { - streetName: 'Main', - streetAddress(i) { - return 1000 + i; - } - } - }) - }); - - let contact1 = this.server.build('contact'); - let contact2 = this.server.build('contact'); - - assert.deepEqual(contact1, { address: { streetName: 'Main', streetAddress: 1000 } }); - assert.deepEqual(contact2, { address: { streetName: 'Main', streetAddress: 1001 } }); -}); - -test('build allows for arrays of attr overrides', function(assert) { - this.server.loadFactories({ - contact: Factory.extend({ - websites: [ - 'http://example.com', - function(i) { - return `http://placekitten.com/${320 + i}/${240 + i}`; - } - ] - }) - }); - - let contact1 = this.server.build('contact'); - let contact2 = this.server.build('contact'); - - assert.deepEqual(contact1, { websites: ['http://example.com', 'http://placekitten.com/320/240'] }); - assert.deepEqual(contact2, { websites: ['http://example.com', 'http://placekitten.com/321/241'] }); -}); - -test('build allows to extend factory with trait', function(assert) { - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - published: trait({ - isPublished: true, - publishedAt: '2010-01-01 10:00:00' - }) - }); - - this.server.loadFactories({ - article: ArticleFactory - }); - - let article = this.server.build('article'); - let publishedArticle = this.server.build('article', 'published'); - - assert.deepEqual(article, { title: 'Lorem ipsum' }); - assert.deepEqual(publishedArticle, { title: 'Lorem ipsum', isPublished: true, - publishedAt: '2010-01-01 10:00:00' }); -}); - -test('build allows to extend factory with multiple traits', function(assert) { - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - published: trait({ - isPublished: true, - publishedAt: '2010-01-01 10:00:00' - }), - - withContent: trait({ - content: 'content' - }) - }); - - this.server.loadFactories({ - article: ArticleFactory - }); - - let article = this.server.build('article'); - let publishedArticle = this.server.build('article', 'published'); - let publishedArticleWithContent = this.server.build('article', 'published', 'withContent'); - - assert.deepEqual(article, { title: 'Lorem ipsum' }); - assert.deepEqual(publishedArticle, { title: 'Lorem ipsum', isPublished: true, - publishedAt: '2010-01-01 10:00:00' }); - assert.deepEqual(publishedArticleWithContent, { title: 'Lorem ipsum', isPublished: true, - publishedAt: '2010-01-01 10:00:00', content: 'content' }); -}); - -test('build allows to extend with multiple traits and to apply attr overrides', function(assert) { - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - published: trait({ - isPublished: true, - publishedAt: '2010-01-01 10:00:00' - }), - - withContent: trait({ - content: 'content' - }) - }); - - this.server.loadFactories({ - article: ArticleFactory - }); - - let overrides = { - publishedAt: '2012-01-01 10:00:00' - }; - let publishedArticleWithContent = this.server.build('article', 'published', 'withContent', overrides); - - assert.deepEqual(publishedArticleWithContent, { title: 'Lorem ipsum', isPublished: true, - publishedAt: '2012-01-01 10:00:00', content: 'content' }); -}); - -test('build allows to build objects with associations', function(assert) { - let AuthorFactory = Factory.extend({ - name: 'Yehuda' - }); - let CategoryFactory = Factory.extend({ - name: 'splendid software' - }); - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - withCategory: trait({ - awesomeCategory: association() - }), - - someOtherTrait: trait({ - user: association() - }), - - author: association() - }); - - this.server.loadFactories({ - article: ArticleFactory, - author: AuthorFactory, - category: CategoryFactory - }); - this.server.schema.registerModels({ - author: Model.extend({ - articles: hasMany() - }), - category: Model.extend({ - }), - article: Model.extend({ - author: belongsTo(), - awesomeCategory: belongsTo('category') - }) - }); - - let article = this.server.build('article', 'withCategory'); - - assert.deepEqual(article, { title: 'Lorem ipsum', authorId: '1', awesomeCategoryId: '1' }); - assert.equal(server.db.authors.length, 1); - assert.equal(server.db.categories.length, 1); -}); - -test('build allows to build objects with associations with traits and overrides for associations', function(assert) { - let CategoryFactory = Factory.extend({ - name: 'splendid software', - - published: trait({ - isPublished: true, - publishedAt: '2014-01-01 10:00:00' - }) - }); - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - withCategory: trait({ - category: association('published', { publishedAt: '2016-01-01 12:00:00' }) - }) - }); - - let server = new Server({ - environment: 'test', - factories: { - article: ArticleFactory, - category: CategoryFactory - }, - models: { - category: Model.extend({ - }), - article: Model.extend({ - category: belongsTo() - }) - } - }); - - let article = server.build('article', 'withCategory'); - - assert.deepEqual(article, { title: 'Lorem ipsum', categoryId: '1' }); - assert.equal(server.db.categories.length, 1); - assert.deepEqual( - server.db.categories[0], - { name: 'splendid software', id: '1', isPublished: true, publishedAt: '2016-01-01 12:00:00' } - ); -}); - -test('build throws errors when using trait that is not defined and distinquishes between traits and non-traits', function(assert) { - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - published: trait({ - isPublished: true, - publishedAt: '2010-01-01 10:00:00' - }), - - private: { - someAttr: 'value' - } - }); - - this.server.loadFactories({ - article: ArticleFactory - }); - - assert.throws(() => { - this.server.build('article', 'private'); - }, /'private' trait is not registered in 'article' factory/); -}); - -test('build does not build objects and throws error if model is not registered and association helper is used', function(assert) { - let CategoryFactory = Factory.extend({ - name: 'splendid software', - - published: trait({ - isPublished: true, - publishedAt: '2014-01-01 10:00:00' - }) - }); - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - withCategory: trait({ - category: association('published', { publishedAt: '2016-01-01 12:00:00' }) - }) - }); - - let server = new Server({ - environment: 'test', - factories: { - article: ArticleFactory, - category: CategoryFactory - }, - models: { - category: Model.extend({ - }) - } - }); - - assert.throws(() => { - server.build('article', 'withCategory'); - }, /Model not registered: article/); -}); - -test('build does not build objects and throws error if model for given association is not registered', function(assert) { - let CategoryFactory = Factory.extend({ - name: 'splendid software', - - published: trait({ - isPublished: true, - publishedAt: '2014-01-01 10:00:00' - }) - }); - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - withCategory: trait({ - category: association('published', { publishedAt: '2016-01-01 12:00:00' }) - }) - }); - - let server = new Server({ - environment: 'test', - factories: { - article: ArticleFactory, - category: CategoryFactory - }, - models: { - article: Model.extend() - } - }); - - assert.throws(() => { - server.build('article', 'withCategory'); - }, /You're using the `association` factory helper on the 'category' attribute/); -}); - -module('Unit | Server #buildList', { - beforeEach() { - this.server = new Server({ environment: 'test' }); - }, - afterEach() { - this.server.shutdown(); - } -}); - -test('buildList does not add elements to the db', function(assert) { - this.server.loadFactories({ - contact: Factory.extend({ name: 'Sam' }) - }); - - this.server.buildList('contact', 3); - let contactsInDb = this.server.db.contacts; - - assert.equal(contactsInDb.length, 0); -}); - -test('buildList returns the built elements without ids', function(assert) { - this.server.loadFactories({ - contact: Factory.extend({ name: 'Sam' }) - }); - - this.server.create('contact'); - let contacts = this.server.buildList('contact', 3); - - assert.equal(contacts.length, 3); - assert.deepEqual(contacts[0], { name: 'Sam' }); - assert.deepEqual(contacts[1], { name: 'Sam' }); - assert.deepEqual(contacts[2], { name: 'Sam' }); -}); - -test('buildList respects sequences', function(assert) { - this.server.loadFactories({ - contact: Factory.extend({ - name(i) { - return `name${i}`; - } - }) - }); - - let contacts = this.server.buildList('contact', 3); - - assert.deepEqual(contacts[0], { name: 'name0' }); - assert.deepEqual(contacts[1], { name: 'name1' }); - assert.deepEqual(contacts[2], { name: 'name2' }); -}); - -test('buildList respects attr overrides', function(assert) { - this.server.loadFactories({ - contact: Factory.extend({ name: 'Sam' }) - }); - - let sams = this.server.buildList('contact', 2); - let links = this.server.buildList('contact', 2, { name: 'Link' }); - - assert.deepEqual(sams[0], { name: 'Sam' }); - assert.deepEqual(sams[1], { name: 'Sam' }); - assert.deepEqual(links[0], { name: 'Link' }); - assert.deepEqual(links[1], { name: 'Link' }); -}); - -test('buildList respects traits', function(assert) { - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - published: trait({ - isPublished: true, - publishedAt: '2010-01-01 10:00:00' - }), - - withContent: trait({ - content: 'content' - }) - }); - - this.server.loadFactories({ - article: ArticleFactory - }); - - let articles = this.server.buildList('article', 2, 'published', 'withContent'); - - assert.deepEqual(articles[0], { title: 'Lorem ipsum', isPublished: true, - publishedAt: '2010-01-01 10:00:00', content: 'content' }); - assert.deepEqual(articles[1], { title: 'Lorem ipsum', isPublished: true, - publishedAt: '2010-01-01 10:00:00', content: 'content' }); -}); - -test('buildList respects traits with attr overrides', function(assert) { - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - published: trait({ - isPublished: true, - publishedAt: '2010-01-01 10:00:00' - }), - - withContent: trait({ - content: 'content' - }) - }); - - this.server.loadFactories({ - article: ArticleFactory - }); - - let overrides = { publishedAt: '2012-01-01 10:00:00' }; - let articles = this.server.buildList('article', 2, 'published', 'withContent', overrides); - - assert.deepEqual(articles[0], { title: 'Lorem ipsum', isPublished: true, - publishedAt: '2012-01-01 10:00:00', content: 'content' }); - assert.deepEqual(articles[1], { title: 'Lorem ipsum', isPublished: true, - publishedAt: '2012-01-01 10:00:00', content: 'content' }); -}); - -test('buildList throws errors when using trait that is not defined and distinquishes between traits and non-traits', function(assert) { - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - published: trait({ - isPublished: true, - publishedAt: '2010-01-01 10:00:00' - }), - - private: { - someAttr: 'value' - } - }); - - this.server.loadFactories({ - article: ArticleFactory - }); - - assert.throws(() => { - this.server.buildList('article', 2, 'private'); - }, /'private' trait is not registered in 'article' factory/); -}); - -test('buildList throws an error if the second argument is not an integer', function(assert) { - let ArticleFactory = Factory.extend({ - title: 'Lorem ipsum', - - published: trait({ - isPublished: true, - publishedAt: '2010-01-01 10:00:00' - }) - }); - - this.server.loadFactories({ - article: ArticleFactory - }); - - assert.throws(() => { - this.server.buildList('article', 'published'); - }, /second argument has to be an integer, you passed: string/); -}); - -module('Unit | Server #defaultPassthroughs'); - -test('server configures default passthroughs when useDefaultPassthroughs is true', function(assert) { - let server = new Server({ useDefaultPassthroughs: true }); - - assert.expect(defaultPassthroughs.length); - defaultPassthroughs.forEach((passthroughUrl) => { - let passthroughRequest = { method: 'GET', url: passthroughUrl }; - let isPassedThrough = server.pretender.checkPassthrough(passthroughRequest); - - assert.ok(isPassedThrough); - }); - - server.shutdown(); -}); - -test('server does not configure default passthroughs when useDefaultPassthroughs is false', function(assert) { - let server = new Server({ useDefaultPassthroughs: false }); - - assert.expect(defaultPassthroughs.length); - defaultPassthroughs.forEach((passthroughUrl) => { - let passthroughRequest = { method: 'GET', url: passthroughUrl }; - let isPassedThrough = server.pretender.checkPassthrough(passthroughRequest); - - assert.ok(!isPassedThrough); - }); - - server.shutdown(); -}); diff --git a/tests/unit/utils/normalize-name-test.js b/tests/unit/utils/normalize-name-test.js deleted file mode 100644 index d17963cd8..000000000 --- a/tests/unit/utils/normalize-name-test.js +++ /dev/null @@ -1,26 +0,0 @@ -import { toCollectionName, toModelName } from 'ember-cli-mirage/utils/normalize-name'; -import Inflector from 'ember-inflector'; - -import {module, test} from 'qunit'; - -module('Unit | Normalize name'); - -test('can convert Model name to DbCollection name', function(assert) { - assert.equal(toCollectionName('test'), 'tests'); - assert.equal(toCollectionName('hard-test'), 'hardTests'); -}); - -test('can convert DbCollection name to Model name', function(assert) { - assert.equal(toModelName('tests'), 'test'); - assert.equal(toModelName('hardTests'), 'hard-test'); -}); - -test('can convert Model name to DbCollection using custom inflector rules', function(assert) { - Inflector.inflector.irregular('head-of-state', 'heads-of-state'); - assert.equal(toCollectionName('head-of-state'), 'headsOfState'); -}); - -test('can convert DbCollection name to Model name using custom inflector rules', function(assert) { - Inflector.inflector.irregular('head-of-state', 'heads-of-state'); - assert.equal(toModelName('headsOfState'), 'head-of-state'); -}); diff --git a/vendor/ember-cli-mirage/pretender-shim.js b/vendor/ember-cli-mirage/pretender-shim.js deleted file mode 100644 index b67c94306..000000000 --- a/vendor/ember-cli-mirage/pretender-shim.js +++ /dev/null @@ -1,9 +0,0 @@ -/* globals Pretender */ - -define('pretender', [], function() { - "use strict"; - - return { - 'default': Pretender - }; -}); diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 000000000..930030998 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,16676 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== + dependencies: + "@babel/highlight" "^7.10.4" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" + integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== + dependencies: + "@babel/highlight" "^7.8.3" + +"@babel/code-frame@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658" + integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g== + dependencies: + "@babel/highlight" "^7.12.13" + +"@babel/code-frame@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431" + integrity sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA== + dependencies: + "@babel/highlight" "^7.16.0" + +"@babel/code-frame@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" + integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== + dependencies: + "@babel/highlight" "^7.16.7" + +"@babel/compat-data@^7.13.0": + version "7.13.11" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.13.11.tgz#9c8fe523c206979c9a81b1e12fe50c1254f1aa35" + integrity sha512-BwKEkO+2a67DcFeS3RLl0Z3Gs2OvdXewuWjc1Hfokhb5eQWP9YRYH1/+VrVZvql2CfjOiNGqSAFOYt4lsqTHzg== + +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.4", "@babel/compat-data@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.16.8.tgz#31560f9f29fdf1868de8cb55049538a1b9732a60" + integrity sha512-m7OkX0IdKLKPpBlJtF561YJal5y/jyI5fNfWbPxh2D/nbzzGI4qRyrD8xO2jB24u7l+5I2a43scCG2IrfjC50Q== + +"@babel/core@^7.0.0", "@babel/core@^7.1.6", "@babel/core@^7.12.0", "@babel/core@^7.12.3", "@babel/core@^7.13.10", "@babel/core@^7.13.8", "@babel/core@^7.3.4": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.0.tgz#c4ff44046f5fe310525cc9eb4ef5147f0c5374d4" + integrity sha512-mYZEvshBRHGsIAiyH5PzCFTCfbWfoYbO/jcSdXQSUQu1/pW0xDZAUP7KEc32heqWTAfAHhV9j1vH8Sav7l+JNQ== + dependencies: + "@babel/code-frame" "^7.16.0" + "@babel/generator" "^7.16.0" + "@babel/helper-compilation-targets" "^7.16.0" + "@babel/helper-module-transforms" "^7.16.0" + "@babel/helpers" "^7.16.0" + "@babel/parser" "^7.16.0" + "@babel/template" "^7.16.0" + "@babel/traverse" "^7.16.0" + "@babel/types" "^7.16.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + semver "^6.3.0" + source-map "^0.5.0" + +"@babel/generator@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.0.tgz#d40f3d1d5075e62d3500bccb67f3daa8a95265b2" + integrity sha512-RR8hUCfRQn9j9RPKEVXo9LiwoxLPYn6hNZlvUOR8tSnaxlD0p0+la00ZP9/SnRt6HchKr+X0fO2r8vrETiJGew== + dependencies: + "@babel/types" "^7.16.0" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/generator@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.8.tgz#359d44d966b8cd059d543250ce79596f792f2ebe" + integrity sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw== + dependencies: + "@babel/types" "^7.16.8" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/helper-annotate-as-pure@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.0.tgz#9a1f0ebcda53d9a2d00108c4ceace6a5d5f1f08d" + integrity sha512-ItmYF9vR4zA8cByDocY05o0LGUkp1zhbTQOH1NFyl5xXEqlTJQCEJjieriw+aFpxo16swMxUnUiKS7a/r4vtHg== + dependencies: + "@babel/types" "^7.16.0" + +"@babel/helper-annotate-as-pure@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz#bb2339a7534a9c128e3102024c60760a3a7f3862" + integrity sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-annotate-as-pure@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee" + integrity sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz#38d138561ea207f0f69eb1626a418e4f7e6a580b" + integrity sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/helper-compilation-targets@^7.12.0", "@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.0", "@babel/helper-compilation-targets@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b" + integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA== + dependencies: + "@babel/compat-data" "^7.16.4" + "@babel/helper-validator-option" "^7.16.7" + browserslist "^4.17.5" + semver "^6.3.0" + +"@babel/helper-create-class-features-plugin@^7.13.0": + version "7.13.11" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.13.11.tgz#30d30a005bca2c953f5653fc25091a492177f4f6" + integrity sha512-ays0I7XYq9xbjCSvT+EvysLgfc3tOkwCULHjrnscGT3A9qD4sk3wXnJ3of0MAWsWGjdinFvajHU2smYuqXKMrw== + dependencies: + "@babel/helper-function-name" "^7.12.13" + "@babel/helper-member-expression-to-functions" "^7.13.0" + "@babel/helper-optimise-call-expression" "^7.12.13" + "@babel/helper-replace-supers" "^7.13.0" + "@babel/helper-split-export-declaration" "^7.12.13" + +"@babel/helper-create-class-features-plugin@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.7.tgz#9c5b34b53a01f2097daf10678d65135c1b9f84ba" + integrity sha512-kIFozAvVfK05DM4EVQYKK+zteWvY85BFdGBRQBytRyY3y+6PX0DkDOn/CZ3lEuczCfrCxEzwt0YtP/87YPTWSw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-member-expression-to-functions" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + +"@babel/helper-create-class-features-plugin@^7.5.5": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.0.tgz#090d4d166b342a03a9fec37ef4fd5aeb9c7c6a4b" + integrity sha512-XLwWvqEaq19zFlF5PTgOod4bUA+XbkR4WLQBct1bkzmxJGB0ZEJaoKF4c8cgH9oBtCDuYJ8BP5NB9uFiEgO5QA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.0" + "@babel/helper-function-name" "^7.16.0" + "@babel/helper-member-expression-to-functions" "^7.16.0" + "@babel/helper-optimise-call-expression" "^7.16.0" + "@babel/helper-replace-supers" "^7.16.0" + "@babel/helper-split-export-declaration" "^7.16.0" + +"@babel/helper-create-class-features-plugin@^7.8.3": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.6.tgz#243a5b46e2f8f0f674dc1387631eb6b28b851de0" + integrity sha512-klTBDdsr+VFFqaDHm5rR69OpEQtO2Qv8ECxHS1mNhJJvaHArR6a1xTf5K/eZW7eZpJbhCx3NW1Yt/sKsLXLblg== + dependencies: + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-member-expression-to-functions" "^7.8.3" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.6" + "@babel/helper-split-export-declaration" "^7.8.3" + +"@babel/helper-create-regexp-features-plugin@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.16.7.tgz#0cb82b9bac358eb73bfbd73985a776bfa6b14d48" + integrity sha512-fk5A6ymfp+O5+p2yCkXAu5Kyj6v0xh0RBeNcAkYUMDvvAAoxvSKXn+Jb37t/yWFiQVDFK1ELpUTD8/aLhCPu+g== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + regexpu-core "^4.7.1" + +"@babel/helper-create-regexp-features-plugin@^7.8.3", "@babel/helper-create-regexp-features-plugin@^7.8.8": + version "7.8.8" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz#5d84180b588f560b7864efaeea89243e58312087" + integrity sha512-LYVPdwkrQEiX9+1R29Ld/wTrmQu1SSKYnuOk3g0CkcZMA1p0gsNxJFj/3gBdaJ7Cg0Fnek5z0DsMULePP7Lrqg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-regex" "^7.8.3" + regexpu-core "^4.7.0" + +"@babel/helper-define-polyfill-provider@^0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.5.tgz#3c2f91b7971b9fc11fe779c945c014065dea340e" + integrity sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg== + dependencies: + "@babel/helper-compilation-targets" "^7.13.0" + "@babel/helper-module-imports" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/traverse" "^7.13.0" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + semver "^6.1.2" + +"@babel/helper-define-polyfill-provider@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.0.tgz#c5b10cf4b324ff840140bb07e05b8564af2ae971" + integrity sha512-7hfT8lUljl/tM3h+izTX/pO3W3frz2ok6Pk+gzys8iJqDfZrZy2pXjRTZAvG2YmfHun1X4q8/UZRLatMfqc5Tg== + dependencies: + "@babel/helper-compilation-targets" "^7.13.0" + "@babel/helper-module-imports" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/traverse" "^7.13.0" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + semver "^6.1.2" + +"@babel/helper-environment-visitor@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" + integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-explode-assignable-expression@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz#12a6d8522fdd834f194e868af6354e8650242b7a" + integrity sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-function-name@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz#93ad656db3c3c2232559fd7b2c3dbdcbe0eb377a" + integrity sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA== + dependencies: + "@babel/helper-get-function-arity" "^7.12.13" + "@babel/template" "^7.12.13" + "@babel/types" "^7.12.13" + +"@babel/helper-function-name@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.0.tgz#b7dd0797d00bbfee4f07e9c4ea5b0e30c8bb1481" + integrity sha512-BZh4mEk1xi2h4HFjWUXRQX5AEx4rvaZxHgax9gcjdLWdkjsY7MKt5p0otjsg5noXw+pB+clMCjw+aEVYADMjog== + dependencies: + "@babel/helper-get-function-arity" "^7.16.0" + "@babel/template" "^7.16.0" + "@babel/types" "^7.16.0" + +"@babel/helper-function-name@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f" + integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== + dependencies: + "@babel/helper-get-function-arity" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/helper-function-name@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz#eeeb665a01b1f11068e9fb86ad56a1cb1a824cca" + integrity sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA== + dependencies: + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-get-function-arity@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz#bc63451d403a3b3082b97e1d8b3fe5bd4091e583" + integrity sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg== + dependencies: + "@babel/types" "^7.12.13" + +"@babel/helper-get-function-arity@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.0.tgz#0088c7486b29a9cb5d948b1a1de46db66e089cfa" + integrity sha512-ASCquNcywC1NkYh/z7Cgp3w31YW8aojjYIlNg4VeJiHkqyP4AzIvr4qx7pYDb4/s8YcsZWqqOSxgkvjUz1kpDQ== + dependencies: + "@babel/types" "^7.16.0" + +"@babel/helper-get-function-arity@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419" + integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-get-function-arity@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" + integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-hoist-variables@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.0.tgz#4c9023c2f1def7e28ff46fc1dbcd36a39beaa81a" + integrity sha512-1AZlpazjUR0EQZQv3sgRNfM9mEVWPK3M6vlalczA+EECcPz3XPh6VplbErL5UoMpChhSck5wAJHthlj1bYpcmg== + dependencies: + "@babel/types" "^7.16.0" + +"@babel/helper-hoist-variables@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" + integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-member-expression-to-functions@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.0.tgz#6aa4bb678e0f8c22f58cdb79451d30494461b091" + integrity sha512-yvRf8Ivk62JwisqV1rFRMxiSMDGnN6KH1/mDMmIrij4jztpQNRoHqqMG3U6apYbGRPJpgPalhva9Yd06HlUxJQ== + dependencies: + "@babel/types" "^7.13.0" + +"@babel/helper-member-expression-to-functions@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.0.tgz#29287040efd197c77636ef75188e81da8bccd5a4" + integrity sha512-bsjlBFPuWT6IWhl28EdrQ+gTvSvj5tqVP5Xeftp07SEuz5pLnsXZuDkDD3Rfcxy0IsHmbZ+7B2/9SHzxO0T+sQ== + dependencies: + "@babel/types" "^7.16.0" + +"@babel/helper-member-expression-to-functions@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz#42b9ca4b2b200123c3b7e726b0ae5153924905b0" + integrity sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-member-expression-to-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c" + integrity sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.8.3": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.13.tgz#ec67e4404f41750463e455cc3203f6a32e93fcb0" + integrity sha512-NGmfvRp9Rqxy0uHSSVP+SRIW1q31a7Ji10cLBcqSDUngGentY4FRiHOFZFE1CLU5eiL0oE8reH7Tg1y99TDM/g== + dependencies: + "@babel/types" "^7.12.13" + +"@babel/helper-module-imports@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz#90538e60b672ecf1b448f5f4f5433d37e79a3ec3" + integrity sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg== + dependencies: + "@babel/types" "^7.16.0" + +"@babel/helper-module-imports@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" + integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-module-transforms@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.0.tgz#1c82a8dd4cb34577502ebd2909699b194c3e9bb5" + integrity sha512-My4cr9ATcaBbmaEa8M0dZNA74cfI6gitvUAskgDtAFmAqyFKDSHQo5YstxPbN+lzHl2D9l/YOEFqb2mtUh4gfA== + dependencies: + "@babel/helper-module-imports" "^7.16.0" + "@babel/helper-replace-supers" "^7.16.0" + "@babel/helper-simple-access" "^7.16.0" + "@babel/helper-split-export-declaration" "^7.16.0" + "@babel/helper-validator-identifier" "^7.15.7" + "@babel/template" "^7.16.0" + "@babel/traverse" "^7.16.0" + "@babel/types" "^7.16.0" + +"@babel/helper-module-transforms@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz#7665faeb721a01ca5327ddc6bba15a5cb34b6a41" + integrity sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng== + dependencies: + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-simple-access" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/helper-validator-identifier" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/helper-optimise-call-expression@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz#5c02d171b4c8615b1e7163f888c1c81c30a2aaea" + integrity sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA== + dependencies: + "@babel/types" "^7.12.13" + +"@babel/helper-optimise-call-expression@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.0.tgz#cecdb145d70c54096b1564f8e9f10cd7d193b338" + integrity sha512-SuI467Gi2V8fkofm2JPnZzB/SUuXoJA5zXe/xzyPP2M04686RzFKFHPK6HDVN6JvWBIEW8tt9hPR7fXdn2Lgpw== + dependencies: + "@babel/types" "^7.16.0" + +"@babel/helper-optimise-call-expression@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz#a34e3560605abbd31a18546bd2aad3e6d9a174f2" + integrity sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-optimise-call-expression@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz#7ed071813d09c75298ef4f208956006b6111ecb9" + integrity sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670" + integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ== + +"@babel/helper-plugin-utils@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" + integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== + +"@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz#806526ce125aed03373bc416a828321e3a6a33af" + integrity sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ== + +"@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5" + integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA== + +"@babel/helper-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.8.3.tgz#139772607d51b93f23effe72105b319d2a4c6965" + integrity sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ== + dependencies: + lodash "^4.17.13" + +"@babel/helper-remap-async-to-generator@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz#29ffaade68a367e2ed09c90901986918d25e57e3" + integrity sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-wrap-function" "^7.16.8" + "@babel/types" "^7.16.8" + +"@babel/helper-replace-supers@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.13.0.tgz#6034b7b51943094cb41627848cb219cb02be1d24" + integrity sha512-Segd5me1+Pz+rmN/NFBOplMbZG3SqRJOBlY+mA0SxAv6rjj7zJqr1AVr3SfzUVTLCv7ZLU5FycOM/SBGuLPbZw== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.13.0" + "@babel/helper-optimise-call-expression" "^7.12.13" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.0" + +"@babel/helper-replace-supers@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.0.tgz#73055e8d3cf9bcba8ddb55cad93fedc860f68f17" + integrity sha512-TQxuQfSCdoha7cpRNJvfaYxxxzmbxXw/+6cS7V02eeDYyhxderSoMVALvwupA54/pZcOTtVeJ0xccp1nGWladA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.16.0" + "@babel/helper-optimise-call-expression" "^7.16.0" + "@babel/traverse" "^7.16.0" + "@babel/types" "^7.16.0" + +"@babel/helper-replace-supers@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz#e9f5f5f32ac90429c1a4bdec0f231ef0c2838ab1" + integrity sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw== + dependencies: + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-member-expression-to-functions" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/helper-replace-supers@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz#5ada744fd5ad73203bf1d67459a27dcba67effc8" + integrity sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.8.3" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/traverse" "^7.8.6" + "@babel/types" "^7.8.6" + +"@babel/helper-simple-access@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.0.tgz#21d6a27620e383e37534cf6c10bba019a6f90517" + integrity sha512-o1rjBT/gppAqKsYfUdfHq5Rk03lMQrkPHG1OWzHWpLgVXRH4HnMM9Et9CVdIqwkCQlobnGHEJMsgWP/jE1zUiw== + dependencies: + "@babel/types" "^7.16.0" + +"@babel/helper-simple-access@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz#d656654b9ea08dbb9659b69d61063ccd343ff0f7" + integrity sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-skip-transparent-expression-wrappers@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz#0ee3388070147c3ae051e487eca3ebb0e2e8bb09" + integrity sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw== + dependencies: + "@babel/types" "^7.16.0" + +"@babel/helper-split-export-declaration@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz#e9430be00baf3e88b0e13e6f9d4eaf2136372b05" + integrity sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg== + dependencies: + "@babel/types" "^7.12.13" + +"@babel/helper-split-export-declaration@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.0.tgz#29672f43663e936df370aaeb22beddb3baec7438" + integrity sha512-0YMMRpuDFNGTHNRiiqJX19GjNXA4H0E8jZ2ibccfSxaCogbm3am5WN/2nQNj0YnQwGWM1J06GOcQ2qnh3+0paw== + dependencies: + "@babel/types" "^7.16.0" + +"@babel/helper-split-export-declaration@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" + integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-split-export-declaration@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9" + integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-validator-identifier@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" + integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== + +"@babel/helper-validator-identifier@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" + integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== + +"@babel/helper-validator-identifier@^7.15.7": + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" + integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== + +"@babel/helper-validator-identifier@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" + integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== + +"@babel/helper-validator-identifier@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz#ad53562a7fc29b3b9a91bbf7d10397fd146346ed" + integrity sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw== + +"@babel/helper-validator-option@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" + integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== + +"@babel/helper-wrap-function@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz#58afda087c4cd235de92f7ceedebca2c41274200" + integrity sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw== + dependencies: + "@babel/helper-function-name" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.8" + "@babel/types" "^7.16.8" + +"@babel/helpers@^7.16.0": + version "7.16.3" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.16.3.tgz#27fc64f40b996e7074dc73128c3e5c3e7f55c43c" + integrity sha512-Xn8IhDlBPhvYTvgewPKawhADichOsbkZuzN7qz2BusOM0brChsyXMDJvldWaYMMUNiCQdQzNEioXTp3sC8Nt8w== + dependencies: + "@babel/template" "^7.16.0" + "@babel/traverse" "^7.16.3" + "@babel/types" "^7.16.0" + +"@babel/highlight@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" + integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/highlight@^7.12.13": + version "7.13.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.13.10.tgz#a8b2a66148f5b27d666b15d81774347a731d52d1" + integrity sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg== + dependencies: + "@babel/helper-validator-identifier" "^7.12.11" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/highlight@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.0.tgz#6ceb32b2ca4b8f5f361fb7fd821e3fddf4a1725a" + integrity sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g== + dependencies: + "@babel/helper-validator-identifier" "^7.15.7" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/highlight@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.7.tgz#81a01d7d675046f0d96f82450d9d9578bdfd6b0b" + integrity sha512-aKpPMfLvGO3Q97V0qhw/V2SWNWlwfJknuwAunU7wZLSfrM4xTBvg7E5opUVi1kJTBKihE38CPg4nBiqX83PWYw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/highlight@^7.8.3": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.9.0.tgz#4e9b45ccb82b79607271b2979ad82c7b68163079" + integrity sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ== + dependencies: + "@babel/helper-validator-identifier" "^7.9.0" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.12.13": + version "7.13.11" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.11.tgz#f93ebfc99d21c1772afbbaa153f47e7ce2f50b88" + integrity sha512-PhuoqeHoO9fc4ffMEVk4qb/w/s2iOSWohvbHxLtxui0eBg3Lg5gN1U8wp1V1u61hOWkPQJJyJzGH6Y+grwkq8Q== + +"@babel/parser@^7.12.3": + version "7.12.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.3.tgz#a305415ebe7a6c7023b40b5122a0662d928334cd" + integrity sha512-kFsOS0IbsuhO5ojF8Hc8z/8vEIOkylVBrjiZUbLTE3XFe0Qi+uu6HjzQixkFaqr0ZPAMZcBVxEwmsnsLPZ2Xsw== + +"@babel/parser@^7.16.0", "@babel/parser@^7.16.3": + version "7.16.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.4.tgz#d5f92f57cf2c74ffe9b37981c0e72fee7311372e" + integrity sha512-6V0qdPUaiVHH3RtZeLIsc+6pDhbYzHR8ogA8w+f+Wc77DuXto19g2QUwveINoS34Uw+W8/hQDGJCx+i4n7xcng== + +"@babel/parser@^7.16.7", "@babel/parser@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.8.tgz#61c243a3875f7d0b0962b0543a33ece6ff2f1f17" + integrity sha512-i7jDUfrVBWc+7OKcBzEe5n7fbv3i2fWtxKzzCvOjnzSxMfWMigAhtfJ7qzZNGFNMsCCd67+uz553dYKWXPvCKw== + +"@babel/parser@^7.4.5", "@babel/parser@^7.7.0", "@babel/parser@^7.8.6": + version "7.9.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8" + integrity sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA== + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz#4eda6d6c2a0aa79c70fa7b6da67763dfe2141050" + integrity sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz#cc001234dfc139ac45f6bcf801866198c8c72ff9" + integrity sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + "@babel/plugin-proposal-optional-chaining" "^7.16.7" + +"@babel/plugin-proposal-async-generator-functions@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz#3bdd1ebbe620804ea9416706cd67d60787504bc8" + integrity sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-remap-async-to-generator" "^7.16.8" + "@babel/plugin-syntax-async-generators" "^7.8.4" + +"@babel/plugin-proposal-class-properties@^7.1.0", "@babel/plugin-proposal-class-properties@^7.16.5", "@babel/plugin-proposal-class-properties@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz#925cad7b3b1a2fcea7e59ecc8eb5954f961f91b0" + integrity sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-proposal-class-static-block@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz#712357570b612106ef5426d13dc433ce0f200c2a" + integrity sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + +"@babel/plugin-proposal-decorators@^7.13.5": + version "7.13.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.13.5.tgz#d28071457a5ba8ee1394b23e38d5dcf32ea20ef7" + integrity sha512-i0GDfVNuoapwiheevUOuSW67mInqJ8qw7uWfpjNVeHMn143kXblEy/bmL9AdZ/0yf/4BMQeWXezK0tQIvNPqag== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.13.0" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/plugin-syntax-decorators" "^7.12.13" + +"@babel/plugin-proposal-dynamic-import@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz#c19c897eaa46b27634a00fee9fb7d829158704b2" + integrity sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + +"@babel/plugin-proposal-export-namespace-from@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz#09de09df18445a5786a305681423ae63507a6163" + integrity sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + +"@babel/plugin-proposal-json-strings@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz#9732cb1d17d9a2626a08c5be25186c195b6fa6e8" + integrity sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-json-strings" "^7.8.3" + +"@babel/plugin-proposal-logical-assignment-operators@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz#be23c0ba74deec1922e639832904be0bea73cdea" + integrity sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz#141fc20b6857e59459d430c850a0011e36561d99" + integrity sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.4.4": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz#e4572253fdeed65cddeecfdab3f928afeb2fd5d2" + integrity sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + +"@babel/plugin-proposal-numeric-separator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz#d6b69f4af63fb38b6ca2558442a7fb191236eba9" + integrity sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-proposal-object-rest-spread@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.7.tgz#94593ef1ddf37021a25bdcb5754c4a8d534b01d8" + integrity sha512-3O0Y4+dw94HA86qSg9IHfyPktgR7q3gpNVAeiKQd+8jBKFaU5NQS1Yatgo4wY+UFNuLjvxcSmzcsHqrhgTyBUA== + dependencies: + "@babel/compat-data" "^7.16.4" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.16.7" + +"@babel/plugin-proposal-optional-catch-binding@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz#c623a430674ffc4ab732fd0a0ae7722b67cb74cf" + integrity sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + +"@babel/plugin-proposal-optional-chaining@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz#7cd629564724816c0e8a969535551f943c64c39a" + integrity sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +"@babel/plugin-proposal-optional-chaining@^7.6.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz#31db16b154c39d6b8a645292472b98394c292a58" + integrity sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + +"@babel/plugin-proposal-private-methods@^7.16.5", "@babel/plugin-proposal-private-methods@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.7.tgz#e418e3aa6f86edd6d327ce84eff188e479f571e0" + integrity sha512-7twV3pzhrRxSwHeIvFE6coPgvo+exNDOiGUMg39o2LiLo1Y+4aKpfkcLGcg1UHonzorCt7SNXnoMyCnnIOA8Sw== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-proposal-private-property-in-object@^7.16.5", "@babel/plugin-proposal-private-property-in-object@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz#b0b8cef543c2c3d57e59e2c611994861d46a3fce" + integrity sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + +"@babel/plugin-proposal-unicode-property-regex@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz#635d18eb10c6214210ffc5ff4932552de08188a2" + integrity sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.8.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz#ee3a95e90cdc04fe8cd92ec3279fa017d68a0d1d" + integrity sha512-EVhjVsMpbhLw9ZfHWSx2iy13Q8Z/eg8e8ccVWt23sWQK5l1UdkoLJPN5w69UA4uITGBnEZD2JOe4QOHycYKv8A== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.8" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-decorators@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.12.13.tgz#fac829bf3c7ef4a1bc916257b403e58c6bdaf648" + integrity sha512-Rw6aIXGuqDLr6/LoBBYE57nKOzQpz/aDkKlMqEwH+Vp0MXbG6H/TfRjaY343LKxzAKAMXIHsQ8JzaZKuDZ9MwA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-dynamic-import@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-export-namespace-from@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" + integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0", "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.0", "@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-top-level-await@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.12.13.tgz#9dff111ca64154cef0f4dc52cf843d9f12ce4474" + integrity sha512-cHP3u1JiUiG2LFDKbXnwVad81GvfyIOmCD6HIEId6ojrY0Drfy2q1jw7BwN7dE84+kTnBjLkXoL3IEy/3JPu2w== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-typescript@^7.2.0", "@babel/plugin-syntax-typescript@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.8.3.tgz#c1f659dda97711a569cef75275f7e15dcaa6cabc" + integrity sha512-GO1MQ/SGGGoiEXY0e0bSpHimJvxqB7lktLLIq2pv8xG7WZ8IMEle74jIe1FhprHBWjwjZtXHkycDLZXIWM5Wfg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-arrow-functions@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz#44125e653d94b98db76369de9c396dc14bef4154" + integrity sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-async-to-generator@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz#b83dff4b970cf41f1b819f8b49cc0cfbaa53a808" + integrity sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg== + dependencies: + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-remap-async-to-generator" "^7.16.8" + +"@babel/plugin-transform-block-scoped-functions@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz#4d0d57d9632ef6062cdf354bb717102ee042a620" + integrity sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-block-scoping@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz#f50664ab99ddeaee5bc681b8f3a6ea9d72ab4f87" + integrity sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-block-scoping@^7.8.3": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.1.tgz#f0ee727874b42a208a48a586b84c3d222c2bbef1" + integrity sha512-zJyAC9sZdE60r1nVQHblcfCj29Dh2Y0DOvlMkcqSo0ckqjiCwNiUezUKw+RjOCwGfpLRwnAeQ2XlLpsnGkvv9w== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-classes@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz#8f4b9562850cd973de3b498f1218796eb181ce00" + integrity sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz#66dee12e46f61d2aae7a73710f591eb3df616470" + integrity sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-destructuring@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.7.tgz#ca9588ae2d63978a4c29d3f33282d8603f618e23" + integrity sha512-VqAwhTHBnu5xBVDCvrvqJbtLUa++qZaWC0Fgr2mqokBlulZARGyIvZDoqbPlPaKImQ9dKAcCzbv+ul//uqu70A== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-dotall-regex@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz#6b2d67686fab15fb6a7fd4bd895d5982cfc81241" + integrity sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-dotall-regex@^7.4.4": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz#c3c6ec5ee6125c6993c5cbca20dc8621a9ea7a6e" + integrity sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-duplicate-keys@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz#2207e9ca8f82a0d36a5a67b6536e7ef8b08823c9" + integrity sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-exponentiation-operator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz#efa9862ef97e9e9e5f653f6ddc7b665e8536fe9b" + integrity sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-for-of@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz#649d639d4617dff502a9a158c479b3b556728d8c" + integrity sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-function-name@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz#5ab34375c64d61d083d7d2f05c38d90b97ec65cf" + integrity sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA== + dependencies: + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz#254c9618c5ff749e87cb0c0cef1a0a050c0bdab1" + integrity sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-member-expression-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz#6e5dcf906ef8a098e630149d14c867dd28f92384" + integrity sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-modules-amd@^7.12.1", "@babel/plugin-transform-modules-amd@^7.13.0", "@babel/plugin-transform-modules-amd@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz#b28d323016a7daaae8609781d1f8c9da42b13186" + integrity sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g== + dependencies: + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-commonjs@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz#cdee19aae887b16b9d331009aa9a219af7c86afe" + integrity sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA== + dependencies: + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-simple-access" "^7.16.7" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-systemjs@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz#887cefaef88e684d29558c2b13ee0563e287c2d7" + integrity sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw== + dependencies: + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-validator-identifier" "^7.16.7" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-umd@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz#23dad479fa585283dbd22215bff12719171e7618" + integrity sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ== + dependencies: + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz#7f860e0e40d844a02c9dcf9d84965e7dfd666252" + integrity sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + +"@babel/plugin-transform-new-target@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz#9967d89a5c243818e0800fdad89db22c5f514244" + integrity sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-object-assign@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.8.3.tgz#dc3b8dd50ef03837868a37b7df791f64f288538e" + integrity sha512-i3LuN8tPDqUCRFu3dkzF2r1Nx0jp4scxtm7JxtIqI9he9Vk20YD+/zshdzR9JLsoBMlJlNR82a62vQExNEVx/Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-object-super@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz#ac359cf8d32cf4354d27a46867999490b6c32a94" + integrity sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" + +"@babel/plugin-transform-parameters@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz#a1721f55b99b736511cb7e0152f61f17688f331f" + integrity sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-property-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz#2dadac85155436f22c696c4827730e0fe1057a55" + integrity sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-regenerator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz#9e7576dc476cb89ccc5096fff7af659243b4adeb" + integrity sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q== + dependencies: + regenerator-transform "^0.14.2" + +"@babel/plugin-transform-reserved-words@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz#1d798e078f7c5958eec952059c460b220a63f586" + integrity sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-runtime@^7.12.1", "@babel/plugin-transform-runtime@^7.13.9": + version "7.13.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.13.10.tgz#a1e40d22e2bf570c591c9c7e5ab42d6bf1e419e1" + integrity sha512-Y5k8ipgfvz5d/76tx7JYbKQTcgFSU6VgJ3kKQv4zGTKr+a9T/KBvfRvGtSFgKDQGt/DBykQixV0vNWKIdzWErA== + dependencies: + "@babel/helper-module-imports" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" + babel-plugin-polyfill-corejs2 "^0.1.4" + babel-plugin-polyfill-corejs3 "^0.1.3" + babel-plugin-polyfill-regenerator "^0.1.2" + semver "^6.3.0" + +"@babel/plugin-transform-shorthand-properties@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz#e8549ae4afcf8382f711794c0c7b6b934c5fbd2a" + integrity sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-spread@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz#a303e2122f9f12e0105daeedd0f30fb197d8ff44" + integrity sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + +"@babel/plugin-transform-sticky-regex@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz#c84741d4f4a38072b9a1e2e3fd56d359552e8660" + integrity sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-template-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz#f3d1c45d28967c8e80f53666fc9c3e50618217ab" + integrity sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-typeof-symbol@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz#9cdbe622582c21368bd482b660ba87d5545d4f7e" + integrity sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-typescript@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.13.0.tgz#4a498e1f3600342d2a9e61f60131018f55774853" + integrity sha512-elQEwluzaU8R8dbVuW2Q2Y8Nznf7hnjM7+DSCd14Lo5fF63C9qNLbwZYbmZrtV9/ySpSUpkRpQXvJb6xyu4hCQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.13.0" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/plugin-syntax-typescript" "^7.12.13" + +"@babel/plugin-transform-typescript@~7.4.0": + version "7.4.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.4.5.tgz#ab3351ba35307b79981993536c93ff8be050ba28" + integrity sha512-RPB/YeGr4ZrFKNwfuQRlMf2lxoCUaU01MTw39/OFE/RiL8HDjtn68BwEPft1P7JN4akyEmjGWAMNldOV7o9V2g== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-typescript" "^7.2.0" + +"@babel/plugin-transform-typescript@~7.5.0": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.5.5.tgz#6d862766f09b2da1cb1f7d505fe2aedab6b7d4b8" + integrity sha512-pehKf4m640myZu5B2ZviLaiBlxMCjSZ1qTEO459AXKX5GnPueyulJeCqZFs1nz/Ya2dDzXQ1NxZ/kKNWyD4h6w== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.5.5" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-typescript" "^7.2.0" + +"@babel/plugin-transform-typescript@~7.8.0": + version "7.8.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.8.7.tgz#48bccff331108a7b3a28c3a4adc89e036dc3efda" + integrity sha512-7O0UsPQVNKqpHeHLpfvOG4uXmlw+MOxYvUv6Otc9uH5SYMIxvF6eBdjkWvC3f9G+VXe0RsNExyAQBeTRug/wqQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-typescript" "^7.8.3" + +"@babel/plugin-transform-unicode-escapes@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz#da8717de7b3287a2c6d659750c964f302b31ece3" + integrity sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-unicode-regex@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz#0f7aa4a501198976e25e82702574c34cfebe9ef2" + integrity sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/polyfill@^7.0.0", "@babel/polyfill@^7.11.5": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.12.1.tgz#1f2d6371d1261bbd961f3c5d5909150e12d0bd96" + integrity sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g== + dependencies: + core-js "^2.6.5" + regenerator-runtime "^0.13.4" + +"@babel/preset-env@^7.10.2", "@babel/preset-env@^7.16.5": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.8.tgz#e682fa0bcd1cf49621d64a8956318ddfb9a05af9" + integrity sha512-9rNKgVCdwHb3z1IlbMyft6yIXIeP3xz6vWvGaLHrJThuEIqWfHb0DNBH9VuTgnDfdbUDhkmkvMZS/YMCtP7Elg== + dependencies: + "@babel/compat-data" "^7.16.8" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-validator-option" "^7.16.7" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.16.7" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.16.7" + "@babel/plugin-proposal-async-generator-functions" "^7.16.8" + "@babel/plugin-proposal-class-properties" "^7.16.7" + "@babel/plugin-proposal-class-static-block" "^7.16.7" + "@babel/plugin-proposal-dynamic-import" "^7.16.7" + "@babel/plugin-proposal-export-namespace-from" "^7.16.7" + "@babel/plugin-proposal-json-strings" "^7.16.7" + "@babel/plugin-proposal-logical-assignment-operators" "^7.16.7" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.16.7" + "@babel/plugin-proposal-numeric-separator" "^7.16.7" + "@babel/plugin-proposal-object-rest-spread" "^7.16.7" + "@babel/plugin-proposal-optional-catch-binding" "^7.16.7" + "@babel/plugin-proposal-optional-chaining" "^7.16.7" + "@babel/plugin-proposal-private-methods" "^7.16.7" + "@babel/plugin-proposal-private-property-in-object" "^7.16.7" + "@babel/plugin-proposal-unicode-property-regex" "^7.16.7" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" + "@babel/plugin-transform-arrow-functions" "^7.16.7" + "@babel/plugin-transform-async-to-generator" "^7.16.8" + "@babel/plugin-transform-block-scoped-functions" "^7.16.7" + "@babel/plugin-transform-block-scoping" "^7.16.7" + "@babel/plugin-transform-classes" "^7.16.7" + "@babel/plugin-transform-computed-properties" "^7.16.7" + "@babel/plugin-transform-destructuring" "^7.16.7" + "@babel/plugin-transform-dotall-regex" "^7.16.7" + "@babel/plugin-transform-duplicate-keys" "^7.16.7" + "@babel/plugin-transform-exponentiation-operator" "^7.16.7" + "@babel/plugin-transform-for-of" "^7.16.7" + "@babel/plugin-transform-function-name" "^7.16.7" + "@babel/plugin-transform-literals" "^7.16.7" + "@babel/plugin-transform-member-expression-literals" "^7.16.7" + "@babel/plugin-transform-modules-amd" "^7.16.7" + "@babel/plugin-transform-modules-commonjs" "^7.16.8" + "@babel/plugin-transform-modules-systemjs" "^7.16.7" + "@babel/plugin-transform-modules-umd" "^7.16.7" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.16.8" + "@babel/plugin-transform-new-target" "^7.16.7" + "@babel/plugin-transform-object-super" "^7.16.7" + "@babel/plugin-transform-parameters" "^7.16.7" + "@babel/plugin-transform-property-literals" "^7.16.7" + "@babel/plugin-transform-regenerator" "^7.16.7" + "@babel/plugin-transform-reserved-words" "^7.16.7" + "@babel/plugin-transform-shorthand-properties" "^7.16.7" + "@babel/plugin-transform-spread" "^7.16.7" + "@babel/plugin-transform-sticky-regex" "^7.16.7" + "@babel/plugin-transform-template-literals" "^7.16.7" + "@babel/plugin-transform-typeof-symbol" "^7.16.7" + "@babel/plugin-transform-unicode-escapes" "^7.16.7" + "@babel/plugin-transform-unicode-regex" "^7.16.7" + "@babel/preset-modules" "^0.1.5" + "@babel/types" "^7.16.8" + babel-plugin-polyfill-corejs2 "^0.3.0" + babel-plugin-polyfill-corejs3 "^0.5.0" + babel-plugin-polyfill-regenerator "^0.3.0" + core-js-compat "^3.20.2" + semver "^6.3.0" + +"@babel/preset-modules@^0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" + integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/runtime@7.12.18", "@babel/runtime@^7.12.5", "@babel/runtime@^7.8.4": + version "7.12.18" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.18.tgz#af137bd7e7d9705a412b3caaf991fe6aaa97831b" + integrity sha512-BogPQ7ciE6SYAUPtlm9tWbgI9+2AgqSam6QivMgXgAT+fKbgppaj4ZX15MHeLC1PVF5sNk70huBu20XxWOs8Cg== + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/template@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.13.tgz#530265be8a2589dbb37523844c5bcb55947fb327" + integrity sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA== + dependencies: + "@babel/code-frame" "^7.12.13" + "@babel/parser" "^7.12.13" + "@babel/types" "^7.12.13" + +"@babel/template@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.0.tgz#d16a35ebf4cd74e202083356fab21dd89363ddd6" + integrity sha512-MnZdpFD/ZdYhXwiunMqqgyZyucaYsbL0IrjoGjaVhGilz+x8YB++kRfygSOIj1yOtWKPlx7NBp+9I1RQSgsd5A== + dependencies: + "@babel/code-frame" "^7.16.0" + "@babel/parser" "^7.16.0" + "@babel/types" "^7.16.0" + +"@babel/template@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" + integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/parser" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/template@^7.8.3": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" + integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/parser" "^7.8.6" + "@babel/types" "^7.8.6" + +"@babel/traverse@^7.1.6", "@babel/traverse@^7.12.1", "@babel/traverse@^7.13.0", "@babel/traverse@^7.16.0", "@babel/traverse@^7.16.3", "@babel/traverse@^7.4.5", "@babel/traverse@^7.7.0", "@babel/traverse@^7.8.6": + version "7.16.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.3.tgz#f63e8a938cc1b780f66d9ed3c54f532ca2d14787" + integrity sha512-eolumr1vVMjqevCpwVO99yN/LoGL0EyHiLO5I043aYQvwOJ9eR5UsZSClHVCzfhBduMAsSzgA/6AyqPjNayJag== + dependencies: + "@babel/code-frame" "^7.16.0" + "@babel/generator" "^7.16.0" + "@babel/helper-function-name" "^7.16.0" + "@babel/helper-hoist-variables" "^7.16.0" + "@babel/helper-split-export-declaration" "^7.16.0" + "@babel/parser" "^7.16.3" + "@babel/types" "^7.16.0" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.8.tgz#bab2f2b09a5fe8a8d9cad22cbfe3ba1d126fef9c" + integrity sha512-xe+H7JlvKsDQwXRsBhSnq1/+9c+LlQcCK3Tn/l5sbx02HYns/cn7ibp9+RV1sIUqu7hKg91NWsgHurO9dowITQ== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.16.8" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/parser" "^7.16.8" + "@babel/types" "^7.16.8" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.1.6", "@babel/types@^7.12.1", "@babel/types@^7.12.13", "@babel/types@^7.13.0", "@babel/types@^7.16.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.7.2", "@babel/types@^7.8.3", "@babel/types@^7.8.6": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.0.tgz#db3b313804f96aadd0b776c4823e127ad67289ba" + integrity sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg== + dependencies: + "@babel/helper-validator-identifier" "^7.15.7" + to-fast-properties "^2.0.0" + +"@babel/types@^7.16.7", "@babel/types@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.8.tgz#0ba5da91dd71e0a4e7781a30f22770831062e3c1" + integrity sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + to-fast-properties "^2.0.0" + +"@cnakazawa/watch@^1.0.3": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a" + integrity sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ== + dependencies: + exec-sh "^0.3.2" + minimist "^1.2.0" + +"@csstools/postcss-sass@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@csstools/postcss-sass/-/postcss-sass-4.0.0.tgz#6617c5096a6b71751ee0b87d2326418b9d97effb" + integrity sha512-yvm2aaODNJ8PBn43HjYiRvVJcYLEpz5BEKXxQ/7HryqcL+TnAceXZO+khadTEkjw90r8afR5wykTzvVpFeo4vw== + dependencies: + "@csstools/sass-import-resolve" "^1.0.0" + postcss "^7.0.14" + sass "^1.16.1" + source-map "~0.7.3" + +"@csstools/sass-import-resolve@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@csstools/sass-import-resolve/-/sass-import-resolve-1.0.0.tgz#32c3cdb2f7af3cd8f0dca357b592e7271f3831b5" + integrity sha512-pH4KCsbtBLLe7eqUrw8brcuFO8IZlN36JjdKlOublibVdAIPHCzEnpBWOVUXK5sCf+DpBi8ZtuWtjF0srybdeA== + +"@ember-data/adapter@3.28.5": + version "3.28.5" + resolved "https://registry.yarnpkg.com/@ember-data/adapter/-/adapter-3.28.5.tgz#34c3bca462983197803f2a9f571fc581da7bad7e" + integrity sha512-ywfm5F/yFujnR+UmKw9NHIStrxvEP/nIyL2/7YzZnqbVq8Ny+LVKyuRB0bRY0iZQ+IAWQODbM59A8YjcVRC6Cg== + dependencies: + "@ember-data/private-build-infra" "3.28.5" + "@ember-data/store" "3.28.5" + "@ember/edition-utils" "^1.2.0" + "@ember/string" "^3.0.0" + ember-cli-babel "^7.26.6" + ember-cli-test-info "^1.0.0" + ember-cli-typescript "^4.1.0" + +"@ember-data/canary-features@3.28.5": + version "3.28.5" + resolved "https://registry.yarnpkg.com/@ember-data/canary-features/-/canary-features-3.28.5.tgz#74cee8904deb0462f11f095fd9683114e23cc444" + integrity sha512-mJzaJ6oCeP4QEJ+9BOr0mdsQ2970yECmiBePadoGiJRJ9JRQcc4GoZfaO/W6Ej7nmp/kSWC/Pc3ROaSkq33SJg== + dependencies: + ember-cli-babel "^7.26.6" + ember-cli-typescript "^4.1.0" + +"@ember-data/debug@3.28.5": + version "3.28.5" + resolved "https://registry.yarnpkg.com/@ember-data/debug/-/debug-3.28.5.tgz#d5cfd8fb33d13f30eaa3038cd0d69714561cf3b4" + integrity sha512-NzbeD5Ax6UvJ6/wFt2ud7AZdIfRLeLH+FP9xzmnqT7NN+Eyn9eti4eqwFgyYljALURpCOxLQ/BhQOtUSWfjOFw== + dependencies: + "@ember-data/private-build-infra" "3.28.5" + "@ember/edition-utils" "^1.2.0" + "@ember/string" "^3.0.0" + ember-cli-babel "^7.26.6" + ember-cli-test-info "^1.0.0" + ember-cli-typescript "^4.1.0" + +"@ember-data/model@3.28.5": + version "3.28.5" + resolved "https://registry.yarnpkg.com/@ember-data/model/-/model-3.28.5.tgz#5aa2c684226ccf3e633f036795bfdfb87d7d19b4" + integrity sha512-g95kqeJccZxo1f9j95GWYbgJXAhCE7xwSiwIBs68ZzEAHV74dE/2QapwC8wsN9t89fSpDG/Lz8JXf0EUMPoglA== + dependencies: + "@ember-data/canary-features" "3.28.5" + "@ember-data/private-build-infra" "3.28.5" + "@ember-data/store" "3.28.5" + "@ember/edition-utils" "^1.2.0" + "@ember/string" "^3.0.0" + ember-cached-decorator-polyfill "^0.1.4" + ember-cli-babel "^7.26.6" + ember-cli-string-utils "^1.1.0" + ember-cli-test-info "^1.0.0" + ember-cli-typescript "^4.1.0" + ember-compatibility-helpers "^1.2.0" + inflection "~1.13.1" + +"@ember-data/private-build-infra@3.28.5": + version "3.28.5" + resolved "https://registry.yarnpkg.com/@ember-data/private-build-infra/-/private-build-infra-3.28.5.tgz#f3f4ac9f2d728abd3652ae0096ab3b3983841051" + integrity sha512-uyiUE/vBunvulFfVWwf/eFLRl3hBhBFoTG+GTjhTGdosLmACjzcaOGe9bGNhmnGBQZLPckWSgM1qrCKDEQCgPw== + dependencies: + "@babel/plugin-transform-block-scoping" "^7.8.3" + "@ember-data/canary-features" "3.28.5" + "@ember/edition-utils" "^1.2.0" + babel-plugin-debug-macros "^0.3.3" + babel-plugin-filter-imports "^4.0.0" + babel6-plugin-strip-class-callcheck "^6.0.0" + broccoli-debug "^0.6.5" + broccoli-file-creator "^2.1.1" + broccoli-funnel "^3.0.3" + broccoli-merge-trees "^4.2.0" + broccoli-rollup "^5.0.0" + calculate-cache-key-for-tree "^2.0.0" + chalk "^4.0.0" + ember-cli-babel "^7.26.6" + ember-cli-path-utils "^1.0.0" + ember-cli-string-utils "^1.1.0" + ember-cli-typescript "^4.1.0" + ember-cli-version-checker "^5.1.1" + esm "^3.2.25" + git-repo-info "^2.1.1" + glob "^7.1.6" + npm-git-info "^1.0.3" + rimraf "^3.0.2" + rsvp "^4.8.5" + semver "^7.1.3" + silent-error "^1.1.1" + +"@ember-data/record-data@3.28.5": + version "3.28.5" + resolved "https://registry.yarnpkg.com/@ember-data/record-data/-/record-data-3.28.5.tgz#fbfaf6fafecbd793fba9ca7d8ca1f96926368f28" + integrity sha512-VdJqu1GtYOFVtPWEU7PflGfDT2lZKJqI0rbCN+W2Nf1iLjpzEoB7nM05RnCKL0EhAwn/UKhOh1c3/Ztm5N9YNw== + dependencies: + "@ember-data/canary-features" "3.28.5" + "@ember-data/private-build-infra" "3.28.5" + "@ember-data/store" "3.28.5" + "@ember/edition-utils" "^1.2.0" + ember-cli-babel "^7.26.6" + ember-cli-test-info "^1.0.0" + ember-cli-typescript "^4.1.0" + +"@ember-data/rfc395-data@^0.0.4": + version "0.0.4" + resolved "https://registry.yarnpkg.com/@ember-data/rfc395-data/-/rfc395-data-0.0.4.tgz#ecb86efdf5d7733a76ff14ea651a1b0ed1f8a843" + integrity sha512-tGRdvgC9/QMQSuSuJV45xoyhI0Pzjm7A9o/MVVA3HakXIImJbbzx/k/6dO9CUEQXIyS2y0fW6C1XaYOG7rY0FQ== + +"@ember-data/serializer@3.28.5": + version "3.28.5" + resolved "https://registry.yarnpkg.com/@ember-data/serializer/-/serializer-3.28.5.tgz#572ead11e595428607a58cdecd612f6bb97cd114" + integrity sha512-EAkkA0VFhfqf3FYvvdvcqAcA2kfVHimmyI0wFGxDwMUGGAJAA+SnPuPtAjM6YD193SMSsU8ixfjbKH72BFqfJg== + dependencies: + "@ember-data/private-build-infra" "3.28.5" + "@ember-data/store" "3.28.5" + ember-cli-babel "^7.26.6" + ember-cli-test-info "^1.0.0" + ember-cli-typescript "^4.1.0" + +"@ember-data/store@3.28.5": + version "3.28.5" + resolved "https://registry.yarnpkg.com/@ember-data/store/-/store-3.28.5.tgz#a0038a3b09fdcf233bb070438fb8538c509801fa" + integrity sha512-UTCohm4u9V8qaISjO2mhVG2A62g/Gnb0zAPd4CnV84lyowE0LQw1ACN9KWRSgeaTOAUfEWP9MkQeuQQuikYtig== + dependencies: + "@ember-data/canary-features" "3.28.5" + "@ember-data/private-build-infra" "3.28.5" + "@ember/string" "^3.0.0" + "@glimmer/tracking" "^1.0.4" + ember-cli-babel "^7.26.6" + ember-cli-path-utils "^1.0.0" + ember-cli-typescript "^4.1.0" + +"@ember-decorators/component@^6.1.1": + version "6.1.1" + resolved "https://registry.yarnpkg.com/@ember-decorators/component/-/component-6.1.1.tgz#b360dc4fa8e576ee1c840879399ef1745fd96e06" + integrity sha512-Cj8tY/c0MC/rsipqsiWLh3YVN72DK92edPYamD/HzvftwzC6oDwawWk8RmStiBnG9PG/vntAt41l3S7HSSA+1Q== + dependencies: + "@ember-decorators/utils" "^6.1.1" + ember-cli-babel "^7.1.3" + +"@ember-decorators/object@^6.1.1": + version "6.1.1" + resolved "https://registry.yarnpkg.com/@ember-decorators/object/-/object-6.1.1.tgz#50c922f5ac9af3ddd381cb6a43a031dfd9a70c7a" + integrity sha512-cb4CNR9sRoA31J3FCOFLDuR9ztM4wO9w1WlS4JeNRS7Z69SlB/XSXB/vplA3i9OOaXEy/zKWbu5ndZrHz0gvLw== + dependencies: + "@ember-decorators/utils" "^6.1.1" + ember-cli-babel "^7.1.3" + +"@ember-decorators/utils@^6.1.1": + version "6.1.1" + resolved "https://registry.yarnpkg.com/@ember-decorators/utils/-/utils-6.1.1.tgz#6b619814942b4fb3747cfa9f540c9f05283d7c5e" + integrity sha512-0KqnoeoLKb6AyoSU65TRF5T85wmS4uDn06oARddwNPxxf/lt5jQlh41uX3W7V/fWL9tPu8x1L1Vvpc80MN1+YA== + dependencies: + ember-cli-babel "^7.1.3" + +"@ember-template-lint/todo-utils@^10.0.0": + version "10.0.0" + resolved "https://registry.yarnpkg.com/@ember-template-lint/todo-utils/-/todo-utils-10.0.0.tgz#085aafcf31ca04ba4d3a9460f088aed752b90ea8" + integrity sha512-US8VKnetBOl8KfKz+rXGsosz6rIETNwSz2F2frM8hIoJfF/d6ME1Iz1K7tPYZEE6SoKqZFlBs5XZPSmzRnabjA== + dependencies: + "@types/eslint" "^7.2.13" + fs-extra "^9.1.0" + slash "^3.0.0" + tslib "^2.2.0" + +"@ember/edition-utils@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ember/edition-utils/-/edition-utils-1.2.0.tgz#a039f542dc14c8e8299c81cd5abba95e2459cfa6" + integrity sha512-VmVq/8saCaPdesQmftPqbFtxJWrzxNGSQ+e8x8LLe3Hjm36pJ04Q8LeORGZkAeOhldoUX9seLGmSaHeXkIqoog== + +"@ember/jquery@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@ember/jquery/-/jquery-2.0.0.tgz#083a1de32333b3fc938fad246a6f3ea7eefe5b10" + integrity sha512-f8+WNqzXBNxl96jo0IwJBO5QCi0bnUlba9I7WbZcGhgnzszC76INJkw6l8UepZ1PMGG1H1wYpoIGoBBp5ZVmFA== + dependencies: + broccoli-funnel "^3.0.6" + broccoli-merge-trees "^4.2.0" + ember-cli-babel "^7.26.6" + jquery "^3.5.0" + resolve "^1.15.1" + +"@ember/optional-features@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@ember/optional-features/-/optional-features-2.0.0.tgz#c809abd5a27d5b0ef3c6de3941334ab6153313f0" + integrity sha512-4gkvuGRYfpAh1nwAz306cmMeC1mG7wxZnbsBZ09mMaMX/W7IyKOKc/38JwrDPUFUalmNEM7q7JEPcmew2M3Dog== + dependencies: + chalk "^4.1.0" + ember-cli-version-checker "^5.1.1" + glob "^7.1.6" + inquirer "^7.3.3" + mkdirp "^1.0.4" + silent-error "^1.1.1" + +"@ember/render-modifiers@^1.0.1": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@ember/render-modifiers/-/render-modifiers-1.0.2.tgz#2e87c48db49d922ce4850d707215caaac60d8444" + integrity sha512-6tEnHl5+62NTSAG2mwhGMFPhUrJQjoVqV+slsn+rlTknm2Zik+iwxBQEbwaiQOU1FUYxkS8RWcieovRNMR8inQ== + dependencies: + ember-cli-babel "^7.10.0" + ember-modifier-manager-polyfill "^1.1.0" + +"@ember/string@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@ember/string/-/string-3.0.0.tgz#e3a3cc7874c9f64eadfdac644d8b1238721ce289" + integrity sha512-T+7QYDp8ItlQseNveK2lL6OsOO5wg7aNQ/M2RpO8cGwM80oZOnr/Y35HmMfu4ejFEc+F1LPegvu7LGfeJOicWA== + dependencies: + ember-cli-babel "^7.26.6" + +"@ember/test-helpers@^2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@ember/test-helpers/-/test-helpers-2.6.0.tgz#d687515c6ab49ba72717fc62046970ef4a72ea9c" + integrity sha512-N5sr3layWk60wB3maCy+/5hFHQRcTh8aqxcZTSs3Od9QkuHdWBtRgMGLP/35mXpJlgWuu3xqLpt6u3dGHc8gCg== + dependencies: + "@ember/test-waiters" "^3.0.0" + broccoli-debug "^0.6.5" + broccoli-funnel "^3.0.8" + ember-cli-babel "^7.26.6" + ember-cli-htmlbars "^5.7.1" + ember-destroyable-polyfill "^2.0.3" + +"@ember/test-waiters@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@ember/test-waiters/-/test-waiters-3.0.0.tgz#b66a35cd5b78ec3c296a6f5f5fb3852780a5d3c8" + integrity sha512-z6+gIlq/rXLKroWv2wxAoiiLtgSOGQFCw6nUufERausV+jLnA7CYbWwzEo5R7XaOejSDpgA5d6haXIBsD5j0oQ== + dependencies: + calculate-cache-key-for-tree "^2.0.0" + ember-cli-babel "^7.26.6" + ember-cli-version-checker "^5.1.2" + semver "^7.3.5" + +"@embroider/core@0.29.0": + version "0.29.0" + resolved "https://registry.yarnpkg.com/@embroider/core/-/core-0.29.0.tgz#51421fbb2bcee607dc6e162400e3502a121230d2" + integrity sha512-2i0QtV1y1jJpj1aiIA3FVZHfuLBN2yCUcJs0PkOsqZYi7J796KT4t7WwAk8gmBq00yGzHDWLw/iH4ULTomPS8A== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.12.3" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/traverse" "^7.12.1" + "@babel/types" "^7.12.1" + "@embroider/macros" "0.29.0" + assert-never "^1.1.0" + babel-plugin-syntax-dynamic-import "^6.18.0" + broccoli-persistent-filter "^2.2.2" + broccoli-plugin "^3.0.0" + broccoli-source "^1.1.0" + debug "^3.1.0" + fast-sourcemap-concat "^1.4.0" + filesize "^4.1.2" + fs-extra "^7.0.1" + fs-tree-diff "^2.0.0" + handlebars "^4.4.2" + js-string-escape "^1.0.1" + jsdom "^16.4.0" + json-stable-stringify "^1.0.1" + lodash "^4.17.10" + pkg-up "^2.0.0" + resolve "^1.8.1" + resolve-package-path "^1.2.2" + semver "^7.3.2" + strip-bom "^3.0.0" + typescript-memoize "^1.0.0-alpha.3" + walk-sync "^1.1.3" + wrap-legacy-hbs-plugin-if-needed "^1.0.1" + +"@embroider/core@0.33.0", "@embroider/core@^0.33.0": + version "0.33.0" + resolved "https://registry.yarnpkg.com/@embroider/core/-/core-0.33.0.tgz#0fb1752d6e34ea45368e65c42e13220a57ffae76" + integrity sha512-Kd3W4vBJCSwskVislwldhuoe1RtdA04lRr2r2ccnPI4msCXxLn292WBaS7/x0LdEu2EMO5ffRDeQva2/xoS4Yg== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.12.3" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-transform-runtime" "^7.12.1" + "@babel/runtime" "^7.12.5" + "@babel/traverse" "^7.12.1" + "@babel/types" "^7.12.1" + "@embroider/macros" "0.33.0" + assert-never "^1.1.0" + babel-plugin-syntax-dynamic-import "^6.18.0" + broccoli-node-api "^1.7.0" + broccoli-persistent-filter "^3.1.2" + broccoli-plugin "^4.0.1" + broccoli-source "^3.0.0" + debug "^3.1.0" + escape-string-regexp "^4.0.0" + fast-sourcemap-concat "^1.4.0" + filesize "^4.1.2" + fs-extra "^7.0.1" + fs-tree-diff "^2.0.0" + handlebars "^4.4.2" + js-string-escape "^1.0.1" + jsdom "^16.4.0" + json-stable-stringify "^1.0.1" + lodash "^4.17.10" + pkg-up "^2.0.0" + resolve "^1.8.1" + resolve-package-path "^1.2.2" + semver "^7.3.2" + strip-bom "^3.0.0" + typescript-memoize "^1.0.0-alpha.3" + walk-sync "^1.1.3" + wrap-legacy-hbs-plugin-if-needed "^1.0.1" + +"@embroider/macros@0.29.0", "@embroider/macros@^0.29.0": + version "0.29.0" + resolved "https://registry.yarnpkg.com/@embroider/macros/-/macros-0.29.0.tgz#33048069b0abdda17efc7ff438b18b0c2c237bff" + integrity sha512-Kg8we7U7TpgUZ0EBKlTC4UGItPa91OrGT5Bzxa2cJi/pPp1z8Amgd7Y+m29N+aLBZwlv+OxlhnOCm0Fhjw/dag== + dependencies: + "@babel/core" "^7.12.3" + "@babel/traverse" "^7.12.1" + "@babel/types" "^7.12.1" + "@embroider/core" "0.29.0" + assert-never "^1.1.0" + ember-cli-babel "^7.23.0" + lodash "^4.17.10" + resolve "^1.8.1" + semver "^7.3.2" + +"@embroider/macros@0.33.0": + version "0.33.0" + resolved "https://registry.yarnpkg.com/@embroider/macros/-/macros-0.33.0.tgz#d5826ea7565bb69b57ba81ed528315fe77acbf9d" + integrity sha512-nl/1zRn+Wd3MO8Bb+YPqHmFl/2vwQLTsEB6Zt+K9bWXsM/kA+dPCeeCReLN6PbkMP16xxqtNSIrQ8Y49hnWjpg== + dependencies: + "@babel/core" "^7.12.3" + "@babel/traverse" "^7.12.1" + "@babel/types" "^7.12.1" + "@embroider/core" "0.33.0" + assert-never "^1.1.0" + ember-cli-babel "^7.23.0" + lodash "^4.17.10" + resolve "^1.8.1" + semver "^7.3.2" + +"@embroider/macros@^0.50.1": + version "0.50.1" + resolved "https://registry.yarnpkg.com/@embroider/macros/-/macros-0.50.1.tgz#ce60d55bbaaa515e532e8e929713bce577713be7" + integrity sha512-UYTSUXezEJiR81R1ZERVkOtaMLZKmwkTAiPtrGL6G+uIVMAGWudACVixb5XKVCwwYPlKi1vAHl1I+s7TQi+03Q== + dependencies: + "@embroider/shared-internals" "0.50.1" + assert-never "^1.2.1" + ember-cli-babel "^7.26.6" + find-up "^5.0.0" + lodash "^4.17.21" + resolve "^1.20.0" + semver "^7.3.2" + +"@embroider/shared-internals@0.50.1": + version "0.50.1" + resolved "https://registry.yarnpkg.com/@embroider/shared-internals/-/shared-internals-0.50.1.tgz#80f2499d2ff2ce6f1534dcd55460b8da6e557b0c" + integrity sha512-EJCttIA2EI5gySMOtsHFOHdWmVOCdGxLiSPBGiSM3tAgV4xkxcsXBcfxZ9/j5IwdyH3YdDhIeXP6Lft6Qjt3XQ== + dependencies: + babel-import-util "^1.1.0" + ember-rfc176-data "^0.3.17" + fs-extra "^9.1.0" + lodash "^4.17.21" + resolve-package-path "^4.0.1" + semver "^7.3.5" + typescript-memoize "^1.0.1" + +"@embroider/test-setup@^0.41.0": + version "0.41.0" + resolved "https://registry.yarnpkg.com/@embroider/test-setup/-/test-setup-0.41.0.tgz#7e18fb266ba2f0b131256b303ef4e682f3ca9b20" + integrity sha512-MH8g9G2robf52Ffc1uan21Z/ehwfCHnVa1E5KuI/zau3Ad1HfcRNOGdNwUtpvOr98wPdpTXdJYSg31urcPRUuQ== + dependencies: + lodash "^4.17.20" + resolve "^1.17.0" + +"@eslint/eslintrc@^0.4.3": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" + integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^13.9.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + +"@fullhuman/postcss-purgecss@^2.1.2": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@fullhuman/postcss-purgecss/-/postcss-purgecss-2.3.0.tgz#50a954757ec78696615d3e118e3fee2d9291882e" + integrity sha512-qnKm5dIOyPGJ70kPZ5jiz0I9foVOic0j+cOzNDoo8KoCf6HjicIZ99UfO2OmE7vCYSKAAepEwJtNzpiiZAh9xw== + dependencies: + postcss "7.0.32" + purgecss "^2.3.0" + +"@glimmer/component@^1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@glimmer/component/-/component-1.0.4.tgz#1c85a5181615a6647f6acfaaed68e28ad7e9626e" + integrity sha512-sS4N8wtcKfYdUJ6O3m8nbTut6NjErdz94Ap8VB1ekcg4WSD+7sI7Nmv6kt2rdPoe363nUdjUbRBzHNWhLzraBw== + dependencies: + "@glimmer/di" "^0.1.9" + "@glimmer/env" "^0.1.7" + "@glimmer/util" "^0.44.0" + broccoli-file-creator "^2.1.1" + broccoli-merge-trees "^3.0.2" + ember-cli-babel "^7.7.3" + ember-cli-get-component-path-option "^1.0.0" + ember-cli-is-package-missing "^1.0.0" + ember-cli-normalize-entity-name "^1.0.0" + ember-cli-path-utils "^1.0.0" + ember-cli-string-utils "^1.1.0" + ember-cli-typescript "3.0.0" + ember-cli-version-checker "^3.1.3" + ember-compatibility-helpers "^1.1.2" + +"@glimmer/di@^0.1.9": + version "0.1.11" + resolved "https://registry.yarnpkg.com/@glimmer/di/-/di-0.1.11.tgz#a6878c07a13a2c2c76fcde598a5c97637bfc4280" + integrity sha1-poeMB6E6LCx2/N5ZilyXY3v8QoA= + +"@glimmer/encoder@^0.42.2": + version "0.42.2" + resolved "https://registry.yarnpkg.com/@glimmer/encoder/-/encoder-0.42.2.tgz#d3ba3dc9f1d4fa582d1d18b63da100fc5c664057" + integrity sha512-8xkdly0i0BP5HMI0suPB9ly0AnEq8x9Z8j3Gee1HYIovM5VLNtmh7a8HsaHYRs/xHmBEZcqtr8JV89w6F59YMQ== + dependencies: + "@glimmer/interfaces" "^0.42.2" + "@glimmer/vm" "^0.42.2" + +"@glimmer/env@0.1.7", "@glimmer/env@^0.1.7": + version "0.1.7" + resolved "https://registry.yarnpkg.com/@glimmer/env/-/env-0.1.7.tgz#fd2d2b55a9029c6b37a6c935e8c8871ae70dfa07" + integrity sha1-/S0rVakCnGs3psk16MiHGucN+gc= + +"@glimmer/global-context@0.65.4": + version "0.65.4" + resolved "https://registry.yarnpkg.com/@glimmer/global-context/-/global-context-0.65.4.tgz#1da1d59dd4260ce912c40e474cd39c2e82de51b8" + integrity sha512-RSYCPG/uVR5XCDcPREBclncU7R0zkjACbADP+n3FWAH1TfWbXRMDIkvO/ZlwHkjHoCZf6tIM6p5S/MoFzfJEJA== + dependencies: + "@glimmer/env" "^0.1.7" + +"@glimmer/interfaces@0.65.4": + version "0.65.4" + resolved "https://registry.yarnpkg.com/@glimmer/interfaces/-/interfaces-0.65.4.tgz#d298cc2b12b8ebcf269f39246ca7ab92816f6680" + integrity sha512-R0kby79tGNKZOojVJa/7y0JH9Eq4SV+L1s6GcZy30QUZ1g1AAGS5XwCIXc9Sc09coGcv//q+6NLeSw7nlx1y4A== + dependencies: + "@simple-dom/interface" "^1.4.0" + +"@glimmer/interfaces@0.79.4": + version "0.79.4" + resolved "https://registry.yarnpkg.com/@glimmer/interfaces/-/interfaces-0.79.4.tgz#3213e7fe73f35340762bef7f4e8c8df593a4a8c8" + integrity sha512-cyNZlRa7aXAfXY9kk7hhnWgL1R7Zw8wwi2UVEWq2nBanmpNmL1lSMJ6nY8oRIWCtWrYA9CeH7RZ6mVP5cQ/v2w== + dependencies: + "@simple-dom/interface" "^1.4.0" + +"@glimmer/interfaces@^0.42.2": + version "0.42.2" + resolved "https://registry.yarnpkg.com/@glimmer/interfaces/-/interfaces-0.42.2.tgz#9cf8d6f8f5eee6bfcfa36919ca68ae716e1f78db" + integrity sha512-7LOuQd02cxxNNHChzdHMAU8/qOeQvTro141CU5tXITP7z6aOv2D2gkFdau97lLQiVxezGrh8J7h8GCuF7TEqtg== + +"@glimmer/low-level@^0.42.2": + version "0.42.2" + resolved "https://registry.yarnpkg.com/@glimmer/low-level/-/low-level-0.42.2.tgz#52c745414d1d04c4245c369bd132c0e786c816ef" + integrity sha512-s+Q44SnKdTBTnkgX0deBlVNnNPVas+Pg8xEnwky9VrUqOHKsIZRrPgfVULeC6bIdFXtXOKm5CjTajhb9qnQbXQ== + +"@glimmer/program@^0.42.2": + version "0.42.2" + resolved "https://registry.yarnpkg.com/@glimmer/program/-/program-0.42.2.tgz#fe504679ca4df6251dd5fcf3003699bb51fa41fa" + integrity sha512-XpQ6EYzA1VL9ESKoih5XW5JftFmlRvwy3bF/I1ABOa3yLIh8mApEwrRI/sIHK0Nv5s1j0uW4itVF196WxnJXgw== + dependencies: + "@glimmer/encoder" "^0.42.2" + "@glimmer/interfaces" "^0.42.2" + "@glimmer/util" "^0.42.2" + +"@glimmer/reference@^0.42.1", "@glimmer/reference@^0.42.2": + version "0.42.2" + resolved "https://registry.yarnpkg.com/@glimmer/reference/-/reference-0.42.2.tgz#57874e27c825fb7041b5295b5eb153f3f3f92f8f" + integrity sha512-XuhbRjr3M9Q/DP892jGxVfPE6jaGGHu5w9ppGMnuTY7Vm/x+A+68MCiaREhDcEwJlzGg4UkfVjU3fdgmUIrc5Q== + dependencies: + "@glimmer/util" "^0.42.2" + +"@glimmer/reference@^0.65.0": + version "0.65.4" + resolved "https://registry.yarnpkg.com/@glimmer/reference/-/reference-0.65.4.tgz#bbc8becd6a1bf01fc189b6489e27446437194711" + integrity sha512-yuRVE4qyqrlCndDMrHKDWUbDmGDCjPzsFtlTmxxnhDMJAdQsnr2cRLITHvQRDm1tXfigVvyKnomeuYhRRbBqYQ== + dependencies: + "@glimmer/env" "^0.1.7" + "@glimmer/global-context" "0.65.4" + "@glimmer/interfaces" "0.65.4" + "@glimmer/util" "0.65.4" + "@glimmer/validator" "0.65.4" + +"@glimmer/runtime@^0.42.1": + version "0.42.2" + resolved "https://registry.yarnpkg.com/@glimmer/runtime/-/runtime-0.42.2.tgz#50e7da5d3cf9144248048a7478be3c489784a4bb" + integrity sha512-52LVZJsLKM3GzI3TEmYcw2LdI9Uk0jotISc3w2ozQBWvkKoYxjDNvI/gsjyMpenj4s7FcG2ggOq0x4tNFqm1GA== + dependencies: + "@glimmer/interfaces" "^0.42.2" + "@glimmer/low-level" "^0.42.2" + "@glimmer/program" "^0.42.2" + "@glimmer/reference" "^0.42.2" + "@glimmer/util" "^0.42.2" + "@glimmer/vm" "^0.42.2" + "@glimmer/wire-format" "^0.42.2" + +"@glimmer/syntax@^0.42.1": + version "0.42.2" + resolved "https://registry.yarnpkg.com/@glimmer/syntax/-/syntax-0.42.2.tgz#89bb3cb787285b84665dc0d8907d94b008e5be9a" + integrity sha512-SR26SmF/Mb5o2cc4eLHpOyoX5kwwXP4KRhq4fbWfrvan74xVWA38PLspPCzwGhyVH/JsE7tUEPMjSo2DcJge/Q== + dependencies: + "@glimmer/interfaces" "^0.42.2" + "@glimmer/util" "^0.42.2" + handlebars "^4.0.13" + simple-html-tokenizer "^0.5.8" + +"@glimmer/syntax@^0.65.0": + version "0.65.4" + resolved "https://registry.yarnpkg.com/@glimmer/syntax/-/syntax-0.65.4.tgz#49164de5dc9e8b67084ec009bdd865e379d8a971" + integrity sha512-y+/C3e8w96efk3a/Z5If9o4ztKJwrr8RtDpbhV2J8X+DUsn5ic2N3IIdlThbt/Zn6tkP1K3dY6uaFUx3pGTvVQ== + dependencies: + "@glimmer/interfaces" "0.65.4" + "@glimmer/util" "0.65.4" + "@handlebars/parser" "^1.1.0" + simple-html-tokenizer "^0.5.10" + +"@glimmer/syntax@^0.79.3": + version "0.79.4" + resolved "https://registry.yarnpkg.com/@glimmer/syntax/-/syntax-0.79.4.tgz#5aa21d4b3918238c24da3d640abc3b66150fc0c6" + integrity sha512-NiMIoW2G0+sBfLYnvDaZ8o8Ul/3P/ezOT8U7ZvsHDGU5hXM2buFozyoSKLILTvAQ56izdfK9fKCsn0oi4ISx3w== + dependencies: + "@glimmer/interfaces" "0.79.4" + "@glimmer/util" "0.79.4" + "@handlebars/parser" "~2.0.0" + simple-html-tokenizer "^0.5.10" + +"@glimmer/tracking@^1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@glimmer/tracking/-/tracking-1.0.4.tgz#f1bc1412fe5e2236d0f8d502994a8f88af1bbb21" + integrity sha512-F+oT8I55ba2puSGIzInmVrv/8QA2PcK1VD+GWgFMhF6WC97D+uZX7BFg+a3s/2N4FVBq5KHE+QxZzgazM151Yw== + dependencies: + "@glimmer/env" "^0.1.7" + "@glimmer/validator" "^0.44.0" + +"@glimmer/util@0.65.4": + version "0.65.4" + resolved "https://registry.yarnpkg.com/@glimmer/util/-/util-0.65.4.tgz#e464145078f3f40da9013ff2590a6016515455d2" + integrity sha512-aofe+rdBhkREKP2GZta6jy1UcbRRMfWx7M18zxGxspPoeD08NscD04Kx+WiOKXmC1TcrfITr8jvqMfrKrMzYWQ== + dependencies: + "@glimmer/env" "0.1.7" + "@glimmer/interfaces" "0.65.4" + "@simple-dom/interface" "^1.4.0" + +"@glimmer/util@0.79.4": + version "0.79.4" + resolved "https://registry.yarnpkg.com/@glimmer/util/-/util-0.79.4.tgz#4762ed9b231482470cb9763332097d50042f9bde" + integrity sha512-n2lEGzM9khM43HmKlig2lG5L5cHoL4tFzW21CZzmhMfc1IDCqHuP7s7924OsXSbLT1WB7B9sm/ZhnEj2nd+GiQ== + dependencies: + "@glimmer/env" "0.1.7" + "@glimmer/interfaces" "0.79.4" + "@simple-dom/interface" "^1.4.0" + +"@glimmer/util@^0.42.2": + version "0.42.2" + resolved "https://registry.yarnpkg.com/@glimmer/util/-/util-0.42.2.tgz#9ca1631e42766ea6059f4b49d0bdfb6095aad2c4" + integrity sha512-Heck0baFSaWDanCYtmOcLeaz7v+rSqI8ovS7twrp2/FWEteb3Ze5sWQ2BEuSAG23L/k/lzVwYM/MY7ZugxBpaA== + +"@glimmer/util@^0.44.0": + version "0.44.0" + resolved "https://registry.yarnpkg.com/@glimmer/util/-/util-0.44.0.tgz#45df98d73812440206ae7bda87cfe04aaae21ed9" + integrity sha512-duAsm30uVK9jSysElCbLyU6QQYO2X9iLDLBIBUcCqck9qN1o3tK2qWiHbGK5d6g8E2AJ4H88UrfElkyaJlGrwg== + +"@glimmer/validator@0.65.4", "@glimmer/validator@^0.65.0": + version "0.65.4" + resolved "https://registry.yarnpkg.com/@glimmer/validator/-/validator-0.65.4.tgz#12c27a9a63706c60e6499fd687940e9d1affb32c" + integrity sha512-0YUjAyo45DF5JkQxdv5kHn96nMNhvZiEwsAD4Jme0kk5Q9MQcPOUtN76pQAS4f+C6GdF9DeUr2yGXZLFMmb+LA== + dependencies: + "@glimmer/env" "^0.1.7" + "@glimmer/global-context" "0.65.4" + +"@glimmer/validator@^0.44.0": + version "0.44.0" + resolved "https://registry.yarnpkg.com/@glimmer/validator/-/validator-0.44.0.tgz#03d127097dc9cb23052cdb7fcae59d0a9dca53e1" + integrity sha512-i01plR0EgFVz69GDrEuFgq1NheIjZcyTy3c7q+w7d096ddPVeVcRzU3LKaqCfovvLJ+6lJx40j45ecycASUUyw== + +"@glimmer/vm-babel-plugins@0.80.3": + version "0.80.3" + resolved "https://registry.yarnpkg.com/@glimmer/vm-babel-plugins/-/vm-babel-plugins-0.80.3.tgz#434b62172318cac43830d3ac29818cf2c5f111c1" + integrity sha512-9ej6xlm5MzHBJ5am2l0dbbn8Z0wJoYoMpM8FcrGMlUP6SPMLWxvxpMsApgQo8u6dvZRCjR3/bw3fdf7GOy0AFw== + dependencies: + babel-plugin-debug-macros "^0.3.4" + +"@glimmer/vm@^0.42.2": + version "0.42.2" + resolved "https://registry.yarnpkg.com/@glimmer/vm/-/vm-0.42.2.tgz#492a4f05eac587c3a37371b3c62593f20bef553d" + integrity sha512-D2MNU5glICLqvet5SfVPrv+l6JNK2TR+CdQhch1Ew+btOoqlW+2LIJIF/5wLb1POjIMEkt+78t/7RN0mDFXGzw== + dependencies: + "@glimmer/interfaces" "^0.42.2" + "@glimmer/util" "^0.42.2" + +"@glimmer/wire-format@^0.42.2": + version "0.42.2" + resolved "https://registry.yarnpkg.com/@glimmer/wire-format/-/wire-format-0.42.2.tgz#b95062b594dddeb8bd11cba3a6a0accbfabc9930" + integrity sha512-IqUo6mdJ7GRsK7KCyZxrc17ioSg9RBniEnb418ZMQxsV/WBv9NQ359MuClUck2M24z1AOXo4TerUw0U7+pb1/A== + dependencies: + "@glimmer/interfaces" "^0.42.2" + "@glimmer/util" "^0.42.2" + +"@handlebars/parser@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@handlebars/parser/-/parser-1.1.0.tgz#d6dbc7574774b238114582410e8fee0dc3532bdf" + integrity sha512-rR7tJoSwJ2eooOpYGxGGW95sLq6GXUaS1UtWvN7pei6n2/okYvCGld9vsUTvkl2migxbkszsycwtMf/GEc1k1A== + +"@handlebars/parser@~2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@handlebars/parser/-/parser-2.0.0.tgz#5e8b7298f31ff8f7b260e6b7363c7e9ceed7d9c5" + integrity sha512-EP9uEDZv/L5Qh9IWuMUGJRfwhXJ4h1dqKTT4/3+tY0eu7sPis7xh23j61SYUnNF4vqCQvvUXpDo9Bh/+q1zASA== + +"@humanwhocodes/config-array@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" + integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg== + dependencies: + "@humanwhocodes/object-schema" "^1.2.0" + debug "^4.1.1" + minimatch "^3.0.4" + +"@humanwhocodes/object-schema@^1.2.0": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + +"@jimp/bmp@^0.5.4": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@jimp/bmp/-/bmp-0.5.4.tgz#b7b375aa774f26154912569864d5466e71333ef1" + integrity sha512-P/ezH1FuoM3FwS0Dm2ZGkph4x5/rPBzFLEZor7KQkmGUnYEIEG4o0BUcAWFmJOp2HgzbT6O2SfrpJNBOcVACzQ== + dependencies: + "@jimp/utils" "^0.5.0" + bmp-js "^0.1.0" + core-js "^2.5.7" + +"@jimp/core@^0.5.4": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@jimp/core/-/core-0.5.4.tgz#69d2d9eef1a6a9d62127171e2688cf21bc0ee77c" + integrity sha512-n3uvHy2ndUKItmbhnRO8xmU8J6KR+v6CQxO9sbeUDpSc3VXc1PkqrA8ZsCVFCjnDFcGBXL+MJeCTyQzq5W9Crw== + dependencies: + "@jimp/utils" "^0.5.0" + any-base "^1.1.0" + buffer "^5.2.0" + core-js "^2.5.7" + exif-parser "^0.1.12" + file-type "^9.0.0" + load-bmfont "^1.3.1" + mkdirp "0.5.1" + phin "^2.9.1" + pixelmatch "^4.0.2" + tinycolor2 "^1.4.1" + +"@jimp/custom@^0.5.4": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@jimp/custom/-/custom-0.5.4.tgz#393338efbf15d158ecf6639cb1b196c70411fddd" + integrity sha512-tLfyJoyouDl2J3RPFGfDzTtE+4S8ljqJUmLzy/cmx1n7+xS5TpLPdPskp7UaeAfNTqdF4CNAm94KYoxTZdj2mg== + dependencies: + "@jimp/core" "^0.5.4" + core-js "^2.5.7" + +"@jimp/gif@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@jimp/gif/-/gif-0.5.0.tgz#7543870b3d744c9758da76ca43fac4ee48fd6a00" + integrity sha512-HVB4c7b8r/yCpjhCjVNPRFLuujTav5UPmcQcFJjU6aIxmne6e29rAjRJEv3UMamHDGSu/96PzOsPZBO5U+ZGww== + dependencies: + "@jimp/utils" "^0.5.0" + core-js "^2.5.7" + omggif "^1.0.9" + +"@jimp/jpeg@^0.5.4": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@jimp/jpeg/-/jpeg-0.5.4.tgz#ff52669f801e9d82041ba6322ee781c344e75241" + integrity sha512-YaPWm+YSGCThNE/jLMckM3Qs6uaMxd/VsHOnEaqu5tGA4GFbfVaWHjKqkNGAFuiNV+HdgKlNcCOF3of+elvzqQ== + dependencies: + "@jimp/utils" "^0.5.0" + core-js "^2.5.7" + jpeg-js "^0.3.4" + +"@jimp/plugin-blit@^0.5.4": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-blit/-/plugin-blit-0.5.4.tgz#8c4f46e00c0a4ca9d5c592713de7575528485e59" + integrity sha512-WqDYOugv76hF1wnKy7+xPGf9PUbcm9vPW28/jHWn1hjbb2GnusJ2fVEFad76J/1SPfhrQ2Uebf2QCWJuLmOqZg== + dependencies: + "@jimp/utils" "^0.5.0" + core-js "^2.5.7" + +"@jimp/plugin-blur@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@jimp/plugin-blur/-/plugin-blur-0.5.0.tgz#c8222bdae8eb4cc86613c0adbcb26a92829739a2" + integrity sha512-5k0PXCA1RTJdITL7yMAyZ5tGQjKLHqFvwdXj/PCoBo5PuMyr0x6qfxmQEySixGk/ZHdDxMi80vYxHdKHjNNgjg== + dependencies: + "@jimp/utils" "^0.5.0" + core-js "^2.5.7" + +"@jimp/plugin-color@^0.5.5": + version "0.5.5" + resolved "https://registry.yarnpkg.com/@jimp/plugin-color/-/plugin-color-0.5.5.tgz#68f9652d5065d3380a9967911a7e529325d230d6" + integrity sha512-hWeOqNCmLguGYLhSvBrpfCvlijsMEVaLZAOod62s1rzWnujozyKOzm2eZe+W3To6mHbp5RGJNVrIwHBWMab4ug== + dependencies: + "@jimp/utils" "^0.5.0" + core-js "^2.5.7" + tinycolor2 "^1.4.1" + +"@jimp/plugin-contain@^0.5.4": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-contain/-/plugin-contain-0.5.4.tgz#1dc258db36d50e23400e0644b7f2694fd74fbf60" + integrity sha512-8YJh4FI3S69unri0nJsWeqVLeVGA77N2R0Ws16iSuCCD/5UnWd9FeWRrSbKuidBG6TdMBaG2KUqSYZeHeH9GOQ== + dependencies: + "@jimp/utils" "^0.5.0" + core-js "^2.5.7" + +"@jimp/plugin-cover@^0.5.4": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-cover/-/plugin-cover-0.5.4.tgz#a086243b151db9eef09e657fbe8bc3ef8683662e" + integrity sha512-2Rur7b44WiDDgizUI2M2uYWc1RmfhU5KjKS1xXruobjQ0tXkf5xlrPXSushq0hB6Ne0Ss6wv0+/6eQ8WeGHU2w== + dependencies: + "@jimp/utils" "^0.5.0" + core-js "^2.5.7" + +"@jimp/plugin-crop@^0.5.4": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-crop/-/plugin-crop-0.5.4.tgz#124cf52aa07e36c7a33f39e2e86e78166c300ca7" + integrity sha512-6t0rqn4VazquGk48tO6hFBrQ+nkvC+A1RnR6UM/m8ZtG2/yjpwF0MXcpgJI1Fb+a4Ug7BY1fu2GPcZOhnAVK/g== + dependencies: + "@jimp/utils" "^0.5.0" + core-js "^2.5.7" + +"@jimp/plugin-displace@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@jimp/plugin-displace/-/plugin-displace-0.5.0.tgz#cb75d8588bdee45c1bdb1bec2323705d0e53d060" + integrity sha512-Bec7SQvnmKia4hOXEDjeNVx7vo/1bWqjuV6NO8xbNQcAO3gaCl91c9FjMDhsfAVb0Ou6imhbIuFPrLxorXsecQ== + dependencies: + "@jimp/utils" "^0.5.0" + core-js "^2.5.7" + +"@jimp/plugin-dither@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@jimp/plugin-dither/-/plugin-dither-0.5.0.tgz#0f1f6b7dcd5aba8f908bbd4b60685fc29cc6a3ed" + integrity sha512-We2WJQsD/Lm8oqBFp/vUv9/5r2avyenL+wNNu/s2b1HqA5O4sPGrjHy9K6vIov0NroQGCQ3bNznLkTmjiHKBcg== + dependencies: + "@jimp/utils" "^0.5.0" + core-js "^2.5.7" + +"@jimp/plugin-flip@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@jimp/plugin-flip/-/plugin-flip-0.5.0.tgz#4a973c9c4bdc6dbcc7da66204a2bb2b12feb9381" + integrity sha512-D/ehBQxLMNR7oNd80KXo4tnSET5zEm5mR70khYOTtTlfti/DlLp3qOdjPOzfLyAdqO7Ly4qCaXrIsnia+pfPrA== + dependencies: + "@jimp/utils" "^0.5.0" + core-js "^2.5.7" + +"@jimp/plugin-gaussian@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@jimp/plugin-gaussian/-/plugin-gaussian-0.5.0.tgz#02c9f07516108e01ba0f2938289b08e6e865c2c9" + integrity sha512-Ln4kgxblv0/YzLBDb/J8DYPLhDzKH87Y8yHh5UKv3H+LPKnLaEG3L4iKTE9ivvdocnjmrtTFMYcWv2ERSPeHcg== + dependencies: + "@jimp/utils" "^0.5.0" + core-js "^2.5.7" + +"@jimp/plugin-invert@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@jimp/plugin-invert/-/plugin-invert-0.5.0.tgz#4496d2d67ab498c8fa3e89c4b6dd5892e7f14b9b" + integrity sha512-/vyKeIi3T7puf+8ruWovTjzDC585EnTwJ+lGOOUYiNPsdn4JDFe1B3xd+Ayv9aCQbXDIlPElZaM9vd/+wqDiIQ== + dependencies: + "@jimp/utils" "^0.5.0" + core-js "^2.5.7" + +"@jimp/plugin-mask@^0.5.4": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-mask/-/plugin-mask-0.5.4.tgz#ac4c2625e328818da1443c92bcb9cabb537c74ba" + integrity sha512-mUJ04pCrUWaJGXPjgoVbzhIQB8cVobj2ZEFlGO3BEAjyylYMrdJlNlsER8dd7UuJ2L/a4ocWtFDdsnuicnBghQ== + dependencies: + "@jimp/utils" "^0.5.0" + core-js "^2.5.7" + +"@jimp/plugin-normalize@^0.5.4": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-normalize/-/plugin-normalize-0.5.4.tgz#d60aeb637bcaecadf654c9621e291d6eed12fa19" + integrity sha512-Q5W0oEz9wxsjuhvHAJynI/OqXZcmqEAuRONQId7Aw5ulCXSOg9C4y2a67EO7aZAt55T+zMVxI9UpVUpzVvO6hw== + dependencies: + "@jimp/utils" "^0.5.0" + core-js "^2.5.7" + +"@jimp/plugin-print@^0.5.4": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-print/-/plugin-print-0.5.4.tgz#00524a7424a4e12a17764d349485dd1120a43728" + integrity sha512-DOZr5TY9WyMWFBD37oz7KpTEBVioFIHQF/gH5b3O5jjFyj4JPMkw7k3kVBve9lIrzIYrvLqe0wH59vyAwpeEFg== + dependencies: + "@jimp/utils" "^0.5.0" + core-js "^2.5.7" + load-bmfont "^1.4.0" + +"@jimp/plugin-resize@^0.5.4": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-resize/-/plugin-resize-0.5.4.tgz#c9b2c4949ee080df3fa2ca587539e2ce8588b8af" + integrity sha512-lXNprNAT0QY1D1vG/1x6urUTlWuZe2dfL29P81ApW2Yfcio471+oqo45moX5FLS0q24xU600g7cHGf2/TzqSfA== + dependencies: + "@jimp/utils" "^0.5.0" + core-js "^2.5.7" + +"@jimp/plugin-rotate@^0.5.4": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-rotate/-/plugin-rotate-0.5.4.tgz#6c4c560779bc3ebf291db9a5095158d32a2a4af3" + integrity sha512-SIdUpMc8clObMchy8TnjgHgcXEQM992z5KavgiuOnCuBlsmSHtE3MrXTOyMW0Dn3gqapV9Y5vygrLm/BVtCCsg== + dependencies: + "@jimp/utils" "^0.5.0" + core-js "^2.5.7" + +"@jimp/plugin-scale@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@jimp/plugin-scale/-/plugin-scale-0.5.0.tgz#095f937e5a4887481b3074f5cd6a144d8f4f815e" + integrity sha512-5InIOr3cNtrS5aQ/uaosNf28qLLc0InpNGKFmGFTv8oqZqLch6PtDTjDBZ1GGWsPdA/ljy4Qyy7mJO1QBmgQeQ== + dependencies: + "@jimp/utils" "^0.5.0" + core-js "^2.5.7" + +"@jimp/plugins@^0.5.5": + version "0.5.5" + resolved "https://registry.yarnpkg.com/@jimp/plugins/-/plugins-0.5.5.tgz#e97fa368d69ad7718d5a2a9b6ffa8e6cc1e4264d" + integrity sha512-9oF6LbSM/K7YkFCcxaPaD8NUkL/ZY8vT8NIGfQ/NpX+tKQtcsLHcRavHpUC+M1xXShv/QGx9OdBV/jgiu82QYg== + dependencies: + "@jimp/plugin-blit" "^0.5.4" + "@jimp/plugin-blur" "^0.5.0" + "@jimp/plugin-color" "^0.5.5" + "@jimp/plugin-contain" "^0.5.4" + "@jimp/plugin-cover" "^0.5.4" + "@jimp/plugin-crop" "^0.5.4" + "@jimp/plugin-displace" "^0.5.0" + "@jimp/plugin-dither" "^0.5.0" + "@jimp/plugin-flip" "^0.5.0" + "@jimp/plugin-gaussian" "^0.5.0" + "@jimp/plugin-invert" "^0.5.0" + "@jimp/plugin-mask" "^0.5.4" + "@jimp/plugin-normalize" "^0.5.4" + "@jimp/plugin-print" "^0.5.4" + "@jimp/plugin-resize" "^0.5.4" + "@jimp/plugin-rotate" "^0.5.4" + "@jimp/plugin-scale" "^0.5.0" + core-js "^2.5.7" + timm "^1.6.1" + +"@jimp/png@^0.5.4": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@jimp/png/-/png-0.5.4.tgz#4ed02435ab8ac219b618e9578dfd60626b3b5dd4" + integrity sha512-J2NU7368zihF1HUZdmpXsL/Hhyf+I3ubmK+6Uz3Uoyvtk1VS7dO3L0io6fJQutfWmPZ4bvu6Ry022oHjbi6QCA== + dependencies: + "@jimp/utils" "^0.5.0" + core-js "^2.5.7" + pngjs "^3.3.3" + +"@jimp/tiff@^0.5.4": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@jimp/tiff/-/tiff-0.5.4.tgz#ce5370283eba390ff32b6fd86b9259d7cf3e2315" + integrity sha512-hr7Zq3eWjAZ+itSwuAObIWMRNv7oHVM3xuEDC2ouP7HfE7woBtyhCyfA7u12KlgtM57gKWeogXqTlewRGVzx6g== + dependencies: + core-js "^2.5.7" + utif "^2.0.1" + +"@jimp/types@^0.5.4": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@jimp/types/-/types-0.5.4.tgz#c312e415ec9c4a35770e89b9eee424a96be60ab8" + integrity sha512-nbZXM6TsdpnYHIBd8ZuoxGpvmxc2SqiggY30/bhOP/VJQoDBzm2v/20Ywz5M0snpIK2SdYG52eZPNjfjqUP39w== + dependencies: + "@jimp/bmp" "^0.5.4" + "@jimp/gif" "^0.5.0" + "@jimp/jpeg" "^0.5.4" + "@jimp/png" "^0.5.4" + "@jimp/tiff" "^0.5.4" + core-js "^2.5.7" + timm "^1.6.1" + +"@jimp/utils@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@jimp/utils/-/utils-0.5.0.tgz#ecb33259c75238053d6c7706a3e91f657dbabf91" + integrity sha512-7H9RFVU+Li2XmEko0GGyzy7m7JjSc7qa+m8l3fUzYg2GtwASApjKF/LSG2AUQCUmDKFLdfIEVjxvKvZUJFEmpw== + dependencies: + core-js "^2.5.7" + +"@miragejs/pretender-node-polyfill@^0.1.0": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@miragejs/pretender-node-polyfill/-/pretender-node-polyfill-0.1.2.tgz#d26b6b7483fb70cd62189d05c95d2f67153e43f2" + integrity sha512-M/BexG/p05C5lFfMunxo/QcgIJnMT2vDVCd00wNqK2ImZONIlEETZwWJu1QtLxtmYlSHlCFl3JNzp0tLe7OJ5g== + +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== + dependencies: + "@nodelib/fs.stat" "2.0.3" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== + dependencies: + "@nodelib/fs.scandir" "2.1.3" + fastq "^1.6.0" + +"@simple-dom/document@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@simple-dom/document/-/document-1.4.0.tgz#af60855f957f284d436983798ef1006cca1a1678" + integrity sha512-/RUeVH4kuD3rzo5/91+h4Z1meLSLP66eXqpVAw/4aZmYozkeqUkMprq0znL4psX/adEed5cBgiNJcfMz/eKZLg== + dependencies: + "@simple-dom/interface" "^1.4.0" + +"@simple-dom/interface@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@simple-dom/interface/-/interface-1.4.0.tgz#e8feea579232017f89b0138e2726facda6fbb71f" + integrity sha512-l5qumKFWU0S+4ZzMaLXFU8tQZsicHEMEyAxI5kDFGhJsRqDwe0a7/iPA/GdxlGyDKseQQAgIz5kzU7eXTrlSpA== + +"@simple-dom/parser@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@simple-dom/parser/-/parser-1.4.0.tgz#b1fee1a23f48a37d6bdd98f5242db0cab5b67abc" + integrity sha512-TNjDkOehueRIKr1df416qk9ELj+qWuVVJNIT25y1aZg3pQvxv4UPGrgaDFte7dsWBTbF3V8NYPNQ5FDUZQ8Wlg== + dependencies: + "@simple-dom/interface" "^1.4.0" + +"@simple-dom/serializer@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@simple-dom/serializer/-/serializer-1.4.0.tgz#98470f357f418d72b1a1ec78d68191e60aefe215" + integrity sha512-mI1yRahsVs8atXLiQksineDsFEFqeG7RHwnnBTDOK6inbzl4tZQgjR+Z7edjgIJq5j5RhZvwPI6EuCji9B3eQw== + dependencies: + "@simple-dom/interface" "^1.4.0" + +"@simple-dom/void-map@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@simple-dom/void-map/-/void-map-1.4.0.tgz#f15f07568fe1076740407266aa5e6eac249bc78c" + integrity sha512-VDhLEyVCbuhOBBgHol9ShzIv9O8UCzdXeH4FoXu2DOcu/nnvTjLTck+BgXsCLv5ynDiUdoqsREEVFnoyPpFKVw== + +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + +"@tootallnate/once@2": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" + integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== + +"@types/acorn@^4.0.3": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@types/acorn/-/acorn-4.0.5.tgz#e29fdf884695e77be4e99e67d748f5147255752d" + integrity sha512-603sPiZ4GVRHPvn6vNgEAvJewKsy+zwRWYS2MeIMemgoAtcjlw2G3lALxrb9OPA17J28bkB71R33yXlQbUatCA== + dependencies: + "@types/estree" "*" + +"@types/body-parser@*": + version "1.19.2" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" + integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/broccoli-plugin@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/broccoli-plugin/-/broccoli-plugin-3.0.0.tgz#290fda2270c47a568edfd0cefab8bb840d8bb7b2" + integrity sha512-f+TcsARR2PovfFRKFdCX0kfH/QoM3ZVD2h1rl2mNvrKO0fq2uBNCBsTU3JanfU4COCt5cXpTfARyUsERlC8vIw== + dependencies: + broccoli-plugin "*" + +"@types/chai-as-promised@^7.1.2": + version "7.1.4" + resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.4.tgz#caf64e76fb056b8c8ced4b761ed499272b737601" + integrity sha512-1y3L1cHePcIm5vXkh1DSGf/zQq5n5xDKG1fpCvf18+uOkpce0Z1ozNFPkyWsVswK7ntN1sZBw3oU6gmN+pDUcA== + dependencies: + "@types/chai" "*" + +"@types/chai@*", "@types/chai@^4.2.9": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.0.tgz#23509ebc1fa32f1b4d50d6a66c4032d5b8eaabdc" + integrity sha512-/ceqdqeRraGolFTcfoXNiqjyQhZzbINDngeoAq9GoHa8PPK1yNzTaxWjA6BFWp5Ua9JpXEMSS4s5i9tS0hOJtw== + +"@types/color-name@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" + integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== + +"@types/component-emitter@^1.2.10": + version "1.2.11" + resolved "https://registry.yarnpkg.com/@types/component-emitter/-/component-emitter-1.2.11.tgz#50d47d42b347253817a39709fef03ce66a108506" + integrity sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ== + +"@types/connect@*": + version "3.4.35" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" + integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + dependencies: + "@types/node" "*" + +"@types/cookie@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" + integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== + +"@types/cors@^2.8.12": + version "2.8.12" + resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080" + integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw== + +"@types/ember@^3.1.0": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@types/ember/-/ember-3.1.1.tgz#401810fa3ba911855d609d334ea77990b9b94802" + integrity sha512-8Yu+7qvcRA80NXuJrgii25hi4B/P3lrCug34O2ksPNHk2z1RaLnjKSj0cptQXMQAMnVtM0Vye8lAwUle47/M9w== + dependencies: + "@types/ember__application" "*" + "@types/ember__array" "*" + "@types/ember__component" "*" + "@types/ember__controller" "*" + "@types/ember__debug" "*" + "@types/ember__engine" "*" + "@types/ember__error" "*" + "@types/ember__object" "*" + "@types/ember__polyfills" "*" + "@types/ember__routing" "*" + "@types/ember__runloop" "*" + "@types/ember__service" "*" + "@types/ember__string" "*" + "@types/ember__template" "*" + "@types/ember__test" "*" + "@types/ember__utils" "*" + "@types/htmlbars-inline-precompile" "*" + "@types/jquery" "*" + "@types/rsvp" "*" + +"@types/ember__application@*": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/ember__application/-/ember__application-3.0.7.tgz#8a34f6d75661256d6d6859dcdde848bdd3bea47e" + integrity sha512-7M5Oba1u9fQ1rLs/LeyHqDhnMAqJJF+K2HBBYkbPkD8hf+DR8Ae5PvWXgHwjAmiiWe559zJcapCqawPgzMw8lg== + dependencies: + "@types/ember__application" "*" + "@types/ember__engine" "*" + "@types/ember__object" "*" + "@types/ember__routing" "*" + +"@types/ember__array@*": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/ember__array/-/ember__array-3.0.5.tgz#46bd3a92f8cf4e996e147601856205316f55a0f3" + integrity sha512-NPv5tmvlSgpvAwzIqTNxpR1qqAppMbZBXpasr1Y4TGWlgmWjHRTzhU09sv828Guvd+PXsAluj0n1Jj8o1tuWDw== + dependencies: + "@types/ember__array" "*" + "@types/ember__object" "*" + +"@types/ember__component@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/ember__component/-/ember__component-3.0.6.tgz#1172dd8c9de3e79df643621d77d71f9e2cfa5d8b" + integrity sha512-RLcIiqqVrAV91gx2IIgElYmeT+uUsxjZJb06yrjCtG+uQPQtN0tcF0xX9BCT/wsBQiuk18uXbFJua1alurEZFQ== + dependencies: + "@types/ember__component" "*" + "@types/ember__object" "*" + "@types/jquery" "*" + +"@types/ember__controller@*": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/ember__controller/-/ember__controller-3.0.7.tgz#ae1e897c38d5764e1263d8a9af34286c16b990f6" + integrity sha512-n1ud2QlX0HQ5XkZvpf3yefth3slvBuAFgCiKeu6ypUXnnW2VjJaO+cgCftBBqak6BGWAoziGPrPvAt/1ayx6cA== + dependencies: + "@types/ember__object" "*" + +"@types/ember__debug@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/ember__debug/-/ember__debug-3.0.6.tgz#fa8bbc58249d8bdeea9be5b4ab8e974b33c39b07" + integrity sha512-he07ArVIGzXw79NDEePawpkQSmiDc9C6Z/K6MkD2sUJdVSFaggGXBKvGh/QdenaP8hdYz36/umXGabq/Z862SA== + dependencies: + "@types/ember__debug" "*" + "@types/ember__engine" "*" + "@types/ember__object" "*" + +"@types/ember__engine@*": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/ember__engine/-/ember__engine-3.0.4.tgz#7e79d72653f5c7fd9f6d828d32540be372128aca" + integrity sha512-DfbM0iKgF8mvthZwshDgYn8H1BZQJOk42X5b183K7vbkaye49seeTnPDelrVRRnlMXH6BA6OHAghY92axwVLzw== + dependencies: + "@types/ember__engine" "*" + "@types/ember__object" "*" + +"@types/ember__error@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/ember__error/-/ember__error-3.0.3.tgz#73e5d9f05212d7965e7c2f4df39abdbf5ea41ab1" + integrity sha512-P1+YLJJ9xzc8w5mKYtXsrS070MOTjsNeoGoEHnj7nO5IfeyC34yTHdceW9hoBMRLZs2tZ+cjElUNdR1kxpl+oA== + +"@types/ember__object@*": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@types/ember__object/-/ember__object-3.1.2.tgz#0237a6709b744a23e11a99ac2294df4e122b2c72" + integrity sha512-rFga/FKPedJzwEncNEFOKQHQQ4nC848QRuBhK+jc1w2QQs0IdcQdn/4gQvtHoLKA6PTALujXakiCX/cXdefGnQ== + dependencies: + "@types/ember__object" "*" + "@types/rsvp" "*" + +"@types/ember__polyfills@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/ember__polyfills/-/ember__polyfills-3.0.6.tgz#18908e2583c1175df1e10a22c6656bab8a4cd0de" + integrity sha512-jNp+88chKEeJB/QdqWKApl5bKDf8AXP38WodrhecHlLnZh7AWTHqSV9wZNXReKZAOaPeYibs6J1oEE5baQt4Tg== + +"@types/ember__routing@*": + version "3.0.12" + resolved "https://registry.yarnpkg.com/@types/ember__routing/-/ember__routing-3.0.12.tgz#4a42e5c0276e2eea2665ac08a890991efdc1c09d" + integrity sha512-uguCrJdycNJtLrdgiu3bfqpcQ4dhCCrS7wB5CyTAvy0SNcqfRBxGOlPUBzgljxPYCtQ1kIqJpmoPorG56hTi0A== + dependencies: + "@types/ember__component" "*" + "@types/ember__controller" "*" + "@types/ember__object" "*" + "@types/ember__routing" "*" + "@types/ember__service" "*" + +"@types/ember__runloop@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/ember__runloop/-/ember__runloop-3.0.6.tgz#5a30b51e542c984439a01e0e441c07b817beefc3" + integrity sha512-mD8NQf7z5UOaoqajOeRhc/CPk5JxiPQdJJWeT17zaqU1pmbwNxGQejX1UUaU5GYYSr2rXq07nySfA/lIsJjsig== + dependencies: + "@types/ember__runloop" "*" + +"@types/ember__service@*": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/ember__service/-/ember__service-3.0.5.tgz#6e566ae03eb26ec16ea6cc84e9cc190d926b791b" + integrity sha512-mThqrHMYVGSvsLRwJRWW0HV2DJ9WwLxiC13kSffhRqAKjQfeyq6ELoGtbXXMY3ri/nnGQJ6MVYY142s7AWdT/A== + dependencies: + "@types/ember__object" "*" + +"@types/ember__string@*": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/ember__string/-/ember__string-3.0.7.tgz#0a2319e4540f5964f62ad2fab63ba472dd3f4950" + integrity sha512-qs5tfiJtEECVDCisJq25T3Amxk/th0NcFvX8VNeigNeiTStgVXkJYrfOO3tJQRdaeE9zoskJTbgy0GoQYf3edw== + dependencies: + "@types/ember__template" "*" + +"@types/ember__template@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/ember__template/-/ember__template-3.0.0.tgz#d499ebf000faa371c1c98124633b9864be69b968" + integrity sha512-aWNg/kL2QToE0fwI8MVgAr2upWyAUwqRv2sp3CpypsMTOC1lZizIehz8QI6w1m1+Eh1WYs/89gvuM3mTc4OyIw== + +"@types/ember__test@*": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/ember__test/-/ember__test-3.0.5.tgz#8435b9b3caa5b97a9057d8f4e922c20f2279f93f" + integrity sha512-7F45zVSaM1hqXtv0bTMOLwgvATPfAGsnvU5CmMdUpuLBHRnOIe5HDAx0s1Yr4I318IAT5LgAX180dIJmXs1/+g== + dependencies: + "@types/ember__application" "*" + +"@types/ember__utils@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/ember__utils/-/ember__utils-3.0.3.tgz#c7bfe0ea89411f3376965a1214028561fdcd24eb" + integrity sha512-GhXlUsGln/7PzLMqmtplqLSG8IWu2F9AjEKlqds/BrZlQtbMVS3MCvIkH1R8xlatYml02PqIdd9rZLi7r6QS6Q== + +"@types/eslint@^7.2.13": + version "7.29.0" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.29.0.tgz#e56ddc8e542815272720bb0b4ccc2aff9c3e1c78" + integrity sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*": + version "0.0.44" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.44.tgz#980cc5a29a3ef3bea6ff1f7d021047d7ea575e21" + integrity sha512-iaIVzr+w2ZJ5HkidlZ3EJM8VTZb2MJLCjw3V+505yVts0gRC4UMvjw0d1HPtGqI/HQC/KdsYtayfzl+AXY2R8g== + +"@types/estree@0.0.39": + version "0.0.39" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" + integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== + +"@types/events@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" + integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== + +"@types/express-serve-static-core@^4.17.18": + version "4.17.26" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.26.tgz#5d9a8eeecb9d5f9d7fc1d85f541512a84638ae88" + integrity sha512-zeu3tpouA043RHxW0gzRxwCHchMgftE8GArRsvYT0ByDMbn19olQHx5jLue0LxWY6iYtXb7rXmuVtSkhy9YZvQ== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + +"@types/express@^4.17.2": + version "4.17.13" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" + integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.18" + "@types/qs" "*" + "@types/serve-static" "*" + +"@types/fs-extra@^5.0.5": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-5.1.0.tgz#2a325ef97901504a3828718c390d34b8426a10a1" + integrity sha512-AInn5+UBFIK9FK5xc9yP5e3TQSPNNgjHByqYcj9g5elVBnDQcQL7PlO1CIRy2gWlbwK7UPYqi7vRvFA44dCmYQ== + dependencies: + "@types/node" "*" + +"@types/fs-extra@^8.1.0": + version "8.1.2" + resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-8.1.2.tgz#7125cc2e4bdd9bd2fc83005ffdb1d0ba00cca61f" + integrity sha512-SvSrYXfWSc7R4eqnOzbQF4TZmfpNSM9FrSWLU3EUnWBuyZqNBOrv1B1JA3byUDPUl9z4Ab3jeZG2eDdySlgNMg== + dependencies: + "@types/node" "*" + +"@types/glob@*", "@types/glob@^7.1.1": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" + integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w== + dependencies: + "@types/events" "*" + "@types/minimatch" "*" + "@types/node" "*" + +"@types/htmlbars-inline-precompile@*": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/htmlbars-inline-precompile/-/htmlbars-inline-precompile-1.0.1.tgz#de564513fabb165746aecd76369c87bd85e5bbb4" + integrity sha512-sVD2e6QAAHW0Y6Btse+tTA9k9g0iKm87wjxRsgZRU5EwSooz80tenbV+fA+f2BI2g0G2CqxsS1rIlwQCtPRQow== + +"@types/jquery@*": + version "3.3.34" + resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.3.34.tgz#0d3b94057063d3854adaeb579652048fec07ba6c" + integrity sha512-lW9vsVL53Xu/Nj4gi2hNmHGc4u3KKghjqTkAlO0kF5GIOPxbqqnQpgqJBzmn3yXLrPqHb6cmNJ6URnS23Vtvbg== + dependencies: + "@types/sizzle" "*" + +"@types/json-schema@*": + version "7.0.9" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" + integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== + +"@types/mime@^1": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" + integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== + +"@types/minimatch@*", "@types/minimatch@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" + integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== + +"@types/node@*": + version "12.12.31" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.31.tgz#d6b4f9645fee17f11319b508fb1001797425da51" + integrity sha512-T+wnJno8uh27G9c+1T+a1/WYCHzLeDqtsGJkoEdSp2X8RTh3oOCZQcUnjAx90CS8cmmADX51O0FI/tu9s0yssg== + +"@types/node@>=10.0.0": + version "16.11.12" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.12.tgz#ac7fb693ac587ee182c3780c26eb65546a1a3c10" + integrity sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw== + +"@types/node@^9.6.0": + version "9.6.55" + resolved "https://registry.yarnpkg.com/@types/node/-/node-9.6.55.tgz#7cc1358c9c18e71f6c020e410962971863232cf5" + integrity sha512-e/5tg8Ok0gSrN6pvHphnwTK0/CD9VPZrtZqpvvpEFAtfs+ZntusgGaWkf2lSEq1OFe2EDPeUMiMVpy4nZpJ4AQ== + +"@types/q@^1.5.1": + version "1.5.2" + resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" + integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== + +"@types/qs@*": + version "6.9.7" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" + integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + +"@types/range-parser@*": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" + integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + +"@types/rimraf@^2.0.2": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-2.0.4.tgz#403887b0b53c6100a6c35d2ab24f6ccc042fec46" + integrity sha512-8gBudvllD2A/c0CcEX/BivIDorHFt5UI5m46TsNj8DjWCCTTZT74kEe4g+QsY7P/B9WdO98d82zZgXO/RQzu2Q== + dependencies: + "@types/glob" "*" + "@types/node" "*" + +"@types/rimraf@^2.0.3": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-2.0.5.tgz#368fb04d59630b727fc05a74d2ca557f64a8ef98" + integrity sha512-YyP+VfeaqAyFmXoTh3HChxOQMyjByRMsHU7kc5KOJkSlXudhMhQIALbYV7rHh/l8d2lX3VUQzprrcAgWdRuU8g== + dependencies: + "@types/glob" "*" + "@types/node" "*" + +"@types/rsvp@*", "@types/rsvp@^4.0.2": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/rsvp/-/rsvp-4.0.3.tgz#4a1223158453257bce09d42b9eef7cfa6d257482" + integrity sha512-OpRwxbgx16nL/0/7ol0WoLLyLaMXBvtPOHjqLljnzAB/E7Qk1wtjytxgBhOTBMZvuLXnJUqfnjb4W/QclNFvSA== + +"@types/serve-static@*": + version "1.13.10" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9" + integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ== + dependencies: + "@types/mime" "^1" + "@types/node" "*" + +"@types/sizzle@*": + version "2.3.2" + resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47" + integrity sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg== + +"@types/symlink-or-copy@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@types/symlink-or-copy/-/symlink-or-copy-1.2.0.tgz#4151a81b4052c80bc2becbae09f3a9ec010a9c7a" + integrity sha512-Lja2xYuuf2B3knEsga8ShbOdsfNOtzT73GyJmZyY7eGl2+ajOqrs8yM5ze0fsSoYwvA6bw7/Qr7OZ7PEEmYwWg== + +"@webassemblyjs/ast@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" + integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA== + dependencies: + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" + +"@webassemblyjs/floating-point-hex-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4" + integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA== + +"@webassemblyjs/helper-api-error@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2" + integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw== + +"@webassemblyjs/helper-buffer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00" + integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA== + +"@webassemblyjs/helper-code-frame@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27" + integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA== + dependencies: + "@webassemblyjs/wast-printer" "1.9.0" + +"@webassemblyjs/helper-fsm@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8" + integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw== + +"@webassemblyjs/helper-module-context@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07" + integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g== + dependencies: + "@webassemblyjs/ast" "1.9.0" + +"@webassemblyjs/helper-wasm-bytecode@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790" + integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw== + +"@webassemblyjs/helper-wasm-section@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346" + integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + +"@webassemblyjs/ieee754@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4" + integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95" + integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab" + integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w== + +"@webassemblyjs/wasm-edit@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf" + integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/helper-wasm-section" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-opt" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + "@webassemblyjs/wast-printer" "1.9.0" + +"@webassemblyjs/wasm-gen@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c" + integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" + +"@webassemblyjs/wasm-opt@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61" + integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + +"@webassemblyjs/wasm-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e" + integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" + +"@webassemblyjs/wast-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914" + integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/floating-point-hex-parser" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-code-frame" "1.9.0" + "@webassemblyjs/helper-fsm" "1.9.0" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/wast-printer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899" + integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" + "@xtuc/long" "4.2.2" + +"@xmldom/xmldom@^0.7.1": + version "0.7.5" + resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.7.5.tgz#09fa51e356d07d0be200642b0e4f91d8e6dd408d" + integrity sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A== + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +abab@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e" + integrity sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4= + +abab@^2.0.3, abab@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" + integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +abortcontroller-polyfill@^1.4.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.5.0.tgz#2c562f530869abbcf88d949a2b60d1d402e87a7c" + integrity sha512-O6Xk757Jb4o0LMzMOMdWvxpHWrQzruYBaUruFaIOfAQRnWFxfdXYobw12jrVHGtoXk6WiiyYzc0QWN9aL62HQA== + +abortcontroller-polyfill@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.3.tgz#1b5b487bd6436b5b764fd52a612509702c3144b5" + integrity sha512-zetDJxd89y3X99Kvo4qFx8GKlt6GsvN3UcRZHwU6iFA/0KiOmhkTVhe8oRoTBiTVPZu09x3vCra47+w8Yz1+2Q== + +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: + version "1.3.7" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" + integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== + dependencies: + mime-types "~2.1.24" + negotiator "0.6.2" + +acorn-dynamic-import@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz#901ceee4c7faaef7e07ad2a47e890675da50a278" + integrity sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg== + dependencies: + acorn "^5.0.0" + +acorn-globals@^1.0.4: + version "1.0.9" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-1.0.9.tgz#55bb5e98691507b74579d0513413217c380c54cf" + integrity sha1-VbtemGkVB7dFedBRNBMhfDgMVM8= + dependencies: + acorn "^2.1.0" + +acorn-globals@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" + integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== + dependencies: + acorn "^7.1.1" + acorn-walk "^7.1.1" + +acorn-jsx@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-node@^1.6.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8" + integrity sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A== + dependencies: + acorn "^7.0.0" + acorn-walk "^7.0.0" + xtend "^4.0.2" + +acorn-walk@^7.0.0, acorn-walk@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.1.1.tgz#345f0dffad5c735e7373d2fec9a1023e6a44b83e" + integrity sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ== + +acorn@^2.1.0, acorn@^2.4.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-2.7.0.tgz#ab6e7d9d886aaca8b085bc3312b79a198433f0e7" + integrity sha1-q259nYhqrKiwhbwzEreaGYQz8Oc= + +acorn@^5.0.0, acorn@^5.5.3: + version "5.7.4" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e" + integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg== + +acorn@^6.4.1: + version "6.4.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" + integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== + +acorn@^7.0.0, acorn@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf" + integrity sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg== + +acorn@^7.4.0: + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== + +acorn@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.1.0.tgz#52311fd7037ae119cbb134309e901aa46295b3fe" + integrity sha512-LWCF/Wn0nfHOmJ9rzQApGnxnvgfROzGilS8936rqN/lfcYkY9MYZzdMqN+2NJ4SlTc+m5HiSa+kNfDtI64dwUA== + +acorn@^8.5.0: + version "8.6.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.6.0.tgz#e3692ba0eb1a0c83eaa4f37f5fa7368dd7142895" + integrity sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw== + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +ajv-errors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" + integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== + +ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" + integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== + +ajv@^6.1.0, ajv@^6.10.2, ajv@^6.12.0, ajv@^6.5.5: + version "6.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.0.tgz#06d60b96d87b8454a5adaba86e7854da629db4b7" + integrity sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^6.10.0, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.1: + version "8.8.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.8.2.tgz#01b4fef2007a28bf75f0b7fc009f62679de4abbb" + integrity sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +amd-name-resolver@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/amd-name-resolver/-/amd-name-resolver-1.2.0.tgz#fc41b3848824b557313897d71f8d5a0184fbe679" + integrity sha512-hlSTWGS1t6/xq5YCed7YALg7tKZL3rkl7UwEZ/eCIkn8JxmM6fU6Qs/1hwtjQqfuYxlffuUcgYEm0f5xP4YKaA== + dependencies: + ensure-posix-path "^1.0.1" + +amd-name-resolver@^1.2.0, amd-name-resolver@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/amd-name-resolver/-/amd-name-resolver-1.3.1.tgz#ffe71c683c6e7191fc4ae1bb3aaed15abea135d9" + integrity sha512-26qTEWqZQ+cxSYygZ4Cf8tsjDBLceJahhtewxtKZA3SRa4PluuqYCuheemDQD+7Mf5B7sr+zhTDWAHDh02a1Dw== + dependencies: + ensure-posix-path "^1.0.1" + object-hash "^1.3.1" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= + +ansi-colors@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-escapes@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== + +ansi-escapes@^4.2.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61" + integrity sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA== + dependencies: + type-fest "^0.11.0" + +ansi-html@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" + integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4= + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + +ansi-styles@^3.0.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" + integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== + dependencies: + "@types/color-name" "^1.1.1" + color-convert "^2.0.1" + +ansi-to-html@^0.6.15: + version "0.6.15" + resolved "https://registry.yarnpkg.com/ansi-to-html/-/ansi-to-html-0.6.15.tgz#ac6ad4798a00f6aa045535d7f6a9cb9294eebea7" + integrity sha512-28ijx2aHJGdzbs+O5SNQF65r6rrKYnkuwTYm8lZlChuoJ9P1vVzIpWO20sQTqTPDXYp6NFwk326vApTtLVFXpQ== + dependencies: + entities "^2.0.0" + +ansi-to-html@^0.6.6: + version "0.6.14" + resolved "https://registry.yarnpkg.com/ansi-to-html/-/ansi-to-html-0.6.14.tgz#65fe6d08bba5dd9db33f44a20aec331e0010dad8" + integrity sha512-7ZslfB1+EnFSDO5Ju+ue5Y6It19DRnZXWv8jrGHgIlPna5Mh4jz7BV5jCbQneXNFurQcKoolaaAjHtgSBfOIuA== + dependencies: + entities "^1.1.2" + +ansicolors@~0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.2.1.tgz#be089599097b74a5c9c4a84a0cdbcdb62bd87aef" + integrity sha1-vgiVmQl7dKXJxKhKDNvNtivYeu8= + +any-base@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/any-base/-/any-base-1.1.0.tgz#ae101a62bc08a597b4c9ab5b7089d456630549fe" + integrity sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg== + +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + +anymatch@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" + integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +aproba@^1.0.3, aproba@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +argparse@^1.0.7, argparse@~1.0.2: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" + integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= + +array-to-error@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-to-error/-/array-to-error-1.1.1.tgz#d68812926d14097a205579a667eeaf1856a44c07" + integrity sha1-1ogSkm0UCXogVXmmZ+6vGFakTAc= + dependencies: + array-to-sentence "^1.1.0" + +array-to-sentence@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/array-to-sentence/-/array-to-sentence-1.1.0.tgz#c804956dafa53232495b205a9452753a258d39fc" + integrity sha1-yASVba+lMjJJWyBalFJ1OiWNOfw= + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= + +asn1.js@^4.0.0: + version "4.10.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" + integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +asn1@0.1.11: + version "0.1.11" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.1.11.tgz#559be18376d08a4ec4dbe80877d27818639b2df7" + integrity sha1-VZvhg3bQik7E2+gId9J4GGObLfc= + +asn1@~0.2.3: + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + dependencies: + safer-buffer "~2.1.0" + +assert-never@^1.1.0, assert-never@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/assert-never/-/assert-never-1.2.1.tgz#11f0e363bf146205fb08193b5c7b90f4d1cf44fe" + integrity sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw== + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +assert-plus@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.1.5.tgz#ee74009413002d84cec7219c6ac811812e723160" + integrity sha1-7nQAlBMALYTOxyGcasgRgS5yMWA= + +assert@^1.1.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" + integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== + dependencies: + object-assign "^4.1.1" + util "0.10.3" + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +ast-types@0.13.2: + version "0.13.2" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.2.tgz#df39b677a911a83f3a049644fb74fdded23cea48" + integrity sha512-uWMHxJxtfj/1oZClOxDEV1sQ1HCDkA4MG8Gr69KKeBjEVH0R84WlejZ0y2DcwyBlpAEMltmVYkVgqfLFb2oyiA== + +ast-types@0.13.3: + version "0.13.3" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.3.tgz#50da3f28d17bdbc7969a3a2d83a0e4a72ae755a7" + integrity sha512-XTZ7xGML849LkQP86sWdQzfhwbt3YwIO6MqbX9mUNYY98VKaaVZP7YNNm70IpwecbkkxmfC5IYAzOQ/2p29zRA== + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + +async-disk-cache@^1.2.1: + version "1.3.5" + resolved "https://registry.yarnpkg.com/async-disk-cache/-/async-disk-cache-1.3.5.tgz#cc6206ed79bb6982b878fc52e0505e4f52b62a02" + integrity sha512-VZpqfR0R7CEOJZ/0FOTgWq70lCrZyS1rkI8PXugDUkTKyyAUgZ2zQ09gLhMkEn+wN8LYeUTPxZdXtlX/kmbXKQ== + dependencies: + debug "^2.1.3" + heimdalljs "^0.2.3" + istextorbinary "2.1.0" + mkdirp "^0.5.0" + rimraf "^2.5.3" + rsvp "^3.0.18" + username-sync "^1.0.2" + +async-disk-cache@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/async-disk-cache/-/async-disk-cache-2.1.0.tgz#e0f37b187ed8c41a5991518a9556d206ae2843a2" + integrity sha512-iH+boep2xivfD9wMaZWkywYIURSmsL96d6MoqrC94BnGSvXE4Quf8hnJiHGFYhw/nLeIa1XyRaf4vvcvkwAefg== + dependencies: + debug "^4.1.1" + heimdalljs "^0.2.3" + istextorbinary "^2.5.1" + mkdirp "^0.5.0" + rimraf "^3.0.0" + rsvp "^4.8.5" + username-sync "^1.0.2" + +async-each@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== + +async-promise-queue@^1.0.3, async-promise-queue@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/async-promise-queue/-/async-promise-queue-1.0.5.tgz#cb23bce9fce903a133946a700cc85f27f09ea49d" + integrity sha512-xi0aQ1rrjPWYmqbwr18rrSKbSaXIeIwSd1J4KAgVfkq8utNbdZoht7GfvfY6swFUAMJ9obkc4WPJmtGwl+B8dw== + dependencies: + async "^2.4.1" + debug "^2.6.8" + +async@^2.4.1, async@^2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" + integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== + dependencies: + lodash "^4.17.14" + +async@~0.2.9: + version "0.2.10" + resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" + integrity sha1-trvgsGdLnXGXCMo43owjfLUmw9E= + +async@~0.9.0: + version "0.9.2" + resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" + integrity sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0= + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +autoprefixer@^9.4.5: + version "9.7.5" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.5.tgz#8df10b9ff9b5814a8d411a5cfbab9c793c392376" + integrity sha512-URo6Zvt7VYifomeAfJlMFnYDhow1rk2bufwkbamPEAtQFcL11moLk4PnR7n9vlu7M+BkXAZkHFA0mIcY7tjQFg== + dependencies: + browserslist "^4.11.0" + caniuse-lite "^1.0.30001036" + chalk "^2.4.2" + normalize-range "^0.1.2" + num2fraction "^1.2.2" + postcss "^7.0.27" + postcss-value-parser "^4.0.3" + +autoprefixer@^9.8.4: + version "9.8.6" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f" + integrity sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg== + dependencies: + browserslist "^4.12.0" + caniuse-lite "^1.0.30001109" + colorette "^1.2.1" + normalize-range "^0.1.2" + num2fraction "^1.2.2" + postcss "^7.0.32" + postcss-value-parser "^4.1.0" + +aws-sign2@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.5.0.tgz#c57103f7a17fc037f02d7c2e64b602ea223f7d63" + integrity sha1-xXED96F/wDfwLXwuZLYC6iI/fWM= + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.8.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e" + integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug== + +babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-core@^6.26.0, babel-core@^6.26.3: + version "6.26.3" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" + integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.1" + debug "^2.6.9" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.8" + slash "^1.0.0" + source-map "^0.5.7" + +babel-eslint@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" + integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.7.0" + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" + eslint-visitor-keys "^1.0.0" + resolve "^1.12.0" + +babel-generator@6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5" + integrity sha1-rBriAHC3n248odMmlhMFN3TyDcU= + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.6" + trim-right "^1.0.1" + +babel-generator@^6.26.0: + version "6.26.1" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" + integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.7" + trim-right "^1.0.1" + +babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" + integrity sha1-zORReto1b0IgvK6KAsKzRvmlZmQ= + dependencies: + babel-helper-explode-assignable-expression "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-call-delegate@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" + integrity sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340= + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-define-map@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" + integrity sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8= + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-explode-assignable-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" + integrity sha1-8luCz33BBDPFX3BZLVdGQArCLKo= + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" + integrity sha1-00dbjAPtmCQqJbSDUasYOZ01gKk= + dependencies: + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" + integrity sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-hoist-variables@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" + integrity sha1-HssnaJydJVE+rbyZFKc/VAi+enY= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" + integrity sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-regex@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" + integrity sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI= + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-remap-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" + integrity sha1-XsWBgnrXI/7N04HxySg5BnbkVRs= + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" + integrity sha1-v22/5Dk40XNpohPKiov3S2qQqxo= + dependencies: + babel-helper-optimise-call-expression "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helpers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" + integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI= + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-import-util@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/babel-import-util/-/babel-import-util-0.2.0.tgz#b468bb679919601a3570f9e317536c54f2862e23" + integrity sha512-CtWYYHU/MgK88rxMrLfkD356dApswtR/kWZ/c6JifG1m10e7tBBrs/366dFzWMAoqYmG5/JSh+94tUSpIwh+ag== + +babel-import-util@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/babel-import-util/-/babel-import-util-1.1.0.tgz#4156b16ef090c4f0d3cdb869ff799202f24aeb93" + integrity sha512-sfzgAiJsUT1es9yrHAuJZuJfBkkOE7Og6rovAIwK/gNJX6MjDfWTprbPngdJZTd5ye4F3FvpvpQmvKXObRzVYA== + +babel-loader@^8.0.6: + version "8.1.0" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3" + integrity sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw== + dependencies: + find-cache-dir "^2.1.0" + loader-utils "^1.4.0" + mkdirp "^0.5.3" + pify "^4.0.1" + schema-utils "^2.6.5" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-check-es2015-constants@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" + integrity sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-debug-macros@^0.2.0, babel-plugin-debug-macros@^0.2.0-beta.6: + version "0.2.0" + resolved "https://registry.yarnpkg.com/babel-plugin-debug-macros/-/babel-plugin-debug-macros-0.2.0.tgz#0120ac20ce06ccc57bf493b667cf24b85c28da7a" + integrity sha512-Wpmw4TbhR3Eq2t3W51eBAQSdKlr+uAyF0GI4GtPfMCD12Y4cIdpKC9l0RjNTH/P9isFypSqqewMPm7//fnZlNA== + dependencies: + semver "^5.3.0" + +babel-plugin-debug-macros@^0.3.3, babel-plugin-debug-macros@^0.3.4: + version "0.3.4" + resolved "https://registry.yarnpkg.com/babel-plugin-debug-macros/-/babel-plugin-debug-macros-0.3.4.tgz#22961d0cb851a80654cece807a8b4b73d85c6075" + integrity sha512-wfel/vb3pXfwIDZUrkoDrn5FHmlWI96PCJ3UCDv2a86poJ3EQrnArNW5KfHSVJ9IOgxHbo748cQt7sDU+0KCEw== + dependencies: + semver "^5.3.0" + +babel-plugin-dynamic-import-node@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== + dependencies: + object.assign "^4.1.0" + +babel-plugin-ember-data-packages-polyfill@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/babel-plugin-ember-data-packages-polyfill/-/babel-plugin-ember-data-packages-polyfill-0.1.2.tgz#21154c095ddc703722b1fb8bb06c126c0b6d77dc" + integrity sha512-kTHnOwoOXfPXi00Z8yAgyD64+jdSXk3pknnS7NlqnCKAU6YDkXZ4Y7irl66kaZjZn0FBBt0P4YOZFZk85jYOww== + dependencies: + "@ember-data/rfc395-data" "^0.0.4" + +babel-plugin-ember-modules-api-polyfill@^2.6.0: + version "2.13.4" + resolved "https://registry.yarnpkg.com/babel-plugin-ember-modules-api-polyfill/-/babel-plugin-ember-modules-api-polyfill-2.13.4.tgz#cf62bc9bfd808c48d810d5194f4329e9453bd603" + integrity sha512-uxQPkEQAzCYdwhZk16O9m1R4xtCRNy4oEUTBrccOPfzlIahRZJic/JeP/ZEL0BC6Mfq6r55eOg6gMF/zdFoCvA== + dependencies: + ember-rfc176-data "^0.3.13" + +babel-plugin-ember-modules-api-polyfill@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/babel-plugin-ember-modules-api-polyfill/-/babel-plugin-ember-modules-api-polyfill-3.5.0.tgz#27b6087fac75661f779f32e60f94b14d0e9f6965" + integrity sha512-pJajN/DkQUnStw0Az8c6khVcMQHgzqWr61lLNtVeu0g61LRW0k9jyK7vaedrHDWGe/Qe8sxG5wpiyW9NsMqFzA== + dependencies: + ember-rfc176-data "^0.3.17" + +babel-plugin-ember-template-compilation@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/babel-plugin-ember-template-compilation/-/babel-plugin-ember-template-compilation-1.0.1.tgz#64baf434ff1b751c6292936f8b9eb75a2f8149dc" + integrity sha512-V/kY6CDyUNrl5Kx6UPKUPhzSKNfdrxNii+S5zK4dgJvVyoxFv7Ykg06Ct/yskY0LkA4wUPdYN7JOBtYJwHk2sg== + dependencies: + babel-import-util "^0.2.0" + line-column "^1.0.2" + magic-string "^0.25.7" + string.prototype.matchall "^4.0.5" + +babel-plugin-filter-imports@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/babel-plugin-filter-imports/-/babel-plugin-filter-imports-3.0.0.tgz#a849683837ad29960da17492fb32789ab6b09a11" + integrity sha512-p/chjzVTgCxUqyLM0q/pfWVZS7IJTwGQMwNg0LOvuQpKiTftQgZDtkGB8XvETnUw19rRcL7bJCTopSwibTN2tA== + dependencies: + "@babel/types" "^7.4.0" + lodash "^4.17.11" + +babel-plugin-filter-imports@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/babel-plugin-filter-imports/-/babel-plugin-filter-imports-4.0.0.tgz#068f8da15236a96a9602c36dc6f4a6eeca70a4f4" + integrity sha512-jDLlxI8QnfKd7PtieH6pl4tZJzymzfCDCPGdTq/grgbiYAikwDPp/oL0IlFJn0HQjLpcLkyYhPKkUVneRESw5w== + dependencies: + "@babel/types" "^7.7.2" + lodash "^4.17.15" + +babel-plugin-htmlbars-inline-precompile@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/babel-plugin-htmlbars-inline-precompile/-/babel-plugin-htmlbars-inline-precompile-3.2.0.tgz#c4882ea875d0f5683f0d91c1f72e29a4f14b5606" + integrity sha512-IUeZmgs9tMUGXYu1vfke5I18yYJFldFGdNFQOWslXTnDWXzpwPih7QFduUqvT+awDpDuNtXpdt5JAf43Q1Hhzg== + +babel-plugin-htmlbars-inline-precompile@^5.0.0, babel-plugin-htmlbars-inline-precompile@^5.3.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/babel-plugin-htmlbars-inline-precompile/-/babel-plugin-htmlbars-inline-precompile-5.3.1.tgz#5ba272e2e4b6221522401f5f1d98a73b1de38787" + integrity sha512-QWjjFgSKtSRIcsBhJmEwS2laIdrA6na8HAlc/pEAhjHgQsah/gMiBFRZvbQTy//hWxR4BMwV7/Mya7q5H8uHeA== + dependencies: + babel-plugin-ember-modules-api-polyfill "^3.5.0" + line-column "^1.0.2" + magic-string "^0.25.7" + parse-static-imports "^1.1.0" + string.prototype.matchall "^4.0.5" + +babel-plugin-module-resolver@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/babel-plugin-module-resolver/-/babel-plugin-module-resolver-3.2.0.tgz#ddfa5e301e3b9aa12d852a9979f18b37881ff5a7" + integrity sha512-tjR0GvSndzPew/Iayf4uICWZqjBwnlMWjSx6brryfQ81F9rxBVqwDJtFCV8oOs0+vJeefK9TmdZtkIFdFe1UnA== + dependencies: + find-babel-config "^1.1.0" + glob "^7.1.2" + pkg-up "^2.0.0" + reselect "^3.0.1" + resolve "^1.4.0" + +babel-plugin-module-resolver@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/babel-plugin-module-resolver/-/babel-plugin-module-resolver-4.1.0.tgz#22a4f32f7441727ec1fbf4967b863e1e3e9f33e2" + integrity sha512-MlX10UDheRr3lb3P0WcaIdtCSRlxdQsB1sBqL7W0raF070bGl1HQQq5K3T2vf2XAYie+ww+5AKC/WrkjRO2knA== + dependencies: + find-babel-config "^1.2.0" + glob "^7.1.6" + pkg-up "^3.1.0" + reselect "^4.0.0" + resolve "^1.13.1" + +babel-plugin-polyfill-corejs2@^0.1.4: + version "0.1.10" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.1.10.tgz#a2c5c245f56c0cac3dbddbf0726a46b24f0f81d1" + integrity sha512-DO95wD4g0A8KRaHKi0D51NdGXzvpqVLnLu5BTvDlpqUEpTmeEtypgC1xqesORaWmiUOQI14UHKlzNd9iZ2G3ZA== + dependencies: + "@babel/compat-data" "^7.13.0" + "@babel/helper-define-polyfill-provider" "^0.1.5" + semver "^6.1.1" + +babel-plugin-polyfill-corejs2@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.0.tgz#407082d0d355ba565af24126fb6cb8e9115251fd" + integrity sha512-wMDoBJ6uG4u4PNFh72Ty6t3EgfA91puCuAwKIazbQlci+ENb/UU9A3xG5lutjUIiXCIn1CY5L15r9LimiJyrSA== + dependencies: + "@babel/compat-data" "^7.13.11" + "@babel/helper-define-polyfill-provider" "^0.3.0" + semver "^6.1.1" + +babel-plugin-polyfill-corejs3@^0.1.3: + version "0.1.7" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.7.tgz#80449d9d6f2274912e05d9e182b54816904befd0" + integrity sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.1.5" + core-js-compat "^3.8.1" + +babel-plugin-polyfill-corejs3@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.0.tgz#f81371be3fe499d39e074e272a1ef86533f3d268" + integrity sha512-Hcrgnmkf+4JTj73GbK3bBhlVPiLL47owUAnoJIf69Hakl3q+KfodbDXiZWGMM7iqCZTxCG3Z2VRfPNYES4rXqQ== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.3.0" + core-js-compat "^3.20.0" + +babel-plugin-polyfill-regenerator@^0.1.2: + version "0.1.6" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.1.6.tgz#0fe06a026fe0faa628ccc8ba3302da0a6ce02f3f" + integrity sha512-OUrYG9iKPKz8NxswXbRAdSwF0GhRdIEMTloQATJi4bDuFqrXaXcCUT/VGNrr8pBcjMh1RxZ7Xt9cytVJTJfvMg== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.1.5" + +babel-plugin-polyfill-regenerator@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.0.tgz#9ebbcd7186e1a33e21c5e20cae4e7983949533be" + integrity sha512-dhAPTDLGoMW5/84wkgwiLRwMnio2i1fUe53EuvtKMv0pn2p3S8OCoV1xAzfJPl0KOX7IB89s2ib85vbYiea3jg== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.3.0" + +babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + integrity sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU= + +babel-plugin-syntax-dynamic-import@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" + integrity sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo= + +babel-plugin-syntax-exponentiation-operator@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + integrity sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4= + +babel-plugin-syntax-trailing-function-commas@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + integrity sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM= + +babel-plugin-transform-async-to-generator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" + integrity sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E= + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-arrow-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" + integrity sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" + integrity sha1-u8UbSflk1wy42OC5ToICRs46YUE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoping@^6.23.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" + integrity sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8= + dependencies: + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-plugin-transform-es2015-classes@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" + integrity sha1-WkxYpQyclGHlZLSyo7+ryXolhNs= + dependencies: + babel-helper-define-map "^6.24.1" + babel-helper-function-name "^6.24.1" + babel-helper-optimise-call-expression "^6.24.1" + babel-helper-replace-supers "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-computed-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" + integrity sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM= + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-destructuring@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" + integrity sha1-mXux8auWf2gtKwh2/jWNYOdlxW0= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-duplicate-keys@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" + integrity sha1-c+s9MQypaePvnskcU3QabxV2Qj4= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-for-of@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" + integrity sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-function-name@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" + integrity sha1-g0yJhTvDaxrw86TF26qU/Y6sqos= + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" + integrity sha1-T1SgLWzWbPkVKAAZox0xklN3yi4= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" + integrity sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ= + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: + version "6.26.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" + integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + +babel-plugin-transform-es2015-modules-systemjs@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" + integrity sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM= + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-umd@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" + integrity sha1-rJl+YoXNGO1hdq22B9YCNErThGg= + dependencies: + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-object-super@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" + integrity sha1-JM72muIcuDp/hgPa0CH1cusnj40= + dependencies: + babel-helper-replace-supers "^6.24.1" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-parameters@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" + integrity sha1-V6w1GrScrxSpfNE7CfZv3wpiXys= + dependencies: + babel-helper-call-delegate "^6.24.1" + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-shorthand-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" + integrity sha1-JPh11nIch2YbvZmkYi5R8U3jiqA= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-spread@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" + integrity sha1-1taKmfia7cRTbIGlQujdnxdG+NE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-sticky-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" + integrity sha1-AMHNsaynERLN8M9hJsLta0V8zbw= + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-template-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" + integrity sha1-qEs0UPfp+PH2g51taH2oS7EjbY0= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-typeof-symbol@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" + integrity sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-unicode-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" + integrity sha1-04sS9C6nMj9yk4fxinxa4frrNek= + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-exponentiation-operator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" + integrity sha1-KrDJx/MJj6SJB3cruBP+QejeOg4= + dependencies: + babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" + babel-plugin-syntax-exponentiation-operator "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-regenerator@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" + integrity sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8= + dependencies: + regenerator-transform "^0.10.0" + +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + integrity sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-polyfill@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153" + integrity sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM= + dependencies: + babel-runtime "^6.26.0" + core-js "^2.5.0" + regenerator-runtime "^0.10.5" + +babel-preset-env@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" + integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== + dependencies: + babel-plugin-check-es2015-constants "^6.22.0" + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-to-generator "^6.22.0" + babel-plugin-transform-es2015-arrow-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.23.0" + babel-plugin-transform-es2015-classes "^6.23.0" + babel-plugin-transform-es2015-computed-properties "^6.22.0" + babel-plugin-transform-es2015-destructuring "^6.23.0" + babel-plugin-transform-es2015-duplicate-keys "^6.22.0" + babel-plugin-transform-es2015-for-of "^6.23.0" + babel-plugin-transform-es2015-function-name "^6.22.0" + babel-plugin-transform-es2015-literals "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.22.0" + babel-plugin-transform-es2015-modules-commonjs "^6.23.0" + babel-plugin-transform-es2015-modules-systemjs "^6.23.0" + babel-plugin-transform-es2015-modules-umd "^6.23.0" + babel-plugin-transform-es2015-object-super "^6.22.0" + babel-plugin-transform-es2015-parameters "^6.23.0" + babel-plugin-transform-es2015-shorthand-properties "^6.22.0" + babel-plugin-transform-es2015-spread "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.22.0" + babel-plugin-transform-es2015-template-literals "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.23.0" + babel-plugin-transform-es2015-unicode-regex "^6.22.0" + babel-plugin-transform-exponentiation-operator "^6.22.0" + babel-plugin-transform-regenerator "^6.22.0" + browserslist "^3.2.6" + invariant "^2.2.2" + semver "^5.3.0" + +babel-register@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" + integrity sha1-btAhFz4vy0htestFxgCahW9kcHE= + dependencies: + babel-core "^6.26.0" + babel-runtime "^6.26.0" + core-js "^2.5.0" + home-or-tmp "^2.0.0" + lodash "^4.17.4" + mkdirp "^0.5.1" + source-map-support "^0.4.15" + +babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-template@^6.24.1, babel-template@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI= + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@6.26.0, babel-traverse@^6.24.1, babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babel6-plugin-strip-class-callcheck@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/babel6-plugin-strip-class-callcheck/-/babel6-plugin-strip-class-callcheck-6.0.0.tgz#de841c1abebbd39f78de0affb2c9a52ee228fddf" + integrity sha1-3oQcGr6705943gr/ssmlLuIo/d8= + +babylon@6.18.0, babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== + +backbone@^1.1.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/backbone/-/backbone-1.4.0.tgz#54db4de9df7c3811c3f032f34749a4cd27f3bd12" + integrity sha512-RLmDrRXkVdouTg38jcgHhyQ/2zjg7a8E6sz2zxfz21Hh17xDJYUHBZimVIt5fUyS8vbfpeSmTL3gUjTEvUV3qQ== + dependencies: + underscore ">=1.8.3" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +base64-arraybuffer@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-1.0.1.tgz#87bd13525626db4a9838e00a508c2b73efcf348c" + integrity sha512-vFIUq7FdLtjZMhATwDul5RZWv2jpXQ09Pd6jcVEOvIsqCWTRFD/ONHNfyOS8dA/Ippi5dsIgpyKWKZaAKZltbA== + +base64-js@^1.0.2: + version "1.3.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" + integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +base64id@2.0.0, base64id@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" + integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +basic-auth@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a" + integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg== + dependencies: + safe-buffer "5.1.2" + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + +bignumber.js@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-2.4.0.tgz#838a992da9f9d737e0f4b2db0be62bb09dd0c5e8" + integrity sha1-g4qZLan51zfg9LLbC+YrsJ3Qxeg= + +binary-extensions@^1.0.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== + +binary-extensions@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" + integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== + +"binaryextensions@1 || 2": + version "2.2.0" + resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-2.2.0.tgz#e7c6ba82d4f5f5758c26078fe8eea28881233311" + integrity sha512-bHhs98rj/7i/RZpCSJ3uk55pLXOItjIrh2sRQZSM6OoktScX+LxJzvlU+FELp9j3TdcddTmmYArLSGptCTwjuw== + +binaryextensions@^2.1.2: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-2.3.0.tgz#1d269cbf7e6243ea886aa41453c3651ccbe13c22" + integrity sha512-nAihlQsYGyc5Bwq6+EsubvANYGExeJKHDO3RjnvwU042fawQTQfM3Kxn7IHUXQOz4bzfwsGYYHGSvXyW4zOGLg== + +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +bl@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + +blank-object@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/blank-object/-/blank-object-1.0.2.tgz#f990793fbe9a8c8dd013fb3219420bec81d5f4b9" + integrity sha1-+ZB5P76ajI3QE/syGUIL7IHV9Lk= + +bluebird@^3.1.1, bluebird@^3.4.6, bluebird@^3.5.5: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + +bmp-js@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/bmp-js/-/bmp-js-0.0.1.tgz#5ad0147099d13a9f38aa7b99af1d6e78666ed37f" + integrity sha1-WtAUcJnROp84qnuZrx1ueGZu038= + +bmp-js@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/bmp-js/-/bmp-js-0.0.3.tgz#64113e9c7cf1202b376ed607bf30626ebe57b18a" + integrity sha1-ZBE+nHzxICs3btYHvzBibr5XsYo= + +bmp-js@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/bmp-js/-/bmp-js-0.1.0.tgz#e05a63f796a6c1ff25f4771ec7adadc148c07233" + integrity sha1-4Fpj95amwf8l9Hcex62twUjAcjM= + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +body-parser@1.19.0: + version "1.19.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" + integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== + dependencies: + bytes "3.1.0" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "1.7.2" + iconv-lite "0.4.24" + on-finished "~2.3.0" + qs "6.7.0" + raw-body "2.4.0" + type-is "~1.6.17" + +body@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/body/-/body-5.1.0.tgz#e4ba0ce410a46936323367609ecb4e6553125069" + integrity sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk= + dependencies: + continuable-cache "^0.3.1" + error "^7.0.0" + raw-body "~1.1.0" + safe-json-parse "~1.0.1" + +boolbase@^1.0.0, boolbase@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= + +boom@0.4.x: + version "0.4.2" + resolved "https://registry.yarnpkg.com/boom/-/boom-0.4.2.tgz#7a636e9ded4efcefb19cef4947a3c67dfaee911b" + integrity sha1-emNune1O/O+xnO9JR6PGffrukRs= + dependencies: + hoek "0.9.x" + +bower-config@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/bower-config/-/bower-config-1.4.3.tgz#3454fecdc5f08e7aa9cc6d556e492be0669689ae" + integrity sha512-MVyyUk3d1S7d2cl6YISViwJBc2VXCkxF5AUFykvN0PQj5FsUiMNSgAYTso18oRFfyZ6XEtjrgg9MAaufHbOwNw== + dependencies: + graceful-fs "^4.1.3" + minimist "^0.2.1" + mout "^1.0.0" + osenv "^0.1.3" + untildify "^2.1.0" + wordwrap "^0.0.3" + +bower-endpoint-parser@0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/bower-endpoint-parser/-/bower-endpoint-parser-0.2.2.tgz#00b565adbfab6f2d35addde977e97962acbcb3f6" + integrity sha1-ALVlrb+rby01rd3pd+l5Yqy8s/Y= + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.1, braces@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +braces@^3.0.1, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +broccoli-amd-funnel@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/broccoli-amd-funnel/-/broccoli-amd-funnel-2.0.1.tgz#dbdbfd28841731342d538126567c25bea3f15310" + integrity sha512-VRE+0PYAN4jQfkIq3GKRj4U/4UV9rVpLan5ll6fVYV4ziVg4OEfR5GUnILEg++QtR4xSaugRxCPU5XJLDy3bNQ== + dependencies: + broccoli-plugin "^1.3.0" + symlink-or-copy "^1.2.0" + +broccoli-asset-rev@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/broccoli-asset-rev/-/broccoli-asset-rev-3.0.0.tgz#65a28c8a062d6ee2cffd91ed2a8309e0f8253ac6" + integrity sha512-gAHQZnwvtl74tGevUqGuWoyOdJUdMMv0TjGSMzbdyGImr9fZcnM6xmggDA8bUawrMto9NFi00ZtNUgA4dQiUBw== + dependencies: + broccoli-asset-rewrite "^2.0.0" + broccoli-filter "^1.2.2" + broccoli-persistent-filter "^1.4.3" + json-stable-stringify "^1.0.0" + minimatch "^3.0.4" + rsvp "^3.0.6" + +broccoli-asset-rewrite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/broccoli-asset-rewrite/-/broccoli-asset-rewrite-2.0.0.tgz#603c4a52d4c8987a2f681254436923ac0a9c94ab" + integrity sha512-dqhxdQpooNi7LHe8J9Jdxp6o3YPFWl4vQmint6zrsn2sVbOo+wpyiX3erUSt0IBtjNkAxqJjuvS375o2cLBHTA== + dependencies: + broccoli-filter "^1.2.3" + +broccoli-autoprefixer@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/broccoli-autoprefixer/-/broccoli-autoprefixer-8.0.0.tgz#9c21422e2597433146a43df4b02b6699b0885489" + integrity sha512-9HRCaMLihugxO/f55ESmgpjGiKRN5dWlI7ub5dAOl2zLgVCcV5F4BxNrkLn8nhuQABd1WuYFGmv2GwdQsiuXSg== + dependencies: + autoprefixer "^9.8.4" + broccoli-persistent-filter "^3.0.0" + postcss "^7.0.2" + +broccoli-babel-transpiler@^6.5.0: + version "6.5.1" + resolved "https://registry.yarnpkg.com/broccoli-babel-transpiler/-/broccoli-babel-transpiler-6.5.1.tgz#a4afc8d3b59b441518eb9a07bd44149476e30738" + integrity sha512-w6GcnkxvHcNCte5FcLGEG1hUdQvlfvSN/6PtGWU/otg69Ugk8rUk51h41R0Ugoc+TNxyeFG1opRt2RlA87XzNw== + dependencies: + babel-core "^6.26.0" + broccoli-funnel "^2.0.1" + broccoli-merge-trees "^2.0.0" + broccoli-persistent-filter "^1.4.3" + clone "^2.0.0" + hash-for-dep "^1.2.3" + heimdalljs-logger "^0.1.7" + json-stable-stringify "^1.0.0" + rsvp "^4.8.2" + workerpool "^2.3.0" + +broccoli-babel-transpiler@^7.8.0: + version "7.8.0" + resolved "https://registry.yarnpkg.com/broccoli-babel-transpiler/-/broccoli-babel-transpiler-7.8.0.tgz#7e0f01fce5739f49bbadeee7f1e625ca51cad66e" + integrity sha512-dv30Td5uL7dO3NzQUqQKQs+Iq7JGKnCNtvc6GBO76uVPqGnRlsQZcYqdBVr33JrctR+ZrpTUf7TjsFKeDRFA8Q== + dependencies: + "@babel/core" "^7.12.0" + "@babel/polyfill" "^7.11.5" + broccoli-funnel "^2.0.2" + broccoli-merge-trees "^3.0.2" + broccoli-persistent-filter "^2.2.1" + clone "^2.1.2" + hash-for-dep "^1.4.7" + heimdalljs "^0.2.1" + heimdalljs-logger "^0.1.9" + json-stable-stringify "^1.0.1" + rsvp "^4.8.4" + workerpool "^3.1.1" + +broccoli-bridge@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/broccoli-bridge/-/broccoli-bridge-1.0.0.tgz#6223fd64b62062c31333539f0f3c42d0acd92fb1" + integrity sha1-YiP9ZLYgYsMTM1OfDzxC0KzZL7E= + dependencies: + broccoli-plugin "^1.3.0" + fs-extra "^7.0.0" + symlink-or-copy "^1.2.0" + +broccoli-builder@^0.18.14: + version "0.18.14" + resolved "https://registry.yarnpkg.com/broccoli-builder/-/broccoli-builder-0.18.14.tgz#4b79e2f844de11a4e1b816c3f49c6df4776c312d" + integrity sha1-S3ni+ETeEaThuBbD9Jxt9HdsMS0= + dependencies: + broccoli-node-info "^1.1.0" + heimdalljs "^0.2.0" + promise-map-series "^0.2.1" + quick-temp "^0.1.2" + rimraf "^2.2.8" + rsvp "^3.0.17" + silent-error "^1.0.1" + +broccoli-caching-writer@^2.2.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/broccoli-caching-writer/-/broccoli-caching-writer-2.3.1.tgz#b93cf58f9264f003075868db05774f4e7f25bd07" + integrity sha1-uTz1j5Jk8AMHWGjbBXdPTn8lvQc= + dependencies: + broccoli-kitchen-sink-helpers "^0.2.5" + broccoli-plugin "1.1.0" + debug "^2.1.1" + rimraf "^2.2.8" + rsvp "^3.0.17" + walk-sync "^0.2.5" + +broccoli-caching-writer@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/broccoli-caching-writer/-/broccoli-caching-writer-3.0.3.tgz#0bd2c96a9738d6a6ab590f07ba35c5157d7db476" + integrity sha1-C9LJapc41qarWQ8HujXFFX19tHY= + dependencies: + broccoli-kitchen-sink-helpers "^0.3.1" + broccoli-plugin "^1.2.1" + debug "^2.1.1" + rimraf "^2.2.8" + rsvp "^3.0.17" + walk-sync "^0.3.0" + +broccoli-clean-css@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/broccoli-clean-css/-/broccoli-clean-css-1.1.0.tgz#9db143d9af7e0ae79c26e3ac5a9bb2d720ea19fa" + integrity sha1-nbFD2a9+CuecJuOsWpuy1yDqGfo= + dependencies: + broccoli-persistent-filter "^1.1.6" + clean-css-promise "^0.1.0" + inline-source-map-comment "^1.0.5" + json-stable-stringify "^1.0.0" + +broccoli-concat@^3.7.1, broccoli-concat@^3.7.4: + version "3.7.5" + resolved "https://registry.yarnpkg.com/broccoli-concat/-/broccoli-concat-3.7.5.tgz#223beda8c1184252cf08ae020a3d45ffa6a48218" + integrity sha512-rDs1Mej3Ej0Cy5yIO9oIQq5+BCv0opAwS2NW7M0BeCsAMeFM42Z/zacDUC6jKc5OV5wiHvGTyCPLnZkMe0h6kQ== + dependencies: + broccoli-debug "^0.6.5" + broccoli-kitchen-sink-helpers "^0.3.1" + broccoli-plugin "^1.3.0" + ensure-posix-path "^1.0.2" + fast-sourcemap-concat "^1.4.0" + find-index "^1.1.0" + fs-extra "^4.0.3" + fs-tree-diff "^0.5.7" + lodash.merge "^4.6.2" + lodash.omit "^4.1.0" + lodash.uniq "^4.2.0" + walk-sync "^0.3.2" + +broccoli-concat@^4.2.4: + version "4.2.4" + resolved "https://registry.yarnpkg.com/broccoli-concat/-/broccoli-concat-4.2.4.tgz#78e359ddc540b999d815355163bf3cfb6bd67322" + integrity sha512-NgdBIE57r+U/AslBohQr0mCS7PopIWL8dihMI1CzqffQkisAgqWMuddjYmizqRBQlml7crBFaBeUnPDHhf4/RQ== + dependencies: + broccoli-debug "^0.6.5" + broccoli-kitchen-sink-helpers "^0.3.1" + broccoli-plugin "^4.0.2" + ensure-posix-path "^1.0.2" + fast-sourcemap-concat "^2.1.0" + find-index "^1.1.0" + fs-extra "^8.1.0" + fs-tree-diff "^2.0.1" + lodash.merge "^4.6.2" + lodash.omit "^4.1.0" + lodash.uniq "^4.2.0" + +broccoli-concat@^4.2.5: + version "4.2.5" + resolved "https://registry.yarnpkg.com/broccoli-concat/-/broccoli-concat-4.2.5.tgz#d578f00094048b5fc87195e82fbdbde20d838d29" + integrity sha512-dFB5ATPwOyV8S2I7a07HxCoutoq23oY//LhM6Mou86cWUTB174rND5aQLR7Fu8FjFFLxoTbkk7y0VPITJ1IQrw== + dependencies: + broccoli-debug "^0.6.5" + broccoli-kitchen-sink-helpers "^0.3.1" + broccoli-plugin "^4.0.2" + ensure-posix-path "^1.0.2" + fast-sourcemap-concat "^2.1.0" + find-index "^1.1.0" + fs-extra "^8.1.0" + fs-tree-diff "^2.0.1" + lodash.merge "^4.6.2" + lodash.omit "^4.1.0" + lodash.uniq "^4.2.0" + +broccoli-config-loader@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/broccoli-config-loader/-/broccoli-config-loader-1.0.1.tgz#d10aaf8ebc0cb45c1da5baa82720e1d88d28c80a" + integrity sha512-MDKYQ50rxhn+g17DYdfzfEM9DjTuSGu42Db37A8TQHQe8geYEcUZ4SQqZRgzdAI3aRQNlA1yBHJfOeGmOjhLIg== + dependencies: + broccoli-caching-writer "^3.0.3" + +broccoli-config-replace@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/broccoli-config-replace/-/broccoli-config-replace-1.1.2.tgz#6ea879d92a5bad634d11329b51fc5f4aafda9c00" + integrity sha1-bqh52SpbrWNNETKbUfxfSq/anAA= + dependencies: + broccoli-kitchen-sink-helpers "^0.3.1" + broccoli-plugin "^1.2.0" + debug "^2.2.0" + fs-extra "^0.24.0" + +broccoli-debug@^0.6.1, broccoli-debug@^0.6.4, broccoli-debug@^0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/broccoli-debug/-/broccoli-debug-0.6.5.tgz#164a5cdafd8936e525e702bf8f91f39d758e2e78" + integrity sha512-RIVjHvNar9EMCLDW/FggxFRXqpjhncM/3qq87bn/y+/zR9tqEkHvTqbyOc4QnB97NO2m6342w4wGkemkaeOuWg== + dependencies: + broccoli-plugin "^1.2.1" + fs-tree-diff "^0.5.2" + heimdalljs "^0.2.1" + heimdalljs-logger "^0.1.7" + symlink-or-copy "^1.1.8" + tree-sync "^1.2.2" + +broccoli-favicon@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/broccoli-favicon/-/broccoli-favicon-3.0.0.tgz#de839c2dd905abca80b6971f930829ff3d1d2869" + integrity sha512-UMOgXJgQaQWiWFX3f2tto78SOklk2fDcTiF/SldSECSlIbSed1R7e4+0CPqGiQNnDjPHDm+b2wOxkubP5bpccA== + dependencies: + broccoli-caching-writer "^3.0.3" + favicons "^6.2.2" + heimdalljs-logger "^0.1.10" + himalaya "^1.1.0" + lodash.merge "^4.6.2" + +broccoli-file-creator@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/broccoli-file-creator/-/broccoli-file-creator-1.2.0.tgz#27f1b25b1b00e7bb7bf3d5d7abed5f4d5388df4d" + integrity sha512-l9zthHg6bAtnOfRr/ieZ1srRQEsufMZID7xGYRW3aBDv3u/3Eux+Iawl10tAGYE5pL9YB4n5X4vxkp6iNOoZ9g== + dependencies: + broccoli-plugin "^1.1.0" + mkdirp "^0.5.1" + +broccoli-file-creator@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/broccoli-file-creator/-/broccoli-file-creator-2.1.1.tgz#7351dd2496c762cfce7736ce9b49e3fce0c7b7db" + integrity sha512-YpjOExWr92C5vhnK0kmD81kM7U09kdIRZk9w4ZDCDHuHXW+VE/x6AGEOQQW3loBQQ6Jk+k+TSm8dESy4uZsnjw== + dependencies: + broccoli-plugin "^1.1.0" + mkdirp "^0.5.1" + +broccoli-filter@^1.2.2, broccoli-filter@^1.2.3, broccoli-filter@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/broccoli-filter/-/broccoli-filter-1.3.0.tgz#71e3a8e32a17f309e12261919c5b1006d6766de6" + integrity sha512-VXJXw7eBfG82CFxaBDjYmyN7V72D4In2zwLVQJd/h3mBfF3CMdRTsv2L20lmRTtCv1sAHcB+LgMso90e/KYiLw== + dependencies: + broccoli-kitchen-sink-helpers "^0.3.1" + broccoli-plugin "^1.0.0" + copy-dereference "^1.0.0" + debug "^2.2.0" + mkdirp "^0.5.1" + promise-map-series "^0.2.1" + rsvp "^3.0.18" + symlink-or-copy "^1.0.1" + walk-sync "^0.3.1" + +broccoli-flatiron@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/broccoli-flatiron/-/broccoli-flatiron-0.1.3.tgz#fc7bd8faf7db429ed7199933aa2ec7ef84a8d943" + integrity sha512-dD/4ck+LKOLTBzFlxP2zX7fhWt1TFMVR/88b9/wd8LkAHUyAzWs1vBah94ObSvajYGZ7ic+XvMXw+OhmvdlYoQ== + dependencies: + broccoli-plugin "^1.3.0" + mkdirp "^0.5.1" + +broccoli-funnel-reducer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/broccoli-funnel-reducer/-/broccoli-funnel-reducer-1.0.0.tgz#11365b2a785aec9b17972a36df87eef24c5cc0ea" + integrity sha1-ETZbKnha7JsXlyo234fu8kxcwOo= + +broccoli-funnel@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/broccoli-funnel/-/broccoli-funnel-2.0.1.tgz#6823c73b675ef78fffa7ab800f083e768b51d449" + integrity sha512-C8Lnp9TVsSSiZMGEF16C0dCiNg2oJqUKwuZ1K4kVC6qRPG/2Cj/rtB5kRCC9qEbwqhX71bDbfHROx0L3J7zXQg== + dependencies: + array-equal "^1.0.0" + blank-object "^1.0.1" + broccoli-plugin "^1.3.0" + debug "^2.2.0" + fast-ordered-set "^1.0.0" + fs-tree-diff "^0.5.3" + heimdalljs "^0.2.0" + minimatch "^3.0.0" + mkdirp "^0.5.0" + path-posix "^1.0.0" + rimraf "^2.4.3" + symlink-or-copy "^1.0.0" + walk-sync "^0.3.1" + +broccoli-funnel@^2.0.0, broccoli-funnel@^2.0.1, broccoli-funnel@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/broccoli-funnel/-/broccoli-funnel-2.0.2.tgz#0edf629569bc10bd02cc525f74b9a38e71366a75" + integrity sha512-/vDTqtv7ipjEZQOVqO4vGDVAOZyuYzQ/EgGoyewfOgh1M7IQAToBKZI0oAQPgMBeFPPlIbfMuAngk+ohPBuaHQ== + dependencies: + array-equal "^1.0.0" + blank-object "^1.0.1" + broccoli-plugin "^1.3.0" + debug "^2.2.0" + fast-ordered-set "^1.0.0" + fs-tree-diff "^0.5.3" + heimdalljs "^0.2.0" + minimatch "^3.0.0" + mkdirp "^0.5.0" + path-posix "^1.0.0" + rimraf "^2.4.3" + symlink-or-copy "^1.0.0" + walk-sync "^0.3.1" + +broccoli-funnel@^3.0.0, broccoli-funnel@^3.0.3, broccoli-funnel@^3.0.5, broccoli-funnel@^3.0.6, broccoli-funnel@^3.0.8: + version "3.0.8" + resolved "https://registry.yarnpkg.com/broccoli-funnel/-/broccoli-funnel-3.0.8.tgz#f5b62e2763c3918026a15a3c833edc889971279b" + integrity sha512-ng4eIhPYiXqMw6SyGoxPHR3YAwEd2lr9FgBI1CyTbspl4txZovOsmzFkMkGAlu88xyvYXJqHiM2crfLa65T1BQ== + dependencies: + array-equal "^1.0.0" + broccoli-plugin "^4.0.7" + debug "^4.1.1" + fs-tree-diff "^2.0.1" + heimdalljs "^0.2.0" + minimatch "^3.0.0" + walk-sync "^2.0.2" + +broccoli-kitchen-sink-helpers@^0.2.5: + version "0.2.9" + resolved "https://registry.yarnpkg.com/broccoli-kitchen-sink-helpers/-/broccoli-kitchen-sink-helpers-0.2.9.tgz#a5e0986ed8d76fb5984b68c3f0450d3a96e36ecc" + integrity sha1-peCYbtjXb7WYS2jD8EUNOpbjbsw= + dependencies: + glob "^5.0.10" + mkdirp "^0.5.1" + +broccoli-kitchen-sink-helpers@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/broccoli-kitchen-sink-helpers/-/broccoli-kitchen-sink-helpers-0.3.1.tgz#77c7c18194b9664163ec4fcee2793444926e0c06" + integrity sha1-d8fBgZS5ZkFj7E/O4nk0RJJuDAY= + dependencies: + glob "^5.0.10" + mkdirp "^0.5.1" + +broccoli-merge-trees@^1.0.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/broccoli-merge-trees/-/broccoli-merge-trees-1.2.4.tgz#a001519bb5067f06589d91afa2942445a2d0fdb5" + integrity sha1-oAFRm7UGfwZYnZGvopQkRaLQ/bU= + dependencies: + broccoli-plugin "^1.3.0" + can-symlink "^1.0.0" + fast-ordered-set "^1.0.2" + fs-tree-diff "^0.5.4" + heimdalljs "^0.2.1" + heimdalljs-logger "^0.1.7" + rimraf "^2.4.3" + symlink-or-copy "^1.0.0" + +broccoli-merge-trees@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/broccoli-merge-trees/-/broccoli-merge-trees-2.0.1.tgz#14d4b7fc1a90318c12b16f843e6ba2693808100c" + integrity sha512-WjaexJ+I8BxP5V5RNn6um/qDRSmKoiBC/QkRi79FT9ClHfldxRyCDs9mcV7mmoaPlsshmmPaUz5jdtcKA6DClQ== + dependencies: + broccoli-plugin "^1.3.0" + merge-trees "^1.0.1" + +broccoli-merge-trees@^3.0.0, broccoli-merge-trees@^3.0.1, broccoli-merge-trees@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/broccoli-merge-trees/-/broccoli-merge-trees-3.0.2.tgz#f33b451994225522b5c9bcf27d59decfd8ba537d" + integrity sha512-ZyPAwrOdlCddduFbsMyyFzJUrvW6b04pMvDiAQZrCwghlvgowJDY+EfoXn+eR1RRA5nmGHJ+B68T63VnpRiT1A== + dependencies: + broccoli-plugin "^1.3.0" + merge-trees "^2.0.0" + +broccoli-merge-trees@^4.0.0, broccoli-merge-trees@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/broccoli-merge-trees/-/broccoli-merge-trees-4.2.0.tgz#692d3c163ecea08c5714a9434d664e628919f47c" + integrity sha512-nTrQe5AQtCrW4enLRvbD/vTLHqyW2tz+vsLXQe4IEaUhepuMGVKJJr+I8n34Vu6fPjmPLwTjzNC8izMIDMtHPw== + dependencies: + broccoli-plugin "^4.0.2" + merge-trees "^2.0.0" + +broccoli-middleware@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/broccoli-middleware/-/broccoli-middleware-2.1.1.tgz#183635bbef4dc1241533ee001a162f013d776cb9" + integrity sha512-BK8aPhQpOLsHWiftrqXQr84XsvzUqeaN4PlCQOYg5yM0M+WKAHtX2WFXmicSQZOVgKDyh5aeoNTFkHjBAEBzwQ== + dependencies: + ansi-html "^0.0.7" + handlebars "^4.0.4" + has-ansi "^3.0.0" + mime-types "^2.1.18" + +broccoli-node-api@^1.6.0, broccoli-node-api@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/broccoli-node-api/-/broccoli-node-api-1.7.0.tgz#391aa6edecd2a42c63c111b4162956b2fa288cb6" + integrity sha512-QIqLSVJWJUVOhclmkmypJJH9u9s/aWH4+FH6Q6Ju5l+Io4dtwqdPUNmDfw40o6sxhbZHhqGujDJuHTML1wG8Yw== + +broccoli-node-info@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/broccoli-node-info/-/broccoli-node-info-1.1.0.tgz#3aa2e31e07e5bdb516dd25214f7c45ba1c459412" + integrity sha1-OqLjHgflvbUW3SUhT3xFuhxFlBI= + +broccoli-node-info@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/broccoli-node-info/-/broccoli-node-info-2.1.0.tgz#ca84560e8570ff78565bea1699866ddbf58ad644" + integrity sha512-l6qDuboJThHfRVVWQVaTs++bFdrFTP0gJXgsWenczc1PavRVUmL1Eyb2swTAXXMpDOnr2zhNOBLx4w9AxkqbPQ== + +broccoli-output-wrapper@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/broccoli-output-wrapper/-/broccoli-output-wrapper-2.0.0.tgz#f1e0b9b2f259a67fd41a380141c3c20b096828e6" + integrity sha512-V/ozejo+snzNf75i/a6iTmp71k+rlvqjE3+jYfimuMwR1tjNNRdtfno+NGNQB2An9bIAeqZnKhMDurAznHAdtA== + dependencies: + heimdalljs-logger "^0.1.10" + +broccoli-output-wrapper@^3.2.5: + version "3.2.5" + resolved "https://registry.yarnpkg.com/broccoli-output-wrapper/-/broccoli-output-wrapper-3.2.5.tgz#514b17801c92922a2c2f87fd145df2a25a11bc5f" + integrity sha512-bQAtwjSrF4Nu0CK0JOy5OZqw9t5U0zzv2555EA/cF8/a8SLDTIetk9UgrtMVw7qKLKdSpOZ2liZNeZZDaKgayw== + dependencies: + fs-extra "^8.1.0" + heimdalljs-logger "^0.1.10" + symlink-or-copy "^1.2.0" + +broccoli-persistent-filter@^1.1.5, broccoli-persistent-filter@^1.1.6, broccoli-persistent-filter@^1.4.3: + version "1.4.6" + resolved "https://registry.yarnpkg.com/broccoli-persistent-filter/-/broccoli-persistent-filter-1.4.6.tgz#80762d19000880a77da33c34373299c0f6a3e615" + integrity sha512-0RejLwoC95kv4kta8KAa+FmECJCK78Qgm8SRDEK7YyU0N9Cx6KpY3UCDy9WELl3mCXLN8TokNxc7/hp3lL4lfw== + dependencies: + async-disk-cache "^1.2.1" + async-promise-queue "^1.0.3" + broccoli-plugin "^1.0.0" + fs-tree-diff "^0.5.2" + hash-for-dep "^1.0.2" + heimdalljs "^0.2.1" + heimdalljs-logger "^0.1.7" + mkdirp "^0.5.1" + promise-map-series "^0.2.1" + rimraf "^2.6.1" + rsvp "^3.0.18" + symlink-or-copy "^1.0.1" + walk-sync "^0.3.1" + +broccoli-persistent-filter@^2.1.1, broccoli-persistent-filter@^2.2.1, broccoli-persistent-filter@^2.2.2, broccoli-persistent-filter@^2.3.0, broccoli-persistent-filter@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/broccoli-persistent-filter/-/broccoli-persistent-filter-2.3.1.tgz#4a052e0e0868b344c3a2977e35a3d497aa9eca72" + integrity sha512-hVsmIgCDrl2NFM+3Gs4Cr2TA6UPaIZip99hN8mtkaUPgM8UeVnCbxelCvBjUBHo0oaaqP5jzqqnRVvb568Yu5g== + dependencies: + async-disk-cache "^1.2.1" + async-promise-queue "^1.0.3" + broccoli-plugin "^1.0.0" + fs-tree-diff "^2.0.0" + hash-for-dep "^1.5.0" + heimdalljs "^0.2.1" + heimdalljs-logger "^0.1.7" + mkdirp "^0.5.1" + promise-map-series "^0.2.1" + rimraf "^2.6.1" + rsvp "^4.7.0" + symlink-or-copy "^1.0.1" + sync-disk-cache "^1.3.3" + walk-sync "^1.0.0" + +broccoli-persistent-filter@^3.0.0, broccoli-persistent-filter@^3.1.0, broccoli-persistent-filter@^3.1.1, broccoli-persistent-filter@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/broccoli-persistent-filter/-/broccoli-persistent-filter-3.1.2.tgz#41da6b9577be09a170ecde185f2c5a6099f99c4e" + integrity sha512-CbU95RXXVyy+eJV9XTiHUC7NnsY3EvdVrGzp3YgyvO2bzXZFE5/GzDp4X/VQqX+jsk4qyT1HvMOF0sD1DX68TQ== + dependencies: + async-disk-cache "^2.0.0" + async-promise-queue "^1.0.3" + broccoli-plugin "^4.0.3" + fs-tree-diff "^2.0.0" + hash-for-dep "^1.5.0" + heimdalljs "^0.2.1" + heimdalljs-logger "^0.1.7" + promise-map-series "^0.2.1" + rimraf "^3.0.0" + symlink-or-copy "^1.0.1" + sync-disk-cache "^2.0.0" + +broccoli-plugin@*, "broccoli-plugin@1.5.1 - 5", broccoli-plugin@^4.0.0, broccoli-plugin@^4.0.1, broccoli-plugin@^4.0.2, broccoli-plugin@^4.0.3, broccoli-plugin@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/broccoli-plugin/-/broccoli-plugin-4.0.7.tgz#dd176a85efe915ed557d913744b181abe05047db" + integrity sha512-a4zUsWtA1uns1K7p9rExYVYG99rdKeGRymW0qOCNkvDPHQxVi3yVyJHhQbM3EZwdt2E0mnhr5e0c/bPpJ7p3Wg== + dependencies: + broccoli-node-api "^1.7.0" + broccoli-output-wrapper "^3.2.5" + fs-merger "^3.2.1" + promise-map-series "^0.3.0" + quick-temp "^0.1.8" + rimraf "^3.0.2" + symlink-or-copy "^1.3.1" + +broccoli-plugin@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/broccoli-plugin/-/broccoli-plugin-1.1.0.tgz#73e2cfa05f8ea1e3fc1420c40c3d9e7dc724bf02" + integrity sha1-c+LPoF+OoeP8FCDEDD2efcckvwI= + dependencies: + promise-map-series "^0.2.1" + quick-temp "^0.1.3" + rimraf "^2.3.4" + symlink-or-copy "^1.0.1" + +broccoli-plugin@^1.0.0, broccoli-plugin@^1.1.0, broccoli-plugin@^1.2.0, broccoli-plugin@^1.2.1, broccoli-plugin@^1.3.0, broccoli-plugin@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/broccoli-plugin/-/broccoli-plugin-1.3.1.tgz#a26315732fb99ed2d9fb58f12a1e14e986b4fabd" + integrity sha512-DW8XASZkmorp+q7J4EeDEZz+LoyKLAd2XZULXyD9l4m9/hAKV3vjHmB1kiUshcWAYMgTP1m2i4NnqCE/23h6AQ== + dependencies: + promise-map-series "^0.2.1" + quick-temp "^0.1.3" + rimraf "^2.3.4" + symlink-or-copy "^1.1.8" + +broccoli-plugin@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/broccoli-plugin/-/broccoli-plugin-2.1.0.tgz#2fab6c578219cfcc64f773e9616073313fc8b334" + integrity sha512-ElE4caljW4slapyEhSD9jU9Uayc8SoSABWdmY9SqbV8DHNxU6xg1jJsPcMm+cXOvggR3+G+OXAYQeFjWVnznaw== + dependencies: + promise-map-series "^0.2.1" + quick-temp "^0.1.3" + rimraf "^2.3.4" + symlink-or-copy "^1.1.8" + +broccoli-plugin@^3.0.0, broccoli-plugin@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/broccoli-plugin/-/broccoli-plugin-3.1.0.tgz#54ba6dd90a42ec3db5624063292610e326b1e542" + integrity sha512-7w7FP8WJYjLvb0eaw27LO678TGGaom++49O1VYIuzjhXjK5kn2+AMlDm7CaUFw4F7CLGoVQeZ84d8gICMJa4lA== + dependencies: + broccoli-node-api "^1.6.0" + broccoli-output-wrapper "^2.0.0" + fs-merger "^3.0.1" + promise-map-series "^0.2.1" + quick-temp "^0.1.3" + rimraf "^2.3.4" + symlink-or-copy "^1.1.8" + +broccoli-postcss-single@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/broccoli-postcss-single/-/broccoli-postcss-single-5.0.0.tgz#adcd2b92f59504bbb9b5da1f9aa6a1c7afa4d9d5" + integrity sha512-u8o00CadIDnwQkE4tGqxwK5rXgWVTeB8xh1yDk0ZLy2JNMfI5EhbHr+A1HZpfe40Xy5IBmQ7VlbU9aIrCP2R8Q== + dependencies: + broccoli-caching-writer "^3.0.3" + include-path-searcher "^0.1.0" + minimist ">=1.2.5" + mkdirp "^1.0.3" + object-assign "^4.1.1" + postcss "^8.1.4" + +broccoli-postcss@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/broccoli-postcss/-/broccoli-postcss-6.0.0.tgz#79337302398a3b8f19bcfc3691def46b3951fcf9" + integrity sha512-XldlgbRag80S5MTkA63PpCzTrjiEh3P1wkuVT0e9HzLK9hgD7VQLucShGoy3a7O1PkCjr2g+1Awg8xJoSqgKCA== + dependencies: + broccoli-funnel "^3.0.0" + broccoli-persistent-filter "^3.1.1" + minimist ">=1.2.5" + object-assign "^4.1.1" + postcss "^8.1.4" + +broccoli-rollup@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/broccoli-rollup/-/broccoli-rollup-2.1.1.tgz#0b77dc4b7560a53e998ea85f3b56772612d4988d" + integrity sha512-aky/Ovg5DbsrsJEx2QCXxHLA6ZR+9u1TNVTf85soP4gL8CjGGKQ/JU8R3BZ2ntkWzo6/83RCKzX6O+nlNKR5MQ== + dependencies: + "@types/node" "^9.6.0" + amd-name-resolver "^1.2.0" + broccoli-plugin "^1.2.1" + fs-tree-diff "^0.5.2" + heimdalljs "^0.2.1" + heimdalljs-logger "^0.1.7" + magic-string "^0.24.0" + node-modules-path "^1.0.1" + rollup "^0.57.1" + symlink-or-copy "^1.1.8" + walk-sync "^0.3.1" + +broccoli-rollup@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/broccoli-rollup/-/broccoli-rollup-5.0.0.tgz#a77b53bcef1b70e988913fee82265c0a4ca530da" + integrity sha512-QdMuXHwsdz/LOS8zu4HP91Sfi4ofimrOXoYP/lrPdRh7lJYD87Lfq4WzzUhGHsxMfzANIEvl/7qVHKD3cFJ4tA== + dependencies: + "@types/broccoli-plugin" "^3.0.0" + broccoli-plugin "^4.0.7" + fs-tree-diff "^2.0.1" + heimdalljs "^0.2.6" + node-modules-path "^1.0.1" + rollup "^2.50.0" + rollup-pluginutils "^2.8.1" + symlink-or-copy "^1.2.0" + walk-sync "^2.2.0" + +broccoli-slow-trees@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/broccoli-slow-trees/-/broccoli-slow-trees-3.0.1.tgz#9bf2a9e2f8eb3ed3a3f2abdde988da437ccdc9b4" + integrity sha1-m/Kp4vjrPtOj8qvd6YjaQ3zNybQ= + dependencies: + heimdalljs "^0.2.1" + +broccoli-slow-trees@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/broccoli-slow-trees/-/broccoli-slow-trees-3.1.0.tgz#8e48903f59e061bf1213963733b9e61dec2ee5d7" + integrity sha512-FRI7mRTk2wjIDrdNJd6znS7Kmmne4VkAkl8Ix1R/VoePFMD0g0tEl671xswzFqaRjpT9Qu+CC4hdXDLDJBuzMw== + dependencies: + heimdalljs "^0.2.1" + +broccoli-source@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/broccoli-source/-/broccoli-source-1.1.0.tgz#54f0e82c8b73f46580cbbc4f578f0b32fca8f809" + integrity sha1-VPDoLItz9GWAy7xPV48LMvyo+Ak= + +broccoli-source@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/broccoli-source/-/broccoli-source-2.1.2.tgz#e9ae834f143b607e9ec114ade66731500c38b90b" + integrity sha512-1lLayO4wfS0c0Sj50VfHJXNWf94FYY0WUhxj0R77thbs6uWI7USiOWFqQV5dRmhAJnoKaGN4WyLGQbgjgiYFwQ== + +broccoli-source@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/broccoli-source/-/broccoli-source-3.0.0.tgz#c7c9ba24505941b72a0244568285bc859f69dfbd" + integrity sha512-G4Zc8HngZIdASyQOiz/9H/0Gjc2F02EFwhWF4wiueaI+/FBrM9Ixj6Prno/1aiLIYcN0JvRC3oytN9uOVonTww== + dependencies: + broccoli-node-api "^1.6.0" + +broccoli-sri-hash@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/broccoli-sri-hash/-/broccoli-sri-hash-2.1.2.tgz#bc69905ed7a381ad325cc0d02ded071328ebf3f3" + integrity sha1-vGmQXtejga0yXMDQLe0HEyjr8/M= + dependencies: + broccoli-caching-writer "^2.2.0" + mkdirp "^0.5.1" + rsvp "^3.1.0" + sri-toolbox "^0.2.0" + symlink-or-copy "^1.0.1" + +broccoli-stew@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/broccoli-stew/-/broccoli-stew-1.6.0.tgz#01f6d92806ed6679ddbe48d405066a0e164dfbef" + integrity sha512-sUwCJNnYH4Na690By5xcEMAZqKgquUQnMAEuIiL3Z2k63mSw9Xg+7Ew4wCrFrMmXMcLpWjZDOm6Yqnq268N+ZQ== + dependencies: + broccoli-debug "^0.6.1" + broccoli-funnel "^2.0.0" + broccoli-merge-trees "^2.0.0" + broccoli-persistent-filter "^1.1.6" + broccoli-plugin "^1.3.0" + chalk "^2.4.1" + debug "^3.1.0" + ensure-posix-path "^1.0.1" + fs-extra "^5.0.0" + minimatch "^3.0.4" + resolve "^1.8.1" + rsvp "^4.8.3" + symlink-or-copy "^1.2.0" + walk-sync "^0.3.0" + +broccoli-stew@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/broccoli-stew/-/broccoli-stew-2.1.0.tgz#ba73add17fda3b9b01d8cfb343a8b613b7136a0a" + integrity sha512-tgCkuTWYl4uf7k7ib2D79KFEj2hCgnTUNPMnrCoAha0/4bywcNccmaZVWtL9Ex37yX5h5eAbnM/ak2ULoMwSSw== + dependencies: + broccoli-debug "^0.6.5" + broccoli-funnel "^2.0.0" + broccoli-merge-trees "^3.0.1" + broccoli-persistent-filter "^2.1.1" + broccoli-plugin "^1.3.1" + chalk "^2.4.1" + debug "^3.1.0" + ensure-posix-path "^1.0.1" + fs-extra "^6.0.1" + minimatch "^3.0.4" + resolve "^1.8.1" + rsvp "^4.8.4" + symlink-or-copy "^1.2.0" + walk-sync "^0.3.3" + +broccoli-stew@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/broccoli-stew/-/broccoli-stew-3.0.0.tgz#fd1d19d162ad9490b42e5c563b78c26eb1e80b95" + integrity sha512-NXfi+Vas24n3Ivo21GvENTI55qxKu7OwKRnCLWXld8MiLiQKQlWIq28eoARaFj0lTUFwUa4jKZeA7fW9PiWQeg== + dependencies: + broccoli-debug "^0.6.5" + broccoli-funnel "^2.0.0" + broccoli-merge-trees "^3.0.1" + broccoli-persistent-filter "^2.3.0" + broccoli-plugin "^2.1.0" + chalk "^2.4.1" + debug "^4.1.1" + ensure-posix-path "^1.0.1" + fs-extra "^8.0.1" + minimatch "^3.0.4" + resolve "^1.11.1" + rsvp "^4.8.5" + symlink-or-copy "^1.2.0" + walk-sync "^1.1.3" + +broccoli-string-replace@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/broccoli-string-replace/-/broccoli-string-replace-0.1.2.tgz#1ed92f85680af8d503023925e754e4e33676b91f" + integrity sha1-HtkvhWgK+NUDAjkl51Tk4zZ2uR8= + dependencies: + broccoli-persistent-filter "^1.1.5" + minimatch "^3.0.3" + +broccoli-svg-optimizer@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/broccoli-svg-optimizer/-/broccoli-svg-optimizer-2.0.0.tgz#22b6920bee5e126e86b95ae0cdf8ad6cc4be3735" + integrity sha512-zIbUmBeSxl9r18Mqjl0OArvXyAKuSDd4FFVcH5HmiX2/1SFUofL4JN5g5qhP/GqQnLTEVdwr61LawSGDZHcqOg== + dependencies: + broccoli-persistent-filter "^2.3.1" + json-stable-stringify "^1.0.1" + lodash "^4.17.15" + rsvp "^4.8.5" + svgo "1.3.0" + +broccoli-templater@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/broccoli-templater/-/broccoli-templater-2.0.2.tgz#285a892071c0b3ad5ebc275d9e8b3465e2d120d6" + integrity sha512-71KpNkc7WmbEokTQpGcbGzZjUIY1NSVa3GB++KFKAfx5SZPUozCOsBlSTwxcv8TLoCAqbBnsX5AQPgg6vJ2l9g== + dependencies: + broccoli-plugin "^1.3.1" + fs-tree-diff "^0.5.9" + lodash.template "^4.4.0" + rimraf "^2.6.2" + walk-sync "^0.3.3" + +broccoli-terser-sourcemap@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/broccoli-terser-sourcemap/-/broccoli-terser-sourcemap-4.1.0.tgz#5f37441b64a3b6bfb0c67e9af232259c9576f115" + integrity sha512-zkNnjsAbP+M5rG2aMM1EE4BmXPUSxFKmtLUkUs2D1DLTOJQoF1xlOjGWjjKYCFy5tw8t4+tgGJ+HVa2ucJZ8sw== + dependencies: + async-promise-queue "^1.0.5" + broccoli-plugin "^4.0.3" + debug "^4.1.0" + lodash.defaultsdeep "^4.6.1" + matcher-collection "^2.0.1" + source-map-url "^0.4.0" + symlink-or-copy "^1.3.1" + terser "^5.3.0" + walk-sync "^2.2.0" + workerpool "^6.0.0" + +broccoli@^3.5.1: + version "3.5.2" + resolved "https://registry.yarnpkg.com/broccoli/-/broccoli-3.5.2.tgz#60921167d57b43fb5bad527420d62fe532595ef4" + integrity sha512-sWi3b3fTUSVPDsz5KsQ5eCQNVAtLgkIE/HYFkEZXR/07clqmd4E/gFiuwSaqa9b+QTXc1Uemfb7TVWbEIURWDg== + dependencies: + "@types/chai" "^4.2.9" + "@types/chai-as-promised" "^7.1.2" + "@types/express" "^4.17.2" + ansi-html "^0.0.7" + broccoli-node-info "^2.1.0" + broccoli-slow-trees "^3.0.1" + broccoli-source "^3.0.0" + commander "^4.1.1" + connect "^3.6.6" + console-ui "^3.0.4" + esm "^3.2.4" + findup-sync "^4.0.0" + handlebars "^4.7.3" + heimdalljs "^0.2.6" + heimdalljs-logger "^0.1.9" + https "^1.0.0" + mime-types "^2.1.26" + resolve-path "^1.4.0" + rimraf "^3.0.2" + sane "^4.0.0" + tmp "^0.0.33" + tree-sync "^2.0.0" + underscore.string "^3.2.2" + watch-detector "^1.0.0" + +brorand@^1.0.1, brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + +browser-process-hrtime@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" + integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== + +browserify-aes@^1.0.0, browserify-aes@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" + integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= + dependencies: + bn.js "^4.1.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" + integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= + dependencies: + bn.js "^4.1.1" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.2" + elliptic "^6.0.0" + inherits "^2.0.1" + parse-asn1 "^5.0.0" + +browserify-zlib@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== + dependencies: + pako "~1.0.5" + +browserslist@^3.2.6: + version "3.2.8" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" + integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== + dependencies: + caniuse-lite "^1.0.30000844" + electron-to-chromium "^1.3.47" + +browserslist@^4.0.0, browserslist@^4.11.0: + version "4.11.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.11.0.tgz#aef4357b10a8abda00f97aac7cd587b2082ba1ad" + integrity sha512-WqEC7Yr5wUH5sg6ruR++v2SGOQYpyUdYYd4tZoAq1F7y+QXoLoYGXVbxhtaIqWmAJjtNTRjVD3HuJc1OXTel2A== + dependencies: + caniuse-lite "^1.0.30001035" + electron-to-chromium "^1.3.380" + node-releases "^1.1.52" + pkg-up "^3.1.0" + +browserslist@^4.12.0: + version "4.12.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.12.0.tgz#06c6d5715a1ede6c51fc39ff67fd647f740b656d" + integrity sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg== + dependencies: + caniuse-lite "^1.0.30001043" + electron-to-chromium "^1.3.413" + node-releases "^1.1.53" + pkg-up "^2.0.0" + +browserslist@^4.16.3: + version "4.16.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.3.tgz#340aa46940d7db878748567c5dea24a48ddf3717" + integrity sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw== + dependencies: + caniuse-lite "^1.0.30001181" + colorette "^1.2.1" + electron-to-chromium "^1.3.649" + escalade "^3.1.1" + node-releases "^1.1.70" + +browserslist@^4.17.5: + version "4.18.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.18.1.tgz#60d3920f25b6860eb917c6c7b185576f4d8b017f" + integrity sha512-8ScCzdpPwR2wQh8IT82CA2VgDwjHyqMovPBZSNH54+tm4Jk2pCuv90gmAdH6J84OCRWi0b4gMe6O6XPXuJnjgQ== + dependencies: + caniuse-lite "^1.0.30001280" + electron-to-chromium "^1.3.896" + escalade "^3.1.1" + node-releases "^2.0.1" + picocolors "^1.0.0" + +browserslist@^4.19.1: + version "4.19.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.1.tgz#4ac0435b35ab655896c31d53018b6dd5e9e4c9a3" + integrity sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A== + dependencies: + caniuse-lite "^1.0.30001286" + electron-to-chromium "^1.4.17" + escalade "^3.1.1" + node-releases "^2.0.1" + picocolors "^1.0.0" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== + +buffer-alloc@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" + +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= + +buffer-equal@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b" + integrity sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs= + +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + +buffer@^4.3.0: + version "4.9.2" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" + integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + +buffer@^5.2.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.5.0.tgz#9c3caa3d623c33dd1c7ef584b89b88bf9c9bc1ce" + integrity sha512-9FTEDjLjwoAkEwyMGDjYJQN2gfRgOKBKRfiglhvibGbpeeU/pQn1bJxQqm32OD/AIeEuHxU9roxXxg34Byp/Ww== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= + +builtins@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" + integrity sha1-y5T662HIaWRR2zZTThQi+U8K7og= + +bytes@1: + version "1.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-1.0.0.tgz#3569ede8ba34315fab99c3e92cb04c7220de1fa8" + integrity sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g= + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= + +bytes@3.1.0, bytes@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" + integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== + +cacache@^12.0.2: + version "12.0.4" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" + integrity sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ== + dependencies: + bluebird "^3.5.5" + chownr "^1.1.1" + figgy-pudding "^3.5.1" + glob "^7.1.4" + graceful-fs "^4.1.15" + infer-owner "^1.0.3" + lru-cache "^5.1.1" + mississippi "^3.0.0" + mkdirp "^0.5.1" + move-concurrently "^1.0.1" + promise-inflight "^1.0.1" + rimraf "^2.6.3" + ssri "^6.0.1" + unique-filename "^1.1.1" + y18n "^4.0.0" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + +calculate-cache-key-for-tree@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/calculate-cache-key-for-tree/-/calculate-cache-key-for-tree-2.0.0.tgz#7ac57f149a4188eacb0a45b210689215d3fef8d6" + integrity sha512-Quw8a6y8CPmRd6eU+mwypktYCwUcf8yVFIRbNZ6tPQEckX9yd+EBVEPC/GSZZrMWH9e7Vz4pT7XhpmyApRByLQ== + dependencies: + json-stable-stringify "^1.0.1" + +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +callsites@^3.0.0, callsites@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase-css@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" + integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== + +camelcase@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= + +can-symlink@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/can-symlink/-/can-symlink-1.0.0.tgz#97b607d8a84bb6c6e228b902d864ecb594b9d219" + integrity sha1-l7YH2KhLtsbiKLkC2GTstZS50hk= + dependencies: + tmp "0.0.28" + +caniuse-api@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" + integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== + dependencies: + browserslist "^4.0.0" + caniuse-lite "^1.0.0" + lodash.memoize "^4.1.2" + lodash.uniq "^4.5.0" + +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001036, caniuse-lite@^1.0.30001043, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001181, caniuse-lite@^1.0.30001280: + version "1.0.30001286" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001286.tgz" + integrity sha512-zaEMRH6xg8ESMi2eQ3R4eZ5qw/hJiVsO/HlLwniIwErij0JDr9P+8V4dtx1l+kLq6j3yy8l8W4fst1lBnat5wQ== + +caniuse-lite@^1.0.30001286: + version "1.0.30001299" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001299.tgz#d753bf6444ed401eb503cbbe17aa3e1451b5a68c" + integrity sha512-iujN4+x7QzqA2NCSrS5VUy+4gLmRd4xv6vbBBsmfVqTx8bLAD8097euLqQgKxSVLvxjSDcvF1T/i9ocgnUFexw== + +capture-exit@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" + integrity sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g== + dependencies: + rsvp "^4.8.4" + +cardinal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cardinal/-/cardinal-1.0.0.tgz#50e21c1b0aa37729f9377def196b5a9cec932ee9" + integrity sha1-UOIcGwqjdyn5N33vGWtanOyTLuk= + dependencies: + ansicolors "~0.2.1" + redeyed "~1.0.0" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +chalk@^1.0.0, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +"chalk@^3.0.0 || ^4.0.0", chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^4.0.0, chalk@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + +charm@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/charm/-/charm-1.0.2.tgz#8add367153a6d9a581331052c4090991da995e35" + integrity sha1-it02cVOm2aWBMxBSxAkJkdqZXjU= + dependencies: + inherits "^2.0.1" + +cheerio@0.20.0: + version "0.20.0" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.20.0.tgz#5c710f2bab95653272842ba01c6ea61b3545ec35" + integrity sha1-XHEPK6uVZTJyhCugHG6mGzVF7DU= + dependencies: + css-select "~1.2.0" + dom-serializer "~0.1.0" + entities "~1.1.1" + htmlparser2 "~3.8.1" + lodash "^4.1.0" + optionalDependencies: + jsdom "^7.0.2" + +cheerio@0.22.0, cheerio@^0.22.0: + version "0.22.0" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e" + integrity sha1-qbqoYKP5tZWmuBsahocxIe06Jp4= + dependencies: + css-select "~1.2.0" + dom-serializer "~0.1.0" + entities "~1.1.1" + htmlparser2 "^3.9.1" + lodash.assignin "^4.0.9" + lodash.bind "^4.1.4" + lodash.defaults "^4.0.1" + lodash.filter "^4.4.0" + lodash.flatten "^4.2.0" + lodash.foreach "^4.3.0" + lodash.map "^4.4.0" + lodash.merge "^4.4.0" + lodash.pick "^4.2.1" + lodash.reduce "^4.4.0" + lodash.reject "^4.4.0" + lodash.some "^4.4.0" + +cheerio@^1.0.0-rc.2: + version "1.0.0-rc.3" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.3.tgz#094636d425b2e9c0f4eb91a46c05630c9a1a8bf6" + integrity sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA== + dependencies: + css-select "~1.2.0" + dom-serializer "~0.1.1" + entities "~1.1.1" + htmlparser2 "^3.9.1" + lodash "^4.15.0" + parse5 "^3.0.1" + +"chokidar@>=3.0.0 <4.0.0": + version "3.5.2" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" + integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chokidar@^2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" + integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== + dependencies: + anymatch "^2.0.0" + async-each "^1.0.1" + braces "^2.3.2" + glob-parent "^3.1.0" + inherits "^2.0.3" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + normalize-path "^3.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.2.1" + upath "^1.1.1" + optionalDependencies: + fsevents "^1.2.7" + +chokidar@^3.4.1: + version "3.4.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.3.tgz#c1df38231448e45ca4ac588e6c79573ba6a57d5b" + integrity sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.5.0" + optionalDependencies: + fsevents "~2.1.2" + +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +chrome-trace-event@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" + integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== + dependencies: + tslib "^1.9.0" + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +ci-info@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.0.tgz#b4ed1fb6818dea4803a55c623041f9165d2066b2" + integrity sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw== + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +clean-base-url@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clean-base-url/-/clean-base-url-1.0.0.tgz#c901cf0a20b972435b0eccd52d056824a4351b7b" + integrity sha1-yQHPCiC5ckNbDszVLQVoJKQ1G3s= + +clean-css-promise@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/clean-css-promise/-/clean-css-promise-0.1.1.tgz#43f3d2c8dfcb2bf071481252cd9b76433c08eecb" + integrity sha1-Q/PSyN/LK/BxSBJSzZt2QzwI7ss= + dependencies: + array-to-error "^1.0.0" + clean-css "^3.4.5" + pinkie-promise "^2.0.0" + +clean-css@^3.4.5: + version "3.4.28" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-3.4.28.tgz#bf1945e82fc808f55695e6ddeaec01400efd03ff" + integrity sha1-vxlF6C/ICPVWlebd6uwBQA79A/8= + dependencies: + commander "2.8.x" + source-map "0.4.x" + +clean-stack@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +clean-up-path@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clean-up-path/-/clean-up-path-1.0.0.tgz#de9e8196519912e749c9eaf67c13d64fac72a3e5" + integrity sha512-PHGlEF0Z6976qQyN6gM7kKH6EH0RdfZcc8V+QhFe36eRxV0SMH5OUBZG7Bxa9YcreNzyNbK63cGiZxdSZgosRw== + +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= + dependencies: + restore-cursor "^2.0.0" + +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-spinners@^2.0.0, cli-spinners@^2.5.0: + version "2.6.1" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.1.tgz#adc954ebe281c37a6319bfa401e6dd2488ffb70d" + integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g== + +cli-table3@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.0.tgz#b7b1bc65ca8e7b5cef9124e13dc2b21e2ce4faee" + integrity sha512-gnB85c3MGC7Nm9I/FkiasNBOKjOiO1RNuXXarQms37q4QMpWdlbBgD/VnOStA2faG1dpXMv31RFApjX1/QdgWQ== + dependencies: + object-assign "^4.1.0" + string-width "^4.2.0" + optionalDependencies: + colors "^1.1.2" + +cli-table@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.1.tgz#f53b05266a8b1a0b934b3d0821e6e2dc5914ae23" + integrity sha1-9TsFJmqLGguTSz0IIebi3FkUriM= + dependencies: + colors "1.0.3" + +cli-width@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= + +cli-width@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" + integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== + +clipboard@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.6.tgz#52921296eec0fdf77ead1749421b21c968647376" + integrity sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg== + dependencies: + good-listener "^1.2.2" + select "^1.1.2" + tiny-emitter "^2.0.0" + +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +clone-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" + integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= + +clone-response@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" + integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + dependencies: + mimic-response "^1.0.0" + +clone-stats@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" + integrity sha1-s3gt/4u1R04Yuba/D9/ngvh3doA= + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= + +clone@^2.0.0, clone@^2.1.1, clone@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= + +cloneable-readable@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.3.tgz#120a00cb053bfb63a222e709f9683ea2e11d8cec" + integrity sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ== + dependencies: + inherits "^2.0.1" + process-nextick-args "^2.0.0" + readable-stream "^2.3.5" + +coa@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" + integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== + dependencies: + "@types/q" "^1.5.1" + chalk "^2.4.1" + q "^1.1.2" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0, color-convert@^1.9.1: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-logger@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/color-logger/-/color-logger-0.0.3.tgz#d9b22dd1d973e166b18bf313f9f481bba4df2018" + integrity sha1-2bIt0dlz4Waxi/MT+fSBu6TfIBg= + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@^1.0.0, color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-string@^1.5.2: + version "1.8.2" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.8.2.tgz#08bd49fa5f3889c27b0c670052ed746dd7a671de" + integrity sha512-w5ZkKRdLsc5NOYsmnpS2DpyRW71npwZGwbRpLrJTuqjfTs2Bhrba7UiV59IX9siBlCPl2pne5NtiwnVWUzvYFA== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/color/-/color-3.1.2.tgz#68148e7f85d41ad7649c5fa8c8106f098d229e10" + integrity sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg== + dependencies: + color-convert "^1.9.1" + color-string "^1.5.2" + +colorette@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b" + integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw== + +colors@1.0.3, colors@1.4.0, colors@^1.1.2, colors@^1.3.2, colors@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +combined-stream@~0.0.4: + version "0.0.7" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-0.0.7.tgz#0137e657baa5a7541c57ac37ac5fc07d73b4dc1f" + integrity sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8= + dependencies: + delayed-stream "0.0.5" + +commander@2.8.x: + version "2.8.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" + integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ= + dependencies: + graceful-readlink ">= 1.0.0" + +commander@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + +commander@^2.20.0, commander@^2.6.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" + integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== + +commander@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" + integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== + +commander@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" + integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== + +common-tags@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" + integrity sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw== + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + +component-emitter@^1.2.1, component-emitter@~1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + +compressible@~2.0.16: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + +compression@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" + integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== + dependencies: + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.16" + debug "2.6.9" + on-headers "~1.0.2" + safe-buffer "5.1.2" + vary "~1.1.2" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +concat-stream@^1.5.0, concat-stream@^1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +configstore@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" + integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== + dependencies: + dot-prop "^5.2.0" + graceful-fs "^4.1.2" + make-dir "^3.0.0" + unique-string "^2.0.0" + write-file-atomic "^3.0.0" + xdg-basedir "^4.0.0" + +connect@^3.6.6: + version "3.7.0" + resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" + integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== + dependencies: + debug "2.6.9" + finalhandler "1.1.2" + parseurl "~1.3.3" + utils-merge "1.0.1" + +console-browserify@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" + integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + +console-ui@^3.0.4, console-ui@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/console-ui/-/console-ui-3.1.2.tgz#51aef616ff02013c85ccee6a6d77ef7a94202e7a" + integrity sha512-+5j3R4wZJcEYZeXk30whc4ZU/+fWW9JMTNntVuMYpjZJ9n26Cxr0tUBXco1NRjVZRpRVvZ4DDKKKIHNYeUG9Dw== + dependencies: + chalk "^2.1.0" + inquirer "^6" + json-stable-stringify "^1.0.1" + ora "^3.4.0" + through2 "^3.0.1" + +consolidate@^0.15.1: + version "0.15.1" + resolved "https://registry.yarnpkg.com/consolidate/-/consolidate-0.15.1.tgz#21ab043235c71a07d45d9aad98593b0dba56bab7" + integrity sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw== + dependencies: + bluebird "^3.1.1" + +constants-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= + +content-disposition@0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" + integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== + dependencies: + safe-buffer "5.1.2" + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + +continuable-cache@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/continuable-cache/-/continuable-cache-0.3.1.tgz#bd727a7faed77e71ff3985ac93351a912733ad0f" + integrity sha1-vXJ6f67XfnH/OYWskzUakSczrQ8= + +convert-source-map@^1.5.1, convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + dependencies: + safe-buffer "~5.1.1" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= + +cookie@0.4.0, cookie@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" + integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== + +cookie@~0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" + integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== + +copy-concurrently@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" + integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== + dependencies: + aproba "^1.1.1" + fs-write-stream-atomic "^1.0.8" + iferr "^0.1.5" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.0" + +copy-dereference@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/copy-dereference/-/copy-dereference-1.0.0.tgz#6b131865420fd81b413ba994b44d3655311152b6" + integrity sha1-axMYZUIP2BtBO6mUtE02VTERUrY= + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +core-js-compat@^3.20.0, core-js-compat@^3.20.2: + version "3.20.2" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.20.2.tgz#d1ff6936c7330959b46b2e08b122a8b14e26140b" + integrity sha512-qZEzVQ+5Qh6cROaTPFLNS4lkvQ6mBzE3R6A6EEpssj7Zr2egMHgsy4XapdifqJDGC9CBiNv7s+ejI96rLNQFdg== + dependencies: + browserslist "^4.19.1" + semver "7.0.0" + +core-js-compat@^3.8.1: + version "3.9.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.9.1.tgz#4e572acfe90aff69d76d8c37759d21a5c59bb455" + integrity sha512-jXAirMQxrkbiiLsCx9bQPJFA6llDadKMpYrBJQJ3/c4/vsPP/fAf29h24tviRlvwUL6AmY5CHLu2GvjuYviQqA== + dependencies: + browserslist "^4.16.3" + semver "7.0.0" + +core-js@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e" + integrity sha1-TekR5mew6ukSTjQlS1OupvxhjT4= + +core-js@^2.4.0, core-js@^2.5.0, core-js@^2.5.7, core-js@^2.6.5: + version "2.6.11" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" + integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== + +core-object@2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/core-object/-/core-object-2.0.6.tgz#60134b9c40ff69b27bc15e82db945e4df782961b" + integrity sha1-YBNLnED/abJ7wV6C25ReTfeClhs= + dependencies: + chalk "^1.1.3" + +core-object@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/core-object/-/core-object-2.1.1.tgz#4b7a5f1edefcb1e6d0dcb58eab1b9f90bfc666a8" + integrity sha1-S3pfHt78sebQ3LWOqxufkL/GZqg= + dependencies: + chalk "^1.1.3" + +core-object@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/core-object/-/core-object-3.1.5.tgz#fa627b87502adc98045e44678e9a8ec3b9c0d2a9" + integrity sha512-sA2/4+/PZ/KV6CKgjrVrrUVBKCkdDO02CUlQ0YKTQoYUwPYNOtOAcWlbYhd5v/1JqYaA6oZ4sDlOU4ppVw6Wbg== + dependencies: + chalk "^2.0.0" + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +cors@~2.8.5: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + +create-ecdh@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" + integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== + dependencies: + bn.js "^4.1.0" + elliptic "^6.0.0" + +create-hash@^1.1.0, create-hash@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^6.0.0, cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.1.tgz#0ab56286e0f7c24e153d04cc2aa027e43a9a5d14" + integrity sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +cross-spawn@^7.0.2, cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +cryptiles@0.2.x: + version "0.2.2" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-0.2.2.tgz#ed91ff1f17ad13d3748288594f8a48a0d26f325c" + integrity sha1-7ZH/HxetE9N0gohZT4pIoNJvMlw= + dependencies: + boom "0.4.x" + +crypto-browserify@^3.11.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" + +crypto-random-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" + integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== + +css-select-base-adapter@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" + integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== + +css-select@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef" + integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ== + dependencies: + boolbase "^1.0.0" + css-what "^3.2.1" + domutils "^1.7.0" + nth-check "^1.0.2" + +css-select@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" + integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= + dependencies: + boolbase "~1.0.0" + css-what "2.1" + domutils "1.5.1" + nth-check "~1.0.1" + +css-tree@1.0.0-alpha.29: + version "1.0.0-alpha.29" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" + integrity sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg== + dependencies: + mdn-data "~1.1.0" + source-map "^0.5.3" + +css-tree@1.0.0-alpha.33: + version "1.0.0-alpha.33" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.33.tgz#970e20e5a91f7a378ddd0fc58d0b6c8d4f3be93e" + integrity sha512-SPt57bh5nQnpsTBsx/IXbO14sRc9xXu5MtMAVuo0BaQQmyf0NupNPPSoMaqiAF5tDFafYsTkfeH4Q/HCKXkg4w== + dependencies: + mdn-data "2.0.4" + source-map "^0.5.3" + +css-tree@^1.0.0-alpha.39: + version "1.1.3" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" + integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== + dependencies: + mdn-data "2.0.14" + source-map "^0.6.1" + +css-unit-converter@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996" + integrity sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY= + +css-what@2.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" + integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== + +css-what@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.2.1.tgz#f4a8f12421064621b456755e34a03a2c22df5da1" + integrity sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw== + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +csso@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/csso/-/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b" + integrity sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg== + dependencies: + css-tree "1.0.0-alpha.29" + +cssom@0.3.x, "cssom@>= 0.3.0 < 0.4.0", cssom@~0.3.6: + version "0.3.8" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== + +cssom@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" + integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== + +cssom@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.5.0.tgz#d254fa92cd8b6fbd83811b9fbaed34663cc17c36" + integrity sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw== + +"cssstyle@>= 0.2.29 < 0.3.0": + version "0.2.37" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-0.2.37.tgz#541097234cb2513c83ceed3acddc27ff27987d54" + integrity sha1-VBCXI0yyUTyDzu06zdwn/yeYfVQ= + dependencies: + cssom "0.3.x" + +cssstyle@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" + integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== + dependencies: + cssom "~0.3.6" + +ctype@0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/ctype/-/ctype-0.5.3.tgz#82c18c2461f74114ef16c135224ad0b9144ca12f" + integrity sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8= + +cyclist@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" + integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= + +dag-map@^2.0.1, dag-map@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/dag-map/-/dag-map-2.0.2.tgz#9714b472de82a1843de2fba9b6876938cab44c68" + integrity sha1-lxS0ct6CoYQ94vuptodpOMq0TGg= + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +data-urls@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" + integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== + dependencies: + abab "^2.0.3" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.0.0" + +data-urls@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-3.0.1.tgz#597fc2ae30f8bc4dbcf731fcd1b1954353afc6f8" + integrity sha512-Ds554NeT5Gennfoo9KN50Vh6tpgtvYEwraYjejXnyTpu1C7oXKxdFk75REooENHE8ndTVOJuv+BEs4/J/xcozw== + dependencies: + abab "^2.0.3" + whatwg-mimetype "^3.0.0" + whatwg-url "^10.0.0" + +date-fns@^2.26.0: + version "2.27.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.27.0.tgz#e1ff3c3ddbbab8a2eaadbb6106be2929a5a2d92b" + integrity sha512-sj+J0Mo2p2X1e306MHq282WS4/A8Pz/95GIFcsPNMPMZVI3EUrAdSv90al1k+p74WGLCruMXk23bfEDZa71X9Q== + +date-time@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/date-time/-/date-time-2.1.0.tgz#0286d1b4c769633b3ca13e1e62558d2dbdc2eba2" + integrity sha512-/9+C44X7lot0IeiyfgJmETtRMhBidBYM2QFFIkGa0U1k+hSyY87Nw7PY3eDqpvCBm7I3WCSfPeZskW/YYq6m4g== + dependencies: + time-zone "^1.0.0" + +debug@2.6.9, debug@^2.1.0, debug@^2.1.1, debug@^2.1.3, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@4, debug@^4.3.2, debug@~4.3.1, debug@~4.3.2: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== + dependencies: + ms "2.1.2" + +debug@^3.0.1, debug@^3.1.0, debug@^3.1.1: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + +decamelize@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +decimal.js@^10.2.1: + version "10.2.1" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.1.tgz#238ae7b0f0c793d3e3cea410108b35a2c01426a3" + integrity sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw== + +decimal.js@^10.3.1: + version "10.3.1" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783" + integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ== + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + dependencies: + mimic-response "^1.0.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + +defaults@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= + dependencies: + clone "^1.0.2" + +defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" + integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + +define-properties@^1.1.2, define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +defined@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" + integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= + +delayed-stream@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-0.0.5.tgz#d4b1f43a93e8296dfe02694f4680bc37a313c73f" + integrity sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8= + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +delegate@^3.1.2: + version "3.2.0" + resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166" + integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw== + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + +depd@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +des.js@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + +detect-file@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" + integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= + +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg= + dependencies: + repeating "^2.0.0" + +detect-indent@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.0.0.tgz#0abd0f549f69fc6659a254fe96786186b6f528fd" + integrity sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA== + +detect-newline@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +detective@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.0.tgz#feb2a77e85b904ecdea459ad897cc90a99bd2a7b" + integrity sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg== + dependencies: + acorn-node "^1.6.1" + defined "^1.0.0" + minimist "^1.1.1" + +diff@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dom-serializer@0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" + integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== + dependencies: + domelementtype "^2.0.1" + entities "^2.0.0" + +dom-serializer@~0.1.0, dom-serializer@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" + integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== + dependencies: + domelementtype "^1.3.0" + entities "^1.1.1" + +dom-walk@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" + integrity sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg= + +domain-browser@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== + +domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" + integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== + +domelementtype@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" + integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== + +domexception@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" + integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== + dependencies: + webidl-conversions "^5.0.0" + +domexception@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-4.0.0.tgz#4ad1be56ccadc86fc76d033353999a8037d03673" + integrity sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw== + dependencies: + webidl-conversions "^7.0.0" + +domhandler@2.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.3.0.tgz#2de59a0822d5027fabff6f032c2b25a2a8abe738" + integrity sha1-LeWaCCLVAn+r/28DLCsloqir5zg= + dependencies: + domelementtype "1" + +domhandler@^2.3.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" + integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== + dependencies: + domelementtype "1" + +domutils@1.5, domutils@1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" + integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= + dependencies: + dom-serializer "0" + domelementtype "1" + +domutils@^1.5.1, domutils@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" + integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== + dependencies: + dom-serializer "0" + domelementtype "1" + +dot-case@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.3.tgz#21d3b52efaaba2ea5fda875bb1aa8124521cf4aa" + integrity sha512-7hwEmg6RiSQfm/GwPL4AAWXKy3YNNZA3oFv2Pdiey0mwkRCPZ9x6SZbkLcn8Ma5PYeVokzoD4Twv2n7LKp5WeA== + dependencies: + no-case "^3.0.3" + tslib "^1.10.0" + +dot-prop@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" + integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== + dependencies: + is-obj "^2.0.0" + +dotenv@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-1.2.0.tgz#7cd73e16e07f057c8072147a5bc3a8677f0ab5c6" + integrity sha1-fNc+FuB/BXyAchR6W8OoZ38KtcY= + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + +duplexify@^3.4.2, duplexify@^3.6.0: + version "3.7.1" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" + integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== + dependencies: + end-of-stream "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +editions@^1.1.1: + version "1.3.4" + resolved "https://registry.yarnpkg.com/editions/-/editions-1.3.4.tgz#3662cb592347c3168eb8e498a0ff73271d67f50b" + integrity sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg== + +editions@^2.2.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/editions/-/editions-2.3.1.tgz#3bc9962f1978e801312fbd0aebfed63b49bfe698" + integrity sha512-ptGvkwTvGdGfC0hfhKg0MT+TRLRKGtUiWGBInxOm5pz7ssADezahjCUaYuZ8Dr+C05FW0AECIIPt4WBxVINEhA== + dependencies: + errlop "^2.0.0" + semver "^6.3.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + +electron-to-chromium@^1.3.380, electron-to-chromium@^1.3.47: + version "1.3.386" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.386.tgz#224f97c808da76014096848f80bb9342b6a95cdb" + integrity sha512-M7JHfp32Bq6Am59AWgglh2d3nqe6y8Y94Vcb/AXUsO3DGvKUHYI5ML9+U5oNShfdOEfurrrjKSoSgFt2mz7mpw== + +electron-to-chromium@^1.3.413: + version "1.3.473" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.473.tgz#d0cd5fe391046fb70674ec98149f0f97609d29b8" + integrity sha512-smevlzzMNz3vMz6OLeeCq5HRWEj2AcgccNPYnAx4Usx0IOciq9DU36RJcICcS09hXoY7t7deRfVYKD14IrGb9A== + +electron-to-chromium@^1.3.649: + version "1.3.691" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.691.tgz#a671eaf135a3ccec0915eb8d844a0952aba79f3b" + integrity sha512-ZqiO69KImmOGCyoH0icQPU3SndJiW93juEvf63gQngyhODO6SpQIPMTOHldtCs5DS5GMKvAkquk230E2zt2vpw== + +electron-to-chromium@^1.3.896: + version "1.4.16" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.16.tgz#38ddecc616385e6f101359d1b978c802664157d2" + integrity sha512-BQb7FgYwnu6haWLU63/CdVW+9xhmHls3RCQUFiV4lvw3wimEHTVcUk2hkuZo76QhR8nnDdfZE7evJIZqijwPdA== + +electron-to-chromium@^1.4.17: + version "1.4.45" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.45.tgz#cf1144091d6683cbd45a231954a745f02fb24598" + integrity sha512-czF9eYVuOmlY/vxyMQz2rGlNSjZpxNQYBe1gmQv7al171qOIhgyO9k7D5AKlgeTCSPKk+LHhj5ZyIdmEub9oNg== + +elliptic@^6.0.0: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +"ember-app-scheduler@^5.1.2 || ^6.0.0 || ^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/ember-app-scheduler/-/ember-app-scheduler-7.0.0.tgz#029fe204ccfc86ccc3ff0447307fad4d1d40e2ab" + integrity sha512-5Wy/fWhsnSKT0xtL6EkFOuYMOc8T2lREmi7aRjXMeZCm5nDO7/mukezQ0ViVp9DQVlcbHyJz/qbBylnKq+CILw== + dependencies: + "@ember/test-waiters" "^3.0.0" + "@types/ember" "^3.1.0" + "@types/rsvp" "^4.0.2" + ember-cli-babel "^7.23.0" + ember-cli-typescript "^3.1.4" + ember-compatibility-helpers "^1.1.2" + ember-destroyable-polyfill "^2.0.2" + +ember-assign-polyfill@^2.5.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/ember-assign-polyfill/-/ember-assign-polyfill-2.6.0.tgz#07847e3357ee35b33f886a0b5fbec6873f6860eb" + integrity sha512-Y8NzOmHI/g4PuJ+xC14eTYiQbigNYddyHB8FY2kuQMxThTEIDE7SJtgttJrYYcPciOu0Tnb5ff36iO46LeiXkw== + dependencies: + ember-cli-babel "^6.16.0" + ember-cli-version-checker "^2.0.0" + +ember-auto-import@^1.10.1, ember-auto-import@^1.11.2, ember-auto-import@^1.11.3, ember-auto-import@^1.12.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/ember-auto-import/-/ember-auto-import-1.12.0.tgz#52246b04891090e2608244e65c4c6af7710df12b" + integrity sha512-fzMGnyHGfUNFHchpLbJ98Vs/c5H2wZBMR9r/XwW+WOWPisZDGLUPPyhJQsSREPoUQ+o8GvyLaD/rkrKqW8bmgw== + dependencies: + "@babel/core" "^7.1.6" + "@babel/preset-env" "^7.10.2" + "@babel/traverse" "^7.1.6" + "@babel/types" "^7.1.6" + "@embroider/core" "^0.33.0" + babel-core "^6.26.3" + babel-loader "^8.0.6" + babel-plugin-syntax-dynamic-import "^6.18.0" + babylon "^6.18.0" + broccoli-debug "^0.6.4" + broccoli-node-api "^1.7.0" + broccoli-plugin "^4.0.0" + broccoli-source "^3.0.0" + debug "^3.1.0" + ember-cli-babel "^7.0.0" + enhanced-resolve "^4.0.0" + fs-extra "^6.0.1" + fs-tree-diff "^2.0.0" + handlebars "^4.3.1" + js-string-escape "^1.0.1" + lodash "^4.17.19" + mkdirp "^0.5.1" + resolve-package-path "^3.1.0" + rimraf "^2.6.2" + semver "^7.3.4" + symlink-or-copy "^1.2.0" + typescript-memoize "^1.0.0-alpha.3" + walk-sync "^0.3.3" + webpack "^4.43.0" + +ember-auto-import@^1.2.19, ember-auto-import@^1.5.3: + version "1.11.3" + resolved "https://registry.yarnpkg.com/ember-auto-import/-/ember-auto-import-1.11.3.tgz#6e3384a7fbb163384a34546f2e902cd297b0e683" + integrity sha512-ekq/XCvsonESobFU30zjZ0I4XMy2E/2ZILCYWuQ1JdhcCSTYhnXDZcqRW8itUG7kbsPqAHT/XZ1LEZYm3seVwQ== + dependencies: + "@babel/core" "^7.1.6" + "@babel/preset-env" "^7.10.2" + "@babel/traverse" "^7.1.6" + "@babel/types" "^7.1.6" + "@embroider/core" "^0.33.0" + babel-core "^6.26.3" + babel-loader "^8.0.6" + babel-plugin-syntax-dynamic-import "^6.18.0" + babylon "^6.18.0" + broccoli-debug "^0.6.4" + broccoli-node-api "^1.7.0" + broccoli-plugin "^4.0.0" + broccoli-source "^3.0.0" + debug "^3.1.0" + ember-cli-babel "^7.0.0" + enhanced-resolve "^4.0.0" + fs-extra "^6.0.1" + fs-tree-diff "^2.0.0" + handlebars "^4.3.1" + js-string-escape "^1.0.1" + lodash "^4.17.19" + mkdirp "^0.5.1" + resolve-package-path "^3.1.0" + rimraf "^2.6.2" + semver "^7.3.4" + symlink-or-copy "^1.2.0" + typescript-memoize "^1.0.0-alpha.3" + walk-sync "^0.3.3" + webpack "^4.43.0" + +ember-cache-primitive-polyfill@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ember-cache-primitive-polyfill/-/ember-cache-primitive-polyfill-1.0.1.tgz#a27075443bd87e5af286c1cd8a7df24e3b9f6715" + integrity sha512-hSPcvIKarA8wad2/b6jDd/eU+OtKmi6uP+iYQbzi5TQpjsqV6b4QdRqrLk7ClSRRKBAtdTuutx+m+X+WlEd2lw== + dependencies: + ember-cli-babel "^7.22.1" + ember-cli-version-checker "^5.1.1" + ember-compatibility-helpers "^1.2.1" + silent-error "^1.1.1" + +ember-cached-decorator-polyfill@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/ember-cached-decorator-polyfill/-/ember-cached-decorator-polyfill-0.1.4.tgz#f1e2c65cc78d0d9c4ac0e047e643af477eb85ace" + integrity sha512-JOK7kBCWsTVCzmCefK4nr9BACDJk0owt9oIUaVt6Q0UtQ4XeAHmoK5kQ/YtDcxQF1ZevHQFdGhsTR3JLaHNJgA== + dependencies: + "@glimmer/tracking" "^1.0.4" + ember-cache-primitive-polyfill "^1.0.1" + ember-cli-babel "^7.21.0" + ember-cli-babel-plugin-helpers "^1.1.1" + +ember-classic-decorator@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ember-classic-decorator/-/ember-classic-decorator-2.0.1.tgz#3ea29890959ff7ed0d0fa77bc49fca7142c586af" + integrity sha512-WQH0tY3vZ25fpcqt9xIPnIH3GzXylPFoLmauQFpNZLPtb6/jGuH8EzpFtAjhzakX+zSJb4/36iTaF5QA7aLxow== + dependencies: + "@embroider/macros" "^0.29.0" + babel-plugin-filter-imports "^3.0.0" + ember-cli-babel "^7.11.1" + +ember-cli-addon-docs-esdoc@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/ember-cli-addon-docs-esdoc/-/ember-cli-addon-docs-esdoc-0.4.0.tgz#7c81661c1df511641b6aaff785a1dad2e957dde1" + integrity sha512-8o9ouY3lbHjb4PJQwtD7CxTJNIH4BZXs/z8G0v8CMUDQkiAzg6RaQPGO+WxJH8Qcb1AGDDrITLUJZnZ+B0V/1Q== + dependencies: + broccoli-caching-writer "^3.0.3" + ember-cli-babel "^7.26.3" + ember-cli-htmlbars "^5.7.1" + esdoc pzuraq/esdoc#015a342 + esdoc-accessor-plugin "^1.0.0" + esdoc-ecmascript-proposal-plugin "^1.0.0" + esdoc-typescript-plugin "^1.0.1" + fs-extra "^10.0.0" + json-api-serializer "^2.6.2" + lodash "^4.17.21" + resolve "^1.20.0" + tmp "^0.2.1" + walk-sync "^2.2.0" + +ember-cli-addon-docs@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ember-cli-addon-docs/-/ember-cli-addon-docs-3.0.0.tgz#569f943e91929f78d16c87bf93cf20f39512c89a" + integrity sha512-dw2JdyC9GmJ6tG6cwnAFC2w1kkMcej6VSLEKQ7Fk3L3JhBG3mZyax514DEIsj+Mt6ZAoTJNvxemZRgjyaRZedg== + dependencies: + "@csstools/postcss-sass" "^4.0.0" + "@glimmer/syntax" "^0.79.3" + broccoli-bridge "^1.0.0" + broccoli-caching-writer "^3.0.3" + broccoli-debug "^0.6.5" + broccoli-filter "^1.3.0" + broccoli-funnel "^3.0.6" + broccoli-merge-trees "^4.2.0" + broccoli-persistent-filter "^3.1.0" + broccoli-plugin "1.5.1 - 5" + broccoli-source "^3.0.0" + broccoli-stew "^3.0.0" + chalk "^4.1.0" + ember-auto-import "^1.11.2" + ember-classic-decorator "^2.0.0" + ember-cli-autoprefixer "^1.0.2" + ember-cli-babel "^7.26.3" + ember-cli-clipboard "^0.15.0" + ember-cli-htmlbars "^5.7.1" + ember-cli-postcss "^7.0.0" + ember-cli-string-helpers "^6.1.0" + ember-cli-string-utils "^1.1.0" + ember-cli-version-checker "^5.1.0" + ember-code-snippet "^3.0.0" + ember-composable-helpers "^4.4.1" + ember-concurrency "^2.0.0" + ember-decorators "^6.1.1" + ember-fetch "^8.0.2" + ember-get-config "^0.3.0" + ember-href-to "^4.0.0" + ember-keyboard "^6.0.3" + ember-modal-dialog "^4.0.0-alpha.0" + ember-on-modifier "^1.0.0" + ember-responsive "^4.0.0" + ember-router-generator "^2.0.0" + ember-router-scroll "^4.0.2" + ember-svg-jar "^2.2.3" + ember-tether "^2.0.0" + ember-truth-helpers "^3.0.0" + esm "^3.2.25" + execa "^5.0.0" + fs-extra "^10.0.0" + git-repo-info "^2.1.1" + highlight.js "^10.7.2" + hosted-git-info "^4.0.2" + html-entities "^2.3.2" + inflected "^2.0.3" + jsdom "^16.4.0" + json-api-serializer "^2.2.1" + liquid-fire "^0.29.5 || ^0.30.0 || ^0.31.0" + lodash "^4.17.15" + lunr "^2.3.7" + marked "^0.8.2" + pad-start "^1.0.2" + parse-git-config "^3.0.0" + postcss "^8.2.1" + postcss-import "^14.0.0" + postcss-nested "^5.0.3" + postcss-scss "^3.0.4" + quick-temp "^0.1.8" + resolve "^1.12.0" + semver "^7.3.2" + striptags "^3.1.1" + tailwindcss "1.9.6" + walk-sync "^2.0.2" + yuidocjs "^0.10.2" + +ember-cli-autoprefixer@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/ember-cli-autoprefixer/-/ember-cli-autoprefixer-1.0.3.tgz#d4603c2e649c0b3a094c52b87664e172b550924e" + integrity sha512-bh0BrUKQ4G4aj85mG7k3SkhQB5QpB1NipmYPhXQvMjOw5RihqF3k5aB98RFx/0AWAVnY8pF17iIrsHMvvwD1WQ== + dependencies: + broccoli-autoprefixer "^8.0.0" + ember-cli-htmlbars "^5.0.0" + +ember-cli-babel-plugin-helpers@^1.0.0, ember-cli-babel-plugin-helpers@^1.1.0, ember-cli-babel-plugin-helpers@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ember-cli-babel-plugin-helpers/-/ember-cli-babel-plugin-helpers-1.1.1.tgz#5016b80cdef37036c4282eef2d863e1d73576879" + integrity sha512-sKvOiPNHr5F/60NLd7SFzMpYPte/nnGkq/tMIfXejfKHIhaiIkYFqX8Z9UFTKWLLn+V7NOaby6niNPZUdvKCRw== + +ember-cli-babel@^6.11.0, ember-cli-babel@^6.16.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/ember-cli-babel/-/ember-cli-babel-6.18.0.tgz#3f6435fd275172edeff2b634ee7b29ce74318957" + integrity sha512-7ceC8joNYxY2wES16iIBlbPSxwKDBhYwC8drU3ZEvuPDMwVv1KzxCNu1fvxyFEBWhwaRNTUxSCsEVoTd9nosGA== + dependencies: + amd-name-resolver "1.2.0" + babel-plugin-debug-macros "^0.2.0-beta.6" + babel-plugin-ember-modules-api-polyfill "^2.6.0" + babel-plugin-transform-es2015-modules-amd "^6.24.0" + babel-polyfill "^6.26.0" + babel-preset-env "^1.7.0" + broccoli-babel-transpiler "^6.5.0" + broccoli-debug "^0.6.4" + broccoli-funnel "^2.0.0" + broccoli-source "^1.1.0" + clone "^2.0.0" + ember-cli-version-checker "^2.1.2" + semver "^5.5.0" + +ember-cli-babel@^7.0.0, ember-cli-babel@^7.1.0, ember-cli-babel@^7.1.2, ember-cli-babel@^7.1.3, ember-cli-babel@^7.10.0, ember-cli-babel@^7.11.1, ember-cli-babel@^7.13.0, ember-cli-babel@^7.13.2, ember-cli-babel@^7.19.0, ember-cli-babel@^7.20.2, ember-cli-babel@^7.21.0, ember-cli-babel@^7.22.1, ember-cli-babel@^7.23.0, ember-cli-babel@^7.23.1, ember-cli-babel@^7.26.3, ember-cli-babel@^7.26.5, ember-cli-babel@^7.26.6, ember-cli-babel@^7.7.3: + version "7.26.11" + resolved "https://registry.yarnpkg.com/ember-cli-babel/-/ember-cli-babel-7.26.11.tgz#50da0fe4dcd99aada499843940fec75076249a9f" + integrity sha512-JJYeYjiz/JTn34q7F5DSOjkkZqy8qwFOOxXfE6pe9yEJqWGu4qErKxlz8I22JoVEQ/aBUO+OcKTpmctvykM9YA== + dependencies: + "@babel/core" "^7.12.0" + "@babel/helper-compilation-targets" "^7.12.0" + "@babel/plugin-proposal-class-properties" "^7.16.5" + "@babel/plugin-proposal-decorators" "^7.13.5" + "@babel/plugin-proposal-private-methods" "^7.16.5" + "@babel/plugin-proposal-private-property-in-object" "^7.16.5" + "@babel/plugin-transform-modules-amd" "^7.13.0" + "@babel/plugin-transform-runtime" "^7.13.9" + "@babel/plugin-transform-typescript" "^7.13.0" + "@babel/polyfill" "^7.11.5" + "@babel/preset-env" "^7.16.5" + "@babel/runtime" "7.12.18" + amd-name-resolver "^1.3.1" + babel-plugin-debug-macros "^0.3.4" + babel-plugin-ember-data-packages-polyfill "^0.1.2" + babel-plugin-ember-modules-api-polyfill "^3.5.0" + babel-plugin-module-resolver "^3.2.0" + broccoli-babel-transpiler "^7.8.0" + broccoli-debug "^0.6.4" + broccoli-funnel "^2.0.2" + broccoli-source "^2.1.2" + calculate-cache-key-for-tree "^2.0.0" + clone "^2.1.2" + ember-cli-babel-plugin-helpers "^1.1.1" + ember-cli-version-checker "^4.1.0" + ensure-posix-path "^1.0.2" + fixturify-project "^1.10.0" + resolve-package-path "^3.1.0" + rimraf "^3.0.1" + semver "^5.5.0" + +ember-cli-clipboard@^0.15.0: + version "0.15.0" + resolved "https://registry.yarnpkg.com/ember-cli-clipboard/-/ember-cli-clipboard-0.15.0.tgz#3704baaeab1f0a2df13b3d77632dea7266aabe54" + integrity sha512-gcjm2ofr3NOGH6/MFp+2AVqEKTYkdRUvRsVovTg45Iy414jKyWwxu9l3jWM0ZZkRc2IqjE0V2ta9JJe2/HRPUA== + dependencies: + "@ember/render-modifiers" "^1.0.1" + clipboard "^2.0.6" + ember-auto-import "^1.5.3" + ember-cli-babel "^7.20.2" + ember-cli-htmlbars "^4.2.3" + +ember-cli-dependency-checker@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ember-cli-dependency-checker/-/ember-cli-dependency-checker-3.2.0.tgz#9202ad9e14d6fda33cffc22a11c343c2a8885330" + integrity sha512-dkSmcJ/jY/2ms/S6ph2jXSfOW5VfOpLfg5DFEbra0SaMNgYkNDFF1o0U4OdTsG37L5h/AXWNuVtnOa4TMabz9Q== + dependencies: + chalk "^2.3.0" + find-yarn-workspace-root "^1.1.0" + is-git-url "^1.0.0" + resolve "^1.5.0" + semver "^5.3.0" + +ember-cli-deploy-build@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ember-cli-deploy-build/-/ember-cli-deploy-build-2.0.0.tgz#20d14836f5e8e1325a5b2c3d43367354783d2008" + integrity sha512-o6TCCKVLC85KYkk3TV8PCmEPfUI9R0qYzb7Sda+SIq9f5oR+vOoTsQmjUPyMB5Qou2sBVreUTjgNEaJBzvLtLg== + dependencies: + chalk "^1.0.0" + ember-cli-deploy-plugin "^0.2.1" + glob "^7.1.1" + rsvp "^3.5.0" + +ember-cli-deploy-git-ci@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ember-cli-deploy-git-ci/-/ember-cli-deploy-git-ci-1.0.1.tgz#846b046f82196538cc6eea2aa5d410c9111f76f4" + integrity sha512-F5lbie3T6vBCHYSCi7yT6KC+4dlM/BkeOv+6oPra0a2Px4q2J3Rv4Yuh8aailOVVRE+2iRyVFM57ijB8QBb9WA== + dependencies: + ember-cli-deploy-plugin "^0.2.9" + execa "^0.7.0" + fs-extra "^4.0.0" + +ember-cli-deploy-git@^1.3.3: + version "1.3.4" + resolved "https://registry.yarnpkg.com/ember-cli-deploy-git/-/ember-cli-deploy-git-1.3.4.tgz#918905df863eb867d23a323ff0b80d1336cfa05d" + integrity sha512-ESLyVY7yLM+hS31/7rXIpQnA5skKkpQx+TRn+GVRPp6g6XSApUrmWAmmeBIYhDLsxMZRLgD98DhDF50ogOoU7A== + dependencies: + ember-cli-babel "^6.11.0" + ember-cli-deploy-plugin "^0.2.9" + fs-extra "^5.0.0" + rsvp "^4.8.1" + +ember-cli-deploy-plugin@^0.2.1, ember-cli-deploy-plugin@^0.2.9: + version "0.2.9" + resolved "https://registry.yarnpkg.com/ember-cli-deploy-plugin/-/ember-cli-deploy-plugin-0.2.9.tgz#a3d395b8adad7ef68d8bacdd0b0f4a61bcf9e651" + integrity sha1-o9OVuK2tfvaNi6zdCw9KYbz55lE= + dependencies: + chalk "^1.0.0" + core-object "2.0.6" + lodash.clonedeep "^4.5.0" + +ember-cli-deploy-progress@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/ember-cli-deploy-progress/-/ember-cli-deploy-progress-1.3.0.tgz#18663deed25b4d5397476332f25eed3c3fdf225a" + integrity sha1-GGY97tJbTVOXR2My8l7tPD/fIlo= + +ember-cli-deploy@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/ember-cli-deploy/-/ember-cli-deploy-1.0.2.tgz#9ab39188c882b57937418db5b3da6fc65b16b916" + integrity sha1-mrORiMiCtXk3QY21s9pvxlsWuRY= + dependencies: + chalk "^1.1.3" + core-object "^2.0.0" + dag-map "^2.0.1" + dotenv "^1.2.0" + ember-cli-deploy-progress "^1.3.0" + lodash "^4.0.0" + rsvp "^3.3.3" + silent-error "^1.0.0" + +ember-cli-fastboot@^3.2.0-beta.5: + version "3.2.0-beta.5" + resolved "https://registry.yarnpkg.com/ember-cli-fastboot/-/ember-cli-fastboot-3.2.0-beta.5.tgz#c190bfc3a9b42cb0dc2a2861e2812116fbed3dd0" + integrity sha512-1ugII1SFc/BzQNBlJxSJ7+FmkQd6KCKNGJZdSkvYhEeDQ0mmsC1QXMV2bzSRElU4mh5GUN2jf7FsaGtFH5+v/A== + dependencies: + broccoli-concat "^3.7.1" + broccoli-file-creator "^2.1.1" + broccoli-funnel "^2.0.1" + broccoli-merge-trees "^3.0.1" + broccoli-plugin "^1.3.1" + chalk "^4.1.2" + ember-cli-babel "^7.26.3" + ember-cli-htmlbars "^5.7.1" + ember-cli-lodash-subset "2.0.1" + ember-cli-preprocess-registry "^3.1.2" + ember-cli-version-checker "^3.0.0" + fastboot "3.2.0-beta.5" + fastboot-express-middleware "3.2.0-beta.5" + fastboot-transform "^0.1.3" + fs-extra "^10.0.0" + json-stable-stringify "^1.0.1" + md5-hex "^2.0.0" + recast "^0.19.1" + silent-error "^1.1.0" + +ember-cli-favicon@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ember-cli-favicon/-/ember-cli-favicon-3.0.0.tgz#094d7b978deabdee706fb24801ff5e74c22871b8" + integrity sha512-BzqPK1ymKiLgvZp8OT06xGu6sAfWMsDKcXrLqhfxLwMWePWArC6IWnkv3A+2HjYXYO2rDT+7qaF3hArPe5sCRA== + dependencies: + broccoli-favicon "^3.0.0" + broccoli-merge-trees "^4.2.0" + ember-cli-babel "^7.26.6" + lodash.merge "^4.6.2" + +ember-cli-get-component-path-option@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ember-cli-get-component-path-option/-/ember-cli-get-component-path-option-1.0.0.tgz#0d7b595559e2f9050abed804f1d8eff1b08bc771" + integrity sha1-DXtZVVni+QUKvtgE8djv8bCLx3E= + +ember-cli-htmlbars@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/ember-cli-htmlbars/-/ember-cli-htmlbars-3.1.0.tgz#87806c2a0bca2ab52d4fb8af8e2215c1ca718a99" + integrity sha512-cgvRJM73IT0aePUG7oQ/afB7vSRBV3N0wu9BrWhHX2zkR7A7cUBI7KC9VPk6tbctCXoM7BRGsCC4aIjF7yrfXA== + dependencies: + broccoli-persistent-filter "^2.3.1" + hash-for-dep "^1.5.1" + json-stable-stringify "^1.0.1" + strip-bom "^3.0.0" + +ember-cli-htmlbars@^4.2.3: + version "4.4.0" + resolved "https://registry.yarnpkg.com/ember-cli-htmlbars/-/ember-cli-htmlbars-4.4.0.tgz#7ca17d5ca8f7550984346d9e6e93da0c3323f8d9" + integrity sha512-ohgctqk7dXIZR4TgN0xRoUYltWhghFJgqmtuswQTpZ7p74RxI9PKx+E8WV/95mGcPzraesvMNBg5utQNvcqgNg== + dependencies: + "@ember/edition-utils" "^1.2.0" + babel-plugin-htmlbars-inline-precompile "^3.2.0" + broccoli-debug "^0.6.5" + broccoli-persistent-filter "^2.3.1" + broccoli-plugin "^3.1.0" + common-tags "^1.8.0" + ember-cli-babel-plugin-helpers "^1.1.0" + fs-tree-diff "^2.0.1" + hash-for-dep "^1.5.1" + heimdalljs-logger "^0.1.10" + json-stable-stringify "^1.0.1" + semver "^6.3.0" + strip-bom "^4.0.0" + walk-sync "^2.0.2" + +ember-cli-htmlbars@^5.0.0, ember-cli-htmlbars@^5.3.1, ember-cli-htmlbars@^5.7.1: + version "5.7.1" + resolved "https://registry.yarnpkg.com/ember-cli-htmlbars/-/ember-cli-htmlbars-5.7.1.tgz#eb5b88c7d9083bc27665fb5447a9b7503b32ce4f" + integrity sha512-9laCgL4tSy48orNoQgQKEHp93MaqAs9ZOl7or5q+8iyGGJHW6sVXIYrVv5/5O9HfV6Ts8/pW1rSoaeKyLUE+oA== + dependencies: + "@ember/edition-utils" "^1.2.0" + babel-plugin-htmlbars-inline-precompile "^5.0.0" + broccoli-debug "^0.6.5" + broccoli-persistent-filter "^3.1.2" + broccoli-plugin "^4.0.3" + common-tags "^1.8.0" + ember-cli-babel-plugin-helpers "^1.1.1" + ember-cli-version-checker "^5.1.2" + fs-tree-diff "^2.0.1" + hash-for-dep "^1.5.1" + heimdalljs-logger "^0.1.10" + json-stable-stringify "^1.0.1" + semver "^7.3.4" + silent-error "^1.1.1" + strip-bom "^4.0.0" + walk-sync "^2.2.0" + +ember-cli-htmlbars@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ember-cli-htmlbars/-/ember-cli-htmlbars-6.0.1.tgz#5487831d477e61682bc867fd138808269e5d2152" + integrity sha512-IDsl9uty+MXtMfp/BUTEc/Q36EmlHYj8ZdPekcoRa8hmdsigHnK4iokfaB7dJFktlf6luruei+imv7JrJrBQPQ== + dependencies: + "@ember/edition-utils" "^1.2.0" + babel-plugin-ember-template-compilation "^1.0.0" + babel-plugin-htmlbars-inline-precompile "^5.3.0" + broccoli-debug "^0.6.5" + broccoli-persistent-filter "^3.1.2" + broccoli-plugin "^4.0.3" + ember-cli-version-checker "^5.1.2" + fs-tree-diff "^2.0.1" + hash-for-dep "^1.5.1" + heimdalljs-logger "^0.1.10" + json-stable-stringify "^1.0.1" + semver "^7.3.4" + silent-error "^1.1.1" + strip-bom "^4.0.0" + walk-sync "^2.2.0" + +ember-cli-import-polyfill@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ember-cli-import-polyfill/-/ember-cli-import-polyfill-0.2.0.tgz#c1a08a8affb45c97b675926272fe78cf4ca166f2" + integrity sha1-waCKiv+0XJe2dZJicv54z0yhZvI= + +ember-cli-inject-live-reload@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ember-cli-inject-live-reload/-/ember-cli-inject-live-reload-2.1.0.tgz#ef63c733c133024d5726405a3c247fa12e88a385" + integrity sha512-YV5wYRD5PJHmxaxaJt18u6LE6Y+wo455BnmcpN+hGNlChy2piM9/GMvYgTAz/8Vin8RJ5KekqP/w/NEaRndc/A== + dependencies: + clean-base-url "^1.0.0" + ember-cli-version-checker "^3.1.3" + +ember-cli-is-package-missing@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ember-cli-is-package-missing/-/ember-cli-is-package-missing-1.0.0.tgz#6e6184cafb92635dd93ca6c946b104292d4e3390" + integrity sha1-bmGEyvuSY13ZPKbJRrEEKS1OM5A= + +ember-cli-lodash-subset@2.0.1, ember-cli-lodash-subset@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ember-cli-lodash-subset/-/ember-cli-lodash-subset-2.0.1.tgz#20cb68a790fe0fde2488ddfd8efbb7df6fe766f2" + integrity sha1-IMtop5D+D94kiN39jvu332/nZvI= + +ember-cli-moment-shim@^3.8.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/ember-cli-moment-shim/-/ember-cli-moment-shim-3.8.0.tgz#dc61bbac9dce4963394e60dd42726d4ba38e2bc1" + integrity sha512-dN5ImjrjZevEqB7xhwFXaPWwxdKGSFiR1kqy9gDVB+A5EGnhCL1uveKugcyJE/MICVhXUAHBUu6G2LFWEPF2YA== + dependencies: + broccoli-funnel "^2.0.0" + broccoli-merge-trees "^2.0.0" + broccoli-source "^1.1.0" + broccoli-stew "^1.5.0" + chalk "^1.1.3" + ember-cli-babel "^7.1.2" + ember-cli-import-polyfill "^0.2.0" + ember-get-config "" + lodash.defaults "^4.2.0" + moment "^2.19.3" + moment-timezone "^0.5.13" + +ember-cli-normalize-entity-name@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ember-cli-normalize-entity-name/-/ember-cli-normalize-entity-name-1.0.0.tgz#0b14f7bcbc599aa117b5fddc81e4fd03c4bad5b7" + integrity sha1-CxT3vLxZmqEXtf3cgeT9A8S61bc= + dependencies: + silent-error "^1.0.0" + +ember-cli-path-utils@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ember-cli-path-utils/-/ember-cli-path-utils-1.0.0.tgz#4e39af8b55301cddc5017739b77a804fba2071ed" + integrity sha1-Tjmvi1UwHN3FAXc5t3qAT7ogce0= + +ember-cli-postcss@^7.0.0: + version "7.0.2" + resolved "https://registry.yarnpkg.com/ember-cli-postcss/-/ember-cli-postcss-7.0.2.tgz#b7df580296cbffad4db943c7d2be739b7f68148b" + integrity sha512-nlr5glZlk6VN0nZuxO5yBbhofHo2waoCHYqTQH2CennDgdC0Fph4Kp+VHtif3qCgMyMXTqqvvgkBz2YpOBgsgw== + dependencies: + broccoli-merge-trees "^4.0.0" + broccoli-postcss "^6.0.0" + broccoli-postcss-single "^5.0.0" + ember-cli-babel "^7.1.0" + merge "^2.1.1" + +ember-cli-preprocess-registry@^3.1.2, ember-cli-preprocess-registry@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/ember-cli-preprocess-registry/-/ember-cli-preprocess-registry-3.3.0.tgz#685837a314fbe57224bd54b189f4b9c23907a2de" + integrity sha512-60GYpw7VPeB7TvzTLZTuLTlHdOXvayxjAQ+IxM2T04Xkfyu75O2ItbWlftQW7NZVGkaCsXSRAmn22PG03VpLMA== + dependencies: + broccoli-clean-css "^1.1.0" + broccoli-funnel "^2.0.1" + debug "^3.0.1" + process-relative-require "^1.0.0" + +ember-cli-sri@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ember-cli-sri/-/ember-cli-sri-2.1.1.tgz#971620934a4b9183cf7923cc03e178b83aa907fd" + integrity sha1-lxYgk0pLkYPPeSPMA+F4uDqpB/0= + dependencies: + broccoli-sri-hash "^2.1.0" + +ember-cli-string-helpers@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/ember-cli-string-helpers/-/ember-cli-string-helpers-6.1.0.tgz#aeb96112bb91c540b869ed8b9c680f7fd5859cb6" + integrity sha512-Lw8B6MJx2n8CNF2TSIKs+hWLw0FqSYjr2/NRPyquyYA05qsl137WJSYW3ZqTsLgoinHat0DGF2qaCXocLhLmyA== + dependencies: + "@babel/core" "^7.13.10" + broccoli-funnel "^3.0.3" + ember-cli-babel "^7.7.3" + resolve "^1.20.0" + +ember-cli-string-utils@^1.0.0, ember-cli-string-utils@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ember-cli-string-utils/-/ember-cli-string-utils-1.1.0.tgz#39b677fc2805f55173735376fcef278eaa4452a1" + integrity sha1-ObZ3/CgF9VFzc1N2/O8njqpEUqE= + +ember-cli-terser@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/ember-cli-terser/-/ember-cli-terser-4.0.2.tgz#c436a9e4159f76a615b051cba0584844652b7dcd" + integrity sha512-Ej77K+YhCZImotoi/CU2cfsoZaswoPlGaM5TB3LvjvPDlVPRhxUHO2RsaUVC5lsGeRLRiHCOxVtoJ6GyqexzFA== + dependencies: + broccoli-terser-sourcemap "^4.1.0" + +ember-cli-test-info@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ember-cli-test-info/-/ember-cli-test-info-1.0.0.tgz#ed4e960f249e97523cf891e4aed2072ce84577b4" + integrity sha1-7U6WDySel1I8+JHkrtIHLOhFd7Q= + dependencies: + ember-cli-string-utils "^1.0.0" + +ember-cli-test-loader@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ember-cli-test-loader/-/ember-cli-test-loader-3.0.0.tgz#1c036fc48de36155355fcda3266af63f977826f1" + integrity sha512-wfFRBrfO9gaKScYcdQxTfklx9yp1lWK6zv1rZRpkas9z2SHyJojF7NOQRWQgSB3ypm7vfpiF8VsFFVVr7VBzAQ== + dependencies: + ember-cli-babel "^7.13.2" + +ember-cli-typescript@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ember-cli-typescript/-/ember-cli-typescript-3.0.0.tgz#3b838d1ce9e4d22a98e68da22ceac6dc0cfd9bfc" + integrity sha512-lo5YArbJzJi5ssvaGqTt6+FnhTALnSvYVuxM7lfyL1UCMudyNJ94ovH5C7n5il7ATd6WsNiAPRUO/v+s5Jq/aA== + dependencies: + "@babel/plugin-transform-typescript" "~7.5.0" + ansi-to-html "^0.6.6" + debug "^4.0.0" + ember-cli-babel-plugin-helpers "^1.0.0" + execa "^2.0.0" + fs-extra "^8.0.0" + resolve "^1.5.0" + rsvp "^4.8.1" + semver "^6.0.0" + stagehand "^1.0.0" + walk-sync "^2.0.0" + +ember-cli-typescript@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ember-cli-typescript/-/ember-cli-typescript-2.0.2.tgz#464984131fbdc05655eb61d1c3cdd911d3137f0d" + integrity sha512-7I5azCTxOgRDN8aSSnJZIKSqr+MGnT+jLTUbBYqF8wu6ojs2DUnTePxUcQMcvNh3Q3B1ySv7Q/uZFSjdU9gSjA== + dependencies: + "@babel/plugin-proposal-class-properties" "^7.1.0" + "@babel/plugin-transform-typescript" "~7.4.0" + ansi-to-html "^0.6.6" + debug "^4.0.0" + ember-cli-babel-plugin-helpers "^1.0.0" + execa "^1.0.0" + fs-extra "^7.0.0" + resolve "^1.5.0" + rsvp "^4.8.1" + semver "^6.0.0" + stagehand "^1.0.0" + walk-sync "^1.0.0" + +ember-cli-typescript@^3.1.3, ember-cli-typescript@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/ember-cli-typescript/-/ember-cli-typescript-3.1.4.tgz#21d6ccd670d1f2e34c9cce68c6e32c442f46806b" + integrity sha512-HJ73kL45OGRmIkPhBNFt31I1SGUvdZND+LCH21+qpq3pPlFpJG8GORyXpP+2ze8PbnITNLzwe5AwUrpyuRswdQ== + dependencies: + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.4.4" + "@babel/plugin-proposal-optional-chaining" "^7.6.0" + "@babel/plugin-transform-typescript" "~7.8.0" + ansi-to-html "^0.6.6" + broccoli-stew "^3.0.0" + debug "^4.0.0" + ember-cli-babel-plugin-helpers "^1.0.0" + execa "^3.0.0" + fs-extra "^8.0.0" + resolve "^1.5.0" + rsvp "^4.8.1" + semver "^6.3.0" + stagehand "^1.0.0" + walk-sync "^2.0.0" + +ember-cli-typescript@^4.1.0, ember-cli-typescript@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/ember-cli-typescript/-/ember-cli-typescript-4.2.1.tgz#54d08fc90318cc986f3ea562f93ce58a6cc4c24d" + integrity sha512-0iKTZ+/wH6UB/VTWKvGuXlmwiE8HSIGcxHamwNhEC5x1mN3z8RfvsFZdQWYUzIWFN2Tek0gmepGRPTwWdBYl/A== + dependencies: + ansi-to-html "^0.6.15" + broccoli-stew "^3.0.0" + debug "^4.0.0" + execa "^4.0.0" + fs-extra "^9.0.1" + resolve "^1.5.0" + rsvp "^4.8.1" + semver "^7.3.2" + stagehand "^1.0.0" + walk-sync "^2.2.0" + +ember-cli-version-checker@^2.0.0, ember-cli-version-checker@^2.1.0, ember-cli-version-checker@^2.1.2: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ember-cli-version-checker/-/ember-cli-version-checker-2.2.0.tgz#47771b731fe0962705e27c8199a9e3825709f3b3" + integrity sha512-G+KtYIVlSOWGcNaTFHk76xR4GdzDLzAS4uxZUKdASuFX0KJE43C6DaqL+y3VTpUFLI2FIkAS6HZ4I1YBi+S3hg== + dependencies: + resolve "^1.3.3" + semver "^5.3.0" + +ember-cli-version-checker@^3.0.0, ember-cli-version-checker@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/ember-cli-version-checker/-/ember-cli-version-checker-3.1.3.tgz#7c9b4f5ff30fdebcd480b1c06c4de43bb51c522c" + integrity sha512-PZNSvpzwWgv68hcXxyjREpj3WWb81A7rtYNQq1lLEgrWIchF8ApKJjWP3NBpHjaatwILkZAV8klair5WFlXAKg== + dependencies: + resolve-package-path "^1.2.6" + semver "^5.6.0" + +ember-cli-version-checker@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ember-cli-version-checker/-/ember-cli-version-checker-4.1.0.tgz#7fc9836bdbc87451d286ba6a9a89b23591d8bbb7" + integrity sha512-yLf2YqotTSsjiXwx9Dt6H7AU0QcldFn5SLk/pG3Zqb0aHNeanBOPlx4/Ysa46ILGWYIh0fDH34AEVRueXTrQBQ== + dependencies: + resolve-package-path "^2.0.0" + semver "^6.3.0" + silent-error "^1.1.1" + +ember-cli-version-checker@^5.1.0, ember-cli-version-checker@^5.1.1, ember-cli-version-checker@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/ember-cli-version-checker/-/ember-cli-version-checker-5.1.2.tgz#649c7b6404902e3b3d69c396e054cea964911ab0" + integrity sha512-rk7GY+FmLn/2e22HsZs0Ycrz8HQ1W3Fv+2TFOuEFW9optnDXDgkntPBIl6gact/LHsfBM5RKbM3dHsIIeLgl0Q== + dependencies: + resolve-package-path "^3.1.0" + semver "^7.3.4" + silent-error "^1.1.1" + +ember-cli@~3.28.4: + version "3.28.4" + resolved "https://registry.yarnpkg.com/ember-cli/-/ember-cli-3.28.4.tgz#784cfeaf5319e409edc3e03e5d99bcfcf18f9e53" + integrity sha512-bRQpZqx1YctDNR7gb5CXfXYkZtieMh4F6v6bZtu+Da8jWTKoGizG1LXsG/Bhs96USPjlZZsErkSBo6qiGjJlcA== + dependencies: + "@babel/core" "^7.13.8" + "@babel/plugin-transform-modules-amd" "^7.12.1" + amd-name-resolver "^1.3.1" + babel-plugin-module-resolver "^4.1.0" + bower-config "^1.4.3" + bower-endpoint-parser "0.2.2" + broccoli "^3.5.1" + broccoli-amd-funnel "^2.0.1" + broccoli-babel-transpiler "^7.8.0" + broccoli-builder "^0.18.14" + broccoli-concat "^4.2.5" + broccoli-config-loader "^1.0.1" + broccoli-config-replace "^1.1.2" + broccoli-debug "^0.6.5" + broccoli-funnel "^3.0.5" + broccoli-funnel-reducer "^1.0.0" + broccoli-merge-trees "^3.0.2" + broccoli-middleware "^2.1.1" + broccoli-slow-trees "^3.1.0" + broccoli-source "^3.0.0" + broccoli-stew "^3.0.0" + calculate-cache-key-for-tree "^2.0.0" + capture-exit "^2.0.0" + chalk "^4.1.0" + ci-info "^2.0.0" + clean-base-url "^1.0.0" + compression "^1.7.4" + configstore "^5.0.1" + console-ui "^3.1.2" + core-object "^3.1.5" + dag-map "^2.0.2" + diff "^5.0.0" + ember-cli-is-package-missing "^1.0.0" + ember-cli-lodash-subset "^2.0.1" + ember-cli-normalize-entity-name "^1.0.0" + ember-cli-preprocess-registry "^3.3.0" + ember-cli-string-utils "^1.1.0" + ember-source-channel-url "^3.0.0" + ensure-posix-path "^1.1.1" + execa "^5.0.0" + exit "^0.1.2" + express "^4.17.1" + filesize "^6.1.0" + find-up "^5.0.0" + find-yarn-workspace-root "^2.0.0" + fixturify-project "^2.1.1" + fs-extra "^9.1.0" + fs-tree-diff "^2.0.1" + get-caller-file "^2.0.5" + git-repo-info "^2.1.1" + glob "^7.1.6" + heimdalljs "^0.2.6" + heimdalljs-fs-monitor "^1.1.0" + heimdalljs-graph "^1.0.0" + heimdalljs-logger "^0.1.10" + http-proxy "^1.18.1" + inflection "^1.12.0" + is-git-url "^1.0.0" + is-language-code "^2.0.0" + isbinaryfile "^4.0.6" + js-yaml "^3.14.0" + json-stable-stringify "^1.0.1" + leek "0.0.24" + lodash.template "^4.5.0" + markdown-it "^12.0.4" + markdown-it-terminal "0.2.1" + minimatch "^3.0.4" + morgan "^1.10.0" + nopt "^3.0.6" + npm-package-arg "^8.1.1" + p-defer "^3.0.0" + portfinder "^1.0.28" + promise-map-series "^0.3.0" + promise.hash.helper "^1.0.7" + quick-temp "^0.1.8" + resolve "^1.20.0" + resolve-package-path "^3.1.0" + sane "^4.1.0" + semver "^7.3.4" + silent-error "^1.1.1" + sort-package-json "^1.49.0" + symlink-or-copy "^1.3.1" + temp "0.9.4" + testem "^3.2.0" + tiny-lr "^2.0.0" + tree-sync "^2.1.0" + uuid "^8.3.2" + walk-sync "^2.2.0" + watch-detector "^1.0.0" + workerpool "^6.1.4" + yam "^1.0.0" + +ember-code-snippet@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ember-code-snippet/-/ember-code-snippet-3.0.0.tgz#5e3108a68cc76740355cbbca840656d96c6b7ba1" + integrity sha512-pvIpGPLma7m6WQ5+uOjwkzozIzRAqlUSQk9TMCrQQ/AeEGWtqTJvZyAtH9LoarPtudHtWCZkUqJXIqKsjIqAbw== + dependencies: + broccoli-flatiron "^0.1.3" + broccoli-merge-trees "^1.0.0" + broccoli-plugin "^1.3.1" + ember-cli-babel "^7.7.3" + ember-cli-htmlbars "^3.0.1" + es6-promise "^1.0.0" + glob "^7.1.3" + +ember-compatibility-helpers@^1.1.2, ember-compatibility-helpers@^1.2.0, ember-compatibility-helpers@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/ember-compatibility-helpers/-/ember-compatibility-helpers-1.2.2.tgz#839e0c24190b7a2ec8c39b80e030811b1a95b6d3" + integrity sha512-EKyCGOGBvKkBsk6wKfg3GhjTvTTkcEwzl/cv4VYvZM18cihmjGNpliR4BymWsKRWrv4VJLyq15Vhk3NHkSNBag== + dependencies: + babel-plugin-debug-macros "^0.2.0" + ember-cli-version-checker "^5.1.1" + semver "^5.4.1" + +ember-compatibility-helpers@^1.2.4, ember-compatibility-helpers@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/ember-compatibility-helpers/-/ember-compatibility-helpers-1.2.5.tgz#b8363b1d5b8725afa9a4fe2b2986ac28626c6f23" + integrity sha512-7cddkQQp8Rs2Mqrj0xqZ0uO7eC9tBCKyZNcP2iE1RxQqOGPv8fiPkj1TUeidUB/Qe80lstoVXWMEuqqhW7Yy9A== + dependencies: + babel-plugin-debug-macros "^0.2.0" + ember-cli-version-checker "^5.1.1" + fs-extra "^9.1.0" + semver "^5.4.1" + +ember-composable-helpers@^4.4.1: + version "4.5.0" + resolved "https://registry.yarnpkg.com/ember-composable-helpers/-/ember-composable-helpers-4.5.0.tgz#94febbdf4348e64f45f7a6f993f326e32540a61e" + integrity sha512-XjpDLyVPsLCy6kd5dIxZonOECCO6AA5sY5Hr6tYUbJg3s5ghFAiFWaNcYraYC+fL2yPJQAswwpfwGlQORUJZkw== + dependencies: + "@babel/core" "^7.0.0" + broccoli-funnel "2.0.1" + ember-cli-babel "^7.26.3" + resolve "^1.10.0" + +ember-composable-helpers@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ember-composable-helpers/-/ember-composable-helpers-5.0.0.tgz#055bab3a3e234ab2917499b1465e968c253ca885" + integrity sha512-gyUrjiSju4QwNrsCLbBpP0FL6VDFZaELNW7Kbcp60xXhjvNjncYgzm4zzYXhT+i1lLA6WEgRZ3lOGgyBORYD0w== + dependencies: + "@babel/core" "^7.0.0" + broccoli-funnel "2.0.1" + ember-cli-babel "^7.26.3" + resolve "^1.10.0" + +ember-concurrency@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ember-concurrency/-/ember-concurrency-2.2.0.tgz#0acfb8ca855e0fdfa4c543be150028299a89ba32" + integrity sha512-Ns1MH6t08oJqfeWQ4EMxyf6bLsXM87SbUPwGNUsg7idpikvkGr1PWqtvU6qxDTv1mA4Vrwdhv0I9yxN0ShH9Bg== + dependencies: + "@glimmer/tracking" "^1.0.4" + ember-cli-babel "^7.26.6" + ember-cli-htmlbars "^5.7.1" + ember-compatibility-helpers "^1.2.0" + ember-destroyable-polyfill "^2.0.2" + +ember-data@~3.28.5: + version "3.28.5" + resolved "https://registry.yarnpkg.com/ember-data/-/ember-data-3.28.5.tgz#9ba88ed90b8d3ca319cd85f4dfd2c448202f898b" + integrity sha512-7zUlYt4GMAJIDQ977cdOTV7J+bWmchV1+1vFg4iSv9Vx+rBnk8816BcYEqkuDq8VfN9Wp/WwqrPV+qBZZ3lyPg== + dependencies: + "@ember-data/adapter" "3.28.5" + "@ember-data/debug" "3.28.5" + "@ember-data/model" "3.28.5" + "@ember-data/private-build-infra" "3.28.5" + "@ember-data/record-data" "3.28.5" + "@ember-data/serializer" "3.28.5" + "@ember-data/store" "3.28.5" + "@ember/edition-utils" "^1.2.0" + "@ember/string" "^3.0.0" + "@glimmer/env" "^0.1.7" + broccoli-merge-trees "^4.2.0" + ember-cli-babel "^7.26.6" + ember-cli-typescript "^4.1.0" + ember-inflector "^4.0.1" + +ember-decorators@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/ember-decorators/-/ember-decorators-6.1.1.tgz#6d770f8999cf5a413a1ee459afd520838c0fc470" + integrity sha512-63vZPntPn1aqMyeNRLoYjJD+8A8obd+c2iZkJflswpDRNVIsp2m7aQdSCtPt4G0U/TEq2251g+N10maHX3rnJQ== + dependencies: + "@ember-decorators/component" "^6.1.1" + "@ember-decorators/object" "^6.1.1" + ember-cli-babel "^7.7.3" + +ember-destroyable-polyfill@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ember-destroyable-polyfill/-/ember-destroyable-polyfill-2.0.2.tgz#2cc7532bd3c00e351b4da9b7fc683f4daff79671" + integrity sha512-9t+ya+9c+FkNM5IAyJIv6ETG8jfZQaUnFCO5SeLlV0wkSw7TOexyb61jh5GVee0KmknfRhrRGGAyT4Y0TwkZ+w== + dependencies: + ember-cli-babel "^7.22.1" + ember-cli-version-checker "^5.1.1" + ember-compatibility-helpers "^1.2.1" + +ember-destroyable-polyfill@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/ember-destroyable-polyfill/-/ember-destroyable-polyfill-2.0.3.tgz#1673ed66609a82268ef270a7d917ebd3647f11e1" + integrity sha512-TovtNqCumzyAiW0/OisSkkVK93xnVF4NRU6+FN0ubpfwEOpRrmM2RqDwXI6YAChCgSHON1cz0DfQStpA1Gjuuw== + dependencies: + ember-cli-babel "^7.22.1" + ember-cli-version-checker "^5.1.1" + ember-compatibility-helpers "^1.2.1" + +ember-disable-prototype-extensions@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/ember-disable-prototype-extensions/-/ember-disable-prototype-extensions-1.1.3.tgz#1969135217654b5e278f9fe2d9d4e49b5720329e" + integrity sha1-GWkTUhdlS14nj5/i2dTkm1cgMp4= + +ember-export-application-global@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ember-export-application-global/-/ember-export-application-global-2.0.1.tgz#b120a70e322ab208defc9e2daebe8d0dfc2dcd46" + integrity sha512-B7wiurPgsxsSGzJuPFkpBWnaeuCu2PGpG2BjyrfA1VcL7//o+5RSnZqiCEY326y7qmxb2GoCgo0ft03KBU0rRw== + +ember-fetch@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/ember-fetch/-/ember-fetch-8.0.2.tgz#9838b9f01e33fcd23550ccf38ae4f1f90cc47113" + integrity sha512-BMwm8jLP5LCeT8Jbgz0jA04RsRyt06ZGMaC3Tx2DbHgoWOPlLMfkEKlCFE0dZVW8ZhuICKuyRZTzt4e8GrnnNA== + dependencies: + abortcontroller-polyfill "^1.4.0" + broccoli-concat "^4.2.4" + broccoli-debug "^0.6.5" + broccoli-merge-trees "^4.2.0" + broccoli-rollup "^2.1.1" + broccoli-stew "^3.0.0" + broccoli-templater "^2.0.1" + calculate-cache-key-for-tree "^2.0.0" + caniuse-api "^3.0.0" + ember-cli-babel "^7.19.0" + ember-cli-typescript "^3.1.3" + node-fetch "^2.6.0" + whatwg-fetch "^3.4.0" + +ember-fetch@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/ember-fetch/-/ember-fetch-8.1.1.tgz#d68d4a58529121a572ec09c39c6a3ad174c83a2e" + integrity sha512-Xi1wNmPtVmfIoFH675AA0ELIdYUcoZ2p+6j9c8eDFjiGJiFesyp01bDtl5ryBI/1VPOByJLsDkT+4C11HixsJw== + dependencies: + abortcontroller-polyfill "^1.7.3" + broccoli-concat "^4.2.5" + broccoli-debug "^0.6.5" + broccoli-merge-trees "^4.2.0" + broccoli-rollup "^2.1.1" + broccoli-stew "^3.0.0" + broccoli-templater "^2.0.1" + calculate-cache-key-for-tree "^2.0.0" + caniuse-api "^3.0.0" + ember-cli-babel "^7.23.1" + ember-cli-typescript "^4.1.0" + ember-cli-version-checker "^5.1.2" + node-fetch "^2.6.1" + whatwg-fetch "^3.6.2" + +ember-get-config@, "ember-get-config@0.2.4 - 0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/ember-get-config/-/ember-get-config-0.5.0.tgz#8195f3e4c0ff0742182c81ae54aad78d07a24bcf" + integrity sha512-y1osD6g8wV/BlDjuaN6OG5MT0iHY2X/yE38gUj/05uUIMIRfpcwOdWnFQHBiXIhDojvAJQTEF1VOYFIETQMkeQ== + dependencies: + broccoli-file-creator "^1.1.1" + ember-cli-babel "^7.26.6" + ember-cli-htmlbars "^5.7.1" + +ember-get-config@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/ember-get-config/-/ember-get-config-0.3.0.tgz#a73a1a87b48d9dde4c66a0e52ed5260b8a48cfbd" + integrity sha512-0e2pKzwW5lBZ4oJnvu9qHOht4sP1MWz/m3hyz8kpSoMdrlZVf62LDKZ6qfKgy8drcv5YhCMYE6QV7MhnqlrzEQ== + dependencies: + broccoli-file-creator "^1.1.1" + ember-cli-babel "^7.0.0" + +ember-href-to@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ember-href-to/-/ember-href-to-4.1.0.tgz#daa8b398bc5a51ba3ba5ff736e099f0a0d010b7b" + integrity sha512-h8xSzt9lQAUzk4JvXNnZjRj29hOWKo92VIHzH68io13UurDBaMmJ4WtXa0iy/awlSFs6h8BwpEWQeaCYIZDRuQ== + dependencies: + ember-cli-babel "^7.13.2" + +"ember-inflector@^2.0.0 || ^3.0.0 || ^4.0.2", ember-inflector@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/ember-inflector/-/ember-inflector-4.0.2.tgz#4494f1a5f61c1aca7702d59d54024cc92211d8ec" + integrity sha512-+oRstEa52mm0jAFzhr51/xtEWpCEykB3SEBr7vUg8YnXUZJ5hKNBppP938q8Zzr9XfJEbzrtDSGjhKwJCJv6FQ== + dependencies: + ember-cli-babel "^7.26.5" + +ember-keyboard@^6.0.3: + version "6.0.4" + resolved "https://registry.yarnpkg.com/ember-keyboard/-/ember-keyboard-6.0.4.tgz#396e1be4c815b2972e2a6973dcc45acbc6701e4a" + integrity sha512-Mkg5TG6KBTtxjOUBdyLADajyj/mJo3ua2mSHw20UtG2MxKxMyO+Bs4tttMlEmmrR3XMrQ9qVBLkq2dIuuQku3w== + dependencies: + ember-cli-babel "^7.26.6" + ember-cli-htmlbars "^5.7.1" + ember-compatibility-helpers "^1.2.4" + ember-modifier "^2.1.2 || ^3.0.0" + ember-modifier-manager-polyfill "^1.2.0" + +ember-load-initializers@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ember-load-initializers/-/ember-load-initializers-2.1.2.tgz#8a47a656c1f64f9b10cecdb4e22a9d52ad9c7efa" + integrity sha512-CYR+U/wRxLbrfYN3dh+0Tb6mFaxJKfdyz+wNql6cqTrA0BBi9k6J3AaKXj273TqvEpyyXegQFFkZEiuZdYtgJw== + dependencies: + ember-cli-babel "^7.13.0" + ember-cli-typescript "^2.0.2" + +ember-maybe-import-regenerator@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ember-maybe-import-regenerator/-/ember-maybe-import-regenerator-1.0.0.tgz#c05453dfd3b65dbec2b569612b01ae70b672dd7e" + integrity sha512-wtjgjEV0Hk4fgiAwFjOfPrGWfmFrbRW3zgNZO4oA3H5FlbMssMvWuR8blQ3QSWYHODVK9r+ThsRAs8lG4kbxqA== + dependencies: + broccoli-funnel "^2.0.1" + broccoli-merge-trees "^3.0.0" + ember-cli-babel "^7.26.6" + regenerator-runtime "^0.13.2" + +ember-modal-dialog@^4.0.0-alpha.0: + version "4.0.0-alpha.1" + resolved "https://registry.yarnpkg.com/ember-modal-dialog/-/ember-modal-dialog-4.0.0-alpha.1.tgz#b63b078a2d3a7bbe26514dccb1795d37e95c1de7" + integrity sha512-jkwpX4lj7RBiZO2os+xnRnwdLFPMYNaKnAEZxa1tGl36eER7c9NV/gJZtB2WwnelCMOT5bhGGZI7Evb8whOUrg== + dependencies: + ember-classic-decorator "^2.0.0" + ember-cli-babel "^7.26.6" + ember-cli-htmlbars "^5.7.1" + ember-cli-version-checker "^2.1.0" + ember-decorators "^6.1.1" + ember-wormhole "^0.6.0" + +ember-modifier-manager-polyfill@^1.1.0, ember-modifier-manager-polyfill@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/ember-modifier-manager-polyfill/-/ember-modifier-manager-polyfill-1.2.0.tgz#cf4444e11a42ac84f5c8badd85e635df57565dda" + integrity sha512-bnaKF1LLKMkBNeDoetvIJ4vhwRPKIIumWr6dbVuW6W6p4QV8ZiO+GdF8J7mxDNlog9CeL9Z/7wam4YS86G8BYA== + dependencies: + ember-cli-babel "^7.10.0" + ember-cli-version-checker "^2.1.2" + ember-compatibility-helpers "^1.2.0" + +"ember-modifier@^2.1.2 || ^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/ember-modifier/-/ember-modifier-3.0.0.tgz#74466d32e4ef9b80004915676cc3bfd6e3fd7a3d" + integrity sha512-ccXfMnjWhjEUCB5taeIPQmf0h1zPUIMbmsCV7W+JZ2BioPUZTLhE1WuHspmV0iEOiX3Fwx8jMOx6b74sFcKJ0g== + dependencies: + ember-cli-babel "^7.26.6" + ember-cli-normalize-entity-name "^1.0.0" + ember-cli-string-utils "^1.1.0" + ember-cli-typescript "^4.2.1" + ember-compatibility-helpers "^1.2.5" + +ember-moment@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/ember-moment/-/ember-moment-9.0.1.tgz#fcf06cb8ef07c8d0108820c1639778590d613b38" + integrity sha512-mwcj2g/37pIQua3uTpJWu/zpcnyvbgg9YmkKR6nhtY7FXBaGSIU3aeG95VAoPcfET9DazkPOyqxVB+Dcd5BP5g== + dependencies: + ember-auto-import "^1.10.1" + ember-cli-babel "^7.23.0" + ember-cli-htmlbars "^5.3.1" + moment "^2.29.1" + moment-timezone "^0.5.33" + +ember-on-modifier@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ember-on-modifier/-/ember-on-modifier-1.0.1.tgz#b99e9c9d7919a9f536bfc9d4a68704462eceb0fe" + integrity sha512-4JKUb/DBmdZkLfljN2Dj6gKmqq2vZ0/3TOwRs1+jUIXTUg1MaBMUVD1XYwzUm+a7abW9/JkQNUEVZZu13SwFMg== + dependencies: + broccoli-funnel "^2.0.2" + ember-cli-babel "^7.19.0" + ember-cli-version-checker "^4.1.0" + ember-modifier-manager-polyfill "^1.2.0" + +ember-qunit@^5.1.5: + version "5.1.5" + resolved "https://registry.yarnpkg.com/ember-qunit/-/ember-qunit-5.1.5.tgz#24a7850f052be24189ff597dfc31b923e684c444" + integrity sha512-2cFA4oMygh43RtVcMaBrr086Tpdhgbn3fVZ2awLkzF/rnSN0D0PSRpd7hAD7OdBPerC/ZYRwzVyGXLoW/Zes4A== + dependencies: + broccoli-funnel "^3.0.8" + broccoli-merge-trees "^3.0.2" + common-tags "^1.8.0" + ember-auto-import "^1.11.3" + ember-cli-babel "^7.26.6" + ember-cli-test-loader "^3.0.0" + resolve-package-path "^3.1.0" + silent-error "^1.1.1" + validate-peer-dependencies "^1.2.0" + +ember-resolver@^8.0.3: + version "8.0.3" + resolved "https://registry.yarnpkg.com/ember-resolver/-/ember-resolver-8.0.3.tgz#40f243aa58281bf195c695fe84a6b291e204690a" + integrity sha512-fA53fxfG821BRqNiB9mQDuzZpzSRcSAYZTYBlRQOHsJwoYdjyE7idz4YcytbSsa409G5J2kP6B+PiKOBh0odlw== + dependencies: + babel-plugin-debug-macros "^0.3.4" + broccoli-funnel "^3.0.8" + broccoli-merge-trees "^4.2.0" + ember-cli-babel "^7.26.6" + ember-cli-version-checker "^5.1.2" + resolve "^1.20.0" + +ember-responsive@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/ember-responsive/-/ember-responsive-4.0.1.tgz#4833870c23ed309b6a7daa9c61b6254330f0edd6" + integrity sha512-/RfaacbIgYQf7fkbsxu72YZVFdsiMhKJ7YFGiDOFLaBmOxPSrz2YylmEXED81qw2TdudzWeVFuilpzUoWB1Jkg== + dependencies: + ember-cli-babel "^7.19.0" + +ember-rfc176-data@^0.3.13, ember-rfc176-data@^0.3.15: + version "0.3.15" + resolved "https://registry.yarnpkg.com/ember-rfc176-data/-/ember-rfc176-data-0.3.15.tgz#af3f1da5a0339b6feda380edc2f7190e0f416c2d" + integrity sha512-GPKa7zRDBblRy0orxTXt5yrpp/Pf5CkuRFSIR8qMFDww0CqCKjCRwdZnWYzCM4kAEfZnXRIDDefe1tBaFw7v7w== + +ember-rfc176-data@^0.3.17: + version "0.3.17" + resolved "https://registry.yarnpkg.com/ember-rfc176-data/-/ember-rfc176-data-0.3.17.tgz#d4fc6c33abd6ef7b3440c107a28e04417b49860a" + integrity sha512-EVzTTKqxv9FZbEh6Ktw56YyWRAA0MijKvl7H8C06wVF+8f/cRRz3dXxa4nkwjzyVwx4rzKGuIGq77hxJAQhWWw== + +ember-router-generator@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ember-router-generator/-/ember-router-generator-2.0.0.tgz#d04abfed4ba8b42d166477bbce47fccc672dbde0" + integrity sha512-89oVHVJwmLDvGvAUWgS87KpBoRhy3aZ6U0Ql6HOmU4TrPkyaa8pM0W81wj9cIwjYprcQtN9EwzZMHnq46+oUyw== + dependencies: + "@babel/parser" "^7.4.5" + "@babel/traverse" "^7.4.5" + recast "^0.18.1" + +ember-router-scroll@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/ember-router-scroll/-/ember-router-scroll-4.1.2.tgz#8af1c29b7a596738bbbd71a8a04af7c5c0d19403" + integrity sha512-5AGRmbfhSx7kOu2U8caQkG8qOxlLnvJIoQgKRE9mc1isuYPdime6Qn061NSnnQukMMsSPlV8GAImiEk05BmfGA== + dependencies: + ember-app-scheduler "^5.1.2 || ^6.0.0 || ^7.0.0" + ember-cli-babel "^7.26.6" + ember-compatibility-helpers "^1.2.5" + +ember-source-channel-url@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ember-source-channel-url/-/ember-source-channel-url-3.0.0.tgz#bcd5be72c63fa0b8c390b3121783b462063e2a1b" + integrity sha512-vF/8BraOc66ZxIDo3VuNP7iiDrnXEINclJgSJmqwAAEpg84Zb1DHPI22XTXSDA+E8fW5btPUxu65c3ZXi8AQFA== + dependencies: + node-fetch "^2.6.0" + +ember-source@~3.28.8: + version "3.28.8" + resolved "https://registry.yarnpkg.com/ember-source/-/ember-source-3.28.8.tgz#c58fd4a1538d6c4b9aebe76c764cabf5396c64d9" + integrity sha512-hA15oYzbRdi9983HIemeVzzX2iLcMmSPp6akUiMQhFZYWPrKksbPyLrO6YpZ4hNM8yBjQSDXEkZ1V3yxBRKjUA== + dependencies: + "@babel/helper-module-imports" "^7.8.3" + "@babel/plugin-transform-block-scoping" "^7.8.3" + "@babel/plugin-transform-object-assign" "^7.8.3" + "@ember/edition-utils" "^1.2.0" + "@glimmer/vm-babel-plugins" "0.80.3" + babel-plugin-debug-macros "^0.3.4" + babel-plugin-filter-imports "^4.0.0" + broccoli-concat "^4.2.4" + broccoli-debug "^0.6.4" + broccoli-file-creator "^2.1.1" + broccoli-funnel "^2.0.2" + broccoli-merge-trees "^4.2.0" + chalk "^4.0.0" + ember-cli-babel "^7.23.0" + ember-cli-get-component-path-option "^1.0.0" + ember-cli-is-package-missing "^1.0.0" + ember-cli-normalize-entity-name "^1.0.0" + ember-cli-path-utils "^1.0.0" + ember-cli-string-utils "^1.1.0" + ember-cli-version-checker "^5.1.1" + ember-router-generator "^2.0.0" + inflection "^1.12.0" + jquery "^3.5.1" + resolve "^1.17.0" + semver "^7.3.4" + silent-error "^1.1.1" + +ember-svg-jar@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/ember-svg-jar/-/ember-svg-jar-2.2.3.tgz#632f8d6a999ceb1c815a135fbc2bd681b856330b" + integrity sha512-17kBxi5IfsEnCsVuFTjVs+HEAa3sfdB4t4C+5GZUxWixEbK8hwoRDsuvsboOGhDemycVv21GAyexcTeinabsnQ== + dependencies: + broccoli-caching-writer "^3.0.3" + broccoli-concat "^3.7.4" + broccoli-funnel "^2.0.2" + broccoli-merge-trees "^3.0.2" + broccoli-persistent-filter "^2.3.1" + broccoli-string-replace "^0.1.2" + broccoli-svg-optimizer "2.0.0" + cheerio "^0.22.0" + ember-assign-polyfill "^2.5.0" + ember-cli-babel "^7.7.3" + json-stable-stringify "^1.0.1" + lodash "^4.17.15" + mkdirp "^0.5.1" + path-posix "^1.0.0" + +ember-template-lint@^3.14.0: + version "3.14.0" + resolved "https://registry.yarnpkg.com/ember-template-lint/-/ember-template-lint-3.14.0.tgz#4e7ac709979b229612cab66e8258cf175eefaca2" + integrity sha512-0elxAseSft1SjQFcwqYddCXcsBW783M8TBXQ/eGXBzWTZVFwh/Oe+13SggVeUoyr9ZUX9ngW6rFEsKIyofY0KA== + dependencies: + "@ember-template-lint/todo-utils" "^10.0.0" + chalk "^4.1.2" + ci-info "^3.2.0" + date-fns "^2.26.0" + ember-template-recast "^5.0.3" + find-up "^5.0.0" + fuse.js "^6.4.6" + get-stdin "^8.0.0" + globby "^11.0.4" + is-glob "^4.0.3" + micromatch "^4.0.4" + requireindex "^1.2.0" + resolve "^1.20.0" + v8-compile-cache "^2.3.0" + yargs "^16.2.0" + +ember-template-recast@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/ember-template-recast/-/ember-template-recast-5.0.3.tgz#79df27a70bdce7be17f14db13886afde1e9d02d6" + integrity sha512-qsJYQhf29Dk6QMfviXhUPE+byMOs6iRQxUDHgkj8yqjeppvjHaFG96hZi/NAXJTm/M7o3PpfF5YlmeaKtI9UeQ== + dependencies: + "@glimmer/reference" "^0.65.0" + "@glimmer/syntax" "^0.65.0" + "@glimmer/validator" "^0.65.0" + async-promise-queue "^1.0.5" + colors "^1.4.0" + commander "^6.2.1" + globby "^11.0.3" + ora "^5.4.0" + slash "^3.0.0" + tmp "^0.2.1" + workerpool "^6.1.4" + +ember-tether@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ember-tether/-/ember-tether-2.0.0.tgz#4fcb88749e8c11d3795173e96e894089328005b4" + integrity sha512-07QCzYE5VZsQ53SQQBDbP47E1s2qs6A9p1q6kOQjca693TVKxz0ZKTAKCXoSXOujG1n92hc1hRdA9rOSoxcBJw== + dependencies: + ember-auto-import "^1.2.19" + ember-cli-babel "^7.1.2" + tether "^1.4.0" + +ember-truth-helpers@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ember-truth-helpers/-/ember-truth-helpers-3.0.0.tgz#86766bdca4ac9b86bce3d262dff2aabc4a0ea384" + integrity sha512-hPKG9QqruAELh0li5xaiLZtr88ioWYxWCXisAWHWE0qCP4a2hgtuMzKUPpiTCkltvKjuqpzTZCU4VhQ+IlRmew== + dependencies: + ember-cli-babel "^7.22.1" + +ember-try-config@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/ember-try-config/-/ember-try-config-4.0.0.tgz#8dbdcc071e7acbcb34750b4ed7faf1ab009766f1" + integrity sha512-jAv7fqYJK7QYYekPc/8Nr7KOqDpv/asqM6F8xcRnbmf9UrD35BkSffY63qUuiD9e0aR5qiMNBIQzH8f65rGDqw== + dependencies: + ember-source-channel-url "^3.0.0" + lodash "^4.17.20" + package-json "^6.5.0" + remote-git-tags "^3.0.0" + semver "^7.3.2" + +ember-try@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ember-try/-/ember-try-2.0.0.tgz#2671c221f5a0335fa2c189d00db7146e2e72a1dd" + integrity sha512-2N7Vic45sbAegA5fhdfDjVbEVS4r+ze+tTQs2/wkY+8fC5yAGHfCM5ocyoTfBN5m7EhznC3AyMsOy4hLPzHFSQ== + dependencies: + chalk "^4.1.2" + cli-table3 "^0.6.0" + core-object "^3.1.5" + debug "^4.3.2" + ember-try-config "^4.0.0" + execa "^4.1.0" + fs-extra "^9.0.1" + resolve "^1.20.0" + rimraf "^3.0.2" + walk-sync "^2.2.0" + +ember-wormhole@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/ember-wormhole/-/ember-wormhole-0.6.0.tgz#1f9143aa05c0f0abdf14a97ff22520ebaf85eca0" + integrity sha512-b7RrRxkwCBEJxM2zR34dEzIET81BOZWTcYNJtkidLycLQvdbxPys5QJEjJ/IfDikT/z5HuQBdZRKBhXI0vZNXQ== + dependencies: + ember-cli-babel "^7.22.1" + ember-cli-htmlbars "^5.3.1" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + +end-of-stream@^1.0.0, end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +engine.io-parser@~5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.0.2.tgz#69a2ec3ed431da021f0666712d07f106bcffa6ce" + integrity sha512-wuiO7qO/OEkPJSFueuATIXtrxF7/6GTbAO9QLv7nnbjwZ5tYhLm9zxvLwxstRs0dcT0KUlWTjtIOs1T86jt12g== + dependencies: + base64-arraybuffer "~1.0.1" + +engine.io@~6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.1.0.tgz#459eab0c3724899d7b63a20c3a6835cf92857939" + integrity sha512-ErhZOVu2xweCjEfYcTdkCnEYUiZgkAcBBAhW4jbIvNG8SLU3orAqoJCiytZjYF7eTpVmmCrLDjLIEaPlUAs1uw== + dependencies: + "@types/cookie" "^0.4.1" + "@types/cors" "^2.8.12" + "@types/node" ">=10.0.0" + accepts "~1.3.4" + base64id "2.0.0" + cookie "~0.4.1" + cors "~2.8.5" + debug "~4.3.1" + engine.io-parser "~5.0.0" + ws "~8.2.3" + +enhanced-resolve@^4.0.0, enhanced-resolve@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz#3b806f3bfafc1ec7de69551ef93cca46c1704126" + integrity sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ== + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.5.0" + tapable "^1.0.0" + +enquirer@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + +ensure-posix-path@^1.0.0, ensure-posix-path@^1.0.1, ensure-posix-path@^1.0.2, ensure-posix-path@^1.1.0, ensure-posix-path@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ensure-posix-path/-/ensure-posix-path-1.1.1.tgz#3c62bdb19fa4681544289edb2b382adc029179ce" + integrity sha512-VWU0/zXzVbeJNXvME/5EmLuEj2TauvoaTz6aFYK1Z92JCBlDlZ3Gu0tuGR42kpW1754ywTs+QB0g5TP0oj9Zaw== + +entities@1.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26" + integrity sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY= + +entities@^1.1.1, entities@^1.1.2, entities@~1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" + integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== + +entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" + integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== + +entities@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" + integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== + +errlop@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/errlop/-/errlop-2.2.0.tgz#1ff383f8f917ae328bebb802d6ca69666a42d21b" + integrity sha512-e64Qj9+4aZzjzzFpZC7p5kmm/ccCrbLhAJplhsDXQFs87XTsXwOpH4s1Io2s90Tau/8r2j9f4l/thhDevRjzxw== + +errno@^0.1.3, errno@~0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" + integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== + dependencies: + prr "~1.0.1" + +error-ex@^1.2.0, error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +error@^7.0.0: + version "7.2.1" + resolved "https://registry.yarnpkg.com/error/-/error-7.2.1.tgz#eab21a4689b5f684fc83da84a0e390de82d94894" + integrity sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA== + dependencies: + string-template "~0.2.1" + +es-abstract@^1.17.0-next.1, es-abstract@^1.17.2: + version "1.17.5" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.5.tgz#d8c9d1d66c8981fb9200e2251d799eee92774ae9" + integrity sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.1.5" + is-regex "^1.0.5" + object-inspect "^1.7.0" + object-keys "^1.1.1" + object.assign "^4.1.0" + string.prototype.trimleft "^2.1.1" + string.prototype.trimright "^2.1.1" + +es-abstract@^1.19.1: + version "1.19.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3" + integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w== + dependencies: + call-bind "^1.0.2" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + get-intrinsic "^1.1.1" + get-symbol-description "^1.0.0" + has "^1.0.3" + has-symbols "^1.0.2" + internal-slot "^1.0.3" + is-callable "^1.2.4" + is-negative-zero "^2.0.1" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.1" + is-string "^1.0.7" + is-weakref "^1.0.1" + object-inspect "^1.11.0" + object-keys "^1.1.1" + object.assign "^4.1.2" + string.prototype.trimend "^1.0.4" + string.prototype.trimstart "^1.0.4" + unbox-primitive "^1.0.1" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +es6-promise@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-1.0.0.tgz#f90d3629faa7c26166ae4df77c89bacdeb8dca7f" + integrity sha1-+Q02KfqnwmFmrk33fIm6zeuNyn8= + +es6-promise@^3.0.2: + version "3.3.1" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613" + integrity sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM= + +es6-promise@^4.0.3: + version "4.2.8" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" + integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-html@1.0.3, escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escodegen@^1.6.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.1.tgz#ba01d0c8278b5e95a9a45350142026659027a457" + integrity sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ== + dependencies: + esprima "^4.0.1" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +escodegen@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" + integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== + dependencies: + esprima "^4.0.1" + estraverse "^5.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +esdoc-accessor-plugin@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/esdoc-accessor-plugin/-/esdoc-accessor-plugin-1.0.0.tgz#791ba4872e6c403515ce749b1348d6f0293ad9eb" + integrity sha1-eRukhy5sQDUVznSbE0jW8Ck62es= + +esdoc-ecmascript-proposal-plugin@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/esdoc-ecmascript-proposal-plugin/-/esdoc-ecmascript-proposal-plugin-1.0.0.tgz#390dc5656ba8a2830e39dba3570d79138df2ffd9" + integrity sha1-OQ3FZWuoooMOOdujVw15E43y/9k= + +esdoc-typescript-plugin@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/esdoc-typescript-plugin/-/esdoc-typescript-plugin-1.0.1.tgz#d4b929677f2ee5587a86ec70e766537040b98662" + integrity sha512-QV9rdis5PkypVK1fh2wuESZPQZUVjTwt4hj97Pivb9M8wGPMOTxYu5ofkyGWm3xgNL+K0VxZY6TGEO07kfGAtg== + dependencies: + typescript "^2.8.3" + +esdoc@pzuraq/esdoc#015a342: + version "1.0.4" + resolved "https://codeload.github.com/pzuraq/esdoc/tar.gz/015a3426b2e53b2b0270a9c00133780db3f1d144" + dependencies: + babel-generator "6.26.0" + babel-traverse "6.26.0" + babylon "6.18.0" + cheerio "0.22.0" + color-logger "0.0.3" + escape-html "1.0.3" + fs-extra "1.0.0" + ice-cap "0.0.4" + marked "0.3.6" + minimist "1.2.0" + taffydb "2.7.2" + +eslint-config-prettier@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz#f7471b20b6fe8a9a9254cc684454202886a2dd7a" + integrity sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew== + +eslint-plugin-ember@^10.5.8: + version "10.5.8" + resolved "https://registry.yarnpkg.com/eslint-plugin-ember/-/eslint-plugin-ember-10.5.8.tgz#87e004a5ebed88f94008364554daf57df2c9c718" + integrity sha512-d21mJ+F+htgi6HhrjwbOfllJojF4ZWGruW13HkBoGS2SaHqKUyvIH/8j3EjSxlsGFiNfhTEUWkNaUSLJxgbtWg== + dependencies: + "@ember-data/rfc395-data" "^0.0.4" + css-tree "^1.0.0-alpha.39" + ember-rfc176-data "^0.3.15" + eslint-utils "^3.0.0" + estraverse "^5.2.0" + lodash.kebabcase "^4.1.1" + requireindex "^1.2.0" + snake-case "^3.0.3" + +eslint-plugin-es@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.0.tgz#98cb1bc8ab0aa807977855e11ad9d1c9422d014b" + integrity sha512-6/Jb/J/ZvSebydwbBJO1R9E5ky7YeElfK56Veh7e4QGFHCXoIXGH9HhVz+ibJLM3XJ1XjP+T7rKBLUa/Y7eIng== + dependencies: + eslint-utils "^2.0.0" + regexpp "^3.0.0" + +eslint-plugin-node@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" + integrity sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g== + dependencies: + eslint-plugin-es "^3.0.0" + eslint-utils "^2.0.0" + ignore "^5.1.1" + minimatch "^3.0.4" + resolve "^1.10.1" + semver "^6.1.0" + +eslint-plugin-prettier@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz#8b99d1e4b8b24a762472b4567992023619cb98e0" + integrity sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ== + dependencies: + prettier-linter-helpers "^1.0.0" + +eslint-plugin-qunit@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-qunit/-/eslint-plugin-qunit-7.1.0.tgz#d0d4f9f9f2b9623953a4b7f1ca8a71f4aa7df2b7" + integrity sha512-w1+iL/+idpHGNgWYKknY7uPA3EaVDgl4HT4ndkNM2ONr/MW3FTM3FLRpy6yDZ5YE3km372Ym9Vr/N28E3OI6Jg== + dependencies: + eslint-utils "^3.0.0" + requireindex "^1.2.0" + +eslint-scope@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-utils@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.0.0.tgz#7be1cc70f27a72a76cd14aa698bcabed6890e1cd" + integrity sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" + integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== + +eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + +eslint-visitor-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint@^7.32.0: + version "7.32.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" + integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== + dependencies: + "@babel/code-frame" "7.12.11" + "@eslint/eslintrc" "^0.4.3" + "@humanwhocodes/config-array" "^0.5.0" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.0.1" + doctrine "^3.0.0" + enquirer "^2.3.5" + escape-string-regexp "^4.0.0" + eslint-scope "^5.1.1" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.1" + esquery "^1.4.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.1.2" + globals "^13.6.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.0.4" + natural-compare "^1.4.0" + optionator "^0.9.1" + progress "^2.0.0" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" + table "^6.0.9" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +esm@^3.2.25, esm@^3.2.4: + version "3.2.25" + resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" + integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== + +espree@^7.3.0, espree@^7.3.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" + integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== + dependencies: + acorn "^7.4.0" + acorn-jsx "^5.3.1" + eslint-visitor-keys "^1.3.0" + +esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esprima@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.0.0.tgz#53cf247acda77313e551c3aa2e73342d3fb4f7d9" + integrity sha1-U88kes2ncxPlUcOqLnM0LT+099k= + +esquery@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== + dependencies: + estraverse "^4.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +estraverse@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" + integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + +estree-walker@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362" + integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + +eventemitter3@^4.0.0: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + +events-to-array@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/events-to-array/-/events-to-array-1.1.2.tgz#2d41f563e1fe400ed4962fe1a4d5c6a7539df7f6" + integrity sha1-LUH1Y+H+QA7Uli/hpNXGp1Od9/Y= + +events@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.1.0.tgz#84279af1b34cb75aa88bf5ff291f6d0bd9b31a59" + integrity sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg== + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +exec-sh@^0.3.2: + version "0.3.6" + resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.6.tgz#ff264f9e325519a60cb5e273692943483cca63bc" + integrity sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w== + +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + dependencies: + cross-spawn "^6.0.0" + get-stream "^4.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +execa@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-2.1.0.tgz#e5d3ecd837d2a60ec50f3da78fd39767747bbe99" + integrity sha512-Y/URAVapfbYy2Xp/gb6A0E7iR8xeqOCXsuuaoMn7A5PzrXUK84E1gyiEfq0wQd/GHA6GsoHWwhNq8anb0mleIw== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^3.0.0" + onetime "^5.1.0" + p-finally "^2.0.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + +execa@^3.0.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-3.4.0.tgz#c08ed4550ef65d858fac269ffc8572446f37eb89" + integrity sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + p-finally "^2.0.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + +execa@^4.0.0, execa@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" + integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +exif-parser@^0.1.12, exif-parser@^0.1.9: + version "0.1.12" + resolved "https://registry.yarnpkg.com/exif-parser/-/exif-parser-0.1.12.tgz#58a9d2d72c02c1f6f02a0ef4a9166272b7760922" + integrity sha1-WKnS1ywCwfbwKg70qRZicrd2CSI= + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +expand-tilde@^2.0.0, expand-tilde@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" + integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= + dependencies: + homedir-polyfill "^1.0.1" + +express@^4.10.7, express@^4.13.1, express@^4.17.1: + version "4.17.1" + resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" + integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== + dependencies: + accepts "~1.3.7" + array-flatten "1.1.1" + body-parser "1.19.0" + content-disposition "0.5.3" + content-type "~1.0.4" + cookie "0.4.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "~1.1.2" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "~1.1.2" + fresh "0.5.2" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.5" + qs "6.7.0" + range-parser "~1.2.1" + safe-buffer "5.1.2" + send "0.17.1" + serve-static "1.14.1" + setprototypeof "1.1.1" + statuses "~1.5.0" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extract-stack@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/extract-stack/-/extract-stack-2.0.0.tgz#11367bc865bfcd9bc0db3123e5edb57786f11f9b" + integrity sha512-AEo4zm+TenK7zQorGK1f9mJ8L14hnTDi2ZQPR+Mub1NX8zimka1mXpV5LpH8x9HoUmFSHZCfLHqWvp0Y4FxxzQ== + +extract-zip@^1.6.5: + version "1.7.0" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927" + integrity sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA== + dependencies: + concat-stream "^1.6.2" + debug "^2.6.9" + mkdirp "^0.5.4" + yauzl "^2.10.0" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + +fake-xml-http-request@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/fake-xml-http-request/-/fake-xml-http-request-2.1.2.tgz#f1786720cae50bbb46273035a0173414f3e85e74" + integrity sha512-HaFMBi7r+oEC9iJNpc3bvcW7Z7iLmM26hPDmlb0mFwyANSsOQAtJxbdWsXITKOzZUyMYK0zYCv3h5yDj9TsiXg== + +faker@^5.1.0: + version "5.5.3" + resolved "https://registry.yarnpkg.com/faker/-/faker-5.5.3.tgz#c57974ee484431b25205c2c8dc09fda861e51e0e" + integrity sha512-wLTv2a28wjUyWkbnX7u/ABZBkUkIF2fCd73V6P2oFqEGEktDfzWx4UxrSqtPRw0xPRAcjeAOIiJWqZm3pP4u3g== + +fast-deep-equal@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" + integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA== + +fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + +fast-glob@^3.0.3: + version "3.2.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.2.tgz#ade1a9d91148965d4bf7c51f72e1ca662d32e63d" + integrity sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" + +fast-glob@^3.1.1: + version "3.2.7" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" + integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +fast-ordered-set@^1.0.0, fast-ordered-set@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/fast-ordered-set/-/fast-ordered-set-1.0.3.tgz#3fbb36634f7be79e4f7edbdb4a357dee25d184eb" + integrity sha1-P7s2Y097555PftvbSjV97iXRhOs= + dependencies: + blank-object "^1.0.1" + +fast-sourcemap-concat@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/fast-sourcemap-concat/-/fast-sourcemap-concat-1.4.0.tgz#122c330d4a2afaff16ad143bc9674b87cd76c8ad" + integrity sha512-x90Wlx/2C83lfyg7h4oguTZN4MyaVfaiUSJQNpU+YEA0Odf9u659Opo44b0LfoVg9G/bOE++GdID/dkyja+XcA== + dependencies: + chalk "^2.0.0" + fs-extra "^5.0.0" + heimdalljs-logger "^0.1.9" + memory-streams "^0.1.3" + mkdirp "^0.5.0" + source-map "^0.4.2" + source-map-url "^0.3.0" + sourcemap-validator "^1.1.0" + +fast-sourcemap-concat@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-sourcemap-concat/-/fast-sourcemap-concat-2.1.0.tgz#12dd36bfc38c804093e4bd1de61dd6216f574211" + integrity sha512-L9uADEnnHOeF4U5Kc3gzEs3oFpNCFkiTJXvT+nKmR0zcFqHZJJbszWT7dv4t9558FJRGpCj8UxUpTgz2zwiIZA== + dependencies: + chalk "^2.0.0" + fs-extra "^5.0.0" + heimdalljs-logger "^0.1.9" + memory-streams "^0.1.3" + mkdirp "^0.5.0" + source-map "^0.4.2" + source-map-url "^0.3.0" + sourcemap-validator "^1.1.0" + +fastboot-express-middleware@3.2.0-beta.5: + version "3.2.0-beta.5" + resolved "https://registry.yarnpkg.com/fastboot-express-middleware/-/fastboot-express-middleware-3.2.0-beta.5.tgz#3510bc1a4eb4eec8059ae43cbbf07542b6c8f9a5" + integrity sha512-o1NggiJo/AFuj7OloC9hwxyrQUtN7K6CU4mKMBcG9+HC5uAETioWQkBgEy6qcOARzZrFdrsoUSk9KtYr+sqXyQ== + dependencies: + chalk "^2.0.1" + fastboot "3.2.0-beta.5" + +fastboot-transform@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/fastboot-transform/-/fastboot-transform-0.1.3.tgz#7dea0b117594afd8772baa6c9b0919644e7f7dcd" + integrity sha512-6otygPIJw1ARp1jJb+6KVO56iKBjhO+5x59RSC9qiZTbZRrv+HZAuP00KD3s+nWMvcFDemtdkugki9DNFTTwCQ== + dependencies: + broccoli-stew "^1.5.0" + convert-source-map "^1.5.1" + +fastboot@3.2.0-beta.5, fastboot@^3.2.0-beta.5: + version "3.2.0-beta.5" + resolved "https://registry.yarnpkg.com/fastboot/-/fastboot-3.2.0-beta.5.tgz#3d24bcaa0bd844bcc895ec0dbe96f2cd51713c1c" + integrity sha512-PJXdqtYw0aERX+ZiZpg3sR09xkHdGLXH+8g3NWknuT1+ShR93lsdMCrFcvES2Bnq/GC3PxqW/CJpume4E9KLGw== + dependencies: + chalk "^3.0.0" + cookie "^0.4.0" + debug "^4.1.1" + jsdom "^16.2.2" + resolve "^1.15.0" + simple-dom "^1.4.0" + source-map-support "^0.5.16" + +fastq@^1.6.0: + version "1.6.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.6.1.tgz#4570c74f2ded173e71cf0beb08ac70bb85826791" + integrity sha512-mpIH5sKYueh3YyeJwqtVo8sORi0CgtmkVbK6kZStpQlZBYQuTzG2CZ7idSiJuA7bY0SFCWUc5WIs+oYumGCQNw== + dependencies: + reusify "^1.0.4" + +favicons@5.3.0, favicons@^6.2.2: + version "5.3.0" + resolved "https://registry.yarnpkg.com/favicons/-/favicons-5.3.0.tgz#ba4f826f147718ccf7e312f6f7ae23881ad1dfa6" + integrity sha512-0uU+QToJ790J4X9ACR7AyNCxjoLsChC5mIm3P1TbVYrLlW3MQ6sv6DIxFpEyhnx7CzUP8ww7hpizWAel3Hr4Yw== + dependencies: + "@babel/polyfill" "^7.0.0" + cheerio "^1.0.0-rc.2" + clone "^2.1.2" + colors "^1.3.2" + core-js "^2.5.7" + image-size "^0.6.3" + jimp "^0.5.6" + jsontoxml "^1.0.1" + lodash.defaultsdeep "^4.6.0" + require-directory "^2.1.1" + svg2png "^4.1.1" + through2 "^3.0.0" + tinycolor2 "^1.4.1" + to-ico "^1.1.5" + util.promisify "^1.0.0" + vinyl "^2.2.0" + +faye-websocket@^0.11.3: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== + dependencies: + websocket-driver ">=0.5.1" + +fb-watchman@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" + integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== + dependencies: + bser "2.1.1" + +fd-slicer@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= + dependencies: + pend "~1.2.0" + +figgy-pudding@^3.5.1: + version "3.5.2" + resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" + integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== + +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= + dependencies: + escape-string-regexp "^1.0.5" + +figures@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" + integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +file-type@^3.1.0, file-type@^3.8.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" + integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek= + +file-type@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-9.0.0.tgz#a68d5ad07f486414dfb2c8866f73161946714a18" + integrity sha512-Qe/5NJrgIOlwijpq3B7BEpzPFcgzggOTagZmkXQY4LA6bsXKTUstK7Wp12lEJ/mLKTpvIZxmIuRcLYWT6ov9lw== + +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + +file-url@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/file-url/-/file-url-2.0.2.tgz#e951784d79095127d3713029ab063f40818ca2ae" + integrity sha1-6VF4TXkJUSfTcTApqwY/QIGMoq4= + +filesize@^4.1.2: + version "4.2.1" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-4.2.1.tgz#ab1cb2069db5d415911c1a13e144c0e743bc89bc" + integrity sha512-bP82Hi8VRZX/TUBKfE24iiUGsB/sfm2WUrwTQyAzQrhO3V9IhcBBNBXMyzLY5orACxRyYJ3d2HeRVX+eFv4lmA== + +filesize@^6.1.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-6.4.0.tgz#914f50471dd66fdca3cefe628bd0cde4ef769bcd" + integrity sha512-mjFIpOHC4jbfcTfoh4rkWpI31mF7viw9ikj/JyLoKzqlwG/YsefKfvYlYhdYdg/9mtK2z1AzgN/0LvVQ3zdlSQ== + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@1.1.2, finalhandler@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.3" + statuses "~1.5.0" + unpipe "~1.0.0" + +find-babel-config@^1.1.0, find-babel-config@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/find-babel-config/-/find-babel-config-1.2.0.tgz#a9b7b317eb5b9860cda9d54740a8c8337a2283a2" + integrity sha512-jB2CHJeqy6a820ssiqwrKMeyC6nNdmrcgkKWJWmpoxpE8RKciYJXCcXRq1h2AzCo5I5BJeN2tkGEO3hLTuePRA== + dependencies: + json5 "^0.5.1" + path-exists "^3.0.0" + +find-cache-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" + integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== + dependencies: + commondir "^1.0.1" + make-dir "^2.0.0" + pkg-dir "^3.0.0" + +find-index@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/find-index/-/find-index-1.1.1.tgz#4b221f8d46b7f8bea33d8faed953f3ca7a081cbc" + integrity sha512-XYKutXMrIK99YMUPf91KX5QVJoG31/OsgftD6YoTPAObfQIxM4ziA9f0J1AsqKhJmo+IeaIPP0CFopTD4bdUBw== + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +find-yarn-workspace-root@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz#40eb8e6e7c2502ddfaa2577c176f221422f860db" + integrity sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q== + dependencies: + fs-extra "^4.0.3" + micromatch "^3.1.4" + +find-yarn-workspace-root@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" + integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== + dependencies: + micromatch "^4.0.2" + +findup-sync@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-4.0.0.tgz#956c9cdde804052b881b428512905c4a5f2cdef0" + integrity sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ== + dependencies: + detect-file "^1.0.0" + is-glob "^4.0.0" + micromatch "^4.0.2" + resolve-dir "^1.0.1" + +fireworm@^0.7.0: + version "0.7.1" + resolved "https://registry.yarnpkg.com/fireworm/-/fireworm-0.7.1.tgz#ccf20f7941f108883fcddb99383dbe6e1861c758" + integrity sha1-zPIPeUHxCIg/zduZOD2+bhhhx1g= + dependencies: + async "~0.2.9" + is-type "0.0.1" + lodash.debounce "^3.1.1" + lodash.flatten "^3.0.2" + minimatch "^3.0.2" + +fixturify-project@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/fixturify-project/-/fixturify-project-1.10.0.tgz#091c452a9bb15f09b6b9cc7cf5c0ad559f1d9aad" + integrity sha512-L1k9uiBQuN0Yr8tA9Noy2VSQ0dfg0B8qMdvT7Wb5WQKc7f3dn3bzCbSrqlb+etLW+KDV4cBC7R1OvcMg3kcxmA== + dependencies: + fixturify "^1.2.0" + tmp "^0.0.33" + +fixturify-project@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/fixturify-project/-/fixturify-project-2.1.1.tgz#a511dd26700c6b64ac271ef4393e7124f153c81f" + integrity sha512-sP0gGMTr4iQ8Kdq5Ez0CVJOZOGWqzP5dv/veOTdFNywioKjkNWCHBi1q65DMpcNGUGeoOUWehyji274Q2wRgxA== + dependencies: + fixturify "^2.1.0" + tmp "^0.0.33" + type-fest "^0.11.0" + +fixturify@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fixturify/-/fixturify-1.3.0.tgz#163c468093c7c4d90b70cde39fd6325f6528b25d" + integrity sha512-tL0svlOy56pIMMUQ4bU1xRe6NZbFSa/ABTWMxW2mH38lFGc9TrNAKWcMBQ7eIjo3wqSS8f2ICabFaatFyFmrVQ== + dependencies: + "@types/fs-extra" "^5.0.5" + "@types/minimatch" "^3.0.3" + "@types/rimraf" "^2.0.2" + fs-extra "^7.0.1" + matcher-collection "^2.0.0" + +fixturify@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/fixturify/-/fixturify-2.1.1.tgz#e962d72f062600cb81a9651086f60d822c72d998" + integrity sha512-SRgwIMXlxkb6AUgaVjIX+jCEqdhyXu9hah7mcK+lWynjKtX73Ux1TDv71B7XyaQ+LJxkYRHl5yCL8IycAvQRUw== + dependencies: + "@types/fs-extra" "^8.1.0" + "@types/minimatch" "^3.0.3" + "@types/rimraf" "^2.0.3" + fs-extra "^8.1.0" + matcher-collection "^2.0.1" + walk-sync "^2.0.2" + +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flatted@^3.1.0: + version "3.2.4" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.4.tgz#28d9969ea90661b5134259f312ab6aa7929ac5e2" + integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw== + +flush-write-stream@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" + integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== + dependencies: + inherits "^2.0.3" + readable-stream "^2.3.6" + +follow-redirects@^1.0.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db" + integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA== + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +forever-agent@~0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.5.2.tgz#6d0e09c4921f94a27f63d3b49c5feff1ea4c5130" + integrity sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA= + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +form-data@~0.1.0: + version "0.1.4" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-0.1.4.tgz#91abd788aba9702b1aabfa8bc01031a2ac9e3b12" + integrity sha1-kavXiKupcCsaq/qLwBAxoqyeOxI= + dependencies: + async "~0.9.0" + combined-stream "~0.0.4" + mime "~1.2.11" + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +forwarded@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" + integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + +from2@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" + integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.0" + +fs-extra@1.0.0, fs-extra@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-1.0.0.tgz#cd3ce5f7e7cb6145883fcae3191e9877f8587950" + integrity sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA= + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + klaw "^1.0.0" + +fs-extra@^0.24.0: + version "0.24.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.24.0.tgz#d4e4342a96675cb7846633a6099249332b539952" + integrity sha1-1OQ0KpZnXLeEZjOmCZJJMytTmVI= + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + path-is-absolute "^1.0.0" + rimraf "^2.2.8" + +fs-extra@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.0.tgz#9ff61b655dde53fb34a82df84bb214ce802e17c1" + integrity sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-extra@^4.0.0, fs-extra@^4.0.2, fs-extra@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" + integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" + integrity sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-6.0.1.tgz#8abc128f7946e310135ddc93b98bddb410e7a34b" + integrity sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^7.0.0, fs-extra@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^8.0.0, fs-extra@^8.0.1, fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^9.0.1, fs-extra@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-merger@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/fs-merger/-/fs-merger-3.0.2.tgz#bf111334b89b8d65b95580d33c587dc79620a4e3" + integrity sha512-63wmgjPDClP5XcTSKdIXz66X5paYy/m2Ymq5c5YpGxRQEk1HFZ8rtti3LMNSOSw1ketbBMGbSFFcQeEnpnzDpQ== + dependencies: + broccoli-node-api "^1.7.0" + broccoli-node-info "^2.1.0" + fs-extra "^8.0.1" + fs-tree-diff "^2.0.1" + rimraf "^2.6.3" + walk-sync "^2.0.2" + +fs-merger@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/fs-merger/-/fs-merger-3.2.1.tgz#a225b11ae530426138294b8fbb19e82e3d4e0b3b" + integrity sha512-AN6sX12liy0JE7C2evclwoo0aCG3PFulLjrTLsJpWh/2mM+DinhpSGqYLbHBBbIW1PLRNcFhJG8Axtz8mQW3ug== + dependencies: + broccoli-node-api "^1.7.0" + broccoli-node-info "^2.1.0" + fs-extra "^8.0.1" + fs-tree-diff "^2.0.1" + walk-sync "^2.2.0" + +fs-tree-diff@^0.5.2, fs-tree-diff@^0.5.3, fs-tree-diff@^0.5.4, fs-tree-diff@^0.5.6, fs-tree-diff@^0.5.7, fs-tree-diff@^0.5.9: + version "0.5.9" + resolved "https://registry.yarnpkg.com/fs-tree-diff/-/fs-tree-diff-0.5.9.tgz#a4ec6182c2f5bd80b9b83c8e23e4522e6f5fd946" + integrity sha512-872G8ax0kHh01m9n/2KDzgYwouKza0Ad9iFltBpNykvROvf2AGtoOzPJgGx125aolGPER3JuC7uZFrQ7bG1AZw== + dependencies: + heimdalljs-logger "^0.1.7" + object-assign "^4.1.0" + path-posix "^1.0.0" + symlink-or-copy "^1.1.8" + +fs-tree-diff@^2.0.0, fs-tree-diff@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fs-tree-diff/-/fs-tree-diff-2.0.1.tgz#343e4745ab435ec39ebac5f9059ad919cd034afa" + integrity sha512-x+CfAZ/lJHQqwlD64pYM5QxWjzWhSjroaVsr8PW831zOApL55qPibed0c+xebaLWVr2BnHFoHdrwOv8pzt8R5A== + dependencies: + "@types/symlink-or-copy" "^1.2.0" + heimdalljs-logger "^0.1.7" + object-assign "^4.1.0" + path-posix "^1.0.0" + symlink-or-copy "^1.1.8" + +fs-updater@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/fs-updater/-/fs-updater-1.0.4.tgz#2329980f99ae9176e9a0e84f7637538a182ce63b" + integrity sha512-0pJX4mJF/qLsNEwTct8CdnnRdagfb+LmjRPJ8sO+nCnAZLW0cTmz4rTgU25n+RvTuWSITiLKrGVJceJPBIPlKg== + dependencies: + can-symlink "^1.0.0" + clean-up-path "^1.0.0" + heimdalljs "^0.2.5" + heimdalljs-logger "^0.1.9" + rimraf "^2.6.2" + +fs-write-stream-atomic@^1.0.8: + version "1.0.10" + resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" + integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= + dependencies: + graceful-fs "^4.1.2" + iferr "^0.1.5" + imurmurhash "^0.1.4" + readable-stream "1 || 2" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@^1.2.7: + version "1.2.12" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.12.tgz#db7e0d8ec3b0b45724fd4d83d43554a8f1f0de5c" + integrity sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q== + dependencies: + bindings "^1.5.0" + nan "^2.12.1" + +fsevents@~2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" + integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + +fuse.js@^6.4.6: + version "6.4.6" + resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-6.4.6.tgz#62f216c110e5aa22486aff20be7896d19a059b79" + integrity sha512-/gYxR/0VpXmWSfZOIPS3rWwU8SHgsRTwWuXhyb2O6s7aRuVtHtxCkR33bNYu3wyLyNx/Wpv0vU7FZy8Vj53VNw== + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" + integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + +get-stdin@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" + integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= + +get-stdin@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-8.0.0.tgz#cbad6a73feb75f6eeb22ba9e01f89aa28aa97a53" + integrity sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg== + +get-stream@^2.0.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" + integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4= + dependencies: + object-assign "^4.0.1" + pinkie-promise "^2.0.0" + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= + +get-stream@^4.0.0, get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" + integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== + dependencies: + pump "^3.0.0" + +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + +git-config-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/git-config-path/-/git-config-path-2.0.0.tgz#62633d61af63af4405a5024efd325762f58a181b" + integrity sha512-qc8h1KIQbJpp+241id3GuAtkdyJ+IK+LIVtkiFTRKRrmddDzs3SI9CvP1QYmWBFvm1I/PWRwj//of8bgAc0ltA== + +git-hooks-list@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/git-hooks-list/-/git-hooks-list-1.0.3.tgz#be5baaf78203ce342f2f844a9d2b03dba1b45156" + integrity sha512-Y7wLWcrLUXwk2noSka166byGCvhMtDRpgHdzCno1UQv/n/Hegp++a2xBWJL1lJarnKD3SWaljD+0z1ztqxuKyQ== + +git-repo-info@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/git-repo-info/-/git-repo-info-2.1.1.tgz#220ffed8cbae74ef8a80e3052f2ccb5179aed058" + integrity sha512-8aCohiDo4jwjOwma4FmYFd3i97urZulL8XL24nIPxuE+GZnfsAyy/g2Shqx6OjUiFKUXZM+Yy+KHnOmmA3FVcg== + +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + +glob-parent@^5.1.0, glob-parent@~5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" + integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + dependencies: + is-glob "^4.0.1" + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@^5.0.10: + version "5.0.15" + resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.0, glob@^7.0.4, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global-modules@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" + integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== + dependencies: + global-prefix "^1.0.1" + is-windows "^1.0.1" + resolve-dir "^1.0.0" + +global-prefix@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" + integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= + dependencies: + expand-tilde "^2.0.2" + homedir-polyfill "^1.0.1" + ini "^1.3.4" + is-windows "^1.0.1" + which "^1.2.14" + +global@~4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" + integrity sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8= + dependencies: + min-document "^2.19.0" + process "~0.5.1" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^13.6.0, globals@^13.9.0: + version "13.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.12.0.tgz#4d733760304230a0082ed96e21e5c565f898089e" + integrity sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg== + dependencies: + type-fest "^0.20.2" + +globals@^9.18.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== + +globalyzer@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/globalyzer/-/globalyzer-0.1.0.tgz#cb76da79555669a1519d5a8edf093afaa0bf1465" + integrity sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q== + +globby@10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.0.tgz#abfcd0630037ae174a88590132c2f6804e291072" + integrity sha512-3LifW9M4joGZasyYPz2A1U74zbC/45fvpXUvO/9KbSa+VV0aGZarWkfdgKyR9sExNP0t0x0ss/UMJpNpcaTspw== + dependencies: + "@types/glob" "^7.1.1" + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.0.3" + glob "^7.1.3" + ignore "^5.1.1" + merge2 "^1.2.3" + slash "^3.0.0" + +globby@^11.0.3, globby@^11.0.4: + version "11.0.4" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" + integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + +globrex@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098" + integrity sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg== + +good-listener@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50" + integrity sha1-1TswzfkxPf+33JoNR3CWqm0UXFA= + dependencies: + delegate "^3.1.2" + +got@^9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" + integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== + +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= + +growly@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" + integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= + +handlebars@^4.0.13, handlebars@^4.0.4, handlebars@^4.3.1, handlebars@^4.4.2, handlebars@^4.7.3: + version "4.7.7" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" + integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== + dependencies: + minimist "^1.2.5" + neo-async "^2.6.0" + source-map "^0.6.1" + wordwrap "^1.0.0" + optionalDependencies: + uglify-js "^3.1.4" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" + integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== + dependencies: + ajv "^6.5.5" + har-schema "^2.0.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + dependencies: + ansi-regex "^2.0.0" + +has-ansi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-3.0.0.tgz#36077ef1d15f333484aa7fa77a28606f1c655b37" + integrity sha1-Ngd+8dFfMzSEqn+neihgbxxlWzc= + dependencies: + ansi-regex "^3.0.0" + +has-bigints@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" + integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbols@^1.0.0, has-symbols@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== + +has-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" + integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hash-base@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" + integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +hash-for-dep@^1.0.2, hash-for-dep@^1.2.3, hash-for-dep@^1.4.7, hash-for-dep@^1.5.0, hash-for-dep@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/hash-for-dep/-/hash-for-dep-1.5.1.tgz#497754b39bee2f1c4ade4521bfd2af0a7c1196e3" + integrity sha512-/dQ/A2cl7FBPI2pO0CANkvuuVi/IFS5oTyJ0PsOb6jW6WbVW1js5qJXMJTNbWHXBIPdFTWFbabjB+mE0d+gelw== + dependencies: + broccoli-kitchen-sink-helpers "^0.3.1" + heimdalljs "^0.2.3" + heimdalljs-logger "^0.1.7" + path-root "^0.1.1" + resolve "^1.10.0" + resolve-package-path "^1.0.11" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hasha@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/hasha/-/hasha-2.2.0.tgz#78d7cbfc1e6d66303fe79837365984517b2f6ee1" + integrity sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE= + dependencies: + is-stream "^1.0.1" + pinkie-promise "^2.0.0" + +hawk@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-1.1.1.tgz#87cd491f9b46e4e2aeaca335416766885d2d1ed9" + integrity sha1-h81JH5tG5OKurKM1QWdmiF0tHtk= + dependencies: + boom "0.4.x" + cryptiles "0.2.x" + hoek "0.9.x" + sntp "0.2.x" + +heimdalljs-fs-monitor@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/heimdalljs-fs-monitor/-/heimdalljs-fs-monitor-1.1.1.tgz#bb4021007e88484202402cdf594e3962d70dc4f4" + integrity sha512-BHB8oOXLRlrIaON0MqJSEjGVPDyqt2Y6gu+w2PaEZjrCxeVtZG7etEZp7M4ZQ80HNvnr66KIQ2lot2qdeG8HgQ== + dependencies: + callsites "^3.1.0" + clean-stack "^2.2.0" + extract-stack "^2.0.0" + heimdalljs "^0.2.3" + heimdalljs-logger "^0.1.7" + +heimdalljs-graph@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/heimdalljs-graph/-/heimdalljs-graph-1.0.0.tgz#0059857952988e54f3a74bb23edaf669f8eaf6af" + integrity sha512-v2AsTERBss0ukm/Qv4BmXrkwsT5x6M1V5Om6E8NcDQ/ruGkERsfsuLi5T8jx8qWzKMGYlwzAd7c/idymxRaPzA== + +heimdalljs-logger@^0.1.10, heimdalljs-logger@^0.1.7, heimdalljs-logger@^0.1.9: + version "0.1.10" + resolved "https://registry.yarnpkg.com/heimdalljs-logger/-/heimdalljs-logger-0.1.10.tgz#90cad58aabb1590a3c7e640ddc6a4cd3a43faaf7" + integrity sha512-pO++cJbhIufVI/fmB/u2Yty3KJD0TqNPecehFae0/eps0hkZ3b4Zc/PezUMOpYuHFQbA7FxHZxa305EhmjLj4g== + dependencies: + debug "^2.2.0" + heimdalljs "^0.2.6" + +heimdalljs@^0.2.0, heimdalljs@^0.2.1, heimdalljs@^0.2.3, heimdalljs@^0.2.5, heimdalljs@^0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/heimdalljs/-/heimdalljs-0.2.6.tgz#b0eebabc412813aeb9542f9cc622cb58dbdcd9fe" + integrity sha512-o9bd30+5vLBvBtzCPwwGqpry2+n0Hi6H1+qwt6y+0kwRHGGF8TFIhJPmnuM0xO97zaKrDZMwO/V56fAnn8m/tA== + dependencies: + rsvp "~3.2.1" + +highlight.js@^10.7.2: + version "10.7.3" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531" + integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A== + +himalaya@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/himalaya/-/himalaya-1.1.0.tgz#31724ae9d35714cd7c6f4be94888953f3604606a" + integrity sha512-LLase1dHCRMel68/HZTFft0N0wti0epHr3nNY7ynpLbyZpmrKMQ8YIpiOV77TM97cNpC8Wb2n6f66IRggwdWPw== + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +hoek@0.9.x: + version "0.9.1" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-0.9.1.tgz#3d322462badf07716ea7eb85baf88079cddce505" + integrity sha1-PTIkYrrfB3Fup+uFuviAec3c5QU= + +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg= + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +homedir-polyfill@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" + integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== + dependencies: + parse-passwd "^1.0.0" + +hosted-git-info@^2.1.4: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + +hosted-git-info@^4.0.1, hosted-git-info@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.0.2.tgz#5e425507eede4fea846b7262f0838456c4209961" + integrity sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg== + dependencies: + lru-cache "^6.0.0" + +html-encoding-sniffer@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" + integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== + dependencies: + whatwg-encoding "^1.0.5" + +html-encoding-sniffer@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz#2cb1a8cf0db52414776e5b2a7a04d5dd98158de9" + integrity sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA== + dependencies: + whatwg-encoding "^2.0.0" + +html-entities@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.2.tgz#760b404685cb1d794e4f4b744332e3b00dcfe488" + integrity sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ== + +html-tags@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140" + integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg== + +htmlparser2@^3.9.1: + version "3.10.1" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" + integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== + dependencies: + domelementtype "^1.3.1" + domhandler "^2.3.0" + domutils "^1.5.1" + entities "^1.1.1" + inherits "^2.0.1" + readable-stream "^3.1.1" + +htmlparser2@~3.8.1: + version "3.8.3" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.8.3.tgz#996c28b191516a8be86501a7d79757e5c70c1068" + integrity sha1-mWwosZFRaovoZQGn15dX5ccMEGg= + dependencies: + domelementtype "1" + domhandler "2.3" + domutils "1.5" + entities "1.0" + readable-stream "1.1" + +http-cache-semantics@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + +http-errors@1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" + integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-errors@~1.7.2: + version "1.7.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" + integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +"http-parser-js@>=0.4.0 <0.4.11": + version "0.4.10" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4" + integrity sha1-ksnBN0w1CF912zWexWzCV8u5P6Q= + +http-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" + integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w== + dependencies: + "@tootallnate/once" "2" + agent-base "6" + debug "4" + +http-proxy@^1.13.1, http-proxy@^1.18.1: + version "1.18.1" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" + integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== + dependencies: + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + +http-signature@~0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-0.10.1.tgz#4fbdac132559aa8323121e540779c0a012b27e66" + integrity sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY= + dependencies: + asn1 "0.1.11" + assert-plus "^0.1.5" + ctype "0.5.3" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +https-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= + +https-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + dependencies: + agent-base "6" + debug "4" + +https@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https/-/https-1.0.0.tgz#3c37c7ae1a8eeb966904a2ad1e975a194b7ed3a4" + integrity sha1-PDfHrhqO65ZpBKKtHpdaGUt+06Q= + +human-signals@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +ice-cap@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/ice-cap/-/ice-cap-0.0.4.tgz#8a6d31ab4cac8d4b56de4fa946df3352561b6e18" + integrity sha1-im0xq0ysjUtW3k+pRt8zUlYbbhg= + dependencies: + cheerio "0.20.0" + color-logger "0.0.3" + +iconv-lite@0.4.24, iconv-lite@^0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +iconv-lite@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +ieee754@^1.1.4: + version "1.1.13" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" + integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== + +iferr@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" + integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= + +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + +ignore@^5.1.1: + version "5.1.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf" + integrity sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A== + +ignore@^5.1.4: + version "5.1.9" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.9.tgz#9ec1a5cbe8e1446ec60d4420060d43aa6e7382fb" + integrity sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ== + +image-size@^0.5.0: + version "0.5.5" + resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c" + integrity sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w= + +image-size@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.6.3.tgz#e7e5c65bb534bd7cdcedd6cb5166272a85f75fb2" + integrity sha512-47xSUiQioGaB96nqtp5/q55m0aBQSQdyIloMOc/x+QVTDZLNmXE892IIDrJ0hM1A5vcNUDD5tDffkSP5lCaIIA== + +immutable@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0.tgz#b86f78de6adef3608395efb269a91462797e2c23" + integrity sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw== + +import-fresh@^3.0.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" + integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +include-path-searcher@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/include-path-searcher/-/include-path-searcher-0.1.0.tgz#c0cf2ddfa164fb2eae07bc7ca43a7f191cb4d7bd" + integrity sha1-wM8t36Fk+y6uB7x8pDp/GRy0170= + +indexes-of@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" + integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= + +infer-owner@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" + integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== + +inflected@^2.0.3, inflected@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inflected/-/inflected-2.0.4.tgz#323770961ccbe992a98ea930512e9a82d3d3ef77" + integrity sha512-HQPzFLTTUvwfeUH6RAGjD8cHS069mBqXG5n4qaxX7sJXBhVQrsGgF+0ZJGkSuN6a8pcUWB/GXStta11kKi/WvA== + +inflection@^1.12.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.12.0.tgz#a200935656d6f5f6bc4dc7502e1aecb703228416" + integrity sha1-ogCTVlbW9fa8TcdQLhrstwMihBY= + +inflection@~1.13.1: + version "1.13.1" + resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.13.1.tgz#c5cadd80888a90cf84c2e96e340d7edc85d5f0cb" + integrity sha512-dldYtl2WlN0QDkIDtg8+xFwOS2Tbmp12t1cHa5/YClU6ZQjTFm7B66UcVbh9NQB+HvT5BAd2t5+yKsBkw5pcqA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +ini@^1.3.4: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +ini@^1.3.5, ini@~1.3.0: + version "1.3.7" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84" + integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ== + +inline-source-map-comment@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/inline-source-map-comment/-/inline-source-map-comment-1.0.5.tgz#50a8a44c2a790dfac441b5c94eccd5462635faf6" + integrity sha1-UKikTCp5DfrEQbXJTszVRiY1+vY= + dependencies: + chalk "^1.0.0" + get-stdin "^4.0.1" + minimist "^1.1.1" + sum-up "^1.0.1" + xtend "^4.0.0" + +inquirer@^6: + version "6.5.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" + integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== + dependencies: + ansi-escapes "^3.2.0" + chalk "^2.4.2" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^2.0.0" + lodash "^4.17.12" + mute-stream "0.0.7" + run-async "^2.2.0" + rxjs "^6.4.0" + string-width "^2.1.0" + strip-ansi "^5.1.0" + through "^2.3.6" + +inquirer@^7.3.3: + version "7.3.3" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" + integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA== + dependencies: + ansi-escapes "^4.2.1" + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-width "^3.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash "^4.17.19" + mute-stream "0.0.8" + run-async "^2.4.0" + rxjs "^6.6.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + through "^2.3.6" + +internal-slot@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" + integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== + dependencies: + get-intrinsic "^1.1.0" + has "^1.0.3" + side-channel "^1.0.4" + +invariant@^2.2.2: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= + +ip-regex@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-1.0.3.tgz#dc589076f659f419c222039a33316f1c7387effd" + integrity sha1-3FiQdvZZ9BnCIgOaMzFvHHOH7/0= + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= + dependencies: + binary-extensions "^1.0.0" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-callable@^1.1.4, is-callable@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" + integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== + +is-callable@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" + integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== + +is-core-module@^2.2.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548" + integrity sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw== + dependencies: + has "^1.0.3" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-date-object@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" + integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-finite@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" + integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-function@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" + integrity sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU= + +is-git-url@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-git-url/-/is-git-url-1.0.0.tgz#53f684cd143285b52c3244b4e6f28253527af66b" + integrity sha1-U/aEzRQyhbUsMkS05vKCU1J69ms= + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= + dependencies: + is-extglob "^2.1.0" + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-interactive@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" + integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + +is-language-code@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-language-code/-/is-language-code-2.0.0.tgz#6f4d59c551d73b98c45cf9f1d3ce65cee060e65b" + integrity sha512-6xKmRRcP2YdmMBZMVS3uiJRPQgcMYolkD6hFw2Y4KjqyIyaJlCGxUt56tuu0iIV8q9r8kMEo0Gjd/GFwKrgjbw== + +is-negative-zero@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" + integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== + +is-number-object@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0" + integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g== + dependencies: + has-tostringtag "^1.0.0" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + +is-plain-obj@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-potential-custom-element-name@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397" + integrity sha1-DFLlS8yjkbssSUsh6GJtczbG45c= + +is-potential-custom-element-name@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" + integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== + +is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= + +is-reference@^1.1.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.1.4.tgz#3f95849886ddb70256a3e6d062b1a68c13c51427" + integrity sha512-uJA/CDPO3Tao3GTrxYn6AwkM4nUPJiGGYu5+cB8qbC7WGFlrKZbiRo7SFKxUAEpFUfiHofWCXBUNhvYJMh+6zw== + dependencies: + "@types/estree" "0.0.39" + +is-regex@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" + integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== + dependencies: + has "^1.0.3" + +is-regex@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-shared-array-buffer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" + integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== + +is-stream@^1.0.1, is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-symbol@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" + integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== + dependencies: + has-symbols "^1.0.1" + +is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-type@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/is-type/-/is-type-0.0.1.tgz#f651d85c365d44955d14a51d8d7061f3f6b4779c" + integrity sha1-9lHYXDZdRJVdFKUdjXBh8/a0d5w= + dependencies: + core-util-is "~1.0.0" + +is-typedarray@^1.0.0, is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= + +is-weakref@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.1.tgz#842dba4ec17fa9ac9850df2d6efbc1737274f2a2" + integrity sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ== + dependencies: + call-bind "^1.0.0" + +is-windows@^1.0.1, is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= + +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isbinaryfile@^4.0.6: + version "4.0.8" + resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.8.tgz#5d34b94865bd4946633ecc78a026fc76c5b11fcf" + integrity sha512-53h6XFniq77YdW+spoRrebh0mnmTxRPTlcuIArO57lmMdq4uBKFKaeTjnb92oYWrSn/LVL+LT+Hap2tFQj8V+w== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +istextorbinary@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/istextorbinary/-/istextorbinary-2.1.0.tgz#dbed2a6f51be2f7475b68f89465811141b758874" + integrity sha1-2+0qb1G+L3R1to+JRlgRFBt1iHQ= + dependencies: + binaryextensions "1 || 2" + editions "^1.1.1" + textextensions "1 || 2" + +istextorbinary@^2.5.1: + version "2.6.0" + resolved "https://registry.yarnpkg.com/istextorbinary/-/istextorbinary-2.6.0.tgz#60776315fb0fa3999add276c02c69557b9ca28ab" + integrity sha512-+XRlFseT8B3L9KyjxxLjfXSLMuErKDsd8DBNrsaxoViABMEZlOSCstwmw0qpoFX3+U6yWU1yhLudAe6/lETGGA== + dependencies: + binaryextensions "^2.1.2" + editions "^2.2.0" + textextensions "^2.5.0" + +jimp@^0.2.21: + version "0.2.28" + resolved "https://registry.yarnpkg.com/jimp/-/jimp-0.2.28.tgz#dd529a937190f42957a7937d1acc3a7762996ea2" + integrity sha1-3VKak3GQ9ClXp5N9Gsw6d2KZbqI= + dependencies: + bignumber.js "^2.1.0" + bmp-js "0.0.3" + es6-promise "^3.0.2" + exif-parser "^0.1.9" + file-type "^3.1.0" + jpeg-js "^0.2.0" + load-bmfont "^1.2.3" + mime "^1.3.4" + mkdirp "0.5.1" + pixelmatch "^4.0.0" + pngjs "^3.0.0" + read-chunk "^1.0.1" + request "^2.65.0" + stream-to-buffer "^0.1.0" + tinycolor2 "^1.1.2" + url-regex "^3.0.0" + +jimp@^0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/jimp/-/jimp-0.5.6.tgz#dd114decd060927ae439f2e0980df619c179f912" + integrity sha512-H0nHTu6KgAgQzDxa38ew2dXbnRzKm1w5uEyhMIxqwCQVjwgarOjjkV/avbNLxfxRHAFaNp4rGIc/qm8P+uhX9A== + dependencies: + "@babel/polyfill" "^7.0.0" + "@jimp/custom" "^0.5.4" + "@jimp/plugins" "^0.5.5" + "@jimp/types" "^0.5.4" + core-js "^2.5.7" + +jpeg-js@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.1.2.tgz#135b992c0575c985cfa0f494a3227ed238583ece" + integrity sha1-E1uZLAV1yYXPoPSUoyJ+0jhYPs4= + +jpeg-js@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.2.0.tgz#53e448ec9d263e683266467e9442d2c5a2ef5482" + integrity sha1-U+RI7J0mPmgyZkZ+lELSxaLvVII= + +jpeg-js@^0.3.4: + version "0.3.7" + resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.3.7.tgz#471a89d06011640592d314158608690172b1028d" + integrity sha512-9IXdWudL61npZjvLuVe/ktHiA41iE8qFyLB+4VDTblEsWBzeg8WQTlktdUK4CdncUqtUgUg0bbOmTE2bKBKaBQ== + +jquery@^3.5.0, jquery@^3.5.1: + version "3.6.0" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.0.tgz#c72a09f15c1bdce142f49dbf1170bdf8adac2470" + integrity sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw== + +js-string-escape@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" + integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= + +js-yaml@^3.13.1, js-yaml@^3.14.0, js-yaml@^3.2.5, js-yaml@^3.2.7: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +jsdom@^16.2.2, jsdom@^16.4.0: + version "16.5.3" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.5.3.tgz#13a755b3950eb938b4482c407238ddf16f0d2136" + integrity sha512-Qj1H+PEvUsOtdPJ056ewXM4UJPCi4hhLA8wpiz9F2YvsRBhuFsXxtrIFAgGBDynQA9isAMGE91PfUYbdMPXuTA== + dependencies: + abab "^2.0.5" + acorn "^8.1.0" + acorn-globals "^6.0.0" + cssom "^0.4.4" + cssstyle "^2.3.0" + data-urls "^2.0.0" + decimal.js "^10.2.1" + domexception "^2.0.1" + escodegen "^2.0.0" + html-encoding-sniffer "^2.0.1" + is-potential-custom-element-name "^1.0.0" + nwsapi "^2.2.0" + parse5 "6.0.1" + request "^2.88.2" + request-promise-native "^1.0.9" + saxes "^5.0.1" + symbol-tree "^3.2.4" + tough-cookie "^4.0.0" + w3c-hr-time "^1.0.2" + w3c-xmlserializer "^2.0.0" + webidl-conversions "^6.1.0" + whatwg-encoding "^1.0.5" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.5.0" + ws "^7.4.4" + xml-name-validator "^3.0.0" + +jsdom@^19.0.0: + version "19.0.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-19.0.0.tgz#93e67c149fe26816d38a849ea30ac93677e16b6a" + integrity sha512-RYAyjCbxy/vri/CfnjUWJQQtZ3LKlLnDqj+9XLNnJPgEGeirZs3hllKR20re8LUZ6o1b1X4Jat+Qd26zmP41+A== + dependencies: + abab "^2.0.5" + acorn "^8.5.0" + acorn-globals "^6.0.0" + cssom "^0.5.0" + cssstyle "^2.3.0" + data-urls "^3.0.1" + decimal.js "^10.3.1" + domexception "^4.0.0" + escodegen "^2.0.0" + form-data "^4.0.0" + html-encoding-sniffer "^3.0.0" + http-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.0" + is-potential-custom-element-name "^1.0.1" + nwsapi "^2.2.0" + parse5 "6.0.1" + saxes "^5.0.1" + symbol-tree "^3.2.4" + tough-cookie "^4.0.0" + w3c-hr-time "^1.0.2" + w3c-xmlserializer "^3.0.0" + webidl-conversions "^7.0.0" + whatwg-encoding "^2.0.0" + whatwg-mimetype "^3.0.0" + whatwg-url "^10.0.0" + ws "^8.2.3" + xml-name-validator "^4.0.0" + +jsdom@^7.0.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-7.2.2.tgz#40b402770c2bda23469096bee91ab675e3b1fc6e" + integrity sha1-QLQCdwwr2iNGkJa+6Rq2deOx/G4= + dependencies: + abab "^1.0.0" + acorn "^2.4.0" + acorn-globals "^1.0.4" + cssom ">= 0.3.0 < 0.4.0" + cssstyle ">= 0.2.29 < 0.3.0" + escodegen "^1.6.1" + nwmatcher ">= 1.3.7 < 2.0.0" + parse5 "^1.5.1" + request "^2.55.0" + sax "^1.1.4" + symbol-tree ">= 3.1.0 < 4.0.0" + tough-cookie "^2.2.0" + webidl-conversions "^2.0.0" + whatwg-url-compat "~0.6.5" + xml-name-validator ">= 2.0.1 < 3.0.0" + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s= + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@~0.3.x: + version "0.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.3.0.tgz#1bf5ee63b4539fe2e26d0c1e99c240b97a457972" + integrity sha1-G/XuY7RTn+LibQwemcJAuXpFeXI= + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= + +json-api-serializer@^2.2.1, json-api-serializer@^2.6.2: + version "2.6.6" + resolved "https://registry.yarnpkg.com/json-api-serializer/-/json-api-serializer-2.6.6.tgz#fa5d283b913e0ea25653f4d04f981dc44d66dd4f" + integrity sha512-l7/e2O5/0+GU38RTMowRUKxRlT8zFc1oryAYBxqK54sFZnvJOJI2bo4XbbxnkTtvSzwkyv5DoBUuFm0hvG3avg== + dependencies: + setimmediate "^1.0.5" + +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + +json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + +json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= + dependencies: + jsonify "~0.0.0" + +json-stringify-safe@~5.0.0, json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +json5@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + +json5@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.2.tgz#43ef1f0af9835dd624751a6b7fa48874fb2d608e" + integrity sha512-MoUOQ4WdiN3yxhm7NEVJSJrieAo5hNSLQ5sj05OTRHPL9HOBy8u4Bu88jsC1jvqAdN+E1bJmsUcZH+1HQxliqQ== + dependencies: + minimist "^1.2.5" + +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug= + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= + +jsontoxml@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/jsontoxml/-/jsontoxml-1.0.1.tgz#07fff7f6bfbfa1097d779aec7f041b5046075e70" + integrity sha512-dtKGq0K8EWQBRqcAaePSgKR4Hyjfsz/LkurHSV3Cxk4H+h2fWDeaN2jzABz+ZmOJylgXS7FGeWmbZ6jgYUMdJQ== + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +kew@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/kew/-/kew-0.7.0.tgz#79d93d2d33363d6fdd2970b335d9141ad591d79b" + integrity sha1-edk9LTM2PW/dKXCzNdkUGtWR15s= + +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk= + optionalDependencies: + graceful-fs "^4.1.9" + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= + dependencies: + invert-kv "^1.0.0" + +leek@0.0.24: + version "0.0.24" + resolved "https://registry.yarnpkg.com/leek/-/leek-0.0.24.tgz#e400e57f0e60d8ef2bd4d068dc428a54345dbcda" + integrity sha1-5ADlfw5g2O8r1NBo3EKKVDRdvNo= + dependencies: + debug "^2.1.0" + lodash.assign "^3.2.0" + rsvp "^3.0.21" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +line-column@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/line-column/-/line-column-1.0.2.tgz#d25af2936b6f4849172b312e4792d1d987bc34a2" + integrity sha1-0lryk2tvSEkXKzEuR5LR2Ye8NKI= + dependencies: + isarray "^1.0.0" + isobject "^2.0.0" + +linkify-it@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf" + integrity sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw== + dependencies: + uc.micro "^1.0.1" + +linkify-it@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.3.tgz#a98baf44ce45a550efb4d49c769d07524cc2fa2e" + integrity sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ== + dependencies: + uc.micro "^1.0.1" + +linkify-it@~1.2.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-1.2.4.tgz#0773526c317c8fd13bd534ee1d180ff88abf881a" + integrity sha1-B3NSbDF8j9E71TTuHRgP+Iq/iBo= + dependencies: + uc.micro "^1.0.1" + +"liquid-fire@^0.29.5 || ^0.30.0 || ^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/liquid-fire/-/liquid-fire-0.31.0.tgz#6dc9f4785b5a06dcbe1a7ca4e8b130ac595ee2f5" + integrity sha512-KVI2vBB+6I1kvkOSD/S/Vjq5hYqlFw3zBLiRoCSIDj9LMWmm2GEKvQcmpxiqgsdjMS2VAFaqUd+9BJFRvCmIjA== + dependencies: + broccoli-funnel "^2.0.2" + broccoli-merge-trees "^3.0.2" + broccoli-stew "^2.1.0" + ember-cli-babel "^7.7.3" + ember-cli-htmlbars "^3.0.1" + ember-cli-version-checker "^3.1.3" + match-media "^0.2.0" + velocity-animate "^1.5.2" + +livereload-js@^3.3.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/livereload-js/-/livereload-js-3.3.2.tgz#c88b009c6e466b15b91faa26fd7c99d620e12651" + integrity sha512-w677WnINxFkuixAoUEXOStewzLYGI76XVag+0JWMMEyjJQKs0ibWZMxkTlB96Lm3EjZ7IeOxVziBEbtxVQqQZA== + +load-bmfont@^1.2.3, load-bmfont@^1.3.1, load-bmfont@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/load-bmfont/-/load-bmfont-1.4.0.tgz#75f17070b14a8c785fe7f5bee2e6fd4f98093b6b" + integrity sha512-kT63aTAlNhZARowaNYcY29Fn/QYkc52M3l6V1ifRcPewg2lvUZDAj7R6dXjOL9D0sict76op3T5+odumDSF81g== + dependencies: + buffer-equal "0.0.1" + mime "^1.3.4" + parse-bmfont-ascii "^1.0.3" + parse-bmfont-binary "^1.0.5" + parse-bmfont-xml "^1.1.4" + phin "^2.9.1" + xhr "^2.0.1" + xtend "^4.0.0" + +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +load-json-file@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" + integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= + dependencies: + graceful-fs "^4.1.2" + parse-json "^4.0.0" + pify "^3.0.0" + strip-bom "^3.0.0" + +loader-runner@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" + integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== + +loader-utils@^1.2.3, loader-utils@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" + integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^1.0.1" + +loader.js@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/loader.js/-/loader.js-4.7.0.tgz#a1a52902001c83631efde9688b8ab3799325ef1f" + integrity sha512-9M2KvGT6duzGMgkOcTkWb+PR/Q2Oe54df/tLgHGVmFpAmtqJ553xJh6N63iFYI2yjo2PeJXbS5skHi/QpJq4vA== + +locate-character@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/locate-character/-/locate-character-2.0.5.tgz#f2d2614d49820ecb3c92d80d193b8db755f74c0f" + integrity sha512-n2GmejDXtOPBAZdIiEFy5dJ5N38xBCXLNOtw2WpB9kGh6pnrEuKlwYI+Tkpofc4wDtVXHtoAOJaMRlYG/oYaxg== + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash-es@^4.17.11: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== + +lodash._baseassign@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" + integrity sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4= + dependencies: + lodash._basecopy "^3.0.0" + lodash.keys "^3.0.0" + +lodash._basecopy@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" + integrity sha1-jaDmqHbPNEwK2KVIghEd08XHyjY= + +lodash._baseflatten@^3.0.0: + version "3.1.4" + resolved "https://registry.yarnpkg.com/lodash._baseflatten/-/lodash._baseflatten-3.1.4.tgz#0770ff80131af6e34f3b511796a7ba5214e65ff7" + integrity sha1-B3D/gBMa9uNPO1EXlqe6UhTmX/c= + dependencies: + lodash.isarguments "^3.0.0" + lodash.isarray "^3.0.0" + +lodash._bindcallback@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e" + integrity sha1-5THCdkTPi1epnhftlbNcdIeJOS4= + +lodash._createassigner@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz#838a5bae2fdaca63ac22dee8e19fa4e6d6970b11" + integrity sha1-g4pbri/aymOsIt7o4Z+k5taXCxE= + dependencies: + lodash._bindcallback "^3.0.0" + lodash._isiterateecall "^3.0.0" + lodash.restparam "^3.0.0" + +lodash._getnative@^3.0.0: + version "3.9.1" + resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= + +lodash._isiterateecall@^3.0.0: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" + integrity sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw= + +lodash._reinterpolate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" + integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= + +lodash.assign@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-3.2.0.tgz#3ce9f0234b4b2223e296b8fa0ac1fee8ebca64fa" + integrity sha1-POnwI0tLIiPilrj6CsH+6OvKZPo= + dependencies: + lodash._baseassign "^3.0.0" + lodash._createassigner "^3.0.0" + lodash.keys "^3.0.0" + +lodash.assign@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" + integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= + +lodash.assignin@^4.0.9, lodash.assignin@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2" + integrity sha1-uo31+4QesKPoBEIysOJjqNxqKKI= + +lodash.bind@^4.1.4: + version "4.2.1" + resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35" + integrity sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU= + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= + +lodash.castarray@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.castarray/-/lodash.castarray-4.4.0.tgz#c02513515e309daddd4c24c60cfddcf5976d9115" + integrity sha1-wCUTUV4wna3dTCTGDP3c9ZdtkRU= + +lodash.clonedeep@^4.4.1, lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= + +lodash.compact@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash.compact/-/lodash.compact-3.0.1.tgz#540ce3837745975807471e16b4a2ba21e7256ca5" + integrity sha1-VAzjg3dFl1gHRx4WtKK6IeclbKU= + +lodash.debounce@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-3.1.1.tgz#812211c378a94cc29d5aa4e3346cf0bfce3a7df5" + integrity sha1-gSIRw3ipTMKdWqTjNGzwv846ffU= + dependencies: + lodash._getnative "^3.0.0" + +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= + +lodash.defaults@^4.0.1, lodash.defaults@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" + integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw= + +lodash.defaultsdeep@^4.6.0, lodash.defaultsdeep@^4.6.1: + version "4.6.1" + resolved "https://registry.yarnpkg.com/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz#512e9bd721d272d94e3d3a63653fa17516741ca6" + integrity sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA== + +lodash.filter@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace" + integrity sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4= + +lodash.find@^4.5.1, lodash.find@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.find/-/lodash.find-4.6.0.tgz#cb0704d47ab71789ffa0de8b97dd926fb88b13b1" + integrity sha1-ywcE1Hq3F4n/oN6Ll92Sb7iLE7E= + +lodash.flatten@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-3.0.2.tgz#de1cf57758f8f4479319d35c3e9cc60c4501938c" + integrity sha1-3hz1d1j49EeTGdNcPpzGDEUBk4w= + dependencies: + lodash._baseflatten "^3.0.0" + lodash._isiterateecall "^3.0.0" + +lodash.flatten@^4.2.0, lodash.flatten@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" + integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8= + +lodash.foreach@^4.3.0, lodash.foreach@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" + integrity sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM= + +lodash.forin@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.forin/-/lodash.forin-4.4.0.tgz#5d3f20ae564011fbe88381f7d98949c9c9519731" + integrity sha1-XT8grlZAEfvog4H32YlJyclRlzE= + +lodash.get@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= + +lodash.has@^4.5.2: + version "4.5.2" + resolved "https://registry.yarnpkg.com/lodash.has/-/lodash.has-4.5.2.tgz#d19f4dc1095058cccbe2b0cdf4ee0fe4aa37c862" + integrity sha1-0Z9NwQlQWMzL4rDN9O4P5Ko3yGI= + +lodash.invokemap@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.invokemap/-/lodash.invokemap-4.6.0.tgz#1748cda5d8b0ef8369c4eb3ec54c21feba1f2d62" + integrity sha1-F0jNpdiw74NpxOs+xUwh/rofLWI= + +lodash.isarguments@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo= + +lodash.isarray@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" + integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U= + +lodash.isempty@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.isempty/-/lodash.isempty-4.4.0.tgz#6f86cbedd8be4ec987be9aaf33c9684db1b31e7e" + integrity sha1-b4bL7di+TsmHvpqvM8loTbGzHn4= + +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= + +lodash.isfunction@^3.0.9: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz#06de25df4db327ac931981d1bdb067e5af68d051" + integrity sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw== + +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M= + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= + +lodash.kebabcase@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36" + integrity sha1-hImxyw0p/4gZXM7KRI/21swpXDY= + +lodash.keys@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" + integrity sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo= + dependencies: + lodash._getnative "^3.0.0" + lodash.isarguments "^3.0.0" + lodash.isarray "^3.0.0" + +lodash.lowerfirst@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/lodash.lowerfirst/-/lodash.lowerfirst-4.3.1.tgz#de3c7b12e02c6524a0059c2f6cb7c5c52655a13d" + integrity sha1-3jx7EuAsZSSgBZwvbLfFxSZVoT0= + +lodash.map@^4.4.0, lodash.map@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" + integrity sha1-dx7Hg540c9nEzeKLGTlMNWL09tM= + +lodash.mapvalues@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz#1bafa5005de9dd6f4f26668c30ca37230cc9689c" + integrity sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw= + +lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= + +lodash.merge@^4.4.0, lodash.merge@^4.6.0, lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.omit@^4.1.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.omit/-/lodash.omit-4.5.0.tgz#6eb19ae5a1ee1dd9df0b969e66ce0b7fa30b5e60" + integrity sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA= + +lodash.pick@^4.2.1, lodash.pick@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" + integrity sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM= + +lodash.reduce@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.reduce/-/lodash.reduce-4.6.0.tgz#f1ab6b839299ad48f784abbf476596f03b914d3b" + integrity sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs= + +lodash.reject@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415" + integrity sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU= + +lodash.restparam@^3.0.0: + version "3.6.1" + resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" + integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU= + +lodash.snakecase@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d" + integrity sha1-OdcUo1NXFHg3rv1ktdy7Fr7Nj40= + +lodash.some@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" + integrity sha1-G7nzFO9ri63tE7VJFpsqlF62jk0= + +lodash.template@^4.4.0, lodash.template@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" + integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== + dependencies: + lodash._reinterpolate "^3.0.0" + lodash.templatesettings "^4.0.0" + +lodash.templatesettings@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" + integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== + dependencies: + lodash._reinterpolate "^3.0.0" + +lodash.toarray@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561" + integrity sha1-JMS/zWsvuji/0FlNsRedjptlZWE= + +lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM= + +lodash.uniq@^4.2.0, lodash.uniq@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= + +lodash.uniqby@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302" + integrity sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI= + +lodash.values@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-4.3.0.tgz#a3a6c2b0ebecc5c2cba1c17e6e620fe81b53d347" + integrity sha1-o6bCsOvsxcLLocF+bmIP6BtT00c= + +lodash@^4.0.0, lodash@^4.1.0, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== + dependencies: + chalk "^2.0.1" + +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +loose-envify@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lower-case@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.1.tgz#39eeb36e396115cc05e29422eaea9e692c9408c7" + integrity sha512-LiWgfDLLb1dwbFQZsSglpRj+1ctGnayXz3Uv0/WO8n558JycT5fg6zkNcnW0G68Nn0aEldTFeEfmjCfmqry/rQ== + dependencies: + tslib "^1.10.0" + +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + +lru-cache@^4.0.1: + version "4.1.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +lunr@^2.3.7: + version "2.3.8" + resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.8.tgz#a8b89c31f30b5a044b97d2d28e2da191b6ba2072" + integrity sha512-oxMeX/Y35PNFuZoHp+jUj5OSEmLCaIH4KTFJh7a93cHBoFmpw2IoPs22VIz7vyO2YUnx2Tn9dzIwO2P/4quIRg== + +magic-string@^0.24.0: + version "0.24.1" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.24.1.tgz#7e38e5f126cae9f15e71f0cf8e450818ca7d5a8f" + integrity sha512-YBfNxbJiixMzxW40XqJEIldzHyh5f7CZKalo1uZffevyrPEX8Qgo9s0dmcORLHdV47UyvJg8/zD+6hQG3qvJrA== + dependencies: + sourcemap-codec "^1.4.1" + +magic-string@^0.25.7: + version "0.25.7" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" + integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== + dependencies: + sourcemap-codec "^1.4.4" + +make-dir@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +makeerror@1.0.x: + version "1.0.11" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" + integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw= + dependencies: + tmpl "1.0.x" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + +markdown-it-terminal@0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/markdown-it-terminal/-/markdown-it-terminal-0.2.1.tgz#670fd5ea824a7dcaa1591dcbeef28bf70aff1705" + integrity sha512-e8hbK9L+IyFac2qY05R7paP+Fqw1T4pSQW3miK3VeG9QmpqBjg5Qzjv/v6C7YNxSNRS2Kp8hUFtm5lWU9eK4lw== + dependencies: + ansi-styles "^3.0.0" + cardinal "^1.0.0" + cli-table "^0.3.1" + lodash.merge "^4.6.2" + markdown-it "^8.3.1" + +markdown-it@^12.0.4: + version "12.3.0" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.3.0.tgz#11490c61b412b8f41530319c005ecdcd4367171f" + integrity sha512-T345UZZ6ejQWTjG6PSEHplzNy5m4kF6zvUpHVDv8Snl/pEU0OxIK0jGg8YLVNwJvT8E0YJC7/2UvssJDk/wQCQ== + dependencies: + argparse "^2.0.1" + entities "~2.1.0" + linkify-it "^3.0.1" + mdurl "^1.0.1" + uc.micro "^1.0.5" + +markdown-it@^4.3.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-4.4.0.tgz#3df373dbea587a9a7fef3e56311b68908f75c414" + integrity sha1-PfNz2+pYepp/7z5WMRtokI91xBQ= + dependencies: + argparse "~1.0.2" + entities "~1.1.1" + linkify-it "~1.2.0" + mdurl "~1.0.0" + uc.micro "^1.0.0" + +markdown-it@^8.3.1: + version "8.4.2" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.2.tgz#386f98998dc15a37722aa7722084f4020bdd9b54" + integrity sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ== + dependencies: + argparse "^1.0.7" + entities "~1.1.1" + linkify-it "^2.0.0" + mdurl "^1.0.1" + uc.micro "^1.0.5" + +marked@0.3.6: + version "0.3.6" + resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.6.tgz#b2c6c618fccece4ef86c4fc6cb8a7cbf5aeda8d7" + integrity sha1-ssbGGPzOzk74bE/Gy4p8v1rtqNc= + +marked@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/marked/-/marked-0.8.2.tgz#4faad28d26ede351a7a1aaa5fec67915c869e355" + integrity sha512-EGwzEeCcLniFX51DhTpmTom+dSA/MG/OBUDjnWtHbEnjAH180VzUeAw+oE4+Zv+CoYBWyRlYOTR0N8SO9R1PVw== + +match-media@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/match-media/-/match-media-0.2.0.tgz#ea4e09742e7253cc7d7e1599ba627e0fa29fbc50" + integrity sha1-6k4JdC5yU8x9fhWZumJ+D6KfvFA= + +matcher-collection@^1.0.0, matcher-collection@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/matcher-collection/-/matcher-collection-1.1.2.tgz#1076f506f10ca85897b53d14ef54f90a5c426838" + integrity sha512-YQ/teqaOIIfUHedRam08PB3NK7Mjct6BvzRnJmpGDm8uFXpNr1sbY4yuflI5JcEs6COpYA0FpRQhSDBf1tT95g== + dependencies: + minimatch "^3.0.2" + +matcher-collection@^2.0.0, matcher-collection@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/matcher-collection/-/matcher-collection-2.0.1.tgz#90be1a4cf58d6f2949864f65bb3b0f3e41303b29" + integrity sha512-daE62nS2ZQsDg9raM0IlZzLmI2u+7ZapXBwdoeBUKAYERPDDIc0qNqA8E0Rp2D+gspKR7BgIFP52GeujaGXWeQ== + dependencies: + "@types/minimatch" "^3.0.3" + minimatch "^3.0.2" + +md5-hex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-2.0.0.tgz#d0588e9f1c74954492ecd24ac0ac6ce997d92e33" + integrity sha1-0FiOnxx0lUSS7NJKwKxs6ZfZLjM= + dependencies: + md5-o-matic "^0.1.1" + +md5-o-matic@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/md5-o-matic/-/md5-o-matic-0.1.1.tgz#822bccd65e117c514fab176b25945d54100a03c3" + integrity sha1-givM1l4RfFFPqxdrJZRdVBAKA8M= + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +mdn-data@2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" + integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== + +mdn-data@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" + integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== + +mdn-data@~1.1.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01" + integrity sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA== + +mdn-links@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/mdn-links/-/mdn-links-0.1.0.tgz#e24c83b97cb4c5886cc39f2f780705fbfe273aa5" + integrity sha1-4kyDuXy0xYhsw58veAcF+/4nOqU= + +mdurl@^1.0.1, mdurl@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + +memory-fs@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +memory-fs@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" + integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +memory-streams@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/memory-streams/-/memory-streams-0.1.3.tgz#d9b0017b4b87f1d92f55f2745c9caacb1dc93ceb" + integrity sha512-qVQ/CjkMyMInPaaRMrwWNDvf6boRZXaT/DbQeMYcCWuXPEBf1v8qChOc9OlEVQp2uOvRXa1Qu30fLmKhY6NipA== + dependencies: + readable-stream "~1.0.2" + +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge-trees@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-trees/-/merge-trees-1.0.1.tgz#ccbe674569787f9def17fd46e6525f5700bbd23e" + integrity sha1-zL5nRWl4f53vF/1G5lJfVwC70j4= + dependencies: + can-symlink "^1.0.0" + fs-tree-diff "^0.5.4" + heimdalljs "^0.2.1" + heimdalljs-logger "^0.1.7" + rimraf "^2.4.3" + symlink-or-copy "^1.0.0" + +merge-trees@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-trees/-/merge-trees-2.0.0.tgz#a560d796e566c5d9b2c40472a2967cca48d85161" + integrity sha512-5xBbmqYBalWqmhYm51XlohhkmVOua3VAUrrWh8t9iOkaLpS6ifqm/UVuUjQCeDVJ9Vx3g2l6ihfkbLSTeKsHbw== + dependencies: + fs-updater "^1.0.4" + heimdalljs "^0.2.5" + +merge2@^1.2.3, merge2@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" + integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== + +merge@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/merge/-/merge-2.1.1.tgz#59ef4bf7e0b3e879186436e8481c06a6c162ca98" + integrity sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w== + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= + +micromatch@^3.1.10, micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +micromatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + +micromatch@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" + integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== + dependencies: + braces "^3.0.1" + picomatch "^2.2.3" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@1.43.0, "mime-db@>= 1.43.0 < 2": + version "1.43.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58" + integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ== + +mime-db@1.45.0: + version "1.45.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" + integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== + +mime-db@1.51.0: + version "1.51.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" + integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== + +mime-types@^2.1.12, mime-types@^2.1.18, mime-types@~2.1.19: + version "2.1.26" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06" + integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ== + dependencies: + mime-db "1.43.0" + +mime-types@^2.1.26: + version "2.1.34" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" + integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== + dependencies: + mime-db "1.51.0" + +mime-types@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-1.0.2.tgz#995ae1392ab8affcbfcb2641dd054e943c0d5dce" + integrity sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4= + +mime-types@~2.1.24: + version "2.1.28" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd" + integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ== + dependencies: + mime-db "1.45.0" + +mime@1.6.0, mime@^1.3.4: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mime@~1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.2.11.tgz#58203eed86e3a5ef17aed2b7d9ebd47f0a60dd10" + integrity sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA= + +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +min-document@^2.19.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" + integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= + dependencies: + dom-walk "^0.1.0" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + +"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +minimist@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= + +minimist@>=1.2.5, minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + +minimist@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.2.1.tgz#827ba4e7593464e7c221e8c5bed930904ee2c455" + integrity sha512-GY8fANSrTMfBVfInqJAY41QkOM+upUTytK1jZ0c8+3HdHrJxBJ3rF5i9moClXTE8uUSnUo8cAsCoxDXvSY4DHg== + +minipass@^2.2.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +miragejs@^0.1.43: + version "0.1.43" + resolved "https://registry.yarnpkg.com/miragejs/-/miragejs-0.1.43.tgz#47a8546b9e3489f806073e681f380ccfe13d757d" + integrity sha512-BhkyxssOZ2i4JqRjWpRnUQu9AFAKHyft8dJbqsg/N64+gCn2vw6vRteMpTKXllLjCPOA9Os8PhGRVXlXs4Ojhw== + dependencies: + "@miragejs/pretender-node-polyfill" "^0.1.0" + inflected "^2.0.4" + lodash.assign "^4.2.0" + lodash.camelcase "^4.3.0" + lodash.clonedeep "^4.5.0" + lodash.compact "^3.0.1" + lodash.find "^4.6.0" + lodash.flatten "^4.4.0" + lodash.forin "^4.4.0" + lodash.get "^4.4.2" + lodash.has "^4.5.2" + lodash.invokemap "^4.6.0" + lodash.isempty "^4.4.0" + lodash.isequal "^4.5.0" + lodash.isfunction "^3.0.9" + lodash.isinteger "^4.0.4" + lodash.isplainobject "^4.0.6" + lodash.lowerfirst "^4.3.1" + lodash.map "^4.6.0" + lodash.mapvalues "^4.6.0" + lodash.pick "^4.4.0" + lodash.snakecase "^4.1.1" + lodash.uniq "^4.5.0" + lodash.uniqby "^4.7.0" + lodash.values "^4.3.0" + pretender "^3.4.7" + +mississippi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" + integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== + dependencies: + concat-stream "^1.5.0" + duplexify "^3.4.2" + end-of-stream "^1.1.0" + flush-write-stream "^1.0.0" + from2 "^2.1.0" + parallel-transform "^1.1.0" + pump "^3.0.0" + pumpify "^1.3.3" + stream-each "^1.1.0" + through2 "^2.0.0" + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp@0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + dependencies: + minimist "0.0.8" + +mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.4, mkdirp@~0.5.1: + version "0.5.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.4.tgz#fd01504a6797ec5c9be81ff43d204961ed64a512" + integrity sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw== + dependencies: + minimist "^1.2.5" + +mkdirp@^0.5.5: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + dependencies: + minimist "^1.2.5" + +mkdirp@^1.0.3, mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +mktemp@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/mktemp/-/mktemp-0.4.0.tgz#6d0515611c8a8c84e484aa2000129b98e981ff0b" + integrity sha1-bQUVYRyKjITkhKogABKbmOmB/ws= + +moment-timezone@^0.5.13: + version "0.5.28" + resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.28.tgz#f093d789d091ed7b055d82aa81a82467f72e4338" + integrity sha512-TDJkZvAyKIVWg5EtVqRzU97w0Rb0YVbfpqyjgu6GwXCAohVRqwZjf4fOzDE6p1Ch98Sro/8hQQi65WDXW5STPw== + dependencies: + moment ">= 2.9.0" + +moment-timezone@^0.5.33: + version "0.5.34" + resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.34.tgz#a75938f7476b88f155d3504a9343f7519d9a405c" + integrity sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg== + dependencies: + moment ">= 2.9.0" + +"moment@>= 2.9.0", moment@^2.19.3: + version "2.26.0" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.26.0.tgz#5e1f82c6bafca6e83e808b30c8705eed0dcbd39a" + integrity sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw== + +moment@^2.29.1: + version "2.29.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" + integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== + +morgan@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7" + integrity sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ== + dependencies: + basic-auth "~2.0.1" + debug "2.6.9" + depd "~2.0.0" + on-finished "~2.3.0" + on-headers "~1.0.2" + +mout@^1.0.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/mout/-/mout-1.2.2.tgz#c9b718a499806a0632cede178e80f436259e777d" + integrity sha512-w0OUxFEla6z3d7sVpMZGBCpQvYh8PHS1wZ6Wu9GNKHMpAHWJ0if0LsQZh3DlOqw55HlhJEOMLpFnwtxp99Y5GA== + +move-concurrently@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" + integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I= + dependencies: + aproba "^1.1.1" + copy-concurrently "^1.0.0" + fs-write-stream-atomic "^1.0.8" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.3" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +mustache@^3.0.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/mustache/-/mustache-3.2.1.tgz#89e78a9d207d78f2799b1e95764a25bf71a28322" + integrity sha512-RERvMFdLpaFfSRIEe632yDm5nsd0SDKn8hGmcUwswnyiE5mtdZLDybtHAz6hjJhawokF0hXvGLtx9mrQfm6FkA== + +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= + +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + +nan@^2.12.1: + version "2.14.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" + integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== + +nanoid@^3.1.30: + version "3.1.30" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.30.tgz#63f93cc548d2a113dc5dfbc63bfa09e2b9b64362" + integrity sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +negotiator@0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" + integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== + +neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +no-case@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.3.tgz#c21b434c1ffe48b39087e86cfb4d2582e9df18f8" + integrity sha512-ehY/mVQCf9BL0gKfsJBvFJen+1V//U+0HQMPrWct40ixE4jnv0bfvxDbWtAHL9EcaPEOJHVVYKoQn1TlZUB8Tw== + dependencies: + lower-case "^2.0.1" + tslib "^1.10.0" + +node-emoji@^1.8.1: + version "1.10.0" + resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.10.0.tgz#8886abd25d9c7bb61802a658523d1f8d2a89b2da" + integrity sha512-Yt3384If5H6BYGVHiHwTL+99OzJKHhgp82S8/dktEK73T26BazdgZ4JZh92xSVtGNJvz9UbXdNAc5hcrXV42vw== + dependencies: + lodash.toarray "^4.4.0" + +node-fetch@^2.6.0: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + +node-fetch@^2.6.1: + version "2.6.6" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.6.tgz#1751a7c01834e8e1697758732e9efb6eeadfaf89" + integrity sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA== + dependencies: + whatwg-url "^5.0.0" + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= + +node-libs-browser@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" + integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== + dependencies: + assert "^1.1.1" + browserify-zlib "^0.2.0" + buffer "^4.3.0" + console-browserify "^1.1.0" + constants-browserify "^1.0.0" + crypto-browserify "^3.11.0" + domain-browser "^1.1.1" + events "^3.0.0" + https-browserify "^1.0.0" + os-browserify "^0.3.0" + path-browserify "0.0.1" + process "^0.11.10" + punycode "^1.2.4" + querystring-es3 "^0.2.0" + readable-stream "^2.3.3" + stream-browserify "^2.0.1" + stream-http "^2.7.2" + string_decoder "^1.0.0" + timers-browserify "^2.0.4" + tty-browserify "0.0.0" + url "^0.11.0" + util "^0.11.0" + vm-browserify "^1.0.1" + +node-modules-path@^1.0.0, node-modules-path@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/node-modules-path/-/node-modules-path-1.0.2.tgz#e3acede9b7baf4bc336e3496b58e5b40d517056e" + integrity sha512-6Gbjq+d7uhkO7epaKi5DNgUJn7H0gEyA4Jg0Mo1uQOi3Rk50G83LtmhhFyw0LxnAFhtlspkiiw52ISP13qzcBg== + +node-notifier@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-9.0.1.tgz#cea837f4c5e733936c7b9005e6545cea825d1af4" + integrity sha512-fPNFIp2hF/Dq7qLDzSg4vZ0J4e9v60gJR+Qx7RbjbWqzPDdEqeVpEx5CFeDAELIl+A/woaaNn1fQ5nEVerMxJg== + dependencies: + growly "^1.3.0" + is-wsl "^2.2.0" + semver "^7.3.2" + shellwords "^0.1.1" + uuid "^8.3.0" + which "^2.0.2" + +node-releases@^1.1.52: + version "1.1.52" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.52.tgz#bcffee3e0a758e92e44ecfaecd0a47554b0bcba9" + integrity sha512-snSiT1UypkgGt2wxPqS6ImEUICbNCMb31yaxWrOLXjhlt2z2/IBpaOxzONExqSm4y5oLnAqjjRWu+wsDzK5yNQ== + dependencies: + semver "^6.3.0" + +node-releases@^1.1.53: + version "1.1.58" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.58.tgz#8ee20eef30fa60e52755fcc0942def5a734fe935" + integrity sha512-NxBudgVKiRh/2aPWMgPR7bPTX0VPmGx5QBwCtdHitnqFE5/O8DeBXuIMH1nwNnw/aMo6AjOrpsHzfY3UbUJ7yg== + +node-releases@^1.1.70: + version "1.1.71" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.71.tgz#cb1334b179896b1c89ecfdd4b725fb7bbdfc7dbb" + integrity sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg== + +node-releases@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5" + integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA== + +node-uuid@~1.4.0: + version "1.4.8" + resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.8.tgz#b040eb0923968afabf8d32fb1f17f1167fdab907" + integrity sha1-sEDrCSOWivq/jTL7HxfxFn/auQc= + +node-watch@0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/node-watch/-/node-watch-0.7.2.tgz#545f057da8500487eb8287adcb4cb5a7338d7e21" + integrity sha512-g53VjSARRv1JdST0LZRIg8RiuLr1TaBbVPsVvxh0/0Ymvi0xYUjDuoqQQAWtHJQUXhiShowPT/aXKNeHBcyQsw== + +nopt@^3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= + dependencies: + abbrev "1" + +normalize-package-data@^2.3.2: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= + +normalize-url@^4.1.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" + integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== + +normalize.css@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/normalize.css/-/normalize.css-8.0.1.tgz#9b98a208738b9cc2634caacbc42d131c97487bf3" + integrity sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg== + +npm-git-info@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/npm-git-info/-/npm-git-info-1.0.3.tgz#a933c42ec321e80d3646e0d6e844afe94630e1d5" + integrity sha1-qTPELsMh6A02RuDW6ESv6UYw4dU= + +npm-package-arg@^8.1.1: + version "8.1.5" + resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-8.1.5.tgz#3369b2d5fe8fdc674baa7f1786514ddc15466e44" + integrity sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q== + dependencies: + hosted-git-info "^4.0.1" + semver "^7.3.4" + validate-npm-package-name "^3.0.0" + +npm-run-all@^4.1.5: + version "4.1.5" + resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba" + integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ== + dependencies: + ansi-styles "^3.2.1" + chalk "^2.4.1" + cross-spawn "^6.0.5" + memorystream "^0.3.1" + minimatch "^3.0.4" + pidtree "^0.3.0" + read-pkg "^3.0.0" + shell-quote "^1.6.1" + string.prototype.padend "^3.0.0" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= + dependencies: + path-key "^2.0.0" + +npm-run-path@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-3.1.0.tgz#7f91be317f6a466efed3c9f2980ad8a4ee8b0fa5" + integrity sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg== + dependencies: + path-key "^3.0.0" + +npm-run-path@^4.0.0, npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +npmlog@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +nth-check@^1.0.2, nth-check@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" + integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== + dependencies: + boolbase "~1.0.0" + +num2fraction@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" + integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + +"nwmatcher@>= 1.3.7 < 2.0.0": + version "1.4.4" + resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.4.4.tgz#2285631f34a95f0d0395cd900c96ed39b58f346e" + integrity sha512-3iuY4N5dhgMpCUrOVnuAdGrgxVqV2cJpM+XNccjR2DKOB1RUP0aA+wGXEiNziG/UKboFyGBIoKOaNlJxx8bciQ== + +nwsapi@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" + integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== + +oauth-sign@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.3.0.tgz#cb540f93bb2b22a7d5941691a288d60e8ea9386e" + integrity sha1-y1QPk7srIqfVlBaRoojWDo6pOG4= + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-assign@4.1.1, object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-hash@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.3.1.tgz#fde452098a951cb145f039bb7d455449ddc126df" + integrity sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA== + +object-hash@^2.0.3: + version "2.2.0" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5" + integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw== + +object-inspect@^1.11.0, object-inspect@^1.9.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" + integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== + +object-inspect@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" + integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== + +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.assign@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.assign@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" + +object.getownpropertydescriptors@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" + integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + +object.values@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" + integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + function-bind "^1.1.1" + has "^1.0.3" + +omggif@^1.0.9: + version "1.0.10" + resolved "https://registry.yarnpkg.com/omggif/-/omggif-1.0.10.tgz#ddaaf90d4a42f532e9e7cb3a95ecdd47f17c7b19" + integrity sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw== + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= + dependencies: + mimic-fn "^1.0.0" + +onetime@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" + integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + dependencies: + mimic-fn "^2.1.0" + +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +optionator@^0.8.1: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +ora@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/ora/-/ora-3.4.0.tgz#bf0752491059a3ef3ed4c85097531de9fdbcd318" + integrity sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg== + dependencies: + chalk "^2.4.2" + cli-cursor "^2.1.0" + cli-spinners "^2.0.0" + log-symbols "^2.2.0" + strip-ansi "^5.2.0" + wcwidth "^1.0.1" + +ora@^5.4.0: + version "5.4.1" + resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" + integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== + dependencies: + bl "^4.1.0" + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-spinners "^2.5.0" + is-interactive "^1.0.0" + is-unicode-supported "^0.1.0" + log-symbols "^4.1.0" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + +os-browserify@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= + dependencies: + lcid "^1.0.0" + +os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +osenv@^0.1.3: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + +p-defer@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-3.0.0.tgz#d1dceb4ee9b2b604b1d94ffec83760175d4e6f83" + integrity sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw== + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + +p-finally@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-2.0.1.tgz#bd6fcaa9c559a096b680806f4d657b3f0f240561" + integrity sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw== + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-limit@^2.0.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e" + integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +package-json@^6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" + integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== + dependencies: + got "^9.6.0" + registry-auth-token "^4.0.0" + registry-url "^5.0.0" + semver "^6.2.0" + +pad-start@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pad-start/-/pad-start-1.0.2.tgz#23e5bab3e96446b62816cff6f150975f040d1b14" + integrity sha1-I+W6s+lkRrYoFs/28VCXXwQNGxQ= + +pako@^1.0.5, pako@~1.0.5: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== + +parallel-transform@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" + integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg== + dependencies: + cyclist "^1.0.1" + inherits "^2.0.3" + readable-stream "^2.1.5" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-asn1@^5.0.0: + version "5.1.5" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" + integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ== + dependencies: + asn1.js "^4.0.0" + browserify-aes "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" + +parse-bmfont-ascii@^1.0.3: + version "1.0.6" + resolved "https://registry.yarnpkg.com/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz#11ac3c3ff58f7c2020ab22769079108d4dfa0285" + integrity sha1-Eaw8P/WPfCAgqyJ2kHkQjU36AoU= + +parse-bmfont-binary@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz#d038b476d3e9dd9db1e11a0b0e53a22792b69006" + integrity sha1-0Di0dtPp3Z2x4RoLDlOiJ5K2kAY= + +parse-bmfont-xml@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/parse-bmfont-xml/-/parse-bmfont-xml-1.1.4.tgz#015319797e3e12f9e739c4d513872cd2fa35f389" + integrity sha512-bjnliEOmGv3y1aMEfREMBJ9tfL3WR0i0CKPj61DnSLaoxWR3nLrsQrEbCId/8rF4NyRF0cCqisSVXyQYWM+mCQ== + dependencies: + xml-parse-from-string "^1.0.0" + xml2js "^0.4.5" + +parse-git-config@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/parse-git-config/-/parse-git-config-3.0.0.tgz#4a2de08c7b74a2555efa5ae94d40cd44302a6132" + integrity sha512-wXoQGL1D+2COYWCD35/xbiKma1Z15xvZL8cI25wvxzled58V51SJM04Urt/uznS900iQor7QO04SgdfT/XlbuA== + dependencies: + git-config-path "^2.0.0" + ini "^1.3.5" + +parse-headers@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.3.tgz#5e8e7512383d140ba02f0c7aa9f49b4399c92515" + integrity sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA== + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= + dependencies: + error-ex "^1.2.0" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + +parse-ms@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-1.0.1.tgz#56346d4749d78f23430ca0c713850aef91aa361d" + integrity sha1-VjRtR0nXjyNDDKDHE4UK75GqNh0= + +parse-passwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= + +parse-png@^1.0.0, parse-png@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/parse-png/-/parse-png-1.1.2.tgz#f5c2ad7c7993490986020a284c19aee459711ff2" + integrity sha1-9cKtfHmTSQmGAgooTBmu5FlxH/I= + dependencies: + pngjs "^3.2.0" + +parse-static-imports@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/parse-static-imports/-/parse-static-imports-1.1.0.tgz#ae2f18f18da1a993080ae406a5219455c0bbad5d" + integrity sha512-HlxrZcISCblEV0lzXmAHheH/8qEkKgmqkdxyHTPbSqsTUV8GzqmN1L+SSti+VbNPfbBO3bYLPHDiUs2avbAdbA== + +parse5@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== + +parse5@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-1.5.1.tgz#9b7f3b0de32be78dc2401b17573ccaf0f6f59d94" + integrity sha1-m387DeMr543CQBsXVzzK8Pb1nZQ= + +parse5@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c" + integrity sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA== + dependencies: + "@types/node" "*" + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +path-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" + integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= + dependencies: + pinkie-promise "^2.0.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@1.0.1, path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-posix@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/path-posix/-/path-posix-1.0.0.tgz#06b26113f56beab042545a23bfa88003ccac260f" + integrity sha1-BrJhE/Vr6rBCVFojv6iAA8ysJg8= + +path-root-regex@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" + integrity sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0= + +path-root@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7" + integrity sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc= + dependencies: + path-root-regex "^0.1.0" + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +path-type@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" + integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== + dependencies: + pify "^3.0.0" + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +pbkdf2@^3.0.3: + version "3.0.17" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" + integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +phantomjs-prebuilt@^2.1.14: + version "2.1.16" + resolved "https://registry.yarnpkg.com/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz#efd212a4a3966d3647684ea8ba788549be2aefef" + integrity sha1-79ISpKOWbTZHaE6ouniFSb4q7+8= + dependencies: + es6-promise "^4.0.3" + extract-zip "^1.6.5" + fs-extra "^1.0.0" + hasha "^2.2.0" + kew "^0.7.0" + progress "^1.1.8" + request "^2.81.0" + request-progress "^2.0.1" + which "^1.2.10" + +phin@^2.9.1: + version "2.9.3" + resolved "https://registry.yarnpkg.com/phin/-/phin-2.9.3.tgz#f9b6ac10a035636fb65dfc576aaaa17b8743125c" + integrity sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA== + +picocolors@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" + integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== + +picomatch@^2.2.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" + integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== + +pidtree@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.1.tgz#ef09ac2cc0533df1f3250ccf2c4d366b0d12114a" + integrity sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA== + +pify@^2.0.0, pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= + +pixelmatch@^4.0.0, pixelmatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/pixelmatch/-/pixelmatch-4.0.2.tgz#8f47dcec5011b477b67db03c243bc1f3085e8854" + integrity sha1-j0fc7FARtHe2fbA8JDvB8wheiFQ= + dependencies: + pngjs "^3.0.0" + +pkg-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" + integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== + dependencies: + find-up "^3.0.0" + +pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" + integrity sha1-yBmscoBZpGHKscOImivjxJoATX8= + dependencies: + find-up "^2.1.0" + +pkg-up@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" + integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== + dependencies: + find-up "^3.0.0" + +pn@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" + integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== + +pngjs@^3.0.0, pngjs@^3.2.0, pngjs@^3.3.3: + version "3.4.0" + resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" + integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w== + +portfinder@^1.0.28: + version "1.0.28" + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" + integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== + dependencies: + async "^2.6.2" + debug "^3.1.1" + mkdirp "^0.5.5" + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +postcss-functions@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-functions/-/postcss-functions-3.0.0.tgz#0e94d01444700a481de20de4d55fb2640564250e" + integrity sha1-DpTQFERwCkgd4g3k1V+yZAVkJQ4= + dependencies: + glob "^7.1.2" + object-assign "^4.1.1" + postcss "^6.0.9" + postcss-value-parser "^3.3.0" + +postcss-import@^14.0.0: + version "14.0.2" + resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-14.0.2.tgz#60eff77e6be92e7b67fe469ec797d9424cae1aa1" + integrity sha512-BJ2pVK4KhUyMcqjuKs9RijV5tatNzNa73e/32aBVE/ejYPe37iH+6vAu9WvqUkB5OAYgLHzbSvzHnorybJCm9g== + dependencies: + postcss-value-parser "^4.0.0" + read-cache "^1.0.0" + resolve "^1.1.7" + +postcss-js@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-2.0.3.tgz#a96f0f23ff3d08cec7dc5b11bf11c5f8077cdab9" + integrity sha512-zS59pAk3deu6dVHyrGqmC3oDXBdNdajk4k1RyxeVXCrcEDBUBHoIhE4QTsmhxgzXxsaqFDAkUZfmMa5f/N/79w== + dependencies: + camelcase-css "^2.0.1" + postcss "^7.0.18" + +postcss-nested@^4.1.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-4.2.1.tgz#4bc2e5b35e3b1e481ff81e23b700da7f82a8b248" + integrity sha512-AMayXX8tS0HCp4O4lolp4ygj9wBn32DJWXvG6gCv+ZvJrEa00GUxJcJEEzMh87BIe6FrWdYkpR2cuyqHKrxmXw== + dependencies: + postcss "^7.0.21" + postcss-selector-parser "^6.0.2" + +postcss-nested@^5.0.3: + version "5.0.6" + resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-5.0.6.tgz#466343f7fc8d3d46af3e7dba3fcd47d052a945bc" + integrity sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA== + dependencies: + postcss-selector-parser "^6.0.6" + +postcss-scss@^3.0.4: + version "3.0.5" + resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-3.0.5.tgz#bd484faf05890e48a6f5e097acb3d104cc7b9ac7" + integrity sha512-3e0qYk87eczfzg5P73ZVuuxEGCBfatRhPze6KrSaIbEKVtmnFI1RYp1Fv+AyZi+w8kcNRSPeNX6ap4b65zEkiA== + dependencies: + postcss "^8.2.7" + +postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c" + integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg== + dependencies: + cssesc "^3.0.0" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-selector-parser@^6.0.6: + version "6.0.7" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.7.tgz#48404830a635113a71fd79397de8209ed05a66fc" + integrity sha512-U+b/Deoi4I/UmE6KOVPpnhS7I7AYdKbhGcat+qTQ27gycvaACvNEw11ba6RrkwVmDVRW7sigWgLj4/KbbJjeDA== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-value-parser@^3.3.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" + integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== + +postcss-value-parser@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss-value-parser@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz#651ff4593aa9eda8d5d0d66593a2417aeaeb325d" + integrity sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg== + +postcss-value-parser@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" + integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== + +postcss@7.0.32: + version "7.0.32" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d" + integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + +postcss@^6.0.9: + version "6.0.23" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" + integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag== + dependencies: + chalk "^2.4.1" + source-map "^0.6.1" + supports-color "^5.4.0" + +postcss@^7.0.11, postcss@^7.0.18, postcss@^7.0.21, postcss@^7.0.27: + version "7.0.27" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.27.tgz#cc67cdc6b0daa375105b7c424a85567345fc54d9" + integrity sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + +postcss@^7.0.14: + version "7.0.39" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309" + integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA== + dependencies: + picocolors "^0.2.1" + source-map "^0.6.1" + +postcss@^7.0.2, postcss@^7.0.32: + version "7.0.35" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24" + integrity sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + +postcss@^8.1.4, postcss@^8.2.1, postcss@^8.2.7: + version "8.4.4" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.4.tgz#d53d4ec6a75fd62557a66bb41978bf47ff0c2869" + integrity sha512-joU6fBsN6EIer28Lj6GDFoC/5yOZzLCfn0zHAn/MYXI7aPt4m4hK5KC5ovEZXy+lnCjmYIbQWngvju2ddyEr8Q== + dependencies: + nanoid "^3.1.30" + picocolors "^1.0.0" + source-map-js "^1.0.1" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + +pretender@^3.4.7: + version "3.4.7" + resolved "https://registry.yarnpkg.com/pretender/-/pretender-3.4.7.tgz#34a2ae2d1fc9db440a990d50e6c0f5481d8755fc" + integrity sha512-jkPAvt1BfRi0RKamweJdEcnjkeu7Es8yix3bJ+KgBC5VpG/Ln4JE3hYN6vJym4qprm8Xo5adhWpm3HCoft1dOw== + dependencies: + fake-xml-http-request "^2.1.2" + route-recognizer "^0.3.3" + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a" + integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg== + +pretty-hrtime@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" + integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= + +pretty-ms@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-3.2.0.tgz#87a8feaf27fc18414d75441467d411d6e6098a25" + integrity sha512-ZypexbfVUGTFxb0v+m1bUyy92DHe5SyYlnyY0msyms5zd3RwyvNgyxZZsXXgoyzlxjx5MiqtXUdhUfvQbe0A2Q== + dependencies: + parse-ms "^1.0.0" + +printf@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/printf/-/printf-0.6.1.tgz#b9afa3d3b55b7f2e8b1715272479fc756ed88650" + integrity sha512-is0ctgGdPJ5951KulgfzvHGwJtZ5ck8l042vRkV6jrkpBzTmb/lueTqguWHy2JfVA+RY6gFVlaZgUS0j7S/dsw== + +private@^0.1.6, private@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== + +process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process-relative-require@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/process-relative-require/-/process-relative-require-1.0.0.tgz#1590dfcf5b8f2983ba53e398446b68240b4cc68a" + integrity sha1-FZDfz1uPKYO6U+OYRGtoJAtMxoo= + dependencies: + node-modules-path "^1.0.0" + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= + +process@~0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" + integrity sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8= + +progress@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" + integrity sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74= + +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + +promise-inflight@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= + +promise-map-series@^0.2.1: + version "0.2.3" + resolved "https://registry.yarnpkg.com/promise-map-series/-/promise-map-series-0.2.3.tgz#c2d377afc93253f6bd03dbb77755eb88ab20a847" + integrity sha1-wtN3r8kyU/a9A9u3d1XriKsgqEc= + dependencies: + rsvp "^3.0.14" + +promise-map-series@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/promise-map-series/-/promise-map-series-0.3.0.tgz#41873ca3652bb7a042b387d538552da9b576f8a1" + integrity sha512-3npG2NGhTc8BWBolLLf8l/92OxMGaRLbqvIh9wjCHhDXNvk4zsxaTaCpiCunW09qWPrN2zeNSNwRLVBrQQtutA== + +promise.hash.helper@^1.0.7: + version "1.0.8" + resolved "https://registry.yarnpkg.com/promise.hash.helper/-/promise.hash.helper-1.0.8.tgz#8c5fa0570f6f96821f52364fd72292b2c5a114f7" + integrity sha512-KYcnXctWUWyVD3W3Ye0ZDuA1N8Szrh85cVCxpG6xYrOk/0CttRtYCmU30nWsUch0NuExQQ63QXvzRE6FLimZmg== + +proxy-addr@~2.0.5: + version "2.0.6" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" + integrity sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw== + dependencies: + forwarded "~0.1.2" + ipaddr.js "1.9.1" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + +psl@^1.1.28, psl@^1.1.33: + version "1.8.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" + integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + +public-encrypt@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" + +pump@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pumpify@^1.3.3: + version "1.5.1" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" + integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== + dependencies: + duplexify "^3.6.0" + inherits "^2.0.3" + pump "^2.0.0" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= + +punycode@^1.2.4: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + +punycode@^2.1.0, punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +purgecss@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/purgecss/-/purgecss-2.3.0.tgz#5327587abf5795e6541517af8b190a6fb5488bb3" + integrity sha512-BE5CROfVGsx2XIhxGuZAT7rTH9lLeQx/6M0P7DTXQH4IUc3BBzs9JUzt4yzGf3JrH9enkeq6YJBe9CTtkm1WmQ== + dependencies: + commander "^5.0.0" + glob "^7.0.0" + postcss "7.0.32" + postcss-selector-parser "^6.0.2" + +q@^1.1.2: + version "1.5.1" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" + integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= + +qs@6.7.0: + version "6.7.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" + integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== + +qs@^6.4.0: + version "6.9.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.3.tgz#bfadcd296c2d549f1dffa560619132c977f5008e" + integrity sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw== + +qs@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-1.0.2.tgz#50a93e2b5af6691c31bcea5dae78ee6ea1903768" + integrity sha1-UKk+K1r2aRwxvOpdrnjubqGQN2g= + +qs@~6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + +querystring-es3@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= + +quick-temp@^0.1.2, quick-temp@^0.1.3, quick-temp@^0.1.5, quick-temp@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/quick-temp/-/quick-temp-0.1.8.tgz#bab02a242ab8fb0dd758a3c9776b32f9a5d94408" + integrity sha1-urAqJCq4+w3XWKPJd2sy+aXZRAg= + dependencies: + mktemp "~0.4.0" + rimraf "^2.5.4" + underscore.string "~3.3.4" + +qunit-dom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/qunit-dom/-/qunit-dom-2.0.0.tgz#c4d7f7676dbb57f54151b72f8366d862134cd1c0" + integrity sha512-mElzLN99wYPOGekahqRA+mq7NcThXY9c+/tDkgJmT7W5LeZAFNyITr2rFKNnCbWLIhuLdFw88kCBMrJSfyBYpA== + dependencies: + broccoli-funnel "^3.0.3" + broccoli-merge-trees "^4.2.0" + ember-cli-babel "^7.23.0" + ember-cli-version-checker "^5.1.1" + +qunit@^2.17.2: + version "2.17.2" + resolved "https://registry.yarnpkg.com/qunit/-/qunit-2.17.2.tgz#5cb278e131d931f25c109a0fdb0518be7754c25a" + integrity sha512-17isVvuOmALzsPjiV7wFg/6O5vJYXBrQZPwocfQSSh0I/rXvfX7bKMFJ4GMVW3U4P8r2mBeUy8EAngti4QD2Vw== + dependencies: + commander "7.2.0" + node-watch "0.7.2" + tiny-glob "0.2.9" + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" + integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== + dependencies: + bytes "3.1.0" + http-errors "1.7.2" + iconv-lite "0.4.24" + unpipe "1.0.0" + +raw-body@~1.1.0: + version "1.1.7" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-1.1.7.tgz#1d027c2bfa116acc6623bca8f00016572a87d425" + integrity sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU= + dependencies: + bytes "1" + string_decoder "0.10" + +rc@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +read-cache@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" + integrity sha1-5mTvMRYRZsl1HNvo28+GtftY93Q= + dependencies: + pify "^2.3.0" + +read-chunk@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-chunk/-/read-chunk-1.0.1.tgz#5f68cab307e663f19993527d9b589cace4661194" + integrity sha1-X2jKswfmY/GZk1J9m1icrORmEZQ= + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +read-pkg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" + integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= + dependencies: + load-json-file "^4.0.0" + normalize-package-data "^2.3.2" + path-type "^3.0.0" + +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@1.1: + version "1.1.13" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e" + integrity sha1-9u73ZPUUyJ4rniMUanW6EGdW0j4= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +"readable-stream@2 || 3", readable-stream@^3.1.1, readable-stream@^3.4.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@~1.0.2: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readdirp@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== + dependencies: + graceful-fs "^4.1.11" + micromatch "^3.1.10" + readable-stream "^2.0.2" + +readdirp@~3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" + integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== + dependencies: + picomatch "^2.2.1" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +recast@^0.18.1: + version "0.18.7" + resolved "https://registry.yarnpkg.com/recast/-/recast-0.18.7.tgz#56338a6d803c8c3b9113344440dc70d13c8a1ef7" + integrity sha512-qNfoxvMkW4k8jJgNCfmIES7S31MEejXcEQs57eKUcQGiJUuX7cXNOD2h+W9z0rjNun2EkKqf0WvuRtmHw4NPNg== + dependencies: + ast-types "0.13.2" + esprima "~4.0.0" + private "^0.1.8" + source-map "~0.6.1" + +recast@^0.19.1: + version "0.19.1" + resolved "https://registry.yarnpkg.com/recast/-/recast-0.19.1.tgz#555f3612a5a10c9f44b9a923875c51ff775de6c8" + integrity sha512-8FCjrBxjeEU2O6I+2hyHyBFH1siJbMBLwIRvVr1T3FD2cL754sOaJDsJ/8h3xYltasbJ8jqWRIhMuDGBSiSbjw== + dependencies: + ast-types "0.13.3" + esprima "~4.0.0" + private "^0.1.8" + source-map "~0.6.1" + +redeyed@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/redeyed/-/redeyed-1.0.1.tgz#e96c193b40c0816b00aec842698e61185e55498a" + integrity sha1-6WwZO0DAgWsArshCaY5hGF5VSYo= + dependencies: + esprima "~3.0.0" + +reduce-css-calc@^2.1.6: + version "2.1.7" + resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-2.1.7.tgz#1ace2e02c286d78abcd01fd92bfe8097ab0602c2" + integrity sha512-fDnlZ+AybAS3C7Q9xDq5y8A2z+lT63zLbynew/lur/IR24OQF5x98tfNwf79mzEdfywZ0a2wpM860FhFfMxZlA== + dependencies: + css-unit-converter "^1.1.1" + postcss-value-parser "^3.3.0" + +regenerate-unicode-properties@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" + integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== + dependencies: + regenerate "^1.4.0" + +regenerate@^1.2.1, regenerate@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" + integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== + +regenerator-runtime@^0.10.5: + version "0.10.5" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" + integrity sha1-M2w+/BIgrc7dosn6tntaeVWjNlg= + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + +regenerator-runtime@^0.13.2: + version "0.13.9" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" + integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== + +regenerator-runtime@^0.13.4: + version "0.13.5" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" + integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== + +regenerator-transform@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" + integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + +regenerator-transform@^0.14.2: + version "0.14.4" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.4.tgz#5266857896518d1616a78a0479337a30ea974cc7" + integrity sha512-EaJaKPBI9GvKpvUz2mz4fhx7WPgvwRLY9v3hlNHWmAuJHI13T4nwKnNvm5RWJzEdnI5g5UwtOww+S8IdoUC2bw== + dependencies: + "@babel/runtime" "^7.8.4" + private "^0.1.8" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexp.prototype.flags@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz#7ef352ae8d159e758c0eadca6f8fcb4eef07be26" + integrity sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +regexpp@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.0.0.tgz#dd63982ee3300e67b41c1956f850aa680d9d330e" + integrity sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g== + +regexpp@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + integrity sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA= + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +regexpu-core@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.0.tgz#fcbf458c50431b0bb7b45d6967b8192d91f3d938" + integrity sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ== + dependencies: + regenerate "^1.4.0" + regenerate-unicode-properties "^8.2.0" + regjsgen "^0.5.1" + regjsparser "^0.6.4" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.2.0" + +regexpu-core@^4.7.1: + version "4.7.1" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" + integrity sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ== + dependencies: + regenerate "^1.4.0" + regenerate-unicode-properties "^8.2.0" + regjsgen "^0.5.1" + regjsparser "^0.6.4" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.2.0" + +registry-auth-token@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250" + integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw== + dependencies: + rc "^1.2.8" + +registry-url@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" + integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== + dependencies: + rc "^1.2.8" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc= + +regjsgen@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c" + integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg== + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + integrity sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw= + dependencies: + jsesc "~0.5.0" + +regjsparser@^0.6.4: + version "0.6.4" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.4.tgz#a769f8684308401a66e9b529d2436ff4d0666272" + integrity sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw== + dependencies: + jsesc "~0.5.0" + +remote-git-tags@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/remote-git-tags/-/remote-git-tags-3.0.0.tgz#424f8ec2cdea00bb5af1784a49190f25e16983c3" + integrity sha512-C9hAO4eoEsX+OXA4rla66pXZQ+TLQ8T9dttgQj18yuKlPMTVkIkdYXvlMC55IuUsIkV6DpmQYi10JKFLaU+l7w== + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + +repeat-element@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= + dependencies: + is-finite "^1.0.0" + +replace-ext@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" + integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= + +request-progress@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-2.0.1.tgz#5d36bb57961c673aa5b788dbc8141fdf23b44e08" + integrity sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg= + dependencies: + throttleit "^1.0.0" + +request-promise-core@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" + integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw== + dependencies: + lodash "^4.17.19" + +request-promise-native@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28" + integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g== + dependencies: + request-promise-core "1.1.4" + stealthy-require "^1.1.1" + tough-cookie "^2.3.3" + +request@^2.55.0, request@^2.65.0, request@^2.81.0, request@^2.88.2: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +request@~2.40.0: + version "2.40.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.40.0.tgz#4dd670f696f1e6e842e66b4b5e839301ab9beb67" + integrity sha1-TdZw9pbx5uhC5mtLXoOTAaub62c= + dependencies: + forever-agent "~0.5.0" + json-stringify-safe "~5.0.0" + mime-types "~1.0.1" + node-uuid "~1.4.0" + qs "~1.0.0" + optionalDependencies: + aws-sign2 "~0.5.0" + form-data "~0.1.0" + hawk "1.1.1" + http-signature "~0.10.0" + oauth-sign "~0.3.0" + stringstream "~0.0.4" + tough-cookie ">=0.12.0" + tunnel-agent "~0.4.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= + +require-relative@^0.8.7: + version "0.8.7" + resolved "https://registry.yarnpkg.com/require-relative/-/require-relative-0.8.7.tgz#7999539fc9e047a37928fa196f8e1563dabd36de" + integrity sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4= + +requireindex@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/requireindex/-/requireindex-1.2.0.tgz#3463cdb22ee151902635aa6c9535d4de9c2ef1ef" + integrity sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= + +reselect@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/reselect/-/reselect-3.0.1.tgz#efdaa98ea7451324d092b2b2163a6a1d7a9a2147" + integrity sha1-79qpjqdFEyTQkrKyFjpqHXqaIUc= + +reselect@^4.0.0: + version "4.1.5" + resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.5.tgz#852c361247198da6756d07d9296c2b51eddb79f6" + integrity sha512-uVdlz8J7OO+ASpBYoz1Zypgx0KasCY20H+N8JD13oUMtPvSHQuscrHop4KbXrbsBcdB9Ds7lVK7eRkBIfO43vQ== + +resize-img@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/resize-img/-/resize-img-1.1.2.tgz#fad650faf3ef2c53ea63112bc272d95e9d92550e" + integrity sha1-+tZQ+vPvLFPqYxErwnLZXp2SVQ4= + dependencies: + bmp-js "0.0.1" + file-type "^3.8.0" + get-stream "^2.0.0" + jimp "^0.2.21" + jpeg-js "^0.1.1" + parse-png "^1.1.1" + +resolve-dir@^1.0.0, resolve-dir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" + integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= + dependencies: + expand-tilde "^2.0.0" + global-modules "^1.0.0" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-package-path@^1.0.11, resolve-package-path@^1.2.2, resolve-package-path@^1.2.6: + version "1.2.7" + resolved "https://registry.yarnpkg.com/resolve-package-path/-/resolve-package-path-1.2.7.tgz#2a7bc37ad96865e239330e3102c31322847e652e" + integrity sha512-fVEKHGeK85bGbVFuwO9o1aU0n3vqQGrezPc51JGu9UTXpFQfWq5qCeKxyaRUSvephs+06c5j5rPq/dzHGEo8+Q== + dependencies: + path-root "^0.1.1" + resolve "^1.10.0" + +resolve-package-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-package-path/-/resolve-package-path-2.0.0.tgz#7f258ab86ff074fff4ff8027a28f94d17d6fb1df" + integrity sha512-/CLuzodHO2wyyHTzls5Qr+EFeG6RcW4u6//gjYvUfcfyuplIX1SSccU+A5A9A78Gmezkl3NBkFAMxLbzTY9TJA== + dependencies: + path-root "^0.1.1" + resolve "^1.13.1" + +resolve-package-path@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/resolve-package-path/-/resolve-package-path-3.1.0.tgz#35faaa5d54a9c7dd481eb7c4b2a44410c9c763d8" + integrity sha512-2oC2EjWbMJwvSN6Z7DbDfJMnD8MYEouaLn5eIX0j8XwPsYCVIyY9bbnX88YHVkbr8XHqvZrYbxaLPibfTYKZMA== + dependencies: + path-root "^0.1.1" + resolve "^1.17.0" + +resolve-package-path@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/resolve-package-path/-/resolve-package-path-4.0.3.tgz#31dab6897236ea6613c72b83658d88898a9040aa" + integrity sha512-SRpNAPW4kewOaNUt8VPqhJ0UMxawMwzJD8V7m1cJfdSTK9ieZwS6K7Dabsm4bmLFM96Z5Y/UznrpG5kt1im8yA== + dependencies: + path-root "^0.1.1" + +resolve-path@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/resolve-path/-/resolve-path-1.4.0.tgz#c4bda9f5efb2fce65247873ab36bb4d834fe16f7" + integrity sha1-xL2p9e+y/OZSR4c6s2u02DT+Fvc= + dependencies: + http-errors "~1.6.2" + path-is-absolute "1.0.1" + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.11.1, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.15.0, resolve@^1.15.1, resolve@^1.17.0, resolve@^1.20.0, resolve@^1.3.3, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.8.1: + version "1.20.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" + integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== + dependencies: + is-core-module "^2.2.0" + path-parse "^1.0.6" + +responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= + dependencies: + lowercase-keys "^1.0.0" + +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^2.2.8, rimraf@^2.3.4, rimraf@^2.4.1, rimraf@^2.4.3, rimraf@^2.4.4, rimraf@^2.5.3, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +rimraf@^3.0.0, rimraf@^3.0.1, rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +rimraf@~2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +rollup-pluginutils@^2.0.1, rollup-pluginutils@^2.8.1: + version "2.8.2" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e" + integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ== + dependencies: + estree-walker "^0.6.1" + +rollup@^0.57.1: + version "0.57.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.57.1.tgz#0bb28be6151d253f67cf4a00fea48fb823c74027" + integrity sha512-I18GBqP0qJoJC1K1osYjreqA8VAKovxuI3I81RSk0Dmr4TgloI0tAULjZaox8OsJ+n7XRrhH6i0G2By/pj1LCA== + dependencies: + "@types/acorn" "^4.0.3" + acorn "^5.5.3" + acorn-dynamic-import "^3.0.0" + date-time "^2.1.0" + is-reference "^1.1.0" + locate-character "^2.0.5" + pretty-ms "^3.1.0" + require-relative "^0.8.7" + rollup-pluginutils "^2.0.1" + signal-exit "^3.0.2" + sourcemap-codec "^1.4.1" + +rollup@^2.50.0: + version "2.61.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.61.1.tgz#1a5491f84543cf9e4caf6c61222d9a3f8f2ba454" + integrity sha512-BbTXlEvB8d+XFbK/7E5doIcRtxWPRiqr0eb5vQ0+2paMM04Ye4PZY5nHOQef2ix24l/L0SpLd5hwcH15QHPdvA== + optionalDependencies: + fsevents "~2.3.2" + +route-recognizer@^0.3.3: + version "0.3.4" + resolved "https://registry.yarnpkg.com/route-recognizer/-/route-recognizer-0.3.4.tgz#39ab1ffbce1c59e6d2bdca416f0932611e4f3ca3" + integrity sha512-2+MhsfPhvauN1O8KaXpXAOfR/fwe8dnUXVM+xw7yt40lJRfPVQxV6yryZm0cgRvAj5fMF/mdRZbL2ptwbs5i2g== + +rsvp@^3.0.14, rsvp@^3.0.17, rsvp@^3.0.18, rsvp@^3.0.21, rsvp@^3.0.6, rsvp@^3.1.0, rsvp@^3.3.3, rsvp@^3.5.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a" + integrity sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw== + +rsvp@^4.7.0, rsvp@^4.8.1, rsvp@^4.8.2, rsvp@^4.8.3, rsvp@^4.8.4, rsvp@^4.8.5: + version "4.8.5" + resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" + integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== + +rsvp@~3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.2.1.tgz#07cb4a5df25add9e826ebc67dcc9fd89db27d84a" + integrity sha1-B8tKXfJa3Z6Cbrxn3Mn9idsn2Eo= + +run-async@^2.2.0, run-async@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.0.tgz#e59054a5b86876cfae07f431d18cbaddc594f1e8" + integrity sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg== + dependencies: + is-promise "^2.1.0" + +run-parallel@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + +run-queue@^1.0.0, run-queue@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" + integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec= + dependencies: + aproba "^1.1.1" + +rxjs@^6.4.0: + version "6.6.7" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" + integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== + dependencies: + tslib "^1.9.0" + +rxjs@^6.6.0: + version "6.6.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.2.tgz#8096a7ac03f2cc4fe5860ef6e572810d9e01c0d2" + integrity sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg== + dependencies: + tslib "^1.9.0" + +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" + integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== + +safe-json-parse@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/safe-json-parse/-/safe-json-parse-1.0.1.tgz#3e76723e38dfdda13c9b1d29a1e07ffee4b30b57" + integrity sha1-PnZyPjjf3aE8mx0poeB//uSzC1c= + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sane@^4.0.0, sane@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/sane/-/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded" + integrity sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA== + dependencies: + "@cnakazawa/watch" "^1.0.3" + anymatch "^2.0.0" + capture-exit "^2.0.0" + exec-sh "^0.3.2" + execa "^1.0.0" + fb-watchman "^2.0.0" + micromatch "^3.1.4" + minimist "^1.1.1" + walker "~1.0.5" + +sass@^1.16.1: + version "1.45.0" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.45.0.tgz#192ede1908324bb293a3e403d1841dbcaafdd323" + integrity sha512-ONy5bjppoohtNkFJRqdz1gscXamMzN3wQy1YH9qO2FiNpgjLhpz/IPRGg0PpCjyz/pWfCOaNEaiEGCcjOFAjqw== + dependencies: + chokidar ">=3.0.0 <4.0.0" + immutable "^4.0.0" + source-map-js ">=0.6.2 <2.0.0" + +sax@>=0.6.0, sax@^1.1.4, sax@~1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + +saxes@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" + integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== + dependencies: + xmlchars "^2.2.0" + +schema-utils@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" + integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== + dependencies: + ajv "^6.1.0" + ajv-errors "^1.0.0" + ajv-keywords "^3.1.0" + +schema-utils@^2.6.5: + version "2.6.5" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.5.tgz#c758f0a7e624263073d396e29cd40aa101152d8a" + integrity sha512-5KXuwKziQrTVHh8j/Uxz+QUbxkaLW9X/86NBlx/gnKgtsZA2GIVMUn17qWhRFwF8jdYb3Dig5hRO/W5mZqy6SQ== + dependencies: + ajv "^6.12.0" + ajv-keywords "^3.4.1" + +select@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" + integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0= + +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== + +semver@^6.0.0, semver@^6.1.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: + version "7.3.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + dependencies: + lru-cache "^6.0.0" + +send@0.17.1: + version "0.17.1" + resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" + integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== + dependencies: + debug "2.6.9" + depd "~1.1.2" + destroy "~1.0.4" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "~1.7.2" + mime "1.6.0" + ms "2.1.1" + on-finished "~2.3.0" + range-parser "~1.2.1" + statuses "~1.5.0" + +serialize-javascript@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" + integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== + dependencies: + randombytes "^2.1.0" + +serve-static@1.14.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" + integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.17.1" + +set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setimmediate@^1.0.4, setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + +setprototypeof@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" + integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shell-quote@^1.6.1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" + integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw== + +shellwords@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" + integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= + +signal-exit@^3.0.3: + version "3.0.6" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" + integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== + +silent-error@^1.0.0, silent-error@^1.0.1, silent-error@^1.1.0, silent-error@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/silent-error/-/silent-error-1.1.1.tgz#f72af5b0d73682a2ba1778b7e32cd8aa7c2d8662" + integrity sha512-n4iEKyNcg4v6/jpb3c0/iyH2G1nzUNl7Gpqtn/mHIJK9S/q/7MCfoO4rwVOoO59qPFIc0hVHvMbiOJ0NdtxKKw== + dependencies: + debug "^2.2.0" + +simple-dom@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/simple-dom/-/simple-dom-1.4.0.tgz#78ad1f41b8b70d16f82b7e0d458441c9262565b7" + integrity sha512-TnBPkmOyjdaOqyBMb4ick+n8c0Xv9Iwg1PykFV7hz9Se3UCiacTbRb+25cPmvozFNJLBUNvUzX/KsPfXF14ivA== + dependencies: + "@simple-dom/document" "^1.4.0" + "@simple-dom/interface" "^1.4.0" + "@simple-dom/parser" "^1.4.0" + "@simple-dom/serializer" "^1.4.0" + "@simple-dom/void-map" "^1.4.0" + +simple-html-tokenizer@^0.5.10: + version "0.5.11" + resolved "https://registry.yarnpkg.com/simple-html-tokenizer/-/simple-html-tokenizer-0.5.11.tgz#4c5186083c164ba22a7b477b7687ac056ad6b1d9" + integrity sha512-C2WEK/Z3HoSFbYq8tI7ni3eOo/NneSPRoPpcM7WdLjFOArFuyXEjAoCdOC3DgMfRyziZQ1hCNR4mrNdWEvD0og== + +simple-html-tokenizer@^0.5.8: + version "0.5.9" + resolved "https://registry.yarnpkg.com/simple-html-tokenizer/-/simple-html-tokenizer-0.5.9.tgz#1a83fe97f5a3e39b335fddf71cfe9b0263b581c2" + integrity sha512-w/3FEDN94r4JQ9WoYrIr8RqDIPZdyNkdpbK9glFady1CAEyD97XWCv8HFetQO21w81e7h7Nh59iYTyG1mUJftg== + +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= + dependencies: + is-arrayish "^0.3.1" + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +snake-case@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.3.tgz#c598b822ab443fcbb145ae8a82c5e43526d5bbee" + integrity sha512-WM1sIXEO+rsAHBKjGf/6R1HBBcgbncKS08d2Aqec/mrDSpU80SiOU41hO7ny6DToHSyrlwTYzQBIK1FPSx4Y3Q== + dependencies: + dot-case "^3.0.3" + tslib "^1.10.0" + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +sntp@0.2.x: + version "0.2.4" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-0.2.4.tgz#fb885f18b0f3aad189f824862536bceeec750900" + integrity sha1-+4hfGLDzqtGJ+CSGJTa87ux1CQA= + dependencies: + hoek "0.9.x" + +socket.io-adapter@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz#4d6111e4d42e9f7646e365b4f578269821f13486" + integrity sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ== + +socket.io-parser@~4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.0.4.tgz#9ea21b0d61508d18196ef04a2c6b9ab630f4c2b0" + integrity sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g== + dependencies: + "@types/component-emitter" "^1.2.10" + component-emitter "~1.3.0" + debug "~4.3.1" + +socket.io@^4.1.2: + version "4.4.0" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.4.0.tgz#8140a0db2c22235f88a6dceb867e4d5c9bd70507" + integrity sha512-bnpJxswR9ov0Bw6ilhCvO38/1WPtE3eA2dtxi2Iq4/sFebiDJQzgKNYA7AuVVdGW09nrESXd90NbZqtDd9dzRQ== + dependencies: + accepts "~1.3.4" + base64id "~2.0.0" + debug "~4.3.2" + engine.io "~6.1.0" + socket.io-adapter "~2.3.3" + socket.io-parser "~4.0.4" + +sort-object-keys@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/sort-object-keys/-/sort-object-keys-1.1.3.tgz#bff833fe85cab147b34742e45863453c1e190b45" + integrity sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg== + +sort-package-json@^1.49.0: + version "1.53.1" + resolved "https://registry.yarnpkg.com/sort-package-json/-/sort-package-json-1.53.1.tgz#8f2672b06314cf04d9a6bcefc75a5f38d600b811" + integrity sha512-ltLORrQuuPMpy23YkWCA8fO7zBOxM4P1j9LcGxci4K2Fk8jmSyCA/ATU6CFyy8qR2HQRx4RBYWzoi78FU/Anuw== + dependencies: + detect-indent "^6.0.0" + detect-newline "3.1.0" + git-hooks-list "1.0.3" + globby "10.0.0" + is-plain-obj "2.1.0" + sort-object-keys "^1.1.3" + +source-list-map@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" + integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== + +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.1.tgz#a1741c131e3c77d048252adfa24e23b908670caf" + integrity sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA== + +source-map-resolve@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== + dependencies: + source-map "^0.5.6" + +source-map-support@^0.5.16, source-map-support@~0.5.12: + version "0.5.16" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" + integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.3.0.tgz#7ecaf13b57bcd09da8a40c5d269db33799d4aaf9" + integrity sha1-fsrxO1e80J2opAxdJp2zN5nUqvk= + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + +source-map@0.4.x, source-map@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" + integrity sha1-66T12pwNyZneaAMti092FzZSA2s= + dependencies: + amdefine ">=0.0.4" + +source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@~0.1.x: + version "0.1.43" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" + integrity sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y= + dependencies: + amdefine ">=0.0.4" + +source-map@~0.7.2, source-map@~0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + +sourcemap-codec@^1.4.1, sourcemap-codec@^1.4.4: + version "1.4.8" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" + integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== + +sourcemap-validator@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/sourcemap-validator/-/sourcemap-validator-1.1.1.tgz#3d7d8a399ccab09c1fedc510d65436e25b1c386b" + integrity sha512-pq6y03Vs6HUaKo9bE0aLoksAcpeOo9HZd7I8pI6O480W/zxNZ9U32GfzgtPP0Pgc/K1JHna569nAbOk3X8/Qtw== + dependencies: + jsesc "~0.3.x" + lodash.foreach "^4.5.0" + lodash.template "^4.5.0" + source-map "~0.1.x" + +spawn-args@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/spawn-args/-/spawn-args-0.2.0.tgz#fb7d0bd1d70fd4316bd9e3dec389e65f9d6361bb" + integrity sha1-+30L0dcP1DFr2ePew4nmX51jYbs= + +spdx-correct@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" + integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" + integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== + +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.5" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" + integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +sprintf-js@^1.0.3: + version "1.1.2" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673" + integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +sri-toolbox@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/sri-toolbox/-/sri-toolbox-0.2.0.tgz#a7fea5c3fde55e675cf1c8c06f3ebb5c2935835e" + integrity sha1-p/6lw/3lXmdc8cjAbz67XCk1g14= + +sshpk@^1.7.0: + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +ssri@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5" + integrity sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q== + dependencies: + figgy-pudding "^3.5.1" + +stable@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== + +stagehand@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stagehand/-/stagehand-1.0.0.tgz#79515e2ad3a02c63f8720c7df9b6077ae14276d9" + integrity sha512-zrXl0QixAtSHFyN1iv04xOBgplbT4HgC8T7g+q8ESZbDNi5uZbMtxLukFVXPJ5Nl7zCYvYcrT3Mj24WYCH93hw== + dependencies: + debug "^4.1.0" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + +stealthy-require@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" + integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= + +stream-browserify@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" + integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== + dependencies: + inherits "~2.0.1" + readable-stream "^2.0.2" + +stream-each@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" + integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw== + dependencies: + end-of-stream "^1.1.0" + stream-shift "^1.0.0" + +stream-http@^2.7.2: + version "2.8.3" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" + integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.1" + readable-stream "^2.3.6" + to-arraybuffer "^1.0.0" + xtend "^4.0.0" + +stream-shift@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" + integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== + +stream-to-buffer@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/stream-to-buffer/-/stream-to-buffer-0.1.0.tgz#26799d903ab2025c9bd550ac47171b00f8dd80a9" + integrity sha1-JnmdkDqyAlyb1VCsRxcbAPjdgKk= + dependencies: + stream-to "~0.2.0" + +stream-to@~0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/stream-to/-/stream-to-0.2.2.tgz#84306098d85fdb990b9fa300b1b3ccf55e8ef01d" + integrity sha1-hDBgmNhf25kLn6MAsbPM9V6O8B0= + +string-template@~0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add" + integrity sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0= + +string-width@^1.0.1, string-width@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2", string-width@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + +string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string.prototype.matchall@^4.0.5: + version "4.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.6.tgz#5abb5dabc94c7b0ea2380f65ba610b3a544b15fa" + integrity sha512-6WgDX8HmQqvEd7J+G6VtAahhsQIssiZ8zl7zKh1VDMFyL3hRTJP4FTNA3RbIp2TOQ9AYNDcc7e3fH0Qbup+DBg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + get-intrinsic "^1.1.1" + has-symbols "^1.0.2" + internal-slot "^1.0.3" + regexp.prototype.flags "^1.3.1" + side-channel "^1.0.4" + +string.prototype.padend@^3.0.0: + version "3.1.3" + resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.1.3.tgz#997a6de12c92c7cb34dc8a201a6c53d9bd88a5f1" + integrity sha512-jNIIeokznm8SD/TZISQsZKYu7RJyheFNt84DUPrh482GC8RVp2MKqm2O5oBRdGxbDQoXrhhWtPIWQOiy20svUg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +string.prototype.trimend@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" + integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +string.prototype.trimleft@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74" + integrity sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +string.prototype.trimright@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz#440314b15996c866ce8a0341894d45186200c5d9" + integrity sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +string.prototype.trimstart@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" + integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +string_decoder@0.10, string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + +string_decoder@^1.0.0, string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +stringstream@~0.0.4: + version "0.0.6" + resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.6.tgz#7880225b0d4ad10e30927d167a1d6f2fd3b33a72" + integrity sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA== + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + +strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= + dependencies: + is-utf8 "^0.2.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +striptags@^3.1.1: + version "3.2.0" + resolved "https://registry.yarnpkg.com/striptags/-/striptags-3.2.0.tgz#cc74a137db2de8b0b9a370006334161f7dd67052" + integrity sha512-g45ZOGzHDMe2bdYMdIvdAfCQkCTDMGBazSw1ypMowwGIee7ZQ5dU0rBJ8Jqgl+jAKIv4dbeE1jscZq9wid1Tkw== + +styled_string@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/styled_string/-/styled_string-0.0.1.tgz#d22782bd81295459bc4f1df18c4bad8e94dd124a" + integrity sha1-0ieCvYEpVFm8Tx3xjEutjpTdEko= + +sum-up@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sum-up/-/sum-up-1.0.3.tgz#1c661f667057f63bcb7875aa1438bc162525156e" + integrity sha1-HGYfZnBX9jvLeHWqFDi8FiUlFW4= + dependencies: + chalk "^1.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + +supports-color@^5.3.0, supports-color@^5.4.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" + integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== + dependencies: + has-flag "^4.0.0" + +svg2png@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/svg2png/-/svg2png-4.1.1.tgz#6b9e0398aa418778b6436e127a2fb7f00d499c28" + integrity sha1-a54DmKpBh3i2Q24Sei+38A1JnCg= + dependencies: + file-url "^2.0.0" + phantomjs-prebuilt "^2.1.14" + pn "^1.0.0" + yargs "^6.5.0" + +svgo@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.0.tgz#bae51ba95ded9a33a36b7c46ce9c359ae9154313" + integrity sha512-MLfUA6O+qauLDbym+mMZgtXCGRfIxyQoeH6IKVcFslyODEe/ElJNwr0FohQ3xG4C6HK6bk3KYPPXwHVJk3V5NQ== + dependencies: + chalk "^2.4.1" + coa "^2.0.2" + css-select "^2.0.0" + css-select-base-adapter "^0.1.1" + css-tree "1.0.0-alpha.33" + csso "^3.5.1" + js-yaml "^3.13.1" + mkdirp "~0.5.1" + object.values "^1.1.0" + sax "~1.2.4" + stable "^0.1.8" + unquote "~1.1.1" + util.promisify "~1.0.0" + +"symbol-tree@>= 3.1.0 < 4.0.0", symbol-tree@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + +symlink-or-copy@^1.0.0, symlink-or-copy@^1.0.1, symlink-or-copy@^1.1.8, symlink-or-copy@^1.2.0, symlink-or-copy@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/symlink-or-copy/-/symlink-or-copy-1.3.1.tgz#9506dd64d8e98fa21dcbf4018d1eab23e77f71fe" + integrity sha512-0K91MEXFpBUaywiwSSkmKjnGcasG/rVBXFLJz5DrgGabpYD6N+3yZrfD6uUIfpuTu65DZLHi7N8CizHc07BPZA== + +sync-disk-cache@^1.3.3: + version "1.3.4" + resolved "https://registry.yarnpkg.com/sync-disk-cache/-/sync-disk-cache-1.3.4.tgz#53a2c5a09d8f4bb53160bce182a456ad71574024" + integrity sha512-GlkGeM81GPPEKz/lH7QUTbvqLq7K/IUTuaKDSMulP9XQ42glqNJIN/RKgSOw4y8vxL1gOVvj+W7ruEO4s36eCw== + dependencies: + debug "^2.1.3" + heimdalljs "^0.2.3" + mkdirp "^0.5.0" + rimraf "^2.2.8" + username-sync "^1.0.2" + +sync-disk-cache@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/sync-disk-cache/-/sync-disk-cache-2.1.0.tgz#01e879edc41c34a01fcdda5b39d47dd496e154a6" + integrity sha512-vngT2JmkSapgq0z7uIoYtB9kWOOzMihAAYq/D3Pjm/ODOGMgS4r++B+OZ09U4hWR6EaOdy9eqQ7/8ygbH3wehA== + dependencies: + debug "^4.1.1" + heimdalljs "^0.2.6" + mkdirp "^0.5.0" + rimraf "^3.0.0" + username-sync "^1.0.2" + +table@^6.0.9: + version "6.7.5" + resolved "https://registry.yarnpkg.com/table/-/table-6.7.5.tgz#f04478c351ef3d8c7904f0e8be90a1b62417d238" + integrity sha512-LFNeryOqiQHqCVKzhkymKwt6ozeRhlm8IL1mE8rNUurkir4heF6PzMyRgaTa4tlyPTGGgXuvVOF/OLWiH09Lqw== + dependencies: + ajv "^8.0.1" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + +taffydb@2.7.2: + version "2.7.2" + resolved "https://registry.yarnpkg.com/taffydb/-/taffydb-2.7.2.tgz#7bf8106a5c1a48251b3e3bc0a0e1732489fd0dc8" + integrity sha1-e/gQalwaSCUbPjvAoOFzJIn9Dcg= + +tailwindcss@1.9.6: + version "1.9.6" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-1.9.6.tgz#0c5089911d24e1e98e592a31bfdb3d8f34ecf1a0" + integrity sha512-nY8WYM/RLPqGsPEGEV2z63riyQPcHYZUJpAwdyBzVpxQHOHqHE+F/fvbCeXhdF1+TA5l72vSkZrtYCB9hRcwkQ== + dependencies: + "@fullhuman/postcss-purgecss" "^2.1.2" + autoprefixer "^9.4.5" + browserslist "^4.12.0" + bytes "^3.0.0" + chalk "^3.0.0 || ^4.0.0" + color "^3.1.2" + detective "^5.2.0" + fs-extra "^8.0.0" + html-tags "^3.1.0" + lodash "^4.17.20" + node-emoji "^1.8.1" + normalize.css "^8.0.1" + object-hash "^2.0.3" + postcss "^7.0.11" + postcss-functions "^3.0.0" + postcss-js "^2.0.0" + postcss-nested "^4.1.1" + postcss-selector-parser "^6.0.0" + postcss-value-parser "^4.1.0" + pretty-hrtime "^1.0.3" + reduce-css-calc "^2.1.6" + resolve "^1.14.2" + +tap-parser@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/tap-parser/-/tap-parser-7.0.0.tgz#54db35302fda2c2ccc21954ad3be22b2cba42721" + integrity sha512-05G8/LrzqOOFvZhhAk32wsGiPZ1lfUrl+iV7+OkKgfofZxiceZWMHkKmow71YsyVQ8IvGBP2EjcIjE5gL4l5lA== + dependencies: + events-to-array "^1.0.1" + js-yaml "^3.2.7" + minipass "^2.2.0" + +tapable@^1.0.0, tapable@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" + integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== + +temp@0.9.4: + version "0.9.4" + resolved "https://registry.yarnpkg.com/temp/-/temp-0.9.4.tgz#cd20a8580cb63635d0e4e9d4bd989d44286e7620" + integrity sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA== + dependencies: + mkdirp "^0.5.1" + rimraf "~2.6.2" + +terser-webpack-plugin@^1.4.3: + version "1.4.5" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz#a217aefaea330e734ffacb6120ec1fa312d6040b" + integrity sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw== + dependencies: + cacache "^12.0.2" + find-cache-dir "^2.1.0" + is-wsl "^1.1.0" + schema-utils "^1.0.0" + serialize-javascript "^4.0.0" + source-map "^0.6.1" + terser "^4.1.2" + webpack-sources "^1.4.0" + worker-farm "^1.7.0" + +terser@^4.1.2: + version "4.8.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" + integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== + dependencies: + commander "^2.20.0" + source-map "~0.6.1" + source-map-support "~0.5.12" + +terser@^5.3.0: + version "5.10.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.10.0.tgz#b86390809c0389105eb0a0b62397563096ddafcc" + integrity sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA== + dependencies: + commander "^2.20.0" + source-map "~0.7.2" + source-map-support "~0.5.20" + +testem@^3.2.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/testem/-/testem-3.6.0.tgz#bf5c86944bafd035c18f41f520195cce5eef33a8" + integrity sha512-sXwx2IlOadOhrKf0hsV1Yt/yuYhdfrtJ4dpp7T6pFN62GjMyKifjAv2SFm+4zYHee1JwxheO7JUL0+3iN0rlHw== + dependencies: + "@xmldom/xmldom" "^0.7.1" + backbone "^1.1.2" + bluebird "^3.4.6" + charm "^1.0.0" + commander "^2.6.0" + compression "^1.7.4" + consolidate "^0.15.1" + execa "^1.0.0" + express "^4.10.7" + fireworm "^0.7.0" + glob "^7.0.4" + http-proxy "^1.13.1" + js-yaml "^3.2.5" + lodash.assignin "^4.1.0" + lodash.castarray "^4.4.0" + lodash.clonedeep "^4.4.1" + lodash.find "^4.5.1" + lodash.uniqby "^4.7.0" + mkdirp "^0.5.1" + mustache "^3.0.0" + node-notifier "^9.0.1" + npmlog "^4.0.0" + printf "^0.6.1" + rimraf "^2.4.4" + socket.io "^4.1.2" + spawn-args "^0.2.0" + styled_string "0.0.1" + tap-parser "^7.0.0" + tmp "0.0.33" + +tether@^1.4.0: + version "1.4.7" + resolved "https://registry.yarnpkg.com/tether/-/tether-1.4.7.tgz#d56a818590d8fe72e387f77a67f93ab96d8e1fb2" + integrity sha512-Z0J1aExjoFU8pybVkQAo/vD2wfSO63r+XOPfWQMC5qtf1bI7IWqNk4MiyBcgvvnY8kqnY06dVdvwTK2S3PU/Fw== + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +"textextensions@1 || 2", textextensions@^2.5.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/textextensions/-/textextensions-2.6.0.tgz#d7e4ab13fe54e32e08873be40d51b74229b00fc4" + integrity sha512-49WtAWS+tcsy93dRt6P0P3AMD2m5PvXRhuEA0kaXos5ZLlujtYmpmFsB+QvWUSxE1ZsstmYXfQ7L40+EcQgpAQ== + +throttleit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c" + integrity sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw= + +through2@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +through2@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.1.tgz#39276e713c3302edf9e388dd9c812dd3b825bd5a" + integrity sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww== + dependencies: + readable-stream "2 || 3" + +through2@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.2.tgz#99f88931cfc761ec7678b41d5d7336b5b6a07bf4" + integrity sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ== + dependencies: + inherits "^2.0.4" + readable-stream "2 || 3" + +through@^2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +time-zone@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/time-zone/-/time-zone-1.0.0.tgz#99c5bf55958966af6d06d83bdf3800dc82faec5d" + integrity sha1-mcW/VZWJZq9tBtg73zgA3IL67F0= + +timers-browserify@^2.0.4: + version "2.0.11" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f" + integrity sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ== + dependencies: + setimmediate "^1.0.4" + +timm@^1.6.1: + version "1.6.2" + resolved "https://registry.yarnpkg.com/timm/-/timm-1.6.2.tgz#dfd8c6719f7ba1fcfc6295a32670a1c6d166c0bd" + integrity sha512-IH3DYDL1wMUwmIlVmMrmesw5lZD6N+ZOAFWEyLrtpoL9Bcrs9u7M/vyOnHzDD2SMs4irLkVjqxZbHrXStS/Nmw== + +tiny-emitter@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" + integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== + +tiny-glob@0.2.9: + version "0.2.9" + resolved "https://registry.yarnpkg.com/tiny-glob/-/tiny-glob-0.2.9.tgz#2212d441ac17928033b110f8b3640683129d31e2" + integrity sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg== + dependencies: + globalyzer "0.1.0" + globrex "^0.1.2" + +tiny-lr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/tiny-lr/-/tiny-lr-2.0.0.tgz#863659d7ce1ed201a117d8197d7f8b9a27bdc085" + integrity sha512-f6nh0VMRvhGx4KCeK1lQ/jaL0Zdb5WdR+Jk8q9OSUQnaSDxAEGH1fgqLZ+cMl5EW3F2MGnCsalBO1IsnnogW1Q== + dependencies: + body "^5.1.0" + debug "^3.1.0" + faye-websocket "^0.11.3" + livereload-js "^3.3.1" + object-assign "^4.1.0" + qs "^6.4.0" + +tinycolor2@^1.1.2, tinycolor2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.1.tgz#f4fad333447bc0b07d4dc8e9209d8f39a8ac77e8" + integrity sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g= + +tmp@0.0.28: + version "0.0.28" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.28.tgz#172735b7f614ea7af39664fa84cf0de4e515d120" + integrity sha1-Fyc1t/YU6nrzlmT6hM8N5OUV0SA= + dependencies: + os-tmpdir "~1.0.1" + +tmp@0.0.33, tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +tmp@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877" + integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw== + dependencies: + rimraf "^2.6.3" + +tmp@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" + integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== + dependencies: + rimraf "^3.0.0" + +tmpl@1.0.x: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + +to-arraybuffer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + +to-ico@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/to-ico/-/to-ico-1.1.5.tgz#1d32da5f2c90922edee6b686d610c54527b5a8d5" + integrity sha512-5kIh7m7bkIlqIESEZkL8gAMMzucXKfPe3hX2FoDY5HEAfD9OJU+Qh9b6Enp74w0qRcxVT5ejss66PHKqc3AVkg== + dependencies: + arrify "^1.0.1" + buffer-alloc "^1.1.0" + image-size "^0.5.0" + parse-png "^1.0.0" + resize-img "^1.1.0" + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +toidentifier@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" + integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== + +tough-cookie@>=0.12.0, tough-cookie@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" + integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.1.2" + +tough-cookie@^2.2.0, tough-cookie@^2.3.3, tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +tr46@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.0.2.tgz#03273586def1595ae08fedb38d7733cee91d2479" + integrity sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg== + dependencies: + punycode "^2.1.1" + +tr46@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-3.0.0.tgz#555c4e297a950617e8eeddef633c87d4d9d6cbf9" + integrity sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA== + dependencies: + punycode "^2.1.1" + +tr46@~0.0.1, tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + +tree-sync@^1.2.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/tree-sync/-/tree-sync-1.4.0.tgz#314598d13abaf752547d9335b8f95d9a137100d6" + integrity sha512-YvYllqh3qrR5TAYZZTXdspnIhlKAYezPYw11ntmweoceu4VK+keN356phHRIIo1d+RDmLpHZrUlmxga2gc9kSQ== + dependencies: + debug "^2.2.0" + fs-tree-diff "^0.5.6" + mkdirp "^0.5.1" + quick-temp "^0.1.5" + walk-sync "^0.3.3" + +tree-sync@^2.0.0, tree-sync@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tree-sync/-/tree-sync-2.1.0.tgz#31cbbd41f2936f5390b61e8c9d7cb27e75a212fe" + integrity sha512-OLWW+Nd99NOM53aZ8ilT/YpEiOo6mXD3F4/wLbARqybSZ3Jb8IxHK5UGVbZaae0wtXAyQshVV+SeqVBik+Fbmw== + dependencies: + debug "^4.1.1" + fs-tree-diff "^2.0.1" + mkdirp "^0.5.5" + quick-temp "^0.1.5" + walk-sync "^0.3.3" + +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= + +tslib@^1.10.0, tslib@^1.9.0: + version "1.11.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" + integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== + +tslib@^2.2.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" + integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== + +tty-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tunnel-agent@~0.4.0: + version "0.4.3" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" + integrity sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us= + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + dependencies: + prelude-ls "~1.1.2" + +type-fest@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" + integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ== + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type-is@~1.6.17, type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +typescript-memoize@^1.0.0-alpha.3: + version "1.0.0-alpha.3" + resolved "https://registry.yarnpkg.com/typescript-memoize/-/typescript-memoize-1.0.0-alpha.3.tgz#699a5415f886694a8d6e2e5451bc28a39a6bc2f9" + integrity sha1-aZpUFfiGaUqNbi5UUbwoo5prwvk= + dependencies: + core-js "2.4.1" + +typescript-memoize@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/typescript-memoize/-/typescript-memoize-1.1.0.tgz#4a8f512d06fc995167c703a3592219901db8bc79" + integrity sha512-LQPKVXK8QrBBkL/zclE6YgSWn0I8ew5m0Lf+XL00IwMhlotqRLlzHV+BRrljVQIc+NohUAuQP7mg4HQwrx5Xbg== + +typescript@^2.8.3: + version "2.9.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c" + integrity sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w== + +uc.micro@^1.0.0, uc.micro@^1.0.1, uc.micro@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" + integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== + +uglify-js@^3.1.4: + version "3.13.5" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.13.5.tgz#5d71d6dbba64cf441f32929b1efce7365bb4f113" + integrity sha512-xtB8yEqIkn7zmOyS2zUNBsYCBRhDkvlNxMMY2smuJ/qA8NCHeQvKCF3i9Z4k8FJH4+PJvZRtMrPynfZ75+CSZw== + +unbox-primitive@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" + integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== + dependencies: + function-bind "^1.1.1" + has-bigints "^1.0.1" + has-symbols "^1.0.2" + which-boxed-primitive "^1.0.2" + +underscore.string@^3.2.2, underscore.string@~3.3.4: + version "3.3.5" + resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-3.3.5.tgz#fc2ad255b8bd309e239cbc5816fd23a9b7ea4023" + integrity sha512-g+dpmgn+XBneLmXXo+sGlW5xQEt4ErkS3mgeN2GFbremYeMBSJKr9Wf2KJplQVaiPY/f7FN6atosWYNm9ovrYg== + dependencies: + sprintf-js "^1.0.3" + util-deprecate "^1.0.2" + +underscore@>=1.8.3: + version "1.13.1" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.1.tgz#0c1c6bd2df54b6b69f2314066d65b6cde6fcf9d1" + integrity sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g== + +unicode-canonical-property-names-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" + integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== + +unicode-match-property-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" + integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== + dependencies: + unicode-canonical-property-names-ecmascript "^1.0.4" + unicode-property-aliases-ecmascript "^1.0.4" + +unicode-match-property-value-ecmascript@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" + integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== + +unicode-property-aliases-ecmascript@^1.0.4: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" + integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg== + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +uniq@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= + +unique-filename@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" + integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== + dependencies: + unique-slug "^2.0.0" + +unique-slug@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" + integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== + dependencies: + imurmurhash "^0.1.4" + +unique-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" + integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== + dependencies: + crypto-random-string "^2.0.0" + +universalify@^0.1.0, universalify@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + +unquote@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" + integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +untildify@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/untildify/-/untildify-2.1.0.tgz#17eb2807987f76952e9c0485fc311d06a826a2e0" + integrity sha1-F+soB5h/dpUunASF/DEdBqgmouA= + dependencies: + os-homedir "^1.0.0" + +upath@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" + integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== + +uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + dependencies: + prepend-http "^2.0.0" + +url-regex@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/url-regex/-/url-regex-3.2.0.tgz#dbad1e0c9e29e105dd0b1f09f6862f7fdb482724" + integrity sha1-260eDJ4p4QXdCx8J9oYvf9tIJyQ= + dependencies: + ip-regex "^1.0.1" + +url@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +username-sync@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/username-sync/-/username-sync-1.0.2.tgz#0a3697909fb7b5768d29e2921f573acfdd427592" + integrity sha512-ayNkOJdoNSGNDBE46Nkc+l6IXmeugbzahZLSMkwvgRWv5y5ZqNY2IrzcgmkR4z32sj1W3tM3TuTUMqkqBzO+RA== + +utif@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/utif/-/utif-2.0.1.tgz#9e1582d9bbd20011a6588548ed3266298e711759" + integrity sha512-Z/S1fNKCicQTf375lIP9G8Sa1H/phcysstNrrSdZKj1f9g58J4NMgb5IgiEZN9/nLMPDwF0W7hdOe9Qq2IYoLg== + dependencies: + pako "^1.0.5" + +util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +util.promisify@^1.0.0, util.promisify@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" + integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.2" + has-symbols "^1.0.1" + object.getownpropertydescriptors "^2.1.0" + +util@0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= + dependencies: + inherits "2.0.1" + +util@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" + integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== + dependencies: + inherits "2.0.3" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +uuid@^8.3.0, uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +v8-compile-cache@^2.0.3, v8-compile-cache@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +validate-npm-package-name@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e" + integrity sha1-X6kS2B630MdK/BQN5zF/DKffQ34= + dependencies: + builtins "^1.0.3" + +validate-peer-dependencies@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/validate-peer-dependencies/-/validate-peer-dependencies-1.2.0.tgz#22aab93c514f4fda457d36c80685e8b1160d2036" + integrity sha512-nd2HUpKc6RWblPZQ2GDuI65sxJ2n/UqZwSBVtj64xlWjMx0m7ZB2m9b2JS3v1f+n9VWH/dd1CMhkHfP6pIdckA== + dependencies: + resolve-package-path "^3.1.0" + semver "^7.3.2" + +vary@^1, vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + +velocity-animate@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/velocity-animate/-/velocity-animate-1.5.2.tgz#5a351d75fca2a92756f5c3867548b873f6c32105" + integrity sha512-m6EXlCAMetKztO1ppBhGU1/1MR3IiEevO6ESq6rcrSQ3Q77xYSW13jkfXW88o4xMrkXJhy/U7j4wFR/twMB0Eg== + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vinyl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.0.tgz#d85b07da96e458d25b2ffe19fece9f2caa13ed86" + integrity sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg== + dependencies: + clone "^2.1.1" + clone-buffer "^1.0.0" + clone-stats "^1.0.0" + cloneable-readable "^1.0.0" + remove-trailing-separator "^1.0.1" + replace-ext "^1.0.0" + +vm-browserify@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" + integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== + +w3c-hr-time@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" + integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== + dependencies: + browser-process-hrtime "^1.0.0" + +w3c-xmlserializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" + integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== + dependencies: + xml-name-validator "^3.0.0" + +w3c-xmlserializer@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz#06cdc3eefb7e4d0b20a560a5a3aeb0d2d9a65923" + integrity sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg== + dependencies: + xml-name-validator "^4.0.0" + +walk-sync@^0.2.5: + version "0.2.7" + resolved "https://registry.yarnpkg.com/walk-sync/-/walk-sync-0.2.7.tgz#b49be4ee6867657aeb736978b56a29d10fa39969" + integrity sha1-tJvk7mhnZXrrc2l4tWop0Q+jmWk= + dependencies: + ensure-posix-path "^1.0.0" + matcher-collection "^1.0.0" + +walk-sync@^0.3.0, walk-sync@^0.3.1, walk-sync@^0.3.2, walk-sync@^0.3.3: + version "0.3.4" + resolved "https://registry.yarnpkg.com/walk-sync/-/walk-sync-0.3.4.tgz#cf78486cc567d3a96b5b2237c6108017a5ffb9a4" + integrity sha512-ttGcuHA/OBnN2pcM6johpYlEms7XpO5/fyKIr48541xXedan4roO8cS1Q2S/zbbjGH/BarYDAMeS2Mi9HE5Tig== + dependencies: + ensure-posix-path "^1.0.0" + matcher-collection "^1.0.0" + +walk-sync@^1.0.0, walk-sync@^1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/walk-sync/-/walk-sync-1.1.4.tgz#81049f3d8095479b49574cfa5f558d7a252b127d" + integrity sha512-nowc9thB/Jg0KW4TgxoRjLLYRPvl3DB/98S89r4ZcJqq2B0alNcKDh6pzLkBSkPMzRSMsJghJHQi79qw0YWEkA== + dependencies: + "@types/minimatch" "^3.0.3" + ensure-posix-path "^1.1.0" + matcher-collection "^1.1.1" + +walk-sync@^2.0.0, walk-sync@^2.0.2, walk-sync@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/walk-sync/-/walk-sync-2.2.0.tgz#80786b0657fcc8c0e1c0b1a042a09eae2966387a" + integrity sha512-IC8sL7aB4/ZgFcGI2T1LczZeFWZ06b3zoHH7jBPyHxOtIIz1jppWHjjEXkOFvFojBVAK9pV7g47xOZ4LW3QLfg== + dependencies: + "@types/minimatch" "^3.0.3" + ensure-posix-path "^1.1.0" + matcher-collection "^2.0.0" + minimatch "^3.0.4" + +walker@~1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" + integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs= + dependencies: + makeerror "1.0.x" + +watch-detector@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/watch-detector/-/watch-detector-1.0.1.tgz#3106a6b489284ec2ecaef0e65cf1b8ec9117296e" + integrity sha512-8sJ8rvNfg2ciqCa5IxIdmdxU/vuUe9V/jw+thXbdreELSv3+Cq6k8K42cLEL86W2td1PMmfNCWZuAhrZ/sD4mw== + dependencies: + heimdalljs-logger "^0.1.10" + semver "^6.3.0" + silent-error "^1.1.1" + tmp "^0.1.0" + +watchpack-chokidar2@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz#9948a1866cbbd6cb824dea13a7ed691f6c8ddff0" + integrity sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA== + dependencies: + chokidar "^2.1.8" + +watchpack@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.4.tgz#6e9da53b3c80bb2d6508188f5b200410866cd30b" + integrity sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg== + dependencies: + graceful-fs "^4.1.2" + neo-async "^2.5.0" + optionalDependencies: + chokidar "^3.4.1" + watchpack-chokidar2 "^2.0.0" + +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= + dependencies: + defaults "^1.0.3" + +webidl-conversions@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-2.0.1.tgz#3bf8258f7d318c7443c36f2e169402a1a6703506" + integrity sha1-O/glj30xjHRDw28uFpQCoaZwNQY= + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + +webidl-conversions@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" + integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== + +webidl-conversions@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" + integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== + +webidl-conversions@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" + integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== + +webpack-sources@^1.4.0, webpack-sources@^1.4.1: + version "1.4.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" + integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== + dependencies: + source-list-map "^2.0.0" + source-map "~0.6.1" + +webpack@^4.43.0: + version "4.44.2" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.44.2.tgz#6bfe2b0af055c8b2d1e90ed2cd9363f841266b72" + integrity sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/wasm-edit" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + acorn "^6.4.1" + ajv "^6.10.2" + ajv-keywords "^3.4.1" + chrome-trace-event "^1.0.2" + enhanced-resolve "^4.3.0" + eslint-scope "^4.0.3" + json-parse-better-errors "^1.0.2" + loader-runner "^2.4.0" + loader-utils "^1.2.3" + memory-fs "^0.4.1" + micromatch "^3.1.10" + mkdirp "^0.5.3" + neo-async "^2.6.1" + node-libs-browser "^2.2.1" + schema-utils "^1.0.0" + tapable "^1.1.3" + terser-webpack-plugin "^1.4.3" + watchpack "^1.7.4" + webpack-sources "^1.4.1" + +websocket-driver@>=0.5.1: + version "0.7.3" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.3.tgz#a2d4e0d4f4f116f1e6297eba58b05d430100e9f9" + integrity sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg== + dependencies: + http-parser-js ">=0.4.0 <0.4.11" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + +whatwg-encoding@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" + integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== + dependencies: + iconv-lite "0.4.24" + +whatwg-encoding@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz#e7635f597fd87020858626805a2729fa7698ac53" + integrity sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg== + dependencies: + iconv-lite "0.6.3" + +whatwg-fetch@^3.4.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.5.0.tgz#605a2cd0a7146e5db141e29d1c62ab84c0c4c868" + integrity sha512-jXkLtsR42xhXg7akoDKvKWE40eJeI+2KZqcp2h3NsOrRnDvtWX36KcKl30dy+hxECivdk2BVUHVNrPtoMBUx6A== + +whatwg-fetch@^3.6.2: + version "3.6.2" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" + integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== + +whatwg-mimetype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" + integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== + +whatwg-mimetype@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7" + integrity sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q== + +whatwg-url-compat@~0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/whatwg-url-compat/-/whatwg-url-compat-0.6.5.tgz#00898111af689bb097541cd5a45ca6c8798445bf" + integrity sha1-AImBEa9om7CXVBzVpFymyHmERb8= + dependencies: + tr46 "~0.0.1" + +whatwg-url@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-10.0.0.tgz#37264f720b575b4a311bd4094ed8c760caaa05da" + integrity sha512-CLxxCmdUby142H5FZzn4D8ikO1cmypvXVQktsgosNy4a4BHrDHeciBBGZhb0bNoR5/MltoCatso+vFjjGx8t0w== + dependencies: + tr46 "^3.0.0" + webidl-conversions "^7.0.0" + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +whatwg-url@^8.0.0, whatwg-url@^8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.5.0.tgz#7752b8464fc0903fec89aa9846fc9efe07351fd3" + integrity sha512-fy+R77xWv0AiqfLl4nuGUlQ3/6b5uNfQ4WAbGQVMYshCTCCPK9psC1nWh3XHuxGVCtlcDDQPQW1csmmIQo+fwg== + dependencies: + lodash "^4.7.0" + tr46 "^2.0.2" + webidl-conversions "^6.1.0" + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= + +which@^1.2.10, which@^1.2.14, which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +which@^2.0.1, which@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +word-wrap@^1.2.3, word-wrap@~1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wordwrap@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= + +wordwrap@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= + +worker-farm@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" + integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw== + dependencies: + errno "~0.1.7" + +workerpool@^2.3.0: + version "2.3.3" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-2.3.3.tgz#49a70089bd55e890d68cc836a19419451d7c81d7" + integrity sha512-L1ovlYHp6UObYqElXXpbd214GgbEKDED0d3sj7pRdFXjNkb2+un/AUcCkceHizO0IVI6SOGGncrcjozruCkRgA== + dependencies: + object-assign "4.1.1" + +workerpool@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-3.1.2.tgz#b34e79243647decb174b7481ab5b351dc565c426" + integrity sha512-WJFA0dGqIK7qj7xPTqciWBH5DlJQzoPjsANvc3Y4hNB0SScT+Emjvt0jPPkDBUjBNngX1q9hHgt1Gfwytu6pug== + dependencies: + "@babel/core" "^7.3.4" + object-assign "4.1.1" + rsvp "^4.8.4" + +workerpool@^6.0.0, workerpool@^6.1.4: + version "6.1.5" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.5.tgz#0f7cf076b6215fd7e1da903ff6f22ddd1886b581" + integrity sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw== + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-legacy-hbs-plugin-if-needed@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wrap-legacy-hbs-plugin-if-needed/-/wrap-legacy-hbs-plugin-if-needed-1.0.1.tgz#6683eb74747f33e7caea54bb2ed85106ef9006b4" + integrity sha512-aJjXe5WwrY0u0dcUgKW3m2SGnxosJ66LLm/QaG0YMHqgA6+J2xwAFZfhSLsQ2BmO5x8PTH+OIxoAXuGz3qBA7A== + dependencies: + "@glimmer/reference" "^0.42.1" + "@glimmer/runtime" "^0.42.1" + "@glimmer/syntax" "^0.42.1" + "@simple-dom/interface" "^1.4.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + +ws@^7.4.4: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + +ws@^8.2.3: + version "8.3.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.3.0.tgz#7185e252c8973a60d57170175ff55fdbd116070d" + integrity sha512-Gs5EZtpqZzLvmIM59w4igITU57lrtYVFneaa434VROv4thzJyV6UjIL3D42lslWlI+D4KzLYnxSwtfuiO79sNw== + +ws@~8.2.3: + version "8.2.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba" + integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA== + +xdg-basedir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" + integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== + +xhr@^2.0.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.5.0.tgz#bed8d1676d5ca36108667692b74b316c496e49dd" + integrity sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ== + dependencies: + global "~4.3.0" + is-function "^1.0.1" + parse-headers "^2.0.0" + xtend "^4.0.0" + +"xml-name-validator@>= 2.0.1 < 3.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635" + integrity sha1-TYuPHszTQZqjYgYb7O9RXh5VljU= + +xml-name-validator@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" + integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== + +xml-name-validator@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835" + integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw== + +xml-parse-from-string@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" + integrity sha1-qQKekp09vN7RafPG4oI42VpdWig= + +xml2js@^0.4.5: + version "0.4.23" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" + integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + +xmlbuilder@~11.0.0: + version "11.0.1" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" + integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== + +xmlchars@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== + +xtend@^4.0.0, xtend@^4.0.2, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^3.2.1: + version "3.2.2" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" + integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== + +y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= + +yallist@^3.0.0, yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yam@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/yam/-/yam-1.0.0.tgz#7f6c91dc0f5de75a031e6da6b3907c3d25ab0de5" + integrity sha512-Hv9xxHtsJ9228wNhk03xnlDReUuWVvHwM4rIbjdAXYvHLs17xjuyF50N6XXFMN6N0omBaqgOok/MCK3At9fTAg== + dependencies: + fs-extra "^4.0.2" + lodash.merge "^4.6.0" + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-parser@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c" + integrity sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw= + dependencies: + camelcase "^3.0.0" + +yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yargs@^6.5.0: + version "6.6.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208" + integrity sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg= + dependencies: + camelcase "^3.0.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.2" + which-module "^1.0.0" + y18n "^3.2.1" + yargs-parser "^4.2.0" + +yauzl@^2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +yui@^3.18.1: + version "3.18.1" + resolved "https://registry.yarnpkg.com/yui/-/yui-3.18.1.tgz#e000269ec0a7b6fbc741cbb8fcbd0e65117b014c" + integrity sha1-4AAmnsCntvvHQcu4/L0OZRF7AUw= + dependencies: + request "~2.40.0" + +yuidocjs@^0.10.2: + version "0.10.2" + resolved "https://registry.yarnpkg.com/yuidocjs/-/yuidocjs-0.10.2.tgz#33924967ce619024cd70ef694e267d2f988f73f6" + integrity sha1-M5JJZ85hkCTNcO9pTiZ9L5iPc/Y= + dependencies: + express "^4.13.1" + graceful-fs "^4.1.2" + markdown-it "^4.3.0" + mdn-links "^0.1.0" + minimatch "^3.0.2" + rimraf "^2.4.1" + yui "^3.18.1"