From 8533e42d1a257305fb2f3d08fd5c2c518cd840b8 Mon Sep 17 00:00:00 2001 From: Divesh Otwani Date: Fri, 24 Aug 2018 13:45:42 +0200 Subject: [PATCH] Squashed 'funflow-cwl/' content from commit 3580a4a git-subtree-dir: funflow-cwl git-subtree-split: 3580a4acf9490d934e6d1fa836878749b4fbb1f2 --- .circleci/config.yml | 33 + .github/settings.yml | 30 + .gitignore | 4 + .stylish-haskell.yaml | 228 ++++++ README.md | 8 + funflow-cwl/LICENSE | 30 + funflow-cwl/README.md | 295 ++++++++ funflow-cwl/Setup.hs | 2 + funflow-cwl/app/FFCwlRunner.hs | 123 ++++ funflow-cwl/funflow-cwl.cabal | 106 +++ funflow-cwl/readme/RabixComposer.png | Bin 0 -> 101609 bytes .../src/Control/Funflow/CWL/Convert.hs | 24 + .../Funflow/CWL/Convert/FlowCmdWrapper.hs | 603 ++++++++++++++++ .../src/Control/Funflow/CWL/Convert/Job.hs | 326 +++++++++ .../Control/Funflow/CWL/Convert/Scatter.hs | 401 ++++++++++ .../src/Control/Funflow/CWL/Convert/Tool.hs | 128 ++++ .../src/Control/Funflow/CWL/Convert/Wiring.hs | 205 ++++++ .../Control/Funflow/CWL/Convert/Workflow.hs | 309 ++++++++ funflow-cwl/src/Control/Funflow/CWL/Parse.hs | 682 ++++++++++++++++++ .../src/Control/Funflow/CWL/PreProcess.hs | 110 +++ funflow-cwl/src/Control/Funflow/CWL/Run.hs | 170 +++++ funflow-cwl/src/Control/Funflow/CWL/Types.hs | 24 + .../src/Control/Funflow/CWL/Types/CWLTypes.hs | 233 ++++++ .../Control/Funflow/CWL/Types/FunflowTypes.hs | 70 ++ .../src/Control/Funflow/CWL/Types/Schema.hs | 256 +++++++ .../src/Control/Funflow/CWL/Util/CWLUtil.hs | 38 + .../Control/Funflow/CWL/Util/StringParse.hs | 159 ++++ funflow-cwl/src/Data/ErrorMonad.hs | 142 ++++ funflow-cwl/src/Data/Existentials.hs | 31 + funflow-cwl/src/Data/Graph.hs | 173 +++++ funflow-cwl/src/Data/HList.hs | 195 +++++ funflow-cwl/src/Data/Nat.hs | 49 ++ funflow-cwl/src/Data/Type/Equality.hs | 13 + funflow-cwl/src/Data/Vec.hs | 183 +++++ funflow-cwl/test/Test.hs | 183 +++++ funflow-cwl/test/guide/1st-tool.cwl | 10 + funflow-cwl/test/guide/1st-workflow-job.yml | 4 + funflow-cwl/test/guide/1st-workflow.cwl | 25 + funflow-cwl/test/guide/Hello.java | 1 + funflow-cwl/test/guide/arguments-job.yml | 3 + funflow-cwl/test/guide/arguments.cwl | 19 + funflow-cwl/test/guide/array-inputs-job.yml | 12 + funflow-cwl/test/guide/array-inputs.cwl | 32 + funflow-cwl/test/guide/array-outputs-job.yml | 7 + funflow-cwl/test/guide/array-outputs.cwl | 18 + funflow-cwl/test/guide/createfile-job.yml | 1 + funflow-cwl/test/guide/createfile.cwl | 14 + funflow-cwl/test/guide/docker-job.yml | 3 + funflow-cwl/test/guide/docker.cwl | 13 + funflow-cwl/test/guide/echo-job.yml | 1 + funflow-cwl/test/guide/echo-pair-job.yml | 2 + funflow-cwl/test/guide/echo-pair.cwl | 22 + funflow-cwl/test/guide/echo.cwl | 11 + funflow-cwl/test/guide/echox-job.yml | 3 + funflow-cwl/test/guide/empty.json | 1 + funflow-cwl/test/guide/empty.yml | 1 + funflow-cwl/test/guide/env.cwl | 17 + funflow-cwl/test/guide/expression.cwl | 23 + funflow-cwl/test/guide/goodbye.txt | 0 funflow-cwl/test/guide/hello.js | 1 + funflow-cwl/test/guide/hello.tar | Bin 0 -> 10240 bytes funflow-cwl/test/guide/hello.txt | 0 funflow-cwl/test/guide/hello2.tar | Bin 0 -> 10240 bytes funflow-cwl/test/guide/hello3.tar | Bin 0 -> 10240 bytes funflow-cwl/test/guide/inp-job.yml | 12 + funflow-cwl/test/guide/inp-job2.yml | 6 + funflow-cwl/test/guide/inp.cwl | 35 + funflow-cwl/test/guide/nestedworkflows.cwl | 52 ++ funflow-cwl/test/guide/output | 4 + funflow-cwl/test/guide/output.txt | 1 + funflow-cwl/test/guide/record-job1.yml | 4 + funflow-cwl/test/guide/record-job2.yml | 6 + funflow-cwl/test/guide/record-job3.yml | 5 + funflow-cwl/test/guide/record.cwl | 35 + .../test/guide/scatter-job-cwltool.yml | 2 + funflow-cwl/test/guide/scatter-job.yml | 8 + funflow-cwl/test/guide/scatter1.cwl | 26 + funflow-cwl/test/guide/scatter2.cwl | 26 + funflow-cwl/test/guide/stdout.cwl | 15 + funflow-cwl/test/guide/step1_out | 1 + funflow-cwl/test/guide/tar-job.yml | 3 + funflow-cwl/test/guide/tar-param-job.yml | 4 + funflow-cwl/test/guide/tar-param.cwl | 18 + funflow-cwl/test/guide/tar.cwl | 14 + funflow-cwl/test/guide/whale.txt | 0 funflow-cwl/test/rabix/argtest-job.yml | 1 + funflow-cwl/test/rabix/argtest.cwl | 23 + funflow-cwl/test/rabix/compdocker-job.yml | 5 + funflow-cwl/test/rabix/compdocker.cwl | 27 + funflow-cwl/test/rabix/compile-default.cwl | 21 + funflow-cwl/test/rabix/compile-job.yml | 5 + funflow-cwl/test/rabix/compile.cwl | 26 + .../test/rabix/compileandexecute-job.yml | 10 + funflow-cwl/test/rabix/compileandexecute.cwl | 52 ++ funflow-cwl/test/rabix/eval-file-creator.cwl | 26 + funflow-cwl/test/rabix/eval-stdout.cwl | 27 + funflow-cwl/test/rabix/eval-sum.cwl | 27 + funflow-cwl/test/rabix/inputfiles/collatz | Bin 0 -> 8904 bytes funflow-cwl/test/rabix/inputfiles/collatzfn.c | 42 ++ funflow-cwl/test/rabix/inputfiles/execute.sh | 5 + funflow-cwl/test/rabix/inputfiles/genfiles.c | 31 + funflow-cwl/test/rabix/inputfiles/intfile | 1 + funflow-cwl/test/rabix/inputfiles/oldFile.txt | 3 + funflow-cwl/test/rabix/inputfiles/outNm | Bin 0 -> 8600 bytes funflow-cwl/test/rabix/inputfiles/sumofints.c | 28 + funflow-cwl/test/rabix/inputfiles/test.c | 7 + funflow-cwl/test/rabix/rename-job.yml | 4 + funflow-cwl/test/rabix/rename.cwl | 24 + funflow-cwl/test/rabix/simple-example-job.yml | 14 + funflow-cwl/test/rabix/simple-example.cwl | 78 ++ funflow-cwl/test/rabix/simple-wf-job.yml | 10 + funflow-cwl/test/rabix/simple-wf.cwl | 62 ++ funflow-cwl/test/rabix/touchfile-job.yml | 3 + funflow-cwl/test/rabix/touchfile.cwl | 20 + funflow-cwl/test/rabix/write-file-job.yml | 1 + funflow-cwl/test/rabix/write-file.cwl | 19 + stack.yaml | 15 + 117 files changed, 6704 insertions(+) create mode 100644 .circleci/config.yml create mode 100644 .github/settings.yml create mode 100644 .gitignore create mode 100644 .stylish-haskell.yaml create mode 100644 README.md create mode 100644 funflow-cwl/LICENSE create mode 100644 funflow-cwl/README.md create mode 100644 funflow-cwl/Setup.hs create mode 100644 funflow-cwl/app/FFCwlRunner.hs create mode 100644 funflow-cwl/funflow-cwl.cabal create mode 100644 funflow-cwl/readme/RabixComposer.png create mode 100644 funflow-cwl/src/Control/Funflow/CWL/Convert.hs create mode 100644 funflow-cwl/src/Control/Funflow/CWL/Convert/FlowCmdWrapper.hs create mode 100644 funflow-cwl/src/Control/Funflow/CWL/Convert/Job.hs create mode 100644 funflow-cwl/src/Control/Funflow/CWL/Convert/Scatter.hs create mode 100644 funflow-cwl/src/Control/Funflow/CWL/Convert/Tool.hs create mode 100644 funflow-cwl/src/Control/Funflow/CWL/Convert/Wiring.hs create mode 100644 funflow-cwl/src/Control/Funflow/CWL/Convert/Workflow.hs create mode 100644 funflow-cwl/src/Control/Funflow/CWL/Parse.hs create mode 100644 funflow-cwl/src/Control/Funflow/CWL/PreProcess.hs create mode 100644 funflow-cwl/src/Control/Funflow/CWL/Run.hs create mode 100644 funflow-cwl/src/Control/Funflow/CWL/Types.hs create mode 100644 funflow-cwl/src/Control/Funflow/CWL/Types/CWLTypes.hs create mode 100644 funflow-cwl/src/Control/Funflow/CWL/Types/FunflowTypes.hs create mode 100644 funflow-cwl/src/Control/Funflow/CWL/Types/Schema.hs create mode 100644 funflow-cwl/src/Control/Funflow/CWL/Util/CWLUtil.hs create mode 100644 funflow-cwl/src/Control/Funflow/CWL/Util/StringParse.hs create mode 100644 funflow-cwl/src/Data/ErrorMonad.hs create mode 100644 funflow-cwl/src/Data/Existentials.hs create mode 100644 funflow-cwl/src/Data/Graph.hs create mode 100644 funflow-cwl/src/Data/HList.hs create mode 100644 funflow-cwl/src/Data/Nat.hs create mode 100644 funflow-cwl/src/Data/Type/Equality.hs create mode 100644 funflow-cwl/src/Data/Vec.hs create mode 100644 funflow-cwl/test/Test.hs create mode 100644 funflow-cwl/test/guide/1st-tool.cwl create mode 100644 funflow-cwl/test/guide/1st-workflow-job.yml create mode 100644 funflow-cwl/test/guide/1st-workflow.cwl create mode 100644 funflow-cwl/test/guide/Hello.java create mode 100644 funflow-cwl/test/guide/arguments-job.yml create mode 100644 funflow-cwl/test/guide/arguments.cwl create mode 100644 funflow-cwl/test/guide/array-inputs-job.yml create mode 100644 funflow-cwl/test/guide/array-inputs.cwl create mode 100644 funflow-cwl/test/guide/array-outputs-job.yml create mode 100644 funflow-cwl/test/guide/array-outputs.cwl create mode 100644 funflow-cwl/test/guide/createfile-job.yml create mode 100644 funflow-cwl/test/guide/createfile.cwl create mode 100644 funflow-cwl/test/guide/docker-job.yml create mode 100644 funflow-cwl/test/guide/docker.cwl create mode 100644 funflow-cwl/test/guide/echo-job.yml create mode 100644 funflow-cwl/test/guide/echo-pair-job.yml create mode 100644 funflow-cwl/test/guide/echo-pair.cwl create mode 100644 funflow-cwl/test/guide/echo.cwl create mode 100644 funflow-cwl/test/guide/echox-job.yml create mode 100644 funflow-cwl/test/guide/empty.json create mode 100644 funflow-cwl/test/guide/empty.yml create mode 100644 funflow-cwl/test/guide/env.cwl create mode 100644 funflow-cwl/test/guide/expression.cwl create mode 100644 funflow-cwl/test/guide/goodbye.txt create mode 100644 funflow-cwl/test/guide/hello.js create mode 100644 funflow-cwl/test/guide/hello.tar create mode 100644 funflow-cwl/test/guide/hello.txt create mode 100644 funflow-cwl/test/guide/hello2.tar create mode 100644 funflow-cwl/test/guide/hello3.tar create mode 100644 funflow-cwl/test/guide/inp-job.yml create mode 100644 funflow-cwl/test/guide/inp-job2.yml create mode 100644 funflow-cwl/test/guide/inp.cwl create mode 100644 funflow-cwl/test/guide/nestedworkflows.cwl create mode 100644 funflow-cwl/test/guide/output create mode 100644 funflow-cwl/test/guide/output.txt create mode 100644 funflow-cwl/test/guide/record-job1.yml create mode 100644 funflow-cwl/test/guide/record-job2.yml create mode 100644 funflow-cwl/test/guide/record-job3.yml create mode 100644 funflow-cwl/test/guide/record.cwl create mode 100644 funflow-cwl/test/guide/scatter-job-cwltool.yml create mode 100644 funflow-cwl/test/guide/scatter-job.yml create mode 100644 funflow-cwl/test/guide/scatter1.cwl create mode 100644 funflow-cwl/test/guide/scatter2.cwl create mode 100644 funflow-cwl/test/guide/stdout.cwl create mode 100644 funflow-cwl/test/guide/step1_out create mode 100644 funflow-cwl/test/guide/tar-job.yml create mode 100644 funflow-cwl/test/guide/tar-param-job.yml create mode 100644 funflow-cwl/test/guide/tar-param.cwl create mode 100644 funflow-cwl/test/guide/tar.cwl create mode 100644 funflow-cwl/test/guide/whale.txt create mode 100644 funflow-cwl/test/rabix/argtest-job.yml create mode 100644 funflow-cwl/test/rabix/argtest.cwl create mode 100644 funflow-cwl/test/rabix/compdocker-job.yml create mode 100644 funflow-cwl/test/rabix/compdocker.cwl create mode 100644 funflow-cwl/test/rabix/compile-default.cwl create mode 100644 funflow-cwl/test/rabix/compile-job.yml create mode 100644 funflow-cwl/test/rabix/compile.cwl create mode 100644 funflow-cwl/test/rabix/compileandexecute-job.yml create mode 100644 funflow-cwl/test/rabix/compileandexecute.cwl create mode 100644 funflow-cwl/test/rabix/eval-file-creator.cwl create mode 100644 funflow-cwl/test/rabix/eval-stdout.cwl create mode 100644 funflow-cwl/test/rabix/eval-sum.cwl create mode 100755 funflow-cwl/test/rabix/inputfiles/collatz create mode 100644 funflow-cwl/test/rabix/inputfiles/collatzfn.c create mode 100755 funflow-cwl/test/rabix/inputfiles/execute.sh create mode 100644 funflow-cwl/test/rabix/inputfiles/genfiles.c create mode 100644 funflow-cwl/test/rabix/inputfiles/intfile create mode 100644 funflow-cwl/test/rabix/inputfiles/oldFile.txt create mode 100755 funflow-cwl/test/rabix/inputfiles/outNm create mode 100644 funflow-cwl/test/rabix/inputfiles/sumofints.c create mode 100644 funflow-cwl/test/rabix/inputfiles/test.c create mode 100644 funflow-cwl/test/rabix/rename-job.yml create mode 100644 funflow-cwl/test/rabix/rename.cwl create mode 100644 funflow-cwl/test/rabix/simple-example-job.yml create mode 100644 funflow-cwl/test/rabix/simple-example.cwl create mode 100644 funflow-cwl/test/rabix/simple-wf-job.yml create mode 100644 funflow-cwl/test/rabix/simple-wf.cwl create mode 100644 funflow-cwl/test/rabix/touchfile-job.yml create mode 100644 funflow-cwl/test/rabix/touchfile.cwl create mode 100644 funflow-cwl/test/rabix/write-file-job.yml create mode 100644 funflow-cwl/test/rabix/write-file.cwl create mode 100644 stack.yaml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 00000000..cc9c4425 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,33 @@ +version: 2 +jobs: + build: + docker: + - image: fpco/stack-build + steps: + - checkout + - run: + name: Compute cache key + command: | + find . -name "*.cabal" -o -name "stack.yaml" -type f | sort | xargs cat > /tmp/stack-deps + - restore_cache: + keys: + - funflow-stack-deps-{{arch}}-{{checksum "/tmp/stack-deps"}} + - run: + name: Setup build toolchain + command: stack setup + - run: + name: Building dependencies + command: stack test --only-snapshot --prefetch + - save_cache: + paths: + - "~/.stack" + key: funflow-stack-deps-{{arch}}-{{checksum "/tmp/stack-deps"}} + - run: + name: Building + command: stack build --pedantic + - run: + name: Building tests + command: stack test --pedantic --no-run-tests + - run: + name: Running tests + command: stack test diff --git a/.github/settings.yml b/.github/settings.yml new file mode 100644 index 00000000..9c9f0dd8 --- /dev/null +++ b/.github/settings.yml @@ -0,0 +1,30 @@ +repository: + has_wiki: false + +labels: + - name: "duplicate" + color: cfd3d7 + - name: "good first issue" + color: 7057ff + - name: "invalid" + color: cfd3d7 + - name: "P0" + color: b60205 + - name: "P1" + color: d93f0b + - name: "P2" + color: e99695 + - name: "P3" + color: fbca04 + - name: "P4" + color: fef2c0 + - name: "question" + color: d876e3 + - name: "type: bug" + color: 0052cc + - name: "type: documentation" + color: 0052cc + - name: "type: feature request" + color: 0052cc + - name: "wontfix" + color: ffffff diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..93c36086 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.stack-work +*cwlFunflowTest* +*tmp/funflow* +.\#* diff --git a/.stylish-haskell.yaml b/.stylish-haskell.yaml new file mode 100644 index 00000000..e8e6477c --- /dev/null +++ b/.stylish-haskell.yaml @@ -0,0 +1,228 @@ +# stylish-haskell configuration file +# ================================== + +# The stylish-haskell tool is mainly configured by specifying steps. These steps +# are a list, so they have an order, and one specific step may appear more than +# once (if needed). Each file is processed by these steps in the given order. +steps: + # Convert some ASCII sequences to their Unicode equivalents. This is disabled + # by default. + # - unicode_syntax: + # # In order to make this work, we also need to insert the UnicodeSyntax + # # language pragma. If this flag is set to true, we insert it when it's + # # not already present. You may want to disable it if you configure + # # language extensions using some other method than pragmas. Default: + # # true. + # add_language_pragma: true + + # Align the right hand side of some elements. This is quite conservative + # and only applies to statements where each element occupies a single + # line. + - simple_align: + cases: true + top_level_patterns: true + records: true + + # Import cleanup + - imports: + # There are different ways we can align names and lists. + # + # - global: Align the import names and import list throughout the entire + # file. + # + # - file: Like global, but don't add padding when there are no qualified + # imports in the file. + # + # - group: Only align the imports per group (a group is formed by adjacent + # import lines). + # + # - none: Do not perform any alignment. + # + # Default: global. + align: global + + # The following options affect only import list alignment. + # + # List align has following options: + # + # - after_alias: Import list is aligned with end of import including + # 'as' and 'hiding' keywords. + # + # > import qualified Data.List as List (concat, foldl, foldr, head, + # > init, last, length) + # + # - with_alias: Import list is aligned with start of alias or hiding. + # + # > import qualified Data.List as List (concat, foldl, foldr, head, + # > init, last, length) + # + # - new_line: Import list starts always on new line. + # + # > import qualified Data.List as List + # > (concat, foldl, foldr, head, init, last, length) + # + # Default: after_alias + list_align: new_line + + # Right-pad the module names to align imports in a group: + # + # - true: a little more readable + # + # > import qualified Data.List as List (concat, foldl, foldr, + # > init, last, length) + # > import qualified Data.List.Extra as List (concat, foldl, foldr, + # > init, last, length) + # + # - false: diff-safe + # + # > import qualified Data.List as List (concat, foldl, foldr, init, + # > last, length) + # > import qualified Data.List.Extra as List (concat, foldl, foldr, + # > init, last, length) + # + # Default: true + pad_module_names: false + + # Long list align style takes effect when import is too long. This is + # determined by 'columns' setting. + # + # - inline: This option will put as much specs on same line as possible. + # + # - new_line: Import list will start on new line. + # + # - new_line_multiline: Import list will start on new line when it's + # short enough to fit to single line. Otherwise it'll be multiline. + # + # - multiline: One line per import list entry. + # Type with constructor list acts like single import. + # + # > import qualified Data.Map as M + # > ( empty + # > , singleton + # > , ... + # > , delete + # > ) + # + # Default: inline + long_list_align: new_line_multiline + + # Align empty list (importing instances) + # + # Empty list align has following options + # + # - inherit: inherit list_align setting + # + # - right_after: () is right after the module name: + # + # > import Vector.Instances () + # + # Default: inherit + empty_list_align: inherit + + # List padding determines indentation of import list on lines after import. + # This option affects 'long_list_align'. + # + # - : constant value + # + # - module_name: align under start of module name. + # Useful for 'file' and 'group' align settings. + list_padding: 4 + + # Separate lists option affects formatting of import list for type + # or class. The only difference is single space between type and list + # of constructors, selectors and class functions. + # + # - true: There is single space between Foldable type and list of it's + # functions. + # + # > import Data.Foldable (Foldable (fold, foldl, foldMap)) + # + # - false: There is no space between Foldable type and list of it's + # functions. + # + # > import Data.Foldable (Foldable(fold, foldl, foldMap)) + # + # Default: true + separate_lists: true + + # Space surround option affects formatting of import lists on a single + # line. The only difference is single space after the initial + # parenthesis and a single space before the terminal parenthesis. + # + # - true: There is single space associated with the enclosing + # parenthesis. + # + # > import Data.Foo ( foo ) + # + # - false: There is no space associated with the enclosing parenthesis + # + # > import Data.Foo (foo) + # + # Default: false + space_surround: false + + # Language pragmas + - language_pragmas: + # We can generate different styles of language pragma lists. + # + # - vertical: Vertical-spaced language pragmas, one per line. + # + # - compact: A more compact style. + # + # - compact_line: Similar to compact, but wrap each line with + # `{-#LANGUAGE #-}'. + # + # Default: vertical. + style: vertical + + # Align affects alignment of closing pragma brackets. + # + # - true: Brackets are aligned in same column. + # + # - false: Brackets are not aligned together. There is only one space + # between actual import and closing bracket. + # + # Default: true + align: true + + # stylish-haskell can detect redundancy of some language pragmas. If this + # is set to true, it will remove those redundant pragmas. Default: true. + remove_redundant: true + + # Replace tabs by spaces. This is disabled by default. + # - tabs: + # # Number of spaces to use for each tab. Default: 8, as specified by the + # # Haskell report. + # spaces: 8 + + # Remove trailing whitespace + - trailing_whitespace: {} + +# A common setting is the number of columns (parts of) code will be wrapped +# to. Different steps take this into account. Default: 80. +columns: 80 + +# By default, line endings are converted according to the OS. You can override +# preferred format here. +# +# - native: Native newline format. CRLF on Windows, LF on other OSes. +# +# - lf: Convert to LF ("\n"). +# +# - crlf: Convert to CRLF ("\r\n"). +# +# Default: native. +newline: native + +# Sometimes, language extensions are specified in a cabal file or from the +# command line instead of using language pragmas in the file. stylish-haskell +# needs to be aware of these, so it can parse the file correctly. +# +# No language extensions are enabled by default. +language_extensions: + - ExplicitNamespaces + - FlexibleContexts + - TypeOperators + - DataKinds + - PolyKinds + # - QuasiQuotes diff --git a/README.md b/README.md new file mode 100644 index 00000000..081a1ef1 --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# funflow-interface + + +This allows a UI to be used with Funflow. See the inner project for +details. + + + diff --git a/funflow-cwl/LICENSE b/funflow-cwl/LICENSE new file mode 100644 index 00000000..5afcf975 --- /dev/null +++ b/funflow-cwl/LICENSE @@ -0,0 +1,30 @@ +Copyright Tweag IO (c) 2018 + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of Author name here nor the names of other + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/funflow-cwl/README.md b/funflow-cwl/README.md new file mode 100644 index 00000000..04d3bf06 --- /dev/null +++ b/funflow-cwl/README.md @@ -0,0 +1,295 @@ +# The cwl-funflow Project + +This is an implementation of a subset of the +[Common Workflow Language](https://www.commonwl.org/) using +[Funflow](https://github.com/tweag/funflow) as a backend. + +The executable we provide is called ``ffcwlrunner``. + +Executing ``ffcwlrunner cwlfile.cwl job.yml`` runs the CWL workflow or +tool ``cwlfile.cwl`` with the input job file ``job.yml``. + + +## Installation + +### System Requirements + +To install and use ``ffcwlrunner``, your system needs these: + +* [stack](https://docs.haskellstack.org/en/stable/README/) +* [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) +* [docker](https://www.docker.com/) + + +### Install Process + +```bash +$ git clone git@github.com:tweag/funflow-interface.git +$ cd funflow-interface +$ stack install +``` + +## Why? + +1. Our CWL implementation capitalizes on some of `funflow`'s advantages. + Namely, `ffcwlrunner` has some caching to avoid repeated work, the ability + to nicely distribute computation and internally has typed verification of + the composition that happens in CWL workflows. + + +2. CWL has several nice visualization tools and UIs that effectively allow + data scientists to write powerful workflows easily, and then execute and + edit them with all the power of Funflow. + + +## Restrictions: Our Subset of CWL + +We only support a subset of the CWL specification. We lay out exactly what is +supported here. To understand CWL, take a look at the official specification or +the user guide available [here](https://www.commonwl.org/v1.0/). + +The CWL specification uses the YAML format for its tool or workflow files. So, +we describe our restrictions by specifying which fields we support and what +types those fields must hold. Again, note that this is a subset of the CWL +specification; we are specifying which valid CWL files will work with +`ffcwlrunner`. + +Usually, our specification just makes more basic fields required and supports +fewer obscure optional fields. + +**It's critical to note that excessive fields are ignored. For example, we do not support the InitialWorkDir requirement so a CWL file that has this requirement will not behave as expected.** + + +### Command Line Tool Files + +#### Required: + +These are the required fields we support. + +- **class** must be the string "CommandLineTool" +- **id** must be some unique string (all ids are unique in a file) +- **inputs** is a list of inputs, with a few changes + - **id** is required + - **type** is required + - **inputBinding** only supports two fields: + - **position** which is *required* + - **prefix** which is optional +- **outputs** has a few changes + - **id** is required + - **type** is required + - **outputBinding** is required and it has exactly one field: + - **glob** is required +- **baseCmd** is required + +#### Optional: + +These are the only optional fields we support. + +- **stdout** is optional but must be a literal string and *not* a reference + like `$(inputs.someinput)`. +- **arguments** is optional. If it is provided, it must be an array of strings. + If no position is specified, these arguments come directly after the base + command. +- **requirements** is optional. + + +#### Significant Changes: + +- There are no runtime environment references +- **stdout** must be a literal string +- We don't support any All outputs must be obtained through globing. +- All positions must be unique. This makes the ordering of command line + arguments explicit and organized. If this is not the case, **the executable will refuse to accept the cwl tool**. + + + +### Workflow Files + +Workflows must have the following form: + +- **class** must be the string "Workflow" +- **inputs** is an array of YAML objects that have two fields + - **id** for a unique id among the inputs + - **type** for the type of the input and outputs +- **outputs** is an array of YAML objects with three fields + - **id** for a unique id among the inputs and outputs + - **type** for the type of the output + - **source** a string of the form `"/"` +- **steps** is an array of workflow steps with unique ids. These have the + following form: + - **id** is an identifier unique among steps + - **in** is a list of YAML objects with the fields + - **id** which is is the id of an input to the tool or workflow specified + by the *run* field. + - **source** which is a string of the form `"/"` + - **out** is a list of YAML objects with the single field + - **id** which is an output id of the cwl workflow or tool from the + *run* field. + - **run** is a string naming a path to another cwl workflow or tool, so long + as this reference doesn't result in a loop. + - **scatter** is the optional CWL scatter field that names input ids in a + list to scatter. If it is provided, a *scatterMethod* field must be + provided. If an input is scattered more than once, **we error**. + - **scatterMethod** is one of two strings `"dotproduct"` or + `"nested_crossproduct"`. The string `"flat_crossproduct"` **causes an + error**. + + + +### Job Files + +There is no official specification for CWL job files. For our purposes, these +are just JSON objects whose fields are the input ids of the CWL workflow or +tool. These fields store the data of the expected type. + +For instance, a command line tool which has as input a string with id `strIn` +is provided for with a field in the job file like `strIn: "Some Input"`. + +In some cases, the input to a workflow or tool is optional or an array. Here, +the job file must specify the type of the data. + +For optional inputs, the id maps to an object with the fields `class` `items` +and `value`. `class` is one of `maybe` or `array` and items is a CWL type. The +value is actual input. + +Consider an optional file input `example_file`. The job files would have a +field like this: + +```yaml +example_file: + class: maybe + items: File + value: + class: File + path: whale.txt +``` + +For an array input with id `filesA`, the job file would have a field like this: + +```yaml +filesA: + class: array + items: string + value: [one, two, three] +``` + +### Allowed 'Requirements' + +We only support two requirements, environment variables and docker. +That is, `EnvVarRequirement` and `DockerRequirement`. + +The only supported field for docker requirements is the `dockerPull` field. + + +### Types + +We support all input types **except for records**. + +The only types that can be listed in outputs are `File`s and arrays of `File`s. + + + + +## Usage + +Using `ffcwlrunner` is easy. It takes a CWL file, a job file, a name for a +directory in which to cache stuff and then a **coordinator** +that organizes distributed computation. + +There are three coordinators we support: + +- A **memory** coordinator which is not concurrent and executes computations + one after another. +- A **sqlite** coordinator which just makes a sqlite database and concurrently + executes computations using the data base to keep things straight. +- A **redis** online "database" analogous to sqlite. + + +### The Command Line Help + +You can use the command line interface to get help when using `ffcwlrunner`: + +```bash +$ ffcwlrunner +Missing: CWL-FILE CWL-JOB STOREDIR COORDINATOR + +Usage: ffcwlrunner CWL-FILE CWL-JOB STOREDIR COORDINATOR + Execute CWL workflows or CWL tools. WARNING: All Hints are ignored. + + +$ ffcwlrunner -h +ffcwlrunner - A CWL implementation using Funflow + +Usage: ffcwlrunner CWL-FILE CWL-JOB STOREDIR COORDINATOR + Execute CWL workflows or CWL tools. WARNING: All Hints are ignored. + +Available options: + CWL-FILE The cwl tool or workflow file. + CWL-JOB The yaml cwl job file. + STOREDIR Path to the root of the content store. + -h,--help Show this help text + +Available coordinators: + redis Use Redis coordinator. + sqlite Use SQLite coordinator. + memory Use internal memory coordinator +``` + + +### A Simple Example + + +```bash +$ pwd +.../funflow-interface/funflow-cwl/test/guide +$ ffcwlrunner inp.cwl inp-job.yml storeDirName memory +$ cd storeDirName/item8* +$ cat out.txt +-f -i 42.0 --example-string hello --file= /home/divesh/tweag/work/funflow-work/funflow-interface/funflow-cwl/test/guide/storeDirName/item-f174a7c27a12c55ae8c8fcd2fbbb20cf4be4a795a9fdf3cd637e81e28878bd35/whale.txt +``` + + +### Using A CWL UI + +We can create CWL tools or workflows using the [Rabix +composer](http://docs.rabix.io/rabix-composer-home) available +[here](https://github.com/rabix/composer). + +After making these `.cwl` and `.yml` files, we can use the `ffcwlrunner` as +before. However, **we need to make sure that these are of the subset of CWL +that is supported**. As long as we don't use any fancy features, this is easy. +Here's a helpful checklist: + +* The only requirements that are used are `EnvVarRequirement` and + `DockerRequirement` specifying only one image. These requirements are only in + command line tools. +* The `stdout` field is a literal string. +* The outputs are one of two types: `File` or an array of `File`s. + +#### A Screenshot + +The Rabix GUI is friendly and intuitive: + +![Rabix GUI Screenshot](readme/RabixComposer.png) + + +### Checking Valid CWL + +If you use Rabix, the produced CWL will be correct. + +To check errors for hand-written CWL, we can do the following: + +```bash +$ ls +some-cwl-file.cwl +$ git clone git@github.com:common-workflow-language/common-workflow-language.git +$ pip install schema_salad +$ schema-salad-tool common-workflow-language/v1.0/CommonWorkflowLanguage.yml +some-cwl-file.cwl + +Document `some-cwl-file` is valid +``` + + + + diff --git a/funflow-cwl/Setup.hs b/funflow-cwl/Setup.hs new file mode 100644 index 00000000..44671092 --- /dev/null +++ b/funflow-cwl/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/funflow-cwl/app/FFCwlRunner.hs b/funflow-cwl/app/FFCwlRunner.hs new file mode 100644 index 00000000..0691b4c0 --- /dev/null +++ b/funflow-cwl/app/FFCwlRunner.hs @@ -0,0 +1,123 @@ +{-# LANGUAGE GADTs #-} +{-# LANGUAGE QuasiQuotes #-} + + +module Main ( main ) where + +import Control.Exception ( displayException ) +import Control.Applicative +import Data.Monoid ((<>)) +import qualified Options.Applicative as Opt +import qualified Database.Redis as R +import qualified Data.ByteString as B +import Network.Socket.Internal ( PortNumber ) + + +import Data.HList +import Data.ErrorMonad +import Control.Funflow.CWL.Run + ( tryRun + , Args (..) + , UseCoord (..) + ) + + + +main :: IO () +main = do + args <- parseArgs + let run = tryRun args + let ioRun = runIOErrM run + result <- ioRun + case result of + Left err -> do + putStrLn "Execution failed: \n" + putStrLn $ displayException err + Right (SomeHL outputList) -> do + putStrLn "Execution succeeded." + putStrLn "List of outputs (in the content store): \n" + putStrLn $ show outputList + putStrLn "Access these outputs by going to the \ + \folder item/ inside the selected content store." + + + +-- # Parsing Arguments +-------------------------------------------------------------------------------- + +parseArgs :: IO Args +parseArgs = Opt.execParser $ Opt.info (argsParser Opt.<**> Opt.helper) + $ Opt.fullDesc + <> Opt.progDesc + "Execute CWL workflows or CWL tools.\n\ + \WARNING: All Hints are ignored." + <> Opt.header "ffcwlrunner - A CWL implementation using Funflow" + + +argsParser :: Opt.Parser Args +argsParser = Args + <$> cwlFileParser + <*> cwlJobParser + <*> storeParser + <*> Opt.hsubparser + ( Opt.command "redis" + (Opt.info (Opt.helper <*> redisParser) + (Opt.progDesc "Use Redis coordinator.") ) + <> Opt.command "sqlite" + (Opt.info (Opt.helper <*> sqliteParser) + (Opt.progDesc "Use SQLite coordinator.")) + <> Opt.command "memory" + (Opt.info (pure UseMem) $ + Opt.progDesc "Use internal memory coordinator") + <> Opt.metavar "COORDINATOR" + <> Opt.commandGroup "Available coordinators:") + where + + cwlFileParser :: Opt.Parser FilePath + cwlFileParser = Opt.strArgument $ + ( Opt.help "The cwl tool or workflow file." + <> Opt.metavar "CWL-FILE" + <> Opt.completer (Opt.bashCompleter "filenames") + ) + + cwlJobParser :: Opt.Parser FilePath + cwlJobParser = Opt.strArgument $ + ( Opt.help "The yaml cwl job file." + <> Opt.metavar "CWL-JOB" + <> Opt.completer (Opt.bashCompleter "filenames") + ) + + + storeParser :: Opt.Parser String + storeParser = Opt.strArgument + $ Opt.metavar "STOREDIR" + <> Opt.help "Path to the root of the content store." + + + redisParser :: Opt.Parser UseCoord + redisParser = useRedis + <$> Opt.strArgument + ( Opt.metavar "HOSTNAME" + <> Opt.help "Host for the Redis instance." ) + <*> Opt.argument Opt.auto + ( Opt.metavar "PORT" + <> Opt.help "Port for the Redis instance." ) + <*> optional (Opt.argument Opt.auto + ( Opt.metavar "PASSWORD" + <> Opt.help "Password for the Redis instance, if needed." )) + + useRedis :: + R.HostName -> PortNumber -> Maybe B.ByteString -> UseCoord + useRedis host port pw = UseRedis $ R.defaultConnectInfo + { R.connectHost = host + , R.connectPort = R.PortNumber port + , R.connectAuth = pw + } + + sqliteParser :: Opt.Parser UseCoord + sqliteParser = UseSQLite + <$> Opt.strArgument + ( Opt.metavar "SQLFILE" + <> Opt.help "Path to SQLite database file." ) + + diff --git a/funflow-cwl/funflow-cwl.cabal b/funflow-cwl/funflow-cwl.cabal new file mode 100644 index 00000000..ab97c057 --- /dev/null +++ b/funflow-cwl/funflow-cwl.cabal @@ -0,0 +1,106 @@ +name: funflow-cwl +version: 0.1.0.0 +synopsis: A CWL implementation using Funflow. +homepage: https://github.com/githubuser/cwl-funflow#readme +license: BSD3 +license-file: LICENSE +author: Divesh Otwani +maintainer: divesh.otwani@tweag.io +category: Control +build-type: Simple +cabal-version: >=1.10 +extra-source-files: README.md + +library + hs-source-dirs: src + default-language: Haskell2010 + build-depends: base >= 4.7 && < 5 + , async + , bytestring + , containers + , directory + , exceptions + , filepath + , funflow + , hashable + , ilist + , katip + , parsec + , path + , path-io + , process + , scientific + , text + , transformers + , unordered-containers + , vector + , yaml + exposed-modules: + Data.Nat + , Data.HList + , Data.Vec + , Data.Graph + , Data.ErrorMonad + , Data.Existentials + , Data.Type.Equality + + , Control.Funflow.CWL.Types + , Control.Funflow.CWL.Parse + , Control.Funflow.CWL.PreProcess + , Control.Funflow.CWL.Convert + , Control.Funflow.CWL.Run + + , Control.Funflow.CWL.Types.CWLTypes + , Control.Funflow.CWL.Types.FunflowTypes + , Control.Funflow.CWL.Types.Schema + + , Control.Funflow.CWL.Util.StringParse + , Control.Funflow.CWL.Util.CWLUtil + + , Control.Funflow.CWL.Convert.Job + , Control.Funflow.CWL.Convert.Tool + , Control.Funflow.CWL.Convert.FlowCmdWrapper + , Control.Funflow.CWL.Convert.Workflow + , Control.Funflow.CWL.Convert.Wiring + , Control.Funflow.CWL.Convert.Scatter + other-modules: + +executable ffcwlrunner + hs-source-dirs: app + main-is: FFCwlRunner.hs + default-language: Haskell2010 + build-depends: base >= 4.7 && < 5 + , bytestring + , directory + , funflow + , funflow-cwl + , hedis + , network + , optparse-applicative + , path + , path-io + + +Test-suite tests + type: exitcode-stdio-1.0 + default-language: Haskell2010 + hs-source-dirs: test + main-is: Test.hs + other-modules: + ghc-options: -Wall -threaded + build-depends: base + , containers + , deepseq + , directory + , filepath + , funflow + , funflow-cwl + , path + , path-io + , safe-exceptions + , tasty + , tasty-hunit + , transformers + , yaml + + diff --git a/funflow-cwl/readme/RabixComposer.png b/funflow-cwl/readme/RabixComposer.png new file mode 100644 index 0000000000000000000000000000000000000000..68af638a73b3289d0e80291c3722139f4cb5ac74 GIT binary patch literal 101609 zcmc$`bySsW-!6)}R7_A26a*FqNGl>pBPvQu2+}Gk-CZhJh^PoiHwXwwHz*1SNOvn8 zlG1su>0*8F9((LF_BeZddz|^l`?97mpJ(3j`(1TE&u&UzKd_f_FA)*Z0kIob<%o!O zyAcunb%}U8-qA}{B*XvhuoMwfASNd6{3-JT|4C|f?Y5P?sjijnT?-u|d3|duD;*21 zhjn|1i2f!LyLwr{uH#p?qp*VY#^y}zxeK3&zO0YAJ#^p2sBx3+A%#NI_s)lgDtXF@ z$;}DfDILw~?CUnF6G19j8se=isSO-QRL@nMICO;b=H<&f59QYWot-|WBvh(p}zttMX0D zl$}^!WB9H{?r`hRK8h3;X<4bwanE`sKEdvdGwj9}dp1`hKWE3%Ze8ogu8gC?O4=^w z(HeALKU24BQCzjUlQT-SxfHq7nH+Cu?(Jw-=IVGkqU9`~eJ{U=6B(li&(X*FdiUk? z9!+f&t5-g&{l09^y+0;5M&#(vDHiwHmiZl9AFdXbxV!H0!?)_ClV8XsKRDU0Q^Zr8 zqF>qIzv4eXvsw{w&39gu&b^X>)8JRrvqLnMhTqd{%xjrFZI{{Y45gpS5z~$Bl@r>q zt9^a1kaX|j^zqv7&&-l9Eloc6wq*7aAX==&lc<-FPWT+n#b=e`K>PruvOMwlJ^T0E*P*_0 zt%V}!P2+DSFOk7y^Oik7yTj}j@dHXn-_Wwh7QTRXwg;yXm9n8(1+fBvdY-C&IC z>$Ht(xtX&5Lp8=Vd6ZY`DO^`opR;MVt*3wCcTX1iE5V(#=7ISUTAIO07AucT_%pWnY+5zJoTD9vz!&(o<`bzvc9^LH#CYfO479KH@j1VGrSvH zQY>0o@?Mg*104*U)B)fzfL>-5<{#|7S3SnUl$d$2sIJeD8XD@a>DSTste(L6M*4Lw@ykq_oHN z+jh5~%02xkNH-~=(QR?8}zja$nNvFrvA7&y9I6c00VjVOGlYA|vn z`olL#cI%g6=Obpji(_$fi92#th1$3lvb=isJ#Tm_)o!0BOH*UL z^SZbPX^fv<=}9w(S39OoZ7qhR9C0G&nLFYUynUmjyXoAgpB_6pTe>0;aP-h4)jfOy zC6UfoEi}wSrmb@}l!Y!R43Qr{difCRJ!QhmrJef5!qVKj&qIVb;{34`>(fe{gC`n# zuNze}H}Bab=Si<@y?$md^Z17<8MPqCu3t~0Tr@7n&(6H!3bd6y`*3B+s^-|8-J2Vf zsTWgjGCbTLFj`7uPO`d6b*gFfegMU8Z#i=EmVKMkhQ=LZcRJfTxg6O~cU*UhV14g- zkhz6Cenn=ww%b?vCIz+JdsfoGXi^hr;(xwZ_^qT}r~w&G;t?{Noj#+A^70Mr2SZ03 znQg}Ul5ZI{?qBzbl_8nAIcCw4(otW3J&CO3&bcf(*{B2JUamJ^l_xpd^NW;pT@$y7 zV2l2{u!%viMCt4`D|bf~2M1ZJo4WCJr_~&nW?V_Kx*ZSE4EhvEsJ^$XVIjSI;bh;K zZBi@w*olKf$DPX_+fTC*S`}V(2`$@4@=BT{3wcczf-hCA?>KNx^Fy1}xuiS4n!^2F zCncZD7kS^WLiNMP*ZJXx$9(zaPZ$+-V#(=udJxmOpEp&qFi?B% zE#hCu%u{>p9hqr`cM6BZVASDx`_cAmf`>K~sVs@ZNQXDFGma*Hb-#PJNc@UN4IN9z zsXF!O7?;#u2ElL2%9;v`VIIDd5k=4Ez7MG1)w)8)8^XcD`#mrIWAxogiN+ph&5JyO zlCrOJnR#RmaX7zqy?(3wJu}<)io`WjLnf)G#b0Wv)Kf)HpK)L1J;pXPs>1xMzA{u( z)8fP2v%T^$hVp4g>C(TrYLs$2ywfdjdCUJZl+;D*R0Eb-mSgQHr+4)BhLwk|EonVC zSVDK2?dwObGphQN-haF9`e!!HE++j|m&=$dy6FCX(~FCGdw&U8d%L5>n23`*sfeu7 z$KfceLfQA6KgDEZyt6CmRKo@jowt9tu%6*v^px1Ot2^PYPF<58jpgPg9-Z+HPC9p{ zbDxFo^?l`892e}!v~E5We>qdeJza#D?!<~@*rEB2a>j9`7-C=gno}nwjl17&4(O3z za%HJje7_?quJ{#MxB1TJ^P}TR%KoSK1Q)Ia2p$yQtYGJ#m@%IX9mpINy{~uWN=lc0 zl|XS1k;>Wi{*qfNNpvi9U*(Lx@Z3|lF}uP){PaCl($j{r9;|5^XHgF$bxkrF+P=Tt z&4{0o$PWzt<@G##9UUF* zE=~9(lWmM+cmLwt`p|HBQsIA*0PoIi|IKfo<&E}z|Ni~AZ#SwM`}+DKBO|-I)Cx6v z7oJmk(Vss*Qx|bXB`K?Ur^uBnmX?;CsX~-qqQtL*f;wL|Z|xr+93hcf-KG2%WuxHO6_Tsg);$l}5 zljQXDbkQhACMJiC<>3@^vmHccdg-aD=H}+{2?>$RZd51zs|pJWUWjVh+w&9>u9^`P zxudhA$l1}tB8^les@~nh1J_K_D0Em`nwg+^q^6*d;k>#qUi*@QP3@B9(05;ErDV-w z4N9k^dVO--l+*HT#FZzr_jcGGCL!_e=;$ab6V=qzq@oJiN5NLd@X7b#!-wRoDg&dV z%C~PXbr`1HQdDeU_+9d^&!<~&j~MaF|l^s z8SdW1WYV_RxwWnBlJ>V(v$GbAm;Dlq_aEmt&B>WjP@uN=DMrZW&6^ArV`=G{9P@tB zmnTMl{Zdm@Y-wsb?M}RZ|J=+BBP(n3sFme#jn|78{8l5cGD_>}>h3qj=H}!C^H`Rp zk(d@O4@G$k=IK=grT0ElA0RJMBDd(3nbLM z(Ta(2QbAnW-$?HhWyZ9B{d#rWIaJ8iMOOAT{#sJ<1dl~@adEM9Tsj+9q+;Te{l_hO zofp-4Bn()Yn8Z_BRYe=$H;)xLuhP@gtFVW?dpClcR#P*w|5WjuFEk{i+nSB%&L_9m zr>-yjYERF}v6~yIzkB!Y^_M5^TZ^%?r#zu?ID6qjBS&dz>EP?@G|QuLVJ}2aIlt7* zkBz0zROv3;Ud#Vm^5)G~q$SPGw_@aUw6!xFRmWSB_%M+%68;_8E3r~RFKLA|WM$2L zo&>*rJBJC93gjG3uNCb7OL(=ZrA4FmUU$Cj;^HEO$iTqBh!yV&fsf?K$~8re6dbs5 z+(bd)E$O}G*}-Sep7|+zlCwHY<_>3>_Oc0B+t~EvTE@+3I?=gH$2m@a-i>8Hl{*|- zPUHBYsAvQGAtE9I%a}RsIa8Pvcgxl38zm z{84|Mw%H(4j!3|ANHRb&wsAB#Bm_%2$8P4{sM+Dehy7SpV_U~PpFhX@{_L7X_e!7J z_Sj$V_~P#F{`T!#tdZ+9_5;=2y4&`u5yFLvAZ=H}Fg zp&{Lx<2N=xQ(ZEf13AXT{`V01wF~$Txwx>&#@aIej6`Vd zV{!3jr7v@mr=$Dh$H{8BXPxa=LDHnoiZ@161_xAEkpmNPiF4YT^Sp>m1wDbUL$5H4E%gIVB9nzCJsG z+r6My#OHc1oja77K;XcJi&Cn51Oa$GczL_Z+z-we8uXM_&pTdknR- zd_qE~DJYbbl>-6-2sBXu#Eg_6b@Z%P?4vY85x<{qs)qH(_cvN_q4czmRA20S{FN1 zQ^j6N8NuZNtO#`_CEKOxpP7cOfs(Q1w61Ft*}Z}`zuNMw$BQ;r#&dEmadT(y*nKdV z-`=7jS`3RV-*#%FwRmH2csSc?v|*}vQ}Eomn@NhUSarQlzrC#c+1S|9^=c;@<79Bb zR!vvdqf=?2`R4s)SiR9{X=$dtMWzKaWm?_>iV6x%_*K0y=d84}hN>#Vj*R=bLJ+s< zQ1AoNlY)XhSSg*Ij#E8_B2Q6zn0zbmet9f56-9N%zv|S31Ya_LD7c%5=u-&O-+za{e?LQ@gD!MVz(MD|_FN?RuBvAA4@HiCq z$mw07_fcjK3kqUB;OZA>z$drcMV?taZvGM|?s<`-9ScNMA&=KO^CX);H|M-Se>~yt}IlYhdEXkLfs}^>~0hYF1lq zqL8<5PoIe+uN7Df=6uIZM|ZcUz#d&PDY-4uL=><_fs{u`sJQeV)&rJ{T$NH*RK0$3 zmTAK=Kl1D=Zx^bos>UmoMTq0&o_JX2Ib%VR?=#Hoc>n%vh_vk>>yb>ABn21k$*x?~ zP89n$&voLWqnB1!6PpQ>q@J6oWV3IYirZms%q&^DO@UOZN((B$dz7^W__4RUdEbf=gehAyx zEJ$$$`TFYE8y28Z$n7__-@UxDlC@;W?5=NMFjgOR-N@({{ud=@hB?J0E;begXm)ls zFpzSz!`sUITUAwJY;2h}hnWBU#KgqKsa_$gk(*Vt%BH4MfGIWa&J(U35pj2QVM43y zMe4zD4^l#-Lk%}DFhIqSmy>f?oWvHJ+_qzv(_H=a;L|yB($X&_>BoDEi^&8e;%??o zxfyc=bO=zOQ7zpH5^^olx%&3ZBfo~>A3yHUeceIAKb>8?p7dvGlbQ`;mYREeHJNDX zoHyTAo){h)5?t)EY#QKYuOH^@lHAj%d{DGCqlZPHg??yb}#0Lw$Ys;zcqphDbAb(eA!80|;e< z?}6gRDpX4L{OQxD*5fUivZPsgc^w?Bv%)cQ*psRae}QTY44f9o>dI0euJ6LpKJ&sclwdWQVHp+!IQh{=ml$5ai zwaQzDwfyN0 z^9C|9G7`Hc#>Nc9!mvntoEN)oTrNy}Dn!lmdvmD4c`aInT+X1tVo<#5RS&3(Y6=#9 zjA9}yxAGfN-J?g3DnE7;^JCYX{PhdJREbTCU&02ut@jm7q6_E-&>+-xW0{hV`z+&LWXxngYn5i?12=OS_W52kDOOx0* zU%!4G4s+GWi;0LiN9>k(-@qVEq4s@JQa8G~x3`Ru(Fe{L>Zpb}heGifxwB+)Uq2`& zj*pM03pX)^Ko)^p30vRWW0JrqhSUAi1YWciu#Mx?YtZYiMXFh=%jP>+67*HtSTk z5}O-#(u{^jt9}tnNJx;RZv=seVdj>WmR?v`u(r0|N6zw!9GEon^BsK?6PgRUlK3ak zh;}0yA(u7mSXH$H+fSn`oDzNUvA}%5Vi|+7IN5FJ+}HgoGV&Wkz}7d8XUCY2?~Fdw0)7<4WlRZ{ zBZ`vBiCuU9{{061J|G|#wVXPRS>E&K&3~47pmwDsCg#^iS(=+G;|iQ@%9OoHt>ZpE zKHNraH`UY%(AMvRmPRRO8G$CY^_6-?MMi44EbCM)jR1mUlivTn1n35vh zZ4+FCMN~Qd`O)qe6&dtXjA%{(*XrVwslC(C_W*Qmb$7= zY``vw@n0n@qli4)f2wyrd)~(!b|{wZzNE=~f5opke|b zc3IX|qi7~4Pj{(StQA|RI-#dhx#JSTl+ z<(PaydFS?H63wEb_p7WVTtaU-C>D0D{H0r#9{@?Wlj-M&J3T1~BESp~RZLiyL1qVL zOx6F#?P8Zgr~o>1K8lGz2g%lklwP`k@(zU>fhPCw;-{AE(N1s~aB8d-*5V0Yi=UV< zV!G(_RiJMw1YmAh`ur#rmy!N;y9^XCFd>i<<%0_kcGJ8P6%d;Kw4=(Oy%*eW{sU$v zMB4xDTkXQAARU%3d7TO-aR zLPf=g_8%arNSN{=BjJ4NOJ;x5(ftII5!zUa;ylB_F$?gVQ?V&<+l18&ka_(05c_)R z+V8Nj_9V+=YNthZ@(K5%WLfgTy zBJ z_o#i00G};8xj(4tTaWum=UCW}vufn-_(Uy}q}aG;$;+o|uw`Cbg}?BPM#|#v--cS- zKon3yckSLyi-DNv$jlDc&J7Fe#n)wMUMDg+Kt)BB-tLqcr)1C@k`KYht@q`pPoJ6- zl_OOhp=@L1Q9}@0gxc4*XQ#k+EZQbtkTAaz^z3qB{7$R35E}NJvN=9UWIb2R{5) z5_JnYbo@AvUd;(q5D>~F#e9S2gt4))gT0mL`CVOI3QWGFCHkCb`w0q6Ns2*XVVgiL zJ)r_$h(}b*J3E7D5A@;1xCT#U(yJy;3IK`jh`g0IRbpcO8ndNpi-n1E_9$7Y1$7S zt@;X?K(FG>8K7GYn7^HgXh*B;uFIZtfHUJ(dFUqdY$nip1WHzKV|IX z1nHYwQLSXEb7C+x93N9dQ9mkZ}xR6)Fp=TiupR=&+d$Gtvm z%7uweTY<##uU{2F_Zt$ALu5I87{c(qbH|{yO!s>WwY0Ws);@pm-~s3g{;aS2kJVqy z=EET4S2ftskC7noqwyAF?CiZBksm%7p(O(@gk+3jY0!OrNzDgR$){8KmY^)yj0bDl z?s>VgvQk%f6R@w!Z2`<(eY5I5M*v#V8TVHe+B7sYzlW+<`)N0GpmZ4~-lPN5c*=nf?#&t zN#iMD(4C^9BJ_~t_wP|_#xd|BA|?KsF88^D>^lh}@~4nW4pAl^9((i!O0OYEcXM-d zWFmI<_VXk4{h&|OnXFYrl|R2cS;T+n)rK~FjDwPqg#Hn=T^}?U`sDYT8WYUD$WyEm zZZ585l}rQZ2O#;(Y-}3@P>>$4X-m{yS7$cX6c0@g3cMT)?X$ZMo_H4!z*v}J*qXeK zLB{aXxgX;;QM-Ee>v&3WPvp+~$)u451y0}?5Tz(YjJk5ndyAZbzPiAg(Ci4kUd)F+ zH!qKzjEu0<0OK%ewSud^Hr7`?NC6Gxd2K5=&s7IM{yxHyvrshZ__;f7 zA`!>Pk16J@Oa=Qw1@x*T zCr%h?Y00A?zJ7g|lhWAOSW8O_&dvT^k2ueBawRFwi zp9hkqmmj&4VgZYQM-$V1Rnm06c<<}e@bGYm2^y|M z>xn7b3ZYEWU3q-NdpAl=-`8hAmiy>{+ogjq9ipN#6frgGsRS*G+-)kXXw9HV^d0OPAQnJob1l0 zwfphFi;BBwx?~@iWN(^|1Z*N~k{^(j+O)h2XUeD`L43j;4%LKIQO#38m#9N=P>kXp zzc7G`7v?l81}26MBT`>kN(FN5vc3`%7iZd?mswEIWwE0CUV#bk!uVQSbMg|^Qh(Ue zi}ky)j#kOW&hFpSBSNgH*^5?Au$(~TVC2a&`BHk7)z+Fq#{=`?KDHmUV#T;fo4eP? zm~(Psq7a3uR%lZ#Npbh?-C+Wbij>uP&Z{;tay%GOGz^f>d2}Dh*KamnS$!aA(j#>d zewvdvD8784c!y4j?+&+WVWHDhXs+%GYKoHKm z`4PnB3zLO)B2a9%Z{Ln@8AQ1Eh?`eMMa2R8sZeAZQF9?qp<7;LV2Fd}&BvFo)u>13 zE*cg8;X_8ztTtEBCiGDW{|}EzXnX4FUIhmSzj@OD)f~v<`pS_>Oc+|#M0b9+gg={~ z&pCQ}(Zpt#*$M{i`I(s+j(``n1_b<*a{%*gf;QIBkM4ED;~feZjopuJ5&~sV4O}YU zGE(Q%V^s}rJ~`t&dAqr}nchc?SXP??U zuRPx04g&*AAX*uG6lAh3RSU5=8B_rvdr#{@i(G~ITWtQ!zLn5moR@w+X<(7iI0v;E zNG6QeTAUa}@TF{&=(Vd?g9V*cR9FCgE?&H~Qolmz?l2K(XeP(TR5Ua~-@G~L{tXK{ z$1K8H=O+MwPX#Bs#X5F;N2Ua2zL#okS(z>x5_pOvy?+(re9-yIx%^V#O4rs>h`>+a zfMbf$f@;g^w`c!;ma}JH)db@PLIfPMO1GnqU@v=ld5Js);|~>ZRN)E?3uAX?3b|w+ zDHA5xaO(rSgoXw=x~urI06_#bnTm>#06PP`3>zE$3-)Np{Ptas=;-NV3kqPG z^rP7so0t@J#57&=B=`06gTtJcmj_=rCoeB6wHx(I+*Rc?+AW52>J{A;IXStSFd=sL zC141xd-syFR`8}Di}K0!odhA8+qmQOnSNN@a!D^#f1o4rS`0k3IzEeC2uRsrkV)@T z(b$--nr(vLK}{WLq6W&ySIN}_QqNRbZ&uO_s2;*ipy6QKQwzE9pF3xU4&LB4iS_yF z73rujqyo#)hBKp*aPRV+ot^nIiT?1LaOaXQUy_O`!>}0vaG=rApis}>TSRfF3E@lm zO@7%J3W@#dMD{Hv-}$fTt~>XUTm3K(5ps3Gw4!G=2u^k9w`y|`=1-&Gc8uIbPEIvf z`QjC#y!d#r#O8y?IkeHyfG1ryS9@8vSvfeYKtC@mEF_rESh>urrP>?dFEXaDFlA@WRU;ma- zzQ^fzHJUt>5^I~kA1Y!Osv1t|=nVP!l5E+}An)0Xua{IPE zoXi_%1L296ekc-woz>pnE;pbTA6?(ngzX+fa%g;(^1y)u5XDgL1nj2o;D52aQ(DK- zn&vuLPCNe=Xcz65OJ)tB;^Nx;ec=#n&hZPEQ(9M-m#vrTFLHB3Tij18$bah8DOdrR z7*@d|KQ?t<$kjmqe7wA|F)>N%`3nY89`5c0kHjD|@8ie1($bg-*$jf;`s@e;i%iV6 zDu8_;6u;QpuE(7pr~IqTC5gaSWTVRkGP_i7P7(sB4cO?~*t(($S%U+MTOrVrXdCPFuC(`t|ED@x#Oa9*u`cQNE$} zXO+~+CjVY6f=;>OVE0?q%GQ?s>{+|t)!a!8MTNSJr* zRc_syUmgxK?Z^;w=s+R>OAfw=t*vbphkUH$^2X{E>j7R~UM8~VrJfX3gR|)46q-&m z1Q4wuO5PgP%(t71n_E?!_V)A947(3<@hZ-7sFupff{bL(r>Cc(wy4a~3keD3s%?}~ zXx^57jA~~y-XcXQZOAxrvQ$#;j)D5rHTbd3%{;ukib_hZ_^RSDC{tGGK?FW(I^i+? zD%7Yqc6@BCps+A0C@+H9rIr2686DVpusu=fAzP(|>S$>-qBmSLY&o|7G0F={yC6y_ zA75u4%L^!Cq$MCMFl?Qm=EejL5t0#|R7nX5d9$ZdBO^=XbO$Q+n`aMmUc5MJ#Y;;| z8^4o+g2Gq)jCyn`i{(B}PEIG3kA_>v10;tA1{73PaXSv!lpj8@?B4wZWf?<5eyWnM z4iyR89Gi;uOpvjW5oE95fP?ALE@y&=hf6^`_Y^xCnt+nyQg5e zseXTxV21XcwJPd^%8X$@xM$Dns=*`ll9+{$8?4L4=%rw++1OViPjR~lIg~dx{zlyc zegqZCPE7^6{uC|d1C{*q9W!J#unf%1?0~9Z=fJXop4wqvPZR zUL=JQT2oz}gd5`s_+DNfhaYzC+!U6BjfAm>#Fanhd}3y04z~GeSLka ztE(LfivZK^oI8E`G;CC9L^Jkw#T45#__p;FI+C2Y^s%{PkQ{nyzpGf71z{xj??;3` z=)9Jw=dEbfwfmfyydY5X-Ly`1-QDUja@7GBhM{Z9wfm@!&W$#LC0d%9fonrFrG^M=<-b@D`d7l04vS zV*U4kKp<^+dV1u3j4Pdy2I*c*e+AfxqlmNYF!W@(%Um!#lhJ`kHOndlIzyK$p%}6q>uH%x`01fy? zKt>XNEcK&S@F+w0?Pq(zv9NlJe%J7M3oH=GiM93o^P|iz=}JN-G7K`IbJNo|Bqa-w zCIeA@_~=p0C_dun&!6Z7yB_`QG%Yrsf5F7cN^pSS=7`5Y@$W2lE!Oc12~igo7WP!F z2oZG7Lk*TIQ&3TX!yToV$gY+H@nYNk2cQ!WJrSJ4n1W>kXv3+6!Fpb+?5uAk-mIbe zX5TsX9#y6Vwh#ez60A=Sjx?~D#AX`}RX|$Hd5p%#CvDy;9VSLZs7BJ$IC1G5E^EXE_nw!TSz?8c1H*{o+lD+4=ySFz*}Wn$ zz`Ut~-!&*Rc8?;id@U;z=RT7jYS*f6YdzKDjBa22TKX&_WA3s;<=klkcqjT~e9e3} zZBR;z>D8<5720EMbIS1wU=8!UjQ5ipL*gtRkp%igN-0aV16aC1#cZFa?|9SE5_-~JdmJGX!v4=aSDZPX!KK}Iy zD=o{PORepyKn!$rCsB6jlP6E+8!=}qfBpHF9|xoKUvJy?i5*R`aZ75qJ#6sbp-i7u z2{GWLWM*cTqCZ0Y*AHD37L<4ok;_m#39q$XnW1~3pFmgOI7P%QmKQiUF(LJzf7E#R zMVsTb;Eo*oy&eyHaop<9AL+{O_}?n_9m*rQfasu1aI7;j=3qR{o%-kRiNZao4u*#W z2a9@94g!D%$SErNy?G<2sw!c+6^5&6nScTQ4dmdb?>E-x>S4G5kRb7RE-gO4O44LUrEEgVXyST;-H zqbS61vjPGt#{d1S;vA~{JrSZ&heS^B*?f11oNMasE%rM4=;1>UBzQ-lc`M)qd*~($ z7c~MT%l^yAuuY(%+Loli1ib}(H;I9ZlarWkz`~x2*}=g<0~8KP4`NwW)qLn5xU8@E zEhQyAQ&XghU@n<*Qd%Opl9uL9iUJ5&DJUq2A8y^c1u%?;N^;-;6yd}u!mB^axD%n# z$fzh(>p6#Y7@J^X?xY5pD?qcqXJ!!n6_=2J#@csrE1&MB`PIwIE&0QTw-wqAm-P4D z|78gskcv4JB^1>hgE85X6a>=n`A%E9o(w#4(t8lpkkf>h1M;$e&z{lxs3)W+!MKT2 zp&lKe;zA4zLY}Yz!{2}ZnEv?%AQ6%QjO_0yBwR*qX5bzmx$PYtd+G9QCIVl-oKf`Vdra*|DIW^V3T$L@SOxW=H|9VtV`r6EOvm2_z-9cqn9z=V09T2Phb#L7RftWPW_uwQq^EqDQagJ81x{rpk2d~-s@4) z+uPgOxe7a;Hv~(Kg`R#0^7co-Or#5l8PiL_FC2oD81AXblq5kW(ZN^ zwZA_FDJdxpO=wV1Rn@ZdPCm95}7e=$FsOZ@IiXz3gii-0=)nL4!W2i14KKz2U z^!mBoFSKloOJl5*PlYytO`831BfSSgh~L|>Yrnpc(f8WgDWsA_W`y!P+S+n}Aum7L zRr>WSQqPm^>2VPe5B`Vmo(7elInM9xTj&lAd_*Q1*4CLYS}#&CGcx`xi}+`ZY>!dp zZH*RD-SPip`!aH#NQKRx%1hK?_a`Y1N-vAtV3&VBcF9;SgSWZ6yAUdjHb?zsB9q5z zY$)P!Tc;;of>cPtk$1?><}Tb?Iz;;1|1I6)e`#R;e?3uQB}~NX!+c9n;FrMmQK_w= za`WgL3Ys1Z8=<;zh4}U2%#nHj+0jPD_BP&1Z4P-YR`my(hmfnypDOD7{5b;cBQDGZ zqcXR(Dv~vK|5e8&-dsy!bgMPJAj&mo(T(w?i+~5|yv|M?A(vRb^)E?6vy);H!JLIL z<+@t(SM2Y$zn-|bJldLW^6A}hV8V0p%+0)wY7a?O^M&yk`t1&D;+HO6S_8zR;IZFE-A|Txb(g|_Gq-vYAHVT9>rA$7pV5~T z512MNW_O{R0^v3`Hd^zl!&gO_53}pr<5Pj{f9>B3J7ipN^Q$lxSb5>YJmEq5QoSVl znTf6Ut1>cf#iL4L9j#+3fp;xE8(S0xqi@JFr4<_`%;S=T4^*EECQyh=BB z*thtXfsV6T-?=X~@AOg~IC62~my+wA)yDFjd>V$~f9*EeB-!b44>SPtGr{`#uF1HDc6DsaaOJJ!*s=~?d3n###~piPqJl_EjJU)yFGX-zR7a%WrJUn4G(;rS3~A;>y*?V4&j3RqK>h z7tWmdx|8Wd*Nb^xk4K%ptNllKn)&Xfk(P+wH#PXcDy`nEU@808)7Zen&Y$UUwtAIK zm7=(SRfaPtFwiO{ro(mlpu@Mr!pzM*n0yKEh%=+(FZ`L^Nr&Y(*o?@6^_GsJz9a0E zjDTL!`jq!BfB+Wju%x)H0%xqR$K|lxSFvVXD{VBMv7^+ zjH$$~7OPX|^e59CAxZgj~oiz6GW?5s|u8>DcACo#%iR*upOo<)Q;h>U#v@zU5 zX(g1>yH_zn?7y-AeicR^sNU}R`J?fRW7kP+nuvm%5f*+GD(zvhshgc3yCit0Z_>3ZK zX0>(j&E$roq3}Lg+n)@hsZp`nbK%KzO@onI#viPgMP8;}p6W4_yw-BC>ZAo5 zyp$(V)#lhcI6|TFI#Zt0GVN#U<*53Cr9MxHDk4u|ov z{lQ<1YtTu-OJF>>xVYTEzbWujhoc?R{0UN0v!U!BOMBR7x|u>R)Sc$mUT3%Xh3dPM^|jt)qnx+wNBX*w zW7Hql>~UTS6VZ)gzohUsYba3l{#ibG8*RtwDgPiZDXBb9Umldpa2sm1-|gzI6C763 zBd4eWrOFbz3S)L}@=gCXShX3Qj^h%)<$a%7+d@ZbW6}Sh@gWg~L6>o%d!b%Q3A1f% z(tK+wf9>3fR2+<0K|paF3)@3NQd?aOG5v3We|C)9I33iWd?}mKmeQ%oCoQ@uCu~<2 zRZwNQ6@m-j&YWi;o#co8sDgAMBr!tP;^x`!x|Uj6QQ|R&MaYm#K=2b z)aE}Q+$Bb4_1Wu9Cr^9cQVY3G{n4CLP-O`GsJgOp1ui*2{4sL!p^*_gXhcY5q!e#- z+&NcwZL3I0|5e9*gMMncZnsokLtvv&-SM1L!1|l63zPiGl^mO!OV;EyB}``f2j2Z{ zscpIat0a|qG^cUwcg9pk>mr`AjCcEHF8HUZiSH@r*f(+h-b>AkA!%j7jMZhb67upQ ze+!eTwLMc`*zv^D#kH%K$CAeAr^WX9`L##og-(;>dD&?_8fvz{rKFJ`Kbpam?IPV; z!s&vXJ9oQv9+%&e4Z0i#y8b1nZUX;7M!)_OQ@ca)Ur*~G%KzJKi+K^X{pZ-}C$|3p zM4SIS=HuhO|2h%trv88Y(QgIVt!-@y@K%x@c0<0?a$1FU-@+D^ADj;rzTj6@nj|oxKPy#lRX=Jp|<%0VZh@WIbGTbOvEi zntU6@iLhCqd_*LYtgCRy1WeTUiB>UubaW*4!np<cMhA1?U+V_R-NJF>t@(bb7m*ygX#aDL^HuFhPNnCq>|qU%F(}k-><=v`;4RU2jls zGw$x2ngZF5YBpdcuL7W4foKQO7b!IGYtK>(EKr>8nBm&G?N0}+nzva&JQEdt40a?E z@v$4Gym9JnG$Vo~Y5KXo-W+K-1Wllb;p`R+GH#qR#EH(e0Uw#N(o&FjsQ?Z{wHP&# zYrc824p9PCRn>AYszsb?v^py6jg)cId)bCrLf!;Yz0FP>iJa*x#U^pMeE9+5Y{;wN znB56vL%4#F2k{jjgp!UkNsx5x>9%h4hiGmd(Fz0>dwcuh^$F8v1MBiaG){!n?IFG| zdchsRJ%f;k zcV6d%Hn1=~ef#5`2N_KMRY+YRpmH9}632pL$)^Ix$tH5{BT_p$IyyF%r(Yilg;rNr7tv;OoJ?zVdTo)r zhO=5|GX9DJ{QL%nhEnv6po_N93?XusmY1h!7Q?729`@K80ynB_Jzw%3KYk3l4WZLI z5Iq;9b??4?jtvT!LL@OD19^}-6bi!DVTGzJfMrrrT`fgCQ+I`guxj}E`7d0s1Zl*n zQq)iX3T@m7%x()aGo+6`klw?=K?J0a{o|PYIWbwh=>l~G2N2<`Fqr;JzPf}3sJE$W zY6>Cbh-lf%e3%D>m^7AG@=NDmspU8ra+(zc-3F`{R#wAxVpehqB=1~Yib(Il%Ej#G z5fWo-P+f1uE8tMI8nSBbMmV;Ji5Ov8-4KJGOE}wynG?{dB!kn2(LlTxip+Nm{rU5$ zu;9U(uty921Pn1uW;-fQo;sDgkH|q?OzfGb=f1@)HluiQ_}_E-M8E!%#r^-en*9%j zGNK^0x?<1*syQF;!JnxusiEZ|0cydD|R@iu%|wef92QSJ!LTcG_+|(1pn4 z%5yOM?oUHFD1_s_Nr}86(kZRT5g`Ke`HxER-H1!`N;>B8LQpkgV_8%}IA}~bJ$mut z4A}!!VaOFKNkdy@vP;}#nphtxu>3JNanOO(;rD&7tjv>jMv9`jscD+{-y&uz*O78R zs=lqE;a+~}y;Lie^wn|!3e zu=x01sx2%o!ap;?#Aj#Q{?CO7Am7KQ5eg257k`0hIs(5jJ7B+aBC`?~>VO-hV`ldJ zuWi2al!{iE%Bu{c)QfyB$VUiyFhoLt+6gX2MMZIWek{fhn#F=lOqEqt%%@LZO>7q5 zsp&kA!)wU!;{2+Von6jFH}XGWNVsR%kw`i6%Wlo-$f*JDEFQpRa2!O(k{gC0j6w=~ z*$H7a#sgL_Y+qhJK0RGs7d-Z$MJy&M-TpRk#rKn+rIpR=l~mNw#+<$H+FV*NJl$6WX0&*6%(BiuF6!Ifca&lH@y_Lxf}*t%5{BQQ{*XR({;qKaXOf} z_TP&*gs^aMyvZjDZ$+LK%9Pob{$p~+!endB5q+ZhAGXbZH@^7afAm?$7^MJ7E}S34 zO6r!=)P%NYABt1Le_mZ24h(JwiHUFHIM9S2vf}JTOHkDNa3GBT-!GZ7bFPN$M3z=q z5*%Qq54R5;JN8X}>)W}h3ik%?$ZNeY0vDZI@v zn0(fu73d(aBCGdp>H0s0Vt$<({`rrEkF=U1F;bR}3meu54-XGo3f3d^eq0X5_LncGPzSiV zTeCdjn4jRa8X*KPRLMo~)Cepi$e%EDk!>3q9`2-Z1cF12xJ-;J4g6nt$#=VB8b_hM zPvaz@tavt3M(a4rBeeFD1f9JHX#@=o0P_81COUe6y5p!P)<<5Oc**OsW=C)wPU7S? zG<0ap*^>$H-`|jsfUR*@1dkwSX>L|8a#AKn^fwKLF*I`|X|QJzI9fxh7p^SF)S0b$ zQvD=#M0j;|6(Mc}fA-M95bf{l+rR4y>}42D1f+isQ6U`LA(qw9VDpkfto)MgWN^C? zSAZmfG=K{tPYVhPU>MUOy!aS)4vJ=ZQJw)0JG%^J{~94)KGmy1gmc1BCP>sA3*8BcFhi#`%?%;-maqOZkUxT!FH5lM$CH3;B3L zN=gdAB`e|shyW4ah3DdJ(2Dc3t5c=SzGyNyaQ8+L!M5m~xoSQ4tFqD`zN^-SK@SW5 zwl^yZ^UIe-h%sq6PGrKfw^_#uNoXGX`0*pc&p;;EJKEOcx0=K!sfpM<;fU38QdR@~ zU$}5#$BrHTEXo|VlU>M~BdY{lqL|Y9;|+W4LP|tK0aEGzmOjm1ir@!fQp3+kFn4|Nql05+Hlwk z2$m2Jec7nG1(`l24dbo=2yxsG-?PcU8XtyE1j_)C+qrmQ&(b&V-n|P8Gd*`K&onMC z5BVeqz%j(e0KP+70O_oZc<>wor0fwiM10&L*9mMP>xq752O)<*?m3v^x}KOZ7`C}K z3<|R`7bgVQQ+!7Zp~>NpH_-cZ$JXTJP=5nZa^29F${SCk3{0uN97opS}K zqJaMd*!Ab}7&MSP{QZ^i{2x4L1pC{_$OsTxlKwY>C4ZjKk~wh?hXS!maMT$Q?g~64 zWBpfp?LnB95jP1>+W6yyA(TAPTin~)+KQ(F;MhZ$^FjdWJ;ZVTCvb+iqXEKn$onJ5 zkLeuv6S9$xQ!RFJ#(8(x)a8Cjpk@T)>CPu2oT@?0j&Kxvp-l^MwZjCgGlQrwfD&{N zr}3oh4Ma<3cWrHgk#q;+gCkvU`tMULuG@S)nN*p?Fb^Dv=a2Nj??snHkd^FDA|nU- zH{$6vLEKXShcCUn=4WOOiQrfgp|gxO#DFloSk~d|j`RE8n_Uzor z8z{AEm5tNT0tWZ%+96Nx&&h??uyn)%(;-tK9CYf`iIG%I4IxuSb|O67+s7w0DXAwe zK8&Du@7|5C0f%MN2KOJK=i{<86~j+!-v?=F)*8Fbc^uGMKQd6Z_k9UoV|;Jz4Cu{^F7s?;eE(c?>zLS9ona7o#zy zcq=1r`)U4}n|JT>RCzc#ol};{^U0K#VW}nMK7G)8Fp$bkx!5J>!e7c5QNqf0ozw zx=N*?2aZm;SNFihH`^9D{Q7Crc9};zu3Wie&mKhVzI*lr8pv#8&8QS{EorMT{u6FK zrW7EM=#GVkGE@%@z7135EtU+p6@gd@Cc>}HTIvlMLz_us#e-)zDi~rGD1(W{yiXakW00nwj`Xi#z?aGE7f*|T^QLY?Qk|vWa=!aiEr@&j@zBWw1!`(tfX{&aU@BW!P`={G z(WP@|vc4t^%n?B@RYgIE4^xC&ZFuet`Hj&!EFzc$d(`v`XkMW>fD4oR8GMWzw@BT8 zZA14zcfRf6hmSoDdlNlhG!mYzI2in`1{7$Xgv|+&e++uYa zaY|?Tor9BlyPK%{>x>$uK41W4?Z$seQscf?@0k(visPiC>W3V`$<_54E>WV&J$h6? zX((L3qlW)e=f`<)8abzSen#?u3~%Mjy`;MZgG$z&*uZ6y16Pm!yB&wOQ(U|&bB^b(L62mIKvV!R1okxvBj zg|2q>vub_p%g=Swx~XjHuOC@)+xzGP&?Db;8%sWOe7ivh zZY~`WK1Z%sN|+RHH%Z<9+ou-+w*?B~mvegI(6^7y$4xz+ZA($&t*qj^jK)bQ;^5=c z6TwrWNaAFj7;$8VsSvHgkE!@>uB4;{3rZh}83bC0UK1zLMe75$q((;Wa1{pYysk_? z?P?%AkrwiDbBdf3GzM42LdXyi1~3AA7t2cSaWJ$7R9@!oE4LJ=0VmI4G5 zLwSV1QmBC3lNJ8zG>M20&n(CtI^Z$|1r0=oT?ZK+WiMcyVfHjKXqupk;(WFK>*qCA zvl_ny-kVRmH+iyZmBHcKt`OqJ4Gd}3;X`4Ug_`;Shd)GCs)S`HA)}|g$5=5Zr(^Hl zi%db^~Ef7neWC5WG^QmK7O=4x8jhL{q{WWOofJV{xP<~p_E`xl@}DkDuV zTZ{xBo&PWRE;;h@gV&-kjau}r3KKhEc3=*v1K_PwtHST5bMHCxMys(;K?r{8A);ocm3LXfB2OX1tF9nrIWOP^AN3 zG5OfPckelnAOd+=jhl!H&){Uzsc?NTyuBaW&%>jE3rn*4hb`U01E& zytdys=EwOidf<3SQt(eiNPGXIDeC@%1Exq}z@OJYZ8>H{P{rl0F(xjWz;|GTTx$RM z>-CN-9NGZbCyl;w{kmDEUgZ;)*UA?j7eR=%sO19g>OJlfCW{P$at>5w{Wa%tv>JW4 zb5F*Fl$ceDZPB*BlYo>_oomduLo&DrPO-)-xMP-@zOL1{=6c3hH(RG{| zX$?4bcEN>{2rswHpJ{rkHGcfW6~FL`0ISTi3ym+w zHH2_# zEnrFwCI+i98KI*C)ZGameBHW*=a=5%FP7X5{)A3HOBgh4$2f*^jT`~f_6rlozkPwf7uGuQ3+ry#5Sd9OI0i~5VCMnm zLrwGVn7Ss=!NrSXX_OSP9-h5u(Q0s)j|1ON(Rl!w1IKVD#9r7nzz6 zky26)J^az`Ua36uu<4sEGYmRyOIMpbQzO+mbf75iZDP$#VM4%?cK8(+IgJ3BA`J0O zCaEr9U>?J)A}h@L1ZF~X=SB>SE`Y1Bog%vYJceK&Ki-jbX)DSR%v?RuF>-oyeoW7-A{qYzHiCw!t+|yCT)*p+5GVNzY>kX*pEN<|0?xrmNO^q z%>~XrFE3@t1kv+bOLq$K4TT+5K#_bZYuH;jsTnQ`ogek>>sQpZGa_6S9PzFD%j1(b2Es zC0n*Mzn>J%I1~9v`BGJ*u-S*kzvN;(?9?4vhM7`WxW^&372smPvzGi^TpQ1)Ib-HJ zeJp>N<)Sla5RSE(DFsDE!Wo2zq3RT91C#UeQtYT06;8<{?hs?YltsnR_<|L01UMSk zez4mCqo2^vM1+Tn%eE~}(@(%D2d!dyqu50qzr900x>hVN+|deEjTLWPT=H;ClelT> z7c4PYdmYYb0XiDSFqaj)0xd@nP zO4B~(_(s59<%c~Fk!|61Mm=(6RtS-Uw<{ z3lo#;jkvmoztYGx7WZ@|ZA9f64s8sUFn#(r zh&LNoOCg>>2H($M18#VNwX`^gi3V{G9O}OU3BB9`8#`K;BYvX#}nOH!u zK9gIDD+VcS%eG&$j_6_aHgRG)oQ2+cz}W=$xU?Z7h4ha+;$vj*d;H>JWw|c{iE&v#vvB zn3a93*`eTI(`fU&oE+R}4`BBlmylqtc>wFc4^JhMEx&75o;QzXD4$f&A%o|G7gOvA z#_&;5b{UuTFmND}3>iA~-km#RU8@$h?-A(iv~of%Cuh@|33B#k@hGXk!S;_Mc`&+< zc0BCsJ2hex(gWeN&!FPy=+DH4DT_M)xufamNW$6K@2ry9MMPKQB*vQqVm`U{b0C8p z=8CXc?$aGrc`S$sBPx=gF^)%p{qcm=A>V7Z+LR&>>s{mIXSK+QqCEviQn5>;s+q)b zGK$R6m+Sn@qY1KAlk3mqtr|G(pmO)_k=T((XYhAV#BQYC_*dl6Qojeo8wr;h#^ zgL9ZfpPKCy+HyKhjey#39k)&iPa#+lUI8moPp`xoATkmMob6UISRTE3KDv$kq`r~D zsCIAKMBA~6(8X|YFiIz%qz?W9_xKB@Uo_Pr&-YXQF=LntA&*SP8JvMb|0*6(P;F3P z3a*X2#hvx+VJs%_#r35%ZfRCXbpgK%9dF|(_3N{*uSbvjkUY`IXvPt}_~73Fso^K^ z2Qhh38z6qUSfMXm@M48-gkfE{i-R$ZQz;yfXo%<>0R3#O7@Uw~H z7bHc7f=Iql_{2~S^SAE)*@NT^(j2$&sh!7r-btr_{}WMZ3_!V*z>my8$I4O7D}JJk zxKbl7Qo4si2UohEQZ}hjiKcD%9S%192uMJdU5ra8KyUYvAFm(3w4SXu)C4f&z_+VT zzkcr1+XX^-&0MV3#W*mvfGlFNa3N0G-J8oNYDu$2v6(b9$L9;Iiu`%Ml15{;)I=FL zC*YFRs$ILPRWa+jh%Y0qp*M!Eo^~bdNsLN}4HLwSL6Wxf0g7fkNw9ezJyF0M{x zTO+;&Kl^$E@nEjyoP(@o$+#x}(S_p#)&A^0^XRHA&Er5TE?@TOJ$5Y-U-%KEL}8m{ z3re4ol9cpryZk6Uj7)558?;rHJNoTSN^U0Am8Q?`{UDe5DoRH8!#PGe0aM0o+lshj z!#wWB1h4gfzizp_bdfB)3~c$<=|hP2`!0Ut7xgqJ1-i`(*_l${Cb=?X{7zdOogdu| z=`cDWgVahthATw*Y7HopSRSNIJv7_vt+JfFb2j8ZPq%7lT6-C6e#E+;h+N?02Kl^& zvp#9U1ek`HhJer!votLd&M>Uh*8b=}(_r${sb6wKzO&7Ui6nUACkUlX$5EJ`!yyc!++uGU&H_dJ{d&jUX(<16d2Xz=j4naeK?M2EirsnQdXwn zbqa0ox|l%mdf2vl$*U=Et8$o zVXYA%1!Fut-O{p;IE9jNlOJ33Dml=ztL&?b*ZyA?l|G+M9gTp=lVS}LHVm;T;glI5 z@M}P4S$A`E!;2m4E|GdoQwPmEDGS}eG))9f;G@9-V(>eRi%R-+PQJ*;^=SCy!ML{J z4sQBiDlPzm;S}n;bm^aV5;dX_eJPBCZpN}u^?`&ZF6QvBPN5IKe+&zTRPA&G4 z4KKQ0J{O&Mbg7}?74BJg*4@mTrz7M9b5BxPjOg39FQ#C9`yRh^X$u7wjw8YggLI+` z^Zcnyk~I0}F=NEkWK2WwgC06xlTV*6BlubH72{To3T6OAP<(#PN5ofP49m3&IKUPS z^{oB)@h}=5;{A!d6-PH3Db8k%7r{V9Mdkf<`7>cU^|7zJX};zBF}9X*DMwr0m)Bz; z_JDxGv6sSfA*>iIC*kK98*iT<6>yst^{$w+ZNXECwMkn(r9LB?65Z^sa#-b)xJJxS zwjHY6;7NOLE&;)y~8Q_4qv**OX0L$e2AHvRTy-1;^ zsWR2c>D}>(zLa{wK|ve2^<4VNn`l$Qy@`lC{bIn$y`(LOQ*%6`e<5n6_A*G*g3>W> z<;qCqKNvU*U1YQas(To)l$tm#e&rd2TlciutZ)>AV@#EB%$O5-5n=&>lCCBV(+mDO z3jPn@n_L-k2PY^!i&JOMKBWjF+lnnOfzW6=RWfPi<$;+TP#*C09dJol6yNP^pYa^k z+K-tY5=|2`n~p-aF@4M{JrYxrtoL;Inhh1%cP^`#9!WdhOim%XjyF5J_q}Wzk#ji) ze|zf+Njmk}FHou(tK&-lW%RSnxdjDf_^bObnuAf=+(?uE$Olo_D%^Mhtwq_&@6lSE z0Sd$HV_91!sz6%M!eraokY)>cOC}sLg;yn)k_fxa+*trE!$3|epU&B_}K_| z|67!Jp^QgZeozO^s#nHbF_aYp$?a6sAWRF#cjcYu4(goq9?&mka>#(35L=ldJzcDs zz3YPSF9(iJ_{la=+4ZVw=*)KM&6wqb9sJnW_>v zL{STN&ei=lg~#6W){`wP3dyLV;i6ebG7}K+>gCH1{v|F9&KaaL&-qV;6E9^LiDH`w z{V-Jw<(xw~&$K!|2#9v4(4j&+6_SJMfXTH~oMsGOLKHpyNW(Y1_JWYQfOX zO5XndbAkKj3wp}91>=O5bhDO(4wtX3pUi03`DtLo(}(8PmgmegIn?zlE#ocE4Jl9R zC9d85hk|*z`oP+646fiA{QP>lg5zYOLc)b6688|R7&aq0)9b?C&R-K_6jlcfVspHM z@c*n_z7{ZwBm+{S>UT1?O+7H^BWBM+$M!A%UY;A`EZD@`SRu%LKKg*;-Ei;r?ek`u z)T1iC>0f*2I9pf*uTOq?BR_xs82#2OCF@hY%s=*NBBw7t3jUqB(iNS(TcS>a$K;|4 zXd>7MDYvHyey~GfEgdEtMM{exBqhp`D7foyO@vTS0Cbe#oV|(^4 zpY!|j->P_Qt5gei?c7<`?f0W&H{uru;TNICX-jO^c*ox{dD-0Op`l(Dy^>l!WjNb8 zZ{rHKaH#(+ZqfS3^>Ygb4Jl;rgiJAfPNa#3hx4V<-SlM^_QtK&L)C@Q!2E}Xp8p*` z9w#G(ZIR<5$J9N(4O&&if;hcykF6!Nv*;@Pva z*9*Ct|E&k#Hmh2)=A_rwm8B869t=78h%{ONxifmK#8l;vHz48|J{BHM2@QQdaOSQ? zjm%jUVJr3U_?N-DUdq%}4?7vMI*N0{lRg&uBT*YZJ_PZ^s(3R^XwwGNAJf#u!o*Dm zJ1#_{-?{KubBKUsSj)i*(cpTNf@Yh#>VJN-$n>RmcxC>0H{COUe7x!+8ZwO{1w4f* zrBO~obsT2+!l0Ojx-^yoix0pzAXcDEjGRIj!&@~~8`AY;U@soGFLOdgp4-NakJaFo z_Z^U(Z=6D!x^(HO-imb*T_3INE4T7W6b+r^>}+HL2$@AgAJP-f75wjHX&UV~9*zQ& zqV`>WVL|=%5Tme-TukaPkGn&r=DM1JX0pfT4vSfyEbIy9lu&vhExxtGnAZ;y>egq> ze)J?!-Tlfr>i*m*h;*n*c&+T%UL3@lx6huvUy?B8FD`(~=VawS*q4^SLBWxl;KDqr7CsB&;KS zH3zVDMOb}5ay0O<3!60v#KVP7h{Li#Q^i~Mytvruhy#9~V!E4>iT`43?C_BzFD#L{ z{}el8e|Fx`!5tiFnOCjCsV{yAtO=(t?aPm?95`^`%1p7BC3^pyQgSV*3kp>JmsPQa zyT6ay9DilbkNdeHRpyFX|A>mj4Q7^ z^lE|NN>wn$#LO2XQUW8@ip!bD?0#~l;;cGo-=kok(WF)7O$ zmctTyJ>-i|>Zw!PPv5DWIjD0-nZmTZNkP)%PYovCc2D?JTg!^WRnjRxVNDq^tKizT zt#_Bt-2=3C36 z0!e+o>hY8X{X2G$?VmE>sm+L4!KGK77ZY*_LJ?QB5ksJ1FbK(bSzX8fu@*!H?7mw! z!-P#}|=`X$?i)cKqAQxgj18=%l zsRoioS zdF$p)e>Jr3g?ah3_=;mwPNb%$-si`S7y_K;_RpO**OhE-Usv04@H-f=}? zH`T>lJzly^8}Hf7n1^=p<_00dI_^+t?ZEel-(2UMkt}SFZ`+S*|G8rqH|!E)&ozDC zD}S82`lz3JnkRPiyMYLq@LleLro6D@O28XtW{}!s#;jGdwCvTzXtcIAK3|1lq3Vr{ z+@8OtHMKp|X=|QcnOgeD9?$|=b%^7>)gRLpBw8thJ1a$+96ESV*Gytb9GEo=nN|Nu zNd-JlY*TAfy9#bncV~B5QhJDw!j5gxk;C&krjQi~{|}}z>4tzKV@*Y8Mu_GQMOSjLE*Ig3puC=X>xsM%xVs_Ti18Id%d|Lo}SubVx5Ln9lcklKZ_usny zHv`}}LqkbmX8hZ5fFaPv4d+ZbR=nCOG;3-*Nz2R#;t8+$=H^orVF5tCVP_Gqm(?3g zG^Q)!>cRpgB^3DaSFQUri#}qkZ`iSso1GZo-t^73e5K^~_=!5HfKCV@zsU9(61VaW4SA{F6pmM`Rriks? zZUt6iLY%#D=uD;x#>Vgqn>!AZcn%lL)q}&A(3wvO|6S=zz3uAN&j1twi2#u+*6&+> zVI!XmZU4C@aAKuij1HQ3G*9wZXyg55QVudFssUbJ%H$pm&sr`R)_+XItE<7sM$8-U z&^8Pk>unyJRUpuqv3)cOybvI2XZ3k8YvlXC?=1c`KmucJJjxCJLaPx0XT$CcZMbK0b;m+CF3U^)R6|(dZ(b5I%=^ zxm)=>tr8z!pK1-To#%*C_h6`r-m$z@I;zvxt{o|z5RuDI&gkE*i*$nT=5O2KwHI_6 zuWbKYFJ8V(x2cA|hb9M76RSpG$yN>Fu?SB{n9qFN`wxh#6%`d%xA82w@+>^PxY2b) z@fSP`d>q?!LDKa6IeaspLHo9K!2WG^W=E@JXYUyiB%W1IWCkI2 zIo@His97af?#5;L9yrQ%%%tB^BbBaUNSR$H=z5 zi0>@S9{Qm*OPWY_{UWy1U9~14cHFUa`(n__I(k)mkCkp;i2Y(E6A&I>@!asf`;0XL zI?A@)yt{ZpH!WSd)BHstaAD%j-C+ZYsW?3eP$i@Rg{{Ay-XZjs4exx$v52G@JW=~m zg|+8QT-)8zl0WlB&A*r!eo{@%QmHt(DkQDQ`@+iuHQi?|2>kS+CTwfv)4aTRa3qEg z)b967KcZ=iG&v1n!{8c(QX25@=+<${N3@UW_NtYirENAWmE9DpDk~mI{ck;GIn%CP zZB%^ofQ6tT@i~(h-g{Y%>|Rky+pup+IKWF%tVD975Btab{YNsVM)vro#?6j!jejNs zBocn)w%Li3;odS8!>UAi$>+`A`7uSQs4|tiw&~X)U{aw=-nq)?Y>dR=Ezg-l%>*+C zbJhC&6QQAC;nLPpW%{h{jalJx{Sz+@x2BSF!_aD2IJMMrhM~fXQ2;;|D|@9zZW}g? z<*&0TIq|Eirb;GLl64Hv^7BLIFR+d^6W-H4K0dNg!@3U#N0^zmrFTQ2%?r;J^igwr zL_awW#l^wG|FPQ6K06vqsb9390t|00v39MjtkhI#{Xr7uX&w!H+4R>d4<9Bn8_Ke2 zmcWJ`9(8J~jbo1jP)DbD(m=oq;P8Am4eYe=oOKhQYm^tveXsWzeR7tij(y^+^lZ`& zEnOo^DtrzN1TZa#QzJKOkh;3MrY7i|e|<=TPI}d%Res$YKT|_Pi{@SKONtd|HEA2x z$~XPc=+$Z=SuxSk`V?DEE?9bOf;bRq`}QO@K&%-l1Hl}>ZgavRhP@N|W|!BnA)qer zl8Cry{r@%F5OjDwgx+t*2Qea7edgHtK{uDd~DPZED+X*(3W}2G|QU56D7s z-RwT&58;7NgTTCNn~zUJ{y4=!WLOQ26l$Y}cCDHn&nbESu~n0EjCh*<%8sYKWh&Dh zDoRUdYXp$sP}60tHkj46@#Z$CT-8-3;FU8*4iW<-e1n;<3dh=kFf7{Jq`|H`uiqqEdPH4x!Cks`&C6aNW`F z`h=9?^>0c7Q)c)L9dhYroru`{;!bzS=w%ux&ew^}H zTUbzlKBmfSFf6d$d-mX$(Z}m6J)(1R&$lg#oWJ=VTB%(?kORY?(05olgBPWOZ$pcnc$G z)2%?m>EjYFsurLvq6{Ntdnv=05@=V8(!uvsuH zfA%rwko+?j7b9Bp9B(LTyF|%1{kV;7S>#n~*1ggVQ$&5%w`(Tva0YeUacWx+g{{A+ z`-he&JnGP8{HIo7kOstPUqxjUW(MUqXm!z&vED58ZG%DdaZUO4w(dWk;cUAmO|*CY z!XQ9Xg%x7AYG22kIm3cS2Fnq-Z3pgp{h@BG+RXkPF*mjtQwd2Pc6(r^$IQcRo$P92 zc2IclVY62I_MhIrKc4VrT?+acuFb- zdk$~S8!y{zuxL={Dg8U1UUXr|)~kj!I~aPH^dHz+sg+byC91(1IEGI%<&}fOkhbqO zwK3~-_mwl#d|szgQxHEx06%wbRz&XN8}fHE()-dJHOvMKbP_BmtLT&1=!|~9`YhR! zJEh2<^<5QqwdBK>lFVkT+i^=fT2@THAMT^|+s9!JDvHe;XD%lGZwQ}|!iAFAqo*f93=HHEzX56!!` z)pD*G<}G-OOtNp?>fp;DFqk20Da_L}e(v?!~z^3+r(%frHz?S`(WqC!WY@f>@n zTA1ooZy3GiIOGq0;rr34uxK&G&cYypa~s`*5wKWpf7PW9%=hP>_o5F)F$$c$4;sTR z8&*vKUs3o_oeHlTBmIf>ZNj!XY`3>ue~#7}Asy_HF>78-fJt)U!UrDTu0zbVDXeJ{ z;S+{s?=@&V=AEatOm2s?gJc6oMp?G)vP}*hg@w6!h4WP+Aj5oUZV5fu?iah|n_JO5 zaX&5x=*&&1-7z0XH{kY@C;Id<&`8BrrHnmq-@IX&n_!~6d2?>}z(L#PdBw?OcSpmP z3JO(d;Onu*y6aN2_BON2PQ80WbO7AOB!ZZL9x;vil(X((n$wx!i8Nf)3YQzct!8mI z>|D@BzC?EzEXcqaTAQj}Zb-V#&u$-W(aTqMZ@{~iB4`+z zx50x~B7#JD$U>rx^uBkNf3S3Yg3=`p4w=|;oB=8<6y}sp3x|F}*w9(AxwdL0^%JAV za0N~Cxb3U#HZaF2Dq2{+8*LuwWigt`DT>cO)G=qid-EpK0FVE!0X*|8NnAanpEP!G zad6^*{f&(T@Fapl*5`zbShjOcq^5?(>Bz{~Ub`A=P$%s>`<&Twc!{xy2cvH)EpjDM zz^SHeUU?KeU!?XiXU|%p3=|VK1e8>@9wce(;08!(aTML5VJQ_k|%C}>Ya#)XxY3uTrqx#7Y@{V zN7%gf4rwA2A%ljmAK2=F5N%6k{KFG-N*UH|-6Yr&Irm0#{py6sJi#+*s;)~znmB|aMEuI|NVTlN6Wy@qK$ zGh&7f3?N)x2YOKra*$=lix-E|n9%pt0&3xY4R;a^I}IV6xxV{u)}Etc-{tGu&xnqX6^0WgRg0ctUF>#;!c%Cv!`= zon-b0E7uMnz0FASzn)hs?Y;xw#>jbZ3&wv7=ATUu+yA zNB??W-yZ3Sr;IR;*s$RA)3_6Dk-}7}ZAC@5$Fbt0`Ss5H-Fdyi+7&=gHFW58cfd7Y;e9-tyz z121J(A!2w}UsnfR19k~9pf)^4G#k}?1z?R^z zhYuV;SNAYGyBbePvqabR>v20Aj6necjCFeMsC7*u+F5YqHj8?@`On0!L4%B=^1hdK zCsr;(MlN^>x0bT<;cCI0et=7Z2j6<~#GO5l)UIB8xw8NrTUW)e;r=oMWAyy;lHkB~ z+f@^D_mo+XQ5ahi7!{$XosJ=co}T$2hIW52FJR_<{``otm}mF9G(J)Wy^CpjkBlpa zV2?0%>~&A()f_?#=d*NwbSFYc*Y4{=q!O&Zx+(pEL*b@;1dpj~ck$5gH>)n?*5MBj5c1Z9y zzF$hvVxwnjRZ3J+lG)He*LCY=rS@@ee4FvT3o7R@W4zx|1D08_tLnM9$3V%fsO{g8 zJwuR;V6tGyj|p>X>yvUf<>K1Ke=DLRTl~y}=(syR?y90Go`+rDH>Q0i&C` ze8q|gtC)xzeYQ2et@~d^phS|W#BA1Ili~`1sB4!l-TjO}bvUZ~jK6;S1{Y9go4WCF z`NQtm4Ai(-ncs!hwZbnnGJ|zJ(esJL(P?Q{=vdUIwOfSTD3F($XahjIaD_72L zbILT>$)eisP^VqdqrS8cVf)LdU_UmDd5*c3@MNT)5nHy7j98}Rb4}_6k_4m5&uC<^ zHFrlM`8>T_(_b0JNL-InI9ARz5#Qy=gMqV7o(`q&id^-E!joqgY0PQWLuJLoi{<1< ziIz5B-MY7c=&xiqR-{dq*q+{}T{mEtQ5$)$r!`H~>;`;`k5rnm3aXw@W)EKn$-#5D zwvIw$b9O~5w57J>QA;;|r~_V!EN+A5pez$+2TVHk;c^&-?Q>fX_Xqb*!A}`JTjE-^ zb%dXanwkMNm;mfDW6q)#{6@=O%jI{|`tzHE;)$PB%%Y1gt`gFMFy7D_B5_$7Yev2i z;3E+h3Nj?-?~t>^zD|dR-|iRmkl!qc!qP;^q4c=^KG`-Ion-GKLClSYa21ePiO2>I zXxPPfO}Ad{z{zVgsLOULr(ID6h zRAvl(h^b;htJhvnPfzM=Skc%ye?(+(1SEl-Sxi_D;2i<5RjCUp2VEPnWieUh6K zVxmAxKt)%K2->h!vMtMg)K8tois_@{JT6_hFcO1tN|Bk9C$FI(xE$woLsR~^eOwVD z(R<*d{-WXSgA4uRf`|UbayV>|l6UkHN`H>_vk(0Mz0t%iTd|^Lixy9=S3wB+PQ|{a z0UXb<r8{ZnQh&Cv+Wn>tn^YgT~UxQDX68#D9gDP zCwIJYusjf@qaxcDf8sMAu-?l)Qgq*WKi=AdbUH(k?* z>5;fAw^WDDZI9mxvJ|2Y)@%s)u-l?u;C?pdS}jX?5J{-$WLU0eYjJ60c>0Kfwkit( zUWM8gq_jM!5aykJqJ!+x@4*d6?5Zw5M9sGjrBF9N^k=E4Q0Vp1$_c!Evq1xUwOI?# z;PcvZd6H#c#`o`x?J4;%c*1OL2_~=1NI%qZVuh_~%|UulwnL&MWH!X{uLoUr$Pyg^ zrDg*+10owT&};giik9H@LeYeY!oh<#ZDNHA6^O?ogUGp&OG6h-QV@o)EACa4l@%nf z9k?e0I`vzzQr7=gmA1=7o|;BqfXfZv8K^*nZ8N&JXw6F@+&Ib;$Y7-MR@LC{rRgKA4EW(VM`|?b$;eo%qxZ8kUfx5e5yuY2z>g z7j1?jhDcQNzJ7j;TM-SSb$E_og#YT0yF$gch6?bTh=bT7Kiybz1UJ0GsYmnH~RW>;IE-AIVstUctrt0*rt)$mVUw_360@)=dC!J&%7s8|b z5L~{vh2*;W4s|a|slyOq@oYm;Za-=hOEH7>1>Etoddx!aJTp1LD% zew!Wlc+|%8DeFD=lrm+dNfu$00gJd|)h{L%nu4BcXlR^T?3`R=KMF9Oq$JN;9PMSx z21x&emqdF*Qg~oRt;#MX{M~qR-+`xhZ?nxzGeO@Tk`LqsFU%jr0f8aJtrr@Ib8men z^j*1nbyj9(KQF#Nckc~Rj7ZGjk`qGS2pZ*pDe1-Xv#E$QCKYWIL#T8cIEJR5H*aAj zI-648bFemZlfCv5f^pqE!uRLqhpCS4B%{y==;w-x2Cqa{>>IbR=uxwQwvsU{C@jdy ze2oB#a5VOx^L`RCB1mBQF^jO{`j9hqShQ6dg|_NyhnP%QrTkxw60Kl!vYs z3Kf?z%*2M{u~2Fs(W?;zXD(6A+wHBS0PXo1Mq#luS@SgL&h5WHt1eyVHg#$y6Sf)p z4BTjdFks!l7j7kmJZP5a*vtRcv>7wNPed9S^Y$VRQOI#e7Pnuft?F>u+)HjJ^c^Q) z4l_|wSS-z)8G@n@yPdMKKaRANXc^gRAEG7y`1ld5VHDpMA#>b=pkwxK_&jM0PU?C4k@m_W zO>l3&k&(enjl)Uap`)Szgra5#VUd^T@N|PN_d^Y|HE63jl2IAE%4Zz9{JVu!-5(!c zuUtDlQ<6Gi!i1h2D!?=fbp6erooG&1>ss2{nwWH!E~QuF;I4{4RA9w^XlOqq!A>$( zx>JOxC@Y^MR6{`J1&g(V?A}rRR33Qv7u1{3Va8E*xYtkUB=eGm!qS>J(Hjob!i7Dh z!Y&7Set{Xi(5v;G*!iyV*j~#p1yxDE> zOq_>H$8(Q!lK8Eid?CONI;p$MKM))LgqQoQ;d`L+@4>-iz!q?=f0-ZdA}yZgXuZOcFA8yj9s3XQq(nwB*X~B^Cof?Z9yO zV;RA1i)X>)UGc>vEc@JJ`)MeUca2~WA(j4GR{4}%z_seCqGDq%u8nntbwT;{t^t1@ z&+!^9{y}2Y`*fCqpOKxTBXn1u->K84eWXr;7YDenwjth!WW|_KG9(C9NBw z!Ya;aw4H*(6C_}x9166{o~3fufY#Ei_Uw@VY_^|NSy8LC#HobgRiOd<$J8NynHtjJ2@JA6YDdfHp}cT6=i25IxBkmbf~hTZqFH@$q8*SCL!FO*UAHH%h{kfCKJm3Q|W2mS=fcGCgGM=R*Z;AT#?5CxrOtsl@ZBNE4=ZSr1Ghl(zOQ{kPC%;5jss%03N6h>r zp0Zb&CX;qE7U4s;^XbG!2;^GXws)3~%vmA6X}4eg*@+s)-VH=mNly?o?IePJ!#<3~ znQYO5J%}3QEsx%Ec9<9?^0%AtV*tb86_u5DpF6=yFMj(rW_}dpp~j2v`SP#%2v<*; zRMA<9#O!0(r`SmsU3nXYu(M~|mCAuBUEP!;_olA3N&1@a&c5PEz`cf}7hqm(0YY*g zrO>=N(C`Xo{FIgJ`zy`bv+o4XDmRb0 zEH+28`zYVHjRT)l(|6mi>9HV8y;f{Yq+t7(Tn)R5CeeTti(JjSnqmAFp>CEKuf5-P?V1oQa zfBwekjvWbz5awH2(!6N~Ou-W5=F94v!&d4Xl1CBGe#Z){i}b#=J>dUSVL(H0t<8ua z$`jP!{iP>x4g(+n%51j#u=dIvv^zx)9!yYVEb`{4{w75!wI*N8YcD|G%&gG!tM?gS zf8~r`Iv^-0dCg1U`Jo+moQc`yDOiSG{E_FZG z9o?3{Gx*CL2lw07TK0=@Kr)H4#W$tb>lZI%d0Xk+$|u!^j@zGG`Vr0_pvCN&usHLc zZM7K{?C{eRM8VWD)6^MOclAvN1)RxLaN0DJL7f5Nld|N;;J}3~$H0v>0#>1GfosTf z6{NM8DN0wYQF%@Z)`%bTbblPtwBXv^756MNhjsoo>50jRuW8fNJLNegpF79%-n+jS zD>^wL(3LvLz~^aW6s54%+t)}fh6eJG&R%v;41_QMtO*{9-hsyedznr$VY5?JR9aFp z=?At98;AiJJ+7B>tl34zYOjZ{w5OmXHzq$lWw5Dw7}_ZPzx z0g-*ItyTLz(dEB_)fxdim4(nA1p$&e%AKG3_1l_mQ}glTMO4ht<%b3`JS}rW9MCsl z3UA=#FMpUTmsk{ISHQkSRVGbLC+YrJTLffy+OFr-7hd9fSqElC&57(RvRFj6ExGoKpXp;fhsAXC?|zoY`~0umgAdw2K!RqGMr??#0ijUt^+6YWB}W z=VUj#ZbX;yt}ZUH1#lYw)$q#8YWSlJTcRyP9fBu`PbDcb|G`TjOeFO>HOIDW4a}wm z3xbdy?8(4|l^4D@bP2}~Os$IOdXTAd`p=hg;xyqh22udS;t@GSI|VuxN_`rBPowChr-%?FS)=OO|?W`T^9EU6fh`--VXH<3S&I|T&y-9L%cjCb0`m4#YiiEi(sx@VyA}wPTGI2^Y}+%ZPGNZZ z@zbXgd2vA*aOslTNco){?V}zrCUL*(b8ObfdWaQR7J- z1;*zDrQ1vnpA%~~O@7Yr9gfZSJ*Fx@<=gf+2428A_0zLAI5-kb%0@P_8j3cWB({}p zziN#U;2mlg*uAvi=H>;sZNO`&yKFf|d=JSsBZvug-@31ZI0OdJN{W9wCN0+<4*z6uO=-LPj#`&h2{6X_EJ;` zRejg4BfITFO{}>v=|2AVdO3RXQ)8|5Z`1>3W7B)HccI>I^wU0GUf$lbTc}>vU=R~J z%f2w-E`rqa=bb;7q+n!CSGlIWc&96a#^>qIjUGi4#0bz7HR|ub|MA@Ebymo*z)Ygd zE~BtYt!eVh)aK^wrf)#G-~wBOu(N~E^r#(t`O*Jf#SzE=9SZlMyUXE6AcS0vvn``e zY)$BNa?5L&vrfc22Lc>C7<-x;HDu`__)LFZC?mR@LfR`31 z86m0FkIrQ8!G5n~Z~*rICx&%%jm|KTH)6{PJ9*YDW$6jly^R?YeASwfb636}Jjh27 z3pk9NYDzJjkk9yFjoS%McIZ1gbH%o8P?K2_-({|RNBD{nlf$(fbR>REaaYyDxW@ljrFGe>rB9K08 z#vX*mP$-s}LZUdtn@%Uvq@JZJ#WUpLC-vNo`$QaaZp4&OCOtUgnX;jg6;)53_%(K_ zR|S!P(@Wl>6^BItop##Mu|c<%8ch-&Io`_f57`q&fd2A!19ZhTx`#1A8pDD&YQkyi z{#hmMOLq0$w>|UKS@U=e{+STCPR|l9cW*XM0KIHrCB4iT^#;ss2+om#r~J_VgwC2U zX_AHOa8>!3nQ9(12~><69dD`b-$52<9&Ho`S>oiDvpfpVN6EiWOFS)DGqUd0?JkJ= zRD4Qs0%L-6y-L^B1GTe9M~+*q)B6Uw<@nKp z`Qtx5i;a(856bvp?$E%({QLyq7(R4I8L-s{aCHAI9?r&L*=N!sqJK?Fx8buVTmwu6 zm?O(Vu*kcA-_QYBNFz4@^-E#`&*P_hf{r&PNqFQ6u2>t5ASH=>#luUK4!i#0u@HuhZRSF2E_;JwihKahm-iK4N5Xe(B^TOJ1VaT+_9wvh1G;YgcFYKUkv2=;IAc@DV`*ny!1l>~zI7n^=*@ zY4J1v>v(^6h=E`OeYi6cjQ7$GcPezWr zHhw(A4?yoT*Y?Uevb(ag{9Gb=n>WpXn)u#<4m#^V!+@B{-;S|nG+yw6Y=;c}MM0n> zS_;GeM#O&5@rd}h7YKUo&KE&3nllF>CN{$qacJ=oURNsl$<2wZr-|)nf@vudk>RUM zb^l1Z($lA>AcWem0Th>E7RIj>5OYdL$_J#Lu>$mI#8zN?JNT`I4kdSW!43tn2>md@ z2yi=p@rgzKoc z`#}kyk%rD<{081aD8nyB-G70psgE4+vex`3QQ*p(B^EF7k7Bzf(K(~!1KdXl#dGKS z^R?Rbe6Hc^@Yb&3=dv%iG^-$&-|$L&P}cuLr2D6ZQ%4n08Xrm#pjXx9UXIA z4z*cp|8>a?J!GMKS1-{`W&09b0rchbqZ}H}VOh7v?87p(J%PXfPNW;JNE)bPoJ7C& zWtXTJJomNx>kiC^rAnxr(AO?#N9O^)kA zR`=6cbTZo(A{_-1(qgz5>i(}vO2ALP_Y;5H+DrH%$q$5YI$b8D(EOqWF%LNd#PuUH zCdC(go(EqV*-`(Ft-NJ+i)tWo=H$#_XQ@^`+>(oZnvBmI!zbq`>JI!yI(ID z_s5}86`L~jn1eba=zahRXmRtYokeZ1OHQ1SLUtYwUwCTx91S<*(%=JA!r$i~{o~oQ zaqyqbubqpIMjQWlXl)BVD6y9b4a;#kd-a+#wl|jP{W|}s>KC`Mx$syJvJdG-2|C%R zI|e;QXYiNUv9YQPLSh!fI+mAGe8$X7y7RIcHo(TQYSI&U4zNFwB{)6owfJNbU0qtZ zWBPIw?%g;5(rmp6z4B25y@ zPNTSciqQ%{-OFvwx=n*}6u)T56*J}Dy~nY0sGSevT6~@x7}>D>uF%aW&1wugig6_x3~+}|yVd+R@~3tpW8 z%gZ^nVrJ&k%Br;VMG5?p;1$b^&CI%Oz1r>G(0|ZtIZHf0Ndu{z6L9+gLF6e?K5n8x zTzmUxfv2dRX5pR6i<@H*5_05--{=;So=RP`Ghe+2G)MZxWueBVEoBAg*^?&~vIQV> z<)%%D(wlbU*T!V;?fk9CuRg@@o89Z$}cd~z@XS))_>=>>9IK!zEW}3uv3O5?* zZ#Z^9U1!;Z2mGo{*bz{i zLi>s`GL$9FYOhxxN1W;}tn; zx9;3wiOArZ#n_Wm^?rfrAX)(Sb}ZSWpMZjkaU6s0flTY-_3f>!o&s4isb-U7?f33i zN%8zhJWOMFI%}B$nFP<+2{qdeRs|%ai_Gu@vjt+zwo9UGHwYOA)6O6yCT~^pEk*Ko zBNqUn+?HJ5wxk)FWZ*eYAZ0`FnC%dGw|v#j+xIdyLoLh=5reMc={rFh-e)5tf5r_4 z#x5N>2~+rTMb9zzJ8|QYO9}5Ik@)-(_cD2XeGkonrU^e?j*6%;ZHZ|5?^W*|iadZI z0w0jk7L0^vL`0oEtLBserOx--bAj+QeEBtKT3K*I%+cBXJFZDCVhPLanWgJejQgKI z`>->kTxfB#W*I6Hd_WRUWZQ1FT zD`2|-)DoFj2B#kThQ(?)RjU2$>~;G(ReRu(Bks9Dx{@oE)_$RoH5ir&#@^w>nw^#K zf&@U}ArkGv@Hd$vMi-x}P%+$;+T|Efs7d2A_>&h}e+KXN2pLlxe;(EjOp(WoXhol>>r3tkI*hMz0 z{EIiPmsbOxj;+nY+#E%B9(Fjymm=L2>=)AB>D?03ASNZmVi_3-JI4|Smk?%p)fpNc zROwLb6FPTw_4Q$|3Htyv6JTb~J;STYx(%%G!>J?aKg+-8NJhurx+Mi2ME`@Da^xa9 zLaPQAAK$J4d50L+V}nUz(n(Dj-Y$RI>G+_7Bo#^W&A}5p3`80$MOGG;QG2LBfDaRR z=Gn6~s>H&T`Lsdy|Er@?BMf)l07)cgF*5g?PaO~fG2u&EghTJd2}HMxChG2c#mXF3 z1cVpZl%9~^-rXBWxh%VakpD#h0CMLaA?2it{L*96)Y6i>NVs%z_0Y}T_CL5Om;W#N z)Cg66Lf64J2yElvyb-kDVlRF~A&BwJvnVv7cz58R;*$h$kF-A!f9ojL@Tq1S4RBGC zHmIgHKXh`~Wq#Jd0fz@{aF9e$T;@fjTtUInj28XshZc{otiGC!{~&hPl_1Z8OoRU_ z<}2-vdCR9x^qCl3^Rj1Uql~=#kyyzzbnnledFM*N69s_<8XYL1OtXI)cZgHsGj<>7 za*%?<2p%KopJ0(jvBJQhheP^|;$Nb-BK#jzG_?t-q_9Ci{;Vy?VPgV>j5yout2VRW zVCLeQ{QA|%Kyrk?0^er+6+UrspjgJDcLpv}UWx?vmkMN{tgO4KsR{ZZjG})18Vjk> zV-4#q6`~aQJpj?{w|;IfU@-#Zf5ldj>8JY31iBk=pbTHOEJ!iTvQW2d8kez>kOV(3U*q`A&1?@)H zJPkXZ0`#mNAu4EZ;I1*;)n>I8NEy!Yh}zvEB3%3jHjtbt+t+Q(%m5!dHnvjR`{GcM zORv{j9*aZU90jhb^Gbc;zkXo-wr}g?rO%QFicWH7$mmWy2x*x-+w!B(zHCxIUtxf@nd-o(S1>?NQW$F}KrpqTzPGclR#j&1`oJnAD;Klo=-8UCq^5 zLmFQvPZw9+kDL))dP1+5gP!14A5OyrsAdPI%PvHxNFrrXp@2Q04D6pQfDKq#pNI}I zTcQq8{T`k4hq88N?}Wge`X1Pb;P0oTVB>f%1zedbfR&T;sxrc-=lDgA+wFD*tAHp$ z>vln{7v zxg!px8PpBo?>!RrpneFIXYMN5NHSsqCvYhMe}5;dGbh1zSBuLA?FTUY3<7HB-x$$L z=xpqtvn#UFBGMVMRA(87xS&ZIk_m!kzG5PR6g%D^*mytU?tu?1H3tJrUVAqI2PI18 zuKzw=j2!}MWCD$3TU?$pQr@9M)z`atyUvzLt!whto&be!NmWZ<_#J<2e;Fbnr z3{y{b$N14thh!-c?c zz|?Ego%%VH!_YAM;b#+!2K+aIwr7Gb@eJ*d4Dn-rNT%7nMWo;rfplL=JIX$>6m?i0=_qVm_vbE_q=%3EHpB3m?hF zDDM$nTgkj3lPUlh5&|WyN8Sb1Qw8WT#r$#qEQ4^osAF_dkR7)~e zAL#%U2WWW(ZZY;7aoXvqrw;K)w*F-J>jNBI`*&7a{S~e?iP(%Q1@`d>Fe%CvawFgaOFzewLRJSN|3+-@J5(z*6 zaRJUzb8y`k0s{yTt#c{qRFP>{-n)gXZ-hb_DK8JmU<-XZikk&CE~yC$`o~7QIV{)a zeu%nqzl)>anJ8TV6GB{wUZbn{jM>GDMEuj)zL#7Pwb8YzOjP^g@>K;NO&S_$uMLrnr15yZmy>2%hkd zA5uZqTJhrI%wbSu+E1KGGg!F7^T*2icY>`H`?;QHs4uL__P+!DM29hN78W;Bgv<`4 zf)oYZ%p4Y&^3Y2B?r`{_7AZA-_`}Ix06#c$;?RXt9w8Y`!%dBiH8v6^{Z?CZS#AmJ z8PX7N1rCW_6IdpSbY!<;ZdEda87uqO9Yilldb8o5z0qWvDu6JS%WxuH^yC$Extv~8 zDJjh(044}>NHP|Z16(ca5R}#0ZiMBdaq2N`3a&=)4ho@8Y{f`$f|3sP?aRZ4l{Z?``9+I&-oMfghP`}X#lsWB9v zUAiU0+sb;*mULrSFV?YUlz=8Ab*FZ_udT?}+D)6NApoVAy1F`0c^GVAszl0UgB_|- z$k`5aS4wgZt$qM*Q`DjOxB5$55eaAB7Ns5YU&c(-{2`Wp=U<>ge^t`^-DGBt7Kqgl z==}0POV8Y#T+)rYeU?n5rA65mry+TZO+BL*OTe#uf41L`s>&cL?Qh4dkkmuFer*6R zaA~mQ-J`c-2wkL67QC-GJ{=t^U7o{)uvebM?OOLE_664sb=;+Klt(zP;U9eP`n|L0 z>VD3<>F;qTX_Y!0cuK-VYd1TxdzS;NuVVgIl{jr^ivLoF{|o1b`8{XBbYm}boDP^A zhJxkZBtWZ44|yU*sT9xo1s_^C+JpK`)#9|(t_q*V=RQbHE^75V%XIM$2syG^JpHZ5 zr0651c@wS6JRTHB9qN! z*x92X0>nk=6LCIEUQ^|#3b5UMikpfO7|>GtB?#Fvj{2iyJokKNeY{fnj}KY^7aS*t zhlhiMf*2?PP-ywEOgyxWZ@6v02t-Wg&`D(6F^1%pzv|rS#Y&d_o)hYfzzkAQ3Y7v1-3`7{=>4BCB%kNle7Bfg4bDrsvD}F zmn)W(LV5_LF!|iM9aKcZ1_WLvuKpyG{MN8NRsG-4lS5t{E3&FiAd&vAlHH=rVQ8)} zIAze@iuEhVXQTymeXyrgCT5>YO9%13K@4Pmp{}ENl^4B&%!0UQ?&z1~_KUxdv zici&>erMc#7jwKS0*um8Xyyzu3*n4RGuSTAK)XKE$Ijkfk^9I;-jP;X_NtK~H3krp z8$wf<)By1h?Z3Uhad^+xt;u6!*G##pXB^TKleXNT7CJ1xXIp+ZcC^`dsXIgE09)e^ zb(cWX+&SsdX<)Tig!5y9e2{L|=QX=mD?WOTzje;33Uw>?8-iwQlbYsv*GPq?KyOeE z(Ku#WG=LkpQxE(-N(-kuB-@0+0eS;Cg#U!eWS{__@l1HJ1UzPWcK?do6a_o_Db4kj z8tGLHnG!Qq<}#5Qlo-k;es`u0!)Op}eK>8`&Yj4KA!1RsZmlD#f4bo6vn5A#bktIt zTaAyr6n&sTPgmSIwqly+IXl zKRUYe%{6z2Ys2%ye!SJ}+Cdf~z&FN6N2>Goof-#`bn%J5R2ZP$;*& z2k7kM+3i3`fS8nBG#C0Y)vI&f{pye34^=KZm(DMSN|Y)*ZfWi=ejTXNIy$JDTH0-v zZNyoNecj7z0eX=XMM|8fN0~lO{=^33si4aM@qXuXFE?nHnh@KuM3ulzY=afm8~*LU zNZ|9EhGFKtu6$P|8SRnJH{%)a7tm#-)eo`r@JvI;gt3hN{wos`k2M6~m@_f$8d(J4 z2s$>Z949M^DC9R4&a`@zE$v?(*xzZ>LN6o|-)N-1jXPp-X&L$f9Koozpd6G>Y;=|Z zY6y}KHV&sEVB$C&D3!l0_?Gu2xooL;SiR_qkv&lYJ42rVQkf#}s~l+VE-4G=p+EQW z>L>f;S=y)O>RD;=aSU{aWE2}p_wCxhEvxNO%P4e5xW;;EDt4K9=8G_g{;Gb4kX z=A^@5?;Jms>IY)e>Kq};W+qCi`<3hUjvo&h_%%3aTO(I``M_twGy2WAQk)EVgn(v{ z3g6`e3=y?Orjw|2%aSIfeY!IHGFC%6d;gE)+Fpe0jon)V}4>C_Y=iX=Mvmg))dre!72h}^{52#$;o75d!weHd~dZDMKh(c9@CJ! z9E<2CN(wv~bm{cVDu|DJ{1{50Gk9W%GOobkjk)$wWtOuk*exN%9*9+s&p)M&m=W-< zM`u4Bi#8hCwpTS=m7huNMtC^9BPZcTWS~M2)L`xi4!G9#cIeEUW!|MftQ)@kbjOA( zl@*OAy)c=}!}2YeKP|0s_+FT3=2uUpFE%dslh+h={p#AW-*)XwB+VC@Hi&E29N{6I z4peLvI62~}@WgP}Dao#Mop_9BRp3sFj}NOIa5g9SwThbc{}fiz>t9%6xx<4}lZGXM z0ga|lI=-x?u;M>+KOb2W@aehNECfz$EHHux@M0xX3w$&)`4X#hCZO_ubw6gSJwt1c zvsIWm`fwU!2t+uTxnXV1xT);4I;AqFya%oFO|<=>kvK)JcrU$cIa13r@vb(7kwW=? zvhwFSYKte26*sO|ah+-6ceBz!L~2V&6WN z8|p_RwElLeR@*K^DW}JP#maF&i0NbT8IJIQuD1vF&;sebS2ghmVpcS`lA;JLgLx7H z1U!Pku7yIH&eUd@`Gw_$KaRSi#OAE+@}lVyh|6w_%*&^|suWDe1tlT|(spm$=yAj6 z!t}k16B4$vx_-jp^_$w;1%LSp`|vh~w+d=TDITW?-lpeJDOZdB|0`gr2 zqay{nIy;3THBiGC&=>qYHLa=%G3S4NVqxZORH*Gd748+QxbzlmRl)O9;mcM;pT8Te(_AnyejZ1Sh|L%yiHhE7|QczZqqmzLr zgLq>yEg{lF(VbimL!}9`Ia*#fBdlT~llYlCiN*1EC#yk8fr{6eb9#EZsq<2b z5UM7_T{Ia@;APlJR>9;e=)T6 z9;9?_!BnA8k;7#SYWfih-!=MwEYSP^I#}HQgi<+o9UEdyp7-w48EXwhkr=7*wC8Nt zYgc#|ti%!E^}t}KycW1FsL`?ajnC!NYii}~bNY??Wiyi+bYlf=IoGW3&Xx`vdAC=p zIhR((v4?cM)7hC2<>cXkvFf*O-^Q8$^&vmSfyuewEw)<$T7|&A#F$N!ula> zw9;z>}(&070MEVNaw~^OCaQj>AujRKfosq8d?qk~h)Q+h0GsE%MrHn=T+)usvky zqKGm+adB_AZ3tCBVNp?Dby7#qk1O-LMfB1gy#eIfO5!E{zTgW-19KSADgHYeEL)Ao(tJq$7X6%snz;_$eJ1oyg0vmfM5C&%J$Xq7gd`#K0Z`;Ftm06 zu~_+CWc=x5J@hdrPUN(Vewle%JD|xOW|ab>ibP_P{1<(W)ccE$%Z8GE`Mv~J3V5gJ zEe)PL#;O*Pwb0ZaJ-S5)a>yQfGd>IH`H(yPH zR*8oj4c_#ATU=reJ7sGtfWqj!EK+(Qh<;_0*ED>R)h^XCfdDWs-2i0%A7Ea*j-MoJ zr-BgR@YgnINwWH0fGs8x!(`b7hEv_-66w2(wdyaXGz*yte6-0^P1TRp4zj*$kcr$y zM@{#S)kpnBoKZ#8xI8C{?su^p>4IS_f2wNW&=Y>^_LqIOnF z2a4@L6R`$?4sV+<16@yKZlppTjvr^@+i`uQ5A^oPyZLEbesLem`fI)L|@N;0zA+Q;WsVJ{yA?z<0HJF~#` z|K4i_CN*eqF-VoOU^73Jq?FVx4S^rtOS>pQ|61(;nGsn&!~kCoj*S7IXFUDNlQy}v+45V9eTz{R z1~+$Bl$D_=`OIuNkp$2=M*cVekqWfNMdziiPCBpIvl;T&rj#W5Ey-T^3pT)bM^l)El% zq@;l3_V83FC8aXh9-!fn9(a(sG>V*`RpDHP|3xOT(UvjWaM!*w9}(T89VHNCji&PW zy&~~(RfL(XR%!V$W-dGmtSn(PZeg#sGakQf@D&*Ei(=AG+uS^Q)fvxEL#~_X=ybKU zol8FfNsKv6Ov?sHsmkB)QHJdDv2|>@6vSH3{r&Iu9i*y{C_!Wg0IUNC&q`}|S{6cL zB#PjtpP?4G7^3W8(ojGYcr1*SCX`=uAiBNqdOIa1e#XVE_C2~jSJFoeBE zflH~3)Hf*HaG19_LGF!geL#?zI1%}&s{C|25)bfN6`7s`R!qCzg;NZz2V%s?WT+01 ziO)%Q@HgQVxKvctWoG3Tx0b}Mi%23cD&8ax18BH(Gg5^f6%<5U-{lnPa(Yfo1gl{M z!}+^>dA!`UHCYz{wM@zkOlpaWKFr0Y_wv6P%Z{5jx z?-OZJn)1}w%W;~HOvVY3ZG<6LnQcy-@WOg6MfCO}R zIY8tG8Lp;0gl`j>BRF2vBCPO<0SErK=(C!5V-vtT;o$=gSsqoTa08+>+l?PgWpdE6{7~~BOWV@*+)cPsaAoGLW-Um}IrRLlb!52Mi zGIVs6etvdrMyv`1r!+rmb7^<^c*}P6ez-a{G5Mtp*}jg#LHqL_+~PyNZ4*SsDW|zD9pT zpN65g(Dp$~*?aCXdqI~1LVNIR>^V=CF~lqFp+!{u#y!Q^oJvVeg0O;_rWtIc3}{V5 z;Wgx%7yY%={0R;@wIuOawlu*GnsJ{8qT8vyAX%qT@zwJ1{*}@OyT$1%vovC=QgLbJ z!zPahKgp8ar5-fDQ<&$h8W35*#MbR6{1abb8*nQxvl9Q6bz*7P!c@ij0vv%5V|~BX zPh{%Dl?X}p*|Vb1*2(7WGHZgX3BEzothRJNLrg3In}n2pv(H&J{dK$23?RcbK6(_m z;%3Sa^;9(DIAHO0;(8|4D+0kJnMnNG8CP$kg5F@QTC=Z{%Y!aJC*aCpfHD_FzMNy_ z_5fa-&-nEH&a`xN2vz!%q#!F7Z+#c7pzp5pmlk7OIwhfHtVcj{sK_BL2Gx(3<~?5p&1hfd1^tz*+yjG=SETAh-{3xJy=>*Mo%u`i;JL#FiAbevT7@&Heu z=$$5q1bJ86t^yHV8S|O26T*`{d^AqZJ4$pv8ay=Ad%x1;ECXm2;u#I*uKPs2<4Y#L zvnx=1GrUfjLG%tbge-7+yLU&QFnn$aT|*zZyW%Wn>Yu-=`<7+y`!M<9v_=|FQWYs%zSKlr+T%1%!Wrp9Y06Ls-Q z6c=vpvN}Ha@*^S*fV5}A6H6e~b+(X`LZeKTzQ=}D&>M0g$cY+<^@%|Xb+&PL>NxlR zs?2|Wy!nmBXsKI>s?Be+zEDFW(djs07-srEB_No3v3zCG_alKUF^6qOMPVcH(_Vnl z+88>&SformnWU-f3B{3trU#=jsRFc*93j#-uokmsKcGJZnrnXo29_}-NSt7qH4{Aj z{Xtu1U!fy0z)d~XdKyT{$&B6F*(MZ=t0rP@B6(m{Y2fL3UkDtAlQ^C)`c2FPJz~87 z&zV*3LYV<)94h&0_2UOK)wpl|d6bhc0b;POuBDU1ChzW2?BwN%Z)3jRV3f`yGb>kp zz_&l}lvjL;{Ds4fiD9V^$1^kThK3GV1aDuNJJC5f2paU1trRBdvH*M$2zz8CR7Q{LVZs@5n|4N3_ z@5?L=hDf4dN^mKM~ ztGo`+w4Y=3+XRTJT zc$Ds2H{IvXG6^mM=?!-EdoI~&v3w=8`vhP&DM!-KeDXPWsNObukHFAAEtd9v+;VbD*y#4?;=0owicTT@}d2XN=It!|@ zx*ydd@-uy2^cGEifSVg|38+1E;TdgCm?Qra#}E<0_-)6Ica@VKD7=PHlObfJxR{tH z1FI|?Nli`NXN;cx!n!x^?y%$&i%&?MDm|Ig0Q$G1Ea zSg84^7^wr{0D$BsW%_Kh>kEP*3K9PORwle4uoS8ref>z>yInElU6}1-uzyta&S`J& zk3+5v@80F^O?Nvdmdg-iO-w^jPepqe=rI@6F@6!*J}5R(wXCwFuydJ<#dcIRzpqO| zF^7v#QA4Y3nbXk|tsx*3iqueCC$qX9SX8W$-(x~Nu8R@cf+ur^-mV-(SUGMeP6)Zg z)91Uuzbmw^yg9H5%^}|<_V=HygHj%%+h@Na6p9K{{CXD|TDo+hG39$k87(mTC+gNN zN7oRPB2Vil&o>y6nY8>PgEi>XX%NVM3-u=i4{ZU%BJs#jbYW;P$=ASrlKmh95mjB@ zG`eN>)tu+smFbm+m7XQ2oruDaPR~My+spdc)FOLN-PdN#35D~SLZNZ7u`a}ecWV=D zFq?Mf+z)Yf_&}t_AVi+)%)X+j`$CLRPQIyFepfD}?{}1hGBVjQu>mTg{Corc$lMF- zDK2BNAj2uXVSO^U$wuHwz~!O*e(=Dy-yp~ucLfMoaP>sf;LuK+Jl1OQWWA@~^np*J z+r)H`7p-SDkS=W^1_rDO+DOttNY|)q3TPTe*gun+J`>_!zI!nS@S@t*&Df?Hb)#T2 zWwPT(vNR}{wxmf0ru!CU9z-N2+tH7DLO&2xYYqj!KV4&!5=Z7^^N%!|ITpJSQG8Wn zP{D=YHRne`r>)Iyy9YBJZQGebw?7Yk-!HV-GkyE#)a|c+hb}xae1wTw5CP#U0E1RF z+G;dbqoa znS(uvK2XJFq7xAElAk~7;y9L#Ue0VsD$s2JwMJPHbNIDr=xZB~G6XLodwAV)zW0%_ zQchO3P2Y{p%ub857Mf13___`cqb5T^Ha_Fo`JLTsNh0d71nq87(O#TSUS4qSX^CPv zVpqaF%`IL-vP%0$rndH`D#KOO4x{dlJk+5nos_ZGcWpPV`FYr%Nv(ytIe&7s<+)f9 z*=jWa!jZ_S%QCVq>4p`xsPH?})Wt<#5VcqDXsD*XrB|w${^Y`?$WA6}_n!DMQ~N!q zT=!gpMkf|xu@z6_?&BlV#(qDVQ>Ghj@)AJpdB`%>m`{7><$X{|&VBIU>Wiz-A3RXK zWzcI2c{aFkSJx;J#{4H?RALD9N-1(8s;Xnh`p2Bo9|)KlGO>ge z6b-Jw;v2CcF?Ms$i{0!z!;MX1{X^okKJd{(d4YK(Fy)jBhj{V5dFpeLwI-a%^RG)z z2ZT$`bjWBabv_cr%07rJb|^%ku8#Cpx+k*m#aZUd%&#j7#9gEtywh7I3MGL5T$?fO zrSs=?q)RdXBCQoF0-AVaU+(#GtLQW7w4hr&Tawe4RbDxU-3C>}5rrAbq^1=_qM?9h zDc*Qms*%Og{ejc{ECNfX=gYy+R%)j% zccj{e*xM>IVzPl|lx?uuj<8uAgm|NIftp#kCAELfi{b7Ih6nG*=TO|DFJ3L43hX6~ zMo3Q#GNFJ){-oKbD=80&aBni1wwU707KpJz_IcdfN~!Ft#Iraj&lpnii=Oo1AFyL> z?!&h$Cze8^cizD{ zi&EPts|eKx!?U<;r6(Z(%{DT_*b!{^GYuy$#N)ip`PjDh^sf(AT$L^fiDrSk z*A#{;Z0kq5COv|y*9@qT{^fK?m-gm4=*j#1%Jm;_ubO!7>7X&UyvW84=_qGqPz}j5^ru$4E1Rt1?;^5ED7H|EDZI+J$etZaH6n zeP_IJW2?o>>$*pVyY4j&C&{=3@KPZV0%0)Z)~rQ0T3cr7KmfzI2r)s+u8AM(ACuSq z+5E6|MjTu%vJ=n%As{z>lt>b~Fx_jhbW+#Cq6ZQUe&#Sp8lW~p@(_E7s?|6tfERE; zynKcTIFBC92@iQ6`tSj=vXQ`iVS`m)n}rH+>|inQh*dmGebE7+)?0PX;v{%*3DpLfV+x zTr_rFPlymAk;#LurIl9S@Up#iqjt#UE9V0B2_-~AOT0C!v~pwlJB$3g_jEI~lp>mj zA)rEaaHX`evie_`l0<5M3x^C+3D8d0=*w=TvmcZ1ixu0sv+(TfbIb2@9kQ`0)aaCY zdv*0&fsJ$wFxTDXg7q^>0MYe@rf0@ZXeTx8L!y9$gmpm|bGw&G#DWEcjLS=l)&1WP z(Ks;YJ?nL?{H5Q|k>)feZ_79nZLj6$Qb)Uf1X2YM8H(7QphE$kvVH^5)|Api$$A3Q z^x#ng$LNCBQu8W69596k|KZc8>%4CeR0l2pH^!&EV=qokG-8~h9qU@3 zpe9*qLELiIZVY(13jEpbud>OLK~74H(h(nB%9=wtM;Jo}Lw4MIn3)L%f`FTq+sded zkwGR)umzyE-a?Vw;cPB#q601fleEzA!5ZD~3|&34`?R&SZOb}^{BcrapVt%Yya;Y#qDfBH=l>2ZvecqgI&2R!}#{cF}&m6kf6I;AZtmY_sqE;@9G z=TulCoJ;zvYHQ@Zqtl1~Kvzd6u-Y1;JbVm;O!d^vtSqgd zW(4i9sc+lq^&=&k|4Cb!lE=hdReoYn;A@-Xg;3PEpLeH>i)(*Sa@~ky=gvxXb(wji zbJFO-*l*mvb0=CrRz`;P#N(x)TORyZmtqvNB@qlNE^Z|m3q|JI%NUr6;t2;O_97$z z;GGf%u%aP=)xboZrf5I5OuJ!r4kaTJ%kULF2gV2Z|M5$oH{XjAoJkGj1S$nIaDZAi z$;Jq2@N4F$rk+GRq)?~<(|Is$a8Jgt#vIYV)kOyLhp98kdJwU~>W$raZ*67GiXdq_ zROjoyZ>K-(jP+>hg;^t@eJ3Wgbst0v8d@sNesT+Jv2N=s_#(_woxgHWl6H3d#ESR9 zvyaKg<5l_jG^4V~df+Ob?`IB^P1J?B67k8p_QgNkboigI-9U%3KHDhFn$_%BG%rP^T7-#v z(2p9y(O+h44)Hm#ih@&e_!c#Z0&|7blr8JPouO9etQLnD4cq+Sal0KQ*9_RA>ry0- zn+tzkSW-xen4aBuJN0JR;WTfQM+m#nX~A>H9Kqam`yRlUfm}mMWrw(_@o}@F(XjJ! z7Rav+O`)wuu461(cxJ1$L`Szu5Md8r>DYat*><=tx_@j;WhC3#_xZ$pc~fy=YARF+ zxaGJumG|dwvaS)ozR3ft-C)@Fq`equkcrPP$!mWb@f9E46(jcYSBg=VPT79Okmqyl zW?}7z=}t>M0X%)ugpa)Ltk47R#WT$|bC$3GAqWTu4|X)*vTK7AKP@^lM$`hiA+w@j zUGVjDwNDocB~*=S`rtYsGN~`#agfmhO~NU}Bti=