diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000000000000000000000000000000000000..5de13d239d46bfab8be30d649d470b3bc0100bd2
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,10 @@
+# Exclude all binaries from the diff
+*.exe binary
+*.dll binary
+*.so binary
+*.a binary
+*.png binary
+*.ico binary
+
+# The unciado linux installer
+./UNICADOworkflow/UNICADOinstaller binary
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..59bd72deae04f30e96290d7da84b768e060aa726
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,55 @@
+# Project specific
+*.layout
+*.res
+*.depend
+*.layout
+*.cscope_file_list
+*.log
+test_runner_config.json
+
+# IDE Files
+.vscode
+*.cbp
+
+# Prerequisites
+*.d
+
+# Compiled object files
+*.slo
+*.lo
+*.o
+*.obj
+
+# precompiled headers
+*.gch
+*.pch
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Fortran module files
+*.mod
+*.smod
+
+# Compiled static libraries
+*.lai
+*.la
+*.a
+*.lib
+
+# Executable files
+*.exe
+*.out
+*.app
+
+# Build directories
+build
+package
+
+# Package artifacts
+*.zip
+*.ZIP
+_CPack_Packages
+UNICADOinstaller.spec
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/.gitlab/issue_templates/Default.md b/.gitlab/issue_templates/Default.md
new file mode 100644
index 0000000000000000000000000000000000000000..ed6f8d8cfb4c948a3cb438fb92d89159e2d1a352
--- /dev/null
+++ b/.gitlab/issue_templates/Default.md
@@ -0,0 +1,18 @@
+<!-- Title: Provide a concise and descriptive title for the issue incl. tool or library name -->
+
+## Choose Your Issue Template
+Before creating an issue, please review existing issues to avoid duplicates!
+ALso, select the **appropriate type for your issue in the desciption drop-down**. 
+- Bug Report Template
+- Feature Request Template
+- TODO Template
+- Documentation Request Template
+- Testing Request Template
+
+If not suitable, use the sections below and contact the owners.
+
+## Description
+Provide a concise description of the issue.
+
+## Additional Context
+Add screenshots, logs, or relevant information here.
diff --git a/.gitlab/issue_templates/Todo.md b/.gitlab/issue_templates/Todo.md
new file mode 100644
index 0000000000000000000000000000000000000000..07bdd0f8b2e7294d7949344698e4426530efc826
--- /dev/null
+++ b/.gitlab/issue_templates/Todo.md
@@ -0,0 +1,16 @@
+<!-- Title: Provide a concise and descriptive title for the issue incl. tool or library name -->
+# TODO
+
+## Summary
+Briefly describe the task. Provide any background information or related issues.
+
+## Subtasks
+- [ ] Step 1
+- [ ] Step 2
+- [ ] Step 3
+
+## Acceptance Criteria
+- [ ] Define measurable outcomes for success.
+- [ ] List specific requirements.
+
+/label ~"type::todo"
diff --git a/.gitlab/issue_templates/bug_report.md b/.gitlab/issue_templates/bug_report.md
new file mode 100644
index 0000000000000000000000000000000000000000..b906703dce8a5a8d1ca99bd5a36d980f6a2fc26a
--- /dev/null
+++ b/.gitlab/issue_templates/bug_report.md
@@ -0,0 +1,22 @@
+<!-- Title: Provide a concise and descriptive title for the issue incl. tool or library name -->
+# Bug Report
+
+## Description
+Describe the bug clearly. What happened?
+
+## Steps to Reproduce
+1. [Step 1]
+2. [Step 2]
+3. [Step 3]
+
+## Expected Behavior
+Explain what you expected to see.
+
+## Environment
+- **OS**: [e.g., Windows 10]
+- **Version/Branch**: [e.g., v1.2.3]
+
+## Additional Context
+Attach any logs, screenshots, or context.
+
+/label ~"type::bug"
diff --git a/.gitlab/issue_templates/documentation_request.md b/.gitlab/issue_templates/documentation_request.md
new file mode 100644
index 0000000000000000000000000000000000000000..bc94cf6d704aa0645ae950ba690cc716b81659f1
--- /dev/null
+++ b/.gitlab/issue_templates/documentation_request.md
@@ -0,0 +1,14 @@
+<!-- Title: Provide a concise and descriptive title for the issue -->
+# Documentation
+
+## Summary
+Explain what documentation is missing.
+
+- **Unicado Version**: vx.x.x 
+- **Page**: page-to-change
+
+## Additional Context
+Attach any logs, screenshots, or context.
+
+/label ~"type::documentation"
+
diff --git a/.gitlab/issue_templates/feature_request.md b/.gitlab/issue_templates/feature_request.md
new file mode 100644
index 0000000000000000000000000000000000000000..2c12fdb6bfc6f26eec57a4c7b1b228b65d991e24
--- /dev/null
+++ b/.gitlab/issue_templates/feature_request.md
@@ -0,0 +1,17 @@
+<!-- Title: Provide a concise and descriptive title for the issue incl. tool or library name -->
+# Feature Request
+
+## Summary
+What feature are you requesting?
+
+## Why?
+Explain the problem this feature solves or the value it adds.
+
+## Acceptance Criteria
+- [ ] Define measurable outcomes for success.
+- [ ] List specific requirements.
+
+## Additional Notes
+Include references, examples, or diagrams if applicable.
+
+/label ~"type::feature"
diff --git a/.gitlab/issue_templates/testing_request.md b/.gitlab/issue_templates/testing_request.md
new file mode 100644
index 0000000000000000000000000000000000000000..0289f4df34cec1c786d637480d7456bbf20b3d08
--- /dev/null
+++ b/.gitlab/issue_templates/testing_request.md
@@ -0,0 +1,24 @@
+<!-- Title: Provide a concise and descriptive title for the issue incl. tool or library name -->
+# Testing Issue
+
+## Summary
+Provide a brief overview of what should be tested or changed in the test process. Also think about what is the goal of this test? E.g.
+- Verify that [feature/bug fix/module] works as expected.
+- Ensure that [specific requirement] is met.
+
+## Related Issues or Merge Requests
+- Issue(s): #[Issue ID]
+- Merge Request(s): #[Merge Request ID]
+
+## Expected Results
+- [Outcome 1]: [What should happen].
+- [Outcome 2]: [Another expected result].
+
+## Environment
+- **OS**: [e.g., Windows 10]
+- **Version/Branch**: [e.g., v1.2.3]
+
+## Additional Context
+Attach any logs, screenshots, or context.
+
+/label ~"type::testing"
diff --git a/.gitlab/merge_request_templates/Default.md b/.gitlab/merge_request_templates/Default.md
new file mode 100644
index 0000000000000000000000000000000000000000..00be17dc34a7fc90bb7096112e57c895a2f6d4bf
--- /dev/null
+++ b/.gitlab/merge_request_templates/Default.md
@@ -0,0 +1,29 @@
+<!-- Title: Use an imperative, clear title (e.g., "Fix login bug" or "Add new analytics feature") -->
+
+## Description
+Provide a concise explanation of the changes made in this merge request.
+
+## Related Issue(s)
+- Closes #[feature issues]
+- Fixes #[bug report issue] 
+- Resolves #[any other issues]
+
+### Other Changes
+- [Mention refactoring, tests, etc.]
+
+## Screenshots/Logs
+Attach screenshots or log outputs if applicable.
+
+## Testing Instructions
+1. [Step 1: How to test]
+2. [Step 2: Expected outcome]
+3. [Step 3: Additional steps if required]
+
+## Developer Checklist
+- [ ] Code has been tested locally and/or in pipeline.
+- [ ] (if applicable) documentation updated.
+- [ ] (if applicable) impact of new dependencies reviewed and included in project.
+- [ ] Merge conflicts resolved with the target branch.
+
+## Additional Notes
+Add any information reviewers should focus on, e.g., specific files, functions, or changes of interest.
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000000000000000000000000000000000000..6b220a10092cab8a0a8cec28ff669d03861048ac
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,21 @@
+[submodule "aircraft_design"]
+	path = aircraft_design
+	url = ssh://git@git.rwth-aachen.de/unicado/aircraft-design.git
+[submodule "utilities"]
+	path = utilities
+	url = ssh://git@git.rwth-aachen.de/unicado/utilities.git
+[submodule "aircraft_references"]
+	path = aircraft_references
+	url = ssh://git@git.rwth-aachen.de/unicado/aircraft-references.git
+[submodule "libraries"]
+	path = libraries
+	url = ssh://git@git.rwth-aachen.de/unicado/libraries.git
+[submodule "engines"]
+	path = engines
+	url = ssh://git@git.rwth-aachen.de/unicado/engines.git
+[submodule "rce-workflow"]
+	path = rce-workflow
+	url = ssh://git@git.rwth-aachen.de/unicado/rce-workflow.git
+[submodule "rce_workflow"]
+	path = rce_workflow
+	url = ssh://git@git.rwth-aachen.de/unicado/rce-workflow.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..dd6e9516af94a575dddaf6489a632fc961396980
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,85 @@
+# Set a recent minimum version
+cmake_minimum_required(VERSION 3.29)
+
+# Start the project
+project(UNICADO
+    VERSION 3.0.0
+    DESCRIPTION "Calculate all the things!"
+    LANGUAGES CXX
+)
+
+# Set the C++ standard
+set(CMAKE_CXX_STANDARD 20)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+# Check whether parallel build is enabled
+if(NOT DEFINED ENV{CMAKE_BUILD_PARALLEL_LEVEL})
+    # Give the user a warning, since almost all PCs have multiple cores nowadays
+    message(WARNING "\n[${PROJECT_NAME}] -> Parallel build is not enabled. Consider setting the environment variable CMAKE_BUILD_PARALLEL_LEVEL to the number of available cores.")
+endif()
+
+# Disable the min and max macros when building with MSVC
+if(MSVC)
+    add_compile_definitions(NOMINMAX)
+endif()
+
+# *optional* Add cppcheck and cpplint
+# set(CMAKE_CXX_CPPCHECK "cppcheck")
+# set(CMAKE_CXX_CPPLINT "cpplint")
+
+# Option for blackbox testing
+option(BUILD_BLACKBOXTESTS "Use blackbox testing" OFF)
+# Option for unit testing
+option(BUILD_UNITTEST "Use unit testing" OFF)
+# Option to include system libraries in the package archive
+option(PACKAGE_SYSTEM_LIBRARIES "Include system libraries in the package archive" OFF)
+# Finally decide whether to build static or shared libraries
+option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
+# Option where to look for the libraries
+option(FIND_LIBRARIES_AS_PACKAGE "If true the libraries are included with find_package(), otherwise the submodule is used." ON)
+# Option to link glibs statically
+option(STATIC_GLIBS "Link glibs statically" OFF)
+# Option to compile Python modules to an executable
+option(BUILD_PYTHON_MODULES "If true the python modules will be compiled to executables." OFF)
+
+# Link system libs statically if static glibs is enabled
+if(STATIC_GLIBS)
+    message(DEPRECATION "Linking with static glibs is enabled. This is not guaranted to work and will be removed due to the native compiler support!")
+    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
+endif()
+
+# Get the path to the c/c++ runtime libraries to include in the package if enabled
+if(PACKAGE_SYSTEM_LIBRARIES)
+    get_filename_component( SYSTEM_LIBS_PATH ${CMAKE_CXX_COMPILER} PATH )
+    message(STATUS "[${PROJECT_NAME}] -> Packaging System Libraries from: ${SYSTEM_LIBS_PATH}")
+    message(DEPRECATION "Packaging system libraries is enabled. This will be removed in the future due to the native compiler support!")
+endif()
+
+# Setup the python environment
+find_program(PIPENV pipenv)
+if(PIPENV)
+    message(STATUS "[${PROJECT_NAME}] -> Python/pipenv found. Updating required packages from Pipfile...")
+    execute_process(
+        COMMAND ${PIPENV} update
+        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} # Execute in the top level source directory
+        OUTPUT_QUIET
+    )
+else()
+    message(WARNING "[${PROJECT_NAME}] -> pipenv not found. Python support is disabled!")
+endif()
+
+# *** Important ***
+# Set the path to the libraries package manually
+set(UnicadoLibs_DIR ${CMAKE_CURRENT_LIST_DIR}/libraries/cmake)
+
+# Add the library and tell the other packages to not look for them
+add_subdirectory(libraries)
+set(UnicadoLibs_FOUND TRUE)
+
+# Add the software components
+add_subdirectory(aircraft_design)
+add_subdirectory(utilities)
+
+# Include the package script
+include(cmake/PackageUnicado.cmake)
+add_subdirectory(installer)
diff --git a/CMakePresets.json b/CMakePresets.json
new file mode 100644
index 0000000000000000000000000000000000000000..0396d3d39b7b3d01fbe014b0f12e62a357e6408b
--- /dev/null
+++ b/CMakePresets.json
@@ -0,0 +1,216 @@
+{
+    "version": 6,
+    "configurePresets": [
+        {
+            "name": "unix-common",
+            "description": "Common settings for Unix compilers",
+            "hidden": true,
+            "binaryDir": "${sourceDir}/build",
+            "cacheVariables": {
+                "CMAKE_CXX_FLAGS": "-fexceptions -fno-builtin"
+            }
+
+        },
+        {
+            "name": "unix-debug",
+            "description": "Base settings for building debug configuration with Unix compilers.",
+            "hidden": true,
+            "cacheVariables": {
+                "CMAKE_BUILD_TYPE": "Debug",
+                "CMAKE_CXX_FLAGS_DEBUG": "-Wextra -Wsign-conversion -Wfloat-equal -g"
+            }
+        },
+        {
+            "name": "unix-release",
+            "description": "Base settings for building release configuration with Unix compilers.",
+            "hidden": true,
+            "cacheVariables": {
+                "CMAKE_BUILD_TYPE": "Release",
+                "CMAKE_CXX_FLAGS_RELEASE": "-O2 -s"
+            }
+        },
+        {
+            "name": "windows-common",
+            "description": "Common settings for Windows compilers",
+            "hidden": true,
+            "binaryDir": "${sourceDir}/build",
+            "generator": "Visual Studio 17 2022",
+            "toolset": "ClangCL",
+            "toolchainFile": "C:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake",
+            "cacheVariables": {
+                "Python_EXECUTABLE": {"type": "FILEPATH", "value": "$ENV{HOMEDRIVE}$ENV{HOMEPATH}/AppData/Local/Programs/Python/Python311/python.exe"},
+                "CMAKE_CXX_FLAGS": "/permissive- /EHsc"
+            }
+        },
+        {
+            "name": "windows-debug",
+            "description": "Base settings for building debug configuration with Windows compilers.",
+            "hidden": true,
+            "cacheVariables": {
+                "CMAKE_BUILD_TYPE": "Debug",
+                "CMAKE_CXX_FLAGS_DEBUG": "/W4"
+            }
+        },
+        {
+            "name": "windows-release",
+            "description": "Base settings for building release configuration with Windows compilers.",
+            "hidden": true,
+            "cacheVariables": {
+                "CMAKE_BUILD_TYPE": "Release",
+                "CMAKE_CXX_FLAGS_RELEASE": "/O2"
+            }
+        },
+        {
+            "name": "x64-linux-debug",
+            "description": "Default debug configuration for building on Linux",
+            "generator": "Unix Makefiles",
+            "inherits": ["unix-common", "unix-debug"]
+        },
+        {
+            "name": "x64-linux-release",
+            "description": "Default release configuration for building on Linux",
+            "generator": "Unix Makefiles",
+            "inherits": ["unix-common", "unix-release"]
+        },
+        {
+            "name": "x64-mingw-debug",
+            "description": "Default debug configuration for building with MSYS2/MinGW on Windows",
+            "generator": "MinGW Makefiles",
+            "inherits": ["unix-common", "unix-debug"]
+        },
+        {
+            "name": "x64-mingw-release",
+            "description": "Default release configuration for building with MSYS2/MinGW on Windows",
+            "generator": "MinGW Makefiles",
+            "inherits": ["unix-common", "unix-release"]
+        },
+        {
+            "name": "x64-windows-debug",
+            "description": "Default debug configuration for building on Windows",
+            "architecture": "x64",
+            "inherits": ["windows-common", "windows-debug"]
+        },
+        {
+            "name": "x64-windows-release",
+            "description": "Default release configuration for building on Windows",
+            "architecture": "x64",
+            "inherits": ["windows-common", "windows-release"]
+        }
+    ],
+    "buildPresets": [
+        {
+            "name": "x64-linux-debug",
+            "description": "Sets the build type to Debug for the Linux build system.",
+            "configurePreset": "x64-linux-debug"
+        },
+        {
+            "name": "x64-linux-release",
+            "description": "Sets the build type to Release for the Linux build system.",
+            "configurePreset": "x64-linux-release"
+        },
+        {
+            "name": "x64-linux-installer",
+            "inherits": "x64-linux-release",
+            "targets": "installer"
+        },
+        {
+            "name": "linux-python-packages",
+            "inherits": "x64-linux-release",
+            "targets": "install_python_packages"
+        },
+        {
+            "name": "x64-windows-debug",
+            "description": "Sets the build type to Debug for the Windows build system.",
+            "configurePreset": "x64-windows-debug",
+            "configuration": "Debug"
+        },
+        {
+            "name": "x64-windows-release",
+            "description": "Sets the build type to Release for the Windows build system.",
+            "configurePreset": "x64-windows-release",
+            "configuration": "Release"
+        },
+        {
+            "name": "x64-windows-installer",
+            "inherits": "x64-windows-release",
+            "targets": "installer"
+        },
+        {
+            "name": "windows-python-packages",
+            "inherits": "x64-windows-release",
+            "targets": "install_python_packages"
+        }
+    ],
+    "packagePresets": [
+        {
+            "name": "x64-linux-release",
+            "description": "Create the package file of the Linux release version.",
+            "configurePreset": "x64-linux-release",
+            "configFile": "${sourceDir}/build/CPackConfig.cmake",
+            "generators": ["ZIP"],
+            "packageName": "UNICADO",
+            "packageDirectory": "${sourceDir}/installer"
+        },
+        {
+            "name": "x64-windows-release",
+            "description": "Create the package file of the Windows release version.",
+            "configurePreset": "x64-windows-release",
+            "configFile": "${sourceDir}/build/CPackConfig.cmake",
+            "generators": ["ZIP"],
+            "packageName": "UNICADO",
+            "packageDirectory": "${sourceDir}/installer"
+        }
+    ],
+    "workflowPresets": [
+        {
+            "name": "x64-linux-release",
+            "steps": [
+                {
+                    "type": "configure",
+                    "name": "x64-linux-release"
+                },
+                {
+                    "type": "build",
+                    "name": "linux-python-packages"
+                },
+                {
+                    "type": "build",
+                    "name": "x64-linux-release"
+                },
+                {
+                    "type": "package",
+                    "name": "x64-linux-release"
+                },
+                {
+                    "type": "build",
+                    "name": "x64-linux-installer"
+                }
+            ]
+        },
+        {
+            "name": "x64-windows-release",
+            "steps": [
+                {
+                    "type": "configure",
+                    "name": "x64-windows-release"
+                },
+                {
+                    "type": "build",
+                    "name": "windows-python-packages"
+                },
+                {
+                    "type": "build",
+                    "name": "x64-windows-release"
+                },
+                {
+                    "type": "package",
+                    "name": "x64-windows-release"
+                },
+                {
+                    "type": "build",
+                    "name": "x64-windows-installer"
+                }
+            ]
+        }
+    ]
+}
diff --git a/CODEOWNERS b/CODEOWNERS
new file mode 100644
index 0000000000000000000000000000000000000000..bae5ee300cdb91cbf76cbf47064a301a95edf9b8
--- /dev/null
+++ b/CODEOWNERS
@@ -0,0 +1,13 @@
+# Repository-specific code ownership
+*                            @Florian.Schueltke 
+
+# File-specific code ownership
+.gitattributes               @Florian.Schueltke
+.gitignore                   @Florian.Schueltke
+.gitlab-ci.yml               @maurice.zimmnau   @kristina.mazur
+.gitmodules                  @Florian.Schueltke
+CMakeLists.txt               @Florian.Schueltke
+CMakePresets.json            @Florian.Schueltke
+CODEOWNERS                   @Florian.Schueltke
+LICENSE                      @Florian.Schueltke
+README.md                    @Florian.Schueltke
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..e06ae69696acc3a0209f8fb93f7e4203fd960279
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 2025 UNICADO consortium
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) 2025 UNICADO consortium
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<https://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<https://www.gnu.org/licenses/why-not-lgpl.html>.
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000000000000000000000000000000000000..845615c4586e99b4d8350eedf9a431e238f54a85
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,21 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+pyinstaller = "*"
+pyqt5 = "*"
+numpy = "*"
+ambiance = "*"
+matplotlib = "*"
+yattag = "*"
+termcolor = "*"
+bs4 = "*"
+pandas = "*"
+openpyxl = "*"
+
+[dev-packages]
+
+[requires]
+python_version = "3.11"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000000000000000000000000000000000000..caf89f47c231aaefa3bc84f413300fb0c6972895
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,763 @@
+{
+    "_meta": {
+        "hash": {
+            "sha256": "ea76d0d42b38be487b49162bfd491011106d08810411dc447579d518b0ebe475"
+        },
+        "pipfile-spec": 6,
+        "requires": {
+            "python_version": "3.11"
+        },
+        "sources": [
+            {
+                "name": "pypi",
+                "url": "https://pypi.org/simple",
+                "verify_ssl": true
+            }
+        ]
+    },
+    "default": {
+        "altgraph": {
+            "hashes": [
+                "sha256:1b5afbb98f6c4dcadb2e2ae6ab9fa994bbb8c1d75f4fa96d340f9437ae454406",
+                "sha256:642743b4750de17e655e6711601b077bc6598dbfa3ba5fa2b2a35ce12b508dff"
+            ],
+            "version": "==0.17.4"
+        },
+        "ambiance": {
+            "hashes": [
+                "sha256:ceff180945a96996da5a3aceff2f2ff4f1ae67dadd24919675223c8e01d0a416",
+                "sha256:d7ccd04390e59727ffca5c54079586fe0b40419db5445b524db563a9405f015a"
+            ],
+            "index": "pypi",
+            "markers": "python_full_version >= '3.6.0'",
+            "version": "==1.3.1"
+        },
+        "beautifulsoup4": {
+            "hashes": [
+                "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051",
+                "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"
+            ],
+            "markers": "python_full_version >= '3.6.0'",
+            "version": "==4.12.3"
+        },
+        "bs4": {
+            "hashes": [
+                "sha256:a48685c58f50fe127722417bae83fe6badf500d54b55f7e39ffe43b798653925",
+                "sha256:abf8742c0805ef7f662dce4b51cca104cffe52b835238afc169142ab9b3fbccc"
+            ],
+            "index": "pypi",
+            "version": "==0.0.2"
+        },
+        "contourpy": {
+            "hashes": [
+                "sha256:041b640d4ec01922083645a94bb3b2e777e6b626788f4095cf21abbe266413c1",
+                "sha256:05e806338bfeaa006acbdeba0ad681a10be63b26e1b17317bfac3c5d98f36cda",
+                "sha256:08d9d449a61cf53033612cb368f3a1b26cd7835d9b8cd326647efe43bca7568d",
+                "sha256:0ffa84be8e0bd33410b17189f7164c3589c229ce5db85798076a3fa136d0e509",
+                "sha256:113231fe3825ebf6f15eaa8bc1f5b0ddc19d42b733345eae0934cb291beb88b6",
+                "sha256:14c102b0eab282427b662cb590f2e9340a9d91a1c297f48729431f2dcd16e14f",
+                "sha256:174e758c66bbc1c8576992cec9599ce8b6672b741b5d336b5c74e35ac382b18e",
+                "sha256:19c1555a6801c2f084c7ddc1c6e11f02eb6a6016ca1318dd5452ba3f613a1751",
+                "sha256:19d40d37c1c3a4961b4619dd9d77b12124a453cc3d02bb31a07d58ef684d3d86",
+                "sha256:1bf98051f1045b15c87868dbaea84f92408337d4f81d0e449ee41920ea121d3b",
+                "sha256:20914c8c973f41456337652a6eeca26d2148aa96dd7ac323b74516988bea89fc",
+                "sha256:287ccc248c9e0d0566934e7d606201abd74761b5703d804ff3df8935f523d546",
+                "sha256:2ba94a401342fc0f8b948e57d977557fbf4d515f03c67682dd5c6191cb2d16ec",
+                "sha256:31c1b55c1f34f80557d3830d3dd93ba722ce7e33a0b472cba0ec3b6535684d8f",
+                "sha256:36987a15e8ace5f58d4d5da9dca82d498c2bbb28dff6e5d04fbfcc35a9cb3a82",
+                "sha256:3a04ecd68acbd77fa2d39723ceca4c3197cb2969633836ced1bea14e219d077c",
+                "sha256:3e8b974d8db2c5610fb4e76307e265de0edb655ae8169e8b21f41807ccbeec4b",
+                "sha256:3ea9924d28fc5586bf0b42d15f590b10c224117e74409dd7a0be3b62b74a501c",
+                "sha256:4318af1c925fb9a4fb190559ef3eec206845f63e80fb603d47f2d6d67683901c",
+                "sha256:44a29502ca9c7b5ba389e620d44f2fbe792b1fb5734e8b931ad307071ec58c53",
+                "sha256:47734d7073fb4590b4a40122b35917cd77be5722d80683b249dac1de266aac80",
+                "sha256:4d76d5993a34ef3df5181ba3c92fabb93f1eaa5729504fb03423fcd9f3177242",
+                "sha256:4dbbc03a40f916a8420e420d63e96a1258d3d1b58cbdfd8d1f07b49fcbd38e85",
+                "sha256:500360b77259914f7805af7462e41f9cb7ca92ad38e9f94d6c8641b089338124",
+                "sha256:523a8ee12edfa36f6d2a49407f705a6ef4c5098de4f498619787e272de93f2d5",
+                "sha256:573abb30e0e05bf31ed067d2f82500ecfdaec15627a59d63ea2d95714790f5c2",
+                "sha256:5b75aa69cb4d6f137b36f7eb2ace9280cfb60c55dc5f61c731fdf6f037f958a3",
+                "sha256:61332c87493b00091423e747ea78200659dc09bdf7fd69edd5e98cef5d3e9a8d",
+                "sha256:805617228ba7e2cbbfb6c503858e626ab528ac2a32a04a2fe88ffaf6b02c32bc",
+                "sha256:841ad858cff65c2c04bf93875e384ccb82b654574a6d7f30453a04f04af71342",
+                "sha256:89785bb2a1980c1bd87f0cb1517a71cde374776a5f150936b82580ae6ead44a1",
+                "sha256:8eb96e79b9f3dcadbad2a3891672f81cdcab7f95b27f28f1c67d75f045b6b4f1",
+                "sha256:974d8145f8ca354498005b5b981165b74a195abfae9a8129df3e56771961d595",
+                "sha256:9ddeb796389dadcd884c7eb07bd14ef12408aaae358f0e2ae24114d797eede30",
+                "sha256:a045f341a77b77e1c5de31e74e966537bba9f3c4099b35bf4c2e3939dd54cdab",
+                "sha256:a0cffcbede75c059f535725c1680dfb17b6ba8753f0c74b14e6a9c68c29d7ea3",
+                "sha256:a761d9ccfc5e2ecd1bf05534eda382aa14c3e4f9205ba5b1684ecfe400716ef2",
+                "sha256:a7895f46d47671fa7ceec40f31fae721da51ad34bdca0bee83e38870b1f47ffd",
+                "sha256:a9fa36448e6a3a1a9a2ba23c02012c43ed88905ec80163f2ffe2421c7192a5d7",
+                "sha256:ab29962927945d89d9b293eabd0d59aea28d887d4f3be6c22deaefbb938a7277",
+                "sha256:abbb49fb7dac584e5abc6636b7b2a7227111c4f771005853e7d25176daaf8453",
+                "sha256:ac4578ac281983f63b400f7fe6c101bedc10651650eef012be1ccffcbacf3697",
+                "sha256:adce39d67c0edf383647a3a007de0a45fd1b08dedaa5318404f1a73059c2512b",
+                "sha256:ade08d343436a94e633db932e7e8407fe7de8083967962b46bdfc1b0ced39454",
+                "sha256:b2bdca22a27e35f16794cf585832e542123296b4687f9fd96822db6bae17bfc9",
+                "sha256:b2f926efda994cdf3c8d3fdb40b9962f86edbc4457e739277b961eced3d0b4c1",
+                "sha256:b457d6430833cee8e4b8e9b6f07aa1c161e5e0d52e118dc102c8f9bd7dd060d6",
+                "sha256:c414fc1ed8ee1dbd5da626cf3710c6013d3d27456651d156711fa24f24bd1291",
+                "sha256:cb76c1a154b83991a3cbbf0dfeb26ec2833ad56f95540b442c73950af2013750",
+                "sha256:dfd97abd83335045a913e3bcc4a09c0ceadbe66580cf573fe961f4a825efa699",
+                "sha256:e914a8cb05ce5c809dd0fe350cfbb4e881bde5e2a38dc04e3afe1b3e58bd158e",
+                "sha256:ece6df05e2c41bd46776fbc712e0996f7c94e0d0543af1656956d150c4ca7c81",
+                "sha256:efa874e87e4a647fd2e4f514d5e91c7d493697127beb95e77d2f7561f6905bd9",
+                "sha256:f611e628ef06670df83fce17805c344710ca5cde01edfdc72751311da8585375"
+            ],
+            "markers": "python_version >= '3.10'",
+            "version": "==1.3.1"
+        },
+        "cycler": {
+            "hashes": [
+                "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30",
+                "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"
+            ],
+            "markers": "python_version >= '3.8'",
+            "version": "==0.12.1"
+        },
+        "et-xmlfile": {
+            "hashes": [
+                "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa",
+                "sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54"
+            ],
+            "markers": "python_version >= '3.8'",
+            "version": "==2.0.0"
+        },
+        "fonttools": {
+            "hashes": [
+                "sha256:00f7cf55ad58a57ba421b6a40945b85ac7cc73094fb4949c41171d3619a3a47e",
+                "sha256:01124f2ca6c29fad4132d930da69158d3f49b2350e4a779e1efbe0e82bd63f6c",
+                "sha256:12db5888cd4dd3fcc9f0ee60c6edd3c7e1fd44b7dd0f31381ea03df68f8a153f",
+                "sha256:161d1ac54c73d82a3cded44202d0218ab007fde8cf194a23d3dd83f7177a2f03",
+                "sha256:1f0e115281a32ff532118aa851ef497a1b7cda617f4621c1cdf81ace3e36fb0c",
+                "sha256:23bbbb49bec613a32ed1b43df0f2b172313cee690c2509f1af8fdedcf0a17438",
+                "sha256:2863555ba90b573e4201feaf87a7e71ca3b97c05aa4d63548a4b69ea16c9e998",
+                "sha256:2b3ab90ec0f7b76c983950ac601b58949f47aca14c3f21eed858b38d7ec42b05",
+                "sha256:31d00f9852a6051dac23294a4cf2df80ced85d1d173a61ba90a3d8f5abc63c60",
+                "sha256:33b52a9cfe4e658e21b1f669f7309b4067910321757fec53802ca8f6eae96a5a",
+                "sha256:37dbb3fdc2ef7302d3199fb12468481cbebaee849e4b04bc55b77c24e3c49189",
+                "sha256:3e569711464f777a5d4ef522e781dc33f8095ab5efd7548958b36079a9f2f88c",
+                "sha256:3f901cef813f7c318b77d1c5c14cf7403bae5cb977cede023e22ba4316f0a8f6",
+                "sha256:51c029d4c0608a21a3d3d169dfc3fb776fde38f00b35ca11fdab63ba10a16f61",
+                "sha256:5435e5f1eb893c35c2bc2b9cd3c9596b0fcb0a59e7a14121562986dd4c47b8dd",
+                "sha256:553bd4f8cc327f310c20158e345e8174c8eed49937fb047a8bda51daf2c353c8",
+                "sha256:55718e8071be35dff098976bc249fc243b58efa263768c611be17fe55975d40a",
+                "sha256:61dc0a13451143c5e987dec5254d9d428f3c2789a549a7cf4f815b63b310c1cc",
+                "sha256:636caaeefe586d7c84b5ee0734c1a5ab2dae619dc21c5cf336f304ddb8f6001b",
+                "sha256:6c99b5205844f48a05cb58d4a8110a44d3038c67ed1d79eb733c4953c628b0f6",
+                "sha256:7208856f61770895e79732e1dcbe49d77bd5783adf73ae35f87fcc267df9db81",
+                "sha256:732a9a63d6ea4a81b1b25a1f2e5e143761b40c2e1b79bb2b68e4893f45139a40",
+                "sha256:7636acc6ab733572d5e7eec922b254ead611f1cdad17be3f0be7418e8bfaca71",
+                "sha256:7dd91ac3fcb4c491bb4763b820bcab6c41c784111c24172616f02f4bc227c17d",
+                "sha256:8118dc571921dc9e4b288d9cb423ceaf886d195a2e5329cc427df82bba872cd9",
+                "sha256:81ffd58d2691f11f7c8438796e9f21c374828805d33e83ff4b76e4635633674c",
+                "sha256:838d2d8870f84fc785528a692e724f2379d5abd3fc9dad4d32f91cf99b41e4a7",
+                "sha256:8c9679fc0dd7e8a5351d321d8d29a498255e69387590a86b596a45659a39eb0d",
+                "sha256:9ce4ba6981e10f7e0ccff6348e9775ce25ffadbee70c9fd1a3737e3e9f5fa74f",
+                "sha256:a656652e1f5d55b9728937a7e7d509b73d23109cddd4e89ee4f49bde03b736c6",
+                "sha256:a7ad1f1b98ab6cb927ab924a38a8649f1ffd7525c75fe5b594f5dab17af70e18",
+                "sha256:aa046f6a63bb2ad521004b2769095d4c9480c02c1efa7d7796b37826508980b6",
+                "sha256:abe62987c37630dca69a104266277216de1023cf570c1643bb3a19a9509e7a1b",
+                "sha256:b2e526b325a903868c62155a6a7e24df53f6ce4c5c3160214d8fe1be2c41b478",
+                "sha256:b5263d8e7ef3c0ae87fbce7f3ec2f546dc898d44a337e95695af2cd5ea21a967",
+                "sha256:b7ef9068a1297714e6fefe5932c33b058aa1d45a2b8be32a4c6dee602ae22b5c",
+                "sha256:bca35b4e411362feab28e576ea10f11268b1aeed883b9f22ed05675b1e06ac69",
+                "sha256:ca7fd6987c68414fece41c96836e945e1f320cda56fc96ffdc16e54a44ec57a2",
+                "sha256:d12081729280c39d001edd0f4f06d696014c26e6e9a0a55488fabc37c28945e4",
+                "sha256:dd2820a8b632f3307ebb0bf57948511c2208e34a4939cf978333bc0a3f11f838",
+                "sha256:e198e494ca6e11f254bac37a680473a311a88cd40e58f9cc4dc4911dfb686ec6",
+                "sha256:e7e6a352ff9e46e8ef8a3b1fe2c4478f8a553e1b5a479f2e899f9dc5f2055880",
+                "sha256:e8e67974326af6a8879dc2a4ec63ab2910a1c1a9680ccd63e4a690950fceddbe",
+                "sha256:f0a4b52238e7b54f998d6a56b46a2c56b59c74d4f8a6747fb9d4042190f37cd3",
+                "sha256:f27526042efd6f67bfb0cc2f1610fa20364396f8b1fc5edb9f45bb815fb090b2",
+                "sha256:f307f6b5bf9e86891213b293e538d292cd1677e06d9faaa4bf9c086ad5f132f6",
+                "sha256:f46b863d74bab7bb0d395f3b68d3f52a03444964e67ce5c43ce43a75efce9246",
+                "sha256:f50a1f455902208486fbca47ce33054208a4e437b38da49d6721ce2fef732fcf",
+                "sha256:f8c8c76037d05652510ae45be1cd8fb5dd2fd9afec92a25374ac82255993d57c",
+                "sha256:fa34aa175c91477485c44ddfbb51827d470011e558dfd5c7309eb31bef19ec51"
+            ],
+            "markers": "python_version >= '3.8'",
+            "version": "==4.55.0"
+        },
+        "kiwisolver": {
+            "hashes": [
+                "sha256:073a36c8273647592ea332e816e75ef8da5c303236ec0167196793eb1e34657a",
+                "sha256:08471d4d86cbaec61f86b217dd938a83d85e03785f51121e791a6e6689a3be95",
+                "sha256:0c18ec74c0472de033e1bebb2911c3c310eef5649133dd0bedf2a169a1b269e5",
+                "sha256:0c6c43471bc764fad4bc99c5c2d6d16a676b1abf844ca7c8702bdae92df01ee0",
+                "sha256:10849fb2c1ecbfae45a693c070e0320a91b35dd4bcf58172c023b994283a124d",
+                "sha256:18077b53dc3bb490e330669a99920c5e6a496889ae8c63b58fbc57c3d7f33a18",
+                "sha256:18e0cca3e008e17fe9b164b55735a325140a5a35faad8de92dd80265cd5eb80b",
+                "sha256:22f499f6157236c19f4bbbd472fa55b063db77a16cd74d49afe28992dff8c258",
+                "sha256:2a8781ac3edc42ea4b90bc23e7d37b665d89423818e26eb6df90698aa2287c95",
+                "sha256:2e6039dcbe79a8e0f044f1c39db1986a1b8071051efba3ee4d74f5b365f5226e",
+                "sha256:34ea1de54beef1c104422d210c47c7d2a4999bdecf42c7b5718fbe59a4cac383",
+                "sha256:3ab58c12a2cd0fc769089e6d38466c46d7f76aced0a1f54c77652446733d2d02",
+                "sha256:3abc5b19d24af4b77d1598a585b8a719beb8569a71568b66f4ebe1fb0449460b",
+                "sha256:3bf1ed55088f214ba6427484c59553123fdd9b218a42bbc8c6496d6754b1e523",
+                "sha256:3ce6b2b0231bda412463e152fc18335ba32faf4e8c23a754ad50ffa70e4091ee",
+                "sha256:3da53da805b71e41053dc670f9a820d1157aae77b6b944e08024d17bcd51ef88",
+                "sha256:3f9362ecfca44c863569d3d3c033dbe8ba452ff8eed6f6b5806382741a1334bd",
+                "sha256:409afdfe1e2e90e6ee7fc896f3df9a7fec8e793e58bfa0d052c8a82f99c37abb",
+                "sha256:40fa14dbd66b8b8f470d5fc79c089a66185619d31645f9b0773b88b19f7223c4",
+                "sha256:4322872d5772cae7369f8351da1edf255a604ea7087fe295411397d0cfd9655e",
+                "sha256:44756f9fd339de0fb6ee4f8c1696cfd19b2422e0d70b4cefc1cc7f1f64045a8c",
+                "sha256:46707a10836894b559e04b0fd143e343945c97fd170d69a2d26d640b4e297935",
+                "sha256:48b571ecd8bae15702e4f22d3ff6a0f13e54d3d00cd25216d5e7f658242065ee",
+                "sha256:48be928f59a1f5c8207154f935334d374e79f2b5d212826307d072595ad76a2e",
+                "sha256:4bfa75a048c056a411f9705856abfc872558e33c055d80af6a380e3658766038",
+                "sha256:4c00336b9dd5ad96d0a558fd18a8b6f711b7449acce4c157e7343ba92dd0cf3d",
+                "sha256:4c26ed10c4f6fa6ddb329a5120ba3b6db349ca192ae211e882970bfc9d91420b",
+                "sha256:4d05d81ecb47d11e7f8932bd8b61b720bf0b41199358f3f5e36d38e28f0532c5",
+                "sha256:4e77f2126c3e0b0d055f44513ed349038ac180371ed9b52fe96a32aa071a5107",
+                "sha256:5337ec7809bcd0f424c6b705ecf97941c46279cf5ed92311782c7c9c2026f07f",
+                "sha256:5360cc32706dab3931f738d3079652d20982511f7c0ac5711483e6eab08efff2",
+                "sha256:58370b1ffbd35407444d57057b57da5d6549d2d854fa30249771775c63b5fe17",
+                "sha256:58cb20602b18f86f83a5c87d3ee1c766a79c0d452f8def86d925e6c60fbf7bfb",
+                "sha256:599b5c873c63a1f6ed7eead644a8a380cfbdf5db91dcb6f85707aaab213b1674",
+                "sha256:5b7dfa3b546da08a9f622bb6becdb14b3e24aaa30adba66749d38f3cc7ea9706",
+                "sha256:5b9c3f4ee0b9a439d2415012bd1b1cc2df59e4d6a9939f4d669241d30b414327",
+                "sha256:5d34eb8494bea691a1a450141ebb5385e4b69d38bb8403b5146ad279f4b30fa3",
+                "sha256:5d5abf8f8ec1f4e22882273c423e16cae834c36856cac348cfbfa68e01c40f3a",
+                "sha256:5e3bc157fed2a4c02ec468de4ecd12a6e22818d4f09cde2c31ee3226ffbefab2",
+                "sha256:612a10bdae23404a72941a0fc8fa2660c6ea1217c4ce0dbcab8a8f6543ea9e7f",
+                "sha256:657a05857bda581c3656bfc3b20e353c232e9193eb167766ad2dc58b56504948",
+                "sha256:65e720d2ab2b53f1f72fb5da5fb477455905ce2c88aaa671ff0a447c2c80e8e3",
+                "sha256:693902d433cf585133699972b6d7c42a8b9f8f826ebcaf0132ff55200afc599e",
+                "sha256:6af936f79086a89b3680a280c47ea90b4df7047b5bdf3aa5c524bbedddb9e545",
+                "sha256:71bb308552200fb2c195e35ef05de12f0c878c07fc91c270eb3d6e41698c3bcc",
+                "sha256:764202cc7e70f767dab49e8df52c7455e8de0df5d858fa801a11aa0d882ccf3f",
+                "sha256:76c8094ac20ec259471ac53e774623eb62e6e1f56cd8690c67ce6ce4fcb05650",
+                "sha256:78a42513018c41c2ffd262eb676442315cbfe3c44eed82385c2ed043bc63210a",
+                "sha256:79849239c39b5e1fd906556c474d9b0439ea6792b637511f3fe3a41158d89ca8",
+                "sha256:7ab9ccab2b5bd5702ab0803676a580fffa2aa178c2badc5557a84cc943fcf750",
+                "sha256:7bbfcb7165ce3d54a3dfbe731e470f65739c4c1f85bb1018ee912bae139e263b",
+                "sha256:7c06a4c7cf15ec739ce0e5971b26c93638730090add60e183530d70848ebdd34",
+                "sha256:801fa7802e5cfabe3ab0c81a34c323a319b097dfb5004be950482d882f3d7225",
+                "sha256:803b8e1459341c1bb56d1c5c010406d5edec8a0713a0945851290a7930679b51",
+                "sha256:82a5c2f4b87c26bb1a0ef3d16b5c4753434633b83d365cc0ddf2770c93829e3c",
+                "sha256:84ec80df401cfee1457063732d90022f93951944b5b58975d34ab56bb150dfb3",
+                "sha256:8705f17dfeb43139a692298cb6637ee2e59c0194538153e83e9ee0c75c2eddde",
+                "sha256:88a9ca9c710d598fd75ee5de59d5bda2684d9db36a9f50b6125eaea3969c2599",
+                "sha256:88f17c5ffa8e9462fb79f62746428dd57b46eb931698e42e990ad63103f35e6c",
+                "sha256:8a3ec5aa8e38fc4c8af308917ce12c536f1c88452ce554027e55b22cbbfbff76",
+                "sha256:8a9c83f75223d5e48b0bc9cb1bf2776cf01563e00ade8775ffe13b0b6e1af3a6",
+                "sha256:8b01aac285f91ca889c800042c35ad3b239e704b150cfd3382adfc9dcc780e39",
+                "sha256:8d53103597a252fb3ab8b5845af04c7a26d5e7ea8122303dd7a021176a87e8b9",
+                "sha256:8e045731a5416357638d1700927529e2b8ab304811671f665b225f8bf8d8f933",
+                "sha256:8f0ea6da6d393d8b2e187e6a5e3fb81f5862010a40c3945e2c6d12ae45cfb2ad",
+                "sha256:90da3b5f694b85231cf93586dad5e90e2d71b9428f9aad96952c99055582f520",
+                "sha256:913983ad2deb14e66d83c28b632fd35ba2b825031f2fa4ca29675e665dfecbe1",
+                "sha256:9242795d174daa40105c1d86aba618e8eab7bf96ba8c3ee614da8302a9f95503",
+                "sha256:929e294c1ac1e9f615c62a4e4313ca1823ba37326c164ec720a803287c4c499b",
+                "sha256:933d4de052939d90afbe6e9d5273ae05fb836cc86c15b686edd4b3560cc0ee36",
+                "sha256:942216596dc64ddb25adb215c3c783215b23626f8d84e8eff8d6d45c3f29f75a",
+                "sha256:94252291e3fe68001b1dd747b4c0b3be12582839b95ad4d1b641924d68fd4643",
+                "sha256:9893ff81bd7107f7b685d3017cc6583daadb4fc26e4a888350df530e41980a60",
+                "sha256:9e838bba3a3bac0fe06d849d29772eb1afb9745a59710762e4ba3f4cb8424483",
+                "sha256:a0f64a48bb81af7450e641e3fe0b0394d7381e342805479178b3d335d60ca7cf",
+                "sha256:a17f6a29cf8935e587cc8a4dbfc8368c55edc645283db0ce9801016f83526c2d",
+                "sha256:a1ecf0ac1c518487d9d23b1cd7139a6a65bc460cd101ab01f1be82ecf09794b6",
+                "sha256:a79ae34384df2b615eefca647a2873842ac3b596418032bef9a7283675962644",
+                "sha256:a91b5f9f1205845d488c928e8570dcb62b893372f63b8b6e98b863ebd2368ff2",
+                "sha256:aa0abdf853e09aff551db11fce173e2177d00786c688203f52c87ad7fcd91ef9",
+                "sha256:ac542bf38a8a4be2dc6b15248d36315ccc65f0743f7b1a76688ffb6b5129a5c2",
+                "sha256:ad42ba922c67c5f219097b28fae965e10045ddf145d2928bfac2eb2e17673640",
+                "sha256:aeb3531b196ef6f11776c21674dba836aeea9d5bd1cf630f869e3d90b16cfade",
+                "sha256:b38ac83d5f04b15e515fd86f312479d950d05ce2368d5413d46c088dda7de90a",
+                "sha256:b7d755065e4e866a8086c9bdada157133ff466476a2ad7861828e17b6026e22c",
+                "sha256:bd3de6481f4ed8b734da5df134cd5a6a64fe32124fe83dde1e5b5f29fe30b1e6",
+                "sha256:bfa1acfa0c54932d5607e19a2c24646fb4c1ae2694437789129cf099789a3b00",
+                "sha256:c619b101e6de2222c1fcb0531e1b17bbffbe54294bfba43ea0d411d428618c27",
+                "sha256:ce8be0466f4c0d585cdb6c1e2ed07232221df101a4c6f28821d2aa754ca2d9e2",
+                "sha256:cf0438b42121a66a3a667de17e779330fc0f20b0d97d59d2f2121e182b0505e4",
+                "sha256:cf8bcc23ceb5a1b624572a1623b9f79d2c3b337c8c455405ef231933a10da379",
+                "sha256:d2b0e12a42fb4e72d509fc994713d099cbb15ebf1103545e8a45f14da2dfca54",
+                "sha256:d83db7cde68459fc803052a55ace60bea2bae361fc3b7a6d5da07e11954e4b09",
+                "sha256:dda56c24d869b1193fcc763f1284b9126550eaf84b88bbc7256e15028f19188a",
+                "sha256:dea0bf229319828467d7fca8c7c189780aa9ff679c94539eed7532ebe33ed37c",
+                "sha256:e1631290ee9271dffe3062d2634c3ecac02c83890ada077d225e081aca8aab89",
+                "sha256:e28c7fea2196bf4c2f8d46a0415c77a1c480cc0724722f23d7410ffe9842c407",
+                "sha256:e2e6c39bd7b9372b0be21456caab138e8e69cc0fc1190a9dfa92bd45a1e6e904",
+                "sha256:e33e8fbd440c917106b237ef1a2f1449dfbb9b6f6e1ce17c94cd6a1e0d438376",
+                "sha256:e8df2eb9b2bac43ef8b082e06f750350fbbaf2887534a5be97f6cf07b19d9583",
+                "sha256:e968b84db54f9d42046cf154e02911e39c0435c9801681e3fc9ce8a3c4130278",
+                "sha256:eb542fe7933aa09d8d8f9d9097ef37532a7df6497819d16efe4359890a2f417a",
+                "sha256:edcfc407e4eb17e037bca59be0e85a2031a2ac87e4fed26d3e9df88b4165f92d",
+                "sha256:eee3ea935c3d227d49b4eb85660ff631556841f6e567f0f7bda972df6c2c9935",
+                "sha256:ef97b8df011141c9b0f6caf23b29379f87dd13183c978a30a3c546d2c47314cb",
+                "sha256:f106407dda69ae456dd1227966bf445b157ccc80ba0dff3802bb63f30b74e895",
+                "sha256:f3160309af4396e0ed04db259c3ccbfdc3621b5559b5453075e5de555e1f3a1b",
+                "sha256:f32d6edbc638cde7652bd690c3e728b25332acbadd7cad670cc4a02558d9c417",
+                "sha256:f37cfe618a117e50d8c240555331160d73d0411422b59b5ee217843d7b693608",
+                "sha256:f4c9aee212bc89d4e13f58be11a56cc8036cabad119259d12ace14b34476fd07",
+                "sha256:f4d742cb7af1c28303a51b7a27aaee540e71bb8e24f68c736f6f2ffc82f2bf05",
+                "sha256:f5a8b53bdc0b3961f8b6125e198617c40aeed638b387913bf1ce78afb1b0be2a",
+                "sha256:f816dd2277f8d63d79f9c8473a79fe54047bc0467754962840782c575522224d",
+                "sha256:f9a9e8a507420fe35992ee9ecb302dab68550dedc0da9e2880dd88071c5fb052"
+            ],
+            "markers": "python_version >= '3.8'",
+            "version": "==1.4.7"
+        },
+        "matplotlib": {
+            "hashes": [
+                "sha256:039082812cacd6c6bec8e17a9c1e6baca230d4116d522e81e1f63a74d01d2e21",
+                "sha256:03ba9c1299c920964e8d3857ba27173b4dbb51ca4bab47ffc2c2ba0eb5e2cbc5",
+                "sha256:050598c2b29e0b9832cde72bcf97627bf00262adbc4a54e2b856426bb2ef0697",
+                "sha256:18128cc08f0d3cfff10b76baa2f296fc28c4607368a8402de61bb3f2eb33c7d9",
+                "sha256:1cd93b91ab47a3616b4d3c42b52f8363b88ca021e340804c6ab2536344fad9ca",
+                "sha256:1d94ff717eb2bd0b58fe66380bd8b14ac35f48a98e7c6765117fe67fb7684e64",
+                "sha256:306c8dfc73239f0e72ac50e5a9cf19cc4e8e331dd0c54f5e69ca8758550f1e1e",
+                "sha256:37e51dd1c2db16ede9cfd7b5cabdfc818b2c6397c83f8b10e0e797501c963a03",
+                "sha256:3fd595f34aa8a55b7fc8bf9ebea8aa665a84c82d275190a61118d33fbc82ccae",
+                "sha256:4876d7d40219e8ae8bb70f9263bcbe5714415acfdf781086601211335e24f8aa",
+                "sha256:5413401594cfaff0052f9d8b1aafc6d305b4bd7c4331dccd18f561ff7e1d3bd3",
+                "sha256:5816b1e1fe8c192cbc013f8f3e3368ac56fbecf02fb41b8f8559303f24c5015e",
+                "sha256:65aacf95b62272d568044531e41de26285d54aec8cb859031f511f84bd8b495a",
+                "sha256:6758baae2ed64f2331d4fd19be38b7b4eae3ecec210049a26b6a4f3ae1c85dcc",
+                "sha256:6d1ce5ed2aefcdce11904fc5bbea7d9c21fff3d5f543841edf3dea84451a09ea",
+                "sha256:6d9f07a80deab4bb0b82858a9e9ad53d1382fd122be8cde11080f4e7dfedb38b",
+                "sha256:7741f26a58a240f43bee74965c4882b6c93df3e7eb3de160126d8c8f53a6ae6e",
+                "sha256:8912ef7c2362f7193b5819d17dae8629b34a95c58603d781329712ada83f9447",
+                "sha256:909645cce2dc28b735674ce0931a4ac94e12f5b13f6bb0b5a5e65e7cea2c192b",
+                "sha256:96ab43906269ca64a6366934106fa01534454a69e471b7bf3d79083981aaab92",
+                "sha256:9d78bbc0cbc891ad55b4f39a48c22182e9bdaea7fc0e5dbd364f49f729ca1bbb",
+                "sha256:ab68d50c06938ef28681073327795c5db99bb4666214d2d5f880ed11aeaded66",
+                "sha256:ac43031375a65c3196bee99f6001e7fa5bdfb00ddf43379d3c0609bdca042df9",
+                "sha256:ae82a14dab96fbfad7965403c643cafe6515e386de723e498cf3eeb1e0b70cc7",
+                "sha256:b2696efdc08648536efd4e1601b5fd491fd47f4db97a5fbfd175549a7365c1b2",
+                "sha256:b82c5045cebcecd8496a4d694d43f9cc84aeeb49fe2133e036b207abe73f4d30",
+                "sha256:be0fc24a5e4531ae4d8e858a1a548c1fe33b176bb13eff7f9d0d38ce5112a27d",
+                "sha256:bf81de2926c2db243c9b2cbc3917619a0fc85796c6ba4e58f541df814bbf83c7",
+                "sha256:c375cc72229614632c87355366bdf2570c2dac01ac66b8ad048d2dabadf2d0d4",
+                "sha256:c797dac8bb9c7a3fd3382b16fe8f215b4cf0f22adccea36f1545a6d7be310b41",
+                "sha256:cef2a73d06601437be399908cf13aee74e86932a5ccc6ccdf173408ebc5f6bb2",
+                "sha256:d52a3b618cb1cbb769ce2ee1dcdb333c3ab6e823944e9a2d36e37253815f9556",
+                "sha256:d719465db13267bcef19ea8954a971db03b9f48b4647e3860e4bc8e6ed86610f",
+                "sha256:d8dd059447824eec055e829258ab092b56bb0579fc3164fa09c64f3acd478772",
+                "sha256:dbe196377a8248972f5cede786d4c5508ed5f5ca4a1e09b44bda889958b33f8c",
+                "sha256:e0830e188029c14e891fadd99702fd90d317df294c3298aad682739c5533721a",
+                "sha256:f053c40f94bc51bc03832a41b4f153d83f2062d88c72b5e79997072594e97e51",
+                "sha256:f32c7410c7f246838a77d6d1eff0c0f87f3cb0e7c4247aebea71a6d5a68cab49",
+                "sha256:f6ee45bc4245533111ced13f1f2cace1e7f89d1c793390392a80c139d6cf0e6c",
+                "sha256:f7c0410f181a531ec4e93bbc27692f2c71a15c2da16766f5ba9761e7ae518413"
+            ],
+            "index": "pypi",
+            "markers": "python_version >= '3.9'",
+            "version": "==3.9.2"
+        },
+        "numpy": {
+            "hashes": [
+                "sha256:016d0f6f5e77b0f0d45d77387ffa4bb89816b57c835580c3ce8e099ef830befe",
+                "sha256:02135ade8b8a84011cbb67dc44e07c58f28575cf9ecf8ab304e51c05528c19f0",
+                "sha256:08788d27a5fd867a663f6fc753fd7c3ad7e92747efc73c53bca2f19f8bc06f48",
+                "sha256:0d30c543f02e84e92c4b1f415b7c6b5326cbe45ee7882b6b77db7195fb971e3a",
+                "sha256:0fa14563cc46422e99daef53d725d0c326e99e468a9320a240affffe87852564",
+                "sha256:13138eadd4f4da03074851a698ffa7e405f41a0845a6b1ad135b81596e4e9958",
+                "sha256:14e253bd43fc6b37af4921b10f6add6925878a42a0c5fe83daee390bca80bc17",
+                "sha256:15cb89f39fa6d0bdfb600ea24b250e5f1a3df23f901f51c8debaa6a5d122b2f0",
+                "sha256:17ee83a1f4fef3c94d16dc1802b998668b5419362c8a4f4e8a491de1b41cc3ee",
+                "sha256:2312b2aa89e1f43ecea6da6ea9a810d06aae08321609d8dc0d0eda6d946a541b",
+                "sha256:2564fbdf2b99b3f815f2107c1bbc93e2de8ee655a69c261363a1172a79a257d4",
+                "sha256:3522b0dfe983a575e6a9ab3a4a4dfe156c3e428468ff08ce582b9bb6bd1d71d4",
+                "sha256:4394bc0dbd074b7f9b52024832d16e019decebf86caf909d94f6b3f77a8ee3b6",
+                "sha256:45966d859916ad02b779706bb43b954281db43e185015df6eb3323120188f9e4",
+                "sha256:4d1167c53b93f1f5d8a139a742b3c6f4d429b54e74e6b57d0eff40045187b15d",
+                "sha256:4f2015dfe437dfebbfce7c85c7b53d81ba49e71ba7eadbf1df40c915af75979f",
+                "sha256:50ca6aba6e163363f132b5c101ba078b8cbd3fa92c7865fd7d4d62d9779ac29f",
+                "sha256:50d18c4358a0a8a53f12a8ba9d772ab2d460321e6a93d6064fc22443d189853f",
+                "sha256:5641516794ca9e5f8a4d17bb45446998c6554704d888f86df9b200e66bdcce56",
+                "sha256:576a1c1d25e9e02ed7fa5477f30a127fe56debd53b8d2c89d5578f9857d03ca9",
+                "sha256:6a4825252fcc430a182ac4dee5a505053d262c807f8a924603d411f6718b88fd",
+                "sha256:72dcc4a35a8515d83e76b58fdf8113a5c969ccd505c8a946759b24e3182d1f23",
+                "sha256:747641635d3d44bcb380d950679462fae44f54b131be347d5ec2bce47d3df9ed",
+                "sha256:762479be47a4863e261a840e8e01608d124ee1361e48b96916f38b119cfda04a",
+                "sha256:78574ac2d1a4a02421f25da9559850d59457bac82f2b8d7a44fe83a64f770098",
+                "sha256:825656d0743699c529c5943554d223c021ff0494ff1442152ce887ef4f7561a1",
+                "sha256:8637dcd2caa676e475503d1f8fdb327bc495554e10838019651b76d17b98e512",
+                "sha256:96fe52fcdb9345b7cd82ecd34547fca4321f7656d500eca497eb7ea5a926692f",
+                "sha256:973faafebaae4c0aaa1a1ca1ce02434554d67e628b8d805e61f874b84e136b09",
+                "sha256:996bb9399059c5b82f76b53ff8bb686069c05acc94656bb259b1d63d04a9506f",
+                "sha256:a38c19106902bb19351b83802531fea19dee18e5b37b36454f27f11ff956f7fc",
+                "sha256:a6b46587b14b888e95e4a24d7b13ae91fa22386c199ee7b418f449032b2fa3b8",
+                "sha256:a9f7f672a3388133335589cfca93ed468509cb7b93ba3105fce780d04a6576a0",
+                "sha256:aa08e04e08aaf974d4458def539dece0d28146d866a39da5639596f4921fd761",
+                "sha256:b0df3635b9c8ef48bd3be5f862cf71b0a4716fa0e702155c45067c6b711ddcef",
+                "sha256:b47fbb433d3260adcd51eb54f92a2ffbc90a4595f8970ee00e064c644ac788f5",
+                "sha256:baed7e8d7481bfe0874b566850cb0b85243e982388b7b23348c6db2ee2b2ae8e",
+                "sha256:bc6f24b3d1ecc1eebfbf5d6051faa49af40b03be1aaa781ebdadcbc090b4539b",
+                "sha256:c006b607a865b07cd981ccb218a04fc86b600411d83d6fc261357f1c0966755d",
+                "sha256:c181ba05ce8299c7aa3125c27b9c2167bca4a4445b7ce73d5febc411ca692e43",
+                "sha256:c7662f0e3673fe4e832fe07b65c50342ea27d989f92c80355658c7f888fcc83c",
+                "sha256:c80e4a09b3d95b4e1cac08643f1152fa71a0a821a2d4277334c88d54b2219a41",
+                "sha256:c894b4305373b9c5576d7a12b473702afdf48ce5369c074ba304cc5ad8730dff",
+                "sha256:d7aac50327da5d208db2eec22eb11e491e3fe13d22653dce51b0f4109101b408",
+                "sha256:d89dd2b6da69c4fff5e39c28a382199ddedc3a5be5390115608345dec660b9e2",
+                "sha256:d9beb777a78c331580705326d2367488d5bc473b49a9bc3036c154832520aca9",
+                "sha256:dc258a761a16daa791081d026f0ed4399b582712e6fc887a95af09df10c5ca57",
+                "sha256:e14e26956e6f1696070788252dcdff11b4aca4c3e8bd166e0df1bb8f315a67cb",
+                "sha256:e6988e90fcf617da2b5c78902fe8e668361b43b4fe26dbf2d7b0f8034d4cafb9",
+                "sha256:e711e02f49e176a01d0349d82cb5f05ba4db7d5e7e0defd026328e5cfb3226d3",
+                "sha256:ea4dedd6e394a9c180b33c2c872b92f7ce0f8e7ad93e9585312b0c5a04777a4a",
+                "sha256:ecc76a9ba2911d8d37ac01de72834d8849e55473457558e12995f4cd53e778e0",
+                "sha256:f55ba01150f52b1027829b50d70ef1dafd9821ea82905b63936668403c3b471e",
+                "sha256:f653490b33e9c3a4c1c01d41bc2aef08f9475af51146e4a7710c450cf9761598",
+                "sha256:fa2d1337dc61c8dc417fbccf20f6d1e139896a30721b7f1e832b2bb6ef4eb6c4"
+            ],
+            "index": "pypi",
+            "markers": "python_version >= '3.10'",
+            "version": "==2.1.3"
+        },
+        "openpyxl": {
+            "hashes": [
+                "sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2",
+                "sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050"
+            ],
+            "index": "pypi",
+            "markers": "python_version >= '3.8'",
+            "version": "==3.1.5"
+        },
+        "packaging": {
+            "hashes": [
+                "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759",
+                "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"
+            ],
+            "markers": "python_version >= '3.8'",
+            "version": "==24.2"
+        },
+        "pandas": {
+            "hashes": [
+                "sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a",
+                "sha256:15c0e1e02e93116177d29ff83e8b1619c93ddc9c49083f237d4312337a61165d",
+                "sha256:1948ddde24197a0f7add2bdc4ca83bf2b1ef84a1bc8ccffd95eda17fd836ecb5",
+                "sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4",
+                "sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0",
+                "sha256:29401dbfa9ad77319367d36940cd8a0b3a11aba16063e39632d98b0e931ddf32",
+                "sha256:31d0ced62d4ea3e231a9f228366919a5ea0b07440d9d4dac345376fd8e1477ea",
+                "sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28",
+                "sha256:37e0aced3e8f539eccf2e099f65cdb9c8aa85109b0be6e93e2baff94264bdc6f",
+                "sha256:381175499d3802cde0eabbaf6324cce0c4f5d52ca6f8c377c29ad442f50f6348",
+                "sha256:38cf8125c40dae9d5acc10fa66af8ea6fdf760b2714ee482ca691fc66e6fcb18",
+                "sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468",
+                "sha256:3fc6873a41186404dad67245896a6e440baacc92f5b716ccd1bc9ed2995ab2c5",
+                "sha256:4850ba03528b6dd51d6c5d273c46f183f39a9baf3f0143e566b89450965b105e",
+                "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667",
+                "sha256:56534ce0746a58afaf7942ba4863e0ef81c9c50d3f0ae93e9497d6a41a057645",
+                "sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13",
+                "sha256:5dbca4c1acd72e8eeef4753eeca07de9b1db4f398669d5994086f788a5d7cc30",
+                "sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3",
+                "sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d",
+                "sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb",
+                "sha256:63cc132e40a2e084cf01adf0775b15ac515ba905d7dcca47e9a251819c575ef3",
+                "sha256:66108071e1b935240e74525006034333f98bcdb87ea116de573a6a0dccb6c039",
+                "sha256:6dfcb5ee8d4d50c06a51c2fffa6cff6272098ad6540aed1a76d15fb9318194d8",
+                "sha256:7c2875855b0ff77b2a64a0365e24455d9990730d6431b9e0ee18ad8acee13dbd",
+                "sha256:7eee9e7cea6adf3e3d24e304ac6b8300646e2a5d1cd3a3c2abed9101b0846761",
+                "sha256:800250ecdadb6d9c78eae4990da62743b857b470883fa27f652db8bdde7f6659",
+                "sha256:86976a1c5b25ae3f8ccae3a5306e443569ee3c3faf444dfd0f41cda24667ad57",
+                "sha256:8cd6d7cc958a3910f934ea8dbdf17b2364827bb4dafc38ce6eef6bb3d65ff09c",
+                "sha256:99df71520d25fade9db7c1076ac94eb994f4d2673ef2aa2e86ee039b6746d20c",
+                "sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4",
+                "sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a",
+                "sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9",
+                "sha256:b8661b0238a69d7aafe156b7fa86c44b881387509653fdf857bebc5e4008ad42",
+                "sha256:ba96630bc17c875161df3818780af30e43be9b166ce51c9a18c1feae342906c2",
+                "sha256:bc6b93f9b966093cb0fd62ff1a7e4c09e6d546ad7c1de191767baffc57628f39",
+                "sha256:c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc",
+                "sha256:cd8d0c3be0515c12fed0bdbae072551c8b54b7192c7b1fda0ba56059a0179698",
+                "sha256:d9c45366def9a3dd85a6454c0e7908f2b3b8e9c138f5dc38fed7ce720d8453ed",
+                "sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015",
+                "sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24",
+                "sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319"
+            ],
+            "index": "pypi",
+            "markers": "python_version >= '3.9'",
+            "version": "==2.2.3"
+        },
+        "pefile": {
+            "hashes": [
+                "sha256:82e6114004b3d6911c77c3953e3838654b04511b8b66e8583db70c65998017dc",
+                "sha256:da185cd2af68c08a6cd4481f7325ed600a88f6a813bad9dea07ab3ef73d8d8d6"
+            ],
+            "markers": "sys_platform == 'win32'",
+            "version": "==2023.2.7"
+        },
+        "pillow": {
+            "hashes": [
+                "sha256:00177a63030d612148e659b55ba99527803288cea7c75fb05766ab7981a8c1b7",
+                "sha256:006bcdd307cc47ba43e924099a038cbf9591062e6c50e570819743f5607404f5",
+                "sha256:084a07ef0821cfe4858fe86652fffac8e187b6ae677e9906e192aafcc1b69903",
+                "sha256:0ae08bd8ffc41aebf578c2af2f9d8749d91f448b3bfd41d7d9ff573d74f2a6b2",
+                "sha256:0e038b0745997c7dcaae350d35859c9715c71e92ffb7e0f4a8e8a16732150f38",
+                "sha256:1187739620f2b365de756ce086fdb3604573337cc28a0d3ac4a01ab6b2d2a6d2",
+                "sha256:16095692a253047fe3ec028e951fa4221a1f3ed3d80c397e83541a3037ff67c9",
+                "sha256:1a61b54f87ab5786b8479f81c4b11f4d61702830354520837f8cc791ebba0f5f",
+                "sha256:1c1d72714f429a521d8d2d018badc42414c3077eb187a59579f28e4270b4b0fc",
+                "sha256:1e2688958a840c822279fda0086fec1fdab2f95bf2b717b66871c4ad9859d7e8",
+                "sha256:20ec184af98a121fb2da42642dea8a29ec80fc3efbaefb86d8fdd2606619045d",
+                "sha256:21a0d3b115009ebb8ac3d2ebec5c2982cc693da935f4ab7bb5c8ebe2f47d36f2",
+                "sha256:224aaa38177597bb179f3ec87eeefcce8e4f85e608025e9cfac60de237ba6316",
+                "sha256:2679d2258b7f1192b378e2893a8a0a0ca472234d4c2c0e6bdd3380e8dfa21b6a",
+                "sha256:27a7860107500d813fcd203b4ea19b04babe79448268403172782754870dac25",
+                "sha256:290f2cc809f9da7d6d622550bbf4c1e57518212da51b6a30fe8e0a270a5b78bd",
+                "sha256:2e46773dc9f35a1dd28bd6981332fd7f27bec001a918a72a79b4133cf5291dba",
+                "sha256:3107c66e43bda25359d5ef446f59c497de2b5ed4c7fdba0894f8d6cf3822dafc",
+                "sha256:375b8dd15a1f5d2feafff536d47e22f69625c1aa92f12b339ec0b2ca40263273",
+                "sha256:45c566eb10b8967d71bf1ab8e4a525e5a93519e29ea071459ce517f6b903d7fa",
+                "sha256:499c3a1b0d6fc8213519e193796eb1a86a1be4b1877d678b30f83fd979811d1a",
+                "sha256:4ad70c4214f67d7466bea6a08061eba35c01b1b89eaa098040a35272a8efb22b",
+                "sha256:4b60c9520f7207aaf2e1d94de026682fc227806c6e1f55bba7606d1c94dd623a",
+                "sha256:5178952973e588b3f1360868847334e9e3bf49d19e169bbbdfaf8398002419ae",
+                "sha256:52a2d8323a465f84faaba5236567d212c3668f2ab53e1c74c15583cf507a0291",
+                "sha256:598b4e238f13276e0008299bd2482003f48158e2b11826862b1eb2ad7c768b97",
+                "sha256:5bd2d3bdb846d757055910f0a59792d33b555800813c3b39ada1829c372ccb06",
+                "sha256:5c39ed17edea3bc69c743a8dd3e9853b7509625c2462532e62baa0732163a904",
+                "sha256:5d203af30149ae339ad1b4f710d9844ed8796e97fda23ffbc4cc472968a47d0b",
+                "sha256:5ddbfd761ee00c12ee1be86c9c0683ecf5bb14c9772ddbd782085779a63dd55b",
+                "sha256:607bbe123c74e272e381a8d1957083a9463401f7bd01287f50521ecb05a313f8",
+                "sha256:61b887f9ddba63ddf62fd02a3ba7add935d053b6dd7d58998c630e6dbade8527",
+                "sha256:6619654954dc4936fcff82db8eb6401d3159ec6be81e33c6000dfd76ae189947",
+                "sha256:674629ff60030d144b7bca2b8330225a9b11c482ed408813924619c6f302fdbb",
+                "sha256:6ec0d5af64f2e3d64a165f490d96368bb5dea8b8f9ad04487f9ab60dc4bb6003",
+                "sha256:6f4dba50cfa56f910241eb7f883c20f1e7b1d8f7d91c750cd0b318bad443f4d5",
+                "sha256:70fbbdacd1d271b77b7721fe3cdd2d537bbbd75d29e6300c672ec6bb38d9672f",
+                "sha256:72bacbaf24ac003fea9bff9837d1eedb6088758d41e100c1552930151f677739",
+                "sha256:7326a1787e3c7b0429659e0a944725e1b03eeaa10edd945a86dead1913383944",
+                "sha256:73853108f56df97baf2bb8b522f3578221e56f646ba345a372c78326710d3830",
+                "sha256:73e3a0200cdda995c7e43dd47436c1548f87a30bb27fb871f352a22ab8dcf45f",
+                "sha256:75acbbeb05b86bc53cbe7b7e6fe00fbcf82ad7c684b3ad82e3d711da9ba287d3",
+                "sha256:8069c5179902dcdce0be9bfc8235347fdbac249d23bd90514b7a47a72d9fecf4",
+                "sha256:846e193e103b41e984ac921b335df59195356ce3f71dcfd155aa79c603873b84",
+                "sha256:8594f42df584e5b4bb9281799698403f7af489fba84c34d53d1c4bfb71b7c4e7",
+                "sha256:86510e3f5eca0ab87429dd77fafc04693195eec7fd6a137c389c3eeb4cfb77c6",
+                "sha256:8853a3bf12afddfdf15f57c4b02d7ded92c7a75a5d7331d19f4f9572a89c17e6",
+                "sha256:88a58d8ac0cc0e7f3a014509f0455248a76629ca9b604eca7dc5927cc593c5e9",
+                "sha256:8ba470552b48e5835f1d23ecb936bb7f71d206f9dfeee64245f30c3270b994de",
+                "sha256:8c676b587da5673d3c75bd67dd2a8cdfeb282ca38a30f37950511766b26858c4",
+                "sha256:8ec4a89295cd6cd4d1058a5e6aec6bf51e0eaaf9714774e1bfac7cfc9051db47",
+                "sha256:94f3e1780abb45062287b4614a5bc0874519c86a777d4a7ad34978e86428b8dd",
+                "sha256:9a0f748eaa434a41fccf8e1ee7a3eed68af1b690e75328fd7a60af123c193b50",
+                "sha256:a5629742881bcbc1f42e840af185fd4d83a5edeb96475a575f4da50d6ede337c",
+                "sha256:a65149d8ada1055029fcb665452b2814fe7d7082fcb0c5bed6db851cb69b2086",
+                "sha256:b3c5ac4bed7519088103d9450a1107f76308ecf91d6dabc8a33a2fcfb18d0fba",
+                "sha256:b4fd7bd29610a83a8c9b564d457cf5bd92b4e11e79a4ee4716a63c959699b306",
+                "sha256:bcd1fb5bb7b07f64c15618c89efcc2cfa3e95f0e3bcdbaf4642509de1942a699",
+                "sha256:c12b5ae868897c7338519c03049a806af85b9b8c237b7d675b8c5e089e4a618e",
+                "sha256:c26845094b1af3c91852745ae78e3ea47abf3dbcd1cf962f16b9a5fbe3ee8488",
+                "sha256:c6a660307ca9d4867caa8d9ca2c2658ab685de83792d1876274991adec7b93fa",
+                "sha256:c809a70e43c7977c4a42aefd62f0131823ebf7dd73556fa5d5950f5b354087e2",
+                "sha256:c8b2351c85d855293a299038e1f89db92a2f35e8d2f783489c6f0b2b5f3fe8a3",
+                "sha256:cb929ca942d0ec4fac404cbf520ee6cac37bf35be479b970c4ffadf2b6a1cad9",
+                "sha256:d2c0a187a92a1cb5ef2c8ed5412dd8d4334272617f532d4ad4de31e0495bd923",
+                "sha256:d69bfd8ec3219ae71bcde1f942b728903cad25fafe3100ba2258b973bd2bc1b2",
+                "sha256:daffdf51ee5db69a82dd127eabecce20729e21f7a3680cf7cbb23f0829189790",
+                "sha256:e58876c91f97b0952eb766123bfef372792ab3f4e3e1f1a2267834c2ab131734",
+                "sha256:eda2616eb2313cbb3eebbe51f19362eb434b18e3bb599466a1ffa76a033fb916",
+                "sha256:ee217c198f2e41f184f3869f3e485557296d505b5195c513b2bfe0062dc537f1",
+                "sha256:f02541ef64077f22bf4924f225c0fd1248c168f86e4b7abdedd87d6ebaceab0f",
+                "sha256:f1b82c27e89fffc6da125d5eb0ca6e68017faf5efc078128cfaa42cf5cb38798",
+                "sha256:fba162b8872d30fea8c52b258a542c5dfd7b235fb5cb352240c8d63b414013eb",
+                "sha256:fbbcb7b57dc9c794843e3d1258c0fbf0f48656d46ffe9e09b63bbd6e8cd5d0a2",
+                "sha256:fcb4621042ac4b7865c179bb972ed0da0218a076dc1820ffc48b1d74c1e37fe9"
+            ],
+            "markers": "python_version >= '3.9'",
+            "version": "==11.0.0"
+        },
+        "pyinstaller": {
+            "hashes": [
+                "sha256:0d6475559c4939f0735122989611d7f739ed3bf02f666ce31022928f7a7e4fda",
+                "sha256:208c0ef6dab0837a0a273ea32d1a3619a208e3d1fe3fec3785eea71a77fd00ce",
+                "sha256:2e8365276c5131c9bef98e358fbc305e4022db8bedc9df479629d6414021956a",
+                "sha256:32c742a24fe65d0702958fadf4040f76de85859c26bec0008766e5dbabc5b68f",
+                "sha256:35e6b8077d240600bb309ed68bb0b1453fd2b7ab740b66d000db7abae6244423",
+                "sha256:44e36172de326af6d4e7663b12f71dbd34e2e3e02233e181e457394423daaf03",
+                "sha256:491dfb4d9d5d1d9650d9507daec1ff6829527a254d8e396badd60a0affcb72ef",
+                "sha256:6d12c45a29add78039066a53fb05967afaa09a672426072b13816fe7676abfc4",
+                "sha256:7ac83c0dc0e04357dab98c487e74ad2adb30e7eb186b58157a8faf46f1fa796f",
+                "sha256:ad84abf465bcda363c1d54eafa76745d77b6a8a713778348377dc98d12a452f7",
+                "sha256:ddc0fddd75f07f7e423da1f0822e389a42af011f9589e0269b87e0d89aa48c1f",
+                "sha256:e21c7806e34f40181e7606926a14579f848bfb1dc52cbca7eea66eccccbfe977"
+            ],
+            "index": "pypi",
+            "markers": "python_version < '3.14' and python_version >= '3.8'",
+            "version": "==6.11.1"
+        },
+        "pyinstaller-hooks-contrib": {
+            "hashes": [
+                "sha256:8a46655e5c5b0186b5e527399118a9b342f10513eb1425c483fa4f6d02e8800c",
+                "sha256:ad47db0e153683b4151e10d231cb91f2d93c85079e78d76d9e0f57ac6c8a5e10"
+            ],
+            "markers": "python_version >= '3.8'",
+            "version": "==2024.10"
+        },
+        "pyparsing": {
+            "hashes": [
+                "sha256:93d9577b88da0bbea8cc8334ee8b918ed014968fd2ec383e868fb8afb1ccef84",
+                "sha256:cbf74e27246d595d9a74b186b810f6fbb86726dbf3b9532efb343f6d7294fe9c"
+            ],
+            "markers": "python_version >= '3.9'",
+            "version": "==3.2.0"
+        },
+        "pyqt5": {
+            "hashes": [
+                "sha256:6cd75628f6e732b1ffcfe709ab833a0716c0445d7aec8046a48d5843352becb6",
+                "sha256:76be0322ceda5deecd1708a8d628e698089a1cea80d1a49d242a6d579a40babd",
+                "sha256:bdde598a3bb95022131a5c9ea62e0a96bd6fb28932cc1619fd7ba211531b7517",
+                "sha256:c8b03dd9380bb13c804f0bdb0f4956067f281785b5e12303d529f0462f9afdc2",
+                "sha256:cd672a6738d1ae33ef7d9efa8e6cb0a1525ecf53ec86da80a9e1b6ec38c8d0f1",
+                "sha256:fda45743ebb4a27b4b1a51c6d8ef455c4c1b5d610c90d2934c7802b5c1557c52"
+            ],
+            "index": "pypi",
+            "markers": "python_version >= '3.8'",
+            "version": "==5.15.11"
+        },
+        "pyqt5-qt5": {
+            "hashes": [
+                "sha256:1988f364ec8caf87a6ee5d5a3a5210d57539988bf8e84714c7d60972692e2f4a",
+                "sha256:750b78e4dba6bdf1607febedc08738e318ea09e9b10aea9ff0d73073f11f6962",
+                "sha256:76980cd3d7ae87e3c7a33bfebfaee84448fd650bad6840471d6cae199b56e154",
+                "sha256:9cc7a768b1921f4b982ebc00a318ccb38578e44e45316c7a4a850e953e1dd327"
+            ],
+            "version": "==5.15.2"
+        },
+        "pyqt5-sip": {
+            "hashes": [
+                "sha256:0b718a362f4392430903bbb2a4b9bbff9841a16a52f0cfdd5b5bbd9d11457980",
+                "sha256:0c1c727ede7fdc464a1fe2e46109ba836509b2d7187a46fdeae443148ce51d1c",
+                "sha256:0cd21c3215e3c47fdd5fa7a2dc3dd1e07a7230b0626e905a7217925068c788b9",
+                "sha256:13f0c6a78e781255863e3e160304648efaf62276b7102741af637b63a6e96930",
+                "sha256:24a1d4937332bf0a38dd95bb2ce4d89723df449f6e912b52ef0e107e11fefac1",
+                "sha256:2575f428de584a12009fd29d00c89df16ed101a3b38beba818dfdcbc4a10709c",
+                "sha256:749f7a3ffd6e3d2d5db65ed92c95cbd14490631595c61f0c0672c9238bfb17de",
+                "sha256:7f88c85702dce80ac2e1a162054f688ed394811d6dd03a5574b3fa8111b0a6db",
+                "sha256:83d247cdc43ef224410b14c97413067ea26356dfa39e9ed0fe702a31e25710b0",
+                "sha256:852b75cf208825602480e95ab63314108f872d0da251e9ad3deaaff5a183a6f5",
+                "sha256:855563d4d3b59ce7438bbf2dd32fed2707787defa40f3efe94f204a19ef92b25",
+                "sha256:91b9538458a3a23e033c213bc879ce64f3d0a33d5a49cbd03e1e584efe307a35",
+                "sha256:97f2d6e8d9b7b3d3e795d576d7f56e6257f524221f6383b33ded7287763e9f06",
+                "sha256:b4adc529fa4ec05728e14ea55194d907cc51f18d6f2ac5cc9f6eb52ac038aa0f",
+                "sha256:b58eeedc9b2a3037b136bf96915196c391a33be470ed1c0723d7163ef0b727a2",
+                "sha256:c0c543d604116af26694a8a5ba90f510551ff9124d503ae5ee14bb73a61363a3",
+                "sha256:c85be433fbafcb3d417581c0e1b67c8198d23858166e4f938e971c2262c13cdb",
+                "sha256:d23fdfcf363b5cedd9d39f8a9c5710e7d52804f5b08a58e91c638b36eafcb702",
+                "sha256:dd241de9c569c07bbba62bff1049996e5b52478164f61f430073a87bf6d26d33",
+                "sha256:ed5221c6241981bd98d39504823efb9cbe36841bf8917288f8fe8fc1d5569a41",
+                "sha256:f600ae6f03e4bff91153c0dc7ebe52f90bd2b6afda58fd580e6990b3b951adc0"
+            ],
+            "markers": "python_version >= '3.8'",
+            "version": "==12.15.0"
+        },
+        "python-dateutil": {
+            "hashes": [
+                "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3",
+                "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"
+            ],
+            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'",
+            "version": "==2.9.0.post0"
+        },
+        "pytz": {
+            "hashes": [
+                "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a",
+                "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725"
+            ],
+            "version": "==2024.2"
+        },
+        "pywin32-ctypes": {
+            "hashes": [
+                "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8",
+                "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755"
+            ],
+            "markers": "sys_platform == 'win32'",
+            "version": "==0.2.3"
+        },
+        "scipy": {
+            "hashes": [
+                "sha256:0c2f95de3b04e26f5f3ad5bb05e74ba7f68b837133a4492414b3afd79dfe540e",
+                "sha256:1729560c906963fc8389f6aac023739ff3983e727b1a4d87696b7bf108316a79",
+                "sha256:278266012eb69f4a720827bdd2dc54b2271c97d84255b2faaa8f161a158c3b37",
+                "sha256:2843f2d527d9eebec9a43e6b406fb7266f3af25a751aa91d62ff416f54170bc5",
+                "sha256:2da0469a4ef0ecd3693761acbdc20f2fdeafb69e6819cc081308cc978153c675",
+                "sha256:2ff0a7e01e422c15739ecd64432743cf7aae2b03f3084288f399affcefe5222d",
+                "sha256:2ff38e22128e6c03ff73b6bb0f85f897d2362f8c052e3b8ad00532198fbdae3f",
+                "sha256:30ac8812c1d2aab7131a79ba62933a2a76f582d5dbbc695192453dae67ad6310",
+                "sha256:3a1b111fac6baec1c1d92f27e76511c9e7218f1695d61b59e05e0fe04dc59617",
+                "sha256:4079b90df244709e675cdc8b93bfd8a395d59af40b72e339c2287c91860deb8e",
+                "sha256:5149e3fd2d686e42144a093b206aef01932a0059c2a33ddfa67f5f035bdfe13e",
+                "sha256:5a275584e726026a5699459aa72f828a610821006228e841b94275c4a7c08417",
+                "sha256:631f07b3734d34aced009aaf6fedfd0eb3498a97e581c3b1e5f14a04164a456d",
+                "sha256:716e389b694c4bb564b4fc0c51bc84d381735e0d39d3f26ec1af2556ec6aad94",
+                "sha256:8426251ad1e4ad903a4514712d2fa8fdd5382c978010d1c6f5f37ef286a713ad",
+                "sha256:8475230e55549ab3f207bff11ebfc91c805dc3463ef62eda3ccf593254524ce8",
+                "sha256:8bddf15838ba768bb5f5083c1ea012d64c9a444e16192762bd858f1e126196d0",
+                "sha256:8e32dced201274bf96899e6491d9ba3e9a5f6b336708656466ad0522d8528f69",
+                "sha256:8f9ea80f2e65bdaa0b7627fb00cbeb2daf163caa015e59b7516395fe3bd1e066",
+                "sha256:97c5dddd5932bd2a1a31c927ba5e1463a53b87ca96b5c9bdf5dfd6096e27efc3",
+                "sha256:a49f6ed96f83966f576b33a44257d869756df6cf1ef4934f59dd58b25e0327e5",
+                "sha256:af29a935803cc707ab2ed7791c44288a682f9c8107bc00f0eccc4f92c08d6e07",
+                "sha256:b05d43735bb2f07d689f56f7b474788a13ed8adc484a85aa65c0fd931cf9ccd2",
+                "sha256:b28d2ca4add7ac16ae8bb6632a3c86e4b9e4d52d3e34267f6e1b0c1f8d87e389",
+                "sha256:b99722ea48b7ea25e8e015e8341ae74624f72e5f21fc2abd45f3a93266de4c5d",
+                "sha256:baff393942b550823bfce952bb62270ee17504d02a1801d7fd0719534dfb9c84",
+                "sha256:c0ee987efa6737242745f347835da2cc5bb9f1b42996a4d97d5c7ff7928cb6f2",
+                "sha256:d0d2821003174de06b69e58cef2316a6622b60ee613121199cb2852a873f8cf3",
+                "sha256:e0cf28db0f24a38b2a0ca33a85a54852586e43cf6fd876365c86e0657cfe7d73",
+                "sha256:e4f5a7c49323533f9103d4dacf4e4f07078f360743dec7f7596949149efeec06",
+                "sha256:eb58ca0abd96911932f688528977858681a59d61a7ce908ffd355957f7025cfc",
+                "sha256:edaf02b82cd7639db00dbff629995ef185c8df4c3ffa71a5562a595765a06ce1",
+                "sha256:fef8c87f8abfb884dac04e97824b61299880c43f4ce675dd2cbeadd3c9b466d2"
+            ],
+            "markers": "python_version >= '3.10'",
+            "version": "==1.14.1"
+        },
+        "setuptools": {
+            "hashes": [
+                "sha256:5c4ccb41111392671f02bb5f8436dfc5a9a7185e80500531b133f5775c4163ef",
+                "sha256:87cb777c3b96d638ca02031192d40390e0ad97737e27b6b4fa831bea86f2f829"
+            ],
+            "markers": "python_version >= '3.9'",
+            "version": "==75.5.0"
+        },
+        "six": {
+            "hashes": [
+                "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+                "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+            ],
+            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'",
+            "version": "==1.16.0"
+        },
+        "soupsieve": {
+            "hashes": [
+                "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb",
+                "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9"
+            ],
+            "markers": "python_version >= '3.8'",
+            "version": "==2.6"
+        },
+        "termcolor": {
+            "hashes": [
+                "sha256:37b17b5fc1e604945c2642c872a3764b5d547a48009871aea3edd3afa180afb8",
+                "sha256:998d8d27da6d48442e8e1f016119076b690d962507531df4890fcd2db2ef8a6f"
+            ],
+            "index": "pypi",
+            "markers": "python_version >= '3.9'",
+            "version": "==2.5.0"
+        },
+        "tzdata": {
+            "hashes": [
+                "sha256:7d85cc416e9382e69095b7bdf4afd9e3880418a2413feec7069d533d6b4e31cc",
+                "sha256:a48093786cdcde33cad18c2555e8532f34422074448fbc874186f0abd79565cd"
+            ],
+            "markers": "python_version >= '2'",
+            "version": "==2024.2"
+        },
+        "yattag": {
+            "hashes": [
+                "sha256:baa8f254e7ea5d3e0618281ad2ff5610e0e5360b3608e695c29bfb3b29d051f4"
+            ],
+            "index": "pypi",
+            "version": "==1.16.1"
+        }
+    },
+    "develop": {}
+}
diff --git a/README.md b/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..505df0f645bc7f5b54bfc4680c5db9479706f5fe
--- /dev/null
+++ b/README.md
@@ -0,0 +1,37 @@
+# Welcome to the UNICADO package :airplane:
+This repository is a container which collects all UNICADO repositories as submodules. It the best starting point for a newbie to get to know the overall tool chain. The repository is also used to create the standalone UNICADO installer to run the designs in RCE.
+
+> &rarr; Checkout your [UNICADO website](https://unicado.io/) for more information! 
+
+## Installation
+
+### For User
+You want to use UNICADO to get familiar with the workflow and see first results? Great :fire: Then check out the [Installation Guide](https://unicado.pages.rwth-aachen.de/unicado.gitlab.io/download/installation/) and the [Cleared for Take-Off](https://unicado.pages.rwth-aachen.de/unicado.gitlab.io/download/takeoff/). It includes the prerequisites, troubleshooting hints and a standalone installer.
+
+### For Developer
+We welcome contributions! :sparkles: Please read our [developer guide](https://unicado.pages.rwth-aachen.de/unicado.gitlab.io/developer/developer-installation/). It explains step-by-step what you need to install, how to get the source code, how to build it, how to contribute and how to create the installer.
+
+## License
+This project is licensed under the GNU General Public License, Version 3 License - see the [LICENSE](LICENSE) file for details.
+
+## Acknowledgments and Funding
+This project is a collaborative effort by 
+- RWTH Aachen, Chair and Institute of Aerospace Systems
+- TU Berlin
+    - Aircraft Design and Aerostructures
+    - Flight Mechanics, Flight Control and Aeroelasticity
+- TU Braunschweig, Chair of Overall Aircraft Design
+- TU Hamburg, Institute of Air Transportation Systems
+- TU Munich, Chair of Aircraft Design
+- University of Stuttgart, Institute of Aircraft Design
+
+including its associated partner
+- Airbus SE
+- Collins Aerospace 
+- TGM Lightweight Solutions GmbH
+
+and is funded by the Federal Ministry of Economic Affairs and Climate Action on the basis of a decision by the German Bundestag.
+
+## Contact
+For questions or support, feel free to contact us :email: **E-Mail:** [contacts@unicado.io](mailto:contacts@unicado.io).
+
diff --git a/aircraft_design b/aircraft_design
new file mode 160000
index 0000000000000000000000000000000000000000..f1c70dad7cffec6776c26d4521c328f824f6fe21
--- /dev/null
+++ b/aircraft_design
@@ -0,0 +1 @@
+Subproject commit f1c70dad7cffec6776c26d4521c328f824f6fe21
diff --git a/aircraft_references b/aircraft_references
new file mode 160000
index 0000000000000000000000000000000000000000..23227daf5f425cc2536df5b75f7faba2774a7813
--- /dev/null
+++ b/aircraft_references
@@ -0,0 +1 @@
+Subproject commit 23227daf5f425cc2536df5b75f7faba2774a7813
diff --git a/cmake/PackageUnicado.cmake b/cmake/PackageUnicado.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..d0a72019adda7e84e907e28d60faf0e27f411ebc
--- /dev/null
+++ b/cmake/PackageUnicado.cmake
@@ -0,0 +1,81 @@
+# Find and include all system runtime libraries if enabled
+if(PACKAGE_SYSTEM_LIBRARIES)
+    # Get the path to the c/c++ runtime libraries to include in the package
+    get_filename_component( SYSTEM_LIBS_PATH ${CMAKE_CXX_COMPILER} PATH )
+    message(STATUS "-> Packaging System Libraries from: ${SYSTEM_LIBS_PATH}")
+    message(DEPRECATION "Packaging system libraries is deprecated and will be removed in the future. Please use the native compiler for your OS where packaging the libraries should no longer be needed.")
+
+    # Install the runtime dependencies
+    install( RUNTIME_DEPENDENCY_SET unicado_runtime_deps
+        PRE_INCLUDE_REGEXES "libgcc.*" "libstdc.*" "libwinpthread.*"
+        PRE_EXCLUDE_REGEXES ".*\.dll" ".*\.so" # Skip all other system libs for now
+        DIRECTORIES
+            ${SYSTEM_LIBS_PATH}
+            ${CMAKE_CURRENT_SOURCE_DIR}/libraries/unicadoRuntimeLibs
+        DESTINATION unicadoRuntimeLibs
+    )
+endif()
+
+# Include information about the project
+install(
+    FILES
+        ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE
+    DESTINATION .
+)
+
+# Install the include directory for report generation
+install(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/utilities/report_generator/inc
+    DESTINATION report_generator/
+)
+
+install(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/aircraft_references/UNICADO-SMR
+    DESTINATION projects/
+)
+
+# Install airfoil data
+install(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/libraries/airfoils/F15
+    DESTINATION databases/airfoils/
+)
+install(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/libraries/airfoils/NACA
+    DESTINATION databases/airfoils/
+)
+
+install(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/engines/PW1127G-JM
+    DESTINATION databases/engines/
+)
+install(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/engines/V2527-A5
+    DESTINATION databases/engines/
+)
+
+# Define the install rules for the worflow files
+install(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/rce_workflow/jsonFiles
+    DESTINATION workflowComponent
+)
+install(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/rce_workflow/UNICADOworkflow
+    DESTINATION workflowComponent
+)
+
+# Set the package information
+set(CPACK_PACKAGE_NAME "UNICADO")
+
+# Use maximum available threads for packaging
+set(CPACK_THREADS 0)
+
+# Set packaging options
+set(CPACK_PACKAGE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/installer)
+if( WIN32 )
+    set(CPACK_GENERATOR "ZIP")
+elseif( UNIX )
+    set(CPACK_GENERATOR "ZIP")
+endif()
+# set(CPACK_PACKAGE_CHECKSUM "SHA256")
+# set(CPACK_PACKAGE_CHECKSUM_TYPE "SHA256")
+include(CPack)
diff --git a/engines b/engines
new file mode 160000
index 0000000000000000000000000000000000000000..922a8f10da97099c74441349fbdaa0d210d9b262
--- /dev/null
+++ b/engines
@@ -0,0 +1 @@
+Subproject commit 922a8f10da97099c74441349fbdaa0d210d9b262
diff --git a/installer/CMakeLists.txt b/installer/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..72a46a62dd103981b7f77e39e962228af3e9e255
--- /dev/null
+++ b/installer/CMakeLists.txt
@@ -0,0 +1,49 @@
+# Set the target separators according to the OS
+if(WIN32)
+    set(TARGET_SEPARATOR "\;")
+    set(TARGET_ID "win64")
+    set(TARGET_EXT "zip")
+    set(INSTALLER_EXECUTABLE "UNICADOinstaller.exe")
+else()
+    set(TARGET_SEPARATOR ":")
+    set(TARGET_ID "Linux")
+    set(TARGET_EXT "zip")
+    set(INSTALLER_EXECUTABLE "UNICADOinstaller")
+endif()
+
+add_custom_target(debug-info
+    COMMAND echo "${PROJECT_NAME}-${PROJECT_VERSION}-${TARGET_ID}.${TARGET_EXT}"
+)
+
+# Set the installer commands
+set(PYINSTALLER_OPTIONS
+    --noconfirm
+    --onefile
+    --windowed
+    --icon "${CMAKE_CURRENT_LIST_DIR}/iconUNICADO.ico"
+    --add-data "${CMAKE_CURRENT_LIST_DIR}/${PROJECT_NAME}-${PROJECT_VERSION}-${TARGET_ID}.${TARGET_EXT}${TARGET_SEPARATOR}."
+    --add-data "${CMAKE_CURRENT_LIST_DIR}/sub_functions${TARGET_SEPARATOR}sub_functions/"
+    --add-data "${CMAKE_CURRENT_LIST_DIR}/image_rc.py${TARGET_SEPARATOR}."
+    --add-data "${CMAKE_CURRENT_LIST_DIR}/unicadoICON.svg${TARGET_SEPARATOR}."
+    --add-data "${CMAKE_CURRENT_LIST_DIR}/UNICADOLogo90.svg${TARGET_SEPARATOR}."
+    --add-data "${CMAKE_CURRENT_LIST_DIR}/own_python_packages.txt${TARGET_SEPARATOR}."
+    --add-data "${CMAKE_CURRENT_LIST_DIR}/python_module_list.txt${TARGET_SEPARATOR}."
+    --add-data "${CMAKE_CURRENT_LIST_DIR}/standard_python_packages.txt${TARGET_SEPARATOR}."
+    --add-data "${CMAKE_CURRENT_LIST_DIR}/version.txt${TARGET_SEPARATOR}."
+)
+set(PYINSTALLER_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/UNICADOinstaller.py")
+
+# Add the pyinstaller target if pipenv is found
+if(PIPENV)
+    add_custom_target(installer
+        COMMAND ${PIPENV} run pyinstaller ${PYINSTALLER_OPTIONS} ${PYINSTALLER_SCRIPT}
+        COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_LIST_DIR}/dist/${INSTALLER_EXECUTABLE} ${CMAKE_SOURCE_DIR}
+        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+        COMMENT "Building workflow installer for ${PROJECT_NAME} with pyinstaller"
+        BYPRODUCTS 
+            ${CMAKE_CURRENT_LIST_DIR}/dist
+            ${CMAKE_SOURCE_DIR}/${INSTALLER_EXECUTABLE}
+    )
+else()
+    message(WARNING "-> pipenv not found, installer target will not be available")
+endif()
diff --git a/installer/UNICADOLogo90.svg b/installer/UNICADOLogo90.svg
new file mode 100644
index 0000000000000000000000000000000000000000..90767cb3448143cb678802aafd55dc021b5846d6
--- /dev/null
+++ b/installer/UNICADOLogo90.svg
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="45mm" height="182mm" version="1.1" viewBox="0 0 45 182" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+  <clipPath id="clip0-82">
+   <rect x="-176" y="-103" width="1625" height="837"/>
+  </clipPath>
+  <clipPath id="clip1-87">
+   <rect x="726" y="168" width="241" height="235"/>
+  </clipPath>
+  <clipPath id="clip2-48">
+   <rect x="726" y="168" width="241" height="235"/>
+  </clipPath>
+  <clipPath id="clip3-49">
+   <rect x="726" y="168" width="241" height="235"/>
+  </clipPath>
+  <linearGradient id="fill4-5" x1="802.87" x2="700.23" y1="961.54" y2="1064.2" gradientUnits="userSpaceOnUse">
+   <stop stop-color="#6C6C6C" offset="0"/>
+   <stop offset="1"/>
+  </linearGradient>
+  <linearGradient id="fill5" x1="759.5" x2="623.11" y1="1024.8" y2="1053" gradientUnits="userSpaceOnUse">
+   <stop stop-color="#00427D" offset="0"/>
+   <stop stop-color="#007DEC" offset="1"/>
+  </linearGradient>
+  <linearGradient id="fill6" x1="655.12" x2="723.78" y1="927.65" y2="1019.8" gradientUnits="userSpaceOnUse">
+   <stop stop-color="#E20E1F" offset="0"/>
+   <stop stop-color="#F24657" offset="1"/>
+  </linearGradient>
+  <linearGradient id="fill7-95" x1="851.63" x2="712.36" y1="960.46" y2="924.63" gradientUnits="userSpaceOnUse">
+   <stop stop-color="#EA7D92" offset="0"/>
+   <stop stop-color="#A91B36" stop-opacity=".8902" offset="1"/>
+  </linearGradient>
+  <clipPath id="clip8-5">
+   <rect x="789" y="168" width="106" height="115"/>
+  </clipPath>
+  <clipPath id="clip10-3">
+   <rect x="788" y="167" width="107" height="117"/>
+  </clipPath>
+  <linearGradient id="fill11-7" x1="867.34" x2="787.59" y1="1016.6" y2="929.84" gradientUnits="userSpaceOnUse">
+   <stop stop-color="#204B78" offset="0"/>
+   <stop stop-color="#6199D4" offset="1"/>
+  </linearGradient>
+  <clipPath id="clip12-3">
+   <rect width="900647" height="903600"/>
+  </clipPath>
+  <clipPath id="clip14-7">
+   <rect width="900647" height="900647"/>
+  </clipPath>
+  <clipPath id="clip15-61">
+   <rect x="1216" y="205" width="197" height="198"/>
+  </clipPath>
+  <clipPath id="clip16-42">
+   <rect x="1216" y="205" width="197" height="198"/>
+  </clipPath>
+  <clipPath id="clip17-4">
+   <rect x="1216" y="205" width="197" height="198"/>
+  </clipPath>
+ </defs>
+ <metadata>
+  <rdf:RDF>
+   <cc:Work rdf:about="">
+    <dc:format>image/svg+xml</dc:format>
+    <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+    <dc:title/>
+   </cc:Work>
+  </rdf:RDF>
+ </metadata>
+ <g transform="matrix(-.0042763 -.49238 .49238 -.0042763 2.5055 182.11)">
+  <g transform="matrix(.26458 0 0 .26458 -11.633 -26.742)" clip-path="url(#clip0-82)">
+   <g clip-path="url(#clip1-87)">
+    <g clip-path="url(#clip2-48)">
+     <g clip-path="url(#clip3-49)">
+      <g stroke-width=".37715">
+       <path transform="matrix(1 0 0 1.0002 99.788 -668.56)" d="m802.87 961.54s23.324 44.524-8.89 81.894c-40.158 46.59-93.749 20.74-93.749 20.74s43.37-9.91 71.659-40.67c20.654-22.46 30.98-61.964 30.98-61.964z" fill="url(#fill4-5)" stroke="#161616"/>
+       <path transform="matrix(1 0 0 1.0002 99.788 -668.56)" d="m759.5 1024.8s-67.962 59.57-122.57 18.05c-29.925-22.75 13.47-72.734 13.47-72.734s-22.776 34.064 15.086 53.614c27.449 14.17 94.018 1.07 94.018 1.07z" fill="url(#fill5)" stroke="#444"/>
+       <path transform="matrix(1 0 0 1.0002 99.788 -668.56)" d="m686.82 882.21s-11.775 28.955-1.905 74.673c7.495 34.712 38.86 62.864 38.86 62.864s-56.332-1.17-68.957-59.436c-10.515-48.527 32.002-78.101 32.002-78.101z" fill="url(#fill6)" stroke="#e30e1f" stroke-opacity=".98431"/>
+       <path transform="matrix(1 0 0 1.0002 99.788 -668.56)" d="m712.36 924.63s29.45-44.075 81.627-32.058c56.571 13.028 57.65 67.887 57.65 67.887s-42.896-35.083-68.965-41.217c-22.881-5.385-70.312 5.388-70.312 5.388z" fill="url(#fill7-95)" stroke="#c7314f" stroke-opacity=".95294"/>
+      </g>
+      <g clip-path="url(#clip8-5)">
+       <g clip-path="url(#clip10-3)">
+        <image x="788" y="167" width="107" height="117" preserveAspectRatio="none" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGsAAAB1CAYAAABJYx/nAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAAxBSURBVHhe7Z1ZcxNXFsfzEeYbZCYLmUwSs3gBjDdsvAAGAgQDYQlJIDNJJsnAZOaJ8itU5c3FI1SqJsTj4EW2ZFmSpdZurZZtZIzsKDGjDBmXixcs5/3OOfJtaDct6UpuSS37/qtOaWv1cn86939u9237pa2kRp3jdxi7dY7fY9C3uUopBFKtc1yuGbL31AwJ5qpBwbNr0JbYOWBdxtjeP76ainup15GdAzbPjv7xvqohW0/1kKOTroarUNo74uis1Am3qoftnsohIQ6NTwAIqbi3Fu/cs6Ti7R/M5C2MPjP5U5+JvPlvjDHyx94x8kavEWIMl1neMWC1VA3Zu+nquTaqGp2zfo/ecROyKFA1JCQhe8hOjAErgcZOwRKBibDe+SE7sG3fr8Xrd0dJxQ+WBKxbx7vNPIVZtEfv9Nfo7MkqnUAgk1KBsFiASWGxAHsNAiAnYN29dBe4sgkzqVbvmqoZcSRrhh2kZthOqnV2IgcmwmIFJoWVCdhrdw2kot/yuHrY9g3dJS656iCTENKeEWcSguxOgRIjMzApLFZgclhyYK9+Z8DvClU6+yd0F7mwqturd/UAqCUIslfvJAhrPbA1WNUAiwXYOv/KAdhzWM+Bbes1JmFbt+jubl3t07uu1xlciX0GN6k1uNYiCzApLFZg+fiXCOuV7/Sp5/BDcdLd3lraOyC8vG/U46wbda9AEIxnwGSwsgErtH+JwF75lx7XZ9lSFWO93nW6btQTazB6SYPRQ+ohsgFDWKzACuVfIjBYR2LTD6rRm+oM7tuNxolk4xiCehFWNmDr/YsNmJr+JQJ7o9e0tGmB1UI5DnCC+00TpAljbIKkA4aw9mnYv0Rg274fna8ddeygh7g5VGtw1jcavZFms488g8UATAqLFVgx/esPEPD9xKYBVm90XQZASy0WP0FY64BRWACSCZgUllb8C4Ht6B9/VPZFBzR4d7PJt9o6HiAHAFYmYFJYrMC04l8iMPRkeujlpQaDpwcArSAoJVjZgElhsQIrpX+lgN2zmOnhl4fw19Uw6tG1WfxP261B0mZdg5Uuu1iBlYN/4ePOe9brtCm0LQQFje9st4YIghIjG7B1/sUITApLS/4Fn69qvqRHUC1mv77DFiIHIfBRCRYLMO5fBVbTmFd3SAiRQ0KYHITHTMBEWKzApLDKxb92DdhMtGm0pWaTvwcAPT1sDz+HxQhMCosVWLn4V+Wg9SptIm2oYczdDVCSnY5JctiOIQEmg8UCbDP5F3xnWTPjr/1j3kMAY+mII0IwWIBtNf/aNSToaHOVTg0Gb32rNRA76gRQGOtgsQPb7P716l3DStWg7QxttuJr/+jEy62WQPSYa4pgKAPj/iVm1/Z+a4w2XfHVbg3o33VNp0AxA5PBYgG2WfwLn5dksLzf5L35LsA57p4mUmDPYOUAbCv515t9puIWG81j/oqDQnjxhGcmBSstMO5fz2BJgRW12Ggx+8wnAZQUFhsw7fpX5aCQhPcSEJFUDNstu6FRq3W23spB250qOoc+FUPCI/CfvP0Llv2tKNmF3R9Aevqe9z6RAysr/xqxJ3cP22PwvgPiG5xQmsupIWxsgHoHMrIXIv4WgMvFv/B7dFWF0Vr3F4qdmogShJUNmAb9a3XviEufD5xs2mdwNCEA6DqfyLNLCVjBs6tt3D/cBaCksJiBldK/Rlyx2hGnDgHRQymoMOPA+x6nyy4RWMGyq2nM1w0gkl2+KJED06J/AajVfQZnX63e2V2qM9+7Bq06KEp+S9cdQre5qnp24cFCY8bP+GfJad8sYQFWKv+qN7qTKUhFyqJswkk0kEHOdMDw9iK6qDpqtfh7ugCSHFYuwIrhXzhhtG7UqcmbB/AuS6wc5cCgolxWLfNTWSWE42f9DwAWRvrsYgamsn/Vj3ridXp3ybo7VuGdlW/3mRelsPA5+Js6ZzVaLYEehPR+YI6wACumfzUZvfE6g/uG1iFJVaOz1cuBQQUZpR/nL2wEaMQ4gpLDKqV/IaxG44QFJ43SXS0rIbDt98ZjIjB8rNEJX9OP8xNmFUI6F1yDlSm7iuVfLWZfEiq+3nLKJiVh4QGV4qwIbMeA1UI/yl3YGIchq84HHxIMFmCF9q/9Jm8Mur3SXRNSWZhhb6W6RAOU8abVvMt4zKpzCCr0IixWYGr5F05pazR6nXVj/gq6e5tGeEESqsQkAtvZb71N32ZXKqvs4fjFcIxcCMUUgRXLvzoAFFR8znLv9jKpZtj+baoqHMzj4mSrxXcV4SAsVmCF8C/Mqv1Gr3kzgxJVOWDzvw4D55xvModGMn8wOa8IixXYRv0LM6vF5Lu5FUCh8DixpK/UCezzDJtNgXpo7KVLACsdsEL71yF76Clk1O2tAkrUbsiq7f3WOH2ZXZBVNz6MLBCExQpMTf/CzDpg8d2hu7PlVDkozDGPuY45pyIISwQmhcUKLF//OgKgmk0T/q2WUVJhOV8z7AjSl+nVNOY9dzH0cOWjyI8pWErACulfLRb/pq76WLVnxDVCn6ZXpzA5/PHUjwRhsQJTy786bMFZvBJNd2VLa2e/rSLjABl/0e95o4sISwQmhVVI/2q3BRN1Rjf/I42sarUGrn4EYC5Px1OwlIAVwr+g+ks2m3yX6W5wsajTPtl7BUAhLFZgG/UvzCwoKHroLnCx6oR7OnJl5iciApPCKpR/tVoCvKDIVTgQvhCeT36CsNIAk8JSw78OCqEY3thAd4GLVTAQ7vnz/Z8JwmIFthH/Ou6aSvKCIk8dd0/1ISwRmBSW2v6FXeABi5/7VD5Cz4BGXvpLdA2WEjAprI36V5s1yH0qX3VAyf7xVJwgLFZgUli5+NdheziBd0rSTXPlqsNCWPdpdJFgyGGp6V+nvNEVvORBN8uVj465p4KfzT5KwVICppZ/ddiCw3STXPkIvQMqtCcIixWYFBYrsCOOSKLZxLu/DakdxldXZuLkcwVYavkX/Bh496eG2sYD3X998B/y+YNHisCksPL1LxjD8e5PDR2xh3UIixVYrv510nt/iXd/Kum0b074Yu5FWGr4F3aB7eOhG3RTXBvVudDc4hdzCaIETAorH/866oxE+OBXJeFca2jw5JcPEVZ2YFJY2YCdDcwm28eD/BqVWhKLCzksVmCZ/AvnHdLNcKmhY87Ijb/FfiFfPfzlBWAb8a8TnpkneMmFboZLDR13TfciLBZgUliZgF2aXCDtFj6mUl3vB+cEOayN+tdRRyTKi4oC6D1vNHp1/r8pWOmyKxf/wsk27dYAz6pC6Hxg7sk1gJUNGKt/4RwOnlUFEE4g/CAcW5bDYgEmwvpU4l+XIvMrOJWNrp5LTXXYQmcQwrX5xxDK2ZWLfx1zT+V/PyxXZgGs7q8XfiV/X0BY6YGx+Nf50MPVRuMEn/xSKEHVdn09LDZgIiwpsE4hzAfAhdQpz/2er3/8lWTKrmzAENZZ/9xyC8+qwuqoM6L7B8LKAgxhfZXBv2A9/N+ZF1rvOqeew2IAJoUlArsQii112PgtOgXXWd+Dvn/G/0fk2cUKDL0KgPOJmsXQmcCcB2EpAZPCSgesyzcb4wPgIqlrYjYqwsoGTAoLA/3qoDXETysVSxfDsYAcFiuwk577cZ5VRdS54FxMCksEls2/0K867ZPcq4opJVhKwOT+dcbPvaroOh+MJZRgYaQDhsUFz6oSKBssJWAXQw8XeVaVQJlgYSj510nPNM+qUigbLAwpsMtT8aWC/isGLmVhV/ZhZGFZCZA8RGAnXNP8HGAphLAuTS4sKsGRB8L6cHLht3Ybn1pWMrF0g2Icd0/z61WlFCusz6KPki1mfr2qpEo3KJbHKU+U31tVarHAwvOAh22hTfM31MtWp/2zcSVA0ng/8CBCF+cqpRCEEiAxrsEguMMavEUX5yqlpBcfleKDyflZfmpJI+ryRS1KkMTA2U90Ua5SC6s8JUgYeHajw80nwmhGp32zd5RAYfByXWM66pzqUQL15VxipcMS0uT/TNyy6rSHFTML52bQRbi0IrwxQQ6Kl+saVZPZew7hSGHhmXhermtQeCER56pLYfGz6xoVZtAnMz+viqD42XWNS3qZ5EIoJtC3ubQoBISgeGFRBjrpmXEirCvTP/Hp0FrXcWfkNsLihUUZCAfGWFjwMxZlIBxr4a0/9CWXloU+1WYNfUtfcmldvLDQsl566f8TI2xy81b3IQAAAABJRU5ErkJggg=="/>
+       </g>
+      </g>
+      <path transform="matrix(1 0 0 1.0002 99.788 -668.56)" d="m787.6 929.84s80.712 25.689 79.434 85.154c-1.239 57.65-72.386 37.14-72.386 37.14s38.892 2.48 40.161-36.35c1.184-36.238-47.209-85.944-47.209-85.944z" fill="url(#fill11-7)" stroke="#3d6ea2" stroke-opacity=".98039" stroke-width=".37715"/>
+     </g>
+    </g>
+   </g>
+   <g transform="translate(63.407 399)" fill="#bfbfbf" font-family="Quantify, Quantify_MSFontService, Arial" font-size="398px" font-weight="400">
+    <path d="m213.33-199v200.19h-54.526v-200.19zm-83.58 148.85 19.104 34.626v0.398c-13.797 12.205-30.911 18.308-51.342 18.308-32.371 0-55.322-8.756-68.854-26.268-12.471-15.655-18.706-40.596-18.706-74.824v-101.09h54.526v101.09c0 7.164 0.1327 14.063 0.398 20.696 0.5307 6.6333 1.99 12.471 4.378 17.512 2.6533 5.0413 6.6333 9.154 11.94 12.338 5.3067 2.9187 12.869 4.378 22.686 4.378 4.511 0 8.889-0.6633 13.134-1.99s8.225-3.0513 11.94-5.174z"/>
+    <path d="m159.18-199h54.128v199h-54.128zm183.88 23.084c6.633 8.225 11.409 18.573 14.328 31.044s4.378 27.86 4.378 46.168v98.704h-54.128v-98.704c0-7.429-0.265-14.461-0.796-21.094-0.265-6.899-1.592-12.869-3.98-17.91-2.388-5.307-6.235-9.419-11.542-12.338s-12.869-4.378-22.686-4.378c-9.287 0-17.91 1.99-25.87 5.97v0.398l-0.398-0.398-19.502-34.626 0.398-0.398c13.797-12.471 31.044-18.706 51.74-18.706 31.84 0 54.526 8.756 68.058 26.268z"/>
+    <path d="m383.66 0v-199h52.934v199zm0-278.6h52.934v46.566h-52.934z"/>
+    <path d="m605.74-76.018 42.984 28.258-0.398 0.398c-9.286 15.92-21.89 28.391-37.81 37.412-15.654 9.0213-32.636 13.532-50.944 13.532-14.328 0-27.727-2.6533-40.198-7.96-12.47-5.572-23.349-13.001-32.636-22.288-9.286-9.2867-16.716-20.165-22.288-32.636-5.306-12.471-7.96-25.737-7.96-39.8 0-14.063 2.654-27.329 7.96-39.8 5.572-12.471 13.002-23.349 22.288-32.636 9.287-9.287 20.166-16.583 32.636-21.89 12.471-5.572 25.87-8.358 40.198-8.358 18.308 0 35.29 4.511 50.944 13.532 15.92 9.021 28.524 21.492 37.81 37.412l0.398 0.398-43.382 28.258-0.398-0.398c-4.245-9.817-10.48-17.777-18.706-23.88-7.96-6.103-16.848-9.154-26.666-9.154-7.164 0-13.93 1.592-20.298 4.776-6.102 2.919-11.409 7.031-15.92 12.338-4.51 5.041-8.092 11.011-10.746 17.91-2.653 6.633-3.98 13.797-3.98 21.492 0 7.6947 1.327 14.859 3.98 21.492 2.654 6.6333 6.236 12.471 10.746 17.512 4.511 4.776 9.818 8.6233 15.92 11.542 6.368 2.6533 13.134 3.98 20.298 3.98 9.818 0 18.706-2.6533 26.666-7.96 8.226-5.572 14.461-13.267 18.706-23.084l0.398-0.796z"/>
+    <path d="m1134.2-278.6v278.6h-52.93l0.4-99.898c0-7.429-1.6-14.461-4.78-21.094-2.92-6.633-6.9-12.338-11.94-17.114-4.78-5.041-10.61-8.889-17.51-11.542-6.64-2.919-13.8-4.378-21.5-4.378-7.69 0-14.85 1.459-21.49 4.378-6.63 2.653-12.468 6.501-17.509 11.542-4.776 5.041-8.623 10.879-11.542 17.512s-4.378 13.797-4.378 21.492c0 7.6947 1.459 14.859 4.378 21.492s6.766 12.471 11.542 17.512c5.041 4.776 10.879 8.6233 17.509 11.542 6.64 2.9187 13.8 4.378 21.49 4.378 3.72 0 7.43-0.2653 11.15-0.796 3.71-0.5307 7.16-1.592 10.35-3.184h0.79l19.5 35.82-0.39 0.398c-13 10.083-28.92 15.124-47.76 15.124-14.33 0-27.73-2.6533-40.201-7.96-12.471-5.3067-23.349-12.603-32.636-21.89s-16.716-20.165-22.288-32.636c-5.307-12.471-7.96-25.737-7.96-39.8 0-14.063 2.653-27.329 7.96-39.8 5.572-12.471 13.001-23.349 22.288-32.636s20.165-16.583 32.636-21.89 25.871-7.96 40.201-7.96c27.06 0 47.76 10.083 62.09 30.248v-107.46z"/>
+   </g>
+   <g transform="matrix(.00013052 1.3718e-5 -1.3718e-5 .00013052 1234.4 133.92)" clip-path="url(#clip12-3)">
+    <g transform="scale(1 1.0033)" clip-path="url(#clip14-7)">
+     <image width="900647" height="900647" preserveAspectRatio="none" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJkAAACZCAYAAAA8XJi6AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAy2SURBVHhe7Z0LsFVVGccZe5dmPjLyiSn4osLKzKSxZmpytDCxpimLh5YwQmYDOVONghalpRNYOpHpZBZljkpkwL37APdxuDBF45RMGoVhJpFyDUtTC6Xfun4Htot1ztnv5/eb+c++95y91/q+b/3P2vvsc87eo5R6sHr16gvRzfKvoiRHs9ncb9WqVfevWbNmlxF//5vlXHlaUeKBmT6BHmgZzC/MdgfL8bKqooQHA830m8oldp9P9fX1vVk2UZRgeJ63P7PUJpepHLpVNlOUYDAznR/CYE8i3V0qwcEws30G6ioM+XHZVFE6Mzg4eACmWWibqIu2yeaK0hljMGakzQ4TtZU5hYFOkiYUpT0Y5lLbQEGEKW+RJhTFzdDQ0IGYZZFtniAys1ij0ThRmlKUvfE87yCM8heXgYKIWUw/VlLag0nm2qYJI8y5VZpSlL3BJF+0TRNWfX1950pzirIHzHEweshvloh6RJpUlD1w/HQhu7i/OgwTSrTxL5bHS7OK8gKY4kt+o8TUYmlWUUaNWrt27SGY4gbLJHH0BDPZcdK8UncajcYbMMXfLJPEEgf7H5bmlbrD8ddF6BGXUaKKGexhaV6pO5jrCpdJYmqH53njpAulrmCE0Rhsq2WORMRu8kbpRqkrGGEmu7O/2+ZISDsw2VjpSqkjmOBKyxSJCvOeJV0pdaO3t/dQTLDNNkXC2iLdKXWj2WweyvHXPxymSEzMYP9keax0qdQJBn6B3wxpCRN/R7pU6gIDfzizy022GdKQzmI1hAE3BnvMb4Q0xSx2vXRdHgh6Hm+D55klScyX5fvl6cpBbnMxhblGRGvg/ow+LU+Hgnau8bWTuujvQem6+GCkM9BqVyJtNF+M+EFpopSQx2IrL782M4hTZNWO9Pf3H8H6P7C2T12NRuMDEkKxoZDE604iqGhjnTEdf58pzRYec9KSeM0vqZ05tWRmC15MU2WzvfA870ieH3Ztm7IWSgjFhuIYY7gSiCUG5kpU6BODmOwsV+ztRD7mRxzTZPMRqN8lPJaHwYYx95skjGLjCD5xMRC/NrMc7CPdFoKwJvNpC4abzvI66/HMRE2/LWkUH1cCaYriXMXyQ9J9rsQwWd4a5hjwaEmj+DgSyEzGcAx0rl+sI45OB/6FFDV7n4RfDhjoVI7JQuq3FG6ShJQ59P89K57Cit30Jgm7PBD4e+1E8hSm/yo6R8LLDPo+lgG8zY6nYNqOxkjI5YJZJI1vZ8YSA34vy/nopRJmJmDwOfRtfkbmjCtnXSthlhOKG+ZEbNb62oYNG14moWYCfX7XiiFvbcf8R0l45aXgRjOz2wJm3ckSbqrQX6FMRt7vkdDKDwmZ0//ORIsizPZ7Xg/nSciJQtvHFHB3+YCEVx0YwMIbzQgz3McrfN7y5ctfIaHHgrznoCIej02UEKsFiTWsRAstzPb1OGajjaKexrhGQqwmJFgqoxkxE32D5Sslha5gzrHMiP6v+RRGxPWY+fBdQq0uJDvRTr4MCmI2BtFc96vrtzBy1NUSavUh2YkMiGcVoCy6emho6FWSym7IJ5OvRscRMb5bwq0PzA69rmKUQQzYNcuWLXv1wMDAOPJY4lqnoLp5cHCw+rtMPwzQ6Y5CqNJV9U5hBAGz9TiKoUpJlToZGwYSP43d0POuoqiSFS/qb0nZ6wkFmKdmS1e1ncn8UIh3YbQVdnFUyUhN5oNZ7VSd1RJXPQ/8u4HZfuUolqqNqNfZ6EbHc/U7hRGGRqPxToqkZusidoVXSclG4LHPoPnmB8PykNINingKRbunVVTVHjF7bTPXLpNSKXGhqO+gqM/Zha6zmK3eJuVRkoTiXq5mG/mo614piZIWFPpytNNf+LpIDZYxFLyOZpsg6StZwZuDkyn8UmsgKilyvULSVvKAQZiAKm02Zu63SrpKnjAYExiMu+0BKrvIydyFZLSkqRQB86rnnehd9mCVWeSzFc2QFJWi0Gg03sIA3WkPWNlFXov1ZGwBYRb4MgP0rD1gZRY5fR/DHSYpKkWAgRnPuzRzYeRKmY3Dg5vI62JJs1Ts2rVrH8Zj95XTzZKc5svT5YZEzD27n2kNVBWE2R5loGZJioUFY70EM5mrZzrzIIczZNXyQ0JP2AlWQZjN3HRitqRZGIjpTGJb54/VoVWyejUgoUqazCdz6ajPSbq5wKx0NjEEvVdUQzarDkzZH3MkWjkx0MPoEkk7dcz1RejP/IbjN654XGLd5xmP6n1dvC4m82mYnFMzG21PwlzmUg+uvjvpOd4lV/P3CDU02YiYNR7HDJ+XMsTCXM6BNq+2+wgjYumV5qpHXU3WEmYztyO8VMoRCradjDl+Z7cZVrTzP2myulCoqh/8B9EO9AUpSVt6enpeQ72+aW0bRztp73RpvrqoyV4s6rGE2eU4KY95B74vM745QbrRv15CmivdVBs1mVsY7Wcsr7UfT0rUfbkMQfVRk2Uvar6T2fE0GYJyQzJf4RX5X0luAf/vdfVrHv9oK3lV+jIH+p7nld9gJGK+T9Yyl53kfRs3bny5rKomy173SOnLDQb7uSO5F4l1Rq58zd9qsoxEzZfJEJUbM4uZKdmVpEsk/gvX46pkZfYs6FQZpnLDAeUUV5JFFfFez9Lcyc35fFXECz/XD+oTJexMlrc4CB5n4ubv2cRtvqLjXK/kWjoyOFWCabnrMVlB1JSQd0PsszDbo451y6onJbVqYWYzcwzgSLho2stkLZrN5qE8X7rbUFt6lsOBUySlaoLR/OfJCicGYKyE2pb+/v43ml8nubYvgWZKGtWHwSzkL5WCmMwPL5oZyPzQ19lekUScd0rY9YLEi3RXkba7ym5gzovY/hGrvSLpGWr9dgm3flCA8exC77CKkocim6wFbXyWwXRdMzZP1dtgfjDaSRQjz3ehx0oosenp6TmE47YbHH1kLlNTCUtpMTAwcCLFud0uVgZKzGQtyOX1DLL57tdDVl9Z6XYJRXFBgcy3Q12FS1zMooPSbWrQz3S0xd9vmiKnpzlWPFm6V1xQqMxMxmwzR7pNHfqbRn/moytnLEkJk02XLpV2UKgsZ7JjpNvMWLly5YH0vciOJQmRz0+lG6UTFOtWu3hpKQ+TtRgcHDyAGBbaMcURM+VUaV7pBIU6z1XAlLQIo10gXecCMSR179FhaVLpRsYmG5E5VvI87yAJIVN6enqOdsUUQWqyoORhspZ4V3aZhJEZ9Ps6ZtM/2bFEkJosKAz0CRT9aUcRUxf9PszyYAklM+hztj+OKOLFuUSaU4LAYJuf7TuLmbaazebuH9RmBf2OseMIK2o2RZpTgpCnyeh7nYSRKfQb687JarKQ5GmyPGYyA7u7Wa54gkpNFpK8TEa/uRyTGej7KDueoMKgetAfFgo+2VXMtJXHu0s/xBDpTslqsgikbLIxZtZgYMxlLh83j/F3bufJ/BDHxVasgaQmi0DaJpNuCgdG35/cNzli7qYfSxNKUNIyGe2ukS4KC3FGud/7p2RzJQzsAkZ2ZUmqDCbr7+8/whV7F6nJopCGyVBhd5UtzC6TOP9oxd1NarIo1NVkBmbcXzpib6ftspkSlqRNVoZdZQviPdyOv4PUZFGheD+0ihlLZTKZgRfZMlceDqnJotLX13euo6CRhcmOkqZLASab4crDFnndJpsoYam7yYg50C4TM54vmyhhSdJkDMRqabZUEPtSOxdbarIY9Pb2nkAB/+MqbFiV1WSEba614cypJTVZTNjFJfIO0/O8I6XJUtFsNvejBve7cjLiucdkVSUqdTeZgRrc7crJSE2WAAmZrNS3OeawwVzp0ZWXmiwJEjJZqa/2bHaZHHf9wZGX+f7bj2Q1JSoU8iN2YcPKfOAszZUWTHaXKzdehJ+UVZSoUMhYJmMQHjQfOEtzpcVcr7ZNfmqyuFDIuDNZQ5oqPewaL7DzU5MlAIWMa7LZ0lQlIB9zrbOR3DDYo/KwEgeKeTzFjHNC9nBpqjKQ0zSTm5osQSjosBgmrDavX7/+tdJMpeCNwFQ1WYJglkgmYxA8aUJROoNhos5kldtVKimBWdRkSrpw/HGOw0AdxTa9srmidEdNpqROFJM1Go3DZHNF6Y6aTMkEjBb44F93lUok1GRK6oQxmfmSn2ymKMFRkympg8lucRnKFuv1yCaKEg7ME+gdpppMiUxQk5lvkMomihIONZmSOgFNtlJWV5RoYKLtlqlszZRVFSUamKijyVasWKG7SiUeGKmtyVa9cCu/fWVVRYkGJupkshWymqJEByNNchnMiDcGM2Q1RYlOJ5Oh0bKaokSnncn0eExJFHaLl6Gn/Cbj/+XytKIkh+d54zDXT8RkejyWGqNG/R8YjKGM+W8KWwAAAABJRU5ErkJggg=="/>
+    </g>
+   </g>
+   <g clip-path="url(#clip15-61)">
+    <g clip-path="url(#clip16-42)">
+     <g clip-path="url(#clip17-4)">
+      <path transform="matrix(1 0 0 1.0024 1216 205)" d="m43.77 25.533c-11.827 7.476-25.56 21.312-32.461 41.775-5.2 15.42-6.0171 33.834-0.137 51.448 5.2127 15.616 15.546 29.89 29.485 39.598 13.266 9.239 29.358 14.029 45.059 13.584 16.924-0.38 33.006-6.789 44.919-16.918 12.54-10.661 20.332-25.122 23.029-39.234 3.049-15.957-0.167-31.256-6.113-42.76-3.879-7.5046-8.968-13.658-14.185-18.446-5.225-4.7961-10.533-8.1973-15.219-10.642-0.025-0.0131 11.317-22.044 11.281-22.063 0.036 0.0186 11.593-21.901 11.64-21.876 8.696 4.5365 18 11.089 26.661 20.152 8.613 9.0146 16.588 20.543 22.056 34.377 8.348 21.117 10.356 46.884 2.263 71.748-7.174 22.037-22.075 42.043-42.424 55.096-19.367 12.423-42.784 17.865-65.276 15.319-20.842-2.455-40.093-11.686-54.523-25.103-15.173-14.108-24.587-32.328-28.128-50.37-3.9939-20.35-0.5637-39.853 6.3855-55.187 9.1897-20.277 24.038-33.135 35.688-40.5z" fill="#bfbfbf"/>
+     </g>
+    </g>
+   </g>
+  </g>
+ </g>
+</svg>
diff --git a/installer/UNICADOinstaller.py b/installer/UNICADOinstaller.py
new file mode 100644
index 0000000000000000000000000000000000000000..29aa0e47e8508a69f9e5265d99cbdd10b9a63abf
--- /dev/null
+++ b/installer/UNICADOinstaller.py
@@ -0,0 +1,588 @@
+# imports for python
+import sys
+import image_rc
+import argparse
+from pathlib import Path
+from PyQt5 import QtCore, QtGui, QtWidgets
+from sub_functions.last_step import last_step
+from sub_functions.line_edit import line_edit
+from sub_functions.next_step import next_step
+from sub_functions.check_tool import check_tool
+from sub_functions.update_steps import update_steps
+from sub_functions.current_text import current_text
+from sub_functions.abort_install import abort_install
+from sub_functions.browse_folder import browse_folder
+from sub_functions.retranslate_ui import retranslate_ui
+from sub_functions.install_unicado import install_unicado, install_unicado_headless
+from sub_functions.uninstall_steps import uninstall_steps
+from sub_functions.integration_step import integration_step
+
+""" -*- coding: utf-8 -*-
+
+    Form implementation generated from reading ui file 'UNICADOinstaller.ui'
+
+    Created by: PyQt5 UI code generator 5.15.4
+
+    WARNING: Any manual changes made to this file will be lost when pyuic5 is
+    run again.  Do not edit this file unless you know what you are doing.
+"""
+
+''' class for gui-layout and action handling '''
+# noinspection PyAttributeOutsideInit
+
+
+class UNICADOworkflowInstaller(object):
+    def setup_ui(self, unicado_workflow_installer):
+        unicado_workflow_installer.setObjectName("unicado_workflow_installer")
+        unicado_workflow_installer.resize(550, 400)
+        #unicado_workflow_installer.setMinimumSize(550, 400)
+        #unicado_workflow_installer.setMaximumSize(1920, 1080)
+        font = QtGui.QFont()
+        font.setFamily("Calibri")
+        font.setPointSize(12)
+        unicado_workflow_installer.setFont(font)
+        icon = QtGui.QIcon()
+        icon.addPixmap(QtGui.QPixmap(":/newPrefix/unicadoICON.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        unicado_workflow_installer.setWindowIcon(icon)
+        unicado_workflow_installer.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.Germany))
+
+        # button panel
+        self.button_panel = QtWidgets.QWidget(unicado_workflow_installer)
+        self.button_panel.setGeometry(QtCore.QRect(0, 350, 550, 50))
+        self.button_panel.setAutoFillBackground(True)
+        self.button_panel.setStyleSheet("border-top:3px solid rgb(200, 200, 200)")
+        self.button_panel.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.Germany))
+        self.button_panel.setObjectName("button_panel")
+        self.integration_button = QtWidgets.QPushButton(self.button_panel)
+        self.integration_button.setStyleSheet("border:1px solid rgb(200, 200, 200); "
+                                              "Background-color: rgb(225, 225, 225);")
+        self.integration_button.setGeometry(QtCore.QRect(115, 10, 110, 30))
+        self.integration_button.setAutoFillBackground(True)
+        self.integration_button.setObjectName("integration_button")
+        self.integration_button.released.connect(self.integrationStep)
+        self.integration_button.setVisible(False)
+        self.next_button = QtWidgets.QPushButton(self.button_panel)
+        self.next_button.setStyleSheet("border:1px solid rgb(200, 200, 200); "
+                                       "Background-color: rgb(225, 225, 225);")
+        self.next_button.setGeometry(QtCore.QRect(325, 10, 100, 30))
+        self.next_button.setAutoFillBackground(True)
+        self.next_button.setObjectName("next_button")
+        self.next_button.released.connect(self.nextStep)
+        self.cancel_button = QtWidgets.QPushButton(self.button_panel)
+        self.cancel_button.setStyleSheet("border:1px solid rgb(200, 200, 200); "
+                                         "Background-color: rgb(225, 225, 225);")
+        self.cancel_button.setGeometry(QtCore.QRect(440, 10, 100, 30))
+        self.cancel_button.setMouseTracking(False)
+        self.cancel_button.setAutoFillBackground(True)
+        self.cancel_button.setObjectName("cancelButton")
+        self.cancel_button.released.connect(self.abortInstall)
+        self.back_button = QtWidgets.QPushButton(self.button_panel)
+        self.back_button.setStyleSheet("border:1px solid rgb(200, 200, 200); "
+                                       "Background-color: rgb(225, 225, 225);")
+        self.back_button.setGeometry(QtCore.QRect(225, 10, 100, 30))
+        self.back_button.setAutoFillBackground(True)
+        self.back_button.setObjectName("back_button")
+        self.back_button.released.connect(self.lastStep)
+        self.back_button.setVisible(False)
+        self.update_button = QtWidgets.QPushButton(self.button_panel)
+        self.update_button.setStyleSheet("border:1px solid rgb(200, 200, 200); "
+                                         "Background-color: rgb(225, 225, 225);")
+        self.update_button.setGeometry(QtCore.QRect(325, 10, 100, 30))
+        self.update_button.setAutoFillBackground(True)
+        self.update_button.setObjectName("update_button")
+        self.update_button.released.connect(self.updateSteps)
+        self.update_button.setVisible(False)
+        self.uninstall_button = QtWidgets.QPushButton(self.button_panel)
+        self.uninstall_button.setStyleSheet("border:1px solid rgb(200, 200, 200); "
+                                            "Background-color: rgb(225, 225, 225);")
+        self.uninstall_button.setGeometry(QtCore.QRect(225, 10, 100, 30))
+        self.uninstall_button.setAutoFillBackground(True)
+        self.uninstall_button.setObjectName("uninstall_button")
+        self.uninstall_button.released.connect(self.uninstallSteps)
+        self.uninstall_button.setVisible(False)
+
+        # welcome panel
+        self.welcome_panel = QtWidgets.QWidget(unicado_workflow_installer)
+        self.welcome_panel.setGeometry(QtCore.QRect(100, 0, 450, 350))
+        self.welcome_panel.setAutoFillBackground(True)
+        self.welcome_panel.setObjectName("welcome_panel")
+        self.welcome_text_label_1 = QtWidgets.QLabel(self.welcome_panel)
+        self.welcome_text_label_1.setGeometry(QtCore.QRect(30, 22, 400, 50))
+        font = QtGui.QFont()
+        font.setPointSize(16)
+        font.setBold(True)
+        font.setWeight(75)
+        self.welcome_text_label_1.setFont(font)
+        self.welcome_text_label_1.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
+        self.welcome_text_label_1.setWordWrap(True)
+        self.welcome_text_label_1.setObjectName("welcome_text_label_1")
+        self.install_text_label_1 = QtWidgets.QLabel(self.welcome_panel)
+        self.install_text_label_1.setGeometry(QtCore.QRect(30, 90, 400, 40))
+        self.install_text_label_1.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
+        self.install_text_label_1.setWordWrap(True)
+        self.install_text_label_1.setObjectName("install_text_label_1")
+        self.continue_text_label = QtWidgets.QLabel(self.welcome_panel)
+        self.continue_text_label.setGeometry(QtCore.QRect(30, 190, 400, 20))
+        self.continue_text_label.setAlignment(QtCore.Qt.AlignBottom | QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft)
+        self.continue_text_label.setObjectName("continue_text_label")
+        self.install_text_label_2 = QtWidgets.QLabel(self.welcome_panel)
+        self.install_text_label_2.setGeometry(QtCore.QRect(30, 140, 400, 40))
+        self.install_text_label_2.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
+        self.install_text_label_2.setWordWrap(True)
+        self.install_text_label_2.setObjectName("install_text_label_2")
+
+        # header panel
+        self.header_panel = QtWidgets.QWidget(unicado_workflow_installer)
+        self.header_panel.setGeometry(QtCore.QRect(100, 0, 450, 80))
+        self.header_panel.setStyleSheet("border-bottom:3px solid rgb(200, 200, 200)")
+        self.header_panel.setAutoFillBackground(True)
+        self.header_panel.setObjectName("header_panel")
+        self.header_panel.setVisible(False)
+        self.header_text_label_1 = QtWidgets.QLabel(self.header_panel)
+        self.header_text_label_1.setGeometry(QtCore.QRect(10, 10, 430, 30))
+        font = QtGui.QFont()
+        font.setPointSize(13)
+        font.setBold(True)
+        font.setWeight(75)
+        self.header_text_label_1.setFont(font)
+        self.header_text_label_1.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
+        self.header_text_label_1.setObjectName("header_text_label_1")
+        self.header_text_label_2 = QtWidgets.QLabel(self.header_panel)
+        self.header_text_label_2.setGeometry(QtCore.QRect(20, 30, 410, 30))
+        self.header_text_label_2.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
+        self.header_text_label_2.setObjectName("header_text_label_2")
+
+        # logo label
+        self.logo_label = QtWidgets.QLabel(unicado_workflow_installer)
+        self.logo_label.setGeometry(QtCore.QRect(10, 0, 80, 350))
+        self.logo_label.setText("")
+        self.logo_label.setPixmap(QtGui.QPixmap(":/newPrefix/UNICADOLogo90.svg"))
+        self.logo_label.setScaledContents(True)
+        self.logo_label.setAlignment(QtCore.Qt.AlignCenter)
+        self.logo_label.setObjectName("logo_label")
+
+        # install and finish panel
+        self.install_and_finish_panel = QtWidgets.QWidget(unicado_workflow_installer)
+        self.install_and_finish_panel.setGeometry(QtCore.QRect(100, 80, 450, 270))
+        self.install_and_finish_panel.setAutoFillBackground(True)
+        self.install_and_finish_panel.setObjectName("install_and_finish_panel")
+        self.install_and_finish_panel.setVisible(False)
+        self.install_progress_bar = QtWidgets.QProgressBar(self.install_and_finish_panel)
+        self.install_progress_bar.setGeometry(QtCore.QRect(20, 145, 410, 25))
+        self.install_progress_bar.setProperty("value", 0)
+        self.install_progress_bar.setObjectName("install_progress_bar")
+        self.install_and_finish_panel_text_label_1 = QtWidgets.QLabel(self.install_and_finish_panel)
+        self.install_and_finish_panel_text_label_1.setGeometry(QtCore.QRect(20, 20, 410, 80))
+        self.install_and_finish_panel_text_label_1.setAlignment(
+            QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
+        self.install_and_finish_panel_text_label_1.setObjectName("install_and_finish_panel_text_label_1")
+        self.install_and_finish_panel_text_label_2 = QtWidgets.QLabel(self.install_and_finish_panel)
+        self.install_and_finish_panel_text_label_2.setGeometry(QtCore.QRect(20, 40, 410, 80))
+        self.install_and_finish_panel_text_label_2.setAlignment(
+            QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
+        self.install_and_finish_panel_text_label_2.setObjectName("install_and_finish_panel_text_label_2")
+
+        # repository path panel
+        self.repository_path_panel = QtWidgets.QWidget(unicado_workflow_installer)
+        self.repository_path_panel.setGeometry(QtCore.QRect(100, 80, 450, 270))
+        self.repository_path_panel.setAutoFillBackground(True)
+        self.repository_path_panel.setObjectName("repository_path_panel")
+        self.repository_path_panel.setVisible(False)
+
+        # repository browse panel
+        self.repository_browse_panel = QtWidgets.QWidget(self.repository_path_panel)
+        self.repository_browse_panel.setStyleSheet("border:1px solid rgb(200, 200, 200)")
+        self.repository_browse_panel.setGeometry(QtCore.QRect(20, 130, 410, 55))
+        self.repository_browse_panel.setObjectName("repository_browse_panel")
+        self.repository_path_line_edit = QtWidgets.QLineEdit(self.repository_browse_panel)
+        self.repository_path_line_edit.setGeometry(QtCore.QRect(15, 15, 295, 25))
+        self.repository_path_line_edit.setObjectName("repository_path_line_edit")
+        self.repository_path_line_edit.textEdited.connect(self.lineEdit)
+        font = QtGui.QFont()
+        font.setPointSize(10)
+        self.repository_path_browse_button = QtWidgets.QPushButton(self.repository_browse_panel)
+        self.repository_path_browse_button.setStyleSheet("border:1px solid rgb(200, 200, 200); "
+                                                         "Background-color: rgb(225, 225, 225);")
+        self.repository_path_browse_button.setGeometry(QtCore.QRect(315, 15, 80, 25))
+        self.repository_path_browse_button.setFont(font)
+        self.repository_path_browse_button.setAutoFillBackground(True)
+        self.repository_path_browse_button.setObjectName("repository_path_browse_button")
+        self.repository_path_browse_button.released.connect(self.browseFolder)
+        self.repository_path_text_label_1 = QtWidgets.QLabel(self.repository_path_panel)
+        self.repository_path_text_label_1.setGeometry(QtCore.QRect(20, 20, 410, 80))
+        self.repository_path_text_label_1.setAutoFillBackground(True)
+        self.repository_path_text_label_1.setAlignment(
+            QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
+        self.repository_path_text_label_1.setWordWrap(True)
+        self.repository_path_text_label_1.setObjectName("repository_path_text_label_1")
+        self.repository_path_text_label_2 = QtWidgets.QLabel(self.repository_path_panel)
+        self.repository_path_text_label_2.setGeometry(QtCore.QRect(30, 110, 102, 30))
+        self.repository_path_text_label_2.setAutoFillBackground(True)
+        self.repository_path_text_label_2.setFont(font)
+        self.repository_path_text_label_2.setAlignment(
+            QtCore.Qt.AlignBottom | QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft)
+        self.repository_path_text_label_2.setObjectName("repository_path_text_label_2")
+
+        # install path panel
+        self.install_path_panel = QtWidgets.QWidget(unicado_workflow_installer)
+        self.install_path_panel.setGeometry(QtCore.QRect(100, 80, 450, 270))
+        self.install_path_panel.setAutoFillBackground(True)
+        self.install_path_panel.setObjectName("install_path_panel")
+        self.install_path_panel.setVisible(False)
+        self.install_path_text_label_1 = QtWidgets.QLabel(self.install_path_panel)
+        self.install_path_text_label_1.setGeometry(QtCore.QRect(20, 20, 410, 80))
+        self.install_path_text_label_1.setAlignment(
+            QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
+        self.install_path_text_label_1.setWordWrap(True)
+        self.install_path_text_label_1.setObjectName("install_path_text_label_1")
+        self.install_path_text_label_2 = QtWidgets.QLabel(self.install_path_panel)
+        self.install_path_text_label_2.setGeometry(QtCore.QRect(20, 210, 410, 30))
+        self.install_path_text_label_2.setAlignment(
+            QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
+        self.install_path_text_label_2.setObjectName("install_path_text_label_2")
+        self.install_path_text_label_3 = QtWidgets.QLabel(self.install_path_panel)
+        self.install_path_text_label_3.setGeometry(QtCore.QRect(20, 230, 410, 30))
+        self.install_path_text_label_3.setAlignment(
+            QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
+        self.install_path_text_label_3.setObjectName("install_path_text_label_3")
+        self.install_path_text_label_4 = QtWidgets.QLabel(self.install_path_panel)
+        self.install_path_text_label_4.setAutoFillBackground(True)
+        self.install_path_text_label_4.setGeometry(QtCore.QRect(30, 107, 108, 15))
+        self.install_path_text_label_4.setFont(font)
+        self.install_path_text_label_4.setAlignment(
+            QtCore.Qt.AlignBottom | QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft)
+        self.install_path_text_label_4.setObjectName("install_path_text_label_4")
+        self.install_radio_button_repo = QtWidgets.QRadioButton('Install from repository', self.install_path_panel)
+        self.install_radio_button_repo.move(60, 180)
+        self.install_radio_button_repo.toggled.connect(self.install_mode)
+        self.install_radio_button_repo.setVisible(False)
+        self.install_radio_button_alone = QtWidgets.QRadioButton('Install standalone', self.install_path_panel)
+        self.install_radio_button_alone.move(240, 180)
+        self.install_radio_button_alone.toggled.connect(self.install_mode)
+        self.install_radio_button_alone.setChecked(True)
+        self.install_radio_button_alone.setVisible(False)
+        self.install_button_group = QtWidgets.QButtonGroup(self.install_path_panel)
+        self.install_button_group.addButton(self.install_radio_button_repo)
+        self.install_button_group.addButton(self.install_radio_button_alone)
+
+        # install browse panel
+        self.install_browse_panel = QtWidgets.QWidget(self.install_path_panel)
+        self.install_browse_panel.setStyleSheet("border:1px solid rgb(200, 200, 200)")
+        self.install_browse_panel.setGeometry(QtCore.QRect(20, 115, 410, 55))
+        self.install_browse_panel.setObjectName("install_browse_panel")
+        self.install_path_line_edit = QtWidgets.QLineEdit(self.install_browse_panel)
+        self.install_path_line_edit.setGeometry(QtCore.QRect(15, 15, 310, 25))
+        self.install_path_line_edit.setFont(font)
+        self.install_path_line_edit.setObjectName("install_path_line_edit")
+        self.install_path_line_edit.textEdited.connect(self.lineEdit)
+        self.install_path_browse_button = QtWidgets.QPushButton(self.install_browse_panel)
+        self.install_path_browse_button.setStyleSheet("border:1px solid rgb(200, 200, 200); "
+                                                      "Background-color: rgb(225, 225, 225);")
+        self.install_path_browse_button.setGeometry(QtCore.QRect(315, 15, 80, 25))
+        self.install_path_browse_button.setFont(font)
+        self.install_path_browse_button.setAutoFillBackground(True)
+        self.install_path_browse_button.setObjectName("install_path_browse_button")
+        self.install_path_browse_button.released.connect(self.browseFolder)
+
+        # module integration panel
+        self.integration_panel = QtWidgets.QWidget(unicado_workflow_installer)
+        self.integration_panel.setGeometry(QtCore.QRect(100, 80, 450, 270))
+        self.integration_panel.setAutoFillBackground(True)
+        self.integration_panel.setObjectName("install_path_panel")
+        self.integration_panel.setVisible(False)
+        self.integration_text_label_0 = QtWidgets.QLabel(self.integration_panel)
+        self.integration_text_label_0.setGeometry(QtCore.QRect(20, 20, 410, 80))
+        self.integration_text_label_0.setAlignment(
+            QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
+        self.integration_text_label_0.setWordWrap(True)
+        self.integration_text_label_0.setObjectName("integration_text_label_0")
+        self.integration_text_label_0.setVisible(False)
+        self.integration_text_label_0.setEnabled(False)
+        self.integration_text_label_1 = QtWidgets.QLabel(self.integration_panel)
+        self.integration_text_label_1.setGeometry(QtCore.QRect(20, 20, 410, 80))
+        self.integration_text_label_1.setAlignment(
+            QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
+        self.integration_text_label_1.setWordWrap(True)
+        self.integration_text_label_1.setObjectName("integration_text_label_1")
+        self.integration_text_label_2 = QtWidgets.QLabel(self.integration_panel)
+        self.integration_text_label_2.setGeometry(QtCore.QRect(20, 170, 410, 80))
+        self.integration_text_label_2.setAlignment(
+            QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
+        self.integration_text_label_2.setWordWrap(True)
+        self.integration_text_label_2.setObjectName("integration_text_label_2")
+        self.integration_text_label_2.setVisible(False)
+        self.integration_text_label_3 = QtWidgets.QLabel(self.integration_panel)
+        self.integration_text_label_3.setGeometry(QtCore.QRect(20, 125, 410, 80))
+        self.integration_text_label_3.setAlignment(
+            QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
+        self.integration_text_label_3.setWordWrap(True)
+        self.integration_text_label_3.setObjectName("integration_text_label_3")
+        self.integration_text_label_3.setVisible(False)
+        self.integration_text_label_4 = QtWidgets.QLabel(self.integration_panel)
+        self.integration_text_label_4.setGeometry(QtCore.QRect(20, 200, 410, 80))
+        self.integration_text_label_4.setAlignment(
+            QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
+        self.integration_text_label_4.setWordWrap(True)
+        self.integration_text_label_4.setObjectName("integration_text_label_4")
+        self.integration_text_label_4.setVisible(False)
+        self.integration_text_label_5 = QtWidgets.QLabel(self.integration_panel)
+        self.integration_text_label_5.setGeometry(QtCore.QRect(20, 125, 410, 80))
+        self.integration_text_label_5.setAlignment(
+            QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
+        self.integration_text_label_5.setWordWrap(True)
+        self.integration_text_label_5.setObjectName("integration_text_label_5")
+        self.integration_text_label_5.setVisible(False)
+        self.tool_name_panel = QtWidgets.QWidget(self.integration_panel)
+        self.tool_name_panel.setStyleSheet("border:1px solid rgb(200, 200, 200)")
+        self.tool_name_panel.setGeometry(QtCore.QRect(20, 107, 410, 55))
+        self.tool_name_panel.setObjectName("tool_name_panel")
+        self.tool_name_panel_edit = QtWidgets.QLineEdit(self.tool_name_panel)
+        self.tool_name_panel_edit.setGeometry(QtCore.QRect(15, 15, 295, 25))
+        self.tool_name_panel_edit.setFont(font)
+        self.tool_name_panel_edit.setObjectName("tool_name_panel_edit")
+        self.tool_name_panel_edit.textEdited.connect(self.lineEdit)
+        self.tool_name_panel_edit_button = QtWidgets.QPushButton(self.tool_name_panel)
+        self.tool_name_panel_edit_button.setStyleSheet("border:1px solid rgb(200, 200, 200); "
+                                                       "Background-color: rgb(225, 225, 225);")
+        self.tool_name_panel_edit_button.setGeometry(QtCore.QRect(315, 15, 80, 25))
+        self.tool_name_panel_edit_button.setFont(font)
+        self.tool_name_panel_edit_button.setAutoFillBackground(True)
+        self.tool_name_panel_edit_button.setObjectName("tool_name_panel_edit_button")
+        self.tool_name_panel_edit_button.released.connect(self.checkTool)
+
+        self.button_name_panel = QtWidgets.QWidget(self.integration_panel)
+        self.button_name_panel.setGeometry(QtCore.QRect(20, 230, 410, 55))
+        self.button_name_panel.setObjectName("button_name_panel")
+        self.button_name_panel.setVisible(False)
+        self.integration_radio_button_delete = QtWidgets.QRadioButton('Delete Tool', self.button_name_panel)
+        self.integration_radio_button_delete.move(10, 10)
+        self.integration_radio_button_delete.toggled.connect(self.deleteOrOverwriteTool)
+        self.integration_radio_button_overwrite = QtWidgets.QRadioButton('Overwrite Tool', self.button_name_panel)
+        self.integration_radio_button_overwrite.move(150, 10)
+        self.integration_radio_button_overwrite.toggled.connect(self.deleteOrOverwriteTool)
+        self.integration_button_group_name = QtWidgets.QButtonGroup(self.button_name_panel)
+        self.integration_button_group_name.addButton(self.integration_radio_button_delete)
+        self.integration_button_group_name.addButton(self.integration_radio_button_overwrite)
+
+        self.group_name_panel = QtWidgets.QWidget(self.integration_panel)
+        self.group_name_panel.setStyleSheet("border:1px solid rgb(200, 200, 200)")
+        self.group_name_panel.setGeometry(QtCore.QRect(20, 173, 410, 55))
+        self.group_name_panel.setObjectName("group_name_panel")
+        self.group_name_panel_edit = QtWidgets.QLineEdit(self.group_name_panel)
+        self.group_name_panel_edit.setGeometry(QtCore.QRect(15, 15, 295, 25))
+        self.group_name_panel_edit.setFont(font)
+        self.group_name_panel_edit.setObjectName("group_name_panel_edit")
+        self.group_name_panel_edit.textEdited.connect(self.lineEdit)
+        self.group_name_panel_edit_button = QtWidgets.QPushButton(self.group_name_panel)
+        self.group_name_panel_edit_button.setStyleSheet("border:1px solid rgb(200, 200, 200); "
+                                                        "Background-color: rgb(225, 225, 225);")
+        self.group_name_panel_edit_button.setGeometry(QtCore.QRect(315, 15, 80, 25))
+        self.group_name_panel_edit_button.setFont(font)
+        self.group_name_panel_edit_button.setAutoFillBackground(True)
+        self.group_name_panel_edit_button.setObjectName("group_name_panel_edit_button")
+        self.group_name_panel_edit_button.released.connect(self.checkTool)
+        self.group_name_panel.setVisible(False)
+        self.tool_path_panel = QtWidgets.QWidget(self.integration_panel)
+        self.tool_path_panel.setStyleSheet("border:1px solid rgb(200, 200, 200)")
+        self.tool_path_panel.setGeometry(QtCore.QRect(20, 50, 410, 55))
+        self.tool_path_panel.setObjectName("tool_path_panel")
+        self.tool_path_panel.setVisible(False)
+        self.tool_path_panel_edit = QtWidgets.QLineEdit(self.tool_path_panel)
+        self.tool_path_panel_edit.setGeometry(QtCore.QRect(15, 15, 295, 25))
+        self.tool_path_panel_edit.setFont(font)
+        self.tool_path_panel_edit.setObjectName("tool_path_panel_edit")
+        self.tool_path_panel_edit.textEdited.connect(self.lineEdit)
+        self.tool_path_panel_edit.setEnabled(False)
+        self.tool_path_panel_browse_button = QtWidgets.QPushButton(self.tool_path_panel)
+        self.tool_path_panel_browse_button.setStyleSheet("border:1px solid rgb(200, 200, 200); "
+                                                         "Background-color: rgb(225, 225, 225);")
+        self.tool_path_panel_browse_button.setGeometry(QtCore.QRect(315, 15, 80, 25))
+        self.tool_path_panel_browse_button.setFont(font)
+        self.tool_path_panel_browse_button.setAutoFillBackground(True)
+        self.tool_path_panel_browse_button.setObjectName("tool_path_panel_browse_button")
+        self.tool_path_panel_browse_button.released.connect(self.browseFolder)
+        self.integration_combo_box = QtWidgets.QComboBox(self.integration_panel)
+        self.integration_combo_box.setGeometry(QtCore.QRect(20, 150, 410, 25))
+        self.integration_combo_box.addItems(['- please select a tool group -', 'postProcessing', 'preSizing',
+                                             'sizingLoop', 'visualization', '- other -'])
+        self.integration_combo_box.activated.connect(self.currentText)
+        self.integration_combo_box.setVisible(False)
+        self.button_group_panel = QtWidgets.QWidget(self.integration_panel)
+        self.button_group_panel.setGeometry(QtCore.QRect(20, 50, 410, 55))
+        self.button_group_panel.setObjectName("button_group_panel")
+        self.button_group_panel.setVisible(False)
+        self.integration_radio_button_yes = QtWidgets.QRadioButton('Yes', self.button_group_panel)
+        self.integration_radio_button_yes.move(10, 15)
+        self.integration_radio_button_yes.toggled.connect(self.start_integration)
+        self.integration_radio_button_no = QtWidgets.QRadioButton('No', self.button_group_panel)
+        self.integration_radio_button_no.move(10, 35)
+        self.integration_radio_button_no.toggled.connect(self.start_integration)
+        self.integration_button_group = QtWidgets.QButtonGroup(self.button_group_panel)
+        self.integration_button_group.addButton(self.integration_radio_button_yes)
+        self.integration_button_group.addButton(self.integration_radio_button_no)
+        self.checkbox_panel = QtWidgets.QWidget(self.integration_panel)
+        self.checkbox_panel.setGeometry(QtCore.QRect(20, 178, 410, 55))
+        self.checkbox_panel.setObjectName("checkbox_panel")
+        self.checkbox_panel.setVisible(False)
+        self.integration_checkbox = QtWidgets.QCheckBox('Repository integration', self.checkbox_panel)
+        self.integration_checkbox.move(10, 10)
+        self.integration_checkbox.setChecked(False)
+        self.integration_checkbox.setVisible(False)
+        self.integration_checkbox.toggled.connect(self.enterPassword)
+        self.checkbox_panel_edit = QtWidgets.QLineEdit(self.checkbox_panel)
+        self.checkbox_panel_edit.setGeometry(QtCore.QRect(210, 10, 125, 25))
+        self.checkbox_panel_edit.setStyleSheet("border:1px solid rgb(200, 200, 200); "
+                                               "Background-color: rgb(255, 255, 255);")
+        self.checkbox_panel_edit.setFont(font)
+        self.checkbox_panel_edit.setObjectName("checkbox_panel_edit")
+        self.checkbox_panel_edit.textEdited.connect(self.lineEdit)
+        self.checkbox_panel_edit.setVisible(False)
+        self.checkbox_panel_text_label_0 = QtWidgets.QLabel(self.checkbox_panel)
+        self.checkbox_panel_text_label_0.setGeometry(QtCore.QRect(20, 20, 410, 80))
+        self.checkbox_panel_text_label_0.setAlignment(
+            QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
+        self.checkbox_panel_text_label_0.setWordWrap(True)
+        self.checkbox_panel_text_label_0.setObjectName("checkbox_panel_text_label_0")
+        self.checkbox_panel_text_label_0.setVisible(False)
+        self.checkbox_panel_text_label_0.setEnabled(False)
+        self.integration_checkbox_show = QtWidgets.QCheckBox('show', self.checkbox_panel)
+        self.integration_checkbox_show.move(340, 10)
+        self.integration_checkbox_show.setChecked(False)
+        self.integration_checkbox_show.setVisible(False)
+        self.integration_checkbox_show.toggled.connect(self.show_input)
+
+        self.button_panel.raise_()
+        self.logo_label.raise_()
+        self.repository_path_panel.raise_()
+        self.install_path_panel.raise_()
+        self.integration_panel.raise_()
+        self.install_and_finish_panel.raise_()
+        self.header_panel.raise_()
+        self.welcome_panel.raise_()
+
+        # show gui with all settings set above
+        unicado_workflow_installer.show()
+
+        # function call to set text to all elements
+        self.retranslateUi(unicado_workflow_installer)
+        QtCore.QMetaObject.connectSlotsByName(unicado_workflow_installer)
+
+    # function to set module integration button settings
+    def integrationStep(self):
+        # call function to handle the next step button
+        integration_step(self)
+
+    # function to set properties of next step button
+    def nextStep(self):
+        # call function to handle the next step button
+        next_step(self)
+
+    # function for back button
+    def lastStep(self):
+        # call function to handle the back button
+        last_step(self)
+
+    # function for abort installation
+    def abortInstall(self):
+        # call function to handle the cancel button
+        abort_install(self)
+
+    # function to update unicado to current version
+    def updateSteps(self):
+        # call function to handle the update button
+        update_steps(self)
+
+    # function to uninstall the entire unicado workflow
+    def uninstallSteps(self):
+        # call function to handle the uninstallation button
+        uninstall_steps(self)
+
+    # function for browse buttons
+    def browseFolder(self):
+        browse_folder(self)
+
+    # function to handle user inputs by line edit field
+    def lineEdit(self):
+        line_edit(self)
+
+    # function to check given tool name to be integrated
+    def checkTool(self):
+        check_tool(self)
+
+    # function to delete or overwrite an integrated non-basic tool
+    def deleteOrOverwriteTool(self):
+        self.next_button.setEnabled(True)
+
+    # function to display required disk space dependent on installation mode
+    def install_mode(self):
+        # check which installation mode is selected
+        if self.install_radio_button_repo.isChecked():
+            self.install_path_text_label_2.setText("Disk space required: 0.85 GB")
+        else:
+            self.install_path_text_label_2.setText("Disk space required: 1.75 GB")
+
+    # function to make user input visible
+    def show_input(self):
+        if self.integration_checkbox_show.isChecked():
+            self.checkbox_panel_edit.setText(self.checkbox_panel_text_label_0.text())
+        else:
+            stars = ''
+            for _ in self.checkbox_panel_edit.text():
+                stars += '*'
+            self.checkbox_panel_edit.setText(stars)
+
+    # function to get the selected string from combo box
+    def currentText(self):
+        current_text(self)
+
+    # function to activate password entering
+    def enterPassword(self):
+        if self.integration_checkbox.isChecked():
+            self.checkbox_panel_edit.setVisible(True)
+            if not self.checkbox_panel_edit.text() == 'enter password':
+                self.integration_checkbox_show.setVisible(True)
+            if self.integration_radio_button_yes.isChecked() or self.integration_radio_button_no.isChecked():
+                self.next_button.setEnabled(False)
+                if self.integration_text_label_0.text() == self.checkbox_panel_text_label_0.text():
+                    self.next_button.setEnabled(True)
+        else:
+            self.checkbox_panel_edit.setVisible(False)
+            self.integration_checkbox_show.setVisible(False)
+            if self.integration_radio_button_yes.isChecked() or self.integration_radio_button_no.isChecked():
+                self.next_button.setEnabled(True)
+
+    # function to activate the start integration button
+    def start_integration(self):
+        if self.integration_checkbox.isChecked():
+            if self.integration_text_label_0.text() == self.checkbox_panel_text_label_0.text() and \
+                    (self.integration_radio_button_yes.isChecked() or self.integration_radio_button_no.isChecked()):
+                self.next_button.setEnabled(True)
+        else:
+            self.next_button.setEnabled(True)
+
+    # function to install UNICADOworkflow on system
+    def installUNICADO(self):
+        install_unicado(self)
+
+    # set text to text-fields
+    def retranslateUi(self, UNICADOworkflow_installer):
+        retranslate_ui(self, UNICADOworkflow_installer)
+
+''' main function für installer gui '''
+if __name__ == "__main__":
+    parser = argparse.ArgumentParser(description="Unicado Installer")
+    parser.add_argument(
+        '--install-dir',
+        type=Path,
+        help='Install path'
+    )
+    args = parser.parse_args()
+    if args.install_dir is None: 
+        print("no argumens")
+        app = QtWidgets.QApplication(sys.argv)
+        UNICADOworkflow_installer = QtWidgets.QFrame()
+        ui = UNICADOworkflowInstaller()
+        ui.setup_ui(UNICADOworkflow_installer)
+        sys.exit(app.exec_())
+    else:
+        install_unicado_headless(args.install_dir)
diff --git a/installer/iconUNICADO.ico b/installer/iconUNICADO.ico
new file mode 100644
index 0000000000000000000000000000000000000000..bb960a72aa445e12d49c0fed4ae52e8497cdddac
Binary files /dev/null and b/installer/iconUNICADO.ico differ
diff --git a/installer/image_rc.py b/installer/image_rc.py
new file mode 100644
index 0000000000000000000000000000000000000000..2824d89e7967f0acee80f777a268da3e0aa2d269
--- /dev/null
+++ b/installer/image_rc.py
@@ -0,0 +1,1196 @@
+# -*- coding: utf-8 -*-
+
+# Resource object code
+#
+# Created by: The Resource Compiler for PyQt5 (Qt v5.15.2)
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore
+
+qt_resource_data = b"\
+\x00\x00\x25\x6b\
+\x3c\
+\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\x22\x33\x38\x22\x20\x68\
+\x65\x69\x67\x68\x74\x3d\x22\x33\x38\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x6f\x76\x65\x72\x66\x6c\x6f\
+\x77\x3d\x22\x68\x69\x64\x64\x65\x6e\x22\x3e\x3c\x64\x65\x66\x73\
+\x3e\x3c\x63\x6c\x69\x70\x50\x61\x74\x68\x20\x69\x64\x3d\x22\x63\
+\x6c\x69\x70\x30\x22\x3e\x3c\x72\x65\x63\x74\x20\x78\x3d\x22\x36\
+\x31\x38\x22\x20\x79\x3d\x22\x32\x36\x36\x22\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x33\x38\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\
+\x38\x22\x2f\x3e\x3c\x2f\x63\x6c\x69\x70\x50\x61\x74\x68\x3e\x3c\
+\x63\x6c\x69\x70\x50\x61\x74\x68\x20\x69\x64\x3d\x22\x63\x6c\x69\
+\x70\x31\x22\x3e\x3c\x72\x65\x63\x74\x20\x78\x3d\x22\x36\x31\x39\
+\x22\x20\x79\x3d\x22\x32\x36\x37\x22\x20\x77\x69\x64\x74\x68\x3d\
+\x22\x33\x36\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x36\x22\
+\x2f\x3e\x3c\x2f\x63\x6c\x69\x70\x50\x61\x74\x68\x3e\x3c\x63\x6c\
+\x69\x70\x50\x61\x74\x68\x20\x69\x64\x3d\x22\x63\x6c\x69\x70\x32\
+\x22\x3e\x3c\x72\x65\x63\x74\x20\x78\x3d\x22\x36\x31\x39\x22\x20\
+\x79\x3d\x22\x32\x36\x37\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x33\
+\x36\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x36\x22\x2f\x3e\
+\x3c\x2f\x63\x6c\x69\x70\x50\x61\x74\x68\x3e\x3c\x63\x6c\x69\x70\
+\x50\x61\x74\x68\x20\x69\x64\x3d\x22\x63\x6c\x69\x70\x33\x22\x3e\
+\x3c\x72\x65\x63\x74\x20\x78\x3d\x22\x36\x31\x39\x22\x20\x79\x3d\
+\x22\x32\x36\x38\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x33\x35\x22\
+\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x34\x22\x2f\x3e\x3c\x2f\
+\x63\x6c\x69\x70\x50\x61\x74\x68\x3e\x3c\x63\x6c\x69\x70\x50\x61\
+\x74\x68\x20\x69\x64\x3d\x22\x63\x6c\x69\x70\x34\x22\x3e\x3c\x72\
+\x65\x63\x74\x20\x78\x3d\x22\x36\x31\x39\x22\x20\x79\x3d\x22\x32\
+\x36\x38\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x33\x35\x22\x20\x68\
+\x65\x69\x67\x68\x74\x3d\x22\x33\x34\x22\x2f\x3e\x3c\x2f\x63\x6c\
+\x69\x70\x50\x61\x74\x68\x3e\x3c\x63\x6c\x69\x70\x50\x61\x74\x68\
+\x20\x69\x64\x3d\x22\x63\x6c\x69\x70\x35\x22\x3e\x3c\x72\x65\x63\
+\x74\x20\x78\x3d\x22\x36\x31\x39\x22\x20\x79\x3d\x22\x32\x36\x38\
+\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x33\x35\x22\x20\x68\x65\x69\
+\x67\x68\x74\x3d\x22\x33\x34\x22\x2f\x3e\x3c\x2f\x63\x6c\x69\x70\
+\x50\x61\x74\x68\x3e\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\
+\x69\x65\x6e\x74\x20\x78\x31\x3d\x22\x31\x31\x33\x2e\x33\x31\x39\
+\x22\x20\x79\x31\x3d\x22\x31\x33\x35\x2e\x37\x31\x33\x22\x20\x78\
+\x32\x3d\x22\x39\x38\x2e\x38\x33\x32\x37\x22\x20\x79\x32\x3d\x22\
+\x31\x35\x30\x2e\x31\x39\x39\x22\x20\x67\x72\x61\x64\x69\x65\x6e\
+\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\
+\x65\x4f\x6e\x55\x73\x65\x22\x20\x73\x70\x72\x65\x61\x64\x4d\x65\
+\x74\x68\x6f\x64\x3d\x22\x70\x61\x64\x22\x20\x69\x64\x3d\x22\x66\
+\x69\x6c\x6c\x36\x22\x3e\x3c\x73\x74\x6f\x70\x20\x6f\x66\x66\x73\
+\x65\x74\x3d\x22\x30\x22\x20\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\
+\x72\x3d\x22\x23\x36\x43\x36\x43\x36\x43\x22\x2f\x3e\x3c\x73\x74\
+\x6f\x70\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x2f\x3e\x3c\
+\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\
+\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x20\
+\x78\x31\x3d\x22\x31\x30\x37\x2e\x31\x39\x38\x22\x20\x79\x31\x3d\
+\x22\x31\x34\x34\x2e\x36\x34\x38\x22\x20\x78\x32\x3d\x22\x38\x37\
+\x2e\x39\x34\x37\x31\x22\x20\x79\x32\x3d\x22\x31\x34\x38\x2e\x36\
+\x32\x39\x22\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\
+\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\
+\x65\x22\x20\x73\x70\x72\x65\x61\x64\x4d\x65\x74\x68\x6f\x64\x3d\
+\x22\x70\x61\x64\x22\x20\x69\x64\x3d\x22\x66\x69\x6c\x6c\x37\x22\
+\x3e\x3c\x73\x74\x6f\x70\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\
+\x22\x20\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x30\
+\x30\x34\x32\x37\x44\x22\x2f\x3e\x3c\x73\x74\x6f\x70\x20\x6f\x66\
+\x66\x73\x65\x74\x3d\x22\x31\x22\x20\x73\x74\x6f\x70\x2d\x63\x6f\
+\x6c\x6f\x72\x3d\x22\x23\x30\x30\x37\x44\x45\x43\x22\x2f\x3e\x3c\
+\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\
+\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x20\
+\x78\x31\x3d\x22\x39\x32\x2e\x34\x36\x34\x39\x22\x20\x79\x31\x3d\
+\x22\x31\x33\x30\x2e\x39\x33\x31\x22\x20\x78\x32\x3d\x22\x31\x30\
+\x32\x2e\x31\x35\x36\x22\x20\x79\x32\x3d\x22\x31\x34\x33\x2e\x39\
+\x33\x22\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\
+\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\
+\x22\x20\x73\x70\x72\x65\x61\x64\x4d\x65\x74\x68\x6f\x64\x3d\x22\
+\x70\x61\x64\x22\x20\x69\x64\x3d\x22\x66\x69\x6c\x6c\x38\x22\x3e\
+\x3c\x73\x74\x6f\x70\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\x22\
+\x20\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x45\x32\
+\x30\x45\x31\x46\x22\x2f\x3e\x3c\x73\x74\x6f\x70\x20\x6f\x66\x66\
+\x73\x65\x74\x3d\x22\x31\x22\x20\x73\x74\x6f\x70\x2d\x63\x6f\x6c\
+\x6f\x72\x3d\x22\x23\x46\x32\x34\x36\x35\x37\x22\x2f\x3e\x3c\x2f\
+\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x3c\
+\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x20\x78\
+\x31\x3d\x22\x31\x32\x30\x2e\x32\x30\x31\x22\x20\x79\x31\x3d\x22\
+\x31\x33\x35\x2e\x35\x36\x31\x22\x20\x78\x32\x3d\x22\x31\x30\x30\
+\x2e\x35\x34\x34\x22\x20\x79\x32\x3d\x22\x31\x33\x30\x2e\x35\x30\
+\x34\x22\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\
+\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\
+\x22\x20\x73\x70\x72\x65\x61\x64\x4d\x65\x74\x68\x6f\x64\x3d\x22\
+\x70\x61\x64\x22\x20\x69\x64\x3d\x22\x66\x69\x6c\x6c\x39\x22\x3e\
+\x3c\x73\x74\x6f\x70\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\x22\
+\x20\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x45\x41\
+\x37\x44\x39\x32\x22\x2f\x3e\x3c\x73\x74\x6f\x70\x20\x6f\x66\x66\
+\x73\x65\x74\x3d\x22\x31\x22\x20\x73\x74\x6f\x70\x2d\x63\x6f\x6c\
+\x6f\x72\x3d\x22\x23\x41\x39\x31\x42\x33\x36\x22\x20\x73\x74\x6f\
+\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x30\x2e\x38\x39\x30\
+\x31\x39\x36\x22\x2f\x3e\x3c\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\
+\x61\x64\x69\x65\x6e\x74\x3e\x3c\x63\x6c\x69\x70\x50\x61\x74\x68\
+\x20\x69\x64\x3d\x22\x63\x6c\x69\x70\x31\x30\x22\x3e\x3c\x72\x65\
+\x63\x74\x20\x78\x3d\x22\x36\x32\x38\x22\x20\x79\x3d\x22\x32\x36\
+\x38\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x31\x36\x22\x20\x68\x65\
+\x69\x67\x68\x74\x3d\x22\x31\x37\x22\x2f\x3e\x3c\x2f\x63\x6c\x69\
+\x70\x50\x61\x74\x68\x3e\x3c\x63\x6c\x69\x70\x50\x61\x74\x68\x20\
+\x69\x64\x3d\x22\x63\x6c\x69\x70\x31\x31\x22\x3e\x3c\x72\x65\x63\
+\x74\x20\x78\x3d\x22\x36\x32\x38\x22\x20\x79\x3d\x22\x32\x36\x38\
+\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x31\x36\x22\x20\x68\x65\x69\
+\x67\x68\x74\x3d\x22\x31\x37\x22\x2f\x3e\x3c\x2f\x63\x6c\x69\x70\
+\x50\x61\x74\x68\x3e\x3c\x63\x6c\x69\x70\x50\x61\x74\x68\x20\x69\
+\x64\x3d\x22\x63\x6c\x69\x70\x31\x32\x22\x3e\x3c\x72\x65\x63\x74\
+\x20\x78\x3d\x22\x36\x32\x38\x22\x20\x79\x3d\x22\x32\x36\x38\x22\
+\x20\x77\x69\x64\x74\x68\x3d\x22\x31\x36\x22\x20\x68\x65\x69\x67\
+\x68\x74\x3d\x22\x31\x37\x22\x2f\x3e\x3c\x2f\x63\x6c\x69\x70\x50\
+\x61\x74\x68\x3e\x3c\x63\x6c\x69\x70\x50\x61\x74\x68\x20\x69\x64\
+\x3d\x22\x63\x6c\x69\x70\x31\x33\x22\x3e\x3c\x72\x65\x63\x74\x20\
+\x78\x3d\x22\x2d\x34\x2e\x33\x37\x39\x37\x35\x22\x20\x79\x3d\x22\
+\x2d\x30\x2e\x33\x31\x38\x36\x37\x22\x20\x77\x69\x64\x74\x68\x3d\
+\x22\x31\x31\x33\x2e\x33\x36\x31\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x31\x31\x39\x2e\x30\x36\x35\x22\x2f\x3e\x3c\x2f\x63\x6c\
+\x69\x70\x50\x61\x74\x68\x3e\x3c\x69\x6d\x61\x67\x65\x20\x77\x69\
+\x64\x74\x68\x3d\x22\x35\x34\x22\x20\x68\x65\x69\x67\x68\x74\x3d\
+\x22\x35\x39\x22\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\
+\x22\x64\x61\x74\x61\x3a\x69\x6d\x61\x67\x65\x2f\x70\x6e\x67\x3b\
+\x62\x61\x73\x65\x36\x34\x2c\x69\x56\x42\x4f\x52\x77\x30\x4b\x47\
+\x67\x6f\x41\x41\x41\x41\x4e\x53\x55\x68\x45\x55\x67\x41\x41\x41\
+\x41\x38\x41\x41\x41\x41\x52\x43\x41\x4d\x41\x41\x41\x41\x31\x31\
+\x41\x61\x54\x41\x41\x41\x41\x41\x58\x4e\x53\x52\x30\x49\x41\x72\
+\x73\x34\x63\x36\x51\x41\x41\x41\x41\x52\x6e\x51\x55\x31\x42\x41\
+\x41\x43\x78\x6a\x77\x76\x38\x59\x51\x55\x41\x41\x41\x45\x49\x55\
+\x45\x78\x55\x52\x51\x41\x41\x41\x50\x2f\x2f\x2f\x34\x44\x2f\x2f\
+\x7a\x50\x4d\x7a\x44\x6e\x47\x78\x6c\x57\x2f\x31\x55\x37\x45\x32\
+\x45\x65\x34\x78\x6c\x48\x46\x30\x54\x57\x31\x74\x53\x6d\x31\x76\
+\x57\x4c\x4c\x32\x43\x79\x6f\x74\x46\x72\x4c\x31\x54\x65\x79\x75\
+\x7a\x2b\x30\x78\x43\x79\x6e\x74\x79\x2b\x70\x75\x31\x43\x39\x7a\
+\x44\x61\x77\x76\x69\x2b\x72\x75\x31\x76\x48\x31\x57\x4c\x4d\x32\
+\x43\x53\x6a\x73\x79\x53\x6c\x74\x43\x69\x6e\x74\x56\x4c\x44\x7a\
+\x32\x66\x52\x33\x57\x6a\x52\x33\x56\x2f\x4b\x31\x7a\x4b\x74\x76\
+\x44\x32\x30\x77\x6a\x71\x79\x77\x47\x44\x4c\x31\x79\x53\x6b\x73\
+\x33\x58\x5a\x35\x53\x65\x6d\x74\x6b\x79\x2f\x7a\x48\x50\x5a\x35\
+\x43\x57\x6b\x74\x43\x65\x6d\x74\x53\x6d\x6e\x74\x69\x71\x6f\x74\
+\x79\x75\x6f\x75\x43\x79\x70\x75\x43\x32\x71\x75\x53\x36\x71\x75\
+\x54\x43\x72\x75\x6a\x4b\x74\x76\x44\x4f\x75\x76\x54\x53\x76\x76\
+\x6a\x61\x77\x76\x7a\x65\x78\x77\x44\x69\x78\x77\x44\x75\x7a\x77\
+\x6a\x36\x31\x78\x44\x2b\x32\x78\x45\x43\x33\x78\x55\x4b\x34\x78\
+\x6b\x53\x35\x78\x30\x61\x37\x79\x45\x65\x37\x79\x55\x69\x38\x79\
+\x6b\x71\x2b\x79\x30\x75\x2b\x79\x30\x32\x2f\x7a\x55\x37\x42\x7a\
+\x6b\x2f\x42\x7a\x6c\x4c\x43\x7a\x31\x54\x45\x30\x56\x58\x46\x30\
+\x6c\x62\x47\x30\x6c\x6a\x48\x31\x46\x72\x49\x31\x56\x76\x4a\x31\
+\x6c\x33\x4b\x31\x31\x2f\x4d\x32\x47\x4c\x4e\x32\x6d\x50\x4f\x32\
+\x6d\x58\x50\x32\x32\x62\x51\x33\x47\x6a\x53\x33\x6d\x6e\x53\x33\
+\x6d\x7a\x55\x34\x47\x2f\x57\x34\x6e\x50\x5a\x35\x48\x54\x5a\x35\
+\x58\x62\x62\x35\x71\x48\x6d\x6c\x6b\x51\x41\x41\x41\x41\x6e\x64\
+\x46\x4a\x4f\x55\x77\x41\x42\x41\x67\x55\x4a\x44\x41\x30\x53\x46\
+\x68\x67\x66\x4a\x79\x6b\x32\x4f\x44\x31\x41\x52\x32\x6c\x36\x67\
+\x34\x79\x52\x76\x39\x6e\x6b\x35\x4f\x6a\x75\x38\x50\x4c\x79\x39\
+\x2f\x6a\x37\x2f\x66\x37\x2b\x2f\x76\x78\x32\x73\x2b\x45\x41\x41\
+\x41\x41\x4a\x63\x45\x68\x5a\x63\x77\x41\x41\x44\x73\x4d\x41\x41\
+\x41\x37\x44\x41\x63\x64\x76\x71\x47\x51\x41\x41\x41\x43\x56\x53\
+\x55\x52\x42\x56\x43\x68\x54\x4e\x63\x6e\x56\x47\x6f\x4a\x51\x45\
+\x49\x58\x52\x45\x62\x75\x37\x4f\x37\x46\x62\x44\x4f\x7a\x75\x56\
+\x74\x37\x2f\x54\x59\x54\x44\x64\x74\x33\x4d\x76\x37\x38\x68\x6c\
+\x53\x4e\x52\x7a\x62\x6e\x51\x52\x4a\x70\x6b\x72\x39\x32\x6f\x46\
+\x45\x4f\x59\x65\x6e\x45\x6f\x64\x46\x76\x31\x4d\x68\x39\x6b\x6b\
+\x31\x74\x4d\x78\x59\x48\x51\x61\x64\x5a\x4b\x76\x45\x58\x5a\x6b\
+\x64\x56\x38\x4d\x75\x71\x6e\x76\x46\x70\x7a\x4f\x43\x4e\x50\x77\
+\x33\x36\x7a\x6e\x49\x32\x64\x79\x6f\x66\x63\x4e\x71\x4c\x34\x63\
+\x62\x66\x4f\x63\x32\x77\x53\x2b\x59\x69\x75\x35\x38\x50\x57\x69\
+\x43\x6d\x7a\x33\x79\x38\x6e\x44\x31\x6f\x52\x65\x4e\x37\x53\x53\
+\x43\x62\x32\x65\x75\x69\x51\x7a\x50\x63\x64\x52\x61\x6d\x6b\x6a\
+\x77\x6d\x6c\x6b\x72\x49\x49\x6b\x4b\x77\x49\x4b\x4f\x44\x2b\x2b\
+\x58\x45\x5a\x6f\x68\x2f\x70\x58\x68\x41\x39\x38\x47\x33\x62\x7a\
+\x77\x41\x41\x41\x41\x42\x4a\x52\x55\x35\x45\x72\x6b\x4a\x67\x67\
+\x67\x3d\x3d\x22\x20\x70\x72\x65\x73\x65\x72\x76\x65\x41\x73\x70\
+\x65\x63\x74\x52\x61\x74\x69\x6f\x3d\x22\x6e\x6f\x6e\x65\x22\x20\
+\x69\x64\x3d\x22\x69\x6d\x67\x31\x34\x22\x3e\x3c\x2f\x69\x6d\x61\
+\x67\x65\x3e\x3c\x63\x6c\x69\x70\x50\x61\x74\x68\x20\x69\x64\x3d\
+\x22\x63\x6c\x69\x70\x31\x35\x22\x3e\x3c\x72\x65\x63\x74\x20\x78\
+\x3d\x22\x30\x22\x20\x79\x3d\x22\x30\x22\x20\x77\x69\x64\x74\x68\
+\x3d\x22\x31\x30\x37\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x31\
+\x31\x36\x2e\x39\x30\x37\x22\x2f\x3e\x3c\x2f\x63\x6c\x69\x70\x50\
+\x61\x74\x68\x3e\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\
+\x65\x6e\x74\x20\x78\x31\x3d\x22\x31\x32\x32\x2e\x34\x31\x38\x22\
+\x20\x79\x31\x3d\x22\x31\x34\x33\x2e\x34\x38\x32\x22\x20\x78\x32\
+\x3d\x22\x31\x31\x31\x2e\x31\x36\x33\x22\x20\x79\x32\x3d\x22\x31\
+\x33\x31\x2e\x32\x33\x39\x22\x20\x67\x72\x61\x64\x69\x65\x6e\x74\
+\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\
+\x4f\x6e\x55\x73\x65\x22\x20\x73\x70\x72\x65\x61\x64\x4d\x65\x74\
+\x68\x6f\x64\x3d\x22\x70\x61\x64\x22\x20\x69\x64\x3d\x22\x66\x69\
+\x6c\x6c\x31\x36\x22\x3e\x3c\x73\x74\x6f\x70\x20\x6f\x66\x66\x73\
+\x65\x74\x3d\x22\x30\x22\x20\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\
+\x72\x3d\x22\x23\x32\x30\x34\x42\x37\x38\x22\x2f\x3e\x3c\x73\x74\
+\x6f\x70\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x20\x73\x74\
+\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x36\x31\x39\x39\x44\
+\x34\x22\x2f\x3e\x3c\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\
+\x69\x65\x6e\x74\x3e\x3c\x2f\x64\x65\x66\x73\x3e\x3c\x67\x20\x63\
+\x6c\x69\x70\x2d\x70\x61\x74\x68\x3d\x22\x75\x72\x6c\x28\x23\x63\
+\x6c\x69\x70\x30\x29\x22\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\
+\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x2d\x36\x31\x38\
+\x20\x2d\x32\x36\x36\x29\x22\x3e\x3c\x67\x20\x63\x6c\x69\x70\x2d\
+\x70\x61\x74\x68\x3d\x22\x75\x72\x6c\x28\x23\x63\x6c\x69\x70\x31\
+\x29\x22\x3e\x3c\x67\x20\x63\x6c\x69\x70\x2d\x70\x61\x74\x68\x3d\
+\x22\x75\x72\x6c\x28\x23\x63\x6c\x69\x70\x32\x29\x22\x3e\x3c\x67\
+\x20\x63\x6c\x69\x70\x2d\x70\x61\x74\x68\x3d\x22\x75\x72\x6c\x28\
+\x23\x63\x6c\x69\x70\x33\x29\x22\x3e\x3c\x67\x20\x63\x6c\x69\x70\
+\x2d\x70\x61\x74\x68\x3d\x22\x75\x72\x6c\x28\x23\x63\x6c\x69\x70\
+\x34\x29\x22\x3e\x3c\x67\x20\x63\x6c\x69\x70\x2d\x70\x61\x74\x68\
+\x3d\x22\x75\x72\x6c\x28\x23\x63\x6c\x69\x70\x35\x29\x22\x3e\x3c\
+\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x31\x33\x2e\x33\x31\x39\
+\x20\x31\x33\x35\x2e\x37\x31\x33\x43\x31\x31\x33\x2e\x33\x31\x39\
+\x20\x31\x33\x35\x2e\x37\x31\x33\x20\x31\x31\x36\x2e\x36\x31\x31\
+\x20\x31\x34\x31\x2e\x39\x39\x38\x20\x31\x31\x32\x2e\x30\x36\x35\
+\x20\x31\x34\x37\x2e\x32\x37\x32\x20\x31\x30\x36\x2e\x33\x39\x37\
+\x20\x31\x35\x33\x2e\x38\x34\x38\x20\x39\x38\x2e\x38\x33\x32\x37\
+\x20\x31\x35\x30\x2e\x31\x39\x39\x20\x39\x38\x2e\x38\x33\x32\x37\
+\x20\x31\x35\x30\x2e\x31\x39\x39\x20\x39\x38\x2e\x38\x33\x32\x37\
+\x20\x31\x35\x30\x2e\x31\x39\x39\x20\x31\x30\x34\x2e\x39\x35\x34\
+\x20\x31\x34\x38\x2e\x38\x30\x31\x20\x31\x30\x38\x2e\x39\x34\x37\
+\x20\x31\x34\x34\x2e\x34\x35\x39\x20\x31\x31\x31\x2e\x38\x36\x32\
+\x20\x31\x34\x31\x2e\x32\x38\x39\x20\x31\x31\x33\x2e\x33\x31\x39\
+\x20\x31\x33\x35\x2e\x37\x31\x33\x20\x31\x31\x33\x2e\x33\x31\x39\
+\x20\x31\x33\x35\x2e\x37\x31\x33\x5a\x22\x20\x73\x74\x72\x6f\x6b\
+\x65\x3d\x22\x23\x31\x36\x31\x36\x31\x36\x22\x20\x73\x74\x72\x6f\
+\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x30\x2e\x30\x35\x33\x32\
+\x33\x32\x22\x20\x66\x69\x6c\x6c\x3d\x22\x75\x72\x6c\x28\x23\x66\
+\x69\x6c\x6c\x36\x29\x22\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\
+\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x31\x20\x30\x20\x30\x20\x31\
+\x2e\x30\x31\x31\x37\x35\x20\x35\x33\x31\x2e\x34\x38\x32\x20\x31\
+\x34\x38\x2e\x37\x34\x35\x29\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\
+\x64\x3d\x22\x4d\x31\x30\x37\x2e\x31\x39\x38\x20\x31\x34\x34\x2e\
+\x36\x34\x38\x43\x31\x30\x37\x2e\x31\x39\x38\x20\x31\x34\x34\x2e\
+\x36\x34\x38\x20\x39\x37\x2e\x36\x30\x35\x33\x20\x31\x35\x33\x2e\
+\x30\x35\x36\x20\x38\x39\x2e\x38\x39\x37\x32\x20\x31\x34\x37\x2e\
+\x31\x39\x36\x20\x38\x35\x2e\x36\x37\x33\x35\x20\x31\x34\x33\x2e\
+\x39\x38\x35\x20\x39\x31\x2e\x37\x39\x38\x34\x20\x31\x33\x36\x2e\
+\x39\x33\x20\x39\x31\x2e\x37\x39\x38\x34\x20\x31\x33\x36\x2e\x39\
+\x33\x20\x39\x31\x2e\x37\x39\x38\x34\x20\x31\x33\x36\x2e\x39\x33\
+\x20\x38\x38\x2e\x35\x38\x33\x37\x20\x31\x34\x31\x2e\x37\x33\x38\
+\x20\x39\x33\x2e\x39\x32\x37\x37\x20\x31\x34\x34\x2e\x34\x39\x37\
+\x20\x39\x37\x2e\x38\x30\x31\x39\x20\x31\x34\x36\x2e\x34\x39\x37\
+\x20\x31\x30\x37\x2e\x31\x39\x38\x20\x31\x34\x34\x2e\x36\x34\x38\
+\x20\x31\x30\x37\x2e\x31\x39\x38\x20\x31\x34\x34\x2e\x36\x34\x38\
+\x5a\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x34\x34\x34\x34\
+\x34\x34\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\
+\x3d\x22\x30\x2e\x30\x35\x33\x32\x33\x32\x22\x20\x66\x69\x6c\x6c\
+\x3d\x22\x75\x72\x6c\x28\x23\x66\x69\x6c\x6c\x37\x29\x22\x20\x74\
+\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\
+\x28\x31\x20\x30\x20\x30\x20\x31\x2e\x30\x31\x31\x37\x35\x20\x35\
+\x33\x31\x2e\x34\x38\x32\x20\x31\x34\x38\x2e\x37\x34\x35\x29\x22\
+\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x39\x36\x2e\x39\
+\x34\x30\x31\x20\x31\x32\x34\x2e\x35\x31\x38\x43\x39\x36\x2e\x39\
+\x34\x30\x31\x20\x31\x32\x34\x2e\x35\x31\x38\x20\x39\x35\x2e\x32\
+\x37\x38\x31\x20\x31\x32\x38\x2e\x36\x30\x34\x20\x39\x36\x2e\x36\
+\x37\x31\x32\x20\x31\x33\x35\x2e\x30\x35\x37\x20\x39\x37\x2e\x37\
+\x32\x39\x31\x20\x31\x33\x39\x2e\x39\x35\x36\x20\x31\x30\x32\x2e\
+\x31\x35\x36\x20\x31\x34\x33\x2e\x39\x33\x20\x31\x30\x32\x2e\x31\
+\x35\x36\x20\x31\x34\x33\x2e\x39\x33\x20\x31\x30\x32\x2e\x31\x35\
+\x36\x20\x31\x34\x33\x2e\x39\x33\x20\x39\x34\x2e\x32\x30\x35\x32\
+\x20\x31\x34\x33\x2e\x37\x36\x35\x20\x39\x32\x2e\x34\x32\x33\x32\
+\x20\x31\x33\x35\x2e\x35\x34\x31\x20\x39\x30\x2e\x39\x33\x39\x31\
+\x20\x31\x32\x38\x2e\x36\x39\x32\x20\x39\x36\x2e\x39\x34\x30\x31\
+\x20\x31\x32\x34\x2e\x35\x31\x38\x20\x39\x36\x2e\x39\x34\x30\x31\
+\x20\x31\x32\x34\x2e\x35\x31\x38\x5a\x22\x20\x73\x74\x72\x6f\x6b\
+\x65\x3d\x22\x23\x45\x33\x30\x45\x31\x46\x22\x20\x73\x74\x72\x6f\
+\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x30\x2e\x30\x35\x33\x32\
+\x33\x32\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\
+\x74\x79\x3d\x22\x30\x2e\x39\x38\x34\x33\x31\x34\x22\x20\x66\x69\
+\x6c\x6c\x3d\x22\x75\x72\x6c\x28\x23\x66\x69\x6c\x6c\x38\x29\x22\
+\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\
+\x69\x78\x28\x31\x20\x30\x20\x30\x20\x31\x2e\x30\x31\x31\x37\x35\
+\x20\x35\x33\x31\x2e\x34\x38\x32\x20\x31\x34\x38\x2e\x37\x34\x35\
+\x29\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x30\
+\x30\x2e\x35\x34\x34\x20\x31\x33\x30\x2e\x35\x30\x34\x43\x31\x30\
+\x30\x2e\x35\x34\x34\x20\x31\x33\x30\x2e\x35\x30\x34\x20\x31\x30\
+\x34\x2e\x37\x20\x31\x32\x34\x2e\x32\x38\x33\x20\x31\x31\x32\x2e\
+\x30\x36\x35\x20\x31\x32\x35\x2e\x39\x38\x20\x31\x32\x30\x2e\x30\
+\x34\x39\x20\x31\x32\x37\x2e\x38\x31\x38\x20\x31\x32\x30\x2e\x32\
+\x30\x31\x20\x31\x33\x35\x2e\x35\x36\x31\x20\x31\x32\x30\x2e\x32\
+\x30\x31\x20\x31\x33\x35\x2e\x35\x36\x31\x20\x31\x32\x30\x2e\x32\
+\x30\x31\x20\x31\x33\x35\x2e\x35\x36\x31\x20\x31\x31\x34\x2e\x31\
+\x34\x37\x20\x31\x33\x30\x2e\x36\x31\x20\x31\x31\x30\x2e\x34\x36\
+\x38\x20\x31\x32\x39\x2e\x37\x34\x34\x20\x31\x30\x37\x2e\x32\x33\
+\x38\x20\x31\x32\x38\x2e\x39\x38\x34\x20\x31\x30\x30\x2e\x35\x34\
+\x34\x20\x31\x33\x30\x2e\x35\x30\x34\x20\x31\x30\x30\x2e\x35\x34\
+\x34\x20\x31\x33\x30\x2e\x35\x30\x34\x5a\x22\x20\x73\x74\x72\x6f\
+\x6b\x65\x3d\x22\x23\x43\x37\x33\x31\x34\x46\x22\x20\x73\x74\x72\
+\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x30\x2e\x30\x35\x33\
+\x32\x33\x32\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\
+\x69\x74\x79\x3d\x22\x30\x2e\x39\x35\x32\x39\x34\x31\x22\x20\x66\
+\x69\x6c\x6c\x3d\x22\x75\x72\x6c\x28\x23\x66\x69\x6c\x6c\x39\x29\
+\x22\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\
+\x72\x69\x78\x28\x31\x20\x30\x20\x30\x20\x31\x2e\x30\x31\x31\x37\
+\x35\x20\x35\x33\x31\x2e\x34\x38\x32\x20\x31\x34\x38\x2e\x37\x34\
+\x35\x29\x22\x2f\x3e\x3c\x67\x20\x63\x6c\x69\x70\x2d\x70\x61\x74\
+\x68\x3d\x22\x75\x72\x6c\x28\x23\x63\x6c\x69\x70\x31\x30\x29\x22\
+\x3e\x3c\x67\x20\x63\x6c\x69\x70\x2d\x70\x61\x74\x68\x3d\x22\x75\
+\x72\x6c\x28\x23\x63\x6c\x69\x70\x31\x31\x29\x22\x3e\x3c\x67\x20\
+\x63\x6c\x69\x70\x2d\x70\x61\x74\x68\x3d\x22\x75\x72\x6c\x28\x23\
+\x63\x6c\x69\x70\x31\x32\x29\x22\x3e\x3c\x67\x20\x63\x6c\x69\x70\
+\x2d\x70\x61\x74\x68\x3d\x22\x75\x72\x6c\x28\x23\x63\x6c\x69\x70\
+\x31\x33\x29\x22\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\
+\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x31\x34\x31\x31\x34\x32\x20\
+\x30\x20\x30\x20\x30\x2e\x31\x34\x32\x37\x37\x39\x20\x36\x32\x38\
+\x2e\x36\x31\x38\x20\x32\x36\x38\x2e\x30\x34\x36\x29\x22\x3e\x3c\
+\x67\x20\x63\x6c\x69\x70\x2d\x70\x61\x74\x68\x3d\x22\x75\x72\x6c\
+\x28\x23\x63\x6c\x69\x70\x31\x35\x29\x22\x20\x74\x72\x61\x6e\x73\
+\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x31\x20\x30\
+\x20\x30\x20\x31\x2e\x30\x30\x30\x37\x39\x20\x32\x2e\x39\x32\x31\
+\x35\x36\x65\x2d\x30\x35\x20\x34\x2e\x36\x31\x30\x38\x33\x65\x2d\
+\x30\x35\x29\x22\x3e\x3c\x75\x73\x65\x20\x77\x69\x64\x74\x68\x3d\
+\x22\x31\x30\x30\x25\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x31\
+\x30\x30\x25\x22\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\
+\x22\x23\x69\x6d\x67\x31\x34\x22\x20\x74\x72\x61\x6e\x73\x66\x6f\
+\x72\x6d\x3d\x22\x73\x63\x61\x6c\x65\x28\x31\x2e\x39\x38\x31\x34\
+\x38\x20\x31\x2e\x39\x38\x31\x34\x38\x29\x22\x3e\x3c\x2f\x75\x73\
+\x65\x3e\x3c\x2f\x67\x3e\x3c\x2f\x67\x3e\x3c\x2f\x67\x3e\x3c\x2f\
+\x67\x3e\x3c\x2f\x67\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\
+\x31\x31\x31\x2e\x31\x36\x33\x20\x31\x33\x31\x2e\x32\x33\x39\x43\
+\x31\x31\x31\x2e\x31\x36\x33\x20\x31\x33\x31\x2e\x32\x33\x39\x20\
+\x31\x32\x32\x2e\x35\x35\x35\x20\x31\x33\x34\x2e\x38\x36\x35\x20\
+\x31\x32\x32\x2e\x33\x37\x34\x20\x31\x34\x33\x2e\x32\x35\x38\x20\
+\x31\x32\x32\x2e\x32\x20\x31\x35\x31\x2e\x33\x39\x35\x20\x31\x31\
+\x32\x2e\x31\x35\x38\x20\x31\x34\x38\x2e\x35\x20\x31\x31\x32\x2e\
+\x31\x35\x38\x20\x31\x34\x38\x2e\x35\x20\x31\x31\x32\x2e\x31\x35\
+\x38\x20\x31\x34\x38\x2e\x35\x20\x31\x31\x37\x2e\x36\x34\x37\x20\
+\x31\x34\x38\x2e\x38\x35\x20\x31\x31\x37\x2e\x38\x32\x36\x20\x31\
+\x34\x33\x2e\x33\x37\x20\x31\x31\x37\x2e\x39\x39\x33\x20\x31\x33\
+\x38\x2e\x32\x35\x35\x20\x31\x31\x31\x2e\x31\x36\x33\x20\x31\x33\
+\x31\x2e\x32\x33\x39\x20\x31\x31\x31\x2e\x31\x36\x33\x20\x31\x33\
+\x31\x2e\x32\x33\x39\x5a\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\
+\x23\x33\x44\x36\x45\x41\x32\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\
+\x77\x69\x64\x74\x68\x3d\x22\x30\x2e\x30\x35\x33\x32\x33\x32\x22\
+\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3d\
+\x22\x30\x2e\x39\x38\x30\x33\x39\x32\x22\x20\x66\x69\x6c\x6c\x3d\
+\x22\x75\x72\x6c\x28\x23\x66\x69\x6c\x6c\x31\x36\x29\x22\x20\x74\
+\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\
+\x28\x31\x20\x30\x20\x30\x20\x31\x2e\x30\x31\x31\x37\x35\x20\x35\
+\x33\x31\x2e\x34\x38\x32\x20\x31\x34\x38\x2e\x37\x34\x35\x29\x22\
+\x2f\x3e\x3c\x2f\x67\x3e\x3c\x2f\x67\x3e\x3c\x2f\x67\x3e\x3c\x70\
+\x61\x74\x68\x20\x64\x3d\x22\x4d\x33\x30\x2e\x31\x30\x39\x36\x2d\
+\x32\x38\x2e\x30\x38\x37\x33\x20\x33\x30\x2e\x31\x30\x39\x36\x20\
+\x30\x2e\x31\x36\x38\x35\x32\x34\x20\x32\x32\x2e\x34\x31\x33\x37\
+\x20\x30\x2e\x31\x36\x38\x35\x32\x34\x20\x32\x32\x2e\x34\x31\x33\
+\x37\x2d\x32\x38\x2e\x30\x38\x37\x33\x5a\x4d\x31\x38\x2e\x33\x31\
+\x32\x39\x2d\x37\x2e\x30\x37\x38\x30\x31\x20\x32\x31\x2e\x30\x30\
+\x39\x33\x2d\x32\x2e\x31\x39\x30\x38\x31\x20\x32\x31\x2e\x30\x30\
+\x39\x33\x2d\x32\x2e\x31\x33\x34\x36\x34\x43\x31\x39\x2e\x30\x36\
+\x31\x39\x2d\x30\x2e\x34\x31\x31\x39\x34\x37\x20\x31\x36\x2e\x36\
+\x34\x36\x34\x20\x30\x2e\x34\x34\x39\x33\x39\x37\x20\x31\x33\x2e\
+\x37\x36\x32\x38\x20\x30\x2e\x34\x34\x39\x33\x39\x37\x20\x39\x2e\
+\x31\x39\x33\x39\x32\x20\x30\x2e\x34\x34\x39\x33\x39\x37\x20\x35\
+\x2e\x39\x35\x34\x35\x31\x2d\x30\x2e\x37\x38\x36\x34\x34\x35\x20\
+\x34\x2e\x30\x34\x34\x35\x37\x2d\x33\x2e\x32\x35\x38\x31\x33\x20\
+\x32\x2e\x32\x38\x34\x34\x34\x2d\x35\x2e\x34\x36\x37\x36\x37\x20\
+\x31\x2e\x34\x30\x34\x33\x37\x2d\x38\x2e\x39\x38\x37\x39\x34\x20\
+\x31\x2e\x34\x30\x34\x33\x37\x2d\x31\x33\x2e\x38\x31\x39\x4c\x31\
+\x2e\x34\x30\x34\x33\x37\x2d\x32\x38\x2e\x30\x38\x37\x33\x20\x39\
+\x2e\x31\x30\x30\x32\x39\x2d\x32\x38\x2e\x30\x38\x37\x33\x20\x39\
+\x2e\x31\x30\x30\x32\x39\x2d\x31\x33\x2e\x38\x31\x39\x43\x39\x2e\
+\x31\x30\x30\x32\x39\x2d\x31\x32\x2e\x38\x30\x37\x38\x20\x39\x2e\
+\x31\x31\x39\x30\x32\x2d\x31\x31\x2e\x38\x33\x34\x31\x20\x39\x2e\
+\x31\x35\x36\x34\x37\x2d\x31\x30\x2e\x38\x39\x37\x39\x20\x39\x2e\
+\x32\x33\x31\x33\x37\x2d\x39\x2e\x39\x36\x31\x36\x34\x20\x39\x2e\
+\x34\x33\x37\x33\x34\x2d\x39\x2e\x31\x33\x37\x37\x34\x20\x39\x2e\
+\x37\x37\x34\x33\x39\x2d\x38\x2e\x34\x32\x36\x32\x20\x31\x30\x2e\
+\x31\x34\x38\x39\x2d\x37\x2e\x37\x31\x34\x36\x35\x20\x31\x30\x2e\
+\x37\x31\x30\x36\x2d\x37\x2e\x31\x33\x34\x31\x38\x20\x31\x31\x2e\
+\x34\x35\x39\x36\x2d\x36\x2e\x36\x38\x34\x37\x38\x20\x31\x32\x2e\
+\x32\x30\x38\x36\x2d\x36\x2e\x32\x37\x32\x38\x34\x20\x31\x33\x2e\
+\x32\x37\x35\x39\x2d\x36\x2e\x30\x36\x36\x38\x36\x20\x31\x34\x2e\
+\x36\x36\x31\x36\x2d\x36\x2e\x30\x36\x36\x38\x36\x20\x31\x35\x2e\
+\x32\x39\x38\x32\x2d\x36\x2e\x30\x36\x36\x38\x36\x20\x31\x35\x2e\
+\x39\x31\x36\x32\x2d\x36\x2e\x31\x36\x30\x34\x39\x20\x31\x36\x2e\
+\x35\x31\x35\x33\x2d\x36\x2e\x33\x34\x37\x37\x33\x20\x31\x37\x2e\
+\x31\x31\x34\x35\x2d\x36\x2e\x35\x33\x34\x39\x38\x20\x31\x37\x2e\
+\x36\x37\x36\x33\x2d\x36\x2e\x37\x37\x38\x34\x31\x20\x31\x38\x2e\
+\x32\x30\x30\x36\x2d\x37\x2e\x30\x37\x38\x30\x31\x5a\x22\x20\x66\
+\x69\x6c\x6c\x3d\x22\x23\x42\x46\x42\x46\x42\x46\x22\x20\x74\x72\
+\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\
+\x31\x20\x30\x20\x30\x20\x31\x2e\x30\x31\x31\x36\x20\x35\x32\x36\
+\x2e\x33\x34\x37\x20\x33\x30\x31\x2e\x31\x37\x29\x22\x2f\x3e\x3c\
+\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x32\x2e\x34\x36\x37\x35\
+\x2d\x32\x38\x2e\x30\x38\x37\x33\x20\x33\x30\x2e\x31\x30\x37\x32\
+\x2d\x32\x38\x2e\x30\x38\x37\x33\x20\x33\x30\x2e\x31\x30\x37\x32\
+\x20\x30\x20\x32\x32\x2e\x34\x36\x37\x35\x20\x30\x5a\x4d\x34\x38\
+\x2e\x34\x32\x30\x31\x2d\x32\x34\x2e\x38\x32\x39\x32\x43\x34\x39\
+\x2e\x33\x35\x36\x34\x2d\x32\x33\x2e\x36\x36\x38\x33\x20\x35\x30\
+\x2e\x30\x33\x30\x35\x2d\x32\x32\x2e\x32\x30\x37\x37\x20\x35\x30\
+\x2e\x34\x34\x32\x34\x2d\x32\x30\x2e\x34\x34\x37\x36\x20\x35\x30\
+\x2e\x38\x35\x34\x34\x2d\x31\x38\x2e\x36\x38\x37\x34\x20\x35\x31\
+\x2e\x30\x36\x30\x34\x2d\x31\x36\x2e\x35\x31\x35\x33\x20\x35\x31\
+\x2e\x30\x36\x30\x34\x2d\x31\x33\x2e\x39\x33\x31\x33\x4c\x35\x31\
+\x2e\x30\x36\x30\x34\x20\x30\x20\x34\x33\x2e\x34\x32\x30\x36\x20\
+\x30\x20\x34\x33\x2e\x34\x32\x30\x36\x2d\x31\x33\x2e\x39\x33\x31\
+\x33\x43\x34\x33\x2e\x34\x32\x30\x36\x2d\x31\x34\x2e\x39\x37\x39\
+\x39\x20\x34\x33\x2e\x33\x38\x33\x32\x2d\x31\x35\x2e\x39\x37\x32\
+\x33\x20\x34\x33\x2e\x33\x30\x38\x33\x2d\x31\x36\x2e\x39\x30\x38\
+\x36\x20\x34\x33\x2e\x32\x37\x30\x38\x2d\x31\x37\x2e\x38\x38\x32\
+\x33\x20\x34\x33\x2e\x30\x38\x33\x36\x2d\x31\x38\x2e\x37\x32\x34\
+\x39\x20\x34\x32\x2e\x37\x34\x36\x35\x2d\x31\x39\x2e\x34\x33\x36\
+\x34\x20\x34\x32\x2e\x34\x30\x39\x35\x2d\x32\x30\x2e\x31\x38\x35\
+\x34\x20\x34\x31\x2e\x38\x36\x36\x34\x2d\x32\x30\x2e\x37\x36\x35\
+\x39\x20\x34\x31\x2e\x31\x31\x37\x34\x2d\x32\x31\x2e\x31\x37\x37\
+\x38\x20\x34\x30\x2e\x33\x36\x38\x34\x2d\x32\x31\x2e\x35\x38\x39\
+\x38\x20\x33\x39\x2e\x33\x30\x31\x31\x2d\x32\x31\x2e\x37\x39\x35\
+\x38\x20\x33\x37\x2e\x39\x31\x35\x35\x2d\x32\x31\x2e\x37\x39\x35\
+\x38\x20\x33\x36\x2e\x36\x30\x34\x37\x2d\x32\x31\x2e\x37\x39\x35\
+\x38\x20\x33\x35\x2e\x33\x38\x37\x36\x2d\x32\x31\x2e\x35\x31\x34\
+\x39\x20\x33\x34\x2e\x32\x36\x34\x31\x2d\x32\x30\x2e\x39\x35\x33\
+\x31\x4c\x33\x34\x2e\x32\x36\x34\x31\x2d\x32\x30\x2e\x38\x39\x37\
+\x20\x33\x34\x2e\x32\x30\x38\x2d\x32\x30\x2e\x39\x35\x33\x31\x20\
+\x33\x31\x2e\x34\x35\x35\x34\x2d\x32\x35\x2e\x38\x34\x30\x33\x20\
+\x33\x31\x2e\x35\x31\x31\x36\x2d\x32\x35\x2e\x38\x39\x36\x35\x43\
+\x33\x33\x2e\x34\x35\x39\x2d\x32\x37\x2e\x36\x35\x36\x37\x20\x33\
+\x35\x2e\x38\x39\x33\x32\x2d\x32\x38\x2e\x35\x33\x36\x37\x20\x33\
+\x38\x2e\x38\x31\x34\x33\x2d\x32\x38\x2e\x35\x33\x36\x37\x20\x34\
+\x33\x2e\x33\x30\x38\x33\x2d\x32\x38\x2e\x35\x33\x36\x37\x20\x34\
+\x36\x2e\x35\x31\x30\x32\x2d\x32\x37\x2e\x33\x30\x30\x39\x20\x34\
+\x38\x2e\x34\x32\x30\x31\x2d\x32\x34\x2e\x38\x32\x39\x32\x5a\x22\
+\x20\x66\x69\x6c\x6c\x3d\x22\x23\x42\x46\x42\x46\x42\x46\x22\x20\
+\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\
+\x78\x28\x31\x20\x30\x20\x30\x20\x31\x2e\x30\x31\x31\x36\x20\x35\
+\x32\x36\x2e\x33\x34\x37\x20\x33\x30\x31\x2e\x31\x37\x29\x22\x2f\
+\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x35\x34\x2e\x31\x34\
+\x39\x39\x20\x30\x20\x35\x34\x2e\x31\x34\x39\x39\x2d\x32\x38\x2e\
+\x30\x38\x37\x33\x20\x36\x31\x2e\x36\x32\x31\x31\x2d\x32\x38\x2e\
+\x30\x38\x37\x33\x20\x36\x31\x2e\x36\x32\x31\x31\x20\x30\x5a\x4d\
+\x35\x34\x2e\x31\x34\x39\x39\x2d\x33\x39\x2e\x33\x32\x32\x33\x20\
+\x36\x31\x2e\x36\x32\x31\x31\x2d\x33\x39\x2e\x33\x32\x32\x33\x20\
+\x36\x31\x2e\x36\x32\x31\x31\x2d\x33\x32\x2e\x37\x34\x39\x38\x20\
+\x35\x34\x2e\x31\x34\x39\x39\x2d\x33\x32\x2e\x37\x34\x39\x38\x5a\
+\x22\x20\x66\x69\x6c\x6c\x3d\x22\x23\x42\x46\x42\x46\x42\x46\x22\
+\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\
+\x69\x78\x28\x31\x20\x30\x20\x30\x20\x31\x2e\x30\x31\x31\x36\x20\
+\x35\x32\x36\x2e\x33\x34\x37\x20\x33\x30\x31\x2e\x31\x37\x29\x22\
+\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x38\x35\x2e\x34\
+\x39\x35\x33\x2d\x31\x30\x2e\x37\x32\x39\x34\x20\x39\x31\x2e\x35\
+\x36\x32\x32\x2d\x36\x2e\x37\x34\x30\x39\x36\x20\x39\x31\x2e\x35\
+\x30\x36\x2d\x36\x2e\x36\x38\x34\x37\x38\x43\x39\x30\x2e\x31\x39\
+\x35\x32\x2d\x34\x2e\x34\x33\x37\x38\x20\x38\x38\x2e\x34\x31\x36\
+\x34\x2d\x32\x2e\x36\x37\x37\x36\x36\x20\x38\x36\x2e\x31\x36\x39\
+\x34\x2d\x31\x2e\x34\x30\x34\x33\x37\x20\x38\x33\x2e\x39\x35\x39\
+\x39\x2d\x30\x2e\x31\x33\x31\x30\x37\x34\x20\x38\x31\x2e\x35\x36\
+\x33\x31\x20\x30\x2e\x35\x30\x35\x35\x37\x32\x20\x37\x38\x2e\x39\
+\x37\x39\x20\x30\x2e\x35\x30\x35\x35\x37\x32\x20\x37\x36\x2e\x39\
+\x35\x36\x37\x20\x30\x2e\x35\x30\x35\x35\x37\x32\x20\x37\x35\x2e\
+\x30\x36\x35\x35\x20\x30\x2e\x31\x33\x31\x30\x37\x34\x20\x37\x33\
+\x2e\x33\x30\x35\x34\x2d\x30\x2e\x36\x31\x37\x39\x32\x31\x20\x37\
+\x31\x2e\x35\x34\x35\x33\x2d\x31\x2e\x34\x30\x34\x33\x37\x20\x37\
+\x30\x2e\x30\x30\x39\x38\x2d\x32\x2e\x34\x35\x32\x39\x36\x20\x36\
+\x38\x2e\x36\x39\x39\x31\x2d\x33\x2e\x37\x36\x33\x37\x20\x36\x37\
+\x2e\x33\x38\x38\x33\x2d\x35\x2e\x30\x37\x34\x34\x34\x20\x36\x36\
+\x2e\x33\x33\x39\x37\x2d\x36\x2e\x36\x30\x39\x38\x38\x20\x36\x35\
+\x2e\x35\x35\x33\x33\x2d\x38\x2e\x33\x37\x30\x30\x32\x20\x36\x34\
+\x2e\x38\x30\x34\x33\x2d\x31\x30\x2e\x31\x33\x30\x32\x20\x36\x34\
+\x2e\x34\x32\x39\x38\x2d\x31\x32\x2e\x30\x30\x32\x36\x20\x36\x34\
+\x2e\x34\x32\x39\x38\x2d\x31\x33\x2e\x39\x38\x37\x35\x20\x36\x34\
+\x2e\x34\x32\x39\x38\x2d\x31\x35\x2e\x39\x37\x32\x33\x20\x36\x34\
+\x2e\x38\x30\x34\x33\x2d\x31\x37\x2e\x38\x34\x34\x38\x20\x36\x35\
+\x2e\x35\x35\x33\x33\x2d\x31\x39\x2e\x36\x30\x34\x39\x20\x36\x36\
+\x2e\x33\x33\x39\x37\x2d\x32\x31\x2e\x33\x36\x35\x31\x20\x36\x37\
+\x2e\x33\x38\x38\x33\x2d\x32\x32\x2e\x39\x30\x30\x35\x20\x36\x38\
+\x2e\x36\x39\x39\x31\x2d\x32\x34\x2e\x32\x31\x31\x33\x20\x37\x30\
+\x2e\x30\x30\x39\x38\x2d\x32\x35\x2e\x35\x32\x32\x20\x37\x31\x2e\
+\x35\x34\x35\x33\x2d\x32\x36\x2e\x35\x35\x31\x39\x20\x37\x33\x2e\
+\x33\x30\x35\x34\x2d\x32\x37\x2e\x33\x30\x30\x39\x20\x37\x35\x2e\
+\x30\x36\x35\x35\x2d\x32\x38\x2e\x30\x38\x37\x33\x20\x37\x36\x2e\
+\x39\x35\x36\x37\x2d\x32\x38\x2e\x34\x38\x30\x35\x20\x37\x38\x2e\
+\x39\x37\x39\x2d\x32\x38\x2e\x34\x38\x30\x35\x20\x38\x31\x2e\x35\
+\x36\x33\x31\x2d\x32\x38\x2e\x34\x38\x30\x35\x20\x38\x33\x2e\x39\
+\x35\x39\x39\x2d\x32\x37\x2e\x38\x34\x33\x39\x20\x38\x36\x2e\x31\
+\x36\x39\x34\x2d\x32\x36\x2e\x35\x37\x30\x36\x20\x38\x38\x2e\x34\
+\x31\x36\x34\x2d\x32\x35\x2e\x32\x39\x37\x33\x20\x39\x30\x2e\x31\
+\x39\x35\x32\x2d\x32\x33\x2e\x35\x33\x37\x32\x20\x39\x31\x2e\x35\
+\x30\x36\x2d\x32\x31\x2e\x32\x39\x30\x32\x4c\x39\x31\x2e\x35\x36\
+\x32\x32\x2d\x32\x31\x2e\x32\x33\x34\x20\x38\x35\x2e\x34\x33\x39\
+\x31\x2d\x31\x37\x2e\x32\x34\x35\x36\x20\x38\x35\x2e\x33\x38\x32\
+\x39\x2d\x31\x37\x2e\x33\x30\x31\x38\x43\x38\x34\x2e\x37\x38\x33\
+\x38\x2d\x31\x38\x2e\x36\x38\x37\x34\x20\x38\x33\x2e\x39\x30\x33\
+\x37\x2d\x31\x39\x2e\x38\x31\x30\x39\x20\x38\x32\x2e\x37\x34\x32\
+\x37\x2d\x32\x30\x2e\x36\x37\x32\x33\x20\x38\x31\x2e\x36\x31\x39\
+\x32\x2d\x32\x31\x2e\x35\x33\x33\x36\x20\x38\x30\x2e\x33\x36\x34\
+\x37\x2d\x32\x31\x2e\x39\x36\x34\x33\x20\x37\x38\x2e\x39\x37\x39\
+\x2d\x32\x31\x2e\x39\x36\x34\x33\x20\x37\x37\x2e\x39\x36\x37\x39\
+\x2d\x32\x31\x2e\x39\x36\x34\x33\x20\x37\x37\x2e\x30\x31\x32\x39\
+\x2d\x32\x31\x2e\x37\x33\x39\x36\x20\x37\x36\x2e\x31\x31\x34\x31\
+\x2d\x32\x31\x2e\x32\x39\x30\x32\x20\x37\x35\x2e\x32\x35\x32\x38\
+\x2d\x32\x30\x2e\x38\x37\x38\x32\x20\x37\x34\x2e\x35\x30\x33\x38\
+\x2d\x32\x30\x2e\x32\x39\x37\x38\x20\x37\x33\x2e\x38\x36\x37\x31\
+\x2d\x31\x39\x2e\x35\x34\x38\x38\x20\x37\x33\x2e\x32\x33\x30\x35\
+\x2d\x31\x38\x2e\x38\x33\x37\x32\x20\x37\x32\x2e\x37\x32\x34\x39\
+\x2d\x31\x37\x2e\x39\x39\x34\x36\x20\x37\x32\x2e\x33\x35\x30\x34\
+\x2d\x31\x37\x2e\x30\x32\x30\x39\x20\x37\x31\x2e\x39\x37\x35\x39\
+\x2d\x31\x36\x2e\x30\x38\x34\x37\x20\x37\x31\x2e\x37\x38\x38\x37\
+\x2d\x31\x35\x2e\x30\x37\x33\x35\x20\x37\x31\x2e\x37\x38\x38\x37\
+\x2d\x31\x33\x2e\x39\x38\x37\x35\x20\x37\x31\x2e\x37\x38\x38\x37\
+\x2d\x31\x32\x2e\x39\x30\x31\x34\x20\x37\x31\x2e\x39\x37\x35\x39\
+\x2d\x31\x31\x2e\x38\x39\x30\x33\x20\x37\x32\x2e\x33\x35\x30\x34\
+\x2d\x31\x30\x2e\x39\x35\x34\x31\x20\x37\x32\x2e\x37\x32\x34\x39\
+\x2d\x31\x30\x2e\x30\x31\x37\x38\x20\x37\x33\x2e\x32\x33\x30\x35\
+\x2d\x39\x2e\x31\x39\x33\x39\x32\x20\x37\x33\x2e\x38\x36\x37\x31\
+\x2d\x38\x2e\x34\x38\x32\x33\x37\x20\x37\x34\x2e\x35\x30\x33\x38\
+\x2d\x37\x2e\x38\x30\x38\x32\x38\x20\x37\x35\x2e\x32\x35\x32\x38\
+\x2d\x37\x2e\x32\x36\x35\x32\x35\x20\x37\x36\x2e\x31\x31\x34\x31\
+\x2d\x36\x2e\x38\x35\x33\x33\x31\x20\x37\x37\x2e\x30\x31\x32\x39\
+\x2d\x36\x2e\x34\x37\x38\x38\x31\x20\x37\x37\x2e\x39\x36\x37\x39\
+\x2d\x36\x2e\x32\x39\x31\x35\x36\x20\x37\x38\x2e\x39\x37\x39\x2d\
+\x36\x2e\x32\x39\x31\x35\x36\x20\x38\x30\x2e\x33\x36\x34\x37\x2d\
+\x36\x2e\x32\x39\x31\x35\x36\x20\x38\x31\x2e\x36\x31\x39\x32\x2d\
+\x36\x2e\x36\x36\x36\x30\x36\x20\x38\x32\x2e\x37\x34\x32\x37\x2d\
+\x37\x2e\x34\x31\x35\x30\x35\x20\x38\x33\x2e\x39\x30\x33\x37\x2d\
+\x38\x2e\x32\x30\x31\x35\x20\x38\x34\x2e\x37\x38\x33\x38\x2d\x39\
+\x2e\x32\x38\x37\x35\x34\x20\x38\x35\x2e\x33\x38\x32\x39\x2d\x31\
+\x30\x2e\x36\x37\x33\x32\x4c\x38\x35\x2e\x34\x33\x39\x31\x2d\x31\
+\x30\x2e\x37\x38\x35\x35\x5a\x22\x20\x66\x69\x6c\x6c\x3d\x22\x23\
+\x42\x46\x42\x46\x42\x46\x22\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\
+\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x31\x20\x30\x20\x30\x20\
+\x31\x2e\x30\x31\x31\x36\x20\x35\x32\x36\x2e\x33\x34\x37\x20\x33\
+\x30\x31\x2e\x31\x37\x29\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\
+\x3d\x22\x4d\x31\x36\x30\x2e\x30\x38\x34\x2d\x33\x39\x2e\x33\x32\
+\x32\x33\x20\x31\x36\x30\x2e\x30\x38\x34\x20\x30\x20\x31\x35\x32\
+\x2e\x36\x31\x33\x20\x30\x20\x31\x35\x32\x2e\x36\x36\x39\x2d\x31\
+\x34\x2e\x30\x39\x39\x38\x43\x31\x35\x32\x2e\x36\x36\x39\x2d\x31\
+\x35\x2e\x31\x34\x38\x34\x20\x31\x35\x32\x2e\x34\x34\x34\x2d\x31\
+\x36\x2e\x31\x34\x30\x38\x20\x31\x35\x31\x2e\x39\x39\x35\x2d\x31\
+\x37\x2e\x30\x37\x37\x31\x20\x31\x35\x31\x2e\x35\x38\x33\x2d\x31\
+\x38\x2e\x30\x31\x33\x33\x20\x31\x35\x31\x2e\x30\x32\x31\x2d\x31\
+\x38\x2e\x38\x31\x38\x35\x20\x31\x35\x30\x2e\x33\x30\x39\x2d\x31\
+\x39\x2e\x34\x39\x32\x36\x20\x31\x34\x39\x2e\x36\x33\x35\x2d\x32\
+\x30\x2e\x32\x30\x34\x31\x20\x31\x34\x38\x2e\x38\x31\x31\x2d\x32\
+\x30\x2e\x37\x34\x37\x32\x20\x31\x34\x37\x2e\x38\x33\x38\x2d\x32\
+\x31\x2e\x31\x32\x31\x37\x20\x31\x34\x36\x2e\x39\x30\x31\x2d\x32\
+\x31\x2e\x35\x33\x33\x36\x20\x31\x34\x35\x2e\x38\x39\x2d\x32\x31\
+\x2e\x37\x33\x39\x36\x20\x31\x34\x34\x2e\x38\x30\x34\x2d\x32\x31\
+\x2e\x37\x33\x39\x36\x20\x31\x34\x33\x2e\x37\x31\x38\x2d\x32\x31\
+\x2e\x37\x33\x39\x36\x20\x31\x34\x32\x2e\x37\x30\x37\x2d\x32\x31\
+\x2e\x35\x33\x33\x36\x20\x31\x34\x31\x2e\x37\x37\x31\x2d\x32\x31\
+\x2e\x31\x32\x31\x37\x20\x31\x34\x30\x2e\x38\x33\x35\x2d\x32\x30\
+\x2e\x37\x34\x37\x32\x20\x31\x34\x30\x2e\x30\x31\x31\x2d\x32\x30\
+\x2e\x32\x30\x34\x31\x20\x31\x33\x39\x2e\x32\x39\x39\x2d\x31\x39\
+\x2e\x34\x39\x32\x36\x20\x31\x33\x38\x2e\x36\x32\x35\x2d\x31\x38\
+\x2e\x37\x38\x31\x31\x20\x31\x33\x38\x2e\x30\x38\x32\x2d\x31\x37\
+\x2e\x39\x35\x37\x32\x20\x31\x33\x37\x2e\x36\x37\x2d\x31\x37\x2e\
+\x30\x32\x30\x39\x20\x31\x33\x37\x2e\x32\x35\x38\x2d\x31\x36\x2e\
+\x30\x38\x34\x37\x20\x31\x33\x37\x2e\x30\x35\x32\x2d\x31\x35\x2e\
+\x30\x37\x33\x35\x20\x31\x33\x37\x2e\x30\x35\x32\x2d\x31\x33\x2e\
+\x39\x38\x37\x35\x20\x31\x33\x37\x2e\x30\x35\x32\x2d\x31\x32\x2e\
+\x39\x30\x31\x34\x20\x31\x33\x37\x2e\x32\x35\x38\x2d\x31\x31\x2e\
+\x38\x39\x30\x33\x20\x31\x33\x37\x2e\x36\x37\x2d\x31\x30\x2e\x39\
+\x35\x34\x31\x20\x31\x33\x38\x2e\x30\x38\x32\x2d\x31\x30\x2e\x30\
+\x31\x37\x38\x20\x31\x33\x38\x2e\x36\x32\x35\x2d\x39\x2e\x31\x39\
+\x33\x39\x32\x20\x31\x33\x39\x2e\x32\x39\x39\x2d\x38\x2e\x34\x38\
+\x32\x33\x37\x20\x31\x34\x30\x2e\x30\x31\x31\x2d\x37\x2e\x38\x30\
+\x38\x32\x38\x20\x31\x34\x30\x2e\x38\x33\x35\x2d\x37\x2e\x32\x36\
+\x35\x32\x35\x20\x31\x34\x31\x2e\x37\x37\x31\x2d\x36\x2e\x38\x35\
+\x33\x33\x31\x20\x31\x34\x32\x2e\x37\x30\x37\x2d\x36\x2e\x34\x34\
+\x31\x33\x36\x20\x31\x34\x33\x2e\x37\x31\x38\x2d\x36\x2e\x32\x33\
+\x35\x33\x39\x20\x31\x34\x34\x2e\x38\x30\x34\x2d\x36\x2e\x32\x33\
+\x35\x33\x39\x20\x31\x34\x35\x2e\x33\x32\x39\x2d\x36\x2e\x32\x33\
+\x35\x33\x39\x20\x31\x34\x35\x2e\x38\x35\x33\x2d\x36\x2e\x32\x37\
+\x32\x38\x34\x20\x31\x34\x36\x2e\x33\x37\x37\x2d\x36\x2e\x33\x34\
+\x37\x37\x33\x20\x31\x34\x36\x2e\x39\x30\x31\x2d\x36\x2e\x34\x32\
+\x32\x36\x33\x20\x31\x34\x37\x2e\x33\x38\x38\x2d\x36\x2e\x35\x37\
+\x32\x34\x33\x20\x31\x34\x37\x2e\x38\x33\x38\x2d\x36\x2e\x37\x39\
+\x37\x31\x33\x4c\x31\x34\x37\x2e\x38\x39\x34\x2d\x36\x2e\x37\x39\
+\x37\x31\x33\x20\x31\x34\x37\x2e\x39\x35\x2d\x36\x2e\x37\x39\x37\
+\x31\x33\x20\x31\x35\x30\x2e\x37\x30\x33\x2d\x31\x2e\x37\x34\x31\
+\x34\x31\x20\x31\x35\x30\x2e\x36\x34\x36\x2d\x31\x2e\x36\x38\x35\
+\x32\x34\x43\x31\x34\x38\x2e\x38\x31\x31\x2d\x30\x2e\x32\x36\x32\
+\x31\x34\x38\x20\x31\x34\x36\x2e\x35\x36\x34\x20\x30\x2e\x34\x34\
+\x39\x33\x39\x37\x20\x31\x34\x33\x2e\x39\x30\x35\x20\x30\x2e\x34\
+\x34\x39\x33\x39\x37\x20\x31\x34\x31\x2e\x38\x38\x33\x20\x30\x2e\
+\x34\x34\x39\x33\x39\x37\x20\x31\x33\x39\x2e\x39\x39\x32\x20\x30\
+\x2e\x30\x37\x34\x38\x39\x39\x35\x20\x31\x33\x38\x2e\x32\x33\x32\
+\x2d\x30\x2e\x36\x37\x34\x30\x39\x36\x20\x31\x33\x36\x2e\x34\x37\
+\x32\x2d\x31\x2e\x34\x32\x33\x30\x39\x20\x31\x33\x34\x2e\x39\x33\
+\x36\x2d\x32\x2e\x34\x35\x32\x39\x36\x20\x31\x33\x33\x2e\x36\x32\
+\x36\x2d\x33\x2e\x37\x36\x33\x37\x20\x31\x33\x32\x2e\x33\x31\x35\
+\x2d\x35\x2e\x30\x37\x34\x34\x34\x20\x31\x33\x31\x2e\x32\x36\x36\
+\x2d\x36\x2e\x36\x30\x39\x38\x38\x20\x31\x33\x30\x2e\x34\x38\x2d\
+\x38\x2e\x33\x37\x30\x30\x32\x20\x31\x32\x39\x2e\x37\x33\x31\x2d\
+\x31\x30\x2e\x31\x33\x30\x32\x20\x31\x32\x39\x2e\x33\x35\x36\x2d\
+\x31\x32\x2e\x30\x30\x32\x36\x20\x31\x32\x39\x2e\x33\x35\x36\x2d\
+\x31\x33\x2e\x39\x38\x37\x35\x20\x31\x32\x39\x2e\x33\x35\x36\x2d\
+\x31\x35\x2e\x39\x37\x32\x33\x20\x31\x32\x39\x2e\x37\x33\x31\x2d\
+\x31\x37\x2e\x38\x34\x34\x38\x20\x31\x33\x30\x2e\x34\x38\x2d\x31\
+\x39\x2e\x36\x30\x34\x39\x20\x31\x33\x31\x2e\x32\x36\x36\x2d\x32\
+\x31\x2e\x33\x36\x35\x31\x20\x31\x33\x32\x2e\x33\x31\x35\x2d\x32\
+\x32\x2e\x39\x30\x30\x35\x20\x31\x33\x33\x2e\x36\x32\x36\x2d\x32\
+\x34\x2e\x32\x31\x31\x33\x20\x31\x33\x34\x2e\x39\x33\x36\x2d\x32\
+\x35\x2e\x35\x32\x32\x20\x31\x33\x36\x2e\x34\x37\x32\x2d\x32\x36\
+\x2e\x35\x35\x31\x39\x20\x31\x33\x38\x2e\x32\x33\x32\x2d\x32\x37\
+\x2e\x33\x30\x30\x39\x20\x31\x33\x39\x2e\x39\x39\x32\x2d\x32\x38\
+\x2e\x30\x34\x39\x39\x20\x31\x34\x31\x2e\x38\x38\x33\x2d\x32\x38\
+\x2e\x34\x32\x34\x34\x20\x31\x34\x33\x2e\x39\x30\x35\x2d\x32\x38\
+\x2e\x34\x32\x34\x34\x20\x31\x34\x37\x2e\x37\x32\x35\x2d\x32\x38\
+\x2e\x34\x32\x34\x34\x20\x31\x35\x30\x2e\x36\x34\x36\x2d\x32\x37\
+\x2e\x30\x30\x31\x33\x20\x31\x35\x32\x2e\x36\x36\x39\x2d\x32\x34\
+\x2e\x31\x35\x35\x31\x4c\x31\x35\x32\x2e\x36\x36\x39\x2d\x33\x39\
+\x2e\x33\x32\x32\x33\x5a\x22\x20\x66\x69\x6c\x6c\x3d\x22\x23\x42\
+\x46\x42\x46\x42\x46\x22\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\
+\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x31\x20\x30\x20\x30\x20\x31\
+\x2e\x30\x31\x31\x36\x20\x35\x32\x36\x2e\x33\x34\x37\x20\x33\x30\
+\x31\x2e\x31\x37\x29\x22\x2f\x3e\x3c\x2f\x67\x3e\x3c\x2f\x67\x3e\
+\x3c\x2f\x67\x3e\x3c\x2f\x73\x76\x67\x3e\
+\x00\x00\x21\x27\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\
+\x2d\x38\x22\x3f\x3e\x0a\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\
+\x3d\x22\x32\x35\x6d\x6d\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\
+\x31\x30\x38\x6d\x6d\x22\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\
+\x31\x2e\x31\x22\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\
+\x30\x20\x32\x35\x20\x31\x30\x38\x22\x20\x78\x6d\x6c\x6e\x73\x3d\
+\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\
+\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\
+\x6e\x73\x3a\x63\x63\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\
+\x65\x61\x74\x69\x76\x65\x63\x6f\x6d\x6d\x6f\x6e\x73\x2e\x6f\x72\
+\x67\x2f\x6e\x73\x23\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x64\x63\x3d\
+\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\x67\
+\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\x2e\x31\
+\x2f\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\
+\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\
+\x31\x39\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\
+\x79\x6e\x74\x61\x78\x2d\x6e\x73\x23\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\
+\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x78\
+\x6c\x69\x6e\x6b\x22\x3e\x0a\x20\x3c\x64\x65\x66\x73\x3e\x0a\x20\
+\x20\x3c\x63\x6c\x69\x70\x50\x61\x74\x68\x3e\x0a\x20\x20\x20\x3c\
+\x72\x65\x63\x74\x20\x78\x3d\x22\x2d\x31\x34\x31\x22\x20\x79\x3d\
+\x22\x2d\x38\x32\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x31\x33\x30\
+\x30\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x36\x39\x22\x2f\
+\x3e\x0a\x20\x20\x3c\x2f\x63\x6c\x69\x70\x50\x61\x74\x68\x3e\x0a\
+\x20\x20\x3c\x63\x6c\x69\x70\x50\x61\x74\x68\x20\x69\x64\x3d\x22\
+\x63\x6c\x69\x70\x30\x2d\x33\x22\x3e\x0a\x20\x20\x20\x3c\x72\x65\
+\x63\x74\x20\x78\x3d\x22\x2d\x31\x34\x31\x22\x20\x79\x3d\x22\x2d\
+\x38\x32\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x31\x33\x30\x30\x22\
+\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x36\x39\x22\x2f\x3e\x0a\
+\x20\x20\x3c\x2f\x63\x6c\x69\x70\x50\x61\x74\x68\x3e\x0a\x20\x20\
+\x3c\x63\x6c\x69\x70\x50\x61\x74\x68\x20\x69\x64\x3d\x22\x63\x6c\
+\x69\x70\x31\x35\x2d\x30\x39\x22\x3e\x0a\x20\x20\x20\x3c\x72\x65\
+\x63\x74\x20\x78\x3d\x22\x39\x37\x33\x22\x20\x79\x3d\x22\x31\x36\
+\x34\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x31\x35\x38\x22\x20\x68\
+\x65\x69\x67\x68\x74\x3d\x22\x31\x35\x38\x22\x2f\x3e\x0a\x20\x20\
+\x3c\x2f\x63\x6c\x69\x70\x50\x61\x74\x68\x3e\x0a\x20\x20\x3c\x63\
+\x6c\x69\x70\x50\x61\x74\x68\x20\x69\x64\x3d\x22\x63\x6c\x69\x70\
+\x31\x36\x2d\x31\x22\x3e\x0a\x20\x20\x20\x3c\x72\x65\x63\x74\x20\
+\x78\x3d\x22\x39\x37\x33\x22\x20\x79\x3d\x22\x31\x36\x34\x22\x20\
+\x77\x69\x64\x74\x68\x3d\x22\x31\x35\x38\x22\x20\x68\x65\x69\x67\
+\x68\x74\x3d\x22\x31\x35\x38\x22\x2f\x3e\x0a\x20\x20\x3c\x2f\x63\
+\x6c\x69\x70\x50\x61\x74\x68\x3e\x0a\x20\x20\x3c\x63\x6c\x69\x70\
+\x50\x61\x74\x68\x20\x69\x64\x3d\x22\x63\x6c\x69\x70\x31\x37\x2d\
+\x38\x39\x22\x3e\x0a\x20\x20\x20\x3c\x72\x65\x63\x74\x20\x78\x3d\
+\x22\x39\x37\x33\x22\x20\x79\x3d\x22\x31\x36\x34\x22\x20\x77\x69\
+\x64\x74\x68\x3d\x22\x31\x35\x38\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x31\x35\x38\x22\x2f\x3e\x0a\x20\x20\x3c\x2f\x63\x6c\x69\
+\x70\x50\x61\x74\x68\x3e\x0a\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\
+\x47\x72\x61\x64\x69\x65\x6e\x74\x20\x69\x64\x3d\x22\x6c\x69\x6e\
+\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x32\x38\x34\x22\
+\x20\x78\x31\x3d\x22\x31\x38\x33\x2e\x35\x36\x22\x20\x78\x32\x3d\
+\x22\x31\x32\x37\x2e\x36\x32\x22\x20\x79\x31\x3d\x22\x31\x36\x31\
+\x2e\x30\x38\x22\x20\x79\x32\x3d\x22\x31\x30\x30\x2e\x32\x33\x22\
+\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\x72\x61\x6e\x73\x66\x6f\
+\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x34\x32\
+\x34\x2e\x39\x20\x35\x35\x32\x2e\x30\x38\x29\x22\x20\x67\x72\x61\
+\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\
+\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\x22\x3e\x0a\x20\x20\x20\
+\x3c\x73\x74\x6f\x70\x20\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\
+\x3d\x22\x23\x33\x30\x37\x30\x62\x33\x22\x20\x6f\x66\x66\x73\x65\
+\x74\x3d\x22\x30\x22\x2f\x3e\x0a\x20\x20\x20\x3c\x73\x74\x6f\x70\
+\x20\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x38\x36\
+\x62\x31\x64\x66\x22\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\x22\
+\x2f\x3e\x0a\x20\x20\x3c\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\
+\x64\x69\x65\x6e\x74\x3e\x0a\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\
+\x47\x72\x61\x64\x69\x65\x6e\x74\x20\x69\x64\x3d\x22\x6c\x69\x6e\
+\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x31\x31\x38\x39\x2d\
+\x30\x2d\x36\x2d\x32\x22\x20\x78\x31\x3d\x22\x31\x37\x32\x2e\x35\
+\x35\x22\x20\x78\x32\x3d\x22\x31\x30\x34\x2e\x35\x31\x22\x20\x79\
+\x31\x3d\x22\x31\x32\x31\x2e\x37\x31\x22\x20\x79\x32\x3d\x22\x38\
+\x35\x2e\x36\x31\x35\x22\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\
+\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\
+\x61\x74\x65\x28\x36\x2e\x31\x30\x32\x35\x20\x2d\x32\x36\x2e\x39\
+\x37\x38\x29\x22\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\
+\x74\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\
+\x73\x65\x22\x3e\x0a\x20\x20\x20\x3c\x73\x74\x6f\x70\x20\x73\x74\
+\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x65\x61\x37\x62\x39\
+\x30\x22\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\x22\x2f\x3e\x0a\
+\x20\x20\x20\x3c\x73\x74\x6f\x70\x20\x73\x74\x6f\x70\x2d\x63\x6f\
+\x6c\x6f\x72\x3d\x22\x23\x62\x65\x31\x65\x33\x63\x22\x20\x6f\x66\
+\x66\x73\x65\x74\x3d\x22\x31\x22\x2f\x3e\x0a\x20\x20\x3c\x2f\x6c\
+\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\x20\
+\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\
+\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\
+\x65\x6e\x74\x39\x36\x37\x2d\x32\x2d\x36\x2d\x34\x2d\x36\x22\x20\
+\x78\x31\x3d\x22\x31\x33\x38\x2e\x33\x34\x22\x20\x78\x32\x3d\x22\
+\x36\x36\x2e\x33\x33\x35\x22\x20\x79\x31\x3d\x22\x31\x32\x32\x2e\
+\x34\x36\x22\x20\x79\x32\x3d\x22\x31\x39\x34\x2e\x34\x37\x22\x20\
+\x67\x72\x61\x64\x69\x65\x6e\x74\x54\x72\x61\x6e\x73\x66\x6f\x72\
+\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x36\x2e\x31\
+\x30\x32\x35\x20\x2d\x32\x36\x2e\x39\x37\x38\x29\x22\x20\x67\x72\
+\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\
+\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\x22\x3e\x0a\x20\x20\
+\x20\x3c\x73\x74\x6f\x70\x20\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\
+\x72\x3d\x22\x23\x36\x63\x36\x63\x36\x63\x22\x20\x6f\x66\x66\x73\
+\x65\x74\x3d\x22\x30\x22\x2f\x3e\x0a\x20\x20\x20\x3c\x73\x74\x6f\
+\x70\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x2f\x3e\x0a\x20\
+\x20\x3c\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\
+\x74\x3e\x0a\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\
+\x69\x65\x6e\x74\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\
+\x72\x61\x64\x69\x65\x6e\x74\x31\x30\x33\x33\x2d\x37\x2d\x31\x2d\
+\x30\x22\x20\x78\x31\x3d\x22\x31\x30\x37\x2e\x39\x31\x22\x20\x78\
+\x32\x3d\x22\x31\x32\x2e\x32\x33\x22\x20\x79\x31\x3d\x22\x31\x36\
+\x36\x2e\x38\x38\x22\x20\x79\x32\x3d\x22\x31\x38\x36\x2e\x36\x35\
+\x22\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\x72\x61\x6e\x73\x66\
+\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x36\
+\x2e\x31\x30\x32\x35\x20\x2d\x32\x36\x2e\x39\x37\x38\x29\x22\x20\
+\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\
+\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\x22\x3e\x0a\
+\x20\x20\x20\x3c\x73\x74\x6f\x70\x20\x73\x74\x6f\x70\x2d\x63\x6f\
+\x6c\x6f\x72\x3d\x22\x23\x30\x30\x34\x32\x37\x64\x22\x20\x6f\x66\
+\x66\x73\x65\x74\x3d\x22\x30\x22\x2f\x3e\x0a\x20\x20\x20\x3c\x73\
+\x74\x6f\x70\x20\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3d\x22\
+\x23\x30\x30\x37\x64\x65\x63\x22\x20\x6f\x66\x66\x73\x65\x74\x3d\
+\x22\x31\x22\x2f\x3e\x0a\x20\x20\x3c\x2f\x6c\x69\x6e\x65\x61\x72\
+\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\x20\x20\x3c\x6c\x69\x6e\
+\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x20\x69\x64\x3d\x22\
+\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x31\x36\
+\x37\x31\x2d\x37\x2d\x35\x22\x20\x78\x31\x3d\x22\x33\x34\x2e\x36\
+\x38\x35\x22\x20\x78\x32\x3d\x22\x38\x32\x2e\x38\x35\x34\x22\x20\
+\x79\x31\x3d\x22\x39\x38\x2e\x36\x39\x35\x22\x20\x79\x32\x3d\x22\
+\x31\x36\x33\x2e\x33\x22\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\
+\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\
+\x61\x74\x65\x28\x36\x2e\x31\x30\x32\x35\x20\x2d\x32\x36\x2e\x39\
+\x37\x38\x29\x22\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\
+\x74\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\
+\x73\x65\x22\x3e\x0a\x20\x20\x20\x3c\x73\x74\x6f\x70\x20\x73\x74\
+\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x65\x32\x30\x65\x31\
+\x66\x22\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\x22\x2f\x3e\x0a\
+\x20\x20\x20\x3c\x73\x74\x6f\x70\x20\x73\x74\x6f\x70\x2d\x63\x6f\
+\x6c\x6f\x72\x3d\x22\x23\x66\x32\x34\x36\x35\x37\x22\x20\x6f\x66\
+\x66\x73\x65\x74\x3d\x22\x31\x22\x2f\x3e\x0a\x20\x20\x3c\x2f\x6c\
+\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\x20\
+\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\
+\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\
+\x65\x6e\x74\x32\x39\x39\x38\x2d\x33\x22\x20\x78\x31\x3d\x22\x36\
+\x30\x2e\x31\x22\x20\x78\x32\x3d\x22\x31\x32\x31\x2e\x32\x39\x22\
+\x20\x79\x31\x3d\x22\x39\x32\x2e\x31\x35\x31\x22\x20\x79\x32\x3d\
+\x22\x34\x36\x2e\x30\x39\x31\x22\x20\x67\x72\x61\x64\x69\x65\x6e\
+\x74\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\
+\x73\x6c\x61\x74\x65\x28\x36\x2e\x31\x30\x32\x35\x20\x2d\x32\x36\
+\x2e\x39\x37\x38\x29\x22\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\
+\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\
+\x6e\x55\x73\x65\x22\x3e\x0a\x20\x20\x20\x3c\x73\x74\x6f\x70\x20\
+\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x37\x36\x64\
+\x62\x65\x36\x22\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\x22\x2f\
+\x3e\x0a\x20\x20\x20\x3c\x73\x74\x6f\x70\x20\x73\x74\x6f\x70\x2d\
+\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x32\x30\x61\x31\x62\x31\x22\x20\
+\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x2f\x3e\x0a\x20\x20\x3c\
+\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\
+\x0a\x20\x20\x3c\x66\x69\x6c\x74\x65\x72\x20\x69\x64\x3d\x22\x66\
+\x69\x6c\x74\x65\x72\x33\x37\x32\x33\x2d\x39\x2d\x37\x2d\x38\x2d\
+\x33\x2d\x33\x2d\x30\x22\x20\x78\x3d\x22\x2d\x34\x2e\x35\x32\x34\
+\x31\x65\x2d\x35\x22\x20\x79\x3d\x22\x2d\x34\x2e\x31\x33\x33\x35\
+\x65\x2d\x35\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x31\x2e\x30\x30\
+\x30\x31\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x31\x2e\x30\x30\
+\x30\x31\x22\x20\x63\x6f\x6c\x6f\x72\x2d\x69\x6e\x74\x65\x72\x70\
+\x6f\x6c\x61\x74\x69\x6f\x6e\x2d\x66\x69\x6c\x74\x65\x72\x73\x3d\
+\x22\x73\x52\x47\x42\x22\x3e\x0a\x20\x20\x20\x3c\x66\x65\x47\x61\
+\x75\x73\x73\x69\x61\x6e\x42\x6c\x75\x72\x20\x73\x74\x64\x44\x65\
+\x76\x69\x61\x74\x69\x6f\x6e\x3d\x22\x30\x2e\x30\x30\x31\x33\x38\
+\x37\x37\x34\x30\x35\x22\x2f\x3e\x0a\x20\x20\x3c\x2f\x66\x69\x6c\
+\x74\x65\x72\x3e\x0a\x20\x3c\x2f\x64\x65\x66\x73\x3e\x0a\x20\x3c\
+\x6d\x65\x74\x61\x64\x61\x74\x61\x3e\x0a\x20\x20\x3c\x72\x64\x66\
+\x3a\x52\x44\x46\x3e\x0a\x20\x20\x20\x3c\x63\x63\x3a\x57\x6f\x72\
+\x6b\x20\x72\x64\x66\x3a\x61\x62\x6f\x75\x74\x3d\x22\x22\x3e\x0a\
+\x20\x20\x20\x20\x3c\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x69\
+\x6d\x61\x67\x65\x2f\x73\x76\x67\x2b\x78\x6d\x6c\x3c\x2f\x64\x63\
+\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x0a\x20\x20\x20\x20\x3c\x64\x63\
+\x3a\x74\x79\x70\x65\x20\x72\x64\x66\x3a\x72\x65\x73\x6f\x75\x72\
+\x63\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\
+\x6f\x72\x67\x2f\x64\x63\x2f\x64\x63\x6d\x69\x74\x79\x70\x65\x2f\
+\x53\x74\x69\x6c\x6c\x49\x6d\x61\x67\x65\x22\x2f\x3e\x0a\x20\x20\
+\x20\x20\x3c\x64\x63\x3a\x74\x69\x74\x6c\x65\x2f\x3e\x0a\x20\x20\
+\x20\x3c\x2f\x63\x63\x3a\x57\x6f\x72\x6b\x3e\x0a\x20\x20\x3c\x2f\
+\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\x3c\x2f\x6d\x65\x74\x61\
+\x64\x61\x74\x61\x3e\x0a\x20\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\
+\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x2e\x32\x36\x34\
+\x35\x38\x20\x30\x20\x30\x20\x2e\x32\x36\x34\x35\x38\x20\x2d\x39\
+\x2e\x38\x38\x37\x34\x20\x2d\x32\x30\x2e\x32\x35\x38\x29\x22\x20\
+\x63\x6c\x69\x70\x2d\x70\x61\x74\x68\x3d\x22\x75\x72\x6c\x28\x23\
+\x63\x6c\x69\x70\x30\x2d\x33\x29\x22\x3e\x0a\x20\x20\x3c\x67\x20\
+\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\
+\x6c\x61\x74\x65\x28\x35\x38\x30\x20\x33\x33\x30\x29\x22\x3e\x0a\
+\x20\x20\x20\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\
+\x22\x6d\x61\x74\x72\x69\x78\x28\x2e\x30\x30\x32\x32\x34\x34\x20\
+\x2d\x2e\x33\x37\x30\x35\x39\x20\x2e\x33\x36\x34\x34\x31\x20\x2e\
+\x30\x30\x32\x32\x38\x32\x20\x2d\x35\x37\x32\x2e\x32\x38\x20\x31\
+\x37\x31\x2e\x33\x38\x29\x22\x3e\x0a\x20\x20\x20\x20\x3c\x67\x20\
+\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\
+\x78\x28\x31\x2e\x31\x33\x39\x20\x30\x20\x30\x20\x31\x2e\x31\x33\
+\x39\x20\x35\x35\x37\x2e\x32\x35\x20\x31\x32\x35\x2e\x39\x29\x22\
+\x3e\x0a\x20\x20\x20\x20\x20\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\
+\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x2d\
+\x2e\x37\x38\x32\x36\x38\x20\x2d\x35\x34\x36\x2e\x33\x33\x29\x22\
+\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x67\x20\x74\x72\x61\x6e\x73\
+\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\
+\x2d\x34\x31\x38\x2e\x30\x31\x20\x2d\x33\x32\x2e\x37\x33\x31\x29\
+\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x20\
+\x64\x3d\x22\x6d\x35\x35\x32\x2e\x35\x32\x20\x36\x35\x32\x2e\x33\
+\x31\x73\x35\x36\x2e\x36\x32\x32\x20\x31\x38\x2e\x30\x32\x32\x20\
+\x35\x35\x2e\x37\x32\x36\x20\x35\x39\x2e\x37\x33\x35\x63\x2d\x30\
+\x2e\x38\x36\x39\x32\x34\x20\x34\x30\x2e\x34\x34\x36\x2d\x35\x30\
+\x2e\x37\x38\x31\x20\x32\x36\x2e\x30\x35\x39\x2d\x35\x30\x2e\x37\
+\x38\x31\x20\x32\x36\x2e\x30\x35\x39\x73\x32\x37\x2e\x32\x38\x34\
+\x20\x31\x2e\x37\x34\x20\x32\x38\x2e\x31\x37\x34\x2d\x32\x35\x2e\
+\x35\x30\x31\x63\x30\x2e\x38\x33\x30\x36\x32\x2d\x32\x35\x2e\x34\
+\x32\x32\x2d\x33\x33\x2e\x31\x31\x38\x2d\x36\x30\x2e\x32\x39\x32\
+\x2d\x33\x33\x2e\x31\x31\x38\x2d\x36\x30\x2e\x32\x39\x32\x7a\x22\
+\x20\x66\x69\x6c\x6c\x3d\x22\x75\x72\x6c\x28\x23\x6c\x69\x6e\x65\
+\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x32\x38\x34\x29\x22\
+\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x33\x64\x36\x65\x61\x32\
+\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\
+\x3d\x22\x2e\x39\x38\x30\x33\x39\x22\x20\x73\x74\x72\x6f\x6b\x65\
+\x2d\x77\x69\x64\x74\x68\x3d\x22\x2e\x32\x36\x34\x35\x38\x70\x78\
+\x22\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x2f\x67\x3e\x0a\x20\
+\x20\x20\x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\x20\x20\x20\x3c\x67\
+\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x2e\
+\x32\x36\x34\x35\x38\x70\x78\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\
+\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x6d\x38\x30\x2e\x39\x34\x32\
+\x20\x36\x39\x2e\x35\x39\x35\x73\x32\x30\x2e\x36\x36\x2d\x33\x30\
+\x2e\x39\x32\x20\x35\x37\x2e\x32\x36\x33\x2d\x32\x32\x2e\x34\x39\
+\x63\x33\x39\x2e\x36\x38\x36\x20\x39\x2e\x31\x33\x39\x39\x20\x34\
+\x30\x2e\x34\x34\x33\x20\x34\x37\x2e\x36\x32\x35\x20\x34\x30\x2e\
+\x34\x34\x33\x20\x34\x37\x2e\x36\x32\x35\x73\x2d\x33\x30\x2e\x30\
+\x39\x33\x2d\x32\x34\x2e\x36\x31\x32\x2d\x34\x38\x2e\x33\x38\x31\
+\x2d\x32\x38\x2e\x39\x31\x35\x63\x2d\x31\x36\x2e\x30\x35\x32\x2d\
+\x33\x2e\x37\x37\x37\x32\x2d\x34\x39\x2e\x33\x32\x36\x20\x33\x2e\
+\x37\x37\x39\x38\x2d\x34\x39\x2e\x33\x32\x36\x20\x33\x2e\x37\x37\
+\x39\x38\x7a\x22\x20\x66\x69\x6c\x6c\x3d\x22\x75\x72\x6c\x28\x23\
+\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x31\x31\
+\x38\x39\x2d\x30\x2d\x36\x2d\x32\x29\x22\x20\x73\x74\x72\x6f\x6b\
+\x65\x3d\x22\x23\x63\x37\x33\x31\x34\x66\x22\x20\x73\x74\x72\x6f\
+\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x2e\x39\x35\x32\
+\x39\x34\x22\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x70\x61\x74\
+\x68\x20\x64\x3d\x22\x6d\x31\x34\x34\x2e\x34\x34\x20\x39\x35\x2e\
+\x34\x38\x37\x73\x31\x36\x2e\x33\x36\x32\x20\x33\x31\x2e\x32\x33\
+\x33\x2d\x36\x2e\x32\x33\x36\x36\x20\x35\x37\x2e\x34\x35\x32\x63\
+\x2d\x32\x38\x2e\x31\x37\x32\x20\x33\x32\x2e\x36\x38\x35\x2d\x36\
+\x35\x2e\x37\x36\x38\x20\x31\x34\x2e\x35\x35\x32\x2d\x36\x35\x2e\
+\x37\x36\x38\x20\x31\x34\x2e\x35\x35\x32\x73\x33\x30\x2e\x34\x32\
+\x36\x2d\x36\x2e\x39\x35\x38\x34\x20\x35\x30\x2e\x32\x37\x31\x2d\
+\x32\x38\x2e\x35\x33\x37\x63\x31\x34\x2e\x34\x39\x2d\x31\x35\x2e\
+\x37\x35\x36\x20\x32\x31\x2e\x37\x33\x34\x2d\x34\x33\x2e\x34\x36\
+\x37\x20\x32\x31\x2e\x37\x33\x34\x2d\x34\x33\x2e\x34\x36\x37\x7a\
+\x22\x20\x66\x69\x6c\x6c\x3d\x22\x75\x72\x6c\x28\x23\x6c\x69\x6e\
+\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x39\x36\x37\x2d\x32\
+\x2d\x36\x2d\x34\x2d\x36\x29\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\
+\x22\x23\x31\x36\x31\x36\x31\x36\x22\x2f\x3e\x0a\x20\x20\x20\x20\
+\x20\x20\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x6d\x31\x31\x34\x2e\
+\x30\x31\x20\x31\x33\x39\x2e\x39\x73\x2d\x34\x37\x2e\x36\x37\x38\
+\x20\x34\x31\x2e\x37\x39\x31\x2d\x38\x35\x2e\x39\x39\x20\x31\x32\
+\x2e\x36\x36\x32\x63\x2d\x32\x30\x2e\x39\x39\x33\x2d\x31\x35\x2e\
+\x39\x36\x31\x20\x39\x2e\x34\x34\x39\x34\x2d\x35\x31\x2e\x30\x32\
+\x37\x20\x39\x2e\x34\x34\x39\x34\x2d\x35\x31\x2e\x30\x32\x37\x73\
+\x2d\x31\x35\x2e\x39\x37\x38\x20\x32\x33\x2e\x38\x39\x33\x20\x31\
+\x30\x2e\x35\x38\x33\x20\x33\x37\x2e\x36\x30\x39\x63\x31\x39\x2e\
+\x32\x35\x36\x20\x39\x2e\x39\x34\x33\x32\x20\x36\x35\x2e\x39\x35\
+\x37\x20\x30\x2e\x37\x35\x35\x39\x36\x20\x36\x35\x2e\x39\x35\x37\
+\x20\x30\x2e\x37\x35\x35\x39\x36\x7a\x22\x20\x66\x69\x6c\x6c\x3d\
+\x22\x75\x72\x6c\x28\x23\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\
+\x69\x65\x6e\x74\x31\x30\x33\x33\x2d\x37\x2d\x31\x2d\x30\x29\x22\
+\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x34\x34\x34\x22\x2f\x3e\
+\x0a\x20\x20\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\
+\x6d\x36\x33\x2e\x30\x33\x31\x20\x33\x39\x2e\x38\x34\x73\x2d\x38\
+\x2e\x32\x36\x30\x38\x20\x32\x30\x2e\x33\x31\x33\x2d\x31\x2e\x33\
+\x33\x36\x34\x20\x35\x32\x2e\x33\x38\x35\x63\x35\x2e\x32\x35\x37\
+\x36\x20\x32\x34\x2e\x33\x35\x32\x20\x32\x37\x2e\x32\x36\x31\x20\
+\x34\x34\x2e\x30\x39\x39\x20\x32\x37\x2e\x32\x36\x31\x20\x34\x34\
+\x2e\x30\x39\x39\x73\x2d\x33\x39\x2e\x35\x31\x39\x2d\x30\x2e\x38\
+\x31\x37\x35\x36\x2d\x34\x38\x2e\x33\x37\x36\x2d\x34\x31\x2e\x36\
+\x39\x34\x63\x2d\x37\x2e\x33\x37\x36\x34\x2d\x33\x34\x2e\x30\x34\
+\x34\x20\x32\x32\x2e\x34\x35\x31\x2d\x35\x34\x2e\x37\x39\x20\x32\
+\x32\x2e\x34\x35\x31\x2d\x35\x34\x2e\x37\x39\x7a\x22\x20\x66\x69\
+\x6c\x6c\x3d\x22\x75\x72\x6c\x28\x23\x6c\x69\x6e\x65\x61\x72\x47\
+\x72\x61\x64\x69\x65\x6e\x74\x31\x36\x37\x31\x2d\x37\x2d\x35\x29\
+\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x65\x33\x30\x65\x31\
+\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\
+\x79\x3d\x22\x2e\x39\x38\x34\x33\x31\x22\x2f\x3e\x0a\x20\x20\x20\
+\x20\x20\x20\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x6d\x31\x33\x38\
+\x2e\x33\x39\x20\x34\x31\x2e\x38\x31\x34\x73\x2d\x31\x34\x2e\x34\
+\x35\x38\x2d\x35\x33\x2e\x39\x37\x33\x2d\x35\x31\x2e\x30\x32\x37\
+\x2d\x32\x36\x2e\x30\x38\x63\x2d\x33\x30\x2e\x37\x39\x36\x20\x32\
+\x33\x2e\x34\x39\x2d\x32\x31\x2e\x31\x36\x37\x20\x37\x32\x2e\x35\
+\x37\x31\x2d\x32\x31\x2e\x31\x36\x37\x20\x37\x32\x2e\x35\x37\x31\
+\x73\x31\x35\x2e\x35\x35\x38\x2d\x34\x33\x2e\x33\x35\x34\x20\x33\
+\x34\x2e\x30\x31\x38\x2d\x35\x34\x2e\x38\x30\x37\x63\x32\x37\x2e\
+\x34\x36\x36\x2d\x31\x37\x2e\x30\x34\x20\x33\x38\x2e\x31\x37\x36\
+\x20\x38\x2e\x33\x31\x35\x35\x20\x33\x38\x2e\x31\x37\x36\x20\x38\
+\x2e\x33\x31\x35\x35\x7a\x22\x20\x66\x69\x6c\x6c\x3d\x22\x75\x72\
+\x6c\x28\x23\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\
+\x74\x32\x39\x39\x38\x2d\x33\x29\x22\x20\x66\x69\x6c\x74\x65\x72\
+\x3d\x22\x75\x72\x6c\x28\x23\x66\x69\x6c\x74\x65\x72\x33\x37\x32\
+\x33\x2d\x39\x2d\x37\x2d\x38\x2d\x33\x2d\x33\x2d\x30\x29\x22\x20\
+\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x33\x62\x62\x33\x63\x32\x22\
+\x2f\x3e\x0a\x20\x20\x20\x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\x20\
+\x20\x3c\x2f\x67\x3e\x0a\x20\x20\x20\x20\x3c\x67\x20\x63\x6c\x69\
+\x70\x2d\x70\x61\x74\x68\x3d\x22\x75\x72\x6c\x28\x23\x63\x6c\x69\
+\x70\x31\x35\x2d\x30\x39\x29\x22\x3e\x0a\x20\x20\x20\x20\x20\x3c\
+\x67\x20\x63\x6c\x69\x70\x2d\x70\x61\x74\x68\x3d\x22\x75\x72\x6c\
+\x28\x23\x63\x6c\x69\x70\x31\x36\x2d\x31\x29\x22\x3e\x0a\x20\x20\
+\x20\x20\x20\x20\x3c\x67\x20\x63\x6c\x69\x70\x2d\x70\x61\x74\x68\
+\x3d\x22\x75\x72\x6c\x28\x23\x63\x6c\x69\x70\x31\x37\x2d\x38\x39\
+\x29\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x3c\x70\x61\x74\x68\
+\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\
+\x69\x78\x28\x31\x2e\x30\x30\x32\x36\x20\x30\x20\x30\x20\x31\x20\
+\x39\x37\x33\x20\x31\x36\x34\x29\x22\x20\x64\x3d\x22\x6d\x33\x35\
+\x2e\x30\x31\x33\x20\x32\x30\x2e\x34\x32\x34\x63\x2d\x39\x2e\x34\
+\x36\x30\x39\x20\x35\x2e\x39\x38\x30\x33\x2d\x32\x30\x2e\x34\x34\
+\x36\x20\x31\x37\x2e\x30\x34\x38\x2d\x32\x35\x2e\x39\x36\x36\x20\
+\x33\x33\x2e\x34\x31\x37\x2d\x34\x2e\x31\x35\x39\x37\x20\x31\x32\
+\x2e\x33\x33\x35\x2d\x34\x2e\x38\x31\x33\x32\x20\x32\x37\x2e\x30\
+\x36\x35\x2d\x30\x2e\x31\x30\x39\x36\x20\x34\x31\x2e\x31\x35\x35\
+\x20\x34\x2e\x31\x36\x39\x39\x20\x31\x32\x2e\x34\x39\x31\x20\x31\
+\x32\x2e\x34\x33\x36\x20\x32\x33\x2e\x39\x30\x39\x20\x32\x33\x2e\
+\x35\x38\x36\x20\x33\x31\x2e\x36\x37\x35\x20\x31\x30\x2e\x36\x31\
+\x32\x20\x37\x2e\x33\x39\x31\x20\x32\x33\x2e\x34\x38\x35\x20\x31\
+\x31\x2e\x32\x32\x32\x20\x33\x36\x2e\x30\x34\x34\x20\x31\x30\x2e\
+\x38\x36\x36\x20\x31\x33\x2e\x35\x33\x38\x2d\x30\x2e\x33\x30\x33\
+\x20\x32\x36\x2e\x34\x30\x33\x2d\x35\x2e\x34\x33\x20\x33\x35\x2e\
+\x39\x33\x32\x2d\x31\x33\x2e\x35\x33\x32\x20\x31\x30\x2e\x30\x33\
+\x31\x2d\x38\x2e\x35\x32\x39\x20\x31\x36\x2e\x32\x36\x34\x2d\x32\
+\x30\x2e\x30\x39\x37\x20\x31\x38\x2e\x34\x32\x31\x2d\x33\x31\x2e\
+\x33\x38\x35\x20\x32\x2e\x34\x34\x2d\x31\x32\x2e\x37\x36\x34\x2d\
+\x30\x2e\x31\x33\x33\x2d\x32\x35\x2e\x30\x30\x33\x2d\x34\x2e\x38\
+\x38\x39\x2d\x33\x34\x2e\x32\x30\x35\x2d\x33\x2e\x31\x30\x33\x2d\
+\x36\x2e\x30\x30\x33\x32\x2d\x37\x2e\x31\x37\x35\x2d\x31\x30\x2e\
+\x39\x32\x35\x2d\x31\x31\x2e\x33\x34\x38\x2d\x31\x34\x2e\x37\x35\
+\x35\x2d\x34\x2e\x31\x38\x2d\x33\x2e\x38\x33\x36\x35\x2d\x38\x2e\
+\x34\x32\x35\x34\x2d\x36\x2e\x35\x35\x37\x32\x2d\x31\x32\x2e\x31\
+\x37\x34\x2d\x38\x2e\x35\x31\x32\x37\x2d\x30\x2e\x30\x31\x39\x39\
+\x2d\x30\x2e\x30\x31\x30\x34\x20\x39\x2e\x30\x35\x32\x39\x2d\x31\
+\x37\x2e\x36\x33\x34\x20\x39\x2e\x30\x32\x33\x39\x2d\x31\x37\x2e\
+\x36\x34\x39\x20\x30\x2e\x30\x32\x39\x20\x30\x2e\x30\x31\x34\x39\
+\x20\x39\x2e\x32\x37\x34\x2d\x31\x37\x2e\x35\x31\x39\x20\x39\x2e\
+\x33\x31\x31\x2d\x31\x37\x2e\x35\x20\x36\x2e\x39\x35\x37\x20\x33\
+\x2e\x36\x32\x38\x39\x20\x31\x34\x2e\x34\x20\x38\x2e\x38\x37\x30\
+\x32\x20\x32\x31\x2e\x33\x32\x37\x20\x31\x36\x2e\x31\x32\x20\x36\
+\x2e\x38\x39\x31\x20\x37\x2e\x32\x31\x31\x31\x20\x31\x33\x2e\x32\
+\x36\x39\x20\x31\x36\x2e\x34\x33\x33\x20\x31\x37\x2e\x36\x34\x34\
+\x20\x32\x37\x2e\x34\x39\x39\x20\x36\x2e\x36\x37\x37\x20\x31\x36\
+\x2e\x38\x39\x32\x20\x38\x2e\x32\x38\x34\x20\x33\x37\x2e\x35\x30\
+\x34\x20\x31\x2e\x38\x31\x20\x35\x37\x2e\x33\x39\x33\x2d\x35\x2e\
+\x37\x33\x38\x20\x31\x37\x2e\x36\x32\x38\x2d\x31\x37\x2e\x36\x35\
+\x39\x20\x33\x33\x2e\x36\x33\x32\x2d\x33\x33\x2e\x39\x33\x36\x20\
+\x34\x34\x2e\x30\x37\x33\x2d\x31\x35\x2e\x34\x39\x33\x20\x39\x2e\
+\x39\x33\x38\x2d\x33\x34\x2e\x32\x32\x34\x20\x31\x34\x2e\x32\x39\
+\x31\x2d\x35\x32\x2e\x32\x31\x37\x20\x31\x32\x2e\x32\x35\x34\x2d\
+\x31\x36\x2e\x36\x37\x32\x2d\x31\x2e\x39\x36\x34\x2d\x33\x32\x2e\
+\x30\x37\x32\x2d\x39\x2e\x33\x34\x38\x2d\x34\x33\x2e\x36\x31\x35\
+\x2d\x32\x30\x2e\x30\x38\x31\x2d\x31\x32\x2e\x31\x33\x37\x2d\x31\
+\x31\x2e\x32\x38\x35\x2d\x31\x39\x2e\x36\x36\x38\x2d\x32\x35\x2e\
+\x38\x35\x39\x2d\x32\x32\x2e\x35\x30\x31\x2d\x34\x30\x2e\x32\x39\
+\x32\x2d\x33\x2e\x31\x39\x34\x39\x2d\x31\x36\x2e\x32\x37\x38\x2d\
+\x30\x2e\x34\x35\x30\x39\x32\x2d\x33\x31\x2e\x38\x38\x20\x35\x2e\
+\x31\x30\x38\x2d\x34\x34\x2e\x31\x34\x35\x20\x37\x2e\x33\x35\x31\
+\x32\x2d\x31\x36\x2e\x32\x32\x20\x31\x39\x2e\x32\x32\x39\x2d\x32\
+\x36\x2e\x35\x30\x36\x20\x32\x38\x2e\x35\x34\x38\x2d\x33\x32\x2e\
+\x33\x39\x37\x7a\x22\x20\x66\x69\x6c\x6c\x3d\x22\x23\x62\x66\x62\
+\x66\x62\x66\x22\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x2f\x67\
+\x3e\x0a\x20\x20\x20\x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\x20\x20\
+\x3c\x2f\x67\x3e\x0a\x20\x20\x20\x20\x3c\x67\x20\x66\x69\x6c\x6c\
+\x3d\x22\x23\x62\x66\x62\x66\x62\x66\x22\x3e\x0a\x20\x20\x20\x20\
+\x20\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x6d\x32\x32\x31\x2e\x37\
+\x31\x20\x31\x35\x39\x2e\x35\x76\x31\x36\x30\x2e\x34\x36\x68\x2d\
+\x34\x33\x2e\x37\x30\x33\x76\x2d\x31\x36\x30\x2e\x34\x36\x7a\x6d\
+\x2d\x36\x36\x2e\x39\x39\x20\x31\x31\x39\x2e\x33\x31\x20\x31\x35\
+\x2e\x33\x31\x32\x20\x32\x37\x2e\x37\x35\x33\x76\x30\x2e\x33\x31\
+\x39\x71\x2d\x31\x36\x2e\x35\x38\x38\x20\x31\x34\x2e\x36\x37\x34\
+\x2d\x34\x31\x2e\x31\x35\x31\x20\x31\x34\x2e\x36\x37\x34\x2d\x33\
+\x38\x2e\x39\x31\x38\x20\x30\x2d\x35\x35\x2e\x31\x38\x37\x2d\x32\
+\x31\x2e\x30\x35\x34\x2d\x31\x34\x2e\x39\x39\x33\x2d\x31\x38\x2e\
+\x38\x32\x31\x2d\x31\x34\x2e\x39\x39\x33\x2d\x35\x39\x2e\x39\x37\
+\x32\x76\x2d\x38\x31\x2e\x30\x32\x36\x68\x34\x33\x2e\x37\x30\x33\
+\x76\x38\x31\x2e\x30\x32\x36\x71\x30\x20\x38\x2e\x36\x31\x33\x20\
+\x30\x2e\x33\x31\x39\x20\x31\x36\x2e\x35\x38\x38\x20\x30\x2e\x36\
+\x33\x38\x20\x37\x2e\x39\x37\x35\x20\x33\x2e\x35\x30\x39\x20\x31\
+\x34\x2e\x30\x33\x36\x20\x33\x2e\x31\x39\x20\x36\x2e\x30\x36\x31\
+\x20\x39\x2e\x35\x37\x20\x39\x2e\x38\x38\x39\x20\x36\x2e\x33\x38\
+\x20\x33\x2e\x35\x30\x39\x20\x31\x38\x2e\x31\x38\x33\x20\x33\x2e\
+\x35\x30\x39\x20\x35\x2e\x34\x32\x33\x20\x30\x20\x31\x30\x2e\x35\
+\x32\x37\x2d\x31\x2e\x35\x39\x35\x74\x39\x2e\x35\x37\x2d\x34\x2e\
+\x31\x34\x37\x7a\x22\x2f\x3e\x0a\x20\x20\x20\x20\x20\x3c\x70\x61\
+\x74\x68\x20\x64\x3d\x22\x6d\x31\x37\x38\x2e\x30\x39\x20\x31\x35\
+\x39\x2e\x35\x68\x34\x33\x2e\x33\x38\x34\x76\x31\x35\x39\x2e\x35\
+\x68\x2d\x34\x33\x2e\x33\x38\x34\x7a\x6d\x31\x34\x37\x2e\x33\x38\
+\x20\x31\x38\x2e\x35\x30\x32\x71\x37\x2e\x39\x37\x35\x20\x39\x2e\
+\x38\x38\x39\x20\x31\x31\x2e\x34\x38\x34\x20\x32\x34\x2e\x38\x38\
+\x32\x74\x33\x2e\x35\x30\x39\x20\x33\x37\x2e\x30\x30\x34\x76\x37\
+\x39\x2e\x31\x31\x32\x68\x2d\x34\x33\x2e\x33\x38\x34\x76\x2d\x37\
+\x39\x2e\x31\x31\x32\x71\x30\x2d\x38\x2e\x39\x33\x32\x2d\x30\x2e\
+\x36\x33\x38\x2d\x31\x36\x2e\x39\x30\x37\x2d\x30\x2e\x33\x31\x39\
+\x2d\x38\x2e\x32\x39\x34\x2d\x33\x2e\x31\x39\x2d\x31\x34\x2e\x33\
+\x35\x35\x2d\x32\x2e\x38\x37\x31\x2d\x36\x2e\x33\x38\x2d\x39\x2e\
+\x32\x35\x31\x2d\x39\x2e\x38\x38\x39\x74\x2d\x31\x38\x2e\x31\x38\
+\x33\x2d\x33\x2e\x35\x30\x39\x71\x2d\x31\x31\x2e\x31\x36\x35\x20\
+\x30\x2d\x32\x30\x2e\x37\x33\x35\x20\x34\x2e\x37\x38\x35\x76\x30\
+\x2e\x33\x31\x39\x6c\x2d\x30\x2e\x33\x31\x39\x2d\x30\x2e\x33\x31\
+\x39\x2d\x31\x35\x2e\x36\x33\x31\x2d\x32\x37\x2e\x37\x35\x33\x20\
+\x30\x2e\x33\x31\x39\x2d\x30\x2e\x33\x31\x39\x71\x31\x36\x2e\x35\
+\x38\x38\x2d\x31\x34\x2e\x39\x39\x33\x20\x34\x31\x2e\x34\x37\x2d\
+\x31\x34\x2e\x39\x39\x33\x20\x33\x38\x2e\x32\x38\x20\x30\x20\x35\
+\x34\x2e\x35\x34\x39\x20\x32\x31\x2e\x30\x35\x34\x7a\x22\x2f\x3e\
+\x0a\x20\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x6d\
+\x33\x35\x38\x2e\x30\x31\x20\x33\x31\x39\x76\x2d\x31\x35\x39\x2e\
+\x35\x68\x34\x32\x2e\x34\x32\x37\x76\x31\x35\x39\x2e\x35\x7a\x6d\
+\x30\x2d\x32\x32\x33\x2e\x33\x68\x34\x32\x2e\x34\x32\x37\x76\x33\
+\x37\x2e\x33\x32\x33\x68\x2d\x34\x32\x2e\x34\x32\x37\x7a\x22\x2f\
+\x3e\x0a\x20\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\
+\x6d\x35\x33\x36\x2e\x30\x31\x20\x32\x35\x38\x2e\x30\x37\x20\x33\
+\x34\x2e\x34\x35\x32\x20\x32\x32\x2e\x36\x34\x39\x2d\x30\x2e\x33\
+\x31\x39\x20\x30\x2e\x33\x31\x39\x71\x2d\x31\x31\x2e\x31\x36\x35\
+\x20\x31\x39\x2e\x31\x34\x2d\x33\x30\x2e\x33\x30\x35\x20\x32\x39\
+\x2e\x39\x38\x36\x2d\x31\x38\x2e\x38\x32\x31\x20\x31\x30\x2e\x38\
+\x34\x36\x2d\x34\x30\x2e\x38\x33\x32\x20\x31\x30\x2e\x38\x34\x36\
+\x2d\x31\x37\x2e\x32\x32\x36\x20\x30\x2d\x33\x32\x2e\x32\x31\x39\
+\x2d\x36\x2e\x33\x38\x2d\x31\x34\x2e\x39\x39\x33\x2d\x36\x2e\x36\
+\x39\x39\x2d\x32\x36\x2e\x31\x35\x38\x2d\x31\x37\x2e\x38\x36\x34\
+\x74\x2d\x31\x37\x2e\x38\x36\x34\x2d\x32\x36\x2e\x31\x35\x38\x71\
+\x2d\x36\x2e\x33\x38\x2d\x31\x34\x2e\x39\x39\x33\x2d\x36\x2e\x33\
+\x38\x2d\x33\x31\x2e\x39\x74\x36\x2e\x33\x38\x2d\x33\x31\x2e\x39\
+\x71\x36\x2e\x36\x39\x39\x2d\x31\x34\x2e\x39\x39\x33\x20\x31\x37\
+\x2e\x38\x36\x34\x2d\x32\x36\x2e\x31\x35\x38\x74\x32\x36\x2e\x31\
+\x35\x38\x2d\x31\x37\x2e\x35\x34\x35\x71\x31\x34\x2e\x39\x39\x33\
+\x2d\x36\x2e\x36\x39\x39\x20\x33\x32\x2e\x32\x31\x39\x2d\x36\x2e\
+\x36\x39\x39\x20\x32\x32\x2e\x30\x31\x31\x20\x30\x20\x34\x30\x2e\
+\x38\x33\x32\x20\x31\x30\x2e\x38\x34\x36\x20\x31\x39\x2e\x31\x34\
+\x20\x31\x30\x2e\x38\x34\x36\x20\x33\x30\x2e\x33\x30\x35\x20\x32\
+\x39\x2e\x39\x38\x36\x6c\x30\x2e\x33\x31\x39\x20\x30\x2e\x33\x31\
+\x39\x2d\x33\x34\x2e\x37\x37\x31\x20\x32\x32\x2e\x36\x34\x39\x2d\
+\x30\x2e\x33\x31\x39\x2d\x30\x2e\x33\x31\x39\x71\x2d\x35\x2e\x31\
+\x30\x34\x2d\x31\x31\x2e\x38\x30\x33\x2d\x31\x34\x2e\x39\x39\x33\
+\x2d\x31\x39\x2e\x31\x34\x2d\x39\x2e\x35\x37\x2d\x37\x2e\x33\x33\
+\x37\x2d\x32\x31\x2e\x33\x37\x33\x2d\x37\x2e\x33\x33\x37\x2d\x38\
+\x2e\x36\x31\x33\x20\x30\x2d\x31\x36\x2e\x32\x36\x39\x20\x33\x2e\
+\x38\x32\x38\x2d\x37\x2e\x33\x33\x37\x20\x33\x2e\x35\x30\x39\x2d\
+\x31\x32\x2e\x37\x36\x20\x39\x2e\x38\x38\x39\x2d\x35\x2e\x34\x32\
+\x33\x20\x36\x2e\x30\x36\x31\x2d\x38\x2e\x36\x31\x33\x20\x31\x34\
+\x2e\x33\x35\x35\x2d\x33\x2e\x31\x39\x20\x37\x2e\x39\x37\x35\x2d\
+\x33\x2e\x31\x39\x20\x31\x37\x2e\x32\x32\x36\x74\x33\x2e\x31\x39\
+\x20\x31\x37\x2e\x32\x32\x36\x20\x38\x2e\x36\x31\x33\x20\x31\x34\
+\x2e\x30\x33\x36\x71\x35\x2e\x34\x32\x33\x20\x35\x2e\x37\x34\x32\
+\x20\x31\x32\x2e\x37\x36\x20\x39\x2e\x32\x35\x31\x20\x37\x2e\x36\
+\x35\x36\x20\x33\x2e\x31\x39\x20\x31\x36\x2e\x32\x36\x39\x20\x33\
+\x2e\x31\x39\x20\x31\x31\x2e\x38\x30\x33\x20\x30\x20\x32\x31\x2e\
+\x33\x37\x33\x2d\x36\x2e\x33\x38\x20\x39\x2e\x38\x38\x39\x2d\x36\
+\x2e\x36\x39\x39\x20\x31\x34\x2e\x39\x39\x33\x2d\x31\x38\x2e\x35\
+\x30\x32\x6c\x30\x2e\x33\x31\x39\x2d\x30\x2e\x36\x33\x38\x7a\x22\
+\x2f\x3e\x0a\x20\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x20\x64\x3d\
+\x22\x6d\x39\x35\x38\x2e\x34\x33\x20\x39\x35\x2e\x37\x76\x32\x32\
+\x33\x2e\x33\x68\x2d\x34\x32\x2e\x34\x32\x37\x6c\x30\x2e\x33\x31\
+\x39\x2d\x38\x30\x2e\x30\x36\x39\x71\x30\x2d\x38\x2e\x39\x33\x32\
+\x2d\x33\x2e\x38\x32\x38\x2d\x31\x36\x2e\x39\x30\x37\x2d\x33\x2e\
+\x35\x30\x39\x2d\x37\x2e\x39\x37\x35\x2d\x39\x2e\x35\x37\x2d\x31\
+\x33\x2e\x37\x31\x37\x2d\x35\x2e\x37\x34\x32\x2d\x36\x2e\x30\x36\
+\x31\x2d\x31\x34\x2e\x30\x33\x36\x2d\x39\x2e\x32\x35\x31\x2d\x37\
+\x2e\x39\x37\x35\x2d\x33\x2e\x35\x30\x39\x2d\x31\x37\x2e\x32\x32\
+\x36\x2d\x33\x2e\x35\x30\x39\x74\x2d\x31\x37\x2e\x32\x32\x36\x20\
+\x33\x2e\x35\x30\x39\x71\x2d\x37\x2e\x39\x37\x35\x20\x33\x2e\x31\
+\x39\x2d\x31\x34\x2e\x30\x33\x36\x20\x39\x2e\x32\x35\x31\x2d\x35\
+\x2e\x37\x34\x32\x20\x36\x2e\x30\x36\x31\x2d\x39\x2e\x32\x35\x31\
+\x20\x31\x34\x2e\x30\x33\x36\x74\x2d\x33\x2e\x35\x30\x39\x20\x31\
+\x37\x2e\x32\x32\x36\x20\x33\x2e\x35\x30\x39\x20\x31\x37\x2e\x32\
+\x32\x36\x20\x39\x2e\x32\x35\x31\x20\x31\x34\x2e\x30\x33\x36\x71\
+\x36\x2e\x30\x36\x31\x20\x35\x2e\x37\x34\x32\x20\x31\x34\x2e\x30\
+\x33\x36\x20\x39\x2e\x32\x35\x31\x74\x31\x37\x2e\x32\x32\x36\x20\
+\x33\x2e\x35\x30\x39\x71\x34\x2e\x34\x36\x36\x20\x30\x20\x38\x2e\
+\x39\x33\x32\x2d\x30\x2e\x36\x33\x38\x74\x38\x2e\x32\x39\x34\x2d\
+\x32\x2e\x35\x35\x32\x68\x30\x2e\x36\x33\x38\x6c\x31\x35\x2e\x36\
+\x33\x31\x20\x32\x38\x2e\x37\x31\x2d\x30\x2e\x33\x31\x39\x20\x30\
+\x2e\x33\x31\x39\x71\x2d\x31\x35\x2e\x36\x33\x31\x20\x31\x32\x2e\
+\x31\x32\x32\x2d\x33\x38\x2e\x32\x38\x20\x31\x32\x2e\x31\x32\x32\
+\x2d\x31\x37\x2e\x32\x32\x36\x20\x30\x2d\x33\x32\x2e\x32\x31\x39\
+\x2d\x36\x2e\x33\x38\x74\x2d\x32\x36\x2e\x31\x35\x38\x2d\x31\x37\
+\x2e\x35\x34\x35\x2d\x31\x37\x2e\x38\x36\x34\x2d\x32\x36\x2e\x31\
+\x35\x38\x71\x2d\x36\x2e\x33\x38\x2d\x31\x34\x2e\x39\x39\x33\x2d\
+\x36\x2e\x33\x38\x2d\x33\x31\x2e\x39\x74\x36\x2e\x33\x38\x2d\x33\
+\x31\x2e\x39\x71\x36\x2e\x36\x39\x39\x2d\x31\x34\x2e\x39\x39\x33\
+\x20\x31\x37\x2e\x38\x36\x34\x2d\x32\x36\x2e\x31\x35\x38\x74\x32\
+\x36\x2e\x31\x35\x38\x2d\x31\x37\x2e\x35\x34\x35\x20\x33\x32\x2e\
+\x32\x31\x39\x2d\x36\x2e\x33\x38\x71\x33\x32\x2e\x35\x33\x38\x20\
+\x30\x20\x34\x39\x2e\x37\x36\x34\x20\x32\x34\x2e\x32\x34\x34\x76\
+\x2d\x38\x36\x2e\x31\x33\x7a\x22\x2f\x3e\x0a\x20\x20\x20\x20\x20\
+\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x6d\x39\x38\x35\x2e\x30\x39\
+\x20\x31\x33\x33\x2e\x34\x20\x30\x2e\x30\x31\x30\x31\x20\x34\x65\
+\x2d\x33\x63\x2d\x33\x2e\x31\x34\x35\x35\x20\x37\x2e\x32\x31\x35\
+\x33\x20\x31\x38\x2e\x34\x34\x31\x20\x31\x36\x2e\x33\x31\x20\x32\
+\x38\x2e\x39\x30\x38\x20\x32\x32\x2e\x30\x31\x35\x6c\x30\x2e\x34\
+\x38\x36\x38\x20\x39\x2e\x30\x31\x31\x33\x63\x2d\x31\x2e\x34\x31\
+\x39\x36\x2d\x31\x2e\x34\x30\x39\x38\x2d\x32\x2e\x37\x37\x37\x35\
+\x2d\x31\x2e\x39\x30\x33\x32\x2d\x34\x2e\x31\x33\x33\x31\x2d\x32\
+\x2e\x35\x39\x30\x39\x2d\x32\x2e\x34\x30\x31\x39\x2d\x31\x2e\x30\
+\x30\x36\x32\x2d\x35\x2e\x37\x37\x36\x31\x20\x34\x2e\x34\x35\x33\
+\x31\x2d\x32\x2e\x36\x35\x34\x33\x20\x36\x2e\x31\x33\x33\x35\x20\
+\x32\x2e\x34\x34\x35\x31\x20\x31\x2e\x35\x33\x36\x34\x20\x34\x2e\
+\x36\x39\x33\x35\x20\x32\x2e\x30\x33\x38\x20\x36\x2e\x37\x38\x39\
+\x34\x20\x32\x2e\x34\x35\x38\x6c\x2d\x30\x2e\x36\x34\x36\x39\x20\
+\x33\x33\x2e\x33\x36\x31\x20\x33\x2e\x37\x36\x36\x35\x20\x31\x2e\
+\x38\x33\x37\x31\x20\x31\x35\x2e\x36\x36\x2d\x33\x39\x2e\x37\x35\
+\x20\x31\x37\x2e\x39\x31\x38\x20\x39\x2e\x32\x33\x35\x35\x20\x34\
+\x2e\x36\x39\x37\x32\x20\x31\x37\x2e\x31\x31\x39\x20\x31\x2e\x39\
+\x35\x37\x39\x20\x31\x2e\x35\x31\x39\x33\x20\x35\x2e\x33\x36\x32\
+\x35\x2d\x31\x39\x2e\x34\x32\x31\x20\x31\x32\x2e\x39\x32\x34\x2d\
+\x31\x35\x2e\x34\x35\x35\x2d\x32\x2e\x33\x36\x32\x32\x2d\x30\x2e\
+\x37\x34\x37\x38\x38\x2d\x31\x36\x2e\x37\x35\x33\x20\x35\x2e\x38\
+\x37\x34\x36\x2d\x31\x37\x2e\x37\x38\x37\x2d\x39\x2e\x34\x38\x35\
+\x31\x20\x32\x33\x2e\x37\x38\x38\x2d\x33\x35\x2e\x34\x38\x38\x2d\
+\x33\x2e\x36\x35\x32\x32\x2d\x32\x2e\x30\x35\x34\x39\x2d\x32\x37\
+\x2e\x30\x37\x32\x20\x31\x39\x2e\x35\x30\x36\x63\x2d\x31\x2e\x35\
+\x33\x37\x33\x2d\x31\x2e\x34\x38\x35\x2d\x33\x2e\x32\x32\x38\x37\
+\x2d\x33\x2e\x30\x34\x39\x31\x2d\x35\x2e\x38\x38\x32\x39\x2d\x34\
+\x2e\x31\x38\x36\x34\x2d\x33\x2e\x31\x35\x37\x36\x2d\x31\x2e\x36\
+\x31\x32\x33\x2d\x35\x2e\x37\x32\x39\x20\x34\x2e\x32\x36\x38\x32\
+\x2d\x33\x2e\x35\x33\x35\x33\x20\x35\x2e\x36\x37\x31\x35\x20\x31\
+\x2e\x33\x33\x35\x38\x20\x30\x2e\x37\x32\x35\x33\x37\x20\x32\x2e\
+\x35\x31\x33\x39\x20\x31\x2e\x35\x36\x31\x37\x20\x34\x2e\x34\x38\
+\x30\x38\x20\x31\x2e\x39\x32\x37\x37\x6c\x2d\x37\x2e\x36\x38\x38\
+\x20\x34\x2e\x37\x32\x32\x38\x63\x2d\x31\x30\x2e\x36\x34\x35\x2d\
+\x35\x2e\x33\x36\x34\x35\x2d\x33\x30\x2e\x34\x30\x34\x2d\x31\x37\
+\x2e\x39\x34\x36\x2d\x33\x34\x2e\x35\x35\x2d\x31\x31\x2e\x32\x35\
+\x35\x6c\x2d\x30\x2e\x30\x31\x30\x31\x2d\x34\x65\x2d\x33\x63\x34\
+\x2e\x33\x65\x2d\x34\x20\x37\x65\x2d\x33\x20\x39\x2e\x32\x65\x2d\
+\x34\x20\x30\x2e\x30\x31\x34\x34\x2d\x39\x65\x2d\x33\x20\x30\x2e\
+\x30\x32\x34\x36\x20\x33\x2e\x37\x65\x2d\x34\x20\x36\x65\x2d\x33\
+\x20\x2d\x30\x2e\x30\x31\x30\x31\x20\x30\x2e\x30\x31\x31\x32\x2d\
+\x30\x2e\x30\x31\x33\x36\x20\x30\x2e\x30\x31\x38\x7a\x22\x2f\x3e\
+\x0a\x20\x20\x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\x20\x3c\x2f\x67\
+\x3e\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x20\x3c\x2f\x67\x3e\x0a\x3c\
+\x2f\x73\x76\x67\x3e\x0a\
+"
+
+qt_resource_name = b"\
+\x00\x09\
+\x0c\x78\x54\x88\
+\x00\x6e\
+\x00\x65\x00\x77\x00\x50\x00\x72\x00\x65\x00\x66\x00\x69\x00\x78\
+\x00\x0f\
+\x0b\x2f\xcc\x47\
+\x00\x75\
+\x00\x6e\x00\x69\x00\x63\x00\x61\x00\x64\x00\x6f\x00\x49\x00\x43\x00\x4f\x00\x4e\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x11\
+\x08\x93\x84\x47\
+\x00\x55\
+\x00\x4e\x00\x49\x00\x43\x00\x41\x00\x44\x00\x4f\x00\x4c\x00\x6f\x00\x67\x00\x6f\x00\x39\x00\x30\x00\x2e\x00\x73\x00\x76\x00\x67\
+\
+"
+
+qt_resource_struct_v1 = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x02\
+\x00\x00\x00\x3c\x00\x00\x00\x00\x00\x01\x00\x00\x25\x6f\
+\x00\x00\x00\x18\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+"
+
+qt_resource_struct_v2 = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x02\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x3c\x00\x00\x00\x00\x00\x01\x00\x00\x25\x6f\
+\x00\x00\x01\x78\x87\xfe\x9e\x5b\
+\x00\x00\x00\x18\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x01\x78\x64\x9b\x11\xd4\
+"
+
+qt_version = [int(v) for v in QtCore.qVersion().split('.')]
+if qt_version < [5, 8, 0]:
+    rcc_version = 1
+    qt_resource_struct = qt_resource_struct_v1
+else:
+    rcc_version = 2
+    qt_resource_struct = qt_resource_struct_v2
+
+def qInitResources():
+    QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+def qCleanupResources():
+    QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+qInitResources()
diff --git a/installer/own_python_packages.txt b/installer/own_python_packages.txt
new file mode 100644
index 0000000000000000000000000000000000000000..434116936b8a5ac58c8de3c1ac6ff3bf71a46ca9
--- /dev/null
+++ b/installer/own_python_packages.txt
@@ -0,0 +1,6 @@
+pyaircraftgeometry2
+pyaixml
+pycoordinatesystemconversion
+pyenergycarriers
+pymodulepackage
+pyunitconversion
\ No newline at end of file
diff --git a/installer/python_module_list.txt b/installer/python_module_list.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f2a0771c0adda20ab1322aeeb182cc9825bde23a
--- /dev/null
+++ b/installer/python_module_list.txt
@@ -0,0 +1,5 @@
+fuselage_design
+tank_design
+landing_gear_design
+weight_and_balance_analysis
+cost_estimation
\ No newline at end of file
diff --git a/installer/standard_python_packages.txt b/installer/standard_python_packages.txt
new file mode 100644
index 0000000000000000000000000000000000000000..2478e03a2c0f6a65d43c91cc404c83cde3be1fca
--- /dev/null
+++ b/installer/standard_python_packages.txt
@@ -0,0 +1,10 @@
+numpy
+pandas
+scipy
+statsmodels
+ambiance
+matplotlib
+yattag
+termcolor
+bs4
+openpyxl
\ No newline at end of file
diff --git a/installer/sub_functions/abort_install.py b/installer/sub_functions/abort_install.py
new file mode 100644
index 0000000000000000000000000000000000000000..72ddbc1852cca393bfd0c0983fa4062e33875b07
--- /dev/null
+++ b/installer/sub_functions/abort_install.py
@@ -0,0 +1,41 @@
+def abort_install(self):
+    """ Call function to handle the cancel button.
+
+        :rtype: object
+    """
+
+    ''' imports for python '''
+    import os
+    import shutil
+    import PyQt5.QtWidgets
+
+    check_finished = self.cancel_button.text()
+    check_uninstall = self.uninstall_button.isVisible()
+    check_welcome_panel = self.welcome_panel.isVisible()
+    check_integration_panel = self.integration_panel.isVisible()
+
+    if not check_finished == 'Finish' and not check_uninstall and not check_welcome_panel\
+            and not check_integration_panel:
+        install_folder = self.install_path_line_edit.text()
+        install_folder = install_folder.replace(os.sep, '/')
+
+        if os.path.isdir(install_folder):
+            shutil.rmtree(install_folder)
+        last_character = install_folder[-1]
+
+        if not (last_character == '/'):
+            install_folder = install_folder + '/'
+
+        indices = []
+        i = install_folder.find('/')
+        while i >= 0:
+            indices.append(i)
+            i = install_folder.find('/', i + 1)
+        parent_folder = install_folder[:indices[-2]]
+        check_flag_parent_folder = os.path.isdir(parent_folder)
+
+        if check_flag_parent_folder:
+            if not os.listdir(parent_folder):
+                shutil.rmtree(parent_folder)
+
+    PyQt5.QtWidgets.QApplication.quit()
diff --git a/installer/sub_functions/browse_folder.py b/installer/sub_functions/browse_folder.py
new file mode 100644
index 0000000000000000000000000000000000000000..04e5eefc531b98cf3b26f4689b62eac07f7fc47b
--- /dev/null
+++ b/installer/sub_functions/browse_folder.py
@@ -0,0 +1,171 @@
+def browse_folder(self):
+    """ Call function to handle the browse button.
+
+        :rtype: object
+    """
+
+    ''' imports for python '''
+    import os
+    import shutil
+    import configparser
+    from PyQt5.QtCore import QCoreApplication
+    from PyQt5.QtWidgets import QFileDialog
+
+    # read user path string from browse edit-field of installer application
+    install_path_panel_visibility = self.install_path_panel.isVisible()
+    repository_path_panel_visibility = self.repository_path_panel.isVisible()
+    integration_panel_visibility = self.integration_panel.isVisible()
+    user_path_string = os.path.expanduser("~")
+    user_path_string = user_path_string.replace(os.sep, '/')
+    user_path_string = user_path_string + '/'
+
+    # check if the installation panel is shown in the installer application
+    #  -> if true: -> set UNICADO install path to browse edit-field of installer application
+    if install_path_panel_visibility:
+        install_string = self.install_path_line_edit.text()
+        install_string = str(install_string.replace(os.sep, '/'))
+        if len(install_string) < 3:
+            install_string = 'C:/Programs/UNICADOworkflow'
+            # check if the current operating system is linux
+            #  -> if true: -> set linux specific install path to browse edit-field
+            if os.name == 'posix':
+                install_string = user_path_string + 'UNICADOworkflow'
+
+        # check if the given install path is not an existing directory -> if true: -> create install directory
+        if not os.path.isdir(install_string):
+            os.makedirs(install_string)
+        install_folder = QFileDialog.getExistingDirectory(self.repository_path_panel,
+                                                          'Choose Install Directory', install_string)
+        self.install_path_line_edit.setText(install_folder)
+
+        # check if the current operating system is windows
+        #  -> if true: -> set windows specific install path to browse edit-field
+        if os.name == 'nt':
+            check_input_string = install_folder.find('C:/Program Files')
+            # check if the 'C:/Program Files' is not existing
+            #  -> if true: -> try to generate a test folder inside of current hard drive directory
+            #                 to check for necessary administrator rights
+            if check_input_string == 0:
+                try:
+                    if os.path.isdir(install_folder):
+                        os.mkdir(install_folder + '/test')
+                        shutil.rmtree(install_folder + '/test')
+                    else:
+                        os.mkdir(install_folder)
+                    self.install_path_text_label_1.setText("ATTENTION: If UNICADOworkflow is to be installed in"
+                                                           " C:/Program Files or C:/Program Files (x86), "
+                                                           "the installer and RCE must be executed with "
+                                                           "administrator rights. Ensure that you have these rights.")
+                    QCoreApplication.processEvents()
+
+                # exception handling if necessary administrator rights not existing
+                #  -> set UNICADO install path to 'C:/Programs/UNICADOworkflow/'
+                except OSError:
+                    install_folder = 'C:/Programs/UNICADOworkflow/'
+                    self.install_path_text_label_1.setText("ATTENTION: Please note that you do not have the necessary "
+                                                           "administrator rights for the installation in the selected "
+                                                           "directory. Installation continues in"
+                                                           " C:/Programs/UNICADOworkflow/.")
+                    self.install_path_line_edit.setText(install_folder)
+                    QCoreApplication.processEvents()
+
+            # else condition: necessary administrator rights are existing
+            #  -> set install path to given path from browse edit-field
+            else:
+                self.install_path_text_label_1.setText("Setup will install the UNICADO workflow in the following "
+                                                       "folder. To install in a different folder, click Browse and "
+                                                       "select another folder. Attention, this cannot be changed later!"
+                                                       " Then click Next to select the repository folder.")
+                QCoreApplication.processEvents()
+                if not os.path.isdir(install_folder):
+                    self.install_path_line_edit.setText(install_string)
+                    QCoreApplication.processEvents()
+                if not (install_folder == install_string):
+                    check_input_string = install_string.find('C:/Program Files')
+                    if check_input_string == -1:
+                        os.removedirs(install_string)
+
+        # check if the current operating system is linux
+        #  -> if true: -> set linux specific install path to browse edit-field
+        if os.name == 'posix':
+            if not os.path.isdir(install_folder):
+                self.install_path_line_edit.setText(install_string)
+                QCoreApplication.processEvents()
+            if not (install_folder == install_string):
+                os.removedirs(install_string)
+
+    # check if the select repository panel is shown in the installer application
+    #  -> if true: -> check if all necessary repositories exist and set git url path
+    if repository_path_panel_visibility:
+        current_dir = os.path.expanduser("~")
+        repository_folder = QFileDialog.getExistingDirectory(self.repository_path_panel, 'Select Repository Directory',
+                                                             current_dir)
+        if not os.path.isdir(repository_folder):
+            self.repository_path_line_edit.setText(current_dir)
+            QCoreApplication.processEvents()
+            repository_folder = current_dir
+        else:
+            self.repository_path_line_edit.setText(repository_folder)
+            QCoreApplication.processEvents()
+
+        self.next_button.setEnabled(False)
+        QCoreApplication.processEvents()
+        folders_in_directory = os.listdir(repository_folder)
+        for folder in folders_in_directory:
+            path_to_check = repository_folder + '/' + folder + '/.git'
+            if os.path.isdir(path_to_check):
+                if os.path.isfile(repository_folder + '/' + folder + '/.git/config'):
+                    config = configparser.ConfigParser()
+                    config.read(repository_folder + '/' + folder + '/.git/config')
+                    if config.has_section('remote "origin"'):
+                        url = config['remote "origin"']['url']
+                        if url == 'ssh://git@unicado.ilr.rwth-aachen.de:2222/source/rADDITIONALSOFTWARE.git':
+                            self.next_button.setEnabled(True)
+                            QCoreApplication.processEvents()
+                            break
+                        elif url == 'ssh://git@unicado.ilr.rwth-aachen.de:2222/source/rAircraftDesign.git':
+                            self.next_button.setEnabled(True)
+                            QCoreApplication.processEvents()
+                            break
+                        elif url == 'ssh://git@unicado.ilr.rwth-aachen.de:2222/source/rAIRCRAFTREFERENCES.git':
+                            self.next_button.setEnabled(True)
+                            QCoreApplication.processEvents()
+                            break
+                        elif url == 'ssh://git@unicado.ilr.rwth-aachen.de:2222/source/rEngines.git':
+                            self.next_button.setEnabled(True)
+                            QCoreApplication.processEvents()
+                            break
+                        elif url == 'ssh://git@unicado.ilr.rwth-aachen.de:2222/source/rLibraries.git':
+                            self.next_button.setEnabled(True)
+                            QCoreApplication.processEvents()
+                            break
+
+    if integration_panel_visibility:
+        tool_name = self.tool_name_panel_edit.text()
+        current_dir = os.path.expanduser("~")
+        local_tool_folder = QFileDialog.getExistingDirectory(self.tool_path_panel, 'Select Tool Directory', current_dir)
+        self.tool_path_panel_edit.setText(local_tool_folder)
+        content_of_directory = os.listdir(local_tool_folder)
+        if os.path.isdir(local_tool_folder + '/' + tool_name):
+            self.next_button.setEnabled(False)
+            self.integration_text_label_4.setVisible(False)
+            self.integration_text_label_3.setVisible(True)
+            self.integration_combo_box.setVisible(False)
+            self.integration_text_label_3.setText(
+                'Attention: There is no executable file with the entered tool name in the selected directory. '
+                'Please change path.')
+        else:
+            if tool_name in content_of_directory or tool_name + '.exe' in content_of_directory:
+                self.integration_text_label_3.setVisible(True)
+                self.integration_combo_box.setVisible(True)
+                self.integration_text_label_3.setText('Please select the group in which the tool is to be integrated.')
+            else:
+                self.next_button.setEnabled(False)
+                self.integration_combo_box.setVisible(False)
+                self.integration_text_label_4.setVisible(False)
+                self.integration_text_label_3.setVisible(True)
+                self.integration_text_label_3.setText(
+                    'Attention: There is no executable file with the entered tool name in the selected directory. '
+                    'Please change path.')
+
+        QCoreApplication.processEvents()
diff --git a/installer/sub_functions/change_execution_rights_on_linux.py b/installer/sub_functions/change_execution_rights_on_linux.py
new file mode 100644
index 0000000000000000000000000000000000000000..a17d28fa47289001f006a4766cdfe556c5a7b001
--- /dev/null
+++ b/installer/sub_functions/change_execution_rights_on_linux.py
@@ -0,0 +1,19 @@
+def change_execution_rights_on_linux(path_to_folder):
+    """ Changes the access rights of all files inside the given directory to read, write and execute.
+
+        The input string "path_to_folder" contains the system path of directory to be changed.
+
+        :param: path_to_folder: input string
+        :return: none
+    """
+
+    ''' imports for python '''
+    import os
+    import stat
+
+    ''' loop across all directories and files inside the given directory to change access rights '''
+    for root, dirs, files in os.walk(path_to_folder):
+        for directory in dirs:
+            os.chmod(os.path.join(root, directory), stat.S_IRWXU)
+        for file in files:
+            os.chmod(os.path.join(root, file), stat.S_IRWXU)
diff --git a/installer/sub_functions/check_tool.py b/installer/sub_functions/check_tool.py
new file mode 100644
index 0000000000000000000000000000000000000000..cc4c87d99a1d6b394c509bbfaf2d10799bd042c3
--- /dev/null
+++ b/installer/sub_functions/check_tool.py
@@ -0,0 +1,179 @@
+import os
+from PyQt5.QtCore import QCoreApplication
+
+
+def check_tool(self):
+    # read tool name from edit fild
+    input_string = str()
+    self.integration_text_label_2.setVisible(False)
+    self.integration_button_group_name.setExclusive(False)
+    self.integration_radio_button_delete.setChecked(False)
+    self.integration_radio_button_overwrite.setChecked(False)
+    self.integration_button_group_name.setExclusive(True)
+    self.next_button.setEnabled(False)
+    self.button_name_panel.setVisible(False)
+    tool_name_panel_visibility = self.tool_name_panel.isVisible()
+    group_name_panel_visibility = self.group_name_panel.isVisible()
+
+    if tool_name_panel_visibility:
+        input_string = self.tool_name_panel_edit.text()
+
+    if group_name_panel_visibility:
+        input_string = self.group_name_panel_edit.text()
+
+    ''' check if the entered tool is already existing in the workflow '''
+    user_path_string = os.path.expanduser("~")
+    user_path_string = user_path_string.replace(os.sep, '/')
+    user_path_string = user_path_string + '/'
+
+    # check if the text file with installed tools exist -> if true:
+    # -> open file and check if the entered tool name already exist
+    if tool_name_panel_visibility:
+        if os.path.isfile(user_path_string + '.rce/default/integration/tools/common/toolListUNICADOworkflow.txt'):
+            with open(user_path_string + '.rce/default/integration/tools/common/toolListUNICADOworkflow.txt', 'r') \
+                    as tool_list:
+                if input_string in tool_list.read():
+                    if os.path.isfile(user_path_string + '.rce/default/integration/tools/common/'
+                                                         'standardToolListUNICADOworkflow.txt'):
+                        with open(user_path_string + '.rce/default/integration/tools/common/'
+                                                     'standardToolListUNICADOworkflow.txt', 'r') as standard_tools:
+                            if input_string in standard_tools.read():
+                                self.integration_text_label_2.setText("The entered tool name already exists in the "
+                                                                      "UNICADO workflow"
+                                                                      " and is a basic tool that cannot be changed. \n"
+                                                                      "Please enter another tool name or abort with "
+                                                                      "Cancel.")
+                                self.integration_text_label_2.setVisible(True)
+                                standard_tools.close()
+                                tool_list.close()
+
+                            else:
+                                self.integration_text_label_2.setText("The entered tool name already exists in the "
+                                                                      "UNICADO workflow"
+                                                                      " but is not a basic tool. \n"
+                                                                      "Please select if you want to remove or overwrite"
+                                                                      " the tool.")
+                                self.integration_text_label_2.setVisible(True)
+                                self.button_name_panel.setVisible(True)
+                                standard_tools.close()
+                                tool_list.close()
+
+                        QCoreApplication.processEvents()
+                        return
+
+                    else:
+                        self.integration_text_label_2.setText(
+                            "The entered tool name already exists in the UNICADO workflow"
+                            " but is not a basic tool. \n"
+                            "Please select if you want to remove or overwrite the tool.")
+                        self.integration_text_label_2.setVisible(True)
+                        self.button_name_panel.setVisible(True)
+                        tool_list.close()
+
+                        QCoreApplication.processEvents()
+                        return
+
+            tool_list.close()
+
+        # else condition: text file with installed tools is not existing -> abort installer
+        else:
+            # generate Error message and show in installer application
+            self.header_text_label_1.setText('Attention! An Error has occurred!')
+            self.header_text_label_2.setText('')
+            self.integration_text_label_1.setText('The UNICADO workflow is not installed correctly! \n'
+                                                  'Please reinstall the workflow correctly, after that the tool '
+                                                  'integration'
+                                                  ' should be possible.')
+            self.tool_name_panel.setVisible(False)
+            self.tool_name_panel_edit_button.setVisible(False)
+            self.next_button.setVisible(False)
+            self.back_button.setVisible(False)
+            self.cancel_button.setText('Abort')
+            return
+
+    ''' check input string for camel case convention '''
+    # check if is blank character in the given input string -> if true: -> display an error message in ui
+    if not input_string.isalnum():
+        if tool_name_panel_visibility:
+            self.integration_text_label_2.setText("Blanks or special characters are not allowed in the tool name, "
+                                                  "please change.")
+            self.integration_text_label_2.setVisible(True)
+
+        if group_name_panel_visibility:
+            self.integration_text_label_4.setText("Blanks or special characters are not allowed in the group name, "
+                                                  "please change.")
+            self.integration_text_label_4.setVisible(True)
+
+        QCoreApplication.processEvents()
+        return
+
+    # check if is a number in the given string -> if true: -> display an error message in ui
+    if not input_string.isalpha():
+        if tool_name_panel_visibility:
+            self.integration_text_label_2.setText("Numbers are not allowed in the tool name, please change.")
+            self.integration_text_label_2.setVisible(True)
+
+        if group_name_panel_visibility:
+            self.integration_text_label_4.setText("Numbers are not allowed in the group name, please change.")
+            self.integration_text_label_4.setVisible(True)
+
+        QCoreApplication.processEvents()
+        return
+
+    # check if is the first character upper case -> if true: -> display an error message in ui
+    if not input_string[0].islower():
+        if tool_name_panel_visibility:
+            self.integration_text_label_2.setText("First letter in tool name is not allowed to be uppercase, "
+                                                  "please change.")
+            self.integration_text_label_2.setVisible(True)
+
+        if group_name_panel_visibility:
+            self.integration_text_label_4.setText("First letter in group name is not allowed to be uppercase, "
+                                                  "please change.")
+            self.integration_text_label_4.setVisible(True)
+
+        QCoreApplication.processEvents()
+        return
+
+    # check if all characters of input string are lower case -> if true: -> display an error message in ui
+    if input_string.islower():
+        if tool_name_panel_visibility:
+            self.integration_text_label_2.setText("Only lowercase letters are not allowed, please change.")
+            self.integration_text_label_2.setVisible(True)
+
+        if group_name_panel_visibility:
+            self.integration_text_label_4.setText("Only lowercase letters are not allowed, please change.")
+            self.integration_text_label_4.setVisible(True)
+
+        QCoreApplication.processEvents()
+        return
+
+    # check if there is exactly one uppercase letter in the given string
+    camel_case_flag = [True for character in input_string if character.isupper()]
+    upper_character_count = [1 for character in input_string if character.isupper()]
+    if not camel_case_flag or len(upper_character_count) > 1:
+        if tool_name_panel_visibility:
+            self.integration_text_label_2.setText("Only one uppercase letter is allowed in the tool name, "
+                                                  "please change.")
+            self.integration_text_label_2.setVisible(True)
+
+        if group_name_panel_visibility:
+            self.integration_text_label_4.setText("Only one uppercase letter is allowed in the tool name, "
+                                                  "please change.")
+            self.integration_text_label_4.setVisible(True)
+
+        QCoreApplication.processEvents()
+        return
+
+    # the entered tool name matched the camel case convention -> prepare ui for the next steps
+    if tool_name_panel_visibility:
+        self.integration_text_label_2.setText("Please click 'Next' to continue the tool integration.")
+        self.integration_text_label_2.setVisible(True)
+
+    if group_name_panel_visibility:
+        self.integration_text_label_4.setText("Please click 'Next' to continue the tool integration.")
+        self.integration_text_label_4.setVisible(True)
+
+    self.next_button.setEnabled(True)
+    QCoreApplication.processEvents()
+    return
diff --git a/installer/sub_functions/current_text.py b/installer/sub_functions/current_text.py
new file mode 100644
index 0000000000000000000000000000000000000000..58ef13c7ba47ab3a0334ff92baad5d02551675b4
--- /dev/null
+++ b/installer/sub_functions/current_text.py
@@ -0,0 +1,24 @@
+# imports for python
+from sub_functions.check_tool import check_tool
+
+
+def current_text(self):
+    selected_group = self.integration_combo_box.currentText()
+
+    if selected_group == '- please select a tool group -' or selected_group == '- other -':
+        self.integration_text_label_4.setVisible(False)
+        self.next_button.setEnabled(False)
+        self.group_name_panel.setVisible(False)
+        if selected_group == '- other -':
+            self.group_name_panel.setVisible(True)
+            input_string = self.group_name_panel_edit.text()
+            if not input_string == 'Please enter tool group name.':
+                check_tool(self)
+    else:
+        self.group_name_panel_edit.setText(selected_group)
+        self.group_name_panel.setVisible(False)
+        self.integration_text_label_4.setText("Please click 'Next' to continue the tool integration.")
+        self.integration_text_label_4.setVisible(True)
+        self.next_button.setEnabled(True)
+
+    return
diff --git a/installer/sub_functions/delete_tool.py b/installer/sub_functions/delete_tool.py
new file mode 100644
index 0000000000000000000000000000000000000000..ffeed5ba472ab2ac16e9b9d52e9f35a4e5360d6a
--- /dev/null
+++ b/installer/sub_functions/delete_tool.py
@@ -0,0 +1,55 @@
+import os
+import time
+import shutil
+
+
+def delete_tool(self):
+    # initialize local parameter
+    tools = []
+    install_directory = []
+    tool_name = self.tool_name_panel_edit.text()
+    error_flag = False
+
+    # generate path to internal rce tool directory
+    user_path_string = os.path.expanduser("~")
+    user_path_string = user_path_string.replace(os.sep, '/')
+    user_path_string = user_path_string + '/'
+    path_to_json_files = user_path_string + '.rce/default/integration/tools/common/'
+
+    if not os.path.isfile(path_to_json_files + 'absolutPathToUNICADOInstallDirectory.txt'):
+        error_flag = True
+
+    else:
+        install_path = open(user_path_string + '.rce/default/integration/tools/common/'
+                                               'absolutPathToUNICADOInstallDirectory.txt', 'r')
+        install_directory = install_path.read()
+        install_path.close()
+
+    if not os.path.isfile(path_to_json_files + 'toolListUNICADOworkflow.txt'):
+        error_flag = True
+
+    else:
+        tool_list = open(user_path_string + '.rce/default/integration/tools/common/toolListUNICADOworkflow.txt', 'r')
+        tools = tool_list.read()
+        tool_list.close()
+
+    if not error_flag:
+        if os.path.isdir(path_to_json_files + tool_name):
+            shutil.rmtree(path_to_json_files + tool_name)
+
+        if tool_name in tools:
+            tools = tools.split()
+            tools.remove(tool_name)
+            tools = '\n'.join([str(item) for item in tools])
+            tool_list = open(user_path_string + '.rce/default/integration/tools/common/toolListUNICADOworkflow.txt',
+                             'w')
+            tool_list.write(tools)
+            tool_list.write('\n')
+            tool_list.close()
+
+        if os.path.isdir(install_directory + tool_name):
+            shutil.rmtree(install_directory + tool_name)
+
+        time.sleep(3)
+
+    return error_flag
diff --git a/installer/sub_functions/install_unicado.py b/installer/sub_functions/install_unicado.py
new file mode 100644
index 0000000000000000000000000000000000000000..00357a56ab77d7e7154526e40f186950ade0af54
--- /dev/null
+++ b/installer/sub_functions/install_unicado.py
@@ -0,0 +1,1360 @@
+''' imports for python '''
+import os
+import json
+import time
+import shutil
+import platform
+import subprocess
+import configparser
+from zipfile import ZipFile
+from pathlib import Path
+from PyQt5.QtCore import QCoreApplication
+from sub_functions.resource_path import resource_path
+from sub_functions.write_path_to_environment import write_path_to_environment
+from sub_functions.change_execution_rights_on_linux import change_execution_rights_on_linux
+from sub_functions.remove_tigl_entry import remove_tigl_entry_from_wf_file
+
+def install_unicado(self):
+    """ Call function to uninstall all UNICADO components of the working- and .rce-directory.
+
+            rtype: object
+    """
+
+    ''' initialize local parameter '''
+    percent = int(0)
+    install_percent = int(0)
+    current_working_step = str()
+    python_error_flag = False
+    error_flag = False
+
+    # set buttons to invisible or disabled
+    self.next_button.setEnabled(False)
+    self.back_button.setVisible(False)
+    self.cancel_button.setVisible(False)
+    self.cancel_button.setText('Finish')
+    self.install_progress_bar.setValue(1)
+    QCoreApplication.processEvents()
+
+    # check if the standalone installation is selected
+    if self.install_radio_button_alone.isChecked():
+        # read UNICADO install path from line edit field of install panel
+        install_folder = self.install_path_line_edit.text()
+        install_folder = install_folder.replace(os.sep, '/')
+        if not os.path.isdir(install_folder):
+            os.makedirs(install_folder)
+
+        # create path-files for UNICADOworkflow
+        user_path_string = os.path.expanduser("~")
+        user_path_string = user_path_string.replace(os.sep, '/')
+        user_path_string = user_path_string + '/'
+        path_to_tool_json_files = user_path_string + '.rce/default/integration/tools/common/'
+
+        # check if the .rce system path for json tool integration is not existing
+        #  -> if true: -> generate directories recursively
+        if not os.path.isdir(path_to_tool_json_files):
+            os.makedirs(path_to_tool_json_files)
+
+        # check if a standalone origin design tool directory is not existing in the .rce folder
+        #  -> if true: -> generate directories recursively
+        if not os.path.isdir(path_to_tool_json_files + 'originUnicadoDesignTools'):
+            os.makedirs(path_to_tool_json_files + 'originUnicadoDesignTools/UNICADOworkflow')
+
+        # check if a standalone origin software tool directory is not existing in the .rce folder
+        #  -> if true: -> generate directories recursively
+        if not os.path.isdir(path_to_tool_json_files + 'originUnicadoProjects'):
+            os.makedirs(path_to_tool_json_files + 'originUnicadoProjects')
+
+        # generate standalone flag file in .rce directory
+        if not os.path.isfile(path_to_tool_json_files + 'standAloneInstallationFlag.dat'):
+            with open(path_to_tool_json_files + 'standAloneInstallationFlag.dat', 'w') as file:
+                file.close()
+
+        # delete repository path file if it is existing
+        if os.path.isfile(path_to_tool_json_files + 'absolutPathToUNICADOrepositoryDirectory.txt'):
+            os.remove(path_to_tool_json_files + 'absolutPathToUNICADOrepositoryDirectory.txt')
+
+        # get path to temporary working directory including the version txt-file
+        path_to_resources, status_flag = resource_path()
+        path_to_version_file = os.path.join(path_to_resources, 'version.txt').replace(os.sep, '/')
+        
+        # check if python is already installed on the local machine
+        startupinfo = None
+        python_executables = []
+        
+        try:
+            # For Windows, use the `where` command
+            if os.name == "nt":
+                startupinfo = subprocess.STARTUPINFO()
+                startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW  # Suppress console window
+                result = subprocess.run(["where", "python"], capture_output=True, text=True, check=True,
+                                        startupinfo=startupinfo)
+                python_executables = result.stdout.strip().split("\n")
+            else:
+                # For Linux/macOS, use the `which -a` command
+                with open(os.devnull, 'w') as devnull:
+                    result = subprocess.run(["which", "-a", "python"], text=True, check=True,
+                                            stdout=subprocess.PIPE, stderr=devnull)
+                    python_executables = result.stdout.strip().split("\n")
+        except subprocess.CalledProcessError as e:
+            print(f"Failed to locate Python interpreters. Error: {e}")
+
+        # Filter and clean up results
+        installed_python_versions = [exe.strip() for exe in python_executables if exe.strip()]
+        
+        # check if any python version is installed on the lcoal machine
+        if installed_python_versions:
+            python_count = 0
+            python_numbers = []
+            python_versions = []
+            python_check_flag = False
+            # loop across all installed python verions to extract version number
+            for py_version in range(0, len(installed_python_versions)):
+                if not 'INKSCAPE' in installed_python_versions[py_version].upper() and \
+                    not '.VIRTUALENVS' in installed_python_versions[py_version].upper() and \
+                     not 'WINDOWSAPPS' in installed_python_versions[py_version].upper():
+                    try:
+                        # Prepare platform-specific settings to suppress console output
+                        startupinfo = None
+                        if os.name == "nt":
+                            startupinfo = subprocess.STARTUPINFO()
+                            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW                   
+                        # Capture Python version silently
+                        with open(os.devnull, 'w') as devnull:
+                            results = subprocess.run([installed_python_versions[py_version], "--version"], 
+                                                    stdout=subprocess.PIPE, stderr=devnull, text=True, check=True,
+                                                    startupinfo=startupinfo)
+                        # Process and store the version information
+                        python_versions.append(results.stdout.strip())
+                        python_numbers.append(results.stdout.strip().split(' ')[-1])
+                    except subprocess.CalledProcessError as e:
+                        print(f"Error retrieving version for {py_version}: {e}")
+                    
+            # loop across all extracted python verion numbers to check if one of them is valid for UNCIADO   
+            for py_number in range(0, len(python_numbers)):
+                if int(python_numbers[py_number][0]) == 3 \
+                    and (int(python_numbers[py_number][2:4]) == 10 or int(python_numbers[py_number][2:4]) == 11):
+                    python_check_flag = True
+                    break
+                python_count += 1
+            
+            # check if the python version check is failed -> if true: -> set error message and prepare termination  
+            if not python_check_flag:
+                python_error_flag = True
+                python_error_string_1 = 'Attention: Your installed Python versions are not valid.'
+                python_error_string_2 = 'Currently only Python 3.10 and 3.11 are supported.'
+        
+        # else conditon: no python installation was found on the local machine        
+        else:
+            python_error_flag = True
+            python_error_string_1 = 'Attention! No installed Python version was found on your local machine!' 
+            python_error_string_2 = 'At least one non third party version should be added to the PATH variables of your system.'
+        
+        # Read list of python modules
+        path_to_python_module_file = os.path.join(path_to_resources, 'python_module_list.txt').replace(os.sep, '/')
+        if os.path.isfile(path_to_python_module_file) and not python_error_flag:
+            python_module_file = open(path_to_python_module_file, 'r')
+            python_module_list = python_module_file.read()
+            python_module_file.close()
+        
+        # check if the python version check is not failed -> if true: -> run installation process
+        if not python_error_flag:
+            # check if the version text file is really existing -> if true: -> read version number from txt-file
+            if os.path.isfile(path_to_version_file) and status_flag:
+                file = open(path_to_version_file, 'r')
+                version_number = file.read()
+                file.close()
+
+                # get path to temporary working directory including the installation zip-file
+                if os.name == 'posix':
+                    name_of_zip = 'UNICADO-' + version_number + '-Linux.zip'
+                else:
+                    name_of_zip = 'UNICADO-' + version_number + '-win64.zip'
+                index = path_to_version_file.rfind('/')
+                path_to_zip = path_to_version_file[:index] + '/' + name_of_zip
+                path_to_temp = path_to_version_file[:index]
+
+                # check if the installation zip file is really existing
+                if os.path.isfile(path_to_zip):
+                    # delete old temporary zip directory if it is existing
+                    if os.path.isdir(path_to_temp + '/' + name_of_zip[:-4]):
+                        shutil.rmtree(path_to_temp + '/' + name_of_zip[:-4])
+
+                    # try to unzip installer data an install workflow component
+                    try:
+                        current_working_step = 'unzipping'
+                        with ZipFile(path_to_zip, 'r') as zObject:
+                            # Extracting specific file in the zip into a specific location
+                            zObject.extractall(path=path_to_temp)
+                            zObject.close()
+
+                        if os.path.isdir(path_to_temp + '/' + name_of_zip[:-4]):
+                            content_of_zip_directory = os.listdir(path_to_temp + '/' + name_of_zip[:-4])
+                            copy_count = len(content_of_zip_directory) + 20
+                            percent = int(round(100 / copy_count, 0))
+
+                            # generate text file for RCE with install directory
+                            current_working_step = 'path generation'
+                            file_for_install_path = open(path_to_tool_json_files
+                                                        + 'absolutPathToUNICADOInstallDirectory.txt', 'w')
+                            file_for_install_path.write(install_folder + '/')
+                            file_for_install_path.close()
+                            install_percent += percent
+                            self.install_progress_bar.setValue(install_percent)
+                            QCoreApplication.processEvents()
+
+                            # generate results and working directory
+                            current_working_step = 'tool list generation'
+                            if not install_folder[-1] == '/':
+                                install_folder = install_folder + '/'
+                            if not os.path.isdir(install_folder + 'workflowResults'):
+                                os.mkdir(install_folder + 'workflowResults')
+                            if not os.path.isdir(install_folder + 'workingDirectoryRCE'):
+                                os.mkdir(install_folder + 'workingDirectoryRCE')
+                            file_for_tool_list = open(path_to_tool_json_files + 'toolListUNICADOworkflow.txt', 'a')
+                            file_for_tool_list.write('workflowResults' + '\n')
+                            file_for_tool_list.write('workingDirectoryRCE' + '\n')
+                            file_for_tool_list.close()
+
+                            # loop across all elements from temporary zip directory to install UNICADO
+                            for content in content_of_zip_directory:
+                                current_working_step = 'installation of ' + content
+                                # open text file to write tool list
+                                file_for_tool_list = open(path_to_tool_json_files + 'toolListUNICADOworkflow.txt', 'a')
+                                path_of_content = path_to_temp + '/' + name_of_zip[:-4] + '/' + content
+                                if os.path.isdir(path_of_content):
+                                    if not content == 'workflowComponent':
+                                        # add tool name to tool list file
+                                        file_for_tool_list.write(content + '\n')
+                                        file_for_tool_list.close()
+                                        # copy design tool to install directory
+                                        src_path = Path(path_of_content).resolve()
+                                        dst_path = Path(install_folder + content).resolve()
+                                        if os.name == "nt":
+                                            shutil.copytree(r"\\?\{}".format(src_path), r"\\?\{}".format(dst_path))
+                                        else:
+                                            shutil.copytree(src_path, dst_path)
+
+                                        # copy design tool to origin design tool directory
+                                        if not content == 'projects':
+                                            src_path = Path(path_of_content).resolve()
+                                            dst_path = Path(path_to_tool_json_files + 'originUnicadoDesignTools/' + content).resolve()
+                                            if os.name == "nt":
+                                                shutil.copytree(r"\\?\{}".format(src_path), r"\\?\{}".format(dst_path))
+                                            else:
+                                                shutil.copytree(src_path, dst_path)
+
+                                        # copy aircraft projects to origin projects directory
+                                        else:
+                                            src_path = Path(path_of_content).resolve()
+                                            dst_path = Path(path_to_tool_json_files + 'originUnicadoProjects/' + content).resolve()
+                                            if os.name == "nt":
+                                                shutil.copytree(r"\\?\{}".format(src_path), r"\\?\{}".format(dst_path))
+                                            else:
+                                                shutil.copytree(src_path, dst_path)
+
+                                        # copy tool json file to hidden .rce directory
+                                        if not content == 'projects' and not content == 'unicadoRuntimeLibs':
+                                            path_json_file = path_to_temp + '/' + name_of_zip[:-4] \
+                                                            + '/workflowComponent/jsonFiles/' + content
+                                            # check if a sjson file of current tool exist
+                                            if os.path.isdir(path_json_file):
+                                                src_path = Path(path_json_file).resolve()
+                                                dst_path = Path(path_to_tool_json_files + '/' + content).resolve()
+                                                if os.name == "nt":
+                                                    shutil.copytree(r"\\?\{}".format(src_path), r"\\?\{}".format(dst_path))
+                                                else:
+                                                    shutil.copytree(src_path, dst_path)
+                                                # write paths to json configuration file of each module
+                                                with open(path_to_tool_json_files + content + '/configuration.json',
+                                                        'r+') as jsonFile:
+                                                    json_data = json.load(jsonFile)
+                                                launch_settings = json_data['launchSettings']
+                                                launch_settings[0]['rootWorkingDirectory'] =\
+                                                    install_folder + 'workingDirectoryRCE'
+                                                launch_settings[0]['toolDirectory'] = install_folder + content
+                                                if content in python_module_list:
+                                                    if os.name == 'posix':
+                                                        commandScriptLinux = json_data['commandScriptLinux']
+                                                        json_data['commandScriptLinux'] = \
+                                                            (installed_python_versions[python_count] + ' ' + commandScriptLinux)
+                                                    else:
+                                                        commandScriptWindows = json_data['commandScriptWindows']
+                                                        json_data['commandScriptWindows'] = \
+                                                            (installed_python_versions[python_count] + ' ' + commandScriptWindows)
+                                                json.dump(json_data, open(path_to_tool_json_files + content
+                                                                        + '/configuration.json', 'w'),
+                                                        indent=2, sort_keys=False)
+
+                                        # update ui
+                                        install_percent += percent
+                                        self.install_progress_bar.setValue(install_percent)
+                                        QCoreApplication.processEvents()
+
+                                    # installation of standalone workflow components
+                                    elif content == 'workflowComponent':
+                                        current_working_step = 'installation of ' + content
+                                        if not os.path.isdir(path_of_content + '/UNICADOworkflow'):
+                                            os.makedirs(path_of_content + '/UNICADOworkflow')
+                                        
+                                        # copy workflow file to istallation directory    
+                                        src_path = Path(path_of_content + '/UNICADOworkflow').resolve()
+                                        dst_path = Path(install_folder + '/workingDirectoryRCE/UNICADOworkflow').resolve()
+                                        if os.name == "nt":
+                                            shutil.copytree(r"\\?\{}".format(src_path), r"\\?\{}".format(dst_path))
+                                        else:
+                                            shutil.copytree(src_path, dst_path)    
+                                        
+                                        workflow_file_path = \
+                                            install_folder + '/workingDirectoryRCE/UNICADOworkflow/UNICADOworkflow.wf'
+                                        if os.path.isfile(workflow_file_path):
+                                            with open(workflow_file_path, "r") as workflow_file:
+                                                json_data = workflow_file.read()  # Read the entire file as a string
+
+                                                # Replace the placeholder with the desired value
+                                                print(installed_python_versions[python_count].replace(os.sep, '/'))
+                                                updated_json_data = \
+                                                    json_data.replace('${pythonExecutionPath}', 
+                                                                      installed_python_versions[python_count].replace(os.sep, '/'))
+
+                                            # Validate the JSON to ensure it's still valid
+                                            try:
+                                                data = json.loads(updated_json_data)  # Parse the updated JSON
+                                                print("JSON is valid. Writing updates back to the same file...")
+                                                
+                                                # Write the updated JSON back to the same file
+                                                with open(workflow_file_path, "w") as file:
+                                                    file.write(updated_json_data)
+                                                
+                                                # create back-up file of workflow
+                                                if os.path.isfile(install_folder + '/workingDirectoryRCE/UNICADOworkflow/UNICADOworkflow_backUp.wf'):
+                                                    os.remove(install_folder + '/workingDirectoryRCE/UNICADOworkflow/UNICADOworkflow_backUp.wf')
+                                                
+                                                # copy workflow back-up file to istallation directory    
+                                                src_path = Path(workflow_file_path).resolve()
+                                                dst_path = Path(install_folder + '/workingDirectoryRCE/UNICADOworkflow/UNICADOworkflow_backUp.wf').resolve()
+                                                if os.name == "nt":
+                                                    shutil.copyfile(r"\\?\{}".format(src_path), r"\\?\{}".format(dst_path))
+                                                else:
+                                                    shutil.copyfile(src_path, dst_path)
+                                                print(f"Updated JSON has been written to {workflow_file_path}")
+                                            except json.JSONDecodeError as e:
+                                                print(f"Error: The JSON structure is invalid after replacement. {e}")
+                            
+                                        # copy json files to origin design tool directory
+                                        if not os.path.isdir(path_to_tool_json_files
+                                                            + 'originUnicadoDesignTools/UNICADOworkflow/jsonFiles'):
+                                            os.makedirs(path_to_tool_json_files
+                                                        + 'originUnicadoDesignTools/UNICADOworkflow/jsonFiles')
+
+                                        list_of_json_files = os.listdir(path_of_content + '/jsonFiles')
+                                        for json_file in list_of_json_files:
+                                            # copy module json files to hidden .rce directory    
+                                            src_path = Path(path_of_content + '/jsonFiles/' + json_file).resolve()
+                                            dst_path = Path(path_to_tool_json_files
+                                                            + 'originUnicadoDesignTools/UNICADOworkflow/jsonFiles/'
+                                                            + json_file).resolve()
+                                            if os.name == "nt":
+                                                shutil.copytree(r"\\?\{}".format(src_path), r"\\?\{}".format(dst_path))
+                                            else:
+                                                shutil.copytree(src_path, dst_path)
+
+                                        # update ui
+                                        install_percent += percent
+                                        self.install_progress_bar.setValue(install_percent)
+                                        QCoreApplication.processEvents()
+                                 
+                            # check if the current operating system a linux os -> if true: -> Remove TiGL Viewer and change execution rights
+                            if os.name == 'posix':
+                                # call function to remove TiGL viewer workflow component and its connections within the workflow, since deprecated on linux
+                                remove_tigl_entry_from_wf_file(install_folder + 'workingDirectoryRCE/UNICADOworkflow/UNICADOworkflow.wf')
+                                # call function to change the execution rights on linux os of each module
+                                change_execution_rights_on_linux(install_folder)
+
+                        # else condition: unzipping of installer data failed -> display error message and abort installation
+                        else:
+                            error_flag = True
+                            self.welcome_panel.setVisible(True)
+                            self.integration_panel.setVisible(False)
+                            self.header_panel.setVisible(False)
+                            self.welcome_text_label_1.setText('Attention! An internal error has occurred!')
+                            self.install_text_label_1.setText('Unzipping of installation components failed!')
+                            self.install_text_label_2.setText('Please reinstall UNICADOworkflow or contact the'
+                                                            ' developer team.')
+                            self.continue_text_label.setText('To close the installer, click Abort.')
+                            self.update_button.setVisible(False)
+                            self.update_button.setEnabled(True)
+                            self.cancel_button.setText('Abort')
+                            self.cancel_button.setEnabled(True)
+                            self.cancel_button.setVisible(True)
+                            self.next_button.setVisible(False)
+                            QCoreApplication.processEvents()
+
+                        # delete temporary files from system after successfully installation
+                        if os.path.isdir(path_to_temp + '/' + name_of_zip[:-4]):
+                            shutil.rmtree(path_to_temp + '/' + name_of_zip[:-4])
+                            # update ui
+                            install_percent += percent
+                            self.install_progress_bar.setValue(install_percent)
+                            QCoreApplication.processEvents()
+
+                    except OSError:
+                        error_flag = True
+                        self.welcome_panel.setVisible(True)
+                        self.integration_panel.setVisible(False)
+                        self.header_panel.setVisible(False)
+                        self.welcome_text_label_1.setText('Attention! An internal error has occurred!')
+                        self.install_text_label_1.setText('Error during ' + current_working_step + '!')
+                        self.install_text_label_2.setText('Please reinstall UNICADOworkflow or contact the developer team.')
+                        self.continue_text_label.setText('To close the installer, click Abort.')
+                        self.update_button.setVisible(False)
+                        self.update_button.setEnabled(True)
+                        self.cancel_button.setText('Abort')
+                        self.cancel_button.setEnabled(True)
+                        self.cancel_button.setVisible(True)
+                        self.next_button.setVisible(False)
+                        QCoreApplication.processEvents()
+                        
+                    # Try to install python required packages
+                    if not error_flag:
+                        if os.path.isdir(install_folder + '/lib'):
+                            # Try to install own unicado python packages
+                            try:
+                                own_package_list = \
+                                    open(os.path.join(path_to_resources, 
+                                                      'own_python_packages.txt').replace(os.sep, '/'), 'r')
+                                for own_package in own_package_list:
+                                    clean_position = own_package.find('\n')
+                                    if clean_position != -1:
+                                        own_package = own_package[:clean_position]
+                                    if os.path.isdir(install_folder + 'lib/' + own_package):
+                                        # Suppress output using devnull and platform-specific logic
+                                        with open(os.devnull, 'w') as devnull:
+                                            if os.name == "nt":
+                                                startupinfo = subprocess.STARTUPINFO()
+                                                startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
+                                                subprocess.check_call([installed_python_versions[python_count], 
+                                                                       "-m", "pip", "install", "-e", "."],
+                                                                       cwd=install_folder + 'lib/' + own_package,
+                                                                       stdout=devnull, stderr=devnull, 
+                                                                       startupinfo=startupinfo)
+                                            else:  # For Linux/macOS
+                                                subprocess.check_call(
+                                                    [installed_python_versions[python_count],
+                                                     "-m", "pip", "install", "-e", "."],
+                                                    cwd=install_folder + 'lib/' + own_package,
+                                                    stdout=devnull, stderr=devnull)
+                                                
+                                    # Update UI
+                                    install_percent += percent
+                                    self.install_progress_bar.setValue(install_percent)
+                                    QCoreApplication.processEvents()
+
+                                # Copy package list file and store Python path
+                                src_path = Path(os.path.join(path_to_resources, 'own_python_packages.txt').replace(os.sep, '/')).resolve()
+                                dst_path = Path(path_to_tool_json_files + 'unicado_own_python_packages.txt').resolve()
+                                if os.name == "nt":
+                                    shutil.copyfile(r"\\?\{}".format(src_path), r"\\?\{}".format(dst_path))
+                                else:
+                                    shutil.copyfile(src_path, dst_path)
+                                with open(path_to_tool_json_files + 'unicado_python_path.txt', 'w') as python_path_file:
+                                    python_path_file.write(installed_python_versions[python_count])
+
+                            except OSError:
+                                print('Error: The file "own_python_packages.txt" could not be opened!')
+                        else:
+                            print('Attention: The lib directory could not be found inside of the UNICADO installation.\n'
+                                '           Required own Python packages could not be installed.')
+
+                        # Try to install required standard python packages
+                        try:
+                            standard_package_list = \
+                                open(os.path.join(path_to_resources, 
+                                                  'standard_python_packages.txt').replace(os.sep, '/'), 'r')
+                            for standard_python_package in standard_package_list:
+                                clean_position = standard_python_package.find('\n')
+                                if clean_position != -1:
+                                    standard_python_package = standard_python_package[:clean_position]
+                                with open(os.devnull, 'w') as devnull:
+                                    if os.name == "nt":
+                                        startupinfo = subprocess.STARTUPINFO()
+                                        startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
+                                        subprocess.check_call([installed_python_versions[python_count],
+                                                               "-m", "pip", "install", standard_python_package],
+                                                               stdout=devnull, stderr=devnull, 
+                                                               startupinfo=startupinfo)
+                                    else:  # For Linux/macOS
+                                        subprocess.check_call(
+                                            [installed_python_versions[python_count], 
+                                             "-m", "pip", "install", standard_python_package],
+                                            stdout=devnull, stderr=devnull)
+                                        
+                                # Update UI
+                                install_percent += percent
+                                self.install_progress_bar.setValue(install_percent)
+                                QCoreApplication.processEvents()
+                        except OSError:
+                            print('Error: The file "standard_python_packages.txt" could not be opened!')
+            
+                # else condition: installer zip file not found -> display error message and abort installation
+                else:
+                    error_flag = True
+                    self.welcome_panel.setVisible(True)
+                    self.integration_panel.setVisible(False)
+                    self.header_panel.setVisible(False)
+                    self.welcome_text_label_1.setText('Attention! An internal error has occurred!')
+                    self.install_text_label_1.setText('Standalone installation packages not found!')
+                    self.install_text_label_2.setText('Please reinstall UNICADOworkflow or contact the developer team.')
+                    self.continue_text_label.setText('To close the installer, click Abort.')
+                    self.update_button.setVisible(False)
+                    self.update_button.setEnabled(True)
+                    self.cancel_button.setText('Abort')
+                    self.cancel_button.setEnabled(True)
+                    self.cancel_button.setVisible(True)
+                    self.next_button.setVisible(False)
+                    QCoreApplication.processEvents()
+                
+            # else condition: version file not found -> display error message and abort installation
+            else:
+                error_flag = True
+                self.welcome_panel.setVisible(True)
+                self.integration_panel.setVisible(False)
+                self.header_panel.setVisible(False)
+                self.welcome_text_label_1.setText('Attention! An internal error has occurred!')
+                if not status_flag:
+                    self.install_text_label_1.setText('At least two installer application are currently running!')
+                    self.install_text_label_2.setText('Please wait until all other installations are completed '
+                                                    'and try again.')
+                else:
+                    self.install_text_label_1.setText('Version file not found!')
+                    self.install_text_label_2.setText('Please reinstall UNICADOworkflow or contact the developer team.')
+                self.continue_text_label.setText('To close the installer, click Abort.')
+                self.update_button.setVisible(False)
+                self.update_button.setEnabled(True)
+                self.cancel_button.setText('Abort')
+                self.cancel_button.setEnabled(True)
+                self.cancel_button.setVisible(True)
+                self.next_button.setVisible(False)
+                QCoreApplication.processEvents()
+        
+        # Python check is failed -> display error message and abort installation
+        else:
+            error_flag = True
+            self.welcome_panel.setVisible(True)
+            self.integration_panel.setVisible(False)
+            self.header_panel.setVisible(False)
+            self.welcome_text_label_1.setText('Attention! An internal error has occurred!')
+            if not status_flag:
+                self.install_text_label_1.setText(python_error_string_1)
+                self.install_text_label_2.setText(python_error_string_2)
+            else:
+                self.install_text_label_1.setText(python_error_string_1)
+                self.install_text_label_2.setText(python_error_string_2)
+            self.continue_text_label.setText('To close the installer, click Abort.')
+            self.update_button.setVisible(False)
+            self.update_button.setEnabled(True)
+            self.cancel_button.setText('Abort')
+            self.cancel_button.setEnabled(True)
+            self.cancel_button.setVisible(True)
+            self.next_button.setVisible(False)
+            QCoreApplication.processEvents()
+
+    # else condition: the repository installation is selected
+    else:
+        ''' initialize local parameter '''
+        path_to_software_tools = str()
+        path_to_aircraft_projects = str()
+        path_to_aircraft_design_tools = str()
+
+        # read UNICADO install path from line edit field of install panel
+        install_folder = self.install_path_line_edit.text()
+        install_folder = install_folder.replace(os.sep, '/')
+        last_character = install_folder[-1]
+        # check if the last character of install path is not '/'
+        #  -> if true: -> add '/' to the end of path of install folder
+        if not (last_character == '/'):
+            install_folder = install_folder + '/'
+        path_of_origin_tool_directory = self.repository_path_line_edit.text()
+        path_of_origin_tool_directory = path_of_origin_tool_directory.replace(os.sep, '/')
+        last_character = path_of_origin_tool_directory[-1]
+
+        # check if the last character of repository path is not '/'
+        #  -> if true: -> add '/' to the end of path of repositories
+        if not (last_character == '/'):
+            path_of_origin_tool_directory = path_of_origin_tool_directory + '/'
+
+        # create path-files for UNICADOworkflow
+        user_path_string = os.path.expanduser("~")
+        user_path_string = user_path_string.replace(os.sep, '/')
+        user_path_string = user_path_string + '/'
+        path_to_tool_json_files = user_path_string + '.rce/default/integration/tools/common/'
+
+        # check if the .rce system path for json tool integration is not existing
+        #  -> if true: -> generate directories recursively
+        if not os.path.isdir(path_to_tool_json_files):
+            os.makedirs(path_to_tool_json_files)
+
+        # read repository paths from .git configuration files and set repository paths to copy files
+        files = os.listdir(path_of_origin_tool_directory)
+        for fileName in files:
+            check_if_file_is_directory = os.path.isdir(path_of_origin_tool_directory + fileName)
+            if check_if_file_is_directory:
+                check_git_folder = os.path.isdir(path_of_origin_tool_directory + fileName + '/.git')
+                if check_git_folder:
+                    check_config_file = os.path.isfile(path_of_origin_tool_directory + fileName + '/.git/config')
+                    if check_config_file:
+                        config = configparser.ConfigParser()
+                        config.read(path_of_origin_tool_directory + fileName + '/.git/config')
+                        if config.has_section('remote "origin"'):
+                            url = config['remote "origin"']['url']
+                            if url == 'ssh://git@unicado.ilr.rwth-aachen.de:2222/source/rADDITIONALSOFTWARE.git':
+                                path_to_software_tools = path_of_origin_tool_directory + fileName + '/'
+
+                            if url == 'ssh://git@unicado.ilr.rwth-aachen.de:2222/source/rAircraftDesign.git':
+                                path_to_aircraft_design_tools = path_of_origin_tool_directory + fileName + '/'
+
+                            if url == 'ssh://git@unicado.ilr.rwth-aachen.de:2222/source/rAIRCRAFTREFERENCES.git':
+                                path_to_aircraft_projects = path_of_origin_tool_directory + fileName + '/'
+
+        # create list of tools from origin tool directory
+        files_in_origin_tool_directory = os.listdir(path_to_aircraft_design_tools)
+        copy_count = len(files_in_origin_tool_directory)
+        percent = int(round(100 / copy_count, 0))
+
+        # generate text file for RCE with install directory
+        file_for_install_path = open(path_to_tool_json_files + 'absolutPathToUNICADOInstallDirectory.txt', 'w')
+        file_for_install_path.write(install_folder)
+        file_for_install_path.close()
+        install_percent += percent
+        self.install_progress_bar.setValue(install_percent)
+        QCoreApplication.processEvents()
+
+        # delete standalone flag file if it is existing
+        if os.path.isfile(path_to_tool_json_files + 'standAloneInstallationFlag.dat'):
+            os.remove(path_to_tool_json_files + 'standAloneInstallationFlag.dat')
+
+        # generate text file for RCE with repository directory
+        file_for_repository_path = open(path_to_tool_json_files + 'absolutPathToUNICADOrepositoryDirectory.txt', 'w')
+        file_for_repository_path.write(path_of_origin_tool_directory)
+        file_for_repository_path.close()
+        install_percent += percent
+        self.install_progress_bar.setValue(install_percent)
+        QCoreApplication.processEvents()
+        time.sleep(1)
+
+        # generate working directory for RCE
+        if not os.path.isdir(install_folder + 'workingDirectoryRCE'):
+            os.makedirs(install_folder + 'workingDirectoryRCE/UNICADOworkflow')
+            os.mkdir(install_folder + 'workingDirectoryRCE/temporaryResults')
+
+        # copy workflow files to working directory
+        files_to_copy_for_workflow = os.listdir(path_to_aircraft_design_tools + 'UNICADOworkflow/UNICADOworkFlowOnRCE')
+        for file in files_to_copy_for_workflow:
+            if os.path.isdir(path_to_aircraft_design_tools + 'UNICADOworkflow/UNICADOworkFlowOnRCE/' + file):
+                source = path_to_aircraft_design_tools + 'UNICADOworkflow/UNICADOworkFlowOnRCE/' + file
+                destination = install_folder + 'workingDirectoryRCE/UNICADOworkflow/' + file
+                shutil.copytree(source, destination)
+            if os.path.isfile(path_to_aircraft_design_tools + 'UNICADOworkflow/UNICADOworkFlowOnRCE/' + file):
+                source = path_to_aircraft_design_tools + 'UNICADOworkflow/UNICADOworkFlowOnRCE/' + file
+                destination = install_folder + 'workingDirectoryRCE/UNICADOworkflow/' + file
+                shutil.copyfile(source, destination)
+            QCoreApplication.processEvents()
+
+        shutil.copyfile(path_to_aircraft_design_tools + 'UNICADOworkflow/UNICADOworkflow_conf.xml',
+                        install_folder + 'workingDirectoryRCE/UNICADOworkflow/UNICADOworkflow_conf.xml')
+        shutil.copyfile(path_to_aircraft_design_tools + 'UNICADOworkflow/version.txt',
+                        install_folder + 'workingDirectoryRCE/UNICADOworkflow/workingVersion.txt')
+        install_percent += percent
+        file_for_tool_list = open(path_to_tool_json_files + 'toolListUNICADOworkflow.txt', 'a')
+        file_for_tool_list.write('workingDirectoryRCE' + '\n')
+        file_for_tool_list.close()
+        self.install_progress_bar.setValue(install_percent)
+        QCoreApplication.processEvents()
+
+        if os.name == 'posix':
+            remove_tigl_entry_from_wf_file(install_folder + 'workingDirectoryRCE/UNICADOworkflow/UNICADOworkflow.wf')
+
+        # generate directory for workflow results
+        check_flag_workflow_results = os.path.isdir(install_folder + 'workflowResults')
+        if not check_flag_workflow_results:
+            os.mkdir(install_folder + '/workflowResults')
+        install_percent += percent
+        file_for_tool_list = open(path_to_tool_json_files + 'toolListUNICADOworkflow.txt', 'a')
+        file_for_tool_list.write('workflowResults' + '\n')
+        file_for_tool_list.close()
+        self.install_progress_bar.setValue(install_percent)
+        QCoreApplication.processEvents()
+
+        # for all modules in repositories, copy to install directory
+        test_list_json_files = os.listdir(path_to_aircraft_design_tools + 'UNICADOworkflow/jsonFiles/')
+        for fileName in test_list_json_files:  # files_in_origin_tool_directory:
+            if not (fileName == '.git') and not (fileName == 'template') and not (fileName == 'UNICADOworkflow') \
+                    and not (fileName == 'convergenceLoop'):
+                # check if fileName a directory
+                check_for_directory = os.path.isdir(path_to_aircraft_design_tools + fileName)
+                check_for_software_tool = os.path.isdir(path_to_software_tools + fileName)
+                check_existing_json = os.path.isdir(path_to_aircraft_design_tools
+                                                    + 'UNICADOworkflow/jsonFiles/' + fileName)
+                # if true -> copy design tool to workingDirectory
+                if check_for_directory and check_existing_json:
+                    file_for_tool_list = open(path_to_tool_json_files + 'toolListUNICADOworkflow.txt', 'a')
+                    file_name_content = os.listdir(path_to_aircraft_design_tools + fileName)
+                    os.mkdir(install_folder + fileName)
+                    for content in file_name_content:
+                        # check if content is a directory -> if true: -> check if content is not equal to 'src'
+                        #  -> if true: -> copy content to install folder of current module
+                        if os.path.isdir(path_to_aircraft_design_tools + fileName + '/' + content):
+                            # check if data is not equal to src
+                            #  -> if true: -> copy data from origin to working directory
+                            if not content == 'src':
+                                shutil.copytree(path_to_aircraft_design_tools + fileName + '/' + content,
+                                                install_folder + fileName + '/' + content)
+
+                        # else condition: content is a file -> copy content to install folder of current module
+                        else:
+                            shutil.copyfile(path_to_aircraft_design_tools + fileName + '/' + content,
+                                            install_folder + fileName + '/' + content)
+
+                    # check if the json file of current module is not existing in .rce directory
+                    #  -> if true: -> copy json data to .rce directory
+                    if not os.path.isdir(path_to_tool_json_files + fileName):
+                        shutil.copytree(path_to_aircraft_design_tools + 'UNICADOworkflow/jsonFiles/' + fileName,
+                                        path_to_tool_json_files + fileName)
+                    # else condition: json file of current module is existing in .rce directory
+                    #  -> replace old files by json files of current module
+                    else:
+                        shutil.rmtree(path_to_tool_json_files + fileName)
+                        shutil.copytree(path_to_aircraft_design_tools + 'UNICADOworkflow/jsonFiles/' + fileName,
+                                        path_to_tool_json_files + fileName)
+
+                    # write tool name to tool list and close file
+                    file_for_tool_list.write(fileName + '\n')
+                    file_for_tool_list.close()
+
+                    # write paths to json configuration file of each module
+                    with open(path_to_tool_json_files + fileName + '/configuration.json', 'r+') as jsonFile:
+                        json_data = json.load(jsonFile)
+                    launch_settings = json_data['launchSettings']
+                    launch_settings[0]['rootWorkingDirectory'] = install_folder + 'workingDirectoryRCE'
+                    launch_settings[0]['toolDirectory'] = install_folder + fileName
+                    json.dump(json_data, open(path_to_tool_json_files + fileName + '/configuration.json', 'w'),
+                              indent=2, sort_keys=False)
+                    # update progress bar
+                    install_percent += percent
+                    self.install_progress_bar.setValue(install_percent)
+                    QCoreApplication.processEvents()
+
+                # if true -> copy software tool to workingDirectory
+                #  -> cpacsInterface is handled separately in the following lines of this function
+                if check_for_software_tool and check_existing_json and not (fileName == 'cpacsInterface'):
+                    file_for_tool_list = open(path_to_tool_json_files + 'toolListUNICADOworkflow.txt', 'a')
+                    shutil.copytree(path_to_software_tools + fileName, install_folder + fileName)
+                    check_tool_file = os.path.isdir(path_to_tool_json_files + fileName)
+                    if not check_tool_file:
+                        shutil.copytree(path_to_aircraft_design_tools + 'UNICADOworkflow/jsonFiles/' + fileName,
+                                        path_to_tool_json_files + fileName)
+                    else:
+                        shutil.rmtree(path_to_tool_json_files + fileName)
+                        shutil.copytree(path_to_aircraft_design_tools + 'UNICADOworkflow/jsonFiles/' + fileName,
+                                        path_to_tool_json_files + fileName)
+                    file_for_tool_list.write(fileName + '\n')
+                    # write paths to json configuration file of each module
+                    with open(path_to_tool_json_files + fileName + '/configuration.json', 'r+') as jsonFile:
+                        json_data = json.load(jsonFile)
+                    launch_settings = json_data['launchSettings']
+                    launch_settings[0]['rootWorkingDirectory'] = install_folder + 'workingDirectoryRCE'
+                    launch_settings[0]['toolDirectory'] = install_folder + fileName
+                    json.dump(json_data, open(path_to_tool_json_files + fileName + '/configuration.json', 'w'),
+                              indent=2, sort_keys=False)
+                    # update progress bar
+                    install_percent += percent
+                    self.install_progress_bar.setValue(install_percent)
+                    file_for_tool_list.close()
+                    QCoreApplication.processEvents()
+
+        # copy project folder to install directory
+        files_in_origin_project_directory = os.listdir(path_to_aircraft_projects)
+        for fileName in files_in_origin_project_directory:
+            if not (fileName == '.git'):
+                # check if fileName a directory
+                check_for_directory = os.path.isdir(path_to_aircraft_projects + fileName)
+                if check_for_directory:
+                    shutil.copytree(path_to_aircraft_projects + fileName, install_folder + 'projects/' + fileName)
+                    # copy CPACS exchange file to all aircraft projects
+                    if os.path.isfile(path_to_software_tools
+                                      + 'cpacsInterface/_zeroFiles/Cpacs_aircraft/Cpacs_aircraft.xml'):
+                        shutil.copyfile(path_to_software_tools
+                                        + 'cpacsInterface/_zeroFiles/Cpacs_aircraft/Cpacs_aircraft.xml',
+                                        install_folder + 'projects/' + fileName + '/' + fileName + '_CPACS.xml')
+
+        # update progress bar
+        install_percent += percent
+        file_for_tool_list = open(path_to_tool_json_files + 'toolListUNICADOworkflow.txt', 'a')
+        file_for_tool_list.write('projects' + '\n')
+        file_for_tool_list.close()
+        self.install_progress_bar.setValue(install_percent)
+        QCoreApplication.processEvents()
+
+        # copy inkscape and gnuplot to working directory
+        # check for Windows OS
+        if os.name == 'nt':
+            file_for_tool_list = open(path_to_tool_json_files + 'toolListUNICADOworkflow.txt', 'a')
+            if not os.path.isdir(install_folder + 'inkscape'):
+                shutil.copytree(path_to_software_tools + 'inkscape', install_folder + 'inkscape')
+                file_for_tool_list.write('inkscape' + '\n')
+            if not os.path.isdir(install_folder + 'gnuplot'):
+                shutil.copytree(path_to_software_tools + 'gnuplot', install_folder + 'gnuplot')
+                file_for_tool_list.write('gnuplot' + '\n')
+            # update progress bar
+            install_percent += percent
+            file_for_tool_list.close()
+            self.install_progress_bar.setValue(install_percent)
+            QCoreApplication.processEvents()
+
+        # check for linux OS
+        if os.name == 'posix':
+            file_for_tool_list = open(path_to_tool_json_files + 'toolListUNICADOworkflow.txt', 'a')
+            if not os.path.isdir(install_folder + 'inkscape-linux'):
+                shutil.copytree(path_to_software_tools + 'inkscape-linux', install_folder + 'inkscape-linux')
+                file_for_tool_list.write('inkscape-linux' + '\n')
+            if not os.path.isdir(install_folder + 'gnuplot-linux'):
+                shutil.copytree(path_to_software_tools + 'gnuplot-linux', install_folder + 'gnuplot-linux')
+                file_for_tool_list.write('gnuplot-linux' + '\n')
+            # update progress bar
+            install_percent += percent
+            file_for_tool_list.close()
+            self.install_progress_bar.setValue(install_percent)
+            QCoreApplication.processEvents()
+
+        # copy cpacsInterface to working directory
+        if not os.path.isdir(install_folder + 'cpacsInterface'):
+            file_for_tool_list = open(path_to_tool_json_files + 'toolListUNICADOworkflow.txt', 'a')
+            file_name_content = os.listdir(path_to_software_tools + 'cpacsInterface')
+            os.mkdir(install_folder + 'cpacsInterface')
+            for data in file_name_content:
+                if os.path.isfile(path_to_software_tools + 'cpacsInterface/' + data):
+                    shutil.copyfile(path_to_software_tools + 'cpacsInterface/' + data,
+                                    install_folder + 'cpacsInterface/' + data)
+                    # check if data a directory, then replace with directory from origin tool directory
+                if os.path.isdir(path_to_software_tools + 'cpacsInterface/' + data):
+                    # check if data is not equal to src or convertUNICADO2CPACS
+                    #  -> if true: -> copy data from origin to working directory
+                    if not data == 'src' and not data == 'convertUNICADO2CPACS':
+                        shutil.copytree(path_to_software_tools + 'cpacsInterface/' + data,
+                                        install_folder + 'cpacsInterface/' + data)
+                    # check if data is equal to convertUNICADO2CPACS
+                    #  -> if true: -> copy all content inside the origin directory out of the src directory
+                    #   to working copy
+                    if data == 'convertUNICADO2CPACS':
+                        data_inside = os.listdir(path_to_software_tools + 'cpacsInterface/' + data)
+                        os.mkdir(install_folder + 'cpacsInterface/' + data)
+                        for element in data_inside:
+                            if not element == 'src':
+                                if os.path.isfile(path_to_software_tools + 'cpacsInterface/' + data + '/' + element):
+                                    shutil.copyfile(path_to_software_tools + 'cpacsInterface/' + data + '/' + element,
+                                                    install_folder + 'cpacsInterface/' + data + '/' + element)
+                                else:
+                                    shutil.copytree(path_to_software_tools + 'cpacsInterface/' + data + '/' + element,
+                                                    install_folder + 'cpacsInterface/' + data + '/' + element)
+
+            # check if the json file of cpacsInterface is not existing in the .rce directory
+            #  -> if true: -> copy file to .rce directory
+            check_tool_file = os.path.isdir(path_to_tool_json_files + 'cpacsInterface')
+            if not check_tool_file:
+                shutil.copytree(path_to_aircraft_design_tools + 'UNICADOworkflow/jsonFiles/cpacsInterface',
+                                path_to_tool_json_files + 'cpacsInterface')
+
+            # else condition: json file of cpacsInterface is existing
+            #  -> delete old file and copy current version to .rce directory
+            else:
+                shutil.rmtree(path_to_tool_json_files + 'cpacsInterface')
+                shutil.copytree(path_to_aircraft_design_tools + 'UNICADOworkflow/jsonFiles/cpacsInterface',
+                                path_to_tool_json_files + 'cpacsInterface')
+            # write paths to json configuration file of each module
+            with open(path_to_tool_json_files + 'cpacsInterface' + '/configuration.json', 'r+') as jsonFile:
+                json_data = json.load(jsonFile)
+            launch_settings = json_data['launchSettings']
+            launch_settings[0]['rootWorkingDirectory'] = install_folder + 'workingDirectoryRCE'
+            launch_settings[0]['toolDirectory'] = install_folder + 'cpacsInterface'
+            json.dump(json_data, open(path_to_tool_json_files + '/cpacsInterface' + '/configuration.json', 'w'),
+                      indent=2, sort_keys=False)
+            # update progress bar
+            install_percent += percent
+            file_for_tool_list.write('cpacsInterface' + '\n')
+            file_for_tool_list.close()
+            self.install_progress_bar.setValue(install_percent)
+            QCoreApplication.processEvents()
+
+    if not error_flag:
+        # check if the current operating system is windows -> if true: -> check if the installation directory is empty
+        #  -> if true: -> delete install directory
+        if os.name == 'nt':
+            if os.path.isdir('C:/Programs/UNICADOworkflow'):
+                if not os.listdir('C:/Programs/UNICADOworkflow'):
+                    os.rmdir('C:/Programs/UNICADOworkflow')
+
+                # check if the parent directory of install directory is empty -> if true: -> delete parent directory
+                if not os.listdir('C:/Programs'):
+                    os.rmdir('C:/Programs')
+
+        # check if the current operating system is linux -> if true: -> check if the installation directory is empty
+        #  -> if true: -> delete install directory
+        if os.name == 'posix':
+            user_path_string = os.path.expanduser("~")
+            user_path_string = user_path_string.replace(os.sep, '/')
+            user_path_string = user_path_string + '/'
+            if os.path.isdir(user_path_string + 'UNICADOworkflow'):
+                if not os.listdir(user_path_string + 'UNICADOworkflow'):
+                    os.rmdir(user_path_string + 'UNICADOworkflow')
+
+        # write absolute paths to json configuration file of each module
+        path_to_settings_file = user_path_string + '.rce/default/internal/'
+        if not os.path.isdir(user_path_string + '.rce/default/internal/'):
+            os.makedirs(user_path_string + '.rce/default/internal/')
+
+        if not os.path.isfile(user_path_string + '.rce/default/internal/settings.json'):
+            json_data = {'rce.workspace.recentLocations': '',
+                         'rce.workspace.lastLocation': '',
+                         'rce.workspace.dontAskAgain': 'false'}
+            # Write JSON file
+            with open(user_path_string + '.rce/default/internal/settings.json', 'w') as jsonFile:
+                json.dump(json_data, open(path_to_settings_file + 'settings.json', 'w'))
+
+        if os.path.isfile(user_path_string + '.rce/default/internal/settings.json'):
+            with open(path_to_settings_file + 'settings.json', 'r+') as jsonFile:
+                # check if settings.json file is empty
+                try:
+                    json_data = json.load(jsonFile)
+                except OSError:
+                    json_data = {'rce.workspace.recentLocations': '',
+                                 'rce.workspace.lastLocation': '',
+                                 'rce.workspace.dontAskAgain': 'false'}
+            workspace_location_rce = json_data['rce.workspace.recentLocations']
+
+            # check if the current operating system is windows
+            #  -> if true: -> set windows specific path to workingDirectoryRCE as default path to RCE
+            if os.name == 'nt':
+                install_path = install_folder.replace('/', '\\')
+                alternate_path = install_path.replace('\\', '\\\\')
+                json_data['rce.workspace.lastLocation'] = install_path + 'workingDirectoryRCE'
+                if not install_path[0] + '\:' + '\\' + install_path[3:] + 'workingDirectoryRCE' in workspace_location_rce:
+                    if not install_path[0] + '\:' + alternate_path[2:] + 'workingDirectoryRCE' \
+                           in workspace_location_rce:
+                        json_data['rce.workspace.recentLocations'] = install_path[0] + '\:' + alternate_path[2:] \
+                                                                     + 'workingDirectoryRCE' + ':' \
+                                                                     + workspace_location_rce
+                        install_percent += percent
+                        self.install_progress_bar.setValue(int(install_percent))
+                        QCoreApplication.processEvents()
+
+                    else:
+                        str_start = workspace_location_rce.index(
+                            install_path[0] + '\:' + alternate_path[2:] + 'workingDirectoryRCE')
+                        str_end = workspace_location_rce.index('workingDirectoryRCE')
+                        if str_start > 0:
+                            sub_string_front = workspace_location_rce[0:str_start - 1]
+                            total_length = len(workspace_location_rce)
+                            new_string = workspace_location_rce[str_start:str_end + 19] + ':' + sub_string_front
+                            if str_end + 19 < total_length:
+                                sub_string_end = workspace_location_rce[str_end + 20:total_length]
+                                new_string = new_string + ':' + sub_string_end
+                            json_data['rce.workspace.recentLocations'] = new_string
+                            install_percent += percent
+                            self.install_progress_bar.setValue(int(install_percent))
+                            QCoreApplication.processEvents()
+
+            #  check if the current operating system is linux
+            #   -> if true: -> set linux specific path to workingDirectoryRCE as default path to RCE
+            if os.name == 'posix':
+                json_data['rce.workspace.lastLocation'] = install_folder + 'workingDirectoryRCE'
+                if not install_folder + 'workingDirectoryRCE' in workspace_location_rce:
+                    json_data['rce.workspace.recentLocations'] = install_folder + 'workingDirectoryRCE' + ':' \
+                                                                 + workspace_location_rce
+                    QCoreApplication.processEvents()
+
+            # check if rce.workspace.dontAskAgain exist and set to false
+            if 'rce.workspace.dontAskAgain' in json_data:
+                json_data['rce.workspace.dontAskAgain'] = 'false'
+            else:
+                json_data['rce.workspace.dontAskAgain'] = 'false'
+
+            json.dump(json_data, open(path_to_settings_file + 'settings.json', 'w'))
+
+        # update install process bar and set value to 100%
+        self.install_progress_bar.setValue(100)
+        self.next_button.setVisible(False)
+        self.cancel_button.setVisible(True)
+        QCoreApplication.processEvents()
+
+    else:
+        if os.path.isfile(path_to_tool_json_files + 'standAloneInstallationFlag.dat'):
+            os.remove(path_to_tool_json_files + 'standAloneInstallationFlag.dat')
+
+def install_unicado_headless(install_dir: Path):
+    error_flag = False
+    # read UNICADO install path from line edit field of install panel
+    install_folder = install_dir
+    install_folder = str(install_folder.absolute()).replace(os.sep, '/')
+    if not os.path.isdir(install_folder):
+        os.makedirs(install_folder)
+
+    # create path-files for UNICADOworkflow
+    user_path_string = os.path.expanduser("~")
+    user_path_string = user_path_string.replace(os.sep, '/')
+    user_path_string = user_path_string + '/'
+    path_to_tool_json_files = user_path_string + '.rce/default/integration/tools/common/'
+
+    # check if the .rce system path for json tool integration is not existing
+    #  -> if true: -> generate directories recursively
+    if not os.path.isdir(path_to_tool_json_files):
+        os.makedirs(path_to_tool_json_files)
+
+    # check if a standalone origin design tool directory is not existing in the .rce folder
+    #  -> if true: -> generate directories recursively
+    if not os.path.isdir(path_to_tool_json_files + 'originUnicadoDesignTools'):
+        os.makedirs(path_to_tool_json_files + 'originUnicadoDesignTools/UNICADOworkflow')
+
+    # check if a standalone origin software tool directory is not existing in the .rce folder
+    #  -> if true: -> generate directories recursively
+    if not os.path.isdir(path_to_tool_json_files + 'originUnicadoSoftwareTools'):
+        os.makedirs(path_to_tool_json_files + 'originUnicadoSoftwareTools')
+
+    # check if a standalone origin software tool directory is not existing in the .rce folder
+    #  -> if true: -> generate directories recursively
+    if not os.path.isdir(path_to_tool_json_files + 'originUnicadoProjects'):
+        os.makedirs(path_to_tool_json_files + 'originUnicadoProjects')
+
+    # generate standalone flag file in .rce directory
+    if not os.path.isfile(path_to_tool_json_files + 'standAloneInstallationFlag.dat'):
+        with open(path_to_tool_json_files + 'standAloneInstallationFlag.dat', 'w') as file:
+            file.close()
+
+    # delete repository path file if it is existing
+    if os.path.isfile(path_to_tool_json_files + 'absolutPathToUNICADOrepositoryDirectory.txt'):
+        os.remove(path_to_tool_json_files + 'absolutPathToUNICADOrepositoryDirectory.txt')
+
+    # get path to temporary working directory including the version txt-file
+    version_file = 'version.txt'
+    path_to_version_file, status_flag = resource_path(version_file)
+
+    # check if the version text file is really existing -> if true: -> read version number from txt-file
+    if os.path.isfile(path_to_version_file) and status_flag:
+        file = open(path_to_version_file, 'r')
+        version_number = file.read()
+        file.close()
+
+        # get path to temporary working directory including the installation zip-file
+        if os.name == 'posix':
+            name_of_zip = 'UNICADO-' + version_number + '-Linux.zip'
+        else:
+            name_of_zip = 'UNICADO-' + version_number + '-win64.zip'
+        index = path_to_version_file.rfind('/')
+        path_to_zip = path_to_version_file[:index] + '/' + name_of_zip
+        path_to_temp = path_to_version_file[:index]
+
+        # check if the installation zip file is really existing
+        if os.path.isfile(path_to_zip):
+            # delete old temporary zip directory if it is existing
+            if os.path.isdir(path_to_temp + '/' + name_of_zip[:-4]):
+                shutil.rmtree(path_to_temp + '/' + name_of_zip[:-4])
+
+            # try to unzip installer data an install workflow component
+            try:
+                with ZipFile(path_to_zip, 'r') as zObject:
+                    # Extracting specific file in the zip into a specific location
+                    zObject.extractall(path=path_to_temp)
+                    zObject.close()
+
+                if os.path.isdir(path_to_temp + '/' + name_of_zip[:-4]):
+                    content_of_zip_directory = os.listdir(path_to_temp + '/' + name_of_zip[:-4])
+
+                    # generate text file for RCE with install directory
+                    file_for_install_path = open(path_to_tool_json_files
+                                                    + 'absolutPathToUNICADOInstallDirectory.txt', 'w')
+                    file_for_install_path.write(install_folder + '/')
+                    file_for_install_path.close()
+
+                    # generate results and working directory
+                    if not install_folder[-1] == '/':
+                        install_folder = install_folder + '/'
+                    if not os.path.isdir(install_folder + 'workflowResults'):
+                        os.mkdir(install_folder + 'workflowResults')
+                    if not os.path.isdir(install_folder + 'workingDirectoryRCE'):
+                        os.mkdir(install_folder + 'workingDirectoryRCE')
+                    file_for_tool_list = open(path_to_tool_json_files + 'toolListUNICADOworkflow.txt', 'a')
+                    file_for_tool_list.write('workflowResults' + '\n')
+                    file_for_tool_list.write('workingDirectoryRCE' + '\n')
+                    file_for_tool_list.close()
+
+                    # loop across all elements from temporary zip directory to install UNICADO
+                    for content in content_of_zip_directory:
+                        # open text file to write tool list
+                        file_for_tool_list = open(path_to_tool_json_files + 'toolListUNICADOworkflow.txt', 'a')
+                        path_of_content = path_to_temp + '/' + name_of_zip[:-4] + '/' + content
+                        if os.path.isdir(path_of_content):
+                            if not content == 'softwareTools' and not content == 'workflowComponent':
+                                # add tool name to tool list file
+                                file_for_tool_list.write(content + '\n')
+                                file_for_tool_list.close()
+                                # copy design tool to install directory
+                                shutil.copytree(path_of_content, install_folder + content)
+
+                                # check if current content equal to the unicado library directory
+                                #  -> if true: -> add path to local environment variables
+                                if content == 'unicadoRuntimeLibs':
+                                    path_to_add_to_environment = install_folder + content
+                                    status_path_adding = write_path_to_environment(path_to_add_to_environment)
+
+                                # copy design tool to origin design tool directory
+                                if not content == 'projects':
+                                    shutil.copytree(path_of_content,
+                                                    path_to_tool_json_files + 'originUnicadoDesignTools/' + content)
+
+                                # copy aircraft projects to origin projects directory
+                                else:
+                                    shutil.copytree(path_of_content,
+                                                    path_to_tool_json_files + 'originUnicadoProjects/' + content)
+
+                                # copy tool json file to hidden .rce directory
+                                if not content == 'projects' and not content == 'unicadoRuntimeLibs':
+                                    path_json_file = path_to_temp + '/' + name_of_zip[:-4] \
+                                                        + '/workflowComponent/jsonFiles/' + content
+                                    # check if a sjson file of current tool exist
+                                    if os.path.isdir(path_json_file):
+                                        shutil.copytree(path_json_file, path_to_tool_json_files + '/' + content)
+                                        # write paths to json configuration file of each module
+                                        with open(path_to_tool_json_files + content + '/configuration.json',
+                                                    'r+') as jsonFile:
+                                            json_data = json.load(jsonFile)
+                                        launch_settings = json_data['launchSettings']
+                                        launch_settings[0]['rootWorkingDirectory'] =\
+                                            install_folder + 'workingDirectoryRCE'
+                                        launch_settings[0]['toolDirectory'] = install_folder + content
+                                        json.dump(json_data, open(path_to_tool_json_files + content
+                                                                    + '/configuration.json', 'w'),
+                                                    indent=2, sort_keys=False)
+
+                            elif content == 'softwareTools':
+                                file_for_tool_list.close()
+                                content_of_software_tools = os.listdir(path_of_content)
+                                # loop across all tools in the directory to install os specific software version
+                                for software_tool in content_of_software_tools:
+                                    file_for_tool_list = open(path_to_tool_json_files
+                                                                + 'toolListUNICADOworkflow.txt', 'a')
+                                    # check if the current software tool contains the string 'gnuplot' or 'inkscape'
+                                    #  if true: -> install os dependent software version
+                                    if 'gnuplot' in software_tool or 'inkscape' in software_tool:
+                                        if os.name == 'nt':
+                                            if not os.path.isdir(install_folder + 'gnuplot'):
+                                                shutil.copytree(path_of_content + '/gnuplot',
+                                                                install_folder + 'gnuplot')
+                                                # copy tool to software design tool directory
+                                                shutil.copytree(path_of_content,
+                                                                path_to_tool_json_files
+                                                                + 'originUnicadoSoftwareTools/gnuplot')
+                                                # add tool name to tool list file
+                                                file_for_tool_list.write('gnuplot' + '\n')
+
+                                            if not os.path.isdir(install_folder + 'inkscape'):
+                                                shutil.copytree(path_of_content + '/inkscape',
+                                                                install_folder + 'inkscape')
+                                                # copy tool to software design tool directory
+                                                shutil.copytree(path_of_content,
+                                                                path_to_tool_json_files
+                                                                + 'originUnicadoSoftwareTools/inkscape')
+                                                # add tool name to tool list file
+                                                file_for_tool_list.write('inkscape' + '\n')
+
+                                        # check for linux OS
+                                        if os.name == 'posix':
+                                            if not os.path.isdir(install_folder + 'gnuplot-linux'):
+                                                shutil.copytree(path_of_content + '/gnuplot-linux',
+                                                                install_folder + 'gnuplot-linux')
+                                                # copy tool to software design tool directory
+                                                shutil.copytree(path_of_content,
+                                                                path_to_tool_json_files
+                                                                + 'originUnicadoSoftwareTools/gnuplot-linux')
+                                                # add tool name to tool list file
+                                                file_for_tool_list.write('gnuplot-linux' + '\n')
+
+                                                if not os.path.isdir(install_folder + 'inkscape-linux'):
+                                                    shutil.copytree(path_of_content + '/inkscape-linux',
+                                                                    install_folder + 'inkscape-linux')
+                                                    # copy tool to software design tool directory
+                                                    shutil.copytree(path_of_content,
+                                                                    path_to_tool_json_files
+                                                                    + 'originUnicadoSoftwareTools/inkscape-linux')
+                                                    # add tool name to tool list file
+                                                    file_for_tool_list.write('inkscape-linux' + '\n')
+
+                                        file_for_tool_list.close()
+
+                                    else:
+                                        # copy software tool to install directory
+                                        shutil.copytree(path_of_content + '/' + software_tool,
+                                                        install_folder + software_tool)
+                                        # copy tool to software design tool directory
+                                        shutil.copytree(path_of_content + '/' + software_tool,
+                                                        path_to_tool_json_files
+                                                        + 'originUnicadoSoftwareTools/' + software_tool)
+
+                                        # add tool name to tool list file
+                                        file_for_tool_list.write(software_tool + '\n')
+                                        file_for_tool_list.close()
+
+                                        # copy tool json file to hidden .rce directory
+                                        path_json_file = path_to_temp + '/' + name_of_zip[:-4] \
+                                            + '/workflowComponent/jsonFiles/' + software_tool
+                                        # check if a sjson file of current tool exist
+                                        if os.path.isdir(path_json_file):
+                                            shutil.copytree(path_json_file,
+                                                            path_to_tool_json_files + '/' + software_tool)
+                                            # write paths to json configuration file of each module
+                                            with open(path_to_tool_json_files + software_tool
+                                                        + '/configuration.json', 'r+') as jsonFile:
+                                                json_data = json.load(jsonFile)
+                                            launch_settings = json_data['launchSettings']
+                                            launch_settings[0]['rootWorkingDirectory'] = \
+                                                install_folder + 'workingDirectoryRCE'
+                                            launch_settings[0]['toolDirectory'] = install_folder + software_tool
+                                            json.dump(json_data, open(path_to_tool_json_files + software_tool
+                                                                        + '/configuration.json', 'w'),
+                                                        indent=2, sort_keys=False)
+
+                            # installation of standalone workflow components
+                            elif content == 'workflowComponent':
+                                if not os.path.isdir(path_of_content + '/UNICADOworkflow'):
+                                    os.makedirs(path_of_content + '/UNICADOworkflow')
+
+                                shutil.copytree(path_of_content + '/UNICADOworkflow',
+                                                install_folder + '/workingDirectoryRCE/UNICADOworkflow')
+
+                                # copy json files to origin design tool directory
+                                if not os.path.isdir(path_to_tool_json_files
+                                                        + 'originUnicadoDesignTools/UNICADOworkflow/jsonFiles'):
+                                    os.makedirs(path_to_tool_json_files
+                                                + 'originUnicadoDesignTools/UNICADOworkflow/jsonFiles')
+
+                                list_of_json_files = os.listdir(path_of_content + '/jsonFiles')
+                                for json_file in list_of_json_files:
+                                    shutil.copytree(path_of_content + '/jsonFiles/' + json_file,
+                                                    path_to_tool_json_files
+                                                    + 'originUnicadoDesignTools/UNICADOworkflow/jsonFiles/'
+                                                    + json_file)
+
+                    # check if the current operating system a linux os -> if true: -> Remove TiGL Viewer and change execution rights
+                    if os.name == 'posix':
+                        # call function to remove TiGL viewer workflow component and its connections within the workflow, since deprecated on linux
+                        remove_tigl_entry_from_wf_file(install_folder + 'workingDirectoryRCE/UNICADOworkflow/UNICADOworkflow.wf')
+                        # call function to change the execution rights on linux os of each module
+                        change_execution_rights_on_linux(install_folder)
+
+                # else condition: unzipping of installer data failed -> display error message and abort installation
+                else:
+                    error_flag = True
+
+                # delete temporary files from system after successfully installation
+                if os.path.isdir(path_to_temp + '/' + name_of_zip[:-4]):
+                    shutil.rmtree(path_to_temp + '/' + name_of_zip[:-4])
+
+            except OSError:
+                error_flag = True
+
+        # else condition: installer zip file not found -> display error message and abort installation
+        else:
+            error_flag = True
+
+    # else condition: version file not found -> display error message and abort installation
+    else:
+        error_flag = True
+
+    if not error_flag:
+        # check if the current operating system is windows -> if true: -> check if the installation directory is empty
+        #  -> if true: -> delete install directory
+        if os.name == 'nt':
+            if os.path.isdir('C:/Programs/UNICADOworkflow'):
+                if not os.listdir('C:/Programs/UNICADOworkflow'):
+                    os.rmdir('C:/Programs/UNICADOworkflow')
+
+                # check if the parent directory of install directory is empty -> if true: -> delete parent directory
+                if not os.listdir('C:/Programs'):
+                    os.rmdir('C:/Programs')
+
+        # check if the current operating system is linux -> if true: -> check if the installation directory is empty
+        #  -> if true: -> delete install directory
+        if os.name == 'posix':
+            user_path_string = os.path.expanduser("~")
+            user_path_string = user_path_string.replace(os.sep, '/')
+            user_path_string = user_path_string + '/'
+            if os.path.isdir(user_path_string + 'UNICADOworkflow'):
+                if not os.listdir(user_path_string + 'UNICADOworkflow'):
+                    os.rmdir(user_path_string + 'UNICADOworkflow')
+
+        # write absolute paths to json configuration file of each module
+        path_to_settings_file = user_path_string + '.rce/default/internal/'
+        if not os.path.isdir(user_path_string + '.rce/default/internal/'):
+            os.makedirs(user_path_string + '.rce/default/internal/')
+
+        if not os.path.isfile(user_path_string + '.rce/default/internal/settings.json'):
+            json_data = {'rce.workspace.recentLocations': '',
+                         'rce.workspace.lastLocation': '',
+                         'rce.workspace.dontAskAgain': 'false'}
+            # Write JSON file
+            with open(user_path_string + '.rce/default/internal/settings.json', 'w') as jsonFile:
+                json.dump(json_data, open(path_to_settings_file + 'settings.json', 'w'))
+
+        if os.path.isfile(user_path_string + '.rce/default/internal/settings.json'):
+            with open(path_to_settings_file + 'settings.json', 'r+') as jsonFile:
+                # check if settings.json file is empty
+                try:
+                    json_data = json.load(jsonFile)
+                except OSError:
+                    json_data = {'rce.workspace.recentLocations': '',
+                                 'rce.workspace.lastLocation': '',
+                                 'rce.workspace.dontAskAgain': 'false'}
+            workspace_location_rce = json_data['rce.workspace.recentLocations']
+
+            # check if the current operating system is windows
+            #  -> if true: -> set windows specific path to workingDirectoryRCE as default path to RCE
+            if os.name == 'nt':
+                install_path = install_folder.replace('/', '\\')
+                alternate_path = install_path.replace('\\', '\\\\')
+                json_data['rce.workspace.lastLocation'] = install_path + 'workingDirectoryRCE'
+                if not install_path[0] + '\:' + '\\' + install_path[3:] + 'workingDirectoryRCE' in workspace_location_rce:
+                    if not install_path[0] + '\:' + alternate_path[2:] + 'workingDirectoryRCE' \
+                           in workspace_location_rce:
+                        json_data['rce.workspace.recentLocations'] = install_path[0] + '\:' + alternate_path[2:] \
+                                                                     + 'workingDirectoryRCE' + ':' \
+                                                                     + workspace_location_rce
+
+                    else:
+                        str_start = workspace_location_rce.index(
+                            install_path[0] + '\:' + alternate_path[2:] + 'workingDirectoryRCE')
+                        str_end = workspace_location_rce.index('workingDirectoryRCE')
+                        if str_start > 0:
+                            sub_string_front = workspace_location_rce[0:str_start - 1]
+                            total_length = len(workspace_location_rce)
+                            new_string = workspace_location_rce[str_start:str_end + 19] + ':' + sub_string_front
+                            if str_end + 19 < total_length:
+                                sub_string_end = workspace_location_rce[str_end + 20:total_length]
+                                new_string = new_string + ':' + sub_string_end
+                            json_data['rce.workspace.recentLocations'] = new_string
+
+            #  check if the current operating system is linux
+            #   -> if true: -> set linux specific path to workingDirectoryRCE as default path to RCE
+            if os.name == 'posix':
+                json_data['rce.workspace.lastLocation'] = install_folder + 'workingDirectoryRCE'
+                if not install_folder + 'workingDirectoryRCE' in workspace_location_rce:
+                    json_data['rce.workspace.recentLocations'] = install_folder + 'workingDirectoryRCE' + ':' \
+                                                                 + workspace_location_rce
+
+            # check if rce.workspace.dontAskAgain exist and set to false
+            if 'rce.workspace.dontAskAgain' in json_data:
+                json_data['rce.workspace.dontAskAgain'] = 'false'
+            else:
+                json_data['rce.workspace.dontAskAgain'] = 'false'
+
+            json.dump(json_data, open(path_to_settings_file + 'settings.json', 'w'))
+
+    else:
+        if os.path.isfile(path_to_tool_json_files + 'standAloneInstallationFlag.dat'):
+            os.remove(path_to_tool_json_files + 'standAloneInstallationFlag.dat')
\ No newline at end of file
diff --git a/installer/sub_functions/integration_step.py b/installer/sub_functions/integration_step.py
new file mode 100644
index 0000000000000000000000000000000000000000..4ae865a49856ad0c2a4454e6bf707b72a83d87fe
--- /dev/null
+++ b/installer/sub_functions/integration_step.py
@@ -0,0 +1,196 @@
+# imports for python
+import os
+import time
+import shutil
+from PyQt5.QtCore import QCoreApplication
+from sub_functions.check_tool import check_tool
+from sub_functions.write_json_file import write_json_file
+from sub_functions.repository_integration import repository_integration
+
+
+# function to handle module integration steps
+def integration_step(self):
+    # handle ui objects for visibility
+    self.welcome_panel.setVisible(False)
+    self.header_panel.setVisible(True)
+    self.integration_panel.setVisible(True)
+    self.update_button.setVisible(False)
+    self.update_button.setEnabled(False)
+    self.uninstall_button.setVisible(False)
+    self.uninstall_button.setEnabled(False)
+    self.next_button.setVisible(True)
+    self.next_button.setEnabled(False)
+    self.next_button.setText('Next >')
+    self.cancel_button.setText('Cancel')
+    self.back_button.setVisible(True)
+    self.back_button.setEnabled(True)
+    self.integration_button.setVisible(False)
+    self.integration_button.setEnabled(False)
+    self.tool_name_panel.setVisible(True)
+
+    # set description to text fields
+    self.header_text_label_1.setText('Welcome to the UNICADO module integration tool.')
+    self.header_text_label_2.setText('This tool will guide you through the model integration.')
+    self.integration_text_label_1.setText('Please enter the name of tool to be integrated and click OK.\n'
+                                          "Attention: The tool name must be written in 'camelCase'"
+                                          " and consist of two words.\n"
+                                          'As example: "initialSizing".')
+
+    # check if the module integration tool is running the first time in the current UNICADOworkflow version
+    user_path_string = os.path.expanduser("~")
+    user_path_string = user_path_string.replace(os.sep, '/')
+    user_path_string = user_path_string + '/'
+    path_to_tool_json_files = user_path_string + '.rce/default/integration/tools/common/'
+    if not os.path.isfile(path_to_tool_json_files + 'standardToolListUNICADOworkflow.txt'):
+        shutil.copyfile(path_to_tool_json_files + 'toolListUNICADOworkflow.txt',
+                        path_to_tool_json_files + 'standardToolListUNICADOworkflow.txt')
+
+    tool_name = self.tool_name_panel_edit.text()
+    if not tool_name == 'Please enter name of tool to be integrated':
+        check_tool(self)
+
+    string = self.integration_text_label_0.text()
+    hex_string = ''
+    for char in string:
+        dual = ' '.join(format(ord(x), 'b') for x in char)
+        hex_string += f'{int(dual, 2):X}'
+
+    self.integration_text_label_0.setText(hex_string)
+
+    # update ui
+    QCoreApplication.processEvents()
+
+
+# function to perform tool integration
+def perform_integration(self):
+    # initialize local parameter
+    repo_error = 0
+    tool_flag = False
+    error_flag = False
+    install_path = str()
+    installed_tool_list = []
+    tool_name = self.tool_name_panel_edit.text()
+    group_name = self.group_name_panel_edit.text()
+
+    # get install path of UNICADOworkflow
+    user_path_string = os.path.expanduser("~")
+    user_path_string = user_path_string.replace(os.sep, '/')
+    user_path_string = user_path_string + '/'
+    path_to_tool_json_files = user_path_string + '.rce/default/integration/tools/common/'
+
+    # check if the file containing the installation path exists
+    if os.path.isfile(path_to_tool_json_files + 'absolutPathToUNICADOInstallDirectory.txt'):
+        read_install_path = open(path_to_tool_json_files + 'absolutPathToUNICADOInstallDirectory.txt', 'r')
+        install_path = read_install_path.read()
+    else:
+        error_flag = True
+
+    # check if the file containing the names of installed tools exists
+    if os.path.isfile(path_to_tool_json_files + 'toolListUNICADOworkflow.txt'):
+        installed_tool_list = open(path_to_tool_json_files + 'toolListUNICADOworkflow.txt', 'r')
+        for tool in installed_tool_list:
+            if tool_name == tool[:-1]:
+                tool_flag = True
+        installed_tool_list.close()
+        installed_tool_list = open(path_to_tool_json_files + 'toolListUNICADOworkflow.txt', 'a')
+    else:
+        error_flag = True
+
+    # start integration if no error is occurred before
+    if not error_flag:
+        # call function to write user data from ui to configuration.json file of new tool
+        error_flag = write_json_file(self, path_to_tool_json_files, install_path, tool_name, group_name, error_flag,
+                                     False, '')
+
+        if not error_flag:
+            # copy tool to be integrated from locale directory to unicado installation directory
+            tool_path = self.tool_path_panel_edit.text()
+            # check if the tool overwriting option selected
+            #  -> if true: -> try to delete selected tool from install directory
+            if self.integration_radio_button_overwrite.isChecked():
+                if os.path.isdir(install_path + tool_name):
+                    shutil.rmtree(install_path + tool_name)
+
+            # check if the entered tool path not inside the unicado installation
+            #  -> if true: -> copy tool to installation directory
+            if not os.path.isdir(install_path + tool_name):
+                shutil.copytree(tool_path, install_path + tool_name)
+
+            # write tool name to list of installed tools text file
+            if tool_flag:
+                installed_tool_list.close()
+            else:
+                installed_tool_list.write(tool_name + '\n')
+                installed_tool_list.close()
+
+            # check if the repository integration is selected
+            if self.integration_checkbox.isChecked():
+                # call function to integrate or overwrite tool in working branch of repository
+                repo_error, error_flag = repository_integration(self)
+                print(repo_error)
+                print(error_flag)
+
+    # an error is occurred -> prepare ui to display error message
+    if error_flag:
+        installed_tool_list.close()
+        self.welcome_panel.setVisible(True)
+        self.install_and_finish_panel.setVisible(False)
+        self.header_panel.setVisible(False)
+        self.update_button.setVisible(False)
+        self.update_button.setEnabled(True)
+        self.cancel_button.setText('Abort')
+        self.cancel_button.setEnabled(True)
+        self.cancel_button.setVisible(True)
+        self.next_button.setVisible(False)
+        QCoreApplication.processEvents()
+        if repo_error == 0:
+            self.welcome_text_label_1.setText('Attention! An Error has occurred!')
+            self.install_text_label_1.setText('Tool can not be integrated!')
+            self.install_text_label_2.setText('Please reinstall UNICADOworkflow. '
+                                              'After that please start the tool integration again.')
+            QCoreApplication.processEvents()
+
+        if repo_error == 1:
+            self.welcome_text_label_1.setText('Attention! An Error has occurred!')
+            self.install_text_label_1.setText('Tool could be integrated, but path to the aircraft design repository '
+                                              'could not be found. Repository integration failed!')
+            self.install_text_label_2.setText('Please check your repository installation and add the tool to the '
+                                              'repository manually.')
+            self.continue_text_label.setText('To quit the installer, click Finish.')
+            self.cancel_button.setText('Finish')
+            QCoreApplication.processEvents()
+
+        if repo_error == 2:
+            self.welcome_text_label_1.setText('Attention! An Error has occurred!')
+            self.install_text_label_1.setText('Tool could be integrated, but the automatic git checkout could not be '
+                                              'performed. Repository integration failed!')
+            self.install_text_label_2.setText('Please check your repository installation and add the tool to the '
+                                              'repository manually.')
+            self.continue_text_label.setText('To quit the installer, click Finish.')
+            self.cancel_button.setText('Finish')
+            QCoreApplication.processEvents()
+
+        if repo_error == 3:
+            self.welcome_text_label_1.setText('Attention! An Error has occurred!')
+            self.install_text_label_1.setText('Tool could be integrated, but the automatic json file generation failed.'
+                                              ' Repository integration only partially done!')
+            self.install_text_label_2.setText('Please check your repository installation and add the missing files to '
+                                              'the repository manually.')
+            self.continue_text_label.setText('To quit the installer, click Finish.')
+            self.cancel_button.setText('Finish')
+            QCoreApplication.processEvents()
+
+        if repo_error == 4:
+            self.welcome_text_label_1.setText('Attention! An Error has occurred!')
+            self.install_text_label_1.setText('Tool could be integrated, but the automatic repository commit failed. '
+                                              'Repository integration only partially done!')
+            self.install_text_label_2.setText('Please check your repository installation and perform the repository '
+                                              'commit manually.')
+            self.continue_text_label.setText('To quit the installer, click Finish.')
+            self.cancel_button.setText('Finish')
+            QCoreApplication.processEvents()
+
+    else:
+        time.sleep(3)
+
+    return error_flag
diff --git a/installer/sub_functions/last_step.py b/installer/sub_functions/last_step.py
new file mode 100644
index 0000000000000000000000000000000000000000..3945a8ee36e0963db24ee91b21336c95626acbc4
--- /dev/null
+++ b/installer/sub_functions/last_step.py
@@ -0,0 +1,134 @@
+# import for python
+import os
+from PyQt5 import QtCore
+from sub_functions.check_tool import check_tool
+
+
+def last_step(self):
+    """ Call function to handle the back button.
+
+        :rtype: object
+    """
+
+    header_panel_visibility = self.header_panel.isVisible()
+    install_path_panel_visibility = self.install_path_panel.isVisible()
+    integration_panel_visibility = self.integration_panel.isVisible()
+    repository_path_panel_visibility = self.repository_path_panel.isVisible()
+
+    if header_panel_visibility:
+        header_string = self.header_text_label_1.text()
+        if header_string == 'UNICADO workflow will be installed':
+            self.header_text_label_1.setText('Select UNICADO Repository Location')
+            self.header_text_label_2.setText('Select the folder in which UNICADO repositories lies.')
+
+        if header_string == 'Select UNICADO Repository Location':
+            self.header_text_label_1.setText('Choose Install Location')
+            self.header_text_label_2.setText('Chose the folder in which to install UNICADOworkflow.')
+
+    if install_path_panel_visibility:
+        self.welcome_panel.setVisible(True)
+        self.install_path_panel.setVisible(False)
+        self.header_panel.setVisible(False)
+        self.back_button.setVisible(False)
+
+    elif integration_panel_visibility:
+        tool_name_panel_visibility = self.tool_name_panel.isVisible()
+        tool_path_panel_visibility = self.tool_path_panel.isVisible()
+        header_string = self.header_text_label_1.text()
+        if tool_name_panel_visibility or self.next_button.text() == 'Uninstall' or self.next_button.text() == 'Update':
+            self.welcome_panel.setVisible(True)
+            self.integration_panel.setVisible(False)
+            self.header_panel.setVisible(False)
+            self.update_button.setVisible(True)
+            self.update_button.setEnabled(True)
+            self.uninstall_button.setVisible(True)
+            self.uninstall_button.setEnabled(True)
+            self.next_button.setVisible(False)
+            self.next_button.setEnabled(False)
+            self.back_button.setVisible(False)
+            self.back_button.setEnabled(False)
+            self.integration_button.setVisible(True)
+            self.integration_button.setEnabled(True)
+
+        elif tool_path_panel_visibility or header_string == 'Final steps to delete an integrated tool':
+            self.next_button.setText('Next >')
+            self.next_button.setEnabled(True)
+            self.tool_path_panel.setVisible(False)
+            self.tool_name_panel.setVisible(True)
+            self.tool_name_panel_edit_button.setVisible(True)
+            self.integration_combo_box.setVisible(False)
+            self.integration_text_label_2.setVisible(True)
+            self.integration_text_label_2.setGeometry(QtCore.QRect(20, 170, 410, 80))
+            self.integration_text_label_4.setGeometry(QtCore.QRect(20, 200, 410, 80))
+            self.integration_text_label_4.setVisible(False)
+            self.header_text_label_1.setText('Welcome to the UNICADO module integration tool.')
+            self.header_text_label_2.setText('This tool will guide you through the model integration.')
+            self.integration_text_label_1.setText(
+                'Please enter the name of tool to be integrated and click OK.\n'
+                "Attention: The tool name must be written in 'camelCase'"
+                " and consist of two words.\n"
+                'As example: "initialSizing".')
+            self.integration_text_label_3.setVisible(False)
+            self.group_name_panel.setVisible(False)
+            if self.integration_radio_button_delete.isChecked() or self.integration_radio_button_overwrite.isChecked():
+                self.button_name_panel.setVisible(True)
+
+        else:
+            self.next_button.setEnabled(False)
+            self.next_button.setText('Next >')
+            self.header_text_label_1.setText('Please select tool path and workflow group')
+            self.header_text_label_2.setText('')
+            self.integration_text_label_2.setVisible(False)
+            self.integration_text_label_1.setText('Please enter the local system path to the integrating tool.')
+            self.tool_name_panel.setVisible(False)
+            self.tool_name_panel_edit_button.setVisible(False)
+            self.tool_name_panel.setVisible(False)
+            self.tool_path_panel.setVisible(True)
+            self.tool_path_panel_browse_button.setText('Browse')
+            self.button_group_panel.setVisible(False)
+            self.integration_text_label_5.setVisible(False)
+            self.checkbox_panel.setVisible(False)
+
+            tool_name = self.tool_name_panel_edit.text()
+            local_tool_folder = self.tool_path_panel_edit.text()
+            if not local_tool_folder == 'Click Browse to enter local tool path':
+                content_of_directory = os.listdir(local_tool_folder)
+                if os.path.isdir(local_tool_folder + '/' + tool_name):
+                    self.integration_text_label_3.setVisible(True)
+                    self.integration_combo_box.setVisible(False)
+                    self.integration_text_label_3.setText(
+                        'Attention: There is no executable file with the entered tool name in the selected directory. '
+                        'Please change path.')
+                else:
+                    if tool_name in content_of_directory or tool_name + '.exe' in content_of_directory:
+                        self.integration_text_label_3.setVisible(True)
+                        self.integration_combo_box.setVisible(True)
+                        self.integration_text_label_3.setText(
+                            'Please select the group in which the tool is to be integrated.')
+                        selected_group = self.integration_combo_box.currentText()
+                        if selected_group == '- please select a tool group -' or selected_group == '- other -':
+                            self.integration_text_label_4.setVisible(False)
+                            self.next_button.setEnabled(False)
+                            self.group_name_panel.setVisible(False)
+                            if selected_group == '- other -':
+                                self.group_name_panel.setVisible(True)
+                                input_string = self.group_name_panel_edit.text()
+                                if not input_string == 'Please enter tool group name.':
+                                    check_tool(self)
+                        else:
+                            self.group_name_panel.setVisible(False)
+                            self.integration_text_label_4.setText(
+                                "Please click 'Next' to continue the tool integration.")
+                            self.integration_text_label_4.setVisible(True)
+                            self.next_button.setEnabled(True)
+                    else:
+                        self.integration_text_label_3.setVisible(True)
+                        self.integration_text_label_3.setText(
+                            'Attention: There is no executable file with the entered tool name '
+                            'in the selected directory. '
+                            'Please change path.')
+
+    elif repository_path_panel_visibility:
+        self.install_path_panel.setVisible(True)
+        self.repository_path_panel.setVisible(False)
+        self.next_button.setEnabled(True)
diff --git a/installer/sub_functions/line_edit.py b/installer/sub_functions/line_edit.py
new file mode 100644
index 0000000000000000000000000000000000000000..e3abbdd1bba536fc46fcbcc05f6f314877b18383
--- /dev/null
+++ b/installer/sub_functions/line_edit.py
@@ -0,0 +1,108 @@
+def line_edit(self):
+    """ Call function to handle the line edit field.
+
+        :rtype: object
+    """
+
+    ''' imports for python '''
+    import os
+    import shutil
+    import configparser
+    from PyQt5.QtCore import QCoreApplication
+
+    # check if the installation panel is shown in the installer application
+    #  -> if true: -> read install path from line edit-field of installer application
+    install_path_panel_visibility = self.install_path_panel.isVisible()
+    repository_path_panel_visibility = self.repository_path_panel.isVisible()
+    checkbox_panel_visibility = self.checkbox_panel.isVisible()
+    install_folder = self.install_path_line_edit.text()
+    install_folder = str(install_folder.replace(os.sep, '/'))
+    if install_path_panel_visibility:
+        # check if the current operating system is windows -> if true: -> check for necessary administrator rights
+        if os.name == 'nt':
+            # check if the 'C:/Program Files' is not existing -> if true:
+            #  -> try to generate a test folder inside of current hard drive directory to check for necessary administrator rights
+            try:
+                if os.path.isdir(install_folder):
+                    os.mkdir(install_folder + '/test')
+                    shutil.rmtree(install_folder + '/test')
+                self.install_path_text_label_1.setText("ATTENTION: If UNICADOworkflow is to be installed in "
+                                                       "C:/Program Files or C:/Program Files (x86), the installer and "
+                                                       "RCE must be executed with administrator rights. Ensure that you"
+                                                       " have these rights.")
+                QCoreApplication.processEvents()
+
+            # exception handling if necessary administrator rights not existing
+            #  -> set UNICADO install path to 'C:/Programs/UNICADOworkflow/'
+            except OSError:
+                install_folder = 'C:/Programs/UNICADOworkflow/'
+                self.install_path_text_label_1.setText("ATTENTION: Please note that you do not have the necessary "
+                                                       "administrator rights for the installation in the selected "
+                                                       "directory. Installation continues in "
+                                                       "C:/Programs/UNICADOworkflow/.")
+                self.install_path_line_edit.setText(install_folder)
+                QCoreApplication.processEvents()
+
+    # check if the select repository panel is shown in the installer application
+    #  -> if true: -> check if all necessary repositories exist and set git url path
+    if repository_path_panel_visibility:
+        self.next_button.setEnabled(False)
+        QCoreApplication.processEvents()
+        input_string = self.repository_path_line_edit.text()
+        input_string = str(input_string.replace(os.sep, '/'))
+        if os.path.isdir(input_string):
+            folders_in_directory = os.listdir(input_string)
+            for folder in folders_in_directory:
+                path_to_check = input_string + '/' + folder + '/.git'
+                if os.path.isdir(path_to_check):
+                    if os.path.isfile(input_string + folder + '/.git/config'):
+                        config = configparser.ConfigParser()
+                        config.read(input_string + folder + '/.git/config')
+                        if config.has_section('remote "origin"'):
+                            url = config['remote "origin"']['url']
+                            if url == 'ssh://git@unicado.ilr.rwth-aachen.de:2222/source/rADDITIONALSOFTWARE.git':
+                                self.next_button.setEnabled(True)
+                                QCoreApplication.processEvents()
+
+    if checkbox_panel_visibility:
+        stars = str()
+        string = self.integration_text_label_0.text()
+        user_input = self.checkbox_panel_text_label_0.text()
+        input_string = self.checkbox_panel_edit.text().upper()
+
+        # password manager to handle user input string
+        if input_string[:-1] == 'ENTER PASSWORD':
+            input_string = ''
+            self.integration_checkbox_show.setVisible(False)
+
+        if len(input_string) > 0:
+            self.integration_checkbox_show.setVisible(True)
+            diff = len(input_string) - len(user_input)
+            if diff < 0:
+                if diff == -1:
+                    self.checkbox_panel_text_label_0.setText(user_input[:-1])
+                elif -1*diff >= len(input_string):
+                    self.checkbox_panel_text_label_0.setText(input_string)
+                else:
+                    self.checkbox_panel_text_label_0.setText(user_input[:diff])
+            elif diff == 0:
+                self.checkbox_panel_text_label_0.setText(input_string)
+            else:
+                self.checkbox_panel_text_label_0.setText(user_input + input_string[len(user_input):len(user_input)+diff])
+
+            if string == self.checkbox_panel_text_label_0.text() and\
+                    (self.integration_radio_button_yes.isChecked() or self.integration_radio_button_no.isChecked()):
+                self.next_button.setEnabled(True)
+
+            if not self.integration_checkbox_show.isChecked():
+                for _ in input_string:
+                    stars += '*'
+            else:
+                stars = input_string
+        else:
+            stars = 'enter password'
+            self.checkbox_panel_text_label_0.setText('')
+            self.integration_checkbox_show.setVisible(False)
+
+        self.checkbox_panel_edit.setText(stars)
+        QCoreApplication.processEvents()
diff --git a/installer/sub_functions/next_step.py b/installer/sub_functions/next_step.py
new file mode 100644
index 0000000000000000000000000000000000000000..edfe8dd17f52842531a9fe72ed5a3b9564d5f703
--- /dev/null
+++ b/installer/sub_functions/next_step.py
@@ -0,0 +1,307 @@
+# imports for python
+import os
+import shutil
+from PyQt5 import QtCore
+from PyQt5.QtCore import QCoreApplication
+from sub_functions.check_tool import check_tool
+from sub_functions.delete_tool import delete_tool
+from sub_functions.update_steps import update_unicado
+from sub_functions.uninstall_steps import uninstall_unicado
+from sub_functions.integration_step import perform_integration
+
+
+def next_step(self):
+    """ Call function to handle the next button.
+
+        :rtype: object
+    """
+
+    welcome_panel_visibility = self.welcome_panel.isVisible()
+    header_panel_visibility = self.header_panel.isVisible()
+    install_path_panel_visibility = self.install_path_panel.isVisible()
+    repository_path_panel_visibility = self.repository_path_panel.isVisible()
+    integration_panel_visibility = self.integration_panel.isVisible()
+
+    if header_panel_visibility:
+        header_string = self.header_text_label_1.text()
+        if header_string == 'Choose Install Location':
+            self.header_text_label_1.setText('Select UNICADO Repository Location')
+            self.header_text_label_2.setText('Select the folder in which UNICADO repositories lies.')
+
+        if self.install_radio_button_repo.isChecked():
+            if header_string == 'Select UNICADO Repository Location':
+                self.header_text_label_1.setText('UNICADO workflow will be installed')
+                self.header_text_label_2.setText('This may take a moment.')
+
+    if welcome_panel_visibility:
+        user_path_string = os.path.expanduser("~")
+        user_path_string = user_path_string.replace(os.sep, '/')
+        user_path_string = user_path_string + '/'
+        check_for_existing_installation = os.path.isfile(user_path_string + '.rce/default/integration/tools/common/'
+                                                                            'absolutPathToUNICADOInstallDirectory.txt')
+        check_for_existing_repository_file = os.path.isfile(user_path_string + '.rce/default/integration/tools/common/'
+                                                                               'absolutPathToUNICADOrepositoryDirectory'
+                                                                               '.txt')
+        check_for_existing_tool_file = os.path.isfile(user_path_string + '.rce/default/integration/tools/common/'
+                                                                         'toolListUNICADOworkflow.txt')
+
+        if check_for_existing_installation or check_for_existing_repository_file or check_for_existing_tool_file:
+            self.next_button.setVisible(False)
+            self.integration_button.setVisible(True)
+            self.uninstall_button.setVisible(True)
+            self.update_button.setVisible(True)
+            if self.install_radio_button_repo.isChecked():
+                self.update_button.setEnabled(True)
+                self.welcome_text_label_1.setText('UNICADOworkflow is already installed')
+                self.install_text_label_1.setText('Please select if you want to Uninstall the existing installation or '
+                                                  'Update to the current version.')
+                self.install_text_label_2.setText('If you want to add a module click Tool Integration.')
+                self.continue_text_label.setText('To abort the installer, click Cancel.')
+            else:
+                self.update_button.setEnabled(False)
+                self.welcome_text_label_1.setText('UNICADOworkflow is already installed')
+                self.install_text_label_1.setText('Please select if you want to Uninstall the existing installation or '
+                                                  'if you want to Integrate a new tool.')
+                self.install_text_label_2.setText('Attention: The Update function is not available for standalone '
+                                                  'installations.')
+                self.continue_text_label.setText('To abort the installer, click Cancel.')
+        else:
+            if os.name == 'posix':
+                self.install_path_line_edit.setText(user_path_string + 'UNICADOworkflow')
+            self.header_panel.setVisible(True)
+            self.install_path_panel.setVisible(True)
+            self.back_button.setVisible(True)
+            self.welcome_panel.setVisible(False)
+            total, used, free = shutil.disk_usage("/")
+            self.install_path_text_label_3.setText("Disk space available:  %d GB" % (used // (2 ** 30)))
+
+    elif install_path_panel_visibility:
+        if self.install_radio_button_repo.isChecked():
+            self.repository_path_panel.setVisible(True)
+            self.install_path_panel.setVisible(False)
+            self.next_button.setEnabled(False)
+        else:
+            self.header_text_label_1.setText('UNICADO workflow will be installed')
+            self.header_text_label_2.setText('This may take a moment.')
+            self.install_and_finish_panel.setVisible(True)
+            self.repository_path_panel.setVisible(False)
+            self.back_button.setVisible(False)
+            self.next_button.setText('Install')
+            self.next_button.released.connect(self.installUNICADO)
+
+    elif repository_path_panel_visibility:
+        self.install_and_finish_panel.setVisible(True)
+        self.repository_path_panel.setVisible(False)
+        self.back_button.setVisible(False)
+        self.next_button.setText('Install')
+        self.next_button.released.connect(self.installUNICADO)
+
+    elif integration_panel_visibility:
+        tool_name_panel_visibility = self.tool_name_panel.isVisible()
+        tool_path_panel_visibility = self.tool_path_panel.isVisible()
+        radio_button_panel_visibility = self.button_group_panel.isVisible()
+
+        if self.next_button.text() == 'Uninstall':
+            uninstall_unicado(self)
+
+        if self.next_button.text() == 'Update':
+            update_unicado(self)
+
+        if self.next_button.text() == 'Delete':
+            self.integration_text_label_1.setText('Please wait until the integrated tool is deleted.')
+            self.cancel_button.setText('Finish')
+            self.cancel_button.setEnabled(False)
+            self.next_button.setVisible(False)
+            self.back_button.setVisible(False)
+            QCoreApplication.processEvents()
+
+            # call function to delete an integrated non-basic tool
+            error_flag = delete_tool(self)
+
+            if error_flag:
+                self.welcome_panel.setVisible(True)
+                self.integration_panel.setVisible(False)
+                self.header_panel.setVisible(False)
+                self.welcome_text_label_1.setText('Attention! An internal error has occurred!')
+                self.install_text_label_1.setText('Selected tool can not be deleted!')
+                self.install_text_label_2.setText('Please reinstall UNICADOworkflow or contact the developer team.')
+                self.update_button.setVisible(False)
+                self.update_button.setEnabled(True)
+                self.cancel_button.setText('Abort')
+                self.cancel_button.setEnabled(True)
+                self.cancel_button.setVisible(True)
+                self.next_button.setVisible(False)
+                QCoreApplication.processEvents()
+
+            else:
+                self.header_text_label_1.setText('Deleting of tool finished')
+                self.cancel_button.setEnabled(True)
+                self.integration_button.setVisible(True)
+                self.integration_button.setEnabled(True)
+                self.integration_button_group.setExclusive(False)
+                self.integration_radio_button_yes.setChecked(False)
+                self.integration_radio_button_no.setChecked(False)
+                self.integration_button_group.setExclusive(True)
+                self.integration_button_group_name.setExclusive(False)
+                self.integration_radio_button_delete.setChecked(False)
+                self.integration_radio_button_overwrite.setChecked(False)
+                self.integration_button_group_name.setExclusive(True)
+                self.integration_text_label_0.setText("UNICADO")
+                self.integration_text_label_2.setGeometry(QtCore.QRect(20, 170, 410, 80))
+                self.integration_text_label_4.setGeometry(QtCore.QRect(20, 200, 410, 80))
+                self.tool_name_panel_edit.setText('Please enter name of tool to be integrated')
+                self.tool_name_panel_edit_button.setVisible(True)
+                self.tool_path_panel_edit.setText('Click Browse to enter local tool path')
+                self.integration_combo_box.clear()
+                self.integration_combo_box.addItems(['- please select a tool group -', 'postProcessing', 'preSizing',
+                                                     'sizingLoop', 'visualization', '- other -'])
+                self.group_name_panel_edit.setText("Please enter tool group name.")
+                self.integration_checkbox.setChecked(False)
+                QCoreApplication.processEvents()
+
+            return
+
+        if tool_name_panel_visibility:
+            if not self.integration_radio_button_delete.isChecked():
+                self.next_button.setEnabled(False)
+                self.button_name_panel.setVisible(False)
+                self.header_text_label_1.setText('Please select tool path and workflow group')
+                self.header_text_label_2.setText('')
+                self.integration_text_label_2.setVisible(False)
+                self.integration_text_label_2.setGeometry(QtCore.QRect(20, 200, 410, 80))
+                self.integration_text_label_4.setGeometry(QtCore.QRect(20, 230, 410, 80))
+                self.integration_text_label_1.setText('Please enter the local system path to the integrating tool.')
+                self.tool_name_panel.setVisible(False)
+                self.tool_name_panel_edit_button.setVisible(False)
+                self.tool_name_panel.setVisible(False)
+                self.tool_path_panel.setVisible(True)
+                self.tool_path_panel_browse_button.setText('Browse')
+
+                tool_name = self.tool_name_panel_edit.text()
+                local_tool_folder = self.tool_path_panel_edit.text()
+
+                if not local_tool_folder == 'Click Browse to enter local tool path':
+                    content_of_directory = os.listdir(local_tool_folder)
+                    if os.path.isdir(local_tool_folder + '/' + tool_name):
+                        self.integration_text_label_3.setVisible(True)
+                        self.integration_combo_box.setVisible(False)
+                        self.integration_text_label_3.setText(
+                            'Attention: There is no executable file with the entered tool name '
+                            'in the selected directory. Please change path.')
+                    else:
+                        if tool_name in content_of_directory or tool_name + '.exe' in content_of_directory:
+                            self.integration_text_label_3.setVisible(True)
+                            self.integration_combo_box.setVisible(True)
+                            self.integration_text_label_3.setText('Please select the group in which the tool is to be'
+                                                                  ' integrated.')
+                            selected_group = self.integration_combo_box.currentText()
+                            if selected_group == '- please select a tool group -' or selected_group == '- other -':
+                                self.integration_text_label_4.setVisible(False)
+                                self.next_button.setEnabled(False)
+                                self.group_name_panel.setVisible(False)
+                                if selected_group == '- other -':
+                                    self.group_name_panel.setVisible(True)
+                                    input_string = self.group_name_panel_edit.text()
+                                    if not input_string == 'Please enter tool group name.':
+                                        check_tool(self)
+                            else:
+                                self.group_name_panel.setVisible(False)
+                                self.integration_text_label_4.setText(
+                                    "Please click 'Next' to continue the tool integration.")
+                                self.integration_text_label_4.setVisible(True)
+                                self.next_button.setEnabled(True)
+                        else:
+                            self.integration_text_label_3.setVisible(True)
+                            self.integration_text_label_3.setText(
+                                'Attention: There is no executable file with the entered tool name in the '
+                                'selected directory. Please change path.')
+            else:
+                self.next_button.setText('Delete')
+                self.integration_text_label_1.setText('Attention: You have selected delete tool.\n'
+                                                      'If you really want to delete the selected tool, click "Delete" '
+                                                      'or click "Back" to return to the previous page.')
+                self.header_text_label_1.setText('Final steps to delete an integrated tool')
+                self.header_text_label_2.setText('')
+                self.integration_text_label_2.setVisible(False)
+                self.integration_text_label_3.setVisible(False)
+                self.integration_text_label_4.setVisible(False)
+                self.tool_name_panel.setVisible(False)
+                self.button_name_panel.setVisible(False)
+
+        if tool_path_panel_visibility:
+            if self.integration_radio_button_overwrite.isChecked():
+                self.next_button.setText('Overwrite')
+                self.integration_checkbox.setText('Repository overwrite')
+                self.header_text_label_1.setText('Final steps for overwrite the selected tool')
+                self.integration_text_label_1.setText('Please select if the tool to be overwrite should abort the '
+                                                      'workflow loop if it returns an error code.')
+                self.integration_text_label_5.setText(
+                    'Please select if the tool should also be overwritten in your working branch of the aircraft '
+                    'design repository.\n'
+                    'Attention: The developer password is required.')
+                self.integration_text_label_5.setVisible(True)
+            else:
+                self.next_button.setText('Integrate')
+                self.integration_checkbox.setText('Repository integration')
+                self.header_text_label_1.setText('Final steps for the tool integration')
+                self.integration_text_label_1.setText('Please select if the tool to be integrated should abort the '
+                                                      'workflow loop if it returns an error code.')
+                self.integration_text_label_5.setText(
+                    'Please activate the following checkbox if the tool should also be integrated into your '
+                    'aircraft design repository.\n'
+                    'Attention: The developer password is required.')
+                self.integration_text_label_5.setVisible(False)
+
+            self.next_button.setEnabled(False)
+            self.header_text_label_2.setText('')
+            self.integration_text_label_3.setVisible(False)
+            self.integration_text_label_4.setVisible(False)
+            self.tool_path_panel.setVisible(False)
+            self.group_name_panel.setVisible(False)
+            self.integration_combo_box.setVisible(False)
+            self.button_group_panel.setVisible(True)
+            self.checkbox_panel.setVisible(True)
+
+        if radio_button_panel_visibility:
+            self.header_text_label_1.setText('Integration in progress')
+            self.integration_text_label_1.setText('Please wait until the tool integration is completed.')
+            self.button_group_panel.setVisible(False)
+            self.checkbox_panel.setVisible(False)
+            self.back_button.setEnabled(False)
+            self.back_button.setVisible(False)
+            self.next_button.setEnabled(False)
+            self.cancel_button.setText('Finish')
+            self.cancel_button.setEnabled(False)
+            self.integration_text_label_5.setVisible(False)
+            QCoreApplication.processEvents()
+
+            # function call to perform tool integration
+            error_flag = perform_integration(self)
+
+            # reset ui settings to allow next tool integration
+            if not error_flag:
+                self.header_text_label_1.setText('Integration finished')
+                self.next_button.setVisible(False)
+                self.cancel_button.setEnabled(True)
+                self.integration_button.setVisible(True)
+                self.integration_button.setEnabled(True)
+                self.integration_button_group.setExclusive(False)
+                self.integration_radio_button_yes.setChecked(False)
+                self.integration_radio_button_no.setChecked(False)
+                self.integration_button_group.setExclusive(True)
+                self.integration_button_group_name.setExclusive(False)
+                self.integration_radio_button_delete.setChecked(False)
+                self.integration_radio_button_overwrite.setChecked(False)
+                self.integration_button_group_name.setExclusive(True)
+                self.integration_text_label_0.setText("UNICADO")
+                self.integration_text_label_2.setGeometry(QtCore.QRect(20, 170, 410, 80))
+                self.integration_text_label_4.setGeometry(QtCore.QRect(20, 200, 410, 80))
+                self.tool_name_panel_edit.setText('Please enter name of tool to be integrated')
+                self.tool_name_panel_edit_button.setVisible(True)
+                self.tool_path_panel_edit.setText('Click Browse to enter local tool path')
+                self.integration_combo_box.clear()
+                self.integration_combo_box.addItems(['- please select a tool group -', 'postProcessing', 'preSizing',
+                                                     'sizingLoop', 'visualization', '- other -'])
+                self.group_name_panel_edit.setText("Please enter tool group name.")
+                self.integration_checkbox.setChecked(False)
+                QCoreApplication.processEvents()
diff --git a/installer/sub_functions/remove_tigl_entry.py b/installer/sub_functions/remove_tigl_entry.py
new file mode 100644
index 0000000000000000000000000000000000000000..ce511825fa8f36387e945f96d112ef8fbc621001
--- /dev/null
+++ b/installer/sub_functions/remove_tigl_entry.py
@@ -0,0 +1,83 @@
+"""Module removing the TiGL viewer application and its connectors from an RCE .wf file"""
+
+import json
+
+
+def find_sub_dict_by_key_value(data, key, value) -> list | dict | None :
+    """Search for the sub-list in .wf file which 
+    contains the tigl entry or the tigl identifier for the connector
+
+    Depending on the structure of the json format sometimes the sub-dictionary is of type dict 
+    and sometimes it is of type list, which is handled by this function.
+    
+    :param dict/list data: Here the .wf file is passed (in json format).
+    :param str key: A key word to be searched for within a dictionary or a list.
+    :param str value: The value of the respective key.
+    :returns: sub_result: Dictionary or list from within data, which match the key-value pair
+    
+    """
+    if isinstance(data, dict):
+        if key in data and data[key] == value:
+            return data
+        for _, v in data.items():
+            sub_result = find_sub_dict_by_key_value(v, key, value)
+            if sub_result:
+                return sub_result
+    elif isinstance(data, list):
+        for item in data:
+            sub_result = find_sub_dict_by_key_value(item, key, value)
+            if sub_result:
+                return sub_result
+    return None
+
+
+def remove_sublist(data, sublist, key, value):
+    """ Removes a sub-list or a sub-dictionary from a dictionary or a list.
+
+    If function find_sub_dict_by_key_value (above) was successful, 
+    then there are two sublist: One with the tigl module entry and one with the 
+    connector identifier. Both lists are removed from the json file
+
+    :param dict/list data: Data could be a dictionary or a list
+    :param dict/list sublist: sub-list or sub-dict containing a key-value pair, which is removed.
+    :param str key: A key word to be searched for within a dictionary or a list.
+    :param str value: The value of the respective key.
+    :returns: -
+    """
+    if isinstance(data, dict):
+        for _, v in data.items():
+            remove_sublist(v, sublist, key, value)
+    if isinstance(data, list):
+        for item in data:
+            first_set = set(map(tuple, item))
+            second_set = set(map(tuple, sublist))
+            if second_set.symmetric_difference(first_set) == set() and item[key] == value:
+                data.remove(item)
+
+
+def remove_tigl_entry_from_wf_file(wf_file_path):
+    """ Function which removes the TiGL viewer entry from the workflow file
+    
+        Function reads the workflow file in a specific json format.
+        It searches for the TiGL viewer entry and for the connections to the TiGL viewer.
+        Both elements are probably either existent in a dictionary or in a list containing
+        RCE specific information, which has to be removed.
+
+        :params: str wf_file_path: .wf file path
+        :return: -
+    """
+    with open(wf_file_path, 'r', encoding="utf-8") as input_file:
+        data = json.load(input_file)
+
+    # Find the sub-dictionary containing the key-value pair "name": "TiGL Viewer"
+    result = find_sub_dict_by_key_value(data, "name", "TiGL Viewer")
+    if result:
+        # Save identifier of Tigl Viewer to delete the connector later
+        tigl_identifier = result["identifier"]
+        remove_sublist(data, result, "name", "TiGL Viewer") # Remove Tigl viewer sub dictionary
+        # Find connector of Tigl viewer
+        result = find_sub_dict_by_key_value(data, "target", tigl_identifier)
+        if result:
+            remove_sublist(data, result, "target", tigl_identifier) # Remove Tigl viewer connector
+            with open(wf_file_path, 'w', encoding="utf-8") as output_file:
+                json.dump(data, output_file, indent=2, separators=(', ',' : '))
diff --git a/installer/sub_functions/repository_integration.py b/installer/sub_functions/repository_integration.py
new file mode 100644
index 0000000000000000000000000000000000000000..22c266988884d7c1d302a1d8afc6e544525cd540
--- /dev/null
+++ b/installer/sub_functions/repository_integration.py
@@ -0,0 +1,130 @@
+import os
+import shutil
+
+#import git
+import configparser
+from sub_functions.write_json_file import write_json_file
+
+
+def repository_integration(self):
+    # initialize local parameter
+    repo_error = 0
+    error_flag = False
+    path_to_aircraft_design_tools = str()
+    tool_name = self.tool_name_panel_edit.text()
+    group_name = self.group_name_panel_edit.text()
+    tool_directory = self.tool_path_panel_edit.text()
+
+    # try to read repository path file
+    user_path_string = os.path.expanduser("~")
+    user_path_string = user_path_string.replace(os.sep, '/')
+    user_path_string = user_path_string + '/'
+    path_to_repository_file = user_path_string + '.rce/default/integration/tools/common/' \
+                                                 'absolutPathToUNICADOrepositoryDirectory.txt'
+
+    if os.path.isfile(path_to_repository_file):
+        read_repository_path = open(path_to_repository_file, 'r')
+        repository_path = read_repository_path.read() + ''
+        read_repository_path.close()
+    else:
+        repo_error = 1
+        return repo_error, error_flag
+
+    # try to read repository url from repository configuration file
+    try:
+        files = os.listdir(repository_path)
+        for fileName in files:
+            check_if_file_is_directory = os.path.isdir(repository_path + fileName)
+            if check_if_file_is_directory:
+                check_git_folder = os.path.isdir(repository_path + fileName + '/.git')
+                if check_git_folder:
+                    check_config_file = os.path.isfile(repository_path + fileName + '/.git/config')
+                    if check_config_file:
+                        config = configparser.ConfigParser()
+                        config.read(repository_path + fileName + '/.git/config')
+                        if config.has_section('remote "origin"'):
+                            ssh_url = config['remote "origin"']['url']
+                            if ssh_url == 'ssh://git@unicado.ilr.rwth-aachen.de:2222/source/rAircraftDesign.git':
+                                path_to_aircraft_design_tools = repository_path + fileName + '/'
+                                print(path_to_aircraft_design_tools)
+                                repo_error = 0
+
+    except OSError:
+        error_flag = True
+        repo_error = 1
+        return repo_error, error_flag
+
+    if repo_error == 0:
+        path_to_tool_json_files = path_to_aircraft_design_tools + 'UNICADOworkflow/jsonFiles/'
+        # try:
+        #    # checkout develop branch from aircraft design repository
+        #     local_branches = os.listdir(path_to_aircraft_design_tools + '.git/refs/heads')
+        #     repo = git.Repo(path_to_aircraft_design_tools)
+        #     current_branch = repo.active_branch.name
+        #     if tool_name in local_branches:
+        #         repo.git.switch(tool_name, '-f')
+        #     elif current_branch == 'develop':
+        #         repo.git.checkout("develop", b=tool_name)
+        #     else:
+        #         repo.git.switch('develop', '-f')
+        #         repo.git.checkout("develop", b=tool_name)
+        #
+        # except OSError:
+        #     error_flag = True
+        #     repo_error = 2
+        #     return repo_error, error_flag
+        #
+        # # copy tool to local repository
+        # list_of_tools_repository = os.listdir(path_to_aircraft_design_tools)
+        # if tool_name in list_of_tools_repository:
+        #     list_of_tool_content = os.listdir(tool_directory)
+        #     list_ot_repository_content = os.listdir(path_to_aircraft_design_tools + tool_name)
+        #     for element in list_of_tool_content:
+        #         if element in list_ot_repository_content:
+        #             if os.path.isdir(tool_directory + '/' + element):
+        #                 shutil.rmtree(path_to_aircraft_design_tools + tool_name + '/' + element)
+        #                 shutil.copytree(tool_directory + '/' + element, path_to_aircraft_design_tools + tool_name
+        #                 + '/' + element)
+        #                 repo.git.add(path_to_aircraft_design_tools + tool_name + '/' + element)
+        #
+        #             elif os.path.isfile(tool_directory + '/' + element):
+        #                 shutil.copyfile(tool_directory + '/' + element, path_to_aircraft_design_tools + tool_name
+        #                 + '/' + element)
+        #                 repo.git.add(path_to_aircraft_design_tools + tool_name + '/' + element)
+        #         else:
+        #             if os.path.isdir(tool_directory + '/' + element):
+        #                 shutil.copytree(tool_directory + '/' + element, path_to_aircraft_design_tools + tool_name
+        #                 + '/' + element)
+        #                 repo.git.add(path_to_aircraft_design_tools + tool_name + '/' + element)
+        #
+        #             elif os.path.isfile(tool_directory + '/' + element):
+        #                 shutil.copyfile(tool_directory + '/' + element, path_to_aircraft_design_tools + tool_name
+        #                 + '/' + element)
+        #                 repo.git.add(path_to_aircraft_design_tools + tool_name + '/' + element)
+        #
+        #     commit_message = tool_name + ' - This is an automatically generated commit for the ' \
+        #                                  'update of the named tool.'
+        #
+        # else:
+        #     shutil.copytree(tool_directory, path_to_aircraft_design_tools + tool_name)
+        #     repo.git.add(tool_name)
+        #     commit_message = tool_name + ' - This is an automatically generated commit for the initial ' \
+        #                                  'integration of the named tool.'
+
+        # call function to write user data from ui to configuration.json file of new tool
+        error_flag = write_json_file(self, path_to_tool_json_files, '', tool_name, group_name, False, True,
+                                     path_to_aircraft_design_tools)
+
+        if error_flag:
+            repo_error = 3
+
+        # try:
+        #     changed_files = repo.index.diff("HEAD")
+        #     if changed_files:
+        #         repo.git.commit('-m', commit_message)
+        #
+        # except OSError:
+        #     error_flag = True
+        #     repo_error = 4
+
+    return repo_error, error_flag
diff --git a/installer/sub_functions/resource_path.py b/installer/sub_functions/resource_path.py
new file mode 100644
index 0000000000000000000000000000000000000000..35e827450f58c43e86102e6828164932310c90b2
--- /dev/null
+++ b/installer/sub_functions/resource_path.py
@@ -0,0 +1,29 @@
+def resource_path():
+    """ Function to get the absolute path to the installer added resources
+
+        * The input string "relative_path" contains the relative path of the resource you want to use.
+
+        :param relative_path: input string
+        :return path_to_resources: output string
+    """
+
+    ''' imports for python '''
+    import sys
+    import os
+    import tempfile
+    status_flag = True
+    list_of_running_executables = []
+
+    # generate path from temporary executable directory
+    path_to_resources = tempfile.gettempdir()   # Get temp directory
+    content_of_temp = os.listdir(path_to_resources)
+
+    if getattr(sys, 'frozen', False):
+        # If the script is compiled, sys._MEIPASS gives the temp directory for PyInstaller
+        path_to_resources = sys._MEIPASS
+    else:
+        path_to_resources = os.environ.get("_MEIPASS", os.path.abspath("."))
+
+    path_to_resources = path_to_resources.replace(os.sep, '/')
+
+    return path_to_resources, status_flag
diff --git a/installer/sub_functions/retranslate_ui.py b/installer/sub_functions/retranslate_ui.py
new file mode 100644
index 0000000000000000000000000000000000000000..78b50c0692503e2142bf95702b4cf23789cc3544
--- /dev/null
+++ b/installer/sub_functions/retranslate_ui.py
@@ -0,0 +1,75 @@
+def retranslate_ui(self, UNICADOworkflowInstaller):
+    """ Call function to retranslate the strings of the installer application text fields.
+
+        :rtype: object
+    """
+
+    ''' imports for python '''
+    import os
+    from PyQt5 import QtCore
+
+    _translate = QtCore.QCoreApplication.translate
+    UNICADOworkflowInstaller.setWindowTitle(_translate("UNICADOworkflow_installer", "UNICADOworkflow installer"))
+    self.integration_button.setText(_translate("UNICADOworkflow_installer", "Tool Integration"))
+    self.next_button.setText(_translate("UNICADOworkflow_installer", "Next >"))
+    self.cancel_button.setText(_translate("UNICADOworkflow_installer", "Cancel"))
+    self.back_button.setText(_translate("UNICADOworkflow_installer", "< Back"))
+    self.update_button.setText(_translate("UNICADOworkflow_installer", "Update"))
+    self.uninstall_button.setText(_translate("UNICADOworkflow_installer", "Uninstall"))
+    self.welcome_text_label_1.setText(_translate("UNICADOworkflow_installer",
+                                                 "Welcome to the UNICADOworkflow Setup Wizard"))
+    self.install_text_label_1.setText(_translate("UNICADOworkflow_installer",
+                                                 "This Wizard will guide you through the installation of "
+                                                 "UNICADOworkflow."))
+    self.continue_text_label.setText(_translate("UNICADOworkflow_installer", "Click Next to continue."))
+    self.install_text_label_2.setText(_translate("UNICADOworkflow_installer",
+                                                 "Please note: This is an unofficial installer. "
+                                                 "It is provided by UNICADO project team."))
+    self.header_text_label_1.setText(_translate("UNICADOworkflow_installer", "Choose Install Location"))
+    self.header_text_label_2.setText(_translate("UNICADOworkflow_installer",
+                                                "Chose the folder in which to install UNICADOworkflow."))
+    self.install_and_finish_panel_text_label_1.setText(_translate("UNICADOworkflow_installer",
+                                                                  "If you are sure you want to perform, "
+                                                                  "click Install."))
+    self.install_and_finish_panel_text_label_2.setText(_translate("UNICADOworkflow_installer",
+                                                                  "After completing the installation, click Finish."))
+    self.repository_path_text_label_2.setText(_translate("UNICADOworkflow_installer", " Repository Folder"))
+    self.repository_path_line_edit.setText(_translate("UNICADOworkflow_installer", os.path.expanduser("~")))
+    self.repository_path_browse_button.setText(_translate("UNICADOworkflow_installer", "Browse..."))
+    self.repository_path_text_label_1.setText(_translate("UNICADOworkflow_installer",
+                                                         "Please, select the path to the parent directory of the "
+                                                         "UNICADO repositories by clicking Browse. Attention, "
+                                                         "do not select a specific repository! Then, click Install to "
+                                                         "start the installation."))
+    self.install_path_text_label_1.setText(_translate("UNICADOworkflow_installer", "Setup will install the UNICADO "
+                                                                                   "workflow in the following folder. "
+                                                                                   "To install in a different folder, "
+                                                                                   "click Browse and select another f"
+                                                                                   "older. Attention, this cannot be "
+                                                                                   "changed later! Then click Next to "
+                                                                                   "select the repository folder."))
+    self.install_path_line_edit.setText(_translate("UNICADOworkflow_installer", "C:\\Programs\\UNICADOworkflow"))
+    self.install_path_browse_button.setText(_translate("UNICADOworkflow_installer", "Browse..."))
+    self.install_path_text_label_2.setText(_translate("UNICADOworkflow_installer", "Disk space required: 1.75 GB"))
+    self.install_path_text_label_3.setText(_translate("UNICADOworkflow_installer", "Disk space available: enough"))
+    self.install_path_text_label_4.setText(_translate("UNICADOworkflow_installer", " Destination Folder"))
+    self.integration_text_label_0.setText(_translate("UNICADOworkflow_installer", "UNICADO"))
+    self.integration_text_label_1.setText(_translate("UNICADOworkflow_installer", "Welcome to the UNICADO module "
+                                                                                  "integration tool."))
+    self.integration_text_label_2.setText(_translate("UNICADOworkflow_installer", "Entered tool name does not match the"
+                                                                                  " 'camelCase' convention."))
+    self.integration_text_label_3.setText(_translate("UNICADOworkflow_installer", 'Attention: There is no executable '
+                                                                                  'file with the entered tool name in '
+                                                                                  'the selected directory. '
+                                                                                  'Please change.'))
+    self.integration_text_label_4.setText(_translate("UNICADOworkflow_installer", "Entered group name does not match "
+                                                                                  "the 'camelCase' convention."))
+    self.integration_text_label_5.setText(_translate("UNICADOworkflow_installer", ""))
+    self.tool_name_panel_edit.setText(_translate("UNICADOworkflow_installer", "Please enter name of tool to be "
+                                                                              "integrated"))
+    self.tool_name_panel_edit_button.setText(_translate("UNICADOworkflow_installer", "OK"))
+    self.tool_path_panel_edit.setText(_translate("UNICADOworkflow_installer", "Click Browse to enter local tool path"))
+    self.group_name_panel_edit.setText(_translate("UNICADOworkflow_installer", "Please enter tool group name."))
+    self.group_name_panel_edit_button.setText(_translate("UNICADOworkflow_installer", "OK"))
+    self.checkbox_panel_edit.setText(_translate("UNICADOworkflow_installer", "enter password"))
+    self.checkbox_panel_text_label_0.setText(_translate("UNICADOworkflow_installer", ""))
diff --git a/installer/sub_functions/uninstall_steps.py b/installer/sub_functions/uninstall_steps.py
new file mode 100644
index 0000000000000000000000000000000000000000..4641c2fc7b6ce3e40295b5d18b78dc497ae36c7c
--- /dev/null
+++ b/installer/sub_functions/uninstall_steps.py
@@ -0,0 +1,249 @@
+# imports for python
+import os
+import json
+import time
+import shutil
+import subprocess
+from PyQt5 import QtCore
+from PyQt5.QtCore import QCoreApplication
+
+
+def uninstall_steps(self):
+    # handle ui objects for visibility
+    self.welcome_panel.setVisible(False)
+    self.header_panel.setVisible(True)
+    self.integration_panel.setVisible(True)
+    self.tool_name_panel.setVisible(False)
+    self.update_button.setVisible(False)
+    self.update_button.setEnabled(False)
+    self.uninstall_button.setVisible(False)
+    self.uninstall_button.setEnabled(False)
+    self.next_button.setVisible(True)
+    self.next_button.setEnabled(True)
+    self.next_button.setText('Uninstall')
+    self.cancel_button.setText('Cancel')
+    self.back_button.setVisible(True)
+    self.back_button.setEnabled(True)
+    self.integration_button.setVisible(False)
+    self.integration_button.setEnabled(False)
+
+    # set description to text fields
+    self.header_text_label_1.setText('Welcome to the UNICADO uninstaller.')
+    self.header_text_label_2.setText('This tool will guide you through the uninstallation of UNICADO.')
+    self.integration_text_label_1.setText('If you really want to uninstall the UNICADO workflow, click "Uninstall" '
+                                          'or click "Back" to return to the previous page. \n'
+                                          'Click "Cancel" to quit the uninstaller.')
+
+
+def uninstall_unicado(self):
+    """ Call function to uninstall all UNICADO components of the working- and .rce-directory.
+
+        :rtype: object
+    """
+
+    # set handles for ui visibility
+    self.integration_button.setVisible(False)
+    self.integration_button.setEnabled(False)
+    self.continue_text_label.setText('')
+    QCoreApplication.processEvents()
+
+    # generate absolute path to the json files inside the .rce directory
+    user_path_string = os.path.expanduser("~")
+    user_path_string = user_path_string.replace(os.sep, '/')
+    user_path_string = user_path_string + '/'
+    path_to_tool_json_files = user_path_string + '.rce/default/integration/tools/common/'
+
+    # check if the absolute path file is not existing
+    #  -> if true: -> open UNICADO tool list file to generate absolute path file
+    if not os.path.isfile(path_to_tool_json_files + 'absolutPathToUNICADOInstallDirectory.txt'):
+        # check if the UNICADO tool list file is existing
+        #  -> if true: -> open json files of each listed tool in UNICADO tool list file
+        if os.path.isfile(path_to_tool_json_files + 'toolListUNICADOworkflow.txt'):
+            workflow_tools = open(path_to_tool_json_files + 'toolListUNICADOworkflow.txt', 'r')
+            # loop across all listed tools in UNICADO tool list file to read absolute path of UNICADO install directory
+            for tool in workflow_tools:
+                folder_name = tool.rstrip()
+                if os.path.isdir(path_to_tool_json_files + '/' + folder_name):
+                    # try to open json tool file and read absolute path of UNICADO install directory
+                    with open(path_to_tool_json_files + folder_name + '/configuration.json', 'r+') as jsonFile:
+                        json_data = json.load(jsonFile)
+                    launch_settings = json_data['launchSettings']
+                    install_path = launch_settings[0]['rootWorkingDirectory']
+                    string_position = install_path.find('UNICADOworkflow')
+                    # check if the absolute path of UNICADO install directory exist
+                    #  -> if true: -> generate absolute path file and break the loop
+                    if not (string_position == -1):
+                        install_directory = install_path[:string_position] + 'UNICADOworkflow/'
+                        if os.path.isdir(install_directory):
+                            file_for_install_path = open(path_to_tool_json_files
+                                                         + 'absolutPathToUNICADOInstallDirectory.txt', 'w')
+                            file_for_install_path.write(install_directory)
+                            file_for_install_path.close()
+                            break
+
+            workflow_tools.close()
+
+        # generate Error message and show in installer application
+        self.welcome_panel.setVisible(True)
+        self.integration_panel.setVisible(False)
+        self.welcome_text_label_1.setText('Attention! An Error has occurred!')
+        self.install_text_label_1.setText('UNICADOworkflow was not uninstalled successfully!')
+        self.install_text_label_2.setText('Please re-run the uninstaller. '
+                                          'After that, UNICADOworkflow will be uninstalled successfully.')
+        self.uninstall_button.setVisible(False)
+        self.update_button.setVisible(False)
+        self.cancel_button.setText('Abort')
+        self.cancel_button.setVisible(True)
+        QCoreApplication.processEvents()
+
+    # else condition: the absolute path file is existing -> read absolute path from file and start uninstall process
+    else:
+        install_folder = open(path_to_tool_json_files + 'absolutPathToUNICADOInstallDirectory.txt', 'r')
+        install_directory = install_folder.read()
+        install_folder.close()
+        last_character = install_directory[-1]
+        if not (last_character == '/'):
+            install_directory = install_directory + '/'
+        indices = []
+        i = install_directory.find('/')
+
+        # try to uninstall the installed UNICADO working version and all components
+        try:
+            self.welcome_panel.setVisible(True)
+            self.integration_panel.setVisible(False)
+            self.welcome_text_label_1.setText('Uninstallation in progress, please wait.')
+            self.install_text_label_1.setText('Please wait until uninstallation is finished.')
+            self.install_text_label_2.setText('')
+            self.update_button.setVisible(False)
+            self.next_button.setVisible(False)
+            self.back_button.setVisible(False)
+            self.uninstall_button.setEnabled(False)
+            self.cancel_button.setVisible(True)
+            self.cancel_button.setEnabled(False)
+            self.cancel_button.setText('Finish')
+            QCoreApplication.processEvents()
+            
+            # Check if the 'unicado_own_python_packages.txt' file exists
+            if os.path.isfile(path_to_tool_json_files + 'unicado_own_python_packages.txt'):
+                # Check if the 'unicado_python_path.txt' file exists
+                if os.path.isfile(path_to_tool_json_files + 'unicado_python_path.txt'):
+                    try:
+                        # Read the Python interpreter path
+                        with open(path_to_tool_json_files + 'unicado_python_path.txt', 'r') \
+                            as python_path_file:
+                            python_path = python_path_file.read().strip()
+                        
+                        # Read and process the list of own packages
+                        with open(path_to_tool_json_files + 'unicado_own_python_packages.txt', 'r') \
+                            as own_package_list:
+                            for own_package in own_package_list:
+                                own_package = own_package.strip()
+                                if own_package:
+                                    with open(os.devnull, 'w') as devnull:
+                                        # Windows-specific console supress
+                                        if os.name == "nt":  
+                                            startupinfo = subprocess.STARTUPINFO()
+                                            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
+                                            subprocess.check_call([python_path, "-m", "pip", "uninstall", 
+                                                                    own_package, '--yes'], stdout=devnull,
+                                                                    stderr=devnull, startupinfo=startupinfo)
+                                        # Linux/macOS 
+                                        else:  
+                                            subprocess.check_call([python_path, "-m", "pip", "uninstall", 
+                                                                    own_package, '--yes'], stdout=devnull, 
+                                                                    stderr=devnull)
+                        
+                        # Remove package list and Python path files after uninstallation
+                        os.remove(path_to_tool_json_files + 'unicado_own_python_packages.txt')
+                        os.remove(path_to_tool_json_files + 'unicado_python_path.txt')
+
+                    except OSError as e:
+                        print(f'Error: Unable to handle files related to own Python packages. Details: {e}')
+                    except subprocess.CalledProcessError as e:
+                        print(f'Error: Failed to uninstall a package. Details: {e}')
+                else:
+                    print('Error: The file "unicado_python_path.txt" does not exist. Cannot proceed.')
+            else:
+                print('Error: The file "unicado_own_python_packages.txt" does not exist. Cannot proceed.')
+
+            while i >= 0:
+                indices.append(i)
+                i = install_directory.find('/', i + 1)
+            parent_folder = install_directory[:indices[-2]]
+            if os.path.isdir(install_directory):
+                workflow_tools = open(path_to_tool_json_files + 'toolListUNICADOworkflow.txt', 'r')
+                # loop across all listed tools in the tool list file to remove tool from system
+                for tool in workflow_tools:
+                    folder_name = tool.rstrip()
+                    if os.path.isdir(install_directory + folder_name):
+                        shutil.rmtree(install_directory + folder_name)
+
+            # check if the installation directory is empty -> if true: -> delete empty directory
+            if not os.listdir(install_directory):
+                shutil.rmtree(install_directory)
+
+            # check if the parent directory of install directory is empty -> if true: -> delete parent directory
+            if not os.listdir(parent_folder):
+                shutil.rmtree(parent_folder)
+
+            # remove all json files of installed tools from .rce directory
+            workflow_tools = open(path_to_tool_json_files + 'toolListUNICADOworkflow.txt', 'r')
+            for tool in workflow_tools:
+                folder_name = tool.rstrip()
+                if os.path.isdir(path_to_tool_json_files + '/' + folder_name):
+                    shutil.rmtree(path_to_tool_json_files + folder_name)
+
+            workflow_tools.close()
+
+            # remove all UNICADO specific files from .rce directory
+            os.remove(path_to_tool_json_files + 'toolListUNICADOworkflow.txt')
+            os.remove(path_to_tool_json_files + 'absolutPathToUNICADOInstallDirectory.txt')
+            if os.path.isfile(path_to_tool_json_files + 'absolutPathToUNICADOrepositoryDirectory.txt'):
+                os.remove(path_to_tool_json_files + 'absolutPathToUNICADOrepositoryDirectory.txt')
+            if os.path.isfile(path_to_tool_json_files + 'standAloneInstallationFlag.dat'):
+                os.remove(path_to_tool_json_files + 'standAloneInstallationFlag.dat')
+
+            # check if the standard tool file is existing -> if true: -> delete the file
+            if os.path.isfile(path_to_tool_json_files + 'standardToolListUNICADOworkflow.txt'):
+                os.remove(path_to_tool_json_files + 'standardToolListUNICADOworkflow.txt')
+
+            # check if a standalone origin design tool directory is existing -> if true: -> delete the directory
+            if os.path.isdir(path_to_tool_json_files + 'originUnicadoDesignTools'):
+                shutil.rmtree(path_to_tool_json_files + 'originUnicadoDesignTools')
+
+            # check if a standalone origin software tool directory is existing -> if true: -> delete the directory
+            if os.path.isdir(path_to_tool_json_files + 'originUnicadoSoftwareTools'):
+                shutil.rmtree(path_to_tool_json_files + 'originUnicadoSoftwareTools')
+
+            # check if a standalone origin software tool directory is existing -> if true: -> delete the directory
+            if os.path.isdir(path_to_tool_json_files + 'originUnicadoProjects'):
+                shutil.rmtree(path_to_tool_json_files + 'originUnicadoProjects')
+
+            # update the UNICADO installer application and show finished text
+            time.sleep(2)
+            self.welcome_text_label_1.setText('UNICADOworkflow was successfully uninstalled')
+            self.install_text_label_1.setText('Please click Finish to exit the installer.')
+            self.install_text_label_2.setText('')
+            self.uninstall_button.setVisible(False)
+            self.cancel_button.setVisible(True)
+            self.cancel_button.setEnabled(True)
+            QCoreApplication.processEvents()
+
+        # exception handling if an error occurs during the uninstallation process
+        except OSError as e:
+            self.welcome_panel.setVisible(True)
+            self.integration_panel.setVisible(False)
+            self.welcome_text_label_1.setText('ERROR! Access denied!')
+            self.install_text_label_1.setGeometry(QtCore.QRect(30, 90, 400, 90))
+            if ".metadata//.lock" in str(e).replace(os.sep, '/'):
+                self.install_text_label_1.setText("RCE is still running. Please close RCE before uninstallation.")
+            else:
+                self.install_text_label_1.setText(f"Attention: {str(e).replace(os.sep, '/')}")
+            self.continue_text_label.setText('To quit the installer, click Abort.')
+            self.next_button.setVisible(False)
+            self.back_button.setVisible(False)
+            self.uninstall_button.setVisible(False)
+            self.cancel_button.setEnabled(True)
+            self.cancel_button.setText('Abort')
+            self.cancel_button.setVisible(True)
+            QCoreApplication.processEvents()
diff --git a/installer/sub_functions/update_additional_software.py b/installer/sub_functions/update_additional_software.py
new file mode 100644
index 0000000000000000000000000000000000000000..c306fe2f80b64ad9209a06006ec4e99cecfd812c
--- /dev/null
+++ b/installer/sub_functions/update_additional_software.py
@@ -0,0 +1,119 @@
+def update_additional_software(self, path_of_working_directory, path_to_origin, file_name, install_percent, percent):
+    """ Function to auto update the additional software tools in the UNICADO working directory.
+
+        The input string "path_of_working_directory" contains the absolute path to installed working directory of
+            UNICADO.
+
+        The input string "path_to_origin" contains the absolute system path to the repository of additional software.
+
+        The input string "fileName" contains the folder name of aircraft projects.
+
+        The input float "install_percent" contains the current value of install progress bar in percent.
+
+        The input float "percent" contains the delta increment of install progress bar in percent.
+
+        The output float "install_percent" contains the current value of install progress bar in percent after updating
+            the bar.
+
+        :param self: input ui object
+        :param path_of_working_directory: input string
+        :param path_to_origin: input string
+        :param file_name: input string
+        :param install_percent: input float
+        :param percent: input float
+        :return install_percent: output float
+    """
+
+    ''' imports for python '''
+    import os
+    import shutil
+    from PyQt5.QtCore import QCoreApplication
+
+    # check for origin tool data and update only this files in working directory
+    if os.path.isdir(path_to_origin + file_name):
+        files_in_origin_tool_directory = os.listdir(path_to_origin + file_name)
+
+        for data in files_in_origin_tool_directory:
+            # check if data a file, then replace with file from origin tool directory
+            if os.path.isfile(path_of_working_directory + file_name + '/' + data):
+                os.remove(path_of_working_directory + file_name + '/' + data)
+                shutil.copyfile(path_to_origin + file_name + '/' + data, path_of_working_directory + file_name + '/'
+                                + data)
+                # update the installation progress bar
+                install_percent += percent
+                self.install_progress_bar.setValue(int(install_percent))
+                QCoreApplication.processEvents()
+
+            # check if data a directory, then replace with directory from origin tool directory
+            if os.path.isdir(path_of_working_directory + file_name + '/' + data):
+                shutil.rmtree(path_of_working_directory + file_name + '/' + data)
+                # check if data is not equal to src or convertUNICADO2CPACS
+                #  -> if true: -> copy data from origin to working directory
+                if not data == 'src' and not data == 'convertUNICADO2CPACS':
+                    shutil.copytree(path_to_origin + file_name + '/' + data, path_of_working_directory + file_name
+                                    + '/' + data)
+                    # update the installation progress bar
+                    install_percent += percent
+                    self.install_progress_bar.setValue(int(install_percent))
+                    QCoreApplication.processEvents()
+
+                # check if data is equal to convertUNICADO2CPACS
+                #  -> if true: -> copy all content inside the origin directory out of the src directory to working copy
+                if data == 'convertUNICADO2CPACS':
+                    data_inside = os.listdir(path_to_origin + file_name + '/' + data)
+                    os.mkdir(path_of_working_directory + file_name + '/' + data)
+                    for element in data_inside:
+                        if not element == 'src':
+                            if os.path.isfile(path_to_origin + file_name + '/' + data + '/' + element):
+                                shutil.copyfile(path_to_origin + file_name + '/' + data + '/' + element,
+                                                path_of_working_directory + file_name + '/' + data + '/' + element)
+                            else:
+                                shutil.copytree(path_to_origin + file_name + '/' + data + '/' + element,
+                                                path_of_working_directory + file_name + '/' + data + '/' + element)
+                                # update the installation progress bar
+                                install_percent += percent
+                                self.install_progress_bar.setValue(int(install_percent))
+                                QCoreApplication.processEvents()
+
+            # check if data exist in working directory, if not, then copy data to working directory
+            if not os.path.exists(path_of_working_directory + file_name + '/' + data):
+                if os.path.isfile(path_to_origin + file_name + '/' + data):
+                    shutil.copyfile(path_to_origin + file_name + '/' + data, path_of_working_directory + file_name
+                                    + '/' + data)
+                    # update the installation progress bar
+                    install_percent += percent
+                    self.install_progress_bar.setValue(int(install_percent))
+                    QCoreApplication.processEvents()
+
+                # check if data a directory, then replace with directory from origin tool directory
+                if os.path.isdir(path_to_origin + file_name + '/' + data):
+                    # check if data is not equal to src or convertUNICADO2CPACS
+                    #  -> if true: -> copy data from origin to working directory
+                    if not data == 'src' and not data == 'convertUNICADO2CPACS':
+                        shutil.copytree(path_to_origin + file_name + '/' + data, path_of_working_directory + file_name
+                                        + '/' + data)
+                        # update the installation progress bar
+                        install_percent += percent
+                        self.install_progress_bar.setValue(int(install_percent))
+                        QCoreApplication.processEvents()
+
+                    # check if data is equal to convertUNICADO2CPACS
+                    #  -> if true: -> copy all content inside the origin directory out of the src directory
+                    #   to working copy
+                    if data == 'convertUNICADO2CPACS':
+                        data_inside = os.listdir(path_to_origin + file_name + '/' + data)
+                        os.mkdir(path_of_working_directory + file_name + '/' + data)
+                        for element in data_inside:
+                            if not element == 'src':
+                                if os.path.isfile(path_to_origin + file_name + '/' + data + '/' + element):
+                                    shutil.copyfile(path_to_origin + file_name + '/' + data + '/' + element,
+                                                    path_of_working_directory + file_name + '/' + data + '/' + element)
+                                else:
+                                    shutil.copytree(path_to_origin + file_name + '/' + data + '/' + element,
+                                                    path_of_working_directory + file_name + '/' + data + '/' + element)
+                                    # update the installation progress bar
+                                    install_percent += percent
+                                    self.install_progress_bar.setValue(int(install_percent))
+                                    QCoreApplication.processEvents()
+
+    return install_percent
diff --git a/installer/sub_functions/update_design_tools.py b/installer/sub_functions/update_design_tools.py
new file mode 100644
index 0000000000000000000000000000000000000000..6453ef8b1f8855c1de937c4c7d56cbf794590e2a
--- /dev/null
+++ b/installer/sub_functions/update_design_tools.py
@@ -0,0 +1,79 @@
+def update_design_tools(self, path_of_working_directory, path_to_origin, file_name, install_percent, percent):
+    """ Function to auto update the additional software tools in the UNICADO working directory.
+
+        The input string "path_of_working_directory" contains the absolute path to installed working directory
+            of UNICADO.
+
+        The input string "path_to_origin" contains the absolute system path to the repository of additional software.
+
+        The input string "fileName" contains the folder name of aircraft projects.
+
+        The input float "install_percent" contains the current value of install progress bar in percent.
+
+        The input float "percent" contains the delta increment of install progress bar in percent.
+
+        The output float "install_percent" contains the current value of install progress bar in percent after updating
+            the bar.
+
+        :param self: input ui object
+        :param path_of_working_directory: input string
+        :param path_to_origin: input string
+        :param file_name: input string
+        :param install_percent: input float
+        :param percent: input float
+        :return install_percent: output float
+    """
+
+    ''' imports for python '''
+    import os
+    import shutil
+    from PyQt5.QtCore import QCoreApplication
+
+    # check for origin tool data and update only this files in working directory
+    if os.path.isdir(path_to_origin + file_name):
+        files_in_origin_tool_directory = os.listdir(path_to_origin + file_name)
+
+        for data in files_in_origin_tool_directory:
+            # check if data a file, then replace with file from origin tool directory
+            if os.path.isfile(path_of_working_directory + file_name + '/' + data):
+                os.remove(path_of_working_directory + file_name + '/' + data)
+                shutil.copyfile(path_to_origin + file_name + '/' + data, path_of_working_directory + file_name
+                                + '/' + data)
+                # update the installation progress bar
+                install_percent += percent
+                self.install_progress_bar.setValue(int(install_percent))
+                QCoreApplication.processEvents()
+
+            # check if data a directory, then replace with directory from origin tool directory
+            if os.path.isdir(path_of_working_directory + file_name + '/' + data):
+                shutil.rmtree(path_of_working_directory + file_name + '/' + data)
+                # check if data is not equal to src -> if true: -> copy data from origin to working directory
+                if not data == 'src':
+                    shutil.copytree(path_to_origin + file_name + '/' + data, path_of_working_directory + file_name
+                                    + '/' + data)
+                    # update the installation progress bar
+                    install_percent += percent
+                    self.install_progress_bar.setValue(int(install_percent))
+                    QCoreApplication.processEvents()
+
+            # check if data exist in working directory, if not, then copy data to working directory
+            if not os.path.exists(path_of_working_directory + file_name + '/' + data):
+                if os.path.isfile(path_to_origin + file_name + '/' + data):
+                    shutil.copyfile(path_to_origin + file_name + '/' + data, path_of_working_directory + file_name
+                                    + '/' + data)
+                    # update the installation progress bar
+                    install_percent += percent
+                    self.install_progress_bar.setValue(int(install_percent))
+                    QCoreApplication.processEvents()
+
+                if os.path.isdir(path_to_origin + file_name + '/' + data):
+                    # check if data is not equal to src -> if true: -> copy data from origin to working directory
+                    if not data == 'src':
+                        shutil.copytree(path_to_origin + file_name + '/' + data, path_of_working_directory + file_name
+                                        + '/' + data)
+                        # update the installation progress bar
+                        install_percent += percent
+                        self.install_progress_bar.setValue(int(install_percent))
+                        QCoreApplication.processEvents()
+
+    return install_percent
diff --git a/installer/sub_functions/update_projects_folder.py b/installer/sub_functions/update_projects_folder.py
new file mode 100644
index 0000000000000000000000000000000000000000..59eece31c663bb48c8ea5baa27bb78868bfaeb0d
--- /dev/null
+++ b/installer/sub_functions/update_projects_folder.py
@@ -0,0 +1,54 @@
+def update_projects_folder(path_of_working_directory, path_to_aircraft_projects, file_name):
+    """ Function to auto update the additional software tools in the UNICADO working directory.
+
+        The input string "path_of_working_directory" contains the absolute path to installed working directory
+            of UNICADO.
+
+        The input string "path_to_aircraft_projects" contains the absolute system path to the repository of additional
+            software.
+
+        The input string "fileName" contains the folder name of aircraft projects.
+
+        :param path_of_working_directory: input string
+        :param path_to_aircraft_projects: input string
+        :param file_name: input string
+        :return none
+    """
+
+    ''' imports for python '''
+    import os
+    import shutil
+
+    ''' loop across all existing aircraft projects in current project folder '''
+    files_in_origin_reference_directory = os.listdir(path_to_aircraft_projects)
+    for project in files_in_origin_reference_directory:
+        if not project == '.git':
+            # check if aircraft reference project exist in projects working directory
+            #  -> if false: -> then copy aircraft reference project to working directory
+            if not os.path.exists(path_of_working_directory + file_name + '/' + project):
+                if os.path.isdir(path_to_aircraft_projects + project):
+                    shutil.copytree(path_to_aircraft_projects + project, path_of_working_directory + file_name + '/'
+                                    + project)
+            else:
+                files_in_origin_reference_project_directory = os.listdir(path_to_aircraft_projects + project)
+                for data in files_in_origin_reference_project_directory:
+                    # check if data a file, then replace with file from origin tool directory
+                    if os.path.isfile(path_of_working_directory + file_name + '/' + project + '/' + data):
+                        os.remove(path_of_working_directory + file_name + '/' + project + '/' + data)
+                        shutil.copyfile(path_to_aircraft_projects + project + '/' + data, path_of_working_directory
+                                        + file_name + '/' + project + '/' + data)
+
+                    # check if data a directory, then replace with directory from origin tool directory
+                    if os.path.isdir(path_of_working_directory + file_name + '/' + project + '/' + data):
+                        shutil.rmtree(path_of_working_directory + file_name + '/' + project + '/' + data)
+                        shutil.copytree(path_to_aircraft_projects + project + '/' + data, path_of_working_directory
+                                        + file_name + '/' + project + '/' + data)
+
+                    # check if data exist in working directory, if not, then copy data to working directory
+                    if not os.path.exists(path_of_working_directory + file_name + '/' + project + '/' + data):
+                        if os.path.isfile(path_to_aircraft_projects + project + '/' + data):
+                            shutil.copyfile(path_to_aircraft_projects + project + '/' + data, path_of_working_directory
+                                            + file_name + '/' + project + '/' + data)
+                        if os.path.isdir(path_to_aircraft_projects + project + '/' + data):
+                            shutil.copytree(path_to_aircraft_projects + project + '/' + data, path_of_working_directory
+                                            + file_name + '/' + project + '/' + data)
diff --git a/installer/sub_functions/update_steps.py b/installer/sub_functions/update_steps.py
new file mode 100644
index 0000000000000000000000000000000000000000..156de38469712c6ba92649d5c89266cf8b7b9fa8
--- /dev/null
+++ b/installer/sub_functions/update_steps.py
@@ -0,0 +1,431 @@
+# imports for python
+import os
+import json
+import stat
+import time
+import shutil
+import configparser
+from PyQt5 import QtCore, QtGui
+from PyQt5.QtCore import QCoreApplication
+from sub_functions.update_design_tools import update_design_tools
+from sub_functions.update_projects_folder import update_projects_folder
+from sub_functions.update_additional_software import update_additional_software
+
+
+def update_steps(self):
+    # handle ui objects for visibility
+    self.welcome_panel.setVisible(False)
+    self.header_panel.setVisible(True)
+    self.integration_panel.setVisible(True)
+    self.tool_name_panel.setVisible(False)
+    self.update_button.setVisible(False)
+    self.update_button.setEnabled(False)
+    self.uninstall_button.setVisible(False)
+    self.uninstall_button.setEnabled(False)
+    self.next_button.setVisible(True)
+    self.next_button.setEnabled(True)
+    self.next_button.setText('Update')
+    self.cancel_button.setText('Cancel')
+    self.back_button.setVisible(True)
+    self.back_button.setEnabled(True)
+    self.integration_button.setVisible(False)
+    self.integration_button.setEnabled(False)
+
+    # set description to text fields
+    self.header_text_label_1.setText('Welcome to the UNICADO updater.')
+    self.header_text_label_2.setText('This tool will guide you through the update job of UNICADO.')
+    self.integration_text_label_1.setText('If you really want to update the UNICADO workflow, click "Update" '
+                                          'or click "Back" to return to the previous page. \n'
+                                          'Click "Cancel" to quit the uninstaller.')
+
+
+def update_unicado(self):
+    """ Call function to update all installed UNICADO components of the working directory.
+
+        :rtype: object
+    """
+
+    ''' initialize public parameter '''
+    repository_path = str()
+    install_path = str()
+    path_to_aircraft_design_tools = str()
+    path_to_aircraft_projects = str()
+    path_to_software_tools = str()
+
+    ''' update installed working version of UNICADO '''
+    self.install_and_finish_panel.setVisible(True)
+    self.header_panel.setVisible(True)
+    font = QtGui.QFont()
+    font.setPointSize(16)
+    font.setBold(True)
+    font.setWeight(75)
+    self.header_text_label_1.setFont(font)
+    self.header_text_label_1.setText('Update in progress, please wait.')
+    self.header_text_label_2.setText('')
+    self.header_text_label_1.setGeometry(QtCore.QRect(30, 22, 400, 50))
+    font = QtGui.QFont()
+    font.setFamily("Calibri")
+    font.setPointSize(11)
+    font.setBold(False)
+    self.install_and_finish_panel_text_label_1.setText('Please wait until UNICADOworkflow update is finished.')
+    self.install_and_finish_panel_text_label_2.setText('After completing the update process, click Finish.')
+    QCoreApplication.processEvents()
+    self.uninstall_button.setVisible(False)
+    self.back_button.setVisible(False)
+    self.back_button.setEnabled(False)
+    self.next_button.setVisible(False)
+    self.next_button.setEnabled(False)
+    self.update_button.setEnabled(False)
+    self.cancel_button.setVisible(True)
+    self.cancel_button.setEnabled(False)
+    self.cancel_button.setText('Finish')
+    self.integration_button.setVisible(False)
+    self.integration_button.setEnabled(False)
+    QCoreApplication.processEvents()
+    user_path_string = os.path.expanduser("~")
+    user_path_string = user_path_string.replace(os.sep, '/')
+    user_path_string = user_path_string + '/'
+    path_to_tool_json_files = user_path_string + '.rce/default/integration/tools/common/'
+
+    # check if toolListUNICADOworkflow.txt exist and readable
+    try:
+        error_flag = False
+        workflow_tools = open(path_to_tool_json_files + 'toolListUNICADOworkflow.txt', 'a')
+
+        # check if absolutPathToUNICADOInstallDirectory.txt and readable
+        try:
+            read_install_path = open(path_to_tool_json_files + 'absolutPathToUNICADOInstallDirectory.txt', 'r')
+            install_path = read_install_path.read()
+            read_install_path.close()
+
+        # exception handling if not absolutPathToUNICADOInstallDirectory.txt exist or is not readable
+        except OSError:
+            for tool in workflow_tools:
+                folder_name = tool.rstrip()
+                if os.path.isdir(path_to_tool_json_files + '/' + folder_name):
+                    with open(path_to_tool_json_files + folder_name + '/configuration.json', 'r+') as jsonFile:
+                        json_data = json.load(jsonFile)
+                    launch_settings = json_data['launchSettings']
+                    install_path = launch_settings[0]['rootWorkingDirectory']
+                    string_position = install_path.find('UNICADOworkflow')
+                    if not (string_position == -1):
+                        install_directory = install_path[:string_position] + 'UNICADOworkflow/'
+                        if os.path.isdir(install_directory):
+                            file_for_install_path = open(path_to_tool_json_files
+                                                         + 'absolutPathToUNICADOInstallDirectory.txt', 'w')
+                            file_for_install_path.write(install_directory)
+                            file_for_install_path.close()
+                            break
+
+        # check if absolutPathToUNICADOrepositoryDirectory.txt and readable
+        try:
+            read_repository_path = open(path_to_tool_json_files + 'absolutPathToUNICADOrepositoryDirectory.txt', 'r')
+            repository_path = read_repository_path.read()
+            read_repository_path.close()
+
+        # exception handling if not absolutPathToUNICADOrepositoryDirectory.txt exist or is not readable
+        except OSError:
+            error_flag = True
+            self.welcome_panel.setVisible(True)
+            self.install_and_finish_panel.setVisible(False)
+            self.header_panel.setVisible(False)
+            self.welcome_text_label_1.setText('Attention! An Error has occurred!')
+            self.install_text_label_1.setText('UNICADOworkflow can not be updated!')
+            self.install_text_label_2.setText('Please re-install UNICADOworkflow. After that, UNICADO will '
+                                              'automatically be updated.')
+            self.update_button.setVisible(False)
+            self.update_button.setEnabled(True)
+            self.uninstall_button.setVisible(True)
+            self.cancel_button.setText('Abort')
+            self.cancel_button.setEnabled(True)
+            self.cancel_button.setVisible(True)
+            QCoreApplication.processEvents()
+
+        if not error_flag:
+            # check if the standard tool file is existing -> if true: -> delete the file
+            if os.path.isfile(path_to_tool_json_files + 'standardToolListUNICADOworkflow.txt'):
+                os.remove(path_to_tool_json_files + 'standardToolListUNICADOworkflow.txt')
+
+            # set repository directories to copy files
+            files = os.listdir(repository_path)
+            for fileName in files:
+                if os.path.isdir(repository_path + fileName):
+                    if os.path.isdir(repository_path + fileName + '/.git'):
+                        if os.path.isfile(repository_path + fileName + '/.git/config'):
+                            config = configparser.ConfigParser()
+                            config.read(repository_path + fileName + '/.git/config')
+                            if config.has_section('remote "origin"'):
+                                url = config['remote "origin"']['url']
+                                if url == 'ssh://git@unicado.ilr.rwth-aachen.de:2222/source/rADDITIONALSOFTWARE.git':
+                                    path_to_software_tools = repository_path + fileName + '/'
+
+                                if url == 'ssh://git@unicado.ilr.rwth-aachen.de:2222/source/rAircraftDesign.git':
+                                    path_to_aircraft_design_tools = repository_path + fileName + '/'
+
+                                if url == 'ssh://git@unicado.ilr.rwth-aachen.de:2222/source/rAIRCRAFTREFERENCES.git':
+                                    path_to_aircraft_projects = repository_path + fileName + '/'
+
+            # tool exist in working directory, only origin tool files will be updated, no changes to own files
+            #  -> create list of files in working directory
+            files_in_working_directory = os.listdir(install_path)
+            files_in_origin_tool_directory = os.listdir(path_to_aircraft_design_tools)
+            self.timer = QtCore.QTimer()
+            self.timer.start(0)
+            install_percent = float(0)
+            copy_count_working = len(files_in_working_directory) * 10
+            copy_count_origin = len(files_in_origin_tool_directory) * 10
+            if copy_count_working >= copy_count_origin:
+                percent = float(round(100 / copy_count_working, 1))
+            else:
+                percent = float(round(100 / copy_count_origin, 1))
+
+            # loop for all elements in list of files
+            for fileName in files_in_working_directory:
+                if fileName == 'projects':
+                    update_projects_folder(install_path, path_to_aircraft_projects, fileName)
+                    # update the installation progress bar
+                    install_percent += percent
+                    self.install_progress_bar.setValue(int(install_percent))
+                    QCoreApplication.processEvents()
+
+                # check if current list element not 'workingDirectoryRCE' or 'workflowResults'
+                if not (fileName == 'workingDirectoryRCE') and not (fileName == 'workflowResults') \
+                        and not (fileName == 'projects'):
+                    # change execution rights for each file and folder in 'filName' to read, write and execute
+                    for root, dirs, files in os.walk(install_path + fileName):
+                        for directory in dirs:
+                            os.chmod(os.path.join(root, directory), stat.S_IRWXU)
+                        for file in files:
+                            os.chmod(os.path.join(root, file), stat.S_IRWXU)
+
+                    # path handling to origin tool directories
+                    if (fileName == 'gnuplot') or (fileName == 'gnuplot-linux') or (fileName == 'inkscape') \
+                            or (fileName == 'inkscape-linux') or (fileName == 'reportGenerator') \
+                            or (fileName == 'cpacsInterface'):
+                        path_to_origin = path_to_software_tools
+                        # call function to update the installed additional software in the unicado working directory
+                        install_percent = update_additional_software(self, install_path, path_to_origin, fileName,
+                                                                     install_percent, percent)
+
+                    else:
+                        path_to_origin = path_to_aircraft_design_tools
+                        # call function to update the installed aircraft design tools in the unicado working directory
+                        install_percent = update_design_tools(self, install_path, path_to_origin, fileName,
+                                                              install_percent, percent)
+
+            # copy json files to .rce directory and set paths to module json file
+            json_files = os.listdir(path_to_aircraft_design_tools + 'UNICADOworkflow/jsonFiles')
+            for jsonfile in json_files:
+                if not os.path.isdir(install_path + jsonfile):
+                    if os.path.isdir(path_to_software_tools + jsonfile):
+                        source = path_to_aircraft_design_tools + 'UNICADOworkflow/jsonFiles/' + jsonfile
+                        destination = path_to_tool_json_files + jsonfile
+                        if not os.path.isdir(path_to_tool_json_files + jsonfile):
+                            shutil.copytree(source, destination)
+                            workflow_tools.write(jsonfile + '\n')
+                        if not os.path.isdir(install_path + jsonfile):
+                            shutil.copytree(path_to_software_tools + jsonfile, install_path + jsonfile)
+                        # write paths to json configuration file of each module
+                        with open(path_to_tool_json_files + jsonfile + '/configuration.json', 'r+') as jsonFile:
+                            json_data = json.load(jsonFile)
+                        launch_settings = json_data['launchSettings']
+                        launch_settings[0]['rootWorkingDirectory'] = install_path + 'workingDirectoryRCE'
+                        launch_settings[0]['toolDirectory'] = install_path + jsonfile
+                        json.dump(json_data, open(path_to_tool_json_files + jsonfile + '/configuration.json', 'w'),
+                                  indent=2, sort_keys=False)
+                    elif os.path.isdir(path_to_aircraft_design_tools + jsonfile):
+                        source = path_to_aircraft_design_tools + 'UNICADOworkflow/jsonFiles/' + jsonfile
+                        destination = path_to_tool_json_files + jsonfile
+                        if not (os.path.isdir(path_to_tool_json_files + jsonfile)):
+                            shutil.copytree(source, destination)
+                            workflow_tools.write(jsonfile + '\n')
+                        if not (os.path.isdir(install_path + jsonfile)):
+                            shutil.copytree(path_to_aircraft_design_tools + jsonfile, install_path + jsonfile)
+                        # write paths to json configuration file of each module
+                        with open(path_to_tool_json_files + jsonfile + '/configuration.json', 'r+') as jsonFile:
+                            json_data = json.load(jsonFile)
+                        launch_settings = json_data['launchSettings']
+                        launch_settings[0]['rootWorkingDirectory'] = install_path + 'workingDirectoryRCE'
+                        launch_settings[0]['toolDirectory'] = install_path + jsonfile
+                        json.dump(json_data, open(path_to_tool_json_files + jsonfile + '/configuration.json', 'w'),
+                                  indent=2, sort_keys=False)
+                else:
+                    source = path_to_aircraft_design_tools + 'UNICADOworkflow/jsonFiles/' + jsonfile \
+                             + '/configuration.json'
+                    destination = path_to_tool_json_files + jsonfile + '/configuration.json'
+                    shutil.copy(source, destination)
+                    # write paths to json configuration file of each module
+                    with open(path_to_tool_json_files + jsonfile + '/configuration.json', 'r+') as jsonFile:
+                        json_data = json.load(jsonFile)
+                    launch_settings = json_data['launchSettings']
+                    launch_settings[0]['rootWorkingDirectory'] = install_path + 'workingDirectoryRCE'
+                    launch_settings[0]['toolDirectory'] = install_path + jsonfile
+                    json.dump(json_data, open(path_to_tool_json_files + jsonfile + '/configuration.json', 'w'),
+                              indent=2, sort_keys=False)
+
+            install_percent += percent
+            self.install_progress_bar.setValue(int(install_percent))
+            QCoreApplication.processEvents()
+
+            # copy workflow and workflow configuration file
+            if os.path.isdir(path_to_aircraft_design_tools + 'UNICADOworkflow/UNICADOworkFlowOnRCE/'):
+                list_of_elements = os.listdir(path_to_aircraft_design_tools + 'UNICADOworkflow/UNICADOworkFlowOnRCE/')
+                for element in list_of_elements:
+                    source = path_to_aircraft_design_tools + 'UNICADOworkflow/UNICADOworkFlowOnRCE/' + element
+                    destination = install_path + 'workingDirectoryRCE/UNICADOworkflow/'
+                    if os.path.isfile(path_to_aircraft_design_tools + 'UNICADOworkflow/UNICADOworkFlowOnRCE/'
+                                      + element):
+                        shutil.copy(source, destination)
+                    if os.path.isdir(path_to_aircraft_design_tools + 'UNICADOworkflow/UNICADOworkFlowOnRCE/' + element):
+                        if os.path.isdir(install_path + 'workingDirectoryRCE/UNICADOworkflow/src'):
+                            shutil.rmtree(install_path + 'workingDirectoryRCE/UNICADOworkflow/src')
+                        shutil.copytree(source, destination + 'src')
+                    QCoreApplication.processEvents()
+
+                # check for own files, if existing, copy to new working directory
+                if os.path.isdir(install_path + 'workingDirectoryRCE/UNICADOworkflow/UNICADOworkFlowOnRCE/'):
+                    list_of_existing_elements = os.listdir(
+                        install_path + 'workingDirectoryRCE/UNICADOworkflow/UNICADOworkFlowOnRCE/')
+                    for existing_element in list_of_existing_elements:
+                        source = install_path + 'workingDirectoryRCE/UNICADOworkflow/UNICADOworkFlowOnRCE/'
+                        destination = install_path + 'workingDirectoryRCE/UNICADOworkflow/'
+                        if not os.path.exists(install_path + 'workingDirectoryRCE/UNICADOworkflow/' + existing_element):
+                            if os.path.isfile(
+                                    install_path + 'workingDirectoryRCE/UNICADOworkflow/UNICADOworkFlowOnRCE/'
+                                    + existing_element):
+                                shutil.copyfile(source + existing_element, destination + existing_element)
+                            if os.path.isdir(
+                                    install_path + 'workingDirectoryRCE/UNICADOworkflow/UNICADOworkFlowOnRCE/'
+                                    + existing_element):
+                                shutil.copytree(source + existing_element, destination + existing_element)
+                        QCoreApplication.processEvents()
+                    shutil.rmtree(install_path + 'workingDirectoryRCE/UNICADOworkflow/UNICADOworkFlowOnRCE/')
+            install_percent += percent
+            self.install_progress_bar.setValue(int(install_percent))
+            QCoreApplication.processEvents()
+
+            # move .metadata directory to workingDirectoryRCE
+            if os.path.isdir(install_path + 'workingDirectoryRCE/UNICADOworkflow/.metadata'):
+                if os.path.isdir(install_path + 'workingDirectoryRCE/.metadata'):
+                    shutil.rmtree(install_path + 'workingDirectoryRCE/.metadata')
+                source = install_path + 'workingDirectoryRCE/UNICADOworkflow/.metadata'
+                destination = install_path + 'workingDirectoryRCE/.metadata'
+                shutil.copytree(source, destination)
+                shutil.rmtree(install_path + 'workingDirectoryRCE/UNICADOworkflow/.metadata')
+                QCoreApplication.processEvents()
+
+            # copy workflow configuration file to workflow directory
+            if os.path.isfile(path_to_aircraft_design_tools + 'UNICADOworkflow/UNICADOworkflow_conf.xml'):
+                source = path_to_aircraft_design_tools + 'UNICADOworkflow/UNICADOworkflow_conf.xml'
+                destination = install_path + 'workingDirectoryRCE/UNICADOworkflow/UNICADOworkflow_conf.xml'
+                shutil.copy(source, destination)
+
+            # copy version.txt to working directory of UNICADOworkflow
+            if os.path.isfile(path_to_aircraft_design_tools + 'UNICADOworkflow/version.txt'):
+                shutil.copyfile(path_to_aircraft_design_tools + 'UNICADOworkflow/version.txt',
+                                install_path + 'workingDirectoryRCE/UNICADOworkflow/workingVersion.txt')
+
+            install_percent += percent
+            self.install_progress_bar.setValue(int(install_percent))
+            QCoreApplication.processEvents()
+
+            # write paths to json configuration file of each module
+            path_to_settings_file = user_path_string + '.rce/default/internal/'
+            if not os.path.isdir(user_path_string + '.rce/default/internal/'):
+                os.makedirs(user_path_string + '.rce/default/internal/')
+
+            if not os.path.isfile(user_path_string + '.rce/default/internal/settings.json'):
+                json_data = {'rce.workspace.recentLocations': '',
+                             'rce.workspace.lastLocation': '',
+                             'rce.workspace.dontAskAgain': 'false'}
+                # Write JSON file
+                with open(user_path_string + '.rce/default/internal/settings.json', 'w') as jsonFile:
+                    json.dump(json_data, open(path_to_settings_file + 'settings.json', 'w'))
+
+            if os.path.isfile(user_path_string + '.rce/default/internal/settings.json'):
+                with open(path_to_settings_file + 'settings.json', 'r+') as jsonFile:
+                    # check if settings.json file is empty
+                    try:
+                        json_data = json.load(jsonFile)
+                    except OSError:
+                        json_data = {'rce.workspace.recentLocations': '',
+                                     'rce.workspace.lastLocation': '',
+                                     'rce.workspace.dontAskAgain': 'false'}
+                workspace_location_rce = json_data['rce.workspace.recentLocations']
+                if os.name == 'nt':
+                    install_path = install_path.replace('/', '\\')
+                    alternate_path = install_path.replace('\\', '\\\\')
+                    json_data['rce.workspace.lastLocation'] = install_path + 'workingDirectoryRCE'
+                    if not install_path[0] + '\:' + '\\' + install_path[3:] \
+                                           + 'workingDirectoryRCE' in workspace_location_rce:
+                        if not install_path[0] + '\:' + alternate_path[2:] + 'workingDirectoryRCE' \
+                               in workspace_location_rce:
+                            json_data['rce.workspace.recentLocations'] = install_path[0] + '\:' + alternate_path[2:] \
+                                                                         + 'workingDirectoryRCE' + ':' \
+                                                                         + workspace_location_rce
+                            install_percent += percent
+                            self.install_progress_bar.setValue(int(install_percent))
+                            QCoreApplication.processEvents()
+
+                        else:
+                            str_start = workspace_location_rce.index(install_path[0] + '\:' + alternate_path[2:]
+                                                                     + 'workingDirectoryRCE')
+                            str_end = workspace_location_rce.index('workingDirectoryRCE')
+                            if str_start > 0:
+                                sub_string_front = workspace_location_rce[0:str_start - 1]
+                                total_length = len(workspace_location_rce)
+                                new_string = workspace_location_rce[str_start:str_end + 19] + ':' + sub_string_front
+                                if str_end + 19 < total_length:
+                                    sub_string_end = workspace_location_rce[str_end + 20:total_length]
+                                    new_string = new_string + ':' + sub_string_end
+                                json_data['rce.workspace.recentLocations'] = new_string
+                                install_percent += percent
+                                self.install_progress_bar.setValue(int(install_percent))
+                                QCoreApplication.processEvents()
+
+                if os.name == 'posix':
+                    json_data['rce.workspace.lastLocation'] = install_path + 'workingDirectoryRCE'
+                    if not install_path + 'workingDirectoryRCE' in workspace_location_rce:
+                        json_data['rce.workspace.recentLocations'] = install_path + 'workingDirectoryRCE' + ':' \
+                                                                     + workspace_location_rce
+                        install_percent += percent
+                        self.install_progress_bar.setValue(int(install_percent))
+                        QCoreApplication.processEvents()
+
+                # check if rce.workspace.dontAskAgain exist and set to false
+                if 'rce.workspace.dontAskAgain' in json_data:
+                    json_data['rce.workspace.dontAskAgain'] = 'false'
+                else:
+                    json_data['rce.workspace.dontAskAgain'] = 'false'
+
+                json.dump(json_data, open(path_to_settings_file + 'settings.json', 'w'))
+
+            self.install_progress_bar.setValue(int(100))
+            QCoreApplication.processEvents()
+            time.sleep(1)
+            self.welcome_text_label_1.setText('UNICADOworkflow was successfully updated')
+            self.install_text_label_1.setText('Please click Finish to exit the installer.')
+            self.install_text_label_2.setText('')
+            self.update_button.setVisible(False)
+            self.cancel_button.setVisible(True)
+            self.cancel_button.setEnabled(True)
+            QCoreApplication.processEvents()
+
+        workflow_tools.close()
+
+    # exception handling if not toolListUNICADOworkflow.txt exist or is not readable
+    except OSError:
+        self.welcome_panel.setVisible(True)
+        self.install_and_finish_panel.setVisible(False)
+        self.header_panel.setVisible(False)
+        self.welcome_text_label_1.setText('Attention! An Error has occurred!')
+        self.install_text_label_1.setText('UNICADOworkflow can not be updated!')
+        self.install_text_label_2.setText('Please re-install UNICADOworkflow. '
+                                          'After that, UNICADO will automatically be updated.')
+        self.update_button.setVisible(False)
+        self.update_button.setEnabled(True)
+        self.uninstall_button.setVisible(True)
+        self.cancel_button.setText('Abort')
+        self.cancel_button.setEnabled(True)
+        self.cancel_button.setVisible(True)
+        QCoreApplication.processEvents()
diff --git a/installer/sub_functions/write_json_file.py b/installer/sub_functions/write_json_file.py
new file mode 100644
index 0000000000000000000000000000000000000000..c8ce4fe6522a8ff1c0f37896030a50ef4dfd8e19
--- /dev/null
+++ b/installer/sub_functions/write_json_file.py
@@ -0,0 +1,104 @@
+# imports for python
+import os
+#import git
+import json
+
+
+def write_json_file(self, path_to_tool_json_files, install_path, tool_name, group_name, error_flag, integration_flag,
+                    path_to_aircraft_design_tools):
+    # initialize local parameter
+    error_handling_string = str("")
+
+    try:
+        if self.integration_radio_button_yes.isChecked():
+            error_handling_string = "import os\r\ncurrent_working_dir = \"${in:current_workflow_name}\"\r\n\r\nif ${addProp:exitCode} == 1:\r\n\t### read sys path for python scripts\r\n\tuser_path_string = os.path.expanduser(\"~\")\r\n\r\n\t## convert path of curent working directory to a python path -> \\ to /\r\n\tuser_path_string = user_path_string.replace(os.sep, '/')\r\n\r\n\t## generate sys paths from file in .rce-directory\r\n\tinstall_path = open(user_path_string + '/.rce/default/integration/tools/common/absolutPathToUNICADOInstallDirectory.txt','r')\r\n\tinstall_path_directory = str(install_path.read())\r\n\tinstall_path_directory = install_path_directory.replace(os.sep, '/')\r\n\r\n\t## path to working directory of rce \r\n\tpath_of_working_directory_rce = install_path_directory + 'workingDirectoryRCE/' + current_working_dir\r\n\r\n\t## write error data to system\r\n\terror_dat = open(path_of_working_directory_rce + '/temp/workflowExecutionError.dat', 'a+')\r\n\terror_dat.close()\r\n\t\r\n\t## write tool name to tool error list of current workflow loop\r\n\ttool_error_list = open(path_of_working_directory_rce + '/temp/toolErrorList.log', 'a+')\r\n\ttool_error_list.write('Error occurred in design tool: calculatePolar' + '\\n')\r\n\ttool_error_list.close()\r\n\r\n${out:current_workflow_name} = current_working_dir\r\n"
+
+        if self.integration_radio_button_no.isChecked():
+            error_handling_string = "import os\r\ncurrent_working_dir = \"${in:current_workflow_name}\"\r\n\r\nif ${addProp:exitCode} == 1:\r\n\t### read sys path for python scripts\r\n\tuser_path_string = os.path.expanduser(\"~\")\r\n\r\n\t## convert path of curent working directory to a python path -> \\ to /\r\n\tuser_path_string = user_path_string.replace(os.sep, '/')\r\n\r\n\t## generate sys paths from file in .rce-directory\r\n\tinstall_path = open(user_path_string + '/.rce/default/integration/tools/common/absolutPathToUNICADOInstallDirectory.txt','r')\r\n\tinstall_path_directory = str(install_path.read())\r\n\tinstall_path_directory = install_path_directory.replace(os.sep, '/')\r\n\r\n\t## path to working directory of rce \r\n\tpath_of_working_directory_rce = install_path_directory + 'workingDirectoryRCE/' + current_working_dir\r\n\r\n\t## write tool name to tool error list of current workflow loop\r\n\ttool_error_list = open(path_of_working_directory_rce + '/temp/toolErrorList.log', 'a+')\r\n\ttool_error_list.write('Error occurred in design tool: calculateEmissions' + '\\n')\r\n\ttool_error_list.close()\r\n\r\n${out:current_workflow_name} = current_working_dir\r\n"
+
+        if not os.path.isdir(path_to_tool_json_files + tool_name):
+            os.mkdir(path_to_tool_json_files + tool_name)
+
+        configuration_dict = {
+            "commandScriptLinux": './' + tool_name + '-c ../workingDirectoryRCE/${in:current_workflow_name}/'
+                                  + tool_name + '_conf.xml',
+            "commandScriptWindows": tool_name + '.exe -c ../workingDirectoryRCE/${in:current_workflow_name}/'
+                                              + tool_name + '_conf.xml',
+            "copyToolBehavior": "never",
+            "deleteWorkingDirectoriesAfterWorkflowExecution": True,
+            "documentationFilePath": "",
+            "dontCrashOnNonZeroExitCodes": True,
+            "enableCommandScriptLinux": True,
+            "enableCommandScriptWindows": True,
+            "groupName": group_name,
+            "imitationScript": "",
+            "imitationToolOutputFilename": "",
+            "inputs": [{
+                "inputHandling": "Queue",
+                "endpointFileName": "",
+                "endpointDataType": "ShortText",
+                "defaultInputExecutionConstraint": "Required",
+                "endpointName": 'current_workflow_name',
+                "defaultInputHandling": "Queue",
+                "inputExecutionConstraint": "Required",
+                "endpointFolder": ""
+            }],
+            "integrationType": "Common",
+            "isActive": True,
+            "launchSettings": [{
+                "limitInstallationInstancesNumber": "10",
+                "limitInstallationInstances": "true",
+                "rootWorkingDirectory": install_path + 'workingDirectoryRCE',
+                "host": "RCE",
+                "toolDirectory": install_path + tool_name,
+                "version": "allTime"
+            }],
+            "outputs": [{
+                "inputHandling": "-",
+                "endpointFileName": "",
+                "endpointDataType": "Boolean",
+                "endpointName": 'outputFlag' + tool_name[0].upper() + tool_name[1:],
+                "inputExecutionConstraint": "-",
+                "endpointFolder": ""
+            }, {
+                "inputHandling": "-",
+                "endpointFileName": "",
+                "endpointDataType": "ShortText",
+                "endpointName": "current_workflow_name",
+                "inputExecutionConstraint": "-",
+                "endpointFolder": ""
+            }],
+            "postScript": error_handling_string,
+            "preScript": "",
+            "setToolDirAsWorkingDir": True,
+            "toolDescription": "",
+            "toolIconPath": "",
+            "toolIntegrationVersion": 1,
+            "toolIntegratorE-Mail": "",
+            "toolIntegratorName": "",
+            "toolName": tool_name,
+            "toolProperties": {
+                "Default": {}
+            },
+            "uploadIcon": True
+        }
+
+        json.dump(configuration_dict, open(path_to_tool_json_files + tool_name + '/configuration.json', 'w'),
+                  indent=2, sort_keys=False)
+
+        # if integration_flag:
+        #     with open(path_to_tool_json_files + tool_name + '/configuration.json', 'r+') as jsonFile:
+        #         json_dict = json.load(jsonFile)
+        #     json_dict['launchSettings'][0]['rootWorkingDirectory'] = 'C:/'
+        #     json_dict['launchSettings'][0]['toolDirectory'] = 'C:/'
+        #     json.dump(json_dict, open(path_to_tool_json_files + tool_name + '/configuration.json', 'w'),
+        #               indent=2, sort_keys=False)
+        #     repo = git.Repo(path_to_aircraft_design_tools)
+        #     repo.git.add(path_to_tool_json_files + tool_name + '/configuration.json')
+
+    # exception handling for json error -> if error: -> set error flag to true for display error message in ui
+    except OSError:
+        error_flag = True
+        return error_flag
+
+    return error_flag
diff --git a/installer/sub_functions/write_path_to_environment.py b/installer/sub_functions/write_path_to_environment.py
new file mode 100644
index 0000000000000000000000000000000000000000..015e88bdbf89fb3a9730d70df4585ddb9d5481a2
--- /dev/null
+++ b/installer/sub_functions/write_path_to_environment.py
@@ -0,0 +1,88 @@
+def write_path_to_environment(path_to_add_to_environment):
+    """
+        Function to write the entered path permanently to the local user environment.
+
+        * The input string 'path_to_add_to_environment' contains the path to add.
+
+        * The output bool 'status_path_adding' contains the status whether adding paths was successful.
+
+        :param path_to_add_to_environment: input string
+        :return status_path_adding: output bool
+    """
+    ''' imports for python '''
+    import os
+    import winreg
+    import unicodedata
+
+    ''' initialize local parameter '''
+    count = 0
+    index_1 = 0
+    path_new = str()
+    status_path_adding = True
+
+    # check if the operating system is Windows -> if true: -> try to write local user path environment
+    if os.name == 'nt':
+        ''' convert entered string to windows norm path '''
+        path_to_add_to_environment = os.path.normpath(path_to_add_to_environment)
+
+        ''' read existing path variables from users local registry '''
+        # try to open environment path variable to read existing local path entries
+        try:
+            key_q = winreg.OpenKey(winreg.HKEY_CURRENT_USER, 'Environment', 0, winreg.KEY_QUERY_VALUE)
+            path_old, _ = winreg.QueryValueEx(key_q, "PATH")
+            winreg.CloseKey(key_q)
+
+            # convert registry key value to ascii string containing the existing path variables
+            path_old = str(unicodedata.normalize('NFKD', path_old).encode('ascii', 'ignore'))
+
+            # loop across all characters of string to cut unnecessary elements at the beginning of converted string
+            for char in path_old:
+                if not char == 'C' or char == '%':
+                    path_old = path_old[1:]
+                else:
+                    break
+
+            # check if the last character of converted string equal to ' -> if true: -> delete character from string
+            if path_old[-1] == "'":
+                path_old = path_old[:-1]
+
+            # loop across all characters of loaded string to convert containing path elements to windows norm paths
+            for chars in path_old:
+                if chars == ';':
+                    index_2 = count
+                    single_path = path_old[index_1:index_2]
+                    index_1 = index_2 + 1
+                    single_path = os.path.normpath(single_path)
+                    path_new = path_new + ';' + single_path
+
+                count += 1
+
+        # exception handling if the local environment variables could not read or does not exist
+        except OSError:
+            status_path_adding = False
+            return status_path_adding
+
+        # check if the entered path already exist in the local user environment variables
+        #  -> if true: -> do nothing and return
+        if not str(path_new).find(str(path_to_add_to_environment)) == -1:
+            return status_path_adding
+
+        # else condition: entered path currently does not exist in the local user environment variables -> add path
+        else:
+            path_new = path_new[1:] + ';' + path_to_add_to_environment
+            # try to open environment path variable to write new local path entries
+            try:
+                registry_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, 'Environment', 0, winreg.KEY_WRITE)
+                winreg.SetValueEx(registry_key, "PATH", 0, winreg.REG_SZ, path_new)
+                winreg.CloseKey(registry_key)
+
+            # exception handling if the paths could not write to the local user environment variables
+            except OSError:
+                status_path_adding = False
+                return status_path_adding
+
+    # check if the operating system is unix or linux -> if true: -> send False to caller function
+    if os.name == 'posix':
+        # add path to local user environment variables for unix or linx currently not implemented
+        status_path_adding = False
+        return status_path_adding
diff --git a/installer/unicadoICON.svg b/installer/unicadoICON.svg
new file mode 100644
index 0000000000000000000000000000000000000000..08022fe96a92b816be749cb6715a4c88d7f11b33
--- /dev/null
+++ b/installer/unicadoICON.svg
@@ -0,0 +1 @@
+<svg width="38" height="38" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" overflow="hidden"><defs><clipPath id="clip0"><rect x="618" y="266" width="38" height="38"/></clipPath><clipPath id="clip1"><rect x="619" y="267" width="36" height="36"/></clipPath><clipPath id="clip2"><rect x="619" y="267" width="36" height="36"/></clipPath><clipPath id="clip3"><rect x="619" y="268" width="35" height="34"/></clipPath><clipPath id="clip4"><rect x="619" y="268" width="35" height="34"/></clipPath><clipPath id="clip5"><rect x="619" y="268" width="35" height="34"/></clipPath><linearGradient x1="113.319" y1="135.713" x2="98.8327" y2="150.199" gradientUnits="userSpaceOnUse" spreadMethod="pad" id="fill6"><stop offset="0" stop-color="#6C6C6C"/><stop offset="1"/></linearGradient><linearGradient x1="107.198" y1="144.648" x2="87.9471" y2="148.629" gradientUnits="userSpaceOnUse" spreadMethod="pad" id="fill7"><stop offset="0" stop-color="#00427D"/><stop offset="1" stop-color="#007DEC"/></linearGradient><linearGradient x1="92.4649" y1="130.931" x2="102.156" y2="143.93" gradientUnits="userSpaceOnUse" spreadMethod="pad" id="fill8"><stop offset="0" stop-color="#E20E1F"/><stop offset="1" stop-color="#F24657"/></linearGradient><linearGradient x1="120.201" y1="135.561" x2="100.544" y2="130.504" gradientUnits="userSpaceOnUse" spreadMethod="pad" id="fill9"><stop offset="0" stop-color="#EA7D92"/><stop offset="1" stop-color="#A91B36" stop-opacity="0.890196"/></linearGradient><clipPath id="clip10"><rect x="628" y="268" width="16" height="17"/></clipPath><clipPath id="clip11"><rect x="628" y="268" width="16" height="17"/></clipPath><clipPath id="clip12"><rect x="628" y="268" width="16" height="17"/></clipPath><clipPath id="clip13"><rect x="-4.37975" y="-0.31867" width="113.361" height="119.065"/></clipPath><image width="54" height="59" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAARCAMAAAA11AaTAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAEIUExURQAAAP///4D//zPMzDnGxlW/1U7E2Ee4xlHF0TW1tSm1vWLL2CyotFrL1Teyuz+0xCynty+pu1C9zDawvi+ru1vH1WLM2CSjsySltCintVLDz2fR3WjR3V/K1zKtvD20wjqywGDL1ySks3XZ5Semtky/zHPZ5CWktCemtSmntiqotyuouCypuC2quS6quTCrujKtvDOuvTSvvjawvzexwDixwDuzwj61xD+2xEC3xUK4xkS5x0a7yEe7yUi8ykq+y0u+y02/zU7Bzk/BzlLCz1TE0VXF0lbG0ljH1FrI1VvJ1l3K11/M2GLN2mPO2mXP22bQ3GjS3mnS3mzU4G/W4nPZ5HTZ5Xbb5qHmlkQAAAAndFJOUwABAgUJDA0SFhgfJyk2OD1AR2l6g4yRv9nk5Oju8PLy9/j7/f7+/vx2s+EAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACVSURBVChTNcnVGoJQEIXREbu7O7FbDOzuVt7/TYTDdt3Mv78hlSNRzbnQRJpkr92oFEOYenEodFv1Mh9kk1tMxYHQadZKvEXZkdV8MuqnvFpzOCNPw36znI2dyofcNqL4cbfOc2wS+Yiu58PWiCmz3y8nD1oReN7SSCb2euiQzPcdRamkjwmlkrIIkKwIKOD++XEZoh/pXhA98G3bzwAAAABJRU5ErkJggg==" preserveAspectRatio="none" id="img14"></image><clipPath id="clip15"><rect x="0" y="0" width="107" height="116.907"/></clipPath><linearGradient x1="122.418" y1="143.482" x2="111.163" y2="131.239" gradientUnits="userSpaceOnUse" spreadMethod="pad" id="fill16"><stop offset="0" stop-color="#204B78"/><stop offset="1" stop-color="#6199D4"/></linearGradient></defs><g clip-path="url(#clip0)" transform="translate(-618 -266)"><g clip-path="url(#clip1)"><g clip-path="url(#clip2)"><g clip-path="url(#clip3)"><g clip-path="url(#clip4)"><g clip-path="url(#clip5)"><path d="M113.319 135.713C113.319 135.713 116.611 141.998 112.065 147.272 106.397 153.848 98.8327 150.199 98.8327 150.199 98.8327 150.199 104.954 148.801 108.947 144.459 111.862 141.289 113.319 135.713 113.319 135.713Z" stroke="#161616" stroke-width="0.053232" fill="url(#fill6)" transform="matrix(1 0 0 1.01175 531.482 148.745)"/><path d="M107.198 144.648C107.198 144.648 97.6053 153.056 89.8972 147.196 85.6735 143.985 91.7984 136.93 91.7984 136.93 91.7984 136.93 88.5837 141.738 93.9277 144.497 97.8019 146.497 107.198 144.648 107.198 144.648Z" stroke="#444444" stroke-width="0.053232" fill="url(#fill7)" transform="matrix(1 0 0 1.01175 531.482 148.745)"/><path d="M96.9401 124.518C96.9401 124.518 95.2781 128.604 96.6712 135.057 97.7291 139.956 102.156 143.93 102.156 143.93 102.156 143.93 94.2052 143.765 92.4232 135.541 90.9391 128.692 96.9401 124.518 96.9401 124.518Z" stroke="#E30E1F" stroke-width="0.053232" stroke-opacity="0.984314" fill="url(#fill8)" transform="matrix(1 0 0 1.01175 531.482 148.745)"/><path d="M100.544 130.504C100.544 130.504 104.7 124.283 112.065 125.98 120.049 127.818 120.201 135.561 120.201 135.561 120.201 135.561 114.147 130.61 110.468 129.744 107.238 128.984 100.544 130.504 100.544 130.504Z" stroke="#C7314F" stroke-width="0.053232" stroke-opacity="0.952941" fill="url(#fill9)" transform="matrix(1 0 0 1.01175 531.482 148.745)"/><g clip-path="url(#clip10)"><g clip-path="url(#clip11)"><g clip-path="url(#clip12)"><g clip-path="url(#clip13)" transform="matrix(0.141142 0 0 0.142779 628.618 268.046)"><g clip-path="url(#clip15)" transform="matrix(1 0 0 1.00079 2.92156e-05 4.61083e-05)"><use width="100%" height="100%" xlink:href="#img14" transform="scale(1.98148 1.98148)"></use></g></g></g></g></g><path d="M111.163 131.239C111.163 131.239 122.555 134.865 122.374 143.258 122.2 151.395 112.158 148.5 112.158 148.5 112.158 148.5 117.647 148.85 117.826 143.37 117.993 138.255 111.163 131.239 111.163 131.239Z" stroke="#3D6EA2" stroke-width="0.053232" stroke-opacity="0.980392" fill="url(#fill16)" transform="matrix(1 0 0 1.01175 531.482 148.745)"/></g></g></g><path d="M30.1096-28.0873 30.1096 0.168524 22.4137 0.168524 22.4137-28.0873ZM18.3129-7.07801 21.0093-2.19081 21.0093-2.13464C19.0619-0.411947 16.6464 0.449397 13.7628 0.449397 9.19392 0.449397 5.95451-0.786445 4.04457-3.25813 2.28444-5.46767 1.40437-8.98794 1.40437-13.819L1.40437-28.0873 9.10029-28.0873 9.10029-13.819C9.10029-12.8078 9.11902-11.8341 9.15647-10.8979 9.23137-9.96164 9.43734-9.13774 9.77439-8.4262 10.1489-7.71465 10.7106-7.13418 11.4596-6.68478 12.2086-6.27284 13.2759-6.06686 14.6616-6.06686 15.2982-6.06686 15.9162-6.16049 16.5153-6.34773 17.1145-6.53498 17.6763-6.77841 18.2006-7.07801Z" fill="#BFBFBF" transform="matrix(1 0 0 1.0116 526.347 301.17)"/><path d="M22.4675-28.0873 30.1072-28.0873 30.1072 0 22.4675 0ZM48.4201-24.8292C49.3564-23.6683 50.0305-22.2077 50.4424-20.4476 50.8544-18.6874 51.0604-16.5153 51.0604-13.9313L51.0604 0 43.4206 0 43.4206-13.9313C43.4206-14.9799 43.3832-15.9723 43.3083-16.9086 43.2708-17.8823 43.0836-18.7249 42.7465-19.4364 42.4095-20.1854 41.8664-20.7659 41.1174-21.1778 40.3684-21.5898 39.3011-21.7958 37.9155-21.7958 36.6047-21.7958 35.3876-21.5149 34.2641-20.9531L34.2641-20.897 34.208-20.9531 31.4554-25.8403 31.5116-25.8965C33.459-27.6567 35.8932-28.5367 38.8143-28.5367 43.3083-28.5367 46.5102-27.3009 48.4201-24.8292Z" fill="#BFBFBF" transform="matrix(1 0 0 1.0116 526.347 301.17)"/><path d="M54.1499 0 54.1499-28.0873 61.6211-28.0873 61.6211 0ZM54.1499-39.3223 61.6211-39.3223 61.6211-32.7498 54.1499-32.7498Z" fill="#BFBFBF" transform="matrix(1 0 0 1.0116 526.347 301.17)"/><path d="M85.4953-10.7294 91.5622-6.74096 91.506-6.68478C90.1952-4.4378 88.4164-2.67766 86.1694-1.40437 83.9599-0.131074 81.5631 0.505572 78.979 0.505572 76.9567 0.505572 75.0655 0.131074 73.3054-0.617921 71.5453-1.40437 70.0098-2.45296 68.6991-3.7637 67.3883-5.07444 66.3397-6.60988 65.5533-8.37002 64.8043-10.1302 64.4298-12.0026 64.4298-13.9875 64.4298-15.9723 64.8043-17.8448 65.5533-19.6049 66.3397-21.3651 67.3883-22.9005 68.6991-24.2113 70.0098-25.522 71.5453-26.5519 73.3054-27.3009 75.0655-28.0873 76.9567-28.4805 78.979-28.4805 81.5631-28.4805 83.9599-27.8439 86.1694-26.5706 88.4164-25.2973 90.1952-23.5372 91.506-21.2902L91.5622-21.234 85.4391-17.2456 85.3829-17.3018C84.7838-18.6874 83.9037-19.8109 82.7427-20.6723 81.6192-21.5336 80.3647-21.9643 78.979-21.9643 77.9679-21.9643 77.0129-21.7396 76.1141-21.2902 75.2528-20.8782 74.5038-20.2978 73.8671-19.5488 73.2305-18.8372 72.7249-17.9946 72.3504-17.0209 71.9759-16.0847 71.7887-15.0735 71.7887-13.9875 71.7887-12.9014 71.9759-11.8903 72.3504-10.9541 72.7249-10.0178 73.2305-9.19392 73.8671-8.48237 74.5038-7.80828 75.2528-7.26525 76.1141-6.85331 77.0129-6.47881 77.9679-6.29156 78.979-6.29156 80.3647-6.29156 81.6192-6.66606 82.7427-7.41505 83.9037-8.2015 84.7838-9.28754 85.3829-10.6732L85.4391-10.7855Z" fill="#BFBFBF" transform="matrix(1 0 0 1.0116 526.347 301.17)"/><path d="M160.084-39.3223 160.084 0 152.613 0 152.669-14.0998C152.669-15.1484 152.444-16.1408 151.995-17.0771 151.583-18.0133 151.021-18.8185 150.309-19.4926 149.635-20.2041 148.811-20.7472 147.838-21.1217 146.901-21.5336 145.89-21.7396 144.804-21.7396 143.718-21.7396 142.707-21.5336 141.771-21.1217 140.835-20.7472 140.011-20.2041 139.299-19.4926 138.625-18.7811 138.082-17.9572 137.67-17.0209 137.258-16.0847 137.052-15.0735 137.052-13.9875 137.052-12.9014 137.258-11.8903 137.67-10.9541 138.082-10.0178 138.625-9.19392 139.299-8.48237 140.011-7.80828 140.835-7.26525 141.771-6.85331 142.707-6.44136 143.718-6.23539 144.804-6.23539 145.329-6.23539 145.853-6.27284 146.377-6.34773 146.901-6.42263 147.388-6.57243 147.838-6.79713L147.894-6.79713 147.95-6.79713 150.703-1.74141 150.646-1.68524C148.811-0.262148 146.564 0.449397 143.905 0.449397 141.883 0.449397 139.992 0.0748995 138.232-0.674096 136.472-1.42309 134.936-2.45296 133.626-3.7637 132.315-5.07444 131.266-6.60988 130.48-8.37002 129.731-10.1302 129.356-12.0026 129.356-13.9875 129.356-15.9723 129.731-17.8448 130.48-19.6049 131.266-21.3651 132.315-22.9005 133.626-24.2113 134.936-25.522 136.472-26.5519 138.232-27.3009 139.992-28.0499 141.883-28.4244 143.905-28.4244 147.725-28.4244 150.646-27.0013 152.669-24.1551L152.669-39.3223Z" fill="#BFBFBF" transform="matrix(1 0 0 1.0116 526.347 301.17)"/></g></g></g></svg>
\ No newline at end of file
diff --git a/installer/version.txt b/installer/version.txt
new file mode 100644
index 0000000000000000000000000000000000000000..56fea8a08d2faa60fec80b40241566d3c39744f7
--- /dev/null
+++ b/installer/version.txt
@@ -0,0 +1 @@
+3.0.0
\ No newline at end of file
diff --git a/libraries b/libraries
new file mode 160000
index 0000000000000000000000000000000000000000..fe74dcde23ebf9749dee533e2e4d13d369f6d51a
--- /dev/null
+++ b/libraries
@@ -0,0 +1 @@
+Subproject commit fe74dcde23ebf9749dee533e2e4d13d369f6d51a
diff --git a/rce_workflow b/rce_workflow
new file mode 160000
index 0000000000000000000000000000000000000000..6e53d4fdac61f832495bdf5c76da36a87c32cf43
--- /dev/null
+++ b/rce_workflow
@@ -0,0 +1 @@
+Subproject commit 6e53d4fdac61f832495bdf5c76da36a87c32cf43
diff --git a/scripts/lint.py b/scripts/lint.py
new file mode 100644
index 0000000000000000000000000000000000000000..b5ebd2cc25102e88d0effd62143752c8cd197542
--- /dev/null
+++ b/scripts/lint.py
@@ -0,0 +1,320 @@
+#! python
+#
+# UNICADO - UNIversity Conceptual Aircraft Design and Optimization
+#
+# Copyright (C) 2025 UNICADO consortium
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+# Description:
+# This file is part of UNICADO.
+#
+"""Lint the given src directory using UNICADO standards."""
+## @file lint.py
+#
+# @brief Lint the given src directory using UNICADO standards.
+#
+# @details Invokes cpplint, cppcheck, and (optionally) clang-tidy
+# to lint the given source directory.
+#
+# @author Sebastian Oberschwendtner, sebastian.oberschwendtner@gmail.com
+
+# === Imports ===
+import argparse
+import errno
+import json
+import os
+import sys
+from pathlib import Path
+from shutil import which
+
+# === Meta data ===
+__version__ = "0.1.0"
+
+# === Default Configuration ===
+DEFAULT_SETTINGS = {
+    "std": "c++20",
+    "cpplint": {
+        "enable": ["readability", "naming", "performance"],
+        "disable": [
+            "whitespace",
+            "build/include_order",
+            "build/include_subdir",
+            "build/header_guard",
+            "runtime/indentation_namespace",
+        ],
+        "options": ["--linelength=180"],
+    },
+    "cppcheck": {
+        "enable": ["warning", "performance", "portability", "information"],
+        "disable": ["missingInclude"],
+        "options": ["--inline-suppr"],
+    },
+    "clang-tidy": {
+        "enable": [
+            "bugprone-*",
+            "clang-analyzer-*",
+            "cppcoreguidelines-*",
+            "google-*",
+            "misc-*",
+            "modernize-*",
+            "performance-*",
+            "portability-*",
+            "readability-*",
+        ],
+        "disable": ["misc-include-cleaner"],
+        "options": [],
+    },
+}
+
+
+# === Classes ===
+class Context:
+    """Context which defines how linter are invoked."""
+
+    def __init__(self):
+        """Initialize the context."""
+        self.src = Path("")
+        self.verbose = False
+        self.preview = False
+        self.quiet = False
+
+    def invoke(self, command: str) -> int:
+        """Invoke the command in the current context.
+
+        Args:
+            command (str): The command to be called.
+
+        Returns:
+            int: The return value of the command.
+        """
+        # Split the command into tokens
+        tokens = command.split(" ")
+
+        # Enable quiet output
+        if self.quiet:
+            tokens.insert(1, "--quiet")
+
+        # Check if the command can be executed
+        if not self.check_command(tokens[0]):
+            print(f"Command '{tokens[0]}' not available!")
+            return errno.ENOSYS
+
+        # Join the tokens back together
+        command = " ".join(tokens)
+
+        # Output the command if verbose
+        if (self.verbose and not self.quiet) or self.preview:
+            print(60 * "*" + "\nRunning:", command)
+
+        # Run the command
+        return 0 if self.preview else os.system(command)
+
+    def check_command(self, command: str) -> bool:
+        """Check if the command can be executed in the current context.
+
+        Args:
+            command (str): The command to be checked.
+
+        Returns:
+            bool: True if the command can be executed, False otherwise.
+        """
+        return which(command) is not None
+
+
+# === Linter Calls ===
+def lint_cpplint(settings: dict, context: Context) -> int:
+    """Lint the given source directory using cpplint
+
+    Args:
+        settings (dict): The settings dictionary of which checks to enable/disable.
+        context (Context): How the linter should be invoked.
+
+    Returns:
+        int: The return code of the command.
+    """
+    # Get the list of enabled and disabled checks
+    filter_list = ",".join("+" + item for item in settings["cpplint"]["enable"])
+    filter_list += "," + ",".join("-" + item for item in settings["cpplint"]["disable"])
+
+    # Assembly the command
+    cmd = (
+        "cpplint "
+        f"--filter={filter_list} "
+        "--recursive "
+        f"{' '.join(settings['cpplint']['options'])} "
+        f"{context.src.resolve()}"
+    )
+
+    # Invoke the linter
+    return context.invoke(cmd)
+
+
+def lint_cppcheck(settings: dict, context: Context) -> int:
+    """Lint the given source directory using cppcheck.
+
+    Args:
+        settings (dict): The settings dictionary of which checks to enable/disable.
+        context (Context): How the linter should be invoked.
+
+    Returns:
+        int: The return code of the command.
+    """
+    # Get the list of enabled and disabled checks
+    enable_list = ",".join(settings["cppcheck"]["enable"])
+    disable_list = ",".join(settings["cppcheck"]["disable"])
+
+    # Assembly the command
+    cmd = (
+        "cppcheck "
+        f"--disable={disable_list} "
+        f"--enable={enable_list} "
+        f"--std={settings['std']} "
+        "--language=c++ "
+        "--check-level=exhaustive "
+        f"{' '.join(settings['cppcheck']['options'])} "
+        f"{context.src.resolve()}"
+    )
+
+    # Invoke the linter
+    return context.invoke(cmd)
+
+
+def lint_clang_tidy(settings: dict, context: Context) -> int:
+    """Lint the given source directory using clang-tidy.
+
+    Args:
+        settings (dict): The settings dictionary of which checks to enable/disable.
+        context (Context): How the linter should be invoked.
+
+    Returns:
+        int: The return code of the command.
+    """
+    # Get the list of enabled and disabled checks
+    filter_list = ",".join(settings["clang-tidy"]["enable"])
+    filter_list += "," + ",".join(
+        "-" + item for item in settings["clang-tidy"]["disable"]
+    )
+
+    # Generate a list with all source files
+    # => Use os.walk to be compatible with python 3.11
+    sources = ""
+    for dirpath, _, filenames in os.walk(context.src):
+        for filename in filenames:
+            if filename.endswith(".cpp"):
+                sources += str(Path(dirpath).resolve() / filename) + " "
+
+    # Assembly the command
+    cmd = (
+        "clang-tidy "
+        f"--checks={filter_list} "
+        "--header-filter=.* "
+        f"-extra-arg=-std={settings['std']} "
+        f"{' '.join(settings['clang-tidy']['options'])} "
+        f"{sources}"
+    )
+
+    # Invoke the linter
+    return context.invoke(cmd)
+
+
+def read_configuration_file(file: Path) -> dict:
+    """Read the configuration file and return the settings dictionary.
+
+    Args:
+        file (Path): The path to the configuration file.
+
+    Returns:
+        dict: The settings dictionary.
+    """
+    try:
+        with open(file, "r", encoding="utf-8") as config:
+            return json.load(config)
+    except OSError as e:
+        print(f"Error reading configuration file: {e}\nUsing default settings!")
+        return DEFAULT_SETTINGS
+
+
+# === Main ===
+if __name__ == "__main__":
+    # Parse the command line arguments
+    parser = argparse.ArgumentParser(
+        description="Lint the given src directory using UNICADO standards. "
+        "All files within the directory will be linted recursively."
+    )
+    parser.add_argument("src", help="source directory to lint", default=".", nargs="?")
+    parser.add_argument(
+        "--config", help="use custom configuration file", type=Path, default=None
+    )
+    parser.add_argument(
+        "--dry-run", action="store_true", help="preview how the linters will be called"
+    )
+    parser.add_argument(
+        "--dump-config", action="store_true", help="dump the default configuration"
+    )
+    parser.add_argument(
+        "-e",
+        "--extra",
+        action="store_true",
+        help="enable extra linters (e.g. clang-tidy)",
+    )
+    parser.add_argument(
+        "-q",
+        "--quiet",
+        action="store_true",
+        help="only output errors and no progress information",
+    )
+    parser.add_argument(
+        "-v", "--verbose", action="store_true", help="enable verbose output"
+    )
+    parser.add_argument(
+        "--version", action="version", version=f"%(prog)s - Version: {__version__}"
+    )
+    args = parser.parse_args()
+
+    # Read the configuration file if given
+    settings_ = (
+        read_configuration_file(args.config) if args.config else DEFAULT_SETTINGS
+    )
+
+    # Check if the source directory exists
+    if not os.path.exists(args.src):
+        print(f"The source directory '{args.src}' does not exist")
+        sys.exit(errno.ENOENT)
+
+    # Dump the default configuration if requested
+    if args.dump_config:
+        print(json.dumps(DEFAULT_SETTINGS, indent=4))
+        sys.exit(0)
+
+    # Lint the source directory
+    print(f"Linting source directory '{args.src}'")
+
+    # Setup the context
+    context_ = Context()
+    context_.src = Path(args.src)
+    context_.preview = args.dry_run
+    context_.quiet = args.quiet
+    context_.verbose = args.verbose
+
+    # Call the default linters
+    ret_val = lint_cpplint(settings_, context_)
+    ret_val += lint_cppcheck(settings_, context_)
+
+    # Call the extra linters
+    if args.extra:
+        ret_val += lint_clang_tidy(settings_, context_)
+
+    # Return the return value of the linters
+    sys.exit(ret_val)
diff --git a/utilities b/utilities
new file mode 160000
index 0000000000000000000000000000000000000000..f2a3b7406c7f123bafa6c7a36b13a9a17f261a51
--- /dev/null
+++ b/utilities
@@ -0,0 +1 @@
+Subproject commit f2a3b7406c7f123bafa6c7a36b13a9a17f261a51