From 7480dbca05ebbd9c1dbe0f6786c0f1bc8a438bb5 Mon Sep 17 00:00:00 2001 From: Volker Schukai <volker.schukai@schukai.com> Date: Wed, 29 Jun 2022 19:05:29 +0200 Subject: [PATCH] chore: commit save point --- .gitignore | 1 + .idea/.gitignore | 8 + .idea/aws.xml | 17 + .idea/documentation-manager.iml | 10 + .idea/markdown.xml | 9 + .idea/misc.xml | 6 + .idea/modules.xml | 10 + .idea/vcs.xml | 6 + Makefile | 68 +++ README.md | 317 ++++++++-- application/source/changelog.go | 69 +++ application/source/commandline.go | 185 ++++++ application/source/commandlineoptions.go | 62 ++ application/source/config.go | 113 ++++ application/source/defaults.go | 233 ++++++++ application/source/errors.go | 9 + application/source/files.go | 101 ++++ application/source/gitlab.go | 377 ++++++++++++ application/source/go.mod | 49 ++ application/source/go.sum | 546 ++++++++++++++++++ application/source/issues.go | 157 +++++ application/source/items.go | 127 ++++ application/source/l10n.go | 447 ++++++++++++++ application/source/main.go | 50 ++ application/source/message.go | 57 ++ application/source/overview.go | 300 ++++++++++ application/source/pandoc.go | 46 ++ application/source/privacy.go | 95 +++ application/source/requirements.go | 432 ++++++++++++++ application/source/run.go | 40 ++ application/source/tasks.go | 143 +++++ application/source/util.go | 196 +++++++ application/web/index.html | 59 ++ deployment/scripts | 0 deployment/upload.sh | 4 + .../assets/schukai-weiss-1000-210.png | Bin 0 -> 10512 bytes development/examples/example1/1425.md | 145 +++++ development/examples/example1/144444.md | 160 +++++ development/examples/example1/assets/demo.png | Bin 0 -> 67352 bytes development/examples/example1/req1/1/test1.md | 176 ++++++ development/examples/example1/req1/1/test2.md | 142 +++++ development/examples/example1/req1/1/test3.md | 142 +++++ development/examples/example1/req1/1/test4.md | 142 +++++ development/examples/example1/req1/2/test1.md | 142 +++++ development/examples/example1/req1/2/test2.md | 142 +++++ development/examples/example1/req1/2/test3.md | 142 +++++ development/examples/example1/req1/2/test4.md | 142 +++++ development/examples/example1/req1/2/test5.md | 142 +++++ development/examples/example1/req1/2/test6.md | 142 +++++ development/examples/example1/req1/3/test1.md | 142 +++++ development/examples/example1/req1/3/test2.md | 142 +++++ development/examples/example1/req1/3/test3.md | 142 +++++ development/examples/example1/req1/3/test4.md | 142 +++++ development/examples/example1/req1/3/test5.md | 142 +++++ development/examples/example1/req1/3/test6.md | 142 +++++ development/examples/example1/req1/3/test7.md | 142 +++++ development/examples/example1/req1/4/test1.md | 142 +++++ development/examples/example1/req1/4/test2.md | 142 +++++ development/examples/example1/req1/4/test3.md | 142 +++++ development/examples/example1/req1/4/test4.md | 142 +++++ development/examples/example1/req1/5/test1.md | 143 +++++ development/examples/example1/req1/5/test2.md | 142 +++++ development/examples/example1/req1/6/test1.md | 142 +++++ development/examples/example1/req1/6/test2.md | 142 +++++ development/examples/overview.template | 108 ++++ development/makefiles/color.mk | 17 + development/makefiles/directories-default.mk | 32 + development/makefiles/directories-standard.mk | 36 ++ development/makefiles/go.mk | 12 + development/makefiles/license-agpl3.mk | 13 + development/makefiles/nodejs.mk | 36 ++ development/makefiles/output.mk | 54 ++ development/makefiles/placeholder.mk | 9 + development/makefiles/s3.mk | 14 + development/makefiles/target-build-go.mk | 22 + development/makefiles/target-build-nodejs.mk | 0 development/makefiles/target-caddy.mk | 23 + development/makefiles/target-deploy-tool.mk | 20 + development/makefiles/target-git.mk | 47 ++ development/makefiles/target-help.mk | 46 ++ development/makefiles/target-init-standard.mk | 20 + development/makefiles/target-init.mk | 18 + development/makefiles/target-jekyll.mk | 0 development/makefiles/target-minerva.mk | 0 .../makefiles/target-update-makefiles.mk | 22 + development/makefiles/target-variable.mk | 12 + development/makefiles/terminal-check.mk | 13 + development/makefiles/terminal.mk | 41 ++ development/makefiles/version.mk | 27 + documentation/assets/.gitkeep | 0 project.mk | 3 + release.json | 3 + 92 files changed, 8830 insertions(+), 57 deletions(-) create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/aws.xml create mode 100644 .idea/documentation-manager.iml create mode 100644 .idea/markdown.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 Makefile create mode 100644 application/source/changelog.go create mode 100644 application/source/commandline.go create mode 100644 application/source/commandlineoptions.go create mode 100644 application/source/config.go create mode 100644 application/source/defaults.go create mode 100644 application/source/errors.go create mode 100644 application/source/files.go create mode 100644 application/source/gitlab.go create mode 100644 application/source/go.mod create mode 100644 application/source/go.sum create mode 100644 application/source/issues.go create mode 100644 application/source/items.go create mode 100644 application/source/l10n.go create mode 100644 application/source/main.go create mode 100644 application/source/message.go create mode 100644 application/source/overview.go create mode 100644 application/source/pandoc.go create mode 100644 application/source/privacy.go create mode 100644 application/source/requirements.go create mode 100644 application/source/run.go create mode 100644 application/source/tasks.go create mode 100644 application/source/util.go create mode 100644 application/web/index.html create mode 100644 deployment/scripts create mode 100644 deployment/upload.sh create mode 100644 development/examples/assets/schukai-weiss-1000-210.png create mode 100644 development/examples/example1/1425.md create mode 100644 development/examples/example1/144444.md create mode 100644 development/examples/example1/assets/demo.png create mode 100644 development/examples/example1/req1/1/test1.md create mode 100644 development/examples/example1/req1/1/test2.md create mode 100644 development/examples/example1/req1/1/test3.md create mode 100644 development/examples/example1/req1/1/test4.md create mode 100644 development/examples/example1/req1/2/test1.md create mode 100644 development/examples/example1/req1/2/test2.md create mode 100644 development/examples/example1/req1/2/test3.md create mode 100644 development/examples/example1/req1/2/test4.md create mode 100644 development/examples/example1/req1/2/test5.md create mode 100644 development/examples/example1/req1/2/test6.md create mode 100644 development/examples/example1/req1/3/test1.md create mode 100644 development/examples/example1/req1/3/test2.md create mode 100644 development/examples/example1/req1/3/test3.md create mode 100644 development/examples/example1/req1/3/test4.md create mode 100644 development/examples/example1/req1/3/test5.md create mode 100644 development/examples/example1/req1/3/test6.md create mode 100644 development/examples/example1/req1/3/test7.md create mode 100644 development/examples/example1/req1/4/test1.md create mode 100644 development/examples/example1/req1/4/test2.md create mode 100644 development/examples/example1/req1/4/test3.md create mode 100644 development/examples/example1/req1/4/test4.md create mode 100644 development/examples/example1/req1/5/test1.md create mode 100644 development/examples/example1/req1/5/test2.md create mode 100644 development/examples/example1/req1/6/test1.md create mode 100644 development/examples/example1/req1/6/test2.md create mode 100644 development/examples/overview.template create mode 100644 development/makefiles/color.mk create mode 100644 development/makefiles/directories-default.mk create mode 100644 development/makefiles/directories-standard.mk create mode 100644 development/makefiles/go.mk create mode 100644 development/makefiles/license-agpl3.mk create mode 100644 development/makefiles/nodejs.mk create mode 100644 development/makefiles/output.mk create mode 100644 development/makefiles/placeholder.mk create mode 100644 development/makefiles/s3.mk create mode 100644 development/makefiles/target-build-go.mk create mode 100644 development/makefiles/target-build-nodejs.mk create mode 100644 development/makefiles/target-caddy.mk create mode 100644 development/makefiles/target-deploy-tool.mk create mode 100644 development/makefiles/target-git.mk create mode 100644 development/makefiles/target-help.mk create mode 100644 development/makefiles/target-init-standard.mk create mode 100644 development/makefiles/target-init.mk create mode 100644 development/makefiles/target-jekyll.mk create mode 100644 development/makefiles/target-minerva.mk create mode 100644 development/makefiles/target-update-makefiles.mk create mode 100644 development/makefiles/target-variable.mk create mode 100644 development/makefiles/terminal-check.mk create mode 100644 development/makefiles/terminal.mk create mode 100644 development/makefiles/version.mk create mode 100644 documentation/assets/.gitkeep create mode 100644 project.mk create mode 100644 release.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8f5819e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/deployment/build/ \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/aws.xml b/.idea/aws.xml new file mode 100644 index 0000000..ec328d0 --- /dev/null +++ b/.idea/aws.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="accountSettings"> + <option name="activeProfile" value="profile:default" /> + <option name="activeRegion" value="eu-west-1" /> + <option name="recentlyUsedProfiles"> + <list> + <option value="profile:default" /> + </list> + </option> + <option name="recentlyUsedRegions"> + <list> + <option value="eu-west-1" /> + </list> + </option> + </component> +</project> \ No newline at end of file diff --git a/.idea/documentation-manager.iml b/.idea/documentation-manager.iml new file mode 100644 index 0000000..25ed3f6 --- /dev/null +++ b/.idea/documentation-manager.iml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="JAVA_MODULE" version="4"> + <component name="Go" enabled="true" /> + <component name="NewModuleRootManager" inherit-compiler-output="true"> + <exclude-output /> + <content url="file://$MODULE_DIR$" /> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + </component> +</module> \ No newline at end of file diff --git a/.idea/markdown.xml b/.idea/markdown.xml new file mode 100644 index 0000000..ec0b30f --- /dev/null +++ b/.idea/markdown.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="MarkdownSettings"> + <enabledExtensions> + <entry key="MermaidLanguageExtension" value="false" /> + <entry key="PlantUMLLanguageExtension" value="true" /> + </enabledExtensions> + </component> +</project> \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..639900d --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="ProjectRootManager"> + <output url="file://$PROJECT_DIR$/out" /> + </component> +</project> \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..3cb0cef --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="ProjectModuleManager"> + <modules> + <module fileurl="file://$PROJECT_DIR$/.idea/documentation-manager.iml" filepath="$PROJECT_DIR$/.idea/documentation-manager.iml" /> + <module fileurl="file://$PROJECT_DIR$/../../../schukai/utilities/makefile/makefile.iml" filepath="$PROJECT_DIR$/../../../schukai/utilities/makefile/makefile.iml" /> + <module fileurl="file://$PROJECT_DIR$/../requirements-manager/requirements-manager.iml" filepath="$PROJECT_DIR$/../requirements-manager/requirements-manager.iml" /> + </modules> + </component> +</project> \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="VcsDirectoryMappings"> + <mapping directory="" vcs="Git" /> + </component> +</project> \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0a1ccd2 --- /dev/null +++ b/Makefile @@ -0,0 +1,68 @@ +############################################################################################# +############################################################################################# +## +## PROJECT-DEFINITIONS +## +############################################################################################# +############################################################################################# + +COMPONENT_NAME := DocMan + +############################################################################################# +############################################################################################# +## +## MORE GENERAL BLOCK WITH STANDARD DEFINITIONS +## +############################################################################################# +############################################################################################# + +# get Makefile directory name: http://stackoverflow.com/a/5982798/376773 +THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)) +PROJECT_ROOT:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd)/ +THIS_MAKEFILE:=$(PROJECT_ROOT)$(THIS_MAKEFILE_PATH) + + +-include $(PROJECT_ROOT)project.mk + + +## Define the location of Makefiles +MAKEFILE_IMPORT_PATH?=$(PROJECT_ROOT)makefiles/ + +############################################################################################# +############################################################################################# +## +## INCLUSION OF VARIOUS STANDARD RULES +## +############################################################################################# +############################################################################################# + +include $(MAKEFILE_IMPORT_PATH)license-agpl3.mk +include $(MAKEFILE_IMPORT_PATH)placeholder.mk +include $(MAKEFILE_IMPORT_PATH)directories-standard.mk +include $(MAKEFILE_IMPORT_PATH)go.mk +include $(MAKEFILE_IMPORT_PATH)s3.mk +include $(MAKEFILE_IMPORT_PATH)color.mk +include $(MAKEFILE_IMPORT_PATH)terminal.mk +include $(MAKEFILE_IMPORT_PATH)output.mk +include $(MAKEFILE_IMPORT_PATH)version.mk +include $(MAKEFILE_IMPORT_PATH)target-help.mk +include $(MAKEFILE_IMPORT_PATH)target-variable.mk +include $(MAKEFILE_IMPORT_PATH)target-update-makefiles.mk +include $(MAKEFILE_IMPORT_PATH)target-deploy-tool.mk +include $(MAKEFILE_IMPORT_PATH)target-build-go.mk +include $(MAKEFILE_IMPORT_PATH)target-git.mk +include $(MAKEFILE_IMPORT_PATH)terminal-check.mk + + +############################################################################################# +############################################################################################# +## +## PROJECT-DEFINITIONS +## +############################################################################################# +############################################################################################# + + + + + diff --git a/README.md b/README.md index 02f1c40..321c6b3 100644 --- a/README.md +++ b/README.md @@ -1,92 +1,295 @@ -# Document Manager +# Documentation Manager +This tool helps to manage requirements written in Markdown. +## Install -## Getting started +DocMan is a binary file that must be stored in a directory. +The files can be found [here](http://download.schukai.com/tools/docman/). -To make it easy for you to get started with GitLab, here's a list of recommended next steps. +For Linux, the execution bit must still be set. -Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! +```bash +chmod u+x docman +``` + +## Commands + +The date format for the output can be specified with the parameter `--date-format`. +The format can be looked up in the first column of the table below. + +| Layout | Java notation | C notation | Notes | +| ------------------ | --------------- | ------------ | ---------- | +| 2006-01-02 | yyyy-MM-dd | %F | ISO 8601 | +| 20060102 | yyyyMMdd | %Y%m%d | ISO 8601 | +| January 02, 2006 | MMMM dd, yyyy | %B %d, %Y | | +| 02 January 2006 | dd MMMM yyyy | %d %B %Y | | +| 02-Jan-2006 | dd-MMM-yyyy | %d-%b-%Y | | +| 01/02/06 | MM/dd/yy | %D | US | +| 01/02/2006 | MM/dd/yyyy | %m/%d/%Y | US | +| 010206 | MMddyy | %m%d%y | US | +| Jan-02-06 | MMM-dd-yy | %b-%d-%y | US | +| Jan-02-2006 | MMM-dd-yyyy | %b-%d-%Y | US | +| 06 | yy | %y | | +| Mon | EEE | %a | | +| Monday | EEEE | %A | | +| Jan-06 | MMM-yy | %b-%y | | + +### Help + +There is help on the command line for each individual command. + +```bash +docman --help +``` + +### New Requiremants + +A new request can be created with the following command. + +```bash +docman requirements add --id 1425 +``` + +A completely new file with a structure is created. The `--id 1425` is both the file name and the ID of the request. + +All available fields are listed in the new file. + +### Output a PDF + +A pdf can be created using the following command: + +```bash +docman overview \ + print \ + --path=requirement/documents \ + --column=ID \ + --column=Title \ + --template=template/schukai.md \ + --latex-template-path=requirement/template/schukai.latex \ + --output=report.pdf \ + --format=pdf +``` + +In this case the markdown files in the path `requirement/documents` are read. + +A table with all requirements is created in the file and the two columns +`ID` and `Title` are used. Additional columns can be added using additional options `--column`. + +File `template/schukai.md` is used as a template. + +The LaTeX template `requirement/template/schukai.latex` is used for the design of the pdf. + +The output format is PDF and the filename of the pdf document is `report.pdf`. + +You can use a complete directory or a subdirectory as the path. + +### Output of the tasks + +```bash +docman tasks print --path=examples/ +``` + +The output is then of the type: + +| AUFGABE | BIS | ERLEDIGT | DATEI | +| -------------------------- | ----- | ---------- | -------------------- | +| das ist das erste todo 1 | — | — | ./req1/001-1425.md | + +### Output of the items -## Add your files +```bash +docman requirements print --path examples/ --column ID --column Title +``` + +The output is then of the type: + +| ID | TITEL | +| ---- | ---------------- | +| A1 | My requirement | + +More columns can be added with `--column`. -- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files -- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command: +### Output of privacy +```bash +docman privacy print --path=example/ ``` -cd existing_repo -git remote add origin https://gitlab.schukai.com/oss/utilities/document-manager.git -git branch -M master -git push -uf origin master + +### Output of requirements + +```bash +docman requirements print --path=example/ --column=ID --column= ``` -## Integrate with your tools +The output is then of the type: -- [ ] [Set up project integrations](https://gitlab.schukai.com/oss/utilities/document-manager/-/settings/integrations) +| ID | GRUPPE | NAME | TYP | BESCHREIBUNG | BIS | ERLEDIGT | AM | VON | DATEI | +| -------------------- | -------- | -------------------------- | ------ | -------------- | ------------ | ---------- | ------------ | ----- | ---------------------- | +| 23423-Beistellung1 | A1 | Beistellung eines Bildes | Bild | Großes Logo | 2022-12-12 | ✓ | 2022-12-01 | Me | ./req1/002/002-01.md | -## Collaborate with your team +### Output changelog -- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/) -- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) -- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) -- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) -- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html) +```bash +docman changelog print --path=example/ +``` -## Test and Deploy +The output is then of the type: -Use the built-in continuous integration in GitLab. +``` +### 01.05.2022 -- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html) -- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) -- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) -- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/) -- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html) +- Requirement (R2) -*** +### 24.01.2022 -# Editing this README +- Requirement (R1) -When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template. +``` -## Suggestions for a good README -Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information. +### Output report -## Name -Choose a self-explaining name for your project. +``` +requirements report --grouped-by ID +``` -## Description -Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors. +This command produces two tables: + +| Anforderung | Gesch | TIME SPENT | +| ------------- | ------- | --------- | +| ID1 | 40 | 1 | +| ID2 | 40 | 1 | +| ID3 | 40 | 1 | +| ID4 | 40 | 1 | +| ID5 | 40 | 2 | +| ID6 | 40 | 2 | +| ID7 | 40 | 2 | +| ID8 | 40 | 2 | +| ID9 | 40 | 2 | +| ID10 | 40 | 2 | +| ID11 | 40 | 3 | +| ID12 | 40 | 3 | +| ID13 | 40 | 3 | +| ID14 | 40 | 3 | +| ID15 | 40 | 3 | +| ID16 | 40 | 3 | +| ID17 | 40 | 3 | +| ID18 | 40 | 4 | +| ID19 | 40 | 4 | +| ID20 | 40 | 4 | +| ID21 | 40 | 4 | +| ID22 | 40 | 5 | +| ID23 | 40 | 5 | +| ID24 | 40 | 6 | +| ID25 | 40 | 6 | + +1) Groups all estimates and adds up the estimate and the booked times. This allows you to see how much time you have + spent. + +| KEY | PLANNED VALUE | TIME SPENT | RATIO | +| :---- | --------------- | ------------ | ------- | +| ID1 | 1000 | 75h0m0s | 7.50 | + +2) This table shows for each plan value the hours needed, the mean, the variance and the standard deviation. + +| PLAN VALUE | TIME SPENT | MEAN | VARIANCE | STANDARD DEVIATION | +| ------------ | ------------ | ------ | ---------- | -------------------- | +| 40 | 75h0m0s | 3.00 | 2.08 | 1.44 | + +On average, we needed 3 hours in the example. +However, we needed 6 hours for 2 requirements. + +The variance, or standard deviation, gives us a measure of how accurate we are. +The smaller the standard deviation, the better. + +So what decision can we derive? If a new requirement is estimated at +40, the hours offered should be between 3 and 5. + +### Sync with Gitlab + +You can synchronize the issues of a document with a Gitlab server. + +```bash +docman gitlab sync --path=example/ +``` -## Badges -On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge. +If no ID is defined in the document, an issue is created, -## Visuals -Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method. +```yaml +issues: + - gitlab: + title: "Issue 1" +``` + +otherwise the data is updated. + +```yaml +issues: + - gitlab: + id: 1 +``` + +## Structure + +### The Text + +The individual requirements are Markdown files with integrated YAML structure. The YAML structure must +be introduced with `---` and closed with `...`. + +The data from the YAML block can be integrated in the text via [placeholders](https://pkg.go.dev/text/template). + +For example, the following statement can be used to include the items within the document. + +```golang +{{ if.Items }} +**Items** + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range.Items +}}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} +``` -## Installation -Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection. +If the PDF function is used, LaTeX commands can also be included in the text. For example, the LaTex instruction ` +/newline' leads to a line break. -## Usage -Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. +## YAML -## Support -Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc. +| | `>` | `│` | | `"` | `'` | `>-` | `>+` | `│-` | `│+` | +|-----------------------------------|---------|--------|-----|------|-----|-------|--------|--------|--------| +| **Spaces/newlines converted as:** | | | | | | | | | | +| Trailing space → | \_ | \_ | | | | \_ | \_ | \_ | \_ | +| Leading space → | \\n\_ | \\n\_ | | | | \\n\_ | \\n\_ | \\n\_ | \\n\_ | +| Single newline → | \_ | \\n | \_ | \_ | \_ | \_ | \_ | \\n | \\n | +| Double newline → | \\n | \\n\\n | \\n | \\n | \\n | \\n | \\n | \\n\\n | \\n\\n | +| Final newline → | \\n | \\n | | | | | \\n | | \\n | +| Final double newline → | | | | | | | \\n\\n | | \\n\\n | +| **How to create a literal:** | | | | | | | | | | +| Single quote | ' | ' | ' | ' | '' | ' | ' | ' | ' | +| Double quote | " | " | " | \\" | " | " | " | " | " | +| Backslash | \\ | \\ | \\ | \\\\ | \\ | \\ | \\ | \\ | \\ | +| **Other features** | | | | | | | | | | +| In-line newlines with `\n` | 🚫 | 🚫 | 🚫 | ✅ | 🚫 | 🚫 | 🚫 | 🚫 | 🚫 | +| Spaceless newlines with `\` | 🚫 | 🚫 | 🚫 | ✅ | 🚫 | 🚫 | 🚫 | 🚫 | 🚫 | +| `#` or `:` in value | ✅ | ✅ | 🚫 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| Can start on same line as key | 🚫 | 🚫 | ✅ | ✅ | ✅ | 🚫 | 🚫 | 🚫 | 🚫 | -## Roadmap -If you have ideas for releases in the future, it is a good idea to list them in the README. +`│ -> |` -## Contributing -State if you are open to contributions and what your requirements are for accepting them. +## Latex -For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self. +Individual LaTeX commands can be looked up here: -You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser. +* [tug.ctan.org/info/latex-refsheet/LaTeX_RefSheet.pdf](http://tug.ctan.org/info/latex-refsheet/LaTeX_RefSheet.pdf) +* [www.uni-frankfurt.de/53485609/latexsheet.pdf](https://www.uni-frankfurt.de/53485609/latexsheet.pdf) +* [www.latex4ei.de/downloads/LaTeX_CheatSheet.pdf](https://www.latex4ei.de/downloads/LaTeX_CheatSheet.pdf) +* [download.schukai.com/tools/docman/](http://download.schukai.com/tools/docman/) -## Authors and acknowledgment -Show your appreciation to those who have contributed to the project. -## License -For open source projects, say how it is licensed. +## Change Log -## Project status -If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers. +- Version 1.0.25 (20220622174620) + - Added support for `gitlab sync` command diff --git a/application/source/changelog.go b/application/source/changelog.go new file mode 100644 index 0000000..c944df9 --- /dev/null +++ b/application/source/changelog.go @@ -0,0 +1,69 @@ +package main + +import ( + "fmt" + "sort" + "strings" +) + +type logs []string + +func buildChangelog(pageMap map[string]*requirement) (error, string, bool) { + + changelog := make(map[string]logs) + datemap := make(map[string]string) + + for _, q := range pageMap { + p := *q + + e := strings.Trim(p.Title+" ("+p.ID+")", " ") + + d := p.Created.String() + datemap[d] = p.Created.Format(config.Locale.DateFormat) + if p.Created.Before(p.LastUpdate) { + d = p.LastUpdate.String() + datemap[d] = p.LastUpdate.Format(config.Locale.DateFormat) + } + + changelog[d] = append(changelog[d], e) + + } + + hasChangelog := false + result := "" + + var sortedKeys sort.StringSlice + for k := range changelog { + sortedKeys = append(sortedKeys, k) + } + + sort.Sort(sort.Reverse(sortedKeys)) + + for _, k := range sortedKeys { + + result += "### " + datemap[k] + "\n\n" + + for _, m := range changelog[k] { + result += "- " + m + "\n" + } + + result += "\n" + hasChangelog = true + + } + + return nil, result, hasChangelog + +} + +func printChangelog() error { + + err, pageData := collectStructureFromFiles(config.Path) + if err != nil { + return err + } + + err, table, _ := buildChangelog(pageData) + fmt.Println(table) + return err +} diff --git a/application/source/commandline.go b/application/source/commandline.go new file mode 100644 index 0000000..35b5366 --- /dev/null +++ b/application/source/commandline.go @@ -0,0 +1,185 @@ +package main + +import ( + "os" + "path" + "path/filepath" + + "github.com/jessevdk/go-flags" +) + +var ( + config *Configuration + arguments *commandLineOptions +) + +func executeCommand() { + + arguments = new(commandLineOptions) + p := flags.NewParser(arguments, flags.Default) + _, err := p.Parse() + if err != nil { + os.Exit(-1) + } + + config = NewConfiguration(arguments.Config) + + if arguments.Path != "" { + config.Path = arguments.Path + } + + if arguments.DateFormat != "" { + config.Locale.DateFormat = arguments.DateFormat + } + + activeCommand := p.Command.Active + + if activeCommand == nil { + return + } + + switch activeCommand.Name { + + case "version": + printInfo("Version " + version + " (" + build + ")") + case "changelog": + subcommand := activeCommand.Active + switch subcommand.Name { + case "print": + err := printChangelog() + if err != nil { + printErrorAndExit(2, err.Error()) + } + } + case "privacy": + subcommand := activeCommand.Active + switch subcommand.Name { + case "print": + err := printPrivacy() + if err != nil { + printErrorAndExit(2, err.Error()) + } + } + case "overview": + subcommand := activeCommand.Active + switch subcommand.Name { + case "print": + + if len(arguments.Overview.Print.Columns) > 0 { + config.Requirement.Table.Columns = validateColumns(arguments.Overview.Print.Columns) + } + + if arguments.Overview.Print.TemplatePath != "" { + config.Overview.Template.Internal.MarkdownContent = readTemplate(arguments.Overview.Print.TemplatePath) + } else if config.Overview.Template.Markdown != "" { + config.Overview.Template.Internal.MarkdownContent = readTemplate(config.Overview.Template.Markdown) + } else { + config.Overview.Template.Internal.MarkdownContent = defaultOverviewTemplate + } + + if arguments.Overview.Print.LatexTemplatePath != "" { + config.Overview.Template.Latex = arguments.Overview.Print.LatexTemplatePath + } + + err := PrintOverview() + if err != nil { + printErrorAndExit(2, err.Error()) + } + } + + case "requirements": + subcommand := activeCommand.Active + switch subcommand.Name { + case "report": + err := printRequirementReport() + if err != nil { + printErrorAndExit(2, err.Error()) + } + case "add": + config.Requirement.Template.Add = defaultNewRequirementTemplate + err := addRequirement() + if err != nil { + printErrorAndExit(2, err.Error()) + } + case "print": + if len(arguments.Requirements.Print.Columns) > 0 { + config.Requirement.Table.Columns = validateColumns(arguments.Requirements.Print.Columns) + } + err := printRequirements() + if err != nil { + printErrorAndExit(2, err.Error()) + } + } + + case "tasks": + subcommand := activeCommand.Active + switch subcommand.Name { + case "print": + err := printTaskTable() + if err != nil { + printErrorAndExit(2, err.Error()) + } + } + + case "issues": + subcommand := activeCommand.Active + switch subcommand.Name { + case "print": + + if arguments.Issues.Print.GitlabToken != "" { + config.Gitlab.Token = arguments.Issues.Print.GitlabToken + } + + err := printIssueTable() + if err != nil { + printErrorAndExit(2, err.Error()) + } + + case "items": + subcommand := activeCommand.Active + switch subcommand.Name { + case "print": + err := printItemTable() + if err != nil { + printErrorAndExit(2, err.Error()) + } + } + + } + + case "gitlab": + subcommand := activeCommand.Active + switch subcommand.Name { + case "sync": + + if arguments.Gitlab.GitlabToken != "" { + config.Gitlab.Token = arguments.Gitlab.GitlabToken + } + + syncFilesWithGitlab() + } + } + +} + +func readTemplate(argPath string) string { + + current, err := os.Getwd() + if err != nil { + printErrorAndExit(2, "Unknown Error", err.Error()) + } + + p := argPath + + if !filepath.IsAbs(p) { + p = path.Clean(current + "/" + p) + } + + template, err := os.ReadFile(p) + if err != nil { + printErrorAndExit(exitCodeCatchAll, + "the specified template", argPath) + } + + return convertTemplateImages(string(template), path.Dir(p)) +} diff --git a/application/source/commandlineoptions.go b/application/source/commandlineoptions.go new file mode 100644 index 0000000..40b407e --- /dev/null +++ b/application/source/commandlineoptions.go @@ -0,0 +1,62 @@ +package main + +type commandLineOptions struct { + Config string `short:"c" long:"config" description:"file with configuration values"` + Path string `short:"p" long:"path" description:"define the path where the specifications are located" default:"."` + DateFormat string `long:"date-format" description:"date format" default:"2006-01-02"` + Requirements struct { + Print struct { + Columns []string `short:"c" long:"column" description:"defines the columns used"` + } `command:"print"` + Add struct { + ID string `long:"id" required:"true" description:"new requirement id"` + } `command:"add"` + Report struct { + GroupedBy string `long:"grouped-by" required:"false" description:"grouped by"` + Remote bool `long:"remote" description:"get data from remote"` + } `command:"report"` + } `command:"requirements"` + Tasks struct { + Print struct { + } `command:"print"` + //Sync struct { + // //ProjectID string `long:"project-id" required:"false" description:"gitlab project id"` + // //Token string `long:"token" required:"false" description:"gitlab token"` + //} `command:"sync"` + } `command:"tasks"` + Issues struct { + Print struct { + GitlabToken string `long:"gitlab-token" required:"false" description:"gitlab token"` + Remote bool `long:"remote" required:"false" description:"get data from remote"` + } `command:"print"` + } `command:"issues"` + Items struct { + Print struct { + } `command:"print"` + } `command:"items"` + Changelog struct { + Print struct { + } `command:"print"` + } `command:"changelog"` + Privacy struct { + Print struct { + } `command:"print"` + } `command:"privacy"` + Overview struct { + Print struct { + Columns []string `short:"c" long:"column" description:"defines the columns used"` + TemplatePath string `short:"t" long:"template" description:"file name of the template of the overview page"` + Output string `short:"o" long:"output" description:"redirect output to a file"` + Format string `short:"f" long:"format" description:"the desired output format" choice:"pdf" choice:"md"` + LatexTemplatePath string `short:"l" long:"latex-template-path" description:"latex template"` + } `command:"print"` + } `command:"overview"` + Version struct { + } `command:"version"` + Gitlab struct { + Sync struct { + } `command:"sync"` + // ProjectID string `long:"project-id" required:"false" description:"gitlab project id"` + GitlabToken string `long:"gitlab-token" required:"false" description:"gitlab token"` + } `command:"gitlab"` +} diff --git a/application/source/config.go b/application/source/config.go new file mode 100644 index 0000000..84ef8bc --- /dev/null +++ b/application/source/config.go @@ -0,0 +1,113 @@ +package main + +import ( + "os" + "os/user" + "path" + + "gopkg.in/yaml.v2" +) + +type configPathsStruct struct { + argument string + current string + user string + main string +} + +var ( + configPaths = configPathsStruct{ + main: "/etc/requirements-manager/config.yaml", + } +) + +// Configuration +type Configuration struct { + Path string `yaml:"Path"` + + Locale struct { + DateFormat string `yaml:"DateFormat"` + } `yaml:"Locale"` + + Gitlab struct { + Token string `yaml:"Token"` + } `yaml:"Gitlab"` + + Overview struct { + Template struct { + Markdown string `yaml:"Markdown"` + Latex string `yaml:"Latex"` + Internal struct { + MarkdownContent string + } + } `yaml:"Template"` + } `yaml:"Overview"` + + Requirement struct { + Table struct { + Columns []string `yaml:"Columns"` + } `yaml:"Table"` + Template struct { + Add string `yaml:"Add"` + } `yaml:"Template"` + } `yaml:"Requirement"` +} + +func fileExists(name string) (found bool) { + if f, err := os.Stat(name); err == nil { + return f.Mode().IsRegular() + } + return false +} + +// NewConfiguration +func NewConfiguration(argConfigPath string) *Configuration { + + current, err := os.Getwd() + if err != nil { + panic(err) + } + + filename := path.Clean(current + "/config.yaml") + + cfg := Configuration{} + + usr, err := user.Current() + if err == nil { + configPaths.user = usr.HomeDir + "/.config/requirements-manager/config.yaml" + } + + if argConfigPath != "" { + configPaths.argument = argConfigPath + } + + switch { + case fileExists(configPaths.argument): + readFile(&cfg, configPaths.argument) + case fileExists(filename): + readFile(&cfg, filename) + case fileExists(current): + readFile(&cfg, current) + case fileExists(configPaths.user): + readFile(&cfg, configPaths.user) + case fileExists(configPaths.main): + readFile(&cfg, configPaths.main) + } + + return &cfg +} + +func readFile(cfg *Configuration, filename string) { + f, err := os.Open(filename) + if err != nil { + printErrorAndExit(2, err.Error()) + } + + defer f.Close() + + decoder := yaml.NewDecoder(f) + err = decoder.Decode(cfg) + if err != nil { + printErrorAndExit(2, err.Error()) + } +} diff --git a/application/source/defaults.go b/application/source/defaults.go new file mode 100644 index 0000000..a54ff24 --- /dev/null +++ b/application/source/defaults.go @@ -0,0 +1,233 @@ +package main + +const exitOK = 0 + +// - Catchall for general errors +const exitCodeCatchAll = 1 + +// Invalid argument to exit +// const exitCodeInvalidArgument = 128 + +const defaultOverviewTemplate = ` + +--- +block-headings: true +--- + +{{ if .HasChangelog }} +## Changelog + +{{.Changelog}} + +{{ end}}{{ if .HasPrivacy }} +## Privacy + +{{.Privacy}} + +{{ end}}{{ if .HasMeta }} +## Overview + +{{.Meta}} + +{{ end}}{{ if .HasTasks }} +## Tasks + +{{.Tasks}} + +{{ end}}{{ if .HasItems }} +## Items + +{{.Items}} + +{{ end}}{{ if .HasRequirements }} +## Requirements + +{{.Requirements}} + +{{ end}} + + +` + +// +const defaultNewRequirementTemplate = ` +--- +ID: %%ID%% +Title: null + +# Reference to other requirements +References: null + +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null + +Alias: null + +Keywords: + - Requirement + +# First and last name of the authors as a list +Author: + - null + +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" + +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null + +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: + +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: + +# who is the source of the demand +Source: null +Created: %%CREATED%% +Last Update: null + +# The issues that are associated with this requirement +# You can add an issue by adding a new line to the list with the following format: +# - Gitlab: +# ID: <issue-id> +# +# if the issue is not yet in the project, you can add it by using the following format: +# Only the Title is required. +# - Gitlab: +# Title: <issue-title> +# Description: <issue-description> +# Priority: <issue-priority> +# Status: <issue-status> +# Assignee: <issue-assignee> +# Milestone: <issue-milestone> +# Labels: <issue-labels> +# +Issues: + + +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null + +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + + # More detailed description of the reason and process of data processing. + Description: null + + # Who is responsible for data protection + Contact: null + + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + + # + Category: + + # Example: 5 years from the payment of the salary + Data Retention Period: null + + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +{{ if .Purposes }}**{{ .Purposes }}** {{ end }}**({{ .ID }})** + +{{ if .Description }} {{ .Description }} +{{ end }} +| | | +|-----------------------|----------------------------| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + +` diff --git a/application/source/errors.go b/application/source/errors.go new file mode 100644 index 0000000..bef18c3 --- /dev/null +++ b/application/source/errors.go @@ -0,0 +1,9 @@ +package main + +import "errors" + +var ( + noGitRepositoryError = errors.New("no git repository found") + notFoundError = errors.New("not found") + notPermittedError = errors.New("not permitted") +) diff --git a/application/source/files.go b/application/source/files.go new file mode 100644 index 0000000..5e8d6dc --- /dev/null +++ b/application/source/files.go @@ -0,0 +1,101 @@ +package main + +import ( + "bytes" + "io/ioutil" + "os" + "path" + "path/filepath" + "strings" + + "gopkg.in/yaml.v3" +) + +// +func collectStructureFromFiles(directory string) (error, map[string]*requirement) { + + cleanedDirectory := path.Clean(directory) + + pageMap := make(map[string]*requirement) + + //pageMap := []requirement{} + + err := filepath.Walk(cleanedDirectory, + func(current string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + cleanedPath := path.Clean(current) + + if info.IsDir() { + return nil + } + + ext := filepath.Ext(cleanedPath) + if ext != ".md" { + return nil + } + + content, err := ioutil.ReadFile(cleanedPath) + + if err != nil { + return err + } + + err, p := splitYamlParts(content) + + if err != nil { + printWarning("the file contains structural errors. check the YAML and if necessary the template.", cleanedPath, err) + return nil + } + + bd := []byte(cleanedDirectory) + bp := []byte(cleanedPath) + bs := string(bp[len(bd):len(bp)]) + + p.data.File = "." + bs + p.data.Absolute = cleanedPath + p.data.ToDos = findTask(content) + + k := cleanedPath + + pageMap[k] = &p.data + + return nil + }) + + return err, pageMap +} + +func rewriteFiles(pageData map[string]*requirement) error { + + for filename, pd := range pageData { + + buf := new(bytes.Buffer) + + var encoder = yaml.NewEncoder(buf) + err := encoder.Encode(pd.OriginNode) + if err != nil { + return err + } + encoder.Close() + + text := "---\n" + buf.String() + "\n...\n" + text += strings.Trim(pd.OriginText, "\n") + + info, err := os.Stat(filename) + if err != nil { + return err + } + mode := info.Mode() + + err = os.WriteFile(filename, []byte(text), mode) + if err != nil { + return err + } + + } + + return nil +} diff --git a/application/source/gitlab.go b/application/source/gitlab.go new file mode 100644 index 0000000..7ca2a44 --- /dev/null +++ b/application/source/gitlab.go @@ -0,0 +1,377 @@ +package main + +import ( + "errors" + "net/url" + + "path" + + "gopkg.in/yaml.v3" + + "github.com/go-git/go-git/v5" + "github.com/xanzy/go-gitlab" +) + +type gitlabContext struct { + rootPath string + repos *git.Repository + apiUrl url.URL + + group string + name string + + token string + client *gitlab.Client + + project *gitlab.Project +} + +func getGitlabContext() *gitlabContext { + + context := &gitlabContext{} + workingPath, err := getGitDirectory() + if err != nil { + printErrorAndExit(2, "Failed to get git directory", err.Error()) + } + + context.rootPath = workingPath + + repos, err := git.PlainOpen(workingPath) + if err != nil { + printErrorAndExit(2, "Failed to open repository", err.Error()) + } + + context.repos = repos + if err != nil { + printErrorAndExit(2, "Failed to get remotes", err.Error()) + } + + remotes, err := repos.Remotes() + if err != nil { + printErrorAndExit(2, "Failed to get remotes", err.Error()) + } + + remote := remotes[0] + if remote == nil { + printErrorAndExit(2, "Failed to get remote") + } + + urls := remote.Config().URLs + if len(urls) == 0 { + printErrorAndExit(2, "Failed to get remote url") + } + + u, err := url.Parse(urls[0]) + if err != nil { + printErrorAndExit(2, "Failed to parse remote url", err.Error()) + } + + context.apiUrl = *u + context.apiUrl.Path = "" //path.Join("api", "v4") + + p := u.Path + if p == "" { + printErrorAndExit(2, "Failed to get remote path") + } + + s := p[1 : len(p)-4] + context.name = path.Base(s) + context.group = path.Dir(s) + + options := gitlab.WithBaseURL(context.apiUrl.String()) + + context.token = config.Gitlab.Token + c, err := gitlab.NewClient(config.Gitlab.Token, options) + if err != nil { + printErrorAndExit(2, "Failed to create client", err.Error()) + } + + context.client = c + + return context +} + +func searchProject(context *gitlabContext) { + // + options := gitlab.ListProjectsOptions{ + Search: gitlab.String(context.group + "/" + context.name), + SearchNamespaces: gitlab.Bool(true), + } + + projects, response, err := context.client.Projects.ListProjects(&options) + + if response.StatusCode == 404 { + printErrorAndExit(2, "Project not found %s", err.Error()) + } + + if err != nil { + printErrorAndExit(2, "Failed to get projects %s", err.Error()) + } + + if response.StatusCode != 200 { + printErrorAndExit(2, "Failed to get projects %s", err.Error()) + } + + if len(projects) == 0 { + printErrorAndExit(2, "Project not found") + } + + context.project = projects[0] + +} + +func enrichIssuesWithGitlab(pageMap map[string]*requirement) error { + + context := getGitlabContext() + searchProject(context) + + for _, requirement := range pageMap { + + for k, issue := range requirement.Issues { + + if issue.GitlabIntern == nil { + continue + } + + if issue.GitlabIntern.ID == 0 { + continue + } + + i, err := loadIssuesFromGitlab(context, issue.GitlabIntern.ID) + if err != nil { + return err + } + + requirement.Issues[k].GitlabRemote = i + } + } + + return nil +} + +func syncFilesWithGitlab() error { + + err, pageData := collectStructureFromFiles(config.Path) + if err != nil { + return err + } + + issuesList := []Issue{} + + for _, pageData := range pageData { + for _, info := range pageData.Issues { + issuesList = append(issuesList, info) + } + } + + context := getGitlabContext() + searchProject(context) + + syncIssuesWithGitlab(pageData) + return rewriteFiles(pageData) + +} + +func nodesEqual(l, r *yaml.Node) bool { + if l.Kind == yaml.ScalarNode && r.Kind == yaml.ScalarNode { + return l.Value == r.Value + } + panic("equals on non-scalars not implemented!") +} + +func recursiveRemove(nodes *yaml.Node) error { + + if nodes.Kind == yaml.DocumentNode { + recursiveRemove(nodes.Content[0]) + } + + if nodes.Kind != yaml.MappingNode { + return nil + } + + var found int + + for i := 0; i < len(nodes.Content); i += 2 { + + if nodes.Content[i].Value == "Issues" { + found = i + break + } + + if err := recursiveRemove(nodes.Content[i+1]); err != nil { + return errors.New("at key " + nodes.Content[i].Value + ": " + err.Error()) + } + + } + + if found > 0 { + + copy(nodes.Content[found:], nodes.Content[found+2:]) // Shift a[i+1:] left one index. + nodes.Content[len(nodes.Content)-1] = nil // Erase last element (write zero value). + nodes.Content[len(nodes.Content)-2] = nil // Erase last element (write zero value). + nodes.Content = nodes.Content[:len(nodes.Content)-2] + } + + return nil +} + +func recursiveMerge(from, into *yaml.Node) error { + if from.Kind != into.Kind { + return errors.New("cannot merge nodes of different kinds") + } + switch from.Kind { + case yaml.MappingNode: + for i := 0; i < len(from.Content); i += 2 { + found := false + for j := 0; j < len(into.Content); j += 2 { + if nodesEqual(from.Content[i], into.Content[j]) { + found = true + + if err := recursiveMerge(from.Content[i+1], into.Content[j+1]); err != nil { + return errors.New("at key " + from.Content[i].Value + ": " + err.Error()) + } + break + } + } + if !found { + into.Content = append(into.Content, from.Content[i:i+2]...) + } + } + case yaml.SequenceNode: + into.Content = append(into.Content, from.Content...) + case yaml.DocumentNode: + recursiveMerge(from.Content[0], into.Content[0]) + default: + return errors.New("can only merge mapping and sequence nodes") + } + return nil +} + +func syncIssuesWithGitlab(pageData map[string]*requirement) { + + err := enrichIssuesWithGitlab(pageData) + if err != nil { + printError(err.Error()) + printErrorAndExit(2, "Failed to enrich issues with gitlab") + } + + for _, pageData := range pageData { + for k, info := range pageData.Issues { + + if info.GitlabIntern.ID == 0 { + issue, err := createIssue(info) + if err != nil { + printErrorAndExit(2, "Failed to create issue %s", err.Error()) + } + + pageData.Issues[k].GitlabRemote = issue + pageData.Issues[k].GitlabIntern = new(GitlabInternalIssueStruct) + pageData.Issues[k].GitlabIntern.ID = issue.IID + pageData.Issues[k].GitlabIntern.URL = issue.WebURL + pageData.Issues[k].GitlabIntern.Title = issue.Title + pageData.Issues[k].GitlabIntern.Description = issue.Description + pageData.Issues[k].GitlabIntern.Labels = issue.Labels + pageData.Issues[k].GitlabIntern.Status = issue.State + + } else { + + pageData.Issues[k].GitlabIntern = new(GitlabInternalIssueStruct) + pageData.Issues[k].GitlabIntern.ID = info.GitlabRemote.IID + pageData.Issues[k].GitlabIntern.URL = info.GitlabRemote.WebURL + pageData.Issues[k].GitlabIntern.Title = info.GitlabRemote.Title + pageData.Issues[k].GitlabIntern.Description = info.GitlabRemote.Description + pageData.Issues[k].GitlabIntern.Labels = info.GitlabRemote.Labels + pageData.Issues[k].GitlabIntern.Status = info.GitlabRemote.State + } + + var change yaml.Node + bytes, err := yaml.Marshal(&pageData) + if err != nil { + printError("Failed to marshal page data %s", err.Error()) + continue + } + + yaml.Unmarshal(bytes, &change) + recursiveRemove(pageData.OriginNode) + recursiveMerge(&change, pageData.OriginNode) + + } + } +} + +func createIssue(issue Issue) (*gitlab.Issue, error) { + context := getGitlabContext() + searchProject(context) + + //title := *string(issue.GitlabIntern.Title) + labels := gitlab.Labels{} + for _, label := range issue.GitlabIntern.Labels { + labels = append(labels, label) + } + + createionOptions := gitlab.CreateIssueOptions{ + Title: gitlab.String(issue.GitlabIntern.Title), + Description: gitlab.String(issue.GitlabIntern.Description), + Labels: &labels, + } + + ptr := &createionOptions + + gitlabIssue, response, err := context.client.Issues.CreateIssue(context.project.ID, ptr) + + if response.StatusCode == 401 { + return gitlabIssue, err + } + + if response.StatusCode > 299 { + return gitlabIssue, err + } + + printInfo("Created issue %v (ID %v)", gitlabIssue.Title, gitlabIssue.IID) + printInfo("\t%s", gitlabIssue.WebURL) + + return gitlabIssue, nil +} + +// +// context := getGitlabContext(config) +// searchProject(context) +// +// options := &gitlab.CreateIssueOptions{ +// Title: gitlab.String(issue.Title), +// Status: gitlab.String(issue.Status), +// Labels: gitlab.StringSlice(issue.Labels), +// } +// +// i, _, err := context.client.Issues.CreateIssue(context.project.ID, options) +// if err != nil { +// return nil, err +// } +// +// return i, nil +// +//} +// +// +//func getProject(config *Configuration) *gitlab.Project { +// +// client := getGitlabClient(config) +// +// pattern := "test" +// +// options := gitlab.ListProjectsOptions{ +// Search: &pattern, +// } +// +// projects, _, err := client.Projects.ListProjects(&options) +// if err != nil { +// printErrorAndExit(2, "Failed to get projects", err.Error()) +// } +// +// //project, _, err := client.Projects.GetProject(config.GitlabProjectID, nil) +// //if err != nil { +// // printErrorAndExit(2, "Failed to get project", err.Error()) +// //} +// +// return projects[0] +//} diff --git a/application/source/go.mod b/application/source/go.mod new file mode 100644 index 0000000..ddd4660 --- /dev/null +++ b/application/source/go.mod @@ -0,0 +1,49 @@ +module gitlab.schukai.com/oss/utilities/requirements-manager + +go 1.18 + +require ( + github.com/go-git/go-git/v5 v5.4.2 + github.com/gookit/color v1.5.1 + github.com/jessevdk/go-flags v1.5.0 + github.com/olekukonko/tablewriter v0.0.5 + github.com/xanzy/go-gitlab v0.68.0 + golang.org/x/text v0.3.7 + gopkg.in/yaml.v2 v2.4.0 + gopkg.in/yaml.v3 v3.0.1 +) + +require ( + github.com/Microsoft/go-winio v0.5.2 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20220517143526-88bb52951d5b // indirect + github.com/acomagu/bufpipe v1.0.3 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/emirpasic/gods v1.18.1 // indirect + github.com/go-git/gcfg v1.5.0 // indirect + github.com/go-git/go-billy/v5 v5.3.1 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/google/go-querystring v1.1.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-retryablehttp v0.7.1 // indirect + github.com/imdario/mergo v0.3.13 // indirect + github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect + github.com/kevinburke/ssh_config v1.2.0 // indirect + github.com/kr/pretty v0.2.1 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/sergi/go-diff v1.2.0 // indirect + github.com/src-d/gcfg v1.4.0 // indirect + github.com/xanzy/ssh-agent v0.3.1 // indirect + github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect + golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect + golang.org/x/net v0.0.0-20220621193019-9d032be2e588 // indirect + golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb // indirect + golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c // indirect + golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/protobuf v1.28.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + gopkg.in/src-d/go-billy.v4 v4.3.2 // indirect + gopkg.in/warnings.v0 v0.1.2 // indirect +) diff --git a/application/source/go.sum b/application/source/go.sum new file mode 100644 index 0000000..ab243f5 --- /dev/null +++ b/application/source/go.sum @@ -0,0 +1,546 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= +github.com/ProtonMail/go-crypto v0.0.0-20220517143526-88bb52951d5b h1:lcbBNuQhppsc7A5gjdHmdlqUqJfgGMylBdGyDs0j7G8= +github.com/ProtonMail/go-crypto v0.0.0-20220517143526-88bb52951d5b/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= +github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= +github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= +github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= +github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= +github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= +github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34= +github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-git v4.7.0+incompatible h1:+W9rgGY4DOKKdX2x6HxSR7HNeTxqiKrOvKnuittYVdA= +github.com/go-git/go-git v4.7.0+incompatible/go.mod h1:6+421e08gnZWn30y26Vchf7efgYLe4dl5OQbBSUXShE= +github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0= +github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4= +github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gookit/color v1.5.0 h1:1Opow3+BWDwqor78DcJkJCIwnkviFi+rrOANki9BUFw= +github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= +github.com/gookit/color v1.5.1 h1:Vjg2VEcdHpwq+oY63s/ksHrgJYCTo0bwWvmmYWdE9fQ= +github.com/gookit/color v1.5.1/go.mod h1:wZFzea4X8qN6vHOSP2apMb4/+w/orMznEzYsIHPaqKM= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-retryablehttp v0.7.1 h1:sUiuQAnLlbvmExtFQs72iFW/HXeUn8Z1aJLQ4LJJbTQ= +github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= +github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY= +github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4= +github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/xanzy/go-gitlab v0.68.0 h1:b2iMQHgZ1V+NyRqLRJVv6RFfr4xnd/AASeS/PETYL0Y= +github.com/xanzy/go-gitlab v0.68.0/go.mod h1:o4yExCtdaqlM8YGdDJWuZoBmfxBsmA9TPEjs9mx1UO4= +github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= +github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= +github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= +github.com/xanzy/ssh-agent v0.3.1 h1:AmzO1SSWxw73zxFZPRwaMN1MohDw8UyHnmuxyceTEGo= +github.com/xanzy/ssh-agent v0.3.1/go.mod h1:QIE4lCeL7nkC25x+yA3LBIYfwCc1TFziCtG7cBAac6w= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= +golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 h1:NWy5+hlRbC7HK+PmcXVUmW1IMyFce7to56IUvhUFm7Y= +golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220615171555-694bf12d69de h1:ogOG2+P6LjO2j55AkRScrkB2BFpd+Z8TY2wcM0Z3MGo= +golang.org/x/net v0.0.0-20220615171555-694bf12d69de/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220621193019-9d032be2e588 h1:9ubFuySsnAJYGyJrZ3koiEv8FyqofCBdz3G9Mbf2YFc= +golang.org/x/net v0.0.0-20220621193019-9d032be2e588/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 h1:OSnWWcOd/CtWQC2cYSBgbTSJv3ciqd8r54ySIW2y3RE= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb h1:8tDJ3aechhddbdPAxpycgXHJRMLpk/Ab+aa4OgdN5/g= +golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886 h1:eJv7u3ksNXoLbGSKuv2s/SIO4tJVxc/A+MTpzxDgz/Q= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c h1:aFV+BgZ4svzjfabn8ERpuB4JI4N6/rdy1iusx77G3oU= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220411224347-583f2d630306 h1:+gHMid33q6pen7kv9xvT+JRinntgeXO2AeZVd0AWD3w= +golang.org/x/time v0.0.0-20220411224347-583f2d630306/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U= +golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg= +gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= +gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= +gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE= +gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8= +gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20220512140231-539c8e751b99 h1:dbuHpmKjkDzSOMKAWl10QNlgaZUd3V1q99xc81tt2Kc= +gopkg.in/yaml.v3 v3.0.0-20220512140231-539c8e751b99/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/application/source/issues.go b/application/source/issues.go new file mode 100644 index 0000000..372baa6 --- /dev/null +++ b/application/source/issues.go @@ -0,0 +1,157 @@ +package main + +import ( + "bytes" + "fmt" + "strings" + "time" + + "github.com/olekukonko/tablewriter" + "github.com/xanzy/go-gitlab" +) + +type GitlabInternalIssueStruct struct { + ID int `yaml:"ID"` + Title string `yaml:"Title,omitempty"` + Description string `yaml:"Description,omitempty"` + Status string `yaml:"Status,omitempty"` + Labels []string `yaml:"Labels,omitempty"` + URL string `yaml:"URL,omitempty"` +} + +//Priority string `yaml:"Priority,omitempty"` +//Assignee string `yaml:"Assignee,omitempty"` +//Milestone string `yaml:"Milestone,omitempty"` + +type Issue struct { + GitlabIntern *GitlabInternalIssueStruct `yaml:"Gitlab"` + GitlabRemote *gitlab.Issue `yaml:"-"` +} + +func loadIssuesFromGitlab(context *gitlabContext, issueID int) (*gitlab.Issue, error) { + + client := context.client + + issue, _, err := client.Issues.GetIssue(context.project.ID, issueID) // .ListProjectIssues(context.project.ID, &gitlab.ListProjectIssuesOptions{}) + if err != nil { + return nil, err + } + + return issue, nil + + //err, pageData := collectStructureFromFiles(config.Path) +} + +func buildIssueOverviewTable(pageMap map[string]*requirement, extended bool) (error, string, bool) { + + buf := new(bytes.Buffer) + has := false + + table := tablewriter.NewWriter(buf) + + header := []string{ + printer.Sprintf("ID"), + printer.Sprintf("Title"), + printer.Sprintf("State")} + + if extended == true { + + header = append(header, printer.Sprintf("Assignees")) + header = append(header, printer.Sprintf("Due date")) + header = append(header, printer.Sprintf("Labels")) + header = append(header, printer.Sprintf("Estimate")) + header = append(header, printer.Sprintf("Spent")) + } + + table.SetHeader(header) + + table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) + table.SetCenterSeparator("|") + + var tableData [][]string + + for _, requirement := range pageMap { + for _, issue := range requirement.Issues { + + gitlabIntern := issue.GitlabIntern + + if gitlabIntern == nil { + continue + } + + var col []string + dueDate := "—" + + id := "—" + labels := "—" + estimate := "—" + spent := "—" + state := "—" + title := "—" + assignees := "—" + + id = printer.Sprintf("%d", gitlabIntern.ID) + if gitlabIntern.Labels != nil { + labels = strings.Join(gitlabIntern.Labels, ", ") + } + if gitlabIntern.Title != "" { + title = gitlabIntern.Title + } + + gitlabRemote := issue.GitlabRemote + if gitlabRemote != nil { + if gitlabRemote.DueDate != nil { + d := (time.Time)(*gitlabRemote.DueDate) + dueDate = d.Format(config.Locale.DateFormat) + } + + labels = printer.Sprintf("%s", strings.Join(gitlabRemote.Labels, ", ")) + estimate = printer.Sprintf("%s", gitlabRemote.TimeStats.HumanTimeEstimate) + spent = printer.Sprintf("%s", gitlabRemote.TimeStats.HumanTotalTimeSpent) + state = printer.Sprintf(gitlabRemote.State) + title = printer.Sprintf("%s", gitlabRemote.Title) + + a := []string{} + for _, assignee := range gitlabRemote.Assignees { + a = append(a, assignee.Name) + } + + assignees = printer.Sprintf("%s", strings.Join(a, ", ")) + + } + + if extended { + col = []string{id, title, state, assignees, dueDate, labels, estimate, spent} + } else { + col = []string{id, title, state, labels} + } + + tableData = append(tableData, col) + has = true + + } + + } + + table.AppendBulk(tableData) // Add Bulk Data + table.SetHeaderAlignment(tablewriter.ALIGN_LEFT) + table.Render() + + return nil, buf.String(), has +} + +func printIssueTable() error { + err, pageMap := collectStructureFromFiles(config.Path) + + if arguments.Issues.Print.Remote { + enrichIssuesWithGitlab(pageMap) + if err != nil { + return err + } + } + + err, table, _ := buildIssueOverviewTable(pageMap, true) + fmt.Println(table) + + return nil +} diff --git a/application/source/items.go b/application/source/items.go new file mode 100644 index 0000000..2515db4 --- /dev/null +++ b/application/source/items.go @@ -0,0 +1,127 @@ +package main + +import ( + "bytes" + "fmt" + "time" + + "github.com/olekukonko/tablewriter" +) + +type Item struct { + ID string `yaml:"ID"` + Name string `yaml:"Name"` + Type string `yaml:"Type"` + Group string `yaml:"group"` + Description string `yaml:"Description"` + DeliveryUntil time.Time `yaml:"Delivery until"` + ProvidedOn time.Time `yaml:"Provided on"` + ProvidedBy string `yaml:"Provided by"` +} + +func buildItemOverviewTable(pageMap map[string]*requirement, extended bool) (error, string, bool) { + + buf := new(bytes.Buffer) + has := false + + table := tablewriter.NewWriter(buf) + + var header []string + + if extended { + header = []string{ + printer.Sprintf("ID"), + printer.Sprintf("group"), + printer.Sprintf("Name"), + printer.Sprintf("Type"), + printer.Sprintf("Description"), + printer.Sprintf("Delivery until"), + printer.Sprintf("Checked"), + printer.Sprintf("Provided on"), + printer.Sprintf("Provided by"), + printer.Sprintf("File"), + } + } else { + header = []string{ + printer.Sprintf("ID"), + printer.Sprintf("Name"), + printer.Sprintf("Delivery until"), + printer.Sprintf("Checked"), + } + + } + + table.SetHeader(header) + + table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) + table.SetCenterSeparator("|") + + var tableData [][]string + + for _, pageData := range pageMap { + for _, info := range pageData.Items { + + var deliveryUntilFormatted, providedOnDate, checked string + + if info.DeliveryUntil.IsZero() { + deliveryUntilFormatted = "—" + } else { + deliveryUntilFormatted = info.DeliveryUntil.Format(config.Locale.DateFormat) + } + + if info.ProvidedOn.IsZero() { + providedOnDate = "—" + } else { + providedOnDate = info.ProvidedOn.Format(config.Locale.DateFormat) + } + + if info.DeliveryUntil.IsZero() { + deliveryUntilFormatted = "—" + } else { + deliveryUntilFormatted = info.DeliveryUntil.Format(config.Locale.DateFormat) + } + + if info.ProvidedOn.IsZero() { + checked = "—" + } else { + checked = "✓" + } + + id := "—" + if info.ID != "" { + id = info.ID + } + + var col []string + + if extended { + col = []string{id, info.Group, info.Name, info.Type, info.Description, deliveryUntilFormatted, checked, providedOnDate, info.ProvidedBy, pageData.File} + } else { + col = []string{id, info.Name, deliveryUntilFormatted, deliveryUntilFormatted, checked} + } + + tableData = append(tableData, col) + has = true + + } + + } + + table.AppendBulk(tableData) // Add Bulk Data + table.SetHeaderAlignment(tablewriter.ALIGN_LEFT) + table.Render() + + return nil, buf.String(), has +} + +func printItemTable() error { + err, pageMap := collectStructureFromFiles(config.Path) + if err != nil { + return err + } + + err, table, _ := buildItemOverviewTable(pageMap, true) + fmt.Println(table) + + return nil +} diff --git a/application/source/l10n.go b/application/source/l10n.go new file mode 100644 index 0000000..b7ad9c2 --- /dev/null +++ b/application/source/l10n.go @@ -0,0 +1,447 @@ +package main + +import ( + "golang.org/x/text/language" + "golang.org/x/text/message" + "golang.org/x/text/message/catalog" +) + +type l10nLocaleTranslation struct { + tag string + msg interface{} +} +type l10nKeyTranslation struct { + key string + tm []l10nLocaleTranslation +} + +var l10nMap = []l10nKeyTranslation{ + { + "does not contain a valid yaml definition", + []l10nLocaleTranslation{ + {"de", "\"%s\" enthält keine gültige yaml Struktur."}, + {"en", "\"%s\" does not contain a valid yaml definition."}, + }, + }, + { + "the specified template", + []l10nLocaleTranslation{ + {"de", "Das angegebene AddTemplate \"%s\" wurde nicht gefunden."}, + {"en", "the specified template \"%s\" was not found."}, + }, + }, + { + "the due of the todo cannot be parsed", + []l10nLocaleTranslation{ + {"de", "Das Datum %s der Aufgabe \"%s\" kann nicht verarbeitet werden."}, + {"en", "the due %s of the todo \"%s\" cannot be parsed."}, + }, + }, + { + "ToDo", + []l10nLocaleTranslation{ + {"de", "Aufgabe"}, + {"en", "task"}, + }, + }, + { + "Due", + []l10nLocaleTranslation{ + {"de", "Bis"}, + {"en", "due"}, + }, + }, { + "File", + []l10nLocaleTranslation{ + {"de", "Datei"}, + {"en", "file"}, + }, + }, { + "group", + []l10nLocaleTranslation{ + {"de", "Gruppe"}, + {"en", "group"}, + }, + }, + { + "Description", + []l10nLocaleTranslation{ + {"de", "Beschreibung"}, + {"en", "Description"}, + }, + }, + { + "Delivery until", + []l10nLocaleTranslation{ + {"de", "Bis"}, + {"en", "until"}, + }, + }, + { + "Provided on", + []l10nLocaleTranslation{ + {"de", "Am"}, + {"en", "on"}, + }, + }, + { + "Provided by", + []l10nLocaleTranslation{ + {"de", "Von"}, + {"en", "by"}, + }, + }, + { + "Type", + []l10nLocaleTranslation{ + {"de", "Typ"}, + {"en", "Type"}, + }, + }, + { + "Title", + []l10nLocaleTranslation{ + {"de", "Titel"}, + {"en", "Title"}, + }, + }, + { + "Alias", + []l10nLocaleTranslation{ + {"de", "Alias"}, + {"en", "Alias"}, + }, + }, + { + "Type", + []l10nLocaleTranslation{ + {"de", "Typ"}, + {"en", "Type"}, + }, + }, + { + "Keywords", + []l10nLocaleTranslation{ + {"de", "Schlüsselwörter"}, + {"en", "Keywords"}, + }, + }, { + "Estimation", + []l10nLocaleTranslation{ + {"de", "Schätzung"}, + {"en", "Estimation"}, + }, + }, { + "Source", + []l10nLocaleTranslation{ + {"de", "Quelle"}, + {"en", "Source"}, + }, + }, + { + "Author", + []l10nLocaleTranslation{ + {"de", "Autor"}, + {"en", "Author"}, + }, + }, + { + "Status", + []l10nLocaleTranslation{ + {"de", "Status"}, + {"en", "Status"}, + }, + }, + { + "Complexity", + []l10nLocaleTranslation{ + {"de", "Komplexität"}, + {"en", "Complexity"}, + }, + }, + { + "Difficulty", + []l10nLocaleTranslation{ + {"de", "Schwierigkeit"}, + {"en", "Difficulty"}, + }, + }, + { + "Priority", + []l10nLocaleTranslation{ + {"de", "Priorität"}, + {"en", "Priority"}, + }, + }, + { + "Version", + []l10nLocaleTranslation{ + {"de", "Version"}, + {"en", "Version"}, + }, + }, + { + "Milestone", + []l10nLocaleTranslation{ + {"de", "Meilenstein"}, + {"en", "Milestone"}, + }, + }, + { + "Created", + []l10nLocaleTranslation{ + {"de", "Erstellt am"}, + {"en", "Created"}, + }, + }, + { + "LastUpdate", + []l10nLocaleTranslation{ + {"de", "Letzte Änderung"}, + {"en", "LastUpdate"}, + }, + }, + { + "The file cannot be read", + []l10nLocaleTranslation{ + {"de", "Die Datei \"%s\" kann nicht eingelesen werden."}, + {"en", "The file \"%s\" cannot be read."}, + }, + }, + { + "The output file cannot be written", + []l10nLocaleTranslation{ + {"de", "Die Ausgabedatei kann nicht geschrieben werden (%s)."}, + {"en", "The output file cannot be written (%s)."}, + }, + }, { + "A temporary file cannot be created", + []l10nLocaleTranslation{ + {"de", "Es kann keine temporäre Datei angelegt werden (%s)."}, + {"en", "A temporary file cannot be created (%s)."}, + }, + }, { + "Checked", + []l10nLocaleTranslation{ + {"de", "Erledigt"}, + {"en", "done"}, + }, + }, + { + "Name", + []l10nLocaleTranslation{ + {"de", "Name"}, + {"en", "Name"}, + }, + }, + { + "Type", + []l10nLocaleTranslation{ + {"de", "Typ"}, + {"en", "Type"}, + }, + }, { + "RequirementID", + []l10nLocaleTranslation{ + {"de", "Requirements"}, + {"en", "Anforderungen"}, + }, + }, { + "the id must not be empty", + []l10nLocaleTranslation{ + {"de", "Die ID muss angegeben werden"}, + {"en", "the id must not be empty"}, + }, + }, + { + "the request with id already exists", + []l10nLocaleTranslation{ + {"de", "Die Anforderung mit der ID %s existiert bereits (%s)."}, + {"en", "the request with id %s already exists (%s)."}, + }, + }, + { + "YAML parse error", + []l10nLocaleTranslation{ + {"de", "YAML Fehler: %s "}, + {"en", "YAML parse error: %s ."}, + }, + }, + { + "if the type is pdf, the output option must be specified", + []l10nLocaleTranslation{ + {"de", "Der Tpy PDF benötigt die Option --output"}, + {"en", "if the type is pdf, the output option must be specified"}, + }, + }, + { + "Unknown Error", + []l10nLocaleTranslation{ + {"de", "Unbekannter Fehler: %s"}, + {"en", "Unknown Error %s"}, + }, + }, + { + "the file contains structural errors. check the YAML and if necessary the template.", + []l10nLocaleTranslation{ + {"de", "Die Datei %s enthält strukturelle Fehler (%s). Überprüfen Sie die Datei."}, + {"en", "the file %s contains structural errors (%s). Check the if necessary the file."}, + }, + }, + { + "the file is empty", + []l10nLocaleTranslation{ + {"de", "Die Datei enthält keinen Inhalt."}, + {"en", "the file is empty."}, + }, + }, + { + "the grouping key was not found", + []l10nLocaleTranslation{ + {"de", "Der Schlüssel %s existiert nicht"}, + {"en", "the grouping key %s was not found"}, + }, + }, + + { + "Ratio", + []l10nLocaleTranslation{ + {"de", "Verhältnis"}, + {"en", "Ratio"}, + }, + }, + { + "Standard Deviation", + []l10nLocaleTranslation{ + {"de", "Standardabweichung"}, + {"en", "Standard Deviation"}, + }, + }, + { + "Variance", + []l10nLocaleTranslation{ + {"de", "Varianz"}, + {"en", "Variance"}, + }, + }, + { + "Average", + []l10nLocaleTranslation{ + {"de", "Mittelwert"}, + {"en", "Average"}, + }, + }, + { + "Time Spent", + []l10nLocaleTranslation{ + {"de", "Aufwand"}, + {"en", "Time Spent"}, + }, + }, + { + "Estimated", + []l10nLocaleTranslation{ + {"de", "Planwert"}, + {"en", "Estimated"}, + }, + }, + { + "unsuported type", + []l10nLocaleTranslation{ + {"de", "nicht unterstützter Typ %s"}, + {"en", "unsuported type %s"}, + }, + }, + { + "no value", + []l10nLocaleTranslation{ + {"de", "kein Wert"}, + {"en", "no value"}, + }, + }, + { + "opened", + []l10nLocaleTranslation{ + {"de", "offen"}, + {"en", "opened"}, + }, + }, + + { + "closed", + []l10nLocaleTranslation{ + {"de", "geschlossen"}, + {"en", "closed"}, + }, + }, + + { + "State", + []l10nLocaleTranslation{ + {"de", "Status"}, + {"en", "State"}, + }, + }, + { + "Due date", + []l10nLocaleTranslation{ + {"de", "Fälligkeitsdatum"}, + {"en", "Due Date"}, + }, + }, + + { + "Labels", + []l10nLocaleTranslation{ + {"de", "Labels"}, + {"en", "Labels"}, + }, + }, + + { + "Estimate", + []l10nLocaleTranslation{ + {"de", "Planwert"}, + {"en", "Estimate"}, + }, + }, + + { + "Spent", + []l10nLocaleTranslation{ + {"de", "Aufwand"}, + {"en", "Spent"}, + }, + }, + + { + "Assignees", + []l10nLocaleTranslation{ + {"de", "Zuweisungen"}, + {"en", "Assignees"}, + }, + }, { + "Statistics", + []l10nLocaleTranslation{ + {"de", "Statistiken"}, + {"en", "Statistics"}, + }, + }, +} + +func initL10n() { + for _, e := range l10nMap { + key := e.key + for _, f := range e.tm { + tag := language.MustParse(f.tag) + switch msg := f.msg.(type) { + case string: + message.SetString(tag, key, msg) + case catalog.Message: + message.Set(tag, key, msg) + case []catalog.Message: + message.Set(tag, key, msg...) + } + } + } +} diff --git a/application/source/main.go b/application/source/main.go new file mode 100644 index 0000000..ff52d3b --- /dev/null +++ b/application/source/main.go @@ -0,0 +1,50 @@ +package main + +import ( + "os" + + "golang.org/x/text/language" + "golang.org/x/text/message" +) + +// Wird beim Bauen per +// -ldflags "-X main.version=$app_version -X main.build=$(due --iso-8601 | tr -d "-" )" +// gesetzt +var ( + version string + build string + printer *message.Printer + //sugar *zap.SugaredLogger +) + +var serverLangs = []language.Tag{ + language.English, // en fallback + language.German, // de +} + +var matcher = language.NewMatcher(serverLangs) + +var userPrefs = []language.Tag{ + language.Make(os.Getenv("LANG")), + language.Make("en"), +} + +func init() { + + initEnvironment() + + tag, _, _ := matcher.Match(userPrefs...) + printer = message.NewPrinter(tag) + + initL10n() + +} + +func initEnvironment() { +} + +/** + */ +func main() { + executeCommand() +} diff --git a/application/source/message.go b/application/source/message.go new file mode 100644 index 0000000..60f014a --- /dev/null +++ b/application/source/message.go @@ -0,0 +1,57 @@ +package main + +import ( + "os" + + "github.com/gookit/color" +) + +var lastBlock string + +// print error +func printErrorAndExit(code int, message string, a ...interface{}) { + printError(message, a...) + if code == 0 { + code = exitCodeCatchAll + } + os.Exit(code) +} + +func printError(message string, a ...interface{}) { + + message = printer.Sprintf(message, a...) + + if lastBlock == "error" { + color.Error.Println(" " + message) + return + } + lastBlock = "error" + + color.Error.Block(message) +} + +func printWarning(message string, a ...interface{}) { + + message = printer.Sprintf(message, a...) + + if lastBlock == "warning" { + color.Warn.Println(" " + message) + return + } + lastBlock = "warning" + + color.Warn.Block(message) +} + +func printInfo(message string, a ...interface{}) { + + message = printer.Sprintf(message, a...) + + if lastBlock == "info" { + color.Info.Println(" " + message) + return + } + lastBlock = "info" + + color.Info.Block(message) +} diff --git a/application/source/overview.go b/application/source/overview.go new file mode 100644 index 0000000..137a642 --- /dev/null +++ b/application/source/overview.go @@ -0,0 +1,300 @@ +package main + +import ( + "io/ioutil" + "os" + "path" + "path/filepath" + "regexp" + "sort" + "strings" + "text/template" + "time" +) + +type Dataset struct { + Config *Configuration + Meta string + HasChangelog bool + Changelog string + HasPrivacy bool + Privacy string + HasMeta bool + Tasks string + HasTasks bool + Items string + HasItems bool + Requirements string + HasRequirements bool + Created time.Time + CreatedFormat string +} + +func PrintOverview() error { + + err, pageData := collectStructureFromFiles(config.Path) + if err != nil { + return err + } + + err, meta, hasMeta := buildRequirements(pageData) + if err != nil { + return err + } + + err, changelog, hasChangelog := buildChangelog(pageData) + if err != nil { + return err + } + + err, privacy, hasPrivacy := buildPrivacy(pageData) + if err != nil { + return err + } + + err, tasks, hasTasks := buildTasksTable(pageData, false) + if err != nil { + return err + } + + err, items, hasItems := buildItemOverviewTable(pageData, false) + if err != nil { + return err + } + + t, err := template.New("overview").Parse(config.Overview.Template.Internal.MarkdownContent) + if err != nil { + return err + } + + requirements := "" + + keys := make([]string, 0, len(pageData)) + for k := range pageData { + keys = append(keys, k) + } + + sort.Strings(keys) + + hasRequirements := false + for _, k := range keys { + hasRequirements = true + p := pageData[k] + requirements = requirements + getAdjustedContent(p.Absolute) + } + + d := new(Dataset) + + d.Changelog = changelog + d.HasChangelog = hasChangelog + + d.Privacy = privacy + d.HasPrivacy = hasPrivacy + + d.Meta = meta + d.HasMeta = hasMeta + + d.Tasks = tasks + d.HasTasks = hasTasks + + d.Items = items + d.HasItems = hasItems + + d.Requirements = requirements + d.HasRequirements = hasRequirements + + d.Config = config + d.Created = time.Now() + d.CreatedFormat = time.Now().Format(config.Locale.DateFormat) + //d.requirement = requirement + + outputName := arguments.Overview.Print.Output + + if arguments.Overview.Print.Format == "pdf" { + + if outputName == "" { + printErrorAndExit(2, "if the type is pdf, the output option must be specified") + } + + file, err := ioutil.TempFile(os.TempDir(), "reqman") + if err != nil { + printErrorAndExit(2, "A temporary file cannot be created", err.Error()) + } + defer os.Remove(file.Name()) + + err = t.Execute(file, d) + if err != nil { + return err + } + + convertToPDF(file.Name(), outputName, config.Overview.Template.Latex) + + } else { + + if outputName != "" { + file, err := os.Create(outputName) + if err != nil { + printErrorAndExit(2, "The output file cannot be written", err.Error()) + } + + // close fo on exit and check for its returned error + defer func() { + if err := file.Close(); err != nil { + printErrorAndExit(2, "The output file cannot be written", err.Error()) + } + }() + + err = t.Execute(file, d) + if err != nil { + return err + } + + } else { + + err = t.Execute(os.Stdout, d) + if err != nil { + return err + } + } + + } + + return nil + +} + +func getAdjustedContent(absolute string) string { + + content, err := os.ReadFile(absolute) + if err != nil { + printError("The file cannot be read", absolute) + return "" + } + + err, def := splitYamlParts(content) + if err != nil { + printError(err.Error()) + return "" + } + + s := convertImages(def.content, path.Dir(absolute)) + + return s +} + +func convertImages(content string, absolute string) string { + + todoRegEx := regexp.MustCompile(`(?P<match>\!\[(?P<label>[^]]*)\]\((?P<path>[^)]*)\))`) + + matches := todoRegEx.FindAllStringSubmatch(content, -1) + if matches == nil { + return content + } + + for _, match := range matches { + result := make(map[string]string) + for i, name := range todoRegEx.SubexpNames() { + if i != 0 && name != "" { + result[name] = match[i] + } + } + + if filepath.IsAbs(result["path"]) { + continue + } + + path := path.Clean(absolute + "/" + result["path"]) + content = strings.Replace(content, result["match"], "!["+result["label"]+"]("+path+")", -1) + + } + + return content +} + +func convertTemplateLogo(content string, absolute string) string { + todoRegEx := regexp.MustCompile(`(?m)^(?P<match>logo:\s*"?(?P<path>[^"\n]*)"?\s*)$`) + + matches := todoRegEx.FindAllStringSubmatch(content, -1) + if matches == nil { + return content + } + + for _, match := range matches { + result := make(map[string]string) + for i, name := range todoRegEx.SubexpNames() { + if i != 0 && name != "" { + result[name] = match[i] + } + } + + if filepath.IsAbs(result["path"]) { + continue + } + + path := path.Clean(absolute + "/" + result["path"]) + content = strings.Replace(content, result["match"], "logo: \""+path+"\"", -1) + + } + + return content +} + +func convertTemplateLatexLogo(content string, absolute string) string { + todoRegEx := regexp.MustCompile(`(?m)(?P<match>\\includegraphics[^{]*\{(?P<path>[^}]*)\})`) + + matches := todoRegEx.FindAllStringSubmatch(content, -1) + if matches == nil { + return content + } + + for _, match := range matches { + result := make(map[string]string) + for i, name := range todoRegEx.SubexpNames() { + if i != 0 && name != "" { + result[name] = match[i] + } + } + + if filepath.IsAbs(result["path"]) { + continue + } + + path := path.Clean(absolute + "/" + result["path"]) + a := strings.Replace(result["match"], result["path"], path, -1) + + content = strings.Replace(content, result["match"], a, -1) + + } + + return content +} + +func convertTemplateImages(content string, absolute string) string { + content = convertTemplateLogo(content, absolute) + content = convertTemplateLatexLogo(content, absolute) + + return content + +} + +func validateColumns(columns []string) []string { + + //for i, column := range columns { + // columns[i] = printer.Sprintf(column) + //} + + // VALIDATE COLUMS NAME + + // + //for _, name := range config.Requirements.Columns { + // + // field := reflect.Indirect(r).FieldByName(name) + // if field == (reflect.Value{}) { + // printError("the specified column " + name + " for the table does not exist") + // continue + + // } + + return columns + +} diff --git a/application/source/pandoc.go b/application/source/pandoc.go new file mode 100644 index 0000000..95ebac5 --- /dev/null +++ b/application/source/pandoc.go @@ -0,0 +1,46 @@ +package main + +import ( + "fmt" + "os/exec" +) + +func convertToPDF(source string, outputName string, latexPath string) string { + + arguments := "/bin/env pandoc " + + arguments += "--number-sections " + arguments += "--variable \"geometry:a4paper,margin=2cm\" " + arguments += "--variable fontsize=12pt " + arguments += "--variable version=2.0 " + arguments += source + " " + arguments += "--pdf-engine=xelatex " + arguments += "--listings " + + if latexPath != "" { + arguments += "--template=" + latexPath + " " + } + + arguments += "--columns=5 " + arguments += "--highlight-style espresso " + arguments += "--toc " + arguments += "--output=" + outputName + " " + + cmd, err := exec.Command("bash", "-c", arguments).Output() + if err != nil { + + exitErr, ok := err.(*exec.ExitError) + if ok { + printErrorAndExit(2, string(exitErr.Stderr)) + + } else { + printErrorAndExit(2, err.Error()) + } + + } + + fmt.Println(string(cmd)) + + return string(cmd) + +} diff --git a/application/source/privacy.go b/application/source/privacy.go new file mode 100644 index 0000000..2063525 --- /dev/null +++ b/application/source/privacy.go @@ -0,0 +1,95 @@ +package main + +import ( + "fmt" + "strings" +) + +type Privacy struct { + ID string `yaml:"ID"` + Purposes string `yaml:"Purposes"` + Description string `yaml:"Description"` + Contact string `yaml:"Contact"` + AffectedGroups string `yaml:"Affected Groups"` // Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Category string `yaml:"Category"` + DataRetentionPeriod string `yaml:"Data Retention Period"` + LegalBasis string `yaml:"Legal Basis"` + Consent string `yaml:"Consent"` + Transfers string `yaml:"Transfers"` + TOM string `yaml:"TOM"` +} + +func buildPrivacy(pageMap map[string]*requirement) (error, string, bool) { + + hasPrivacy := false + text := "" + + for _, pageData := range pageMap { + for _, data := range pageData.Privacy { + + text += strings.Trim(data.Purposes+" ("+data.ID+")", " ") + "\n\n" + + d := strings.Trim(data.Description, " \n") + if d != "" { + text += d + "\n\n" + } + + d = strings.Trim(data.Contact, " \n") + if d != "" { + text += d + "\n\n" + } + + d = strings.Trim(data.AffectedGroups, " \n") + if d != "" { + text += d + "\n\n" + } + + d = strings.Trim(data.Category, " \n") + if d != "" { + text += d + "\n\n" + } + + d = strings.Trim(data.DataRetentionPeriod, " \n") + if d != "" { + text += d + "\n\n" + } + + d = strings.Trim(data.LegalBasis, " \n") + if d != "" { + text += d + "\n\n" + } + + d = strings.Trim(data.Consent, " \n") + if d != "" { + text += d + "\n\n" + } + + d = strings.Trim(data.Transfers, " \n") + if d != "" { + text += d + "\n\n" + } + + d = strings.Trim(data.TOM, " \n") + if d != "" { + text += d + "\n\n" + } + + hasPrivacy = true + } + } + + return nil, text, hasPrivacy + +} + +func printPrivacy() error { + + err, pageData := collectStructureFromFiles(config.Path) + if err != nil { + return err + } + + err, data, _ := buildPrivacy(pageData) + fmt.Println(data) + return err +} diff --git a/application/source/requirements.go b/application/source/requirements.go new file mode 100644 index 0000000..02a3b40 --- /dev/null +++ b/application/source/requirements.go @@ -0,0 +1,432 @@ +package main + +import ( + "bytes" + "fmt" + "math" + "os" + "path" + "reflect" + "strconv" + "strings" + "time" + + "gopkg.in/yaml.v3" + + "github.com/olekukonko/tablewriter" +) + +type requirement struct { + ToDos []task `yaml:"-"` + Absolute string `yaml:"-"` + File string `yaml:"-"` + Items []Item `yaml:"Items"` + Privacy []Privacy `yaml:"Privacy"` + Issues []Issue `yaml:"Issues"` + + // remember the node structure of yaml + OriginNode *yaml.Node `yaml:"-"` + OriginText string `yaml:"-"` + + ID string `yaml:"ID"` + References []string `yaml:"References"` + Type string `yaml:"Type"` // Display, Functional, Performance, Printing, Report, Testing and Validate + Title string `yaml:"Title"` + Alias []string `yaml:"Alias"` + Keywords []string `yaml:"Keywords"` + Author []string `yaml:"Author"` + Status string `yaml:"Status"` + Complexity string `yaml:"Complexity"` + Difficulty string `yaml:"Difficulty"` // Low, Medium, High + Priority string `yaml:"Priority"` // Low, Medium, High + Version string `yaml:"Version"` + Milestone string `yaml:"Milestone"` + Estimation int `yaml:"Estimation"` // 0, 1, 2, 3, 5, 8, 13, 20, 40, 100 + TimeSpent time.Duration `yaml:"Time Spent"` // 3h2m20s + Source string `yaml:"Source"` + Created time.Time `yaml:"Created"` + LastUpdate time.Time `yaml:"Last Update"` +} + +func addRequirement() error { + + if arguments.Requirements.Add.ID == "" { + printErrorAndExit(2, "the id must not be empty") + } + + p := path.Join(arguments.Path, arguments.Requirements.Add.ID+".md") + if fileExists(p) { + printErrorAndExit(2, "the request with id already exists", arguments.Requirements.Add.ID, p) + } + + t := config.Requirement.Template.Add + t = strings.Replace(t, "%%ID%%", arguments.Requirements.Add.ID, -1) + t = strings.Replace(t, "%%CREATED%%", time.Now().Format("2006-01-02"), -1) + + d1 := []byte(t) + err := os.WriteFile(p, d1, 0644) + if err != nil { + return err + } + + return nil +} + +func buildRequirements(pageMap map[string]*requirement) (error, string, bool) { + + hasRequirements := false + + buf := new(bytes.Buffer) + table := tablewriter.NewWriter(buf) + + translateMetaColumns := translateHeaders(config.Requirement.Table.Columns) + + table.SetHeader(translateMetaColumns) + table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) + table.SetCenterSeparator("|") + + var tableData [][]string + + for _, pd := range pageMap { + + r := reflect.ValueOf(pd) + + var row []string + found := false + for _, name := range config.Requirement.Table.Columns { + + field := reflect.Indirect(r).FieldByName(name) + if field == (reflect.Value{}) { + row = append(row, printer.Sprintf("no value")) + continue + } + + t := field.Type() + + switch t.Name() { + case "string": + found = true + row = append(row, field.String()) + case "Duration": + found = true + t := field.Interface().(time.Duration) + row = append(row, t.String()) + case "Time": + found = true + t := field.Interface().(time.Time) + if t.IsZero() { + row = append(row, "—") + } else { + row = append(row, field.Interface().(time.Time).Format(config.Locale.DateFormat)) + } + case "int": + found = true + row = append(row, strconv.FormatInt(field.Int(), 10)) + case "float64": + found = true + row = append(row, strconv.FormatFloat(field.Float(), 'f', 10, 2)) + case "nil": + row = append(row, field.String()) + case "bool": + found = true + expr := field.Bool() + if expr { + row = append(row, "true") + } else { + row = append(row, "false") + } + + default: + row = append(row, printer.Sprintf("unsuported type", t.Name())) + } + + } + + if found { + tableData = append(tableData, row) + hasRequirements = true + } + + } + + table.AppendBulk(tableData) // Add Bulk Data + table.SetHeaderAlignment(tablewriter.ALIGN_LEFT) + table.Render() + + return nil, buf.String(), hasRequirements + +} + +func printRequirements() error { + err, pageData := collectStructureFromFiles(config.Path) + if err != nil { + return err + } + + err, table, _ := buildRequirements(pageData) + fmt.Println(table) + return err +} + +func integrateGitlabTimeSpent(pageMap map[string]*requirement) { + + for _, requirement := range pageMap { + + for _, i := range requirement.Issues { + if i.GitlabRemote == nil { + continue + } + + d := time.Duration(i.GitlabRemote.TimeStats.TotalTimeSpent) * time.Second + requirement.TimeSpent += d + } + + } + +} + +func buildTimeReport(pageMap map[string]*requirement) (error, string, string, bool) { + + if arguments.Requirements.Report.Remote { + err := enrichIssuesWithGitlab(pageMap) + if err != nil { + return err, "", "", false + } + + integrateGitlabTimeSpent(pageMap) + + } + + groupedByKey := arguments.Requirements.Report.GroupedBy + if groupedByKey == "" { + groupedByKey = "ID" + } + + hasReport := false + + found := false + for _, q := range pageMap { + p := *q + + fields := reflect.VisibleFields(reflect.TypeOf(p)) + for _, field := range fields { + if field.Name == groupedByKey { + found = true + break + } + } + if found { + break + } + } + + if !found { + printErrorAndExit(2, "the grouping key was not found", groupedByKey) + } + + t1 := buildTable1(groupedByKey, pageMap) + + t2 := buildTable2(pageMap) + + return nil, t1, t2, hasReport +} + +func buildTable1(groupedByKey string, pageMap map[string]*requirement) string { + + estimated := map[string]float64{} + timeSpent := map[string]float64{} + + for _, q := range pageMap { + d := *q + r := reflect.ValueOf(d) + f := r.FieldByName(groupedByKey) + k := "" + switch f.Interface().(type) { + case bool: + k = strconv.FormatBool(r.FieldByName(groupedByKey).Bool()) + case int: + k = strconv.FormatInt(r.FieldByName(groupedByKey).Int(), 10) + case int64: + k = strconv.FormatInt(r.FieldByName(groupedByKey).Int(), 10) + case float64: + k = strconv.FormatFloat(r.FieldByName(groupedByKey).Float(), 'f', 10, 2) + case string: + k = r.FieldByName(groupedByKey).String() + default: + k = r.FieldByName(groupedByKey).String() + } + + s := float64(d.TimeSpent.Milliseconds()) / 1000 + + estimated[k] += float64(d.Estimation) + timeSpent[k] += s + + } + + buf := new(bytes.Buffer) + table := tablewriter.NewWriter(buf) + + columns := []string{"Key", "Estimated", "Time Spent", "Ratio"} + + table.SetHeader(translateHeaders(columns)) + table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) + table.SetCenterSeparator("|") + + var tableData [][]string + + for k := range estimated { + var row []string + row = append(row, k) + row = append(row, strconv.FormatInt(int64(estimated[k]), 10)) + // nanosecond + row = append(row, time.Duration(timeSpent[k]*1000000000).String()) + + var ratio float64 + ratio = 0 + if timeSpent[k] > 0 { + + e := float64(estimated[k]) * 3600 + s := timeSpent[k] + ratio = s / e * 100 + + } + + row = append(row, fmt.Sprintf("%.2f", ratio)) + tableData = append(tableData, row) + } + + table.AppendBulk(tableData) // Add Bulk Data + table.SetHeaderAlignment(tablewriter.ALIGN_LEFT) + table.Render() + + return buf.String() +} + +type timeStruct struct { + sum float64 + hour map[int]int // [time]count + average float64 + sqrtAverage float64 +} + +type mathData struct { + count float64 + estimate struct { + } + time timeStruct +} + +func buildTable2(pageMap map[string]*requirement) string { + + est := map[int]mathData{} + + // inti struct + for _, d := range pageMap { + k := d.Estimation + + m := mathData{} + m.count = 0 + m.time = timeStruct{ + 0, + make(map[int]int), + 0, + 0, + } + + est[k] = m + } + + // calc sum + for _, d := range pageMap { + k := d.Estimation + s := est[k] + + s.count++ + sec := float64(d.TimeSpent.Milliseconds()) / 1000 + s.time.sum += sec + + h := int(math.Round(sec / 3600)) + mh := s.time.hour + mh[h]++ + + est[k] = s + } + + for k, s := range est { + // + a := 0.0 + c := 0.0 + + for h, m := range s.time.hour { + a += float64(h * m) + // g += math.Pow(a, 2) + c += float64(m) + } + + x := est[k] + x.time.average = a / c + + g := 0.0 + for q, m := range s.time.hour { + z := float64(q) - x.time.average + g += math.Pow(z, 2) * float64(m) + } + + x.time.sqrtAverage = g / c + est[k] = x + + } + + buf := new(bytes.Buffer) + table := tablewriter.NewWriter(buf) + + columns := []string{"Estimated", "Time Spent", "Average", "Variance", "Standard Deviation"} + + table.SetHeader(translateHeaders(columns)) + table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) + table.SetCenterSeparator("|") + + var tableData [][]string + + for e, c := range est { + + row := []string{} + row = append(row, fmt.Sprintf("%d", e)) + row = append(row, time.Duration(c.time.sum*float64(time.Second)).String()) + row = append(row, fmt.Sprintf("%.2f", c.time.average)) + row = append(row, fmt.Sprintf("%.2f", c.time.sqrtAverage)) + row = append(row, fmt.Sprintf("%.2f", math.Sqrt(c.time.sqrtAverage))) + + tableData = append(tableData, row) + + } + + table.AppendBulk(tableData) // Add Bulk Data + table.SetHeaderAlignment(tablewriter.ALIGN_LEFT) + table.Render() + + return buf.String() +} + +func printRequirementReport() error { + + err, pageData := collectStructureFromFiles(config.Path) + if err != nil { + return err + } + + err, table1, table2, _ := buildTimeReport(pageData) + if err != nil { + return err + } + + report := "## " + printer.Sprintf("Auflistung") + "\n\n" + report += table1 + report += "\n" + report += "## " + printer.Sprintf("Statistics") + "\n\n" + report += table2 + + fmt.Println(report) + + return nil +} diff --git a/application/source/run.go b/application/source/run.go new file mode 100644 index 0000000..8e9f1e0 --- /dev/null +++ b/application/source/run.go @@ -0,0 +1,40 @@ +package main + +import ( + "bytes" + "log" + "os/exec" + "syscall" +) + +func runCommand(name string, args ...string) (stdout string, stderr string, exitCode int) { + var outbuf, errbuf bytes.Buffer + + cmd := exec.Command(name, args...) + cmd.Stdout = &outbuf + cmd.Stderr = &errbuf + + err := cmd.Run() + stdout = outbuf.String() + stderr = errbuf.String() + + if err != nil { + // try to get the exit code + if exitError, ok := err.(*exec.ExitError); ok { + ws := exitError.Sys().(syscall.WaitStatus) + exitCode = ws.ExitStatus() + } else { + log.Printf("Could not get exit code for failed program: %v, %v", name, args) + exitCode = exitCodeCatchAll + if stderr == "" { + stderr = err.Error() + } + } + } else { + // success, exitCode should be 0 if go is ok + ws := cmd.ProcessState.Sys().(syscall.WaitStatus) + exitCode = ws.ExitStatus() + } + + return +} diff --git a/application/source/tasks.go b/application/source/tasks.go new file mode 100644 index 0000000..45616e1 --- /dev/null +++ b/application/source/tasks.go @@ -0,0 +1,143 @@ +package main + +import ( + "bytes" + "fmt" + "regexp" + "time" + + "github.com/olekukonko/tablewriter" +) + +type task struct { + due time.Time + text string + checked bool +} + +const dateLayout = "2006-01-02 15:04:05 GMT" + +func newTask(date string, text string, checked bool) task { + + var d time.Time + var err error + + if date != "" { + d, err = time.Parse(dateLayout, date+" 00:00:00 GMT") + if err != nil { + printError("the due of the todo cannot be parsed", date, text) + } + } + + t := task{ + due: d, + text: text, + checked: checked, + } + + return t +} + +func findTask(content []byte) []task { + + toDos := []task{} + + todoRegEx := regexp.MustCompile(`(?m)^\- \[(?P<checked>(x|\s?))\]\s*(?P<due>[2][0-9]{3}-[0-9]{2}-[0-9]{2}){0,1}\s*(?P<text>[^\n]*)`) + + s := string(content) + matches := todoRegEx.FindAllStringSubmatch(s, -1) + if matches == nil { + return []task{} + } + + for _, match := range matches { + result := make(map[string]string) + for i, name := range todoRegEx.SubexpNames() { + if i != 0 && name != "" { + result[name] = match[i] + } + } + + checked := true + + if result["checked"] != "x" { + checked = false + } + + t := newTask(result["due"], result["text"], checked) + toDos = append(toDos, t) + + } + + return toDos +} + +func buildTasksTable(pageMap map[string]*requirement, extended bool) (error, string, bool) { + + buf := new(bytes.Buffer) + + table := tablewriter.NewWriter(buf) + has := false + + header := []string{ + printer.Sprintf("ToDo"), + printer.Sprintf("Due"), + printer.Sprintf("Checked")} + + if extended == true { + header = append(header, printer.Sprintf("File")) + } + + table.SetHeader(header) + table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) + table.SetCenterSeparator("|") + + var tableData [][]string + + for _, pageData := range pageMap { + for _, info := range pageData.ToDos { + + has = true + + var d string + + if info.due.IsZero() { + d = "—" + } else { + d = info.due.Format(config.Locale.DateFormat) + } + + checked := "—" + if info.checked == true { + checked = "✓" + } + + cols := []string{info.text, d, checked} + + if extended == true { + cols = append(cols, pageData.File) + } + + tableData = append(tableData, cols) + } + + } + + table.AppendBulk(tableData) // Add Bulk Data + table.SetHeaderAlignment(tablewriter.ALIGN_LEFT) + table.Render() + + return nil, buf.String(), has +} + +func printTaskTable() error { + err, pageData := collectStructureFromFiles(config.Path) + if err != nil { + return err + } + + err, table, _ := buildTasksTable(pageData, true) + fmt.Println(table) + + return nil +} diff --git a/application/source/util.go b/application/source/util.go new file mode 100644 index 0000000..3e31ee7 --- /dev/null +++ b/application/source/util.go @@ -0,0 +1,196 @@ +package main + +import ( + "bytes" + "errors" + "os" + "path/filepath" + "strings" + "text/template" + + "gopkg.in/yaml.v3" +) + +type contentRequirement struct { + content string + data requirement +} + +func splitYamlParts(content []byte) (error, contentRequirement) { + + origin := string(content) + + meta := "" + text := "" + + before, remaining, found := strings.Cut(origin, "---") + if !found { + + t := strings.TrimSpace(origin) + if len(t) == 0 { + return errors.New("the file is empty"), contentRequirement{ + content: origin, + data: requirement{}, + } + } + + return errors.New("the file does not contain a definition block"), contentRequirement{ + content: origin, + data: requirement{}, + } + } + + text += before + + a, b, found := strings.Cut(remaining, "\n...") + if !found { + a, b, found = strings.Cut(remaining, "\n---") + + if !found { + + a, b, found = strings.Cut(remaining, "...") + + if !found { + + a, b, found = strings.Cut(remaining, "---") + + if !found { + return errors.New("the file does not contain a definition block"), contentRequirement{} + } + + } + } + + } + + meta = a + text += b + + t, err := template.New("overview").Parse(text) + if err != nil { + return err, contentRequirement{} + } + + var node yaml.Node + err = yaml.Unmarshal([]byte(meta), &node) + if err != nil { + return err, contentRequirement{} + } + + data := requirement{} + err = node.Decode(&data) + if err != nil { + return err, contentRequirement{} + } + + tempItem := []Item{} + for i, _ := range data.Items { + + if data.Items[i].ID == "" { + continue + } + + data.Items[i].ID = data.ID + "-" + data.Items[i].ID + tempItem = append(tempItem, data.Items[i]) + } + + data.Items = tempItem + + p := []Privacy{} + for i, _ := range data.Privacy { + if data.Privacy[i].ID == "" { + continue + } + + data.Privacy[i].ID = data.ID + "-" + data.Privacy[i].ID + p = append(p, data.Privacy[i]) + + } + + data.Privacy = p + + req := contentRequirement{} + req.data = data + + req.data.OriginNode = &node + req.data.OriginText = text + + var buffer bytes.Buffer + err = t.Execute(&buffer, data) + if err != nil { + printError(err.Error()) + return err, contentRequirement{} + } + + req.content = buffer.String() + + return nil, req + +} + +func translateHeaders(columns []string) []string { + + result := []string{} + + for _, column := range columns { + result = append(result, printer.Sprintf(column)) + } + + return result + +} + +func getGitDirectory() (string, error) { + + path := config.Path + + fileInfo, err := os.Stat(path) + if err != nil { + return "", err + } + + if !fileInfo.IsDir() { + path = filepath.Dir(path) + } + + return findGitDirectory(path) +} + +func findGitDirectory(path string) (string, error) { + + if path == "" { + return "", noGitRepositoryError + } + + if volume := filepath.VolumeName(path); volume != "" { + if volume == path { + return "", noGitRepositoryError + } + } else { + if path == "/" { + return "", noGitRepositoryError + } + } + + if !exists(filepath.Join(path, ".git")) { + return findGitDirectory(filepath.Dir(path)) + } + + return path, nil + +} + +func exists(path string) bool { + _, err := os.Stat(path) + if err == nil { + return true + } + + if os.IsNotExist(err) { + return false + } + + printErrorAndExit(0, err.Error()) + + return false +} diff --git a/application/web/index.html b/application/web/index.html new file mode 100644 index 0000000..f557455 --- /dev/null +++ b/application/web/index.html @@ -0,0 +1,59 @@ +<!doctype html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + + <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" + integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> + + <style> + + body { + background-color: #ffffff; + } + + </style> + <title>Download Portal schukai GmbH</title> +</head> +<body> + + +<div class="d-flex flex-column align-items-center justify-content-center" + style="height:100vh;"> + + <div class="text-center"> + <a href="https://www.schukai.com" class="text-decoration-none text-white text-decoration"><img + src="https://cdn.alvine.io/image/logo/schukai-rot.svg" width="300px"></a> + <br> + + <div class="card mt-5"> + <div class="card-header"> + DocMan + </div> + <ul class="list-group"> + <li class="list-group-item"><a class="text-decoration-none link-danger" href="./docman-linux-386">docman-linux-386</a></li> + <li class="list-group-item"><a class="text-decoration-none link-danger" href="./docman-linux-amd64">docman-linux-amd64</a></li> + <li class="list-group-item"><a class="text-decoration-none link-danger" href="./docman-linux-arm">docman-linux-arm</a></li> + <li class="list-group-item"><a class="text-decoration-none link-danger" href="./docman-linux-arm64">docman-linux-arm64</a></li> + <li class="list-group-item"><a class="text-decoration-none link-danger" href="./docman-windows">docman-windows</a></li> + </ul> + </div> + + <p class="mt-5"> + <a href="https://about.schukai.com/de/impressum/" class="text-decoration-none text-decoration" + style="color:#c10000">Imprint</a></p> + + </div> + + +</div> + + + +<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" + integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" + crossorigin="anonymous"></script> + +</body> +</html> diff --git a/deployment/scripts b/deployment/scripts new file mode 100644 index 0000000..e69de29 diff --git a/deployment/upload.sh b/deployment/upload.sh new file mode 100644 index 0000000..2d62512 --- /dev/null +++ b/deployment/upload.sh @@ -0,0 +1,4 @@ +#!/bin/bash +# shellcheck shell=bash + +$(command -v aws) s3 ls --recursive s3://doc.alvine.io/de/ --region eu-central-1 > "$(THIS_DIR)s3-temp/inventory.txt" \ No newline at end of file diff --git a/development/examples/assets/schukai-weiss-1000-210.png b/development/examples/assets/schukai-weiss-1000-210.png new file mode 100644 index 0000000000000000000000000000000000000000..c6a76eaf936e00d416808e9318c2dec3a6bb8735 GIT binary patch literal 10512 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 literal 0 HcmV?d00001 diff --git a/development/examples/example1/1425.md b/development/examples/example1/1425.md new file mode 100644 index 0000000..dbe89dd --- /dev/null +++ b/development/examples/example1/1425.md @@ -0,0 +1,145 @@ +--- +ID: 1425 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: +# who is the source of the demand +Source: null +Created: 2022-06-18 +Last Update: null +# The issues that are associated with this requirement +Issues: + - Title: null + URL: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +{{ if .Purposes }}**{{ .Purposes }}** {{ end }}**({{ .ID }})** + +{{ if .Description }} {{ .Description }} +{{ end }} +| | | +|-----------------------|----------------------------| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/144444.md b/development/examples/example1/144444.md new file mode 100644 index 0000000..a9c31ee --- /dev/null +++ b/development/examples/example1/144444.md @@ -0,0 +1,160 @@ +--- +ID: 144444 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: +# who is the source of the demand +Source: null +Created: 2022-06-19 +Last Update: null +# The issues that are associated with this requirement +# You can add an issue by adding a new line to the list with the following format: +# - ID: <issue-id> +# +# if the issue is not yet in the project, you can add it by using the following format: +# Only the Title is required. +# - GitlabIntern: +# - Title: <issue-title> +# - Description: <issue-description> +# - Priority: <issue-priority> +# - Status: <issue-status> +# - Assignee: <issue-assignee> +# - Milestone: <issue-milestone> +# - Labels: <issue-labels> +# +# Issues: +# - GitlabIntern: +# - ID: <issue-id> + +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +{{ if .Purposes }}**{{ .Purposes }}** {{ end }}**({{ .ID }})** + +{{ if .Description }} {{ .Description }} +{{ end }} +| | | +|-----------------------|----------------------------| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/assets/demo.png b/development/examples/example1/assets/demo.png new file mode 100644 index 0000000000000000000000000000000000000000..f3688147978fe724ca884efbfa263840f41b6f4f GIT binary patch literal 67352 zcmeAS@N?(olHy`uVBq!ia0y~yU|h?<z*xY+#=yY9{Y~W<0|NtRfk$L90|Va?5N4dJ z%_q&kpuphi;uumf=gr*m3Yn`r+wW)I-uh~9MA6i0=GhEv%#6W$s#{DrSeRIZJUp5w zOmN^}*>OdH<DuG@drk^7;(QAkzqid!iHwb!`gZr_ck;)h#A8&NH}*cSm9xKg?u_Mg z>(qVs=a?x^4ZU{5!otFWVOwr+RFIQ*w)P~I+J!sT{d|1YXKs<g_WPCMyVj-m$(y|m z;G1RDdb<9j_O+{5KW^XsuPgJ#nVP4jYJM{3UtC<g^TQ%<iJ0KCyw~H8e>J~zgk8R_ z<No{SH<!<U@G^bg(v>?~H=q9{H*3|WTd(s!++20l#LV>L_1pQW2b)^Y#BZ4JxX-#R z!{k{0x*b`&&HUyV%(IU#*X<V9e>f|9z4N5he>HFAB?GOS?#GpydQaEAy>!oX5%GG> z)E6Hruh`}`G&di<cXayOjPrJ{t8aW;mY%%-{PdsIzrMT-37b-U^=kcsee34kEPnRs z{O@;9A2jnX+PbuKcj3N&zocc%A4}NC@$=jKFksmK>*>=am#x14`71B6%rRZ#h<shW zsOZyF6Eo9%<9V#y;)SQzZvVVGKJJ`p{T?abP>_3O=j|(<&U!lW`=gF&&CQ3!W=!i` zqj6)}*QH0w54MU=_E9t5UtjT#-{N!6WyTd6`pge5dFw6nzh>n;clQ*(%1X<;?X#ux z_t+J$S-Dek`|Z7l3*PVfEvMjeev?k#uAgCcKRz6e-NfiHG1cevou?o8td9xmva`4A z8u)U%PBYx6a`Bd+tgO?5bw4l9&&;^7;poo7<l_tq+J9gFEG;VuhzU8;ulM7lnC<R= zAI|N5fAR9==FC|-ahpmU61TgBrRWrYpMLjW*Pi9P1qB5+c3&u!^}W1r(iXda6=okR z=6LJ<Gd$eRoBU@-;h#Uxrw0ZF`FMM4Z_6#du_cp7+HA`En%`%152*!fe)?22)1c1A z^{DHfujj0vJbU)xF}MDLWxHk_UM72Jsr}w1_bVee6kHS+(_!!}UMPJ`yzhA8ZHq-u zH<WMqY2$TOV$0$E-M?>eU*!9*7t(w4TPfe}))b@8<C`BVZq@HT7tmoJTh3frS$U`O z_}ZBN&$CaSJf}9*>*B?mCm;LU9lfH-UUd4b`NMBJGBPtyw$#4eYW|^W@126b^DQ2I zI6Tv~TCe{9@me4IM+NV8{$3yRZ}Vx7r9lz#j{Swjd*aTE9bU*6uXkzP8o4<oA2RwZ zKPI&C%DN;vGR`{PyR7Qs9XXS$t!>=>j}C3i5t-h$@b!&do(EnZUYeEA+}o5lE27Km z6w}>J6ICSlYfbc8HqnHCnyxbQwA{y`u^y8;QxCuCe^zk){=2k$b1Zi+^pM$Cq{5ja z-IW#K|5Nnm(x)L=oSQ;scPMUj{4SK0d8p!{SjPI>C3_D~_q)F#%F~l`VF1Tt?Kg%M zHgY<rRpwsXZt<=tGh*6a-{?Df;@eav`YqjNA;<Bf^SE&Q&V-e#yd3N7bk`;cc5bfv za60|KBGZr3%9j7dmp_^m$~2F`ZaaVf@%Gbi)n`oQJ+UK~_qNH$6?zjyL^yBFnw^=S zd3bFW%O6G^Z>ONpO`o|rpFK}jNRAQ{G80R<#g%#4ZJMZxbV#JrAtq^`=tC~g{>cAn z@ZazBQ0v6`<tvuVDA77P%QV~mdv*EZRayJzc3gkGG_8P_VYOZK*3;*npYB+`Wedyc zO_|x*zyF-HV_YTG{AurggEiTTSAFFld%15ck&V3Uv76~ixXhVXcRtSO|1Tyr&Faur z>5aLw6AU^Qo%r(Q%e&0tZ<<9#n+$!s3oPDnT+2&3z-`E9{g2_%M~h9j+aFDxm?}Aa z*~9M@ffGLL-lL*yxalvWimR*tl8S$w$1_)~UT&a2e}R32*6J0jxbJQ{p{sLfN{XAm zRl}l9MvFdL%(~t`&#Z8#?UJC(5Ld_TJ}S4}CaEZ9-H7>dd4ADFK9|#P%Zl&sEq`3L z`{(;J;T2yl9^Y>9z9{p~m+8_P+S;k#=Ip#vcRap)#&_kuIp->$&vP#J=6?SF#iH|n z@5%o7TX)X#xlZ34JK6pB{r&y<i=Ul&dhz(Y1;!$`@^(0ePQ6q0xtC$i-)8xDA8yHh zbbTyoS7WjLZjms<{vTIG*F<g2I?bIUeOp+i_R)LEU4K-I!uKEh)5r04VV<JbB$vQC zJ?Cq>i*s)9T$}TwI_Cc_0Zqw!OaEAW>Gx1^3Jkp1AUEY(c}VEdw?&t)-P^a^_h*#x z1Ix7smAy9RGDl7e5M}iZEY#GRA-0Mo&B`;*pkuDjray~s#(eKS9r^8J&Y!l{tGAsO zt>s<3TiRM^+2(zHmihZmo~kUae6THgMf66V`Nw-_`YqPvTDDI4G}o@gq+4d++zv8v zdQOtCE4sp$>$@~aCt}NtH*a$Mte-wPuUk9UDwS*NR%H&h<}<Ut9(3qV+OF&=bp7AM z?{g{+asK#Q$8%UgUA<k>xG(Wo&*JY}D*r0Y5OoL?5ph-27P#@u^ySL?jnl5?RD86v zi`zKw+qreVdo^w^+q=2DKYUI4;qLE_r?U!eEj~x@=JcGjA$Rt?d2*XJH$M>hd~TwG zwY5jNKmWI5?b+>j4>!1aZ#rtRDLObXMAG-_1Xb41zyk&wgEhaT%-J4SJG1@YKXbkn zvIiA~k1c-b`D&V;qo?Z0!qq1_HN1@4E=n)TcD7C1(S3XUKiT!R|83-aosE1`xJ5Wk zLS3h&sCYU}OHJ`~nx?X8^XBrb_p8_M;c7Vk`soB`zI%`EOmvrFbf~Vjo_{Xh;KHIC zZ+m1SProo+%(&yx_Wh5KO!j{&zW<M@{=Oga|Nb88uD-GB-^Y{7KmUBZ^?Kn~`E?I3 z|NOkY(sxyk&8I^%AGNF0#`Tz4tLe}2T$R&g@y}FRPDe}YN!#mncQ2=<cq|Q4nXFm# zt8o6?>o?3SZ{Ac9@(hYTyVkPiCr?F1K%kC|o_XH(wpA-KRyDP>q}+_y<>wbRp>3*m z<^QKMWlBFBe8ReE!xxh@N4r?xUYFh08fQ<d-IG?jDC=}_a>ZZ9F7NJwm0aKN)M>M- zK9wo>@bHEvvon*lz)B7k&qK@VyLNxt9J*%p>huC%Q+GMTx!dp8u{R`yiA`4bXL)cn z{QiM$xto|6_kF+n-XQT%g~{||vrJ!Ce7WepefR9T=$H?SKTDVvsra5fd#CEQ?3EDy zM{hRo^S`=4YnPMay~_8sY3D?osvfdFH%>aj@vi=XVxRpxi8g-ub64wkv|S4`{62Z| z<jI}a4UVQA71g#+K6>iB*=qjQ%l_6=o%wB9=AZX=KFl_+_TBv%$CjOZlX;o%;e&jc z7W)U!7xzE^a75TYahBRv<+kFBt>O$HUTfENCrZpI`s687cf;h`)vJZq@4vg5Cf9HE ziKEZ{p9Rn12m0ps&RkGzw*2=aSu)0WhKtg{J3BvD{OMHpTzXkVRP^KBUhk>Wvu7Dq zzCIjet0F4@?;TrVLbTJCn}$1gH!gXkx}a)8@4xjIw6t}fHhn(-_-*;U)N5hV?&T$U z*<D=RKX0bmKRvm8UfRi^kH=aLnqHk#bEz|9R-2CJo`277pNZe_)Omu=={t3&&&HJh z?TyZvCu^T4qb^gfV}7Tkc>m{5p%<>-?s8lFBqe?F?8(ml{`~RlkGJTz-`Nx6b6G{K zoAKPE?z?9jT(uvRPxM(bQPh6g(qt*NWmAt$GYRoLwng{dzOP|w{W8AOj`!xi`eCD| zrG09JhHl#1SD`yhX1>vp&$R7cGlxNMIy+~xV)Ln&JnA!ke!1KuWy~ldzUtAz4M(4B z=<U^M);X!MsYmzw`ocZGPG!dwopkk)u<zTmCuY~KU6whwOiX+a8}P){f9Bo9#Q1LC z@AV>LA_D!#J(pgRsk^aI=1=d+Kaaxqzr60$y?B46%JRC`A|<iU=T-kdc*Ah<&(EdT z7p>AdJzaPCo;^+8^+lYOJ1cE|-FO@l8fKK0q8tAI-6@~-7w_Z*Kbo~Q+mMGjH1y|v z>HLI;hmP*~{_ppm-~ZN}$y#Y2``KO1cUHr?*Ci!oMo$kguUMgRKdJ8BA?`XCjVrEo zb#kUxO_vCH&Z~S^`R5<Q)~(766U?Wj76uA#-KuPGHuwFD^(!=<U-GVRy8ZOg`~N%o z|Llob_xrLbLrF<lKwR9hnd$TT?!SMY|NW2bbnnwk9+p+x$uHEIwLnC$ICavZq}lW5 zJHNEPR~{R`<DWs^n+QMKr%Q76obO%SnPAXeU@__E+m96%KbHtcZcg)kHe->-obq>; ze?I?XUlD)b!O_t!{Lim&oyc7*vHz>iuzvmW?a}w&Cr_VVynOlf%G-zCL?RW{&D$$% z{A}dzUw-z+oTs9~K=S=jv&kxt1(Pls+_jB8B5YU^>pn5%-mmlC9&N6^m8zQ(m2M}@ zGTWA`yxQn$^XiSM94V|C+S&`ZteN33O+0dwVUQ==RI!WKHq5)XEsUv7zKbQ|(X;8Q zN0NAMA2Q?3alXHCqjcr(yXBs0lQp^yJ#3d}J227Rmp$R#9)FJ3T^6s`ybp{BaPao# zPM=>aci;ZE%(F9d+m~hjsYuRGaTgI2D>~R;$8z8>zx}CKSF?BgI4-_0Q>x$Qlg0jB zkG9ABne6Sky!4#KUlW^ozI=CHe=WTIw*15I)$127UaVZaXYbm%yWj7e9%9w2bJ}N? zN#p7II?3<%{)T&bby>bxpy@Nqgz@&apHJ7XfAB{>_K2(fzLxv3f8E!db$Nd3{=a#f z>k9Pp_x&_u2wo<0VSUkUDc8`SPoLT!e_Lc&eouYRk4N>9yVv#E|NY6P_w!`xp9gb3 z?|fUPIPLOs`D^<vd=<t1y}bYI%VocZQy%x<eD>ji=5hJMFPG14s{gfpJI8hTRjb)Q zZm<65SbX|<xPIRIn7~BE{kuPLefs>_==i?xbB!zCel_=4dTD0ztYsg+Y(5{nKkkdj z=c3}5Z{Hp@C_B5+d(s)t|HVwx|GzO>x9idMD_1(E&USTe{qtv&_s?r5)jys-t-pB3 zj*RJ#<Y(y4ex)eZE!gXJ^7MICYl$;9Pu}#O*yLg$p`vd;Jws(vYl7w8HFwW9R7b6J zVOf8he_P)wj~m-qrQ6><+Grtv_E&@FWA%jDY%42dPCq`nMJFYa?Y0Y3imTvihRd2I zw!JFeD^@w_OjLUCHR-jc)b(|Xl3oO)c;2&E&bTdw*-VYitZ0AyRiW;q75UfL&shAL zEn``0C0}ndd*aru40|>eo?HEXs^R=|@e?vz<ZC`C1}~R6u_92pe8=j2OLokt|9gLL z#;jv+EQ>3@{j3*0b8gwLDglP$GM|0<tltDUm{f#@YU*m9Y?*KRn)%)h4UOo}ud>&F zzWBz{$NEV^pT!>ow|+_A%uLPa^NRU$bCdK>{QCMja&MH)-|xJs&vMPS+_-Xu#i4lf zjTtlN&ON;DLx1)AV{eNDxk?K!pWU9)SO4c@P8+}Uu}<|l4rd=^IjpJr^82rK@8xsr zmz3NP;Oe)NIlue5;OiX6%O+pGOgqFNHZMW1RXx^s*FHhx{XuVTzGBzk_vJq0{OtEH z9(1j)oBy-+PvP;P@a^;3c%%1aY0UK5RB=*>Vcp-yS9iqf{d*tJ&-267sWxNQu|-F_ zD?jenH?F*-;`eL*<DH+^?PgrDYR!YC|M#8Q|NryVv+3V>g_|mvT{rDzUVq&?E>CV+ z>O`Mq7kFha8|~k=UT>19q-$8gP7@nBej%ZY5k2?r>27DXX!?59AmO6X7mHmwiP8^B zSwHOfQ?WNr=d_Ygrx2&Rrj`!NVI_O>`CE8T7@c$x=|AplB&a_1T3{$^isS?jm7pb; zGkq>QU9-u^Yds&fKH-(&@uUc|45PNxygSQPr|nbLWRAM}<<yz*nT21>C9O(0md~%! zV#v*%Eta6srNLFaS^der<*A;NCOmmt?)CU1%V%+&2OBcmjVdp>XlZM|czbt?O7+uI zQ@7;5aXdTMod5PF<NdBy*6$44s;et2pK0&0`7Byj{WRYq=hi}=bt~1RI&%`!>u+AI ze%%}?Z<Kp$;gjdj3tud3|M2T|en3pjnfLYIqucl-d)B><=2`x={mPf_g6E+Z?g}ai z@hw*0ZaZ<V*Rl<V5_efU&8QSrx^p@FU6dQ!i5(l0S8C`#-dBHb|KZpFD&Cgz$QsR% zpI2;Fzw_s`GcxQOgavPx=*{)pSohfahtzDTljl#LpX04Ic}?v0yz53ESzi<%tF81< z5mFK2RPj9Y_~V1G6#=HAp`n2yPqnw_mnY3qYfDUc!Il}TF7oPEOsrMX*Q-Ve7rWf5 z0#m0t7<8!IJTa*yQDVp4dA;wsHf!i;EZV$o-nn;aI+2T4Y+;%H%++7oX@&}`^Y$YK z-MSA8cW?CJK5P_VIx|J<;H%Q?14|Q@mH2R8n%0*qePdf=OUt5;-s69tZVp`?v3p&g zVsp09>7()0Z+m^1W47nXPMs>+BVlMGoc2V+Q2g?Z8$Wi+exEJe*YfjpuX%7tgh%dM z4!wOZnAZLJE1#L0yLicx8P~3v$yGfGWZ1NM^Tyn2?)GiApFV%y@h5%y$7j*+Km1!0 z=`qRWfc~`J?d2r_@%!Z(R;|)1DlUHU?%l!n-@o53R1uopX3Esa5F2}UNBM_e^VsF9 zW~_Us2P(VkD$d=k`SH+w&fmZ94NFcW*!_6moVW8WA6sZ>;d9yT-?VERG7f44*%sc| zF;j7-&zldwJPs+%=~yh@<0SncsV6q|6eD{;M8tuq`~RsbRINJP#<y_Mo;jAEpG_3y zNNGtsd#luCQD9d$S7iA1r5UB)zf71cd?!iKt*mT9-?`lPwYP6i^UJ^Ynkg}Ue#6`K zZ+yRQ-fxg_v1qqRO7tPGXqTkKm`cYjI=ySw=q%d1mq*g1BO{+*zWxj2q|D8EwZg5c zsxl^D9rncWcj+wL8S|y>u!Ne&CKsEDDsui0KmPPs9&}@yr~8WLE%Tg;GG|Qd&3idx zT4U}k>F*sUS6n)9rvB^H>pxEV*Uh<U@blN~{FHOHzivF1`O@3GVy*1K-0k;#^7Ch` z4CZ5b(AX~bGW-v}%?|<dyA{mB>V8k8?^|@R%hgP{A6LnG|KB&s9tp#qkf`)WM>tE$ z%8EX!PJd^zFTegbkDC9yBTr6F{_*p?{!yc|KI^}IRG*jfcGlK8Ww*9#Xlg$D7M-8? z@=~hLER%^TMhD-P-`RQj$Ls6n0{zE7{;Y|qzq|Fzm$sP(b$9p<+x$JVS;jh<&C=2m z6juvZEaE$*eahnLlgTscD*iv)^vfW5?~+MEljf;xWj^SoCLFPjWunKV6=Dv(Ul-jt zmKS^W+IE4*^Z9Ky9R2vd_W5m{$X!!Zy{88T1|F=mx0!zX{hsc5^W;`(t>#Eey||}0 z-?8@3$DBUPUl~%f<&<XnOqx9T@Wac?J|61+ee4_SjZ2>IUkSX}*QXp(J&mzD?80>S zJO%lqUml%1b?o_B$4RClp2vKSuGG_Bw0!T(z+^Xp6Q`2iOj)TDwPQx;>af7TurB)t z?)?&9T$D{r%r@pc^*Z#BqiacEXynnv%ljImLp@a{m$cj}crHG1i*C@ezTC(g%UW|! zo!HiDbzt_hx8?Vr{`q|F;N!1pVhLX^-nepRYIxjHRq^;KGvB{@@#aY*yWFG2{dVud z|8!5+dHOd}zTn0d=bazipBG;|I=$fg-S407zOS3zDSY(PFJ5V>$}b;}Z~rmr^|y)- z2i-f|AInr;5fl*<$=R~G^Y^>o>Zhl#XL#^E{Qtz$`u`;tyZ0{Hv7=+!G%>llCm-w9 z#&jQle5devY)sip|CQ_3EnB;G?s2*5ruQ|^&%ABxbW67RbR+rCk3-xR4_hAZcv+vH z`ej8_)~aj`ZQaK|#p4$2UOu~1SnbR56Cd=dCVCuIxio2dhEC(YxuFpoE9Pu@q^etK z{BYaWQw7mAj~A?zskz|zMEpr`aO}}3%={1J|Njxcm{GF(c}<-D{yl%v@6^1`jovbO zZDvl+lczJ+7kq3LPl!@m88WNh?!yJMaOHjfo<+-KO2qt{>^(unP{j80)$2yy&%c|> zJb$}EUE;%T_W5-$#aV0}LoRn8pW6J2chQbJ6`|r^xy1#ub5t(famtS7zPmRu>h|u5 z6Hjuc80MXc;Ntomu_s4UIx6Zyjoqf=;=q*N3>Cj}jUyipHb?Brlbt*5>{@<1pOCOl zNw#IF$~TjWH@9{zS>@4ntjBQjzAsLkEPqz4a`X2;KV2+6FOTo#mV4_H59SK;urYG9 zZ~yyiQ9_uQ$EC9K?>Rgtoj7@N+4AM()924CE-LCcn)Fxb@!C!w3+CiQo^vAV?cJ74 z_Mcv}?Wq&b^zM_%?hDdHKLmZPT)`c$lKs$lcgphS=EM8WHdIGh9*o)3#ecQvabe}g zlncEklawZRxJ}IEoPWGMy3}~bt~OrjsEZ-I)0aIeTPd+p<l#HLs@+zcH!9D}+}pC~ z5Cda;!>3C|A(3wmYMnW+{NVd!pVuC05>-)qL=R6h*f>!@X`6M2Te)vUnM?V1ap41V zI|D6@Hn0lJPQLw3eB1kOj+$$S(i1LjUZbt+xaqAf3%7&+@|zd#H0qX4`hAaoUs?X4 zf`Wn<_RRAy2kp(6)RpADqN}Bkb6fAq=Id)GZaTO&L*&VmiJMB6$(L!!&Ydgr>{)Qg zjP`}gKkhPNveU1;85t7()L_M;E*BHdwmz08&z>3mobA5&l-A3XmJ%!88xhl5bDLV5 zbWXlWaGZa5Ut4bav?ux9%W}^MT3T4Vspt7)>NkmLTW^YVM46EEgcMfKNfT40`=1?> zy~6Q}$>lQVB)3^}-sIS<@-mWB7VKAMHVqB^(G+<lgx|@3S&KyEgKs|rloC&!_MW(5 zLdpbz)gr2#Z+i7lPfa-q8X;$I|J%dZJ#E#B1PO^SF73H$t*xq=J8W;x2$N#v=9HX% zy0^9WO^^W(v+YEc+w)r|dOZ#bJ+wFR)TvXB6Hk0(-@rS$!p1Yi|KX>qfLJLrv$l!H zj=4+|5s7pRO3@L~i9A^LtWj1*M&_F~+nsPvNlhK=R!vpU7k5>9@(z70t6KEdWV>ln zLZb3AS)bF3R<EA@?3kKK=;7BNn|OEbtUR&F$3*Dh>u(LIiMPd;txP^G)Rrrtb3%C* z$6{$sm77lHlO)`vHcT*I7gc0(`ryHXiT{%h*sfi7kFO?=HPmaO$srY;xmz?BFAsWP z)Ty4d<0*sNEd??ECf$j%C!gL^IX`I5bbp(92`@J-eIhD$@!m~O$3VqR+deuMceUs` zJNY*!U6y@&bc3#sx6`DY1BW*GOz{2a#>39e&ffmFt8u@evgpx6$F?aQ35q@P)}(Fi z#Mex7MG9q$Y8@Y4l;{kZb?=@5*M_vSR$)h`1qU0?nD&hC(l(!?53(MuG?~QmGNoxt zs*tg7&i1agT1PH(^0*$IBoY$owrBC>W7~Wtl-+;j2)1bNWXA4mzpj<C>=DWf=L+td zJf-APThr8O8$@UB$P@H)^OR=$DlK*6!UYEt88xZS$?|7h&2>z+Pv7;GcgCtSOHNKc zp?^X#cV@&U7xxvj7tPAbIqDV|qLcmjxrYen$!QaGy!YHYW;BuQgOobhy4v}S-C@z? z+L@PK59BvYQ|NR&70}^QTJ)wSCuU1&*@J0&*Q{Qj{_qd0Ox=lvBG1GYDhTtW1<&)C zoGo(s!mSf~TDe!q+D&=1$jNHgt{0w1EEkkna5}q(i|E`wwoO%qdt=tcAcI`t+eQUp zNuYVOH}O0XTda0l8}f)>+|j7#y3r&crY>fikN=w4O67)kWdoVIT9#zU6dXudCU4gp zkS;D^c6V>$r*7_x&TmCTL^m$n*g5N9^UGdUkJ}TbEnKi_&Wwpl>%4EwViUVDt+!R_ zUPoeM=ItBTu73{Z-~)l%X$KaiCJTGdlGxUiS2^MC1EW+QYev199g+)=cU-(Xb;-(= zQ=5<RtIED#v@efUR#q_}Mr6tq1CxA%ZL2PQ_LEp|?w~Shfw8EvMU}wI1?>eoJ?7f8 zw@h@py643WjW25@M6^Zb=GR+WSXjJ?=czckds#|yq+F6A=j9SbZ@m;xx62NnZ_V)H z^1j-+R7qs|)WsElOj>tou9Wjxuz};|bLBLNj5_&~AyQYLCLQexEh%r$%*aZ*(o(pk zb+<?21<{vk3zv7OJXY~-F3|GS5L>D(x7d89!lYY2)z^Lg{CUT}UD+$-LbiIdK6&uq z!GjIo4L)4A*janzaiGuXW2;wc%viChCneIu!7-2VW+>O^>pIH&H_X`eO-|@_w1iy} z%fCfMUYnYZBpbexmd?z~R-AcFQRvtv9VSQny#Co0N`6ME0%uMt&+B{m@zjw?dtX>d zENfBQeZj=MYuDfPoZlBNFTG`L<(c#RaT6$<`F`^;i|Jl|<1nd&sZM{D%EAaK#&Et> zPY!kWAN!>tzt^I_@TxH9*5e<Zia*p0xFOIb(C?<H<ul1g#Ut8m;X64q6Vt$m8U6<9 z-IqQUaed;7xO%f^$%>LTrxkkgv9^Ic(Z}4JCxwcfZN9xJVC~%cSxPdU1<&LEZ}V<_ z4EB4uVZueOAF7i!HF=jlE@aizTX$?JON2$e=E-?{^Qu3XcHOxtQ+`5W*X`+(JeHn3 zuc<K2=Yn*v!fGK`*2)#DT9#$<tdetabhN9R-(Pa;!6)y!<6rV+kDl20xL~E!#CsOo z7EQVo>@llz$qs|u2`bW_-`-q_i=4Le?X=lHKJ%JS@=)3N>QwyaPiMj{|Lu@;SrquM z^ndf5f;$^~WGp9r>noG1`Vr`~P*274(Tv6Yj}|m9dsMhPa#xO}zui}!Wtl}!1TS0W z+*&AYpQzOJq4ocsBfH=4_4oATyl?l|#LL?|GdKI`%k+7_?{p{pt+Nl0{h6J%?~_!! z%qQMW&5qB`%st+%zju!1_jlFri*Iak4h)?dDPMEsOn4mYjl^4^xQQ=kv$N4)KXLN> zvPD~_>BL*g=5qe~`Th9Jujgc#;`r@Md~PpTvuR3+)~P!`yEAg4+M|O#T^76Sy50Hp z*#sZ8f=sT+%AHTd#U7MZzvws`@#m#cSk1P+J9BJ~$=Ec?$JQ9GUFdfvMd~J7<VJ(k z*f)<q@zk8$egFOO*Iz%iXRk{>X6XKTvv>We{qaBe`E5T*-2Z>C+~VC0Nt<6cgez?1 zQX(Hti+-;#*YES?`G00G^Ud&ac4l_>vG19kzq8jv<y7YKc}=IEKKdIe|DY%{rsg8+ zo}brlpV{>~uZ>^&RAuSgH^H#A0MF+gj?eoQ?{oRj99dV_);m?V=RSFoQvCD0-qL+_ zw%OOOKK%as<8S7e>btz4iP+ikf16yp#gikim0i9kY25cS?V0zP*~aPbY~rf_o@JcA zxVgFc@VtZr+=hQXMOaC1uK0T2+w%Dt?VtZv?oW8P#`Fn`*2c?mHuD%Bdh}%M>YkN& z)JM*IiVXjkGP6m2WsfG7?z%nupwGnV^PLk51vf2QSXFc8cZ%Sww}(`JX6C+p@>cxb zqleY<YPYUAJA8bwQN_k#n$}~t<H}#(pWYg6TzxJ^=XBD~F3}$~anJN4I1XG&J*}y& z%c?NZ<HM=d>r?G=cBGw+($YS)(TCe}(ghRou0;!0X?3~?o!+!U*03o=>*yMOJC=m2 zuS{DGCu(VHZ_7OXI)6`V=ByT{Se>XnEfbZqji2AE_^iuwc){Yulb=l!J9YY0*^F=J zGHzV($jj5KtgM__zjNnKlbnn@ON~lEbKt@}JC=Xl{{Juk!gG2-ohCDkenuW;+59;( zCre5Fw7=2P<e6Ok_J8B+Do?WZNT>zR5LS^Aynob7ML1$xOJ0=3HlJHt3V%19iQX|I zG<)_5t|yawZl|ntyfp2k^#97K;q$5|o>~|>r{Yy-2><G3I~Gl8YO<-ZyDxrfPioYo zx$QIWr=^|Xeb8`n@(in|4qjeeAFKAB`TZpL)~(w=pIl~*`M247Vrpk;>DN79?k{Kj zSo*N3spenN-_n^DBCf~Ye|~>uT7iXAs_W0Pw;`dW?V0a;M76^{UAcVz)7<>|6D_}8 zF+RU3>FBAt)^d<fr6o3Gl$tD^plV+?UH-I}@@a*enL5h8UggRwwN_0#yN9*Z=Hnab zKQF4)1wZ`E$jESTI>e-OQ9~ndPh(DwYwEv8qGzIa@Em>WIPp%#w9b^9GnRGcHl2RD zaO=L-_IG>br!O)rN#RwWQ^7P>cH!Lsl_qBX8D}oux9L)!U)Of*nA*O|D-%;vSudFM zt_<dT&?cR)Ce)cHxNP<6*}T2Icj}JEGW+T4>ra0-x8`rTd*=7{o5jyS{lSgKeb1(b z$ESaLvy-{+FsN<hZ<KJcD3j}Dh>Yhp&m+4|o;#~1_1bAtu8*`&%#ul-oAy-NeECv8 z<MYS%n2LWleI)E9ZRaWpbxw$1Cv@VR>J{OKmtDOpKHb;9EbBXQ>QrZ~sSKVqGc8Vw zAK2h~DNSno@%H0y6({z6zS(rO=F`9VAFKYd?6KUvI7UN9XUWp7Q%hgJI&u1R@{bRR zTefUj@Y-r&fcXCXue@@kb8aU+O<!H{=;ZQ<tyQMW=a+F!R`-2!`6qY5?wB4)<5@?& zr#<>yW%+&1=E^@Omv<Z&X6TVKowW0_-NLE>QQ>3#&*$yGzuS3s*_1M?wcoYl*YEpg z<vm?@@y3lWxu;JAW!mtw4X)niLXT3ndT31QNjbSBSTiJ4I6vDwSYwvwp*M=_HKw<n zi(B{Wbo@#U{lp&|5_g1(9yZCy$yu^+V{1UZ$kn$;rOzCmB$A`q`fQS?w5QKq78Q{c z1C>V)Rr02b-=4BkOHU>BMZ~vvmAatu*qsml$QK=+zdrTst<p2|jN2VULw)8LG;Z5g zmbddQ9|IGk{q(<I)Olo$raaXS`_TXU-_gwFa}Q-MpXX$?c5}r^Au;{PuG?>yEm<Pb ze|xgv+ODpmf6rSUPgLoAKJUNzYiY9w-}CD=3ez*ci@R?CwW~vyY&tcIvAXu;rj3_8 zMRHVJ7pe=nU#wY?Cw{V|=Mj_r-MhUNCgNRFdRKaDO!Bpnay=;0%^}jdC2?V8jf;?H z%sqx_nF%jFWAr3XZ!4_)qcS;jf{Kdgv8SIBUOZ}^sJFgtFZ({<qBlLs8rs@VHy)p- zFx4+OF76oX^ZCbR>;FpIT1(!0efa(N;=iTWKkQz;UQw*Oc4;QK33U3+q>Q)ccf{)X z+5Zj6a_?~nOu1!kRq^v_c;wzR-~EqogkJn*bg2xK$EFv$fZFc|6Xz!$_`O9248Do< zWmtk+iN+R-o`UQ3^AA8PhnkxY+chgkfhse;-#l<dJU@CRep?Bv`8?<`_D_E?L6Ju; z$k|}VUhj`f9vK#G+AeP<)qh#I^UbQ6e0+S>ma|p`&Y8dc?&nSyCT`BiyYKJhv=!`_ zUi$h~<mM{V^ERJlxW)DU94dTg{(H-vJoD-C|BTOBK4;hHVw&_rY`O~XpV=`Coe@+1 z+_|HF*@d0GeZAnu2p;cAf!~rZZZhAO=Fh})_`yMT`Dfd1=eb}1{e9h)+>P-({CzT! zr@Qs{9;kf&Um*1IgcM27NoA3sXq1sD^E-ClOK8=y!hijBC-%oz)OF{x^G*5dw8hWr zrAk)Ts)<YfD(wdOxmtCSigC`306(jjOJe&TXTLwH?mO!Ue|<%tas*hOag$E*y~^kB zit=A)zdz}3{Wki<r|WjJL2|!&Ht7^!i@bk->xTGEy4A8<mEF_CVnKmy@uo5-;lu>R z-6G$z^`lI$Hh<f~3DUtAZI~fm`}um@mOpj-H+x+Gl_dI3lT<#H6`sEEZ+ByY`Q@w9 zX+L*anS>_3*|6}3jU2<HPL+)*LZ>&C?J&G}@ZiCN4?owut&Xbh>KD^ZbIz9Ddr^Xa zzsckfD_?(=L${8(#r>}^)8A*_y=C2H*}jBXY7--R?q!tt&wdMP#fCrrvZYM<?n47J zGrj4@-uBx$mMJt`e|&6hriaj-&sR3H)YvsOG89kKQMG>X{LtlnuAYwn=9%3ExpMuH zmzi(XR2FR6&`>HpOTs)yBX0X_VgC8YHf=3!Xvw{KCjO^nW~{nQuTkn54YezM1y#`? z4_hAqY3us@`Q$mSf-6^;EB~!6*VNW}^mF_Dr)L)TD^2v8c<FM;6p@W(&cch^d5&%I ziJ9eg;Q8Il%fN|#tHq+Nvn>+7oH%p;`Mi=ta$AmoLg00?vCRuu626wFG}GtOojX3+ z+1hQ1DSfYZ`6*3Qkn4YMP@^Mu`(fqnZ5ws6mw)^+y~3t1HPU*^@|`<pK6~~|wk}Lz zuHR(8<uBj8QxogHc=__?!zI;KRUXSP&%D2DopAqgPqoR>G3k+F7kfX~?pin5Yw0$N ze2HVv`*M9PWd6nMxqW!s+cW8+Wo|Zd>T~^)Z=1==%9@y)r}yQ~GZ*-oo0q31!j&sn zuQX9%qQ{#JIosFe-`@7})hi_#zI?%O6RE#WZx3(Fby_Ge(c?*RYJ$WuztaX{-50N2 zYs;Kvof{s#eD_`>e+jmSQ#4M$bLpCrnD=?ty(i0xWk0ga{iw2Qr{>>t6+)Zmf3tWq z7ZgMp85s-q?wxz@UYwY2R7>WpC6_aI?b;QwIgM94eBF^vYkD?cF0JKm-&*j{DQKn0 zw%lY1wq5IzZ=1a=kvhHU$D7UPJKPq}Sk{>+vE*_l&*1|mXMLh-k2_lYI(t6%okvM* z`pr$LOM+IO*}3oauQ?v`g=6+qZ2Ym~?y>A&Ij=S^_MalI7jt4$>gkT0KLX2gZ!Za2 zse4Fuvgfn&^XGdWHt~&$ipt2zITN$Ja%Ro1m&<1?JDEPe)=fp|<c%x|wzqHJnwXd* zNVuu3-S_9)%^xS#=hvL;J9~PE{=R*mUI<ULlisFx*zVc6xu-8J^)~dK%*rj65GnTg z+1cd7ZM-Jt=J^-(#B?GWGH0!c+S;{k+cuv$tHahNeSLMc#YvIp@BxD!pWg<)!lyTN z98Fpiu~8{l?_!3@<h=R5wb$20ZS5+snDcXQsrBtW_qOE;&z(DWP2Aq9?hUn1MY&p6 ztY3eBS+9az)U)&R{dL5WPfk*en6}k*_uW0Zx%bZbTuym<YU+{4AAPKE-Fde)cJH3p z`yPi340O1;XYa_HVCGwLS!vp}jg95k%s1~dce-U#nR7BrsI4*e_K{0gyD~q%>Dt;7 zZ1pScq0Vi!h0;e#ncMfur~74_Un)=bnsnsN&CP+KqU*2Eu5>=GKEI}Ek;ac2J1Hrt zg57sz3Jx%`FfmqDS4VD2;cRqh2+(L*q`}hcxNFxg4L!YOTepgahIYCrm6Vh`DBE4Q zGv>y&-c_q2rny?k9D7=1So5Rc+WL6@hD92Z6K7bJYQ@IJu8G*#v~Hc=rcIkV+!kwe zIcbO}X=``y*<;hjEA6Hruwe7%$%4vm7p`7)wUJ9d+{U}(Zr-JrCVThpm1uL!%hSu- zZvD9C)TvVp8Ch9MB3!8~$xlv9)QR6WCqk!9#WP~s(RTT|j?_pNCdO;)<NY;6oGzQV z^+-7S`SG>3ww9EXT)2F>`TFan`}Wx-XZ!i_ZH(wiG4f1IR9w4u?U5uy6W`=7FD~jt zZRzk(af*$VwY9aKGJSe*czFB$_s1W9Ot@{fckkXO&z@bnchAp8?)dZ18?&xz*~sxv zojSFotc=NN&!^9yB`u3oK32%|A9q#}I%$!5*~Iw1;H_)7BYw4P*}i>x>FaBWkz#WF z?Aveq>WC%3y|wkkrk>-E6(@Qm+%}WzSAYEA`I(u`%QAPw=#|8#pPglTV$&SK@W^SN zDnc4vPAWo*Q@s|h(vs_MU$#u`PF}g1{Unu%e#;AY#_YJ8cdTFDzr4KM?T620mq3w_ z(6culeXW{loX)pN=ke#CMwRo;a;3T!DV#Q1yLK&)v{}#A?CWW_3=TB1%Xz2>E!?<K zFf{b#+qbGa3pejglmI0GY3V=_R>+FJ;AK9Ho{tXmuGPtSnUWD_mKs?nw!Kwge%7QD z->ZK7n~}(1v%g68@+z;1s-4?kOKWofh`b}W$VR&%GxE><rl)g^7PZaHmin-Q%e78l zJ~!j&`%62%9M~xG!)EtsRf`%<3){7KJ5E1cv~}y$OP7K|LQ}7-2;8!DYw9_3Q`6M8 zfK#VWYwGHr<tcpn<cUGqn+Pc>DUMdB8Ou7)KR^7mD0L1fD!1hd^RTU4xpLvAO+v1L z0V1upZbg0i^hrZgbK%B~hRR9|i`{xpS=?B+PA@AfOG8(8>B^Ow#%G>={wZNwRgyMi z)AHr*=g#@9TD{uX|J1H^!hG$L=6N!5{q1kw<al{|fBgM-%G9ZWAt5gBj)iai@|ADb z?%l@z-{tz-CruKH(Gy=8!nOYT=?#g8K7w-TzTa(&*?6UnJUZHa^6c5AOP8i{N3UMB zilf!3V(&el_4%K-nD{PUvZQ6xCL<NkMccQF_a8s}<KyF(FJGSIsdil)$i^$>l9{P_ zFk!-`O-83qpI*6sz4}zIg|DqvtqKYYJGOj&-KkSkwT+#tb8~Y~Z0foG`so2?ev$YS z_qyy9yN^G<vCY@lm-pt)n==#l+`AWd=wZP!b>pNX93rlYa{b0>XJ+&$<jhmQy=`LZ z%!$hGX>B)(ii%F0J9qBOv}1j;-r3pOPoF*o`8Ga&zU01;(5Z&W$8s)y>+0&-prft) z>tu?M=cE;D*Q$zjr=AMCUfRYl-?uEYLEy_m=XRsAHxbixqo=*J{l4_-_0PBVh}-7e zFu0RvzH{f!9Wi=V*4D;f?NUw%+{rU%a1RSNFwt+%h)R!iH(%&7X-A%dqG57@>LiuK z2(kICRT{iM7&qw5o;ufdj?JF7$!+1nzOQpQ+%-Q`&b)r7FEO&@*kqZIz%x4*{W&AB z<nX=j%a?EY{;077WkIVFjnmWhLHRT1rcqXQwlQDkl@)<szI+LYi0DX-)aaVD^Ji*g z+QBAPpIIiIywYYVb5tF|!o=kI+vm-b+q7wu0S|Nk@n)UVEX|G~p{}8!O$Qa?)=zJ0 zVtV!JRe(tAnl(Biu8P*y(hXf*Tw=OWE=Ds`uB-?&F)^7icW!TL<cd{Z3IYrXcXyR8 z3DSIacDB2#D{E<KsmG)v3mltg*w@>=ESYubQqY~e@@K&YlT=b=%I_CM#l^|h?Vo>j zb@=4z)29pi_aARQ{dCc~b$y2pIqiwlU$ttIkJ`yor%p}DR1jFOYE{>xM@iS##m?S% z^=Xk|>M0SYg#pW+Pn$pAzpl<sJAB=lBNKhp0!36mf3dIsSCf^MW%Tpg&zg$8Nw*#I z^YtSmBX`8;Wo2h)W@VlF(oth4KUv*B?c^j?nX(&+Dw925y?O=8H!D_XOjZ}*SAY8S zDZ`WJ&x0c)JC|j;C<&V7+?XJEa9>>c{0~o_K3$j@wM<T2KhCGD%<N#oga{qCxH!3! zDMF#4#(NjOd6T2!dFo5hua@kCO{`b0U0d|pYSuEtq9-0w($dCH?_Do*u*vyZv(G0w zNJRDXhmBQVvre5p&B?+vW0_}MoSfct?aT8_d{1{=d2q1VbNS_v(9n%#Z=-7L<TvR& z{{GvTKd`m6b>@e>?b5N=B~3B}UY5*iYHI39U^SUqGoL+lnx}+b+tbv~WwFX}zDsYs zKfHD0+^MNQcYd1Sc_uS!v5~}q)mkCXQ$Bv0^>s@6Ps!LB$2$+No_YPwIZ5UA4T>_U zA&z>r#+h+f3p=Z=gCbLX|EJCV9%%PF$MTceyo&uApgu%w&BMpnJ595%32?O<G40jg zm~fEkSg-W<vvL!g4~wgcbtifnbt$*pK4RqS)+1s1pujKFsz$MmPxjOVMdxoP&0qS@ zu_*MP{oug^1BW@5y6yUB_Gy5+0>9PzGT!Q?oo^G>R*-5{pWl*t`j>d#$D|wg{w>)5 zU-sQD?tef1GjdvZrOVE4tNfhs^_6b_+Bn|R)AK9eES;_(Blaz)mQP`7ll>pZ8>P?Z zZulv;c=`Oc|9{x4s@c<`<D<I8YVCY)w=JJ1v~Ah`N1UH`7Td?C#fvTDydKN`{SNc@ z`~0)tzD_<X6?ks<sdo88%KbHk(vCMi-blW1nYsS&>WtgkVKw_?|NVU*5dZ(^rK(q& zf%muRzS;j;@5ck?h@C>eHeX-2)b)<{-#gQvZ+QQJhyR`4uHA`OwK8&BcUfuZw?CiX z-p99MZR;VYhz$(Oe1*+_tO_+KTqMxxZ!h}1&zf)6?8H+dg6Zk%GL<Sn{wjDXy)(bZ zaJos@uVJR~(fjT)jPLg_v&*W;c)7FBsnXi>Yn8yXH#rr*a}(Qd>$V&<aQX9ci-)~^ z{GYfD3`~qW-kR<BS5@)9Rzs^v(%2=cks+qW@J_|z0*%e-hhJPglv%M?fa_rK`GXr0 z51q`tq3}k^-0#WPozEBSin<XRub;E)dz{5%o`(X{_1h;ZCtlN$unz0^$}WFk=ku=D zzQS$%;%4GvhdR}rRFqtTLtS_7`C}9kntMvQ;W+dCKg(83UZj-xdX}j{T93v48cUz~ zeDC*ZpR%%-zgOjb<>CazM?V&}ADUx%XxZj-LY3213TvME6zqJ^!2Dow|AP;QA3pAH z6}J7E5@>HH|L6SwjxQ;adOKY@4y}pYkSF`(Y3HYZ@5&dh^z1mcBJj~dW&8Le!o6Jv zv9XKxK6%=?;qtQ1Kj&wux~R<+<5!fGRa&#^(2tKFp3M#jR(|zp^Ldw_Yopa~9cg6m z`f&4R!Lyl*_Jyx+o1Nb#|3Bi$*JraA{R>;$<jg1dv+lX9#WRT?*Y~^JEiLP^@>FpM zeDM3e_{;sD`F!T_e16_t&Eg^#R~N}~Zf1IyjeaDP{SU??k00&hVtcsty2~zi8O5CX zf0cpz^`>Xk%gP@5*KaTOz4Ny2o9dUUfo)Hpe)#p;pmbG6`rf@tZ%>_Cf5_URhH=ik zYvGNVUDEkKiyppteqP+~{oCyi@BeQTj~6k2qTJshcdSeFkz2o;Ip?)&El!6TzkG9Y zZ7ul1F00b_|NehY!HOS=g7M|s3r_6PlQBJTki9$Edpg(im@u`xFZ}i*=MwH(W#o(Z zrN4=I7&A>zG;`mFrUH>kDs!&N|5KQAwEF!)Pj$|~m#<6zKDSqzr#@eVsp8GXLxRl( ze!jjR&KNK9NjoF($hdS>!J6P@2af$soierab*x@uzYh1oe@}!z*5|I(FuyI9I@7Pa z=FiXb7cMZIx6{7#<CwXN-L73NmuH!Ha=dJpKNRTBdHelt|05rNJU*29>`6y9pMA`e z|L3e*n`_<}2F_z;RqC(XFR*`he%s@I@x*^0`2+v++v^<3edH3j?DI3u_WPGMrS5(9 zgyVT!q~<5nsx2ozpP9L#U}3>E=k~6m?K&q;2|YEf*pR_JckZIKk<)%u-!xK`m|vsx zZ=Ox$lHhp#bt_j1J*~PD=;RWs7if04z1v7zSCrrH{T}68umAj1vYYPBasI=@L+4bz zUFL4z-o5SXIcueP%jXGY`p?z66f9EMo64Ekb=2%@$EHmW7Phy%5EtXJj@8@o!Rcec zhkMnJ4!+p=yv6stt@^u(DM2?<A{W`&|BHxGKdtmG_4E<j3zw8`1zYg&+iZ9#7r9TS z&#o$Xcgc;_g;i0zxjlvYN`4ePT#ys}#jD2dqsgC_%Rj8m?^NHvxL@qt#x*_`+ZHJm zI_t)0RIyyWs^oWC=-ib}N6zNlex!Nhv0&o!bE14zpHdz=oId4ZQ~T)JC8ar=R5;le zt~%7|ve?N+)Yal~f`Eyy&0M+qJq2Q&EgSYPak21NA8zqD@$iFBrysUSw=AxGZ<~1k z*wWuTQYtcTsY?rz?B;vOw;b+qIbu4oV?*S$R^@KDR*4;Vom4h&c9s0fD|s|&QH+<j ztKFteW=lDpN*uqGJSx06yTiq$CixhLdi9fui}I|jS|Wb@UBu(oC-QU6x_ctWOkC$4 zee7gXT)c2c#1}h%yT~Pb%hvA5dlT`HAv&t%#gpgV?A^Pp0>gj)T=b`?*mak}sb_n? zw@lX6746%rzyIP2jnAKoCi=zyW!SQ{Gx6x=b3(aE-*OZ)6moXFF`D@8@AvLspQ~Ie zLPZzlN;p0E|3zI<Y?<aM<*7nHx!KIWO6YoX{JWWc_-=XkukNER(#F1uD^^a~v2It? zlvLMN0g2GNQ^HRReVyacac^~MXR%zr#`l|>UEg!K{IvhQ#$*3_8#Z2{)aX#vLr0Pp z)oPqt7RYf~<mctm!28|e-T#mG2!7<3R$Hg9C&u*db8daay~Op0B0ufxep7O?+C(dl zYq~ej`4gLVXf`<(PL^ydP@34WBk}d?)`+jXg(jw)?zivi=IIES7o{)nSiQ(eW^?Yt z1G8owx%^ap{sGbOj{8fO9x`-MI@DQG(lOh@Jp6`Of48)agvef|>E0F@`{P@fKbBkQ z$aLS=uPVyhzTxDimfD{`XII6&efucJO7{&9i_4vxH)mhsYH#J;raP~OxzYEKFkknE zS!yylMw*9Oos`xr>ZqTly3Tv)5$A?wokeHQiaz~vr?}vh=An!EbKQzJZ&<s=r=#Zn z&V74!#T?QM3(GszzK;9h`ICZt>-NQ2+<2DuP~kU=#F782!@J{7=GQ4-TCql?^5ahz z+3#OEYNk%@EXv3b_%?ld_ourX9B<qz-@C5+11sz7S9<2*GOwkhR<FEiq7xmY^lI7p zncKJLpGuw|kU2|Zbwa^qfuzWr%i0$oa!QQWQhn6u`}OWMwVdp1;fJ<zihFL}oGrKP z+WPw;=OZI$-<on=`_j92Vo&deuivE8XKvnYbmNDa=&s$aR?Tdj(zSLU3#Lz1J$2Z? z<)-JPj@|F?y?!P1vi-2qyGcSH4T2*yPAy!|S6X|y_U82S`i$u(fA`(Is`|b!<E>Kl zUAwg@L0=YSWgVGw`k#-H=A4qytMfeVg#<rGBp>4tEV`jz=#qWh;`f$s<-f$lEIKyb z2yS9s#BPv$Y@YZ1gAcQNHVY)@AK7+P;Ow*c0WYk#Eq-l&eAAH)R~<I4(YM=n|GvNd zm#2lVzx;Z(mQCoo_|{bSZ#mqz#SVM5eSCVZHD})Uv;DPK=U<lakj>*hd?RF9{1Vy2 z2X24-_NdU#^V8M?f@^JCbGxsWcu((IdaPFXyh51q-haQA9c58C_94Ee@OGi<<RqiI z;&=Pw*T~3p*uLMZ{%r5AUBBel^=~uVD6nLy>zaM9`M=-S|FrMxyw$4SW>2@~FTJ-e zAu{P}T>XaJjp8qErn^eM>8bpD<WcMH_hPFVeqSivC{!3e)6{zlr@-e)wcSE;brlZ^ zZ*GfNY8Ak<xc+IHMAG>O*UrpRJ#@ch@{H!YHRr=>_ui=5s4FFX^w5&Ek$a=IbpE@- z-SP9_Ok?}{Kl^@{y>&d7xc-o&+@07z_SNqtQ^Jd6GwRO&{{Cub)ziJqT%j9yZ{OSK zxym#rXpzMwk68~pq}tL}TwG^XW~L^x`_|mpw@2D!+?VL6UhK#*yIsw|8||=gRlvRK z_jf<vyZd)yg~441b7_`cjGyWRIT-ZcpRK-h$Hv_F{K?{<n>O?m?L4CP{<1&!<cC*7 zH!A+SQ=H^*YG(TND;>T6?#2DMH2p~0rxP6pYa-&r?9|fFah%?eK3~*p?S_CK#*H_0 z>OcE_Y}y@jsA$bf&VQfuj}}GN?K`2K&M;x}>MbD=M@2<BwfENle}DA7{jZ6jf@TJf zwalTW+ysXo`{&r{nw_oxd)-w|T(9HlNn!PtO@F%g3wWnIKiB!XtE;8-?)!i10=n#f zP1NYVtH(C!^75nq&aeN&b>({ZrZ@NXr`?LH4duDh&ewVHM3$(X8&_+<w2Lb=>WepP zl<VzX?tbU{A?`yle-E)HimkueWo1+7^v3@0MfupxX{Tp8PoLgh?d{!~*l<zfRY6_c z4~?ZkO6QNui=R6EUYxn8cJGAi2?FP{GX&nwILo#9lWp~p1+@<vG7i7Zop}A>;YDxN z)gIjcYkhH<uI`~3Po7S1J-Pk9{u;}EdGXXOQAZvAS?^cA_3di7t1MgdBK^>CZgZ~5 zo+mEd(fM`%SlfmPZ(a-Ad4K-A$UY>Lv$gs`gTbqxpY6r#0%T>K7|l#N>gG;Y|MmL8 zf{JV0`W-g&tNkQ6a`U^*YJVhN)O-9`>Hb>Xi*4$D9o6+er@P8NS;J^78TfCbVc@&R z$6f0z|8Ll}E4wTEecVO!wszOK^X+t}wG_+ON3GSUK4-pqjgQUa_5Zx4EZ!Xa<>mRh zuqm2SqNUevXuK*)cAjy*zn^>YgiS^lzu(P!sI2jMrQ-Q5@5IiYO<M5#()1&zCwavh ztM<7ZQF!pNWBQ^sJ{mKgr5SE`s<Y_YwIkP`*Z(`8bik&>gGbE%M`J+Nbp87kT&?%@ z+5YzOE{yn7_wka|+@uLV-lVrOS(kY5_*kCS-yOT>Pdgtc>*cGeac^!#EsU67S-oRI z3v4Zb+mo-8=X1CgzMCU4Wqw^0kAcD`uca+#zJ5KV`0e(6G3IYqrf59B?BD%7evihP zBhu2XYx4K1zFM-_S)*XC9}k~p@bm5Wgesp;aj4rjVdLgto*lBXi}I|kTZ41WwC8=? zx}Gz8!&Xy6>DX9N<`myvi3jyx!(F9g`=fNv9Dn}YHQI8nlccXNXX|(G{VMBr$}J5# zF?;hd>#C3wbIx)#_hf`v9RK#U^Y!*^E|t@!wJiGcD*WhIzV-mGolg&54ZX-87QX&# zZ+_k9SxYnCF}p1l+84BNLco>Nrx(2m4tA1!_Oz4HQck?S{_pEY&Z_CHJGZK)l^^ft zcK_JSe$@Tg^!+*_&ki&M+}XR=sm;UX%ijBcV=v0zs|~*rTE2b4?+1<-ub-PI`qs`` zd*1Kf{ElBW9~?g({QBqfqCb|~o6pzBeL484=wqNTU$@Qj<*xBLSwer6g#@q9u~Pk% zn=hXB!`pk2eeJtqr-@-99ITSPUFjJni{gI$a@oIrrC{dH{+;V<eKoG91f3{)H)qA+ zn~@*?+5BE}BK}#hYgkly_xoD^8Lz&5<(&LVJWfD=+esC+=?fQTGq+#VV0)Nf7rbXe z-1>@xU#cd4<NvSVv!K__aDlvyM%=Dr$Fl!fMXlXoS3W;Xo9)Nu^rPWfl{-B)N35H< zO`7MC_x0zy3zr4P>ay*Bm-jL0b;+aihxxnr%$~jer|VN4<F{po9I8S|2kQS-7IL|# zF0Cj_Tv(yk@jJdY^u*Gu_x9NM+bF(Tw=s|>MXY;<tOQTehf_0e*MHmW<hko^(y|GY zw=Q!#Ged~e@WcL3T_<j*2)#Ue)=BeO&8&6nowr8)$u;ZV!_Dm~+10g9Q)g?`nU;Uw z@{h6~+Wnr(bxBw^<G%xpim%tjUO#iLI8|FiK%T*Feudk)`I&WbXC#Ww8_awV|IbyU z?PH-KL;cUwPMP6hT{T75-`&@LwPD}CTb<%;%^8=sng+K0ti1UB-_Q9+8}hbxRTWsc z%zl4c{a3Dc_lo?fUN*~Dy^4~3@@mB*rzeYpIyXhFO;TfV+Bw%k@k#ma)=Ov7T<znc zcVFx0mlb+?f1~q>37<D#dg(Iv*{S5MT~;!Zg5TX1U;lIc+gst<C+_yUzI~iv9sA^x zs^Q~vUuAd4Ug-|go);WYaQ5Kc6roJL=_meQ4R@8-(%kvYeYI$**5{Q<v-jLrlh6D# z@Ai`Ll}AobkiJkf`?6H;k42|{E|1w?xb|X9@qyOtebGC6Q(7NI-P5|-D}CPU>DKzy zA=m%(h;(IV?%Y!x|7B*6$LWP3anZlSS04Gg^LLP@;(V3Z)9Tan*Y#LdZn>3hd@#mt zXZ56$*+x(QEGT+<^5nFW9e<2wO22;a%jj9k*|hb%4<@P9oxhrY?xxA~?M{kmTF%ao zw14gYGd=rjO|9+IC+DUrs%NjWD@whP<@#^u^JgiZYU@u<`E7eW?)vFz-lwn5j;ejT zJ;wU^rLDL4x2<$4)II;*{{63A7c!3QZ214|K8Nar$?DVN-`(H&ZSTyO_v`Q9$=~^H zXPns5Pf_#Ff888&&;0b`zi+E*qt@{jpFe-Ka^3xX@$crG*=h9jQ{c*VPe1>&TNKjO zKPNn1R9?irpR4u9zwZy0%lM~E{?70I?eZ?x{RVYWM)Lh7Q98dXZ61055og^We<o(# ze~*bfC-(9hI_qlh{`mM~vXb^%korjze_E`#n)LIzc<-G+FQe_xyq;vvtQP)R{5o#I z{`fblCr_L>aiT`!lh5ls!Oj@#FwMDQ(|p<aI()0vhvyiaKhv?dwUIGVpx{YI#B_NH zf!SA-m6K*FiKjWaxw$<Pm#I|Q6TN0#*V#w!YuqEEZ9n%E2>32<y&B|xe5-TB-MqxV zUz_DScpu!|-5MHYps{9NTl>*`BO@cD{SQu@ZZ7Y>7x(b`=DoT;6JEb+Idmyw-P}98 zNovck#&O@AxcQKlzIf)+rH2;1tg6?Ml$4wqAMj-6wY!f_2tItirFwe=lgaGX%a70W z1f=b}%(NxS@bat~4eM)MBTAn#DYiKsx}-f(pe`yjbbi^&l$4YdyU>)SrQ1(fs>J!% z?)|{4r6F*-vFdMcrls9k;Zvz8DJky~Q<i@9TolwP%nMSVlE+=?@9hTi<vz!-D3F_t zzVmLnG-=|*i4%9`Px!v&oshHiZJ!EebKlilZ)be6uutp+X?$0ovb1!1Mr_REZtJ|f zMgKmX*s^8|NFtB9vhsu8!XT{zN!}g#pWI6)3vc`XrP_W;aYjpo&B6b_rq{dvsa1Rt zZob{(YTeKDNiTmsR`<M{_o52q`D%vBWu^TSe3rhDkaAmmQGmxiA}0EIPP#d(ANxz6 zwySG%b=;KK&(D5%<6T;ub@jYimxK;&l<<BnEpun<<f~_O)24-2r2MzL#m06q)5K;^ zz5a45z2G_X&$nGa{qdUFJc}<3xy;Qf!I@!ZW<RGcmwR5~u70tiDZcWP;TNmB%VT9h z0buSrFY~UlM2S_<OOxEc%pudKEC|uk)csJf>8;UZ?rxjP7mWLUAG;lKR_)%df{DKK z=ZpK#O)Myyb>6<Dr@NN<My}bVnI`GGcNt2%wuHuOxU4*Wxbs?>h=#|~%X{k9wWeqt z{cy$PUqHvtsiF6>cAj|gMyFPI^86xSP!hc(6`6Tg*~8;X_>|2Lzb?GE!t(yr!ymrz zoDAV=_G|ZA`NX{b<>oD4c>^AuJf3_0@r!qAI%>*nd;5IU4)@=)^s|ssp6QinJo{pn z>717@l2Xe0Qmk5Aj$FKZ_Ro*IlVxsip1tW1)1{d_xBoG0O<j6r`t;zi2S2y02B-3A zCr&qi=ZOD%XtP9#mE5h}?LKDReybC6v!%OFc0?^bmU1EZLD9r>OAIA>u1xPXX?1G6 znek+Ge8sc~8^(sP)sD+APMW$&LxgMF9=kJY!dX+hLafdjAMZ;rl&XC7L9uBf$I^K< zvtDO+9u*eZ6$AIKYhdQmFPYqh=92RAjw^%ieymBJXyCW|@3fced;B&_b>1~On{4ty z+j{l;9X|HFm%F`h=%mFIu|!MG-0h_zq_{d@(WK;ucc<j2IoJL@*Izq7W_Ed}{<|L~ zQ!cp&#zuX*C=SZ`cNU+hj{44VGNkLW?A$G1zDzoqmhW*oZSxtu^#(gPocQwSlJ4gj zkx|dya<64k7EGHqZQ_#tc`nN@Wu7Z7oqR4uV*c#(tiqSh@1rB4m4&)DKK;J=;n&)f ze=~EYwO;+&zvtawA3Yr<PoeDFw|_J(od3(tbJC2Mh&`!QR+AG8-(LH4=heSCHVi@r z`#1dxKK-R|=8X7+s>03^wc^v+DxOIRNt3omM{%|smY;S1(JiZwEfH36cW<TT<jqUb za{YZkp*i@ne8&5eKacYNdB)4~k+qp&O@8&vxLu|8e@t$C`FZop&xok|Keo6|+<AJ1 zj@fVd`ddzSeD{6q{onCOtuD}B`(=pG;)4apKmC4w{r;j&J330N4qy7kwp_n_qK~TO z&1;T<`({5}Df#c=)awOLpB64$&fkCdoVB?AMMDdp*h)#QrIYgae-LV)E&WnPN_ASt zWWV%^$1&WldFE-08^1Lw-m|H1tZ8rlxYM%cpn$CN;W=6R&jh>keLP&=ciGtL;Ey{t za?6{=?_2wt&3^i0X&H}|tX{R;@#xzdqjk=#Uu(R7m)GwD3bn$MOZs~fO=ng-f27(p z(V+Xa^q#v#f_wdro7ewHHro?-Z|99;_kLNGMDa4{+U{Kunk5!?z2di%wz6^Y6w!(w zA3KBRynXZNBJ=N;5;AHty@Fp9T{5>jxH|pZ!%fdG8X6qgxlS(To6Wu4+~mWr4~z2@ zZQMTp`uS}e9)1l9jX5LzJUZgu4VR@sA3v?!d_<UY-{(`WQ&c-Q&%IkA!xvZep6B!G z)fQ{Q;w%cg&P@yq;Zl9RtE%Ak+dU<(c*LuI7u^0_@$*Y$i4<@Bx4-g9+oLRNcTQH? zK0DlR{?hWArn#Y^M}#>4{rtLp$Bo<mMsp7>xNN+CSKIGXMW2@bV?5)gtbBR%mT%uK zTiP5ta74svE!%Y4e))aXO%q>Awk=y$cw^0;%7025Q<^Tz&P_3r?7EZpOI_`y^!yZm zXW8V<pTln@btrA04GLeSsVRA>Q!mTT_0iQUs?1>Nbvyj(nb`B))drG0e{O!S_c;DQ z;3pqDs62dh@_35Dhj9CUoSRQ;PZ1R<*tU80!<Uk0+?Y>>aP7W&%HMCFd-Q*Wv!$kc ze%#AsQ(yi<PWJHB>Bnb3*EiU^#YaQvsk*wKpzo2Fl9K6FnVmUir?b<~P4-X)m64Sh zGsOMoBprUOI{9pu*@np0L+8?7$j(lvOP$(X`*+9N$~_gIOg5j^4)5)COHbcvW8(Dv zgv7~^uEvv@adx$04f{40>Zl3p&$BtZ>$<ydCMQ?xqrScC?Ri&*aCt6ts1!doe?Gg4 z=cDNRzrG#c=N}fe{p8%RsO8qXDqfv%yqEntAuY4>S69(Jn|j8%VW;n$k~&z>^63y0 zoBHyLnWjDG&OPL1$y~EiMan<mMcKlu85Z}iHXENWJ9>UK`&zftcTQ>jF1xb%<>$>? zHg=i|B;;n#jxcJxJ<q-KxU+90=k#{B08LSw9p(JW#>PLK6|e1$Q`#so_wZtyZwKn! z($h7|c5@z2a!E3r=x=lI;@z`b`1uSC&HIhdw_Q$4PR!-yEVz+lQ~E>U_3hglQ@PTn zg=y&PJXkv|Eascdv+%HwY)uj+QEckVEH>@#Y`tpQ_a-kXFZFAeVAtfg4h_2X4KtUj zZew<|@na9}_WsiAYhbwFK~1}`AY55{cJ!Ov70=H+)vG#wY-VJX+v<x3oA>yXdU96H z?Gy61Yn~jeA;LAqi*=vFgo7(H>wZpbmzW=)U@f5_(rL7P&!J@gH|bTGGk<jzF)12$ z>wbK4`O@WXzs0GAwaoDb9t%%*o=i}<pQt|jY|@3-Gv~xFvABQs%_Xj_sY@B=WV~Lm z=7974A1dA1*%3Z!WmiKkTALkw_bbY(-911{#HR3v!ra5kYx1ivuDEh$-I`0LR>vOm zzj+>XpP_x0^voI2OR7^^KF97=3Caw5Y0^A-@)K*BFMYlro-UuCl9kx$&iCfAQ@;IG zRn;}Q`O2O`t$O03uB}_XeOr7vD>CMGf`6^-UFBq(!WWEwr7_P+ey7$nDokQwn=6(+ zueZMHt*_HWjnJb<bAHw2RMft?fAheZPh5PndxK@C|2$>vZ)jxPef*_EBU8S?iBr$i ztXHpoAtm=TAXu5zPn}sf_|1w{37NIcOM88@yu1Qdhwiz2sY_qv$&saHn<ll`OSmn+ zI^k^EOBuP;%4Ff?XWLFDJP7*Fu+B!BZ#Hkk=exEnhXsRPnv|`cy7Q^%w|6V{uMGZw z*Ci}U{@hzF-JNFd1y^}@TNdx^w&`Y_8r6F=W5KR9Q=F!EFPo*cX_AZD?4_G_bkwxZ z-TSq4Mlai!DA`C&Z?)M=*VZ>Y+Z7dNwta%i3O&tb2c9ljxs9!1y5HPm(i{_}s)U)D zzm$}9p476_w!<&QNW$R77LQ3SH#3&3S-_AUC)Zxq$$L4dzy0&wy(RrUL9b38Pcuut z@N!**kyCLj@7`qLN0A2=Ui!?^o!|fe-}(E?*KBCGwaG{>L!?r5vZmg*FBARJH_SZy zVoTH=KI`f2?l<^4mTG9uUYcL?>6K3Q-Pfwxo-K<5-O`?Ih}IE#{(N)&bG|cf%x-(< zeO;T&roL>2rtY#Mlh5yy<rUd6Cqzut(8Ba++x6r9_iP<Cq*P~mO-$dm;A+MP3z;on zz6kZXXliRH%sn?@s>&@kHqMqqdrJQ?X-CgixtyuAQKD5(-1VnkSy*V2;mixKOHwvR zn$^~U8e|r0!h&9!q+9RyTrx=~zhkNPR<DyUPtQFfR9HAatov$?nz`Tv70$h3-Ja{+ z8#nOjmh3)Je#3IhYQd#JC-=$n?y27B8`1Tu<jRz(0pW38u8E4iTTM%Pdlm()%y=uU zFwZB+Oe%17$eu6vGHV(cPKI!KPU<-JSY*c>kzI34u6EQ$#A~=bzreBd=g*L-B9|kA zTQ8@%PFhf0F(v;0oAe)t@BiZU+g6&eIby>MABitj%fzNx+`sE=Gx3SKy8mRKr2(2# z&*<oG+_ty%X2OvoSH6b%b8LLACM!-pYh-4A{=*j@4Tbv;6H4;>_VRuW5fu*(jq#}r zWK?Tzyu`#GwYKft!$7VWzkB;Gc$vtl&po*yNb4h8bBLJe#>K0c`Y(5$&2d|N?Ex=K z=aIZT3Dx3y#c2L}YVxVJKME(Rbl!X_I>k#>ZaK5(qyP<(Gwas{hQ_#9h&eM#e630g z4_m3BqaxM6_<ClbhKNLo)t`k1r=@3yh>8n(s~EicdS>mqpvagOzr~5Qx4li|j%RKb z>^thQ{PK=Bl_{Gd&#*Dya}a2CYCO3>eWK6Ashc8t)Rs-3rcttU!;GG!`rK63wQkN6 zZ~JNp?OgRHsZ%Ao&faWuXNi@w&cp*#(+|sY33IrgNHe}Nb$YCA;bD2Mjc@rM6k2(t zZ_=2$NQOK6wZvB|t~q{(E=p`Zt^J}jO2$mPF@UB0?5R%gw_o~tKgZWUzc0kmesPtl z1aB3Om8^7}{K}G9pAIo?G+7byXv57Jk#Wm5t(f4uf4+}echJHES!RpFG(FReX7I2* z3ky5Bc}C#sker{)A)?}jyEk<m&2U*AxLKCt(UwThWtTEcv&{C`X?1sZ97)Q!lC?#O zcV^DCm94H*yi||=%-i;d(T2}j*S5Ci-@;^<$A#0(%|2SlEZLm2!SqFm%j3dNI%3<H z8AZ5Q#THM@(D8FSm9#x#Mr72n#LY?DqZn^|`PtH=dekM!u%=N!^l0lD9o@&LHZKg( zy7`H{;MSTMJZy);r<9n?JCL|}(pj%1mo!aYWk0<T_fq{~#+0r{O56U{C3Ujo?UrTb z5?ZN}*37sx=;W^J-8T~yrk+f=^4e2n@|yf=LuuX=qsTo672fT!*)*voYU!>=`xYt* zbwAz^85wmy!CK%z?s?^@=N5#m)F`kF)SR00oB4)L+M$aY(RKEztgI@NG)tm*Cq~Q( zv1&Ee@89`Uv?NM5Z850UZM)tcxL#eRH|Ry##FHtW%O+_|_1YrE+vfjai}=l|4~KWg zzIKevysK6om3gwpCg`OJSL>r!;lKYnymNMWCe9q0S!=QB<nA;2BC~!MC`=HY)^p~3 z-=5{F%F4>h#rGAobtOR^#ouke^LwA#Db77RscQb@0>0j$&M33ysS_to{CVSq*K56x z-))s6wnptZY1U>x?}5GTg)b+$K}HnMSJqy;yCrPt6Z2WG^Dacb%n{ofbkhDyPtAj0 z*Y4Fl3k%mQ+Fg<If8T5?m0wMchb~Gi4L{U=X6>4!?NJ+Mo;@P$xh0DC)cm5&_r-aH zdR#R1b#^@bUZK?Jw|Z(X8>oNnnX>dNr{S)rk8jU){?nf>w<oj8J750)L+|q+PtDwX z<4jtJmZ)5N^U<%oWnrNY_*-8}$*E2j{pT_>r|q=!VUw_ML5|j+|7O4c5PiPx-Kxc@ z6K@~A^h=Fzc0kr-ZtsdYd{?wYU*Eoc=;M~{^N;h}7Cc?jtLepU^XIF7+_Um|zr&9_ z;uPWf*$^u!IkTEOGV`vliiPoZm(9nI*4x!h{Qvr5^Y%HMu8#}j>`L3Fp4BZ22`N}v zKOx2H=tkS!KX*@$Qx)nCesuD<JlDlr*ZmEIj>>a=d@COJ#J=|F=>-igT1T%u5}Mxb zrctufK&nJ%&ALQ0smwL&9&O$H{A7x8h?wX^ujL<En?c33*3_<7mxTJ_v)p$TMIGz( zeybtsRrmVl`M^gf|F>xSfd(9&ow&wOF50>8Ywo-s2c>HY-9_8I^JGPD<QROInm+GY z|GsabYtn>wzs|n6;>w#<E0qNL76h(dp{u>OYSDph_xn{mEpp5bUDPOB-I`-|`oWVa z7Dr<k`Ayy(Niv$~v-Cz}XysEDc73m<LW>>!D+3kvs^z5P^sQHG9pw~M6K43Az|noO z!%MYX5EN4EmCH)a12uj$JD-)&I`=%`Vte~W`)%dsY;*ahdU@_U+~~M`@wz=zwns(% ze4B26{M9wHVr^|u!=r84GR>my!+ze}ToUu<JuC<oUYIfEQWMjwQ>Qgbb{9T>T9^^8 z9M#)a9<85f^y25-=lc#k`NPCMTk55h<k7^<AKCX8PAS)qdvx+J`}%p7KW;Gp_FNKV zv0lbW3zXXR733e6%&xg&=y(5>%#tfv`!a9UC>(h&pR@0=(cP}#x6>tO&U?C2nf+#9 z=+92uaJOgTl0PMu^Sj$se-NvQ^3tB;Bj}})KP&BGreS=irmC{?=g*yMw%E!1d~>jx zXLH!+jUvHXx=D(fQ@y@Kz2(iE>BF`(sPZb0ZL#X2w_o?y%3P8xTvYZh-*eK5w59X2 z{%e)5ZTVs>8>a0k)S1G?$vHQyI+$71bJ7W~OIIyCuK%}J|LuSJ?7I5;fAZh|MNd4L z5^&e;ZpwO##qsaoP4HVDxH3dO<9Uu5H`mdtRl9E*7eAf6Wd7Q<DJkz%pD0Y&esV4! z)6f5ZKYx#miB7-#`f!rTrk9^LKm9)WT*{Akuk(YWUL+>w%Fe!d<oo@a_Jc1ovreCy z5fgDF$7I9H&zm=FYrC7}xHM$b!>^12-YOAM_Z0;Al8t9e%%1&x>GyL53kuooYkphE zO`p7Rrlp#=`1+P(2Ag;6JNW9EnAqZp2`XMHV#?Dz4EFA5Q91bWn%TX57fzj9rIi*Q zc4BixL_}=z>F382Hw$^Ibf`~uSrjO=QslDt=|{7+nr{13CljW9(4)ov-|YSAr{AYn zc)1+&U23eeX5GTe8J<gxOL+JU4GddP=PA!VYqWQZ&;1)LRcoj1ul*?c>eT6(Q4xpI z%r<Y@dGgmb@#SZaU3nz5&_iT#-1#4WnB4Zxd%y3W7~5RF_OqvUT|d3-`tfP^&+lG4 zz2H_3i&EkhEz!%~r<GWG9QivM>yzpl#r@}{rI)HM-drs4waTov&aB36i<Id>j}{lB zlV>g&Rn46S>c?+gx)fBF8PATmc|&DZN3x;R%*d!?;yeq(R=N}%4&YeobnwO-8}HZB zF>-PT^EM`!NuBf(s{fIGf61N|0^9HQnG5WB)m^@7v2eYCi-M5j%8(C_AHQE1xO(F( z-yC)(oi*zwdM&rCTiGkT_U)DMDI0fe>pPq_x%Pvd;uD1l^5@>NHBOn%o<G@IcGi>s ze|EnQ2#oLu^%RtCR(`W?{nIl~_4v$9jjXKu9oHXD+`1q{i_>+{iYZ<>V#XU?no6wB z9=c^^x^(FjanTPS_U)~C{ZriX#+J#v>-+l-ChDjuTd&sYJofmDzt5-o|Hs!GZ{6YY z{)WZuIC+f&NhS*~XT6Z0zhu{zmYVjt2Ulit&G9?M#XVzA{DLh9oE2o!a`NP6-|Vs0 z@3&dqy6vB1*XPfb?>@Q*Xifz+M>$$Omjq3z_~e;x^rfdS_(|Evqv~>pQw%=T|M_}< z<MM@ao|9%o#iac2V^i@=sx0Q-8`ga^MP-`Dgp(;Z0wX)^MIN1<)?M?|*uQAo=GpGw z-lykQbI%R)zWzZ&)YUa)y4dCo+s+-iW79sXT#%#Hb7}CJ>ROYqP{s{A_Vop>Uw-3l zQbv{A8J8<rSzg`|ckd{P`G2tg`)t44!hj3*hMw<lSS&U!{&OpRUQ%9atMB~&rC)vd z%-<hMF)-M<p~G#d)6yV8f3=AF-$3=3gzt(FFSljsKYvZ%-*Gq#6ym$wkKec*;9u%# zC|>>hVwTB{x0Nl64b5up9-UPAe>(p!o42&|p1N;L3Lkg2_kCP`|F5`R@fU;re{LL} zv**gWE02V%dfNg_xEw+Y1y7bpO+I+w#220RS<;|9TvR968|Az2^0{}rqWIor?MeO{ z_Uzh;)6Med-s<t6n$Pf^!))_ReVcC_?XzYT+*l)XV`p>o?y^g!Mqc|4`zeSh&GSgQ z(kaQn#d=zL_K`=NJyp!Edgkr3q&klZGb}OA{Ik&DX3jL*uUkVzL^o~PdGcPH)tfMG zp@7JkBOk8tM6DHDZ||Wr(`EhDpum_D&*iP$yvy|`M$CCsWB#}}Nll>3El_K!$j;cD zpMREI$~4I`wO*xlBQn&{L~i+ow@I0`%-uI#)F!9??_)FDV^<aub|E0p&qR)W!M;UJ z^?%O<|G9P9KPWn^D`;g(d9CcpkS-UallOjAl}PcPobo|)GQ;FJf18<$PP|P^&7OR8 zYiZ3vfzqd`CfCC@Z`$cuTdC>#GcU}1d&iL^iLY!qX~xykuOjZ>JC<e^92ny9%j?5w z-u3)*-J0E&J}daF$5Zw9YS~A2=Qk@v0t>{iU7HadnR;4&!4c&}zub}wnI0OrH8-+< zf9KZN#I$^}gN2jM!~+X12Zp^^c;&I8Os}Eg{sX6usol((=Aq+eA*DRery!+V_?(S2 zd%0<n@$3l=-FyGuIHPuL``#O8)a<@rFqErJ_<wcgB&UTB7S>i@%rc4Sag($E!En%H zO6N~jvFq16)rDS^Mm@at;IoqFg20o^E6)7w-D6WR`_9X!2TRva-*(V3ZQ8Vz>opc1 zc$!pE)iyUYbjp+G!GSR?<`OCQ`>Jxpj9LBIkAHiYn3p>B*)1uV%CN4_cVBFYim6l* zdh_U()!EXmH`a>HF_ZpXZdR~v_4FWryRT1ES4{B=@lyR=cI9$R_~ARJwAiJ}lT2r> z(9~6&>9=|P!oFRfijoQibGNP9(&98-c&gXQd%vu<{bA%YHBB;-_+TM>W38AE8?)5b zS#v|DitM}_^XBdIo9=Qh>n}env?_>LEAhoD#EVtb)wLl)>&E_K_V-)M3wBhBTd&s2 zd@G$$9xKZ>moHw!CAn0TU8-DQ_og1sq_T+cFt3HtEj{aX^d7~8^A~Hcu6gVIzw7AM z(pj&v3|^J=_?-W=R9#+OsP_>!Tji@0ie|NTue45Ge7)t(s+DTzlMXJpY`Akn$Jv}^ zn|5?uyH_{IOnR!TtIMOpvXHQVs0WGZp{%jW$`vwvS*N{Emfr|mebwS~PRLY|jj|j? z3F*vXn`Z{~vrmYKh+V#I&y>SwcfXL3S+;7)3}@fn7L_ZTKP_V7it+PdV^;l{x96b1 z{y*mN=cE`I6u@@`yl@T?5uN0-)Z)$_Z<keUmuBizrWqfdSF=URv^7us=)4*SCQh!q zdRgA53vR5@5aIe}Y9heVZh7NM$49HBI>p~7OlP;3sjU1Uc1Qnovr&0lgwnyI_v*B| zxmIdw?|oadr%^#{^2dEVW}3zM3i|wY7Ms2<=;2AY@Ur67hlBGi<=f9zu`dBlFkL?J zISkUAXN$}PjntpGV}8QR8#*6#@A5A1J=R+f%&{-IeBx+onDPAey8oZFP6FvXKXK}{ z*d$AlXRq0%@|SJSliFz^)i3O?axru33?B1YD$o0DF1_9&zvKOK)tO$4!!%PrM@vf1 z{4G_<^1FpYJ=n(Hq*LYYox>0O_kVZxi^+O?zW#&rwQbw-JtnJk9{u{Y|LdN|YjeZT zZ(^?adM2{!*s+(=^MCv}bo#`J6L*wP7_Z&!V=?p4ionnRW8SFU&uECA^Lts?YKt3N zx_#pt8aqAreSIvxQd?hHfG;>c@Z7CyX3uw5bF?n5`FQep#nUg54|R5}p7?QRWlxo@ zYo53;cehM#-lJCG_YVuLGNdJryyg#jbaHum2~WL-&-)t|=k5Loyx$U+lu{+O`Qm}g z?tF#YHn(qGtNZWC_j>+jzweyar}XsnoN-q^zvZ3MB$bct?_(d;Ti-pm$NtEB*&C&o zpE@<9Xu00M!E*eYN$`uZ!kqVcRc^;8sB|tosrhH2z|S)4#)277dwt)CanH9bnsIGk z-L-AoA|hg)*IyOta`9Mp`OUiZi?<wTzM7MkmpU~<$+0p~v0D1oM^@)0Mwx#O3W&P4 z+EgXjub*pszPR7sDb({LudxZJk5<hYnR(Y$gp2k6-;ak~f;0a;dYSy<%67Y%ix0ef zGF{H@*uS~F8CRrws%+<5R!L0ta;;5e4V&CqVA6JRf&22S54c+^{>E@uzkaPzuv6pX zlgX!23L<h_lmx#-=}vENn>i!;K$c<hg_i}la(vF{KiCje`S6G47Af9JG2^Pa(-!ZZ zUHSJ-W!3RxPlFGnrlh=!eDd_*?iLkCt;q+MgnoYRFVCt_smgclY}wX*|5nHE`Srf- zRFRa{>Gg5dd$}eyxEOh!e_=7xr>%Ln)Xz)7{xN%>{k>lQ?O?L`pZ^Yz`)0?P@7{B$ z?Yg_OD{ItNnFT>^ZqM$yghiEis`XEP-o89<-n92WR(`JhKgXT%#nz~OpJpyU;U#3Y z`K9vu|CyiGYG^&-?ze4nT<`o>(bx$TR{p|~nRiwB#H%f0-t5f&8SQh-de(fWg%i%- zo;-2l&gT=qZ+RyeSM%QFe%(V=zqqXb2R<d5&0d;ZFrzs3Zc2Wl(SOfPZ}~qgF87Zy zz41bJ_5pb=#)5ULXP-H4^2Fk5;miu9lc%1EF;6x>=a)V`d`4{C&Zm1nuU@^UaNW~s z>sTx=&E#3UxmezN-R#13tDnEx{O{@8@{g>|=1a=?K$Ed{M)M0y-0uHiS!}#Hync3E zjM6-hKWB{Ybv<62Tl4z3{--~?)jgM9HsAX!Cj2{ZY2~vb@kuI%+c%y1bnKY!XFk_O zXV$N|S2!~@<zBzd<z4O(QTHEQxBDz2ws_+H`j?@bCLK9k{r$taqhV!X;UAy<><*bO zwm4|z3rWex3u~)i&YzKznA^K}_w0)+LR%IahG>cY6`mX-CYoqG`^EejOBODglP+Hg znsivQa8uLLue@sFVk`AD6Kkub<2B9%x63Eo?_-OzzkcY>DXsaIMIGXP^O%mDe92z+ z?m<qvd0w>~-|DG5r-uG}^>coLk%WQd7n%Ir#T%D(J^jl2B}!Me`LN8*yCta?n)U0S zar(u)a#$R+ar3T8)855-*~ry>o^IFexO#DI!Gxt>eZNHUrt6h|yl~G}CO`M^+YQYs zfssLHUOf}@el2ZN`$fRRDe>&uH4}YQCFjQ{#5>!HSN%4W=CS#8z|L>Ww#xyL=PvzH z>$ls`|MIA+Rl6HU+hLoc1o`FGyKY3rf?Dv61vAq7WEbw-)+X+^=Q#6jshQDn3zsez z@4k3KT&{jfxZnKb+UnWu-`^gU=QG^9<IK%-c|BFO?X#pRpF3&KJ-qmgj_&3?J5MrO zmlv(9pHO1edop9et|c=ZEDqf{#l`>b?%9vm%D%l_@!ZK@KGJj1g||vm&lUW+r0QiW z_voaE)Ko4Jp-M6Bu*sd}(fWaN=KB}t^5!x(NBFAk`_-CW`R|8k-`ktM-%n^1Yp>q% zDd)wOsA=YAH)F$33%AQ96z0x7Z(A|N{9Nn<>-Bs3Zf2-V>k#fc_Tx};|A$jEi+%L< zgnEx!Zc8^;*W0>r*H%zNf8!30GRZDC&94<2CA&YcJEv@lT=dbxU)Ju#p<7n^bFG{g zo_5`L`QV8!JpOWaC;IPMHlECQ@Ou9z*EeCOm;ah~^3MMg#%rrvJaj<KK4s(0B|JPE zAAWtr-`=S@nZag5F?-nL&d1`nPk0IKO@4f2GUq(2nh60WP6jeZrFn!pk5;_f=>CDV zx#!%ukGId)&5Ka#3|gt6?HTjtZF*($<n?tABgL*=JCU}z=I2ZG8L?vVCyz(p_E;Lk z<9jyX*~fq<MIV={%Oxk(HSXmtogyxpWGHDU$t!dBa*y9?RgvD0((`}wWJllD5aH_E zzHRbU6*jeH2GYGYwNDi89!~z!>$_pk&ZCcBS?&Mwp}9p#aMMkl>hdd>Els-21s2pN zb>*0O-~Yi<HoNt1>DE0rizc>p70szM`?FBM`?a)7lHoQc#<H-`f)$zK8!MUuOuQ-^ z+u6UrODiavm0UeLQ(8i4^4SaacAe$|M^X#~I$SKSUi8!v-2W=)@6+Y;_gF3d%+_>7 zn3L(Df$7qvSEf!c-u2fgzUEKhDz7fa&T|U|C%qI&x8D7ct$B&D<e!HIXG^#0<mY_q zjsI=*S9tOZ6REy8_l`POf8VfcYwzuO?g}!FD+4xdU&vQ)&=R*^S)gyj)6bXfEIP~u zl1j?@94w9)^UEC+=XuEA%Hg`$rt*ct%8*&_E*jRoKOL_$&!=l??CPoW=h(O^&3t6+ z&Og~>*^Ljse!LQ&ms*r4*x+Jx^yt01zIU02a!fv4*k}8~<WSL<sh86$3;d0HuU`Fe zIPua=p6Esf?(ElV^71yV-Zl#~pK)_Pe{<aNPsh~y<!-n~|7Z9Y(6REU>Y<AgUP~t> zsGPADk7AUVHB0S&VtTx@t#sUb_1{4!|HLS1udQxjT0U9d?xRNatL&S*7tgC{mu-$~ zKb)0nEub)~W3t!s%8LCQ>-Q~Q#kADv<m>e4f{3*|e!hlg*6netT~}XBxbS*~hSrna z`Fl!BcfLAsPF5vYQ|`|0*`Rr<oHS#x&62%QwO>0{w10npbiwuD(4d~18AnnK7F^A^ z@OsOf*RK-OGG_|)xBu!YI#>R6!`tt{FNzk0tu}o1RpQI8)rt>ZpE|ukqBrA;6jzL2 z+0~H17e$laZ&`dfYrR{Y*{iP^CRtM1t15n+a)^o#>^qv_vi$0&-~0b%@2UL9w6>Nx zT*>(MjtiHMKYC>qwRT#CQRn5f)Z6k4%4?dg?W>d0I&~p?tCIcNX}dld@mR^OERka6 znw6bxAjxAAGA-GxE1}<Ntyrs5W7z74y~W}ItFK1%uzj)8JzKhUPt7l$)zQ%mXV$Ly zaKG-o{f9To{F8i^{=7H){RFS{3t3kpeBAc^J>(rCCZ1?0dGU2g##SklEK~8SUl+2j zthkyLX1+aO^;M5aE@7t@1sr&{D{79J_EpuRPiE?7T+Q0{*U^ft{bKgk7o|}>Y_is? zw0``a9<MCZ%eZ0pzP<vJV-xTC?y3GL)EUCH{cfMz+G7Q(K^yO;J)ACIJEM8Gl;Ml7 z7Hh<q9vVE~wX5>k4Z(BeUyXL}aY_voykGlQ*J!3r@72&N;Zq*-v(1c(c`}!KZHrQ% zjUT&N_sqY&)*GVNOnI_9P*e0!xPjE;gSFKcR$RR@Wm=M9XPHmBQP26a^_SL9J9A#L z=*gqoPyF2Vrm4JKRUZ;I$zf7}*3^_ukyE&iUai$TI<;h})4@*fw`X*8KhHj2$9H*Z z<I5`f)$=wM>V4(?@J3lFWw(l4i_^j#v)+Hz5b4rpUh$>TBwyjgjXO5(<>q%4jJb~b z>Wbt~bI)7<q)M{*|Gql;r^~*_P5fJBxxT(EY?8;apqMvrAD?tKXKSpfuZ#3_S{gFx zY?}Rp$<t2%{`GA~U>&R1(nncUe(%1=*Kao3v!8F>v%;l0*RQ+2yAK+ZzxVL#Pk%j~ zqD^a?-M_tGymH&Gw%_aYuk)VYx$fM$|Gv8}U0-MG-l<Z%A#d6>bI?+h+X2&8>r}+Y z#>Vf9-un3LtEbNeEsH+37w?|fow~Gi_MOb7;4#S7HCycF+zyTU^l3p4sO4JQ3|Tss z@=iJhqyjw7ufOe{s#tTP81uu~%ce&7PPv&<FA8cX^>^EVx&@YY-HwZoRZO<e?>S$4 z>k+8$aA!Jb;D2H0>KnlicKup@^YM{nqYcXsd~Fm^ed*IS{hoENif7N6Ge$<X#nI<w zX3tGds(bkA|Kyb->Uvx6fBKc8b#%A*ZMzS*=hyykx4#<b0$K|;-{jM$2kJ*UU%JLg z&VKmb?*9q)OINf+i&tm=a8C5wR{G&ia{q@vyVXG@!qKgzn{MhH^k~`C#H7{TU9o;` z^QuWnlU|CPmY!|1rJR2<cXy1O)WeI+zZquCh+j}#(ekv{_s%yPt{A;*+qOx}p1XYC zqB#?1O7^|WeCCud-&io?yj=y$?3-r}91)q!-TlSi=h23nFXSYTW*I%?ZvAm*<Kivf z_yxLLZbXK99)Dn9);)9a?%9^tZ=T&~yIXSJJVgP{&o`6ZpDI^_rX?&s`MlOs@)WAS zckTGor=|a%B$@yJeV9G(WyH@LjelkGbDbNTuAkp3(9;5%26z|~ZhrJ<-mhco5jXFs zNc9KKdH<|+^83PdtJ{-z&;Ggm`n{Bzym`AmU0VHf?~i+#pn@z#%k}sJgVV32xA5~! zoVsbx^}3nM`Q()*pIj8UT0>uJL2Uv@gL$;xhSkevZI6zUoHtAD{=)}3;pTG7C$GC0 z$YUkTEFApEg?08+r|I4GmA_->Srv6W@1MUQH(|o5MM}4RvD;6ynl^Fb&!bLZQRRZI zP6yvHiT{7syZO&{cmAL()BB%pExVN!XJ0<g*|*ms*X)d&GP|_&N#khHqKgYVCU0wW z^eZnhv@rEmkvhJ{{6X1`iz`A}76pcxnVoE%aV68lM_+F-!!~BdUutRr3l2=3-hMM9 zp{%ksx1M47RkwLJeXQoH3GgkxoB<jbJmDquFQ7wdy72U~ZC6uLN{hS8^|n0XZ?~-8 z*?qFr)yw9m1aH+cF|ojvAr@=Ia>R^ZYBTDCS6`}p>Xg`i(tU2n$GP_e|NXr;SEHfV zgJ*kS{nr(<>t9Gd%>Hfng41s64wsegM;^SAm0!MRLqmy`^TgY(-(N`l<YPD6-1%`Q z>zqonEmFLyKYy;t&7bU}`jO4)%9N=|#<M@PAM(-D33yO4$!95t>*5`6%f46@nmv5* z#AJ8YDvmbg8*9ZLb*ixK?Mtw5YCL`N)-|(_DU)j2=jzUv-+k4|Xl`0sq2%O?4n|WC zNpmC_O5O~NJb2)VN$=IEEQbW=m}zfxVG57CC%e8}a^`Q=pDsQ8?smssf+iYXSN}~u za>;yt?u$^Ze{bitS?f*i={d8v8Jf?Fa__0uRc~K21++f&oyn(p*K8fsW~ZhW3pe=A zf4}X_S>=rq2R)uBuaCZYLq({&_RSxAzU=7R;r_qpMMv&UopQ(eY?(rV^Ig_Mf<obs zCNi$6-kbC5kIE$TYx!!kQ){D-RDEJ?UXpL<d~V~my}nkH6aOin+V=E&eag+fjSL%I znmlyMOn(*gc}|j;J5%+W;>DiB7d1AzFx6}Lyzu(1pPy6r!Z`nE+x2SaD=)Xc&CL@P zw9@umlb?V8L$roaYHs%LW!F!ixT6^&Hv4bCeXim=wfjGg)w?X*^Ldx$T(7uZ_OF{4 zG5q`0I^E*RmhSqRx4u`jOr3)--^dN~+g2*j<@QoW>fqy&qCH!C6D)iTWFF>(o11N( z*}By<&a#-V)yXlkvHjdb!CSxD3#>m`T)lYm*tY4L4l$`b@c;L5_maz*XWW$2^~*PJ z+k5oD5s`I!Z0=?4>`?LK@$)PGRU~dUxpUe)JC%gY+PT~QIlc+gPFp;2-$%|hX~LUN zYlEg9%(gpJE^HUhmEBYG%A{YurlCabaQ$ET`sUm7+-+tqS-QKwH&_3%xAzN^D3HNt zbDou?i;GwN`d}eDCnNiKnxV0UB`9AnWtA(5(tXS9+;jHa!wpfDzn!%CR!`mc(Nm9~ zH#jQ5;r9Ur{e9(avo;0kefcu+TuQ~yy~Y|1O53|1uYJ3x?wt+a>ZuV%j<*je%*>hA zz4z}E>o<D}*R{GB9p%4g=ht|;^Jd0_v!BH|T$3x98TGz=N!lE-VV2LI)6vH{k0-^* zN$r!`Sy_}gapO%(D|a_dZJh^6`S$vI%iBQBq0+L&0U8mvZahfxw=bK`+I^AZz(?=5 zFSbNo+rF2_|Gd%uO{aeRVLE)-*d@8}-~IYOazFXlW5Yk$-n-SN;(10#*VxM1-Md`> zUx373ztb~M-+glX?Vj3)N~>o_r!3W3Jv;h~zmL)8J%^TEFTZMjK6U$LJA)$^o|uRp zZJm?z`oY%C&n@q4;r5(V@!CoIeasG*eYX5_{Z4;*WOUfrIOjL>m!3Xhj`qrjM>J~| z3WTaEE&8@P{aoRmt-b8u-#(n%J$*)GR9Zq2*Y?AH-r@Si+N+NUd)~|0>0mN1p)Pgm z&8Mj*S*FWx=}-1ps!?G1{)Ba@{sgb36GXVClqdfAS?MrIW#8Ae`Sovpr+{kLz@<wA z9`Le6-oABAoU3r(?%4q$HI?eYnrYL*I9d)@$nY86)X9(E;b9?`?4HUx{TG|W+_{Sv zZj$MZ@{Me4|9Q2vZTa#}RiPYqrZqV^mm*?Y^#zvH7IeH^n)*qWPw1pd?qBC8k-AGZ zOY%g?zK_{+Bz#_F*R^|$LMK(0%JHXL?Vb@E_t2wQ__<Z}joSgoyWh`Uwr)?)w}Xnm z)R!5|<~g%=&7#27k>7t+r2LPoI<6LR`&L?2VW*Fo^Tyj}TkqK^ZL}y`-5O$b_UXYy zyZ;Xice%Mm#>79r@h<J2MRnuJR#mCht0N*}7q40}<NcmbR$f!PPCF|vG0wcj-ZmpX zGBrI^^zY=!I{7&X7hd1^_IqYb#G>Saj$5CMq*kw<5fh^{&uhce&&)BM32Pod4NebS z8KSd3|HG}FVzaWdFJzj$xqs0?X{w4)_vdr1VN4G>c4uYnxN`sey|ya9ZCgLzx+(VW z!S(%4zaI#==9xd=T`e(h*1~mrdKRwC+*VUJ#Y<H>PM$mab<8XIBjP-lV#2+D9}w96 zI-7CEjA-y83cttPZ4xu)9Fpe>jt@Nc<BpB!(N>XNbH4QYPx4!yDKBv(Z)3qaZw;sI zw*9v@1!bM~vb=cBPeDd;p2vnA`wlMM=je1%!*{DGXj;8$F5l{tJ?0WAHD&WQ?yTgR z<Hx3^Zup`khn-0#FKbC{0mtNn1*%RZGX0kwUr((Idr_q1nXoxxMpVR-H3yt+W*(V3 z9kl4m&uH$lU0Y@p$J(yR%e@#7c<{*~CAa3r?fP3jt@gJ+_~Oi*4GFQ4sv@16cI<1s znXx1}W5(j$v%v{aL3=I#^RlVaVrGBm;D3Mr`1bgU&i3zb52l#~#|1Rpp4WalZ~4k) zvvR^7-R++KLPADKqA%gX%M;}mE(-hCv|N{WnWQk&?{nB`SF=5KlUACv>WRDUotG2# zC??!IzUq_VxA!>-6<M<${i*pRTee0`_${+DkB_fl=dmC6r1LMwgf}}bPd@xydG5Id z*I#OUtT>UfUUzP+oRr$^sRcJbZ<u*zMX1)Eg9;m6WE$RGG~D;)%HthxDsz6-h&%;N z#wT8QX;Hkh`{mM9rHvBxpC6sJ*^{p?wYBZ)T3r=|^GOG%rYlcAtK=!fK3i<#S-- zs-bkR$<=EU(ziX>#Lay)L&wiR#&P-8Br~ZSvEkiri`9g>7hcc&$l4S>?WT&uq1^I> z?NJ4{Kd;cxd*V?n{J8kD$0Qe>i3urb)6P8<Y?{bXwRRfQa^`g{bGFPn`{(8VKfi0f zpWQxDrSo5>C(}cYvelyPXWN_>D#&yTcDY=9y=4Xu+qWxMlgvQ#7ak4@GH#PpKFOA` zsV|q9H}Bx%f(iNM6VlCspA>a3=n>jex2@H8J^$9IqyOew@3?XO{KI9jXY}-iJCAa@ zF47R;%JTNkeET{*ytm`jp5+VqCOh`u&3YPeS?||z^~%jpnYdSHy9gKFDYGtH&AK(H z(_BD7s$ZFrZSFkZ_5Bq}on9+N_#Q7bDC=&u>27t<XwjEAGBf>f-quN8%RwtbS8i*2 zE>}Ng^Yq=C1y+U6ZWi4B9C7o`qnvc{#)28s=EWVlsNtG-{i<s2)F97|w|m3ZstI-1 zC!IcN^j&?^*9W;p=1SuIXU<#-h&=e{meuO$=r^m@fsPpTS~@c#BBeZ*_pk8e9iKj( z*c?$1!)draL~BNDTw;2tYNZ%=?PFmNp^7<WTcmh9mqe6B#zcb_E<&cfm$J(JSt#H( zcV39v*)NZb@~Y)-H!?H^%y_m-O6=M-O?@4e*=K`Zlx^I#(>1fPop*iz%A=~Qyt_Kp zCrgxA`LNk48yBw#)%tejy3yu6PNklP(RKFHaq?4-y5{`+6TbMC-nzAu-*4EwW1FAS z%#{0mY{#BI%UrcqQKIv~mYW@_LOb48_MAN{+~sm3G}!m~1rF=g|LecKv-Vi`+v>yL z?`8MTS^9tX@jsSez~RE?Y0xd?+STQ^DW!7h)~Db1e7g0zHZ*(x^YHc8p5EGiuU4-* zcH5q7UfWc?r|AR>86Q+=IB|esa`Cx^%d69@o>%|gXJ2I@=E|_hp^0V5@0CuX7q(Zw zThILL%lq>4@8_s(`pG2MKG$ibi_ScSsV6tBUpuw2Q?o`--Ea0(7c1xB+>Un_4NIZ~ z=ilyhyO3ZcH9=+O!k3wR<!_RVXF5$wW$9%LTzxcg>m_5Ww(C!iq?tV~-WlPqvV!|Z zWJIsPr^?8VHHn6^XUvFRU?{R=k;aZUW-6X(s$$CVI-9m{ZN2xA)5%VLQCRcwhbhXD zd)HkHkzN$E@`9;Ro8Og9>vP#xZ!BeTJn(qK=7~OxS6|N&bzQh`SzG7N%2!N`TuYT! z`b?Aknz(3o;Vr3GC!c+Gxn`cRinp+|VoJmDR=+C`%Pl46%sRHhJi$mR;`R-d7oQgh znnavc+Y+TK{F%EWO1C;XT99RjkxA3loJISVwf#HkDb?&K;;I-UydXP8r2lZEM%NA9 zG#1AN0Xm6hQX6OZ_~`0|?bpy0y;ElWGN*6lQB|33uk4O4-KtSqCvO$#GD*ATPh82O z6KO`Rj_VKSZA_?~9%gvYKkM6r-j$l~uNN+7(Vgn`b+apPl=-qUy|9%bT3658m}aaD z(VF_IZy}rRRIjB$cMY#BSQ@l4WR-PWRqF?_pY8hsy^5aBI_}cjcHd&dYg@UAAVoi~ zEGX?h(RC<a_SV_0yV7g7ra#f$epYY&1%Wk*d8MN3FL&Nes&s$ee^mIyrXG!~`$4&} z)3l#-yMBtUF1@#|^(u$re*Ux9+D`VS2=xZ|3icmet@-vqnQ3*yCY6ikb_W~3&F$E( z&>g%q=x<HnboTqo-Ya?jUtj5`b$#X2Z+FAvl2g*A<?kzC+Uw`8Gf!cj*JOQ>$k=%G ziRU&*MK9O!Jo1S1nlNWr^6RVHlyB;!dMeF5E7%?W-6hjh>REXBOF7Ba*Dg;^6}x`T zBfYrh=kEK;v(GQSn&Fvd<YI2FIqlS%+?-7_SH0t1rE#ikYF~tnpV@qO^{zby-)xvC z2Qz%>^}S$hc5MFN$My>~xR@sg+x-3&X|z*jr&D9h!UL`M>Z*>bX-qw}=17vqq&=a` z2IstT=Ef}iFmErr*3?($mY>^_w{hVMwX=HG`~SaUtxNvD?sb`--}9nB2mk-b{`c+w zKWDKp<vk_;n3hgzIho<0-o@kNcTt3EQ+>L0`mSov=S6p}Ze#8~>5)>~tp3jaoVK|B zW{J)O<7kfSEC!OiF|u-s;Tji0q?3vgCtjRs8FW);vGHaXGqahIQO8oZ=T42kwIo98 zqkH_H?H-ek$p3#EUU=(mOZJ~9+^hmDT1Bb5^W>Ti%&&bs`_C<Rx#c_8O<V3iS8db2 zgTd?P9?ILeK#=8GSop?hotmHV``Yh6by|J(g1KGi*_>s150odK`%wSqSNi?K<t|Hu z?w-6d^P27w4X*ogvz~P3?>}L;zx{aBq3e6sy9xYQtp6{1-_JvwVM(uLa`KlehB#|Y ze%f3vzjW=wdCJvglTV~rY%4dfj+#~Z<b>j;pEjwHYSZ-<!nI^>?w#E??b%zecPo9w z0<UbE=_7czXR}cEMS(R3Ul&a}`TS$`ojb+X<DP|uRebp1n6)QP#nUY?Aw5{x{d-Bl z{l>o<URyf?FFapr_JDms(8>=x)#rn%z87h8uHInFmY$uXGHJ?^tj8yJHO#;E%c@On zx#kqFDW`<k%ik_hjXD1K``zEmmby&!TKdZq<T(`%rush@1nUf}4!hr$%KyRr>&87> znVWmNQ>=V@kDp!Is93V-gtI$e;^rBd`B@4N%JR?eSpynK?Yven!^P_C)Q5t%q@@dP zzRh4^+<mp@Y|caP`Ttbao{1MktbO4+adCB-@Tbbo<v}tT`N?IKt=i7Ye-16~PcWRB zk<Fo;wN*o7i|Lier4}2ab+(wBGB7#LpMKP%<=Zi~tlBuKCeu6h3ID^67Av1E-Fk)X z&l$b-3MYl$`tsh;5wrXMQC)KG+{XdY+D|vRxCR<X_Poi;s#$-JZ>rZ<V+Y;GC6nud zB$w;Q%RceQeK4z2Vy<`gpK}-YzW+5NMC<BXXWhpo$yt)iZ=X@WJ$t?61_ryGt6$p6 zc6%)i`nx7zKhqs0#o4VB-p*aRc7JTwqB~~S+wzugToJNrzHOH9iP>NB%o?Yp%v^8# zSBJf9>*w?9_qbhnyijGTpzA~zwPqDh4F;|$r&5i6etcfC7q%9F>1a{sy^V!p%GqD~ zd;^|;&;M@kwZvFM<Auw_sS!Qv|2>G*<L7%=zVpPB&lxPdsw;aOmnY{YPqzR6Z2Qjg z|91O|ABEnUEp@|VnZc{CB3`PSe%h>$+0%0|;Xsnn#Iw&Mqq=jKubQsXxjfF+^TKmi zfd{+S|Cunimv_mg$S+p1D}CC6A`dONzL?=-3fD@dW~R;(sle5)tFL}K^E!RQ4Bwi+ zH^o=*v+cNG-VnC>=!)x$1zA2FRjU8>{l0<>&jJmus=f14)SBG{0z_K9mO8DBahsGn z=_OB9?N-&(S04&KT4`c8eR9&uo;4vWLbQ$qXYy3Z-gIj8(Q7}Mut3MN=JnF)7rT|# z$Gvk=@A}fyC&b4xAyv|I+RWIfhuQx2-tNW1U5gehm~bXV<FwJt8o9{_9ri^$sa`*K ziCsi<;Cl6mev35>HgD;PTYh-K_0Ma?<I_@W=N=1~kfPSDayq5RvWJa%_DK<q3ECna zOM){@qc;7t5p{K(mO5$Xn{Tg|?W$ertC0UDZMMTI<F&UNR$L9cz0v(zMDN<q{rY=a z;+7|udmBHm{=H$=nG>QjncwEFQJ-|8sI{||m9KP5uwJ<Nd%tt~i>`NXF*hqJtzcOk zcfS75o%9ppT_Rnow`NO4b{_ReE$%sYZlSm<C`oRgZB^FaH}O=;jtk}oe%!GsWwd|% znY%)kPf1!@$2IxKUA<lI$8PN3%scz&nG<Jp6z5N0xH9w6N)c;m=@*jH$;uOtELh+7 z|H#ko8*9bt-W$(Xi`Oc8^hY&q+Vsq|tCgp9ByW%Sap<_cm(A2i|9^f8|M55ecj%;< zIvXpRW-d*2348)7e~L3^oH(X-es7)F<clZH9jo%2v;WBZ`gg`>bi<n+ub+^3x`{=D zr8Z71OgZIKrJQZql$eDFg4fSIvcx<<WBP=rTzsorS1T`Oxszx2>p<-l_Usq3vdha$ z=KTLAU)MfeKPD}!P;jlAx7O^Xi!`RFb_VS{bA5g_W1tA<j@Tu|mTu|KIDYP_c{GuI z<;RL0MkY=r#s@F%m5q^;a9S_Sxx+T%teTFR@W!(iuRB?M7b@JZdB`#|rf<Rd)3v|f zC*_q+{W&$%?$d$Vn$JIl@9fPtKfSS3#q-eHf&iVV22x*Y{w4eGTR%T~>Z`vC>R5O9 z+7vzEsQ-8N{f6C3XMWsSsp6>=uTk)Q-(HhzY?`Ny^yltBGVhw0(94q2<U-FwPd7X+ z-#s%nZduGUjj5_~wq-2cCtDV2oS4cr|JMQMC7UGG#HV!}71mkfrZM&OlvAk;R<mZ$ zh>uha*O_!G?WWJth#r@M2%SHllKUT(@BVqC`FsBR?^*dd3S#~jF5WqETyD?&0^f$? z{r8<0hAdjUa9-!n%2S(M)TTdwS6iL2YOQL#PLR$tk2Iq-F3B%Sl;mq4)TykLGEt3u z*7>`?cwv2mkDkBH+$2je=V_^2N0qAP_Svr0_0iW4p0>*Vx5ID0tZi0|(^WfT7B-yC zdX~&@yJ6}p{ZEa_?gA`~t8e-&U9@4Q-{iC6KU&@8(+YLHymMvwW$m`?U3qK4^~)D8 zoq6%brqieGt4mXbmTTms6VE<h`S~}(M=k8SxyCfFjIB{}RwWZ;zb4ArluS6AvbFik zx@T^EZ|=E1e_*h&Vk>vSR&L`SpYs#Wq;;&xH`u%740Ai*g(&%F|C)by=HyK9Nss6{ zX7K8(Oh&%)lkbHk{_K3Kr`BvdvA*U-;HI5_et!)NU3oA3)u#u(Rp!D+w>gS)$H zK0Ry~*cw%IREYg{d6LPCm3M!+t`ubHd-E<Kp{T3jxO4W7z6s|~d+8kO`(@DNc6i=3 zu{F<L?T9*5%F%S7J6(T)MnTE@yrww)MH)#LUR&O|*tcoxlZqY5;@YoYOMI;oab2hy z(;m0{@uvd@iu>E!0wyG_?75qz_~iS;V#}FvQAt&qGo|`x{|exZ>TQd#Ir#6J*`=E@ z?N+xgzATCGQOo*k=M^;b;mgRTIDYFxiCKH(x|SO0K8(6_Q|9>h_sUaGPCA!%^2w(w zziQsB;4iK$=-Ad)rQ^o@`_`?Fyu6}{?|LOs6MrS}iY=Zf{9OOxhMO52Y%9P1)HrPv zHo5cPN6&9tw>~Pg5@2Cmf7vm*c1C)f{b^-)KIN_`Cp&$%y>i<R_o<w$`81K;^6u4M zo$w8jI&ZSFlI(;O<8?OeUOIEaefOn7Z%^G0iS9oCbdicDOKqG_m95|IUTtS(6(dQz zzc<(;WA7_GC=*`C8Swb4!FHjC$^5nl_Wu5EXkzLcoXas+L+I0Qjj5|e{j>hoEfb&a zk-nLw)~;>Y^1_?BTXJ$WPdq7l(ycnjY<85~YqO<#{P%90)#G2K`QF^~ZOodWm3c0{ zmHQ1%pT>e3*!G{{4Q;6{AzD+tN{<ILPxD$DwDO(AE73#IPaY+;eC$19+W)q|ddGUZ zA9DR3Ai0{X3%gv~l4sW>*8eu`|66<ihH3M)uU-nFBB{Ik9&YW^j_y^>PyMOl8t5SK zfbIFJu#N}2Y!8E4_;Z7%v*!ysGOTrL-tpCaokmPV&jQhwY_UsIQ)k}){l5O(nM<E$ z=gH5R_3Zt;x@rHv@!wBT72Ex6XPj02#MTqHbSuREzuLY2--M@IHR`{f_Xn-p{P0ER zukhsjS4V0V<~O|GTUKP<u_{FC>Tch;nRk;mEm|PR@^4vo$Jd%h_H~<eEVfG>d|gts z>9ZEY?3E(Yohoyioij|N+LotRmi*<oU;S2uccDVI^lXc@Vb{#eXU0Vx%G~_v%}ZmG zRwtLog)A(unCf!Uj3@T;rcDnoxS6x%TKh{m*~6KeKmF{tJ-Jdlw#3A|aNYL)0)+!l z4=VD#$$5P00|yh+{E8=zQHM*Pd}96gJox_ecYCWd)~$XzTYrwiE=l!?=K>xV8ry9@ zF!P<<JL>}R`&A!PFYT0Rx4vb0_iD4s=^4FleQ)ocwf%i%nvT}gSI<@&uZ{Ky6si0E zw7BNyD~0uE^*+|i*;m|E-4m`C<0SCl%2hp~mnO4MimcvPdTX{+<)0sW?`+QJpU&R) z<InN=DOH)By(yCld>dqWzuu|7Za2@mwy$R4iJ9->l4f(-6}&OXmX<#9h;!PaKsl?L z2`*}fS8B)Bd<>RPH=fG2z)<AL%<Ja^w5D6$y?S<f-Ba<MCI%fkr)_>7C~RA{jPb;i z&mme|-PwUGjtVcnPB@byF=K|x)U%spdN<{}Yd>^oxULtUs66pOjK6$)+1ACEyJ~)I z<TtXg{2RCTi`LXv=~JY(<S9A|{AjM`FDNSO-2d;x--xffvhS_e@mx||`R|4K{sZZ9 z^*ukYa!hA$dog>4%j$~?8LO5iyvxddIzO&PvR5I&bY{k?)l1V$dd@8r<ST!3C~xD2 z`saLW(uB=6&+Po^s>jc#l;zsP2HJGlmcR=NYoTbz)ho@8ym%vX{M)-_rZUgu=T*wh zzukH>!)5i=MOVY@mHcK;)&F}+f6?Wv%C|-8>UuFwfg&+w*7kd9T2HpRZi(XMn?2Qb z?b#o9^P&!y&gfzDabsQ-*6p{JXF<@)dx~3oF8luSOr5jun)RW4nHLTWPrO*)_Fs|z zopqig-sZ>pr`}W6zIs?ScU@G-)<pr6PGxLc*Ul-$TeP&vZ?$T;M#6=c0V~4V^{07h zG&n9-j@MZzyjt|}eG9gb=JVIiTU@^CY&2OhTI0iOe>=vIZ2ng+f~+T=a?j{tOWE19 z;%Y#kh|Ah(n^YEF&06hRvHey_1`F?^6-y(ul(S4TOr*9*@lMhSo|e+XW~-r~eRZSv zrZsGOSI_fq?YZ20H%C(a>(xE3uil#NyJTB)Ho4dD_UwPU986WQrDDsjW;ie}`ti)+ zx7&rye<CKvEk3y6Z+Z90io3}SQoU`9tIIcUkV<r~t@!=T{G9HAvW<7m&wY1WahK1m zsUd9f%{rcjjH=HOU+v3cc7F}N(y%mW<vq=>+fV3zS~%^4|Gvw=59Dp!uzc&&zjAG$ zp1z1_#$7ePIr~q%`o-36U6yDjY53yniA_CWixp#pcRWkp^wUOv-tLC`Z<p=e$k-g$ zfBN70%{yMC)o3>^y0tcZQp%P^ZF6~fZ-1XTW48L#vxODk*Ugst{^E@c6VqE?Ui+Wt z-X8#UVTHOk)~8Fe-zwj?_V}KQI>q6^k9B2ddo8VczryjgnW35Wd2zdsf&2d5;eL~q z1)ADzy~<&?y}RLfZ(#lc)0pF}`|6@zzy5jR@ApfV7Cml@6{nsx+PI<N{@Z82)%_oC zy7}V@yBw$=+q$nV=%&v8pDX)6e>r)1ib`jSm2<5xZ>;j-IlC?$op@I^MoQ+<zrW=d zZLL7n=kDlPlC$S3$7?OTob_`4j3<YWzkj&&v$!D3k4NhEpaor5z2|yN>N%VAY~^*o zMS?6M4?aHrUa;x2mf!B)1=ml%Tz&UW`2)RW)29{Qe#^2)ZkL;z#g^4`+4*Ikd|e&; zCNnd!AZymos~nvnT-`Tas*{!ZWvmWd_`<XQ>q`F*Tjgz<6*%U+e*3twncZWVanJel z#ozbsopM@e`Y-mIn-|aQb(s`lbMETHK)atOnzytZR=F&B?)$fgg%+UB?>zfrzTHQi z+`Wav+ueSAsQv!o(al$%e;+z-ziV&Es-Ts5@>$;=<R&T4d}6J?-zlZG`REC$v!z>Y z3SKb8EuXC2to)_l-@wfLxUze{!R|dhi!|P3XS?cmed+7nyltQ3`4bY(lP`k?8|Ha2 zb3L#6Wgy)<gO}|UQ=Qr~@fopkis2fYc5FNL@b2zy)~frjRkr%*o!|TWd*b#ei5auf z>Qbl9+gND#`A71ex~<ZIix=+QIPq!5l(Q*a6JJUmd;V<O`pHvOXEIygj_5nKg7?Qx zE0aSH`^sYYteX@H3a<MJy)-F4t!-2I2eh$-LB~D$Nw@2?Ym1f`Mc$e%1zMzc__8sB z%B9SGwU0!@u3fKuwRQ58(?;UI*k(jTBoq|Q`fOWU(%U2CzqI1*CDBD6E$06^a9HN{ z?%7i_dMdPz-g>6yyH!zuC2nWM%=ljy*gc*X*?hg_*_GOPeSOK|t648HGSd`=D(~BI zYfXLi>&k-C*%!K%;@XAx-)?nNPPp<qGV;E{%##<Q;*Xy@#uig%?ba+ecbk>tycy96 zmQsh)%#_1LnB@3*w<?yInkSmh7GP=AuX(ii3M-S%*ISx?v2Snr1=qhj6M5}1CkxBB zty`0}M_6pw%sbh!UxDL=i(s>#%9GEJ3N0#LZ4JJ{`e#Ou+m~Hg%N`#6$N2B^bNl1+ zH4m>_UcTFXG~-B;(W1+pJ!j8dG`3<paR1Ng@2gekiL`#+`!{D<P{i3Zo+{a0Yg>e8 zA3bEe{QRVo&kbhtyl@emd~w5Efkoo3d;Hk#rg#6fzFlx@jm)j9ernU7JAao+&MNHO z{r%m+w;PHJ!mZWzGS2mLFEKusW_0%Cxz!vTGkV=hqI7+?D$cVkZF`Y6huOOP(Wcus z?q2FSn&PD1<uU2VnNOcg?`u!>`uZ<0_+I{{-FJ6dOg<f`F>OQS83$9}y#YFmSF2jO znArC6^}0DnPBM7)Rin$vXtL{-EQ1$cGgumHHg+gvY?#sGv8iW~Muw>r*V0R6S-S(* ztIs{1c;&U=woBK7XX=D)=G+-{aKU9o4yLD@S{AI#Yx7Glwpb%}YEp~aVn^i+jnkLP ze%0;^xZ!tG+%!t7%gJp1?R{q98dEn)^qvrv3>3MTwW|7nis!9;{#Mfurx-AKeU-8Q z6l1*8rZq`$_R$`Vt|dm2Z^X2NmR8+;-#dTusg&)T)I`5n$<C~)v*x|O;(D{f0u8Q> zXD$B!`Ly~?UhcEza(U&sXOp%^P24t5zCq>mj5;0W;H6c&uT1$az5C{ra?^~vOUkV? zR)(yaubXvY*T&hrQLjENfHVZNE(C!_X=R;xqqL@aE!~y8qI>Ojk5v&$ff{k2XB^Hr zka%JLab@su?R=>%c@y)$^k06nDgN_~5}T9n<?en*ZZ!H>>H5FPxbZG%jm8As=^I~_ z)__KBzt?}f!#eHSwF|Gm{5h4}pJXPr)5hRPW308|i*<J|J#jx8oGBA_x@^}srxf1V zH(O5Ey*===Z0^ff4{z+VU7%6Y+f#VIard@<&rLqh9|#=(e!ukYaen{v8|3^yJb2h_ z|1qXDh|_b@RWA{(sjqfjS@2bE=cY}^u2;GLJmoI8=h?@HD>Lg}i`%!JT%aDWQ&gGI z(fyaXVy>T$o9)q{nLDS3@@;vaQjjIJ)@=cJ*qyb>PXGUhH{3PfI*)riFIu2sa`l?h zNzu67HLc5T3Fz(aJ$Eqi-M!uIlR}o&*G&4&|K@m(k&%t<;TLaY9yZ7?KkMeKaiYk? z%{x~2Xwgh<=fg92*(S}@ncM6v@ukX!kG(ngGHCfgp~VW`A1~$SF9}+CAw>F6;^s{f zouBsa`_B{q<HzJV?_M2yUGk`Sr^JjotLB}~d;IDG2m7t^O%jodiwh(sJD%TITOD!x z#*=ro)e#ZB6V5%$Sj&Ie+^+F(mg2;71ttE+t@%!X27(uFwT$`y^RL{IwO`)<|2tj4 z<bB<~&Jevsv)FpK3&Nd+8;+eWZ(F|MMM=%eBbNV8A3pve+ULufV-_M`_P+eLKJHzL zsZ_F^kmHrEFZrb`c6YCyP5yrG?El~8@$TwfC477vrJ~bwjn5sq!^F3`H8_0N2MZaK z>sLShx|%oXrp{$<?=`tOmrRYi{G!(eY!rz-oM!fUtGrG3;jE>_1v8YZtv1Z^{nFQ) zygkC=_T|Ip+SuZD7IZf6zV*>+E@&8h^=oO9>unW3AEmOXFP{+=vq<m3^RL>mONuPN zy}xtNN#&6DbNxwY(h6_C-Ba*QhHrN7w_|Q~1+Pk7)_Rl_PmbAmV(CA}Gsm*7_KBaH zmz+`6wismL**z8CnApqTKA9PuzT<+ugN|H!Nt&3WfW_UbhbP*~&UyE$@^))+=&J9| zJ7e4gTi#yfzdBp9>rnjvuhZ*a9bdWrneH+TF8`Y6taaZ{#97r`zu%K{NxI_G!QVeF z*d7lE$lzk#7_HNiofXl$mN{Yj49=f5TUuU!u$-G=!le7q%7=})YA&B^V8+VThu@b4 zPgAk+V{f-EE8MrfUzRtKDUV<LH(TJgRjwxO*^Dow=Pw8fwAfQEK1pTs1}Vk(HEI(r za;~jCB`v9=CM?zK5UkO1IBTh*#1gXy>eJ5~@7{Ch=s!oL*U}sZUj4G#Siv+ouK)Ve z2S5Jpejy{XC_*p!%4@-`QRhlZjrZ<wv6`*?;_HKAOGn1}r;qmiGH6W_WNegL&)$F8 zF*#RY|LLRW+Nw@H{iIv}9yA*3zP6)qa^0+RM<>tboE6Kr#px^8_5N}_wihxoNoAFy zfvX>$m<QUs7PM2wRL*?$M&2z^yuzQkWnSHIjhr+gb!O5|pA)ZB3v+q*`fU$=cA`mv z;|aIx95d~^i<7Thzw)4b_l_I(2W)?TQwmSn)pp#XE<rwS`DE|E&1crH6Z%q>$-yc) zd+y?udRy)uN~tq-S{k%aQRInJzWss#=?{-fEh4+zHqJa7BGP*Bq~@D2?zImM_9j2B zkl~Xt(>}X(>ztRbj-_tjJk!T$yVS!*XZ95#B4J5}F=f(Xi$OyGdlx^pcw1Ix(z1OT z+vYXulS)j?7hZqaarE&P(<{cCx12e5Ec!N|>(VOqD_s)i%cd3X>ie#p@i+Iofm&dS zweVy26z|l3cOTlm|25+sOY-L88@ggnb@%=EZT2c<4{pBJdpGAoQ2g2GC*ADU6SSvh z%U$NO-@kg(Ti@RI-vvUnuFAf7{(bv%-DRRIU!vZc{?9PYpIet&WGV7AUVZOLpSB#k z|J%+_*A_YPq$p&au*UtBNh@78hA=5iJ-hE^#MVXCb-(LAhRoWek}Ds+qAYM)%1__^ z(@#F-SDmwex4iOS{+~VDANPI~_g3w)FUwsMpq1NiJN4|or#q*eO1<{D)BNtY#pmT$ zMKcz)9{RTb^U+7QtKzk$a^0+XsJngn=KsHLdZZa$|7%pDJ>^s?SM>YcUZvIno7wX( z`Ja;ellk}V<@1TAvn6NEI+kMc!M*;g{l}d#XLNLhKkQiDD`)=bjE?T)Q)x3}<Bn!- zE?Tx*yxH$~{Qu9vB3-UdcKXxV+YKanT&`VzIe*5X*Cm^Tx(&B(=s29UFgs;Ridysi zw`!X<9z3ZXt8yt*C30EFG>_*+Jig~QO!P3?xWVDX^W-|yL$AYkujFR=ajr9b`|Wuu z#*$TT$9LYaZ#bEtF!}VyKQoK3u>Q$Wn;fFW70liJ=lTA>QfnVtg(Vs4s40iHyH`HE zQ^}NP&JcTeF=&01@X5D6$LxQ;x_|NB6_4{TEF9;HuXQ{8<`Y-c+G)KhT^Dagh9ya} z*yNr2{`K>j*XcXHuiJY@XMMrG<^4H!{;q*1o)o1NRsK>}<EXHydHXW`Wk%kkpT^HG zW|{W*oEQ31`BF~u>6fc{3|vQ*Y!^S~@jox{>Guh7t~KlOKm47%-q^<0d11(^Z#LaW zXUvIzlH;$hx4ZY_PS%_>V`J~rI_}9TmnHZ8e8i~|srKaaMuEuW(%QKbXGSvRnG1jB z_R-UMP`>koxc8r{<^NdQuQnZj`NZiz1KZxdi#IK^{@Mw!{JR|gM>K9ZbKvTw`87=; zW~ZG}c)L#?x%n<GM~pkX-R;HvIftH?fO<1`lM)R#9eeP^gt1?Gu7=V6O<vbeXw+@* zzPFK6>9ur-NbBX;yD6VpjegpE))o{|nCNA=Un)^i=wR;l%a#^<N^1=r@BcVbHsAc} z?3Fj0&C535Y|gr{%kzENg;!FN$rWjB4YytI|6oa5JaK8pl(q!k>Fn)0uh=)lsZY`t zu_$~f^wWv4*Ufun%(Ev`S4W&pGukQhd9~miGigvAlu^aD|MtlfUwF>XwL4y=<ft_{ zHK%MIXbND<`y(r^8(Z%8Fq)j0kkmCvW#bkxklg3JwKsIdQg%932P^Bx@9|j~qBQrk z;pQ!8mL7BrOO|f=V^>%3%EWIr@8XLNk&`55&rPq%lUp0MSyVv#OHbcMp=kAq=Y($F zNHE=Y@WB%msa`S9Nk1M=)l(A}`)DQ0<L4U~sO6)lBe?G4Wm_9BcW>kSb|1O)cK814 z)Lh5YJHcalWXGC?8U~xUoH^{yxA1yr2_K(wsMZ<1^&4b*Hwtu4IQR7C-AgTQ$_86E z9J%v}>v8ethC@H@Fs1LR%HX{I@$2)r2N#pwZ~Cb2v@+?6Tdq9yY|*maprTo8w(3N` z;(g@}E04OCZ8zC05cznk_uQOiK_cF&V#<MaH!4~8#<i=QTyyN&&6_t47_XlX%2Eri zpT2O#q<M0%kG}3@A--gj7nav=`zuXOE30g6y=r>y`?tyGo>^SDckIk1qlvw|%fzQ^ zPU)I*Dm89rMd#TNsl{>r`vM;1`0F44e*b89`uWZCe1tyisC@b;wd%Oqhn;hD+^%Kt zUN<x_JbL7h(#Mcl-L-$Orc9rfrY0_SQoPHi`j?LO#!{7)XM#*X7JwEYJ}!I~7PjMt z`H3^1xa^is-q*?b?OjIg^?&+*)&w+P>s_h&zTC?7V4m6L)jK%_Hq1Jk!NR!wtk=Sb zCHt1KEkAo~-Zim9jP`ZgXYbossP<gkBX!dZ-nOjACxSSa-)+-5xntWmkEyCNgLd{D ze|aFs<kGz>4Y%{$C#7B!_Iwr={`14f>Jy?|I_{v$0;`jmx7Nw)mX?Z~R^1|X_M6?> zZEaOgyjp+FlFAV?emIN4cdOzxGjmYa@XaT#n>F)lHl7Gl>55x^ILjz#n(7`u^{~kk zukEsWBgXC4+?Zn3d^pW@TI!rI?YF+YAtDCSz6(GLK|URQB^0_cCM{F9D`sLQ=k=h+ zUniUv-w>@M@#X3%#m%R+IiwnstIH>!Nr~uOtK6leTe>x4YZTv>_fOc><Cm}9*ci04 zN280SHZF^~ZjG97E-!D-*|Wtf>pQM~eO1=n>oV!9i%|E;mK9f(PK!!4n@0FtU2_~X z3#jvO)9nqj&T=#zaCYarXl>QE;%d@`*O47ACq%h+$nuq$noiOdF?jLyhVHbieSJ)3 zn^#ITbh$q9YHdrHV7{qx9S`s2i!r>rq))0;mv0f`WBFk5rlh~maO(~it;tW1w08e_ z)Na?n#<=~iU*x0@yXL&fSaCn@m(Bg##~<C2+Ue9dtzd>!e|zgy4(XFB{4%%vH^v-$ zUzm8|^~w;f89Z!j(u|KLb#^TZkY95!aqEWFJ12TA{WNW9{M1)rfuLGu_g$8vj4Y|% z1q<y$4u6Ug@tn5ZoWZ{6i^1yGuW#sx<)j&RPc+q0Q(js$^W#s}tXexCH|MRTHNXA* z%1bwwyK65E>fGh9VAsO!0SS4khwlFV7N9fr#FL^eEw5+9#XP!nK%kV-zN~xZSC>h) zYjr!Mc%@g0IQF-9EfV;!!*iK&kG@X9hFbOYv9DAfd`#FpgR{z3C%4x!Ttle)cqR|4 zrbxGo`QtlR@42bXR-SuS@a~-_57w1wd9|KR;aYyyZC^l2N?P08US18ZE37qZ*5z-Q z=#gYRTXO#F=gr?`j;3uiu(1WzFS2KSL$pM<MCtm??k(P1yCcU8G&&sK<|Z+FcDnlx zse;s<PTo8CR^M#Ne{H+l#=^zDSa@em<LBDHHYGn4R&V5;Q>M)}x3Bf8=`}O+i=9gB zx5_VB8nhe^yKA0qJbUMb>;Bn0_*icQ%BQ7eg6DJN9{%{ZyJLCK8NKxhCK4PKca|7M zPFo!KDw`?8b>gys2^lu$ZoaeA<LCLbeE)aVGj5==v*&o?^Md1gaeJ?L2Iq1(3S{Kx zq$CtgVt#8K*}2wu_ntHRWY_ArT)WVzG)c#J>jsw#uM?|4wpr}^ulMViI%p)SM9)3; zfWOVuWriY8YVz%8#`Hbg6~*G{u==7vx4OjKxl0uz?kfK{RvkJ?CC;XL-ouxY|DJgN zmwsOTD}$r;!fTgTOm)*18LD_LTD+6fafjQkH|I4?t3MpOGUfa09l=f0UOn$$q|tNc zOp=*Y<|^L3_Yd#Xi<~AoZ|2d|&4TMV_uN0cGkJyM>tk1@luv!dr_8~$J9^gr_lbX8 zqSj8UePybBHP>nHvZX;^CQNt$TMGbQmxMW8V!Af^$;yYCi+>c#)aRPyK3yRS@{ zKua|;S315H^PJ}OXZPXib&^}wUENucn>;zfrZG<aQK?m7gl<N@<F&{Ar^LH8x|(ig z+_Bq#{;A4?!uZesK8A3$pJj6}np@{Bd@RJQ`(%Q{m8`2*(x-ZrdapR${C?uun#TP* z?)X2o+WKwZujcfK&Z8a6FFoO6RoUsZF~n(7s@7Dl*0sM%Q#}_&XeowkJ>g>QS}N4F zC_rQCHuFlcZF$TSv_(Z+9Vb0~n=I<;I7y|-?f4F>5Z(p#|KEJpaZ~#9bo+kqbpa0R zLbl2OKK2u|VCK?Iouf&e^)>%kjs{h}u9&$=<>RHF+%a+zk7E4qm(5i7oVNWqPtN`C zZl>&^T2o(DftIOkn{@8c_8C78PoBPWzhcWXE8_{9RE*86kMG+S=2sTyy7=M-p>9PE zrt0YE8L^QE)7D+%<*B%HXLG)O^5){6^XEUWbeBsj$dcN8@x+-+MsmxWxBW8kzf(U) z{M@|f>$b`6srY6ieNu#Pb?buj$FDq6ni(^X|88;4>pw!t#h;^RCrzIj-5H=0s-5Vg zt9Lm<T1CwNL+|srBX2htTUnouuX%m@PWAOTwP)fpqa&B9#+-g~Na<rp*TR*VbswAM zAG{1+E;)1N(dR`)Iq&7Fz(<EZJOA(T`$W_I)u|gmi`Upomz8pBb{(p>y?^-mJiAWE z)lb9o3uI4cnSDGO|AU2J*3QLKi<wKl{)eN>S}|6Qsi5@$Hv{FLb^d<0_S_*Yqxv7M z^@pDxROC7;H2b6q-|E)$b{{1s_WClYcsfl=-PFp&w|eUNx+jOv=;=S+cKhdz=I@`~ zc(%?w`{$Xu{kgl<<;FXAxU7s(o2_qPVtP1T?!SP)U4gva^vUP#J|<p!e07y1D6Ecp zOz8?r)RbBppcC}^`^M#4TWdCUsCYi<b}chC{q*9lyJhXx+5LCw=h&{*edXi5H0Um9 z(A}v?;lq9Tz3t47`t_ea1RjwVImh#}=Jw_d4YzyGKRuLV67c%_MycrI3oZvgE))Jz z1z8?wxL@eu)b8n(e}33@ESlDqFrmPg*J^FY{n)kFE?&HJ=CZoKa@N+CKXEQ=J))g$ ztpcB1nY#LhuGj*pE&m?geD0aD>CXOo`^(+lIxb2zFYYD(`FwhP;iEsGzQLjusxLl= z9Zxh_B<yN7Npn_~bHyCLtiN{8!oo7wt$ti>Un9Hzvgd`@N7KwcAFS^Cc<SisFa7?D z;ywkf3^50-8UimXT3^EZ@#0+H>pn*+(rTvN|7ZCo#%BAbQ{3t2ltWYMo?qVIQqe8! z8?x&A<fvmWk6khH+dlKRbk@#YLVKTWWS7djZ&kcKC|Tpg|9_|FJ1yRp9k4RQ+><wI zyGQ$Z*Y@{s#jnKrt9UFkmiSVY^>?57(w_9stUhjszkN!yn$5iG`oVj>SBiE9C04GL zO341ZZ~Ky4+Fed+(~qYa22WE_@jRAdvgf7U%N)MB8jG%GUAX&T_EUfB-K#>ho^ZLY zNfYi2nbn&jwD@4d)tp0#TlcM<AE@PhLR50{!4K1tQ#}{OOf#6><FK`P%h41jM}^s^ z?;AwA1d1rVmVUy;x+YDSu|NIyx0r<vu7Mk7o@G!8%4F$f+q=Sb@x_2Zk)A5snK68~ zuL-@Co-~uEZ1vY!n@d~+J)RfcKD~=e;O>nBZwu~xDE)u&c=+bvr&-=pX8-xKWV5A+ z$QrfF{$E*BjAts%^I9nEddRfVe6D@CM#7cX+w0@3W;+WU$T3+JUleltirNJ8mv{4+ ze%kN*D(e!sBxc&STODhRwr}#<7x6^f|8K*D``-V5sMt;K&fojRNZHufVvU&(8?$$I zU|6yto7(afAFCv0&rL2$6zsq3xGq3t>RF+?J(IOXUP!G=lP~M<*(lH%ApT+VM4wOQ z_y5{`^qF<mMX1+p^VCIp1*sV=Nh^=o+x-tR4VA5Ub#-#bqK?C9Prt6d`=Uh2f4-IP z|062i*@0Qib<-9bnoZKII)1Fs`i+ijGLN5MqUr1xa+1!0B6Fgv_jx@vI(<>%Wlf)t zp8NS17L!yKUd*tpe5w_zy!g%io5$|k{*{?o!^qlt^=s*+n=;LlgIQ|h+Loowh>AFp zW>%P5vE^2|w$#(4{|ej_L;cFXCK%7&7<FdO+jmDZHydr;apcAun@K8y-Rd*qW1k*5 zdiuyCP8l(7&^oRJ_u3iz*7hB@|22!V$-y=7$NKvJyfR_j984E`Ee>Bc?pQQ!|DWaW zLCcSI!dLMAsC@XQa@yj+XW_~{=g$^zTRz=ccK458#rjExk{3Iz^uBz3T)gwe>=_F} zv@ToQHC}(2Vkwqflh-)mzPszRpYiwW**0H1@ZpS()C2zipYm6|4V*T;@Wz@LNh!5? zUZ9;oN^{jFo(s^LzVm{4!_kyS|9}75Zt&vk4%srjFW(-Q@0Of1CoQS2aaY6qc^eCZ zZpx&3t}2@%=KAJZ)&w1Iq32b<D*l~`<f&rz+uhs!7j$6e88_wT$(Li^$S(-dQsy{R z_W0t%nUYO*`tg;oUcSv0SXwl5=F!w?*RFY_Z?1W~b9#aG8y-JjP+9oRd%c0(_J*rD z$1*N#-Xf;DOLBRBjnMqtN6%amO5R+&<1OE*pqafXlg_4e)oeU5^&n_1NY!z*8Ie(H zd%n)wI~|lJmzC-5>$6tP_`Bh=R;uT*G{fS3+vm3>Ojzze_h61m&@`2{<>?c&MR&O$ z6EKl7X=*$1i_J97Tt9x#nX3;4ndHoci@AAx{5Hz;3i7dB$THbewsP{uo0h+hsjv9@ z^M$1B;^KminvEV70e`nuKl-EUmD;)By!ZbjA~R$9UM^L=v{Po0+vyW$c+{FFI&D1R zW_0pT7EAwK$8`Y@o^nq&kmRvg6Lw9QGp0;>`MNSgGvocT3cEqa(#$;Z%j$X6Z^Ku- z8X5{A&DTzz(^Gmaef8Y2nLKxu7x$b!cTs|C(;l(MC*JYtedC{WCS}Ff-x4$DJw0{7 zpl*Bj)vvrotxD;;swZfRCVjN9U7T!F@<U*`)%r)pyH7s(<fEr!WMk`WHT&_U0}9T; zm*1@5H{QF&=lu<fQbzma&BZ1x%{^z%C@2&xtY`3?7TM*p)55@EVZ__OG}GAuBCXHQ z&v9OU`C<9)if3PqD`d)qUh+IGn&|>MOJhll-r}nnmiKS>AAfitZQ}y*(l=RIPxAMF zXLecZasLO)&!ma(CK@Kq2CXJo`LRlJ&a6i}FF(KGvvfoBnIAEJyWHGf%E=y1+&Dp7 z<ihI`AAMcrtgSxh^f&DgOD#zgTYlE<{SAxB+}$^H#ljXDhF!lNDAKX~GLN6{<)HA> zGvCSSedSNO@VaA7e!;HQ?FUb43cWP3n%noe_OHzC=(`&K51$Udz`=Cc`}CAks>hy* z-SAmvasT%5kAKS(&7>^0esxt7^EWWCJn59eyZfq_^M<y~wzW^VD$l4X+b&MNa`ng0 zfBf;s7nm>5;7Z<HJVkZpxr2%>fiA1B3U#Z4PQou*Ir(3wXOkTN;mgKfdiplc^m$lx zW8+L+oBC%mlRtNV>GQuJ!Bv!*(9vDXtkH1&<$=WNYU9u4-BMffeBQ>?v=`sXsrmNt z_>TVvK&L7CZdL4ifB*Q>Mn@ku=1D3GFLzyG&khh_bqy5Q8YOmp(UMJ(HG1M_A6j`m zHL411zZntx?$hpAopr7&KUS?cA*!P$+#1w*ETCh-b@!DqZh;RRs-^dTo5*jxbA!ja z3G2()r=_k@6Be61alv`_9mo6^hAc9bIhMQqvc2KPueo;3i!^5Nu<=y=En{}yef7|} zV^vyStbvOUCK)Aej<DF3ZZ7`ow`cn1DPE~tq<B~6Ok0{E(yOpx^+v(T7duo=-#C-T z;`>#4)6tAa_iNrL%iN9KTk-mP$oyih*-vx)^|PgCdrb1FPF5D1+<Cg$`Ax=(<=5UH z&M{HSG8OSoHIZsO79h}nxbyl;mq3U0mlL-~fL0%03!iN*^~Fjh@>rJH!&0jZp4Jr~ zE4Q21GPf|-*?oWV_|5H$UcJYClQmqH201Rj9QgXXFds`qZ2a=#f{qBAK9$oiN_V|Y zy;Pv!pfq<`fKJ~2{rNR=x1?TeH*c+u^;?r>%ysqu8^`t2+Y&ZJT};XDJh#F;KxcZ! z%GF07muy;W=i_Y9aWmmbO}zc*i5y3RB%9-0lsQgp>N%RTC`2n*{6lcO@QtWzYXanX z5=<m+T)ooar@b$8b46*|3RV`cr>}Ze8HVJB-L$oGtM%nw`_Rg4l4n@5^b1#6--QZN zy==2@9$9YxM^VnQNMiL(pJam*f7!oZwlryR46oh0Rf?B);e&6_W7M-EyN-F}geGRL zUB6uCWJi>)*kn#d#@$z)v?d?T+qyu5OKfsy(n=TS4Q;y``jdA4iThU`cGoHE+XLUK z?Xw-`y?&XjxT)=G&Z4#Z<~`dbuzYvbhh1}K@UTtkI&|a^)A4Wb6es#Ab1*S(?=If^ z_o~?^DPG0-{V8gPSFVnYk(7G4|IfMn$D3|T%wBu0V$w{WzrvGkYJMn8?DgfTvXyI> z4P5<nr}6U(874MGPYi@VbE|BY1kI71JD8Ydljjn6BzJr8javmV8dER4F8Si`BlM}# zP`Y<Vj+xl?MK0#%oE3L&=!(5!stZec-E-#5r%yk<|Fp;d4qYZLzLNXL&FkBkSNs#Q zyMEc-b5aKH^+e;@k+<(0d0tesFu&p3F}7Q?r6lLhUA)t*#ZN?Xe!N4Vh*O;Y%A9Ev zXGVUhvi-_v?>D<Q!sc9&$+26<)Oxo%PMWE+wN8HRL#w)qpIqf{bCkn10$zWfcqXm$ z=;I}uL4&IgXGtxZeRWfq*=Er2f}BlBLxfUe;QHe!7ba_qWN@%mzWn1l=_L>2`q>k% zci(@zEJDw4>xP!YS*i~TmBUl2+>URIUVEkDPDQL=+w!y>{~y%3r9Z#G!4$T6=IX=B zpk)9qR?Th#+jjejcd4d@hy8eP*IjUHlv`Tb#VnJGSii2NpTbh77-?^O)ngK`GwI~> zm4&-Im#-EL<2ovI@vLvu>%%VQk6&zGry2W3ennYs-2DTo+ZPI#^7#8JXSp6?wAb4` zcj;EsXJKJGpRcQ((aRRM`%dTahX+!(3xBDyynEHx-P?HWLo3iw$rdrt0_%+xGK(Gk z*PeGj@c3Ys*+ol>GglrdsWmsop7k}k+P34u?f#=VhaMLMXiS?C7xn1Dx-z4kGE%*5 zQvI_x-`#tKJ=@^L*DF73LDMIEe1*GKPq+W~R$u7Dj+t>$$MOt=wY+0w<sLp%Zjb0) zn`}CJW8|6q-%>AjyPlQXW4N{WW9c1D$Jcj*0!7rGJu{T-HOZ;X-Y@H;uN$~hV@uoX zE4y0C7x=8(wWNG+m)?6**T5Mu5iTOGvz!jz{$#wAZLM^0@V!um43@@k%Z`1omdL*t z6#l)A-|;Koojld;ERGA-F8udbuI*Lrg1F1Oe5a^(p7_PKv}op|u#dOP7X_`Hpf7fR z>BZRDF)KGr^oiT761*|Q?cT0;pWDnYt=;_d&$r|yYjrlsFW2C@S@TbKyLi|8KU)J= zhLr1-E-Rh=WBK&BgE=NS%iq*}c(+*PlH|8-+a{by`CzqrX4OicX*v5GoL97MyjkhP zW*fCu%r(&9MTyC^wjDMWF1@$UazEGmaNyuylj~QF%*_2SymnR3`e-qC&GFSMPkb!t zO0F(5wlVJ33BPgmj>r8QENj1(rW99-U0?L({>`?tNomG2K?esp%f99D^)t3HKK$pC zR{#Ba{krYafvXd9lZCra9yzHU{`14$?-M-IKUlnZQEDZ2{n`sj*>wMG?%%hfUP{Uy z&oMDDF+IDt{O#hsD<?XwJTmoQVwtJA(bf$ur}L6+Cq8*GkMG!Xu^)-gMeE)w%O5M3 z);qf@WL303Z`AhAT@CZsJq-NzHX~6}>hY7QdNN_4xx9`j-F`XiQzy>wgtxmD+*tD_ zCr4rGNrUa1PO<mNK1@j$Z&KK>*skaJ%Y-^pC#}g(KRqZg?X{WvFzCO6-tOMx?{?0f z9KO!Ta{rJ2o6F}rPMY()@%jI!d&}Rh+PmG@R<8Nr0RaUMhA)d;^fcFMtbOBIU9ILM zUM;=7T>e|htsS<lE}5DWnLIleWjxp`{r<MEfA#y-yH~GXwR_j<)9I=A+GR{Qk_;H! zjAuwH)e8#8&W)V;Gc3&C_Upc%&puxW3O<{bH2bN?l&Kz5I$JBvggyPf$GNS(dLbtG zZ1!{g583?oN6PE|@i6w!zM3&bTX^!D?99a4;_jnY4bt`F52hGghzUNr(fjU;Emm%6 zX_7N%s!l!|DD@#QS}p#()SNj<C1um5&B~f~DErALCjGgV?xm5MdzBZ@*>A*f;K&~) z?$xWeT)+D9S*!OM-Sv}BrR06KUK*g0r=D8zfln~<{)6cFil%uJ1AD4$cdmABS!$=> z>eM(jV@i&myV2x>uS*tP&&pi0X32@i2cH*BJejKbsp<qbld7G5*=n28-B;c#>vL?m zdNsl9)OWG9F3C%bZ_d40a{Hx;SvPC@Sudlx3j;I)q&_^{bTeb^%4Go)+8=KV*5s*@ z)!RLH)g+-mdE!=U#kL=Aj9Tin{BlriR9D>k<8QZ2KKt~<vrkig?3wX}E$ejiiV5r8 zIh-036dD}YFJHP$YWi8Xg$hA|F+RQ<rg%FaUU4<6Yp>lattJ)YNF6n0zuBUmPLfI? z8g>h(+-x>~k#=4#CWg28S&@D2R#ORHHldR$m%SCsu3lI45(2eNb2HUsdN*#{=$Ia? zoHe!U#4$GCtD$q=?d@Ta$;p1YwOBl3g^v5`iwiDiO;jnkp|i#%sbUVFUX0{|ox7wK z1}HozoG8w<r{EP&^5)_{^Xq?9&w2B5saZr@)Y^r6G!7K0I60@X7N6EG;pP2&;GXT8 z+?)r676Psl_iZe+oV@#}kAXl!LeZoPQ7yl}zgw7{Au;=?&w;ngPP|Sv6LFff;Kb{P zDgOFvx0+h4347GZ!YeAO5~O)=N5RB%$JjPiG6srh?yJhba^;ay^leYREn6p@OkJs= zw=eT~{K6eKr`&A5zTBs>UcTJ>!mhb3PK}M7o;H5ZWleqK7Vem>>G=BB6wUWt(#x)9 zyvWJgbN6h3hDaCxl9<au8X{arW1TspxLTbS?#R|~^j;XCAyUr!bk;T9PiJ13XrKI^ zR>HtB!?$MX&S%Ma6P*?Y-1$3YL237z^i6**-n*6^Hvezl{S(#GjtX<iguQO}`!n<G z>C8#@^c;(HC#l4i*UyZ}TfXFk`^3}F1=q<{Cue)>&8je6{PXu#<{O#bR<oA|2n4R2 zu$tvQ%f$+r#rHN$R?aux*n79?@zhFDuA_53CFTCi$Vu5$vpZYhqg3TDhJWu?rk59e z5M38m#%ihl@b=c8PfZOPo+4bVZOhXwF5dNiD1N<DXpzPwah6RxW&HP+%6LvX@$|EZ z%fu#)NvF9zCb=wBxMXhScm2YLtGV}UH?Pw;wYBHoJw1I6>;3)b&lYc5&fg%v_m5P# zn%d9V^Z(5Gx>lDf{I&hw+L*ve6_5X@CVlkfTGXMyQNrK*;ndCIJ!S8d7HPbD6aJ(1 z`mEF3B3!L=uPb|f$`)RKEkcN;u}MRzOKE1#wEh34&!2oQtt{>|e|*i%96SHG3EzWv zRLKO2lxscT_xsPiRpoID1Mc{E`M(z9R=-@~!}jm-NAEY<U-#E%wy!?@x#>WET;0^A zAEerE-F_h}n_QPV^?095T3#h<`_)q?zVNul@qa$On#a#?<My4M8+TUbh#5=Ij%Kjg zP_Ms!-d=~&OwGNElXG(OC!c$^VU{mTH<OR<3G-KB?B14lt7o>I;@bD?#PYIP#d~(o z4%$CI*tRxjc~FMQthrhTPln7omsZ(T<0vvSI!;ljf3jD4#iyO(7qd*Ru$`8eHEY@4 zb<?<+i$d>g4-OKov|SORb?GM0{rZ2Z-%QLe+1eb6$zWX@cDiw!n3}j)B-i@DSD%}_ zjxtw&H!w4AcU!9#5prbbKkXM=qD-<(ofaPW@<@nTIGD%JFJ3o*<G3DpaY=@*Q)s4P ze8q>lIE%`*i8CYblv#g&_ijOY%9NWIjOu^x|HsZ#^>^)W=Ku{6^VUn3ceSc`KKgHU z_3ZXI3r3Hc&1?TT=PnLgdGn56(W2ec&)=(_@oiU>-`6h_Pe128eyz~*jm+KKCzZd; zEKrL$W_;Xl(%GjR$FF6sS(Q?&-Kf!3Vs<V5ufnt$Q89<|3_qVeZg=?0BO$-pz31%< z<m;w$@4k8}%j8(+ySRC_bzFgy1X`Gy6gJHDN;Z-BaV&X$qN<SV>afpK+vQz~O;60? zVXOQ6@%*O`2mj7_@h&wdt*=B4G(x}p>ZWb`9CHmi4yPp-WX<x?b61hOU%7W?&NQDe zzwad_`RbxaUBB@3f3l9RU|N6K(c9Pb_3UT~o~mot%p)RrH%s*j^&Y?Jp(4P=y6@A6 z<~O;SNqLp6`8NMFT37E~|L~<`-Sh7GhaZ<rIQQ(tbJj~Ud2+X!-r1gRo*(<_*=c@T z2j|q*OP7N*-U)#cU(m{sKSvL@|2W;v{O97nur05?|L;q<^!n$!%jX4k^pfgQr#9U7 z_0BcTj{yxo$^8HJx&NZIk(=wrm{0d|Oo|E<IOd-|`o8ul_ncQdeKwpp?55OsIO|}J z$s~P_Gdj8xz0x(gSvV^0WNeknYD!&`pZD?EQN3HQvjSHh$TBJ}IiGhW{PvB2$b<gz z_1u9XD>XEomR}Xn;hJ#rS;fOElJD-`Wjs+j?cdL-*C(j_c=oveRA|ZP$}d*3Rde|^ zU+lP@s6Nl5V8`OQC1&2S1|82{6+Y_BJ@+Mc*`g&9%g=hL&0e~1(VYGDzbwNR1t!ft zYOzM_OO)=}tD#T0nX09vXU0b!%`kXSzVkwMDa)O_Z(Gekdj^}%zjaw&8XOyT=)Ub& z9qo$}?YE*UpZ)N>!^h4yTXgo(Gs^9JAMSJpgEj@m{0h=|$LA%rT>6V+=A3`)%4g`C zhQ=4)y{vrs&%t}w_-&3II;EvQ&(7Oy`eXln-$F~~Pbe{X{)=5=&WuAzW*^TUw=X{Y z+wyMt%!w-{--Kz$|9`Xm{^q)@!cOyZ@hbWpfB55nzw%QE)yQL0?Y;a}b0_=#<8Qg5 zoU;wpu9>gjx$fN41-cJ@1{^=h&6KtEm+;rdU*C=htquFVUhDn8Z*?V6Z%xw$_t`FV zUVE`-(Yf`H9xr5B`#QLY|6XF$U%9Bi@_Gi1e;9Xdom+F><n8wAaHoY03L*wl_iQ5- zW}jXdwDQ91lK-#F_Sf?4_4C%6d^F2!qF1_s#25Kj&bE_JFAQ5L;QG?`?H||taD%%2 zFW=p)k?W26yO8<X@3-&Yepd1ndg;S<S^uuwf}oWbVq@p~q;HsUZ*SZrl|vg#i+<Xe zb+b;t%hsUbnX)dd)l9ngQ}uM8MOQNdR)=J)tMj~+Wn%5TbN`O>DOSB#bL#G2pL8Z= zLtL%yBo)El<At~1TL1pLpm^fBG(p#owf!FxzfC-qGC_s2`{b92dD0R0@1$5ybz6Tu z@JZ$O`}JCrZ(54y%QHVIUU6sEf*%`9%-Ubu-+$+J$E*I6dVS9;v6^nNPnKuQU&<*r zq*$Gm|2O@AyR&Sri`k=?nKO>OE!eO@DlMZ(YGJ^GLkAShx?5AUd`;xiE2^XdMLg3t zpIN(R!^|6QBCc%9pFCAI-dr))@0Z*0$lEs-+<2`z(QD(@y}miclU<CCPVMC6v9di` z(sun^tb#~qKy28l_`j$9Ew9`=Rz9yzto`btM_Cf9Z@Qd6A#r=9$Vwlvsa#1PEs{5X zb}=)Pm^CXcr>sx-?%o?ZY1fjZUu==8YIC2cBDnmlo7(ipKJoVXF*{spT`liAD~nX_ z<?;31yl-dg`L~a5EX_08dFN`=WJ5h3p1>!C#+yZwvI;rduO2$^M5NMDVd}|(%91(h zee+$`Uk-Zn^^&=npVe%~)z=FCol<CRI#FKt&xEnRedA5bm@?_Ti<4D?G}ovZFaPz+ z;@;Kf`)`wS%H}1_7vJjTsx|rP`ThT$&$uZ|_0F2=(eiSs>ZhMJ^<N*)H#D;Cj#_)@ zec9(T8-<q`MOL{VmzY00y`pN`r$<WjYzu{&<M@8XIxAPi`mw1k^GGuSo&5Ud>zgwL zI-gE_y|C~1mtu)8RcTJAml#L>`&_=yJJr+h;SDRd=D56SqoY6W*u0)S`^je}=}wl~ z#gAW<M*X{O|CigWn|1O<kM}1u?6!9|c6v@blr2)dw}iJ>L2;tTvKO+lhwHvdX`J|e zVeY%VXQHR?3S1eoLzYi3M)Jtxf`kjNUr0(WO;6zooOB_}q$T-vPM-SAn1}^Oo<BW5 z|Bri#mF~=(X(eW-lPu2oWJm^z{LKIVMgK}T%S-v$2i}%^cpM&=UXUd<|8!^E@?=%1 z)Jok$C(h`o+UYxAHr83!QfU1qCs+OCQ`SST4YvhnvZ<+k+%@M*zwZXA-oTntw^wsj z=ATzy8Df3CQ}n%>r_lX>-|p8uc{^o6X>(rL1*?m9y93v&3-w<%w&^<lGNB@C+8%`q z)<#`niybvYb{N^6e3Uig-9tg4lOiv3`krP?3Eo@F;}2T)wjgZvkDs%Td!`z>JTBbT z<`&U=EMv_og)L%<Np%zdZRC6w9(FNnON@lXlTSA+>b7$)3|O#pR~LB0aZ;h_nWK%4 zVM(u#2y;$5lzm30)#Bn+XSM0cwZ+_y0u^8HRNDBdr%j%?^($|c`>`1@F)9;%1aIG2 zQe82{`R&?0HP2+K=Jw58n)>Uw`U%d;V`<MVZWc>&c3zv6wM=aKhDaS2o4mGVX&h_U z8roT(zwm`;^+pNpixPj6g-dvOg>T<DlDXN?aDT(egp`uBY4aWi{&G8Z!$W0899QD@ zSvT+aC0&w!At$Lg`K+Op@#!CTY`9k^z7gZzyfC$GdD;!X<tw#8qq!%!ne^w|wI9t< zdhqeXmyN<NwnVvjf)2*<SbE|~(Th^6D_W+<cUKo$zqz3+rlTf&uwnlGzc+(_#OmGK zQ_(p`!NAP=c#+Aer3Vvj{Mdy*bMLA9r}SBSH4AfHj+pUtcD5Jt^Iet(ExelLk!Ez{ z(QFs9M?!8##bIj!bk?ldv~lVKpLqMKxqVk}SnXY$9C23dSlaUw+^j+?MP}c=9W!%= z%7en<%z_!~4kiZ8)H!`o;_qYO7#WEq(`|i6Qx=t{Ou5_3%V1Og$s}#@#G3&fE=ET` zTrr70sZzT*`Av4F+xn{?FTE_zFwHXhDU<$ty@BO^2Ukx+S2_Otm>nH{i;pI5{q(HW zn}xY9&azr=uAjTr<iwP!X)$pL1zB7Sq5@Ifk4mj9%T~63{>!}MP1&*MVxW6iO49mf zZ3_C-bl~MZyLCQ3h6a|c#~&`pFPU?1qv17k^OZWfmHz%e%YvJ(eZ8A;A?VyQ*`$i9 zwr8`lmWfZ_Fzc*I=t<+J=i=U}i*!yp`P4v?C*o{cQPY8m=VDcYG@pfs3A8ZnteGdY zpTF79J=UP2)Z=u|*_?&zlr+Sv&v3smkuux1jbr_BgBPV+u7xeWm@z?xbNk_qpL4$+ z{9FBVz5O4-?<Js4WZ~_%pxwMpOMk@p?a@<TKgZTTGO*#^MZ>V<*Bz{ai~Zh(K54P3 z+s-}tqDOG(Q@?AydlVj&-MIL2%M#<rk|<eKJNfUW?-te9H2Ijdvpo6CRO$HO(gTCf z+S)m)lO?`b%?W$$=hnB$fuZ}ROKPTJ+GNhzM}3UuD(Z`9eEglcZr!om?Z!sN?QV;o z{W-vJI$N;lr%i9@REu1*O*>`s+GW><oql*%c8$y8H7<*-&7;l3LO;yzw|A>`osbaN zu<DYKiszvP*8@YNd}iK1|0StITR7Oo%xr?nPqT*Y?b)lny(4?wJkyI`m`MGRGuKjh zP<S~Y&{1oy;`H;6i!BZJ&7JAebZU~4R#$g`Vmhzki?1_!*|=CI-uh(JwMTB1mv_dR zRSs*z3Ll<Q@P26Ew6Ni1g2U3FKmpe~W$Y_`X06&3bc(5N+qUhRB2QLbG}}D$*()uF zefRrTKfjy1eev!pTf@0$7X_`<`1+f{qCB;s+Uk}D?~l%-=AC&*o<5rI%E)kskA45o zBk7iVR?BWb>=^56$sQH`LQ3jTipd0F7LzQ~qjCC^R1_5#202=YC0kEjbmIBabv7Pa zlaD2tByEp!SgI5ul2B1Kt!q+}ib_nG^h%$$TMKIRK85F>3IFpdxGKv0McTJ5pPCx( zCOr&rm$uu^-GA3_gGR&Iq=R`I17gFxYF#ZEx3{l6s`_oKNurUIAWP$KtMcGzxg&X7 zA8osxxpL*Pw<Q-MA`gZso&2{=Y>t`q(K!9M>B9Y&4<=Rgu9}o2rKR<8XUvVYVr8aR zj1BiYqz5zm&E{QwvgP{ACl1lvaof37%C3b@5ebeA^2y!MGi_GZqfVCUSyC(4>nvZi zqoXNe!O~q)t53RQ=kn&Y%l2Pxy#IF5q8%OgCK}$#%HCOjUv8SRAm6s_LcRGx@p4PH z?crJL=6wBw!Rm_=x~8EKXVc0|uL*bO7bYf5$hY|>xkZZisjKT1w$mSW&GDG@=iu+3 zzu!A+h-iGR*5v*X+2>O6WFB+MXC~D;`LCi+uS{jv{8aH_ckG+|+-3PWbNYT&`G7a9 z&PtGs2Cs8jx|JhbP0cfXvq{Lb;76YymhbjlX1wL<wV*fOgC2dK=#_rs{w=54RLiNV zs%!G|0t16wR^E5tc>VOhYiWmGzn00#KKi&sKu2rQjpvFFz6$WLT*%zI<=V9cVXHUJ z=n0uNCE(HLM`brwYUthLY+=9k^!w%4B>|5<KiqWtgXP>GF?wD#cC%J#Yj!C4UJWg| za^29z^lb9?yWN-5mfm>2bm_KPHE|29BD_jx{$V|mx3Or`^6AfBX=!<Py_A(*ymw#U zs!Kt9@3Yjmh$Z@a3-hg>y78vvBI&|Y-Q69>%rn=mT(r)n<NQ;X)f3xU^?CV(qoNnD zT{lgszy0M>)o<Ik28eN72#P&=EUf8o?%5wPeod~fTdrOQ?XH>kOiincS)_WeNcG;H zbLR|=j1Mcf^Cf|=wb^nlEcn%T<GnkMr1#%xKAg4m#OtH4OYTg0y~}*^rOUhaNx#k1 z+{~VT;q8hToh~I~Z^f*p)bcw&{;pN)5=t&Eez7I$)v4y~yDj$@ZQHheWAxhXyCto; zTA2<TZ@!@`rsdt0UtXNoVO0I$*OZ&h^BJ<X&bsCQf_+=m+FO#Rg6`Cm2OVI#kYTdr z`qg{y(lp*Vc<ukn_u-pK>V)MR{uh0^#s64*@_{CskZC8Mg4T)`@BD7_|LxQK^o0Kg zpPC$$X6|~nEBozgg|3w1opZ0V6}A0vTKHk!Tkh6FTW`<&n~@u$A+rD0lzG==9YkFB z{hd7jvwiL7*ET=zbla39$iK{)b}M1R#hH>ee(Do@d99>gfm$-p%aSfh&xnm%wshI7 z6syBC_nl_xW~!L$$DkxF&Ew;<arw@P8*f(fy?=G!d6AKkv2%7V@Bi=ie;B5EoqhlR zmUtxB`ip_#$CE5{;^$}OIjz39K_pID?EaE<N+(X7(OExtw}bD7o>P;Oq_njo@843H zKV7|1=KZT@+wHzvO#aM$C3K3gzsi#(drpcht&`vSG}T8}Z{x<93X@M4t=QYEw7$I} zY4*gKl3Lzg9mgK8U|6VdDKOsq{tb)eRr;Ub@BjBYBmbbldZ&duerq_s=38(vL*wgj z$vJbBrl0@3czXQd$0Y{)_Z)hZHKW9={cO^)90MVLm5QftEW7r`dDVdW^j$Zeso5=W zp6W4WyI$$y%UPN0SG#J6%!rJ7R&qb}jGD6dL(`ZtY2$^dXF!{1+S2>y9!cD6Xk&Z& z&nF{YQ_~k)tY&4e`tf`D{G+c+jP`Fj^yidT*yhN6(@(v8GC!`W)y3%K!oD)Gu<*$H zULUS4)qB**lCJlCvN+4Tml^8&cb<IkL}WT!`;EId95Qlw+s~dlf3K$7{_m~zpHIy! zUX!0Y(JQ^<n7QQ4nM<#{Pd1cMn|yYo-2SpK!B(e_CztT>-&2&kv%mfSclr7=joZY8 zPO5}W=A3-c!8w)n`}?;l6TJ%GonlZn-t2PCd_&}!H(4v(g<P*_iK^Dw-`wM1H1$~S z=7$@iHq7!}5fbp`>!y7>PhR_GrWH~#*KdxQwp@F&PncZa7t6U*elnYchE6({rXk`Y zbW&v6>bDtdRvma>_I3)}$!Ens?&j6#smrx9Z$EtO+BdVGdmIitKKQsmK!;C3F@0XZ z%8)D5rY9OozFe{1dHvM%s#23H3omDtPr7z(D*H+u&9vm~?xgk7v#%=o_lC7`h;p%d z`M>UaSibw`vE=?Z*;$v3_HXjaj^*7MGtb4!cjo=`2fu~s@$p=Y3ij>1-+nnSIexXx z@3e}lHs!gpBGtAjn<8($%IaKm98_*BT{bI6um5n`((Hm6-*!cnNbySbO3glc=*1fu zS>Do+DI$SyK2JLTeB+Fsn#UX6XGX^@UAu0YkDmL=`~BBnKB)j5toeaaXr+kn)li)^ zZ7cP(L2D=O?YZGvTq@ey)Nwm6J-k-7((yosLBY3AqPJeX`mk$`OvYqkw%NUIIcdVb zZ+|<<D(x!ReeuM+Wo~}oW7EQ&WfyMc;9Fg)-aE-@;g2Ul%l6z~aNF={?81OMwo^3U zUoT%Ad~fPQ$5zk?tm%{mOF<*JyW51eh;X$!6<!Z$n&z}HK;xa%DbP6_H#bI3+dlbv zOn8pr=cUVD_3v~ADf%AVbWK;td->1Bd)LNjuYFto+wI=woZ8~<vu|@{!nDISb1n?1 z2tOL_u&@4fj@!~8MbAsVp0j5AEH`}h^?k@uUo}O!_87h%w+%NBq%=v-Y@F%QaFt8` z%DJ_=8*V>6K8fY!mYOsE5kU#9P9G0Wd3ezJNc{gN={$aZpTGOtA3yR(>14?)@PMe( z!Uh%3KZlF;l{i>8{j@nRXWv@!wJkbOWTHyu^UD2u?&_}-b}dx@K3}8D=I^yarH?!A zbR2cHs1*A5NI#(_=3i|#Hwz;dtAMNJ3XVg&<quoGc8pW={Ln1#prvZBC-UTJ`ndxi zK3Jbt;oSE-w(@o_Z^dI?38_i*7YAsF?00#Yc~{Ygjk#aO${{$E_5YVo*>AE|JTA$% zubw5{sV-!ZYxb$>K>0jSs@Yxf@Ji;kNw;f$U2u%Esuf#)*R4d^Z^Md??RsT_(Q$58 zlNWAYDY!5op(s&s`dzpCFD&GiH#g_5jggT_GTU-y`Fl$h^GA0qZ|s+!SH&eJ_T=8V zo0}J0Km0%;V{1S>|H27(x<6Gtm5a>Qo@2py_3DOd^F2S+LP8vL)Yz9y60(etwN%O% z?>vyb{^ak^zn`Yo|GoZcV|=~rzsvQLZeO@nRefKi)v54!U{zH4jI$|1-4{L7W-s2l zZPtlnY&T>2o_e$dRP+X@IOT5WId{yB@BOO>^7CpNkFE0Ri+#0Bq3g{0H37mpPe1;C z=PIJA^wGj<t(fPe8FS*7?Ag(AUUqN)<5=4}*LTjYE-zIm{QB?H*V0Oh4J$e8-hY4a zBJf1YlLKFFB!Aj<(DBFL`_tRs>BUW{_TD%{rsmqU2bWZTJTrgj9nZ8qx=yCkAyo9u zU2XaFG`D;Ir0-AIK6lon@4>OWyUQ96GtTxp=h*7>G0w~XHDBVD*FW!VKCj%R)PJwK z<3be6=94FEWpnqGuAJR)+}A)rAwuNAsUs?tiv9=Qs>N$;*u8OHiq+XChm^jGKF!I= z-MDdU>&+CG^;eCyZs>?wdg$$j$Hlu1B){CbeDU1TM#V+53+Gu>t-sSTNvN_zPpb8O zjr%)KOPNnwb-P(>>{hI9-v2k+a)#}v4w)5QT~F>!zsSLF!|?yl`G7dR{PkB)*|RcE zoBs55>d~X`<G#;4f8uw1^yKCU6D@hrWJz7;q+>7HY6GN}?|(1*?0VF?*dy<j9}fO= zaNe}p_m<Uf-D>*c{q*LGzbl`LMnp|&J|(`tBKub1!=^jMt5@zc{T;4h$L1xq{B^LF z`29q_DWV^*ow;OsT~>#;=FHlk6aLgyyjb|!{`p1srw^T)A70y<{QsZy?6oTbH0qve zI=&Wr$x-owqav@|*lrg;msr+T8=ea5+Y16T>^4s6lql~wdexx*_vPh3-rLvDI(y{X zxsb2ff0-w!biO>Qx-IzSYrF5_+i%|T`!sjH{o(KPD(5}j%CT_kiQU)w&z?0lFm#O* zsCfD1CjZv+@pXT$9n~xP`RClH$+n>O(nVvNQ-4mq+Py74`u>9IjF#fR;rAlzdTaN6 zzi++1zNYTs^m)hGbAI1Te)6gE-j0Howeiz6y8e9mY7U-Lxp~1z*?9B&l^?fm*mR0N zuHxsf<5N|R@MmxzsQ>%0|Ho?i|5Lh~ov-Iyp1H5iXy=`CpQiiGfBN;axMs}Wrw^L% zEzaKCpFh9-aqL|lAD?~CE%z!fUgMU`(RASCynWyAzQ6su^644NW#ZE-zP|Z6_v`gr z&z>4TzgKS0b#$wS?ON+2=kHZ?-~adL@tL+TiTU%N$NXo=YnNSo@4%r`Twg^+mu!x_ zcJ2Dk`h0c!s-LD=r<>no<~{LwpUNc1zq5vKuAh5OF}F(R-?eA=RJ~)8Yj3vy*Bh@a z(mCN=TE^P7sa7JB-e0yVW9p4M`@ZHOXV+f2e;<#ApWtS?STSe+pXc)f-h7^PE`@>P z_%+S1zcoKqfd*>kJ#)La>qhI*oJZdL_s(-KKeu6r)UmX!1s_i-l!`vxQ}&MOtLW1y zKmX3zZFJz>u_`vTWdW;0rihDwe0J1(MS!7+rSCq4f(?6npZCo_^t$MSdi?Lwbv^zI zE@nu~nd2nDwdUBhmpNJBqtBNL^vl~i9h&}Vs_}CJX<yJy>0#k7bFv<s?T$4G3pLum z=g_`sY0IWNr4(Dfdztb4=417zEC0V;JLlbApEv=JrN%lfhwtoOJ$L^8N}1V5&&bz) z)t2}Qnxd|Ja=|f7DNyWiHjkg5aNp62M=u0dd3jsd8=MHTI1^@cvi|2i{tH<q7P(<% zrq_(6qtZ0@9Lu-)#i2jXs@ZMr!ITS|=lXqK+5G$G%k2C|-*^0+zyD_`!=;%#{PK7F z|KDKQ?5(IIU1(QYVDG=bv}sm?rtRUy;j3NqK@H0@K^%MIj(0CVSMdHFUz}xe-_;vz zS)zCLm-DCVeHV`E{?L0|?x{;Tzus=y#RnZU_PF_O=+U<+m=b<&PI^urU-!uqNfw7@ zi|<~sUL!rL5Y#|gdEfu~2aVJ^dC(+>t!%E$?ki_coY847Fa5CD{NAC|?Vp#&|JP!h z+b3+h7ZfS~|Lwm2==b^k9-*F`R&%F4_n&j@eOd96VsUXcwwpdGC!T-SX}eyL@IP)| z%`?^*KI#9D_y3eK>;C!eZ+pm{jZ@}blXVhN-4dm{d130jns=^;HkMAiz9?l=<i2k= z{e^pvTi(3v9w#t^Q}=RIc=P?Ii^@}azOL033qLI4GV$<ks~578puuI4z7H>K+YMfn za5Oa>&U*M_o-L36c?0RFG*zMGgrrFoN{%M`IuB>LE)6PNvs!wso3qWt1idXiUP~W! z{_cCQ>2~D(J4Y5=R`e9wyij1O>QT_4pvKdGR~Gz_vyyscS^kr2W=!AAr2?|NTP@av zZTczm{P+3?8=@rU%}cD!=I%auqIT}?mFqQ@m*>oJ(K`Dns)haA+k;s~lf_wznjG|| zr)$r2SsV8G>v<cejNINDyYtiSzA|J@<yw96NSM*dOSh!L)zk&KSeJ=S*Z5RXk@4To z!8JqI>H7zclO?k*+>&zt{^nTb=1cZw2lMOyasJ6OSFir9A;RUO-<GjLBRxM@_+l?F z*P;{8<t@A{#2%kIqS6`CWn4R5kc;)%G*IrF&ekr_!lYjPi-YaYmTOl(+?aTHja%}K zGoWRkcgn2U=FZcvf5o^a&Dg!{eNsi%toCp3k0zNE?RsydKhNrLnbp}xucV9@rk;!0 z=d>>%K~?DJ+YOs%-dMJCS=Yv!KUcp$`03pJ0Ps}yO|NAJ(!4c)jpu`U;z{e<mFMo3 zm@z|1=5~Urkm^LAk8Aa7`YuGVG<3GI*8SIxKa^oG!9&gP#n&s-*k?w?sB98U*WP({ z<-E9WTg^^SU0!N+MooDVOYv##D^sR!+`VvK?^>1>A#3vU5-+?w`D9bh@=HrLMP9n8 z<Nm!YX?xTQY3ax1`+r!*lv%4+>nnFDeO@T~N~>wh^{bn9?ya5uPhIO>iPwc)&Nfv) z6znS=s)~h$|9tj%{=y^Am+Cw?{JLn-^;a9Bb!>_<?5*bZotl(1$4okGbLZc+x)pQ$ zPIY&Gu$Xg0SB!7#_J<oHG`N2l%<i$sDKZdp?M#ln>oLitGO!_Nf4{A7?~b=+cfv1g z$lkl!=(hIR!N0!?ZoUbbI_<%xn*yqqr`w{|CS_Ey^}6+5OgNCbJ=sj^#?^rHo$KPn zriJgQe=o;VWovpcNJq{1qYKmYyXW@*H{XBo!4sa{Qm+cFWu}OWZx-sEcrMNI!mXyW zIm@oRKb~dwev739$A@P}^@L7}_{|ob>(_ld?|9nA51(d&rVB!}M0rI;r~KMe^XfpI zNfxhZYU++RW!r)^b<~vE_Vyi?eH-DMc8ckf;TtjT>RHl1|9#e<B+epdw}HPm%DFUB z({DF#_stH!<<6@w7VP`awQws(=~Kr!VcPt%H`>EiFWj@EqjhTNzJmXO{~quEoqK3w zsf`~y-)h$8xc<1+$t7iC^Dm!_p1zB7?OH<vLr<&OPtQE9i^|U4Fzc*EZWyRd*16an zG`FCXU2^66#|QuRzA%;gBPTvdCEaf0%(Et8p$nXRLnAr$cJnU3>gAlu`v1oz?Tjl~ zcgn1z)=uksq?9x}dQa6io83~cHNRDAeEj`kcg%||QZZ&brAn$}b^rfO_fNbeU2rRB z$J;WkuI`K#YmU4x3w-nSll;DqrJzahQz<7>HuLzNT@bd~K$3TdY?)4)u+>^N(GL&) z?fr93-2S-naX+Slb^p1xt$uzdacj|nt*!g3UqxQY66Ke_(;u~T*`g&J)9?0O%~6|u z+OV+nMfk!WuBWDamtGR07j}o&CGbh><aCcz<3G0!^Dhiu7GIwO>d7qksSMW;dA~4h z_0L1i?)l}$B3-lHB;`WzEJZOA>^9!JvGi=|RXuB7x#!34D1nx%{023FEbVq5S-e&B zdd&A%PxgSjLyy=r9AArF%(@a{ksGr*VNclSdx1CKEfmz_<$b&%>c^?&a!Pyl`K5Y( zbhmourE==XAtv|lC2`*?_bMk_<c4K6rOIdix1KgFp+v-Q{<PDR-rUz0@5;%ZTr6A{ zV*gvR=IiSBfA(!vl|TG`y7%;knAfYfi_6tT)Wv9=5bf)indm)7L!`@}<!SwI*+*xd z)_pTGUl_LfrKIH3os*aUIJ~~5Gq`s8&h^FS+7mUtiavEQGn+9Z-eLLWz-QkLO>CR* zKTWEuY>n;Z-Bb3BDf_kbm8tAIjSO8=Jq0%}OqH`Pia57!!ue$5Xp4Jyor_CF)tVb` zUNEYjC3VwBEpyG9grvI0nE@PY-A*_E{{HFJ&0-1OqBd5Cbyj=Q`(vJbyjT77RwOfX zk-+Tv?a$J7-n({Xip+^=(-r5p*ZzL6cKd?O!Fn2%Z)U{QzkcMp^TlIk{sSK$7hQdP zG0;*%&RQ+p?B0HPG4ZFDG%jkWOuleWPk#I7Uye}=1OB`UP)oX_`0wp=Idz%n=Rbv) z7u;HN=Q3zEvr5cS<HM89`WNi&4*q&3ra#~E_{)8DekET&Tw9uV>-7^8PoaW+^$oka zig>JK_2=4o2ZyTq+kIEMz0&0Wefz)MD@)pbTa_z&DgBO~Ejf4Q()^M+?BCx%jVR|2 zKc;@;hSvpqyT$;G01c5J_l(bfT-nSnF@JXb@{O-w7iCT=iQ>~}VyLYxV%YiKuHrH8 z&Zdv|_I~*Fx@f`6myOfo+ge#Ge=nck7XQC=L)25I3Dw_DF#0ZSI_0%u{q*g!k`tTn zF7^KKWb&ut)vFV~=k2_A?Zk=Ps^cPDN8c{^vgMtCeeGZ0tftf{qO1&}-r0g#r@TH` zyqWT=HbzeR`Jbtv$|SYU)NZ@93TOAl6QIU*(0=);Txm{<+k!Lq_^F$1?%efB!Bvj` zYU)zZ{tH{1rT~G$h_#@#FjBl>psNdgm1aKrGnJ96l__uc+&u~p%6Gq%l2VhpU$cCp z6tBl5nFJH5o!6B;7hG<<t2bRwQ{+k0BsF1{=A!&HOI+kW?Ji(sV*I)MvSzru*-QtK zr}u7uK7ZPFqmNtNzMDGl-)F}+7e9aSBCzs@fxv|38BPm-90|B&ad!c~*W)jHPb>d9 z_wHGC+~r?+_c{Kr`+WDMx6w|SVD9dUIebic=9?F$di||iCN_PAmTsE$)HLg<hu)WM z+&I-?ib{-`v|IDMf}FWc8c9YH9;rqdTczfhNmtG7%h5X?RMGpZtLWOb>nFKcZTQ%u z*0!Z+@oE*^$~hv;=@OWvJ#$L&pUkZulUy=%55;86oOjXiU;q98u{$@Ox969Y{WKwN zp+bDQ(aa~WBl*~Ka!%N;E{Na@S-W<E*U850B&JiRo;>&WJ-K(8ixXej?c1NeY6ec( zUb^$if*;?kwnn|XI`gbR=Ly^0d#j%&YlxIfsP<m|dN)H#T{YwG0)DP2d&yZTwv+ch zvs&(W{`&1#`Bk&?TF<`CJ@@77<-mCN4KK2eKJ{UHR9Go=?6;&;(^S#Q9UsC%E$7Xi zyuN<ry02Fq7Vg+PWkG4J*M%y1uR}4dPKDMQj<0{^nPg}R8@>~0QYctg->`0>;1T}F zou#H?%9GFDy;9b(=)}=RMbKpElOmVLAM3x`iHC)2ig1}PES2}m&^>fI{oKc2Kf86- zwcYevT7GS<+x_ZuEl!O`uNs`5c*1w}EbZ{$vWu%LT4L<{Ew<GKfBSv<_>B0t%Iljh zM76jW9ld$_uZ!8gukYtN6)q3l$8<-r?#rp{D{Rd<YC=9|^bJfbT{o=Y*z0%v!4;9; z(a{1djR#L=%I$p4uzv3DhMO5r0;;8#`+W<H5A@U1KjA9%wJK;Ps2T<}M<Wj$|6Be2 zg1wnzZK@?`YGIji&hnrVGt+`y+vjg;nE(5GnURU@;R{zp#3s*N*{Z7c?D@^hcUT-^ zD+Rhwf)1%rt<zWERbBby0^_;w{0pwX^jLQJ$~1P#*>fL%{QYieb;XnvtD|QwZHnQ4 zGmp81zjwm9w910}ag%29MBl!>;%XL~`tr>6>s?o0ykKl}>fST8q}j7`a#U|zzjWr~ zI=QYra(1N&^1<ESdnz9aF|ME8wJ2##ny`>it@2}=vipg<+T03m=Z3I*NA~9n`sWxM zSazO&np9jpJELZDb@^6h5tk}=_n%i9|AM++&cT;$%AOdsTiuF?;RWq>v6}sq`@8(p ztDnUkn$-L5o%YF?*>L;pk2^L^5ecSJkMG^xZE^2v@9~EZE*@^5!K+*R@06$)Go#Z( zj#%fzHZ?C8I#VW{d*<d6s3g-ZsKfQ)S*!P*{o5xup3I!|(!~Ayn>4d6O<t^<7m9+0 zZq4;d0s~_};ngo^ccSxMT$jzf)uL_9HZ>m@j_=yFahA^!Gjq#pSDlMPMSn-l7I5u6 zwu<XqoZNy{TUrk9zLozuez#NMWAsHXZg~}d8Jz6eZ>H?Z{9XOoNqoL-5x@Gb>X*`z zsj6a&>uV;}*qz^ZP3&CUzC){@>n*srBC^w^Q+?aUnYy5vlKp#}&VSIj8PjKbwzuZ{ z%;z_5cuhF_yzthVp0npJ-@M{rBKQ2wQ*D=Pk8^TVH$>|6oICTd*iv%l%w+#y=CakT z6K7hA9nLN>xiaxQH)t80rI4!nlZ}yQO8EJU*VQwujXM0`$(EY<2v>p02Tz>8Z_(zr zJULC%B_+9eakZ7?+?h{b-1FPj?mm-OS6GMd#MR<p&1GWZk@xQ`TDojj@n2@p{zd<4 z>%WgD?<sku)0r~KN3Z>6#sqD}>(?I_TY_$PUbLb^TX^ylZl;Yt#Mt)E+jdLJEiG+_ ziHVQRL<bF#i2HY3mIiH<;9DG;edGSEGc)&TPZ4L2=sePK?6JqBmh*4b=G{<>5Lr-P z)AVwwz`;cf&cT;=ye(4`7k{~8z4F|%g{zkLd(<=^y=uD3%WH>?S!3MlWJ{@~OP5LQ zzIrMrW0{%iLIwr}22U5q5KzXjl6vK^^wHJL&u`xGn{+bm;tEq9AHPe+HeDKCUwV3k zy7NDQRtvs)sk~?3!81V}+jdFm@$o1tPV`wG*}HD@T))R#Zm-bLOG>J1Y&*pz7Irvg zljWwJHmQvap{lAgc-Z>NzitrfohZ&V<;R{FIqCHHY~!q_Ru6QipMO3vMC;1-2cMsZ zH>!Bn{JvfPdE)lqbI)WK?Xft}s@=?DBX>qk*lv3F-m|_ldfo1rNoP&%N;u#jso;>i zfoJ*IF0O)GYbxgWecNi1Y$UNET4&0yzb2vKj|y*mw32<X{v1ors#Q-a!ui>6Mcue@ zE2%J5wEJYo@s|$kFDrQ&SXsB<%utc|Al!HC#+`f1jyzwwbz57|{`vbZ7EU`P*i{?1 zM^9arw=_aG?MjxZ-|VRgfek|Qr%#)e6$HLfJ!5Os8!>K=Pd={Q7hB?%C)ec7>-@=T zB4sMqF54T`8@D_;Cr@rFSCea<l$Q2~oiP=2{CKKtC#hUAH92(Sj*VIO%&on=zmBU3 zx^gZ*+xF^J`;m8TRaUQF3%CjfPWoUaBT-UyCCgNAx9r-m!^X$`gyQ1WXP;K|61thw zSE6?M=Rd}vnLK{0dAm=x+)PPIH1#P_=F<|rnz}SbLSo70l@mj(&R%&W6gHW&|8isC za(5BcH0RSCtxR91KGj**)~PN83aPNrfWVkD2cC#*UYOdoNA3=vb@eQ%jWc>eM8pjZ z3|*sRd2hzd`?!;JO`5RZ>ZzX=F_f*I8Bo!C^r|UnJw>$c3}3evC&uMxxlYKlWo?bB zd;iBSDm%O2)|wr%WhGX!AJ^&{?VN4BW=%j%%#=<E^A~CUM+96aUc6~}CCij|s;JMI zv&p8j4JCPRoGCh4wb$=_OvcP(ue`QR*1VEsDmJ-u<<X;aGvD~l?k&(c7G~sXAi$t9 zX(o@|bndNQM}sPQgZB3?{U9|nrti_}%t@18n%HgU7Bw)lZfCg?KE+r%%5DASNvEH# z)YDE)0qwDDyZ$t#B(1OQ6xX(3%`<MwSzEiBG>rD{aPjsv&3-MtWOJlU80g+Z7cJL? z0SCahGtY>RJ-XoX!wpdz<7#^+b9dVmzhMEbF5uj8H%CP%L`*zb!1dBip19?c3v%Y( zykMl)E<5?4gW7D>2Ok$)&Daom#^rIL+B2~yzo&S68AyD|xGH6|QzmOG*Y2Z-j)gVF z*!e5XytDJUuJ)6_)gdlsk64%)Kd~}SzUQz{;Y0KDc%{jwKc?URrE8L9x^OFpYaIW? zuf224p0(KQtdZM(xG`#NT2^ACkC}UMsVHdTkL|GEHBiv%s0km9(^od$e1*l^Gkw#K zyLw@Z4QukmrK6+Qtj!My4s)}b?YK4!bY5O|Zm-RgtgQ<IR~t(AKH+B43K8LAEwR$o z3Te51y*#g4<6G5*6{addnkHGMVw*WHubp*uCBu|X33->9wm<CNO<S;ZLTa&POH;?q z42RNop2W^cE?SchF1W1u^p&XmETJvy-n%tVD>4%;7io?=Klj_;__aZadpob|i*g<9 z4PKY2DZ<tIXx%~<UFcNO!-LT-Q&jG~w+o%hm3nF;Xnu)7HRG<*{kPJN%L5Oa20eSm z#riM7|Mc<u8lYa+X;820;)>8e-_|Yre)iM9(`LfA=e*qynrQgdRrJY;aqqjsdu>?* zU4&eXcFMetj-C>)Kk=>pM3v5!M^#^)YL>5>ExU3`j8aNLfS&KAI@8Nev3K45le9ez z?D%?n-|Gmw{+u86*U$CI+g!`;8iOC_eg$}(Q&|5cPP8k&5<GzM^G|opFF8wFf4%w7 zed6u!|9bR%MkH5YY?PPM)I(`zlZ8L!s6Dyj9=5r&AZPB^v%U_ke#@6uXSAHZQ_X*{ zA?DhV_hl2$KJU!U2?~um<d(#}{H&Ya{B%{JrJI&WOg`vfGcmzbYOz|xv9u)V?wc+~ zbJMb|JKYv9yYfE0DDmT~v#0HLUR=LNX*&POw1*SjpWF)DI3p&~Lag~x(21u{j=Q>U z*s7ZU{PW3FPc7}I2`0wM(={qzY5w>${pp#v-rhwwC-1YfsEN=E+_YEs`kPm;C)dA! zJJoxRicrx`q51F2_SSN>K1yE1vex>@#B;Hr!z=<{eLs0qvZxX?IC!T_T76fQz!9eT zRvYFU*Zw^s%*mjmCagER_i4ryeY*nt_4BOHXPF%PtnQb%IYNMoX=1O%&78hhn}U{! ziU0h#dj038?Q$t4Wqr3k8Qt4)fmQ27%4Tax)j0e5iHobPK#Pxi*Rp6$?b_79zx?X4 zjql|4{Z0Shedoo`O3NEI-{-_czrH-bEq(sf=7?nFJ>O=<+`aLBI`g@2W-q=LH6AaC zTGwi7puoP~$L*crTx<2~k7mtl`}_N;!;eGUMfy4C<#rx;vN5^nuCC*RdNWhUaB-V& zH{Mn=i*g-3?ljZ3qMf5v`OnSmb;Zk@3L+1j&&imXV%2;!MQOVDjXU?!YKtdt{n|TM zI+lOSb|p`t*|%?ZOmeABWffID3R>hk)hE$(X2H$entzSI*DWi^TAH3RCC1L*XzH;f zGo>yi_wQw!cJ2ku7gahc?9*jGR;%k9GEGD{s=HvrV&3(aKl&|Zb^Q19rT=01e+y*} zglO#)c=GrA>4T?Jnqqf9xfh_K#J+Z#*iNTH|9+Vh?{@QdbuZi($CuLC^2b=J^{8t^ zbn~q!%MMkcq6c1TPajQgY=~K}J-6<?XQ+nA{vyy2@1m8vCe7dTPb}4y(MnpnBCmAn z{okLSTiz_5Y1{jCja%{=oz{v!`;>ijbQCz4wmx-?F_WI_+uL*Y?8Tcm4t#keRO$Gj z{`a-~kC$c^gLX>su$@s8cDE|uxPNQw#F>#&tF<aWKT^Gwo$dL&NTdbSVLZ3Y&2s0P ztQoPqUn^q$YV^eC`tt56`E_RZshS4`Ck{6+_d8g=k9l{wbNcc-zYV1x&Z~Z+Q2b^_ z%-#r*r*c!TYk!~9CpWb^$o?m%&4-3Pd(W%KOBe4vkTtbBe(Tnv51%U*tmWmCYq=V_ zVpY>d!<`DLpWXLw2JK;~onqo={-XJk#oyBJ3cPa9P1Tcn+{}Mm{#zbi*>O5qc+RW0 zi&w6i<bS_7AkM;C`}?+6ukO_!eqSFiXZ7dS^(S!`*M7Jb{oz6Ld!K6o8t)jqKvQEy z{QLTEi*C7gSu*M68`JBRK5Tc?9{c7`c3QZj7}U+0a;LdmV*AM-6PYgGRy8rn`r7U# z^1H0{?(B&n-^9O9J^lQptmNVwua_=b@}jLz(d$zCzRF)!>mN^F%~3z2tYguSdB0pI zsl1)?8npAtTs7ma;=ey9<sX$=PE`5v_Po7chOW~F4TqFk=4Qw9Wk#*XA37|*yh(y@ z^VYeb6K&(OjoIe*Wz<Yo>Sq`1eBm}HXn+3lBh@SKyT=Kfc=oAdQHR%3rENPqk0-jX zzG`G*>YGyAd|uA-3}`3N{i;WXplvNbuZjwt6lpKtn!G(CB7!&g)%T4%_xfs0UV7rO z+SHSa!d4r+_`1er(UhOHU;KT7q;-^Mo(p*NdDDhnUK5WyYfVlquAaTAL4IzSx6;f- z*%=buH(hc!@C1r%oT=;bNP0@eUeJy;_S?5-#78<V4inay)Goexr_Itj`O_0M@^<qE zPU<-J*kX;@Jj=4C-{0Q2u}=9>TXeG0b5V80ly<&1O9KQpM(eH!(K5QJBR08n=?AG) zM*G*Zqccph_V_)|{o@^=A#!~&%UWv}v+2i^Oa$ZNpC4bpkFVkS!zU^E^6lkYH*eeL zxG>;A+Qx(nuTMN>4O<k*wtQKkwM>So)D<n!*RyAXmu;r*Df@Tm|NVQl?Z*S}a?Afe zcgAe(t5xEwy{DymZo5->bfY2*4;zz;{*r>pds?QLKWS6RpEUc<gijN`O_+U$L9x-C zvn7Ce8B5Q>y$Po`<(%H8b8_0%-&x_8)@^$~<vYJ<jsaVZ;f-fC|8Cv2eE#NU@w1ut z&z+fB?BVJ2MBBV}Qeyw~#cOkWDvldyawXT<2l^geGQ(iDNY1p6JFhk`G+-0xa_Mjh zmGawi@zPb-xHPqW4g!-;x&&8StM1(SWXaM`r(RdjFkZ}4Z_sfyNln{y>O4pF_3zdx zs_XVnS)vlNcrn8l-d=sV$Qg5wu4?73$hiAiqsu9=%q%+ld-CQejgxcT)?YrkKen28 zp$ALs_2cfwY|S?NORZ-u3!F6DJI9B|_pPkX%ve?j?{M?WpFc|!?0i|u_wmlNwIS2Q z7H3<rTHY-A_WkpN&F6)aw+79c?(J74RW02&NkZD)rB^6>bKvzGNB;kNQmT}}d8pDS zM&Ht3<;c-ZRTr7u_9UBZFBj@_F*MLPd)n10>B#G&OEh{a_Qvci;k=o-a?Olr-=ZYY zPV;{KxRzC`wv>Eb;3xB9^>Y98syeyG1dhl_9PW!M{??sQ6J9N@dt}Ls53Ec&^R3x8 z-{fh~Io)z7aZjDSS$FGC<8*=i?U%3IYqXbenW$QH>GIC1qd{ix)~YJ2N={yM;nrnu z6{)$qM7AfrlZmRXvMkxdI^Vuw(TOGM))A)lcKaMSB=+ZQU$Lpl!^A1P-hPvgaHy%+ z`BjI~HYRM2_`up+QDgTeOnS4Ix5g~9-mBeW2}YV{bhMs4*!Z}FpYM|S6QxzFo}{N5 zJt+FvJKO%~C(ElWhZEgw;x5VX?fS(QkRlm+nWI(t2eV^Tbrnb3A&*Hubzx#hFBjRJ zx$7X%Qoi7bx>en$#PCNkzmA#j>nq`Vm%8F2$G7i=y-UySV|>*wo1RxGsr~Hi!o~Fs ztj6gA$y+z=*wuCJA0yYM%`@Wz&voA}pEPrlQ&^N%*yfog?agbpgqXyp$5l$6dnhOt zcJ4^p)(MklcvKY`^&Mg1Gm}4@WoEcnVg8pVDLe}n?U;~T%DzHJQ^{Jl*Th{&Kj*$@ zT^L*H&!2B{GnN>rxA*JExn%qEhb~oBId;@&vBLbs{^^y*r%#?fwPe+j8Sf4{J_|o{ zByHmZ{?-jM&c<wi6|{?uO;cY-LDg{LoG&IRu4=}rtcML&<lCKF6d7vq=y9M(>#9ph zGMt<$M~+UKIO$M!^*5#sIp=bCm?sH6I_c@}el>(GMlVfFT*=djvvA`X4V?qFuO7OT z^XK)m&pvu6LgB=womY3*%B6{jDV#Q1Eq*Tj_`l|qCCdtqKJw0Z{dV!L9IL`_5?4B_ zlgw5>t$iK+aIvOTZ<5EP9n*iA@f?1z@Atd<^FNQgIJj9QOizsEq0f;Q2aT<7Uu=G) z-=M(JRB%wh(OZDUaYsVO0#%MCg%|^u3qmZ80(ufk8JtZD9O68JTUZ<gTDaRdqM8&q z4zW73=sF6pJZw^Ing-SWTE>W{dHwyr((86VwsujUzRcdeij95en{DeKeyg}Q{S(jO z2itbno!h_dy;btA_kaJz#ogKVId<yKmCL5(|9Lg<a^CL0%gaCCd6xTr>#Qb)nj;-Q zUC%9KoIX3e?7gB;sAb8T)}NwJWiqnV?&U4N{W7I0PA)K1Re&pSl67w^JO9RtGSRnt zYj5a?6<xZ#A~!=tQEyu0W$%}-<PSXl{E(l`v!i$Eq8%Lp7EZZ`19^C&e*fZZJCtJ^ zcYM;#%`aq&9&)pI_<Ak5|I{tiR3}aNYU<_A6<WWg`X<eq(o$T}!aCLXWij8yTbI2P z{mfK%UVb52bkW%2#I;*iT3%hA{$&rOWS9QC@#B&*>&?iTS6!z){mT}t(kkse%i^T? z?ChMzt4RyLod}%t=<&y2e|1)^TCiwIN6U@~hBh}hi;_L9m-g6v+HCYvy67SA4?~{j zW82Ew+}viy2m0OlZLxo`0*APrVdA^UDs$mycK=SXF&z}}P74pbUo%I0y6(f*<^Q|f zujen=yS%@8e$A{+e{AYL9dHg25#RXBJO1IRRPUev-oIa}px$n8^U<W5Pd4%Hvb8fr zX8wAXeCOlp>W&p!_CMbLj@(_uYX9%?{K~x3W_??>T)KJteDC!2k0$^B7i+iwTh_da zr=f9ocF9JD?f7c{&guAr_WB+3L%YR3EMI>8<Au%o7cSg7r7!n~Tl?Ahr_bL1<%pbC zk#U!MO_ag>>1A({&Oc<^#m4sI@MHhNr<ab_yt4k^c>MX}@_xH>pLQ1Sczut3f@o{4 z`|KUhC)PiZkxTP_YbO?RCgtSweI40X4qslMx9I-UL+|-Nz20wo=+@Nfo4(DypLRz6 z!Tx{$B($HOf4uds=@}i(MfE3+&i(#J?)e7}|D1}cufx~62nzRci7OZ;zMDDsZOhI@ zrspTFSoP`0uW(OKuOoSzKR)^<%Tv9_W78Sk@VJ9_@Bh$Jj?)LVc=`H2yjiwZ<k{0t zhqlR<@LSCcj5ts{d;6u=C67K;RQ%d{)??F|J6%O})z9}&o;%GgIoewK`;||>|5vNq z|Go8g#u+sSry!9D4wIgIY|uT}v&gCL``!G&un31@clGo6chBj+`yplj|5td&#@m4@ ztsSe17HpiUJuRk5S&^|pKX(7L{ePagTeP=V=KN*jlg(eaboFe;?*`J}-?+|-$h?_l zcKN3HffqL<vZv`gPf~gFO``7W+4Y|{udkiC+$`tN1cynf-{dkMczA0cx8D7teCN%W z-TVxZlPVugy<Sjlv*r8OO?%%l?Dc!zeyzPpVNU&#rw5Cd>|8v#+4p#XRr>@L&g&mI zqQAdoS2&g>YhOJ<<<Z-+Q{7yZU!I2lcp1L`O#Qw8>C-~aD=8m!?74a>HhyRCnkynH zk!gotS9ffTny6x+X>{s{kkny0{YfVKuI%xgxI9c#u3&fLN7YxkVcJ3oK_V)iN_uK+ z-&eFB*%1*Es;X%>?|A*sVyj=jew?rV?~<0K#nAjNv8GXB*0RSP{pzNg6WQy2*t#7* zHe=evbJsc>ihn+G6?yLa_-k|fj=$;qpFI6t=dK}?c*MHx_;dAZd9$--OU$0ylfqvA z@8b8u>OD_VQ#aH-x;NAI*s-V6bsn{EuWj77P;t}cOLjZ_gjpW$QE$3t`RUHH+?b7D zgy#J@s~?auQ~uAxx_Ng#NOdJS&E$|V+sx`YX-C>oqgQ=qMQ@LXeYo8&|Mb>WZI7Pr z$GiW3v)uPN{(tY$lxOPkdwE?aZk%yUJlkaU*(1kq?fm?C{=>fb`_7JKW`<(io}3?b zX4-bo-v3{DO`7rL&z}QQSi39ttUjwIY}VbHfB%={yQ&9{UB$%)JRjPd?tDGa+@d6C z6cij`v%0Hvw%O*~`*r`e)~aWR={(&W9`E_~qFdg-fBhZ38$Vv3|4(A`$(}_g-sI;z zGUxx#964>ruS-u=)YTT8F#2EkUjF4P`3LIpzl~-sOEjDr84`N(lI7K!U)A<1cE`@e z*Z)iQNfVyL^8a~#ZP)F(Ds%JN@9aA3R;8Tl*~GtDn$^+be8<-<=Pp^VT`tPgK2eo( zb!v^_!4<27I^8C!N>284oS545(7@14x^10sm&=CRIV?_!Ys9$KTn`%XFfBCLq?5Qg zqGOfTtaZtoBRJX)Md+l7M5+mJC7R9bSfy1qn>X}whs)v_zG@}0?txQQ=1$I(|MA?a zX`w*m%9Ve9t?v)`{o`=NnY2R_InpLeu0HCcAaZDlhRY%?!!YiyMGG>e4i>O<-)uRW zqb9+XY@|8ESIz06!K!7#$(tXQ@Na%#9KYb%#r+fJ%y8(r+O;Y(_^U;*<wFmV(9q6} zkw^bBJZw_EcG+t4=2(C4Ezc~4lDE$LbT7v!vF`FYX=}>~&VkF~j?XjM;XFwtDf!-x zHED*km&e`q|5amj{>it?wb!3i@6NTkf2y*$BIoaFo?Y!fU!SkD2|af5r`qLtfA)4Q z5=gIK+-JDWyl(m1CHHgsHx|CWwc4Yjcdpj+CslJ-%B)Vc$>3^I*fZ1OvXytz(<DcM zb1ri-=gy4S83C$-Uv$E&U@P~Ug9_@qcD*d-OO$wD!+P!U=e@bRE*i=w*V(UHwl~=_ zFm&nS_5FtR4FxJr3L;jyR=$@%{HUp@*>^dwoUeb+>Z<)S)8Bk~D%s|^zPMxBy1ZYp z>n<<jY&+bdJaOfhS<4=N{dxb}?mq_~WWJW@bnA3kynOB97c=@VUcOSesqWmv#FAM1 z+*#Y}`n&W6j?7qb`bkLa;(Lb2{xF7wF1>EqvhMZrv;Vi{vVP&;nep<~vg?*5w@em- zR>y8y>u~w&_P3`eSJu`Y`@^^>aH_fa-6zq94J1DH?ah^Z|E&7n+5n55;))+zZkzZX z7w6dX^mF+wT~pu1d$;!s-?i=edH+Pd1lv91H=hr+I<l-SPI){p%Ix~JkNsbzGxFX$ zTrUkNwRzzZDjIv;kSF=i*2E9npT{eS^d(5Jty;G5rPZoci(a$E?VtaATh8+O6Rmj? z!9Ugb->9>1c8{-WJ$&51;QnO)$NX&^ZHFGG&Yj|B&NJt*vd!i~?tKmnf0ukp__Lto z_W5`7xOS|vij$AM?(fO&bG3AnAOG6whf{v7oYl7O^^3NH`Tze($kzVl;qCYNTNitM zd7bmwhirV?w=8;TrT_Lu>-G2PIs!8?cAK9HHs!51IC0uK-aa>ahnsEA%C*)@?RgF> z2=IJ7u|MwE>+ka?@h9XT4vf3Gb+)>B&K!#ydrf=SNv{xAwg?S%4Glf^r*7WO9W#5Y zvoc@5biH1>r_TQWogFi8wYgo(z16kOe@bysY)I(igX#0@y`wXC@wFYymzT|7?fCse z=IvGcep>wQGh6i1YW>@l2W_oR&G>(1-y9$7t@B@6)z@d*9**Om%l!9^MZtu5j_TIm z<d4|CdiXNj+;8jj>(8sb>;13&UYPFxHu<f|OSSK>CvRV=e$_qn`1fvg^PDAXmw%tK zYn5<mX&=w#ywBTK{w+7UAG|)##eU^pwbzzEpC5Sp@x$@u^B%f{^Y5?xadG9_g&r;K z|F_O-kFR*y^Huy@{v*DJmPY^1-#yt;&J#Ip=lhlE6B=IrtbAj8$ssdNuhr6WPh5S+ zq&+cgck=%IIb*fy^5u%Z4-&;frWwDHRMtDzmiD6Mkl?&K8zwGkvCvue@!^Y~ku!7F ztUNkV;Jo;{y=`~S@CYR(TNW*v+B#MA3oq|QQv-+MYV|Ii;>*YNm92HBw$H1rd&IDO zV`aYVLywk@RhufpM2k<KUSWCXK=1UmX@}oQX?b^56#n)TN`AZ{Qg_8HH?JV2?Qxsi zuFaF1cXx+q<TQ;_XBU=VIN5Of>|y;r_6K{`_?W%Bd0KXR&8$CfbZQzEa&7mfEM4|t zdHTG^lUIj*`ZFz8=KU+Rb9w1ynVjsi`wdNO&V2jJzVUX>7v7x`veM3%OSv|0zESx> zz^uDf^z*X`vnL+>U;WNC#CNHJ^=x0$-=HFY?fH8?#qR3U<2MPUCJCIgkE?6FXefVJ zPJjK|bqCY7KHz2n?eDlb=cdYy<jl7(6Tf{4lHvTgXGf{JST|?AflFv6r}yggk7t&h z-SYLzqgfRizmvJ2UA%Yu{IOYkW9m*i&AYotwELz{)7`#B8ZwrJO)HjtI<Y@aO{mu> z-A!`(nN=ypZ|(Z#Wh}2Qm~i}B{sD20Nt5Rtd$#xYk5|j{62M*88QbQ?U6SGZ_vL)) zoua3rHvdkop7Y|JqN3ikn@g8&`S#_3+}DByJ0%YrNEGbkbUoy<NNeXz$u~9u{&Vi0 zyEXOn&HFdbEU2DwWr<6cv=nEHQwcwh(X;QDZ67RIyS?Anv^ui-CD)lW;n(GF)6U2r zNRyq<{JHIPSYZ7di`n1bE#A3zviSD5OYT2avb}lm-LJz-tYm7EUaE#n_f4<9%h*?1 zrg&ONckbOKmNIAbw3n{i*y%WZw)S-0g*z7u&%Wy9?5$lHIrGlv@5dQVoIkZ_>FREY z)uPQG19$BIe_U9j%c(9*?d$Qr%XjX1Rt7Sze|xk0W{Q%j;lz6j6?M{#@Beypmf^_F zw<$|{_^14Oo;|y;(njUzQANf!m5nRY<aO`fRZ%}u{33#TB_DhDDy;~!^l$9-8wBnN z7cML9)95;*9$w!QeSKZx^Tw)ga(NC{O`IMY^tG_C-93Co-um3y?CS+rH!V$BqVoCX z>h(*`Te?Ih+9m&EI9SkeaH8O!MuoE3z312LY`SPDAN}p>!k1Qa|1yV66WN?}PloO8 z<LMDzpOzK==Dogo{lbaw9Mzfi%-y5>1bEyF`uol^yqA-GS{z=_H2bKRhEUq^#wruv z<>>_ihYfDTl{X~zx6e}MWpPTprW5Z~)y3R@{`mBD@uwG5OZZ;5tXed8^)!7&b=zLq z(yuiSZ*5(oqPF4n14WbA<*Vx(c0M)Mm^F>r!Ldwi`~3>rr>(6l&WcJ|QxYtkN^h2c zI_Q>0hu%56Yn+<vmKmpabmwI?y@ir@ik=={nVpjqn93Tu^yrqaUxbo3Z~A>9(ZqN8 z?)rvG<I^+3<Bpw}As#uYV~)w@y7LPr>&I=M7BRaw!Q#xhzh5(Uxt)KYz@Rqy(003W zZnepsYkz+e=4iiBxj@dhTDf=K>pK-cwTg@{?JT($!xnS+NW|JRvm^cX*iM_R7tiaU zAR_m^`%cU%FYk)Ib$e{pPG@GlesFDT_{6!>PW6Ed_xpZ8VXErUDWXr9C(NC9>aBU) z`8O|BS)3A;R(UCiq@@Kao_-!;{Ge>}?+b!lMVmC{ne|@UV^h<p&=@cS6ub4w!o{c4 z4eHY@4=<KW@m#cbJOAAaoo=C<f`eCT=(z=^g!rZ&c$yUVvuC9{ztcpHu<q8|c{}o6 z38fzHG|SsnWBSyUHD|ST!>Y_LJXR-9dOZIXI{lKZ!N1=ruEz{`qIT^%>E-)$S^xU9 z>|EJyE$xUX+u5<~{15qAB)|3r&Y0|5vu5thqphI!=;GYmnxvOWCb7>yhsU=TSF}8y z8{48R_^Ul8W@CyWw^sV2uRmYN7d_->DXg}+Q}Xjw@H({?Wx=vH_9yntG=A~o{qt|q z>lQCvEq&Kuf@<g6-~0l-ZZFGs7OJRxm}we*;o|l0cJiz(#g0BRs;Aw{JaotIxj^){ zs~3%5q@4Y<bcU~*(nXD<J1@VGFA_}NyeY@e^tD-j>XFw+bIgLnCivf<(0ycw#k7#~ zi}o(>U$aF-=<%ZsGtR!Ts_3}1Cq}D_OH%f8U|dMY%_S3NO=+<`<~Hl_!G(`?bM9`R zzvKts>6?ET7}&BvYXK~@yt_I#Ms;qCoT$?28Y+6^X0n8oWNP(YN14u#D(Y%Mv*vf} zOQhsg-u&?`kROyvH>q4SH#xGdx!uFh!{Mq4pNVO3Xw;!Ee{5tpKd!mGhd1={j~j=6 z?%9&8uI8GU7|I&Af4(FuYlLo^*XK_LJk8tI<vp7+UD2~(&+6H~l8<{9TX=YSsTi7- z)s#)}p1%3{2f<I9jS8!6j@(QR5NW;pwLQ{mxzy^LK0Q~xf@*ALEt@!bUYowal06$3 zx^MdIx$C#;@WG9JeohlPc1lWWZ0gaMNO?SO?~$8H9;GUQkx^$>l=qyvlvH%-a-sj3 z_YxefJ4^n>?5VRCJ?h%?<Jbx<T~OBCrzk#i<w~CFJt<3<CK>$eiJ4#Au_cB5@}<j? za+0d&^3)CO`nD`_S(C;cnYpr}wl2+IUsYRIwEO0f;^=M3FRV^K3p2JdbBlDeOWQnC zQrL0z*462Y)~Z<j`gOB>%fu-yER!Y+dHQ;}Ts2u2wQb6-#lDY!PdVLsH%;|iUi$BS z%sMOQ^&U-8GBgw0e*JVqwM4ZK&&`!9Rn%1{O`Ue?;x#k3J#iwgiiUc90V-apo`PbN zJHPGw_c0+T#NoV)LvMfY)0@80AAbFb*;>Qt_npIar{#>ZYFwK)bGj=(Nl)FFTyOg@ zLuB?*r!+4v)t#3EL|T_^<9j7Fdq>?>uRC)5FHiCX2@6L?gdY61tGR@iXTyRdwU>PC z6FsKHvcJ|meO_79PR?_ZhV}_{RYS&j1&6paF}eNxyU)5MmWf?9GA`)tG03jceCRP{ zh1ApH>uVB&eRWkUckcOB#T&ZxXoOGN8#C$d^ze)3CN6blVrJc~lB_>@s%@q`d%8FO zI0tO-LHuuVRCQLIx~eLx=cIeri|n<|XI_=bbC{+o78dqlyLjBAW2eIe<+J~9SnaAJ z_4H`2^^S*|Li1nVUiXjD>ep{iU!Ns=R(z;^U;S{e^tY<Yn!l@mFfqQ{@$>R>8=3lz zLgzE*&OH4z>7%Om{o;Myb{V#xPQ*v<N$KQ>O81<<!&28<Xx2Jq?@N`!EG4n_Z}&&s zHJI>V&&uTndaG7>Olo;4WAmooPRQ}~Tgf)Zv+rzc{$11G^L&r^-^%RZWaH<L7ruVd z=rwDZAW!Q@_U8A_JCA8T{p0WMa&l6OP2q=dwP}i$@q6y3PXDaAfh*r&wvYVG2Gu>x zhZk&I`E$*txG#>cPcEOQCc{~;ao^T5q_SworzgLUZ7Z8~`}T6X_i`nl&OFn#`Sa*> z@ce^6BoCiF|HCKGn1}hU0Y}@RD>8WxBHW)}*%n}76MF8#2@Y%iEAuCvuLz#mq`)D+ z#X;eKu)j@ZSf&22&)53;_}=Y*&$zGjx%tE;{CaNkId;d+F@LoX5_<7QUcvTeV{yfd zJ!gD)cuIWJzduxFaZcna-n86r@4Ooyq?GR&dVMac%q{2T{8(7?@m4lyv_b#hCxcBY zz3NjFt~OO(k;yxdw;9yJ*n3V<EHt#>MFsc%Kc|(Sq%FIA=ibQ|Hze*h`+-_+yYlV( zT3FV_@16ANP!s<eTNXzF1|H|<{NL}nr>8%Ue7gU|`7I1`H6Ijb&F)+H`n}EKBfnFt z?=m_~<ha}19HIN{BO_0l^}9g+osyDgbo7!=-`llv`FBPYPP4057QMF8oqKnR=#$Mw z_hf#x9ZR3ku`yz2-c>IxuP%>riyM^>1m^Eg<6Y=6W!W~qeU+z|&$O+z3ROKCvonWt z)w0bC7R~7uPTltH3#herYwGEjZ(jdDaLY-6h4C13Sny>-xym2!(_@dh+CPy!roVb^ z^mm!C)xD9MS4~K*%qnZzy!ZP@Kj(XolapUcNhqk>&W)Hob<Y}}S+}evq;_^qN|L&L z3zUOI`V1Bu$h*qLC$C<#qr<SiVbh_S6jwFflZ|Jy6qQwHPFt7PRkVrIUFpTHgKsto z#ogG}d}K$&GVv#y>#pbdZ1QmlJ$d?!!)24GUArUAmP>tK(SB)9%mfv#O`9dSSw65f zrz}yKfAzgM%fmBACVVe!OKeD7uu_Zv|69R*wa?2t=B3TrTK;;GyzP&)t5>hyDY?u$ zWy-XmkPrtar$>=fh53GXdfDvW)1(mdr|F=AmCz^miZ2VUzh1a@ZS%EjVe{%<&A)Q} z`v3mZe@?K12euD=y=a#&3K{{|ATR>{@js)B?4%XfTehrcU|?YIboFyt=akR{0NI$p A6#xJL literal 0 HcmV?d00001 diff --git a/development/examples/example1/req1/1/test1.md b/development/examples/example1/req1/1/test1.md new file mode 100644 index 0000000..a28b2fd --- /dev/null +++ b/development/examples/example1/req1/1/test1.md @@ -0,0 +1,176 @@ +--- +ID: ID1-1 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 13 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 2h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null +Issues: + - Gitlab: + ID: 1 + Title: demo + Status: closed + Labels: + - bug + - enhancement + - feature + URL: https://gitlab.schukai.com/oss/utilities/requirements-manager/-/issues/1 + - Gitlab: + ID: 47 + Title: Test 15 + Description: |- + Lorem Ipsum Lila Rot + + Blau1 Lila Rot Blau2 + + ``` + a=4 + ``` + Status: closed + Labels: + - bug + - bugfix + URL: https://gitlab.schukai.com/oss/utilities/requirements-manager/-/issues/47 + +... +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items +}}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +{{ if .Purposes }}**{{ .Purposes }}** {{ end }}**({{ .ID }})** + +{{ if .Description }} {{ .Description }} +{{ end }} +| | | +|-----------------------|----------------------------| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + +## Level 2 + +test + +### Level 3 + +test + +#### Level 4 + +test + +##### Level 5 + +test + +@todo das ist ein todo \ No newline at end of file diff --git a/development/examples/example1/req1/1/test2.md b/development/examples/example1/req1/1/test2.md new file mode 100644 index 0000000..8f23ead --- /dev/null +++ b/development/examples/example1/req1/1/test2.md @@ -0,0 +1,142 @@ +--- +ID: ID1-2 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 1h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/req1/1/test3.md b/development/examples/example1/req1/1/test3.md new file mode 100644 index 0000000..ecb08d9 --- /dev/null +++ b/development/examples/example1/req1/1/test3.md @@ -0,0 +1,142 @@ +--- +ID: ID1-3 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 1h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: XXX + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/req1/1/test4.md b/development/examples/example1/req1/1/test4.md new file mode 100644 index 0000000..d12f8bb --- /dev/null +++ b/development/examples/example1/req1/1/test4.md @@ -0,0 +1,142 @@ +--- +ID: ID1-4 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 1h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/req1/2/test1.md b/development/examples/example1/req1/2/test1.md new file mode 100644 index 0000000..ca9c29f --- /dev/null +++ b/development/examples/example1/req1/2/test1.md @@ -0,0 +1,142 @@ +--- +ID: ID1-5 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 2h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/req1/2/test2.md b/development/examples/example1/req1/2/test2.md new file mode 100644 index 0000000..ffbeb39 --- /dev/null +++ b/development/examples/example1/req1/2/test2.md @@ -0,0 +1,142 @@ +--- +ID: ID1-6 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 2h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/req1/2/test3.md b/development/examples/example1/req1/2/test3.md new file mode 100644 index 0000000..27aba08 --- /dev/null +++ b/development/examples/example1/req1/2/test3.md @@ -0,0 +1,142 @@ +--- +ID: ID1-7 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 2h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/req1/2/test4.md b/development/examples/example1/req1/2/test4.md new file mode 100644 index 0000000..064fc5a --- /dev/null +++ b/development/examples/example1/req1/2/test4.md @@ -0,0 +1,142 @@ +--- +ID: ID1-8 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 2h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/req1/2/test5.md b/development/examples/example1/req1/2/test5.md new file mode 100644 index 0000000..ee82ed6 --- /dev/null +++ b/development/examples/example1/req1/2/test5.md @@ -0,0 +1,142 @@ +--- +ID: ID1-9 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 2h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/req1/2/test6.md b/development/examples/example1/req1/2/test6.md new file mode 100644 index 0000000..a0217ef --- /dev/null +++ b/development/examples/example1/req1/2/test6.md @@ -0,0 +1,142 @@ +--- +ID: ID1-10 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 2h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/req1/3/test1.md b/development/examples/example1/req1/3/test1.md new file mode 100644 index 0000000..c96c538 --- /dev/null +++ b/development/examples/example1/req1/3/test1.md @@ -0,0 +1,142 @@ +--- +ID: ID1-11 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 3h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/req1/3/test2.md b/development/examples/example1/req1/3/test2.md new file mode 100644 index 0000000..66398a2 --- /dev/null +++ b/development/examples/example1/req1/3/test2.md @@ -0,0 +1,142 @@ +--- +ID: ID1-12 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 3h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/req1/3/test3.md b/development/examples/example1/req1/3/test3.md new file mode 100644 index 0000000..3dac2ae --- /dev/null +++ b/development/examples/example1/req1/3/test3.md @@ -0,0 +1,142 @@ +--- +ID: ID1-13 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 3h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/req1/3/test4.md b/development/examples/example1/req1/3/test4.md new file mode 100644 index 0000000..bfd922e --- /dev/null +++ b/development/examples/example1/req1/3/test4.md @@ -0,0 +1,142 @@ +--- +ID: ID1-14 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 3h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/req1/3/test5.md b/development/examples/example1/req1/3/test5.md new file mode 100644 index 0000000..5a4bfa1 --- /dev/null +++ b/development/examples/example1/req1/3/test5.md @@ -0,0 +1,142 @@ +--- +ID: ID1-15 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 3h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/req1/3/test6.md b/development/examples/example1/req1/3/test6.md new file mode 100644 index 0000000..7d95c7c --- /dev/null +++ b/development/examples/example1/req1/3/test6.md @@ -0,0 +1,142 @@ +--- +ID: ID1-16 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 3h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/req1/3/test7.md b/development/examples/example1/req1/3/test7.md new file mode 100644 index 0000000..e77d6d7 --- /dev/null +++ b/development/examples/example1/req1/3/test7.md @@ -0,0 +1,142 @@ +--- +ID: ID1-17 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 3h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/req1/4/test1.md b/development/examples/example1/req1/4/test1.md new file mode 100644 index 0000000..6109fe5 --- /dev/null +++ b/development/examples/example1/req1/4/test1.md @@ -0,0 +1,142 @@ +--- +ID: ID1-18 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 4h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/req1/4/test2.md b/development/examples/example1/req1/4/test2.md new file mode 100644 index 0000000..687ac28 --- /dev/null +++ b/development/examples/example1/req1/4/test2.md @@ -0,0 +1,142 @@ +--- +ID: ID1-19 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 4h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/req1/4/test3.md b/development/examples/example1/req1/4/test3.md new file mode 100644 index 0000000..cb9d2e4 --- /dev/null +++ b/development/examples/example1/req1/4/test3.md @@ -0,0 +1,142 @@ +--- +ID: ID1-20 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 4h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/req1/4/test4.md b/development/examples/example1/req1/4/test4.md new file mode 100644 index 0000000..633451f --- /dev/null +++ b/development/examples/example1/req1/4/test4.md @@ -0,0 +1,142 @@ +--- +ID: ID1-21 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 4h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/req1/5/test1.md b/development/examples/example1/req1/5/test1.md new file mode 100644 index 0000000..ff1657e --- /dev/null +++ b/development/examples/example1/req1/5/test1.md @@ -0,0 +1,143 @@ +--- +null + +... + +ID: ID1-22 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 5h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/req1/5/test2.md b/development/examples/example1/req1/5/test2.md new file mode 100644 index 0000000..cc3cc82 --- /dev/null +++ b/development/examples/example1/req1/5/test2.md @@ -0,0 +1,142 @@ +--- +ID: ID1-23 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 5h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/req1/6/test1.md b/development/examples/example1/req1/6/test1.md new file mode 100644 index 0000000..b9fadde --- /dev/null +++ b/development/examples/example1/req1/6/test1.md @@ -0,0 +1,142 @@ +--- +ID: ID1-24 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 6h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/example1/req1/6/test2.md b/development/examples/example1/req1/6/test2.md new file mode 100644 index 0000000..e8276db --- /dev/null +++ b/development/examples/example1/req1/6/test2.md @@ -0,0 +1,142 @@ +--- +ID: ID1-25 +Title: null +# Reference to other requirements +References: null +# Display, Functional, Performance, Printing, Report, Testing or Validation +Type: null +Alias: null +Keywords: + - Requirement +# First and last name of the authors as a list +Author: + - null +# Proposed (The requirement has been requested by an authorized source.), +# In Progress (A business analyst is actively working on crafting the requirement.), +# Drafted (The initial version of the requirement has been written.), +# Approved (The requirement has been analyzed, its impact on the project has been estimated, and it has been allocated to the baseline for a specific release. ), +# Implemented (The code that implements the requirement has been designed, written, and unit tested. The requirement has been traced to the pertinent design and code elements. It’s now ready for review or other verification.), +# Verified (The requirement has satisfied its acceptance criteria, meaning that the correct functioning of the implemented requirement has been confirmed.), +# Deferred (An approved requirement is now planned for implementation in a later release.), +# Deleted (An approved requirement has been removed from the baseline.) or +# Rejected (The requirement was proposed but was never approved and is not planned for implementation in any upcoming release.) +Status: "Proposed" +# Low, Medium, Hi +Complexity: null +# Low, Medium, Hi +Difficulty: null +# Nice to have, Low, Medium, Hi or Blocker +Priority: null +Version: 0.0.1 +Milestone: null +# 0 (means that a task has already been completed), 1 (is a very small task), 2, 3, 5 (are rather smaller tasks), +# 8, 13, 20, 40, 100 +Estimation: 40 +# The time required for this requirement +# Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. +Time Spent: 6h +# who is the source of the demand +Source: null +Created: 2022-05-03 +Last Update: null +# the individual items as a list +Items: + - ID: null + Name: null + # what is it, a image, font, legal information, access data, texts, decisions, etc. + Type: null + # does this belong to a group + Group: null + Description: null + Delivery until: null + # when was the project items delivered and by whom? + Provided on: null + Provided by: null +# https://gdpr-info.eu/art-30-gdpr/ +Privacy: + - ID: null + # Purpose of the data processing, + # for example, shipping an order and handing it over to a shipping service provider. + Purposes: null + # More detailed description of the reason and process of data processing. + Description: null + # Who is responsible for data protection + Contact: null + # But working with these categories might end up being a bad idea since doing so might + # mean packing different things into one. This leads to either oversimplifications or + # a lot of specifications within a category. It might be advisable to split some of them + # up or to add additional ones to make them fit your business reality. + # Examples: Employees, Suppliers, Customers, Job applicants, Consultants, Visitors, Prospects, Contractors, Trainees + Affected Groups: null + # + Category: + # Example: 5 years from the payment of the salary + Data Retention Period: null + # On what legal basis is the data collected + # Special legal regulation outside the GDPR + # Consent of the data subject (Art. 6 para. 1 a) DSG-VO) use Consent field + # Collective agreement (e.g. company agreement, collective agreement) + # Establishment, performance or termination of an employment relationship (nationally regulated in the BDSG) + # Contract or initiation of a contract with the data subject (Art. 6 para. 1 b) DSG-VO.) + # Balancing of interests (Art. 6 para. 1 f) DSG-VO): Please name the overriding interests + Legal Basis: null + # “Consent” of the data subject refers to any freely given specific, informed and unambiguous indication of his or + # her wishes in the form of a statement or other unambiguous affirmative act by which the data subject signifies + # his or her agreement to personal data relating to him or her being processed. + Consent: null + # Where applicable, transfers of personal data to a third country or an international organisation, including + # the identification of that third country or international organisation and, in the case of transfers referred + # to in the second subparagraph of Article 49(1), the documentation of suitable safeguards; + Transfers: + # Where possible, a general description of the technical and organisational + # security measures referred to in Article 32(1). + TOM: null + +... + + + + +### {{ .Title }} - {{ .ID }} + +#### Subheading + +- [ ] task 1 +- [ ] task 2 + + +{{ if .Items }} +#### Items + +| ID | Name | Delivery until | Provided on | +|--------------------|--------------|----------------------:|-----------------------------------------:| +{{ range .Items + }}| {{ .ID }} | {{ .Name }} | {{ .DeliveryUntil.Format "02.Jan" }} | {{ .ProvidedOn.Format "02.Jan" }} | +{{ end }} + +{{ end }} + + +{{ if .Privacy }} +#### Privacy + +{{ range .Privacy }} +**{{ .Purposes }} ({{ .ID }})** + +{{ .Description }} + +| | | +|--|--| +| Category | {{ .Category }} | +| Data Retention Period | {{ .DataRetentionPeriod }} | +| Legal Basis | {{ .LegalBasis }} | +| Transfers | {{ .Transfers }} | +{{ end }} + +{{ end }} + + + + + + diff --git a/development/examples/overview.template b/development/examples/overview.template new file mode 100644 index 0000000..61054c5 --- /dev/null +++ b/development/examples/overview.template @@ -0,0 +1,108 @@ + +--- +Author: "schukai GmbH" +title: "The Document Title" +author: [Example Author, Another Author] +date: {{ .CreatedFormat }} +keywords: [Markdown, Example] +lang: de + +titlepage: true +titlepage-color: "C10000" +titlepage-text-color: "FFFFFF" +titlepage-rule-color: "FFFFFF" +titlepage-rule-height: 2 + +footer-text: Vertraulich2 + +logo: "./assets/schukai-weiss-1000-210.png" +logo-width: "6cm" +toc-own-page: true +table-use-row-colors: true + +subtitle: document subtitle, included in HTML, EPUB, LaTeX, ConTeXt, and docx documents +abstract: document summary, included in LaTeX, ConTeXt, AsciiDoc, and docx documents +subject: document subject, included in ODT, PDF, docx, EPUB, and pptx metadata + +... + +## Preamble + +Mitwirkungsleistungen + +Der Kunde wird bei Auftragserteilung alle zur Durchführung der Beratungsleistungen erforderlichen Informationen an +schukai übermitteln. Auf Anforderung von schukai wird er unverzüglich schukai noch fehlende Informationen nachreichen. +Der Kunde wird, sofern die Leistungen nur mit Unterstützung Dritter erbracht werden können, die erforderliche Unterstützung veranlassen + +## Management Summary + +{{ if .HasMeta }} +## Overview + +{{.Meta}} + +{{ end}}{{ if .HasTasks }} +## Tasks + +{{.Tasks}} + +{{ end}}{{ if .HasItems }} +## Items + +{{.Items}} + +{{ end}}{{ if .HasRequirements }} +## Requirements + +{{.Requirements}} + +{{ end}} +\newpage + +## + +Die Vervielfältigung dieses Dokuments oder Teilen davon, insbesondere die Verwendung von Texten, Grafiken +Logos oder Teilen bedarf der ausdrücklichen vorherigen Zustimmung der schukai GmbH. Eine unerlaubte +Vervielfältigung sowie die Weitergabe an Dritte ist nicht gestattet. + +Die alleinigen Rechte an diesem Dokument liegen ausschließlich bei der schukai GmbH. +Die in diesem Dokument enthaltenen Informationen und Rahmenbedingungen wurden nach aktuellem Stand +verfasst und entsprechen dem Standpunkt der schukai GmbH in Bezug auf die behandelten Themen zum +Zeitpunkt der Erstellung. + +Da die schukai GmbH auf sich ändernde Bedingungen reagieren muss, darf nur die letzte mit allen +Vertragsparteien abgestimmte Version als verbindlich angesehen werden. Sollten Sie Fragen zu diesem Dokument, +zu unseren Dienstleistungen oder Produkten haben, so wenden Sie sich bitte an Ihren Ansprechpartner. + + +\newpage + + +\definecolor{red}{HTML}{C10000} + +\thispagestyle{empty} +\pagecolor{red} + +\begin{textblock*}{17cm}(2cm,21cm) +\includegraphics[width=3cm]{./assets/schukai-weiss-1000-210.png} +\end{textblock*} + +\begin{textblock*}{17cm}(2cm,22cm) +\color{white} +schukai GmbH\newline +Eichenstraße 26\newline +82290 Landsberied\newline +Deutschland\newline +\newline ++49-8141-5098888\newline +www.schukai.de\newline +info@schukai.com +\end{textblock*} + +\begin{textblock*}{17cm}(2cm,28cm) +\color{white} +\begin{small} +© schukai GmbH.\newline +Alle Rechte vorbehalten. Alle genannten Warenzeichen sind Eigentum der jeweiligen Hersteller. +\end{small} +\end{textblock*} diff --git a/development/makefiles/color.mk b/development/makefiles/color.mk new file mode 100644 index 0000000..2c3fe3d --- /dev/null +++ b/development/makefiles/color.mk @@ -0,0 +1,17 @@ +############################################################################################# +############################################################################################# +## +## COLORS +## +############################################################################################# +############################################################################################# + +BLACK := $(shell tput -Txterm setaf 0) +RED := $(shell tput -Txterm setaf 1) +GREEN := $(shell tput -Txterm setaf 2) +YELLOW := $(shell tput -Txterm setaf 3) +LIGHTPURPLE := $(shell tput -Txterm setaf 4) +PURPLE := $(shell tput -Txterm setaf 5) +BLUE := $(shell tput -Txterm setaf 6) +WHITE := $(shell tput -Txterm setaf 7) +RESET := $(shell tput -Txterm sgr0) \ No newline at end of file diff --git a/development/makefiles/directories-default.mk b/development/makefiles/directories-default.mk new file mode 100644 index 0000000..5ea61d1 --- /dev/null +++ b/development/makefiles/directories-default.mk @@ -0,0 +1,32 @@ +############################################################################################# +############################################################################################# +## +## DIRECTORIES +## +############################################################################################# +############################################################################################# + +APPLICATION_PATH := $(PROJECT_ROOT)application/ +RESOURCE_PATH := $(PROJECT_ROOT)application/resource/ +SOURCE_PATH := $(PROJECT_ROOT)application/source/ +WEB_PATH := $(PROJECT_ROOT)application/web/ +DEPLOYMENT_PATH := $(PROJECT_ROOT)deployment/ +VENDOR_PATH := $(PROJECT_ROOT)deployment/vendor/ +DEVELOPMENT_PATH := $(PROJECT_ROOT)development/ +SCRIPTS_PATH := $(PROJECT_ROOT)development/scripts/ +DOCUMENTATION_PATH := $(PROJECT_ROOT)documentation/ + +## Build path +BUILD_PATH = $(DEPLOYMENT_PATH)build/ + +PROJECT_DIRECTORIES := $(PROJECT_DIRECTORIES) \ + $(APPLICATION_PATH) \ + $(RESOURCE_PATH) \ + $(SOURCE_PATH) \ + $(WEB_PATH) \ + $(DEPLOYMENT_PATH) \ + $(VENDOR_PATH) \ + $(DEVELOPMENT_PATH) \ + $(SCRIPTS_PATH) \ + $(DOCUMENTATION_PATH) + \ No newline at end of file diff --git a/development/makefiles/directories-standard.mk b/development/makefiles/directories-standard.mk new file mode 100644 index 0000000..de063d9 --- /dev/null +++ b/development/makefiles/directories-standard.mk @@ -0,0 +1,36 @@ +############################################################################################# +############################################################################################# +## +## DIRECTORIES +## +############################################################################################# +############################################################################################# + +APPLICATION_PATH ?= $(PROJECT_ROOT)application/ +DEPLOYMENT_PATH ?= $(PROJECT_ROOT)deployment/ +DEVELOPMENT_PATH ?= $(PROJECT_ROOT)development/ +DOCUMENTATION_PATH ?= $(PROJECT_ROOT)documentation/ +REQUIREMENT_PATH ?= $(PROJECT_ROOT)requirement/ +CREDENTIALS_PATH ?= $(PROJECT_ROOT)credential/ + +RESOURCE_PATH ?= $(APPLICATION_PATH)resource/ +SOURCE_PATH ?= $(APPLICATION_PATH)source/ +WEB_PATH ?= $(APPLICATION_PATH)web/ +SCRIPTS_PATH ?= $(DEVELOPMENT_PATH)script/ +BUILD_PATH = $(DEPLOYMENT_PATH)build/ +VENDOR_PATH ?= $(DEPLOYMENT_PATH)vendor/ + +PROJECT_DIRECTORIES := $(PROJECT_DIRECTORIES) \ + $(APPLICATION_PATH) \ + $(RESOURCE_PATH) \ + $(SOURCE_PATH) \ + $(WEB_PATH) \ + $(DEPLOYMENT_PATH) \ + $(VENDOR_PATH) \ + $(DEVELOPMENT_PATH) \ + $(SCRIPTS_PATH) \ + $(DOCUMENTATION_PATH) \ + $(REQUIREMENT_PATH) \ + $(CREDENTIALS_PATH) \ + $(BUILD_PATH) + \ No newline at end of file diff --git a/development/makefiles/go.mk b/development/makefiles/go.mk new file mode 100644 index 0000000..2995536 --- /dev/null +++ b/development/makefiles/go.mk @@ -0,0 +1,12 @@ +############################################################################################# +############################################################################################# +## +## COMMANDS GO +## +############################################################################################# +############################################################################################# + +# path and binaries +GO := go + +EXECUTABLES = $(EXECUTABLES:-) $(GO); diff --git a/development/makefiles/license-agpl3.mk b/development/makefiles/license-agpl3.mk new file mode 100644 index 0000000..ebb06a7 --- /dev/null +++ b/development/makefiles/license-agpl3.mk @@ -0,0 +1,13 @@ +############################################################################################# +############################################################################################# +## +## COLORS +## +############################################################################################# +############################################################################################# + +## License used in the project +LICENSE_TEXT ?= AGPL 3.0 + +## Copyright holder of the project +COPYRIGHT_TEXT ?= © schukai GmbH, Released under the $(LICENSE_TEXT) License. \ No newline at end of file diff --git a/development/makefiles/nodejs.mk b/development/makefiles/nodejs.mk new file mode 100644 index 0000000..374b9b2 --- /dev/null +++ b/development/makefiles/nodejs.mk @@ -0,0 +1,36 @@ +############################################################################################# +############################################################################################# +## +## COMMANDS NODEJS +## +############################################################################################# +############################################################################################# + +# path and binaries +NODEJS ?= node +NPM ?= npm + +EXECUTABLES = $(EXECUTABLES:-) $(npm); + + +NODE_ROOT_DIR ?= $(PROJECT_ROOT) +NODE_MODULES_DIR ?= $(NODE_ROOT_DIR)node_modules/ +NODE_MODULES_BIN_DIR ?= $(NODE_MODULES_DIR).bin/ + +WEBPACK ?= $(NODE_MODULES_BIN_DIR)webpack +BABEL ?= $(NODE_MODULES_BIN_DIR)babel +UGLIFYJS ?= $(NODE_MODULES_BIN_DIR)uglifyjs +C8 ?= $(NODE_MODULES_BIN_DIR)c8 +MOCHA ?= $(NODE_MODULES_BIN_DIR)mocha +JSDOC ?= $(NODE_MODULES_BIN_DIR)jsdoc + + +FIXBROKENPLANTUML := $(NODE_MODULES_DIR)jsdoc-plantuml/fixBrokenNodeJS.js +PACKAGEMODIFIED := $(NODE_MODULES_DIR).modified + + +$(PACKAGEMODIFIED): $(NODE_ROOT_DIR)package.json + $(QUIET) $(NPM) install + $(QUIET) $(TEST) -s $(FIXBROKENPLANTUML) || $(NODE) $(FIXBROKENPLANTUML) + $(QUIET) $(RM) $(PACKAGEMODIFIED) + $(QUIET) $(TOUCH) -m $(PACKAGEMODIFIED) diff --git a/development/makefiles/output.mk b/development/makefiles/output.mk new file mode 100644 index 0000000..9aa5bb7 --- /dev/null +++ b/development/makefiles/output.mk @@ -0,0 +1,54 @@ +############################################################################################# +############################################################################################# +## +## COLORS +## +############################################################################################# +############################################################################################# + +INFO := $(GREEN) +COMMENT := $(YELLOW) + +############################################################################################# +############################################################################################# +## +## OUTPUT CONTROL AND STANDARD OUTPUTS +## +############################################################################################# +############################################################################################# + +MARKER := $(BLUE)[+]$(RESET) +ERRORMARKER := $(RED)[-]$(RESET) + +############################################################################################# +############################################################################################# +## +## DEACTIVATE THE QUIET MODE BY OVERWRITING THE VALUE WITH SPACE +## +############################################################################################# +############################################################################################# + +ifndef DEBUG + QUIET = @ +else + QUIET = +endif + +ifndef DONTOPENBROWSER + OPENBROWSER = false +else + OPENBROWSER = true +endif + +############################################################################################# +############################################################################################# +## +## COMMANDS +## +############################################################################################# +############################################################################################# + +ECHO := @echo +ECHOMARKER := @echo "$(MARKER) $0" +ECHOERRORMARKER := @echo "$(ERRORMARKER) $0" + diff --git a/development/makefiles/placeholder.mk b/development/makefiles/placeholder.mk new file mode 100644 index 0000000..c99024c --- /dev/null +++ b/development/makefiles/placeholder.mk @@ -0,0 +1,9 @@ +############################################################################################# +############################################################################################# +## +## PLACEHOLDER +## +############################################################################################# +############################################################################################# + +COMPONENT_SLUG := $(shell echo "$(COMPONENT_NAME)" | tr '[:upper:]' '[:lower:]') \ No newline at end of file diff --git a/development/makefiles/s3.mk b/development/makefiles/s3.mk new file mode 100644 index 0000000..9569d7e --- /dev/null +++ b/development/makefiles/s3.mk @@ -0,0 +1,14 @@ +############################################################################################# +############################################################################################# +## +## AMAZON S3 +## +############################################################################################# +############################################################################################# + +# path and binaries +AWS ?= aws +EXECUTABLES = $(EXECUTABLES:-) $(AWS) + +## Set AWS profile +AWS_PROFILE ?= schukai diff --git a/development/makefiles/target-build-go.mk b/development/makefiles/target-build-go.mk new file mode 100644 index 0000000..c69de2f --- /dev/null +++ b/development/makefiles/target-build-go.mk @@ -0,0 +1,22 @@ +############################################################################################# +############################################################################################# +## +## BUILD GO +## +############################################################################################# +############################################################################################# + +.PHONY: compile +## Compiling for every OS and Platform +compile: next-patch-version + $(QUIET) $(ECHO) "Compiling for every OS and Platform" + $(QUIET) $(ECHO) "Version: $(PROJECT_VERSION)" + $(QUIET) $(ECHO) "Build: $(PROJECT_BUILD_DATE)" + + $(QUIET) cd $(SOURCE_PATH) ; \ + GO111MODULE=on GOOS=linux GOARCH=arm $(GO) build -ldflags "-X main.version=$(PROJECT_VERSION) -X main.build=$(PROJECT_BUILD_DATE)" -o $(BUILD_PATH)$(COMPONENT_SLUG)-linux-arm ; \ + GOOS=linux GOARCH=amd64 $(GO) build -ldflags "-X main.version=$(PROJECT_VERSION) -X main.build=$(PROJECT_BUILD_DATE)" -o $(BUILD_PATH)$(COMPONENT_SLUG)-linux-amd64 ; \ + GOOS=linux GOARCH=arm64 $(GO) build -ldflags "-X main.version=$(PROJECT_VERSION) -X main.build=$(PROJECT_BUILD_DATE)" -o $(BUILD_PATH)$(COMPONENT_SLUG)-linux-arm64 ; \ + GOOS=linux GOARCH=386 $(GO) build -ldflags "-X main.version=$(PROJECT_VERSION) -X main.build=$(PROJECT_BUILD_DATE)" -o $(BUILD_PATH)$(COMPONENT_SLUG)-linux-386 ; \ + GOOS=windows GOARCH=amd64 $(GO) build -ldflags "-X main.version=$(PROJECT_VERSION) -X main.build=$(PROJECT_BUILD_DATE)" -o $(BUILD_PATH)$(COMPONENT_SLUG)-windows ; \ + cd $(PROJECT_ROOT); diff --git a/development/makefiles/target-build-nodejs.mk b/development/makefiles/target-build-nodejs.mk new file mode 100644 index 0000000..e69de29 diff --git a/development/makefiles/target-caddy.mk b/development/makefiles/target-caddy.mk new file mode 100644 index 0000000..4387423 --- /dev/null +++ b/development/makefiles/target-caddy.mk @@ -0,0 +1,23 @@ +############################################################################################# +############################################################################################# +## +## SERVER CADDY +## +############################################################################################# +############################################################################################# + +CADDY_VENDOR_PATH ?= $(VENDOR_PATH)caddy/ +CADDY_BIN ?= $(CADDY_VENDOR_PATH)caddy +CADDY_CONFIG ?= $(CADDY_VENDOR_PATH)caddy.conf +CADDY_PIDFILE ?= $(shell mktemp -d)/caddy.pid + +$(CADDY_BIN): + $(QUIET) $(MKDIR) -p $(CADDY_VENDOR_PATH) + $(QUIET) $(WGET) -O $(CADDY_BIN) "https://caddyserver.com/api/download?os=linux&arch=amd64&idempotency=75143981108035" + $(QUIET) $(CHMOD) u+x $(CADDY_BIN) + +.PHONY: run-caddy +## run caddy webserver +run-caddy: $(CADDY_BIN) + $(QUIET) $(CADDY_BIN) run -config $(CADDY_CONFIG) -pidfile $(CADDY_PIDFILE) -watch + diff --git a/development/makefiles/target-deploy-tool.mk b/development/makefiles/target-deploy-tool.mk new file mode 100644 index 0000000..bb18b06 --- /dev/null +++ b/development/makefiles/target-deploy-tool.mk @@ -0,0 +1,20 @@ +############################################################################################# +############################################################################################# +## +## DEPLOY TOOLS +## +############################################################################################# +############################################################################################# + + +UPLOAD_TOOL_URL ?= s3://download.schukai.com/tools/$(COMPONENT_SLUG)/ + +.PHONY: deploy +## compile and deploy to S3 +deploy: compile + $(QUIET) AWS_PROFILE=$(AWS_PROFILE) find $(BUILD_PATH) -iname $(COMPONENT_SLUG)-* -exec $(AWS) s3 cp {} $(UPLOAD_TOOL_URL) \; + +.PHONY: overview-to-s3 +## overview-to-s3 +overview-to-s3: + $(QUIET) AWS_PROFILE=$(AWS_PROFILE) $(AWS) s3 cp $(WEB_PATH)/index.html $(UPLOAD_TOOL_URL) \ No newline at end of file diff --git a/development/makefiles/target-git.mk b/development/makefiles/target-git.mk new file mode 100644 index 0000000..7453d89 --- /dev/null +++ b/development/makefiles/target-git.mk @@ -0,0 +1,47 @@ +############################################################################################# +############################################################################################# +## +## GIT-TARGETS +## +############################################################################################# +############################################################################################# + +EXECUTABLES = $(EXECUTABLES:-) uuidgen + +## Current Branch-GIT_TAG +GIT_TAG := - + +## Git Commit GIT_MESSAGE for git-push +GIT_MESSAGE := current status + +.PHONY: git-branch +## create new branch (use GIT_TAG-Variable) +git-branch: + + $(QUIET) export BRANCH="b$(GIT_TAG)/$(shell uuidgen --random)" ; \ + $(QUIET) $(GIT) checkout -b $${BRANCH} && \ + RESULT=$$($(GIT) push origin $$BRANCH 2>&1) && \ + RESULT2=$$($(GIT) branch --set-upstream-to=origin/$$BRANCH $$BRANCH) && \ + GITLABURL=$$(echo "$$RESULT" | tr '\n' '\#' | grep -o 'remote\:\s*https:\/\/gitlab\.schukai\.com[^ ]*' | cut -d " " -f2-9 | sed -e 's/^[ \t]*//') && \ + if $(OPENBROWSER) ; then google-chrome --profile-directory="Default" $$GITLABURL ; fi + +.PHONY: git-to-master +## git checkout master, fetch and merge +git-to-master: + $(QUIET) $(GIT) checkout master && $(GIT) fetch -pP && $(GIT) merge + +.PHONY: git-push-to-server +## git push changes to server +git-push-to-server: + $(QUIET) $(GIT) add -A + $(QUIET) $(GIT) commit -m"$(GIT_MESSAGE)" + $(QUIET) $(GIT) push + +.PHONY: git-push +## git create branch and push changes to server +git-push: git-branch git-push-to-server + +.PHONY: git-tag +## git create version tag +git-tag: + $(QUIET) $(GIT) tag -a "$(COMPONENT_VERSION)" -m "release $(COMPONENT_VERSION)" diff --git a/development/makefiles/target-help.mk b/development/makefiles/target-help.mk new file mode 100644 index 0000000..abe1f92 --- /dev/null +++ b/development/makefiles/target-help.mk @@ -0,0 +1,46 @@ +############################################################################################# +############################################################################################# +## +## HELP-TARGETS +## +############################################################################################# +############################################################################################# + +# @see .PHONY https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html#Phony-Targets +.DEFAULT_GOAL := help + +.PHONY: print +## Print Path +print: + $(ECHO) "THIS_MAKEFILE: $(THIS_MAKEFILE)" + $(ECHO) "THIS_MAKEFILE_PATH: $(THIS_MAKEFILE_PATH)" + $(ECHO) "PROJECT_ROOT: $(PROJECT_ROOT)" + +# Add a comment to the public targets so that it appears +# in this help Use two # characters for a help comment +.PHONY: help +help: + @printf "${COMMENT}Usage:${RESET}\n" + @printf " make [target] [arg=\"val\"...]\n\n" + @printf "${COMMENT}Available targets:${RESET}\n" + @awk '/^[a-zA-Z\-\\_0-9\.@]+:/ { \ + helpMessage = match(lastLine, /^## (.*)/); \ + if (helpMessage) { \ + helpCommand = substr($$1, 0, index($$1, ":")); \ + helpMessage = substr(lastLine, RSTART + 3, RLENGTH); \ + printf " ${INFO}%-22s${RESET} %s\n", helpCommand, helpMessage; \ + } \ + } \ + { lastLine = $$0 }' $(MAKEFILE_LIST) + @printf "\n${COMMENT}Available arguments:${RESET}\n\n" + @awk '/^(([a-zA-Z\-\\_0-9\.@]+)\s[?:]?=)/ { \ + helpMessage = match(lastLine, /^## (.*)/); \ + if (helpMessage) { \ + helpMessage = substr(lastLine, RSTART + 3, RLENGTH); \ + printf " ${INFO}%-22s${RESET} %s (Default: %s)\n", $$1, helpMessage, $$3; \ + } \ + } \ + { lastLine = $$0 }' $(MAKEFILE_LIST) + + + diff --git a/development/makefiles/target-init-standard.mk b/development/makefiles/target-init-standard.mk new file mode 100644 index 0000000..48df91d --- /dev/null +++ b/development/makefiles/target-init-standard.mk @@ -0,0 +1,20 @@ +############################################################################################# +############################################################################################# +## +## INIT-TARGETS +## +############################################################################################# +############################################################################################# + +# @see .PHONY https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html#Phony-Targets +.PHONY: init-standard + +## init standard project +init-standard: + # The default directories are defined in the + # directories-standard.mk file, but all other + # targets can define directories as well. + $(QUIET) $(ECHO) "Run init-standard" + $(foreach path,$(PROJECT_DIRECTORIES),\ + $(shell $(MKDIR) -p $(path))) + $(ECHO) "Done" diff --git a/development/makefiles/target-init.mk b/development/makefiles/target-init.mk new file mode 100644 index 0000000..bee5adb --- /dev/null +++ b/development/makefiles/target-init.mk @@ -0,0 +1,18 @@ +############################################################################################# +############################################################################################# +## +## INIT-TARGETS +## +############################################################################################# +############################################################################################# + +## @see .PHONY https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html#Phony-Targets +.PHONY: init + +## init project +init: + $(QUIET) $(ECHO) "This is the target init" + K := $(foreach path,$(PROJECT_DIRECTORIES),\ + $(shell mkir -p $(path))) + $(QUIET) $(TOUCH) $(RELEASE_FILE) + $(QUIET) $(ECHO) "Done" diff --git a/development/makefiles/target-jekyll.mk b/development/makefiles/target-jekyll.mk new file mode 100644 index 0000000..e69de29 diff --git a/development/makefiles/target-minerva.mk b/development/makefiles/target-minerva.mk new file mode 100644 index 0000000..e69de29 diff --git a/development/makefiles/target-update-makefiles.mk b/development/makefiles/target-update-makefiles.mk new file mode 100644 index 0000000..a1c73d7 --- /dev/null +++ b/development/makefiles/target-update-makefiles.mk @@ -0,0 +1,22 @@ +############################################################################################# +############################################################################################# +## +## INIT-TARGETS +## +############################################################################################# +############################################################################################# + +# @see .PHONY https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html#Phony-Targets +.PHONY: update-makefiles + +## update standard makefiles +update-makefiles: + $(QUIET) $(eval TEMPD := $(shell mktemp -d)) + $(QUIET) $(GIT) clone --depth=1 https://gitlab.schukai.com/schukai/utilities/makefile.git/ "$(TEMPD)" > /dev/null + $(QUIET) $(CP) -rv $(TEMPD)/makefiles/* $(MAKEFILE_IMPORT_PATH) + $(QUIET) $(RM) -rf $(TEMPD) + + + + + diff --git a/development/makefiles/target-variable.mk b/development/makefiles/target-variable.mk new file mode 100644 index 0000000..93f99c0 --- /dev/null +++ b/development/makefiles/target-variable.mk @@ -0,0 +1,12 @@ +############################################################################################# +############################################################################################# +## +## VARIABLES-TARGETS +## +############################################################################################# +############################################################################################# + +.PHONY: variables +## Print all variables +variables: + @$(foreach v, $(.VARIABLES), $(if $(filter file,$(origin $(v))), $(info $(INFO)$(v)$(RESET)=$($(v))$(RESET)))) \ No newline at end of file diff --git a/development/makefiles/terminal-check.mk b/development/makefiles/terminal-check.mk new file mode 100644 index 0000000..5db23c8 --- /dev/null +++ b/development/makefiles/terminal-check.mk @@ -0,0 +1,13 @@ +############################################################################################# +############################################################################################# +## +## TERMINAL CHECK +## +############################################################################################# +############################################################################################# + + + +# Executable Programs the Installed be have to +K := $(foreach exec,$(EXECUTABLES),\ + $(if $(shell which $(exec)),some string,$(error "Missing $(exec) in PATH; please install"))) \ No newline at end of file diff --git a/development/makefiles/terminal.mk b/development/makefiles/terminal.mk new file mode 100644 index 0000000..4ef5caa --- /dev/null +++ b/development/makefiles/terminal.mk @@ -0,0 +1,41 @@ +############################################################################################# +############################################################################################# +## +## COMMANDS +## +############################################################################################# +############################################################################################# + +# Use bash instead of sh +## Sets the shell used +SHELL = bash + +# path and binaries +AWK ?= awk +CP ?= cp +CD ?= cd +KILL ?= kill +MV ?= mv +RM ?= rm +MKDIR ?= mkdir +SED ?= sed +FIND ?= find +SORT ?= sort +TOUCH ?= touch +WGET ?= wget +CHMOD ?= chmod +RSYNC ?= rsync +XARGS ?= xargs +GREP ?= grep +MAKE ?= make +GIT ?= git +LN ?= ln +TOUCH ?= touch +TEST ?= test + + + +EXECUTABLES = $(EXECUTABLES:-) $(AWK) $(CP) $(KILL) $(MV) $(SED) $(FIND) $(SORT) $(TOUCH) $(WGET) $(CHMOD) $(RSYNC) $(XARGS) $(GREP) $(MAKE) $(GIT) + + + \ No newline at end of file diff --git a/development/makefiles/version.mk b/development/makefiles/version.mk new file mode 100644 index 0000000..ff374ab --- /dev/null +++ b/development/makefiles/version.mk @@ -0,0 +1,27 @@ +############################################################################################# +############################################################################################# +## +## VERSIONS +## +############################################################################################# +############################################################################################# + +VERSION_BIN := version +EXECUTABLES = $(EXECUTABLES:-) $(VERSION_BIN) + +RELEASE_FILE ?= $(PROJECT_ROOT)release.json + +ifeq ("$(wildcard $(RELEASE_FILE))","") + $(shell echo '{"version":"0.1.0"}' > $(RELEASE_FILE)) +endif + +PROJECT_VERSION ?= $(shell cat $(RELEASE_FILE) | jq -r .version) +PROJECT_BUILD_DATE ?= $(shell $(VERSION_BIN) date) + + +.PHONY: next-patch-version +## create next-patch-version +next-patch-version: + $(QUIET) $(ECHO) "Creating next version" + $(QUIET) $(VERSION_BIN) patch --path $(RELEASE_FILE) --selector "version" + $(QUIET) $(eval PROJECT_VERSION := $(shell cat $(RELEASE_FILE) | jq -r .version)) diff --git a/documentation/assets/.gitkeep b/documentation/assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/project.mk b/project.mk new file mode 100644 index 0000000..9efb865 --- /dev/null +++ b/project.mk @@ -0,0 +1,3 @@ + + +MAKEFILE_IMPORT_PATH?=$(PROJECT_ROOT)development/makefiles/ \ No newline at end of file diff --git a/release.json b/release.json new file mode 100644 index 0000000..f6287d8 --- /dev/null +++ b/release.json @@ -0,0 +1,3 @@ +{ + "version": "1.0.34" +} \ No newline at end of file -- GitLab