From a55572b18e0c000a54bc5b45e051af0ad5ccf0ae Mon Sep 17 00:00:00 2001 From: Irwan Fathurrahman Date: Fri, 7 Jun 2024 13:18:33 +0700 Subject: [PATCH] Add documentation --- .../BuildMKDocsAndPublishToGithubPages.yml | 38 + .github/workflows/tests.yaml | 1 + LICENSE | 661 ++++++++++++++++++ Makefile | 3 +- README.md | 121 +++- deployment/.template.env | 1 + .../docker-compose.override.template.yml | 1 + .../cloud_native_gis/utils/layer.py | 5 +- docs/.envrc | 2 + docs/.gitignore | 15 + docs/LICENSE | 661 ++++++++++++++++++ docs/README.md | 30 + docs/assets/kartoza-icon.png | Bin 0 -> 76397 bytes docs/build-docs-html.sh | 10 + docs/build-docs-pdf.sh | 10 + docs/clean.sh | 6 + docs/create-mkdocs-html-config.sh | 14 + docs/create-mkdocs-pdf-config.sh | 17 + docs/create-uuid.py | 5 + docs/css/extra.css | 0 docs/default.nix | 61 ++ docs/js/tablesort.js | 6 + docs/mkdocs-base.yml | 42 ++ docs/mkdocs-html.yml | 109 +++ docs/mkdocs-pdf.yml | 56 ++ docs/python_manual_hook.py | 45 ++ docs/requirements.txt | 21 + docs/run-server.sh | 4 + docs/src/developer/index.md | 18 + docs/src/developer/manual/README.txt | 16 + .../manual/img/naming-convention.README | 7 + docs/src/index.md | 60 ++ docs/src/quick_installation.md | 103 +++ docs/templates/cover.html | 8 + docs/templates/footer.svg | 185 +++++ docs/templates/graphics.scss.templ | 7 + docs/templates/header.svg | 173 +++++ docs/templates/styles.scss | 544 ++++++++++++++ docs/templates/variables.scss | 33 + docs/uuid_redirects_hook.py | 30 + 40 files changed, 3126 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/BuildMKDocsAndPublishToGithubPages.yml create mode 100644 LICENSE create mode 100644 docs/.envrc create mode 100644 docs/.gitignore create mode 100644 docs/LICENSE create mode 100644 docs/README.md create mode 100644 docs/assets/kartoza-icon.png create mode 100755 docs/build-docs-html.sh create mode 100755 docs/build-docs-pdf.sh create mode 100755 docs/clean.sh create mode 100755 docs/create-mkdocs-html-config.sh create mode 100755 docs/create-mkdocs-pdf-config.sh create mode 100755 docs/create-uuid.py create mode 100644 docs/css/extra.css create mode 100644 docs/default.nix create mode 100644 docs/js/tablesort.js create mode 100644 docs/mkdocs-base.yml create mode 100644 docs/mkdocs-html.yml create mode 100644 docs/mkdocs-pdf.yml create mode 100755 docs/python_manual_hook.py create mode 100644 docs/requirements.txt create mode 100755 docs/run-server.sh create mode 100644 docs/src/developer/index.md create mode 100644 docs/src/developer/manual/README.txt create mode 100644 docs/src/developer/manual/img/naming-convention.README create mode 100644 docs/src/index.md create mode 100644 docs/src/quick_installation.md create mode 100644 docs/templates/cover.html create mode 100644 docs/templates/footer.svg create mode 100644 docs/templates/graphics.scss.templ create mode 100644 docs/templates/header.svg create mode 100644 docs/templates/styles.scss create mode 100644 docs/templates/variables.scss create mode 100644 docs/uuid_redirects_hook.py diff --git a/.github/workflows/BuildMKDocsAndPublishToGithubPages.yml b/.github/workflows/BuildMKDocsAndPublishToGithubPages.yml new file mode 100644 index 0000000..258298b --- /dev/null +++ b/.github/workflows/BuildMKDocsAndPublishToGithubPages.yml @@ -0,0 +1,38 @@ +name: 📖 Documentation +on: + push: + branches: + - main + - docs + # Paths can be used to only trigger actions when you have edited certain files, such as a file within the /docs directory + paths: + - ".github/workflows/BuildMKDocsAndPublishToGithubPages.yml" + - "docs/**.md" + - "docs/**.py" + - "docs/assets/**" + # Allow manually running in the actions tab + workflow_dispatch: + +jobs: + build: + name: Deploy docs + runs-on: ubuntu-latest + steps: + - name: Checkout main from github + uses: actions/checkout@v1 + - name: Create Mkdocs Config 🚀 + working-directory: ./docs + run: ./create-mkdocs-html-config.sh + - name: Deploy docs to github pages + # This is where we get the material theme from + uses: timlinux/mkdocs-deploy-gh-pages@master + # Wrong + #uses: timlinux/QGISAnimationWorkbench@main + env: + # Read this carefully: + # https://github.com/marketplace/actions/deploy-mkdocs#building-with-github_token + # The token is automatically generated by the GH Action + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BASE_DIRECTORY: docs + CONFIG_FILE: docs/mkdocs.yml + REQUIREMENTS: docs/requirements.txt diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 122602c..160b24e 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -68,6 +68,7 @@ jobs: make dev-runserver make dev-load-demo-data make sleep + # TODO: # Fix this after we have the tests # - name: Test django endpoint diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0ad25db --- /dev/null +++ b/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/Makefile b/Makefile index ef29300..f9cde75 100644 --- a/Makefile +++ b/Makefile @@ -55,7 +55,8 @@ dev-test: @echo "Run tests" @echo "------------------------------------------------------------------" @docker-compose exec -T dev python manage.py collectstatic --noinput - @docker-compose exec -T dev python manage.py test --keepdb --noinput + @docker-compose exec -T dev python manage.py test cloud_native_gis.tests --keepdb --noinput +# TODO: Remove cloud_native_gis.tests by fixing issue https://github.com/kartoza/CloudNativeGIS/issues/7 serve: @echo diff --git a/README.md b/README.md index 6985d3f..baadf73 100644 --- a/README.md +++ b/README.md @@ -1 +1,120 @@ -# Kartoza Cloud Native GIS \ No newline at end of file +# Cloud Native GIS + +[![Tests](https://github.com/kartoza/CloudNativeGIS/workflows/Tests/badge.svg)](https://github.com/kartoza/CloudNativeGIS/actions/workflows/tests.yaml) +[![📖 Documentation](https://github.com/kartoza/CloudNativeGIS/actions/workflows/BuildMKDocsAndPublishToGithubPages.yml/badge.svg)](https://kartoza.github.io/CloudNativeGIS/) + +## Overview + +Cloud Native GIS is a platform for handling layers and served on map. + +## Key Concepts + +**Layer** can be in vector and raster and being served as tile. + +**Style** is saved in database. Vector layer is in mapbox style. + +**Maputnik** is being used to change the style. + +## Quick installation + +### Production + +``` +git submodule update +git clone https://github.com/kartoza/CloudNativeGIS +cp deployment/.template.env deployment/.env +cp deployment/docker-compose.override.template deployment/docker-compose.template +make up +``` + +The web will be available at `http://127.0.0.1/` + +To stop containers: + +``` +make kill +``` + +To stop and delete containers: + +``` +make down +``` + +### Development + +``` +git submodule update +git clone https://github.com/kartoza/CloudNativeGIS +cp deployment/.template.env deployment/.env +cp deployment/docker-compose.override.template deployment/docker-compose.template +``` + +After that, do + +- open new terminal +- on folder root of project, do + +``` +make serve +``` + +Wait until it is done +when there is sentence "webpack xxx compiled successfully in xxx ms".
+After that, don't close the terminal. +If it is accidentally closed, do `make serve` again + +Next step: + +- Open new terminal +- Do commands below + +``` +make up +make dev +``` + +Wait until it is on. + +The web can be accessed using `http://localhost:5000/` + +If the web is taking long time to load, restart cloud_native_gis_dev_1 container.
+The sequence should be `make dev`, after that run or restart cloud_native_gis_dev_1. + +### Maputnik updates + +CloudNativeGIS using maputnik to edit style. +We could update maputnik in the folder root/maputnik. +Maputnik can be accessed in the django-admin and layers, and there is "editor" +column that will be redirect to maputnik instance. +By default, it is using maputnik production. + +To change and test maputnik: + +``` +make serve-maputnik +``` + +After it is done, there will be link to maputnik. +Copy the link and paste in: +go to deployment/.env +change MAPUTNIK_URL to the copied link + +``` +restart dev container +``` + +After done, we need to update the maputnik production.
+First, create commit of maputnik and push it to repo. +Then + +``` +make build-maputnik +``` + +It will create files in the +django_project/cloud_native_gis/templates/maputnik.html +and also assets in the django_project/cloud_native_gis/static + +After that, test it by remove MAPUTNIK_URL and restart dev container. +If satisfied, just create commit for the changes. \ No newline at end of file diff --git a/deployment/.template.env b/deployment/.template.env index 66a825a..6f0e427 100644 --- a/deployment/.template.env +++ b/deployment/.template.env @@ -19,3 +19,4 @@ REDIS_PASSWORD=redis_password RABBITMQ_HOST=rabbitmq SENTRY_DSN= SECRET_KEY=SECRET_KEY +MAPUTNIK_URL= \ No newline at end of file diff --git a/deployment/docker-compose.override.template.yml b/deployment/docker-compose.override.template.yml index 0d57f09..98edb46 100644 --- a/deployment/docker-compose.override.template.yml +++ b/deployment/docker-compose.override.template.yml @@ -61,6 +61,7 @@ services: - DATABASE_PASSWORD=${DATABASE_PASSWORD:-docker} - DATABASE_HOST=${DATABASE_HOST:-db} - DJANGO_SETTINGS_MODULE=core.settings.dev + - MAPUTNIK_URL=${MAPUTNIK_URL} # Email where alters should be sent. This will be used by let's encrypt and as the django admin email. - ADMIN_USERNAME=${ADMIN_USERNAME:-admin} diff --git a/django_project/cloud_native_gis/utils/layer.py b/django_project/cloud_native_gis/utils/layer.py index c1dc45f..7f8a0b6 100644 --- a/django_project/cloud_native_gis/utils/layer.py +++ b/django_project/cloud_native_gis/utils/layer.py @@ -12,7 +12,10 @@ def maputnik_url() -> str: """Return url for mapnik layer.""" try: - return os.environ['MAPUTNIK_URL'] + maputnik_url = os.environ['MAPUTNIK_URL'] + if not maputnik_url: + raise KeyError() + return maputnik_url except KeyError: return reverse('cloud-native-gis-maputnik') diff --git a/docs/.envrc b/docs/.envrc new file mode 100644 index 0000000..c994689 --- /dev/null +++ b/docs/.envrc @@ -0,0 +1,2 @@ +use nix +layout python diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..0446c85 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,15 @@ +.idea +.venv +pdfs/ + +# mkdocs related +mkdocs.yml +templates/graphics.scss +site/* + +#direnv for docs building +.direnv +# Autogenerated api docs +src/developer/manual/*.md + +*.swp diff --git a/docs/LICENSE b/docs/LICENSE new file mode 100644 index 0000000..0ad25db --- /dev/null +++ b/docs/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..0e98b51 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,30 @@ +# Building the documentation as a PDF + +## Install Dependencies + +You need to install these packages: + +```bash +pip install mkdocs-with-pdf +pip install mkdocs-material +pip install mdx_gh_links +pip install mkdocs-pdf-export-plugin +``` + +## Building in a terminal + +> Note that whenever you add new sections to nav in the mkdocs.yml +> (used for building the web version), you should apply those same +> edits to mkdocs-pdf.yml if you want those new sections to appear +> in the pdf too. + +```bash +cd docs +./build-docs-pdf.sh +xdg-open Handbook.pdf +``` + +## Building in VSCode + +If you are in VSCode, you can also just run the 'Compile PDF' task. The +generated PDF will be placed in docs/pdfs/. diff --git a/docs/assets/kartoza-icon.png b/docs/assets/kartoza-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..071e57fc5dfdfa5331025a2ce51eba2637e0ae56 GIT binary patch literal 76397 zcmeENWmjC$lErD<-Q8V-ySuvvC%Aj#E+G)y-Gd~!I|LecclY2h@V?Bv|1cl!>eY9x zK7DRg?Y-+%)s0e7l175ZhX(@#Lz0z|Py+)4zx})bFduiu<~O20KH!{WbX~!~5HLP3 zaIlOlTrhAjFj)yv4KJfpf9O1W&82_mg5KBIROB8M(QdS)YuDiP^ueTLMCkPJG7;qE zq|<8!KwkccU4UbZR zq-co%87N8!bnvJk36cN*`v2DW2nNIGpylG7)V@@Jn*hYK!Oah1`sgs=_7@aLDvi}P zl(q4T2jCdE98@bNI31|XZF{dSIi!1i!`m;O#P$Ln>rSyXzt%MUX}My%wlI7hzq8~n zth3fPr}8<+4hmRX9$jJET4G%xCt3sN9gkgbg%B`Utnr3gq^2dhfT*q7|tiBp|<9GMHcGO3jT5)0oSz zIEM(%?dp{?Ln_;l(;$7L67~3Dl)oJFa{C!|S?I?Tm~d$4Hf+AWb1<2(#@LeE@uY>a zH{WG1?76Vn&U>bm_O3J)1Uk@$ob~USNrvZ7lAi!KIEVmP97^T4iF!U2_S&t92$+#sl?v9Vj#|?hR@N5R7Be*9=~OypOb86e7P6T* z$ft1WTYwULR_E8XK5PT7mxFh12dPzSL_`-~2P@QE1iq?t%>Ys&E(FZXZ3=!W$4TTx zeQar6!fCI#4FxzE_+%QVlt5vclzuH z>UZ$Y19|IXm@r>jPEYt}9@}3m{_aWtny9WElI)GHUE9A{AIiV@`z508dlK_8TA!ct zM?fakIAuA(mNnM^+FVEF^lnnFrmg}ZL%T}ZJN~4Xc%LxAI__3E)9OS>Bka4YP%Jpv?uw1K>qtivO6_?Oy>{f?S821_31aDyKr2gRkn`g0*S$|Xl`AWuF2Qlf~mFrr`{^Evg53=WNf6sYI65>fpFUcwG?n|$^K z(?={Eo6ll0UrpVI$b@M=)TO=#L&zbU5IA{lH zy##HyG-Mw+{vKRL5MUYs?EAV@K?Lg*~k)K8lePTz=F26B~2SRfYVFHuAyS zS`{l}{>geVsRsn92hxEZVR?6P4^HfO8WADjC=7lqD3GdBer1dJj8I0J z&hmR=b8v4a>4FOz?z8(Fnd@b{rBo1WQ9-kyHrMsNGHof~d=0DhH)nR|o_UiXrfb*VqGWuX-W| zMd?G#H;cK%o()n+97`uUdC%=rZhE+TzZRY+1`?XAeahyyO?ozY*3|)rdPTl&o0}U) zJP}$bIFRb6m?omad?<_pn^44!UVe-Hq_e1m+~e-rXe3}o*oPr<@PQ49&p93pa-&T2 zG1zf}R$s60OI*vx9QnSwf-z=(qMiK{?d-H8_ijuOxt-_fA=p^(5yd_?Bye}JfUg`f z{o7imYA7kk$LOtYOa<~NS^G#OU5{Sg+YHEXv1|Y$N!MsBCRXAG|JQzf5JKFl^L2l!lFUcN!TE;0GdjYfFD;M4l=0L?__itq%3JmB{^qc$2* z%g}abVc(KgVUQ6a=YcG!6l26DbX$?~PV?kh$(y#29RQwq=_2lafCK~FM6#P4H( z-?6Xq*&nB`yJ;xg+V_W*+^r8^Y2e)axDqUkpbk7t( zCgo)h#LRs?Y$aXazQ8<}@kMB_N7s-m%>Ujoq&8#Rb$9vK=sQ5}LmuS+18+2Ra8f6b zyK=zhURX>Qo83frjb^2Eb?{5rn;8PN31q+qh>jlSr6*RPR;&(TgDVsbI?28=0Zj4C zK6n*dhkaF~68d+PSDW4KS2{vi$P0{dz~q?<_OgY`%Q<*ByR9@-Ll9Mt0x zS~Yld1L7)~QP;Hf)j|;RrE8J~cU=D-Xx-z*h(z6B)W9e>+AGs!0%sDL51Px6aqxex zd-j(cR0p8!(ojKUhkS5FHpfpF%F4)YA#H(x=loE8-`RxwSA?!;uJD;A{gxsD|=UJU%0Nqpyz>Nb!Ezk4j)bnUj*mZ8_;^m?s zOuP0zwduD3;Vo%cw2%P+Ic=VdIuDL~3x4^}@L0H$Gue2$Xmtpu6o5pn{=25(ZnSbO zuiQ_ip53}aNVG6_MiAXB8zh7;*>--4xFgLM6xXNC{W1to*o&*pH{7aN>BslTXwTPK zf15R-!wA^GuSF})DLWTRP(>ma6W$lgsu#|W=0D2<}gCN#x0sh`eC3lkkqYWu!eqHe`M?3ez+8|=K3J*XxKqKqAUybJ?6t7 zBiZ~*H<}`wHw(gd=g@mscGZ3!>XJ=AIE%uz_~bO@V=AF2)$;3%Dq`_&FEbL!%H?kB z5*Jg1>&9(@atkKMe)|9($j_8D{Be@b`qKwY7CFb!xZL4AL_s0i{ZYm-(L>LMJ;^A7 z>#!}%HN`!vW?D3ulW^zknrDgnC@XGmcRtj@RA@595OI~)iS56}h&|yTe2pJ(C}^^J z&270GY?kC=Sh;O|$mAo`Sa+y;e@TpD%9uYCjMr$A6k^K)FA#t%67bAme+BB=pnCR^ zlF`omREwm=GFPv&V#@Rg4#)~}s0ae$yrieR29v0>jd6b zl#L!w5_oFwuSd~=|HMRW56`$r>Uof)Ob*6~TLc#}m;L~v)mLDS=!fM57O<#SP~WbC zV!w**#6a;HW0Dk%M}iQ^sHsOr3mx6aLJRJn@VVTVv`Bzu_KFf*1iHfHOdZ_d0=D4) zXmyy;cVEcWR&o18m~whapiLe$F$ch@So9B5eq?Ra?`Ynwc#^a}PE~G5Kgvdluz#Rb z5buW4wN+VNJ>I6@a0}CufJT zv28bBNsG*kTDQvh1(J0VQR^#`kLoKj+I0x%Y3(X%NRi(aq-eZ)YCLmP`%)#5m;FJ# z9obgW|GqV$E?!g^pX)LHnEd-U5@Kj&`W8i;%Luqh6Cb^BQ8NrX3|KMVVKn%W5>V+|7W6lR_JUq+ zu4)6Phq_CI{e)J5bt?v}q~gs-ldF(BNhfF%2g7zTOpxhT8ijKA7 z&^{(t_V9yrB7<)8J-4eouG0Q>UQf-qF*Gk3xt_NnTqey3aj%tHArb> zXKs}qjm89GUYe6^JlO&AprmQ_6Y)a{!W~r+!sgYT=&y#c_ihoyrd<-XktkYM?xmK{ z@C?x=DIo*UH>&+FEtC&rl_bda%#F9?W6kxfOiK2)El|whig@O&rU6bJRr^A%@0yc@ zTx$Vilk!l@XyE1fe|D;dg{rY3d=0N=2wZGly9<&^)?t>lFdoNfOT^4@{fc!{A;f>s zLi<;KBV8*WTy6cK+u`8}kAmi}n6IA9h!`2u%e2YpMPOlMA}l9*eezy^ zuf${tC3@LbNUzH|8iE$3%fnRBaL~b^<_|sCEP&z>kmQ@ zik>7%DNWKhGQ0e`X%aB)bX%HWhN)kPa479&hE>C-*eLZf7yfejR7%xg@TWEkD#18o z6+^&#ZSk(p@u~W0c{|BiPuEqRDK3Z}WojIC7xOeAP9wC_H9tQYJYG`EHm*m*IR?7* z13EkOdhC`sU(PmBFqaVX_eskf+N;VRvjZMl;sTe}hKHwUKBJh%dA_xIl7$8TQP$S! zJk_*B+c_z|h+Hqd{gin8thYb@Is-A@JdJ-Q?Q1fioeUx}=)lD}q+Z6IQ6JK#lrP}G zs@B(5JSt0q)aE1Y%4x(q*?v2J%pM9zytr6%Sd~OWrd?@GLeFRh)sqe5;SLSTc%s*K&7PJ?YH!5c&g))Ra7WPadIV&^M?=HnJDf57EWZlDIsLVMBr~J|7zjf zyI(L63-cuZ4VVu@<#FF9^_8QNU?m(sxtluWY?yg*AmjOh9DQQ8xC_z_3c?GLMQ$Ud z3(%z=42~#4JX9`*%_WwpoYl$aMN#yhnKnJ z$CBOn%IzLB!bPgghdu{?=(B8kIrG`U+lKGHV6og?Z^2w;#_wXUV)9Y*jNZT+(dMDE zIJKFgmJWHGNjbz7bqXFujX=R=WUffp>wE3SMt0A&FKyp^-$MRW^%w8zQ$jFFe;6WF z8F<=#jrwqVpF3wvfZrlVlGYSnCVP$zZDEBK)}-(-h7`&+z(nugN*OKq_81r1GCRGu z>^jFu8&r7gU|?2);@Va=e2~b5JK$G8+TPOfeBm}ycp%eA32_$xvFS4*al_TFpAphs z8~nZ|uFzrJoLzt!S~?h1Qi10Lp3zL*Z&s_`LL zvOrXUH+;^!*y)Wz!arjc3I5Jh%yb*%Xx4ZiDcm1KAMYI=F_WKTf$q~;y05u&4c=5v zgP8i_(HY3L+G&z_x7ehTamF96QGf-aIuKw7n8vwlZ6lEOA9YTt<{DZbi%J5u4e3^1 zf1h9`yzhDjcD%Wr(+D%5SyMx}NZV7lUN2XMb(hxqKAq{L!G3A2<}HS!>QhStXt+Q# z@dHF4q}g=t7$aYD>pvU?8$Tp-qzATSlqC^@#MRN%-c2dg@!P3d+XG)#v6M?)&`^`3b=YjTjL2qC@j$dX8@m@|F z_-Mg=leN6jQ`0EVPm)7=s4B2Mt@03c4y&kn5PFYufef=9M6>EI1AQJ<7j5-<@0pA? zzf*nTj*?1|?;(naAEu(QtY|GP%xykApsDScU(JRnDo&SCR`-Lw8*`PRfjA-HHjZ>2 zaIYvJZm~>kbd3Tt#uoeD(7`|d_c(qUaoA>)9C{kV{amw#V@f9g2bjt$qZc`Ri&txk zHyWCuIiEJ?yXo-r{n)kASNT5=hni?`{#Q)P$TJ0P@xAqco7rc*!;)EW(%GQDm+UKD zXf0ueY7q@yFqlLU?wneTpRVk;6z5bD9WJP08xefdAz&q}z^@nY0>T##tFOYYlVlgZ zmUA`K8%$`{#1LxYj>NyOM?a1Zy<1ZlJ+oYsVd*pV3IKF>&(ekGeaBnU{GG z8~Kur*mh+={xl(qzBNZHSuGu!4m>zJ+F)$RFApU(3N?huGp^rjul2^nv}DPEMug8$ z98+*}7Dj&QQ9pT{8$Hli8@028{yk8 zi;-(+v%V|w%+E)V-8iioIgy774Of~7@yVay8jTLaNBDMU<_wiN&RRj8CMbwH%Ha2;6OZ#>oy zQNR{h*&UfoCSd=bQ~+%LsdB z|2kS6A2=3XwK8c_k>?tg2-6G;XB!rZb0yu_ z^KOIE5?nw7UFz#?vA4JL$V%%SC#Wi_jgklg8usE-q(x=VdU8{4??JD%k83Nf$cSGy zQ$OJ1Ggg|{##d);b~?V~daYlNSpgTPuhOg7dCcj!rEPUdU_3i&?D!qWz3PK*8&QE^ z25@F`^=YU|*(nvJh~vkB3%yBOj=$^lujfDd1FL8sb$@-fQ^?MHg|6+kwp0U^)?V*; zuYV(MocODfg`_AWgV69gepo$@e$F$YbVeG=efxC5d%MTq1~^B3=P5Rm*pPeDhyUCX zD$7#vbf}cmyB-wXFP=oxyh{gDp{2<}?WXc3TYElsNDaatOdMUj2ASsVb3(a-aZo{S z&}K>2d>P;>SPyf;3GOJ#-npn!B*NQ(KC)v{QDPr(fBbIyc&P~QQl*&7Iq>y|_!q73 zpyqHJ=W zy{uW#PJlG=9qqB8oJF!CIY0}|yRJFT6SE*X z5|*e(LWTbez9j}=NLrjb^wO;;lI`ZDiHeA7SHkJTm(!Lh^N=;0sG$bqPWj^x#=VjV zyWT8Z8RMx=MN*3hx#F3nz3E_K9Z2+1xyks4#Cq?2|E}31xBrNdBIk|uTAo3wg_?Ea7f(l8r8tB;-o6ql~C5rrW8w^A71}oBy zPy>~LEHa39u627muX_;|g@t5?4c);q3Kx+gQ;kW$!9{V#d-iA30x?5Md{6ENTmNwk z(Pb<$qT09XGFRvdldeYjhm57LatvwLLEod7dt8W zZRC-ECZ<0}il_L10IT#%MEhJw8IAp27FD9LDPB%tNx8m2=SF$9QHM$7zm67J%pg%RO==U07c`( z3h!)TbB|(6nsO}=Bdy7ul27nXz}};O$mwtsj<*;Str)}K&QGZSSvAa9ZL=uR=bV^) z-{gVpi!pwE?Z&sO)|bF^Dicp+>&vpVQjMirl1GJcdy!_EM+cm6wge+%!rTluI()?( zS_o6&&=Jo(@=j?x3Ko zP_jce=A8u&G(hgz)^V)DKIdbO=+}GuuBpt-fX~i=!V^ostj7-4_8OX?q5ST2InI6uY-Ci(rB?YJVl+Y%Lf9BI?%~C=FBey&Bo*j zoRz(iqCRqTnST!S2Tf;ayqmt00XP*$Tg+M+`F3KF(5cnD@wItx(U&dMEsv~B2)Q0i z1M!d7vjUJv%grDO)$B2#GZDlF%n@K{j2FVz!>yt6K{^5(Hbti#6aGEy;_kr7IoI=9 zHS?v~(0S?N+UowcVjx7I>lWMYeARQt&}4;sFsctR+)>Q8w%hoe4T5m_MFWDA*p{(d zY60>+XLs-|MjYSoC}~L$-;uToWeS)wk#>9t>T+EI-oIStCCC~3e5Yyu`^*gOlc}uo zz3o1XARv<%kK{RKN!WJ{EWkvt+bI0+I?(B+EMK&n1DA2+Zx|HCRon;?Q3frKTkdzc z-LbwdL{mj&@57zjf@Lq&z~a1!3&M@!=wi8Y^tV1$_MbvttNRO7a53+X6AkG}^{zj* zW6#(Z&D$47i=U%^Sn}3|JydK<#vs1#$vXwJMkEOCpWbh(E4%D0Hb-Ru5K(VX;<6)} zz#t6!UMO%?b!gai4&n=mTo>{Qj8k{7MmzuTe5QH#FO;pGfN=hCgjI%*vY{;A;%Nm& zbog}{vfmI{NEPX9`5I-5Gb9e-O%o*_2}Gu_>M+42#mVKbnWFe>B9IPQd)XB5eg!#t zbhzwB|F3-Rb+_z_K}YKH0GZZ-bv*9!QwW9c?K^efD5>oK+uY@L#J-~q zKHSc6oa4W+s35)fdxwrGpyk6vtjcGHRnk{2y=DIP?w=h+qL?@cgj2liiJ2!1O6LCR z`#~M*dvaNt8Xg^ZMPDu-;B)+Yf!cF-?EDcK=jGTnUZ2menhRD~EsRn-KVRCyafg&Q zARg$_4+onanz>r|OLE!Ujd!mHNej0M(y%;ICmQSuJ@T7`tuY!fbU(n8uzut$oBP5= z;0!2I?>Y0YTjie_9)Qr}`Gz2s8e7ni-B;1JdiAt`-iA|JO79DgxI?I{!|#|)?h+HS zKkFgsDLp1`6rsfAOQz|lHpT`0h`}4HY@S}KUglcLB=;b=%mga$Rfgl|cpO3ZRvTE@ z%#Yr7EQZPHp9rvSP_JmbjeUyBNY9-b=l3(0d<$yi)0k>S#6(II;IKz`yS6N;$pIF> z1aqgl-~QmFW7A0VWpdz8Kov5?$hxAoRsS^yN3aO$!;rVsXc5SA*HdBvU$spNZ`qls z3GYa0#$j9ZBpg=MnMlHcq8I^^8a$^!%n6IE8(!wNL`sjS_Qmz8V74^S`P#$y(9Kk- zj^sdj zOFXsshStx(&EdGWr!kB_%jN||*}JW8fzWUny@THNk1XzW|o3Wox2=ZYpzj{m(&O9$+>RXAR7 z+%7NfcthI6Z1U6Gd(XulIw!B$>K_&nL?Psy7h8AOp>7K;UF&oOVRl8*z%iJ&5#5HA z+PVde5OoWVX_{=T?#EP z^ZatM&?e?}nR|N{J-1T^1^vJ;N%8Yv30aK;_uqwnTi(52nR5%<6xily66e0xTCSOw z)DRG96>f8=mRT_=NfaHKD&k^?^1THQd#XH8TE5-Rpro3yNcgMT-(&#@o=t9?U0TW5`4JP`DRbrU{vIk3@Irb!&GtI`m16w`_myio!0 za!E9=+UCGk7%VjDfM*JE7b~Uo%MyNY(E7sPVAn5Y2zrlp{l04fxOm0~L z8w&z?GBHFQ zAP{xGb_OzeKDuTV>R2*d&iJY}nwRZduY5&t&$ zVd!qN2ZYNUwVh?jYE}4BD8|Sh`);I)baTWY)h(yR{C1iJ0M-Ylw(4*4a$VjI})}4mjmCJ4{ z1Tq)=>uy&q`6lWhaTOK&_RW9=bhc0=1ZcS>ioK^m1R)ix^Lik}fpOMwaw9+cndLc^ z5o*~&TM^r~{!gv=W(<#jxyERiCzKdN0yp#5!`V4;P?ko!^j9mMB zw&6D_*bgKnb7+5CQ|FoGoLYkZUkZ2J;v4l;>G(enalBaN@Q+GY)|+Ey4TjXXCru47hairN7*tMQ85Z zydt+rgg(Pq4Q6AKI|8x7z3_1`-p>AgYA7pvC&!3ok)-nM;H~-` zH<#*t*f>Vis=)Z^vYMxp2<62$V9~g0+x^Ws%ePxAhBeQ0T{<5D$Z*!Ch9g>Abhg^L zG*}z(US;CK!IgH!x$&J`^W4^yGhGJIU&R$a+GC>qt{%-{{HE;bhrKAIuXoLf=KM3(d<$2z%)0s3hhbKIbgi(XN$hn z0nF(vq#xL3FqsOQBrG?%%|<}V?iI+O)w+@wYvLY+?C<5rJ|*vja>n&*(UZd?AxWBB zKyOi7sh#;yrHw4g8fhcc(;p-I2U8Nq3zQU1NnVhZBq|dAN^tlos^8pW>>8!1|H-IC z!aH-tfriM!Sk{!tbjDN}0WViu*R>=94w;quYxhbW?{UTt-GLemp4CJep_L(2GF&D8 zNqo2&)vSLI0IUITVay>hC6DtNC58|KhHipZ3m}E>CHRhjtbU z`&|6|^YqB+KquUa4lwWp!M@~lE?Ie}xJb@1ndX%E_6M!>nX?h1PT;ay(R4Uxw}7Vq z)-}3L50O7__uSB2;2)lzes^qa6jIwzcrf~gr zp{>sj;U%2C`+d`ornV#q3w&t4@p-l=n32h!0~^Ex83S&WXPZzKocv*5j*OV<+od?` za1qLT@c>p&npBMONGF!Zt6Dp2-|o9!H<5^M{O)LM@nZdRkWF*K!{c>eo5ck%1!a92 zyvi)Hf>P8F#}`k;9V`feDWm0atg(WZw%NkFML`5V`t+3wzL%_`W_r(=oVK$2e%HE`guY1=hQ>~sX6tEI8V7GFf zZSm#$=wssi$qnsvd-A7z*dHqYhXQ22CfCc(j7635{I=aC?50W6<-0iH^?+GygzrKV zN{3wsb_;mSyw7!ZY#hL1`{Z>oLVVRpl#_T%SaIjo=_gr|R%@ z%H6gG3_*Yg@sTnn;#U$1XSk)|#WLs$)YBZ>K;bL%(?sw^y@#9cJ1-PaWMGd|J!u&a zNpSM0H$o!c`!3LKgnZvGgmM&Lx_80!J{!(VK*2|zJ28KMj^xbb+a%U}B}g>nC=0W2 z{vK%*Ae#{P)x~rC+V*-;!Y}owz?~j~mew2}sk%zCLEzja`i6-EsBS$Jg=k0i;KmhF zGf;bbhzb^j{>fKxrz2hEm9_+y&#?1yPcosbGz3|+zQpw4HdrnDWFrnvB5-LNv9nwPxbH0|hu^S2pMEirg*Au0n?!`W ztB5CKRTBCOlnFc5WZ$T(KrPMxeRzot_b!Iq`HB=5Bi@|k^^dtonD~I3#3MVeqeX)d z);q81i23r@1&!CCIa`ZnCR=a?jIa5b3)4rCUv=v=P|+Em?jO%<*=O1tU%YTWUyi_0 zdUA`1ZNB6wRTb?u!%zYXNcOTh;qqDx%CGwuiwAgLPF&p$Qc` zZH_BT+V=f?ZelYEU*`+;$YOe@BJb5%Nolg?eLvvTJD6_(0 zHR|V~&hR9B$SJWN5thuI;SQ1l=ATmq&>vRQhGu#+0(N^fHK$q?VR1deqaWLrV$wjx zA#!UN;;9YdyuDszXulO_9siT+2D}Pu4@F=Yb4r)4fW0V4#!-7h;$hQy)wAbuO)o57 z@OR1lxn~?+ZzA|K+)8YtcOY`}Hcn$>=H>0cFM)6CJ3Qyauc`D=7MJ8d+X~V#!YgQu zR49GavFt3@=fwCXa{uyJMf-2H7BzkH5 z)w&>jQ@?of_fBS55(a?{7zy9ZN64)%8cGLNLE597MSAQ!71 z%LURi$Dw*-#W+wL@*0MH!0)TbFSge&#<=JkPqWOU=fl5zltp)FO%HoGqonFYUlae7VG1Q)>9z*2293@9U%tOOp zX#_knbRdEV3r_<$QRgbaULP~=g`_MoFZ3747lf>lHegvtJH5_=QL_ ze}G91BlfjFI{1gZTMb|1vb|S`NGI`Dhv4n7Rb-aRd+C8>8>@OyVokHl z$O`Z0Ng@dl+cJWTeut6D&R6zdauATeEKx!*e7>T>kdWd>gX-iDn^ha>q%0KImZrQr zw_^fv%)eWZ*_!@9T3Mr4L~EFPdlmf%dXgb10l zyF%o2H$y5j$9{RMnw$2uN$xr=G(7&JxVogFsUDFmkXm!nmf>efK@u^NHVL%)Ixlf> z;bqN@7}G=l32gjNVB^z2N-aWgw3g`SW2Xbk6)8I&d9&*5E3jErWj?3WXpqgKHoC}@ z`FB*wjroe(^2nu#`6_DCeFLAh>qX?hV_U>LXFR|b3_Q5co&DOn)h!`|Z;(jQ{Z6vS zJRQc0`NT3+gd(WRz<2eG<3$u2P7L!kD#o^;;mQ~bg2=3sM^~NPcSQ~g{avIHz1^XW z2Qv~}^fCHxDTU5Z7I-RF9B2(vU2#f*`!EW|9KSPlseW7gKkvCBQ#K6BBa%^vGvZUmKqKu>=5Q zRZr-rw6F-?LJN>b_W{^Jz5?p0puq_TpOU8+QqB%e(4~7Pev4HxGGF^MM0`e7M6w^w z01-5w$COTDpTrtlGw2x1IM|OEoxM@Wk!lWY?FWI5w8G9f zqL_N00pmD-7+w4i&*Y>*0Amgw<(^?l3|LHTukN%e+NLV{;WTC};AgU(OKVJVj1bF* zJS+Zli=gLpYuvTUWf3JG6_?I({`yTu5r^XOF8MyuNv60<#{KIuTt(|55;>XY4DR*ghptg zb1RvJrP<&=Qea+;79@g0d5(6#$zVDv_q;chysmlTG`7#8Q`(@ zSoPg3EkzM^uAE!7rJxYzZ2*)l>!p74ObqWNe9%yw$4OgCNjYqj1?C(cWgbmb_I#)H z^kU=B0o3Ef!<>_0%=}P=8k{Fc#)_FECJin+5WoL-0$!mHT>w}f7|Tgtp({@L zrBE$wy4Fw!411`QG#Szzmu#0kbqj60rDGn$rDvb)nvrI#m z42JltiD{_5+N~uvd5z}VN_!RZ12T>6!&|v*WyygQxJ#1WQ*|{W^3&2-Ly&p@8qEmw zVD5DHsr?n!K<}XPiJdH}4jVH>piFk`15u(B+!&Y$5e&z=6Hs#4K_qy_zGhV8j==gh_Aq{qCx^#EV_vRoIpxH zQSHlLa_)ezZE9bIo}r6aB>mWzBWmKB6CN#cOfTw-6Pl`lRpYWqbJTH0{!U%JkriT< ztMspplrFh)Q4ks)T(20^7SU||%tIKy_Sop!bC)td`=PVq#&CfS9)pZ0H=~7hst^4NOx2+y;Y!EnvPL4I z6oC)rVi=Y^-OY$9P-I*GhbdaEXnyw161>0wdz{*K1Pv@};m3(psL+Y#*)q}pMs=^E zy@=fB`s}=ScZ8G@Ee(ok#B=@osqXR1dZtgaXdXV|o{V4Su6v~7xmZ0cZSXlmi@gW$ z737B#RiXH{($iGCTc0g^phAr`H3jlD0i(0X*7T6Cq~kp(HM}_+f8MdWew5pN6R0&g z@^7G-re0}IW?14v3NbZ^uJgI_8&5;FKH!7m>r8&TN$FSZWD?8c@c8;AlOwqMukmW* zp_h{EmEZuV1&u0D8jH=j31D6X*h)nIXU1S?E(MmtqiX?$+`NBKqEFW;&ZS1qE^vfI zWrFr6Up&0ctAugj=8|JRzxXlwEYurf&IbNR@fK)8%!3(a@4WevG6GQhLl}4 z(WbbIDuUKB;bx^AkU-0^?q=?69Z<)=UM}`Fc+p{Ti);NxXoS6X?5hdFTTpeYPV&3l z+ruuv68&>Q^fTmU?d6Ga9v!@n5Nn=C)JQM}LKVNi5Z``YZ6T*s#1lfqPC0TYxFUzJ zn^MTV;6gGBA%>fyK@h2)kGIms;)FX{zlm?d(*Cb^-YqK}-n3CxBf%&h*__S9LR&EO z`1}uvLtFDB2&e-~_*|j#D>`X7ziG1Bd&zxwbir|c8cwG)CtTWw$Ud@@(R1x^20XsI z?K6(5av^+dGBeCR!U!k&)R=Pt16+1wApsL`CBtDh-k7j9H={7%I_h`^I+A~>;}rBu zsO^!0Qv8i!#+#UZ8cc77|!N=|MQRd8PtCzMJaHS&vu8;Im}|Q$z6VF z++RVn$lsKqaQhOB7?o~EM;w%)G&b}}pboY#E!;#NHF~TCR8pAy^_bdffD#RhaC=eZY51o#cJaKV7sMK3k-1u}YV0ATOl?nhx{hc4+`AJ!mPn1C@3&d2!-v=@f zgS*_;5l7Lu2tLgi=M-W1-pXRHrpPd{!8E5Whaa6Rs;)OxnN8-j6>}$=Lln$NQ>l^i z0|ogTSMf<|haLa_uyhWNadqFIk1NQnPCceu)HyL+~FJEDUQln9xj+2AZuss zc;e8n5X^b)9mSYn|F5dC?-Dr*O-{T=TXFg>MBkdB#0EH=!F>cpI!3e%^UmAu$FgA` zz1eMm7|#h8*L;c)`}h&_TyAb>VBv$y0~E$Iy#quCgJ91AOrR@k9EAqL8+HuK+YR^3 zq9hUrBq%^CI0e-H{s%qxm~(t~A!{~B(vUp{*;L%ib3R?>VE4Qm_~ugeul3K8t{==q zeFvhNiv&d@iNP02S?}of^`bgzv{15@7Jx`=SsbQjoigRSW4v zCnVWxRRnmf&W~PC{O3WR{xU`6hI8D=^qk988KJN{j9s!NfpPie?=Qg)crYVH&SYo@ zz-t$NnGAaQ=#*-a)zyTtMwpjfdn##UMZpvK=Pm76nP~p)i?wz|#||bUN$Rdb!j{4({e$1Pw@+J$PE)#bkm>!Rf`pHuC6$YrjS zK{%%-Lj3V6*_XqsF-~xEA|d=|W)@>VVm4)dMF4%GO+lJ7_b+9}Y&?4J_RA(N!J36!ebRVa&DWxwHCofrHt5&JN=IcdUv%Cd2KM9A0jz)yAHPL*je`m4qJNYOXF=C&~-)nin(CSOrROX-p{z$lh%t= za{*4rpq*+4>qbc%Vbb@h&;}fTD2dgny=}4M$a&o>NPf2N6mmBx<1T#Q?ao(EUP%gN z%)Sp8q1rM0YBl$-D+{+XY~({DyE0j<97a5q#}JYas-?j$dje4QQ8RUaMKGnm*sI2z z;ux9`E%1weivAHHMNGM;*_{gbn&xn#8#)d@9Ua$v*uG$m4hOWgirAmTjQuP|zjFbL z?t=3Z@S^)ur^{x~zxGP$IOlcjJ#2j1b~~A(M^Sa@w664eaV=IVngzWMTtGV4Df@hx zVZs_79-$Hl`1E?bwFD)eJ0q|~osnMK(W_q06X$L}$w2(}DN&tTOMOD@$WmS#Q~z~J zr}FknW0jU-sQ9;-W<91Pcc#8&?PTa+wQ?b4+UUS*p7vc+^qe~VD+n$A5yM^DVqg4M z`^nxzyFzx9i-RzT!r{qnh%TSVI-B(w~P9vf3RcEA(RL^9FJ)~M~4->n^zY=F1TThdyvkwJ8R|8E75mI zSmS%2bJgMON=NRLONll+2N-yn?(_YCs{4Fd*LK>{ut4*p+;mgjD%b(}SVsrLi|noo z*~Zv^6AB+Z9Il*-CW78x-Bv;0g}PP|dg{7}L|3cW>r?~T9Oba#e-d^m;W61e8JTyZ zD}MeHcdFPfv#1JRHK{^Le$5w$K*;ZE{>(cpNRc{@$7^-GTX{pBsV;u$4QvK4<%}vy zuFgnhHPFC9=Yva)M74-~eKDg;4vRCUPZQ>Wm2a4IGP6YRDV7bLFmj8ek|E7y!{Jh&k zO>IMk)}9z`EteNzBS)>{b^VKCM$;?13MR_eW%$1y;jp5U3;fet2xsQgdNa@)acKJS zjPxBnD>IUtQsU@LfR|k0OJethss{A)IKNSSC~d3$r<;)DUpu19+Wdn$rga7EyoMeRg{Q8OL@d4h%jG<$*Bka z`hHj=nkK{U>qt8@;q@p=+4nb;|L78o304&7%k2?H-djAgN^N$DHz5RsT+HvOAL1p_ z6&TU8Y3xp|kZxs+;0OZ|<(x%&n@`1@Bp{4KDQKzpvm zxx?5DHv|Lu9s+8!YzC+ONK32DCQn!G3kiOQ^;=<$aAJ=1_s_FS<-EFDHAgz=i4}tj zYg%*gCFRftSh^$mh6VMPatZc;4#vB9ut|_oRs1MA1a`%#urY$$8v#>PUNNGctI@Af zM#4?=^``S83~)XvN8xz8la*xima*ywss(-=)q1aALAjv@-)!kr&^lYx-4Y0Jv!FSr1Ek1T|D{2l*SvbZiSrPclIN#(_D$#3ty6cdcqFFt5 z?Ek4;dk?L?ybE#L%9cuX>G%i;Hn+m-U30(QAL>phy#&@gJ1n92P-rT~<7GaEYXm(I zH=pZwlFopMn)MSB-qOE8!Ee4EjaOa{q|xA_AlN(GMax~bvD3f`z?jp|ROBEqw59%K ztI1N_>xV-nB8IxBo|o{ji9mrHwW4jJdYuX)4pXKvH@;4&#XsA4C}E(gnvmaHyeax0 z2ra(=p=tAQWoBn2x)}*FeZ`?sbhyAD^}QBffXeNPy4u6)*4uQ~;Oq5Tr2*3spm?uZ z*}3w{$NJ9a7fgkk^$ha8z-o2tU%vlORr|cYJM<7xM7F~fyFn+vuXppLdrw5p%(oSj z`@{lxK4OtdqqOpMnDvTlTH6Z5__ZSEc?Hq$3L3YX`M<-_45P_Fj47{O3C`^jkFUx8 z2Wty5`=6eQiy}t4#rH%pC|2-gzlhB*;@qGRv5}X2)25FnG(;COluX-z9ZrH5yy8XVy&(WsCl|=IAe-t=*@y{!ZGI-4{ZPD!()iGZx zyCQkd^!zKUz}G|D`B@5-Zh=$-tR02QrO2lu13sMVOa7QZe(~YxYLg5=?@C+==kqmx>+n8HGjtt^WI%A6&*tEQ^gG=z!O7kZkAuRmRH=vo`g~O7 zO;qEeJfr@PcE|i_N%5D;X>SIJ%$^bC_hl#Yi+H5)yMysssi|xxG$#xvGm+dJpR4mM_iba z79v1IDkudXN-3iXJsi7_(0$5DH&OpRjj-_7@sY3@M;O8Tw=xAaxBJ)NR4HXl&4ysw z2~g#3eq`8)N?9NpL*&qxZ=@5qHMWkBPvuZjPPGxJs06OqS699Lk)`Rxw0#92b-J)z z@)0I#x;IaCNy&Hn)y9_Y=PQPhw~cxC#g(H=E?#!$db87zZ6uIviS4wT{!G{!;H+Jl zH$c8{Dc5=x=L(1*hqYCN2*rQR0XA`kiu?^#=urTOMC$+j4Ugff(HNH$a~q^AB0f)o z5m1+SJ(p0x`yKYX_!A(wD%o-6tNny11?n#O_!DuG-iyEorGYgb(awJS-Yxd4o^S-x z6ChA9EuQaWe49PtKd_+|HcW9ifYx&Ku@(!;YOc$;cVJ-Dy4E5=c^8W)nPT3Z3{4yo zM+URtsdgSa>w{9J{ijqJ5gAyJc80u|^zZdHIWvmop(91UsD|N?j>AOr!%!ZRojb?~ z*OMnnwk~blY!eEy%Cjv%O^Q$H@5qZ`&d`_8pZQW2;HM+-)*vu`t3PiPqWmcs+A$@w zTyn^(uG4`(d{uM!(GT8aPxCQ`4ImRl9JoX(j1BDhOOInRTp&VMxK#9MM|skLdD;GT zXN6^hn6eP;r00*7M=->Jvy&Qzsqo4gkouWJ!$$at(oI+DbqL=M@*w&6ouS|`%{%+) z8LdJ;X1tkGrc^;3|M7!iL=UTEmGP?|Ec$P(F5VrB%+lR(Fr7yL_|1lkV8ex}?K=l= z({bzDTQ`Wz3GJm92WHDOFLNW}yFLj#5ea0=iRH*Y zF2`x%q<{0b@n#sc?JHMXUh6RE??w6F1-}(zogO|t>2Ud5(S6&qwC20Gt9x_J2U_qc zD-tX(*i6cIJM}RUllXJT;C6Z%m{f^OilVC}0JgbNJ;4iwc57yHO|+ifF?l$Bziu6D zQ<(~FPsbrXe#}5J@q(B8OLR$h&Wh$bnB*^WIE(C9bF(kEfS%P)OjTP3K-$xoBpy^q zidl={l@ow6Duin)FFX4_)T{_P7s4+&^t`wg_}A8XZ6j$np@O-uOE%Q@PidHcZqAWZ_R{!~{7h$6dx?XVvAyvrS$b8T$mZ6o+iW7;Yvq z7ZtlpaRBU$ot$G)=gel(OexskB(@H`8m%bkIkuU_<@4nz*Jm^fDQw3A4EA2iPbd_Q z4^wXhZO|;`;WPE{#5!g30#)DMu6>8K1~LQAqkeD2^B`8HoYo(`FkjfDY;L}%p{G4T zp*95sx_<;by&A>~U5^wf^s2=b{U1Z5sL0#p7)8;~(Y5Q!vf1LH8eJz&B$q?HErM1? zltM~h>>!DhjPlV_ES~F1YpyXncu!qbchhN~a+=fU25^%y7r?0I%j;VW=|K}g6Z9luj5xS8zF?!H|4BlzVN7&+l;XToDCHS|> z-r3q3ZeZ~T+eO2n4_gOs9d7gI^$mR7%4xZ|;wje@|IxnMDtDUBkIAwx`Y8{82_5;>d;OH-L+kj~W5L=D#_(H-%E@QiTfoeE zD9Mxi-FLph5bW{CDa|iW8>Se|&-~i{tP|yJmvquC$L+{2U@icE;h!F301n}iZpyY) z#G2keG6)QH!uF{|sBa~|n?0(Q_IKs^-gUy8MG(K)abi-`t5)!hmHcKZVLNdtx>PMqs}ROn`*bi>}zuAJ}raV95&3 zqe&Yt>02HUa+Cj1R4hHx9+!DLZ&Qs=fie(;N&2riBIER5iFM*uYOZvvJqQ^fj+5ZK z1bdyRfjUBlm_3bb2N~koEX&BC-o~cw`2TLD2z@ly!kwjlI*uj@{asP2olyO?1ay)! zvYNnpAh5jOjgR1LMCpz@Vnw#~1Uk>sD{ZKRj=a)(GL-SWkF8Wit5KhmWA7^sjuF&R~fANd_Yp+6_N5bI-XnqsiV( z98%FkZlQsM%(1lj6j#J)m)`kH`|*9T9j8Vgm*jo0XS+w&EcqqMyzKVF093{l6ANS) zWPM1}<9(^~1%QT0=e%CiRpan3e6jWssL+zXMomc?U2o{xVkhU=(Z&63NXfhRe=GoT@D~y>gN3z=f2f&**zxuzt?Nr@6zm z)B~!up=5WJ1V|m84{$p7_TLzJs+Vx9y)VYcZ5_^=#~;MZ0sIZOg#A56v6gI$*FM1a z``jGCgvPs4Gy9&+TK)xkwe+|n_X1hdhxXhz$tJ}QoA0W;HN-MWFHPGv(`ZZ`KI3S7 z3#S18e7obY6Ev-rc_TwO7(8CfdS$l$5T$#g8_DdZU+`W7WoA3miz!ijwbZEvmgp*& zC8r9w`u#B8f@z)FE;4z{=h-_!WK-ywyg!9jHx2>8G>fC_;r+j(p8%w|tKS?xH_7y& z^OE{liXHvhsns+#wGW3X!a(VB1&yoY_}%vXyRAd6i02wgY`p)&KvDdgjbP5lmKWoAGK){Uh9~b* zLY}-JlqwJ6X~xx43`@C-HK~PD;niQ&iuZA~$pEywdqa;q&A1o0o5TbP(ofQd;uSBh zzvGd%f!X<0rH#E(#VTm>5N<0I*;o`!IhOTG8Az~7VX3h(BkqhVw_#*y;^$1%zC8ht z(-+y?qmHJ-rzwW7+#D$$5y0nQ1Dzss-}q$rxde=P0ZL9$S(X)o7{^5+%Ka7vQ!reI z1vZ7=goSUyuNU&k@jZ^2j5Deg>q*PyTm}Zb8o^{K`i8JDyMgT$$t^6}s5fiamZ!>t zJvuFtwNya&^y!*d+?X091*_JiIG%T=XV+;5Fc=IBm>)HKpQBwj05nhj7vWtsH<}Xn z2q#(hBdv}JSf$}3K~{YO&8n`hS#@x_?zjF4LwR=!Y2VDOY$JZ{d@_KqK>lmI!z;BS z?`!e9WB(^n|8$HsS~H8~!Bth&n~at;O-q!GC4hC`T=MV9MC#`eej1jHxjim5i*yuHgC4HRggCokux{D>W2p5rs~F|YUYFyu`2)m=GfX^j z(CA>bslT6+6e!#cXOMTRU`$fhHTZmWU*Yqeau>7*jE#>0D$%5V@RbEjDSG?dZ1LXJyF2t-y)+i&zQdgU3gEto@A+vE1p2nh721MEt8U2AyZ%SR zcOawTux+yNYxP7}xidCCpW3h2AbdVK5LPid7%zQY04wRH=8wv~57q`q^QO%nH-_2- z46&K_4({5xB?-To<;5x(j9P>}lI{3l}()P?OtcxX#i#1Vls-t1H~wq6*}8)rT)`n%4G(z)*( z5dNGbMwk1eE>-USH7n>2d4xUmT$Gqgj>=V*j9%E9I?Zam-$q>`E3^k+G%g7|zc=(< zZD{yE=t9H7e{xMLL_Ph*B{*YH=>BMUeskH;;^@-i(ht%NtagTkdayi1-ImNB{)wim z*ZbAw51dr@8IR1r^M1%5HEqa8AJ-Pc_HTfbqWd9DZjdex2q$#mOm1AxMU{$(o`cnX zq@i^2TyW&fgA?lDmzTd)*IjFSh)b=|L(`u9@%cZ>0M}1RWrr|Muo%5Sckv7CzRLOg*$ynf8L(Tbhpr-*Pz z=tB<0(WU>={ao9m3dzQMUqk@6jpG#?qt@cQBUYVvkU|g&TfSBX`tkAfUziTjpt$LZ z^1qv7k~PD^__^lgky3##q7BJidK%a*N>SGEiczA&u>3GM74#Q1sHpc}WS02NdGOGZeD$0vGXF zFX2!|gj@B#Sq3p{ifB0eVTU(ys=_q1oMA}y$uNl*>Pnv4&x@4}9O~=ZoLK$8Ww|bx zVMgf=xZIW$q3zl)fvw~B*~!4k_Pig|{Jv(m7^F(|xdY`s9q27DPeA*X(}!Q_?Tjg- z=d(p=K6CFdBQj$$_+R_;Gw@*OsaGLl34`nqj8xrt#|R2?B+Y%0q^X=X4? zEnfEOzZ`=|yp4eO1h5OS@OC%j4bJ!N%=Ekd{K7q)!fd<-Nus)uUaw{qV#r_5t%LQ$ z27jq6b5)vDxe(onLGI}m3A5uT}z8=2#ADu909{s7h$*|>gk#{P55~ZIv zsZ`SLGE-Md2I&(+@e{K03JQLA&bj~c;6Kv%cKh+NDm$%z6?==8cHE5isaUo;GKODn zf>oLHK6VT{bq=TW{EfDfckfTp9R(*^CKgcTjz>gb@hnkcU_L1TRfLEddRX7WN4wooV|JYQM>Krzr zFXqtKe3{!cPenjBms~@eRUZnzmZ+t#wsxec1zTH2&5VR`P(wWFD{7-OdG%3gx(BT! z0exv7+iGuRyR-&zdvdAjIb*7TF`Q2%mp2SGL zrvB6nZMi!yKG`FhsVT{_{>8Qn!M9L))pp>ncR(NW5GxY^*MP{zf4gu}v}h#5=~zy! zLCY5>ba&!gwB2#LJ?Vf?P#0VimB|z4hJ}gV3eLktXbn}Vo$M2|)_^5qfhUi`h5tU4 z9&sL`&Z|fr+lOx4R;@cf(C+ z*Q&fl56~_ZP3paQVuwGtIxk<-Ya_k3{@rLB<>S#+raKVP8EcF!>EOPa^T= zRWLNXf?^~($RLLQu}3xT$?8YWr0;wkYJh)ctM2LEEg0Uu;G}D_n%L&#A6ZB+|7@Q` zB4_5oS`3{=*tP~gabSWQ1a1cJPx#+akozy*i?nK$!yI25&GgSglj5GuO3tI^$?e-z z(zyt(FWdbEnr*WiiQ@t95WnT30qNw`ED9UG&2nDB4NUkP7#Amq&8C>09 z41(TJ1nQ7H3H?nX8Gz&o?{$`3z*AF>qiu%0OAy#ER-jF9gsLU>WV`dRRZh7WF=1_GN8DS|=z z5h`2fmHys#Aav*m@=^b}n5^O>z~da?$Ekne!>|`}75hsPzK2k?ApnDf8IMea@JijVyk zKwxux|DAji(AwpHM4`mgb{6JMKXQh#?XzRJ)ibvdt;q9`90BmV{6XLABvnz!vKk0+H+PEa1pq9y>W>`RM@Zda=?2K)5fg(OyOB@ zRXZ1n`#t}cY6@MrKGoN~;9~8#I&uePQVCBR42P5OiaTcL20_3D@cIowy89s65iFVm z=sTvKeUuFe22~PlF3CuzBJ^{EMI6KX%W4+W=SFa(3?J`w8O8`7OYQ?D)cw9WqZ6Jf z(|%)sL>)CWQic$EHQy5g&-0ZAY#k#BJ*~q5!=@jl!Zmw0l$gV7;mbQ1<%cC-Zo6)k zu-jp@^m6;MFGF8Zo-V7ofE zM$93oF!QH~st;*?&ofFvr1Ktvvsfi2jCsD9u|eyV=nR3%Y*H~ z2dqQAKfvwoc_e~@{7Oi?C2p)J;{A3pQkJI)u^uATRTymg_YluPEvO%JNiX$=_;1e8 z#;S)8rUA@?8t-iLF3Pj&Qs|^L@3Kjwk+%0GqPweP!iHg9VPWhV+f9+`7&Ru2h^f1bTSLjzF#J*q}_8#oR{ie{`Ey3rRrt zevc_&wJ{#s*ViBat!(~6{nbN_kS47L$*4IT>S%>b-XJ-=-URxlIu<#iu^?A@g_z3o z%xU4Vv!n!@dNrj|#v?=9{Bva+3oa0mj{=DF4CRV6u8jG zJ@>5-MOTkt`FR}fWgbm;lNqM9K#dSV`e|HSad4i_$j2lBYs{wbs%^%7bn08Ou||9- zJ4aU}P3-FdbB!40k*3HfZ7AW&dTOy#!`i-Xp8edQ0J$+b&Cd5*Xo2T7q_Ej4e5d@N;7~5LC7ZaL5l^D$s_2LQ^YK6OacrJ6~ z?W;kaQU{{G^(Hp%^_7#~V*}E$1Gd^ryw}A=A78XpnUxG@wWI??ux6q^y@1mEZszl4^?oJ@R_01emzCp`|Y$|Y)M z+0}Nj950xadHJ?Cz2$vu9XwBpV3WEj4*jh?T z0=!k+F2IZ4pvUmM$%bdvuW0ygI!EFE0uNvJK==Ww22g$y7E=)Bm#i&%Z1gHqu8B&` z4!n=Kpx zy_3l!C7ZB9^Z26H?F^;EQjK(x6Otw%xJZ;wa}6c7aX59w-OdF24iloMPK{%%J;)~X zVfww`UKJ$q{?OmpAmeMKZ>e{s^*Y%?1|OBKkx%{+%~|D9-M92FbC>4ht41o8HkM!^ z=9-D14PNlgoUXppUBB@Zqu8`~yx)-6k-wOY$P&$y8`oWJB?ap>Qpo^AihUNl;)^De{ z&F;5`D4U$@g^+eQ_M3mM9-<>7kEbK!)6)W1AA-vxu=V|Bib9E((suTznB+gFRc{bz zClHfbP;kN^fxK@o>Q8qWutxphe`7;p`0WR7gpo>ZYL-WG4JJATkj{ADJl!y;ch0Oz zqVE4_ys~s!+j`9zle~+uz4%?W<2W4f9Gsmu-KVzwN~P|W_0}QeHMLqWFJ!9g{)-UF zI>X`biS)8-dF=t+{boV*lCpQHyJ9o)$RP456VtWhOA@b}Ts5x=`X8j{2@c7Y9i;|l zXPqh-6N{NYPI#S-yybas$%wY8IE&QQ@vv54`RPtwJ}gfikEO$_ap`wR<)C8 zoc784V&cK3ZsfO$L9^Jwi2dnX>hTl>dQ`Jtmr%M(>4B3~<6hK_3-4SB%?Qit|C#m4 zvzK1jx(n^!|3~o@CZxy7+Viovx7TuvZq5FfyshinEgUB}oIOj`PJr_JVeY;EPSi>l ziz4)A?2*`f?LA9Rjpz1nIIF_2ds>T9GD`Db6U?GKhwm_r4EKCuVkW>}#Tm$Xf{hSr zZ8YWAtV&Aric;qg&@-uwHLD{A)vwK;9^u{McmrE?md(-@}$u|v+%&NJ6#^HNUj8684e>#{n$kEHRW(i3&T^m*1b>u4|x}R3* z6#ZU;$2o1xKK{5nd=?I76N*P$k5h4uHkzbX!C$1o0wt-+yfdm}NTMA<;&qFmj-qAzyICaNs2s|OFv6qQD8faUWx(?zdx}tphuu+ zynl|0n-PU+gY&Adt~>o!_pjY%awUHoi==D&JbKE(7zfkM=2@J{qGO17*<^~2%l?8D8>VuN)pX_+bktZ@Z%rBVSH+? zI$2~oKIySKhN~p4PC)}3P#2-}fk#Qg{E>TssnD+^{8B7EDJq5k9s?foW>%R8?F+1r z?_uRu^~%rnRJR&{Hnb)Va*5`t{JB&9pSvP10za=eY%)?PdmH=wHW?$o-x@Q+4|E!i zyIcV8MGDP;m#ES-as%anwYN`v6O&2!5NO42?mBT6dL{R~7Ox}_i`FqFWdBE#w>Xb7 zG{(3!kCHcD&gNjO)vh`BP*b%$6)`xkmE&uaE$>^x7?L?Tnve|2tw}K6a-+l@)NjYt zat4}be77ib471aO`&8eg!dR z>}SRTy56JEw+mPm>SCJR{3#V2qHAO;vYY#Z3kHGUsll|1ra~L{+pQAeJl2@AUG9DgWN|{K%S6;!4aX|WFt3BXp8N`xT|!JvDA}bm7KeBV3GEd?9tLj@ zttm?e)4TQ3QchItF}y^H#|>fy3EqJN5Qi?0?aqQ{Qv0f8C=A+QcSlMUZ)ZVKo^e1sg4Dt>Sx4FLZp9_Od>A zY|s=ctvtAgs;26&!T zVVpHsB*wM+meCECv&>|^#;x!#`8nlgsgtP_OloX3jUT~%tOQ-(+Awf3%h7?!{ep7r zTwaDX|5H;1?kAa^NAyhyJUcznS>?3tc6!Hq0&Hq`xdz|LxmE@0ZC^w;(I+y=m@)mK zaF|9$UzgV?J|I?QtaX?D66L~y>Pf=oClk)Vsf z$ds1dPwn;X7;7D4vK(?!avo`Tnvs0d${;pUp`#lTc>^wop-{cikAOENG2Hs3QFUl= z4>{u9Cg*twE>NpWZg zbI{s$+fOuCwIRPe1K#Umzr??1;d^IiZSwB#=luB0xAv&X>zl?1m-p8J6#mh?qgU9K z)xIw9KIZ7tC5D4mF82!^^p=aT7bk;6)kLncs_p`xpnGKy?pU=6VZ;BGBk9zvYRjK} z&ElHuR>|-GuA#xs7D5jpJDOR*p+SGH>TmfG{@eoiXh(@~wz}n9pzHnB7tC21jGjTA zGHEH0_&FOu&&oSqo@brCPX{BXJllHWnixAjzOu0$SJ5HhQyUKZefTn~$P2F9P6kG2 z8J7h22{oXVxIA+4{0*f**R+WSI&(L)5GTzR&sNx4f-Ul1Vv%bVpB&3J-fFRq>o%XS zZz=okGP+w@6;`L{L{bjw$*q+e$cikZWLVL^3#f)OKdzL#hXM(x4eY%p;w6^}#~|E& zkb7G%8)2$aRecjKioxDo9<==toL|#K*1Alu3lq177k+VkHqTk=nmZ&8Z_5`RDOu}= zfl}xs(oWW9>Vu`@6F9Aoa#NiD2X{7~C&xVk5a6)Cg2E&ml32&sq}rUv|7c}!dS zWJ4lB-Mhh`(zOl(Eqe6mmyOTC>v&WFZ-DXX&gzp4iYnId3}1&O#Ji96j(d){96nZu zPR_~WJ#5(qxp{_&JUzr=WAn!pq`&_})uiV{2u&7P=RTc>l~}a7%H`2LrL|%Xc(Ry` z2yi1-$t}!bYaK;$YP5XVBM+(u$OpQ#B5G6s^-qyG`E+rV`rh6cSq9bl z7D*+&5jBeRMTSyy5u!50=BO=A`SJ@R8rk0Uxr^9@Fz#h$HoffJg0SGzCWmsR_4dT& z^{cRWfc4sQ-p%(*f^A9*d|f^)oQiQC!-vnA1*hbqLQ#u#4sfX9+`6>1%kXR~>-c*n zVrd*-TMzWB92~F4O(;x0a)0}b`g~4c#0hHK2So`^cT?4B_Dp}N=DBJJi^kb-zUILJ zxJcw(6azhc-==q7JiJt`?iS8`eBcDl#bB9&aN!nRZEMwS8`#s`YdR&WP26Y%y^T~` z$;>QQJY^}Mpk#z|gKW5mEmm6PjE-pThewQU!vH7H#*?v_c9d)Q1jnTB!5 zRZHq{&R74r_DyC%6Lep~An`9$ZesxPS_Isli%ES$3m9vPg+zB>W;WEJ#Z6*Q4UJxQ zqcVKTDn0SUF?gB^rD5OQt7)!qTP%ZP83a`^q2Efj4>=TPEF94dFJ*z>!7sy)zi%^5 zM2W23uA84YD7h=pIx2zh^Sn2#a0M%LuHYq-T%o&l;eZcms$Bn@y3&B=2cW1F^4;L$ z`6?HSplkaA+oLMaTo@1TxdT01U?3?Dfh7V>iJMokcek*G_AK~e2ueU^Z4N^b9k*b& z=T|QZ8sLjWSY2mfX>vp1OA=QAIE|0}hGqG_Q!#)lg(d!rk@HdyVtz1FAj8+gq~Z7y z4r9xIqUB3+d%=oCOyDM614zxHMTK+pTU48bOO2GVkpVHZocfL0*a18BTDN;M&ERs* zLId=2)(VJRD&M^R+oZuq9^YwEI8IwuuUFgOTMnRjfspJuLwf1HuzS z!!Gm6{8}o(ijS;`uUaYU3z?73n^fUL?=y3AKD*Lod9QPecfSrVR~w*+LRmse5(hO) z!Al?CU6B%c)slNi;?p~U***O-_6Hrdj6vlXiO9y|pxPw&3t?oeiKN+_n)Nmq zggN3@lzuC9`0;dhoOVt!x02L_y7JspR53*IVl=U{h6>Fk-tVMe)6;GtV>eBs*z z(e%*F>@Z+JWvfnWA;59W`pk|EJ;^Ne2Zi)HJHA*tKI4}BRvDDO@cT3oeK^s*ES~!q zy7fL+kbc<=g%%+(aKVtRrwn}~oI#ilqq9KuU)u9}CltD3AcV1{XIcAuu1A}58N#f7 z#&LguxKr`NWRSK%JM;x&k&2&-(Z|M<5(-fv8ygn%v?KrCsh9yk{V6ukHP|19Vy8LH-B5c*pewJ7hDq)hw|b5 z(336T;|{QMDkAAt-hp1b5Y|WyJsMq z!TW-T=nBsS$KUcdXysG5ijo5wk$fSYQLXpI3XhuJ40vrJX#MMO;SL%HxVe9W`jAiG zZ6*J=WB0_11|NKHyqON|4~AU2Wu19wJdrESs}0f;9>!{I5aN9Qj0^ZNtJ_A!e-P^; zo;E+>Vj4sI!%HMIFS0l)`5=( z`{%0A;Y6YER49Z`xw#QBOu4K!by8C{SW|{=?_AKIcC|cai<;-lFB31DXE40-=ZVtY zQDRvU&~O{jSa;Vup&3XQq%$Yi7Sfx6@EBU$>}>*sBwiQ?f+oLgZ2a$)n_j^v;L6m}a8=pCZT6lFiAz@9yk+ zZWp#1iBK=}@^N7zaG&kjA^Wvi)n0bfQe%BD4)d5v|6_^(eo^mnZb1dF!qN)iCSi)V z+%&RZvL{uspmvYUe302Pb;R0$MMnP#wO|1N=^#r#lbDM32n)4)tSEJ9h+9}5%RHJ! zIzKE@U_*x-9x@F7a%j(2KVE|}e!F&XL&ezQvSK0+$Cen^YVK?y!HHak#As`MjCGi6 zR9pZgWMZK_9(?-pp}^)#mlY;o8q9x(#5_TY8pKGZ37x`7PuzRFi{nx;zh*CJikZQ- z87STHblwPmy$<9+Sn%kn{(!W6M1Pp#Cxr06Q1eDD?k*QYKVl!2ur2+QHBSOzYNQ8E zSvs1w{rV5w*DeYdr-DoTp*kiLa9>=P>#LaLAh4GPq7HhWy$1otF7rI7=Q3Q2A-$GK zPnH(Qa$LEf3n;9WLhM~cEBcx$`slmV$}eO3xBR)X=O=pKIaf+y#(!^7%*dgahYBzo z^NoCB_7DSjSy0iBvGFl`S|Q>*)bZ*b7^VnL8(bbeuSz9jpYqTAfm3}Ai6j=_mrbG+ zrW*AylOe9jrD}xXEo7B6YWVEfh-B{F91}|pKc?({nFYx=h@Ki=>?@)kc%xMrSe`d4 zUyxjzVK=Be7PvyazVBub-}A#F4|?ioyZbZPorfNpva^Azmh(|45jA$o?EY)NKL-rsMK|>XY+-xaO3rHY--KLhy9a zzlxb#S8(S7(@)|B1Z!^RmYuaFdcqzsuE?O3+fWK9x5LerCe<|lj{b@!YiD(ka+;L03YDOwj z+MaXhK0zk&Dp775J^RFQq~-e93u(-mqhFDTbMAagu{I-0KRfD?5^AdsY)|Q|^j(sp z5Qem0Yl-yAFD1sL#SS0Jn>KT%%5xl&7RopgF(&BOHne=fH0T*yxID4R{&N3-G@q%!~69%Uz<< z|0K`LXLkC~k8o&_vU#ETobC#6c^`B@op)4CKX1J%m{i1~T9heab1@o|pf$XU8K4An z2OAL5mtpl)#HYp!Q7uyHiQhB$8`@%&x1x{WWe7r?XoV)c*2f@SBJI`K zx%SO%aXYI;`r_&BITp(IbA*(Kbe^_ADU>Wk%)7EZ4|FbR6Exa2#<8K=Nb)TqqT<(= z!lS1QmcttC<9*LEk{mxLtv#Z|OU__Kud8ZuvHn4_lBJNBzBw+yPC{&+9hUtKZ>-36 zCyu`4@Fcw6)<@f(S}U!(>{qP^?hmSDu?;^4KM5= z=`Y<)SHHCz;ZTJR=P^IhU9rA0%oujMjO&Y--t^C0p1Ewh+!?Dxz-z+r{`06RW`MCI z<7PDf8Zv~cgSYd+5jtbctZtLhx9SJU@Av1g>9XL{&_kZsb=bwH_!lWTTwRe0iQZaC zw~g)aiTrLJOavRe=w4_+-OdPlH#N6gaO61`dea-lN;KVQhnqpRjKHb+u4itjEX^9l zk}4){6%sSUJb#=3Nw|ZW_3Y|n{h~U0f6vXX_B?^p>c}&ID3)Gg*n6-vqt0>HNg3D+An<($7`|EA{$(J6 z%){7Y@0^=gfMy2PIknuX3i@`_U}QnaDO*hzNXGQE&B*VOCWu}Ys8*{XAt$8YL%piU zul_#(ctD50`B^{AZTG!b8;SY8S3Q1&rB^R47+FKNdU%=>Jn!V=XJDj93j<5vBFa6A zYG>*qVkod)7+=xK79TK$3!rA`2(T!lKtEa&kPe7Bun-Rt`1Zj!ANEn1#@5OSTa9~P ze9n1mmOXDLq|bfAajS2)Y-_D-Hao}?wxTvc%{3G=*wqKzQHaM8+Ofu7&s?_}-H{)u zLx9Q(=Ybdxzqs(uZ++*2eUl7OA_e-ZcW=3_TP*ybuRpVO=w+d0K`lc%nrbmM4Zc&? zRBWayLDLZ%y3j0l*C=PyGR^S`@6-9}HGzJ14ia3OH zBxoqyg=j>THH4cWpC9?tuzHk0`RWEeWu;PmUiaOzyVrMr@kQJ4zwKIiJAj$mfTchQ;06$;b#|Uwx*_t=MJykLsECMfF_*sx z*u;T|ZXpVEoIr$?gTyy1t*T*R+epDIBNIJ~pw4i@IpgM|wi1#3vLzpZ^S*iZJjeI8 zs#KjlVWNL`Uw_|v$cHBf{!*HGy-7aiyr*_4`Q)d!28c5?bP@~^OYCE#6AQ+!I_KNx zePw!AZq26?C(!?U?R&4y&V9?l8lu=4{Ny4Cjv7n||ELdX&N|sDqSr%kw3A4L!C8!U z_u=0qZ?@1b`96`49Hm=zbrU}1IEQ-)7Gcf)%Q$rg#swlO4)28k6hG5lfzxeqwDN39 z^PaRU^+AxxJl(g~gDqj|Iq2GF^!ejskLLS(w+YNFvK$aC&Tu8xtgq#pQxA?!+)HYh zw|4fqCdpbGxdQ0-2N4cA#@S~Ga0{uG1`^FcjR^|jBzFHT4S`x-+$T^R8?&P+B0c4aojJU27s?3!Z zOl-BUkx;5>arhdS3pHJl{wmDJAvS+Tnlp+!vP49wT5JgV7OZ(5EEgzyjchLXx)D}Q zcLXV0sU>Qn*hCfLq>T5%f{qhW6$MeN;h^G-SDrHc@KMXq?wz;aL(jJ>;@e*E<3|Pt zdv+k@tPg@AA1(sM-BWm*U@2Y`CBz1T@aY>_ndEN?c8qXkgJ+NYfIwNoFO*%@E`yCp)P&%a~qJygZM*ffLn z43l-Eqf{yeVu6==^+(?ZpNz|wMtw#e5VhWiPE$L% z=*4`ZpX9_Bhda?f=;`RJZJ;t>wV;@lu}Vs}_qy)TZ60a&d64~U4gwdQck!DiO2vab z&)GShNl|Oh#Pp^V&@m5v%!U?Mn2UYw{5cM`qu)4wUvqk!{Hu=4AAWpRfB%8UoqkeV zSRq%0XxmG}MfdISw!&!Pn#{n!);cyiWD|=LnAA2CF3ZK-n6=u>^qoeVIQ_hlR=uR+ z*;Kp`r|%X4 zh85Qw4ok(SVAj1;H|=}-_qu;#MT@B2{=Um)Kf5>ElitI@;Y26V40Gsfnt4PL8{rw# z#kR8lBsdC~nk0hbkh3p%=sA}-SmEhpj0g{2tQt~TH2jl$j^AmAR`yrkyFC!N@cc_v z*R5__u9S~74DADU%3ha3J0_)x)7?ZV<67z)drkpPq0jd*vOA8fZ;w&6UoUuATJ++= z`!Bfs!adrrcdzeJTMP7&hxgJah8Nyp_4Ms!S|A{Wk6d$E!yKnf14S*k0gBMJm&t8dOM)r&}5 zc=#g|8^>)TxQuCRj0sqRZ)-+OfgWdJ@PNg&ZGe=AC22`CQ`HgNiRyq>p;$;8){fVI zVe5{dsB8_|oq1Pi?QfbW77q7Af5-m*-uFUSYt+8!6OOg;IH0bc%tl7ZuXsHWF9yub ze__G*&;Ry$2e0@Ot$jyZOT+oMZGBN-<&R6JNaaeIlm!DBBZ5f^f>Wjiah~uza)jy$ z!7Q|DkwO&-bT+|cCZe5}1gphDn*y8WS=RK9-z$8=Lh}a64t&FEz=AX&+F>3!{paMj z2S08ARy~$E4XVy?X98;0|WX0@kB-gwP2Pd<JV8 zo_ncUDvuwDN^yJVd-5Atme~`t&c)<3Q<>-L`R3bubgk>1a9jAnm|Ji!IpdtKp4qyd ztoY7tE6^9+^NG*7LFSr_RWN-xKOJnqDF`CnL5LH4qpYZgBPaw{vSkntCTz@yrhtxp z>XDE}j6f9E8l_&LiT6M{@z)gY4DO0bghnQM;f6p^9L>xI(#sg^#-KM+;ra-KtEzUf zGBN(Qw5mR5rOXHW_j>q8D_$nad&mCQ{PqK-($IsczJYZjb9R(>F0hVqBz`S_0+#fR znHZc?6X!RkT)H@jdC=P3(fKdV%4D{_{*aITXQpOi=)V0ULk?bpd)z7`r)CQH2Hodd zXMJmjv5CTwsg(KQbS6DF7VKhQA=6{+HMJN_gKpn3m#I$`oERB@A#0`&KKaa3A8XeE zwtPEV7BC|Z?y=7JXyKv39`pUEhXu1Eg1KNWwUAS+x`@I?l(x(KK~c-AwHnrRC$>sz z`I@PmL0hj2f)fE#6xvY}f?qt9HPbuEMnsU;5|cguF3QA0`wv2tETJIx^NKrBemrLx zw}zH|8<^Whr`z{-|NI_T{`%rf$~d-!htg%9t$cV%?ZF{*B4eBZJXwqy^os&jUkKFyg`bD!eBzoY*h97% zMc}-1&fTz3EFA+j&5sQX4y+k#d!U5~Y}SQF+P|odrTIk#yfI)X!#06xg;mgEGEgqbjfWMI zoNyv^(9%+)u5T39Bp<2&b<9660;5F~0kEkZ2I5-g6b8(@u6q7ZSSkK*-nMV|t?c#v zyWO2^lg27c_JQB~{hWn`MZdCV&3Y$4#YY=PA$5?!lIKge?t7eEZ!f2&Z9mA1e*f7FjQ`bjqQ(b`6$N8qFF2r3I1)=d2 zvMz@Dclu$MGd!)-w5|4=F8J1Y?;V{eoM9OHmieCCJejVxa!|$@1aYwVV=wtWnc&rmM3&58SziD7u0(X;C`^7EK%bm;kt`RcE__uRJZh~ zm9nns-Rr@&H4!y?x$kn-Q)gxK=4nL)Q>KwuA39h+aM|cA+D>ZNnzr8Tek||$q$hSj z65t8HJ_4E0HxEQIRUe0sv9U#IHQ49&BR>9kBl|b<*g=L<7`_pY(tfr%DlR=)q-aG4 zLAe$NBwnc7PD@n(marBzML)Pd~Xq)6%fZw3R>~e|WDqk57~y9kBhk zdJxo}nS*>nR6900GG{UBH{xWEG#M7*NIG>Z>$5NMk=IeL3aO6qF_*fQpQj1>N1ENC zSu*tm0zC8}sM2}Gfwh7JDuG*l(e$fN8!7vS{GJbYeZKOiuKiu#!ij~y=$$?HgFG@t zX<^9C7Zu}Lzx;Isz&VhnDkxq#ujB}*Kt=CC>EH2JUi;yXPWZ%U8}_u0Eh(gzZp;=C2ZG7J@WHG8yg!msTvI?Hxl^egwInLO}R(Vd`f1t1UIc# zzB6Kai-X{510vB2G;V{0Fibh)hR8CTOxuHCr2FTcr=)-HN-jiK}k_<6MaIg2x15_Q>#p`*JC3(+pJfGVUL@dIBTyyZ9GV2p{Tyq$rMB9JIOQ z``CIGr%BeoFTOO7p&}I%&$h|~DJ~AjQ>5-=-P3iXGb@Aj=or{pEsUyxJCw_$OKHm( zt7ysts%k&ytEne?x4lvd`BmHt&-&&!_Z=TCexZM`cVm=w?TO+gqLQK%T+yK`Dw)hS zwI+L~7l(;067?l($c%5m62xrrVskxyQG@Ct#sK&=*j zpUw4L*SE(bcdg>{+%<3C>5|7D%?0F1f$rl{tzP!}|{ zwYJ24Q5R?^*bAdT#MyU#O zhNf87AP=FvG3W@JXGI^}uXyCd?HXQ_dGW)0y=AO8`qX%0=%W3zj!-gjLVX2f{2p1{^upzj)sHGWUGsb5qA+%n;9N) zYUh%2q49y%$Dzam!y!2ZJnR=`Sgl}r`KMa;?_BRw_ng|gnN8lE&pZ2^H5U(!o|?&K zKHfLb`_8zeXuWnC3-C_Y%;VXMgW@Q>Ip)}x9#_Ac7@rvFwR`qH?zH27(GD}->YN>c z0W_v#bTjkL&?^feM!HVco1%}L!EZE6i@Mb$OyR>Vv)5`z%+A4cP2g#w*Ip<=Y>^h_f#dC!~6lOxiFIvI4&iG;p z*ZNodd%masGdyT7c`;BmdNG?IwxWsb4QSd%hzf{&DU~HJ9A*r-8%+FO4@>wAHcmd< zkmV>r0Cy6fc(CT_$ZFAhl|qUg~siaLCpGQ@_U_{ATqj)U_p4GR`nUj05 z)pMJ)`=5N;sjpse@%cxZmj1;>uPuH!@Pknbw3w8JLabW^dA&f71vy<2u`iv1ow)S& z_4W^q51-vGbKP=*KKjsZpPKNkJwoK8F{n#}ijuYP5W~FeLL22qLQS0f?G)lPu}2Z_ z&|2FC#cA||RtK6Cqm(7`jz^_5qv~f&8$y}aR9^6`7l()cHxrc4U;Dtv_Uzy1CqEq6 z<-yW4Zrybs&1CZD`;PL03pwr*Z_?Vgxas~l*a9@AtYwtKxc^fBK&C01!=eXv*wfRE z-3=@%U+qU!eG0J|6%lbx^Lga%se1|GUiYf|Tl{{0R`>0tUOapYmO^OTF~7pn5Z8j_ zgwLIQK`X6QfqG==nl$5jwyM3b;>Zq*}XWS>o~b1 zRECrn&}1D0nz>evv~;9vDLzVvf)+E$4IUa{p5#UrxfPTXzVC9`lQ*RDnFD>B={evvXmR<}lscv?()zIka*FrbqMLqx{N|r& z21ftBY2*8IeZ9M>zJA>CaC_rPYxk@x77H zy;c;bZr5=&q;1mD#%Ek)AVj5p8Eh9qv!6`o6yHY~F0nA-&t)5w#&92KC|?u6jWS*- z|9f^%-xqtgyQynaH5<8pzVY=lKNtAg!I`|hS-t7KTQv1JZh*p@E(i*EYUXhUK+KIl zIx_a^yuLY`9(m$X|7|4xt9q@L3iPoD_x@-Q7M@wvPPfzhH5Z$)UP9gNT5uJLY6x>9 zIod_FGlugZ6$fTRMx?7C%Q0zw^g(0m)AS4Wb+Em8*Z}z+(%Kr~IHIph*#6Q=WpVIm zI@fbX-##*Oy%F<%z?IJqObpL|B)j%n8;zJfO0P2kO_hFHSbvbGUT|290a_;yl3;05 zP#ne8qm)T%pC$yD-UqjvucNq7FiS~= zi!q0eGNG=CYXwKl-s8?IS~;dpyZ5)wKIa{a7mb}Yca6bqv8el|lC8uhX$rhJk3Bwg zb$ZZTT-}ayUM)CxpMK_P`?PZYTWWHjD3!n1%E33{-XR2eREwON3RMeG)3U}mg#>;V zhOi`Xn}>ilLU>Ba!wx}C_kshvdIcs!4JJejsb_gqkkhd_c~Db|-t4h(H2iLMAh*91 z=8c%C=o+_t>7&DHe&9iPiBY+)2mzwP{0{dHE7HMfn}WbIa2jWxKX^}}F;ajaqGK{w zt0u@Ny9A*vSW%;rwYVC+%n&}Tc88o*NKOiTllFbs`AwmIdbl6`_bJ7~{1+!G|LmR9 z`|ZY!a>O*8Z1UPGAi_W%Im{0Z+?lT{UUExBbsUH4)9+(76 zBFy@XapxmOUp(=h%w-4WsOk_AFX=s?$SwTFFzs8Lfnzsc^DC#F`nQWNJ@1pRzPk7p z&-Gu6qrEA-`F$KH#-ABH#^1%{G@Xtc$IcfIE@sBq<&tk*ynQRj+%kba^1v>itZL?- ztsHzK?(IW^i@4S!C^ZQ5C}@uw8%R598atz@4W{6*>=)@VRXZx@X|lvAv~pa*EsY94 zO|@daoc6pE20s0(BYSrH(NH7$DX*~vfwXB}xM2R!|LcdA>@&v}MNlGt7}8K&2ncAd z%r{_eG^Gj!jD{E8A;Q|0vphU$1fwmV1{$3lJe^{wN zxI@5$#G?W$O*k>OAPoGQ?>TC_rkIGm;_wk>F25`2*1(3vXyzjIT;Lp)5M(7hT1HTRE-EraZ25eN$oHtktf3VY2Qeq(mCR^QHho$D&Nq#; zd{7yhKdSOpXvfp3|Ci4eGu zd7_X7=10Q;Oc#M(`*6;+7zs zK=HbGQQ@8kkKO+3&46kCJ=<-8JMY(H7kFHRK*te-%y3|*qs3tgUraN)u)=FbKKrN= zp0FFxZGpp)zz|ZLX{*%QX?|xpCUm~W4vFUpIEn&9Mvg_B?jP9WuA5hQL-~ejA#m1N zU;7%0?wp0`l-A#svqqs_QKg==1O0 zekavVeaLV+B}kh=Y$Agmr&Ur|LK9ASSyk7ZOZ^J#I41*I(`+cl;w znHi-zQN2AsIJjfaZVx}&ss+(4_kHll&97cGT>Kddg&=*41%D!wuOT?zNx=#;a83JW zU3r~ax;Ts>jfdu8VG^cLr#4AmeN?XE!9Wx&gSKDutp^Ud1h5uxT?hBj;j`AkE1!YD zpBNu~dG4H^rkv;(J-C}*9bJ4xUoP{u&|}p-tVm>!Xe1|sK&N)@!(!Cx7O}|jAY8L} z2rCFn{nAyz=Y|;{waS8wbij^9ATMTKa^E z@zU?=P3&<*I0bracJFjdV&=R!695OA)bPacVXYc>O9Xn!t$YF0lWQ^JHt8)&IpfA2 z5obhYOlt)zut^E?Yb|KX)mYzJkitZyG4QD~WoO*U7p#hU&b<8|+plNGyQPVJh8D%Z z;G9d*0ES!_a8`2Rd;u_BPCrh$t}qBXO-;6gx)Q@o-dAn1jcmxY5U+9R6MD9;Kn z1U(vvzOI&Wu!C#GfmX>iQW~3h(e}M>-Fo=PCz>%_zch4Mrgv~}#%(y%$PJL_fPoR* zsbaImi4r|*ea#b^+~b^e;y^2g&)~sYxGtX)gFb&qa^mX3UEqtfHlkQoN={zM>FRxb zyWjqNGjNpGTs8tWOA897cUrjA`XD7FUQL7#X9To76<*s!Ev-&49*$Y_=0bo zzke%+KH~y?{K4(_u`}uI4G(5OqpuZXZszhv zql<(;eeN{NFDg|2p4Y>}XYc)^(;C__d9f8DaOYuL{JLBTAJMBIG@$@7aM*%i*RT=s zPtb7bykEC&u6NWjOD0)4;>e(QEHxzh*|`OW#_Gr|BlGDJoN zT_RGN=(x-v!vI#UKoCmtz=Yg^QuP;hI)CvBCtJRu;Ru{|>M6e)nA886*Ir)u7){Q6 z#f{GowfAmlF>731TAR9PZ1It;82gM1^sz$mfLu_{S@1Qos#M}zExMW712=pFW8#ZK zotvf$Wv$96Nc^2aaVDeMu`M|WP8uzn|Lx1A4jSD3o*NU7LqZ48V`a{$6srFhiWD_y z>5y{N(xZT$D55<&h}CkSsjb&B8VNdLAsM5%3E@uRdu!5?>4>ZxXhKU5DiltEGXJ$j zkFPP1ZaB4TJO%#5@JYS>Yj5sU;TnKuPET_PI%Ny|^^}ZdXAIqioru1M7PnBC&v6JQ zk&-aKN5OGIm@^Pg_|9Q|ud&!gvk+Pt=X(1Op1bRvPbM9M zB=`UJLq7C;U}tWE-Upe7d~+Vmps9<36v8CU{PDQrxnwL+VbmNz{sXG=l4#5R?e(W=Fw#E1Z!BO zRDQg7ulsIm^%%PS{wJM$(&9O5&E9u-!N?=AFefIlIXaGZ7bT1FswZVhI(GF1YvS*D zut}%Wsl^k+Gp?o2s6a=3fZXC4K@@n;p3&<<-m zfZ8>5t8iT~5Y9o|qWAY~w)e^wcVFJVhQLWDois6f-mHCIduje7JPcEa^I78eu{k~# z$< zVXY~Rmu|fGm~F0^evg-Z1*f>^7$Y}pYmcdOSd3b&G^x;*1gjnU1Zz?N(>q;7JYlxD zElJ_z!8Zziqqfc$gGceyC?2>PD$sgtWP>0*O~eCaRR2f0-5!zJd5h<-{`M!Hd}3+t znzQ#``0Apc#?|oRJnh(@UT=o)Bo?`;W2tHDnTb+iM#w^M-bZFD{&aF8q@!HXb-E6`MglsPHvW37!Y@+n4&b|KW2<|)BQ8qy0r6mHUtwBi;De@t7MrX7q{rqA*{ z%SPa&lTRKSm@{y|(83X+utdS7k;Wbq(8TrCI|0MkjSznoYq(aGP6&BDeAlJtT=I^Y z8taS+^g_km#?&TEaxl|}=RxvKjT)Y*K{xU~Q85+HB6JBx=rS-$_|-YSi1M=nUh0aI z`B!gW{`meKZj{2jkrU9sYt8BDKWlXH_#aZRsdH9odY_zM+^0TQI=*c{!XV_WBg-5# zvhcb?pc_aNvpn*)Gls%b#)b>OnKh7VnlOI}Ip>u{^AGCH=RSx~Q)sj(HwwOa4FeGA zbg&MP9yM|oFqJMcwFeS*vxblQ=3*0ZapH!s6K24KH*Pp=5#1|&f5?=@24n^>bz-bTC3QhI zW1P^x^DXxze5hT~{l0Ym(uEV@FFX%oSx<@D-u0HGDC2xdAf%|cMxl;BSO|z?N@9gp z88b`X{<0Ywm)`fKEgxibaWBIUspsUpH%=sQedX!_lo4l62zbEnzjX>beLpE?yxmmXap<4B6bFZaU(W4$|=Sxe&0P`(;gVZEZv5kRU6%f-@ ztd#QFV(-Tf9=T;xDM>3s|NS4Mr+`58Rvii9)Rpr2#XAF&xbcR6J!_pzMd)2Kn?gE$t!DTKOwW=@)Vqd{lU;^{U6qBiGYE~&|1InnemQpQ+-&teN`@Wjw@pWV0A35X$*AI=9Zw#pOF3o1Nnb^DzKhPWa)1>~z#UK!t{<P#7@!y6xq#@qJB!gT<$ry-W zC+nyn$$(%-p%oJu3?6cBQJ@sna9w3+{>Za)X7?S{Oz>X5dx!O%iHY5HyLato-ly5u z7L0muRgu5l^KmFahJlGlb_SO6_r%z%mKF{4rXT9vUdbQU{HXg zm(;16k`7o^PgjbJbVthD_|VV`y}9g(w|{A?rp|qNV$s2w{=rWqeSUBr7PPL6!q>sF zr-!U}j@W!e>HAEpBWX`*>{-po$uzYDPxh&&pH!W<<{C#Yn7{CE-2W-qyP?IJJNJsQ z^7uB*9&=L#dd07PT(`1o(wqjLWSxc{F$giOC+UsjirA2Jq?}h^c1k? zb^r9!Pkug?%KQ*Q4)H07G3p{Moq|1`OTYEvvo3sBGvRNlKrcGpw&0bXEtGLQs;piW z!ldToY2^t`YXhdL>4NLRzZ$?4Yw>WRXBFS|A6GKH7ftuN^7E}n;J!mQSXfn!$85M! zEbF;C^ zX3`r4I^z*kSUgBICC*A}83$yPvQ=_HTGejv-Q%bCCViZ;{}BRTKl6-pke~i@e%}pR zdhBB60VbQv&P7i8q0L+iO%v#25AQO^@x%AC!kEvpku*%g|48y2`qV`hO*2O}L)Z48 zwlSq9gqEg+J>%JQ?{|8)zhQWWZZB`sWCXHy_UZ-mho6TF9js*rSPtRug%GC+-h(9a zwF;u!CzP>;)vF#ndYh(~z;#C#9G1)5o0HSrMS+r}HwMYFnwls%%o4BUaX^&57r=Ej z_UbRJbkF%oAEWI5(g+OBn)Bt+k? z!y3=fBI!c%Sh)-bR3j)Vix(Gfd*tLDzSL~kUc6=VQ**NhcN3&VF!fuaqFV-7fZv3bN^Y@|lP8yWYLH14bx^P=~hhC6b2>OBN=E2HaHCyJx_t_s!(`DF*27YeSEV2%SIrNy>jv5k;l6M zpZY>I{e%7Mxt`Osbk?Q`^znl8K@+}5mD&U~bUo50Lj25!Hz@%Tf?pqfr&h-A;}(CP zCL^5Ir(|sNroJ6-_)|A5&~6*!J%@gvkV*C3m_aRW7GB{>wm9#_u~**qrZt-`%wM^G zm)XI@@IhHyUEkC#rCddvJ-%vT@&$T`>WiT;wcAXDfw|pLsuky@-u$d9dw0F3_4Qr5 zZL!bLcuzd#=&-+k@VsK7_*(rf-0`*(V? zu9{<_f=_40Z7L7e)gMp1v??JKn>YMv!?Rn*AH=Ss9S1ZG>eAOQ4+sRI)untYd0_TC} zM)a;pZy~6rG?r2hQ{uVu5NxOg)t}{edq`%9Bz(_kDL`T~E)AE$Yjv!4jpVH0AaU#j2jsC>G+Ps7&o} zQdS3*{!Hd)Jv-j8prJRG7i&8N`Um>YQOCz$Qc9(TYs^~X@bB)o!Ec(~$yaXM;)GOh z-$A4Z0X~yKpYql2xKls8&9xRl{ZXC?z zKYQ`MAGp8Sy<2$Cj@t*GdT38Z&-e&}bFuzRgxmYxxS($JVry5kJJQ7K`(92^Co>)a zHSQ|;OwaYbJKy`~Cf-tBx{VMx<&@)|4Se-?v7b36ouPp5gtWG}_Iq4~jb&srnar$8 zwYpm~rlBb|J0}R4htCy9oQh*{}u2x@Kn7MXvdZZ2W{iC`1l#D@B# zo=<%Lw{1TV*};Y&aPKL5H$63t9UXpf&vna-7k;&Opy#cwgXAtXD$~na=KO+Uz4({q zPZORg654o0Nw z7wD=QyhBwDbT-O8kA!x_;l89LhnPRkAB_7x$wQBWilw@*&fWFa-!)@mFl{89g|4?Nbrv)uq3 z^`ua*bzjt#X35D$52x|htFLz(`$PCU)VRgos{W_(ca&G`W&{@8yZa}qj>_iG~q3+PblMyU;9TkKlt5*4@Gu=8VH!?GXYanA${Y<0Bv&z@wVFO*lD@vzxS(h0vM(7&~YfKlx5axjH z(?WlBj0MbaNV9pVlzOSE&yz$ltBkn(!154S{G)x|85Ty*?oAE9D+kTh#Nw=~rczFW zIn5~IWM4vcH!!$6Q7vX0uu`tov!!I-4F&j1dL`yP^nmPlg|ksS8_Yl)+h*BTHVO= zMnTRPsdh*v@iPn97_51~a>*=mW9Kj?8-FpCe93u2Gwd5%Jq~&Q)+3Nf zr|&J5O7pqbc7iY`qV?%&F~St`6zUbXvTmbMZ>T`8JiK?#an+oN3@2CnB>PI#?Y3lk zT}JAUa2JqMn)R5mX);|+ObiJ{u(<}Ht zg$1lPkgSAxk(L$-bFwXRJ(5a|Sr;`^WE%){6FlsZR*vvJ9E`o%j)F9K{0;&hE(4eK zuQ3WkXkUg>bdk7f_9$*89Pi2W-8#6lWQ6OUmA?Fuo_O+c&s3|!vo_QD$wB*nB#?NF3!;wn@=q@EfSJ(Yv^rPgy{?YsS0p?WNeRlFG_=E8if>F};W3wKfBEri&MQa|~M ztwuHaWWnjs+D4Kn_DmH*J>r<~$zLsmI{wCjOwh`~Z--|GzXNq{27W|$bm1@5O#gYU z?Y+EvyCGoN_Wdxsk4`Fu?bgB7=uhl|jt?j?wQV|+?z!~r^BZb*Z>T``LS;SGu(Hu) zpn{U1rd%S_C*^mYP+tvvn)Hz+n`7+xXAO6x;DMSlGJAr9SNI4$-y6lL#@9vKle2gHKMVw!Rn{M7FTFQB!A~cF|82 z76#C{@@0^V!b7$TkHoCBh|&?_F^VxQM zPn>ri`_Jq92(x?23xanvvfm9A=!pJagCZ}Uh^bNT;$}4&ADP|TK%iq&3|ZTHG9W*O zBqGC6VKOvO*D*36(x7N6>6G}Wo+aWE!}&VtvgszNb5pvbEL9B zE8#&n@8EBH;;04!1$p#ZR?(xGMv?A-s6Vh6Fa?wm?o6pus^a%94#@_B zNL9Bga$X8fxFFTjcX@8d8{6RFpJ}w@{ZcWm5jggtA^goxy2?kq~eVr#XrL1{0p%)*rK zkq9gc0py#1e5B}p(N>1=xYW29j0%dc6e2+#Fv>k6nBfpkhBZmMP~`TZ_6zA433hSJ zY<-J@;ou&pdkS9-M!utZ8XMx;MP$Aup7oT1l=?e!yWI6a>w7JG(5?uWy52FhF=9H~ zI3}Rp1W){3&wEQF=b>R5`shzSWr1coFH&rlQ_ohUvWbE%?XeLFAZx63lc3i8mGn_k zr3koz(km#;?+j2vkX)!QZsa7$YjqC-iy!&qnb&Y9Jxy(xg;Q@lQ`Cj^XvyeQPl zFjI56r4dYqSDeqyNb=f?)+E8cD9rCL(YLtKf*=Gp0^eX+kF<33&VYm$yf^qKgatxD zrpUzb`2QK1{oDk?xGwRJH zu{paP(rjJ_ut-^}xBf+tFyB1N0j9Z=8!GLJ^y@GvNtd)-&Z6;9iI)h5tINC)Cic3Y=}T{Q)2NAy9P~&_Cle$i+IiRz zXX2oY-}_3zw+sD!{TKJ_c=P;L_gUV*y%ErL?Qhj;b-Wt{I?AY~8aW#c6X@8L!1Ac3 zRg$kz@`=p~o76JN;&6ta+?*OYoK?RT1CB(nQB8Q)UqSSpFESUA@d^P+a3vH_MNSIz zRfoFkKe6zRPkhx(_wQ@r8Br0Jp+Xo6q9R6$Gtf;0yD^WOk}&2%h+v!am)F)S56A70 z^%=#u^AHjpF4#{GbhSQQ228U{2{I-Nk?qC%dw0L*2VK7iBmgT!;MkLnf64RQu82_r z$9qFdm^bWV5ZxL03Gku}jHGxJs{cmw7bm=|aE_bz2C)&*-$&DWq^(D8bZ%8qbg}S% zaN}aS9T@u{(1)7WA$jFaL}20FA3p>o(vC8fLfS=r19BRe$Tjyhrl#>>v1`MoFz0%N zK&M40vJJ(tq>~3^YVUMjwY?nt|WB=x3=K{-^H%>!W!|SV%~uQnmq8Tx4k@sSJxQMa+s(T#74%dQllra+%Dn zJv-d=$CbfKzDFWJ1dxyJb%j7j$<9X3cq6529*2#|9CUKAEPq1c+qQv*!N8)|6~Txh z#^!{LR%FqFG((I>Y`krd0Nlt`Ag|Rl1cn~ob)Y&jd}=D!w}FZrY*L|GCjLcSh8HrL zofa)<P)pm{yg%~5y4yN8|b^ff4ggHeudS?QGT+! z5I~vHHqiEF1oMUplZN@wA@lNxPBfUs!suOb?(h)pE@)m&#WNy5HBEB{a&x$^`6^O# z>dTeR2!2y;Vl1ddnuRTXB8Fzn$T-3bv$s0AUwvLkgbl5#g`D#?t4YWFc1$Ajw1;j z6t5mMb#<;{d;T^3yWM`cA{J6S*78&135X(c zqYW!^{Wa9mFpYU$@d0Vl^uq!ax@uuRM!vml5`pC-@Y=oGeA3ghJ1MGRVATlI`J~?) z0x@P-Yc+<D* zjWpUQQ%CNic=024ffBvZ15A;ztZaQ$@?c00T9cyi^kVf03pyDdTME$KnEQZ zQrCj`#1W@^5siqTrCl4f5R!Pr{i}ndM&iN#3u`EXeQe#g4b5M(T}LDP)mj7=-v6<8 zRELMZlJD!;E@ROr&ZA+pzG5pCtN4XraBqi3qNMo1G5G}0%ns?zXnM8gdWs|MNgfmN z$TQv~5Q3a>JqDf+zC0XQbl-iTf0vu?XovC1J|q(X4+MR)*B_pgtU-94Em^;g>bP@s!AKE@w zUA*w5-obg>DeeTbu|)*CFky>GoD;2#F<+zBG+q{DxskZ z_Qc3`MU9?TtpH_Fsg>(q1=mO^6NS=qsovRVcGA4cvCKRIU>%K#8D{?GGk8aswcAre zhgo_8@2xOvx4|a1)O^+Q(Bn#0LZga(1vS$&@Vt%UdM`f%2kPzL6Pt(?JYm3sH!~_oJkcM1fOG(QWr7WO&)ehBvaGg!Tx~)GmernK$%mq#`C#ZSM~4sgO^%3B6;hCBXHUI z7tIBAcsk+3SgG!VDXyXB>xOCQ=zS4^3}ucYiVlx90MVA?FJCq->`LL#z&Aw@ypBq< z)@N!WjPzr*H5O>m;74~IcXsj7LmL{M*uVkFOSJ%j7jJyuS2Kh2jy6QqH0Z2aMr3zH z7AYok)*c0Fvp5(oWyNYif0x{nZUMfg)K;&N!-Qb6V*p(A9yXHNFbjklye$MiP3}b( z2be#sf{5np>$geC5I{nZ2?J#`gS#zLMwQtkq!>UufDbXn?3=GU%1^d0lbSMJ#K zVAZe=Gqfs19|FjrT=djkN3=8`ztLSi@bS9AP|J%+mMIeB_{XA3iO6) z=xV5rL36D}Y-$MmfkrDRQzcKc~8WOYE+u3_hqcDH`xr&nGvNeC>wZ<{?bx^^shr{7Q4jIWTK$bj&} zW<>f^q4YB6Jj%d{qQjZS7X7SGnz36u>iC%yT}OyP@*C;@#Y&@9Oy;RO{)*P*#@1v%;d;cgutTv zxBj?S8a+j`Qtv{>W<(QQGfA5idcr4-H52D_W8H9#Rk566ZQWpEcdJ`1P<3jd7pA9) zF=@z|_Yn(#Dvu_}7&MsZJ($^8qK6E#}XhT4;)#Hbi$Y%rQ-M>7<%-JGJUO) zt1$uBTJ+$@KNyUSd?V8{`xBwV;~%nXsD-l*K+S|6m)_;d=M%vC1+iJ%hbf!duZR|B zsnHfUx&vaDKvdp1ijU)gBs#oe$s2GRK#(&lmFa7WnN~_lucEvD-LrPR`=(|M;k+|1 zIJ8;Ume*}h1VAXWqitKgjiy9x&(Y#}Q`LVpvTqF)=$5W7dc8*8$nG}hT0(dW!A_@P zlsjDCm|_&A;W4xqe^DJu`8TVoyLoeZB(K_z2rPVH+jmsP7JM~5(7Q_zmSK9PK#n-t z#j+55=LUpcZ3Q9djm3Q;(HO;#P&pSBjD*l^=;OCqkkND=r!L@u90OzUpfww{YUA$DVP=b>F_O^(UW|=(Bvw^bv5~ z>Nc^dz0*zZj^m6Pn)Z+BqqgJ<4c$=;O&!LGLqsx6PD))+T+Ejh-M$^P^B4%iP}9ci zTn60U1l2A#U<`}ji;QAc!P5OcGjz6YHE-B=`y$I zia{N7t{M25LlDJytg1%g4oy7fV(@fUM~k%I6#i(FTLv0^wGApn3Qb%{@rcnb*3x5Z z8o3u3(XKHU9f5GPx&@`N=llPEdv5|SXH}n%zx(WS_ar2&Zq>G0MQcTBQB;IL2ndLE z_g}SQSwa>d5JL8ykbr1is-h^$z9VSs@@uWu)@pzLYAJ#&+3$Yu?DH=F=Q;13o5>}R zow?`bGtAA*JMVkWbIyCd=es@MwzjXgpLJ(V7b7|Pw}1KDa|ZH*pN=JCuk4te zzUZ0fU%2;6TfP#Xy0b&ItQH7tzj6C`4qfQ@tjuKY z$vzGdpvq0GiNtfdnMx%D!y%_Asrx_bn0N1^^=kT4&pfpq0k(6vu=ADZa?W}Bh3D?N zW#iwgRMC2YJ_W7|0XIL9Odi9vb~>2c-BLLV1$b{Qp|7bx#~}Q=SSpNAi8UD^&irkf z84=(hB7C8dP+QRvRL0M!sZ90}`aYp$(KJevDd{+odW6hjEXV~cWbhqA>+)z`MT(A% zAfcG+X>orL0USebo$U6j`_~tN!AIVEx>eZql|-lZk-!>-1`aLUk7-spsYOdk%|(54 z7f+FI79e~wpaw2zws1a!@gH-B4je(mf_X-*zJM5v0;-tsd9eMOrl3v;2)0#_#9(f- zR4R+cFrS_;k&lk&fEyRhw(*3_fT_K3o1N&nWXar#pinAYAhmNgzZFdG)ivF#tq$xbOzwp%u3b`7DOg*9 zuIc?CUdb|;Y|I~BF=2=1yaR7H6?}+CJMVWt^pSTR?KRZzrzQe>AAIj$7BiX8da)Bu z_uMYb-(*Pt3p!L(BM}0+*$=-$ZX+B7A_z3hF&Ff-4BFF?wgxd@cEQ(P8u~@Lqw6c} zbML8(6>j^+FB&^`@A^9@;>al%42-QK6C7oiDYlBdsovX39L6++p;0hxxVz;L#eYL`Imb2dGFqx+h-lu^Osx% zx!}n~o&TnQ=V!;ha>o1i_U-!4rZwB&P_K5V>oy*NTqgVJL^3f8#Y%+m<5;%>Qye!Z z?2k;tlLDS|I~Gm+Z>^E8sUV8Yy*n4N?Y%VD2?36U0iMN5n=4v7sU?M^=f4la3tQ_R z*7^j~iz+9*&Nw&n@_X)o_g@=D_XecHo)%%1Ju?iB6tNU=h>K`;2tT(K1UmXc z|Go>0gJu*&ARo)8^2wzeDvFJZ??ISm3g2nJ@W*wFYTvM8!+Xq_aW;a4A~dmcF_(+G zG`%~HBNoP4$9KPLU~u18*R9%mMkD8ix>tP=xaG!Mja)JNKC;7AYv!$Ba+lgU=Q0o3 zC(Lgc`1Jp(HKH{Y=xm&$2fua$Xf%uvhyN`s#aI#Mvh~o^t0`e?-Kj=iuPst~wO`6# z*vNaTd({tt=kI#kWx7|q-n0{Malk*5On;l%Td`Zn27HclhUElbn>v?+_#mfaS^q+^5g6TaWiG?iMG6m9hj&i=*7#z!p z{*hbGf8Z!DrG7q%2t0k;TW(AxI+n*xYgSMO-D!+$Xjw=)XbnPJMg4D)l1A3RkeJ;>p-Crc++L;<|M=*Q<@{y7fa~)0)laT2cFr9D9zt z^fk9)wY6$@0yx}j9uODG*cu<5XW#z<$N_dU_m-UJ;VmT5Qzb%Q2E$E(@{vc|{gNNo z;#dGjv*k|>|M25IM|(Z>`^F-$>*4vcp8V!1UypaqT&R2bi0(PyERShLH?LU^g5F?d zLgEzWG8P+ZufkVkg6$32=#+#_e~^Nf0dQnO3>gz8{i{3L_kE|MXKTH>c+19Z*6w}1 z3sdc>S4r)K+6)CY7k82#`7j=MBXbHgV6&b7a5_E4a!liQE=eJv zzzCwLN)VB6z@#Sr&4_n?S<@7}#*I?doyvMU7R0QUj_I!tO4(0LN+Z-wCxpO`hv&U6 z)3@ukROjqZh*G8|g03)W{h)}-V(`^+deRIHTN8cEV(R)7=C(**D+i*uU{fCs)MHv4 z%8U~LM}#E;|4_rdr2Qe*+3}6|-1`UX)xo`c_uhQWNwd!!pQ0qAf<-Z;N`$)%CaO*Y zlBP`g`&4)Q!kv3}K6cBN&%d@_ZC2N<9RizHZ#plQj=z~>$}yBC_Et5qDx8Gft4E(2dQBGrQYcD;0O3AuIOl$R z=m(#Gol+fB9f2JW%$+whlD)O3D|tr5&todawXzNdI0|wEg9*-c2sVRu_S8S>`W5vfoQ>h6k;bKBH*I2f@h_RQ2dtqpk@OjuM#TqS2@pv0{Hx%4Zff z>elK$6GLFveeYRY_JUhGQ$6ppppDaVZh+Y>oU0Wgh|0eiASSr`F_%S&QO1E7dCfDC zhi*)r@~0C+0-F|C%?eDZK?SvPA+I?WY!ySjk6Ed%^%K43p?-JErmgyOJ9aMa?Cw17 zQ0E@%dkS=!&c?;FP$+1L_QdNl`H?T*xMAChL;YTTKRE~>P4N?LU2P{%&fOb#S7~jK z?}AUk^ZFMpUA(Ivt*DDYHw^1ZSnl>R{e{$*Vxbg^W%K8qj~@in7=e$$fzQ=O)#!p& zENh<}{NYF6SdYO{*F1Uz{_w58{DyBE*S1B<$Ho03#B)N-Or|+`J)$`e4bS||K=^X#`gB@{cJ2A z>u8~F9keUe0$s*{Bx1>$7G$Zuaa{y@`@H*txMM#bXkme*0E?oi=!6B4X)>U(2&3Hv z`Am}^9t1l4uAUwj4A?Q#ePuqIS=!{iYPseQJUahXzrX#IN8=ssA5S7B&0+;yM6r9U zXO6jOQd6f_2zloLwq~B7b|n)WW-PRGL4$^E1U25!r5Ax=79QTz^M2 zp8jIu?8kmuuL-bu<(l{Dap!!Qo_4hN;UdYPISO(afF%D-zhxw8eek)RJ0JhT)-SZY z@Hkp58}<94{=TgLSqD*jUv0_aJb5QJztl z+ZhN~xt&N|lAhb)$8dV~yy!15bSTgY_CTb=@OFp!dOZ-`F?2 z?;FuB{j7+dMFa=xdq5}~kl?apXn4i2<~@DpB7R-)Cscx2uqkzMz9?K0#32BYURB{~ zKC;$Kt+PSQruk*W1OOE;m%B4H|A{ZvtA#gjyvf+Lw{JmPN81TBl~a?h#leMA230Zo zo$fCRbs21x?n=D-*&WaQWZRZoPOZiL)HNoKz}EF!|2!WQ$qEO9SSw_SygU}w#aU=Y z%4V{=EZury;t0O{FY6}I@reD%cgvMrJ1&sSNDnoeRyvABaPr!w7IjKk{}CvKIf@L~ z=s+gBr0<6xJE@iW+Kheaec;TG4-I8*Pp8tS##k{A^ADm~5U7;Ph*k5#%jH%K^Is&CX}Ck! z$z-33w{_f+KKp^X1nO{pY+AME%xGIunA&LyucdazMUy<>l0i<=hf+I|obY_NBi3={ zps;P-icMdfs&lrL+qL4F6*td3w&$JP(8c5Nn$Cf#iW}#-^qq(E(f&a_+gdk)-g(ab zS;L9`!?2zxQ42`9S=2u#tt7-9?3_AYA^@q$57*9U1s0>S(je7>rf#4to;#>@mwHiQ z)BM!l2R|^k$-CHe&F}mE+_&!e&M80cj2o+F25wihOfxwu3qS)8u&@UZ;HC$*v0zZk zW9-V%zG-@QT=-neta;CQ3X?5roXY|%6#NmmR2;nX+_F{F@=?T3O!7esLK)31!ZW~4 zi3O{IftM(Ygnv6&P$DR2?tt~JjAyR^3qyeZI>^jOV(+rsiaq7(k?o1O58qMGuJrd0 zeJ-AipCC0AsaYTGJ!McFg@mMqmDiMIIOXO+FwueA*Ng?9UAE-<`)}U3P5IT2b^s3Z z_cyND^o~+cI!ib7xTHg^<)-d1o6+#oWaT*ad30oCmu*}3*0T|H6XbF4Jn(4-bKQ&BmLew-&xkYI0WgWu7(R)UQv&;G)`_KvX97J{P z{Rr%R=zSj<9xUEur01NLcR`o}A?9H$IOl8xy;%%=6U?nBJ%ahz?1yWSbKS&71Y|ep zmuuyPl_8{aWdNUz9CMQ3WMGlNxk$Aux_B1tu+DjGwD{ZJ6%Y=f>%U9lKU`&FFfSw3^5O z##YBh78eqmOU-z8@imK{u4kX?x}qTt_`ia3aZkX&8!R3)U2)ob49+xFiWrje-DrX^2%J?~vD(CJsF z=~LEK=XY&0+TT8$9lCAxvbCzXOC1N|xj#Jjr8%#h^DbFzhhs6G9k7nKpVUiB_YWHp zk0k_ba$DMXk#P27@xOWPvf)}(@6i<>id*}!5-A;Cyt z7rDs{suF=ySVI%=*LqImuk(eWm9@B^y2gtU=)3=YuiW?iu6xZ`+huWmq}wbEX%P}Q zK$6p9B2p&BW)duLRa34NnBJIX2M@on4uvd?+@+wZxnO04aQ83|qe(4W2DPhQ)*_gn z0d}3GQt(V9oxUSI_r5>WYff$7u+i-8AGto=+4iTBpPh?3P2-JP)G0U^^)8FMNI@ct zfwXnCpJXS@MN2Nf`g@yKZRx5P7Sr{**DbvE=2@?pJy&KNaQqqXz@rtasU2!uB_Dl0 zo7?Ny(XSoq{GPnT3Prw%|-nW&im}q4w(A=fe7sV?y1W%!-YF%9Cy+=(EwG#m@|&RHwWAR z1~hU}?T_0lvC*oOK4nlQN2;RLHZ!I%nA&OiD#54k!9rv~^VWTE(!a z7lOvn)3Z;Sbf9o#LUC;bME?asA`!daf#t`@g@XL^324=z*s8%I7zR@p)T#flH#iB}o zrjYUIt6S7M^g=veHdYKgaNhgtJ*d;+`g`ts_i?}f`YG$Iq_eucCwj70$^dilvHK~Q zlvA1uvz|k{5KPZJxVb7LkGu?$cJj3gzcbkVn*E>^hDPpLniZ{@{b0FCK>-SW zZ-m2%y3#E4LEo()DM1;|m=)JNbUk5eGl%o;_MwN*JFD6IJ(=y__1(8GEN1d|w)Gry zjqM}S+(Q}~g5PrV8Cy0qQ3&%0#sTba1_WFv&>_gEtwM|CK~f{z4NZT|d~l9o_m8KG z)U=38sc_M25a?vVV^qKEBFn@?jduiamb30JQ{6K*rOvo>U%mQ$%cc$H&|qdkJQaT} z7qony#7kklYxyp$bPXWpp%y63?fjbpob8YrdNs#3|Bl2XC&bz#S1h@7@qL?DZ$7zR z7`5_sH>_Oy$&%+SK&|>Y#JYO(#QDH+pw*;S#6nXUOV06JCi|3SIp1zXJL@jc*@=W5 zdB`p1_5^GY3A*W>Bo-d z%YQ%k$OUIKd%qjq{=Ij<>*Qy@_Le&=yJKBvN9=93zZ>D&X$S@gFW_x}!qg?rFx1v! z8Qcw(ptou^I2oBp;kUmMV556dyZbS)kJca?ZU$ys2v?Tin1`SzDGsa3ttu{jSeH$XsE#3K*?-!r*4DcF?udmbYE@$UdWOb2oV0b9rSWlJ~qK62g#tv;b^(ZBu& z-+RLD+uyRyEtkHV?&|tr)GiWKQMbDkz`SlmaU0UTf%T1b0&wW4Z4RrDNKa!>To?%s zEmdf;AsulU71NsiC^N4fRtNIR>zHR^lY$Ngn1g13ymoD`zf(ZBU6NPRhFG zsw=Mg{)W|?l~wH!1GQ%PszsSXenoqC`)jHxPi6VggJE9Jv2WD1Wn2dPCs`0>7DpkM z?{}Q|O^s?x!&0e6A3Aq+#?`J(Sgui`j~VKM1;QDhbev6muy6-;bDBEon`Lz_1|6{w zjo=Gs*-bK8krEsNoq5qEE23o~d;)K9M@&zCWaj(_f6~Md)UD}556{)z{K!)5l;&H} z*jsgj6;&AK7S;s-=a`m%6GBe!!K%)DY3)AP^TQ^PN#`SBD9UU#* zp6E!PMohV=HNvc3&+(If|9mF*Y;L4@-^`w#B@31=XntQ|jX_&|-O4pa%>Jxt8C`O- z)+nxl8h7Q0E+?7bs)>!HTY>!_>L32;s=ROsM{~UpWEI^aVjQl#) zHS3ys3iIuoHX50c;;Kk0dRlc!)8;2+2e&$eHQeOFx`SAC;7e;rNK_XQX z;zTs|okDK(S)?*Rvx4}8w%+UqwLFo!26HY`i1=b)Qi+Q!KBH!C!Bkv?5XnLSQ9LD~ zPf=scAaC6+B88(gWS4F0(<8%!5A{BL?z@^DlOt{azK74Xci#0^pLz1@Z+pTu)89&T z#NQskzwNO-ge?gG@wCwm0Vt9uHgO8YQ4VuzvV#oI&^6|~A$T|?3Idjc% z4Vvkxm9xe<&trUp;WvM^G)DK^+(42_8Jihyez?FumTRL0OKY>Ot@Re>Yp%ck?07o$ zDVP`|(q}CL&yI91Ottf+V5;`{TaMj+!XF)fPTtLab?Jhow{2g4)10Z+?s~Up4Hc{2zZ!44HUybQBKiIQ7nTDW=Lhr zV)2dQcRB=6IT+S_C#Gd`vA&dMt_`Be?LBk9-TYK~FEh47kDQw*WQVWGl+Aag+B#2( z86$>Ao&s!!ibxzcup#2c#};u3)W`#&VFw7Pv=~%LmcCLnj9;K-gu#g9)E7iQBv_%Z z9hJRM|Bi?7o68w5G`eWY40_jA=&%-xhr&o`!-be}Jo~P?^Zzyy z|Dh)?NSnpXg~d!^Zq9RFAB!hn6OHIvsfe^HN^e8g3c$y7pn0>X3bb*7EwxZ;>teGb5^8dC&wcH-*YqNLPdLvxrJq1;}*@CYwSEk;e>@E5m+FeL%Y2scaJcxK+B7#y7BFO9fr)=mxR>F+U{pKZ z9F);M^ZzNtg?F8ToBj}?*W>Rn>OJH<=TXTe;nxuDp6p`;3l-C`lTtPD!fP)a!ZwMqImk!RGy{3(QEO99arh`c8-Y zhn{k??k{?JW^BB2*_FR-L_6zwkFD!B{pGHmdlz-g>U?)38cE5_1!-EYF0>*yK+~Z# zDlwNXrs~qYBZI?Fx3_n^bJ10ccGPoR4tDK^3v@PO;K2`muoUQDO8HNxLAZ!jIzT>g z0i_*Dp9=1CZ2sIl@{Cd9k)*1gD05j!ORDsORn3_9?SQPNnGaEVyP_?QrB_ir37;@~ zZEM+r+aGtVf6=1xuXLVu_ruN5-@YGQkTm?lJG6ZE1NpLhvToV0v@J8iLZ-}@CJzDh zX9(=(x6mBTc!-z_lHo8&k5(N&0T&Jf02yfsQ#xwC7E!xBK-Dw`z6m1+tP?hJ@GZCv z3M>nXXU9RzK>?E~SGNAAE#AH$efAxXA5FUs_1hI!FTKo+$CtwFiU(L72SZ?VVC47N z(cIHByJvpwsufq=*=#7?vhl{#p53wY%2a#$PZR0HE1RwTjcTtXOOh;vqeG*&E?>F) z(nj6C`aY8)&_^Em=!~J!!6&*B#Xl>R69~zL{}0jbCW7TqkPYl=SiBGkZi%2M{8CJrPLzAG^rb1NW~AC3kMF;J+1`^DC37)PkvyS|>7Zd$qeLj})Y5lzNkJzdIRP83fr^7&kTWTb!i$y6-;vs60$^#x0>_{~JG z*NES3->~Jq`}XyJ&Pheyo=m4^NG-ILEHAafv6?7}mYV+F{-?V;d)|(^=XIl2ez~?! zia=+BMjp9n&1j*#IB5itz$idC!~X|Uvc~lPyPo*Q~Z%sRSdtgR?+y3saHZ&Ng z_a8rDqiwTHxA0z&r@tYSEB!IN3UjPT1c5Son+0nNP7r=wrkY9ituRi2Oo7|+K*xrbjtD^D$sBx)0AdWv(B2C{Ja3iU zn`d2k|24H*tPXaa?dvw3(mOo-g|_bYH;y+)*Ym#3dhP0Iw}arScj98w5R(7(-|<71M0! z6QyuxlromPN$WvvhKvGS#L-n~N}0nus^RPFF{qMn-Gb%A@(OocN(fJ~P2)9M;di zuxZ;d&+p!IN6)c6r@a)V>S0}I8l5D4%GG@FGQh4}EbYq-XLh9Gsoy1{i92oE`pMs2 zby>rBC~n(T{yh%kRC-2Nfz!=$;O34rySbsDy`fByyo6hns9* z^eIx9@jOxVgr<3XUqm^~WTeBhYeB^Yp#yZyXu|rVTK)~m% zv@peDWfy|J3`tqek3JW3?0xZw^Mb7#&jx|H4~%xt!!y4FLUpen1X+j)?1u2t19~-Z z;~rwo*`T$2B?(!%i9$)Oc|-V(CL+K?^38(IiX} z&VJx;AGP2^Es}jC?*J)(!|$khiu0$r4_yj$!D7c0I*}C-R)eE?omht?Ma+zV;{qEz z4qFWAQX25hnn^9wpLwu-#_UgY&An}~p3lP41=l>(eO%8ulCN56YlnxnT=Y5LDJ&%= zZZ+{rsaVR7j*RZYQ`Mh{#h;ExVn2p}|Jh|ruBcg1-K{rn{}W``ydj&{)3CFt$&MmRjHlq;^h?uKP6j^sDBK6g?D`sm}IPI$Rz z|GS`d9B)us=_4p!k`1*vKaIY!z5|3j=q;%Qx?~Nj2(<_t=!_=MJFO(p=|-sdMY*VR zw6XhhAgt+sro|#8Y=8{|@dd6653A(>E9Pl~%Ny1V3P`c57KAGJ4rxs+qX{;7)WQz( zuJ1yamt9Y1q!o}3%mQ^li0G(cS~1J8)9S5CREAGY}45ki-mvCmq5nB>y1G7owuWVp53mMT9$K zImob@`VhrkC=Z2OA&eD}?gf!|Erc^w=+I{>9xC{tT}Vao@L_SM(1fBb0_qqb#b7#7 zqy!gZ?Rg4c7UBx8&G*oZOSV2=(A^d??Vx zi_ZYkBJl)ZFO@<@ND}2?!9eH_zF@`X%y1DH5i!k4G3Ly%0j-kvw zujjp6;o9TNwpMe0OCP%wlGXX#)k0L_AkTv!_V9N(@B`Lz3}Yj)KwzU~UcQ>LgmRXUCw`&N^XUuL$!nUz!=! z6v*sSC_D`oc%lCs0@mPyk9YE>nNeu&MJU=L^@-+emZt@5d{CLEjh&AVQ$5p~n4T@_ zW`_>@u~fOSg`y(tLpCj4}YSDlBrKh^u z+yQ~1+$aN2DbTC0B89d*U;447z^%L^!#6M)k23y{=U0Thu%=XhCa*7R#gA`;Jilod z)dn`4V=>q_^sno;Y?yRmE+s|-yZ_=_b-wqTyW7(7F9ktPENIXMNok<T{rs12HkOP~mc_Dl^O zL2J54b303OLXb1Q0oT)E5)KQWz>pura6N3o#I3?Irrel`^gH%P@Z5*my8(UyDcD6D zr@8-J3};mhb3t1RtU2Z;<~WZc2!aC#L2)E2f@UssG21SsWA+zQbMO3GJ*WRSZvJxD z^ZRygv>h9{rJ+X01x#w3N|+xS{g=Y%r2@>VHTCg=S>A2DHh-{INZ~J57G{=&N__a( zRWxz=dG&YI_dIm(rq3DDB_W>y8UK*WSyW zaZJQ)c@SW(5L%3Ar{)@(-d$1plK*c0YHbvtee(Fy@mdnKKXdFcF{ z8ylTf+;FaeR|)P3z65g~wRZZ(DV`w=EMn;)S{g5&E12hC5pXR8SlJn^7#Y!uc3vyt z-~24(LJy~=F!qb^cU}+Lw%AOCn-2=EErJ$DjcWFl4QFVQ!}@3Dx450bv(mP2ol?Qr3o0fhA&TtJ~(?wXoi8 z-h9J`C8%xwR=JST&nkncB+X^DIl12LQP)=pOa=mUF-a>+wTptE4eagzd1rgF?$6?p z^m|GObT+vAoV$LPZfpB|K40qhVCs#aT1f#5J`0#ID2t051s{c0$s&I@-HQzPYVLzU zQSv1Oc7-%243rD~sN%)ap)}7|qToeb0nRPqCwvhnx+Da%9JA0Ul7--B8CUtL#3G;$ zIHRTm2n`BxVj5N~!$wNngZHBaggSRvtt@;oH=3IcwmGySgyl#n>?n=YMB) zBOo&)80#>iQV4Qt<mOznMLT^(P%bkUVl zs$A%cBPu2lJl=ZOUGD?If_9M&8rV{$?4?6;75EiB2%WqGZ4!cqb+99)Bs9y0R;Q~u zIzr%zBh-F{$(sLyPz^&@tIXq-Gs85e@GAV4VE_Os6G=otR39>pkK$lFCw!>USMAw^ z20qSb@6kOfgR(*`yqc^>xBzg3Jo6!$kGKzm?eSi+!W65q`-pS+eZ@Tj7s3AiRkZR- z+8cF$1Kb1C`QRuU%tj!FB&iS^DOgnCTendX)q&v5Ky$Zs{nn22?rkVP^tO%LR%FZB z#q^=SRDf2s|8+W#qw0HWB0#O2FKwE(9OB249>_88{pasjML@0x0;9zlDk8HX=w_tO3gX=^(6oTQvqd%4!Mbo@Uj|=b18fW2F z;=t>12PlH_a8I6Nft#IG%)(b_j5kEeo7@D1ntZr1*gxIEsP6rNI!6FmYn@6OT#=H9 zcLp62KS4$i!^SnLjo@XtrP~`V%n9;>s~4JgVDUT}S?K@6~GO?T;y776T_XHg`-zw4#VfNV|4%RKX7zbeXong_;VyDG+$ z$$}>EcaVmt8(FRFM77+Ac6Ypc_J`8%`R1hWTDNW4+S#{n=ht5A?bYSockQl>WgV;#J5TDmP_|H>iMp}oZRKuw1P=jaDk1=gt1dxRRW3uMB2(rVKiYRWO4u!x( z5eQuq`#Jan);8xnV;NMun9nb25rD#29LNS>Bs zaV_Hd+uGj$z?BniSG|6>^7>WFoT&3r%Q0V5O@Ja7K3S-unt-NWZBf@%2-E@rnPX13 z5@SVZd6JnN^7{OIa97{=)^6SK!CKt2Ue}m%K6Kg9&UyDe*EXZ;7Oyb!Y@B{ZNNlF{ zlpuu5!I01dqZWmGWt|j0+c09B?^1Awk>jDiJ;1{1q4-6B7x}UoWTy^=z)>OKBdCy8 z4Pl*t51dvOkyy?kx6rym;cjS26xvCPEP*ntPBd(QF9-{VgOb5H2>21yJ&$Okg=8jD zC~dXU@hPbV+^~B28jwCM^a}3JxX3YRsG2dZn)F1awH?*WQa^4G0+Qyonn6zzD9QK1 z-F?64p4GOZK~0+QZKkY-E_<}+?lW$VMU2mpD$9r@w1SKLT)~ot6dx}M+R>4)R=6-H zhr&Ay$O^S_3UWq_Gc}84TEp+L5Q)6+is^X5@Tnh8cLa0~LYnn4kOC-N6M`TnOgj@C z`wTV&ajOUEtz#Z)NEh@N{01MnOGY?9EPz8^`)nrGmon`Y$@kxP>r}^e`_?V5?VVLu z9Kf;zg1UN_o}tN z>Rk+b>&+bwSuA4?sy`U~AIb$?EBxjG%En{DN>39PPpvq&PYGwU_15NtJ9ad=m2b+0 z+!o*5moKH+yItHVZ_N0Ef^guAUL!KHi^439$CZ`Ceo?8$Uj&d;no$d@@@udv>3}4Vk}hvP z64-bj5>8m%zy=cdmg0x-t_tpdbLVP+Od~6eqd)kQVRCQgQ3$OE|1Rw8!3DEUCb>3Y z`BIIao&5~|yi1P!FT03QG#uHD|FoI|>eC`diSoXfP+~;w#CHs6l?27QgZez>5i^#@ zGX~C1V$KWpLy{~BS}%O|os@)+F;d?ilCu1Ug6_=+Vymo$ApI9y1U~!iC&LSE}f)FiR5L@<|(E;$D#X)lFy3~tK)N+W$a8} z{GQ{+qsE^I{mtlstYFvUePp?-qDD@k#250W8+L{BxrOw`O5Y8KPpTKhC>u)>rMv9>wLQ%J`d!mpJ7_=!+Fh}Rva0>J{k_6saYHD1Rj|iFAwPdiQmVjV@w3}dKmo3! zFav#59(l$j<~-UzJ%D41hlvZu(&od*xY|#|oP~2!m;jm(zv3fl4%8Ie(>bv|R}}}e zjJ9F-FC)yFP$=l)4Z-WmQpudCHrC$L(^;l@5@dT(@JbBkZbC?^qe`ujtX6TgM!>fL z)r~ipYoJLu0CsOKAHx~}4sU7n5j|rSxqZNJmi5As%S16NQ#KEj>*K_gVQchFmlo21 z!J{o%2oOe!IqyJ(rBVGMAnh~P2o*y;V^fxljFogrb)+&(tFg_H|GVbD4;!g*B0!RL ziTq7I%0%r$L;yV(Y$1gQ)CJxu@BZpzs2IM2hV$WaQ)0}1^z_~k6XJ{1QyR^!(e8eY z6z%C+e|YszM-bm;{sv616{I4l{W|XoAgns~1;%*mz-Uisr0%f|f;&^Hd;Bdpf~M7} zL7$v21`oS88B!O;W43_QNZR3FHxY2vQ}T+y=c`s4_l(U3|DDM#*AwN&8W&eHZu zBqEr)ZDKnG=)d|Ga45ZDz9(!xGu6(KT{-=U#M! z2Jcb75S}-eu6QZXjeAeDLkz`Qd-Q3KeG~vr&$Ot{!%zNb?=lBvvqfke)?o20Cvv6i za@*wVf&oUO@@Bz#1c~NSFATi?tVVJ^cIGtGSbcZpf>0`ZCh-Oe)|&WWx;W;$UvbNG4Q z3E$z_YHX>|<0zXOpU`sj+fN5aSyTfq|A+5xt$dpAvSR}WAHqzRYY;G`PCsMm4Cr<6uXm#LxV~AM@Rx2)+Cl)W<++Dn$B8MpOd`PNFeP^bH zf?y z`SE-lXNkmJx7;kU`@rnWQCP=|H^{HsPV=g2qY^m2Q2+4L0N_XEdL3*$VX}lK_;6U+gOu&(!q{q+r?1AzU#A$bnc^cc)9v7A zhDF2Dr*o?rhw@!yaFDEnU4DIbg+aciqC*xlF)_|{69#-v?<8CHXStg0lPI<3e^M(o zDHum*?vULtT@L2fi>b3Jhj(mK&L_kSjl2asQBt_*Nba}}BH=#T|M;t7H9|Ct|F7Jm zCHp)s`DuOT-DjjK5f_Xe6dh%@Sq4c=8*l(>LAlRPqp$v=g#RG zqpSp&9JJ2V-aYco2sjR0^!2~i)qLS^jTWZi^o#3(G);>_6xhbR)NnEqX^SfgIg1UZ zA|F?8Om$(vtehm%BOdsl=jBMBe;}ZDc9HxNeb!dFcMZ_d(6pRQ?^V=Q!T`rBYJMSX zTmwuAk<7qXn7LwHGU&hO-%&B+M8aGoDQKGE0^vu27#=kVFe=mUN7+ZI7mVoz$p7L-QIH zP2o-o-blDO=ZsV#J#inV>v_DGde}b|*x@!uTQUz96vOfHf4h7HUwl0x&|gh)RdnGz zfQV{yAmNt)kxQl-U4!b6kdownMtSk#KXX|e1vv0yP zO5?SL_sB@geR;({oAmUuZClD+;;8=yo$>2b5(1$Ie#qFrlghiBOT_mIt6x*dVE$f; zEQ$ZFGH}2;Mee?x7g8H6;Kq#grrUa8)!2I?&%<4Exc-(s3R}Q?(PjGdXWxIzk3J`y zgyxIEeMp9SJz$2|SYJVw!e>;X^ZE7QtlRc(nw->(t%BQ&y;NVaVeEo_z*lJ?!oYuj zKI)ur#Ybsqvo%YYX5=l-@bzHY_d-aV;yhPklv+y>iL1SfzbyTe)R<{@t1w{4xtj(^ zgJcVb5F*t4y}nD1*pu@>DrM;>+9i1M%l_FAh7kTCo}k0DoRA;_ z&Y{o@fpB}{iDnIzI~hN&fhzFSfar}kkAIL3EoXmHWA6YSk4M2HMHVbImupWRz%oWq zT%#|!fZ`q|Kk1PRy;0x*VR^HT^rwmILlz}h=(K&)-g~b29K`kc%;!8)9ZGlaAd}0f zrLpj-+VhfGu{iO&s;Abh`=1)w7&+TxCYZpJ-*6c5qFF)RE3bx3BTrrdP7pN?z79dq zkOp!9Pv9!&xRS1Bo*Nv(N4L*6io&;6;IF3EgnovTTWjLkkhkcvIn9Y{i>VsaQ1on1Ya>fRii4FHeWH66TQfL2YrTTN%J zqYY-+yRvd2HZkZwi1xoNFu)064T47qvnsIsI%2F$B-|*lCyQwOL3sK-$XsJQIfDd$ zV??9}5q)^=bj)p1Y`y%@lXYIS3e(pz-1V+;_R965nw`$LA+zc~~f$8Q^&jl`L6rZg@E?ea{jlQibMEj9Z$7zlgqFAseo4_FgR9yT2SO z*277%Fdn7UCT}aTkU>S3s54*c&!LLIDRH$cuVPCWI0KkHt%Gi-8&E3k$P1RmFMsMR zkQa+rPA1T;3$2$5myU(hpgTVzJ9J_-Xe233LcAfc z4AsVSf1bZWf~Bv{mKl3h#E9AaDY(1ZS;|SvG}WfTU8S4Gg3ElIKK(|I5Qdpd!(Q8oNJM#V8t4kkE0#7am+6om-e&6E9THxFh^k$uKL zV^t>I54vt~Zt}iHe%yApAka5XVnbqCu6BpJ6oY$9shRGTLDvV901hZm46~4w@&-HkYC}Nr(f){(213GVqSHKl{%;e5A*Ri+wd62E%Z9myPJS*jZLPH zlG+Ww(#Fx;!9*svqrY3evTi;>zm2qu+*L(G&_e&rimjU#FxgThPdCp^5XTK{AVX9C z^vCXtgI$W?Tt)V*WS(5#y`blW#ZVAPhx4H8t4jmM1i&#k^nCCZX^?3qIX+1qb&Wx7 zG8hf9g*VOM*w)IO6S|NUq`yZihRoQ9SQ$Gi2K8!R*Cf6zYl7n~Q5KaDa=cbV6)FJh zoZM%z!}dUE$z!_%{kmgH(1#tD7nMO|4vb^a+4PXCu_m!lDvPf1nL zvJ{OL{c3t2ji0LDvG)gJUz0Om(mbn}huyLfHqq|Psi$o(xvH2`{jc6Y`4?_kx=sQs zCt7kt0qf|^cjI{Y!d!-Lb5A}&)bw`!S#kdZM9Vx)M&;ntrq50S?J4`t zb2hY!XyS+xe~2Hj&7#YNvi~=&XnAX%EPfZ6kPa^~{*&%?ZVx{)49^A{^*O zsIABNOGJCADt)Qx9|~V+wdsM?vG{G&vD>-7^|g1wxo;7m%CPyMaM}KRrsaMvQ|Gdn zkK5pV+)h@K7wOH`A$yY!^-WsE>FkO9sG85Un~ybdAw9pRf3p<(n1w~hWB%ZGi{r_< z!^(&8LsMoX)~#|+1c=wq_z7kH_G_Yw>}h*>Ga`KP&Im>1+K>1Esm*qrb)0u{YsLM1 zrT6IH%*bAdWnvSyRwjJdu-hmqmgpJ$A?<vS$eWK_Wzc#M9nKmLtU0qCN&a!{LTCaY*DrjK|p!5F8T@f<+vYPbHjOU084YuV6=x%-`v&* z+qOSi?7N`)4R2%Y*Vz4WU8;JOa=ae8lhz%9kY}bsBMR^GCCaRmJvhzCaT_)JDQ)^lZK>rERE6UjzknyRxg6SRA6gAmb`zw3 zwNrSV`}L+*c~rb`5kuEaWD5$gd)u(5`?_)B@*1`XtNzx!`N7=-Jc$j9g35L3PW`hsOTkezsZ5-q$yAMZY?D9H3?ra@!_CSbe z+?++MZtu9<{aRyYZz8ljuT6#|C)EK8{ABC|;h>`dYVm#6^B+xwuK>)9k(R(ckNx1d z+6G?w~6U9q;WLK z_j_+#cI8r194zur^d3s7`IM_x+i}8VE;^;9GweaAjc9X{9p!qV-g_B4dcGUX#kJ5cVQt0IPNZWsTJ}QUzHhT_VHjl&EB%H9ci1sHWoe~ul z)~Jhz)cY!CIEoB%S{X4FV&Vq#)3)0-q~danpky=hg8)axUk>P4Yc%(S8Ut^}htXjd zKe)Qe1fK#IcbycF-<|BCd;yMM$47IS4RH?oCdt{N;}m!sQM7BbEL77$6SkgvI^2nY zdLx3^+|2>75=RaZUJpVw#CG7me2k?glfkb1`~;;SuXCI(%b40NY6g%DND(NUecexj zwEnh<%@9${2x5rv+p~mZQ@B>Zu z$~*~z^!m!Y7&GGX^4g$?r4xdMBWw_0YU8(~^{w!ZF~cpy0PKtDU-_G5klepmnxq&P zLs^}76lE|ix62}nGU+eqZ?fQ(|NCPsVB1TU9|L$LA0$E=0$d68ClIm>4>PM#MH?|E zZc;xf?n}+3dDW4)!cvrL?faR_=(ej&y)i0&RB89!ss)Y#&E9L2 z`Dk8HG5Y8`hO9F$cKjJj=KKqVqiz@Dga^tMvp6tj0Q-%)D`2|sebSTu_FPWRxzO(- zyVAS_m{6KOw08c6)d?i>K3Y@6;lkex5y!aVae90aEl%AW>mQ@eCu&&qTgPM*qa3q@cNgAsmKPvO|tG7b~ z#6~hHza{$aa!QOvI%$06Ej$}~GJ$VP#j3-`JSlLuo@X;0E7cGoe(7D^i)(S#{tt85S*Cr6iQDgZS0MqVkfwzuV|$BOvPP>-S^zp$nOI zKFMxuO?GUJDRGUCODzNzyuJ((NV})bfW)>K@|X5^p4<$c2vgZ5(smwhR=y_R4L|A% z0tj*IU1vY;wYB#KD1V_+j7*sXuBB?#*}g~pQJOl_&x-SF08z-x)qDx4yj~6_^SP-2 zSfd-0ZGKXiHyLC8PGH%Z3u*za`994@sUyguhU$O1ErfGvt3l(UScc+V8S+ zZbok8Xvmn-@U7hM2JC>zj28EG?F*PF;849Z0o9@WQ^i=ttaVGTbdm=} z+>IeQSKPf7AX+HNpl~)L&!n)HpZoSBSogARSGnI#lvK-i52t7wQ?~{`pE>U2N9P;1 zMHX0Z0encs5M-cSqY2mf^SvNE#@a6VAa-+QX{t`&Mn-NRO!L`@f65^uMn zy7#^KQyg_+bH%Kr`|wk^7WTFqJ!dvX_cS1TY;SW{oT8Saa5@R4+dcx06CiJ%3vON{ z>ubFCSG)69k>R-aN7b?Z7gWrQQi3hwax1j!r1ZFDL@wK1;q=+%tze^L$voQTjwPw) zUNtiW%VXUH)iv!eU8O`M@w0aQ_$&^I?RgVg8X2OXAU5!?${%L#llR^~FK-xmyG#=Xz1D-pY6efmwVf z$f7!Z{T)ZtyQ31ayPYgZU>X^ysedq?fVtyPhV0CjPwm3xSGv zc}k!0NN}`>Mj5)G3aXQ>J@h-m30=)OQN0$@r0&130MrBuUQsia>!7cc8`rp1 zb(xJk`x*9g?cK)hk}d-FV)@VmJGw;kY5?}SjrZb3hB+#XDI1w%hj9v&NyDWx z<;!7ekHr~#lD03qa$SG=*zu{D`PJUqwVCNBUGF%Aa(GJlJ~R#Ca>c`>hq4|?pay@& z90x@q%U;8>75~h?-blU#CzdwLD;D%a!IP{N(mXhC2WNq*%G>YPJ)ll1NRa4;U$9B~ zcS+6-BILglQz#11LlKrvLFjX>svTv~3*OP5;l0O(CM;4pb zpm&{g5{-GTw46cu-XP_6?_%_ccXgK0eC7C808R6N>L+Z9uoinmhk z4sY6hg=~!l;`VKod>Y=2%%+dDSajTv&n*dCHLV-5j*>Vd`7e0>B?p>xb70{e{=6Hx z>L3bec5J5`7T;)A5uE~IYHa5HLm~lbmuCArQ3rtu?en+p#+CEr#@Bw4nDHM)I-_?= z`v|vv!Z@TrGJ1{K>aGWiAh{e%4L9!r!6k;vq?fO3|De1cLTxCFiR>LN!B!j;N~ezR z0j4E){QLlau+dx9=^*5Bjk3SWu@WOq9d4m^**d@KBEoPhN0UBzGhy=3N;h;KJ8IZU z!gP8Wfq38w=FS+VMVC~obef3Xp=M=3lc{XjZo?H7FMx#ZgQGae)ah3^D8^!(yu6$u z3jzJ|I2Vzh`snfKu=a)dTeKr+;8X+mjDz>&_mI14mi}(!+4G+IWO{r@#lnMDWkuA2 z{f`UCK`*};oe~DsB0WGZe@u&y^v{4Bc|gBbEef~9@q7h*^)4YWFA9jl+$7QdqB;_q zd-cMKMzr|F#tmi9%<(&13#nh=eGKx}J_UR&6hgNOPCQAIgBg#dof3WrB&y&PlG}1a ztU^btW^7naEw2FQsM|^$%DDT@Qy0>u&X^lX+Q}Q9lDjQVg!H61_pB%bEhoa)vRz|e zR0(17(XLL2Yc0`m>Z`;oZ`l|{?O20SM=C%GZmw?CclA+=*ozgXd^Q_)_xB!698=F4 zo6FKowlAPtX**u4`VQ(k6d&Y#|HVBnbc4G4*+NNZ+N~Ks^mC@gYCUnIDAz9B3%w;U z+?=cmUs#HX2pKx0OP(O1y-|P;=TAQM#m(klvasMR&N^t-Vc&+0h`D-Wp4_p2uvc=m zW?$blG0sFSACY78zuVb7H$L9g%pnrL54sc6%!9zf)fjCy|DMs#3J*OyAbg8A8|w6_ zM%iQg{oJ*~m#>lvvypl&M6EjE9ZFn((zdOjfAWL_z+U44Fvik-5?X(cw$MD?2!ZHGc_e-)i@J_6)+Q6BjOlVGce5t>b~h^;j$32&;??Ka>l!9LN-|6`o%*t!BoKE5@9U!r&6P zdE4vP(pmq&RFnav@36)Y&sDmzupCnvrn@}sVk?H^@xZ67N-P3R_?Mhp6y}DgWF4&l~@r3~3&KR|sd5{OZuT3L(_T Nl95mpuMss4`VSD(_qhN7 literal 0 HcmV?d00001 diff --git a/docs/build-docs-html.sh b/docs/build-docs-html.sh new file mode 100755 index 0000000..5073ac3 --- /dev/null +++ b/docs/build-docs-html.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +# This is only intended for local +# testing. See github workflows for +# how this build is automated. + +# this will create mkdocs.yml +./create-mkdocs-html-config.sh +# and this will build the html site +mkdocs build diff --git a/docs/build-docs-pdf.sh b/docs/build-docs-pdf.sh new file mode 100755 index 0000000..59e2cfd --- /dev/null +++ b/docs/build-docs-pdf.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +# This is only intended for local +# testing. See github workflows for +# how this build is automated. + +# this will create mkdocs.yml +./create-mkdocs-pdf-config.sh +# and this will build the PDF document +mkdocs build > /tmp/document.html diff --git a/docs/clean.sh b/docs/clean.sh new file mode 100755 index 0000000..58f6678 --- /dev/null +++ b/docs/clean.sh @@ -0,0 +1,6 @@ +#! /usr/bin/env bash + +rm -rf .venv +rm -rf site +rm -rf __pycache__ + diff --git a/docs/create-mkdocs-html-config.sh b/docs/create-mkdocs-html-config.sh new file mode 100755 index 0000000..b696d30 --- /dev/null +++ b/docs/create-mkdocs-html-config.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +# This script will assemble a mkdocs.yml +# file with plugins section suitable for +# html site generation. + +# This script is used both in manual +# site compilation (via build-docs-html.sh) +# and via the github workflow for +# publishing the site to github pages +# .github/workflows/BuildMKDocsAndPublishToGithubPages.yml + +cat mkdocs-base.yml > mkdocs.yml +cat mkdocs-html.yml >> mkdocs.yml diff --git a/docs/create-mkdocs-pdf-config.sh b/docs/create-mkdocs-pdf-config.sh new file mode 100755 index 0000000..81ac674 --- /dev/null +++ b/docs/create-mkdocs-pdf-config.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +# This script will assemble a mkdocs.yml +# file with plugins section suitable for +# PDF site generation. + +# This script is used both in manual +# site compilation (via build-docs-html.sh) +# and via the github workflow for +# publishing the site to github pages +# .github/workflows/CompileMKDocsToPDF.yml + +cat mkdocs-base.yml > mkdocs.yml +cat mkdocs-pdf.yml >> mkdocs.yml +# This is a kludge: I could not figure out +# how to reference image resources using a relative path in the scss... +cat templates/graphics.scss.templ | sed "s?\[BASE_FOLDER\]?$PWD?g" > templates/graphics.scss diff --git a/docs/create-uuid.py b/docs/create-uuid.py new file mode 100755 index 0000000..7cd8a6b --- /dev/null +++ b/docs/create-uuid.py @@ -0,0 +1,5 @@ +#! /usr/bin/env python + +import shortuuid +uuid = shortuuid.uuid() +print (uuid) diff --git a/docs/css/extra.css b/docs/css/extra.css new file mode 100644 index 0000000..e69de29 diff --git a/docs/default.nix b/docs/default.nix new file mode 100644 index 0000000..ee1388f --- /dev/null +++ b/docs/default.nix @@ -0,0 +1,61 @@ +with import { }; + +let + # For packages pinned to a specific version + pinnedHash = "933d7dc155096e7575d207be6fb7792bc9f34f6d"; + pinnedPkgs = import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/${pinnedHash}.tar.gz") { }; + pythonPackages = pinnedPkgs.python3Packages; +in pkgs.mkShell rec { + name = "impurePythonEnv"; + venvDir = "./.venv"; + buildInputs = [ + # A Python interpreter including the 'venv' module is required to bootstrap + # the environment. + pythonPackages.python + + # This executes some shell code to initialize a venv in $venvDir before + # dropping into the shell + + # For PDF production in mkdocs + pythonPackages.venvShellHook + python311Packages.weasyprint + pinnedPkgs.cairo + pinnedPkgs.pango + pinnedPkgs.gdk-pixbuf + pinnedPkgs.glib + pinnedPkgs.gtk2 + # Those are dependencies that we would like to use from nixpkgs, which will + # add them to PYTHONPATH and thus make them accessible from within the venv. + pythonPackages.requests + pythonPackages.pygobject3 + # Doesnt work properly + #python311Packages.cffi + pinnedPkgs.gobject-introspection + pinnedPkgs.gtk3 + pinnedPkgs.taglib + pinnedPkgs.openssl + pinnedPkgs.git + pinnedPkgs.libxml2 + pinnedPkgs.libxslt + pinnedPkgs.libzip + pinnedPkgs.zlib + pinnedPkgs.gnused + pinnedPkgs.rpl + ]; + + # Run this command, only after creating the virtual environment + postVenvCreation = '' + unset SOURCE_DATE_EPOCH + pip install -r requirements.txt + ''; + + shellHook = '' + ''; + # Now we can execute any commands within the virtual environment. + # This is optional and can be left out to run pip manually. + postShellHook = '' + # allow pip to install wheels + unset SOURCE_DATE_EPOCH + ''; + +} diff --git a/docs/js/tablesort.js b/docs/js/tablesort.js new file mode 100644 index 0000000..573dd5d --- /dev/null +++ b/docs/js/tablesort.js @@ -0,0 +1,6 @@ +document$.subscribe(function () { + var tables = document.querySelectorAll("article table:not([class])") + tables.forEach(function (table) { + new Tablesort(table) + }) +}) \ No newline at end of file diff --git a/docs/mkdocs-base.yml b/docs/mkdocs-base.yml new file mode 100644 index 0000000..00861e8 --- /dev/null +++ b/docs/mkdocs-base.yml @@ -0,0 +1,42 @@ +site_name: Cloud Native GIS +site_description: "Project technical and user documentation." +site_author: "Kartoza" +docs_dir: ./src +site_dir: ./site +repo_name: "CloudNativeGIS" +repo_url: "https://github.com/kartoza/CloudNativeGIS.git" +edit_uri: "https://github.com/kartoza/CloudNativeGIS/blob/main/docs/" + +copyright: Kartoza and Contributors + +markdown_extensions: + - attr_list # lets us resize images see https://github.com/mkdocs/mkdocs/issues/1678#issuecomment-455500757 + - pymdownx.highlight: + anchor_linenums: true + - pymdownx.inlinehilite + #- mdx_truly_sane_lists + - toc: + permalink: true + #slugify: !!python/name:pymdownx.slugs.slugify + - pymdownx.snippets: + base_path: . + - admonition + - tables + - pymdownx.details + - pymdownx.caret + - pymdownx.keys + - pymdownx.mark + - pymdownx.tilde + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format + - pymdownx.emoji: + emoji_generator: !!python/name:materialx.emoji.to_svg + emoji_index: !!python/name:materialx.emoji.twemoji + +nav: + - Home: + - index.md + - quick_installation.md \ No newline at end of file diff --git a/docs/mkdocs-html.yml b/docs/mkdocs-html.yml new file mode 100644 index 0000000..96700be --- /dev/null +++ b/docs/mkdocs-html.yml @@ -0,0 +1,109 @@ +# Configuration +theme: + name: material + language: en + direction: ltr + include_search_page: false + search_index_only: true + features: + - content.code.annotate + - content.tabs.link + - header.autohide + - navigation.expand + - navigation.indexes + - navigation.instant + - navigation.sections + - navigation.tabs + - navigation.tabs.sticky + - navigation.top + - navigation.tracking + - search.highlight + - search.share + - search.suggest + - toc.follow + palette: + - scheme: default + primary: blue + accent: grey + toggle: + icon: material/brightness-4 + name: Switch to dark mode + - scheme: slate + primary: blue + accent: grey + toggle: + icon: material/brightness-6 + name: Switch to light mode + font: + text: Roboto + code: Roboto Mono + favicon: assets/logo.png + icon: + logo: material/book + +extra: + social: + - icon: fontawesome/brands/github + link: https://github.com/kartoza + +extra_css: + - css/print.css + +extra_javascript: + - https://unpkg.com/tablesort@5.3.0/dist/tablesort.min.js + - js/tablesort.js + +# Needed for the hooks below to work +plugins: + - search + - git-revision-date-localized + - mkdocs-video + - mkdocstrings: + handlers: + python: + paths: [ ../django_project ] + import: + - https://docs.python.org/3/objects.inv + - https://mkdocstrings.github.io/autorefs/objects.inv + options: + # Lots of other nice options can be found at + # https://mkdocstrings.github.io/python/usage/ + docstring_style: sphinx + heading_level: 2 + show_bases: true + show_signature: true + separate_signature: true + show_signature_annotations: true + show_source: true + show_root_heading: true + show_root_full_path: true + show_root_members_full_path: true + merge_init_into_class: true + docstring_options: + ignore_init_summary: false + + - redirects: + redirect_maps: + #see https://github.com/mkdocs/mkdocs-redirects/tree/master#using + #'old.md': 'new.md' + #'old/file.md': 'new/file.md' + #'some_file.md': 'http://external.url.com/foobar' + - enumerate-headings: + toc_depth: 3 + strict: true + increment_across_pages: true + include: + - "*" + exclude: + - index.md + - developer/manual/*.md + restart_increment_after: + - second_section.md + +# Hook to add a uuid to every anchor +# see also hook.py and https://github.com/squidfunk/mkdocs-material/discussions/3758#discussioncomment-4397373 +# Note that although the above link implies you can use UUIDs, you have to use numeric IDS not UUIDS +hooks: + - ./uuid_redirects_hook.py + - ./python_manual_hook.py + diff --git a/docs/mkdocs-pdf.yml b/docs/mkdocs-pdf.yml new file mode 100644 index 0000000..7392d7c --- /dev/null +++ b/docs/mkdocs-pdf.yml @@ -0,0 +1,56 @@ +# See mkdocs base and the create-mkdocs* +# scripts for how this is used + +plugins: + - with-pdf: + # Generate the whole site as a single PDF + # Full details on this plugin here: + # https://github.com/orzih/mkdocs-with-pdf + # And don't get it confused with https://github.com/zhaoterryy/mkdocs-pdf-export-plugin + # which is intended to export a single page at a time + output_path: ../pdfs/Documentation.pdf + author: Kartoza + # copyright will draw in page.bottom-right + # do it manually in templates/styles.scss + # for more control + # if you comment out here or use an empty string, + # the copyright text from mkdocs-base.yml will be + # used instead + copyright: " " + cover: true # see templates/cover.html + back_cover: true + cover_title: Cloud Native GIS + cover_subtitle: Cloud Native GIS + # cover_logo: ./resources/img/logo/logo.svg + # Print css is defined in templates/styles.scss + #custom_template_path: TEMPLATES PATH + # + toc_title: Contents + #heading_shift: false + toc_level: 2 + # Set to 0 so that it does not generate chapter numbering + # we do the numbering in styles.css rather + ordered_chapter_level: 0 + #excludes_children: + # - 'release-notes/:upgrading' + # - 'release-notes/:changelog' + # + #exclude_pages: + # - 'bugs/' + # - 'appendix/contribute/' + #convert_iframe: + # - src: IFRAME SRC + # img: POSTER IMAGE URL + # text: ALTERNATE TEXT + # - src: ... + #two_columns_level: 3 + # + #render_js: true + #headless_chrome_path: headless-chromium + # + + #enabled_if_env: ENABLE_PDF_EXPORT + # See notes at the top of templates/styles.scss.templ + # for debugging workflow details. + debug_html: true + #show_anchors: true diff --git a/docs/python_manual_hook.py b/docs/python_manual_hook.py new file mode 100755 index 0000000..2eee186 --- /dev/null +++ b/docs/python_manual_hook.py @@ -0,0 +1,45 @@ +import logging +import mkdocs.plugins +import os +log = logging.getLogger('mkdocs') + +@mkdocs.plugins.event_priority(-50) + + +def on_startup(command, dirty): + + template = """ +--- +title: Automatically Generated Python Documentation +summary: DO NOT EDIT THIS FILE MANUALLY : It is created during the mkdocs build process +date: 2023-08-03 +--- + +# Python Reference Manual +""" + ignore_list = [ + "__init__", + "migrations", + "tests"] + for root, dirs, files in os.walk("../django_project"): + for file in files: + file = os.path.join(root, file) + ignored = False; + if file.endswith(".py"): + for item in ignore_list: + if item in file: + ignored = True; + #print (item, file, ignored) + if not ignored: + file = file.replace("../django_project/", "::: ") + file = file.replace("/", ".") + file = file.replace(".py", "") + template = template + file + "\n" + output_path = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "src/developer/manual/index.md") + log.info("Manual will be written to: " + output_path) + file = open(output_path,"wt+") + file.write(template) + file.close() + log.info("Manual written to: " + os.path.realpath(file.name)) diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..5b1c45a --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,21 @@ +#Alternative for pdf creation - broken on nixos and lately ubuntu +mkdocs-with-pdf +# Export to pdf - see https://comwes.github.io/mkpdfs-mkdocs-plugin/index.html +#mkpdfs-mkdocs +# Rather do +# pip install -e git+https://github.com/jwaschkau/mkpdfs-mkdocs-plugin.git#egg=mkpdfs-mkdocs +mkdocs-material +mdx_gh_links +mkdocs-pdf-export-plugin +mkdocstrings-python +mkdocs-video +mkdocs-redirects +mkdocs-enumerate-headings-plugin +mkdocs-git-revision-date-localized-plugin +# needed for the create-uuid.py helper script +shortuuid +# Needed for mkdocstrings python documentation generator +black +cffi +# Needed for PDF back page QR Code +qrcode diff --git a/docs/run-server.sh b/docs/run-server.sh new file mode 100755 index 0000000..276f48a --- /dev/null +++ b/docs/run-server.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +cd site +httplz diff --git a/docs/src/developer/index.md b/docs/src/developer/index.md new file mode 100644 index 0000000..7c29992 --- /dev/null +++ b/docs/src/developer/index.md @@ -0,0 +1,18 @@ +--- +title: Documentation +summary: Cloud Native GIS + - Irwan Fathurrahman +date: 2024-06-01 +some_url: https://github.com/kartoza/CloudNativeGIS +copyright: Copyright 2024, Kartoza +contact: +license: This program is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. +context_id: +--- + +# For Developers + + + +This is the homepage for all developer related documentation. + diff --git a/docs/src/developer/manual/README.txt b/docs/src/developer/manual/README.txt new file mode 100644 index 0000000..98a8561 --- /dev/null +++ b/docs/src/developer/manual/README.txt @@ -0,0 +1,16 @@ + _ _ _ ____ _ +| \ | | ___ | |_ __ _ ___ | __ ) ___ _ __ __ _ ___ | | +| \| |/ _ \| __/ _` |/ _ \ | _ \ / _ \ '_ \ / _` |/ _ \ | | +| |\ | (_) | || (_| | __/ | |_) | __/ | | | (_| | __/ |_| +|_| \_|\___/ \__\__,_|\___| |____/ \___|_| |_|\__,_|\___| (_) + +IMPORTANT: DO NOT EDIT FILES IN THIS FOLDER BY HAND! + +The files in this folder will be generated by the script in + +docs/update_python_manual.py + +All markdown files in this folder will also be under .gitignore. + +Tim Sutton +10 August 2023 diff --git a/docs/src/developer/manual/img/naming-convention.README b/docs/src/developer/manual/img/naming-convention.README new file mode 100644 index 0000000..b7fd046 --- /dev/null +++ b/docs/src/developer/manual/img/naming-convention.README @@ -0,0 +1,7 @@ +# Image naming convention + +Images should be named according to reference doc, sub-section and order in document. +e.g. + +- The 1st image in instructions regarding zooming will be something like zooming-1, the 2nd image will be zooming-2, etc. +- The 1st image in quickstart regarding logging in will be login-1, etc diff --git a/docs/src/index.md b/docs/src/index.md new file mode 100644 index 0000000..8735f2c --- /dev/null +++ b/docs/src/index.md @@ -0,0 +1,60 @@ +--- +title: Documentation +summary: Cloud Native GIS + - Irwan Fathurrahman +date: 2024-06-01 +some_url: https://github.com/kartoza/CloudNativeGIS +copyright: Copyright 2024, Kartoza +contact: +license: This program is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. +context_id: nDU6LLGiXPTLADXY +--- + +# Cloud Native GIS + +## Overview + +Cloud Native GIS is a platform for handling layers and served on map. + +## Key Concepts + +**Layer** can be in vector and raster and being served as tile. + +**Style** is saved in database. Vector layer is in mapbox style. + +**Maputnik** is being used to change the style. + +## Disclaimer + +
+The software provided by this project is provided 'as is'. All information provided +within the platform should be independently verified before using as the basis for +action. The contributors and developers of this platform take no responsibility +for any loss of revenue, life, physical harm or any other adverse outcome that may +occur as a result of the use of this platform. +
+ +## Releases + +Our releases are published on our [GitHub releases page](https://github.com/kartoza/CloudNativeGIS/releases) + +| | **Project Badges** | | +| ----------------------- | ----------------------- | ----------------------- | +| ![License](https://img.shields.io/github/license/kartoza/CloudNativeGIS.svg) | ![Version](https://img.shields.io/github/release/kartoza/CloudNativeGIS.svg) | ![Commits](https://img.shields.io/github/commits-since/kartoza/CloudNativeGIS/{version}.svg) | +| ![Issue Tracker](https://img.shields.io/github/issues/kartoza/CloudNativeGIS.svg) | ![Closed Issues](https://img.shields.io/github/issues-closed/kartoza/CloudNativeGIS.svg) | ![Pull requests](https://img.shields.io/github/issues-pr/kartoza/CloudNativeGIS.svg) | + +#### Project Chatroom + +We do not yet have a [Chatroom]() set up for this project. Please use the GitHub issue tracker for discussions rather. + +#### Contributor License Agreement (CLA) + +Contributions to this project will be subject to our [Contributor License Agreement]() (Coming soon) + +#### License + +This project is open source, published under the AGPL-3. +You can read our license to find out what rights this license bestows to users and contributors. + +[License](about/license.md) + diff --git a/docs/src/quick_installation.md b/docs/src/quick_installation.md new file mode 100644 index 0000000..30e1fe1 --- /dev/null +++ b/docs/src/quick_installation.md @@ -0,0 +1,103 @@ +## Quick installation + +### Production + +``` +git submodule update +git clone https://github.com/kartoza/CloudNativeGIS +cp deployment/.template.env deployment/.env +cp deployment/docker-compose.override.template deployment/docker-compose.template +make up +``` + +The web will be available at `http://127.0.0.1/` + +To stop containers: + +``` +make kill +``` + +To stop and delete containers: + +``` +make down +``` + +### Development + +``` +git submodule update +git clone https://github.com/kartoza/CloudNativeGIS +cp deployment/.template.env deployment/.env +cp deployment/docker-compose.override.template deployment/docker-compose.template +``` + +After that, do + +- open new terminal +- on folder root of project, do + +``` +make serve +``` + +Wait until it is done +when there is sentence "webpack xxx compiled successfully in xxx ms".
+After that, don't close the terminal. +If it is accidentally closed, do `make serve` again + +Next step: + +- Open new terminal +- Do commands below + +``` +make up +make dev +``` + +Wait until it is on. + +The web can be accessed using `http://localhost:5000/` + +If the web is taking long time to load, restart cloud_native_gis_dev_1 container.
+The sequence should be `make dev`, after that run or restart cloud_native_gis_dev_1. + +### Maputnik updates + +CloudNativeGIS using maputnik to edit style. +We could update maputnik in the folder root/maputnik. +Maputnik can be accessed in the django-admin and layers, and there is "editor" +column that will be redirect to maputnik instance. +By default, it is using maputnik production. + +To change and test maputnik: + +``` +make serve-maputnik +``` + +After it is done, there will be link to maputnik. +Copy the link and paste in: +go to deployment/.env +change MAPUTNIK_URL to the copied link + +``` +restart dev container +``` + +After done, we need to update the maputnik production.
+First, create commit of maputnik and push it to repo. +Then + +``` +make build-maputnik +``` + +It will create files in the +django_project/cloud_native_gis/templates/maputnik.html +and also assets in the django_project/cloud_native_gis/static + +After that, test it by remove MAPUTNIK_URL and restart dev container. +If satisfied, just create commit for the changes. \ No newline at end of file diff --git a/docs/templates/cover.html b/docs/templates/cover.html new file mode 100644 index 0000000..257b2a8 --- /dev/null +++ b/docs/templates/cover.html @@ -0,0 +1,8 @@ +
+

The Handbook

+
+ +
+

Kartoza

+

2024

+
\ No newline at end of file diff --git a/docs/templates/footer.svg b/docs/templates/footer.svg new file mode 100644 index 0000000..2c42a38 --- /dev/null +++ b/docs/templates/footer.svg @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/templates/graphics.scss.templ b/docs/templates/graphics.scss.templ new file mode 100644 index 0000000..a5b00e3 --- /dev/null +++ b/docs/templates/graphics.scss.templ @@ -0,0 +1,7 @@ +/* BASE FOLDER token will be replaced at compile time by our bash script. */ + + +$logo-url: url('file://[BASE_FOLDER]/assets/kartoza-icon.png'); +$corner-logo-url: url('file://[BASE_FOLDER]/assets/logo.svg'); +$header-url: url('file://[BASE_FOLDER]/templates/header.svg'); +$footer-url: url('file://[BASE_FOLDER]/templates/footer.svg'); diff --git a/docs/templates/header.svg b/docs/templates/header.svg new file mode 100644 index 0000000..bfba99d --- /dev/null +++ b/docs/templates/header.svg @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/templates/styles.scss b/docs/templates/styles.scss new file mode 100644 index 0000000..15dae3b --- /dev/null +++ b/docs/templates/styles.scss @@ -0,0 +1,544 @@ +/* Sass property declarations - these two files contain stuff you can edit. + Don't edit anything in this file unless you are wanting to improve the base style. + This file is only used for the pdf generation. + */ +@import "variables.scss"; +@import "graphics.scss"; +/* To debug and define css rules, run the generator in debug mode + by editing mkdocs-pdf.yml and enabling debug mode. Then + redirect the generator output to an html file e.g. + + ./build-docs-pdf.sh > /tmp/output.html + xdg-open /tmp/output.html + + Then use the inspect tool in your browser to identify the css paths + of styles you want to modify. + + */ + +@import url('https://fonts.googleapis.com/css2?family=Roboto+Slab&family=Source+Code+Pro&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Source+Code+Pro&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+Mono:wght@100&display=swap'); + +// +// Print media specific page setup +// + +html { + font-family: 'Roboto Slab', serif; + font-size: $font-size; + color: $font-color; +} + +img { + display: block; + margin-left: auto; + margin-right: auto; + width: 50%; +} + +.cover-logo { + background-image: $logo-url; + background-repeat: no-repeat; + width: 440px; + height: 440px; + z-index: 1000; + /* Center on page */ + margin-left: auto; + margin-right: auto; + margin-top: 40px; + width: 50%; + background-color: #fff; + /* ensures that svg stretches to fill the container */ + background-size: contain; +} + +@font-face { + src: url(../assets/AvenirLTStd-Book.otf); + font-family: avenir; +} + +@page { + /* size: a4 portrait; */ + size: 210mm 297mm; + margin: 0mm; + padding: 0mm; + counter-increment: page; + font-family: Georgia, serif; + font-size: $font-size; + white-space: normal; + color: $font-color; + /* + Margin properties next: + + See https://www.quackit.com/css/at-rules/css_bottom-left-corner_at-rule.cfm + for a nice explanation of the margin properties for css print layouts */ + + + @top-left-corner { + @if $show-top-left-corner-logo { + background: $corner-logo-url; + } + + background-repeat: no-repeat; + background-position: 0% 0%; + background-size: contain; + z-index: 99; + //Hack needed or image will not show + content: " "; + } + + + @top-left { + /* Note this element gets obscured by top-center if it is solid. */ + z-index: 95; + content: $document-title; + color: $document-title-color; + } + + @top-center { + /* Idiosyncratic note: The top center section is the + only one that you can expand out to the full width of the page. + Also: The left elements will render under it, the right elements + over it (the z order increases as you move right). + + Be careful trying to use a PNG background as the DPI is hard to configure + and your graphics will appear pixelated or not scale correctly + so rather use an SVG. + + The setup below will span your SVG across the page, make sure your + SVG document has exactly the same dimensions. Leave a pixel or two + white space to the very right of your SVG as the right edge is + difficult to page align. + */ + background-color: transparent; + /* Dont remove these two lines, they force the center element + to the width of the page and height of the footer image. */ + min-width: 210mm; + min-height: 22mm; + background-repeat: no-repeat; + background-position: 0% 0%; + background-size: contain; + size: 210mm 22mm; + border: none; + background: $header-url; + /* Hack needed or image will not show */ + content: " "; + z-index: 90; + } + + @top-right { + min-width: 100mm; + background-color: transparent; + /* hack to make it appear as box */ + content: " "; + } + + @bottom-left-corner { + /* has no effect on corner elements */ + max-width: 0mm; + background-color: transparent; + /* hack to make it appear as box */ + content: " "; + } + + @bottom-left { + background-color: transparent; + /* hack to make it appear as box */ + content: " "; + } + + @bottom-center { + /* Idiosyncratic note: The bottom center section is the + only one that you can expand out to the full width of the page. + Also: The left elements will render under it, the right elements + over it (the z order increases as you move right). + + Be careful trying to use a PNG background as the DPI is hard to configure + and your graphics will appear pixelated or not scale correctly + so rather use an SVG. + + The setup below will span your SVG across the page, make sure your + SVG document has exactly the same dimensions. Leave a pixel or two + white space to the very right of your SVG as the right edge is + difficult to page align. + */ + background-color: transparent; + /* Dont remove these two lines, they force the center element + to the width of the page and height of the footer image. */ + min-width: 210mm; + min-height: 22mm; + background-repeat: no-repeat; + background-position: 0% 0%; + background-size: contain; + size: 210mm 22mm; + background: $footer-url; + /* Note you cannot do concatenation in CSS content + except I figured out this little trick below TS */ + content: " " counter(page) " "; + } + + @bottom-right { + max-width: 0mm; + background-color: transparent; + /* hack to make it appear as box */ + content: " "; + } + + @bottom-right-corner { + /* has no effect on corner elements */ + max-width: 0mm; + background-color: transparent; + /* hack to make it appear as box */ + content: " "; + } +} + + + +/** Setting margins */ + +@page { + margin: 2cm; + padding-top: 10mm; +} + + +/* The first page of a print can be manipulated as well */ + +@page :first { + position: absolute; + top: 0px; + right: 0px; +} + +// +// Heading counters and styles +// + +h1 { + counter-increment: c1; + counter-reset: c2; + counter-reset: c3; + counter-reset: c4; +} + +h2 { + counter-increment: c2; + counter-reset: c3; + counter-reset: c4; +} + +h3 { + counter-increment: c3; + counter-reset: c4; +} + +h4 { + counter-increment: c4; +} + +h1:before, +h2:before, +h3:before, +h4:before { + width: 2cm; + display: inline-block; + text-align: right; + padding-right: 0.25cm; +} + +h1:before { + color: $primary-color; + content: counter(c1); +} + +h2:before { + color: $secondary-color; + content: counter(c1) "." counter(c2); +} + +h3:before { + color: $tertiary-color; + content: counter(c1) "." counter(c2) "." counter(c3); +} + +h4:before { + color: $primary-color; + content: counter(c1) "." counter(c2) "." counter(c3) "." counter(c4); +} + +article h1, +h2, +h3, +h4 { + width: 100%; + padding-right: 20pt; + text-align: right; + background: white; + color: black; + page-break-after: avoid; + page-break-inside: avoid; + display: inline-block; +} + + +article h1 { + border-bottom: 1px solid $primary-color; + color: $primary-color; + padding-top: 24px; + text-decoration-style: double; + margin-bottom: 32px; +} + +article h2 { + color: $secondary-color; + border-bottom: 2px solid $secondary-color; + padding-top: 12px; + margin-bottom: 12px; +} + +article h3 { + border-bottom: none; + color: $tertiary-color; + padding-top: 8px; + margin-bottom: 8px; +} + +article h4 { + border-bottom: none; + color: $primary-color; + padding-top: 8px; + margin-bottom: 8px; +} + +/* MKdocs renders code blocks inside a pre element and + inline code simply inside code elements + + Code block related items below are based on the article + at https://css-tricks.com/styling-code-in-and-out-of-blocks/ + + */ + +code { + font-family: monospace; + font-size: inherit; + color: $font-color; +} + + +/* Code in text */ + +p>code, +li>code, +dd>code, +td>code { + display: inline; + background: $inline-code-background; + white-space: pre-wrap; + //max-width: 100%; + //min-width: 100px; + word-wrap: break-word; + box-decoration-break: clone; + border-radius: .2rem; + font-size: $font-size; + color: #000 !important; +} + + +/* code in blocks */ + +pre code:before { + display: block; + width: 25%; + position: relative; + top: -33px; + left: -20px; + content: '🧑‍💻 Code:'; + padding: 1em 1em; + margin-left: 0; + margin-top: 1em; + margin-bottom: 1em; + border-left: 5px solid $codeblock-label-border; + background: $codeblock-label-background; + font-size: $font-size; + color: $codeblock-label-font-color; + font-weight: bolder; +} + +pre code { + display: block; + white-space: pre; + max-width: 100%; + min-width: 100px; + padding: 0; + font-size: $code-font-size; + font-family: $code-font-family; + /* margin: 1em 3em; + */ + padding: 1em 1em; + margin-left: 8px; + margin-top: 1em; + margin-bottom: 1em; + width: 100%; + border-left: 5px solid $codeblock-border; + background: $codeblock-background; + color: $font-color; +} + + +/* End of code blocks */ + +blockquote:before { + display: block; + width: 25%; + position: relative; + top: -33px; + left: -20px; + content: '🧑‍🔧 Note:'; + padding: 1em 1em; + margin-top: 10mm; + margin-left: 0; + margin-bottom: 1em; + border-left: 5px solid $blockquote-label-border; + background: $blockquote-label-background; + font-size: $font-size; + color: $blockquote-label-font-color; + font-weight: bolder !important; +} + +blockquote { + margin-left: 8px; + margin-top: 0mm; + margin-bottom: 0mm; + width: 100%; + border-left: 5px solid $blockquote-border; + background: $blockquote-background; + font-size: $font-size; + color: $font-color; +} + +blockquote p { + margin: 0; +} + +img { + page-break-inside: avoid; + page-break-after: avoid; +} + +table, +pre { + page-break-inside: avoid; +} + +ul, +ol, +dl { + page-break-before: avoid; +} + +table { + border-collapse: collapse; + margin: 25px 0; + font-size: 0.9em; + font-family: sans-serif; + min-width: 400px; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.15); + margin-left: auto; + margin-right: auto; +} + + +/* Next section based on https://dev.to/dcodeyt/creating-beautiful-html-tables-with-css-428l */ + +table thead tr { + background-color: $primary-color; + color: #ffffff; + text-align: left; +} + +table th, +table td { + padding: 12px 15px; +} + +table tbody tr { + border-bottom: 1px solid $primary-color; +} + +table tbody tr:nth-of-type(even) { + background-color: #f3f3f3; +} + +table tbody tr:last-of-type { + border-bottom: 2px solid $primary-color; +} + +table tbody tr.active-row { + font-weight: bold; + color: #009879; +} + +/* End of section based on https://dev.to/dcodeyt/creating-beautiful-html-tables-with-css-428l */ + +ol, +ul { + padding-top: 1ch; + padding-bottom: 1ch; +} + +li { + padding-left: 1ch; +} + +ul.li::marker { + color: $primary-color; + font-weight: bold; + content: '⧈'; + margin-right: 10px; +} + + + +/* CSS Reset Rules from https://perishablepress.com/a-killer-collection-of-global-css-reset-styles/ */ + +* { + vertical-align: baseline; + font-family: inherit; + font-style: inherit; + font-size: 100%; + border: none; + padding: 0; + margin: 0; +} + +h1, +h2, +h3, +h4, +h5, +h6, +p, +pre, +blockquote, +form, +ul, +ol, +dl { + margin: 0px 0; +} + +article p { + color: $font-color; + padding-top: 5px; +} + +li, +dd, +blockquote { + margin-left: 40px; +} + + +/* End of resets ------------------------------- */ \ No newline at end of file diff --git a/docs/templates/variables.scss b/docs/templates/variables.scss new file mode 100644 index 0000000..475de18 --- /dev/null +++ b/docs/templates/variables.scss @@ -0,0 +1,33 @@ +/* Sass property declarations */ +$document-title: 'The Handbook'; +$document-title-color: #ffffff; +$show-top-left-corner-logo: false; +$primary-color: #0099FF; +$secondary-color: #FF0099; +$tertiary-color: #8a8b8b; +$primary-color-light: #cdedff; +$secondary-color-light: #f4ebdb; +$tertiary-color-light: #eaeaea; +$primary-color-dark: #0082c7; +$secondary-color-dark: #e79709; +$tertiary-color-dark: #3f3f3f; + +$font-size: 10pt; +$font-color: #000; + +$code-font-size: 8pt; +$code-font-family: 'Noto Sans Mono', monospace; + +$inline-code-background: #bfe9ff; + +$codeblock-label-font-color: white; +$codeblock-label-background: $primary-color; +$codeblock-label-border: $primary-color-dark; +$codeblock-background: $inline-code-background; +$codeblock-border: $primary-color; + +$blockquote-label-font-color: white; +$blockquote-label-background: $secondary-color; +$blockquote-label-border: $secondary-color-dark; +$blockquote-background: $secondary-color-light; +$blockquote-border: $secondary-color; \ No newline at end of file diff --git a/docs/uuid_redirects_hook.py b/docs/uuid_redirects_hook.py new file mode 100644 index 0000000..638549b --- /dev/null +++ b/docs/uuid_redirects_hook.py @@ -0,0 +1,30 @@ +import logging +import mkdocs.plugins + +log = logging.getLogger('mkdocs') + +@mkdocs.plugins.event_priority(-50) + +def on_page_content(html, page, config, files): + + # get redirect config + redirect_plugin = config.get('plugins', {}).get('redirects') + redirects = redirect_plugin.config.get('redirect_maps',{}) + + if "context_id" in page.meta: + context_id = page.meta.get("context_id") + key = f"{context_id}.md" + if key in redirects: + log_context_id_warning(page.meta.context_id, page.file.src_path, redirects[key]) + redirects[key] = page.file.src_path + + for item in page.toc.items: + # maybe implement check for UUID or something else + if item.id.isdigit(): + key = f"{item.id}.md" + if key in redirects: + log_context_id_warning(item.id, page.file.src_path, redirects[key]) + redirects[key] = f"{page.file.src_path}{item.url}" + +def log_context_id_warning(context_id, markdown1, markdown2): + log.warning(f"Context ID {context_id} used in {markdown1} and {markdown2}")