From 01d6ca3fdab7fb054e9f9d1c68f139322cdeaeea Mon Sep 17 00:00:00 2001 From: "David B. Kinder" Date: Wed, 14 Aug 2024 16:43:29 -0700 Subject: [PATCH] doc: Next phase of public docs * Publish all markdown from the repos as place holders for improved documentation that's under development * Work on community support, including documentation about documentation contributing and doc build process * improved organization of content into themed folders Signed-off-by: David B. Kinder --- Makefile | 13 +- community/ContributionGuidelines.txt | 951 +++++++++++++++++++ community/TSC_Gives_and_gets.md | 18 + community/charter.md | 77 ++ community/index.rst | 65 +- conf.py | 11 +- deploy.rst | 14 - deploy/index.rst | 74 ++ developer-guides/doc_guidelines.rst | 820 ++++++++++++++++ developer-guides/docbuild.rst | 147 ++- developer-guides/graphviz.rst | 123 +++ developer-guides/images/boot-flow.dot | 6 + developer-guides/images/circle-square.dot | 9 + developer-guides/images/gaspump.dot | 11 + developer-guides/images/node-shape-edges.dot | 8 + developer-guides/images/record.dot | 4 + developer-guides/images/trusty-boot-flow.dot | 11 + eval/index.rst | 24 + examples/index.rst | 119 +++ images/BrokenBlocks.png | Bin 48343 -> 18724 bytes index.rst | 11 +- introduction.rst => introduction/index.rst | 2 +- microservices.rst => microservices/index.rst | 17 +- scripts/fix-github-md-refs.sh | 5 +- sphinx/_static/images/BrokenBlocks.png | Bin 48343 -> 18724 bytes sphinx/extensions/link_roles.py | 64 ++ sphinx/substitutions.txt | 23 + 27 files changed, 2511 insertions(+), 116 deletions(-) create mode 100755 community/ContributionGuidelines.txt create mode 100644 community/TSC_Gives_and_gets.md create mode 100644 community/charter.md delete mode 100644 deploy.rst create mode 100644 deploy/index.rst create mode 100644 developer-guides/doc_guidelines.rst create mode 100644 developer-guides/graphviz.rst create mode 100644 developer-guides/images/boot-flow.dot create mode 100644 developer-guides/images/circle-square.dot create mode 100644 developer-guides/images/gaspump.dot create mode 100644 developer-guides/images/node-shape-edges.dot create mode 100644 developer-guides/images/record.dot create mode 100644 developer-guides/images/trusty-boot-flow.dot create mode 100644 eval/index.rst rename introduction.rst => introduction/index.rst (96%) rename microservices.rst => microservices/index.rst (66%) create mode 100644 sphinx/extensions/link_roles.py create mode 100644 sphinx/substitutions.txt diff --git a/Makefile b/Makefile index c34e6e38..ef44331b 100644 --- a/Makefile +++ b/Makefile @@ -47,13 +47,13 @@ help: content: $(Q)mkdir -p $(SOURCEDIR) $(Q)rsync -a --exclude=$(BUILDDIR) . $(SOURCEDIR) -# $(Q)for dir in $(RSYNC_DIRS); do\ -# rsync $(RSYNC_OPTS) ../$$dir $(SOURCEDIR); \ -# done + $(Q)for dir in $(RSYNC_DIRS); do\ + rsync $(RSYNC_OPTS) ../$$dir $(SOURCEDIR); \ + done # temporarily, copy docs content too (were in the docs-work) # $(Q)rsync $(RSYNC_OPTS) ../docs/* $(SOURCEDIR) -# $(Q)find $(SOURCEDIR) -type f -empty -name "README.md" -delete -# $(Q)scripts/fix-github-md-refs.sh $(SOURCEDIR) + $(Q)find $(SOURCEDIR) -type f -empty -name "README.md" -delete + $(Q)scripts/fix-github-md-refs.sh $(SOURCEDIR) html: content @@ -90,6 +90,9 @@ ifeq ($(RELEASE),latest) endif cd $(PUBLISHDIR)/..; git add -A; git commit -s -m "publish $(RELEASE)"; git push origin main; +server: + cd _build/html; python3 -m http.server + # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(OPTS) is meant as a shortcut for $(SPHINXOPTS). diff --git a/community/ContributionGuidelines.txt b/community/ContributionGuidelines.txt new file mode 100755 index 00000000..318aa5de --- /dev/null +++ b/community/ContributionGuidelines.txt @@ -0,0 +1,951 @@ +# Contribution Guidelines + +Thanks for considering contributing to the OPEA project. The contribution +process is similar with other open source projects on Github, involving an +amount of open discussion about issues and feature requests between the +maintainers, contributors, and users. + +As an open-source project, we welcome and encourage the community to submit +patches directly to the project. In our collaborative open source environment, +standards and methods for submitting changes help reduce the chaos that can +result from an active development community. + +This document explains how to participate in project conversations, log bugs and +enhancement requests, and submit patches to the project so your patch will be +accepted quickly in the codebase. + +## Support + +- Feel free to reach out to [opea@opea.dev](mailto: info@opea.dev) for support. +- Submit your questions, feature requests, and bug reports to the GitHub issues page. + +## Contributor Covenant Code of Conduct + +This project is intended to be a safe, welcoming space for collaboration, and +contributors are expected to adhere to the +[Contributor Covenant Code of Conduct](./CODE_OF_CONDUCT.md). + + +## Community Discussions + +Developers are encouraged to participate in discussions by opening an issue in +one of the GitHub repos at +[github.com/opea-project](https://github.com/opea-project). Alternatively, send +an email to [info@opea.dev](mailto:info@opea.dev) or subscribe to +[X/Twitter](https://twitter.com/opeadev) or +[LinkedIn](https://www.linkedin.com/company/opeadev/posts/?feedView=all) to get +the latest updates about the OPEA project. + +## Documentation + +The quality of OPEA project's documentation can have a huge impact on its +success. We reply on OPEA maintainers and contributors to build clear, detailed, +and update-to-date documentation for user. + + +## Licensing + +Licensing is very important to open source projects. It helps ensure the +software continues to be available under the terms that the author desired. + +.. _Apache 2.0 license: + https://github.com/opea-project/License/blob/main/LICENSE.txt + +.. _GitHub repo: https://github.com/opea-project + +OPEA uses the [Apache 2.0 license](https://github.com/opea-project/License/blob/main/LICENSE.txt) +(as found in the LICENSE file in +the project's [GitHub repos](https://github.com/opea-project) to strike a balance between open +contribution and allowing you to use the software however you would like +to. The Apache 2.0 license is a permissive open source license that +allows you to freely use, modify, distribute, and sell your own products +that include Apache 2.0 licensed software. + +A license tells you what rights you have as a developer, as provided by the +copyright holder. It is important that the contributor fully understands the +licensing rights and agrees to them. Sometimes the copyright holder isn't the +contributor, such as when the contributor is doing work on behalf of a +company. + +### Components using other Licenses + +Importing code into the OPEA project from other projects that use a license +other than the Apache 2.0 license needs to be fully understood in +context and approved by the OPEA governing board. + +By carefully reviewing potential contributions and also enforcing a +DCO for contributed code, we can ensure that +the OPEA community can develop products with the OPEA Project +without concerns over patent or copyright issues. + +## Copyrights Notices + +Please follow this [Community Best Practice](https://www.linuxfoundation.org/blog/copyright-notices-in-open-source-software-projects/) +for Copyright Notices from the Linux Foundation. + +## Developer Certification of Origin (DCO) + +To make a good faith effort to ensure licensing criteria are met, the OPEA +project requires the Developer Certificate of Origin (DCO) process to be +followed. + +The DCO is an attestation attached to every contribution made by every +developer. In the commit message of the contribution, (described more fully +later in this document), the developer simply adds a ``Signed-off-by`` +statement and thereby agrees to the DCO. + +When a developer submits a patch, it is a commitment that the contributor has +the right to submit the patch per the license. The DCO agreement is shown +below and at [developercertificate.org](http://developercertificate.org/). + +``` +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the + best of my knowledge, is covered under an appropriate open + source license and I have the right under that license to + submit that work with modifications, whether created in whole + or in part by me, under the same open source license (unless + I am permitted to submit under a different license), as + Indicated in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including + all personal information I submit with it, including my + sign-off) is maintained indefinitely and may be redistributed + consistent with this project or the open source license(s) + involved. +``` + +### DCO Sign-Off + +The sign-off in the DCO is a `Signed-off-by:` line in each commit's log +message. The Signed-off-by: line must be in the following format: + +``` +Signed-off-by: Your Name +``` + +For your commits, replace: + +- `Your Name` with your legal name (pseudonyms, hacker handles, and the + names of groups are not allowed) + +- `your.email@example.com` with the same email address you are using to + author the commit (CI will fail if there is no match) + +You can automatically add the Signed-off-by: line to your commit body using +`git commit -s`. Use other commits in the opea git history as examples. + +Additional requirements: + +- If you are altering an existing commit created by someone else, you must add + your Signed-off-by: line without removing the existing one. + +- If you forget to add the Signed-off-by: line, you can add it to your previous + commit by running `git commit --amend -s`. + +- If you've pushed your changes to GitHub already you'll need to force push + your branch after this with `git push -f`. + +### Notes + +Any contributions made as part of submitted pull requests are considered free +for the Project to use. Developers are permitted to cherry-pick patches that +are included in pull requests submitted by other contributors. It is expected +that + +* the content of the patches will not be substantially modified, +* the cherry-picked commits or portions of a commit shall preserve the original + sign-off messages and the author identity. + + +## Prerequisites + +As a contributor, you'll want to be familiar with the OPEA project, how to +configure, install, and use it and how to set up your development environment. + +You should be familiar with common developer tools such as Git, and +platforms such as GitHub. + + +## Proposing New Features + +OPEA communities use the RFC (request for comments) process for collaborating on +substantial changes to OPEA projects. The RFC process allows the contributors +to collaborate during the design process, providing clarity and validation +before jumping to implementation. + +The RFC process is necessary for changes which have a substantial impact on end +users, workflow, or user facing API. + +It generally includes: + +- Changes to core workflow. +- Changes with significant architectural implications. +- changes which modify or introduce user facing interfaces. + +It is not necessary for changes like: + +- Bug fixes and optimizations with no semantic change. +- Small features which do not involve workflow or interface changes, and only impact a narrow use case. + +Step-by-Step guidelines +####################### + +- Follow the [RFC Template](./rfc_template.md) to propose your idea. +- Submit the proposal to the `Issues` page of the corresponding OPEA github repository. +- Reach out to your RFC's assignee if you need any help with the RFC process. +- Amend your proposal in response to reviewer's feedback. + + +Pull Requests and Issues +************************ + +Submitting Pull Requests +######################## + +Create Pull Request +################### + +If you have improvements to OPEA projects, send your pull requests to each project for review. +If you are new to GitHub, view the pull request [How To](https://help.github.com/articles/using-pull-requests/). + +Step-by-Step guidelines +####################### + +- Star this repository using the button `Star` in the top right corner. +- Fork the corresponding OPEA repository using the button `Fork` in the top right corner. +- Clone your forked repository to your pc by running `git clone "url to your repo"` +- Create a new branch for your modifications by running `git checkout -b new-branch` +- Add your files with `git add -A`, commit `git commit -s -m "This is my commit message"` and push `git push origin new-branch`. +- Create a `pull request` for the project you want to contribute. + + +Pull Request Template +##################### + +See [PR template](./pull_request_template.md) + +Pull Request Acceptance Criteria +################################ + +- At least two approvals from reviewers + +- All detected status checks pass + +- All conversations solved + +- Third-party dependency license compatible + +Pull Request Status Checks Overview +################################### + +The OPEA projects use GitHub Action for CI test. + +| Test Name | Test Scope | Test Pass Criteria | +|--------------------|-------------------------------------------|--------------------| +| DCO | Use `git commit -s` to sign off | PASS | +| Code Format Scan | pre-commit.ci [Bot] | PASS | +| Code Security Scan | Bandit/Hadolint/Dependabot/CodeQL/Trellix | PASS | +| Unit Test | Unit test under test folder | PASS | +| End to End Test | End to end test workflow | PASS | + +- [Developer Certificate of Origin (DCO)](https://en.wikipedia.org/wiki/Developer_Certificate_of_Origin), the PR must agree to the terms of Developer Certificate of Origin by signing off each of commits with `-s`, e.g. `git commit -s -m 'This is my commit message'`. +- Unit Test, the PR must pass all unit tests and without coverage regression. +- End to End Test, the PR must pass all end to end tests. + - If the PR introduces new microservice for `GenAIComps`, the PR must include new end to end tests. The test script name should match with the folder name so the test will be automatically triggered by test structure, for examples, if the new service is `GenAIComps/comps/dataprep/redis/langchain`, then the test script name should be `GenAIComps/tests/test_dataprep_redis_langchain.sh`. + - If the PR introduces new example for `GenAIExamples`, the PR must include new example end to end tests. The test script name should match with the example name so the test will be automatically triggered by test structure, for examples, if the example is `GenAIExamples/ChatQnA`, then the test script name should be `ChatQnA/tests/test_chatqna_on_gaudi.sh` and `ChatQnA/tests/test_chatqna_on_xeon.sh`. + +Pull Request Review +################### +You can add reviewers from [the code owners list](../codeowner.md) to your PR. + + +.. _OPEA Project Issues: https://github.com/search?q=org%3Aopea-project+%2Fissues&type=issues + +.. _open pull requests: https://github.com/opea-project/GenAIComps/pulls + +.. _OPEA Technical Discuss: mailing list: https://lists.lfaidata.foundation/g/OPEA-technical-discuss + + +Before starting on a patch, first check in our issues `OPEA Project Issues`_ +system to see what's been reported on the issue you'd like to address. Have a +conversation on the `OPEA Technical Discuss` to see what others think of your issue (and proposed solution). You +may find others that have encountered the issue you're finding, or that have +similar ideas for changes or additions. Send a message to the `OPEA Technical Discuss`_ to introduce and discuss your idea with the development +community. + +It's always a good practice to search for existing or related issues before +submitting your own. When you submit an issue (bug or feature request), the +triage team will review and comment on the submission, typically within a few +business days. + +You can find all `open pull requests`_ on GitHub and open `OPEA Project Issues`_ in Github issues. + + +### Reporting Issues + +If OPEA user runs into some unexpected behavior, reporting the issue to the `Issues` page under the corresponding github project is the proper way to do. Please ensure there is no similar one already existing on the issue list). Please follow the Bug Report template and supply as much information as you can, and any additional insights you might have. It's helpful if the issue submitter can narrow down the problematic behavior to a minimal reproducible test case. + + +.. _git_setup: + +Git Setup +********* + +We need to know who you are, and how to contact you. To add this +information to your Git installation, set the Git configuration +variables ``user.name`` to your full name, and ``user.email`` to your +email address. + +For example, if your name is ``OPEA Developer`` and your email +address is ``opea.developer@example.com``: + +.. code-block:: console + + git config --global user.name "OPEA Developer" + git config --global user.email "opea.developer@example.com" + + +Pull Request Guidelines +*********************** +When opening a new Pull Request, adhere to the following guidelines to ensure +compliance with OPEA standards and facilitate the review process. + +If in doubt, it's advisable to explore existing Pull Requests within the OPEA +repository. Use the search filters and labels to locate PRs related to changes +similar to the ones you are proposing. + +.. _commit-guidelines: + +Commit Message Guidelines +========================= + +Changes are submitted as Git commits. Each commit has a *commit +message* describing the change. Acceptable commit messages look like +this: + +.. code-block:: none + + [area]: [summary of change] + + [Commit message body (must be non-empty)] + + Signed-off-by: [Your Full Name] <[your.email@address]> + +You need to change text in square brackets (``[like this]``) above to +fit your commit. + +Examples and more details follow. + +Example +------- + +Here is an example of a good commit message. + +.. code-block:: none + + drivers: sensor: abcd1234: fix bus I/O error handling + + The abcd1234 sensor driver is failing to check the flags field in + the response packet from the device which signals that an error + occurred. This can lead to reading invalid data from the response + buffer. Fix it by checking the flag and adding an error path. + + Signed-off-by: OPEA Developer + +[area]: [summary of change] +--------------------------- + +This line is called the commit's *title*. Titles must be: + +* one line +* less than 72 characters long +* followed by a completely blank line + +[area] + The ``[area]`` prefix usually identifies the area of code + being changed. It can also identify the change's wider + context if multiple areas are affected. + + Here are some examples: + + * ``doc: ...`` for documentation changes + * ``drivers: foo:`` for ``foo`` driver changes + * ``Bluetooth: Shell:`` for changes to the Bluetooth shell + * ``net: ethernet:`` for Ethernet-related networking changes + * ``dts:`` for treewide devicetree changes + * ``style:`` for code style changes + + If you're not sure what to use, try running ``git log FILE``, where + ``FILE`` is a file you are changing, and using previous commits that + changed the same file as inspiration. + +[summary of change] + The ``[summary of change]`` part should be a quick description of + what you've done. Here are some examples: + + * ``doc: update wiki references to new site`` + * ``drivers: sensor: sensor_shell: fix channel name collision`` + +Commit Message Body +------------------- + +.. warning:: + + An empty commit message body is not permitted. Even for trivial + changes, please include a descriptive commit message body. Your + pull request will fail CI checks if you do not. + +This part of the commit should explain what your change does, and why +it's needed. Be specific. A body that says ``"Fixes stuff"`` will be +rejected. Be sure to include the following as relevant: + +* **what** the change does, +* **why** you chose that approach, +* **what** assumptions were made, and +* **how** you know it works -- for example, which tests you ran. + +Each line in your commit message should usually be 75 characters or +less. Use newlines to wrap longer lines. Exceptions include lines +with long URLs, email addresses, etc. + +For examples of accepted commit messages, you can refer to the OPEA GitHub +`changelog `__. + + +Signed-off-by: ... +------------------ + +.. tip:: + + You should have set your :ref:`git_setup` + already. Create your commit with ``git commit -s`` to add the + Signed-off-by: line automatically using this information. + +For open source licensing reasons, your commit must include a +Signed-off-by: line that looks like this: + +.. code-block:: none + + Signed-off-by: [Your Full Name] <[your.email@address]> + +For example, if your full name is ``OPEA Developer`` and your email +address is ``opea.developer@example.com``: + +.. code-block:: none + + Signed-off-by: OPEA Developer + +This means that you have personally made sure your change complies +with the :ref:`DCO`. For this reason, you must use your legal name. +Pseudonyms or "hacker aliases" are not permitted. + +Your name and the email address you use must match the name and email +in the Git commit's ``Author:`` field. + +See the :ref:`contributor-expectations` for a more complete discussion of +contributor and reviewer expectations. + +Adding links +------------ + +.. _GitHub references: + https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/autolinked-references-and-urls + +Do not include `GitHub references`_ in the commit message directly, as it can +lose meaning in case the repository is forked, for example. Instead, if the +change addresses a specific GitHub issue, include in the Pull Request message a +line of the form: + +.. code-block:: none + + Fixes #[issue number] + +Where ``[issue number]`` is the relevant GitHub issue's number. For +example: + +.. code-block:: none + + Fixes: #1234 + +You can point to other relevant information that can be found on the web using +:code:`Link:` tags. This includes, for example: GitHub issues, datasheets, +reference manuals, etc. + +.. code-block:: none + + Link: https://github.com/opea-project/genAIComps/issues + +.. _coding_style: + +Coding Style +============ + +.. _Linux kernel coding style: + https://kernel.org/doc/html/latest/process/coding-style.html + +In general, follow the `Linux kernel coding style`_, with the following +exceptions: + +* The line length is 100 columns or fewer. In the documentation, longer lines + for URL references are an allowed exception. +* Add braces to every ``if``, ``else``, ``do``, ``while``, ``for`` and + ``switch`` body, even for single-line code blocks. Use the ``--ignore BRACES`` + flag to make *checkpatch* stop complaining. +* Use spaces instead of tabs to align comments after declarations, as needed. +* Use C89-style single line comments, ``/* */``. The C99-style single line + comment, ``//``, is not allowed. +* Use ``/** */`` for doxygen comments that need to appear in the documentation. +* Avoid using binary literals (constants starting with ``0b``). +* Avoid using non-ASCII symbols in code, unless it significantly improves + clarity, avoid emojis in any case. + +Use these coding guidelines to ensure that your development complies with the +project's style and naming conventions. + +The Linux kernel GPL-licensed tool ``checkpatch`` is used to check +coding style conformity. + +.. note:: + checkpatch does not currently run on Windows. + +Checkpatch is available in the scripts directory. To invoke it when committing +code, make the file *$OPEA_BASE/.git/hooks/pre-commit* executable and edit +it to contain: + +.. code-block:: bash + + #!/bin/sh + set -e exec + exec git diff --cached | ${OPEA_BASE}/scripts/checkpatch.pl - + +Instead of running checkpatch at each commit, you may prefer to run it only +before pushing on OPEA repo. To do this, make the file +*$OPEA_BASE/.git/hooks/pre-push* executable and edit it to contain: + +.. code-block:: bash + + #!/bin/sh + remote="$1" + url="$2" + + z40=0000000000000000000000000000000000000000 + + echo "Run push hook" + + while read local_ref local_sha remote_ref remote_sha + do + args="$remote $url $local_ref $local_sha $remote_ref $remote_sha" + exec ${OPEA_BASE}/scripts/series-push-hook.sh $args + done + + exit 0 + +If you want to override checkpatch verdict and push you branch despite reported +issues, you can add option --no-verify to the git push command. + +A more complete alternative to this is using :ref:`check_compliance_py` script. + +clang-format +------------ + +The `clang-format tool `_ can +be helpful to quickly reformat large amounts of new source code to our +`Coding Style`_ standards together with the ``.clang-format`` configuration file +provided in the repository. ``clang-format`` is well integrated into most +editors, but you can also run it manually like this: + +.. code-block:: bash + + clang-format -i my_source_file.c + +``clang-format`` is part of LLVM, which can be downloaded from the project +`releases page `_. Note that if +you are a Linux user, ``clang-format`` will likely be available as a package in +your distribution repositories. + +When there are differences between the `Coding Style`_ guidelines and the +formatting generated by code formatting tools, the `Coding Style`_ guidelines +take precedence. If there is ambiguity between formatting tools and the +guidelines, maintainers may decide which style should be adopted. + +.. _Continuous Integration: + +Continuous Integration (CI) +=========================== + +The OPEA Project operates a Continuous Integration (CI) system that runs on +every Pull Request (PR) in order to verify several aspects of the PR: + +* Git commit formatting +* Coding Style +* Twister builds for multiple architectures and boards +* Documentation build to verify any doc changes + +CI is run on Github Actions and it uses the same tools described in the +`CI Tests`_ section. The CI results must be green indicating "All +checks have passed" before the Pull Request can be merged. CI is run when the +PR is created, and again every time the PR is modified with a commit. + +The current status of the CI run can always be found at the bottom of the +GitHub PR page, below the review status. Depending on the success or failure +of the run you will see: + +* "All checks have passed" +* "All checks have failed" + +In case of failure you can click on the "Details" link presented below the +failure message in order to navigate to ``Github Actions`` and inspect the +results. +Once you click on the link you will be taken to the ``Github actions`` summary +results page where a table with all the different builds will be shown. To see +what build or test failed click on the row that contains the failed (i.e. +non-green) build. + +.. _CI Tests: + +Running CI Tests Locally +======================== + +.. _check_compliance_py: + +check_compliance.py +------------------- + +The ``check_compliance.py`` script serves as a valuable tool for assessing code +compliance with OPEA's established guidelines and best practices. The script +acts as wrapper for a suite of tools that performs various checks, including +linters and formatters. + +Developers are encouraged to run the script locally to validate their changes +before opening a new Pull Request: + +.. code-block:: bash + + ./scripts/ci/check_compliance.py -c upstream/main.. + +twister +------- + +.. note:: + twister is only fully supported on Linux; on Windows and MacOS the execution + of tests is not supported, only building. + +If you think your change may break some test, you can submit your PR as a draft +and let the project CI automatically run the :ref:`twister_script` for you. + +If a test fails, you can check from the CI run logs how to rerun it locally, +for example: + +.. code-block:: bash + + west twister -p native_sim -s tests/drivers/build_all/sensor/sensors.generic_test + +.. _static_analysis: + +Static Code Analysis +******************** + +Coverity Scan is a free service for static code analysis of Open Source +projects. It is based on Coverity's commercial product and is able to analyze +C, C++ and Java code. + +Coverity's static code analysis doesn't run the code. Instead of that it uses +abstract interpretation to gain information about the code's control flow and +data flow. It's able to follow all possible code paths that a program may take. +For example the analyzer understands that malloc() returns a memory that must +be freed with free() later. It follows all branches and function calls to see +if all possible combinations free the memory. The analyzer is able to detect +all sorts of issues like resource leaks (memory, file descriptors), NULL +dereferencing, use after free, unchecked return values, dead code, buffer +overflows, integer overflows, uninitialized variables, and many more. + +The results are available on the `Coverity Scan +`_ website. In order to access the +results you have to create an account yourself. From the OPEA project page, +you may select "Add me to project" to be added to the project. New members must +be approved by an admin. + +Static analysis of the OPEA codebase is conducted on a bi-weekly basis. GitHub +issues are automatically created for any issues detected by static analysis +tools. These issues will have the same (or equivalent) priority initially +defined by the tool. + +To ensure accountability and efficient issue resolution, they are assigned to +the respective maintainer who is responsible for the affected code. + +A dedicated team comprising members with expertise in static analysis, code +quality, and software security ensures the effectiveness of the static +analysis process and verifies that identified issues are properly +triaged and resolved in a timely manner. + +Workflow +======== + +If after analyzing the Coverity report it is concluded that it is a false +positive please set the classification to either "False positive" or +"Intentional", the action to "Ignore", owner to your own account and add a +comment why the issue is considered false positive or intentional. + +Update the related Github issue in the OPEA project with the details, and only close +it after completing the steps above on scan service website. Any issues +closed without a fix or without ignoring the entry in the scan service will be +automatically reopened if the issue continues to be present in the code. + +.. _Contribution workflow: + +Contribution Workflow +********************* + +One general practice we encourage, is to make small, +controlled changes. This practice simplifies review, makes merging and +rebasing easier, and keeps the change history clear and clean. + +When contributing to the OPEA Project, it is also important you provide as much +information as you can about your change, update appropriate documentation, +and test your changes thoroughly before submitting. + +The general GitHub workflow used by OPEA developers uses a combination of +command line Git commands and browser interaction with GitHub. As it is with +Git, there are multiple ways of getting a task done. We'll describe a typical +workflow here: + +.. _Create a Fork of OPEA: + https://github.com/opea-project#fork-destination-box + +#. `Create a Fork of OPEA`_ + to your personal account on GitHub. (Click on the fork button in the top + right corner of the OPEA project repo page in GitHub.) + +#. On your development computer, change into the :file:`OPEA` folder that was + created when you :ref:`obtained the code `:: + + cd opea-project + + Rename the default remote pointing to the `upstream repository + `_ from ``origin`` to + ``upstream``:: + + git remote rename origin upstream + + Let Git know about the fork you just created, naming it ``origin``:: + + git remote add origin https://github.com//opea-project + + and verify the remote repos:: + + git remote -v + + The output should look similar to:: + + origin https://github.com//opea-project (fetch) + origin https://github.com//opea-project (push) + upstream https://github.com/opea-project (fetch) + upstream https://github.com/opea-project(push) + +#. Create a topic branch (off of ``main``) for your work (if you're addressing + an issue, we suggest including the issue number in the branch name):: + + git checkout main + git checkout -b fix_comment_typo + + Some OPEA subsystems do development work on a separate branch from + ``main`` so you may need to indicate this in your checkout:: + + git checkout -b fix_out_of_date_patch origin/net + +#. Make changes, test locally, change, test, test again, ... (Check out the + prior chapter on `twister`_ as well). + +#. When things look good, start the pull request process by adding your changed + files:: + + git add [file(s) that changed, add -p if you want to be more specific] + + You can see files that are not yet staged using:: + + git status + +#. Verify changes to be committed look as you expected:: + + git diff --cached + +#. Commit your changes to your local repo:: + + git commit -s + + The ``-s`` option automatically adds your ``Signed-off-by:`` to your commit + message. Your commit will be rejected without this line that indicates your + agreement with the :ref:`DCO`. See the :ref:`commit-guidelines` section for + specific guidelines for writing your commit messages. + +#. Push your topic branch with your changes to your fork in your personal + GitHub account:: + + git push origin fix_comment_typo + +#. In your web browser, go to your forked repo and click on the + ``Compare & pull request`` button for the branch you just worked on and + you want to open a pull request with. + +#. Review the pull request changes, and verify that you are opening a pull + request for the ``main`` branch. The title and message from your commit + message should appear as well. + +#. A bot will assign one or more suggested reviewers (based on the + MAINTAINERS file in the repo). If you are a project member, you can + select additional reviewers now too. + +#. Click on the submit button and your pull request is sent and awaits + review. Email will be sent as review comments are made, or you can check + on your pull request at https://github.com/opea-project/pulls. + + .. note:: As more commits are merged upstream, the GitHub PR page will show + a ``This branch is out-of-date with the base branch`` message and a + ``Update branch`` button on the PR page. That message should be ignored, + as the commits will be rebased as part of merging anyway, and triggering + a branch update from the GitHub UI will cause the PR approvals to be + dropped. + +#. While you're waiting for your pull request to be accepted and merged, you + can create another branch to work on another issue. (Be sure to make your + new branch off of ``main`` and not the previous branch.):: + + git checkout main + git checkout -b fix_another_issue + + and use the same process described above to work on this new topic branch. + +#. If reviewers do request changes to your patch, you can interactively rebase + commit(s) to fix review issues. In your development repo:: + + git rebase -i ^ + + In the interactive rebase editor, replace ``pick`` with ``edit`` to select + a specific commit (if there's more than one in your pull request), or + remove the line to delete a commit entirely. Then edit files to fix the + issues in the review. + + As before, inspect and test your changes. When ready, continue the + patch submission:: + + git add [file(s)] + git rebase --continue + + Update commit comment if needed, and continue:: + + git push --force origin fix_comment_typo + + By force pushing your update, your original pull request will be updated + with your changes so you won't need to resubmit the pull request. + +#. After pushing the requested change, check on the PR page if there is a + merge conflict. If so, rebase your local branch:: + + git fetch --all + git rebase --ignore-whitespace upstream/main + + The ``--ignore-whitespace`` option stops ``git apply`` (called by rebase) + from changing any whitespace. Resolve the conflicts and push again:: + + git push --force origin fix_comment_typo + + .. note:: While amending commits and force pushing is a common review model + outside GitHub, and the one recommended by OPEA, it's not the main + model supported by GitHub. Forced pushes can cause unexpected behavior, + such as not being able to use "View Changes" buttons except for the last + one - GitHub complains it can't find older commits. You're also not + always able to compare the latest reviewed version with the latest + submitted version. When rewriting history GitHub only guarantees access + to the latest version. + +#. If the CI run fails, you will need to make changes to your code in order + to fix the issues and amend your commits by rebasing as described above. + Additional information about the CI system can be found in + `Continuous Integration`_. + +.. _contribution_tips: + +Contribution Tips +================= + +The following is a list of tips to improve and accelerate the review process of +Pull Requests. If you follow them, chances are your pull request will get the +attention needed and it will be ready for merge sooner than later: + +.. _git-rebase: + https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---keep-base + +#. When pushing follow-up changes, use the ``--keep-base`` option of + `git-rebase`_ + +#. On the PR page, check if the change can still be merged with no merge + conflicts + +#. Make sure title of PR explains what is being fixed or added + +#. Make sure your PR has a body with more details about the content of your + submission + +#. Make sure you reference the issue you are fixing in the body of the PR + +#. Watch early CI results immediately after submissions and fix issues as they + are discovered + +#. Revisit PR after 1-2 hours to see the status of all CI checks, make sure all + is green + +#. If you get request for changes and submit a change to address them, make + sure you click the "Re-request review" button on the GitHub UI to notify + those who asked for the changes + + + +Identifying Contribution Origin +=============================== + +When adding a new file to the tree, it is important to detail the source of +origin on the file, provide attributions, and detail the intended usage. In +cases where the file is an original to OPEA, the commit message should +include the following ("Original" is the assumption if no Origin tag is +present):: + + Origin: Original + +In cases where the file is :ref:`imported from an external project +`, the commit message shall contain details regarding +the original project, the location of the project, the SHA-id of the origin +commit for the file and the intended purpose. + +For example, a copy of a locally maintained import:: + + Origin: Contiki OS + License: BSD 3-Clause + URL: http://www.contiki-os.org/ + commit: 853207acfdc6549b10eb3e44504b1a75ae1ad63a + Purpose: of networking stack. + +For example, a copy of an externally maintained import in a module repository:: + + Origin: Tiny Crypt + License: BSD 3-Clause + URL: https://github.com/01org/tinycrypt + commit: 08ded7f21529c39e5133688ffb93a9d0c94e5c6e + Purpose: of TinyCrypt + + + + + diff --git a/community/TSC_Gives_and_gets.md b/community/TSC_Gives_and_gets.md new file mode 100644 index 00000000..25f5b8a8 --- /dev/null +++ b/community/TSC_Gives_and_gets.md @@ -0,0 +1,18 @@ +# Technical Steering Committee (TSC) Gives & Gets + +## TSC Member Gives + +- Attend two 1-hour meetings a month +- Keep up with technical changes/suggestions in order to vote +- Facilitate contributions from your company and others +- Help resolve issues +- Promote the project via your company’s social media channels (optional) +- Attend OPEA events (optional) + +## TSC Member Gets + +- A vote and voice in steering the direction of the project + - Control of project scope and budget allocation +- Thought leadership +- Build your company’s reputation in GenAI technology space +- Collaborate/partner with other companies to build business opportunities diff --git a/community/charter.md b/community/charter.md new file mode 100644 index 00000000..437292de --- /dev/null +++ b/community/charter.md @@ -0,0 +1,77 @@ +# Technical Charter (the “Charter”) for OPEA a Series of LF Projects, LLC + + +Adopted April 12, 2024 + +This Charter sets forth the responsibilities and procedures for technical contribution to, and oversight of, the OPEA open source project, which has been established as OPEA a Series of LF Projects, LLC (the “Project”). LF Projects, LLC (“LF Projects”) is a Delaware series limited liability company. All contributors (including committers, maintainers, and other technical positions) and other participants in the Project (collectively, “Collaborators”) must comply with the terms of this Charter. + + +## 1. Mission and Scope of the Project + + 1. The mission of the Project is to develop an ecosystem orchestration framework to efficiently integrate performant GenAI technologies and workflows leading to quicker GenAI adoption and business value. + 2. The scope of the Project includes collaborative development under the Project License (as defined herein) supporting the mission, including documentation, testing, integration and the creation of other artifacts that aid the development, deployment, operation or adoption of the open source project. + +## 2. Technical Steering Committee + + 1. The Technical Steering Committee (the “TSC”) will be responsible for all technical oversight of the open source Project. + 2. The TSC voting members are initially those individuals listed as voting members of the TSC in the GOVERNANCE.MD file in the Project’s governance repo. At the inception of the project, the Maintainers of the Project will be as set forth within the “CONTRIBUTING” file within the Project’s code repository. The TSC may choose an alternative approach for determining the voting members of the TSC, and any such alternative approach will be documented in the GOVERNANCE file. The Project intends to determine additional details on composition of the TSC to enable increased diversity of organizations represented on the TSC within 12 months following the inception of the Project, or such other time as determined by the TSC (the “Steady State Transition”). The TSC expects to have no one company employing more than 50% of the voting members of the TSC by the Steady State Transition. It is expected that the terms of TSC voting members will vary initially (with roughly half 1 year and the remainder 2 years) so that elections will be staggered. Any meetings of the Technical Steering Committee are intended to be open to the public, and can be conducted electronically, via teleconference, or in person. + 3. TSC projects generally will involve Contributors and Maintainers. The TSC may adopt or modify roles so long as the roles are documented in the CONTRIBUTING file. Unless otherwise documented: + 1. Contributors include anyone in the technical community that contributes code, documentation, or other technical artifacts to the Project; + 2. Maintainers are Contributors who have earned the ability to modify (“commit” or merge pull requests) source code, documentation or other technical artifacts in a project’s repository; and + 3. A Contributor may become a Maintainer by a majority approval of the existing Maintainers. A Maintainer may be removed by a majority approval of the other existing Maintainers. + 4. Participation in the Project through becoming a Contributor and Maintainer is open to anyone so long as they abide by the terms of this Charter. + 5. The TSC may (1) establish workflow procedures for the submission, approval, and closure/archiving of sub-projects, (2) set requirements for the promotion of Contributors to Maintainer status, as applicable, and (3) amend, adjust, refine and/or eliminate the roles of Contributors, and Maintainers, and create new roles, and publicly document any TSC roles, as it sees fit. + 6. The TSC may elect a TSC Chair, who will preside over meetings of the TSC and will serve until their resignation or replacement by the TSC. The TSC Chair, or any other TSC member so designated by the TSC, will serve as the primary communication contact between the Project and LF AI & Data Foundation, a directed fund of The Linux Foundation. + 7. Responsibilities: The TSC will be responsible for all aspects of technical oversight relating to the Project, which may include: + 1. coordinating the technical direction of the Project; + 2. approving project or system proposals (including, but not limited to, incubation, deprecation, and changes to a sub-project’s scope); + 3. organizing sub-projects and removing sub-projects; + 4. creating committees or working groups (for example, an executive or architectural committee or end-user advisory committee) to support the Project; + 5. appointing representatives to work with other open source or open standards communities; + 6. establishing community norms, workflows, issuing releases, and security issue reporting policies; + 7. approving and implementing policies and processes for contributing (to be published in the CONTRIBUTING file) and coordinating with the series manager of the Project (as provided for in the Series Agreement, the “Series Manager”) to resolve matters or concerns that may arise as set forth in Section 7 of this Charter; + 8. discussions, seeking consensus, and where necessary, voting on technical matters relating to the code base that affect multiple sub-projects; and + 9. coordinating any marketing, events, or communications regarding the Project. + +## 3. TSC Voting + + 1. While the Project aims to operate as a consensus-based community, if any TSC decision requires a vote to move forward, the voting members of the TSC will vote on a one vote per voting member basis. + 2. Quorum for TSC meetings requires at least fifty percent of all voting members of the TSC to be present. The TSC may continue to meet if quorum is not met but will be prevented from making any decisions at the meeting. + 3. Except as provided in Section 7.c. and 8.a, decisions by vote at a meeting require a majority vote of those voting members in attendance, provided quorum is met. Decisions made by electronic vote without a meeting require a majority vote of all voting members of the TSC. + 4. In the event a vote cannot be resolved by the TSC, any voting member of the TSC may refer the matter to the Series Manager for assistance in reaching a resolution. + +## 4. Compliance with Policies + + 1. This Charter is subject to the Series Agreement for the Project and the Operating Agreement of LF Projects. Contributors will comply with the policies of LF Projects as may be adopted and amended by LF Projects, including, without limitation the policies listed at https://lfprojects.org/policies/. + 2. The TSC may adopt a Project-specific code of conduct (“CoC”) for the Project, which is subject to approval by the Series Manager. In the event that a Project-specific CoC has not been approved, the LF Projects Code of Conduct listed at https://lfprojects.org/policies will apply for all Collaborators in the Project. + 3. When amending or adopting any policy applicable to the Project, LF Projects will publish such policy, as to be amended or adopted, on its web site at least 30 days prior to such policy taking effect; provided, however, that in the case of any amendment of the Trademark Policy or Terms of Use of LF Projects, any such amendment is effective upon publication on LF Project’s web site. + 4. All Collaborators must allow open participation from any individual or organization meeting the requirements for contributing under this Charter and any policies adopted for all Collaborators by the TSC, regardless of competitive interests. Put another way, the Project community must not seek to exclude any participant based on any criteria, requirement, or reason other than those that are reasonable and applied on a non-discriminatory basis to all Collaborators in the Project community. + 5. The Project will operate in a transparent, open, collaborative, and ethical manner at all times. The output of all Project discussions, proposals, timelines, decisions, and status should be made open and easily visible to all. Any potential violations of this requirement should be reported immediately to the Series Manager. + +## 5. Community Assets + + 1. LF Projects will hold title to all trade or service marks used by the Project (“Project Trademarks”), whether based on common law or registered rights. Project Trademarks will be transferred and assigned to LF Projects to hold on behalf of the Project. Any use of any Project Trademarks by Collaborators in the Project will be in accordance with the license from LF Projects and inure to the benefit of LF Projects. + 2. The Project will, as permitted and in accordance with such license from LF Projects, develop and own all Project GitHub and social media accounts, and domain name registrations created by the Project community. + 3. Under no circumstances will LF Projects be expected or required to undertake any action on behalf of the Project that is inconsistent with the tax-exempt status or purpose, as applicable, of the Joint Development Foundation or LF Projects, LLC. + +## 6. General Rules and Operations. + + 1. The Project will: + 1. engage in the work of the Project in a professional manner consistent with maintaining a cohesive community, while also maintaining the goodwill and esteem of LF Projects, Joint Development Foundation and other partner organizations in the open source community; and + 2. respect the rights of all trademark owners, including any branding and trademark usage guidelines. + +## 7. Intellectual Property Policy + + 1. Collaborators acknowledge that the copyright in all new contributions will be retained by the copyright holder as independent works of authorship and that no contributor or copyright holder will be required to assign copyrights to the Project. + 2. Except as described in Section 7.c., all contributions to the Project are subject to the following: + 1. All new inbound code contributions to the Project must be made using Apache License, Version 2.0 available at http://www.apache.org/licenses/LICENSE-2.0 (the “Project License”). + 2. All new inbound code contributions must also be accompanied by a Developer Certificate of Origin (http://developercertificate.org) sign-off in the source code system that is submitted through a TSC-approved contribution process which will bind the authorized contributor and, if not self-employed, their employer to the applicable license; + 3. All outbound code will be made available under the Project License. + 4. Documentation will be received and made available by the Project under the Creative Commons Attribution 4.0 International License (available at http://creativecommons.org/licenses/by/4.0/). + 5. The Project may seek to integrate and contribute back to other open source projects (“Upstream Projects”). In such cases, the Project will conform to all license requirements of the Upstream Projects, including dependencies, leveraged by the Project. Upstream Project code contributions not stored within the Project’s main code repository will comply with the contribution process and license terms for the applicable Upstream Project. + 3. The TSC may approve the use of an alternative license or licenses for inbound or outbound contributions on an exception basis. To request an exception, please describe the contribution, the alternative open source license(s), and the justification for using an alternative open source license for the Project. License exceptions must be approved by a two-thirds vote of the entire TSC. + 4. Contributed files should contain license information, such as SPDX short form identifiers, indicating the open source license or licenses pertaining to the file. + +## 8. Amendments + + 1. This charter may be amended by a two-thirds vote of each of the entire TSC and is subject to approval by LF Projects. diff --git a/community/index.rst b/community/index.rst index bc95f158..ccad1934 100644 --- a/community/index.rst +++ b/community/index.rst @@ -3,13 +3,74 @@ OPEA Community ############## -paragraph here +Community Support +***************** + +Welcome to the OPEA project community! + +The OPEA Community includes developers from member organizations and the general +community all joining in the development of the project. Members contribute and +discuss ideas, submit bugs and bug fixes, and improve documentation. They also +help those in need through the community's forums and mailing lists. Anyone can +join the developer community and the community is always willing to help its +members and the User Community to get the most out of OPEA. + +Resources +********* + +Here's a quick summary of resources to find your way around the OPEA Project +support systems: + +* **OPEA Project Website**: The https://opea.dev website is the + central source of information about what's going on with OPEA. + On this site, you'll + find background and current information about the project as well as + relevant links to project material. + +* **Source Code in GitHub**: OPEA Project source code is maintained on a + public GitHub repository at https://github.com/opea-project. + You'll find information about getting access to the repository and how to + contribute to the project in this `Contribution Guide`_ document. + +* **Documentation**: Project technical documentation is developed + along with the project's code, and can be found at + https://opea-project.github.io. + +* **Issue Reporting and Tracking**: Requirements and Issue tracking is done in + the Github issues system within each of the major repositories such as: https://github.com/opea-project/GenAIComps/issues. + You can browse through the reported issues and submit issues of your own. + +* **Mailing List**: TBD + + +.. _Contribution Guide: https://opea-project.github.io/latest/community/CONTRIBUTING.html + + +Contributing Guides +******************* .. toctree:: :maxdepth: 1 - CODE_OF_CONDUCT CONTRIBUTING SECURITY + ../developer-guides/doc_guidelines + ../developer-guides/graphviz ../developer-guides/docbuild + +Project Governance +****************** + +.. toctree:: + :maxdepth: 1 + + CODE_OF_CONDUCT + SECURITY + +RFC Proposals +************* + +.. toctree:: + :maxdepth: 1 + rfcs diff --git a/conf.py b/conf.py index 2a519188..0938d516 100644 --- a/conf.py +++ b/conf.py @@ -38,6 +38,7 @@ # 'last_updated', 'myst_parser', 'sphinxcontrib.mermaid', + 'link_roles', #'sphinx_md', ] @@ -196,7 +197,7 @@ def setup(app): html_show_sphinx = False # If true, links to the reST sources are added to the pages. -html_show_sourcelink = False +html_show_sourcelink = True # If not '', a 'Last updated on:' timestamp is inserted at every page # bottom, @@ -208,12 +209,10 @@ def setup(app): # html_search_scorer = 'scorer.js' -# -- Options for Texinfo output ------------------------------------------- - -# rst_epilog = """ -# .. include:: /substitutions.txt -# """ +rst_epilog = """ +.. include:: /sphinx/substitutions.txt +""" # Custom last_updated extension for updating last updated date based on git information # needs to know the folders where the cloned files can be found, relative to diff --git a/deploy.rst b/deploy.rst deleted file mode 100644 index a85529d6..00000000 --- a/deploy.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. _GenAIInfra: - -Deploying GenAI -############### - -GenAIInfra is the containerization and cloud native suite for OPEA, including -artifacts to deploy `GenAIExamples`_ in a cloud native way so enterprise users -can deploy to their own cloud. - -As we're building this documentation site, for now, read more in the -`GenAIInfra GitHub repository`_. - -.. _GenAIExamples: https://github.com/opea-project/GenAIExamples/blob/main/README.md -.. _GenAIInfra Github repository: https://github.com/opea-project/GenAIInfra/blob/main/README.md diff --git a/deploy/index.rst b/deploy/index.rst new file mode 100644 index 00000000..1d5cdcb5 --- /dev/null +++ b/deploy/index.rst @@ -0,0 +1,74 @@ +.. _GenAIInfra: + +Deploying GenAI +############### + +GenAIInfra is the containerization and cloud native suite for OPEA, including +artifacts to deploy `GenAIExamples`_ in a cloud native way so enterprise users +can deploy to their own cloud. + +As we're building this documentation site, for now, read more about what's +in the `GenAIInfra GitHub repository`_. + +.. _GenAIExamples: https://github.com/opea-project/GenAIExamples/blob/main/README.md +.. _GenAIInfra Github repository: https://github.com/opea-project/GenAIInfra/blob/main/README.md + + +.. toctree:: + :maxdepth: 1 + :glob: + + /GenAIInfra/README + /GenAIInfra/* + +Helm Charts +*********** + +.. toctree:: + :maxdepth: 1 + :glob: + + /GenAIInfra/helm-charts/README + /GenAIInfra/helm-charts/* + /GenAIInfra/helm-charts/*/* + /GenAIInfra/helm-charts/*/*/* + /GenAIInfra/helm-charts/*/*/*/* + +Kubernetes Addons +***************** + +.. toctree:: + :maxdepth: 1 + :glob: + + /GenAIInfra/kubernetes-addons/README + /GenAIInfra/kubernetes-addons/* + /GenAIInfra/kubernetes-addons/*/* + /GenAIInfra/kubernetes-addons/*/*/* + /GenAIInfra/kubernetes-addons/*/*/*/* + +Microservices Connector +*********************** + +.. toctree:: + :maxdepth: 1 + :glob: + + /GenAIInfra/microservices-connector/README + /GenAIInfra/microservices-connector/* + /GenAIInfra/microservices-connector/*/* + /GenAIInfra/microservices-connector/*/*/* + /GenAIInfra/microservices-connector/*/*/*/* + +Scripts +******* + +.. toctree:: + :maxdepth: 1 + :glob: + + /GenAIInfra/scripts/README + /GenAIInfra/scripts/* + /GenAIInfra/scripts/*/* + /GenAIInfra/scripts/*/*/* + /GenAIInfra/scripts/*/*/*/* diff --git a/developer-guides/doc_guidelines.rst b/developer-guides/doc_guidelines.rst new file mode 100644 index 00000000..ef938734 --- /dev/null +++ b/developer-guides/doc_guidelines.rst @@ -0,0 +1,820 @@ +.. _doc_guidelines: + +Documentation Guidelines +######################## + +OPEA Project content is written using the `markdown`_ (``.md``) and `reStructuredText`_ markup +language (``.rst``) with Sphinx extensions, and processed +using Sphinx to create a formatted stand-alone website. Developers can +view this content either in its raw form as ``.md`` and ``.rst`` markup files, or (with +Sphinx installed) they can build the documentation using the Makefile +(on Linux systems) to generate the HTML content. The HTML content can then be +viewed using a web browser. This same ``.md`` and ``.rst`` content is fed into the +`OPEA Project documentation`_ website. + +You can read details about `reStructuredText`_ and about `Sphinx extensions`_ +from their respective websites. + +.. _Sphinx extensions: https://www.sphinx-doc.org/en/stable/contents.html +.. _reStructuredText: http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html +.. _Sphinx Inline Markup: https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html +.. _OPEA Project documentation: https://opea-project.github.io +.. _markdown: https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax + +This document provides a quick reference for commonly used markdown and reST +with Sphinx-defined directives and roles used to create the documentation +you're reading. + +Markdown vs. RestructuredText +***************************** + +Both markdown and ReStructureText (reST) let you create individual documentation files that +GitHub can render when viewing them in your browser on github.com. Markdown is +popular because of it's familarity with developers and is the default markup +language for StackOverflow, Reddit, GitHub, and others. ReStructuredText came +from the Python community for quite a while and became noticed outside that +community with the release of Sphinx. These days, reST is supported by GitHub +and major projects use it for their documentation, including the Linux kernel, +OpenCV and LLVM/Clang. + +ReStructuredText is more fully-featured, much more standardized and uniform, and +has built-in support for extensions. The markdown language has no standard way +to implement complete documentation systems and doesnt have a standard extension +mechanism, which leads to many different "flavors" of markdown. If you stick to +the core and common markdown syntax (headings, paragraphs, lists, and such), +using markdown is just fine. However, slipping in raw HTML to do formatting +(such as centering) or using HTML for tables creates problems when publishing to the +https://opea-project.github.io site. + + +Within the OPEA documentation, we use both markdown and reST files for the +documentation "leaves". We rely on reST for the documentation organization trunk and +branches, through the use of the reST toctree directives. + +Documentation Organization +************************** + +Documentation is maintained and updated the same as the project's code within +the opea-project GitHub repos. There are many ``README.md`` files within the various +repos along with the other files for those components. This is good because it +keeps the relevent documentation and code for that component together. + +We use the ``docs`` repo to organize the presentation of all these ``README.md`` +files, along with other project related documents that are maintained in the +``docs`` repo. The root of the generated documentation starts with the +``docs/index.rst`` file that starts off the organizational structure that's +shown as the left navigation in the generated HTML site at +https://opea-project.github.io. That ``index.rst`` file uses a toctree +directive to point to other documents that may include additional toctree +directives of their own, ultimately collecting all the content into an +organizational structure you can navigate. + + +Headings +******** + +.. tabs:: + + .. group-tab:: reST + + In reST, document sections are identified through their heading titles, indicated with + an underline below the title text. (While reST allows use of both and + overline and matching underline to indicate a heading, we use only an + underline indicator for headings.) For consistency in our documentation, we + define the order of characters used to indicate the nested levels in the + table of contents: + + * Use ``#`` for the Document title underline character (H1) + * Use ``*`` for the First sub-section heading level (H2) + * Use ``=`` for the Second sub-section heading level (H3) + * Use ``-`` for the Third sub-section heading level (H4) + + Additional heading-level depth is discouraged, but if needed, use ``%`` + (H5), ``+`` (H6), and ``@`` (H7). + + The heading underline must be at least as long as the title it's under. + + Here's an example of nested heading levels and the appropriate + underlines to use: + + .. code-block:: rest + + Document Title heading + ###################### + + Section 1 heading + ***************** + + Section 2 heading + ***************** + + Section 2.1 heading + =================== + + Section 2.1.1 heading + --------------------- + + Section 2.2 heading + =================== + + Section 3 heading + ***************** + + + .. group-tab:: markdown + + In markdown, headings are indicated as a line beginning with a ``#`` + character, with additional ``#`` characters indicating a deeper heading + level, e.g., ``#`` for H1 (title), ``##`` for H2 headings, ``###`` for H3 + headdings, and so on.) + + * The ``#`` character for a heading must be the first character on the + line, then a space, followed by the heading. For example:: + + # My Document's Title + + Some content goes here. + + ## First H2 heading + + Some more content + + * There must be only one ``#`` H1 heading at the beginning of the document + indicating the document's title. + * You must not skip heading levels on the way down in the document hierarchy, e.g., do not go from a H1 ``#`` to an + H3 ``###`` without an intervening H2 ``##``. You may skip heading levels + on the way back up, for example, from an H4 ``####`` back up to an H2 ``##`` + as appropriate. + + + + +Content Highlighting +******************** + +Some common reST and markdown inline markup samples: + +* one asterisk: ``*text*`` for emphasis (*italics*), +* two asterisks: ``**text**`` for strong emphasis (**boldface**), and +* two back quotes: ````text```` for ``inline code`` samples. + +ReST rules for inline markup try to be forgiving to account for common +cases of using these marks. For example, using an asterisk to indicate +multiplication, such as ``2 * (x + y)`` will not be interpreted as an +unterminated italics section. + +For inline markup, the characters between +the beginning and ending characters must not start or end with a space, +so ``*this is italics*``, (*this is italics*) while ``* this isn't*`` +(* this isn't*). + +If an asterisk or back quote appears in running text and could be confused +with inline markup delimiters, you can eliminate the confusion by adding a +backslash (``\``) before it. + + +Lists +***** + +For bullet lists, place an asterisk (``*``) or hyphen (``-``) at the start of +a paragraph and indent continuation lines with two spaces. + +The first item in a list (or sublist) must have a blank line before it and +should be indented at the same level as the preceding paragraph (and not +indented itself). + +For numbered lists +start with a ``1.`` or ``a)`` for example, and continue with autonumbering by +using a ``#`` sign and a ``.`` or ``)`` as used in the first list item. +Indent continuation lines with spaces to align with the text of first +list item: + +.. code-block:: rest + + * This is a bulleted list. + * It has two items, the second + item and has more than one line of reST text. Additional lines + are indented to the first character of the + text of the bullet list. + + 1. This is a new numbered list. If there wasn't a blank line before it, + it would be a continuation of the previous list (or paragraph). + #. It has two items too. + + a) This is a numbered list using alphabetic list headings + #) It has three items (and uses autonumbering for the rest of the list) + #) Here's the third item. Use consistent punctuation on the list + number. + + #. This is an autonumbered list (default is to use numbers starting + with 1). + + #. This is a second-level list under the first item (also + autonumbered). Notice the indenting. + #. And a second item in the nested list. + #. And a second item back in the containing list. No blank line + needed, but it wouldn't hurt for readability. + +Definition lists (with one or more terms and their definition) are a +convenient way to document a word or phrase with an explanation. For example, +this reST content: + +.. code-block:: rest + + The Makefile has targets that include: + + ``html`` + Build the HTML output for the project + + ``clean`` + Remove all generated output, restoring the folders to a + clean state. + +Would be rendered as: + + The Makefile has targets that include: + + html + Build the HTML output for the project + + clean + Remove all generated output, restoring the folders to a + clean state. + +Multi-Column Lists +****************** + +In reST, if you have a long bullet list of items, where each item is short, you can +indicate that the list items should be rendered in multiple columns with a +special ``.. rst-class:: rst-columns`` directive. The directive will apply to +the next non-comment element (for example, paragraph) or to content indented under +the directive. For example, this unordered list:: + + .. rst-class:: rst-columns + + * A list of + * short items + * that should be + * displayed + * horizontally + * so it doesn't + * use up so much + * space on + * the page + +would be rendered as: + +.. rst-class:: rst-columns + + * A list of + * short items + * that should be + * displayed + * horizontally + * so it doesn't + * use up so much + * space on + * the page + +A maximum of three columns will be displayed if you use ``rst-columns`` +(or ``rst-columns3``), and two columns for ``rst-columns2``. The number +of columns displayed can be reduced based on the available width of the +display window, reducing to one column on narrow (phone) screens if necessary. + +.. note:: We've deprecated use of the ``hlist`` directive because it + misbehaves on smaller screens. + +Tables +****** + +There are a few ways to create tables, each with their limitations or quirks. +`Grid tables +`_ +offer the most capability for defining merged rows and columns, but are +hard to maintain:: + + +------------------------+------------+----------+----------+ + | Header row, column 1 | Header 2 | Header 3 | Header 4 | + | (header rows optional) | | | | + +========================+============+==========+==========+ + | body row 1, column 1 | column 2 | column 3 | column 4 | + +------------------------+------------+----------+----------+ + | body row 2 | ... | ... | you can | + +------------------------+------------+----------+ easily + + | body row 3 with a two column span | ... | span | + +------------------------+------------+----------+ rows + + | body row 4 | ... | ... | too | + +------------------------+------------+----------+----------+ + +This example would render as: + ++------------------------+------------+----------+----------+ +| Header row, column 1 | Header 2 | Header 3 | Header 4 | +| (header rows optional) | | | | ++========================+============+==========+==========+ +| body row 1, column 1 | column 2 | column 3 | column 4 | ++------------------------+------------+----------+----------+ +| body row 2 | ... | ... | you can | ++------------------------+------------+----------+ easily + +| body row 3 with a two column span | ... | span | ++------------------------+------------+----------+ rows + +| body row 4 | ... | ... | too | ++------------------------+------------+----------+----------+ + +For reST, `List tables +`_ +are much easier to maintain, but don't support row or column spans:: + + .. list-table:: Table title + :widths: 15 20 40 + :header-rows: 1 + + * - Heading 1 + - Heading 2 + - Heading 3 + * - body row 1, column 1 + - body row 1, column 2 + - body row 1, column 3 + * - body row 2, column 1 + - body row 2, column 2 + - body row 2, column 3 + +This example would render as: + +.. list-table:: Table title + :widths: 15 20 40 + :header-rows: 1 + + * - Heading 1 + - Heading 2 + - Heading 3 + * - body row 1, column 1 + - body row 1, column 2 + - body row 1, column 3 + * - body row 2, column 1 + - body row 2, column 2 + - body row 2, column 3 + +The ``:widths:`` parameter lets you define relative column widths. The +default is equal column widths. If you have a three-column table and you +want the first column to be half as wide as the other two equal-width +columns, you can specify ``:widths: 1 2 2``. If you'd like the browser +to set the column widths automatically based on the column contents, you +can use ``:widths: auto``. + +File Names and Commands +*********************** + +Sphinx extends reST by supporting additional inline markup elements (called +"roles") used to tag text with special meanings and enable output formatting. +(You can refer to the `Sphinx Inline Markup`_ documentation for the full +list). + +For example, there are roles for marking :file:`filenames` +(``:file:`name```) and command names such as :command:`make` +(``:command:`make```). You can also use the \`\`inline code\`\` +markup (double backticks) to indicate a ``filename``. + +Don't use items within a single backtick, for example ```word```. Instead +use double backticks: ````word````. + +Branch-Specific File Links +************************** + +You can add a link in the documentation to a specific file in the GitHub tree. +Be sure the link points to the branch for that version of the documentation. For +example, links in the v0.8 release of the documentation should be to files in +the v0.8 branch. Do not link to files in the main branch because files in that +branch could change or even be deleted after the release is made. + +In reST, to make this kind of file linking possible, use a special role that +creates a hyperlink to that file in the branch currently checked out. + +.. note:: It's assumed that the checked out version of the **docs** repo when we + generate the HTML documentation is the same tagged version for all the repos + we want to reference. + +For example, a GitHub +link to the reST file used to create this document can be generated +using ``:docs_file:`developer-guides/doc_guidelines```, which will +appear as :docs_file:`developer-guides/doc_guidelines.rst`, a link to +the "blob" file in the GitHub repo as displayed by GitHub. There's also an +``:docs_raw:`developer-guides/doc_guidelines.rst``` role that will link +to the "raw" uninterpreted file, +:docs_raw:`developer-guides/doc_guidelines.rst`. Click these links +to see the difference. + +If you don't want the whole path to the file name to +appear in the text, you use the usual linking notation to define what link text +is shown, for example, ``:docs_file:`Guidelines ``` +would show up as simply :docs_file:`Guidelines `. + +.. _internal-linking: + +Internal Cross-Reference Linking +******************************** + +Traditional ReST links are supported only within the current file using the +notation: + +.. code-block:: rest + + refer to the `internal-linking`_ page + +which renders as, + + refer to the `internal-linking`_ page + +Note the use of a trailing underscore to indicate an outbound link. In this +example, the label was added immediately before a heading, so the text that's +displayed is the heading text itself. + +With Sphinx, however, we can create link-references to any tagged text within +the project documentation. + +Target locations within documents are defined with a label directive: + + .. code-block:: rst + + .. _my label name: + +Note the leading underscore indicating an inbound link. The content +immediately following this label is the target for a ``:ref:`my label name``` +reference from anywhere within the documentation set. The label **must** be +added immediately before a heading so that there's a natural phrase to show +when referencing this label (for example, the heading text). + +This directive is also used to define a label that's a reference to a URL: + +.. code-block:: rest + + .. _Hypervisor Wikipedia Page: + https://en.wikipedia.org/wiki/Hypervisor + +To enable easy cross-page linking within the site, each file should have a +reference label before its title so that it can be referenced from another +file. + +.. note:: These reference labels must be unique across the whole site, so generic + names such as "samples" should be avoided. + +For example, the top of this +document's ``.rst`` file is: + +.. code-block:: rst + + .. _doc_guidelines: + + Documentation Guidelines + ######################## + +Other ``.rst`` documents can link to this document using the +``:ref:`doc_guidelines``` tag, and it will appear as :ref:`doc_guidelines`. +This type of internal cross-reference works across multiple files. The link +text is obtained from the document source, so if the title changes, the link +text will automatically update as well. + +There may be times when you'd like to change the link text that's shown in the +generated document. In this case, you can specify alternate text using +``:ref:`alternate text ``` (renders as +:ref:`alternate text `). + + +Non-ASCII Characters +******************** + +You can insert non-ASCII characters such as a Trademark symbol (|trade|) by +using the notation ``|trade|``. (It's also allowed to use the UTF-8 +characters directly.) Available replacement names are defined in an include +file used during the Sphinx processing of the reST files. The names of these +replacement characters are the same as those used in HTML entities to insert +special characters such as \™ and are defined in the file +``sphinx_build/substitutions.txt`` as listed here: + +.. literalinclude:: ../sphinx/substitutions.txt + :language: rst + +We've kept the substitutions list small but you can add others as needed by +submitting a change to the ``substitutions.txt`` file. + +Code and Command Examples +************************* + +.. tabs:: + + .. group-tab:: reST + + Use the reST ``code-block`` directive to create a highlighted block of + fixed-width text, typically used for showing formatted code or console + commands and output. Smart syntax highlighting is also supported (using the + Pygments package). You can also directly specify the highlighting language. + For example: + + .. code-block:: rest + + .. code-block:: c + + struct _k_object { + char *name; + u8_t perms[CONFIG_MAX_THREAD_BYTES]; + u8_t type; + u8_t flags; + u32_t data; + } __packed; + + Note that there is a blank line between the ``code-block`` directive and the + first line of the code-block body, and the body content is indented three + spaces (to the first non-blank space of the directive name). + + This example would render as: + + .. code-block:: c + + struct _k_object { + char *name; + u8_t perms[CONFIG_MAX_THREAD_BYTES]; + u8_t type; + u8_t flags; + u32_t data; + } __packed; + + + You can specify other languages for the ``code-block`` directive, including + ``c``, ``python``, and ``rst``, and also ``console``, ``bash``, or ``shell``. + If you want no syntax highlighting, specify ``none``. For example: + + .. code-block:: rest + + .. code-block:: none + + This block of text would be styled with a background + and box, but with no syntax highlighting. + + Would display as: + + .. code-block:: none + + This block of text would be styled with a background + and box, but with no syntax highlighting. + + There's a shorthand for writing code blocks, too: end the introductory + paragraph with a double colon (``::``) and indent the code block content + by three spaces. On output, only one colon will appear. + + .. note:: The highlighting package makes a best guess at the type of content + in the block, which can lead to odd + highlighting in the generated output. + + .. group-tab:: markdown + + In markdown, fenced code blocks are used to define code blocks. Use three + backticks ``````` on the lines before and after the code block, for + example: + + .. code-block:: none + + ``` + { + "firstName": "John", + "lastName": "Smith", + "age": 25 + } + ``` + + The rendered output would look like this: + + .. code-block:: none + + { + "firstName": "John", + "lastName": "Smith", + "age": 25 + } + + Syntax highlighting is also supported for fenced code blocks by specifying + a language next to the backticks before the fenced code block: + + .. code-block:: none + + ```json + { + "firstName": "John", + "lastName": "Smith", + "age": 25 + } + ``` + + The rendered output would look like this: + + .. code-block:: json + + { + "firstName": "John", + "lastName": "Smith", + "age": 25 + } + + TODO: add the list of supported languages. + +Images +****** + +.. tabs:: + + .. group-tab:: reST + + In reST, images are included in documentation by using an image directive:: + + .. image:: ../images/opea-horizontal-color-w200.png + :align: center + :alt: alt text for the image + + or if you'd like to add an image caption, use the figure directive:: + + .. figure:: ../images/opea-horizontal-color-w200.png + :alt: image description + + Caption for the figure + + .. group-tab:: markdown + + In markdown, images are included in documentation using this syntax:: + + ![OPEA Logo](../images/opea-horizontal-color-w200.png) + +The file name specified is relative to the document source file. We +recommend putting images into an ``images`` folder where the document source +is found. The usual image formats handled by a web browser are supported: +JPEG, PNG, GIF, and SVG. Keep the image size only as large as needed, +generally at least 500 px wide but no more than 1000 px, and no more than +250 KB unless a particularly large image is needed for clarity. + + + +Tabs, Spaces, and Indenting +*************************** + +Indenting is significant in reST file content, and using spaces is preferred. +Extra indenting can (unintentionally) change the way content is rendered, too. +For lists and directives, indent the content text to the first non-blank space +in the preceding line. For example: + +.. code-block:: rest + + * List item that spans multiple lines of text + showing where to indent the continuation line. + + 1. And for numbered list items, the continuation + line should align with the text of the line above. + + .. code-block:: + + The text within a directive block should align with the + first character of the directive name. + +Keep the line length for documentation fewer than 80 characters to make it +easier for reviewing in GitHub. Long lines due to URL references are an +allowed exception. + +Background Colors +***************** + +We've defined some CSS styles for use as background colors for paragraphs. +These styles can be applied using the ``.. rst-class`` directive using one of +these style names. You can also use the defined ``centered`` style to place the +text centered within the element, useful for centering text within a table cell +or column span: + +.. rst-class:: bg-opea-lightorange centered + + \.\. rst-class:: bg-opea-lightorange centered + +.. rst-class:: bg-opea-darkorange centered + + \.\. rst-class:: bg-opea-darkorange centered + +Drawings +******** + +In reST, we've included the ``graphviz`` Sphinx extension to enable you to use a +text description language to render drawings. For more information, see +:ref:`graphviz-examples`. + +Alternative Tabbed Content +************************** + +In ResST, instead of creating multiple documents with common material except for some +specific sections, you can write one document and provide alternative content +to the reader via a tabbed interface. When the reader clicks a tab, the +content for that tab is displayed. For example:: + + .. tabs:: + + .. tab:: Apples + + Apples are green, or sometimes red. + + .. tab:: Pears + + Pears are green. + + .. tab:: Oranges + + Oranges are orange. + +will display as: + +.. tabs:: + + .. tab:: Apples + + Apples are green, or sometimes red. + + .. tab:: Pears + + Pears are green. + + .. tab:: Oranges + + Oranges are orange. + +Tabs can also be grouped so that changing the current tab in one area +changes all tabs with the same name throughout the page. For example: + +.. tabs:: + + .. group-tab:: Linux + + Linux Line 1 + + .. group-tab:: macOS + + macOS Line 1 + + .. group-tab:: Windows + + Windows Line 1 + +.. tabs:: + + .. group-tab:: Linux + + Linux Line 2 + + .. group-tab:: macOS + + macOS Line 2 + + .. group-tab:: Windows + + Windows Line 2 + +In this latter case, we're using a ``.. group-tab::`` directive instead of +a ``.. tab::`` directive. Under the hood, we're using the `sphinx-tabs +`_ extension that's included +in the ACRN (requirements.txt) setup. Within a tab, you can have most +any content *other than a heading* (code-blocks, ordered and unordered +lists, pictures, paragraphs, and such). + +Instruction Steps +***************** + +In reST, a numbered instruction steps style makes it easy to create tutorial guides +with clearly identified steps. Add the ``.. rst-class:: numbered-step`` +directive immediately before a second-level heading (by project convention, a +heading underlined with asterisks ``******``, and it will be displayed as a +numbered step, sequentially numbered within the document. (Second-level +headings without this ``rst-class`` directive will not be numbered.) +For example:: + + .. rst-class:: numbered-step + + Put your right hand in + ********************** + +.. rst-class:: numbered-step + +First Instruction Step +********************** + +This is the first instruction step material. You can do the usual paragraph +and pictures as you'd use in normal document writing. Write the heading to be +a summary of what the step is (the step numbering is automated so you can move +steps around easily if needed). + +.. rst-class:: numbered-step + +Second Instruction Step +*********************** + +This is the second instruction step. + +.. note:: As implemented, + only one set of numbered steps is intended per document and the steps + must be level 2 headings. + + +Documentation Generation +************************ + +For instructions on building the documentation, see :ref:`opea_doc_generation`. diff --git a/developer-guides/docbuild.rst b/developer-guides/docbuild.rst index 3d574c3e..e87cd276 100644 --- a/developer-guides/docbuild.rst +++ b/developer-guides/docbuild.rst @@ -3,10 +3,9 @@ OPEA Documentation Generation ############################# -These instructions walk you through generating the OPEA project -documentation and publishing it to https://opea-project.github.io. -You can also use these instructions to generate the OPEA documentation -on your local system. +These instructions walk you through generating the OPEA project documentation +and publishing it to https://opea-project.github.io. You can also use these +instructions to generate the OPEA documentation on your local system. .. contents:: :local: @@ -15,12 +14,12 @@ on your local system. Documentation Overview ********************** -OPEA project content is written using combination of markdown (``.md``) and reStructuredText (``.rst``) markup -languages (with Sphinx extensions), and processed -using Sphinx to create a formatted stand-alone website. Developers can -view this content either in its raw form as .rst markup files, or you -can generate the HTML content and view it with a web browser directly on -your workstation. +OPEA project content is written using combination of markdown (``.md``) and +reStructuredText (``.rst``) markup languages (with Sphinx extensions), and +processed using Sphinx to create a formatted stand-alone website. Developers can +view this content either in its raw form as .rst markup files, or you can +generate the HTML content and view it with a web browser directly on your +workstation. You can read details about `markdown`_, `reStructuredText`_, and `Sphinx`_ from their respective websites. @@ -31,7 +30,8 @@ The project's documentation contains the following items: https://opea-project.github.io website. All of the documentation sources are found in the ``github.com/opea-project`` repos, rooted in the ``docs`` repo. There's also documentation in the repos where the project's code is - maintained, such as ``GenAIComps``, ``GenAIExamples``, and others. + maintained: ``GenAIComps``, ``GenAIEval``, ``GenAIExamples``, ``GenAIInfra`` + and ``Governance``. .. graphviz:: images/doc-gen-flow.dot :align: center @@ -50,64 +50,40 @@ You'll need ``git`` installed to get the working folders set up: sudo apt install git Here's the recommended folder setup for documentation contributions and -generation, a parent folder called ``opea-project`` holds six locally cloned -repos from the opea-project: +generation, a parent folder called ``opea-project-docsgen`` holds six locally +cloned repos from the opea-project: .. code-block:: none - opea-project + opea-project-docsgen ├── docs ├── GenAIComps ├── GenAIEval ├── GenAIExamples ├── GenAIInfra ├── Governance + ├── opea-project.github.io -The parent ``opea-project`` folder is there to organize the cloned repos from -the project. If you have repo publishing -rights, we'll also be creating a publishing area later in these steps. +The parent ``opea-project-docsgen`` folder is there to organize the cloned repos +from the project. If you have repo publishing rights, we'll also be cloning the +publishing repo opea-project.github.io later in these steps. -In the following steps, you'll create a fork of all the upstream OPEA project -repos needed to build the documentation to your personal GitHub account, clone -your personal fork to your local development computer, and then link that to the -upstream repo as well. You'll only need to do this once to set up the folder -structure: +In the following steps, you'll clone the upstream repos You'll only need to do +this once to set up the folder structure: -#. Use your browser to visit https://github.com/opea-project and do a - fork of the **docs** repo to your personal GitHub account.) - - .. image:: images/opea-docs-fork.png - :align: center - :class: drop-shadow - -#. At a command prompt, create a working folder on your development computer and - clone your personal ``docs`` repository: +#. At a command prompt, create the working folder on your development computer and + clone all the opea-project repos containing documentation: .. code-block:: bash cd ~ - mkdir opea-project && cd opea-project - git clone https://github.com//docs.git - -#. For the cloned local repo, tell git about the upstream repo: - - .. code-block:: bash + mkdir opea-project-docsgen && cd opea-project-docsgen + for d in docs GenAIComps GenAIExamples GenAIEval GenAIInfra Governance ; do + git clone https://github.com/opea-project/$d.git + done - cd docs - git remote add upstream https://github.com/opea-project/docs.git - - After that, you'll have ``origin`` pointing to your cloned personal repo and - ``upstream`` pointing to the project repo. - -#. Do the same steps (fork to your personal account, clone to your local - computer, and setup the git upstream remote) for the other repos containing - project documentation: - - * GenAIComps - * GenAIEval - * GenAIExamples - * GenAIInfra - * Governance + After this, you'll have ``origin`` for each cloned repo pointing to the + upstream project repos. #. If you haven't done so already, be sure to configure git with your name and email address for the ``signed-off-by`` line in your commit messages: @@ -130,8 +106,12 @@ later, and these other tools: * myst-parser version: 3.0.1 * sphinxcontrib-mermaid version: 0.9.2 -Depending on your Linux version, install the needed tools. +Depending on your Linux version, install the needed tools. You should consider +using the `Python virtual environment`_ +tools to maintain your Python environment from being changed by other work on +your computer. +.. _Python virtual environment: https://https://docs.python.org/3/library/venv.html For Ubuntu use: @@ -144,7 +124,7 @@ Then use ``pip3`` to install the remaining Python-based tools specified in the .. code-block:: bash - cd ~/opea-project/docs + cd ~/opea-project-docsgen/docs pip3 install --user -r scripts/requirements.txt Use this command to add ``$HOME/.local/bin`` to the front of your ``PATH`` so @@ -165,20 +145,20 @@ And with that you're ready to generate the documentation. .. note:: - We've provided a script you can run to show what versions of the - documentation building tools are installed and compare with the - tool versions shown above. This tool will also verify you're using tool - versions known to work together:: + We've provided a script in the docs repo you can run to show what versions of + the documentation building tools are installed and compare with the tool + versions shown above. This tool will also verify you're using tool versions + known to work together:: - doc/scripts/show-versions.py + docs/scripts/show-versions.py for example: .. code-block:: console - ~/opea-project/docs$ scripts/show-versions.py + ~/opea-project-docsgen/docs$ scripts/show-versions.py - doc build tool versions found on your system per /home/david/opea-project/docs/scripts/requirements.txt... + doc build tool versions found on your system per /home/david/opea-project-docsgen/docs/scripts/requirements.txt... sphinx version: 7.3.0 docutils version: 0.20 @@ -209,19 +189,19 @@ environment and a ``make html`` again generally fixes these issues. Run the Documentation Processors ******************************** -The ``docs`` folder (and cloned sibling repos) have all the doc source files, +The ``docs`` folder (with all cloned sibling repos) have all the doc source files, images, extra tools, and ``Makefile`` for generating a local copy of the OPEA technical documentation. (The ``Makefile`` copies all needed files from these -cloned repos into a temporary ``_build`` working folder.) +cloned repos into a temporary folder in a ``_build`` working folder.) .. code-block:: bash - cd ~/opea-project/docs + cd ~/opea-project-docsgen/docs make html Depending on your development system, it will take less a minute to collect and generate the HTML content. When done, you can view the HTML output in -``~/opea-project/docs/_build/html/index.html``. You can also ``cd`` to the +``~/opea-project-docsgen/docs/_build/html/index.html``. You can also ``cd`` to the ``_build/html`` folder and run a local web server with the command: .. code-block:: bash @@ -243,7 +223,7 @@ directly to the upstream repo rather than to a personal forked copy): .. code-block:: bash - cd ~/opea-project + cd ~/opea-project-docsgen git clone https://github.com/opea-project/opea-project.github.io.git Then, after you've verified the generated HTML from ``make html`` looks @@ -256,9 +236,9 @@ good, you can push directly to the publishing site with: This uses git commands to synchronize the new content with what's already published and will delete files in the publishing repo's **latest** folder that are no longer needed. New or changed files from -the newly-generated HTML content are added to the GitHub pages +the newly-generated HTML content are pushed to the GitHub pages publishing repo. The public site at https://opea-project.github.io will -be updated by the `GitHub pages system +be automatically updated by the `GitHub pages system `_, typically within a few minutes. @@ -268,7 +248,7 @@ Document Versioning The https://opea-project.github.io site has a document version selector at the top of the left nav panel. The contents of this version selector are defined in the ``conf.py`` sphinx configuration file, -specifically: +specifically something like this: .. code-block:: python :emphasize-lines: 5-6 @@ -284,24 +264,29 @@ specifically: } -As new versions of OPEA documentation are added, update this -``versions`` selection list to include the version number and publishing -folder. Note that there's no direct selection to go to a newer version -from an older one, without going to ``latest`` first. +As new versions of OPEA documentation are added, typically when a new release is +made, update this ``versions`` selection list to include the version number and +publishing folder. Note that there's no direct selection to go to a newer +version from an older one, without going to ``latest`` first. By default, documentation build and publishing both assume we're generating -documentation for the main branch and publishing to the ``/latest/`` -area on https://opea-project.github.io. When we're generating the -documentation for a tagged version (e.g., 0.8), check out that version -of all the component repos, and add some extra flags to the ``make`` commands: +documentation for the main branch and publishing to the ``/latest/`` area on +https://opea-project.github.io. When we're generating the documentation for a +tagged version (e.g., 0.8), check out that version of **all** the component +repos, and add some extra flags to the ``make`` commands: .. code-block:: bash - cd ~/opan-project/docs - git checkout v0.8 + version=0.8 + for d in docs GenAIComps GenAIExamples GenAIEval GenAIInfra Governance ; do + cd ~/opea-project-docsgen/$d + git checkout $version + done + + cd ~/opea-project-docsgen/docs make clean - make DOC_TAG=release RELEASE=0.8 html - make DOC_TAG=release RELEASE=0.8 publish + make DOC_TAG=release RELEASE=$version html + make DOC_TAG=release RELEASE=$version publish .. _filter_expected: diff --git a/developer-guides/graphviz.rst b/developer-guides/graphviz.rst new file mode 100644 index 00000000..41f9bdf6 --- /dev/null +++ b/developer-guides/graphviz.rst @@ -0,0 +1,123 @@ +.. _graphviz-examples: + +Drawings Using Graphviz +####################### + +We support using the Sphinx `Graphviz extension`_ for creating simple +graphs and line drawings using the dot language. The advantage of using +Graphviz for drawings is that the source for a drawing is a text file that +can be edited and maintained in the repo along with the documentation. + +.. _graphviz extension: http://graphviz.gitlab.io + +These source ``.dot`` files are generally kept separate from the document +itself, and included by using a Graphviz directive: + +.. code-block:: none + + .. graphviz:: images/boot-flow.dot + :name: boot-flow-example + :align: center + :caption: ACRN Hypervisor Boot Flow + +where the boot-flow.dot file contains the drawing commands: + +.. literalinclude:: images/boot-flow.dot + +and the generated output would appear as: + +.. graphviz:: images/boot-flow.dot + :name: boot-flow-example + :align: center + :caption: ACRN Hypervisor Boot Flow + + +Let's look at some more examples and then we'll get into more details about +the dot language and drawing options. + +Simple Directed Graph +********************* + +For simple drawings with shapes and lines, you can put the Graphviz commands +in the content block for the directive. For example, for a simple directed +graph (digraph) with two nodes connected by an arrow, you can write: + + +.. code-block:: none + + .. graphviz:: + + digraph { + "a" -> "b" + } + +and get this drawing: + +.. graphviz:: + + digraph { + "a" -> "b" + } + + +You can change the following attributes: + +* Graph layout (from top-to-bottom to left-to-right) +* Node shapes (rectangles, circles, houses, stars, etc.) +* Style (filled, rounded) +* Colors +* Text displayed in the node +* Placement of the resulting image on the page (centered) + +Example: + +.. literalinclude:: images/circle-square.dot + +.. graphviz:: images/circle-square.dot + :align: center + +You can use the `standard HTML color names`_ or use RGB values for colors, +as shown. + +.. _standard HTML color names: + https://www.w3schools.com/colors/colors_hex.asp + +Adding Edge Labels +****************** + +Here's an example of a drawing with labels on the edges (arrows) between +nodes. We also show how to change the default attributes for all nodes and +edges within this graph: + +.. literalinclude:: images/node-shape-edges.dot + +.. graphviz:: images/node-shape-edges.dot + :align: center + +Tables +****** + +For nodes with a ``record`` shape attribute, the text of the label is +presented in a table format: a vertical bar ``|`` starts a new row or +column and curly braces ``{ ... }`` specify a new row (if you're in a +column) or a new column (if you're in a row). For example: + +.. literalinclude:: images/record.dot + +.. graphviz:: images/record.dot + :align: center + +Note that you can also specify the horizontal alignment of text using escape +sequences ``\n``, ``\l``, and ``\r``, which divide the label into lines that +are centered, left-justified, and right-justified, respectively. + +Finite-State Machine +******************** + +Here's an example of using Graphviz for defining a finite-state machine +for pumping gas: + +.. literalinclude:: images/gaspump.dot + +.. graphviz:: images/gaspump.dot + :align: center diff --git a/developer-guides/images/boot-flow.dot b/developer-guides/images/boot-flow.dot new file mode 100644 index 00000000..d65c82a5 --- /dev/null +++ b/developer-guides/images/boot-flow.dot @@ -0,0 +1,6 @@ +digraph G { + rankdir=LR; + bgcolor="transparent"; + UEFI -> "acrn.efi" -> "OS\nBootloader" -> + "SOS\nKernel" -> "ACRN\nDevice Model" -> "Virtual\nBootloader"; +} diff --git a/developer-guides/images/circle-square.dot b/developer-guides/images/circle-square.dot new file mode 100644 index 00000000..c81a2a3e --- /dev/null +++ b/developer-guides/images/circle-square.dot @@ -0,0 +1,9 @@ +digraph { + bgcolor="transparent"; rankdir=LR; + { a [shape=circle height="1" style=filled color=AntiqueWhite + label="Circle\nLabel"] + b [shape=box height="1" width="1" style="rounded,filled" + color="#F080F0" label="Square\nLabel"] + } + a -> b +} diff --git a/developer-guides/images/gaspump.dot b/developer-guides/images/gaspump.dot new file mode 100644 index 00000000..389823b0 --- /dev/null +++ b/developer-guides/images/gaspump.dot @@ -0,0 +1,11 @@ +digraph gaspump { + rankdir=LR; + node [shape = circle;]; + edge [color = grey; fontsize=10]; + S0 -> S1 [ label = "Lift Nozzle" ] + S1 -> S0 [ label = "Replace Nozzle" ] + S1 -> S2 [ label = "Authorize Pump" ] + S2 -> S0 [ label = "Replace Nozzle" ] + S2 -> S3 [ label = "Pull Trigger" ] + S3 -> S2 [ label = "Release Trigger" ] +} diff --git a/developer-guides/images/node-shape-edges.dot b/developer-guides/images/node-shape-edges.dot new file mode 100644 index 00000000..ee59858a --- /dev/null +++ b/developer-guides/images/node-shape-edges.dot @@ -0,0 +1,8 @@ +digraph { + bgcolor=transparent; rankdir=LR; + node [shape="rectangle" style="filled" color="lightblue"] + edge [fontsize="12" fontcolor="grey"] + + "acrnprobe" -> "telemetrics-client" [label="crashlog\npath"] + "telemetrics-client" -> "backend" [label="log\ncontent"] +} diff --git a/developer-guides/images/record.dot b/developer-guides/images/record.dot new file mode 100644 index 00000000..35796d4b --- /dev/null +++ b/developer-guides/images/record.dot @@ -0,0 +1,4 @@ +digraph { + a [shape=record label="left | {above|middle|below} | right"] + b [shape=record label="{row1\l|row2\r|{row3\nleft|row3\nright}|row4}"] +} diff --git a/developer-guides/images/trusty-boot-flow.dot b/developer-guides/images/trusty-boot-flow.dot new file mode 100644 index 00000000..7f9b7a91 --- /dev/null +++ b/developer-guides/images/trusty-boot-flow.dot @@ -0,0 +1,11 @@ +digraph G { + rankdir=LR; + rank=same; + bgcolor="transparent"; + uservml1 [label="User VM OS\nBootloader"] + acrn_init [shape=box style="rounded,filled" label="ACRN"] + acrn_switch [shape=box style="rounded,filled" label="ACRN"] + uservml2 [label="User VM OS\nBootloader"] + uservml1 -> acrn_init -> "Trusty" -> acrn_switch -> uservml2; +} + diff --git a/eval/index.rst b/eval/index.rst new file mode 100644 index 00000000..6b98ac10 --- /dev/null +++ b/eval/index.rst @@ -0,0 +1,24 @@ +.. _GenAIEval: + +Evaluating GenAI +################ + +GenAIEval provides evaluation, benchmark, scorecard, and targeting for performance on throughpuut and latency, accuracy on popular evaluation harnesses, safety, and hallucination. + +As we're building this documentation site, for now, read more about what's +in the `GenAIEval GitHub repository`_. + +.. _GenAIExamples: https://github.com/opea-project/GenAIExamples/blob/main/README.md +.. _GenAIEval Github repository: https://github.com/opea-project/GenAIEval/blob/main/README.md + + +.. toctree:: + :maxdepth: 1 + :glob: + + /GenAIEval/README + /GenAIEval/* + /GenAIEval/*/* + /GenAIEval/*/*/* + /GenAIEval/*/*/*/* + /GenAIEval/*/*/*/*/* diff --git a/examples/index.rst b/examples/index.rst index 7e8632d5..e0b624a6 100644 --- a/examples/index.rst +++ b/examples/index.rst @@ -12,3 +12,122 @@ As we're building this documentation site, for now, read more about these Examples in the `GenAIExamples GitHub repository`_. .. _GenAIExamples Github repository: https://github.com/opea-project/GenAIExamples/blob/main/README.md + + +.. toctree:: + :maxdepth: 1 + :glob: + + /GenAIExamples/README + /GenAIExamples/* + +AudioQnA Application +******************** + +.. toctree:: + :maxdepth: 1 + :glob: + + /GenAIExamples/AudioQnA/* + /GenAIExamples/AudioQnA/*/* + /GenAIExamples/AudioQnA/*/*/* + /GenAIExamples/AudioQnA/*/*/*/* + +ChatQnA Application +******************* + +.. toctree:: + :maxdepth: 1 + :glob: + + /GenAIExamples/ChatQnA/* + /GenAIExamples/ChatQnA/*/* + /GenAIExamples/ChatQnA/*/*/* + /GenAIExamples/ChatQnA/*/*/*/* + +Code Generation Application +*************************** + +.. toctree:: + :maxdepth: 1 + :glob: + + /GenAIExamples/CodeGen/* + /GenAIExamples/CodeGen/*/* + /GenAIExamples/CodeGen/*/*/* + /GenAIExamples/CodeGen/*/*/*/* + /GenAIExamples/CodeGen/*/*/*/*/* + +Code Translation Application +**************************** + +.. toctree:: + :maxdepth: 1 + :glob: + + /GenAIExamples/CodeTrans/* + /GenAIExamples/CodeTrans/*/* + /GenAIExamples/CodeTrans/*/*/* + /GenAIExamples/CodeTrans/*/*/*/* + +Document Summarization Application +********************************** + +.. toctree:: + :maxdepth: 1 + :glob: + + /GenAIExamples/DocSum/* + /GenAIExamples/DocSum/*/* + /GenAIExamples/DocSum/*/*/* + /GenAIExamples/DocSum/*/*/*/* + /GenAIExamples/DocSum/*/*/*/*/* + +FaqGen Application +********************* + +.. toctree:: + :maxdepth: 1 + :glob: + + /GenAIExamples/FaqGen/* + /GenAIExamples/FaqGen/*/* + /GenAIExamples/FaqGen/*/*/* + /GenAIExamples/FaqGen/*/*/*/* + /GenAIExamples/FaqGen/*/*/*/*/* + +SearchQnA Application +********************* + +.. toctree:: + :maxdepth: 1 + :glob: + + /GenAIExamples/SearchQnA/* + /GenAIExamples/SearchQnA/*/* + /GenAIExamples/SearchQnA/*/*/* + /GenAIExamples/SearchQnA/*/*/*/* + +Translation Application +*********************** + +.. toctree:: + :maxdepth: 1 + :glob: + + /GenAIExamples/Translation/* + /GenAIExamples/Translation/*/* + /GenAIExamples/Translation/*/*/* + /GenAIExamples/Translation/*/*/*/* + +VisualQnA Application +********************* + +.. toctree:: + :maxdepth: 1 + :glob: + + /GenAIExamples/VisualQnA/* + /GenAIExamples/VisualQnA/*/* + /GenAIExamples/VisualQnA/*/*/* + /GenAIExamples/VisualQnA/*/*/*/* diff --git a/images/BrokenBlocks.png b/images/BrokenBlocks.png index 96b8f5637ce989347eddb3b90aac15a817f9b8c5..1c9104fdaa1b5ebd8109025304d40efb7de86a22 100755 GIT binary patch literal 18724 zcmdRW^9pcf)AD zH?Q~SpZNa3V-N1#k8{p-UFTf!yq;$fy4q?KWXxnB5QyUWGi7}c2z&zkDUc8WPx9Lb zJ%JBWw`V56CuQ5sA2^Pek_C83{Q9|;3h^p2x zlHe}dza+kJeFj-wW-m@;{eg$bT$%Kha0tcoyWK(M=Hf3a_H>vyw#>!QbmQ&v+^7X`8;cwz;`UU>zmg z;nWWG0t26nUt;mofscxNl)fE|);;ee=a_)+S>{oQo44NofAnRAU9kZSTtR&!h{zi% zG~v%{Jumtm)f>Tx;?}z44OGb$+sScU zLGaGJ#auFk5l&md2CSmt-vZUcB9OLRQ5}t##}(wZ2o(uiaUIQueLlG9LacNNCwCn* zVv&)}PI61+r+}?YgK~dj_2(hf$)q9lo9dE$hGo(Eqr%*8pW~O1US6hT+IvY@0 zPXa)WO7)uVT8$$uLfOb24KHx-luy(4_^6oi!DG3hC}4vy0ZX2v!y5fJ%$24W{jx!v z+P|g^otZ#6*Gg++<)6HnQeeGcjoqMz6fC>(N^n9~9-I+NIii$*{-aYaY6Yl&6 ztSEj_^lm@{AQyK4I$^#3s|}b1PH=o-G%2Zq@J&j$Zw2=!@_jN$I~QQjK)Dv_!op0m zlPdX|cbugbfN3ZITYuq^qIln=>P7GH)y3nOuj%2N_$6HP16R!;s(w+xz?wN9U-ktu zQ0ZbMUIFIwRYCAfQ8jV-OcgdN&bZfFKkmGF=_jy|ZQ~o6YDfJlPFja5`GW1zF3M6i z{F2iBq5-ML@rZZpPm-0AI@er~4Z#PTM1T<_}^FY9N=o zvn#K*vXS#l2e$$9`0wudRF!(I#-RxvLq4SC7YyiZ>zT$Y9G6}7Kl+^^vKQrdbNU(| zPHjzPpXCIc_sx4!0>fMn*C6&E%N^j|jG?ZLANu)bnikWHS6S)z**mpHC% z7>w}?xmikkpU-w#?N3uE`6MMauIp1(Z0qG>0$F-vf-xoI0qABJ4Q>3^j{IV!=+L9% z7x~RK;qgm4fkn%w&it~G2=<$;;;J`vqja~b(jr4x818X%R?_*JE8S=d%T^)+(7K3{ z2lH(?wHvJmIZvAebWoDvDpHJ~N+KugN?0Qya=^MhB;OvS{?Bqf#;`C%pKF%Qsizt6 z(jUP+Kq3-gDXP!4@#pX40ZaKKHUUS9ZVWQJ*4CXI%P3{`StJ?PGA9Bq*$ZF zot{~qDZx#B*l%pjKZ^fEQ3W*enH|^{%vD^y3Xuwp5%EhRJ_W_!5e&G$?s6SdH$!|1 zz~f#Fd};{IywO|hTM=uJ8qM ze-#X_L9IP+@zYJz#%(i-w7uv(082lK$S=^%vgFs@4_klqb^#5BH<7%8=))qA<;QsR zQuzgzcYtYoN&;j`5dv;=cPvLAp6wV*%yF);r#Kb}_w!wiafy2NOJ&y4;Ea|5Rd|vU z%ZikgyN1xlf{E{djf$gHq7zWReDHG7-?Yq(<5P*=M(Y7G5^fBKUkt`_PaVV-6#Zgp z(CojFuP1jMM0iq09MVu7(l^o_++4(7a|p-$=0Z(1KjP8*@Pp}p`@h<#!0-4Uj%SMe zFIE;_0PKIY`t?VNzfWI#dwb^#gbITcFa6GP;H7td^t|Nj-T4Lh> zXBi*AVKdp7+}hY`1;y6!4q26CC4K{jXkvaGLN2IRinwIA6L@@ex{^+;U5KaNEPgzm zu5P{#c!Lhs(~6UwD@}$@!{tA0qnf}rE7AhC8E1RvVxqih_Zo}$6;cr!gvEZGqjUc* zAgSUdCdWIgq;N}&p`f_U_eu{_S*3WfHPPwdjF%n_lAfrHweh}ArhKSl2qP4^m);^$ zD?N$2@ZtWheK{-(gh;JZ#g68|`qNAuL+DTim^=;XR9s{_!zX{2k+EL4?}e?;yeF1k z=nG)8{jUMqDJwD8Anr?5FR@16(+^5lQwNG~NPX^c<$}Lu{m)%Z$lUw2>*vuSTpxMC zo_++x5qoGEzU1ixKqop~7<7{8NaWvp00@v(5> z+`L7`Nh+{mNdeElgJmV|yTX$^zWwn4v5_jXQyjp%RjF{`DQ$tc^V^>8P}^`nEH(S= zrDw?E^NCL3`gdf2L-B6|_sfpDk=E?8B$vT2bTW8!yi_JCvHAs5hg?7OVwm1WdvDkK zVz8~o3){F1H$?9|Q$65#J>ib@A1@US(=RW`6{mTy^uLX2QiX`N5HdSYG*22-afJ*iWM$|CvN8(I zj;#*)yV{D?q&87n<|E4k}Bxw6l{Jz%uMAmZP z^|fh*YpTCV-jui|EMfp{02sQbZTc*64ziePA}csl z;UYPgR_KOLc>bH~zvx&NpBcOQu8v#~+#8l(@bZ#r8At$r-0W6TN?)!=(*&%+Z(AFI z80b(~z{4PU%{yTazerklcmaRcPk5geNQ0U)D}ZP=yMXffoF9l;L+h8Wl;|NlCbiX@ zGCnHc@CJOJdx;ftx&KP5&_w@E=oe~D*-XvYjv8Zf?U)?e%*ZC_x}b1wWoaOLW|~uX z-#Z)FOV*r?oG&7pG-E`;xT z<*%zJS~V!UsuOBom2q~N$Ogr$~`BD7Ni%Fb;Q5=Y*XO7N`#oo6- z#0{5pfzMjfo5;9lbLyB81!F4rg3q{KR|yz&kM>K|uL5tp56+C&$laYj4;;!W#TI~)IUtaFBx3-%q zko@Aezi;2h|1L}NFdHmPX(Ay0<(nt>;!SKn2b6oCb=TIoNz44-#NdxQ z=A5`#!H=n`kiBZ)(2T#6x;qCp&4KS40Fg;Wa<2EsGIyANi)m9{j{wokT5?s1E{qf( zMSXzk&5snq046h%znumIt@sf+(DY;=1A2zcv?T5o!@80*RfYF)+QrcJ@af^%RR^IZEFwqfNSs>>3$%8l4JY35siw9KhLFHFofk_ox> z{ATXVl5e^?+W2@@Mo{ahKeE)Dex3eTslpOq5o6r};xHC7bbUUhZs|%>n4oX{ILOt)^WSkd($ ze4;`xF{T;nD^=?!)O7nIP`u|0OR=-&n!utaDuTIi_}p>un6;^c<`9);UBGLS5I0C9 zAGGTS;3#Bz>N0IVES+FN@(YAj$5n)_1!bK#D-3dLLW9B@(xy3B?4LKi%36UVDHY$P zKGt;pGmVLrH~QZoTodakrBVHWQ_35Ax2i^@?Y+#pv3A{K>P?dmJMxV3I!+zrEOXP0 z(c@O(0iI<()?Y(y_q-X{b$0$O0Eg%;6AFI@M##cF6{!HdF_Dl30kRUj^R_pmNQK}$ zskxwd*<;~OgwNsClkH&GATiyx&8!15h!-UXN*yrYC*A>hvKs@d0TBlTt2a}#tV#p* z^RLQ%(%U;@3od$qsbhkbcE)0Ze$;(#(t@c!Q7A%B_OJI3B9Bug?5i7Yae)@QnEnjA z_>#TYQvlK^qB+!#7B&dbbCvmxp5G$5r@jD1MTC2w^EamRmMTTZFY69d3k-@o%ZOqE z&MEJsot2VrmL*dhxLT=;4pp*SvI|h!I1+S zP`I4xgJlUnus$E9%=Yrjt_}OAj_HmgGv9tuxOst^@aNu!)uCO8Is||yH^f97kg%Ky z_}19}Jdl(TUnem~L2(CT`-*aDf(4KQuH}706&=;|VPw2os)_a%pGJ&B{&JRZ7tSV8HAb0KP>eM4>W7V`qupWZF$Dn(s;(xf9>R8fwsPBSih>=BRvd61MKI{uj1Hn!#~O zfDJpGy9*MWoG|;d)r_}&QMLX^09wn^6~xBvTe31srJemz$COC9U-+kZWEmX85Uk#^ z-6uEDb8+#YElO_W9`1#N;Rnn9siHdOQ>DA!T`5PZGvuJYe1TSwwJSKtAs$I8ZQqf8 zDXqKFK~;J0sq%nY?{Kp$dASZI!IidqZ;Rq47(L|AwbZH609@3n9Yagdx+505`hbaU z+dZFrO-%~K#Y#^_mOHuhnJcd-Yq{pdXPn`x8};F*p~X?#mm^ds$yxWuQpo<(UOli? z&rg5=%-E@rWvS5c1PC_oL5&E=Ek~!VEzq<8G`kK6?3bi9+oWFo{qUzP7PV@Vk}tDX z*#h@H?keq3@o~PKM!EI?K6vAQ@i#E~MGV#9zKdIdRCDx=<8v^zR?EwEDzu2e zbOnP0-T>xEoh}IR(gCxHH%>pKu?lY}nKy0F17TEQ!ALPTQU0NDrjw^$d%1_jjhdaf zYiio|zky?nm+974Beza|GS}%naurMa@@jqc&ttX<$;(a6ctvj6_2p+UhutM=M?dhRlKhGm z==cQviWmRRhb7<)(0r69TR5{CbJUo+0oI zma;p+Vgy~#eEEQ9_{(3E8)DlsZg~+(w{Ke~*QW_cyCsT>yvg}Ci9^(8v53uOB}a%NFpz7L?6^AubHO#9qTFMHo?y za5!05Mz6OwgG6dfx5}ze_rQo+|O1X_}tKFEPOsn;7_&lwjIMI zPn0uL&_4!0t+}op90h%u`ChRJ8W<#a)eJVjQ0O2GJb7W+;~Mf78ReHwxe3{YktuxV zIREQv2(?lm^{J0vNXRR0lUo1N7IV&*mXZ@5YPLvMoNla6hdQ^efN^)O;n z>mJ>3AgOxJ^wt|R0p3E%)#W?QjNQO9q4iQV4@r3Sj} znjOFLXmCp5N}LQA;$kjfKRk{JnwsoF-VUI-|PdoCiS|knmZMdo@zQ02U#p zqDkGor^+TMb;YwgexQhCDLtgO{NR<)`&!ReeX~aJOX&kXyi69hYgv_qzRh=+I&)`d zgYLE8q&LyypN9|j>w@We$A}e3-%=hq_0$bnsk#oQJtXys%#b*h@kbEJD)Q4Fn6E6e z2m;=VSt>3$13;Mb_*@H^RlSAkYoZNi*ZxHoi6~|2UC$foW3=b-V zSjO-(l)R{kYOamuauAEL^?{OX2^#{(L}bT{aT6WITEt}Hx&sog>{z;C5gIB3zusID z5_z~_e0U}`SC+|Vp|A))Lgh%a8LMKk<)oFLx}^|v4VG^I`3<#u3XU8?|Gcf&%Rf|@ zwb?er6XBY2Harqrgf?)zRedPw$?@q!8_a^Vxmkl}L!!<3i9soqpZa#RtC(7QR8vbv zMf7v38vp58*Pa6aQ>7YM600rXSv}oP?)GZ5j+Nk6tN>CIA0HxSR-VwH;pnpwgcz5+ z58>t6j6&|sJfO^5`Q0BrfLRS;Z^2eXfJ#>lYZtcDDGecnnYOw$RQ~4MC(}j{nkTb~ zMYEoDCnq1sooT$J!{!JnPqrU5XK^5#8i*Ku!xO7mzMZg!oqh9Cj7ZRM();~i>iP!J zRn-4STBhAe{xY&VSdbC(P;zHAMIsq+AxHV-!kC2}{2|CkndK`&6kJm1lz)Nwwo3*O9Sye>H2% zFX=6`TmjT~ac5OBALs%7Cd&9_uRO#g9Ui|H7+?gw4{g_;h=Lx<59sGyA6&GysWzOn zpDFB+vF={}z9bI=!WA}d^?@YeGjBG($W*Hyk!Y7%>2;#fm~(o?AK(HSTdY23v9XI= ztBWw3;hUIlsX0W@#gGq%6Y1@FX6ymqH|4%a#} zIt!1?K6&v*JSXi+wP!-+mMQ0kORKY$NcvFn($@eLUVRnxkK(qoW3Z6re(uy?C@KYQ z01IpS)0F*Da12yAx_;e&dLf(zDOJREx?_;70turJ`LlooVlr_BHpMGGfK6aI=xNdn zMul3Gq)*!Z{VI6;RaENVQW>}puO_381YZ+ICcCG1jYbe>!y}mj>r*<_t4N|4o^@pobvw@AiJ*L~`r7i5tjf0_0CP{rUazq5+)Y#pT2{B5;s=bNHrPqG znGFYkPWg3ED*m((!sk=OFjl}Naa}#iz%xpGfu7~?Y@ieEQp9pebDQt<#eK=SM(81R zSU?h?KuJXUgZPDL$#nfVz{elNY+TFow=T4mUzXP97ktXP_vOlExroSAv((Cp!4Kpy z7v*ZhhTC17P$|-Dhi$tdup?Rrzq%3h_J!{Qix$(f z^B2WKzX`bV!GuW4)Uw**`cobJ?kh7d`gOX%hweZX)GtcM zx8G{>5v>w@BquwT7kE-p)grQ5lZrOjA@yD(JH1beqyaYPlJv_5Rk5SQl)fgW>h0yL zaSV?b+a;bgSVKw&5)tVa`h1<;^9&?C-h}64K{K)F$w#40DpsWwX%9l>tulbAKAuC* zkkGt?#$9cFLSaXrI>b+K)=ELKQe&Su_2G>6vQ=?5$LV7D;>ZX&rSJH9A6{-c-k)lg z^Qo~7)L?UVF!R4wfijV%GSitFg9QB_+PK|$A|L-^q;-!H^hATg#+%x*6;eXaTe+2M75=o7$%7HQ;;2a#o*;0jvg}v>t0O_ zwiuUSREFc~yw!_;>Ui~+i!xHVvc1*nectFlx4uN%7Ti#blYq6&J$@GW%w0hc6ZK!E%R zmI(U_ry2VS0|*5F;{vo;_^Qv;JhhFmOsJxpXUN*fuv@z_KsR_AqDJ+`ehG>Ttmt_rr&k|4R$Ec zwVY{r^Zv7GR7%}e6xCpJ%+v!bsV39;?ykM+4<_|YuC6jiRV4mN)sxXR+5k!ty|?L@ z;?Z6>9W_l|ln(;DSU!1KDaSSC)UgIo;!?R`3Py~HUtQ4D9ICC;D$El~3);8Y2xT+0 znH=Ab*vSd+r*C0r=5;l1WIaV)-HLhMr0#WLMSU0qz6@@P+mxGX5MazAoQ3nYkIcyX+6`Qz_W5iQHU>cc(L(l(mp|RlpPfW-|k&T6lOpfU}Q5{mL+5Nc1*N$=RFu91DZ2^ zs^)4UCmC))pUfbMxX@2C;5rIII<nVd9f&X`>|qi0{`-1o%6 z1P$5zJ7}_=PriozYx#>7sSmwq zep(TOYN}@YtuEIEunXq-zUmqYD(Kd!Y zvOT=KBxLt%BsrdYX1(qxkf|$ZPGxvh&LkAT`mvJrnW^fvi7P@PGQ$-+fESH#QSUJj zmByfSn42kAp`M*Yw*=JqDoBS;0kN)1x`Qr{gQ7{uh|sV zSmT>TDJA#p^313*z^Tx&(5^r>vR!`-y(&$Zz5)VjXTq-^3ma5Zhqr*N9LQZ(#<=LV z5m&{5g|U*Yyzg_%icS=2Z)BN z%|Mp1!^dJ&9>l~Ah|tfgw#6+4sJSPK9olod{-;~-s!APyu|VL|o3t(f2qxbbq|qXf zHEyIUNqA1719tya6`KntmNh7FssLImP_iPr; zLSp&po{b((G)A33&|4XuBv$~mjjB5z#_bjk+x1!J1yY#ku3C$eNXDJn;Z1|Goa zQC+eC5J?rQH@k0<=KqRq4ah-2|C1!`^MPD2C2_#D(!0M=a!2lU0=0r_@)-&{3!f(` zWU#BJRy)x!mPvql;x^l?+UEd6_{7)$l3-*!6NMExw)G7p+cpZ-t+jEE%ORe^{y_6DM|%<{3bVp5(v(jLjX77xwvuWx|vF5M$j%6ik}B*Nxbu(#{v3lF$h z3+_*xWgdEC;d)eyiD?0dB;B0}GZj=8gv!0c*M138P@}=44{7Ud;0?arb8sCo5+w#upc|55ZU*4hu@F1W(!^weeHY;)<=`N>9ADC z`aV6Yal7ej0OewROvCSa7QUIX&guKE=2+7|s9w%#5zDu$j^-7|!9rK#D?dL#IZP)$ z9=8`F<~s$6*aI0zAQ^Quf!O%>CP=MM$9o;q^A4sJhUYJc=24?&<0{gRi~{UY9g^v3}RQa~Yze^Ek(;TElyL$XF?G!}N@Y&Ei-wav*1tNMzU zaxOLLEP=mlP|BqMv;(@mdY6YJ@{5%fs;|glr_7e0AAI+>vtJ#lRBdfS|MP@tIkFGR z$KMyf+|J92`B{KifPJ%o7Y7D3x;o^`kiWWM=Dso{2>cPgMdvsK^s0y=e7<*D2!>A2 zX0oh~Vezc&@TW66LrV4X3u-5N;xOMi?yvUO`?Y*BnmWb{t4C9^F!tVeL>Jii%6N3t zU#Zb;=Y59CP;`i#G#M@(u`b#$c==~g?H+7lx>zcyu#>m0)CVh628eSHFKeSs=DW^@dJy zju?&jQH~}}b@SDJ*7TxaYAz&{y-6)Nx1Z0B&ChWPv_R<3VYn74ze#N2dZ zHn>`+izypc983?=j?3oXMVKIgC`7CErwI%<2sm9{QzBCVO~DB(D1>1wlmXJ?h=5kPm5X$H;3Fod)V0+T|P zOn?Y!L7ePZ6)SP-GWU*a?IeT3L7-X1dcFX|ZOw{fGcF`>r9;K zvuzMvjQ3(X;QF47yo7$Ps)D+(5P2d2YM>Qq*zDjcR7Usy62$aE#JhJb#;{?W~LJTPQLGM=%D7~GR?j^a5K(Xn)xMhQ_uv< zq`7@pKWg(@zgiO_PQ!Ra^RYpx_aNy?KUh&?zwCJY>*CKm4Vc=7`IBIOgMKtZxrR7w zsQjY0pJ`XYVOVHtiEo;KJKx#>vRTYZ>j|33IKZ6^7f`0q~WMj3ygQqab7d%yb zuztF+`aXp^(>8*s-aulYHY=NP%xO>oJ+Ox$pkkR!&yG||Z-9UdCEoi))}e%rBcuHUswTu@xE{lb(3%{#XI6ZW;a^MgnvL1xs_7@yEa}`ooQobv(ZX)mz__&Z8CLC2|}H zxm1RdW4yN(dd;7=$nX1aS(_vt#jlF|oaCAUUn2W)53j_}p4Fr%HSOZ#nn$=4d&U;F z{Jg)`eti?#*c?0^6Nr~O_AH^Q$DCBNrWZBOXW6BBmKeaWyA_Pb)%;i9_SO9`An~z> zbn{Ub-vp%Kd*1JBF8Lp-pZnfHG%{V7QT>IJ$n275EQmXdT#n&793BX zy?m!}Gm4-M?DaI{fJrg?Ek$CSAEvrwp!_n5UbFzR8dcHR$SmAnkBVgjNUeSfU*TT{ z0r-7Sf@!u}O)$f46r;t4b468^jR!>E^Z+uoARfi49F_F4+l z*Hix>4{f(dtt(>@1|ue!g7RwhE4^+TDYq8xfE7Ls7$lh(7=TNS_B^b*gxs??;u3zb zUVaR{8te2xORcL?ABxx4cJl`}^j_Mm)lgURDXhEpStr{cmF4h{ zFMyR0xxP@jlPP%hq*8RM@#$o{oX5K4DMui%b$dN>rXC>7D_G=9uKS;}YW$NQnr9H* z3Zfl5CHja|K7a9iK?UO14BA?ddMg&c3ZzZ@0nysd#?c+!2ZcP4v1Er$5rZJbf9wlO zWj!C9s1HxM7P0iV@5hWpSFL$fz)aUepvy;BD+!|M@k_aa0EIt^OeZ2oY|D9~Go>~( zGz}^zXB*8F(BXalRt8hyV_Vo|Kd%mjP*kAD?qQ0qJx&3jCiD2rlqEzi7+{z}2dL^* z&ueVy7*)Fuzn~Jt_yngN`=oq3z!^x=q@h0r~hhNx>0KCw#l-r;5&H>*|Y)!MwYbZR3cfziG|`?C@>|F^4q!i-u6oVMnqk)GavkS| zyZ7DoyQRWW)p1#?RePbFYG<$lYwLvwfR1m`ZiD(~lA11*@?H)Cc@oJR+h*%Ke>;zK z@X!|(4MFs$Ylmf9R2Tqo9;f=v1g&~IC>p6V`>eiY$M=&q-wUn4+Qh2v8px}|fHN6U z>)PWoMo>{_(L@l^diiFD?+maod*o(fY&hq_oad$aF zgP3~^*TjKn@KgBiUGav)1!R*T?1P!itJP8jm_NA_EXt+Ot;P#ne(ZqSk~Y~{2<41q}5=BD|IjW5xw$Hp^aV9kvw<{Yj+xk)$$Bd=tY-7 zlka?SRnvmuWy#6+=XS2cTQjR7g7_aYzt|O#wuWF5Sd!HLt+{A9J~WpX4Pigty^dx>T}EW1A^7Z?0%Svwr&)$ph^{1YZqmZk4Ayj_1i!qtHffR0XgzWX z8n9MeC6QYAv$)M!zw174UQaJUo39HcDhwujb{%RP9U1h5m$)$4uM_3No)zq{^gk$N zkt66R^Su=Q)rGf%nLWcrQyzkTvfU#9Q9o6dvLDiu(9YTLB=*TAThVk)#SzDm9+|hR zV7Pl`qw7%le)i?zY;}|B69sFg#%ry#%u3mz{1Twp;nX?z&2sq;DYh*hkiT<~?1w)i zfcMl7cM-SVA8G0O2a7YIuV2mLT_x@r#rZu})~1Elo$X^2U3jE+$bLwy?k8`n3xZOD z@L4b4D+P5tMjqGTj61w7J2x<&a8YUYX%=cj_#RXc*=CO|Q)s~^w7c8Y4foHEAA zE7;3cJxwc%igA)MLPpw|8oV|>_kDxVErp-g9G4~1EvK}gXI;<$Ezz$@10XzDyF&5` zzTG45^405EHlRBeZ{A;7Ppkzxey=b~Lf(3Df-!D>`*K;kqPy*pqFFnpbr4DQX6at; z^ShU|Tc-u7d&}~w|N4;8n(YB#*W6|Cke3az@W5w$oz>54RQ2DL^DCZGQXdK*M3sCy z_XaLW;9JAXyf>z=D#gJm*Mg-B*Mm9Lr#eF(#nswDD&V-L!E@n#odGpm_Ib^}nOFop z@=7V#dpx`{Hcm+O@Y724>m2K1jJ_a|V2|z;JWTq*j*zIc<-{9tt># zI%72a=tv&B<$5h}SkB^E?wgH_G0YXk6Ios}&td8nmwo0(xn`aesmnE9H&g{U(d6 zdb&-U+5Fw&H>uzZ3wz;HKZRuEscssy(a`;pA)BG0o?!j z@pNNp#4r1sXWQSvsEA1ra(qh?KNS&qVE$PkBkabF&T2I9DQLS~^PEifCIx zZM~*A+bu#zR3AVm^z9S;Dn6GjPoylhdMzvuvr7}smpxl1%~pDI23 zI>BYIyy95;rhYbpK7hBv4qfE;EU&ZJzEbuhf7(U{En*3Y?l`9X0g|XV0*>$8}#{je{9{(5;{~Jcs>Pp*6@xdlQV<#Yq z*!K1g(!WN-ebxD#}WA%piwc_$u}&2M}*=C&{H#t zDqYVs)DU+``QpSAYh-5-{1fn)0RYzuzOU{t0h#UG6X0FpoiEl`#kOlccgC!+<<1;L z8~suL=&%pNd_e=(FlAKGH8G9ji{bo6RwWEiN=Ek!ElgAF4yLZe)@Le^4{Sds_SR3n z}g@pnkMP_HR=(gMbt69eoZ@s5Rr89;I7@!V@sMWv>GxAIaBz2K~Kyzv4cdc zr?-7w=?Bbn11~<>&9z9_4?#TXyui&zVslR;`4PCKD`-fH=2hJ{rwT`@py+k=)Xq*g zYhGkhZgI>AC)v@P9Xuu(EcWHs-#&U>I<=h@B?i=o_XaVTPp=8IRZH+Ssha|qwkp`*2ui5 z%G4>NKz#K+rFYe?u;TtN#Xk=e--kBi5-0(X`i+)$p|AC-(_YZb?5_^xTycOv&VO_^ z%+)=dO}BZ&3nw+u)WWz1(w_{3_F85dphB`j-U`p7Bdk$1)cL&irh}b8-XLzmQFb2y z3XiDCj_n8o8+kq3kjL|$9SXCBwhGVg?P!hu`~v>~!xd@mI}Y6kI@}WvXaU-*CI{bmD{yI2=A20Kfl4n;h4=Nd1vI+pQ(pxnX!ZnQHaHeWw?C6k zu5cVda@I##TUGmj+q`FDL96C-*Vo7LbJZ8@C(l}p^8f8Y`vFXPZ37V?r8H%?3c5YZjg9w@R>O<4k@ylqlxUzJU3s~X z{+qA;1QmQKAhmS|xxm0Z6AeFYk`+~LUNL>rB29Ky4iNm?R0Du^5rk--ZmP}b)6-}N z$_B?NXM68B(I*6fFA5p(U+dpQEy?4u!+n7vF-M)W%pK3fY$ldnsqi(2G0x}wde+2n zITjtpg&+k7E(d{(kNrp%ATu@Qum4b=WV^*fW~=MmJFk=&#RizJk8^fQT4ra7gOAPm zb>Vi``7qv#oUgy<`@B2OUOHi1uh@3?Jkx_=c8Az|Ge zu?#!oZ$3u_2c0p9IC(x zt0@L0*pox{#emJHkW)wQ#ad_QYrIULE$)!B*WWMCZM#Jg2dpjPUEi9wxBNi8aPo%A z0D5NebhML#p~Aa6b^fKTr8x#ZKE-*L@mcya2#>)kI?o_vSMuqfm(!xQkv8WY8XqEs z^V-h2r)akyUyaArPWM$DAiX(k6&9ssg1_LbMX~Qi4iQaWJB~n;szu)A6RzJT#>O0j z2qI3sQhn=}8JgBn=t@5cdvYxS6CRswIAL1fJe1 zR(YD8IEdb`S>n6tM5%E)AlW_nsz%!%AFOTOR$G7M%_E@t?c=>lI`lrtZSg-RE9i^Q zwwvJ+jMq-ywR_cnZ_Ru`E>G)0IYXPyRezUB7?kS39^w3Y+$HBs`k5cYDo(3WIY5YG z1RPN+BDPUaivpn7Ustr%nDxBqSIP|G5Clue<^_(-B*ci*`b0*KA~d6|)_796Vp_52jMX{i>yJem-J3?bzSl8@LPs^fws(--_n~H=MBn zSD_ZCMv8p;eQ(+4k7uj}nRo9^e_r?Q%sk)}sadIdrrG@OW*4Fs?wWP4l@FLgo!eHf zbKAXnw&n|dtAx*sb2iH@NszB!{mM(?vM9UFybiVS^doHb$SKYnWuhg_? zt7*4y#dJ`u|L52}ooSCjYZDL8cn7q>CiiNRS$s8cN6eQx+oysGnKOZN)u9!@HI%hG zUuB(9uT*ON^`^a1gLOKy;WFS}{>kf~t*EfSAC~;*v-0xJ?{66I-FclGsBQ;r;pVq~R{}K69zI>ZdY#+c z$jo)$-*f|40nGr;H2cKsrY_oE`&RSsyvcLijK5XfvtVU7VF#R~js~vuP6lo<>wH=f zZx7s)v`hrJqucE&qu`gfLd@w0Y6{(V_xJrhwD#47Dz2Z#^}q>=eUpxLKmGAS1gJO- zxZLtgM60yM3vcsGY4w~fJKpN1Y?yK>XZ0?JGtaz@flc`E8w`c>YA=+4RBHiMSNOIr zdYZep-S*nwLq{sVy~r-nICspbtn2&dGJ|5)v$xdm0sC*qe1OyKD}#5sv(&n0|DQj< zz?`+3>Hg%mThIAjy#DWy9$Bjz)|de zqb(-4we~7Zd%Kz&xRia~kwV~7G^2FlPCX4fOc7Ca)-%7KD z&%WT#4~X@A@05Jx+z&;d^AFER1#Utv&fLQ?r%voe1{1Iv2DR#3zg@osEWs?>L&J-A zN}krdqaO9*n*A}KCg1@QZlC-+7UZu9i$1+V8o1vqe!;CMaDF*<<7r>5lj8h+7k{Ly z_W&1SZ>;$<(NGt3+)DUrZQ;#77a9Mu*H?);bEEytrT>*ZmY}01)|5y7KC*GwHnG}y zhJP8kzIl3ok(_VX4mxh;>-z)MBA=dDS)O{)8)(k3Ip+CI=BB5;rzMzyYeXc9!(IDc zw1n54{9VY_2i%po(K#jbxCCf3cJdkH=i37>ypMl;^E#`0R|2s0KmV3QGH|1BdQauL z#k@Bj-)fn@b^HJG^Xu&2_RO!D{%@<{F$Q2L9NVH{r(SmZ`m~t8zm?YsZ~oRG@c4D| znS&r7+!CF`axdC-_d7-f4Vj29+z*~TuV9u4twy?06u@Ley zT5fNa#(kX!w~|&5W+#G-gXq~&+09QbzHmHG-C;K86hNgv75^-(@@?G^Q)?lzuUjE4 zFu>!<1traVM)>DDJl*BGE{b6VlrEXE_X?u6k%F9Tx?}{=_n#8>)7v-3{IOH->(!RF zoEpU>o^o`wGHY5;$J~CUsDjmGb?De@VpU5xvFi#ViWU4vne9A>h4~u-b&JaE^lzM2 z|9^i&zRFZhBfkYLhJIbbtXb-{A*(Bib9X_G<0Z5y;+ly}=8uv3iz{y~*vvN8|LnEK zJVqs#F>4B#3$CrV6z8A&!WV?&DaUboB=?R0m56y3XKhYjSBlZl`&{Wr@6*$rjH%2xRXk}; zx@>iCTuOK#mvwqDY`qsb#ml*Yo>`4YWvLlb&a{|4DEx5a&lkJkjNQ2SrQ6@TEA8{? z<)qAH*u9w({o|NI%qfd~F4qpxik&XBfJ0^0pW@Mg<5NwTtJLzyDDdwC)0Z+wOMUVz zSZhg4^B^9OIv?Nt`&cmD7YHUxUm^)H>Q|AWIw=>D6fyVT5+D+o*Il*_x?VP&4DZ#V z6AQ=OV}Xsz45hQ2AN;Qa56FS%u6E;Cu4+LQkKWq6#;gK=#odlhZnv142~C$dzCA%k zvK@z6rX;GvqHLu1GTLw>RyuHUm2_t>k}vSYhe+k9A3F==1lzmJa-ciR~o&2 zXo?r*sgS!P&LqhRz>KoO92HW{-oNmcs5l4{a+9JmN{i!N4U( z6s$yVCT8+EP+bx)xfa)FlIjc>PfcXlTR%=e-uUEWtnZ`PUV% z;OXAMPGs`8Wp_Tc()*nODq&@l*IQhRLQZa6taLaN7g`q}DQc>~Lsyc;<1mx=OzQVr z15}Vv%XB6)W^Qwj*3?YrgfRMR4Zw|$5!G`uXUL}^jWnR{;yTqH6R<60t_p{(#~-gE zLM-E2R!7fd1?S5s9kCU5zK}EIHPbV-b0C-1emgLv`BMhJIU@ySs2U4KJrir^4=)UdD?>Y;2a*n+#Yj5cnKusJl4sHSj0suw(Z0cYKx+)yng#&h#eylkWLho}ll@ zGb@H?aks~CQ<>G-^s2vpPtje+*spK~yclxBl9h1i z#{J;FS^*3q?zac1pn7U2v84@gm6ck`I;R~y=j1V3ad`@Mm~i?Z{tIn- zUxq!$b=kpRX|@@2*cV+PY8Zp-R|1-kq5CffHZQ050?|=m;NrMSQRPcjK5%xheqU%Q z2ir4;@V9i2@WH*kIsTUm12N#7+y8Q4gs;Jg9VcvpnI?z_O;fki=7Qoer}F*;Zs~S# zZ>sOT<7~Y8iS4Nh(dU4NHv4rRRa;>j>|pSRU9DHvnS4?H#mt(`W^(xI4#U;h7&CgN z7Kag83~*sl>zbM5!jd#y90z>`YX_BQ#!UbW58l9FAIdZ&PseApi|70}=u|F98gQLo zj>dfXiKLyJ#vAF~i5QG;(L&GHYb z{u^RaZ`fb@4Z94U6TAr4`J%A#@eAMcpRt&uIzLANE1?q$8nB^y)trWtrg^m-JA>c! z;-@Nt{kWi0e0MyeGDA`k2^^)#$eH{^iSBsZqCSIuhbBN}j6VK$b2Xjuo}1ei!P*fP zv~s@&z!S1wGQ8O0vCt>qgAZq}%KZa4_4M$m1-;t;{j?c+`rl#IA7Fx0WrVo)ke@rx zZ;L41-5f$5I^YMDGTXCz+=B)&8FmC#=+~+F(SOA#?>_@n zqKDBBzcJ#dpiROfB_J05^BA9KLLpdK!&7p&(V$^TbqN z#2MD?*U!hZx(uZWyX`;DX2hu=mB|!5ds_r-h`Rj`bDC<>hol@v3ADPv^IyiqzydwD zt67+ufIFUWTjh|R3TN{gxDi~Z(%w&;qxtKN;-VX;&Z0jQL^ZU22NYjT^lN*I{AsF7v#eE@3DvNbRzBZBxs1v-s4K4YL8o zX{ezTx($wg0b^OkUJ|wY@~5}e>V-~%hVUUgCW!l+$DjiMFG1`XTk?#F(cC*W!4b_GOz2~-kE zkCbIGTnYUrMC^25z(3-Vh7zs%l@<9rYn+}ch6cbHT{S#;F0wm#=KJ&@$M07l`Ba@E zL{c*~=Zq$VNdh^CoIFb#y5@I8^nuwQG#E`8Tkpq-Hy-sy7cjopWDg&(u=FDr_k{IojA0JmUm z1r9$7kcx$SZE;O|%2Tzt>RR-t$aHz8!_9^m-+=@Rg}k3i%!vf2^t&2FgQ$T=4K^XG zh9s`Z1Y134@!#MZCGa~s+!=@bxrDs;aI>^R)UF^<(;v%Qx=$#Nyasfb4akHeSz7_? zhPLfsfxmXXq+fnc>V~j04I+y0Cf>v$OlSfY`dFz!$XN8b0iN$M?k!4ORSv`+*z_Za zbu%f>7Y_%irvo0)NJv2D8D+gH-LlQryPcPQvg2=>_KjEcSJ}=e7(8ob!egMeJpN(85&^~RJ3g$;OodLka*qquz!R=efs@^h}G3k`h=Q4Wi*_C z$O%6li(O5^n*T1#@zP_(m__JL%e_TE`&u-e0E1cs-+sai*7vQbsDZYBFeNiVkj5aZ zw=LYZPJ+IEe6i;}Cxq&8UJBk{oNoQK_T{^C9zD+RyNiYi7w-L(H)4s>nv%c-(|8K$ zmL5OldO~swAU(LX*tV=DiI6XODMMdT(j=jRFO_iI07LxaVRup?Z;}az#c^qIZQ?9_ zQd9fDZ)tT0mdYrVvuo_qYU9Qg1ZZ-C^o+ulNt+csw=Ydv8?ErIjTg|_k8RFYa9ohR z`p_^N-FzSH4!p>HUfgKjz-MA3s&9d4{-*Xw&Z-I*CcL>k%fm=$ z`bsgY1Et`7@SY9+2ay2VGr&QK=dbMM@ipTP^1HbKxqUNUZD`zX1*(ZW_NFom3;gnR zZgr!?KJ!!TUy9zh?x4fcFCUxQKMUDcMtuSYfiT%DU@xYxkCWv#D2L3q3yQ`Vw#^TI8MllcIPpo@||5V7s@H3f8Z~2=f{afhyEpf0?O-a1hc`& zFhDUOwV_FgX$b}6nq%D6e`u4!i?*Ckr7$Emnwo=mY^PnW|F-upd9R=OocPiR zdvQ9l9bhZNdE3CB+LDthBa}euv8=Y4pW-RrIO{oYJxtw@Wt-vny_aAq8E?*0VIw3V zml)<;jWgzJubFQkwQ~Q-0N+HiHtob+?H{L_j zhNre3YkMeIjg0RIX)*98ONw= zUv$;}`LR?@ynr-1Z0ZMJv-KdqG2{Tq&YU)!`h#ldGn*-jB9B|XKU^!;7U@h*8bZ__ zE^)VSntWZD-U=>uFr8x+OK>K52qFDI4g2tuidgo>~()$6&2U7l6 z=FQ^ed%0GdN$e@B!aik7Rs*rGw~f$%Q3pQaD+V?ne^?+Ho?*9`ES1jfv&}=BUjmzJ z3ga|*5hvdzY_Nd=UVa6W!-zUu#>8$y?M$2r{pfs*OkeR|vfASi(ag0$_V|U-(ma-# zV~tvW0z_L-h9fL_p{LLf6dJQ$qT4ZX;f<#x`k8E&MpL_Nr}SMA4B6Uh=+dzd@oTTA z+H>XwIB}&ju~ABZ(qhQuyQYRQ+#X*B7Uav;8l7_}!0{qTpLi8=QKzXY!Rk&tIsmGAZmO}^>Jk=tF{KzII_Q87mkx}pR*myQ z3GGhbj!c9P#`Uu~E`;+hSj-tw0iA=IWoGksqS)^7xnVszNa`r-*ItzRZurD-kl;9J zW@GTrEhVt50sm=%3|7~|GktY)?=V{^I>wF4jO^x7+1d{>s}b6NYi$2&a6JZ=_nC1V zeDG-V9-8$13j8)P9TD{;uB8tZDyP?) zLiU~{3#?|w263qDaU|6B=X(@_&@fHG zzK8^mm@rB9{o^Xi#}mLbC+^Eoy~f#%RnI!+d2UGD%KPQzH&BpU$j!XFJAEIcBDAcf z%q!b?n3W-k_)379<^641qEg50V}J}|J9`ox*)50$7;mb+cw7=eAp+`Xu7lDZP-;fDT87^6ZCpc2BVKN zm+d&T9&0J{GbRzu5KEaaH512|g~ra|(*f@OjqPuu42}T2)B>Gq#ac^i@#kgLD36!8 zde6;LX8^|HNx9oSlx%oxjg~BsIaz-ZWloYLMW}~@GV<7ZIwwDp{Gk`Y%I1%&CsA8- zjkeL(_}(1rIik{JF(~E}Y)epzJ&oaRl{5L&Kc}Uadlfi%W>B*6=J`y}u*)mq?J1O} z5>?$9z}@g3gigH|Eh(r@mZfOI1QPe{>AM6RLiAh~A)P?C^q_q!aTzjqZz? zP!&(DFmOyp?sh3fstKR|t{9Xd0&s+;s#uIk!~p&Ss_Z$DczX^QC3soNQ0e}a(1pU% zP0eMtr|;UNzjr@a1ln*G%K2vXz-aZ(rNI5(irs#WN4Gljy^-UJURgGe>`$Yc$-AtC_N#4A=qa zen}C=(f+WlE9T=2L8&w#U_1%KM;8psV#w~dJJaak1abizgUbJ5W!_zV6`fs?H@|RH zpqfgUJF!JH*^_Zc`YHzHS_+EWc)p?p&{OEnw|Q}ZIKWsiy@B&QTcC+$yK}2TOC2D4 zXu{Wj`B~bsPFnO;P!5s0Yh$S$RM8#{s$M|RR0n7#*&*M z94sI-!d<(Kv)czw2hRK!IG$vtxaI?>&S$i{YS-ISlxP~Y95m^}@%6ELJGj7=zml06 zwA{X&eMw9ddu%`%Z}5VhFp3FuRP8_Cvs55(a2w1#gktctbio&#{& zi{J{5A1r=L(0vcpOBJ3T`Rp*%t47DyYglh;NYrYHQ#5Z86g#jCsDXYy#5qKs8m$Tpks#wQm-;pL3*Ym9c;2X@# zw62h16*3&ZF7p=<0Ar2mfuo0QMhRW0oB1+t+JO2OstB-!&1pQ6U@k_#j8WtMnW_&4 zQLHY?ztsOjP0)M#=}hs?fhLy%+YoKDxP1UNsk7eEEQU$2&f3`mBF4MiKgw-a384zuv(7MQ`r*Voyytj>(KPbZq1eSX@ zwcUJ#mTJZKb;CeM8!;Y@Z26G~kfi@x^x8RBuBM!<(($c2e$R+GpHxun?d1G+sq6Yp z&_bLy1=m`L|1J1EWvEyVdQb3(FywUkg4K8Pz3>;Du%uh4+YAr<3ycEdx`QNp09?FT z!De;et58*FyjQD!e@nhqZW`o@71)aU41iEh^j1Ks{ad% zdmJyCx9$2$6l=~sWQWPO7RT;8G~cM~;1_`ut-ExBZLtg^TE1TO)6-Gb9i*A8@K-3uZyAm&!lK_tq0IAUl*htt5km`cIS!OR zU}^)d7%I$d>51yO#729~6WiYC6wF!W9CUTm5 zYCp?(#e?SOW6pU~bMS0F8_98VM$>Vdoksr>P$Xk#<4WjsFrk|_HoZLw!z}{PMS!2Y zae-?&1ab|@XLSN`RHx??<_fo~zr22C|&jU(U~n$aX+Gi4R{W z`V{i@W8b!N4xLvp9BvpAQ}YWI#k!?`A|UEbsbc4MF{Ld|5p`~G)0_lRtMB2i>iO%&3R2tEjq1&b4@Ls3L83KC7MsJ$MMBlmK^7fN z;gFtZ{LA8X4P(grBv9aY(VRb@?M2uQCYqOpYlT}RUQAQh)*Nq0!Z7B$ZACyCw$Je1IE)Ss5|DEKGdzwqDY}^pgUICyI{fJpQ+W!Ak0NOLpZUR~m5o*N z7^haXV1!3`9b{B5H{JrIf3x#tuuaD1>+!1u-AjrWz!;jZd7T?u)8C}g16Tx2xjc~Z zH{qZjy8gLodL)`4~#E~w~D43$tD8eQ;AAxV-Kt9JTq@=x)9ZY)vX z(<^EP)G~S-3rsb|fO(^ZKX3!h=id}$i!U&Y_H`u=2)kMukUM;ErphNih4RJBpG)S4 ziMEE6l#n|huL&P;Rm%yYOMb@4!Ua}iML1nI7FBV>>K@1Aa7P*-gS_d|KbsZ#z`iB| z2S=*+Vm{ral3_&U{UUZKS*~MvB4ZMJ&CiQ}5fc!K^&;g4p~e*Yb!YRv#VN>L$v9WZ zmw>WHdgtS2hx&_li;jXB6o?Gt_1HeI(oP+vjSk3jnL4t)sUzS_3F#LEj&neB1ZH*Y z;av42e5TKYycOh5$MW0l79DmQb`2TnaL$mN4HI{A(3;y9ch&(0{kfQE>dlbxx1Cfp z#F8YpeCTSOJe`Npd#lW!!3&-Gj6$#6 z0)>I8&m@lf53X*c+*ujT@W zhZ_*jY?wSCe{Oir`gV?T$kR~w6;!6n)w3`-gT~`q_q#8ZEIYqfEWW@ z4=7C`ajLVY(GhcYds=>ab_uLm`@m?43|_Y8`tUyMQXOf~IFZZh18FrEYdmb&{dT!_ zdJdidG?@2M*o1v-n^u40!W(r^XoSq!-*h^^E$x9IaXeIcWW*@1^_RMDQs=MrAY46} z_M4rieU6RGA~KdXb2m}bw=zuDV~g{#r5=gUgTfWSPFP-3>{`yO@%kfvD_IcFJvgD% z^f|1gwuD{`j4VMZH)3Z+(aq^f?PGHxdUX_yLMx~$=}w#n-QZ)`IB?|Sn@{H*SEyd^ zN`jgIpwPGLCh;7`V0_O*el|R__ss#GnN9nix6q-(2C=9*2nJ|U&`gdSXk2FiBTr}s zj51hASPBDfi!{#XrMX!_ECQ2K$T=U_?68RP)jEJRR6RFdcEud%U*?)A0PXxReB*h* zIzXitV)20RdP%9+1$EVi8{uHRqTLy!9hT zTl3cKrb+t%4ee83%E=l0IoISa`SUmUa0m>psZ!OH+v~)`M$}@e-}GLz8e|>;B>&WY zu~k?~p$sBZAN%gQApha>)BPz)g9%6*-;aX)4|H`P6P{GeP9g?o2onxbiv}5bNvyxf z31hN!7f5QOR9+LjtHaYNJe?PCX=^NT{PJDB;!+6cs{Jzwfx#+*V9@NFQ~6HHbcUeG zVuhoXE2OA#^&jg0cT-rD?m9ij~4aSAS-l>R#;=3UY zNtZAFr8b_e7+gJidfVqKv_onkU!czYR>k+usi*`{i^-B=!b~kLlv2ELvldEO+8l(2 zw0?a7!K48jldUubdymiN<$Hlg3q_GDGz}Fn5DmecMN^9j7+JIBS!%y2&-oWdepbJuWjuExpE|It5e})gP)wgW3dI$As7h92kG9Ybv!v!i`UQzIV#Qu|e_Vnre{`FYPEga>ljZ>(^;~vGZ}RKt)9i>cz=!30FN- zbtch-Q~@#byP}pvzYSCIdjgQQ;6aH{t(F3W6-zHVJkf5Me`lXFxJK8uVnGS4>bh9}95{rx`K=qD z^oZWs`8#!!0p~Iv11cJ`&E*V^Um1Ffpx7-r2>IBMvuud`4X$3Hxmbj4rfu%i2q7fO zh)xO{lWIG^dIAwd(2}}C@;M>(Q1R9cX#dIrbyt(7NWW6%&Uo%}2`UCX;F-~0*X+f( zCx{;nweVX$1<9U0CnI52Q9up}|F@0ZeiYJ=^wotgU12{nsc9OX%{150L81AvxwDx@ z)H;F_*V2G+aCB;Ykl)G*lfo7LrMwzYHbm5!^n_U1dmOp+(QlnIk@=DcdS)}1Kp|qO z2pVRUx(o4>NMS=mQ0#X+J$65V`W^*{i+JMDp=~*qJoppRCme}D29R`h7F2=cAV}kZ z`GW)C8(0tqkM!Yx6G`rifDWpfYXfh7*mWDnKU^BJJ4h1~4>c(6l5bfSfP*(YvNglOfnGa`+%w`a6YXEjcM> zUW`z|U#jJJpq{8BQwb^%hy_Wxj_I#$V660eCT7O*8|PV`c1n@{E1UhC$K77d`p8Uh zW;^jMo_18!LJYEM`u*Ise!VMDg#2gj-~>Z0RoDer6Qvi#6@Z!LO+unl(=8~lyiJ6& zQ6@Wm2Bc+3;v7fJ>DIZvm;Sat4UGLo<=fvWuj2o37_sTJJp>qyJM+Xz85_uk;IF;R zf!kTfxE;uN;Gs`#rr+@JFG0~^D@2m+ZEG-?^%&weZ4X##0j0*gl)$ea?K5N0q!g4b z1AE1_1iZC4crlpKvTwQ0=d`47Egiys=gFe9KPDZO%ZK?Dx!aGm+9p^M;gfgqLCO?` zKK!jaD3m?Jh~7#24rQ!a^p}>#5@1*hIglg0e%H2YV`c6;O)>MqO^7A~I>qYJnwsX= zic{=N_jmnj;ZNo1F+0Z(?@SukptEaPa@iWuCtdY?L}CVV>U}VS{Wn3Top2xm9Q504 zwCVqw;xODcNNppHu!h<50DtY<`C$(p`mdnmz}h+qk9BN$)b|}ta2gSjagEuDP((B& z^X7(6U`Xwm@(wwI^8f7QL=l)V)f7`*)3ALDiMCQM0c%)+S zrzv5V@74T(C1aKWgE#N&GFaJ=oFvgjLFOcmdka>EVD@z{GlTI?k6+3OXz}b{#R+K% z!hd_oyoDDk(m4#5VPmFuZhC@|W?a+@z})v2(+>(glfgen5h`n3Q%NH2Oq@Do>z(8x zi$Y5j7hPgJJ_o)vzzlk~J($wX_Tv2Np?3%H>3=2ZuUJQL^(;pL)u>@?KL{s?in019 z@hrM^HKoeGg84A6!OtfU6jGsy`28XoeOdR*v7fT!_g&d$9Dk#KhMwSGIwv}N{q=6$oQ(mh)}^v}yLIi5#_f@63ZpY}xU6Xj9Dekt zk`5OeVs9RU4Uovu%uo^_Zm3HTfAGbT8pmoWYLuIND?QLA_CX zvqH+AjUqM}2Bk6;jbHc_(o3Q2_2;1`dls`zLGY>NRNcrRqp}O&lg4SOyK*^)8m(-+ zS-|gt|7Km}1urOlrP)qi;Noa;E%fs~0Zr0}JO;$+_Mm#h?}6B?yNRl0unp3&Q1ZSV z5y$hPf!QWc8iXQW0{|xUN&-K*y(dYbJ~!=(TpR=;5{Re;Q?;}1Y+I2`wT~|^UyX;IGynZ0O+h?aP`JpRjzXvZOxQsD0 zw+oa_5ZB`V%A5@orI}I!xIbfyuRguwBRqIsZx4=GFa;xlY*1o<+j~MaFe+l#SkQcs zZ~DB^8dbgu$Kg_<#7f_GPhc7JMIc%}w-^9$gYA82g6$rt(p;a7Mf=?Us*^80wAMOZ9dKBd0#Htwj)3 z4=8|QwaE$ok`FO$+`gD*SccH^D%ua@gEr}u>oq`Cp*kmgqAwD$ZNaxlm!z-@eF;JP zDD;_$rM<|=tqzuXGEo4SwdumopHdOiv2aP|J+WUCa$x4!<+tmFk*RYw_ z9=EG$I%Zo2GPC_|i|=T4+&ghn6%%=+w2{ZWXdC$9{U5sT>$WYfHkNw3myJyi5a~tnYBbw=lSD&Jf*Px|%deZ}k zF>D4;s0iJPsJ@U}82nMEnP}3FX{gb&AWajo@U+Pn`($eoHp%DQ;1D?50F!=C2de;+ z3bNNQS-IK~5=5qgRh*ID9CY($(^#JrXF*E}v*)Z5GFB*}N{4xSL6_1|} zZ1vTB(2fd_o=|yjk~8zVnMRbV+e1REM8M1g6x2-+agB5Lj2B>{GYhs~D%HBNr=jkzEN1lDwI*2-(VQx`ZI+ZHv;juojV5ObZl6!TJbOCG5 zO_CI>A!%ID^gY70mx^AOrB&1?`M&aS*C)+0>tb?Yh_6BDqvV*Ae*SNqqVo?y_Ohf4 zBrg{l^{pVE@I%3;`L!ccN*_EB8oW)w7i$>8R}4ki;Lfg?bE0EDfQK|lf$raZwzI_k z&13vcE|R2MVJX06B-g?DI*`$`4XBKf&7j@6k={9duNE596zUeq z@$^VOJ1i}{yd->lX?$Ew<4AiT@tn(C_}hz@lFDtr@QJy{zoiHB+g9mB(?|H4iwTIa zrMpbsG%y?sxmlviopDOmp(83es;~HhlzRL}#TByJ&{f$(7sVp|)lA>^WaxGT)b&h^ zspzHq%-tOQA&!M0Tpsmp5p3}HFECknmiGD2QAYRP?*vumwB_p`i?ptd^j6{13zFWQ zNa(-)B-U)Qz>m5p5Sz!KvB+(-?4EN%e#$coX&X3K>anTFCC0d1k~{|{J5=lJLf36 z{CCi;a9Zn7yAhT6kSq=caM@fvE#j7%=DM~PGS`apgSm8@@#o^|E_i12eCEsP7*>Hl zc{S?0NlZ}@5a+4H(aw65l~3P(z~Ic||5Kr_`5|0$z?RrfDbq~QTtO7fxNBYC;N#zA zc3V2MihS1G-VqS!OAwsWq_-n~(1EThi$^7XqNQ7=@m$i^t!H+og>TIa1pf@~YhJI- zyWA-mjx8~s?w*tK;Qac1z4>~vh5OviU$IFz2EO<>%2R({ z$)1lkYJJfa^VRI*b5M+U76uZ`{@Z6*v9!Zn6T#PqqO2W&aSJGq3-`JcJJUwL>g=M#xhJgorJE>;9S&ho zY=3)lZ7EjW8O!U?tDITSM92y|PKugm!(k@c$ovoB`!xh-f)3s`4U5aAI@`_3qbvYq zgo5VQt_+kg--4&w-xJ*|COYYwF0#H~LmCvtUw? zCOrJxh65+UX|2cAcui()*uB`xWKQT;Y%EDqcOZ7zbiU_XZ*x>Gz;PmX5)NtdIaimG zcodRtq$17TWPs+itIGiMRqaZiM0nzM_iKxeFvpwhh)W#UOp+uxcbhlrjJwu*{l9T# z;W-~M5Oe#RIs`2II#85@f3iT@m3mx~c*I8hfFz|JDl-=3XfVMJO$V5VcV)fAi#mQ8 zb;S%mlEWwbFsTt0lOt^J_lqSJ0txe9AjyIS`){OnQocwc7khcX%L3``FwW`b$-mhd zx?`vKs$X$g!fHoe3tc*d0KK)Os5aUZy9_@Xu)|?6id3jc%vDS=YplbOz5ZCu;T0rt;^!7_HXnK1$gdl_fKY~V(+6y}7G z=81&v5eaynj{(YNAZxAKt3J;ti68RV?>*>FKYe#3F1z~FaVD`h8#Ku~B9`}WaKKHDvQ)cbPITJ8U!4oxExUqn+G^$CujLwhWV`vk*?NPhYKHtb zG|bOI7S(^FPwwTYc+(*e&Mjmm1|n8HW_hFOO;5fp`X<16e(YU?3~I$9-2XDe)NSx( zV=(Y=I(LMf#Ypi!g@Br9Q4>`^^(?*p^!S9?A$en=Y;G$<@u=6oT+%jECE*R2dO}$Lc;?&q#58TM&+#XdNy>H_ zdFxO;eyCb%E~x6;ykY-BHWlxx(sV$Wm8f!urj2nTUl~d*c3w#6a#mc+D0E?*9Ce1D{j*X498>; zki@TIGfCqs;5R;M2;YuH7D<3sZ^n3@FRyKx zIS7bC^l7evFHpcxc%B%~)YNS1JPH4zh3-ms3#VocK{-8fcz4qy)q5J1*dNBplkyAE z__v^Q#+n{I01m5m2kY=H6a5Hzt~O~B5=rWESGM!=B;TY?K2H)((b$EQdMYt6+`HiN zT#esblFGu6D9^4-H34|(ZO`__nf0Rr1Z(PU{M^8>2ocwovN$BxLJYRn-bptj0@J?V zcrnxGHIF}NOUx5yoWi)`@w8^J)7aVf_2z{bXzm_yV$);qI3T3EPW)+w$c8#ZE#^k) zgPRlDecgQv@6$e`3-wH=2NR9^+7Nr|J{;@_WJJ+yi|K6hYw_vw(J4Pu5Ft@*nHC+H zb(d=%&j}G)k8{$viqv}I=fAtIhRW>>QJj@&5j2?|=Xbao^Pb764KxM~UVVD<1@`IK z26b}H&>|MyyDk>2_Cnw25J!<7-_21mOSF{ia`FWd>?kP*EA2cI zWrx?94Lx}r&7gU1PvpR(lEpT2ta64Z-J;{(D4Vw^9^{#71C*z~DD>{hws%ZPzp^}` z3~}}YY|xwycre?c>xQ64>ul0>3m|NMe6Vw)X20-~bXkqgJyK zG4l^2{a7;PRgI-CN4)z_$DAv1old5vEuCD$Gl@b>^+E0k%~vVfWhX!i=7e%`0Ol{@ z1@EoBn=W>ei#`564nFbAL2J-eEvR0Nrx-6Y0$=QDJdBBJ29$zBR=NgOy%loTMJ_9f zQ)j%gcj0liuh$$aq1|4yRnA&l56)BIh2ZWBmHrV$Enx`$yxW@%PCLF`F*@#)E;eK{ z>W8+d1i;M60bK}NCz{HPoLY}dmFeuYjK-*_M#Qpqyiew#j` zbsWeeV==n9$=79h<$X}5SMsejplxx-%P}|Q^P>B@8RNGoT-sKh^}4T zg6$m>{2I>AQT|o&kl=Z>X!R8V8(XNJ>QibXx6y2+ATx2juOq2qR|3+foUr2OT@jOGKz(^*?pMWDP&PMf5mUF%D5N-@QNQe0KTP~I;bcd!mDa;2( zm?_`6qKTwh@~-q$dN;H2Eym`IVq1SrVKk_b*fGf-y6T+pL$8iFc@(Hk~sM@8yBjenoXcIh5$o0JHiUIKqy@O)|$>t--pTFCO zG!ac%4#}x?^*)W7g(CEKV>g}MZ_&NhF%jEh?vDh`yNIQ{bHbb^(^zq1aKpQw-C-za zytvGzESv~`#}f|OJjljdn|R-^b(*LPQNtFo^)4N@onYeea|yavu|aC-&VBQIy}z!5 zUI_xJFmm1aWKwo0$_iIj;MI4XJR%;v5tTjD{$haTLq1-FQ&bI~{;pejdVUv3by+pe zWlE8PAY7)S0P;zujp!Cxju)(m(I`!kyZ(-!B!*WB+dD?~ir$0oW6J8mJ-aM@{V(HZ z8Jwl3q7U4#^!M=er7y0Fg{nnM%w()h9QD2c;Ts>GilY84R3S60G_jn@Byc!54mo zX}+M7w6k!Xy%=CA7vAHJo_v2u1j5NHkhjd9NIEBQLb>hv<=f8+4U!M|2Rf%_e&oe9 z5$PzYii1q%>8AZx&~_y2Yg}A=+B=d>za&vq}eAM zj(aG*`MV$k-t5c=X;gMl_~R(_b5xx$y(>ArJ8rEvmr50N$CpsGSo+iW*%cWgcyi&O zoD}l~w>S%^oYYa!rr>X!{Bh)~TJ&h|_zTAO89SdmH>hu@gFdR?H>vs2%oi%tr!Sh1 zZ)U!x{NbNi0KXsxofK<8moQG|ElPi2a?J|kZQijUaw*;)GzUj2iFbT`LnEe2#%8>* z0R=)&?Q&lkpr{U^Yd|$nZi`<2yoOcvQ0RZ?l<7+WX0QqI)m?e^&%#sp7{$rnfMx%N zIIe-1c{RAEb2wS zDo>7`D?BdMI=X1N9QA#Eu|`J-zJt&32fCf~{iCB(mIG;x;f%aBv=sV;II~S~xwP%u z;BoQ{(NxKXu@(OAYz^??U@z(XTH@p5s}#baB7`P&TymA6ASCp6=NS@3)DYlxh1%C$ z&bl)v|8WDPR^LQvCa&-6gSU{BDYfSUzYeRs#{pQ3;_Tsl@3^0&E`$%Oxlk&wYi_Y} zo~9pLF_{G8@j(myjopJxuU%&-i%TevXD7#BE~PLN3IWh zZArVY9{RO3Ik_N*vW8ZV%9_S@oUy9%x$?sWmc;Jfp*&r80E#Cx1{W5`Hkg49Sxe(f z`)>e_$Y$h&Jtlgo(2b2Y!9175W@=dm)SPBW!GlIXxh2r~o3nv1mvI7r%DtO-p~>a^_Q&2g z@~WL#{#u*O_dwg_JZ#Y*h{{4LGg*!z%91BQ`#+zU~ zAH2uE!iZr`VBy>V@RP03PgYcjluX*u+(N_+q$!hWT#yN~}1@JmLMHltgIOarfz9s_>cWUhegvsv(zCypy2|Z9@Pg(m|x!iBk zqN98Y03qg>mJzGLox%P!v3rtS79x3F!0iNkZuGn&wc?~31T+_raPM{han%3}&s9c4 zxBh9>e+k&VPAwq`DKUVtaK8ULe3^fGYzhZq%}hzir+oUnLNO=8(9J|3J;HGs%?+z) z@ydhXw-qK|gY|PBfD-CONHhYPcZBJk2mssCbcm!nu*?M}{%ga;3jg(<8sI;m$PId4 zijd|zYzJ+cN<^9)$>w};ehd&ov3vLY%FzwtRl*c%%&ROfS6djw=`yxsM)qsIMCF9@1z4`#R zNB`0?^h>-@t+96CNAaN3e#@E0?%lXvWg>89%bin4_@Kr`V?ZOh2Yx9@eA-N<$(z@2BnHG@AOEy8<%;#`?Gh{@9r`&RFFPt^! zerf6S6C*hgDYmw)N_;c#)?+bBGlAMv{3`g|01V51!KCDvg6y>!Kb6=#s0Z*z1l+&c z4$xXOgJvBSy(bH?;e~OBpf`6hJUXSZPC9hjV0r_pn*f9P0%%Wkil4muoIK&5*zuf7 zcSzc6*lC|%U&J4&fQBHFbpDU6ua2v#>$ax5yE~;rx_MvB*6xpcIShN=y!`e{)%PC8)A(x#!*Y>Fmp0GQ@B;LQ3XoQVVu zhYo*72G;K?Y6C`dyjcgeUonOI$T6w~t5Nd|oAdLYa zbMp-D-&|Hu>mU;jQ9XcD;-ZPSKL0)te546~I0_qt^bajhbiiZOH_U79Ci;Rkzq@VP z7CokZV~#1ErSdweAKvVEujq!1^I- z&ROwKiu*77*ZSl%^1isY1ou?*Zhz8!Z$As%-OW7 z0qWP*rHKpO)ZN)wLkfePwpX?=c<~1BeyHaVl4TsH1V8T zrOY%kgc40?Zc~uez5OVUy?%OYnxFD7U^L&oLI!~G}SM>iuNEOw&k&zx%V-bcL>m+#KLwjUT3o24uePjpxFu(f?4jwx?iC|9?baZLrJ9J~thF-Lj^(R4s zmX;KaE78Fv3GWH<@-{V8#-37{G@zZ;1aNA~GyS;)uu>PVd(lE$$b5`w{JKU&TTKhY zV8ZdFgCB+mBE@C`+?->MJEUtcoDsdv(*I93Jd+2XVS+TSFJSI6*B*%F*&9_^=eYcy zj5Jf|1!H(13Xy3BpU3{oO|q}&1Gw>yBq$*jKne!>dp>9?cDXBTRVZ@b0^*? zPOT4xvKD?qzvKQWu`TOZY5i1Ub4CKhYR<>#nN4`XldYM2fv@k~^f77mi81t|eBV%r z21SC=_;G?2V>1h<%ik^c#Bn|bsNRc+dLdX=zS+m~6MoUT2-Kg?(h-7O?wYKN{2L56 zt7RF;b`Q)S38_Za7ukwkFj4TMYt$3FPe_B^06+S4JEFuS_6xDv*o|Fes{VA%6^G zz#j$6QlVZOq|y@q!IzV~J7PFwK7X#V6pTPF*8%qZj|^mW&zuYPC=+zcHq#+CoH27| z{XMp?LzN6*{|!$Vr@bhoJa2IWjRfSW1i=9C1+Npai?^qz)qnaIe5>-qRBxu4b-*`m zgeHq>ZAK_xXok$a3~K~FmuQsPgocbC!p;}^dOI9SNwF>)3C{t|VLJ(~>~JlAEt_mIl&DTk_E%soZta0d}uqGzNhHR-tbcoxzkAyT{{c_ zBDi9HAVxfyK_+qE+4q!E%2ROKiGurt{|}7iK!2v2f5+EK8Y%W2Zp;8`xdOYEF4tqk zinEqli`~+@3=ct9eYTj*5K@UJC4gD?u|aky38in%2!{vfwvLGZv91m=hC-}~D#mMz zbwi}{YqD}1(A72cgD>#sn>O#_g*iT?$eZOP4h(rSU04WjW-RDk$@=1=(P3zsU~z#d z6Q~9xSqR|HZ*s_yvY@M^K@xXULp|L2h$@ z>g^Vqc-CGMb_YPFLJ|K{-RlniPm(_4w2%64oWhun;>5t@H+8QYbwxzGV1z}arM2G7NT!b`s2nh2;9F*> zTD(c+izWS-j=k)T3rq3!rr=Q$$1(irF+=<3zo(ha)ZCOX`9$Ij zQ*>WYhksv!cqqXG+@Fan+Dy&kq|6%>a-j*Yal;P-J^=2i9`{6PIDIN$2VB#?tZtOYn<_pPDG?2HO0(mq;*rG2vn3=WUGvDpDY zAMP~`lA)I$4FaBHbH!4-&+obJs=rYMCZ)4o3HK2v{xmcMw%O(Ato}J%Odhkn!~jWW z7Su}ryX(?~B|gYhRUk`#$!SEoiO#_ww?Z>pBO>h{a@BWhKya#xQe03?wXab5Y~f6GW}H^6doO0DDcqTOEsla&NW~+R4Y-^(N~m3E2UQ zLJXk2XDc)4V-Eb?3|LI7p#UbETTs3woXTTa1&bpW?P61cqJf~!2ysFjN|zpUErq`G z$(LroiQ{)C>ywC%?2#Kg<=~$HWtxE0bAf2^M?QdJBrD!^&&ZK#OS5SJF#VVB%4TWB z6Obm05!25Z4l+^EGYLVYE!Ic*$QuOTf}K$V)7q=LOI&+my)KDsc#2@0u*mC@s|-cU zRlwC-J9L)-V3(9iWL~z;NHGSw-Ecl}0V^f3JltO>C;!mdyLuOplt!il0q7b*X2vjh zIP{gDL18GvP1Q|*R=D0%!@_waxci-fn(8-14m5;IWzpVt**oSx0&M>a zJ#$LGE)Fp81y^KTzd&(>jLMK6zxf*7=)e-{{D3?j3-b6nnkHj#IbxE0`FwnZS&OaM z68Sa46IQeA(}275mHjsg5bNy;(pdAqUOkF?U^xgFXpqX;q>(ODTWp%c zZ$kX18qjSrNK(6OFwP9RO;ok8?(HB>0EIA!GyX9cX-srr4Mues6xTV9WLd=xy=o5JOotfqdWZRy*`a1}bw4B`6Yn>EI*px< zS04c`Pq@Y1i1rM0GSw#o&ARHX7S=-H@UEX^$`5AfTAKHpKM?%f{J$xUEvO5g1x`dM z1EsmPO1cji;DPLOd#d!oP-Z_nfQa*3N0wegJnId5UwbaL@J}xQgygmQUbihi9A>(n z5LNscH53Tec0Xv;fe;P_`pZ7C>0tJ7Aw>x z*Py}(CU1GDr{I1F49K$I+4JX%^*I{0xS)_+uh%(OrEi_-Xnb`m<4pmliYdu3^^uxJ z92f6JAL@k`+xc_hhB>^P!+(hDaDad1R~Fimf|f~=VP#- zsh#FDP8%rbB>9-3J*%$zHwu79+@(C5Ne_Cy+;{1o|Dc?AsHz#F3D9{ZrX%3d( zUm(AHzghy4hUQO?-GO+k2S;NI52_hmnat~E_U9LKK_eWbX+ean4k5(Yb^CBde`K7H z9f%FH0Jx%G!f`Rc>Vf-#ZoDy6G8$CSnAG8+RR(`bx?|V4{iWKzxfX7-}4EU^Wd;`!)l!Pu1L0J5yRX9 z2OEz{XyYLa6`}DmV=sIiT$QcL*@yTx`&$iw6kE+-_R6PkGG4Cq0TuFCY@E#CGk_Mi z!du%cTeM0WZ6vEU&_L?~HhmmgFJQ_c)pevRr?dA4OUOY*?P3vV`PtVwITR|h^n>us z*L(bVx20x?Zw^)K`>frE1*cMhp}hMLb*dWyc-xylEbPQ7n7IHgejR1v zhdMoOO?5E)3ne}9h7IelU=#avn#k1bgZEC$98r?$neS@JomWCm{=bX>;@>JO7RS}a zZMbpl(V+^D++i+GHK{H9;|H!3J|pD9H>{#yosd|RG$Fzr{I(IMa8Lh&1_Xi@wknajK-Pl;F>+%m;Rd_0U!&3q|_b`2yD+rzM}m} z@1AHIp_PwofZ_!#=WDaeTb?cmBqG6)aZ1hP!2Eg8N<9-QLv=^rpD3MVVHdeV*r(iO zex2(hTMIF|0@OqZfW^){UyZ_?6vtaYnfR$p1HH!&PepPHzyqyXfVMXFRt}C*Kb#TWUFjR*tYl5&ysmgFXwa03 z%sf~$t^GV9TMf|OS}&o1u+aE}|08>mDUn1x$Sf7;>2AlzdQ$_)P#K?7@wR+Jhf_oX*fVKeo z^piNk@$V{24w=-VJ>r9A`JVIx`QWmqoRq&1U)>5bIuiwIdM2?1GIE+s(7nv?vwrYt ziE`-E^fgY%FYBq#R@%~(s~gp{7z8}slCo(l-5J&E5&lCI{c>bG$i!@Zf#7ZfHhLtm zA4F`hLqAG`MA4O25SQ-Cc|jE|2^ZLB>&O3%1~ZWF9)$qM&z1+Bg5XMwC?NTzTJ${o z)2M;`xa}J`lu5=+pdv*-I!enPV}QUgmBNIDVV zv!~DTUP=i`mqe;*p+TLwq=$eM`p2UoQfOln(Gn*dbPSK4?v3+&qOUgXI=QXwcSKI% z?6@JU&DQ&YCkjo5532VCljoEH*QN5O0=(h)EQW|}RDZI2nAWZj4u5_BqYGRoQ&0(* z=D{S-+uC@)kp4C#E>)yE!56+6~1*oEI+WzQBVFYm~sM|3BpCAVKW5~#lHo- zJiDh70&7x$k=%I$?W9M{RBP3ec2NgE8hb{984zm$soYb{c{C@isy5d8IQRqOgF0{> zUGJIh?rK0@qss*b$NrkinS3?8^KS7A$qPkjY(cQ-Ewc7tgdv|^`yo|CcG6HSkI{+J zI?3bR`)Z*e0T`5mA^fj3phcKEbeKRz783NE^jv%FdlH8S-)HwjJsMfh3dbmb#J4tG z-)0ImuCM~v9F8wKd8U6GDl47bhExIF{a)K=koegYxVU-9dSp-(dtnb7=2&l)-^^lO zcVAK*eITZ3Y$EcG1K4yO(k3e0f73<7n3oR^CKDXNK!6 zlc~neA5ky54x+k#`$nX4nl@s}_|b*us`A@#_nmRMiXm%If!+pyQdK26vGK&Q0Y!Y& zUHGkZ6Zmt1;S*%;2I?jX)PDP*hB^780olFyY`f?C*yzvl^ImMNb9x@n?&&w-mpwzf zxYXodka@GiZj6-Egpk=lWGpN3o}aFMlg0d9vTQWk({m5?o;M!AR^Hzrd>DLY=n2B6 zi@>wfuJUY_$=*?BPF5~z2~&hzoXEkJCo4prTVyAWNzu!NhF+BFJ{)IXt|#1puAHYU z>Uv9cvbync+gpG2vq{9cNHB);>rKl+uh|v9l{gC3yV!e0tgIdH?klnnu@%?BDchDR ze6H(B`7J0wDoiQ?%)~6P9#i|!Nc=XwGx;}Mi!Pt^v|da|<7<2&m3XJk>aBA#?xGLT ziin32P^Q+%X9_SAL{DB}TezUN%=fXaRY{D}1h9vSp5Cyyl zDQTBQPlD<$7<|bSb0yMkhfsOsP$hy!J?(Glue|wDwv%7IS_9M^{O*4 zyr#Bt$NrW_FOdYo;NqnE=^4*1&;t^!Ec-H1Jlq1S+2KFivI1A=5)$%O20_KbS(Z2o z9N<&%4Uv5DOLM4F6!c*OO*A)w*s8WVG*30y8g?H2{x&g|N5c@a}#};leoek_(fTma`7H zL00*sL@i-t_>7hR(m6$z+i-bq*OdY7UM4FiX-Dzfa!3lrn5DreYzEWNy6;_i8oVD1 zb4wnviLH7J-+rPxX=43%lSVN|`HZu)I5$`@zEmiHT_Yol!NsAm+{h)Vacm zJ!-=wdglx+&nRy#%Zf&Tikg6R<;{be2iyUv*PpyUEZ|_WH4EY9nW|j_Q#libf-korkjo2(ap}Z;CMgOU%@xFt#xT zjhUf*7S2XtX&Nlvm_h0*&?$MTwKI$OOApL)x(fLU_jwXaWY8NozU-AVh^oh#`12?; zox1!rvOa!%!oSeZjS(jVCf+iuO8$zkP-M@e0_1Z!=1g2|T*6>g{>BfCed(OsB= zTAyfZr7z%58}ErhJwc8!!asaJOXzPe0i0h*_!(&TEJ4}>un5bu3Lipd+m(qUhCp@x zfs8f~U7}+#{__C{y(D`7qJlZ;k_Q6+%;@!g|5Q-sj49)IIfVfhD(Syq;UwiHSbgQkMto60m?2eb)%3RCWI)Fbztf2J=8 zC6sHsW2xE`&h`C=++k1W0WUU^d;`_>FNB4+aPOCdrq_W%+yr-}4>W*kzC+%6)95Q} zduElg$L1us)D5_rYVJZ!CDnHSRid%{Z00cqM2lb-l)@1>Y|)5$ zUdJb}q5ZY{%1dw?0_V&^+jdzwAf{ADZpx$&h1Q@U6_ie(o9#canULt}EcsT4UwF$Q z@%uHKo5GN@jr9^d-eVauwoB3@8Dc}6ARq>S<_%9yV{GE>@MbXD{xw_u=%2IGpv5Y# z1LVY~Tr{4Ar1wMHI^8{3U;@e$9AITI(eBDVcu7#oF!2vQOj);3*p@(kzP&$qTI>5H=H)A3g^ku80KymXaXH}Iu zKx;ZN@Vq4ZGZ-r5a~u86J50bAX@@Hm+P^2h^gr5`YUtT8IX@9a##AIAL_~zEP-wLT zQOKi`k`yuHk=jWcO7DE$5HHTlt)?Kwkyqm8iL!hBeD25lCenh%0BO=B`8;%WLKYYi z21-0aB!L1FugoN0 zsr0hcgnyO|y|+EK>l>cWKuq{*Jo*Q`T6}k<*KyT%=-hIs;NzAK6VqqybZmb=xwd2F zC#(*H%f1+j4k0#lV=vkEGEbB!oY;*LaXB;Waxq!@!FLdPGwD7!Vd2&Y?$?x8+ILrC zneT}PEOUD*N6|ZUZS+=~;}kD*CcoXo{-j%7MjwOJm6SFMxq=%a%PM6zJxPZ;MF=rd z6iIiFnEAiNiD*ZSljR4mxWKfixKp0^`A2y^+`+DVD;TB|9~lwhp+gFvoSI)^d{Exv zPDS`Cxv((sQ?p3NxM^m<(TYBgv@cE=Ox_9 z*GCuEYh!2bKe|Uq*c^FhVe}eZdt~8|UeP>qONq&u<@G0i52R;@;ku<8A-Us;BdGRQ zq~Lv_jAK(8#1gl9xEx+dY2_8zh^uR$BJl;t7(S zMvJq#lhv;8>|HBCT`mgmkQGEeWnDcmHC9q;C|x#oSt;)-j+dcLsGrhcVftNKz|~Ja zX0tY>!NkP#S%};sF7!aaam!VVxy_vk^OjxC0Z9h5{LF}!*f(ZQ^xcCYlY&!$N=jD- z&R9l5-+dnPFkQW==}t%U-D4X!hDpYtsL`amRETK5c!?!QNVxY#g_J}FGkO%Zuf5vE z#AGt;OQ5cAHT&Y{x5$WVWwS%66bS;8di0)XJ9MJvU%rUyMyS_&?BI7PNS`q=Eo!=% z$BPc9b4*Y6bX}8L|G*cZ_v7`f(@3T!y~n8Z zQkaROu&)&l^qxw-@-z;obNm%Oss0lgYIol+qN`A1jU(rT!Yz!AQOXp7Fip6p+|Lf&~FbF?3meS@)HVuTpFp?a~cHa zfEC;wzC}ycoz|{kv#qTMy3ZtIB2*HqY0WN1<6q;q`6D>JU?JaYTy)z_D>PeG;rOO{ zN>%qomy8(ccWkJPK(_bLwl5nHd+vt;H#{H&OY+TNJ%35Pm_c%E~;?pHQP%+ z+MwI)s zyQmhsSMK35t4CpR$Ef#RdX+BnN^pL&wJyq(U7|+(fOczy#STTPmS#I0-PjdLzWtcV zt;`2ceH$6rN|r`BdKg$*0<^Rf@B)(7FnY<$J?y|Zs-|L(lcnf(EjNLpdhBG}5Mzfd z(h{acP7sN{{#r<$QwZM%OHsM^{Sh2pvvpbcWS(>XDP*xY!eIaXJhJ@7htq*eh(g@9vSF$0S_Z??&gvL#kF1BEleVJAoNj(0DA2gaj@RX>k z1l^+>vgirWmS!V_+l>QpV+nfbWgdPRKqt4cQ|I_Vd%ga~2l?`XW|l+Vap z&GCOm3%+9D;0qhu4zgBc@Ce)zcGkg7vxu>M< zJ8H9`ap-N6Q|}A9Z>-Huvej+0KeBv5Hb6|eGy242PvWHiJHHDH$p%aPnvbuLd9Kcs zH4EB-XkkRA*k`b^^8ivgyc}WTy<&__Ps-$jaNJ|Xm@&VKNR>Rdb-bEpl(?eMijvP6 zca+l0yihNmut`{{ z*-@M$at~iH4Ovnao_v)_zV|`jA;^EII>Z zj|QaNY$zo2=>82P^TD}&aUBMe>YQ`XqN0C10dwt-p9kW$-1WSU%Ip42!x8XZv^C0X z_dC;{5Yo|B_PD>g>X$_d{EBJO0lgP?rR4I#_7t07SoJ7*)Iv>M3YeFPFa-rxWfg6^ zSvdd7oK{x5Guf-;TZ4hRPt8{J^M>S%3HRdLS!y>e5XeF(dWLyBqnS1jjnvF6$>5d zn-0YM7FIb~2KaNTwbzKffizhoV5MY{|A`(+lQ+>r(W7?7E2WYyEVfGu77yCmY*HV8e|0{-21 z_f1G5GHCZkvepeEzKv^u=&}3~=l@!YAV|<&$BLgc%A>oOSDw?`mYEpkDRxXCi_ z0}~sXbtcQzMYIWs8}7Wf*IdA)?@e7qfo9564m>Ga)kq4bp0xb;Le50|$OMR**7+M) z`thiV=Pkd<8MG`VUq$fcF%V-04Wx`dvqYAkT5h7ZYe<^s_-iHmz90^%s0TefR&ZxD zdX4&3-h1UfOGr=jLKV0{j-lvENXae1c-abyv&u9>$P~CZD25X;OSPpA4N@@iXq9_g z2G2ASecgpK^xEyMEc)796J5uVCwmj4(7yC+wrvVzrPygoXc z*(et~aBk^YzCXE{Vu%7A%%aNQC0B^?VA-O|3~r(I{L>47^cyiomq7LgSpHvwXl>Vx zm$^w%3bRZpA`~Wdv_~Ysyca3K&Ij>QQsBHqs+){itbGAv-eoL9tw7XnFWumREj=w` z!Hs$ssuFW!Tm#(!nArV~OL6`uc>K#GpnZ=fnKy!=3=M-b{EqZ1u%iX94^s#PBF<1; zVwko6_};DOe#-6IBVFKl{uMa>V-GYVs_vM4P%a-O)K18V=Ijs3#yY{#M@!Nl0G_9- zTy`X)FGA5Ya^vl_VifLN&sN&*SM)as67JRfu>}ap5DeoGW70$4^PSXX%b9;@(w?MC z7ojjfGvLO{b{}y<8+zvQ&fXB9{dDV|*)~cy9Y*0b&O_t= z_}vHKAl;<{hf@NtAhSZ($Ge~v`)d*?Tw!oa(Y8ROn{ZZXkFO_j5l+ZK|c=aUGE{6al-<2SZIyh~Vy%7a1TAFU(5kodYfLC1 zI1v3mP`0a&ix`stY&-jhO9n6+_EU)A^T#dW?R$t}h~x;g+?Gy;xMg(uIGZi${KR{O zsaoUwh{;Fcw51X}l7%`Sau4sW@Pig-a znR%x?O@1@-8+^_WAG^G-^e*9EvwLnUXmfd{ z6OX2rKtvV@eH$_7MuUj_E)1`3k_8vU2EA{O;A=ZA7wY2`9XGg-GoRo7R=Rg|vTFq2 zPrYK5d#oPea6Wjb&HLWl)uXk1cw)#Ed*!kg$QJRNh{=fl>?!OkEJi(#T0jz<=y#Mu zc2jOwG^`4Au@CF|Jzw7(P|ZkT%t++w9X*d<178a6f8bA;2|~$Y(orzO60Mm37x5}W z*F8B?7*2c?=RnXib^xfu-|Dd~K7KeZP7aXUw0B>=-k)H1@0z+CdtoF~P9Xt!@rahB zi`kL>e)a7xcdA!QIUqw@)80)<*qlD@r^(8)LB&DhMdY5FbTT3t$MV5gMs{;wil|hn z#H;QP?C@o{HWRx0P^q13(miBnAmr{Cd?*cLmdgQg3{R}z9b+%OL7D$4#l^OFSuOxp zubz(J2omZk!_If!&kN+unn|kL>L5`E5KYM&#fOOB_CR~#C4a&9nfc&r$hUI_6Lt{= zMWOC?zUtMMske1GD{f!qWV6^;C-P`2Sba+SA1tb3sygn)%}-jdMpZ?i16&sw3QDX? zERp-+b@Azw9Bm}#@)u)v$l1s?FGqgu*%DOd|dKJaDp7_Fx5Qe@gz8gRK zzWw-xd5ha9qcPu5q%SaN+k);;T>O@I@qJ?vu&`MNmXtKcwDWn6MRBJgJE`nJexU7( z>BOrN&=ds3S-@N0KA>%9-k@{A;ztns5=x&-H-5)46Zw<*NLNctMb?D zUNnO&agU;)=|?;c6p^QN$w4f5LU|$?OZ6`p7R`-I0$+OA<`S^yGbA$PbKf50y*`qR zu=-xPq{aV{rB33)=~nJDtBH~u^Q>P%_jHzF7L^Cgw`uEnhLW_ZUb|E_@w7JT`b z1xCP6RpyfgcRFlgn`iDT%x0v#&CbL`ys z&l%mmc7YWF_{7Hl#KV^cIt)xqOxt42$ZXug4vm#o%e5WImQSKS%g8Cbl=Zin=Z29C z(O#39Z}EQ`S4my1?09OgYJ_#rmK5i_Sim*k*adT@;`Vx^m*3$A&b{H*XXyifq&p5l zCdYC{7*`f{_&CS|9es@$3AbRlWjI6DPK1Pn$JucLxnH+EQ8iSnGCJ!Q`9r^Tq}WY= zbzd67qln^6z1R)1CR%Nt;^?dDX;W<>dG=9&HM{A|{#}n&iX>t=daI>FKxba`y@SU( z?Y|Q0+p^Z?KO7F3r*8>=9wyx{6QIDDM6A1PQJW`*Wv+08=aVNTw+!>O{F|?>M=)y% zv{k(9Odg^4VdpRh#3onJXdta-&#()TITRbnWWFxQMlh)*w7>~&P_7X7lzd+r zx0KvJ!FqD{0~5I|#gk)G5^O1EyQ$FAW4%P~=X#B?QFleXMEN!$GFMHLBK@Pmt{)U{ zNJ=1E&$-f=iJ0K|B2OOHWOVvsrr_RvL)3Twu4Eu<%NoS80j{Ru$JRp6*S|mz1n)h! zVgdI3OR=3Q?EAShlZHKxYKmcuVlMUXk@;z~b=)22mqK-CnOssg!MnROUu_8!A;_O= zX|u2_&R0^;f0*92ZBTDdXQ?M~Dd$!JFnwN;fqv-XAviXVY}c^I@4~@F=gPa)wq^rH z=|}cvymGJHRD>mDeo{_wm2~J~ih;Sj7QSseiTUGzh#4{PSb^WG=%-KXC|5Hf^tjf6 z+$i8uZVM`DZSJNZJD=HxlyRfb%`mTOY3%b}qKkqiG%{J_#F6<+TQMC#eV)XF7|Nhx zi|@+@UvGsT32s||uz@g^oQL`YIXaLwh1lX|^MnLptqS`;xDbR)nq}B+5G+QYJV<&{ z9axHr_vJvmsmV?72mAJ7fDo08hkvT*l6qDh(yTWQTP{4olJP?!rSk;@*j2UGa$?@h zC^*_7TzLi9M6GaZ6e7vAN#P^|>ZQbDRNV zXn48UtKUZ$+wFOki*yhQ`SHWgxh=slVHW%sI+eB39BuL7v-NiEk%!&h6|gw3d0h9T zM61)edSXwdH64j2RGgF|Xsprrp%wz)v{l&Y8dUN~X`sGUiFfM`Sim+LS5TpRCVAf$ z7;J|f!cY$Y*;|Oo$o}Yff1Xb#Qk8$hq?!)g8JN*;8JxZ4hoT>$Ee1GO;`T5fD$^pDngy{!8M z0KM7JsC#q9-`Ty&o{IFcGD6pxih=f1zj&(cb)wmG#+MD$i_(H51*8@g$5ugZ<#}}D zC_X5*osH(ob^#Rvp`)CN9z;W?+M~1+(+=@9EzTok_+;>?Z&mrDENQOKd*zbbT5Vc>JD)cIl{*l_de$j zQq$f!);_#6xCbrGgQ2+y%z-#r87tgPr2jU5#KjK}?-vqdeyYP77sM7B3^|K0k}qkO z^4uz?ZAUHUS2Q1F5X0|#V*17gV67?6cGZ=R_=z_Au*a({-SwLm1lEzo;=Aq^o2!%^ zW>^`1C^jcDDXdD={DW5ZkzG>shphUKrQzx2Q-NNezZLhtGmD?5>y*KGBL&llRkQlp z%kipA4Y&k*+q%NKn`pb&@?=1o7Jq4VOuKC}PJ$s!diDDlZLMgjqLLEJ=Kqvj9cL}W8!D95Q-NK^F8Wf6}IZhTP3$%%jSQFl*xnnjwIInQu%4&v_&n(j5y+bN0L z_Z&ThRu+^3nff@-efsjxv(#GCS*SzB4agwB_*{c=<(NjfN?%y`Z4nb>x#i4%`$fz- z)!K`foixo3=AyAnM+ks-`QKTf_C?fNYgZ;iMC5?zy<>z^hciHa^3>M6{q0$C6ZNS4 zXmsoX;3?!mniarIt5;e!Kd;)^fD(}i;=-4A0Wu*k4uzM>r2#f@njAkp5>#<-=4tQG zg?fE=r+r{28WjWQphj4JDF2y^idg4-Axakh>T@ITW|9lS!v3WGVb4@MPI%_j zB%P4I2Z}{|gs|p6nE)a$7nwkKb|(2>{;(d$+4F)hUC$9Ng_^PrC2rm{=ca?L#>UxCFe3T3e>LW6Gr&@5ySlA5N0tz+!c5iaGw;ljKLLLP}!z?SwV`C~#ojXmfkcE5u*z2{QvlqKHblCUL*Cm}a#(bJe*QQ2i@>V+wVRVAeqeW58Z4B0!tEcmq=)U)bUwLkr4tnmO}A`SqSG3rj!P ztBmJ!x-t-o3Y&;TGz63`oaLZEOw_?c`OmOkQU z#h+ixLHRLMtG5I+tSiFXF&GP&c`XLp}y+_v*d;N zr|MOpMX*D>rr6py0morOiVLht2rv5X$=$NJ?QI%Vk=i)S3w~u#V2ndaNeR#Ln(Ack zVcCY@{$*LzkG3Onpqz1dqHG*ZX)LGDfQTa`Pf<$yW5_kb6+KWKhl980F^W(a9K6_Z z8}KK~VgTI{hIc5&JziM!q2Q-ZkeI?-Zc@sUb>wtJgHwGa>u4~%VBAGr@T}4Y^3z&j z=&JC9<(#NXO>6eD@yW?l*>?B?V_V4>m!pM2AV-K}_=LTkD)?05to~46nmh+DWNbU| zH^Suv!2@te?X-KU@h|vZ-U_JS%zPh z7*BUxgXJ#Z!j-09kJFuLh7YG@jm;3ev66gsK8du3KyDUxhOWv}hA0%hbnoV@@c0aE zM2va2?LmS}yI;0-p z0{BbCw(1wUWiuZ0Bl#|%RkYt>pI3l!thyS+Z=yd!qN784qk zcf+S(lLXz6)(Y*X?az3`HNJ2ca=G&gursDKL$pGfwgeU?2JuN|B^1k9j7>}?qRVK2 zWCt7&JE|S*gXb(<;bha>BIP>SfMD;0^rMxuZQ9e4C^Gf1ZuzOm^oq0`yYCW*%jqvt zHJ0qGPd;}KlavO}8Q}`uZT&$rWvy@@_`>-2Q?*)0TpT~tNuYf!HHk5h)}mCL3PP0s zR%;*6DUDDUh$Ngch<9dD0TVbaY&8Q1nsVBu&3yEA*r!WaSFh)9rHSp+GFyV>S>*5a zVD+&g+MRa*J+_bZ!J@o(Z@d8sR6OJkVKb=Jqai@7Bisw{TzBF!O2U-TgoWhkNPlSjC!lZ@pu3mdD;Df0BF||cncj@zJUXK_475wkZ zo40}eKF7_Wsdx>?jbVSAj3Bvn2eX)}ui*#6%n<1tgS^R*ItI6c?x0wV(#PSzPz;2!?o~i?vBhW4#IyI^3{45 zuKi$b?@NqKF0iGB!ab#lJcV^hRH8``s+x{k9Or!)te67}0&cemLTVGCc-?mJ{9WvM z_TKk;7$uF-$D4lG$#?;7vLVmkfZwGLh%qQTQ6E2&QVJF%WMWfT*AmHXIuNg1#Nq4t3eg6^R#R0CCb_ zV6hSlM!H%6mjSN2ygqWLMKQD0*g^t-~I$w(3VhlIp8yHMQiJe2Wf|#IULwg zykjjL)bmB;S%=pDATC9QR(1$i_28@*R(W66l{R@RvEQC0UP~2%u!C5BSuwwmumM6gGAM z#9^TDNJA?QcE>l8Ds|^uz9dOL2jBSO!)f9TzKrmsZLKop( z|GAqoef4;E{hWajh5dJ9Uey)?5l5O{3*VhqmnE1-z?E$URP&$ch2u~(5rpvw&*9g3 zX7S~4NG8HAG3ijN0Tr-{C{KyZOr!*Q6jt!tmLAV1pfd-*N9k3?xc-Y&&)oZT_o0Sco#ZRRy z))-GkcCZA}kfqE!nwc+hdeNEw^cL-*D0+n=t4Zsi4+FGz+|F+Fk zTNctd0?M9g&Fy%+bbCn^6~OipKTOAVxF2%3Lw|Xx6Mvfc2E5iyCE(pP;$=DG#3y&q z)&zA)Axc=UDc|a5c?5z+FI~{^aq5VAtZHd*v`Se!tHMSje*wXnMqmg5&IiC-q4OdH zi4d(5l%WZIEc*XBVY}KJC!qGP)#}9}X2%6a7S6}&%_r#`%fv;rciwm#+i~CuAI%)+ zPCRHVV1g(8%iBU>^KG0hp>k+L1CZ_r1R_wb$SAkh|Cg)XSVQf+KjYGt|BU+2WT>() ze5>g`YAaL<9H+Q}!lWKM2RCpUL~74eV8xi#*#rFZ))cStrTyeMuEr&CDNuc=F(x-R z1^cQ3Gy~Oc+&OF-A@N5V*K2mSii|t$vXe)l@BP6gnwoU>?21o_Ue=KV+J1vGo+gO+ z6f~qX;Q6`S?xVpB1sGs2o51H22NP1IYUm%C0YaG5?@>k%Eq=d_sXf`Y7!{3llTOKi3Euk+4&dSjT>7h*KFkUWJB74KG?bk(G z+=;{=QjP4q3vqW`)nwSRTs=3b&h6%2(wD{`dh@FP1NdK7r@d9fL$}fQiXKzeMbMEj zl7$*OC|tEUX0^DdjOQW!4&<{#carDI;){OFCRTixx^hE)Q&N_^*UC;TY2&WIF1Ki+_m82~=%hmTe8;Du~<0gNe>=Ei^@ zGy*W|Bmzbj00;~kxDoaoX!&CWRUFL6@Jh8nDGiX*Q7-QBW8FoG#a`05UbbQj{b z?=TNRpla_lQO_r7?~mtfsVO_ZRXq0-1uQU%Cg_8u*{EwCS4Bo=vj!a=^1IKXK6ALk z96o1vJuQhg0iV-(?i!?ikp+bRTiCoO9ufG1IK;rInC5h}vC?wjKh_uwp8|$w6X`d` zszrBfOF)>zN;{~oUpW*^Ib6kZr`o9riOX!A$zT6;oW!k8tj#S!17+25u7Wv)=|6!l zUrf@ey<}bYeznCS0CoK>s}w|K%?kkO6`p46k1{17)Dv`aTT`zuvYcc}-Uo_xG^%a_ z%bG!arbrvW%S*CLhK>c+4;3S@zjD3=9fHH$`eMWdiq1^eN?<9aHdBO6`}{B8Aw(`r z8WlpnpnuD`pW!;e!;U>N=0z69c*xsdq{7mHt_&0I1oTjX>(V+!U6w{+-5J+d&z=2$wOx5U)Zf?tFeH2S3X$w<*<~B0#jfnxBkL$jgv1QRlopK0PGu=svdg|C zlQm0rAyG76Ym;S|=YFQ&_qROH>v{fr`m4Czd+xdKd(OG%yzl*d0XymA<*hD7Ya-uJ z%)IXY8ffb<{F)gAEf4RUtccpN0OUiyk}|H+*>Lf`w;969OK56C8}16kO}L_7lzcoy zr^yC{o}FtTqEVi7Z)7g7(fuAGw%HZ^vKMT{woIX5Zy~^k{BB?Z%0Fs;YbQy{paP?C zTNsSD!IdeO1)NVc#kh*tNRBUusY-T6{^$?i`pMk6l^IfL-L6;n zMLFVv<@M4GVd6Un)*mLRAuj7BlxkI6b!QNJ9q2R}*dShao!>fDxL`p3VvAqEer`!_ ziiwm~h!FvoMdi>_RZ%tB%>AqZdzVuS1R0Zdu2}DQZ*_h3bz)7wdDL!A{9!#K`;{?c zF$_C~5CKzoa^!qs{2ULdn7xzuV?mFr#gmNy@EIxf9wQx5^6OIH-w?!iT2EKU9FB}% ziU?USd#_|M^^Nb!JDqK-*1<&{nZL2oGHhTTM|)P0K`kQk)-jBx?f$QzPoAjZT$o~YELJ1# z2JzB-Jr>h4@-EAuHMfe1AwP{LQHaVKmp;U`b1emY_+Sjc<6_2h$kHs)l;sjV?`u8NrkFB(@Hxa{Q6Nln=9K4y0+HH zmrw33yCeI`Gw`AV1?!BRX$Ku;Hv8_EfkI4^MBLE(paiEv>3dCv3i%(G5TQbjV5CT8 zGv!!-6gHKoMJF9;5{m%50Md<`-NHgtXA0&p3a4!4+WcRfr%j3A8^6(5V5h;m#3#!a z9mZ1}!G8L;AMxu0^OfjGz0y50^{=WyzG+Vt#1Nw_=Fg54OpRSmx2U^qdW>R8r{FTvOQ@xsV-w^zzp*vyLXqo0GDD_+oZXr z;jcTHH8iR#biO_2sw&@T~;`K*Ui$;dgj4K$a zWA_rxTz-d$@DYpdGXGAw;p3Ui@?$V(Iglvd*#wdX8w$?0j|svuAb3yD>q&eJ=dswm z<0Z@S-h(((D>vAXB0eKPLD-0@@!nL7eRYB0M&2WXSrhH(j9Q|+aQ?HLrsTcuFh_V} zN0ST{3Z*R*OrjcXKsXT}Ou%PtJiCQGZaNQS~->bqYdXCV`-adH#i??y|eN~Ywofd5E}354 zK_nPQU_HU`6I#az5+m(TiG7UpEdbz9N%T<>6Sdr9>tiYWtG})O!JQT|W~&tSHtrdg zFH)vF+xNiGQ}y3|U)gg;>=%ZtFS{>l6}R{PJM#Ioxm*YAfH0@wRdcu$?|oo9x!zk{ z52cG1aynt^t@1!Bl==rci*>j_uzcAm1w8n=X=Q5Vqu#UjW0I#BA02T0Gasj)C9ngj z47L%7c<%jhRYF~y)>)v^=Ve1Ao7$gh1to7Y7DhqcIRG%k4PnEvmRiQ;mSzPg#d=p? zu#D26M1$$R1K?vC(E^mAUJwsSXEH}*uvqM(K<#EQ<{90#j@7uakWPSy`n)F7`ySOx zA?v<}x1_$u&FU+@MVYYGE3sMjwUy`lfXaFLVIT0)C}mC-Wz9?y#n$d%PUZ;OW@U{% zy9wzcv=&lwCV#9?vh%9c(R)wj+Ujti>M5wYp;6NNUzQ%R<(| zPdWAT)rebtvwoHyPeq~KoR$&S`Ztn%Az$n%n5n)N1=tXpjA@y7-^qiFql-YE`M8TZ zmhtk*D3VWOWSGXy$nHCi#h8%aZ5_E)IMwALMFrih^fZ)Myeam~+Op}YIG^<0yTmx6 z+4ns`P^#uPMm>P-zS}1~J&>7>Hjcy3f=fMOlr_VR%a4*cQ6U|PZqB9;Bt8-+0CNF{ z!5}Y8=sX52r`tr%6uD9VeckN8IP-5tONq7I`;9y!1!%MngX)&x-hp3r-Vfi12! z@chx7e7#0j{k&bI!7|J_{CY-GIRcy zdYh0Cv!ubS++g>sGV3O5VD>_vpqJf&dSGG-8+~LMSDeZx@U7`Uu{VIL;s+pBgCD;Pe5>~PAA7RUd?&7*aLB^7fp2V}o z)fu|5Qn44~5~a~3!vYF|hoJ3dWoo4kdbA}{z|bbiNg|4&ED3K9-O!{_5AYH5vn*i( z6f%cx?)aI%&v?JJlNriZ^?p!W838k^tni_|9CoQR#xz0o2WWBGfD!#{R241p@c|rz zduMC+54J8^>U`F)4d{0J*h8iM=~Yjn5c|!LSf_ANRF~gM00?59%o9%%^L_DqseL~< zKwechQt~q5oJm`rSWal-@aD8L72cUYOVmU*F|`YGk&rFQV#WKU30?7mr= z#5v(DioG3Ew7Wb*`e3EQ9R~Q#C3xkDjQ1)O3GIPZ31_I%K*S3cqct90o?$d}=2jF# zATWD1~2oh%NK18POHYI1P z@q=igZuPB29KXZMV_Msqpf-_6hgzM=E}V(Z0w12j0)BN;t7Be@*|lFX!N7TNOOG2K z0YK5!ZGEjlr##7ejfz(|TsW}VE&EVGHAqhXiGYnCV=wCvOSB^B7PM*V8cQ?UZSq+$ zX%V?rjo{#yo4X-u0ir!{p`(XWbtMS!^eKMJ*{Td$SID`VK@fg>DN4<#>gf!Bw)Z^= zJn;Nh()Ff89*2WNndYJf-=0mbsuBJhm_?7>4A z{*si!WQ%iEZS5U8f&!z?!022->|ruxNFa#LuINwawBCp&2={{f6>Mzo^D>d!DWx)t zThk!^(e_lhCJq~vc+vQyqsny3M)!`=sVIkxg*zcupArORFH#L)22-~;+U(+hj&9qO zlB(TsHl`I`h~!DuFZdz2%Y5Azr3*&EyUyYgsyn-{1vgSuRTo8TPTK;WJ-lnMq{4R$ z;$hSd(|qUaSZ5by6q#Qaar41~M-a86Q?b(lBP&3R zPW*a@3=|(9YP}{T-5I$DXM2;tohxkn=YM%$GN}(lLRrdY(MhmrQmaDHx@nE|x?M-D zr-_#`gAf-`zEw8c?HUZVI(F~n3fgWY9jT~S{}ROR?g}J4v!}4c2Fy}J}dsW5~S;NYtO zRJLv{3n`|Ke%)CM-UN(uvxAeS>2=VjB&avLI?X$DIbRXKOea9*2CUVOf|V)F%~G>< z3gBiQfJpG>ma?4+0=}?uKloX(HJC`bmwr!W7ojQ216}-&9Uf=H6NxN!L#O|j{Q8cTLdT_4(4@ruZlCM?|T$GSaOZAaPV3@^GTAoF@226@lSr zjna2Q94fu`0DWX8g1~Wd>-2AJt2;7bB#nA)E=dH@+kJ*>b;@z;#_>oj77m4be<&a9 z=#vKkK)`)rH3PXyuW|od7U)t{A2@ctWKp4gV#~`-*5a8CKinvJbMfnh|IVSqWW~*f z(I9r9;56WsfyeQ?53BoaNgk)NQB+Z%PDKao8bQ9_IEl6=yKpu-KV6-k3w+=^qZd3Q zrqGxVtHwDe^366(x7A>J5e_a`%`w1RagN{OT$~D9P%q-l>WCRw^ps1MfUrC`H|M;? zI+Kd}K3X0k;4;Fqx?pmAWR8dZy2l88aqtjojIwUNmvn;WKyBGU4S(CV;*S-_{!Uy( zI*9(XaRs6AkV}>Qb($qOVRqGf!}Rw16CcQ?whl}yhLPkwgf60jdK290Q^@(H2j5D< zf;h|=4XgwTj(pfwDA~f)R%s?Lj1jW=Jc{ZM1LnnFn*Nunwr{MC@vhFwxunT(0}ET6 z0nTnmQS%(&iPO*!3CE(!HKMcT^fq36=3&$ zr;mFEZWG>3hnI6LAJEtpd(tIiKaU!7@YaFzn4}L~e8i_>4!iw>4|m?e2CFlEOty18 ziV);zU3;u!3EY*P8AV7N5kblwU0Q2-b6r4@Lw#6IX5NEY)avXHddu0o{X>wsPK} z(w18je0U!L2QBd&U!O+4`2>Q?l~Zut);=uflop$8J+Ev%-8)wQl?`kK#TL^im2m5X zizY7e?cRyXW*I$*I<83f{SB|L+T@nOKVnqum*65nZ*%y z6PY<+;DI>EKXnTxItEnC{YPGcaK392+yNB=6m$of&ZFNbK|l|N=V%>sMN$v{?#HylL@n#2N!yhWQsC**x1Cjas<6O zUqxN(YuSZi;^H~X-9e&}?YnE~b0x{FotiR_V@kQDo<~7x?YREH5!X8-BSV?wgAu`wHeq5aG%YtDzk6=UpO6ALy@jRWBLu81QvwRelF zyQ*Vjl!`N(i1eB>u~@7+$vRF6+@1ZC8{&2FFcd(jzyT9I4Mh$Iu3ERa2z(vINQ<|k z8s1d$z7IHH$D%^AW8DH4K~|f`^%0S?#WBCFf9+_q90soH>ApnKqG|*_@{f+r(***~ zD`Sot@|G?I)o(fP0)AL_#pN@g+1G=ByA{2EWc(M%``x+UT#YusI3N%6C}buukoPZi z+7-d+V^D@Axf1qw)QGKZD)DWG?ETe!gkm#KAYaem_Worpa>S%b2;`PNq3q>naI z32EU8ledIxmp1f@9t0kO(6`t-p&5eLBUe(D>zcKErM9P{ft**2hubJ{;| zXbC@DEzHVia(yz3DcwGl4TAVD3L?(^A&3M=4c-LW>SM9co9tqpRwkj2w!^1_g z+pg;kRta+a7kghd%alVyF$M2{)dvEdgDs8a6e^y)xSm<=hc%v{J)<4SNpsnI^2Ct{M?!=L9=M( z_Edxbmb~oxi;F|fASNs)tn44( zULVA7bGYySl1tS(GM8>h4>cdL#F+eqOfQnH%l46F-=4bOyzoPbU{xq$H8mLu!srXQ z*-wKJJzN6%LE2Bl$QEK|)KI@N^%1CIqVuNw?b5)dYXQZZsYKh)$*6`CusY3ti|)1M z?;mwn!u63|P6BmS6{FSVWGEt!)X0!KCU6cFs~|uwEfN-{8c}QJc&<) zAkI(Xnh+#er1i}3r|0`Jm1FwTB+vD}h(w2BheA1%#iR} z2cV4Xl9V?SBk!L7oSVR1q1}&B3M^7R03k0N0;A(LpNI@T5!r~red5m@fgq&FL072% zezYiVEUL&%E-iraLlam~oYLZzcofl8UfvAG=%z5x&%2iIMAxn^{7!yCi_)K_Y@n(4 z5YD15;ob@S(EiI$(wYY$C^QlvbSke=BV`mPeaz(ZG;WB_0Emb#22ey+FL{eD6GdV_ zB*fk@@p?263qjdZ0CfF?oev2=J|t|n;m@h#hTu7&i-o{{C^?*JSR5>xa{E=_jtB&; zHo{VS_of&rYi4yH(?9Q~UqS_;AB(|Fk4|NxLey-?=JGXpn@1t&yETBrW<_Y3msOds zaLRa=VrniO6@>f%OU|&=^-t95-6`D^0__ij_U3wy3O3bpHX2EGVYe@PCpyqT(0d@E z>A5`@{H6<@G&}!1L(dDgF33}G`>}pk|Mv>`NdrBAH!!OB89@Y;5a5P0>JuxENr+Dw z@P;5Ky^z&|knaFc;^xl0oQYTj`OXg|=ns-+_?Pgn?Th3fr~sX0_vEJ$_hVt6Nz+jJRhBSpfpnrHPbhX z#5E5}UZC`0Y$|Y3^e=txFNUIj881cU^5|Rx%K<_CdPm*G%veRivaZ?Uq@@}ThGqg3 zKu|_Ogmg-XkWH{m?MyW2KA$pZKOUftxlbg`(J(d5pahdC49^m&qWXKub&wJNv&D65 z0B-!JZ=>_Kgf~h=lQmPA9ws{=G<7JV6q}h?t{7JxGs-(=e6(jED!cGc*F{SRe7ikf z>4pf$EwNuM1F;l%0TBuRUBq_}C?YmI|4$LU|BUMWpCUfCQumu{zdvvSObV^MGa-j- z(n@=y4OD&;-W}kF`T?;3pa08}{of1v|MFX+++28*dbWAtFf5hcIb+@8Gft8J1s+fZ A3;+NC diff --git a/index.rst b/index.rst index 6b169910..ccc7ce75 100644 --- a/index.rst +++ b/index.rst @@ -18,7 +18,7 @@ Source code for the OPEA Project is maintained in the
  • - +

    What is OPEA

    @@ -40,7 +40,7 @@ Source code for the OPEA Project is maintained in the

    Select from several turnkey enterprise solutions that can be customized for your needs.

  • - +

    Deploy AI Solutions

    @@ -69,11 +69,12 @@ Source code for the OPEA Project is maintained in the :hidden: Documentation Home - introduction + introduction/index getting-started/index examples/index - microservices - deploy + microservices/index + deploy/index + eval/index community/index release_notes/index diff --git a/introduction.rst b/introduction/index.rst similarity index 96% rename from introduction.rst rename to introduction/index.rst index 35efaab3..1eb0c84d 100644 --- a/introduction.rst +++ b/introduction/index.rst @@ -18,4 +18,4 @@ business systems and manage its deployments. .. toctree:: :maxdepth: 1 - framework/framework + ../framework/framework diff --git a/microservices.rst b/microservices/index.rst similarity index 66% rename from microservices.rst rename to microservices/index.rst index a089001c..b1969f4d 100644 --- a/microservices.rst +++ b/microservices/index.rst @@ -9,7 +9,22 @@ the microservices are containerized, allowing cloud native deployment. Checkout how the microservices are used in `GenAIExamples`_. As we're building this documentation site, for now, read more about these -microservice components in the `GenAIComps GitHub repository`_. +microservice components found in the `GenAIComps GitHub repository`_. .. _GenAIExamples: https://github.com/opea-project/GenAIExamples/blob/main/README.md .. _GenAIComps Github repository: https://github.com/opea-project/GenAIComps/blob/main/README.md + + +.. toctree:: + :maxdepth: 1 + :glob: + + /GenAIComps/README + /GenAIComps/* + /GenAIComps/*/* + /GenAIComps/*/*/* + /GenAIComps/*/*/*/* + /GenAIComps/*/*/*/*/* + /GenAIComps/*/*/*/*/*/* + /GenAIComps/*/*/*/*/*/*/* + diff --git a/scripts/fix-github-md-refs.sh b/scripts/fix-github-md-refs.sh index af4a3412..54cb59aa 100755 --- a/scripts/fix-github-md-refs.sh +++ b/scripts/fix-github-md-refs.sh @@ -20,6 +20,9 @@ sed -i 's/https:\/\/github.com\/opea-project\/\([^\/]*\)\/\(blob\|tree\)\/main\/ sed -i 's/(\/docs\//(\//g' $files -# fix tagging on mermaid diagrams, sigh. +# links to a folder should instead be to the folder's README.md +# sed -i 's/\(\/[a-zA-z]*\))/\1\/README.md)/g' $files + +# fix tagging on code blocks, sigh. sed -i 's/^```mermaid/```{mermaid}/' `grep -ril --include="*.md" '\`\`\`mermaid'` diff --git a/sphinx/_static/images/BrokenBlocks.png b/sphinx/_static/images/BrokenBlocks.png index 96b8f5637ce989347eddb3b90aac15a817f9b8c5..1c9104fdaa1b5ebd8109025304d40efb7de86a22 100755 GIT binary patch literal 18724 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 A3;+NC diff --git a/sphinx/extensions/link_roles.py b/sphinx/extensions/link_roles.py new file mode 100644 index 00000000..cd03b0d2 --- /dev/null +++ b/sphinx/extensions/link_roles.py @@ -0,0 +1,64 @@ +# Copyright (c) 2019-2024 Intel Corporation. +# +# SPDX-License-Identifier: Apache-2.0 + +# based on http://protips.readthedocs.io/link-roles.html + +from __future__ import print_function +from __future__ import unicode_literals +import re +import os +import os.path +from os import path +import subprocess +from docutils import nodes + + +def run_cmd_get_output(cmd): + try: + with open(os.devnull, 'w') as devnull: + output = subprocess.check_output(cmd, stderr=devnull, shell=True).strip() + except subprocess.CalledProcessError as e: + output = e.output.decode('ascii') + + return output + +def get_github_rev(): + tag = run_cmd_get_output('git describe --tags --exact-match') + if tag: + return tag.decode("utf-8") + else: + return 'main' + + +def setup(app): + rev = get_github_rev() + + baseurl = 'https://github.com/opea-project/' + repos = ["GenAIComps", "GenAIEval", "GenAIExamples", "GenAIInfra", "Governance", "docs"] + + for r in repos: + app.add_role('{}_file'.format(r), autolink('{}{}/blob/{}/%s'.format(baseurl, r, rev))) + app.add_role('{}_raw'.format(r), autolink('{}{}/raw/{}/%s'.format(baseurl, r, rev))) + + # The role just creates new nodes based on information in the + # arguments; its behavior doesn't depend on any other documents. + return { + 'parallel_read_safe': True, + 'parallel_write_safe': True, + } + + +def autolink(pattern): + def role(name, rawtext, text, lineno, inliner, options={}, content=[]): + m = re.search(r'(.*)\s*<(.*)>', text) + if m: + link_text = m.group(1) + link = m.group(2) + else: + link_text = text + link = text + url = pattern % (link,) + node = nodes.reference(rawtext, link_text, refuri=url, **options) + return [node], [] + return role diff --git a/sphinx/substitutions.txt b/sphinx/substitutions.txt new file mode 100644 index 00000000..d247d2d2 --- /dev/null +++ b/sphinx/substitutions.txt @@ -0,0 +1,23 @@ +.. |br| raw:: html .. force a line break in HTML output (blank lines needed here) + +
    + +.. These are replacement strings for non-ASCII characters used within the project + using the same name as the html entity names (e.g., ©) for that character + +.. |copy| unicode:: U+000A9 .. COPYRIGHT SIGN + :ltrim: +.. |trade| unicode:: U+02122 .. TRADEMARK SIGN + :ltrim: +.. |reg| unicode:: U+000AE .. REGISTERED TRADEMARK SIGN + :ltrim: +.. |deg| unicode:: U+000B0 .. DEGREE SIGN + :ltrim: +.. |plusminus| unicode:: U+000B1 .. PLUS-MINUS SIGN + :rtrim: +.. |micro| unicode:: U+000B5 .. MICRO SIGN + :rtrim: +.. |check| unicode:: U+02714 .. HEAVY CHECK MARK + :rtrim: +.. |oplus| unicode:: U+02295 .. CIRCLED PLUS SIGN +.. |rarr| unicode:: U+02192 .. RIGHTWARDS ARROW