diff --git a/.azure/azure-build-deploy-docs-pipeline.yml b/.azure/azure-build-deploy-docs-pipeline.yml index 8ebfe4d6..255f5821 100644 --- a/.azure/azure-build-deploy-docs-pipeline.yml +++ b/.azure/azure-build-deploy-docs-pipeline.yml @@ -30,7 +30,7 @@ jobs: displayName: 'Install PrimAITE for docs autosummary' - script: | - apt-get install pandoc + sudo apt-get install pandoc displayName: 'Install Pandoc' - script: | diff --git a/.github/workflows/build-sphinx.yml b/.github/workflows/build-sphinx.yml index da20fbd3..4bfa4f4e 100644 --- a/.github/workflows/build-sphinx.yml +++ b/.github/workflows/build-sphinx.yml @@ -1,8 +1,8 @@ name: build-sphinx-to-github-pages env: - GITHUB_ACTOR: Autonomous-Resilient-Cyber-Defence - GITHUB_REPOSITORY: Autonomous-Resilient-Cyber-Defence/PrimAITE + GITHUB_ACTOR: {todo:fill in URL} + GITHUB_REPOSITORY: {todo:fill in URL}/PrimAITE GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN}} on: diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 1b85f4be..1e803d92 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -5,13 +5,11 @@ on: branches: - main - dev - - dev-gui - 'release/**' pull_request: branches: - main - dev - - dev-gui - 'release/**' jobs: build: @@ -19,7 +17,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.8", "3.9", "3.10"] + python-version: ["3.9", "3.10", "3.11"] steps: - uses: actions/checkout@v3 @@ -54,13 +52,6 @@ jobs: run: | primaite setup - - name: Lint with flake8 - run: | - # stop the build if there are Python syntax errors or undefined names - flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - # exit-zero treats all errors as warnings. - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=120 --statistics - - name: Run tests run: | pytest tests/ diff --git a/.gitignore b/.gitignore index 2ba8d4a7..e48dc5dc 100644 --- a/.gitignore +++ b/.gitignore @@ -148,7 +148,7 @@ cython_debug/ # IDE .idea/ -docs/source/primaite-dependencies.rst + .vscode/ # outputs diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 91230171..3088dc1d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,9 +1,17 @@ repos: + - repo: local + hooks: + - id: ensure-copyright-clause + name: ensure copyright clause + entry: python copyright_clause_pre_commit_hook.py + language: python - repo: http://github.com/pre-commit/pre-commit-hooks rev: v4.4.0 hooks: - id: check-yaml - exclude: scenario_with_placeholders/ + exclude: | + | scenario_with_placeholders/ + | mini_scenario_with_simulation_variation/ - id: end-of-file-fixer - id: trailing-whitespace - id: check-added-large-files diff --git a/CHANGELOG.md b/CHANGELOG.md index 227cf729..17bf3557 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added support for SQL INSERT command. - Added ability to log each agent's action choices in each step to a JSON file. - Removal of Link bandwidth hardcoding. This can now be configured via the network configuraiton yaml. Will default to 100 if not present. +- Added NMAP application to all host and layer-3 network nodes. ### Bug Fixes diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4d70ebb3..bf5e75e4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,20 +4,20 @@ ### **Did you find a bug?** -* **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/Autonomous-Resilient-Cyber-Defence/PrimAITE/issues). -* If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/Autonomous-Resilient-Cyber-Defence/PrimAITE/issues/new?assignees=&labels=bug&projects=&template=bug_report.md&title=%5BBUG%5D+-+%3Cbug+title+goes+here%3E). Be sure to follow our bug report template with the headers **Describe the bug**, **To Reproduce**, **Expected behaviour**, **Screenshots/Outputs**, **Environment**, and **Additional context** +* **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/{todo:fill in URL}/PrimAITE/issues). +* If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/{todo:fill in URL}/PrimAITE/issues/new?assignees=&labels=bug&projects=&template=bug_report.md&title=%5BBUG%5D+-+%3Cbug+title+goes+here%3E). Be sure to follow our bug report template with the headers **Describe the bug**, **To Reproduce**, **Expected behaviour**, **Screenshots/Outputs**, **Environment**, and **Additional context** ### **Do you have a solution to fix the bug?** -* [Fork the repository](https://github.com/Autonomous-Resilient-Cyber-Defence/PrimAITE/fork). +* [Fork the repository](https://github.com/{todo:fill in URL}/PrimAITE/fork). * Install the pre-commit hook with `pre-commit install`. * Implement the bug fix. * Update documentation where applicable. * Update the **UNRELEASED** section of the [CHANGELOG.md](CHANGELOG.md) file * Write a suitable test/tests. -* Commit the bug fix to the dev branch on your fork. If the bug has an open issue under [Issues](https://github.com/Autonomous-Resilient-Cyber-Defence/PrimAITE/issues), reference the issue in the commit message (e.g. #1 references issue 1). -* Submit a pull request from your dev branch to the Autonomous-Resilient-Cyber-Defence/PrimAITE dev branch. Again, if the bug has an open issue under [Issues](https://github.com/Autonomous-Resilient-Cyber-Defence/PrimAITE/issues), reference the issue in the pull request description. +* Commit the bug fix to the dev branch on your fork. If the bug has an open issue under [Issues](https://github.com/{todo:fill in URL}/PrimAITE/issues), reference the issue in the commit message (e.g. #1 references issue 1). +* Submit a pull request from your dev branch to the {todo:fill in URL}/PrimAITE dev branch. Again, if the bug has an open issue under [Issues](https://github.com/{todo:fill in URL}/PrimAITE/issues), reference the issue in the pull request description. ### **Did you fix whitespace, format code, or make a purely cosmetic patch?** @@ -25,7 +25,7 @@ Changes that are cosmetic in nature and do not add anything substantial to the s ### **Do you intend to add a new feature or change an existing one?** -* Submit a [feature request issue](https://github.com/Autonomous-Resilient-Cyber-Defence/PrimAITE/issues/new?assignees=&labels=feature_request&projects=&template=feature_request.md&title=%5BREQUEST%5D+-+%3Crequest+title+goes+here%3E). +* Submit a [feature request issue](https://github.com/{todo:fill in URL}/PrimAITE/issues/new?assignees=&labels=feature_request&projects=&template=feature_request.md&title=%5BREQUEST%5D+-+%3Crequest+title+goes+here%3E). * Know how to implement the new feature or change? Follow the same steps in the bug fix section above to fork, build, document, test, commit, and submit a pull request. ### **Do you have questions about the source code?** diff --git a/LICENSE b/LICENSE index 93d6f98b..9575f430 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,27 @@ -MIT License +MIT License License -Copyright (c) 2023 - 2025 Defence Science and Technology Laboratory UK (https://dstl.gov.uk) +MIT License Conditions -Permission is hereby granted, free of charge, to any person obtaining a copy +These MIT License conditions confirm the provision of the following artefacts as MIT License by Defence Science and Technology of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights +request to the QQ or FNC mailbox): + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +- Use Case Release Packs furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +Suppliers are required to read and confirm acceptance of the {todo:fill in URL} Foundry SyOPs (https://github.com/{todo:fill in URL}/foundry-syops) before being admitted access to material hosted on the {todo:fill in URL} Foundry GitHub site. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + +The material is supplied in confidence to QQ / FNC and their subcontractors under SERAPIS, and is issued to inform only those OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +of DSTL. The material must be stored and protected appropriately. All material must be destroyed at the end of the task. + diff --git a/README.md b/README.md index 68a8488b..137852f5 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Currently, the PrimAITE wheel can only be installed from GitHub. This may change #### Windows (PowerShell) **Prerequisites:** -* Manual install of Python >= 3.8 < 3.12 +* Manual install of Python >= 3.9 < 3.12 **Install:** @@ -43,7 +43,7 @@ cd ~\primaite python3 -m venv .venv attrib +h .venv /s /d # Hides the .venv directory .\.venv\Scripts\activate -pip install primaite-3.0.0-py3-none-any.whl[rl] +pip install primaite-{VERSION}-py3-none-any.whl[rl] primaite setup ``` @@ -66,7 +66,7 @@ mkdir ~/primaite cd ~/primaite python3 -m venv .venv source .venv/bin/activate -pip install primaite-3.0.0-py3-none-any.whl[rl] +pip install primaite-{VERSION}-py3-none-any.whl[rl] primaite setup ``` @@ -77,7 +77,7 @@ To make your own changes to PrimAITE, perform the install from source (developer #### 1. Clone the PrimAITE repository ``` unix -git clone git@github.com:Autonomous-Resilient-Cyber-Defence/PrimAITE.git +git clone git@github.com:{todo:fill in URL}/PrimAITE.git ``` #### 2. CD into the repo directory diff --git a/benchmark/results/v3/v3.0.0/session_metadata/1.json b/benchmark/results/v3/v3.0.0/session_metadata/1.json index 5301d60a..e3d656d4 100644 --- a/benchmark/results/v3/v3.0.0/session_metadata/1.json +++ b/benchmark/results/v3/v3.0.0/session_metadata/1.json @@ -1006,4 +1006,4 @@ "999": 112.49999999999994, "1000": 115.2500000000002 } -} \ No newline at end of file +} diff --git a/benchmark/results/v3/v3.0.0/session_metadata/2.json b/benchmark/results/v3/v3.0.0/session_metadata/2.json index e10a9ee5..01dcb983 100644 --- a/benchmark/results/v3/v3.0.0/session_metadata/2.json +++ b/benchmark/results/v3/v3.0.0/session_metadata/2.json @@ -1006,4 +1006,4 @@ "999": 103.49999999999994, "1000": 117.9500000000001 } -} \ No newline at end of file +} diff --git a/benchmark/results/v3/v3.0.0/session_metadata/3.json b/benchmark/results/v3/v3.0.0/session_metadata/3.json index 78ddf66a..55bdb538 100644 --- a/benchmark/results/v3/v3.0.0/session_metadata/3.json +++ b/benchmark/results/v3/v3.0.0/session_metadata/3.json @@ -1006,4 +1006,4 @@ "999": 112.00000000000017, "1000": 106.10000000000002 } -} \ No newline at end of file +} diff --git a/benchmark/results/v3/v3.0.0/session_metadata/4.json b/benchmark/results/v3/v3.0.0/session_metadata/4.json index c714cacb..a4a22f74 100644 --- a/benchmark/results/v3/v3.0.0/session_metadata/4.json +++ b/benchmark/results/v3/v3.0.0/session_metadata/4.json @@ -1006,4 +1006,4 @@ "999": 100.75000000000009, "1000": 110.70000000000007 } -} \ No newline at end of file +} diff --git a/benchmark/results/v3/v3.0.0/session_metadata/5.json b/benchmark/results/v3/v3.0.0/session_metadata/5.json index e7cd6d72..23239cec 100644 --- a/benchmark/results/v3/v3.0.0/session_metadata/5.json +++ b/benchmark/results/v3/v3.0.0/session_metadata/5.json @@ -1006,4 +1006,4 @@ "999": 110.6500000000001, "1000": 113.10000000000015 } -} \ No newline at end of file +} diff --git a/benchmark/results/v3/v3.0.0/v3.0.0_benchmark_metadata.json b/benchmark/results/v3/v3.0.0/v3.0.0_benchmark_metadata.json index ab7b1671..6b6595fc 100644 --- a/benchmark/results/v3/v3.0.0/v3.0.0_benchmark_metadata.json +++ b/benchmark/results/v3/v3.0.0/v3.0.0_benchmark_metadata.json @@ -7433,4 +7433,4 @@ } } } -} \ No newline at end of file +} diff --git a/benchmark/results/v3/v3.1.0/PrimAITE Learning Benchmark of Minor and Bugfix Releases for Major Version 3.png b/benchmark/results/v3/v3.1.0/PrimAITE Learning Benchmark of Minor and Bugfix Releases for Major Version 3.png new file mode 100644 index 00000000..40270a97 Binary files /dev/null and b/benchmark/results/v3/v3.1.0/PrimAITE Learning Benchmark of Minor and Bugfix Releases for Major Version 3.png differ diff --git a/benchmark/results/v3/v3.1.0/PrimAITE Performance of Minor and Bugfix Releases for Major Version 3.png b/benchmark/results/v3/v3.1.0/PrimAITE Performance of Minor and Bugfix Releases for Major Version 3.png new file mode 100644 index 00000000..29036db5 Binary files /dev/null and b/benchmark/results/v3/v3.1.0/PrimAITE Performance of Minor and Bugfix Releases for Major Version 3.png differ diff --git a/benchmark/results/v3/v3.1.0/PrimAITE v3.1.0 Benchmark Report.md b/benchmark/results/v3/v3.1.0/PrimAITE v3.1.0 Benchmark Report.md new file mode 100644 index 00000000..e767ed76 --- /dev/null +++ b/benchmark/results/v3/v3.1.0/PrimAITE v3.1.0 Benchmark Report.md @@ -0,0 +1,38 @@ +# PrimAITE v3.1.0 Learning Benchmark +## PrimAITE Dev Team +### 2024-07-20 + +--- +## 1 Introduction +PrimAITE v3.1.0 was benchmarked automatically upon release. Learning rate metrics were captured to be referenced during system-level testing and user acceptance testing (UAT). +The benchmarking process consists of running 5 training session using the same config file. Each session trains an agent for 1000 episodes, with each episode consisting of 128 steps. +The total reward per episode from each session is captured. This is then used to calculate an caverage total reward per episode from the 5 individual sessions for smoothing. Finally, a 25-widow rolling average of the average total reward per session is calculated for further smoothing. +## 2 System Information +### 2.1 Python +**Version:** 3.10.14 (main, Apr 6 2024, 18:45:05) [GCC 9.4.0] +### 2.2 System +- **OS:** Linux +- **OS Version:** #76~20.04.1-Ubuntu SMP Thu Jun 13 18:00:23 UTC 2024 +- **Machine:** x86_64 +- **Processor:** x86_64 +### 2.3 CPU +- **Physical Cores:** 2 +- **Total Cores:** 4 +- **Max Frequency:** 0.00Mhz +### 2.4 Memory +- **Total:** 15.62GB +- **Swap Total:** 0.00B +## 3 Stats +- **Total Sessions:** 5 +- **Total Episodes:** 5005 +- **Total Steps:** 640000 +- **Av Session Duration (s):** 1632.8888 +- **Av Step Duration (s):** 0.0510 +- **Av Duration per 100 Steps per 10 Nodes (s):** 5.1028 +## 4 Graphs +### 4.1 v3.1.0 Learning Benchmark Plot +![PrimAITE 3.1.0 Learning Benchmark Plot](PrimAITE v3.1.0 Learning Benchmark.png) +### 4.2 Learning Benchmark of Minor and Bugfix Releases for Major Version 3 +![Learning Benchmark of Minor and Bugfix Releases for Major Version 3](PrimAITE Learning Benchmark of Minor and Bugfix Releases for Major Version 3.png) +### 4.3 Performance of Minor and Bugfix Releases for Major Version 3 +![Performance of Minor and Bugfix Releases for Major Version 3](PrimAITE Performance of Minor and Bugfix Releases for Major Version 3.png) diff --git a/benchmark/results/v3/v3.1.0/PrimAITE v3.1.0 Learning Benchmark.png b/benchmark/results/v3/v3.1.0/PrimAITE v3.1.0 Learning Benchmark.png new file mode 100644 index 00000000..acc80804 Binary files /dev/null and b/benchmark/results/v3/v3.1.0/PrimAITE v3.1.0 Learning Benchmark.png differ diff --git a/benchmark/results/v3/v3.1.0/session_metadata/1.json b/benchmark/results/v3/v3.1.0/session_metadata/1.json new file mode 100644 index 00000000..0989c376 --- /dev/null +++ b/benchmark/results/v3/v3.1.0/session_metadata/1.json @@ -0,0 +1,1009 @@ +{ + "total_episodes": 1001, + "total_time_steps": 128000, + "total_s": 1365.522934, + "s_per_step": 0.042672591687500004, + "s_per_100_steps_10_nodes": 4.26725916875, + "total_reward_per_episode": { + "1": -12.399999999999993, + "2": -20.699999999999964, + "3": -7.899999999999991, + "4": -19.549999999999965, + "5": -12.999999999999982, + "6": -22.649999999999952, + "7": -31.350000000000023, + "8": -35.75000000000003, + "9": -67.30000000000007, + "10": -44.900000000000055, + "11": -18.199999999999978, + "12": -21.199999999999957, + "13": -15.599999999999977, + "14": -19.749999999999964, + "15": -18.149999999999988, + "16": -28.000000000000014, + "17": -83.05000000000001, + "18": -39.05000000000012, + "19": -46.800000000000146, + "20": -21.199999999999957, + "21": -23.64999999999999, + "22": -15.999999999999968, + "23": -65.90000000000008, + "24": -35.700000000000024, + "25": -65.04999999999995, + "26": -20.349999999999962, + "27": -18.899999999999963, + "28": -78.39999999999998, + "29": -23.799999999999947, + "30": -96.1, + "31": -60.1, + "32": -31.350000000000023, + "33": -87.05000000000001, + "34": -33.35000000000002, + "35": -15.399999999999983, + "36": -58.40000000000001, + "37": -22.949999999999953, + "38": -12.249999999999986, + "39": -7.000000000000012, + "40": -55.90000000000002, + "41": 3.1499999999999906, + "42": -18.499999999999968, + "43": -84.3, + "44": -10.99999999999999, + "45": -9.54999999999999, + "46": -12.199999999999992, + "47": -16.74999999999997, + "48": -19.499999999999964, + "49": -16.84999999999997, + "50": -77.3, + "51": -19.14999999999997, + "52": -95.29999999999997, + "53": -102.55, + "54": -6.549999999999996, + "55": -18.049999999999965, + "56": -11.849999999999984, + "57": -17.149999999999974, + "58": -20.74999999999996, + "59": -16.64999999999997, + "60": -16.049999999999958, + "61": -64.80000000000005, + "62": -19.299999999999958, + "63": -16.799999999999976, + "64": -70.55000000000004, + "65": -17.799999999999972, + "66": -28.050000000000022, + "67": -12.949999999999989, + "68": -19.699999999999964, + "69": -17.89999999999997, + "70": -11.599999999999989, + "71": -86.5500000000001, + "72": -18.34999999999997, + "73": -20.84999999999996, + "74": -19.549999999999958, + "75": -22.149999999999956, + "76": -2.899999999999988, + "77": -19.949999999999964, + "78": -22.74999999999995, + "79": -23.249999999999968, + "80": -50.50000000000011, + "81": -59.499999999999964, + "82": -16.299999999999976, + "83": -7.649999999999995, + "84": -19.999999999999968, + "85": -22.049999999999955, + "86": 1.0000000000000304, + "87": -18.19999999999997, + "88": -16.44999999999998, + "89": -16.099999999999973, + "90": -14.299999999999983, + "91": -4.149999999999981, + "92": -22.399999999999952, + "93": -13.44999999999999, + "94": -8.649999999999999, + "95": -16.449999999999978, + "96": -14.599999999999984, + "97": -6.500000000000002, + "98": -16.649999999999974, + "99": -22.99999999999995, + "100": -20.74999999999996, + "101": -22.649999999999952, + "102": -11.699999999999989, + "103": -15.749999999999972, + "104": -40.099999999999966, + "105": -81.95000000000002, + "106": -19.249999999999947, + "107": -8.699999999999989, + "108": -6.399999999999987, + "109": -72.85000000000001, + "110": 5.900000000000017, + "111": -18.599999999999966, + "112": -15.19999999999998, + "113": -19.199999999999964, + "114": -7.949999999999991, + "115": -18.699999999999967, + "116": -16.899999999999974, + "117": -6.499999999999993, + "118": -61.44999999999998, + "119": -63.95, + "120": -13.249999999999982, + "121": -64.65000000000002, + "122": -10.949999999999996, + "123": -9.149999999999997, + "124": -15.249999999999972, + "125": -22.199999999999953, + "126": 4.699999999999991, + "127": -15.349999999999977, + "128": 13.55000000000005, + "129": -14.349999999999985, + "130": -19.249999999999964, + "131": -10.299999999999995, + "132": -19.04999999999997, + "133": 7.149999999999976, + "134": -7.7999999999999865, + "135": -3.7999999999999776, + "136": -12.799999999999986, + "137": -0.4999999999999678, + "138": -8.250000000000018, + "139": -18.249999999999968, + "140": -14.649999999999983, + "141": -13.949999999999985, + "142": 9.25000000000005, + "143": -7.849999999999999, + "144": -87.00000000000001, + "145": -28.99999999999997, + "146": 2.4000000000000288, + "147": -74.05, + "148": -10.199999999999992, + "149": -10.4, + "150": -12.799999999999986, + "151": -15.849999999999978, + "152": 3.419486915845482e-14, + "153": -5.649999999999984, + "154": -10.999999999999993, + "155": -59.55, + "156": 15.600000000000001, + "157": -2.6499999999999977, + "158": -79.10000000000001, + "159": -90.7, + "160": -4.049999999999983, + "161": -12.949999999999989, + "162": 4.100000000000027, + "163": -5.849999999999999, + "164": -84.40000000000012, + "165": -21.599999999999955, + "166": -10.049999999999985, + "167": -11.649999999999993, + "168": 9.35000000000003, + "169": -13.049999999999986, + "170": -68.10000000000001, + "171": -75.90000000000008, + "172": -45.750000000000085, + "173": -68.35000000000002, + "174": 6.100000000000035, + "175": -9.650000000000002, + "176": -13.499999999999984, + "177": -7.049999999999989, + "178": -10.249999999999991, + "179": -21.249999999999957, + "180": -21.849999999999987, + "181": -47.150000000000055, + "182": -0.6999999999999749, + "183": -14.250000000000018, + "184": -23.700000000000017, + "185": 5.250000000000005, + "186": -3.249999999999984, + "187": -63.14999999999999, + "188": -12.349999999999996, + "189": -93.65, + "190": -6.199999999999985, + "191": 6.500000000000043, + "192": -10.29999999999999, + "193": 2.100000000000028, + "194": -86.95, + "195": -37.900000000000034, + "196": -6.2499999999999885, + "197": 7.350000000000065, + "198": -10.550000000000011, + "199": -20.39999999999996, + "200": -13.24999999999998, + "201": 14.24999999999979, + "202": -19.899999999999963, + "203": -0.6499999999999813, + "204": -9.049999999999997, + "205": -4.549999999999979, + "206": 20.949999999999967, + "207": -5.949999999999997, + "208": 4.650000000000053, + "209": -8.399999999999999, + "210": -86.19999999999996, + "211": -84.75000000000001, + "212": 6.550000000000047, + "213": -4.64999999999998, + "214": -85.5, + "215": -82.0, + "216": -16.099999999999977, + "217": 11.40000000000002, + "218": -43.05000000000001, + "219": -86.60000000000002, + "220": -36.45000000000005, + "221": -74.3, + "222": -75.05000000000001, + "223": -2.5999999999999712, + "224": -5.649999999999983, + "225": -2.1999999999999726, + "226": -9.299999999999999, + "227": -82.40000000000003, + "228": -13.899999999999986, + "229": -14.849999999999971, + "230": -17.399999999999995, + "231": 19.24999999999998, + "232": -19.449999999999964, + "233": -17.899999999999967, + "234": -78.0, + "235": -84.49999999999996, + "236": -50.5, + "237": -13.899999999999979, + "238": -99.1, + "239": -1.300000000000021, + "240": -6.949999999999983, + "241": -43.550000000000004, + "242": -17.249999999999975, + "243": -18.29999999999997, + "244": -10.099999999999998, + "245": -60.100000000000016, + "246": -22.499999999999954, + "247": 39.84999999999994, + "248": -17.449999999999974, + "249": 16.30000000000005, + "250": -21.34999999999996, + "251": 7.900000000000035, + "252": -75.19999999999999, + "253": 37.09999999999979, + "254": 2.7000000000000215, + "255": -28.19999999999994, + "256": -17.499999999999975, + "257": 4.050000000000029, + "258": 29.249999999999872, + "259": -39.55000000000011, + "260": -29.10000000000001, + "261": -5.900000000000009, + "262": -16.849999999999973, + "263": 7.100000000000022, + "264": -1.5999999999999779, + "265": 19.650000000000006, + "266": -19.249999999999964, + "267": -39.949999999999996, + "268": 8.100000000000056, + "269": -19.99999999999997, + "270": 2.149999999999996, + "271": 10.749999999999979, + "272": -0.4000000000000108, + "273": -29.14999999999997, + "274": 35.349999999999824, + "275": -0.700000000000006, + "276": -22.24999999999998, + "277": -34.349999999999966, + "278": -6.4499999999999815, + "279": -12.549999999999992, + "280": -27.050000000000033, + "281": 16.00000000000003, + "282": -89.19999999999999, + "283": -72.59999999999998, + "284": -2.7999999999999767, + "285": -16.599999999999994, + "286": -17.79999999999997, + "287": -20.74999999999996, + "288": 13.3, + "289": 25.099999999999927, + "290": 22.550000000000026, + "291": 18.85000000000002, + "292": -5.199999999999991, + "293": 9.349999999999993, + "294": 83.85000000000025, + "295": -30.299999999999997, + "296": -8.999999999999995, + "297": 65.15000000000002, + "298": -71.30000000000001, + "299": -6.5499999999999865, + "300": -13.699999999999983, + "301": 26.649999999999853, + "302": 97.05000000000015, + "303": 22.650000000000027, + "304": -76.44999999999999, + "305": 4.95000000000001, + "306": -22.050000000000075, + "307": 15.899999999999999, + "308": 47.69999999999985, + "309": 28.29999999999986, + "310": 51.449999999999854, + "311": -87.54999999999998, + "312": -10.69999999999999, + "313": -7.1999999999999815, + "314": -54.400000000000006, + "315": 107.70000000000014, + "316": 18.600000000000023, + "317": 92.05000000000007, + "318": -73.39999999999998, + "319": 10.899999999999991, + "320": 29.049999999999837, + "321": 10.450000000000026, + "322": -16.349999999999973, + "323": 30.999999999999783, + "324": 6.6500000000000234, + "325": 12.599999999999998, + "326": 2.4500000000000295, + "327": 27.39999999999995, + "328": -8.999999999999988, + "329": 68.24999999999997, + "330": 0.6499999999999742, + "331": 16.15000000000002, + "332": 27.599999999999874, + "333": 32.34999999999984, + "334": 83.74999999999997, + "335": -34.599999999999994, + "336": 58.94999999999986, + "337": 4.549999999999995, + "338": 39.549999999999976, + "339": 49.74999999999994, + "340": 19.099999999999998, + "341": 92.40000000000009, + "342": 37.749999999999986, + "343": 22.399999999999977, + "344": 57.49999999999985, + "345": 46.44999999999981, + "346": -31.65, + "347": 102.05000000000013, + "348": 0.20000000000003948, + "349": 79.90000000000002, + "350": 73.34999999999998, + "351": 50.84999999999999, + "352": 28.549999999999986, + "353": 7.899999999999988, + "354": 10.69999999999997, + "355": -3.350000000000004, + "356": 18.95000000000005, + "357": 89.69999999999995, + "358": 62.199999999999896, + "359": 12.700000000000014, + "360": 54.449999999999775, + "361": 27.449999999999992, + "362": 6.300000000000015, + "363": 26.649999999999945, + "364": 60.29999999999981, + "365": 5.000000000000007, + "366": 74.94999999999995, + "367": 43.849999999999824, + "368": -7.199999999999981, + "369": 37.99999999999982, + "370": 91.05000000000014, + "371": 92.75000000000024, + "372": 64.34999999999992, + "373": 81.34999999999998, + "374": 14.050000000000011, + "375": 74.25000000000004, + "376": 87.95000000000005, + "377": 91.59999999999995, + "378": 91.8999999999999, + "379": 71.79999999999993, + "380": 94.39999999999989, + "381": 62.44999999999998, + "382": 107.20000000000012, + "383": 117.20000000000024, + "384": 111.75000000000026, + "385": 100.3000000000001, + "386": 112.84999999999995, + "387": 67.35000000000002, + "388": 97.35000000000011, + "389": 68.2500000000001, + "390": 94.60000000000002, + "391": 94.35000000000005, + "392": 59.09999999999998, + "393": -13.54999999999998, + "394": 90.10000000000008, + "395": 96.84999999999995, + "396": 37.34999999999992, + "397": 75.80000000000004, + "398": 52.65000000000003, + "399": 113.35000000000021, + "400": 110.59999999999988, + "401": 100.95, + "402": 107.10000000000004, + "403": 27.799999999999926, + "404": 92.4499999999999, + "405": 105.54999999999998, + "406": 118.05000000000013, + "407": 105.75000000000016, + "408": 65.79999999999993, + "409": 53.94999999999991, + "410": 83.95000000000002, + "411": 103.20000000000022, + "412": 111.35000000000018, + "413": 87.30000000000001, + "414": 95.10000000000018, + "415": 95.55000000000017, + "416": 114.0000000000001, + "417": 68.10000000000008, + "418": 92.40000000000002, + "419": 38.1499999999998, + "420": 94.69999999999995, + "421": 107.0000000000002, + "422": 32.449999999999996, + "423": 112.9500000000002, + "424": -4.749999999999992, + "425": 38.60000000000001, + "426": 113.05000000000014, + "427": 111.30000000000003, + "428": 107.14999999999992, + "429": 83.45000000000006, + "430": 93.34999999999985, + "431": 22.45000000000001, + "432": 107.60000000000007, + "433": 118.6, + "434": 117.35, + "435": 7.150000000000011, + "436": 79.89999999999986, + "437": 110.05000000000008, + "438": 51.04999999999984, + "439": 116.25000000000001, + "440": 111.30000000000024, + "441": 113.10000000000014, + "442": 55.8999999999998, + "443": 105.30000000000011, + "444": 98.55000000000008, + "445": 51.449999999999896, + "446": 103.65000000000002, + "447": 103.10000000000008, + "448": 116.99999999999999, + "449": 115.80000000000018, + "450": 102.3, + "451": 51.0499999999998, + "452": 119.7, + "453": 110.9000000000001, + "454": 73.89999999999986, + "455": 113.40000000000008, + "456": 89.10000000000001, + "457": 114.34999999999997, + "458": 101.69999999999989, + "459": 17.450000000000053, + "460": 109.80000000000011, + "461": 119.55000000000031, + "462": 114.30000000000005, + "463": 25.74999999999999, + "464": 108.55000000000011, + "465": 61.54999999999984, + "466": 119.55000000000013, + "467": 87.30000000000008, + "468": 90.54999999999995, + "469": 119.80000000000017, + "470": 104.70000000000002, + "471": 84.9, + "472": 110.55000000000008, + "473": 95.35000000000004, + "474": 101.95000000000007, + "475": 101.84999999999995, + "476": 97.75000000000011, + "477": 60.99999999999984, + "478": 108.65000000000003, + "479": 118.85000000000004, + "480": 55.34999999999983, + "481": 111.85000000000005, + "482": 88.30000000000004, + "483": 106.24999999999989, + "484": 120.45000000000006, + "485": 120.14999999999999, + "486": 72.29999999999988, + "487": 113.50000000000007, + "488": 111.54999999999991, + "489": 107.04999999999998, + "490": 117.60000000000021, + "491": 104.45000000000002, + "492": 50.0499999999998, + "493": 104.90000000000006, + "494": 87.15000000000008, + "495": 109.15000000000018, + "496": 111.0, + "497": 112.45000000000013, + "498": 111.80000000000001, + "499": 120.60000000000008, + "500": 106.60000000000001, + "501": 114.75, + "502": 103.4000000000002, + "503": 101.75000000000004, + "504": 97.2000000000002, + "505": 58.49999999999997, + "506": 110.45000000000009, + "507": 115.84999999999997, + "508": 36.3499999999998, + "509": 101.74999999999999, + "510": 114.35000000000014, + "511": 109.30000000000008, + "512": 94.70000000000014, + "513": 116.35000000000005, + "514": 54.049999999999855, + "515": 92.25000000000009, + "516": 107.3000000000002, + "517": 110.10000000000004, + "518": 119.45000000000012, + "519": 112.24999999999997, + "520": 20.849999999999973, + "521": 119.65000000000009, + "522": 99.05000000000007, + "523": 107.70000000000003, + "524": 16.850000000000062, + "525": 61.54999999999993, + "526": 112.90000000000012, + "527": 105.25000000000006, + "528": 119.00000000000009, + "529": 116.45, + "530": 106.40000000000018, + "531": 76.70000000000007, + "532": 102.69999999999999, + "533": 95.19999999999992, + "534": 106.59999999999995, + "535": 27.099999999999937, + "536": 109.60000000000008, + "537": 98.54999999999987, + "538": 117.20000000000026, + "539": 102.00000000000017, + "540": 117.50000000000011, + "541": 112.05000000000001, + "542": 116.35000000000004, + "543": 110.20000000000007, + "544": 93.35000000000015, + "545": 101.20000000000005, + "546": 113.75000000000014, + "547": 117.30000000000005, + "548": 47.199999999999896, + "549": 100.19999999999995, + "550": 106.05000000000004, + "551": 116.80000000000014, + "552": 92.64999999999995, + "553": 113.14999999999996, + "554": 105.79999999999993, + "555": 106.0500000000001, + "556": -10.649999999999986, + "557": 108.35000000000005, + "558": 115.00000000000013, + "559": 115.60000000000002, + "560": 116.35000000000012, + "561": 108.49999999999991, + "562": 116.35000000000012, + "563": 112.90000000000015, + "564": 114.29999999999997, + "565": 113.00000000000006, + "566": 121.75000000000007, + "567": 111.8, + "568": 117.30000000000004, + "569": 112.15000000000008, + "570": 109.10000000000008, + "571": 108.85000000000016, + "572": 117.25000000000004, + "573": 107.89999999999998, + "574": 113.05000000000005, + "575": 116.6000000000001, + "576": 106.24999999999991, + "577": 103.60000000000004, + "578": 122.80000000000003, + "579": 110.54999999999997, + "580": 112.90000000000012, + "581": 115.5, + "582": 113.00000000000006, + "583": 111.10000000000004, + "584": 113.80000000000013, + "585": 98.29999999999998, + "586": 112.35000000000012, + "587": 111.20000000000013, + "588": 106.15000000000013, + "589": 119.45000000000007, + "590": 109.69999999999999, + "591": 103.24999999999996, + "592": 113.60000000000011, + "593": 115.20000000000002, + "594": 120.35000000000001, + "595": 115.75, + "596": 106.90000000000015, + "597": 105.29999999999998, + "598": 113.50000000000001, + "599": 113.85000000000001, + "600": 110.00000000000023, + "601": 116.50000000000011, + "602": 107.90000000000008, + "603": 103.75, + "604": 112.35000000000018, + "605": 114.1500000000002, + "606": 115.70000000000009, + "607": 114.50000000000011, + "608": 113.25000000000001, + "609": 112.80000000000007, + "610": 113.15000000000002, + "611": 113.25000000000016, + "612": 112.7000000000002, + "613": 78.10000000000002, + "614": 109.95000000000003, + "615": 107.6000000000001, + "616": 113.35000000000002, + "617": 105.85000000000005, + "618": 112.00000000000016, + "619": 119.6000000000001, + "620": 109.8500000000002, + "621": 102.50000000000001, + "622": 86.3, + "623": 113.30000000000013, + "624": 109.44999999999996, + "625": 114.10000000000021, + "626": 115.10000000000012, + "627": 112.75000000000013, + "628": 70.34999999999984, + "629": 100.29999999999994, + "630": 118.85000000000011, + "631": 105.20000000000006, + "632": 109.19999999999993, + "633": 120.49999999999999, + "634": 106.60000000000002, + "635": 108.3500000000001, + "636": 109.85000000000007, + "637": 102.4500000000001, + "638": 116.25000000000024, + "639": 115.85000000000005, + "640": 114.55000000000007, + "641": 111.30000000000011, + "642": 106.90000000000003, + "643": 111.3500000000001, + "644": 115.00000000000009, + "645": 95.64999999999995, + "646": 104.05000000000011, + "647": 114.45000000000019, + "648": 97.54999999999993, + "649": 111.9500000000001, + "650": 117.60000000000015, + "651": 106.10000000000012, + "652": 107.50000000000007, + "653": 102.00000000000013, + "654": 118.95000000000009, + "655": 59.199999999999896, + "656": 111.35000000000012, + "657": 117.70000000000022, + "658": 90.95000000000012, + "659": 84.05000000000013, + "660": 109.90000000000015, + "661": 113.04999999999998, + "662": 109.45000000000006, + "663": 90.80000000000015, + "664": 110.90000000000002, + "665": 115.65000000000002, + "666": 101.94999999999996, + "667": 101.65000000000002, + "668": 115.35, + "669": 112.2, + "670": 98.49999999999997, + "671": 105.30000000000005, + "672": 111.10000000000011, + "673": 95.8000000000001, + "674": 108.20000000000014, + "675": 107.05000000000005, + "676": 113.05000000000004, + "677": 103.0500000000001, + "678": 111.00000000000004, + "679": 95.05000000000021, + "680": 105.79999999999998, + "681": 97.00000000000016, + "682": 112.60000000000011, + "683": 111.5500000000001, + "684": 110.19999999999999, + "685": 100.45000000000014, + "686": 107.90000000000015, + "687": 102.90000000000009, + "688": 98.55000000000015, + "689": 119.99999999999997, + "690": 105.25000000000009, + "691": 99.15000000000003, + "692": 116.1, + "693": 104.85000000000007, + "694": 112.20000000000009, + "695": 121.20000000000006, + "696": 111.10000000000014, + "697": 112.7500000000001, + "698": 109.10000000000002, + "699": 114.0000000000001, + "700": 99.35, + "701": 110.45000000000005, + "702": 119.75, + "703": 105.50000000000006, + "704": 116.30000000000004, + "705": 111.00000000000014, + "706": 114.95000000000002, + "707": 100.50000000000011, + "708": 100.59999999999998, + "709": 100.79999999999991, + "710": 23.449999999999942, + "711": 109.70000000000007, + "712": 99.65000000000005, + "713": 105.9, + "714": 112.3500000000001, + "715": 111.80000000000011, + "716": 110.00000000000013, + "717": 117.60000000000005, + "718": 110.54999999999997, + "719": 110.80000000000008, + "720": 106.6, + "721": 20.300000000000026, + "722": 112.80000000000018, + "723": 112.55, + "724": 103.85000000000002, + "725": 106.40000000000019, + "726": 106.95000000000009, + "727": 109.10000000000005, + "728": 113.94999999999996, + "729": 108.00000000000007, + "730": 113.5500000000001, + "731": 103.0500000000002, + "732": 109.80000000000007, + "733": 109.60000000000011, + "734": 112.2500000000001, + "735": 116.65000000000012, + "736": 106.7, + "737": 100.1000000000001, + "738": 112.14999999999999, + "739": 119.19999999999999, + "740": 117.10000000000015, + "741": 114.30000000000015, + "742": 108.24999999999997, + "743": 106.65000000000013, + "744": 107.75, + "745": 107.55000000000001, + "746": 110.50000000000004, + "747": 111.95000000000022, + "748": 105.25000000000004, + "749": 105.35000000000004, + "750": 106.15000000000008, + "751": 117.40000000000002, + "752": 114.1, + "753": 105.04999999999998, + "754": 109.2, + "755": 113.05000000000015, + "756": 116.65000000000015, + "757": 114.5000000000001, + "758": 111.70000000000009, + "759": 109.44999999999997, + "760": 114.1, + "761": 106.14999999999989, + "762": 112.60000000000001, + "763": 109.15000000000003, + "764": 116.9500000000001, + "765": 113.10000000000022, + "766": 111.35000000000022, + "767": 109.65000000000018, + "768": 115.50000000000009, + "769": 112.95000000000006, + "770": 114.85000000000012, + "771": 111.55000000000017, + "772": 117.20000000000003, + "773": 104.95000000000007, + "774": 112.75000000000014, + "775": 119.75000000000011, + "776": 113.20000000000019, + "777": 110.45000000000019, + "778": 108.89999999999996, + "779": 105.75000000000007, + "780": 103.25000000000004, + "781": 111.1, + "782": 111.15000000000003, + "783": 119.55, + "784": 107.20000000000012, + "785": 112.65000000000013, + "786": 114.50000000000003, + "787": 111.39999999999998, + "788": 116.00000000000003, + "789": 112.00000000000007, + "790": 113.35000000000012, + "791": 113.90000000000012, + "792": 108.85000000000012, + "793": 118.50000000000003, + "794": 108.40000000000002, + "795": 119.75000000000011, + "796": 106.30000000000007, + "797": 113.85000000000002, + "798": 103.85000000000004, + "799": 109.0, + "800": 108.70000000000012, + "801": 116.25000000000009, + "802": 113.45000000000005, + "803": 107.50000000000011, + "804": 113.4000000000001, + "805": 115.90000000000006, + "806": 114.40000000000012, + "807": 106.39999999999996, + "808": 119.05000000000018, + "809": 115.65000000000013, + "810": 107.95000000000003, + "811": 112.55000000000003, + "812": 101.39999999999992, + "813": 101.80000000000013, + "814": 114.80000000000024, + "815": 118.25000000000016, + "816": 102.65000000000005, + "817": 100.65000000000018, + "818": 109.05000000000005, + "819": 117.95000000000005, + "820": 109.4500000000001, + "821": 110.15000000000019, + "822": 117.75, + "823": 115.49999999999996, + "824": 116.1, + "825": 107.70000000000019, + "826": 109.8500000000001, + "827": 116.00000000000009, + "828": 113.05000000000001, + "829": 96.65000000000006, + "830": 115.65000000000005, + "831": 21.94999999999994, + "832": 116.70000000000002, + "833": 113.50000000000007, + "834": 104.89999999999999, + "835": 116.85000000000011, + "836": 112.10000000000005, + "837": 112.20000000000017, + "838": 110.5999999999999, + "839": 111.95000000000005, + "840": 108.0000000000002, + "841": 111.25000000000009, + "842": 91.79999999999998, + "843": 100.95, + "844": 103.74999999999994, + "845": 109.74999999999997, + "846": 104.45000000000012, + "847": 114.30000000000024, + "848": 107.35000000000012, + "849": 115.10000000000008, + "850": 99.60000000000005, + "851": 110.74999999999997, + "852": 108.50000000000007, + "853": 103.5500000000001, + "854": 109.10000000000001, + "855": 107.75000000000006, + "856": 106.40000000000012, + "857": 107.20000000000013, + "858": 119.35000000000016, + "859": 111.55000000000013, + "860": 122.65, + "861": 41.69999999999987, + "862": 106.80000000000008, + "863": 107.04999999999991, + "864": 120.45000000000002, + "865": 110.30000000000018, + "866": 103.40000000000016, + "867": 69.89999999999992, + "868": 105.0000000000001, + "869": 98.49999999999996, + "870": 105.35000000000012, + "871": 107.14999999999999, + "872": 112.40000000000009, + "873": 119.85000000000002, + "874": 112.60000000000007, + "875": 103.20000000000009, + "876": 104.80000000000008, + "877": 114.20000000000014, + "878": 119.55000000000021, + "879": 113.60000000000008, + "880": 105.70000000000012, + "881": 103.85000000000007, + "882": 81.50000000000006, + "883": 107.95000000000013, + "884": 110.60000000000005, + "885": 84.35000000000015, + "886": 116.34999999999998, + "887": 110.55000000000004, + "888": 103.35000000000012, + "889": 115.0000000000002, + "890": 111.44999999999993, + "891": 114.30000000000004, + "892": 109.00000000000009, + "893": 26.599999999999866, + "894": 118.70000000000005, + "895": 105.55000000000007, + "896": 106.45000000000013, + "897": 113.55000000000008, + "898": 115.15000000000008, + "899": 111.00000000000006, + "900": 114.35000000000012, + "901": 100.40000000000005, + "902": 95.25, + "903": 112.00000000000006, + "904": 86.00000000000014, + "905": 118.00000000000009, + "906": 117.69999999999999, + "907": 65.64999999999999, + "908": 115.65000000000002, + "909": 114.65000000000006, + "910": 110.20000000000012, + "911": 111.55000000000005, + "912": 108.55000000000008, + "913": 106.05000000000001, + "914": 118.55000000000011, + "915": 107.6000000000001, + "916": 113.75000000000009, + "917": 118.45000000000016, + "918": 38.69999999999993, + "919": 114.35000000000004, + "920": 107.75000000000006, + "921": 114.25000000000026, + "922": 23.799999999999976, + "923": 108.50000000000006, + "924": 111.05000000000005, + "925": 117.20000000000007, + "926": 116.95000000000005, + "927": 107.64999999999999, + "928": 100.40000000000012, + "929": 118.2500000000001, + "930": 110.55000000000003, + "931": 104.20000000000012, + "932": 108.45000000000009, + "933": 15.89999999999998, + "934": 75.99999999999999, + "935": 109.35000000000001, + "936": 102.99999999999997, + "937": 105.79999999999998, + "938": 108.05000000000003, + "939": 93.95000000000002, + "940": 111.45, + "941": 100.19999999999999, + "942": 111.05000000000011, + "943": 103.00000000000004, + "944": 109.14999999999998, + "945": 99.74999999999993, + "946": 104.70000000000005, + "947": 59.94999999999983, + "948": 110.45000000000017, + "949": 94.14999999999996, + "950": 113.30000000000008, + "951": 99.79999999999994, + "952": 101.09999999999992, + "953": 98.99999999999999, + "954": 102.25000000000024, + "955": 97.50000000000006, + "956": 96.35000000000012, + "957": 108.15000000000005, + "958": 59.19999999999992, + "959": 105.30000000000008, + "960": 114.04999999999997, + "961": 113.85000000000001, + "962": 11.299999999999983, + "963": 91.60000000000005, + "964": 77.45000000000002, + "965": 76.10000000000014, + "966": 68.80000000000015, + "967": 105.7000000000001, + "968": 113.05000000000004, + "969": 107.95000000000006, + "970": 101.30000000000005, + "971": 88.2500000000001, + "972": 85.65000000000015, + "973": 97.85000000000021, + "974": 113.70000000000016, + "975": 119.55000000000014, + "976": 93.80000000000013, + "977": 109.15000000000003, + "978": 114.50000000000013, + "979": 116.75000000000006, + "980": 103.55000000000011, + "981": 107.50000000000013, + "982": 102.20000000000013, + "983": 113.05000000000008, + "984": 107.0500000000001, + "985": 28.14999999999998, + "986": 101.99999999999991, + "987": 112.60000000000015, + "988": 101.59999999999998, + "989": 101.40000000000006, + "990": 104.55000000000005, + "991": 105.40000000000002, + "992": 112.05000000000008, + "993": 106.9500000000001, + "994": 114.30000000000005, + "995": 94.95000000000007, + "996": 113.15000000000002, + "997": 120.80000000000018, + "998": 92.00000000000006, + "999": 112.00000000000009, + "1000": 102.55000000000008 + } +} \ No newline at end of file diff --git a/benchmark/results/v3/v3.1.0/session_metadata/2.json b/benchmark/results/v3/v3.1.0/session_metadata/2.json new file mode 100644 index 00000000..5c0b195e --- /dev/null +++ b/benchmark/results/v3/v3.1.0/session_metadata/2.json @@ -0,0 +1,1009 @@ +{ + "total_episodes": 1001, + "total_time_steps": 128000, + "total_s": 1484.57062, + "s_per_step": 0.046392831875, + "s_per_100_steps_10_nodes": 4.6392831875, + "total_reward_per_episode": { + "1": -53.55000000000008, + "2": -17.099999999999987, + "3": -21.049999999999958, + "4": -37.20000000000004, + "5": -45.20000000000007, + "6": -24.89999999999996, + "7": -43.05000000000009, + "8": -15.94999999999998, + "9": -17.94999999999997, + "10": -75.29999999999997, + "11": -94.85, + "12": -42.24999999999996, + "13": -14.349999999999975, + "14": -29.55000000000002, + "15": -10.199999999999996, + "16": -79.89999999999986, + "17": -45.30000000000006, + "18": -9.099999999999996, + "19": -19.099999999999966, + "20": -50.75000000000007, + "21": -21.549999999999958, + "22": -18.449999999999967, + "23": -32.49999999999998, + "24": -65.20000000000009, + "25": -47.05000000000006, + "26": -83.09999999999984, + "27": -33.84999999999999, + "28": -20.64999999999996, + "29": -23.04999999999995, + "30": -15.349999999999971, + "31": -14.499999999999986, + "32": -51.60000000000007, + "33": -9.349999999999982, + "34": -22.549999999999955, + "35": -69.75000000000006, + "36": -44.799999999999976, + "37": -14.19999999999996, + "38": -12.749999999999993, + "39": -30.74999999999994, + "40": -22.049999999999955, + "41": -58.500000000000114, + "42": -16.64999999999997, + "43": -17.39999999999997, + "44": -20.999999999999957, + "45": -16.099999999999973, + "46": -20.099999999999962, + "47": -30.350000000000005, + "48": -21.699999999999957, + "49": -21.549999999999958, + "50": -17.649999999999974, + "51": -19.299999999999965, + "52": -7.099999999999988, + "53": -21.899999999999952, + "54": -50.250000000000156, + "55": -29.15000000000002, + "56": -17.149999999999977, + "57": -15.699999999999966, + "58": -19.549999999999965, + "59": -16.74999999999997, + "60": -11.549999999999994, + "61": -17.099999999999973, + "62": -17.449999999999967, + "63": -22.099999999999955, + "64": -18.499999999999968, + "65": -14.499999999999982, + "66": -57.450000000000095, + "67": -22.699999999999953, + "68": -20.69999999999996, + "69": -13.34999999999998, + "70": -10.450000000000001, + "71": -14.449999999999989, + "72": -10.299999999999997, + "73": -35.15000000000007, + "74": -19.099999999999966, + "75": -21.54999999999996, + "76": -64.9000000000001, + "77": -68.85000000000005, + "78": -16.399999999999974, + "79": -30.30000000000002, + "80": -10.899999999999999, + "81": -15.949999999999978, + "82": -20.59999999999996, + "83": -67.40000000000016, + "84": -18.899999999999963, + "85": -100.85, + "86": -9.849999999999985, + "87": -18.54999999999997, + "88": -13.999999999999998, + "89": -0.49999999999997136, + "90": -19.699999999999964, + "91": -88.14999999999998, + "92": -18.199999999999967, + "93": -18.29999999999997, + "94": -14.29999999999999, + "95": -12.74999999999999, + "96": -15.399999999999975, + "97": -9.949999999999996, + "98": -19.099999999999966, + "99": -19.74999999999999, + "100": -14.299999999999974, + "101": -11.64999999999999, + "102": -21.399999999999956, + "103": -21.999999999999954, + "104": -19.79999999999996, + "105": -21.599999999999948, + "106": -5.5000000000000036, + "107": -19.99999999999996, + "108": -10.399999999999993, + "109": -8.30000000000001, + "110": -21.39999999999996, + "111": -19.849999999999962, + "112": -20.199999999999964, + "113": -19.149999999999967, + "114": -14.999999999999952, + "115": -14.899999999999975, + "116": -4.149999999999977, + "117": -18.299999999999965, + "118": -34.99999999999995, + "119": 9.900000000000063, + "120": -23.14999999999995, + "121": -89.55, + "122": -7.34999999999999, + "123": -3.950000000000001, + "124": -1.4999999999999765, + "125": -19.099999999999966, + "126": -3.3999999999999773, + "127": -20.39999999999996, + "128": -18.19999999999996, + "129": -13.199999999999985, + "130": 16.449999999999942, + "131": -15.349999999999982, + "132": -21.649999999999956, + "133": -22.899999999999952, + "134": -42.650000000000134, + "135": -10.249999999999988, + "136": -20.149999999999963, + "137": -18.249999999999968, + "138": -18.54999999999996, + "139": -44.050000000000054, + "140": -6.9499999999999895, + "141": -15.19999999999998, + "142": -70.4, + "143": -3.7999999999999794, + "144": -0.45000000000000084, + "145": -11.19999999999999, + "146": -41.10000000000004, + "147": -47.00000000000011, + "148": -14.299999999999985, + "149": -3.1999999999999886, + "150": 4.700000000000002, + "151": -11.19999999999997, + "152": -19.79999999999996, + "153": -5.899999999999985, + "154": -58.599999999999994, + "155": -19.649999999999967, + "156": -17.94999999999997, + "157": -13.599999999999987, + "158": -22.64999999999996, + "159": -15.399999999999979, + "160": 0.2500000000000384, + "161": -4.849999999999978, + "162": -10.300000000000006, + "163": -3.9999999999999796, + "164": -13.099999999999989, + "165": -13.44999999999997, + "166": -27.24999999999995, + "167": 16.550000000000054, + "168": -7.850000000000002, + "169": -5.600000000000016, + "170": -13.349999999999989, + "171": -3.5500000000000016, + "172": -1.5000000000000102, + "173": -83.24999999999997, + "174": -43.350000000000136, + "175": -38.00000000000008, + "176": -88.75000000000001, + "177": -1.8500000000000005, + "178": 11.999999999999993, + "179": 23.049999999999937, + "180": -2.6499999999999684, + "181": 0.7000000000000337, + "182": 14.499999999999982, + "183": -10.300000000000004, + "184": -35.699999999999974, + "185": -77.99999999999997, + "186": -10.74999999999999, + "187": -0.15000000000000013, + "188": -33.60000000000003, + "189": 3.100000000000029, + "190": -14.79999999999998, + "191": -10.049999999999992, + "192": -32.30000000000006, + "193": -61.70000000000005, + "194": 2.3500000000000254, + "195": -34.849999999999945, + "196": -58.000000000000036, + "197": -1.9000000000000652, + "198": 23.049999999999958, + "199": -14.24999999999999, + "200": -67.4, + "201": -15.19999999999997, + "202": -12.849999999999993, + "203": -61.79999999999995, + "204": 2.4500000000000224, + "205": -17.94999999999997, + "206": -34.3, + "207": -47.349999999999994, + "208": -72.7, + "209": -34.75000000000003, + "210": -4.1000000000000085, + "211": 13.549999999999958, + "212": -84.04999999999994, + "213": -11.449999999999987, + "214": -34.79999999999997, + "215": -65.20000000000007, + "216": 2.1999999999999824, + "217": 28.799999999999972, + "218": -29.499999999999964, + "219": -11.149999999999988, + "220": 5.600000000000037, + "221": -10.899999999999988, + "222": 2.250000000000001, + "223": 69.20000000000003, + "224": 2.2499999999999885, + "225": -13.14999999999999, + "226": 33.799999999999784, + "227": 7.100000000000029, + "228": 1.2500000000000346, + "229": -57.70000000000001, + "230": -34.800000000000004, + "231": 30.249999999999932, + "232": 40.09999999999975, + "233": -48.65, + "234": -1.049999999999974, + "235": -75.80000000000001, + "236": -26.949999999999925, + "237": 21.14999999999999, + "238": -0.6999999999999761, + "239": 44.99999999999984, + "240": 42.64999999999988, + "241": -1.5999999999999654, + "242": 16.349999999999962, + "243": -3.6999999999999567, + "244": 42.2499999999999, + "245": -71.9, + "246": -3.5499999999999794, + "247": -50.24999999999999, + "248": -71.99999999999997, + "249": -79.04999999999995, + "250": -32.749999999999986, + "251": 38.34999999999986, + "252": 25.94999999999995, + "253": 21.24999999999999, + "254": -7.150000000000038, + "255": -67.64999999999998, + "256": 23.400000000000002, + "257": 20.950000000000035, + "258": 2.149999999999986, + "259": 7.350000000000016, + "260": -6.250000000000009, + "261": 41.39999999999999, + "262": 23.699999999999957, + "263": 1.1500000000000201, + "264": -55.04999999999996, + "265": 19.35000000000001, + "266": 14.750000000000071, + "267": -14.449999999999985, + "268": 5.399999999999991, + "269": 49.44999999999996, + "270": -2.399999999999986, + "271": -11.249999999999948, + "272": 1.8000000000000265, + "273": -20.900000000000055, + "274": -8.749999999999995, + "275": -77.44999999999999, + "276": 12.699999999999989, + "277": 6.200000000000016, + "278": -7.000000000000002, + "279": 22.10000000000002, + "280": 40.049999999999784, + "281": -75.80000000000001, + "282": 8.050000000000043, + "283": -21.149999999999995, + "284": 40.8999999999998, + "285": 92.9500000000001, + "286": -82.79999999999995, + "287": 60.34999999999996, + "288": 25.449999999999996, + "289": -79.64999999999998, + "290": -75.74999999999994, + "291": 17.44999999999997, + "292": -31.50000000000003, + "293": 39.69999999999993, + "294": -37.09999999999999, + "295": 21.84999999999992, + "296": 12.29999999999999, + "297": 87.2, + "298": -32.6, + "299": 23.449999999999953, + "300": -13.450000000000014, + "301": -15.00000000000004, + "302": -79.65, + "303": -44.89999999999997, + "304": 56.34999999999976, + "305": 11.850000000000051, + "306": 8.649999999999984, + "307": 38.64999999999991, + "308": 50.19999999999997, + "309": -10.750000000000018, + "310": 3.400000000000026, + "311": 29.350000000000033, + "312": 4.79999999999999, + "313": -4.250000000000017, + "314": 93.40000000000008, + "315": 33.19999999999999, + "316": 28.60000000000003, + "317": 16.9, + "318": 63.89999999999988, + "319": -21.850000000000005, + "320": -33.95000000000007, + "321": -79.15, + "322": -24.549999999999976, + "323": 41.79999999999999, + "324": 60.79999999999991, + "325": 1.0000000000000018, + "326": 103.05000000000011, + "327": 111.1, + "328": 28.099999999999948, + "329": 29.84999999999998, + "330": -9.6, + "331": -8.800000000000004, + "332": 50.84999999999994, + "333": 29.949999999999807, + "334": 59.30000000000007, + "335": 88.20000000000007, + "336": 56.34999999999995, + "337": 84.80000000000004, + "338": 55.69999999999988, + "339": 11.250000000000005, + "340": 80.34999999999991, + "341": 116.60000000000018, + "342": 57.849999999999966, + "343": -66.39999999999995, + "344": -6.800000000000019, + "345": 36.40000000000008, + "346": 19.55, + "347": 80.49999999999989, + "348": 98.40000000000023, + "349": 74.00000000000014, + "350": 104.09999999999998, + "351": 105.55000000000011, + "352": 99.00000000000016, + "353": 90.75000000000003, + "354": 19.899999999999892, + "355": 88.5500000000001, + "356": 11.500000000000043, + "357": 20.10000000000002, + "358": 90.89999999999995, + "359": 38.15, + "360": 112.2000000000002, + "361": 100.5500000000002, + "362": 97.45000000000019, + "363": 101.10000000000018, + "364": 45.15000000000002, + "365": 54.44999999999993, + "366": -46.44999999999998, + "367": 90.8000000000001, + "368": 51.399999999999935, + "369": 103.90000000000025, + "370": 64.05000000000005, + "371": 94.0, + "372": 75.45000000000002, + "373": 92.15000000000003, + "374": 17.249999999999925, + "375": 61.74999999999988, + "376": 103.60000000000008, + "377": 96.79999999999981, + "378": 104.60000000000016, + "379": 111.59999999999995, + "380": 95.15000000000009, + "381": 117.00000000000016, + "382": 67.44999999999995, + "383": 59.24999999999986, + "384": 72.74999999999991, + "385": 75.5, + "386": 42.74999999999994, + "387": 88.45000000000002, + "388": 119.75000000000034, + "389": 83.30000000000008, + "390": 93.20000000000014, + "391": 102.35000000000008, + "392": 66.10000000000001, + "393": 99.6000000000001, + "394": 66.75, + "395": 73.34999999999998, + "396": 60.200000000000045, + "397": 82.00000000000003, + "398": 104.55000000000005, + "399": -49.050000000000004, + "400": 108.95000000000006, + "401": 102.45000000000023, + "402": 112.9500000000001, + "403": 59.34999999999997, + "404": 97.69999999999993, + "405": 107.79999999999995, + "406": 63.34999999999991, + "407": 67.85000000000007, + "408": 112.34999999999997, + "409": 103.09999999999994, + "410": 114.90000000000013, + "411": 98.94999999999996, + "412": 105.20000000000019, + "413": 58.799999999999834, + "414": 109.40000000000013, + "415": 84.45000000000002, + "416": 105.05000000000003, + "417": 46.79999999999989, + "418": 85.09999999999997, + "419": 90.19999999999989, + "420": 101.85000000000008, + "421": 59.14999999999989, + "422": 32.500000000000014, + "423": 3.350000000000037, + "424": 49.149999999999885, + "425": 56.349999999999724, + "426": 109.9000000000002, + "427": 102.90000000000022, + "428": -8.999999999999991, + "429": 108.34999999999982, + "430": 118.75000000000021, + "431": 80.45000000000005, + "432": 90.35000000000004, + "433": 106.40000000000016, + "434": 79.55000000000003, + "435": 90.35000000000005, + "436": 85.35000000000004, + "437": 3.4000000000000643, + "438": 118.35000000000002, + "439": 106.9999999999999, + "440": 99.30000000000003, + "441": 69.29999999999993, + "442": 113.29999999999995, + "443": 103.09999999999991, + "444": 106.25000000000011, + "445": 5.250000000000016, + "446": 110.7000000000001, + "447": 97.44999999999978, + "448": 106.45000000000009, + "449": 110.69999999999999, + "450": 108.2500000000002, + "451": 90.40000000000013, + "452": 29.29999999999997, + "453": 3.7500000000000253, + "454": 84.05000000000008, + "455": 38.349999999999774, + "456": 108.20000000000014, + "457": 112.20000000000006, + "458": 96.09999999999982, + "459": 113.10000000000001, + "460": 74.90000000000002, + "461": 104.35000000000022, + "462": 117.14999999999998, + "463": 112.65000000000015, + "464": 116.40000000000006, + "465": 94.20000000000009, + "466": -19.74999999999996, + "467": 101.04999999999997, + "468": 96.25000000000011, + "469": 101.95000000000006, + "470": 92.99999999999993, + "471": 107.65000000000018, + "472": 67.89999999999974, + "473": 104.85, + "474": 99.65000000000012, + "475": -19.949999999999992, + "476": 86.3000000000001, + "477": 79.49999999999996, + "478": 90.29999999999993, + "479": 115.30000000000021, + "480": 107.00000000000027, + "481": 115.20000000000023, + "482": 103.00000000000004, + "483": 110.90000000000009, + "484": 103.10000000000007, + "485": 78.4500000000001, + "486": 78.69999999999979, + "487": 118.20000000000014, + "488": 88.25000000000006, + "489": 81.44999999999997, + "490": 81.10000000000026, + "491": 89.80000000000008, + "492": 91.94999999999999, + "493": 112.70000000000005, + "494": 116.30000000000005, + "495": 114.6, + "496": 85.95000000000002, + "497": -10.349999999999975, + "498": 94.7499999999999, + "499": 92.15000000000003, + "500": 92.8999999999998, + "501": 112.50000000000006, + "502": 93.1000000000001, + "503": 99.60000000000001, + "504": 101.40000000000016, + "505": 112.95000000000002, + "506": 91.99999999999994, + "507": 108.39999999999992, + "508": 103.00000000000018, + "509": 74.40000000000008, + "510": 115.50000000000027, + "511": 91.39999999999993, + "512": 93.49999999999997, + "513": 114.8500000000001, + "514": 67.54999999999991, + "515": 94.04999999999995, + "516": 97.65000000000003, + "517": 97.3499999999999, + "518": 110.85000000000005, + "519": 82.85000000000008, + "520": 79.20000000000012, + "521": 102.70000000000012, + "522": 99.90000000000006, + "523": 76.10000000000004, + "524": 92.10000000000018, + "525": 47.90000000000001, + "526": 96.25000000000009, + "527": 115.45000000000023, + "528": 106.00000000000004, + "529": 52.149999999999885, + "530": 75.04999999999997, + "531": 82.70000000000006, + "532": 105.65000000000012, + "533": 110.95000000000006, + "534": 91.30000000000005, + "535": 94.84999999999995, + "536": 103.50000000000016, + "537": 79.24999999999997, + "538": 95.50000000000009, + "539": 117.40000000000015, + "540": 112.39999999999989, + "541": 109.0500000000002, + "542": 98.55000000000005, + "543": 63.249999999999886, + "544": 97.15000000000025, + "545": 106.20000000000017, + "546": 108.4500000000001, + "547": 86.44999999999992, + "548": 83.0499999999999, + "549": 88.89999999999996, + "550": 111.10000000000018, + "551": 102.64999999999998, + "552": 117.30000000000011, + "553": 117.55000000000035, + "554": 101.59999999999977, + "555": 89.35000000000004, + "556": 103.0500000000001, + "557": 93.84999999999994, + "558": 78.15000000000012, + "559": 96.50000000000016, + "560": 108.54999999999998, + "561": 111.20000000000005, + "562": 118.30000000000005, + "563": 98.90000000000013, + "564": 90.30000000000004, + "565": 115.30000000000014, + "566": 108.25000000000007, + "567": 94.60000000000001, + "568": 99.40000000000012, + "569": 97.19999999999979, + "570": 95.05000000000027, + "571": 112.7000000000001, + "572": 110.64999999999999, + "573": 119.65000000000022, + "574": 108.00000000000013, + "575": 108.00000000000011, + "576": 98.5500000000001, + "577": 100.70000000000009, + "578": 113.40000000000012, + "579": 100.19999999999999, + "580": 111.05000000000005, + "581": 72.74999999999994, + "582": 107.55000000000014, + "583": 115.05000000000022, + "584": 113.75000000000017, + "585": 112.90000000000019, + "586": 87.89999999999989, + "587": 106.40000000000006, + "588": 111.85000000000021, + "589": 90.85000000000007, + "590": 107.19999999999999, + "591": 107.15000000000023, + "592": 115.10000000000002, + "593": 115.00000000000009, + "594": 80.19999999999995, + "595": 116.10000000000018, + "596": 109.7000000000001, + "597": 109.10000000000005, + "598": 107.85000000000002, + "599": 116.70000000000016, + "600": 119.3000000000001, + "601": 108.75000000000003, + "602": 116.40000000000018, + "603": 112.75000000000021, + "604": 116.50000000000004, + "605": 102.29999999999994, + "606": 63.99999999999988, + "607": 111.45000000000022, + "608": 98.59999999999991, + "609": 104.90000000000023, + "610": 115.95000000000029, + "611": 102.9, + "612": 112.65000000000008, + "613": 107.95000000000013, + "614": 119.30000000000018, + "615": 116.50000000000001, + "616": 122.75000000000004, + "617": 113.25000000000006, + "618": 111.00000000000023, + "619": 114.10000000000025, + "620": 98.24999999999997, + "621": 109.75000000000016, + "622": 87.24999999999999, + "623": 87.44999999999996, + "624": 101.59999999999984, + "625": 98.30000000000005, + "626": 108.25000000000004, + "627": 111.40000000000013, + "628": 111.15000000000002, + "629": 114.95000000000012, + "630": 112.25000000000009, + "631": 71.40000000000013, + "632": 88.05000000000001, + "633": 119.15000000000006, + "634": 110.6500000000001, + "635": -6.400000000000002, + "636": 67.84999999999991, + "637": 121.65000000000009, + "638": 116.00000000000009, + "639": 105.70000000000002, + "640": 115.2500000000002, + "641": 99.14999999999995, + "642": 111.10000000000002, + "643": 110.35000000000024, + "644": 109.85000000000014, + "645": 113.5500000000001, + "646": 113.70000000000006, + "647": 113.55000000000017, + "648": 39.69999999999996, + "649": 106.75000000000001, + "650": 111.10000000000022, + "651": 115.25000000000004, + "652": 114.0000000000001, + "653": 108.40000000000006, + "654": 100.94999999999992, + "655": 32.3999999999998, + "656": 113.80000000000014, + "657": 94.09999999999997, + "658": 109.55, + "659": 113.45000000000003, + "660": 109.10000000000011, + "661": 114.85000000000011, + "662": 100.4499999999999, + "663": 110.85000000000004, + "664": 119.80000000000004, + "665": 120.40000000000008, + "666": 119.05000000000018, + "667": 74.29999999999997, + "668": 109.40000000000023, + "669": 116.10000000000018, + "670": 71.39999999999992, + "671": 110.0, + "672": 87.35, + "673": 113.4000000000001, + "674": 115.65000000000008, + "675": 98.29999999999994, + "676": 108.55000000000001, + "677": 114.95000000000014, + "678": 105.35000000000005, + "679": 82.89999999999995, + "680": 113.60000000000014, + "681": 111.95000000000007, + "682": 113.40000000000013, + "683": 118.25000000000023, + "684": 112.4000000000001, + "685": 110.15000000000005, + "686": 120.05, + "687": 116.55000000000005, + "688": 118.1000000000001, + "689": 114.50000000000003, + "690": 104.8000000000001, + "691": 118.10000000000015, + "692": 115.45000000000013, + "693": 118.0500000000001, + "694": 107.19999999999989, + "695": 113.80000000000013, + "696": 103.94999999999993, + "697": 113.05000000000015, + "698": 109.9500000000001, + "699": 113.25000000000018, + "700": 112.20000000000006, + "701": 104.35000000000007, + "702": 103.75000000000006, + "703": 108.15000000000006, + "704": 111.0500000000002, + "705": 96.15000000000002, + "706": 120.50000000000006, + "707": 101.24999999999996, + "708": 117.90000000000009, + "709": 99.35000000000012, + "710": 105.8499999999999, + "711": 110.10000000000012, + "712": 108.35000000000012, + "713": 82.49999999999997, + "714": 118.3000000000001, + "715": 106.25, + "716": 116.25000000000017, + "717": 105.15000000000006, + "718": 97.20000000000009, + "719": 112.10000000000018, + "720": 108.15000000000008, + "721": 115.15000000000003, + "722": 33.94999999999976, + "723": 108.95000000000014, + "724": 97.10000000000012, + "725": 111.90000000000019, + "726": 103.50000000000003, + "727": 116.6500000000001, + "728": 107.95000000000016, + "729": 105.2000000000001, + "730": 112.65000000000009, + "731": 112.60000000000018, + "732": 102.1000000000001, + "733": 107.89999999999995, + "734": 114.25000000000001, + "735": 106.80000000000007, + "736": 103.05000000000005, + "737": 104.49999999999996, + "738": 112.65000000000016, + "739": 100.05000000000017, + "740": 100.00000000000004, + "741": 116.35000000000007, + "742": 111.15000000000008, + "743": 106.54999999999997, + "744": 110.95, + "745": 107.20000000000007, + "746": 109.45000000000003, + "747": 108.70000000000014, + "748": 110.40000000000002, + "749": 113.15000000000003, + "750": 120.05000000000018, + "751": 111.45000000000009, + "752": 111.90000000000009, + "753": 85.50000000000004, + "754": 117.45000000000009, + "755": 112.40000000000018, + "756": 112.5500000000001, + "757": 110.35000000000007, + "758": 115.85000000000002, + "759": 98.94999999999987, + "760": 110.70000000000007, + "761": 112.15000000000015, + "762": 93.0000000000002, + "763": 115.75000000000028, + "764": 108.70000000000002, + "765": 111.25000000000004, + "766": 102.65, + "767": 102.14999999999995, + "768": 107.70000000000003, + "769": 115.99999999999997, + "770": 110.05000000000001, + "771": 116.70000000000007, + "772": 112.80000000000007, + "773": 112.70000000000005, + "774": 116.20000000000017, + "775": 112.70000000000014, + "776": 110.05000000000003, + "777": 117.25000000000006, + "778": 110.45, + "779": 111.20000000000009, + "780": 107.29999999999997, + "781": 108.45000000000013, + "782": 117.20000000000006, + "783": 111.05000000000007, + "784": 101.80000000000003, + "785": 115.05000000000004, + "786": 114.05000000000022, + "787": 110.4500000000002, + "788": 107.40000000000009, + "789": 107.85000000000014, + "790": 110.80000000000008, + "791": 106.39999999999993, + "792": 106.85000000000014, + "793": 112.3000000000001, + "794": 106.35000000000002, + "795": 111.90000000000005, + "796": 101.4, + "797": 115.3500000000001, + "798": 116.60000000000004, + "799": 112.64999999999996, + "800": 102.80000000000008, + "801": 114.60000000000016, + "802": 36.05000000000011, + "803": 109.45000000000016, + "804": 110.70000000000009, + "805": 107.1, + "806": 106.99999999999999, + "807": 116.80000000000004, + "808": 107.00000000000013, + "809": 115.60000000000008, + "810": 104.19999999999997, + "811": 119.10000000000002, + "812": 111.75000000000009, + "813": 118.95000000000019, + "814": 111.80000000000003, + "815": 118.05000000000004, + "816": 115.85000000000004, + "817": 108.85000000000012, + "818": 115.25000000000007, + "819": 114.55000000000003, + "820": 99.50000000000004, + "821": 114.00000000000003, + "822": 108.94999999999999, + "823": 104.25, + "824": 112.85000000000002, + "825": 102.94999999999995, + "826": 109.65000000000016, + "827": 113.55000000000024, + "828": 108.80000000000001, + "829": 103.44999999999983, + "830": 119.60000000000007, + "831": 116.20000000000003, + "832": 113.49999999999999, + "833": 119.50000000000006, + "834": 97.15000000000008, + "835": 98.99999999999996, + "836": 111.65000000000013, + "837": 110.20000000000013, + "838": 108.74999999999996, + "839": 114.65000000000012, + "840": 25.849999999999994, + "841": 108.05000000000013, + "842": 111.00000000000009, + "843": 107.90000000000018, + "844": 117.85000000000002, + "845": 110.40000000000012, + "846": 105.40000000000002, + "847": 99.85000000000008, + "848": 110.19999999999996, + "849": 113.24999999999996, + "850": 108.00000000000003, + "851": 109.75000000000001, + "852": 113.85000000000008, + "853": 108.79999999999997, + "854": 110.80000000000011, + "855": 116.00000000000007, + "856": 109.15000000000015, + "857": 110.50000000000006, + "858": 110.15000000000006, + "859": 108.40000000000002, + "860": 115.4000000000001, + "861": 112.05000000000004, + "862": 84.90000000000009, + "863": 110.65000000000002, + "864": 114.3500000000001, + "865": 118.80000000000001, + "866": 110.85000000000005, + "867": 106.49999999999996, + "868": 106.59999999999991, + "869": 103.20000000000013, + "870": 114.40000000000005, + "871": 122.30000000000007, + "872": 104.10000000000007, + "873": 115.15000000000016, + "874": 109.95000000000014, + "875": 113.7000000000001, + "876": 106.40000000000015, + "877": 115.30000000000013, + "878": 113.95000000000002, + "879": 112.69999999999999, + "880": 111.65, + "881": 115.15000000000016, + "882": 115.1, + "883": 114.20000000000007, + "884": 113.30000000000021, + "885": 110.70000000000009, + "886": 113.35000000000004, + "887": 111.94999999999999, + "888": 104.15000000000003, + "889": 118.05, + "890": 109.90000000000002, + "891": 117.95000000000006, + "892": 117.10000000000012, + "893": 115.40000000000015, + "894": 110.90000000000006, + "895": 110.74999999999994, + "896": 112.14999999999995, + "897": 110.20000000000005, + "898": 110.45000000000006, + "899": 115.65000000000013, + "900": 114.9000000000001, + "901": 108.89999999999996, + "902": 116.0500000000002, + "903": 114.65000000000003, + "904": 112.55000000000001, + "905": 113.05000000000001, + "906": 113.90000000000005, + "907": 109.95000000000014, + "908": 117.20000000000006, + "909": 111.05000000000014, + "910": 111.30000000000008, + "911": 116.85000000000014, + "912": 119.70000000000006, + "913": 117.45000000000013, + "914": 112.15000000000023, + "915": 113.1500000000001, + "916": 115.45000000000019, + "917": 108.04999999999998, + "918": 109.85000000000007, + "919": 108.50000000000001, + "920": 103.55000000000005, + "921": 113.10000000000022, + "922": 112.19999999999997, + "923": 107.09999999999994, + "924": 102.65, + "925": 110.85000000000012, + "926": 107.40000000000002, + "927": 112.40000000000002, + "928": 115.40000000000002, + "929": 109.85000000000014, + "930": 54.79999999999994, + "931": 108.34999999999994, + "932": 107.65000000000009, + "933": 108.5500000000001, + "934": 99.30000000000007, + "935": 118.10000000000014, + "936": 108.35000000000002, + "937": 106.90000000000015, + "938": 112.35000000000018, + "939": 101.5000000000001, + "940": 111.25000000000007, + "941": 113.30000000000011, + "942": 117.8500000000001, + "943": 116.30000000000018, + "944": 105.89999999999986, + "945": 112.85000000000007, + "946": 107.20000000000009, + "947": 108.00000000000013, + "948": 111.25000000000011, + "949": 106.65000000000005, + "950": 110.90000000000016, + "951": 109.60000000000007, + "952": 119.00000000000014, + "953": 114.35000000000004, + "954": 115.00000000000031, + "955": 106.55000000000005, + "956": 111.35000000000002, + "957": 111.85000000000008, + "958": 114.3500000000002, + "959": 114.25000000000006, + "960": 109.44999999999999, + "961": 109.15000000000003, + "962": 118.45000000000003, + "963": 108.50000000000017, + "964": 105.45000000000005, + "965": 113.95000000000013, + "966": 107.55000000000004, + "967": 111.25000000000007, + "968": 101.80000000000015, + "969": 109.99999999999997, + "970": 110.45000000000012, + "971": 110.7500000000001, + "972": 99.64999999999985, + "973": 104.50000000000006, + "974": 111.65000000000009, + "975": 112.9000000000001, + "976": 102.69999999999995, + "977": 108.34999999999994, + "978": 103.45000000000003, + "979": 104.8500000000002, + "980": 115.65, + "981": 105.25000000000001, + "982": 109.30000000000011, + "983": 106.49999999999996, + "984": 90.30000000000004, + "985": 111.20000000000005, + "986": 114.80000000000007, + "987": 116.50000000000004, + "988": 115.1000000000001, + "989": 108.54999999999998, + "990": 111.50000000000011, + "991": 109.10000000000011, + "992": 111.10000000000018, + "993": 105.65, + "994": 111.40000000000012, + "995": 108.1000000000001, + "996": 113.80000000000015, + "997": 112.3000000000001, + "998": 112.35000000000011, + "999": 110.30000000000007, + "1000": 118.05000000000011 + } +} \ No newline at end of file diff --git a/benchmark/results/v3/v3.1.0/session_metadata/3.json b/benchmark/results/v3/v3.1.0/session_metadata/3.json new file mode 100644 index 00000000..4533d3dd --- /dev/null +++ b/benchmark/results/v3/v3.1.0/session_metadata/3.json @@ -0,0 +1,1009 @@ +{ + "total_episodes": 1001, + "total_time_steps": 128000, + "total_s": 1597.651535, + "s_per_step": 0.04992661046875, + "s_per_100_steps_10_nodes": 4.992661046875, + "total_reward_per_episode": { + "1": -56.35000000000008, + "2": -16.69999999999997, + "3": -68.30000000000007, + "4": -55.55000000000008, + "5": -26.899999999999995, + "6": -33.05000000000004, + "7": -15.299999999999981, + "8": -18.999999999999964, + "9": -85.54999999999984, + "10": -15.699999999999974, + "11": -47.25000000000006, + "12": -47.75000000000001, + "13": -105.9, + "14": -23.599999999999948, + "15": -21.799999999999955, + "16": -35.24999999999999, + "17": -39.45000000000013, + "18": -11.3, + "19": -10.65, + "20": -15.949999999999976, + "21": -4.799999999999984, + "22": -23.69999999999995, + "23": 1.0000000000000446, + "24": -16.79999999999997, + "25": -5.8499999999999845, + "26": -28.649999999999963, + "27": -3.1999999999999753, + "28": -16.049999999999983, + "29": -30.549999999999944, + "30": -28.699999999999996, + "31": -19.04999999999997, + "32": -62.650000000000105, + "33": -11.199999999999985, + "34": -0.600000000000001, + "35": -16.04999999999998, + "36": -17.399999999999974, + "37": -21.049999999999958, + "38": -20.54999999999996, + "39": -18.849999999999966, + "40": -31.100000000000023, + "41": -13.39999999999999, + "42": -16.399999999999977, + "43": -19.54999999999997, + "44": -70.65000000000005, + "45": -23.19999999999995, + "46": -21.749999999999957, + "47": -99.5, + "48": -15.149999999999975, + "49": -22.750000000000007, + "50": -19.449999999999964, + "51": -19.599999999999966, + "52": -25.19999999999994, + "53": -94.59999999999997, + "54": -90.89999999999999, + "55": -15.599999999999964, + "56": -10.050000000000008, + "57": -47.40000000000007, + "58": -17.49999999999997, + "59": -36.050000000000104, + "60": -22.799999999999955, + "61": -4.29999999999998, + "62": -18.84999999999997, + "63": -27.49999999999995, + "64": -1.3499999999999772, + "65": -19.699999999999964, + "66": -41.450000000000024, + "67": -12.09999999999998, + "68": -19.599999999999966, + "69": -13.499999999999988, + "70": -22.249999999999954, + "71": 12.100000000000009, + "72": -20.149999999999963, + "73": -17.44999999999996, + "74": -17.099999999999973, + "75": -11.449999999999989, + "76": -18.699999999999978, + "77": -19.949999999999964, + "78": -8.899999999999991, + "79": -33.45000000000001, + "80": -15.299999999999978, + "81": -5.699999999999976, + "82": -87.80000000000001, + "83": -12.199999999999996, + "84": -99.44999999999999, + "85": 14.650000000000052, + "86": -9.099999999999998, + "87": -14.099999999999985, + "88": -13.89999999999999, + "89": -96.1, + "90": 3.0000000000000275, + "91": -4.049999999999979, + "92": -11.299999999999985, + "93": -19.549999999999965, + "94": -51.95000000000009, + "95": -14.199999999999982, + "96": -6.999999999999993, + "97": -9.999999999999993, + "98": 5.100000000000041, + "99": -27.149999999999963, + "100": -12.899999999999979, + "101": 18.000000000000004, + "102": -81.50000000000006, + "103": -53.50000000000008, + "104": -85.05, + "105": -20.59999999999996, + "106": -16.199999999999974, + "107": -20.749999999999957, + "108": 22.349999999999966, + "109": -20.299999999999965, + "110": -74.4, + "111": -4.849999999999994, + "112": 1.1500000000000503, + "113": 32.7499999999998, + "114": -76.44999999999997, + "115": -19.59999999999996, + "116": -13.699999999999994, + "117": -61.00000000000003, + "118": -82.14999999999996, + "119": 2.9000000000000217, + "120": -19.099999999999977, + "121": -10.450000000000001, + "122": 11.900000000000006, + "123": -31.649999999999967, + "124": -7.05, + "125": -61.65000000000004, + "126": -52.599999999999994, + "127": 14.450000000000024, + "128": -16.299999999999976, + "129": 0.2000000000000306, + "130": -75.35000000000002, + "131": -0.9999999999999869, + "132": -41.94999999999999, + "133": -0.099999999999975, + "134": -76.6, + "135": 19.799999999999997, + "136": -21.249999999999957, + "137": -84.5, + "138": -8.699999999999992, + "139": 16.400000000000055, + "140": -43.89999999999998, + "141": -23.549999999999947, + "142": -21.699999999999957, + "143": -96.1, + "144": -8.749999999999998, + "145": -1.099999999999996, + "146": 0.3500000000000114, + "147": 19.549999999999972, + "148": -6.300000000000003, + "149": -80.99999999999997, + "150": -90.60000000000001, + "151": -6.799999999999982, + "152": -5.949999999999982, + "153": -1.9499999999999629, + "154": 20.149999999999935, + "155": 26.65, + "156": -69.44999999999997, + "157": 14.35000000000004, + "158": -17.549999999999976, + "159": -18.449999999999967, + "160": -17.249999999999975, + "161": -14.299999999999969, + "162": -11.149999999999986, + "163": -79.35, + "164": -15.149999999999988, + "165": -77.25, + "166": 2.4499999999999957, + "167": -13.699999999999976, + "168": -85.0, + "169": -6.999999999999998, + "170": 21.34999999999995, + "171": -92.5, + "172": -12.649999999999983, + "173": -5.999999999999974, + "174": 20.55, + "175": -73.64999999999993, + "176": 42.449999999999804, + "177": 12.899999999999999, + "178": -65.25000000000007, + "179": -17.999999999999975, + "180": -52.80000000000008, + "181": -73.55000000000001, + "182": 47.14999999999987, + "183": -50.60000000000009, + "184": -84.80000000000001, + "185": -60.59999999999998, + "186": -51.54999999999996, + "187": -0.25000000000000977, + "188": -12.449999999999998, + "189": -3.94999999999998, + "190": 4.350000000000004, + "191": 36.04999999999978, + "192": -81.5, + "193": 8.850000000000076, + "194": -35.29999999999999, + "195": 14.600000000000005, + "196": -21.34999999999996, + "197": -92.85, + "198": 40.999999999999744, + "199": -102.6, + "200": 6.700000000000043, + "201": -17.099999999999973, + "202": -60.9, + "203": -10.100000000000017, + "204": -9.04999999999999, + "205": 19.999999999999943, + "206": -84.59999999999997, + "207": -14.29999999999994, + "208": 21.699999999999974, + "209": -10.549999999999992, + "210": -0.9499999999999902, + "211": -71.80000000000003, + "212": 71.4, + "213": -29.999999999999993, + "214": 21.949999999999935, + "215": -1.1499999999999844, + "216": -74.6, + "217": 3.3000000000000043, + "218": 5.600000000000062, + "219": -15.699999999999982, + "220": -47.19999999999999, + "221": 0.8000000000000482, + "222": -70.55000000000003, + "223": -63.250000000000014, + "224": -19.099999999999994, + "225": 40.39999999999979, + "226": -94.19999999999996, + "227": -20.35, + "228": 15.600000000000094, + "229": -70.25, + "230": 82.40000000000005, + "231": 21.899999999999938, + "232": -56.50000000000004, + "233": -8.999999999999991, + "234": 12.550000000000058, + "235": 2.750000000000033, + "236": 9.399999999999938, + "237": -8.450000000000017, + "238": -49.150000000000006, + "239": -8.500000000000027, + "240": -56.89999999999999, + "241": 0.7499999999999989, + "242": -0.6999999999999784, + "243": -41.89999999999998, + "244": -91.6, + "245": 40.79999999999988, + "246": -9.949999999999987, + "247": -14.099999999999984, + "248": 8.300000000000026, + "249": -18.049999999999972, + "250": -73.04999999999998, + "251": -93.50000000000006, + "252": 3.300000000000035, + "253": -19.399999999999967, + "254": -64.70000000000003, + "255": -23.150000000000002, + "256": -16.59999999999998, + "257": -20.39999999999998, + "258": 42.799999999999784, + "259": 3.049999999999982, + "260": -69.55000000000001, + "261": -9.399999999999995, + "262": -2.3999999999999897, + "263": 0.6500000000000241, + "264": -9.750000000000044, + "265": 53.7999999999999, + "266": 0.3500000000000505, + "267": -69.49999999999999, + "268": -11.499999999999995, + "269": -69.19999999999997, + "270": 40.09999999999976, + "271": -75.04999999999995, + "272": 15.450000000000028, + "273": -85.94999999999999, + "274": 16.099999999999937, + "275": -13.199999999999989, + "276": 33.49999999999981, + "277": -79.65, + "278": -11.900000000000007, + "279": 65.29999999999998, + "280": 14.550000000000079, + "281": -74.00000000000001, + "282": 49.09999999999979, + "283": -22.349999999999994, + "284": -15.54999999999996, + "285": -9.499999999999995, + "286": -78.05000000000001, + "287": -10.34999999999999, + "288": 0.8500000000000418, + "289": -2.5500000000000176, + "290": -54.19999999999996, + "291": 7.650000000000061, + "292": -21.200000000000006, + "293": -67.25, + "294": -24.299999999999972, + "295": -21.600000000000012, + "296": -13.59999999999999, + "297": 3.750000000000041, + "298": -80.85, + "299": -2.800000000000021, + "300": 21.749999999999957, + "301": -9.450000000000031, + "302": -9.050000000000004, + "303": 18.900000000000002, + "304": -5.199999999999986, + "305": 12.549999999999995, + "306": 3.099999999999995, + "307": 8.35000000000002, + "308": -9.350000000000001, + "309": 18.500000000000018, + "310": -37.35000000000003, + "311": 30.049999999999947, + "312": -40.400000000000034, + "313": -69.89999999999999, + "314": -2.6999999999999176, + "315": -64.79999999999993, + "316": -49.350000000000016, + "317": 66.44999999999993, + "318": 103.95000000000017, + "319": 52.04999999999989, + "320": 90.85000000000022, + "321": 41.24999999999989, + "322": 0.5999999999999952, + "323": -6.849999999999985, + "324": -12.85000000000003, + "325": -13.150000000000034, + "326": -39.550000000000054, + "327": 59.899999999999835, + "328": 10.150000000000011, + "329": -4.650000000000022, + "330": 19.349999999999994, + "331": 91.60000000000015, + "332": 1.9500000000000075, + "333": -17.099999999999977, + "334": 33.149999999999956, + "335": -69.75000000000001, + "336": 33.69999999999994, + "337": -18.650000000000002, + "338": 63.049999999999976, + "339": -29.75000000000002, + "340": 14.05000000000004, + "341": 27.499999999999954, + "342": -10.450000000000005, + "343": 67.04999999999976, + "344": -78.64999999999999, + "345": 5.2500000000000195, + "346": -58.349999999999916, + "347": 23.44999999999997, + "348": 65.74999999999987, + "349": 63.75000000000005, + "350": -10.250000000000004, + "351": 81.09999999999995, + "352": 76.85000000000014, + "353": 24.599999999999998, + "354": 72.95000000000006, + "355": 45.94999999999999, + "356": 78.95000000000007, + "357": 108.10000000000014, + "358": 45.19999999999994, + "359": 107.55000000000021, + "360": -15.000000000000012, + "361": 44.899999999999885, + "362": 22.849999999999923, + "363": 106.75000000000024, + "364": -34.54999999999997, + "365": 112.10000000000024, + "366": 89.85000000000012, + "367": 82.30000000000007, + "368": 95.04999999999995, + "369": 65.39999999999993, + "370": 39.049999999999955, + "371": 57.99999999999983, + "372": 84.70000000000006, + "373": 34.74999999999996, + "374": 88.10000000000001, + "375": 64.79999999999993, + "376": 66.2499999999998, + "377": 60.19999999999985, + "378": 13.750000000000068, + "379": 30.449999999999974, + "380": -20.35000000000001, + "381": 77.84999999999995, + "382": 24.40000000000001, + "383": 113.7500000000003, + "384": 72.55000000000007, + "385": 0.20000000000001217, + "386": 47.29999999999996, + "387": 74.04999999999987, + "388": 33.89999999999996, + "389": -6.949999999999993, + "390": 87.45000000000007, + "391": 115.05000000000025, + "392": 97.15000000000018, + "393": 74.95000000000007, + "394": 107.95, + "395": 84.79999999999997, + "396": 86.60000000000025, + "397": 93.40000000000005, + "398": 99.0000000000002, + "399": 3.8499999999999814, + "400": 109.70000000000022, + "401": 78.29999999999994, + "402": 87.59999999999995, + "403": 66.04999999999995, + "404": 39.999999999999964, + "405": 112.00000000000024, + "406": -8.249999999999986, + "407": 48.7499999999999, + "408": 47.79999999999987, + "409": 107.65000000000018, + "410": 104.10000000000021, + "411": 84.59999999999998, + "412": 108.05000000000004, + "413": 62.24999999999991, + "414": 82.50000000000017, + "415": 108.85000000000016, + "416": 113.3000000000001, + "417": 114.5500000000002, + "418": 46.44999999999994, + "419": 36.6, + "420": 81.6, + "421": 77.95000000000003, + "422": 91.30000000000008, + "423": 64.84999999999994, + "424": 106.90000000000016, + "425": 93.6000000000001, + "426": 100.95000000000024, + "427": 44.69999999999999, + "428": 111.40000000000026, + "429": 115.55000000000025, + "430": 99.8500000000001, + "431": 45.34999999999979, + "432": 112.60000000000025, + "433": -61.549999999999955, + "434": 96.6500000000001, + "435": 108.45000000000023, + "436": -8.34999999999999, + "437": 14.999999999999948, + "438": 94.8000000000001, + "439": 101.75000000000017, + "440": 88.8000000000001, + "441": 119.90000000000009, + "442": 86.30000000000004, + "443": 91.54999999999978, + "444": 88.09999999999981, + "445": 112.70000000000017, + "446": 62.79999999999996, + "447": 101.40000000000016, + "448": 111.75000000000007, + "449": 112.05000000000003, + "450": 99.65000000000026, + "451": 116.00000000000024, + "452": 105.40000000000019, + "453": 28.09999999999999, + "454": 81.7500000000002, + "455": 103.85000000000024, + "456": 114.50000000000027, + "457": 92.29999999999997, + "458": 117.25000000000028, + "459": 100.80000000000017, + "460": 109.95000000000023, + "461": 112.05000000000014, + "462": 88.20000000000014, + "463": 68.54999999999987, + "464": 68.09999999999977, + "465": 67.34999999999994, + "466": 25.299999999999976, + "467": 27.349999999999923, + "468": 111.40000000000012, + "469": 67.79999999999994, + "470": 118.05000000000027, + "471": -3.75000000000003, + "472": 114.45000000000026, + "473": 120.00000000000028, + "474": 91.50000000000007, + "475": 103.6999999999999, + "476": 60.89999999999992, + "477": 111.75000000000023, + "478": 66.94999999999999, + "479": 98.74999999999991, + "480": 119.40000000000028, + "481": 97.0, + "482": 117.0500000000003, + "483": 116.9500000000002, + "484": 117.20000000000024, + "485": 93.94999999999997, + "486": 106.90000000000008, + "487": 99.0500000000001, + "488": 111.65000000000002, + "489": 83.75000000000009, + "490": 2.750000000000017, + "491": 99.65000000000012, + "492": 96.10000000000012, + "493": 32.24999999999996, + "494": 85.90000000000006, + "495": 95.60000000000004, + "496": 119.75000000000017, + "497": 88.39999999999985, + "498": 114.85000000000016, + "499": 42.09999999999992, + "500": 103.95000000000027, + "501": 95.15000000000005, + "502": 81.95000000000002, + "503": 80.30000000000011, + "504": 96.65000000000012, + "505": 116.15000000000006, + "506": 110.75000000000021, + "507": 95.84999999999998, + "508": 54.99999999999988, + "509": 106.35000000000007, + "510": 115.80000000000025, + "511": 101.69999999999982, + "512": 99.55000000000011, + "513": -71.49999999999989, + "514": 101.95000000000007, + "515": 81.44999999999996, + "516": 97.45000000000007, + "517": 109.90000000000002, + "518": 119.9, + "519": 89.9000000000001, + "520": 113.85000000000025, + "521": 78.19999999999987, + "522": 98.0000000000001, + "523": 98.65000000000009, + "524": 107.24999999999999, + "525": 81.45000000000007, + "526": 71.0499999999999, + "527": 93.5500000000002, + "528": 49.149999999999885, + "529": 114.60000000000014, + "530": 115.45000000000002, + "531": 113.15000000000018, + "532": 81.90000000000003, + "533": 88.15, + "534": 102.15000000000005, + "535": 98.95000000000022, + "536": 104.30000000000018, + "537": 106.00000000000003, + "538": 115.95000000000012, + "539": 115.05000000000027, + "540": 109.85000000000001, + "541": 108.7000000000001, + "542": 86.70000000000002, + "543": 49.29999999999997, + "544": 81.99999999999999, + "545": 79.9, + "546": 104.7, + "547": 100.75000000000011, + "548": 105.69999999999999, + "549": 92.05000000000011, + "550": 64.29999999999988, + "551": 83.25000000000003, + "552": 111.00000000000016, + "553": 115.20000000000026, + "554": -21.750000000000014, + "555": 116.20000000000016, + "556": 96.80000000000005, + "557": 113.20000000000005, + "558": 112.70000000000007, + "559": 122.35000000000007, + "560": 109.6, + "561": 109.7000000000001, + "562": 111.85000000000002, + "563": 94.5500000000002, + "564": 109.4000000000002, + "565": 93.10000000000005, + "566": 77.35000000000001, + "567": 103.7500000000001, + "568": 94.04999999999991, + "569": 98.55000000000008, + "570": 108.10000000000001, + "571": 111.35000000000001, + "572": 113.85000000000007, + "573": 110.4000000000001, + "574": 105.74999999999996, + "575": 105.39999999999988, + "576": 107.3999999999999, + "577": 95.50000000000004, + "578": 114.90000000000026, + "579": 87.65000000000006, + "580": 116.75000000000003, + "581": 122.55000000000003, + "582": 105.95000000000003, + "583": 108.00000000000016, + "584": 110.25000000000016, + "585": 90.95000000000009, + "586": 116.4000000000002, + "587": 111.6000000000001, + "588": 108.30000000000004, + "589": 88.84999999999995, + "590": 100.2500000000001, + "591": 109.75000000000004, + "592": 109.95000000000006, + "593": 93.50000000000013, + "594": 116.70000000000009, + "595": 113.00000000000007, + "596": 91.30000000000015, + "597": 106.50000000000003, + "598": 94.50000000000003, + "599": 117.8500000000002, + "600": 114.50000000000003, + "601": 103.90000000000002, + "602": 101.80000000000013, + "603": 99.30000000000007, + "604": 116.80000000000015, + "605": 115.70000000000003, + "606": 113.5, + "607": 105.25000000000013, + "608": 108.65, + "609": 105.94999999999997, + "610": 103.65, + "611": 111.40000000000023, + "612": 112.89999999999998, + "613": 98.60000000000001, + "614": 91.74999999999996, + "615": 114.5000000000001, + "616": 91.54999999999994, + "617": 95.00000000000011, + "618": 74.99999999999986, + "619": 110.00000000000011, + "620": 112.25000000000013, + "621": 108.05000000000011, + "622": 116.80000000000003, + "623": 92.35000000000011, + "624": 108.69999999999995, + "625": 109.8000000000001, + "626": 101.1, + "627": 103.49999999999996, + "628": 54.04999999999981, + "629": 95.85, + "630": 114.30000000000017, + "631": 93.10000000000015, + "632": 90.60000000000016, + "633": 72.44999999999986, + "634": 115.69999999999996, + "635": 73.34999999999987, + "636": 121.45000000000007, + "637": 89.75, + "638": 79.55000000000004, + "639": 110.19999999999997, + "640": 108.50000000000004, + "641": 114.95000000000005, + "642": 107.25000000000003, + "643": 121.95000000000003, + "644": 118.90000000000012, + "645": 115.35, + "646": 102.3500000000001, + "647": 113.00000000000014, + "648": 103.65000000000003, + "649": 118.55000000000005, + "650": 108.55000000000008, + "651": 120.95, + "652": 101.50000000000018, + "653": 109.60000000000016, + "654": 115.90000000000005, + "655": 106.50000000000001, + "656": 114.40000000000006, + "657": 101.94999999999996, + "658": 116.50000000000013, + "659": 119.05000000000004, + "660": 99.15000000000003, + "661": 51.64999999999985, + "662": 102.20000000000006, + "663": 103.09999999999995, + "664": 112.70000000000016, + "665": 106.75000000000001, + "666": 112.20000000000006, + "667": 108.5, + "668": 102.99999999999999, + "669": 115.70000000000012, + "670": 107.15000000000006, + "671": 98.25000000000001, + "672": 118.05000000000017, + "673": 112.70000000000012, + "674": 109.1000000000001, + "675": 117.05, + "676": 107.35000000000007, + "677": 108.10000000000008, + "678": 104.10000000000001, + "679": 100.0000000000001, + "680": 91.24999999999996, + "681": 107.65000000000003, + "682": 114.10000000000002, + "683": 115.25000000000004, + "684": 108.94999999999996, + "685": 120.94999999999997, + "686": 88.65000000000002, + "687": 103.35000000000002, + "688": 109.75000000000013, + "689": 112.30000000000013, + "690": 112.30000000000015, + "691": 117.65000000000008, + "692": 114.3000000000001, + "693": 111.05000000000025, + "694": 112.80000000000017, + "695": 112.15, + "696": 111.34999999999995, + "697": 111.95000000000005, + "698": 113.60000000000004, + "699": 108.05000000000011, + "700": 118.95000000000003, + "701": 110.10000000000014, + "702": 118.25000000000016, + "703": 109.75000000000009, + "704": 110.35000000000005, + "705": 108.95000000000006, + "706": 104.15000000000006, + "707": 116.25, + "708": 109.10000000000021, + "709": 115.8, + "710": 111.50000000000017, + "711": 118.20000000000013, + "712": 114.70000000000003, + "713": 115.30000000000014, + "714": 114.00000000000007, + "715": 100.19999999999995, + "716": 108.15000000000015, + "717": 111.00000000000021, + "718": 99.05000000000001, + "719": 110.84999999999998, + "720": 121.30000000000004, + "721": 112.10000000000007, + "722": 110.15000000000002, + "723": 98.00000000000007, + "724": 116.25000000000006, + "725": 99.55000000000005, + "726": 116.10000000000008, + "727": 112.10000000000008, + "728": 103.80000000000011, + "729": 109.30000000000008, + "730": 100.40000000000005, + "731": 101.14999999999996, + "732": -2.499999999999968, + "733": 114.30000000000017, + "734": 110.45, + "735": 113.00000000000023, + "736": 117.05000000000015, + "737": 109.20000000000007, + "738": 65.09999999999992, + "739": 114.85000000000014, + "740": 110.0, + "741": 110.4500000000001, + "742": 114.45000000000012, + "743": 112.2000000000001, + "744": 107.30000000000017, + "745": 109.05000000000005, + "746": 111.10000000000001, + "747": 116.25000000000023, + "748": 108.75, + "749": 95.89999999999999, + "750": 112.05000000000004, + "751": 111.60000000000005, + "752": 111.3500000000001, + "753": 111.90000000000009, + "754": 105.60000000000007, + "755": 104.59999999999998, + "756": 115.75000000000017, + "757": 114.20000000000007, + "758": 117.85000000000005, + "759": 119.05000000000003, + "760": 107.65000000000003, + "761": 106.8500000000002, + "762": 107.19999999999995, + "763": 114.60000000000002, + "764": 102.80000000000004, + "765": 111.55000000000005, + "766": 82.74999999999999, + "767": 104.5500000000001, + "768": 114.85000000000008, + "769": 115.00000000000009, + "770": 109.79999999999995, + "771": 113.95000000000005, + "772": 51.149999999999814, + "773": 103.64999999999998, + "774": 103.55000000000011, + "775": 117.65000000000005, + "776": 111.3999999999999, + "777": 112.40000000000009, + "778": 113.6500000000001, + "779": 124.85000000000012, + "780": 112.75000000000014, + "781": 106.2500000000001, + "782": 121.00000000000003, + "783": 114.15, + "784": 112.60000000000004, + "785": 108.85000000000015, + "786": 107.85000000000008, + "787": 115.40000000000009, + "788": 114.30000000000008, + "789": 119.55000000000007, + "790": 113.69999999999997, + "791": 108.05000000000018, + "792": 109.55000000000011, + "793": 112.0000000000002, + "794": 112.25000000000009, + "795": 111.75000000000017, + "796": 106.49999999999996, + "797": 104.55000000000004, + "798": 119.15000000000002, + "799": 113.50000000000016, + "800": 112.0500000000001, + "801": 109.1000000000001, + "802": 112.59999999999998, + "803": 114.30000000000018, + "804": 114.85000000000001, + "805": 113.35000000000005, + "806": 108.30000000000015, + "807": 116.75000000000009, + "808": 112.84999999999997, + "809": 117.94999999999999, + "810": 111.49999999999999, + "811": 112.24999999999997, + "812": 115.2500000000001, + "813": 110.05000000000003, + "814": 117.55000000000014, + "815": 101.80000000000001, + "816": 107.49999999999996, + "817": 109.49999999999993, + "818": 109.24999999999999, + "819": 111.25000000000004, + "820": 106.60000000000008, + "821": 106.20000000000009, + "822": 105.74999999999999, + "823": 98.6000000000001, + "824": 109.60000000000005, + "825": 114.70000000000005, + "826": 99.55000000000005, + "827": 112.2500000000001, + "828": 111.4000000000002, + "829": 91.00000000000004, + "830": 108.55000000000004, + "831": 113.35000000000018, + "832": 118.69999999999999, + "833": 113.85000000000004, + "834": 105.55000000000008, + "835": 113.1500000000001, + "836": 114.34999999999994, + "837": 97.65000000000005, + "838": 116.75000000000003, + "839": 110.55000000000013, + "840": 116.25000000000021, + "841": 103.20000000000007, + "842": 120.94999999999999, + "843": 112.00000000000013, + "844": 99.30000000000008, + "845": 116.00000000000024, + "846": 110.2500000000001, + "847": 102.95000000000005, + "848": 110.00000000000003, + "849": 110.15000000000012, + "850": 112.40000000000013, + "851": 111.50000000000016, + "852": 106.74999999999991, + "853": 119.45000000000006, + "854": 85.55000000000007, + "855": 116.85000000000014, + "856": 107.8, + "857": 108.1499999999999, + "858": 106.89999999999988, + "859": 102.8499999999999, + "860": 109.90000000000018, + "861": 114.00000000000003, + "862": 102.84999999999992, + "863": 114.9000000000001, + "864": 114.74999999999994, + "865": 111.85000000000008, + "866": 108.00000000000006, + "867": 110.55000000000001, + "868": 116.59999999999995, + "869": 113.55000000000022, + "870": 118.90000000000006, + "871": 112.75000000000001, + "872": 116.25, + "873": 107.60000000000002, + "874": 114.90000000000008, + "875": 116.45000000000009, + "876": 109.90000000000008, + "877": 108.90000000000013, + "878": 118.80000000000014, + "879": 102.80000000000008, + "880": 116.10000000000004, + "881": 106.45000000000014, + "882": 77.75, + "883": 109.25000000000014, + "884": 106.30000000000011, + "885": 113.00000000000011, + "886": 112.90000000000009, + "887": 115.80000000000003, + "888": 107.15000000000006, + "889": 112.20000000000009, + "890": 111.55000000000013, + "891": 117.10000000000014, + "892": 111.95000000000002, + "893": 92.45000000000005, + "894": 108.84999999999992, + "895": 98.10000000000007, + "896": 116.20000000000009, + "897": 106.44999999999999, + "898": 103.00000000000014, + "899": 105.69999999999995, + "900": 112.05000000000001, + "901": 110.49999999999999, + "902": 104.89999999999999, + "903": 119.3000000000001, + "904": 115.4000000000002, + "905": 106.50000000000014, + "906": 105.60000000000016, + "907": 110.35000000000004, + "908": 114.90000000000005, + "909": 116.80000000000018, + "910": 112.30000000000003, + "911": 115.25000000000003, + "912": 116.60000000000011, + "913": 108.65000000000006, + "914": 106.75000000000016, + "915": 112.25000000000001, + "916": 107.45000000000022, + "917": 112.0, + "918": 109.34999999999995, + "919": 109.15000000000013, + "920": 118.65000000000013, + "921": 104.80000000000013, + "922": 108.24999999999991, + "923": 110.30000000000013, + "924": 107.45000000000009, + "925": 110.90000000000006, + "926": 104.55000000000004, + "927": 109.00000000000013, + "928": 122.10000000000014, + "929": 116.9, + "930": 117.35000000000004, + "931": 110.90000000000012, + "932": 109.80000000000013, + "933": 113.55000000000003, + "934": 113.7500000000001, + "935": 107.30000000000004, + "936": 113.10000000000007, + "937": 109.65000000000016, + "938": 111.80000000000008, + "939": 108.40000000000018, + "940": 115.15000000000015, + "941": 109.40000000000009, + "942": 112.4, + "943": 111.64999999999996, + "944": 103.94999999999996, + "945": 103.00000000000007, + "946": 106.55000000000008, + "947": 118.5500000000001, + "948": 118.05000000000022, + "949": 108.85000000000012, + "950": 69.24999999999997, + "951": 118.3, + "952": 106.74999999999993, + "953": 112.00000000000018, + "954": 93.65000000000003, + "955": 109.60000000000024, + "956": 110.80000000000014, + "957": 102.65000000000003, + "958": 104.24999999999996, + "959": 109.6, + "960": 115.80000000000011, + "961": 102.69999999999995, + "962": 112.65000000000006, + "963": 106.04999999999991, + "964": 117.90000000000002, + "965": 116.30000000000007, + "966": 113.70000000000007, + "967": 110.55000000000008, + "968": 107.75000000000004, + "969": 111.1, + "970": 104.84999999999988, + "971": 108.7500000000001, + "972": 107.75000000000004, + "973": 116.75000000000004, + "974": 117.50000000000006, + "975": 111.10000000000016, + "976": 105.90000000000006, + "977": 105.80000000000008, + "978": 113.45000000000009, + "979": 107.90000000000009, + "980": 110.74999999999994, + "981": 111.8500000000001, + "982": 117.55000000000004, + "983": 113.90000000000009, + "984": 103.55000000000005, + "985": 113.84999999999998, + "986": 104.8500000000001, + "987": 114.15000000000022, + "988": 112.00000000000007, + "989": 109.10000000000008, + "990": 111.49999999999996, + "991": 112.90000000000009, + "992": 69.09999999999988, + "993": 106.49999999999999, + "994": 111.00000000000016, + "995": 40.449999999999946, + "996": 104.59999999999994, + "997": 117.10000000000007, + "998": 107.10000000000012, + "999": 118.44999999999996, + "1000": 108.20000000000029 + } +} \ No newline at end of file diff --git a/benchmark/results/v3/v3.1.0/session_metadata/4.json b/benchmark/results/v3/v3.1.0/session_metadata/4.json new file mode 100644 index 00000000..73288114 --- /dev/null +++ b/benchmark/results/v3/v3.1.0/session_metadata/4.json @@ -0,0 +1,1009 @@ +{ + "total_episodes": 1001, + "total_time_steps": 128000, + "total_s": 1759.704562, + "s_per_step": 0.054990767562499994, + "s_per_100_steps_10_nodes": 5.49907675625, + "total_reward_per_episode": { + "1": -51.95000000000008, + "2": -19.94999999999998, + "3": -60.0500000000001, + "4": -56.90000000000009, + "5": -27.900000000000013, + "6": -40.25000000000004, + "7": -28.29999999999997, + "8": -49.30000000000007, + "9": -58.75000000000002, + "10": -74.15, + "11": -22.249999999999947, + "12": -25.399999999999952, + "13": -28.19999999999998, + "14": -45.250000000000014, + "15": -21.649999999999988, + "16": -56.80000000000011, + "17": -69.20000000000006, + "18": -19.99999999999996, + "19": -59.75000000000009, + "20": -53.40000000000016, + "21": -42.35000000000004, + "22": -11.699999999999989, + "23": -23.599999999999948, + "24": -35.45000000000003, + "25": -20.59999999999996, + "26": -55.55000000000008, + "27": -27.099999999999955, + "28": -44.400000000000055, + "29": -46.90000000000016, + "30": -56.300000000000125, + "31": -95.0, + "32": -107.35, + "33": -16.699999999999985, + "34": -16.599999999999977, + "35": -25.350000000000012, + "36": -72.94999999999999, + "37": -30.400000000000016, + "38": -10.649999999999983, + "39": -21.599999999999955, + "40": -17.499999999999975, + "41": -13.349999999999977, + "42": -27.249999999999932, + "43": -16.899999999999974, + "44": -66.54999999999997, + "45": -6.950000000000002, + "46": -18.34999999999997, + "47": -44.0000000000001, + "48": -41.95000000000005, + "49": -20.84999999999996, + "50": -17.249999999999968, + "51": -18.699999999999967, + "52": -4.899999999999997, + "53": -14.29999999999999, + "54": -75.94999999999997, + "55": -13.899999999999986, + "56": -18.09999999999995, + "57": -6.899999999999999, + "58": -22.79999999999995, + "59": -6.249999999999991, + "60": -12.749999999999973, + "61": -19.099999999999966, + "62": -19.499999999999964, + "63": -10.199999999999992, + "64": 15.55000000000003, + "65": -21.050000000000026, + "66": -16.099999999999977, + "67": -11.350000000000003, + "68": -21.949999999999957, + "69": -13.949999999999994, + "70": -22.449999999999953, + "71": -37.6000000000001, + "72": -16.449999999999978, + "73": -21.999999999999954, + "74": 13.299999999999997, + "75": -10.349999999999982, + "76": -20.44999999999996, + "77": -18.049999999999958, + "78": -87.3, + "79": -9.549999999999986, + "80": 2.2000000000000144, + "81": -13.399999999999986, + "82": -9.300000000000002, + "83": 7.800000000000039, + "84": -9.499999999999995, + "85": -1.7999999999999956, + "86": -19.79999999999996, + "87": -18.999999999999964, + "88": -28.300000000000026, + "89": -11.049999999999988, + "90": -3.599999999999988, + "91": -57.05000000000006, + "92": -21.349999999999955, + "93": -8.3, + "94": -33.24999999999998, + "95": -16.949999999999964, + "96": -1.9999999999999973, + "97": -96.30000000000001, + "98": 7.90000000000003, + "99": -71.85, + "100": 1.600000000000041, + "101": -7.950000000000026, + "102": -17.84999999999997, + "103": -15.999999999999973, + "104": -8.199999999999994, + "105": 9.75000000000005, + "106": 7.000000000000074, + "107": -1.499999999999996, + "108": -11.699999999999985, + "109": -30.049999999999986, + "110": -17.549999999999972, + "111": 20.25000000000002, + "112": -23.79999999999997, + "113": 52.849999999999866, + "114": -90.39999999999995, + "115": -12.499999999999982, + "116": 30.199999999999832, + "117": 15.149999999999949, + "118": -50.39999999999998, + "119": 4.150000000000036, + "120": 12.500000000000025, + "121": 19.149999999999984, + "122": 3.199999999999987, + "123": -13.499999999999984, + "124": -10.999999999999993, + "125": -33.90000000000001, + "126": -80.6, + "127": 7.450000000000011, + "128": -15.549999999999962, + "129": 22.699999999999864, + "130": -96.25, + "131": 21.39999999999999, + "132": -6.499999999999986, + "133": 49.249999999999815, + "134": -18.89999999999996, + "135": 19.49999999999998, + "136": -19.099999999999966, + "137": 9.350000000000058, + "138": 12.300000000000008, + "139": 14.60000000000002, + "140": -11.899999999999993, + "141": -25.400000000000027, + "142": -11.64999999999999, + "143": 35.34999999999992, + "144": 7.05000000000006, + "145": 1.2499999999999956, + "146": -8.749999999999988, + "147": -74.20000000000002, + "148": -34.350000000000044, + "149": -8.999999999999975, + "150": -79.3, + "151": 11.850000000000076, + "152": -18.09999999999997, + "153": 9.200000000000069, + "154": -19.79999999999996, + "155": -73.19999999999999, + "156": -82.35000000000002, + "157": -8.350000000000007, + "158": -22.799999999999958, + "159": 82.0999999999999, + "160": 18.149999999999952, + "161": -26.249999999999968, + "162": 84.65, + "163": -24.849999999999977, + "164": 34.64999999999978, + "165": 39.24999999999988, + "166": -90.84999999999998, + "167": -34.3, + "168": 38.299999999999855, + "169": -29.050000000000004, + "170": -59.000000000000014, + "171": -10.39999999999999, + "172": -11.849999999999993, + "173": -5.8499999999999845, + "174": 29.35000000000004, + "175": 26.199999999999942, + "176": -15.1, + "177": 33.49999999999988, + "178": -72.50000000000001, + "179": 18.29999999999993, + "180": -34.50000000000004, + "181": 26.650000000000023, + "182": -56.69999999999998, + "183": 0.3500000000000256, + "184": -43.34999999999998, + "185": 3.950000000000012, + "186": 27.800000000000022, + "187": -9.949999999999994, + "188": 40.60000000000003, + "189": 46.499999999999766, + "190": 4.800000000000043, + "191": -9.649999999999997, + "192": -60.749999999999986, + "193": -7.949999999999993, + "194": -11.54999999999998, + "195": 2.8500000000000263, + "196": -9.399999999999988, + "197": -13.399999999999993, + "198": 19.79999999999999, + "199": 46.29999999999978, + "200": -39.899999999999984, + "201": 47.04999999999983, + "202": 23.650000000000013, + "203": -5.950000000000013, + "204": 24.550000000000068, + "205": 45.24999999999988, + "206": 99.04999999999974, + "207": 2.5500000000000207, + "208": -57.44999999999994, + "209": 9.150000000000016, + "210": 3.0499999999998817, + "211": 79.69999999999983, + "212": 47.59999999999991, + "213": 38.199999999999996, + "214": 23.900000000000023, + "215": 44.34999999999995, + "216": 65.04999999999987, + "217": 74.59999999999975, + "218": 64.44999999999975, + "219": 66.54999999999977, + "220": 22.899999999999913, + "221": 9.599999999999941, + "222": 24.550000000000036, + "223": -30.44999999999999, + "224": 75.14999999999984, + "225": 43.849999999999795, + "226": 82.9500000000001, + "227": 29.649999999999984, + "228": 90.35000000000012, + "229": -87.2, + "230": -20.500000000000075, + "231": 67.14999999999972, + "232": 25.59999999999999, + "233": -75.95000000000002, + "234": 9.950000000000038, + "235": 79.4999999999998, + "236": 22.500000000000057, + "237": 31.899999999999988, + "238": -9.749999999999972, + "239": 51.64999999999997, + "240": 72.0499999999998, + "241": 29.250000000000057, + "242": 63.9499999999999, + "243": 24.999999999999826, + "244": -23.650000000000006, + "245": 80.94999999999995, + "246": 54.499999999999915, + "247": 27.450000000000003, + "248": 41.550000000000004, + "249": 61.44999999999976, + "250": 33.70000000000005, + "251": 38.64999999999997, + "252": 104.3500000000002, + "253": 84.75000000000007, + "254": -8.349999999999989, + "255": 38.34999999999975, + "256": 63.6499999999998, + "257": 70.74999999999983, + "258": 89.39999999999975, + "259": 75.79999999999986, + "260": 62.74999999999992, + "261": 89.90000000000006, + "262": 58.59999999999977, + "263": 65.54999999999983, + "264": 95.89999999999998, + "265": 15.400000000000073, + "266": 94.49999999999974, + "267": 10.950000000000067, + "268": 103.70000000000026, + "269": 89.69999999999982, + "270": 93.34999999999977, + "271": 99.54999999999973, + "272": 105.04999999999977, + "273": -11.050000000000011, + "274": 97.24999999999991, + "275": 94.09999999999974, + "276": 69.84999999999982, + "277": 57.54999999999991, + "278": -58.29999999999998, + "279": 69.94999999999979, + "280": 44.14999999999976, + "281": -9.899999999999993, + "282": 111.95000000000013, + "283": 79.04999999999986, + "284": 23.00000000000004, + "285": 70.74999999999973, + "286": 93.55000000000004, + "287": 73.54999999999991, + "288": 90.7500000000001, + "289": 71.79999999999973, + "290": 72.74999999999986, + "291": 107.69999999999982, + "292": 58.49999999999977, + "293": 36.84999999999997, + "294": 92.94999999999979, + "295": 101.39999999999974, + "296": 105.75000000000013, + "297": 102.54999999999976, + "298": 41.94999999999994, + "299": 47.299999999999926, + "300": 96.54999999999983, + "301": 58.4999999999998, + "302": 84.25000000000003, + "303": 100.14999999999976, + "304": 60.99999999999973, + "305": 106.14999999999984, + "306": 115.55000000000021, + "307": 117.90000000000026, + "308": 104.34999999999981, + "309": 73.3000000000001, + "310": 95.09999999999975, + "311": 40.24999999999997, + "312": 96.39999999999988, + "313": 107.60000000000021, + "314": 90.59999999999978, + "315": 107.7500000000001, + "316": 73.90000000000008, + "317": 44.799999999999955, + "318": 97.64999999999978, + "319": 83.29999999999983, + "320": 105.30000000000022, + "321": 73.89999999999998, + "322": 62.34999999999992, + "323": 103.79999999999978, + "324": 97.24999999999974, + "325": 23.200000000000056, + "326": 12.34999999999999, + "327": 52.649999999999984, + "328": 84.5499999999998, + "329": 78.99999999999996, + "330": 71.84999999999985, + "331": 81.64999999999984, + "332": 112.29999999999997, + "333": 105.95000000000012, + "334": 107.84999999999974, + "335": 108.1, + "336": -43.70000000000001, + "337": 82.94999999999979, + "338": 110.20000000000023, + "339": 90.55000000000001, + "340": 102.80000000000018, + "341": 101.64999999999976, + "342": 44.94999999999998, + "343": 58.799999999999855, + "344": 104.5000000000001, + "345": 74.50000000000001, + "346": 71.79999999999997, + "347": 71.84999999999988, + "348": 49.79999999999999, + "349": 103.44999999999999, + "350": 101.20000000000002, + "351": 113.25000000000018, + "352": 112.1500000000001, + "353": 95.19999999999986, + "354": 105.20000000000005, + "355": 108.7499999999998, + "356": 104.59999999999995, + "357": 107.50000000000016, + "358": 114.8000000000001, + "359": 95.69999999999982, + "360": 100.89999999999974, + "361": 88.19999999999975, + "362": 95.8, + "363": 96.25000000000013, + "364": 108.85000000000021, + "365": 115.50000000000027, + "366": 82.25000000000001, + "367": 90.79999999999994, + "368": 109.14999999999979, + "369": 107.34999999999977, + "370": 70.29999999999995, + "371": 112.80000000000021, + "372": 97.90000000000005, + "373": 95.50000000000001, + "374": 110.85000000000014, + "375": 110.79999999999997, + "376": 89.90000000000002, + "377": 109.89999999999989, + "378": 113.65000000000016, + "379": 101.50000000000017, + "380": 83.80000000000005, + "381": 109.10000000000004, + "382": 95.00000000000004, + "383": 97.79999999999998, + "384": 83.70000000000003, + "385": 103.95000000000014, + "386": 105.60000000000012, + "387": 103.5500000000001, + "388": 114.55000000000027, + "389": 106.00000000000013, + "390": 114.45000000000023, + "391": 103.44999999999973, + "392": 104.29999999999986, + "393": 110.09999999999988, + "394": 110.85000000000012, + "395": 111.90000000000012, + "396": 111.30000000000011, + "397": 109.89999999999996, + "398": 112.50000000000004, + "399": 82.3999999999999, + "400": 107.6, + "401": 94.84999999999984, + "402": 111.75000000000001, + "403": 90.79999999999991, + "404": 82.85000000000002, + "405": 107.45000000000013, + "406": 107.10000000000011, + "407": 99.2999999999999, + "408": 97.80000000000008, + "409": 91.39999999999986, + "410": 79.74999999999999, + "411": 111.70000000000019, + "412": 110.70000000000012, + "413": 110.15000000000016, + "414": 105.94999999999978, + "415": 104.14999999999988, + "416": 108.20000000000002, + "417": 95.35000000000008, + "418": 100.89999999999976, + "419": 115.60000000000025, + "420": 102.80000000000018, + "421": 110.35000000000015, + "422": 108.6999999999999, + "423": 100.29999999999997, + "424": 113.00000000000021, + "425": 88.84999999999992, + "426": 110.09999999999988, + "427": 111.70000000000026, + "428": 107.50000000000021, + "429": 110.95000000000002, + "430": 96.00000000000001, + "431": 105.44999999999999, + "432": 108.94999999999979, + "433": 110.14999999999993, + "434": 107.64999999999998, + "435": 52.399999999999864, + "436": 100.30000000000015, + "437": 112.9000000000001, + "438": 100.89999999999986, + "439": 110.15000000000012, + "440": 113.20000000000017, + "441": 109.1000000000002, + "442": 109.35000000000021, + "443": 113.70000000000022, + "444": 97.94999999999995, + "445": 84.60000000000005, + "446": 69.34999999999987, + "447": 107.29999999999974, + "448": 112.04999999999998, + "449": 110.80000000000008, + "450": 79.95, + "451": 107.25000000000014, + "452": 106.5499999999999, + "453": 113.15000000000012, + "454": 112.05000000000018, + "455": 60.749999999999986, + "456": 112.45000000000006, + "457": 109.89999999999999, + "458": 103.89999999999988, + "459": 113.6500000000002, + "460": 109.60000000000001, + "461": 108.3000000000002, + "462": 112.85000000000022, + "463": 102.80000000000007, + "464": 112.15000000000006, + "465": 106.30000000000015, + "466": 111.0000000000001, + "467": 114.75000000000009, + "468": 100.24999999999996, + "469": 109.45000000000007, + "470": 47.54999999999989, + "471": 107.49999999999993, + "472": 109.04999999999993, + "473": 108.50000000000016, + "474": 111.24999999999999, + "475": 102.19999999999993, + "476": 92.0000000000001, + "477": 113.90000000000002, + "478": 81.79999999999998, + "479": 100.1499999999998, + "480": 110.9500000000002, + "481": 109.4999999999999, + "482": 108.75000000000004, + "483": 105.89999999999993, + "484": 114.55000000000022, + "485": 88.44999999999983, + "486": 111.85000000000011, + "487": 110.45000000000006, + "488": 100.70000000000013, + "489": 26.449999999999964, + "490": 90.34999999999998, + "491": 107.15000000000019, + "492": 99.04999999999998, + "493": 107.8000000000002, + "494": 114.65000000000026, + "495": 113.15000000000013, + "496": 111.45000000000012, + "497": 101.49999999999996, + "498": 112.25000000000001, + "499": 116.85000000000028, + "500": 100.55000000000007, + "501": 108.05000000000024, + "502": 100.24999999999987, + "503": 103.80000000000018, + "504": 107.85000000000001, + "505": 100.70000000000016, + "506": 107.24999999999993, + "507": 105.55000000000005, + "508": 110.19999999999987, + "509": 105.60000000000001, + "510": 112.50000000000017, + "511": 113.70000000000012, + "512": 99.70000000000002, + "513": 100.5000000000001, + "514": 108.54999999999986, + "515": 105.5500000000002, + "516": 113.95000000000023, + "517": 100.64999999999993, + "518": 99.74999999999991, + "519": 91.99999999999977, + "520": 98.50000000000006, + "521": 113.20000000000007, + "522": 106.05000000000014, + "523": 109.89999999999989, + "524": 113.20000000000013, + "525": 109.89999999999988, + "526": 110.35000000000007, + "527": 115.20000000000014, + "528": 101.65000000000016, + "529": 114.85000000000025, + "530": 115.80000000000003, + "531": 93.85000000000007, + "532": 102.55000000000011, + "533": 98.94999999999996, + "534": 94.19999999999985, + "535": 112.10000000000005, + "536": 105.89999999999988, + "537": 91.05000000000003, + "538": 101.90000000000005, + "539": 105.60000000000021, + "540": 114.15000000000022, + "541": 103.45000000000014, + "542": 61.199999999999775, + "543": 109.05000000000003, + "544": 83.65, + "545": 99.3500000000001, + "546": 114.30000000000022, + "547": 108.34999999999988, + "548": 74.00000000000004, + "549": 109.80000000000014, + "550": 66.79999999999991, + "551": 81.2499999999999, + "552": 103.65000000000009, + "553": 108.55000000000017, + "554": 111.80000000000022, + "555": 101.69999999999997, + "556": 100.54999999999974, + "557": 75.29999999999995, + "558": 108.75000000000009, + "559": 101.05000000000011, + "560": 86.35, + "561": 104.90000000000009, + "562": 105.60000000000002, + "563": 110.04999999999993, + "564": 108.39999999999999, + "565": 107.34999999999995, + "566": 112.85000000000011, + "567": 110.05000000000011, + "568": 98.2, + "569": 111.65000000000008, + "570": 117.7500000000003, + "571": 99.70000000000003, + "572": 107.20000000000013, + "573": 113.10000000000015, + "574": 111.05000000000018, + "575": 111.80000000000018, + "576": 107.70000000000014, + "577": 103.80000000000007, + "578": 113.99999999999991, + "579": 107.75000000000004, + "580": 106.45000000000007, + "581": 100.54999999999993, + "582": 112.85000000000024, + "583": 57.24999999999994, + "584": 116.2000000000002, + "585": 101.60000000000008, + "586": 108.94999999999997, + "587": 87.55000000000015, + "588": 101.60000000000015, + "589": 63.9499999999999, + "590": 103.40000000000018, + "591": 103.54999999999981, + "592": 87.20000000000005, + "593": 107.6500000000002, + "594": 107.70000000000016, + "595": 89.79999999999993, + "596": 103.15000000000023, + "597": 113.00000000000023, + "598": 54.54999999999992, + "599": 112.00000000000003, + "600": 107.09999999999994, + "601": 110.55000000000005, + "602": 88.15000000000006, + "603": 111.05000000000014, + "604": 101.00000000000014, + "605": 107.95000000000012, + "606": 88.75, + "607": 110.4000000000001, + "608": 103.8500000000001, + "609": 114.85000000000026, + "610": 98.1500000000001, + "611": 111.95000000000003, + "612": 82.79999999999995, + "613": 113.05000000000022, + "614": 98.04999999999994, + "615": 106.75000000000023, + "616": 107.04999999999988, + "617": 101.5499999999999, + "618": 104.79999999999998, + "619": 108.25000000000016, + "620": 112.0000000000001, + "621": 107.04999999999993, + "622": 97.50000000000004, + "623": 102.70000000000016, + "624": 97.75000000000001, + "625": 109.55000000000008, + "626": 88.05000000000021, + "627": 111.89999999999998, + "628": 111.10000000000011, + "629": 111.84999999999995, + "630": 108.9500000000002, + "631": 105.15, + "632": 100.95000000000009, + "633": 95.15000000000009, + "634": 110.04999999999998, + "635": 110.40000000000019, + "636": 84.2, + "637": 112.24999999999994, + "638": 90.54999999999986, + "639": 106.00000000000017, + "640": 108.6500000000002, + "641": 102.00000000000011, + "642": 23.099999999999994, + "643": 99.84999999999977, + "644": 97.25, + "645": 110.30000000000004, + "646": 63.39999999999992, + "647": 113.50000000000017, + "648": 99.60000000000002, + "649": 100.40000000000005, + "650": 109.95000000000009, + "651": 93.80000000000011, + "652": 40.85000000000004, + "653": 103.70000000000005, + "654": 114.85000000000016, + "655": 104.30000000000014, + "656": 98.80000000000014, + "657": -71.14999999999998, + "658": 106.55000000000022, + "659": 105.09999999999998, + "660": 80.05000000000025, + "661": 112.35000000000005, + "662": 110.59999999999992, + "663": 108.60000000000008, + "664": 89.25000000000007, + "665": 113.95000000000019, + "666": 109.9500000000001, + "667": 96.75000000000013, + "668": 109.89999999999996, + "669": 107.15000000000018, + "670": 94.04999999999993, + "671": 106.74999999999987, + "672": 102.20000000000013, + "673": 104.80000000000018, + "674": 95.8, + "675": 95.15000000000008, + "676": 109.14999999999998, + "677": 100.89999999999998, + "678": 106.10000000000018, + "679": 109.6500000000002, + "680": 110.35000000000008, + "681": 100.44999999999995, + "682": 95.24999999999999, + "683": 109.45, + "684": 97.25000000000004, + "685": 109.54999999999998, + "686": 96.60000000000004, + "687": 111.80000000000015, + "688": 103.75000000000006, + "689": 110.90000000000009, + "690": 108.3999999999998, + "691": 108.25000000000004, + "692": 112.15000000000016, + "693": 109.64999999999986, + "694": 113.60000000000014, + "695": 114.95000000000016, + "696": 95.75, + "697": 107.65000000000018, + "698": 112.30000000000025, + "699": 117.95000000000027, + "700": 112.1000000000001, + "701": 114.0000000000002, + "702": 100.1499999999999, + "703": 106.85000000000015, + "704": 108.29999999999994, + "705": 108.15000000000009, + "706": 107.60000000000014, + "707": 101.80000000000008, + "708": 103.49999999999974, + "709": 97.05000000000003, + "710": 115.35000000000025, + "711": 107.35000000000015, + "712": 91.89999999999995, + "713": 108.09999999999991, + "714": 105.10000000000007, + "715": 94.94999999999996, + "716": 103.6000000000002, + "717": 112.85000000000007, + "718": 97.25000000000009, + "719": 100.05000000000007, + "720": 108.95000000000017, + "721": 110.7499999999999, + "722": 113.55000000000021, + "723": 109.2500000000001, + "724": 103.00000000000018, + "725": 111.05000000000022, + "726": 109.20000000000009, + "727": 108.85000000000001, + "728": 107.25000000000013, + "729": 106.39999999999996, + "730": 104.55000000000004, + "731": 70.09999999999994, + "732": 115.45000000000026, + "733": 94.9000000000001, + "734": 113.65000000000015, + "735": 107.75000000000004, + "736": 109.04999999999997, + "737": 92.45000000000006, + "738": 107.40000000000018, + "739": 108.10000000000012, + "740": 105.5999999999998, + "741": 109.25, + "742": 78.50000000000001, + "743": 112.90000000000023, + "744": 113.50000000000023, + "745": 93.89999999999988, + "746": 108.45000000000017, + "747": 83.70000000000002, + "748": 113.0000000000001, + "749": 111.3500000000001, + "750": 108.94999999999993, + "751": 109.25000000000028, + "752": 106.79999999999998, + "753": 112.75000000000011, + "754": 109.35000000000011, + "755": 110.60000000000011, + "756": 108.65000000000019, + "757": 112.35000000000014, + "758": 101.85000000000015, + "759": 116.35000000000026, + "760": 114.05000000000018, + "761": 110.25000000000018, + "762": 108.85, + "763": 122.00000000000028, + "764": 113.30000000000001, + "765": 104.6500000000001, + "766": 101.0999999999999, + "767": 102.05000000000005, + "768": 99.40000000000015, + "769": 109.85000000000016, + "770": 112.45000000000022, + "771": 104.75000000000013, + "772": 92.00000000000006, + "773": 112.40000000000015, + "774": 75.45000000000026, + "775": 68.2499999999999, + "776": 87.8000000000002, + "777": 108.79999999999981, + "778": 102.25000000000016, + "779": 81.04999999999995, + "780": 101.10000000000012, + "781": 73.85000000000004, + "782": 108.94999999999993, + "783": 77.54999999999993, + "784": 86.5999999999998, + "785": 98.2500000000001, + "786": 49.949999999999875, + "787": 116.00000000000017, + "788": 45.09999999999978, + "789": 82.15000000000025, + "790": 45.399999999999835, + "791": 107.80000000000025, + "792": 70.65000000000012, + "793": 45.64999999999995, + "794": 108.25000000000021, + "795": 48.099999999999845, + "796": 59.14999999999985, + "797": 89.00000000000016, + "798": 73.9, + "799": 52.79999999999985, + "800": 109.65000000000018, + "801": 66.89999999999995, + "802": -10.949999999999992, + "803": 97.30000000000007, + "804": 100.85000000000018, + "805": 61.599999999999795, + "806": 113.60000000000008, + "807": 27.549999999999955, + "808": 69.44999999999992, + "809": 105.35000000000001, + "810": 109.70000000000005, + "811": 99.75000000000011, + "812": 105.0000000000002, + "813": 66.50000000000023, + "814": 101.29999999999994, + "815": 121.65000000000009, + "816": 109.85000000000004, + "817": 54.69999999999976, + "818": 46.34999999999989, + "819": 82.65000000000015, + "820": 84.85000000000025, + "821": 111.75000000000021, + "822": 111.69999999999996, + "823": 110.60000000000026, + "824": 107.65, + "825": 105.0500000000002, + "826": 88.69999999999999, + "827": 112.75000000000006, + "828": 110.65000000000016, + "829": 38.74999999999978, + "830": 113.45000000000014, + "831": 102.95000000000003, + "832": 75.14999999999999, + "833": 103.05000000000008, + "834": 50.549999999999926, + "835": 103.45000000000026, + "836": 113.60000000000002, + "837": 106.40000000000005, + "838": 42.0499999999999, + "839": 117.40000000000019, + "840": 110.25000000000016, + "841": 99.00000000000003, + "842": 89.49999999999997, + "843": 108.00000000000006, + "844": 107.9000000000001, + "845": 107.59999999999998, + "846": 75.40000000000003, + "847": 103.20000000000023, + "848": 85.69999999999992, + "849": 117.80000000000008, + "850": 70.89999999999985, + "851": 113.10000000000011, + "852": 98.80000000000003, + "853": 103.10000000000018, + "854": 111.5000000000001, + "855": 90.35, + "856": 117.99999999999999, + "857": 112.24999999999999, + "858": 101.24999999999997, + "859": 91.4, + "860": 85.84999999999991, + "861": 106.40000000000003, + "862": 89.19999999999999, + "863": 115.50000000000024, + "864": 95.2500000000001, + "865": 110.65000000000006, + "866": 110.15000000000015, + "867": 103.95, + "868": 101.00000000000007, + "869": 109.75000000000014, + "870": 98.9, + "871": 106.40000000000012, + "872": 112.25000000000001, + "873": 108.30000000000004, + "874": 75.74999999999991, + "875": 113.75000000000028, + "876": 109.24999999999996, + "877": 115.90000000000005, + "878": -37.09999999999996, + "879": 117.05000000000024, + "880": 113.95000000000014, + "881": 113.19999999999999, + "882": 108.6500000000001, + "883": 116.35000000000007, + "884": 109.5, + "885": 90.85000000000007, + "886": 121.20000000000009, + "887": 110.60000000000021, + "888": 111.10000000000007, + "889": 68.54999999999986, + "890": 109.70000000000006, + "891": 118.10000000000001, + "892": 113.60000000000014, + "893": 112.95000000000017, + "894": 116.80000000000001, + "895": 111.64999999999998, + "896": 108.70000000000009, + "897": 116.20000000000003, + "898": 83.35000000000005, + "899": 104.55, + "900": 112.7000000000001, + "901": 106.24999999999997, + "902": 115.35000000000007, + "903": 9.649999999999993, + "904": 109.90000000000008, + "905": 115.60000000000016, + "906": 94.25000000000004, + "907": 96.25000000000013, + "908": 110.85000000000007, + "909": 116.90000000000013, + "910": 99.89999999999998, + "911": 109.55000000000017, + "912": 102.0500000000001, + "913": 99.69999999999993, + "914": 109.25000000000003, + "915": 114.40000000000003, + "916": 117.30000000000013, + "917": 109.2000000000001, + "918": 112.29999999999997, + "919": 78.0000000000001, + "920": 106.00000000000007, + "921": 107.14999999999996, + "922": 86.60000000000025, + "923": 106.49999999999999, + "924": 89.15000000000002, + "925": 109.3500000000001, + "926": 110.40000000000005, + "927": 106.45000000000006, + "928": 103.40000000000012, + "929": 101.95000000000006, + "930": 113.85000000000011, + "931": 108.7500000000001, + "932": 114.70000000000007, + "933": 121.44999999999999, + "934": 95.45000000000013, + "935": 107.35000000000007, + "936": 27.199999999999935, + "937": 105.3, + "938": 104.15000000000009, + "939": 102.30000000000017, + "940": 119.50000000000011, + "941": 113.50000000000013, + "942": 102.24999999999999, + "943": 115.45000000000032, + "944": 107.60000000000002, + "945": 105.65000000000002, + "946": 109.25000000000011, + "947": 105.80000000000011, + "948": 78.7, + "949": 113.30000000000017, + "950": 100.69999999999992, + "951": 100.30000000000015, + "952": 104.04999999999991, + "953": 100.95, + "954": 104.55000000000007, + "955": 108.35000000000007, + "956": 103.85, + "957": 94.09999999999984, + "958": 102.65000000000003, + "959": 94.15000000000008, + "960": 100.25000000000013, + "961": 114.0000000000001, + "962": 103.80000000000007, + "963": 102.85000000000007, + "964": 70.89999999999993, + "965": 97.70000000000002, + "966": 104.50000000000021, + "967": 105.35000000000015, + "968": 111.65000000000006, + "969": 110.20000000000005, + "970": 103.84999999999998, + "971": 104.60000000000002, + "972": 109.80000000000008, + "973": 109.29999999999994, + "974": 106.90000000000009, + "975": 115.15000000000006, + "976": 107.40000000000013, + "977": 101.60000000000008, + "978": 119.50000000000007, + "979": 109.20000000000002, + "980": 105.70000000000006, + "981": 112.15000000000002, + "982": 107.44999999999996, + "983": 120.95000000000005, + "984": 108.60000000000026, + "985": 60.44999999999998, + "986": 31.599999999999927, + "987": 88.95000000000019, + "988": 113.80000000000001, + "989": 75.25000000000004, + "990": 109.00000000000007, + "991": 107.25000000000006, + "992": 93.40000000000002, + "993": 117.5500000000002, + "994": 117.6000000000001, + "995": 117.9, + "996": 105.35000000000014, + "997": 120.05000000000003, + "998": 119.90000000000016, + "999": 99.50000000000009, + "1000": 98.70000000000006 + } +} \ No newline at end of file diff --git a/benchmark/results/v3/v3.1.0/session_metadata/5.json b/benchmark/results/v3/v3.1.0/session_metadata/5.json new file mode 100644 index 00000000..58428719 --- /dev/null +++ b/benchmark/results/v3/v3.1.0/session_metadata/5.json @@ -0,0 +1,1009 @@ +{ + "total_episodes": 1001, + "total_time_steps": 128000, + "total_s": 1956.994206, + "s_per_step": 0.0611560689375, + "s_per_100_steps_10_nodes": 6.11560689375, + "total_reward_per_episode": { + "1": -19.49999999999996, + "2": -15.049999999999978, + "3": -28.85000000000002, + "4": -76.64999999999992, + "5": -66.55000000000011, + "6": -18.79999999999997, + "7": -22.149999999999956, + "8": -60.350000000000115, + "9": -48.850000000000065, + "10": -40.20000000000005, + "11": -11.699999999999992, + "12": -38.40000000000004, + "13": -17.099999999999955, + "14": -55.70000000000008, + "15": -50.04999999999995, + "16": -29.699999999999967, + "17": -28.54999999999999, + "18": -28.799999999999944, + "19": -23.49999999999997, + "20": -34.35000000000003, + "21": -39.400000000000134, + "22": -21.09999999999996, + "23": -22.64999999999995, + "24": -21.549999999999958, + "25": -9.799999999999994, + "26": 10.350000000000051, + "27": -39.20000000000004, + "28": -21.499999999999957, + "29": -52.10000000000008, + "30": -19.149999999999967, + "31": -16.199999999999978, + "32": -17.59999999999997, + "33": -13.699999999999987, + "34": -1.3500000000000056, + "35": -54.15000000000016, + "36": -19.849999999999966, + "37": -22.199999999999953, + "38": -15.44999999999998, + "39": -17.44999999999997, + "40": -15.499999999999975, + "41": -21.89999999999996, + "42": -100.2, + "43": -17.099999999999973, + "44": -87.35, + "45": -2.849999999999997, + "46": -42.45000000000005, + "47": -3.6999999999999966, + "48": -6.700000000000007, + "49": -39.900000000000034, + "50": -17.899999999999974, + "51": -17.14999999999997, + "52": -11.649999999999988, + "53": -56.45000000000008, + "54": -20.84999999999996, + "55": -15.24999999999997, + "56": -8.450000000000015, + "57": -26.650000000000023, + "58": -19.099999999999966, + "59": -22.549999999999986, + "60": -11.099999999999994, + "61": -19.249999999999964, + "62": -9.149999999999988, + "63": -18.849999999999966, + "64": -15.299999999999981, + "65": -21.249999999999957, + "66": -11.449999999999994, + "67": -19.599999999999962, + "68": -7.399999999999988, + "69": -22.149999999999956, + "70": 9.300000000000047, + "71": -9.849999999999994, + "72": -19.74999999999996, + "73": -56.15, + "74": -18.89999999999999, + "75": -4.399999999999982, + "76": -37.700000000000045, + "77": -5.599999999999986, + "78": -13.299999999999988, + "79": -93.80000000000001, + "80": -91.05, + "81": 16.55000000000003, + "82": 22.249999999999982, + "83": 8.400000000000034, + "84": 0.6499999999999975, + "85": 7.050000000000032, + "86": -0.9499999999999684, + "87": -15.099999999999975, + "88": -85.10000000000001, + "89": -83.1, + "90": -6.849999999999995, + "91": -57.35000000000001, + "92": -49.05000000000013, + "93": 15.30000000000004, + "94": -21.649999999999956, + "95": -8.45, + "96": -87.89999999999995, + "97": -15.89999999999998, + "98": 11.750000000000046, + "99": -4.799999999999984, + "100": -6.099999999999992, + "101": -71.7, + "102": -14.949999999999982, + "103": -26.650000000000006, + "104": -21.600000000000037, + "105": -18.14999999999997, + "106": -3.399999999999979, + "107": -22.99999999999998, + "108": -11.299999999999992, + "109": -84.39999999999999, + "110": -21.599999999999955, + "111": -12.449999999999985, + "112": -8.499999999999995, + "113": -38.00000000000011, + "114": -70.44999999999997, + "115": -14.349999999999993, + "116": 2.2500000000000133, + "117": 38.64999999999998, + "118": 34.049999999999876, + "119": -58.99999999999995, + "120": -8.699999999999996, + "121": 35.05000000000002, + "122": 13.000000000000064, + "123": -11.44999999999999, + "124": -68.3, + "125": -6.099999999999999, + "126": 21.700000000000003, + "127": -34.65000000000009, + "128": -19.949999999999964, + "129": 14.350000000000046, + "130": -28.649999999999995, + "131": -21.89999999999995, + "132": -13.449999999999985, + "133": 8.800000000000034, + "134": -6.94999999999998, + "135": -2.8499999999999712, + "136": -17.19999999999997, + "137": -4.2499999999999725, + "138": 57.39999999999983, + "139": -11.449999999999989, + "140": 0.9000000000000461, + "141": 54.04999999999982, + "142": -58.20000000000001, + "143": -0.4500000000000308, + "144": 18.500000000000018, + "145": 1.8000000000000196, + "146": -76.94999999999999, + "147": 8.550000000000004, + "148": -79.64999999999988, + "149": 14.050000000000047, + "150": -26.399999999999984, + "151": -24.95000000000002, + "152": 31.699999999999996, + "153": -59.949999999999996, + "154": -16.50000000000001, + "155": -49.8, + "156": -75.40000000000003, + "157": -13.749999999999984, + "158": -66.49999999999996, + "159": -55.64999999999997, + "160": -61.599999999999916, + "161": 5.850000000000056, + "162": 12.55000000000007, + "163": -66.39999999999993, + "164": -40.19999999999999, + "165": -92.09999999999991, + "166": 10.95000000000002, + "167": 21.099999999999987, + "168": 26.59999999999986, + "169": 3.6500000000000146, + "170": 6.900000000000036, + "171": -18.54999999999997, + "172": 39.19999999999985, + "173": 48.59999999999985, + "174": 31.499999999999748, + "175": -11.749999999999966, + "176": -75.95000000000003, + "177": -19.550000000000036, + "178": -69.95000000000003, + "179": 22.65, + "180": 44.74999999999977, + "181": -57.80000000000005, + "182": -71.50000000000003, + "183": 9.40000000000001, + "184": -31.900000000000002, + "185": -73.95000000000002, + "186": 47.50000000000004, + "187": -7.700000000000012, + "188": 20.250000000000032, + "189": 50.14999999999985, + "190": -12.850000000000039, + "191": 9.150000000000018, + "192": 53.34999999999986, + "193": -15.400000000000007, + "194": 36.399999999999835, + "195": -35.20000000000003, + "196": 30.34999999999993, + "197": 31.249999999999957, + "198": -22.350000000000023, + "199": 22.15000000000009, + "200": -60.14999999999998, + "201": 20.349999999999984, + "202": -39.85, + "203": 1.6000000000000045, + "204": -29.99999999999997, + "205": 38.39999999999981, + "206": -55.35000000000001, + "207": 48.74999999999989, + "208": 6.9499999999999975, + "209": -67.44999999999999, + "210": -76.40000000000002, + "211": -69.75000000000001, + "212": -1.549999999999995, + "213": -21.249999999999957, + "214": 37.79999999999992, + "215": -54.60000000000001, + "216": -73.54999999999988, + "217": 53.44999999999983, + "218": -74.8, + "219": -16.400000000000002, + "220": 48.3999999999999, + "221": 13.000000000000053, + "222": 14.60000000000003, + "223": -96.94999999999999, + "224": -8.499999999999986, + "225": 51.39999999999996, + "226": 81.29999999999993, + "227": 21.44999999999992, + "228": 29.399999999999828, + "229": 10.550000000000061, + "230": -7.400000000000019, + "231": 35.549999999999855, + "232": 56.69999999999993, + "233": -15.649999999999977, + "234": 69.99999999999983, + "235": 38.500000000000014, + "236": 47.59999999999978, + "237": -33.70000000000002, + "238": -39.150000000000055, + "239": 93.05000000000008, + "240": -27.05000000000003, + "241": 36.399999999999835, + "242": 28.749999999999968, + "243": 83.84999999999998, + "244": -27.400000000000013, + "245": 93.34999999999982, + "246": -7.400000000000004, + "247": 35.95000000000002, + "248": -31.20000000000001, + "249": -32.59999999999999, + "250": 67.35000000000004, + "251": -10.749999999999979, + "252": -20.29999999999996, + "253": 93.89999999999976, + "254": 9.800000000000018, + "255": 21.999999999999982, + "256": 33.25, + "257": 82.50000000000023, + "258": 68.4, + "259": 42.699999999999896, + "260": 81.94999999999999, + "261": 54.49999999999989, + "262": 73.89999999999982, + "263": 27.89999999999999, + "264": 55.499999999999886, + "265": -26.750000000000007, + "266": 43.99999999999979, + "267": 39.49999999999998, + "268": 73.04999999999991, + "269": 98.79999999999981, + "270": 65.7999999999999, + "271": 91.49999999999976, + "272": 50.29999999999991, + "273": 52.14999999999978, + "274": 87.85000000000002, + "275": 53.55000000000002, + "276": -9.60000000000003, + "277": -61.10000000000003, + "278": -38.39999999999999, + "279": 3.2499999999999645, + "280": -70.74999999999999, + "281": 24.24999999999995, + "282": 99.79999999999981, + "283": 91.65000000000003, + "284": 67.99999999999994, + "285": 103.39999999999978, + "286": 19.900000000000055, + "287": 64.29999999999993, + "288": 107.4500000000001, + "289": 55.29999999999992, + "290": 41.799999999999805, + "291": 44.499999999999964, + "292": -26.400000000000023, + "293": 82.95000000000005, + "294": 41.45000000000004, + "295": 60.24999999999991, + "296": 81.00000000000004, + "297": 53.49999999999988, + "298": 102.54999999999994, + "299": 75.25000000000009, + "300": 95.54999999999983, + "301": 43.599999999999916, + "302": 88.45000000000005, + "303": 88.30000000000011, + "304": 102.40000000000002, + "305": 112.1000000000002, + "306": 71.7999999999998, + "307": 94.10000000000007, + "308": 66.29999999999993, + "309": 102.60000000000015, + "310": -63.1999999999999, + "311": 61.49999999999986, + "312": 94.45000000000012, + "313": 98.50000000000017, + "314": 52.09999999999988, + "315": 22.59999999999999, + "316": 114.2000000000001, + "317": 77.54999999999998, + "318": 96.90000000000006, + "319": 87.05000000000008, + "320": 106.84999999999972, + "321": 95.64999999999993, + "322": 72.99999999999994, + "323": 84.99999999999974, + "324": 71.30000000000005, + "325": 13.55000000000005, + "326": 87.65000000000009, + "327": 94.15000000000013, + "328": 71.14999999999989, + "329": 78.70000000000022, + "330": 100.60000000000001, + "331": 94.05000000000015, + "332": 71.45000000000026, + "333": 92.20000000000009, + "334": 53.149999999999814, + "335": 98.75000000000018, + "336": 102.70000000000014, + "337": 103.19999999999996, + "338": 56.349999999999824, + "339": 110.15000000000006, + "340": 84.59999999999997, + "341": 113.05000000000014, + "342": 113.80000000000004, + "343": 99.90000000000008, + "344": 56.84999999999995, + "345": 103.50000000000023, + "346": 110.25000000000013, + "347": 104.49999999999999, + "348": 110.00000000000009, + "349": 67.4999999999999, + "350": -13.949999999999983, + "351": 112.05000000000005, + "352": 90.3000000000001, + "353": 103.8000000000001, + "354": 69.80000000000003, + "355": 116.90000000000018, + "356": 106.40000000000009, + "357": 114.55, + "358": 106.3500000000002, + "359": 114.3000000000001, + "360": 82.04999999999998, + "361": 101.0000000000002, + "362": 113.85000000000002, + "363": 89.14999999999999, + "364": 105.65000000000016, + "365": -3.4000000000000026, + "366": 111.30000000000008, + "367": 115.55000000000011, + "368": 105.09999999999995, + "369": 26.60000000000002, + "370": 106.79999999999993, + "371": 109.25, + "372": 102.0, + "373": 111.70000000000014, + "374": 60.09999999999991, + "375": 96.4999999999998, + "376": 80.45000000000006, + "377": 93.95000000000009, + "378": 105.25000000000009, + "379": 105.70000000000007, + "380": 111.7500000000001, + "381": 108.30000000000011, + "382": 101.20000000000009, + "383": 117.40000000000008, + "384": 111.6, + "385": 22.09999999999992, + "386": 110.19999999999992, + "387": 105.65000000000012, + "388": 102.59999999999988, + "389": 113.10000000000004, + "390": 108.94999999999995, + "391": 104.00000000000003, + "392": 96.65000000000006, + "393": 107.9000000000001, + "394": 95.80000000000007, + "395": 112.40000000000002, + "396": 115.20000000000012, + "397": 113.29999999999993, + "398": 121.60000000000004, + "399": 107.00000000000004, + "400": 120.25000000000011, + "401": 112.50000000000009, + "402": 24.10000000000005, + "403": 115.85, + "404": 114.79999999999997, + "405": 95.64999999999986, + "406": 112.30000000000013, + "407": 110.00000000000001, + "408": 95.75, + "409": 80.34999999999998, + "410": 106.00000000000003, + "411": 105.94999999999999, + "412": 118.25000000000003, + "413": 108.4000000000001, + "414": 111.20000000000006, + "415": 85.75, + "416": 118.70000000000009, + "417": 113.50000000000003, + "418": 60.449999999999946, + "419": 113.0500000000001, + "420": 116.30000000000008, + "421": 115.6500000000001, + "422": 109.85000000000014, + "423": 106.20000000000006, + "424": 113.39999999999999, + "425": 110.05000000000014, + "426": 116.0500000000001, + "427": 105.54999999999988, + "428": 66.64999999999996, + "429": 112.95000000000013, + "430": 112.45000000000012, + "431": 108.85000000000004, + "432": 109.45000000000007, + "433": 103.80000000000005, + "434": 98.15000000000009, + "435": 114.19999999999996, + "436": 107.15000000000015, + "437": 109.70000000000009, + "438": 109.20000000000007, + "439": 80.25000000000004, + "440": 117.00000000000001, + "441": 106.5500000000002, + "442": 106.19999999999995, + "443": 113.40000000000009, + "444": 105.15000000000002, + "445": 72.94999999999993, + "446": 113.15000000000009, + "447": 106.70000000000019, + "448": 101.45, + "449": 96.2500000000001, + "450": 118.35000000000011, + "451": 107.9000000000001, + "452": 107.34999999999995, + "453": 109.95000000000009, + "454": 123.40000000000006, + "455": 97.00000000000007, + "456": 96.55000000000004, + "457": 119.05000000000004, + "458": 108.00000000000009, + "459": 106.35000000000018, + "460": 114.65000000000012, + "461": 116.30000000000005, + "462": 120.35000000000022, + "463": 106.85000000000008, + "464": 111.6000000000001, + "465": 111.94999999999997, + "466": 110.60000000000014, + "467": 109.20000000000007, + "468": 104.15000000000005, + "469": 110.05000000000003, + "470": 117.29999999999998, + "471": 98.20000000000005, + "472": 112.80000000000022, + "473": 107.50000000000013, + "474": 90.05000000000007, + "475": 105.50000000000018, + "476": 106.65000000000009, + "477": 114.65000000000013, + "478": 115.8000000000001, + "479": 103.80000000000007, + "480": 100.35000000000007, + "481": 112.89999999999999, + "482": 105.70000000000005, + "483": 96.1500000000002, + "484": 77.05000000000001, + "485": 109.65000000000012, + "486": 105.65000000000008, + "487": 116.89999999999996, + "488": 116.04999999999997, + "489": 102.6999999999999, + "490": 117.1500000000001, + "491": 8.200000000000056, + "492": 114.70000000000005, + "493": -66.89999999999992, + "494": 113.40000000000013, + "495": 105.79999999999994, + "496": 115.0500000000002, + "497": 106.35000000000005, + "498": 103.05000000000013, + "499": 107.10000000000016, + "500": 112.40000000000002, + "501": 111.15, + "502": 115.50000000000001, + "503": 118.90000000000015, + "504": -69.24999999999989, + "505": 111.45000000000006, + "506": 106.15000000000005, + "507": 105.45000000000014, + "508": 107.45000000000003, + "509": 116.20000000000009, + "510": 104.2500000000001, + "511": 108.70000000000003, + "512": 56.39999999999984, + "513": 89.50000000000017, + "514": 112.10000000000001, + "515": 112.45000000000009, + "516": 115.54999999999991, + "517": 116.55000000000007, + "518": 112.50000000000026, + "519": 88.6000000000001, + "520": 114.30000000000007, + "521": 113.69999999999999, + "522": 112.15000000000005, + "523": 110.0999999999999, + "524": 100.09999999999994, + "525": 106.70000000000009, + "526": 111.50000000000001, + "527": 112.05000000000008, + "528": 112.95000000000003, + "529": 109.19999999999999, + "530": 110.20000000000002, + "531": 115.44999999999995, + "532": 113.60000000000016, + "533": 37.39999999999986, + "534": 119.25000000000011, + "535": 110.99999999999994, + "536": 119.75000000000014, + "537": 112.40000000000015, + "538": 120.00000000000013, + "539": 103.85000000000008, + "540": 112.35000000000007, + "541": 115.60000000000015, + "542": 118.69999999999999, + "543": 110.44999999999997, + "544": 116.8500000000001, + "545": 107.75000000000016, + "546": 112.50000000000017, + "547": 114.45000000000017, + "548": 108.9000000000002, + "549": 110.30000000000018, + "550": 107.60000000000005, + "551": 114.50000000000016, + "552": 114.25000000000009, + "553": 113.90000000000006, + "554": 113.85000000000007, + "555": 114.75000000000018, + "556": 109.15000000000006, + "557": 105.14999999999999, + "558": 119.70000000000007, + "559": 115.99999999999997, + "560": 102.70000000000003, + "561": 115.35000000000008, + "562": 109.70000000000013, + "563": 110.9, + "564": 112.6000000000002, + "565": 117.00000000000011, + "566": 111.7000000000001, + "567": 116.95000000000009, + "568": 104.59999999999982, + "569": 119.95000000000007, + "570": 109.7500000000001, + "571": 119.84999999999998, + "572": 108.55, + "573": 95.05000000000001, + "574": 119.80000000000018, + "575": 115.4000000000002, + "576": 104.20000000000005, + "577": 110.60000000000012, + "578": 111.80000000000014, + "579": 117.0000000000001, + "580": 111.75000000000009, + "581": 103.55000000000014, + "582": 115.70000000000005, + "583": 112.30000000000022, + "584": 47.04999999999993, + "585": 114.10000000000011, + "586": 109.90000000000008, + "587": 107.05000000000015, + "588": 112.80000000000013, + "589": 104.85000000000004, + "590": 100.14999999999993, + "591": 102.64999999999999, + "592": 91.59999999999995, + "593": 108.30000000000008, + "594": 110.55000000000004, + "595": 87.1000000000002, + "596": 109.3000000000001, + "597": 100.95000000000012, + "598": 110.85000000000001, + "599": 110.70000000000009, + "600": 117.30000000000013, + "601": 113.1500000000001, + "602": 117.40000000000012, + "603": 109.39999999999998, + "604": 118.05000000000022, + "605": 109.95000000000003, + "606": 108.85000000000011, + "607": 115.05000000000004, + "608": 116.45000000000016, + "609": 106.50000000000013, + "610": 59.29999999999985, + "611": 112.25000000000004, + "612": 108.05000000000005, + "613": 116.10000000000008, + "614": 106.10000000000005, + "615": 105.20000000000006, + "616": 107.89999999999998, + "617": 116.80000000000001, + "618": 110.90000000000016, + "619": 118.65000000000009, + "620": 109.3500000000001, + "621": 111.05, + "622": 110.85000000000011, + "623": 109.04999999999991, + "624": 109.95000000000009, + "625": 105.15000000000006, + "626": 109.25000000000011, + "627": 109.80000000000008, + "628": 112.15000000000023, + "629": 112.15000000000018, + "630": 106.99999999999991, + "631": 108.70000000000009, + "632": 112.75, + "633": 107.75000000000007, + "634": 115.30000000000007, + "635": 118.90000000000019, + "636": 114.00000000000009, + "637": 105.00000000000003, + "638": 115.05000000000014, + "639": 111.05000000000003, + "640": 105.75000000000011, + "641": 121.00000000000016, + "642": 111.9000000000001, + "643": 123.00000000000003, + "644": 109.15000000000002, + "645": 76.15000000000003, + "646": 108.99999999999999, + "647": 116.00000000000003, + "648": 114.80000000000004, + "649": 105.69999999999993, + "650": 117.65000000000018, + "651": 102.90000000000012, + "652": 109.80000000000008, + "653": 107.19999999999985, + "654": 110.50000000000009, + "655": 115.05000000000003, + "656": 115.30000000000015, + "657": 117.30000000000011, + "658": 112.70000000000017, + "659": 106.35000000000014, + "660": 110.8, + "661": 115.55000000000003, + "662": 108.70000000000007, + "663": 106.29999999999997, + "664": 107.60000000000004, + "665": 117.10000000000012, + "666": 116.20000000000007, + "667": 112.30000000000021, + "668": 112.30000000000004, + "669": 117.85000000000001, + "670": 103.75000000000011, + "671": 111.0500000000001, + "672": 108.30000000000008, + "673": 109.85000000000016, + "674": 112.0000000000001, + "675": 116.35000000000022, + "676": 103.95000000000003, + "677": 103.30000000000003, + "678": 107.20000000000005, + "679": 116.70000000000012, + "680": 102.80000000000013, + "681": 101.84999999999995, + "682": 101.54999999999997, + "683": 97.60000000000002, + "684": 107.25000000000007, + "685": 118.70000000000003, + "686": 119.25000000000007, + "687": 107.59999999999994, + "688": 115.60000000000011, + "689": 114.15000000000006, + "690": 116.2000000000001, + "691": 109.35000000000008, + "692": 106.69999999999983, + "693": 118.95000000000016, + "694": 108.80000000000005, + "695": 117.2500000000001, + "696": 117.85000000000004, + "697": 116.05000000000007, + "698": 105.95000000000002, + "699": 104.0, + "700": 114.60000000000014, + "701": 107.19999999999987, + "702": 113.90000000000008, + "703": 108.44999999999997, + "704": 118.2000000000001, + "705": 117.15000000000009, + "706": 88.59999999999992, + "707": 113.7500000000001, + "708": 109.85000000000004, + "709": 112.40000000000006, + "710": 107.15000000000002, + "711": 115.8000000000002, + "712": 119.05000000000017, + "713": 113.4000000000001, + "714": 116.15000000000013, + "715": 110.50000000000007, + "716": 108.50000000000004, + "717": 108.90000000000012, + "718": 115.50000000000001, + "719": 121.30000000000022, + "720": 109.50000000000011, + "721": 106.15000000000006, + "722": 116.4000000000001, + "723": 114.65000000000005, + "724": 112.50000000000017, + "725": 108.20000000000016, + "726": 117.55000000000004, + "727": 112.05000000000014, + "728": 103.85000000000008, + "729": 101.69999999999999, + "730": 112.45, + "731": 107.45000000000009, + "732": 113.15000000000009, + "733": 107.3500000000002, + "734": 112.40000000000005, + "735": 114.70000000000016, + "736": 101.00000000000001, + "737": 114.95000000000005, + "738": 113.35000000000004, + "739": 106.05000000000004, + "740": 108.10000000000022, + "741": 100.29999999999998, + "742": 113.45000000000014, + "743": 107.75, + "744": 113.35000000000014, + "745": 115.80000000000014, + "746": 117.0500000000001, + "747": 112.10000000000018, + "748": 114.60000000000015, + "749": 101.55000000000005, + "750": 108.9000000000001, + "751": 111.15000000000005, + "752": 110.80000000000001, + "753": 102.6499999999999, + "754": 118.75000000000016, + "755": 102.35000000000005, + "756": 101.75000000000014, + "757": 109.70000000000016, + "758": 94.15000000000003, + "759": 108.69999999999993, + "760": 119.20000000000005, + "761": 97.60000000000014, + "762": 108.30000000000014, + "763": 114.20000000000005, + "764": 111.45000000000017, + "765": 109.00000000000004, + "766": 114.6000000000001, + "767": 102.60000000000014, + "768": 108.60000000000012, + "769": 106.10000000000014, + "770": 114.10000000000002, + "771": 107.6000000000001, + "772": 114.59999999999998, + "773": 111.80000000000003, + "774": 110.55000000000003, + "775": 105.60000000000002, + "776": 109.85000000000007, + "777": 111.24999999999997, + "778": 113.85000000000008, + "779": 106.8999999999999, + "780": 107.75000000000001, + "781": 108.05000000000014, + "782": 111.29999999999995, + "783": 111.90000000000008, + "784": 95.74999999999994, + "785": 109.2000000000001, + "786": 108.60000000000015, + "787": 104.80000000000005, + "788": 106.00000000000007, + "789": 107.84999999999992, + "790": 116.5, + "791": 105.6, + "792": 116.15000000000008, + "793": 107.85000000000011, + "794": 111.15000000000013, + "795": 113.1500000000001, + "796": 115.00000000000016, + "797": 106.49999999999997, + "798": 104.40000000000006, + "799": 110.90000000000009, + "800": 114.35000000000026, + "801": 115.5500000000002, + "802": 112.59999999999998, + "803": 114.45000000000002, + "804": 109.40000000000012, + "805": 109.35000000000005, + "806": 110.1, + "807": 102.6000000000002, + "808": 112.59999999999997, + "809": 106.90000000000005, + "810": 106.05000000000003, + "811": 115.35000000000004, + "812": 94.34999999999998, + "813": 116.04999999999995, + "814": 112.95000000000017, + "815": 106.00000000000001, + "816": 117.39999999999995, + "817": 119.8500000000001, + "818": 117.6500000000002, + "819": 98.2, + "820": 115.75000000000023, + "821": -33.549999999999976, + "822": 113.9500000000001, + "823": 112.60000000000004, + "824": 107.60000000000011, + "825": 103.74999999999999, + "826": 113.95000000000017, + "827": 116.00000000000017, + "828": 105.60000000000008, + "829": 109.64999999999995, + "830": 110.70000000000002, + "831": 111.35000000000005, + "832": 117.80000000000017, + "833": 99.9, + "834": 105.14999999999998, + "835": 110.55000000000004, + "836": 110.60000000000001, + "837": 116.2, + "838": 116.95000000000013, + "839": 115.30000000000004, + "840": 104.60000000000014, + "841": 107.75000000000009, + "842": 112.34999999999997, + "843": 106.2500000000001, + "844": 113.45000000000026, + "845": 108.59999999999998, + "846": 107.5, + "847": 119.65000000000012, + "848": 111.55000000000014, + "849": 108.25000000000007, + "850": 106.35000000000016, + "851": 99.55000000000015, + "852": 113.00000000000018, + "853": 113.40000000000006, + "854": 109.85000000000008, + "855": 117.40000000000002, + "856": 113.5, + "857": 101.39999999999993, + "858": 111.45000000000012, + "859": 77.99999999999986, + "860": 109.65000000000006, + "861": 113.15000000000019, + "862": 108.60000000000001, + "863": 109.15000000000016, + "864": 115.70000000000002, + "865": 108.60000000000004, + "866": 112.45000000000016, + "867": 114.90000000000008, + "868": 104.25000000000014, + "869": 104.85000000000011, + "870": 111.35, + "871": 112.9500000000001, + "872": 114.35000000000018, + "873": 103.90000000000012, + "874": 115.55000000000011, + "875": 111.20000000000016, + "876": 108.65000000000009, + "877": 119.45000000000013, + "878": 107.99999999999991, + "879": 108.65000000000015, + "880": 117.55000000000001, + "881": 108.60000000000024, + "882": 114.7500000000001, + "883": 104.2000000000001, + "884": 112.50000000000014, + "885": 109.74999999999993, + "886": 114.20000000000006, + "887": 114.45000000000024, + "888": 118.39999999999992, + "889": 107.1000000000001, + "890": 114.95000000000013, + "891": 105.40000000000002, + "892": 122.45, + "893": 118.30000000000013, + "894": 113.45000000000024, + "895": 113.85000000000011, + "896": 115.10000000000018, + "897": 115.05000000000014, + "898": 105.10000000000005, + "899": 96.3499999999999, + "900": 102.40000000000006, + "901": 113.20000000000014, + "902": 109.74999999999997, + "903": 110.65000000000006, + "904": 109.70000000000013, + "905": 119.19999999999999, + "906": 63.450000000000024, + "907": 115.90000000000006, + "908": 115.8000000000002, + "909": 109.15000000000009, + "910": 111.20000000000007, + "911": 121.30000000000021, + "912": 108.14999999999993, + "913": 108.19999999999995, + "914": 108.4500000000001, + "915": 111.29999999999995, + "916": 40.54999999999992, + "917": 114.0500000000001, + "918": 116.90000000000013, + "919": 103.94999999999986, + "920": 119.65000000000025, + "921": 111.85000000000011, + "922": 116.55000000000021, + "923": 98.4500000000001, + "924": 116.55, + "925": 115.55000000000008, + "926": 45.149999999999956, + "927": 77.70000000000017, + "928": 109.00000000000013, + "929": 81.95000000000012, + "930": 67.94999999999989, + "931": 63.54999999999981, + "932": 114.55000000000011, + "933": 86.10000000000014, + "934": 105.85000000000005, + "935": 111.1500000000003, + "936": 107.6000000000001, + "937": 112.4000000000001, + "938": 108.55000000000001, + "939": 120.00000000000004, + "940": 89.00000000000003, + "941": 89.54999999999994, + "942": 89.80000000000008, + "943": 82.35000000000004, + "944": 97.70000000000013, + "945": 84.64999999999985, + "946": 112.20000000000016, + "947": 121.50000000000003, + "948": 114.14999999999993, + "949": 5.8000000000000185, + "950": 117.10000000000002, + "951": 110.90000000000009, + "952": 101.95000000000016, + "953": 94.90000000000008, + "954": 112.85000000000012, + "955": 112.85000000000014, + "956": 113.35000000000001, + "957": 109.25000000000006, + "958": 108.34999999999997, + "959": 103.39999999999998, + "960": 110.70000000000019, + "961": 109.05000000000017, + "962": 110.65000000000009, + "963": 115.85000000000001, + "964": 110.15000000000002, + "965": 103.4500000000001, + "966": 83.95000000000017, + "967": 120.45000000000003, + "968": 109.05000000000005, + "969": 119.05000000000011, + "970": 98.60000000000005, + "971": 116.3500000000001, + "972": 95.70000000000006, + "973": 108.55000000000021, + "974": 118.65000000000012, + "975": 114.55000000000013, + "976": 108.4, + "977": 104.65000000000019, + "978": 111.55000000000001, + "979": 113.99999999999997, + "980": 82.50000000000011, + "981": 106.40000000000002, + "982": 39.69999999999989, + "983": 104.95000000000007, + "984": 112.49999999999994, + "985": 108.79999999999988, + "986": 113.40000000000018, + "987": 110.7500000000002, + "988": 118.85000000000001, + "989": 116.9500000000001, + "990": 114.75000000000003, + "991": 112.9000000000001, + "992": 106.60000000000008, + "993": 104.49999999999997, + "994": 117.05000000000014, + "995": 114.20000000000013, + "996": 113.60000000000016, + "997": 95.30000000000013, + "998": 106.89999999999982, + "999": 118.45000000000007, + "1000": 116.3000000000001 + } +} \ No newline at end of file diff --git a/benchmark/results/v3/v3.1.0/v3.1.0_benchmark_metadata.json b/benchmark/results/v3/v3.1.0/v3.1.0_benchmark_metadata.json new file mode 100644 index 00000000..a3418c6a --- /dev/null +++ b/benchmark/results/v3/v3.1.0/v3.1.0_benchmark_metadata.json @@ -0,0 +1,7444 @@ +{ + "start_timestamp": "2024-07-20T16:20:43.893936", + "end_datetime": "2024-07-20T18:36:49.588974", + "primaite_version": "3.1.0", + "system_info": { + "System": { + "OS": "Linux", + "OS Version": "#76~20.04.1-Ubuntu SMP Thu Jun 13 18:00:23 UTC 2024", + "Machine": "x86_64", + "Processor": "x86_64" + }, + "CPU": { + "Physical Cores": 2, + "Total Cores": 4, + "Max Frequency": "0.00Mhz" + }, + "Memory": { + "Total": "15.62GB", + "Swap Total": "0.00B" + }, + "GPU": [] + }, + "total_sessions": 5, + "total_episodes": 5005, + "total_time_steps": 640000, + "av_s_per_session": 1632.8887714, + "av_s_per_step": 0.05102777410624999, + "av_s_per_100_steps_10_nodes": 5.1027774106249995, + "combined_total_reward_per_episode": { + "1": -38.75000000000004, + "2": -17.899999999999977, + "3": -37.23000000000003, + "4": -49.170000000000016, + "5": -35.91000000000004, + "6": -27.929999999999996, + "7": -28.03000000000001, + "8": -36.070000000000036, + "9": -55.67999999999999, + "10": -50.050000000000004, + "11": -38.84999999999999, + "12": -34.999999999999986, + "13": -36.22999999999998, + "14": -34.77, + "15": -24.369999999999976, + "16": -45.92999999999999, + "17": -53.110000000000056, + "18": -21.650000000000002, + "19": -31.960000000000036, + "20": -35.13000000000004, + "21": -26.350000000000023, + "22": -18.189999999999962, + "23": -28.729999999999983, + "24": -34.94000000000001, + "25": -29.669999999999987, + "26": -35.459999999999965, + "27": -24.44999999999998, + "28": -36.19999999999999, + "29": -35.280000000000015, + "30": -43.12000000000001, + "31": -40.96999999999999, + "32": -54.110000000000035, + "33": -27.599999999999987, + "34": -14.889999999999992, + "35": -36.140000000000036, + "36": -42.679999999999986, + "37": -22.159999999999968, + "38": -14.32999999999998, + "39": -19.12999999999997, + "40": -28.40999999999999, + "41": -20.80000000000001, + "42": -35.79999999999997, + "43": -31.049999999999972, + "44": -51.30999999999999, + "45": -11.72999999999998, + "46": -22.969999999999988, + "47": -38.860000000000014, + "48": -20.999999999999993, + "49": -24.379999999999985, + "50": -29.909999999999975, + "51": -18.779999999999966, + "52": -28.829999999999977, + "53": -57.959999999999994, + "54": -48.90000000000002, + "55": -18.389999999999983, + "56": -13.119999999999987, + "57": -22.760000000000005, + "58": -19.939999999999962, + "59": -19.650000000000002, + "60": -14.849999999999975, + "61": -24.90999999999999, + "62": -16.84999999999997, + "63": -19.089999999999968, + "64": -18.02999999999999, + "65": -18.859999999999978, + "66": -30.900000000000016, + "67": -15.739999999999977, + "68": -17.86999999999997, + "69": -16.169999999999977, + "70": -11.489999999999968, + "71": -27.27000000000003, + "72": -16.99999999999997, + "73": -30.319999999999986, + "74": -12.269999999999978, + "75": -13.979999999999972, + "76": -28.930000000000017, + "77": -26.479999999999983, + "78": -29.72999999999998, + "79": -38.07, + "80": -33.110000000000014, + "81": -15.599999999999977, + "82": -22.34999999999999, + "83": -14.210000000000013, + "84": -29.43999999999998, + "85": -20.599999999999973, + "86": -7.739999999999976, + "87": -16.989999999999974, + "88": -31.55, + "89": -41.36999999999998, + "90": -8.28999999999998, + "91": -42.15, + "92": -24.459999999999997, + "93": -8.859999999999976, + "94": -25.96, + "95": -13.759999999999982, + "96": -25.379999999999978, + "97": -27.729999999999997, + "98": -2.199999999999965, + "99": -29.309999999999974, + "100": -10.489999999999972, + "101": -19.18999999999999, + "102": -29.47999999999999, + "103": -26.779999999999994, + "104": -34.94999999999999, + "105": -26.50999999999997, + "106": -7.469999999999966, + "107": -14.789999999999974, + "108": -3.4899999999999975, + "109": -43.17999999999999, + "110": -25.809999999999974, + "111": -7.099999999999977, + "112": -13.30999999999997, + "113": 1.8499999999999261, + "114": -52.04999999999997, + "115": -16.009999999999977, + "116": -0.4600000000000195, + "117": -6.400000000000011, + "118": -38.99, + "119": -21.199999999999967, + "120": -10.339999999999977, + "121": -22.090000000000003, + "122": 1.960000000000014, + "123": -13.939999999999989, + "124": -20.619999999999987, + "125": -28.589999999999993, + "126": -22.039999999999996, + "127": -9.7, + "128": -11.28999999999996, + "129": 1.9399999999999946, + "130": -40.61000000000001, + "131": -5.429999999999984, + "132": -20.51999999999998, + "133": 8.43999999999998, + "134": -30.580000000000013, + "135": 4.480000000000008, + "136": -18.09999999999997, + "137": -19.629999999999974, + "138": 6.839999999999972, + "139": -8.549999999999988, + "140": -15.299999999999978, + "141": -4.810000000000024, + "142": -30.53999999999998, + "143": -14.570000000000016, + "144": -14.12999999999999, + "145": -7.649999999999989, + "146": -24.809999999999995, + "147": -33.43000000000003, + "148": -28.95999999999998, + "149": -17.90999999999998, + "150": -40.879999999999995, + "151": -9.389999999999976, + "152": -2.429999999999977, + "153": -12.849999999999971, + "154": -17.15000000000001, + "155": -35.10999999999999, + "156": -45.910000000000004, + "157": -4.799999999999987, + "158": -41.71999999999997, + "159": -19.620000000000005, + "160": -12.899999999999977, + "161": -10.49999999999997, + "162": 15.970000000000022, + "163": -36.089999999999975, + "164": -23.640000000000065, + "165": -33.02999999999999, + "166": -22.94999999999998, + "167": -4.399999999999984, + "168": -3.7200000000000513, + "169": -10.209999999999997, + "170": -22.440000000000005, + "171": -40.18000000000001, + "172": -6.510000000000045, + "173": -22.97000000000002, + "174": 8.829999999999938, + "175": -21.370000000000008, + "176": -30.170000000000044, + "177": 3.58999999999997, + "178": -41.19000000000002, + "179": 4.949999999999987, + "180": -13.410000000000062, + "181": -30.23000000000001, + "182": -13.450000000000028, + "183": -13.080000000000016, + "184": -43.88999999999999, + "185": -40.669999999999995, + "186": 1.9500000000000255, + "187": -16.240000000000002, + "188": 0.4900000000000084, + "189": 0.4299999999999315, + "190": -4.939999999999991, + "191": 6.39999999999997, + "192": -26.300000000000033, + "193": -14.81999999999999, + "194": -19.010000000000026, + "195": -18.099999999999994, + "196": -12.930000000000012, + "197": -13.910000000000005, + "198": 10.18999999999993, + "199": -13.760000000000014, + "200": -34.79999999999998, + "201": 9.86999999999993, + "202": -21.969999999999988, + "203": -15.379999999999992, + "204": -4.219999999999973, + "205": 16.229999999999936, + "206": -10.850000000000051, + "207": -3.260000000000004, + "208": -19.369999999999983, + "209": -22.4, + "210": -32.920000000000016, + "211": -26.610000000000053, + "212": 7.990000000000006, + "213": -5.829999999999984, + "214": -7.33000000000002, + "215": -31.72000000000002, + "216": -19.4, + "217": 34.30999999999991, + "218": -15.460000000000033, + "219": -12.660000000000045, + "220": -1.3500000000000398, + "221": -12.359999999999989, + "222": -20.839999999999993, + "223": -24.809999999999985, + "224": 8.829999999999973, + "225": 24.059999999999917, + "226": 18.90999999999997, + "227": -8.910000000000021, + "228": 24.54000000000002, + "229": -43.889999999999986, + "230": 0.45999999999999036, + "231": 34.81999999999988, + "232": 9.289999999999935, + "233": -33.42999999999999, + "234": 2.6899999999999906, + "235": -7.910000000000022, + "236": 0.40999999999996817, + "237": -0.6000000000000071, + "238": -39.57000000000001, + "239": 35.979999999999976, + "240": 4.759999999999935, + "241": 4.249999999999984, + "242": 18.219999999999978, + "243": 8.98999999999998, + "244": -22.100000000000023, + "245": 16.619999999999926, + "246": 2.219999999999998, + "247": 7.779999999999996, + "248": -14.159999999999986, + "249": -10.390000000000018, + "250": -5.219999999999968, + "251": -3.8700000000000343, + "252": 7.6200000000000445, + "253": 43.51999999999993, + "254": -13.540000000000003, + "255": -11.730000000000036, + "256": 17.23999999999997, + "257": 31.57000000000003, + "258": 46.39999999999988, + "259": 17.869999999999926, + "260": 7.959999999999975, + "261": 34.09999999999999, + "262": 27.38999999999992, + "263": 20.469999999999978, + "264": 16.999999999999975, + "265": 16.29, + "266": 26.869999999999937, + "267": -14.689999999999987, + "268": 35.75000000000004, + "269": 29.749999999999932, + "270": 39.79999999999988, + "271": 23.099999999999913, + "272": 34.43999999999994, + "273": -18.980000000000047, + "274": 45.55999999999994, + "275": 11.259999999999955, + "276": 16.839999999999925, + "277": -22.270000000000017, + "278": -24.409999999999993, + "279": 29.60999999999995, + "280": 0.18999999999992098, + "281": -23.890000000000015, + "282": 35.939999999999955, + "283": 10.919999999999984, + "284": 22.70999999999997, + "285": 48.199999999999925, + "286": -13.039999999999964, + "287": 33.41999999999997, + "288": 47.560000000000045, + "289": 13.999999999999915, + "290": 1.429999999999957, + "291": 39.22999999999997, + "292": -5.160000000000054, + "293": 20.319999999999986, + "294": 31.370000000000022, + "295": 26.319999999999915, + "296": 35.290000000000035, + "297": 62.429999999999936, + "298": -8.050000000000026, + "299": 27.32999999999999, + "300": 37.33999999999992, + "301": 20.8599999999999, + "302": 36.21000000000004, + "303": 37.01999999999999, + "304": 27.61999999999991, + "305": 49.52000000000002, + "306": 35.40999999999998, + "307": 54.980000000000054, + "308": 51.83999999999992, + "309": 42.39000000000002, + "310": 9.879999999999939, + "311": 14.719999999999965, + "312": 28.90999999999999, + "313": 24.950000000000077, + "314": 35.79999999999997, + "315": 41.29000000000006, + "316": 37.19000000000004, + "317": 59.54999999999999, + "318": 57.799999999999976, + "319": 42.28999999999996, + "320": 59.61999999999999, + "321": 28.419999999999966, + "322": 19.009999999999984, + "323": 50.94999999999986, + "324": 44.62999999999994, + "325": 7.440000000000015, + "326": 33.19000000000003, + "327": 69.03999999999998, + "328": 36.98999999999993, + "329": 50.23000000000002, + "330": 36.569999999999965, + "331": 54.93000000000003, + "332": 52.830000000000005, + "333": 48.66999999999997, + "334": 67.43999999999991, + "335": 38.14000000000005, + "336": 41.59999999999998, + "337": 51.36999999999996, + "338": 64.96999999999998, + "339": 46.39, + "340": 60.18000000000002, + "341": 90.24000000000002, + "342": 48.779999999999994, + "343": 36.349999999999945, + "344": 26.67999999999998, + "345": 53.22000000000003, + "346": 22.320000000000036, + "347": 76.46999999999997, + "348": 64.83000000000004, + "349": 77.72000000000001, + "350": 50.89, + "351": 92.56000000000006, + "352": 81.37000000000009, + "353": 64.45, + "354": 55.71, + "355": 71.36000000000001, + "356": 64.08000000000004, + "357": 87.99000000000005, + "358": 83.89000000000001, + "359": 73.68000000000002, + "360": 66.91999999999993, + "361": 72.42, + "362": 67.25000000000003, + "363": 83.9800000000001, + "364": 57.08000000000004, + "365": 56.730000000000096, + "366": 62.38000000000003, + "367": 84.66000000000001, + "368": 70.69999999999993, + "369": 68.24999999999996, + "370": 74.25, + "371": 93.36000000000006, + "372": 84.88000000000001, + "373": 83.09000000000002, + "374": 58.07000000000001, + "375": 81.61999999999992, + "376": 85.63000000000001, + "377": 90.48999999999992, + "378": 85.83000000000007, + "379": 84.21000000000001, + "380": 72.95000000000003, + "381": 94.94000000000004, + "382": 79.05000000000004, + "383": 101.08000000000008, + "384": 90.47000000000006, + "385": 60.41000000000004, + "386": 83.73999999999998, + "387": 87.81000000000002, + "388": 93.63000000000011, + "389": 72.74000000000007, + "390": 99.73000000000008, + "391": 103.84000000000003, + "392": 84.66000000000001, + "393": 75.80000000000003, + "394": 94.29000000000005, + "395": 95.86, + "396": 82.13000000000008, + "397": 94.88, + "398": 98.06000000000007, + "399": 51.510000000000026, + "400": 111.42000000000004, + "401": 97.81000000000002, + "402": 88.70000000000002, + "403": 71.96999999999996, + "404": 85.55999999999996, + "405": 105.69000000000003, + "406": 78.51000000000005, + "407": 86.33000000000001, + "408": 83.89999999999996, + "409": 87.28999999999998, + "410": 97.74000000000008, + "411": 100.88000000000008, + "412": 110.71000000000011, + "413": 85.38000000000001, + "414": 100.83000000000006, + "415": 95.75000000000004, + "416": 111.85000000000007, + "417": 87.66000000000005, + "418": 77.05999999999992, + "419": 78.72, + "420": 99.45000000000005, + "421": 94.02000000000007, + "422": 74.96000000000004, + "423": 77.53000000000004, + "424": 75.54000000000005, + "425": 77.48999999999998, + "426": 110.0100000000001, + "427": 95.23000000000008, + "428": 76.74000000000008, + "429": 106.25000000000007, + "430": 104.08000000000007, + "431": 72.50999999999998, + "432": 105.79000000000003, + "433": 75.48000000000005, + "434": 99.87000000000003, + "435": 74.51000000000002, + "436": 72.87000000000003, + "437": 70.21000000000006, + "438": 94.85999999999997, + "439": 103.08000000000004, + "440": 105.9200000000001, + "441": 103.59000000000012, + "442": 94.21, + "443": 105.41000000000004, + "444": 99.19999999999999, + "445": 65.39000000000001, + "446": 91.93, + "447": 103.18999999999998, + "448": 109.74000000000004, + "449": 109.12000000000008, + "450": 101.70000000000012, + "451": 94.52000000000007, + "452": 93.66, + "453": 73.17000000000006, + "454": 95.03000000000009, + "455": 82.67000000000003, + "456": 104.16000000000011, + "457": 109.55999999999999, + "458": 105.38999999999999, + "459": 90.27000000000012, + "460": 103.78000000000011, + "461": 112.11000000000017, + "462": 110.57000000000014, + "463": 83.32000000000004, + "464": 103.36000000000004, + "465": 88.27000000000001, + "466": 69.34000000000007, + "467": 87.93000000000002, + "468": 100.52000000000002, + "469": 101.81000000000004, + "470": 96.12000000000003, + "471": 78.90000000000002, + "472": 102.95000000000005, + "473": 107.24000000000012, + "474": 98.88000000000007, + "475": 78.66, + "476": 88.72000000000006, + "477": 96.16000000000004, + "478": 92.7, + "479": 107.37000000000003, + "480": 98.61000000000014, + "481": 109.29000000000003, + "482": 104.56000000000009, + "483": 107.23000000000006, + "484": 106.47000000000011, + "485": 98.13, + "486": 95.08, + "487": 111.62000000000008, + "488": 105.64000000000001, + "489": 80.27999999999997, + "490": 81.7900000000001, + "491": 81.8500000000001, + "492": 90.36999999999998, + "493": 58.15000000000007, + "494": 103.4800000000001, + "495": 107.66000000000005, + "496": 108.6400000000001, + "497": 79.67, + "498": 107.34000000000006, + "499": 95.76000000000008, + "500": 103.28000000000004, + "501": 108.32000000000008, + "502": 98.84000000000003, + "503": 100.87000000000009, + "504": 66.77000000000012, + "505": 99.95000000000005, + "506": 105.32000000000005, + "507": 106.22, + "508": 82.39999999999995, + "509": 100.86000000000004, + "510": 112.48000000000017, + "511": 104.96, + "512": 88.77000000000002, + "513": 69.94000000000011, + "514": 88.83999999999995, + "515": 97.15000000000006, + "516": 106.38000000000008, + "517": 106.91, + "518": 112.49000000000005, + "519": 93.12, + "520": 85.3400000000001, + "521": 105.49000000000001, + "522": 103.03000000000009, + "523": 100.48999999999998, + "524": 85.90000000000005, + "525": 81.5, + "526": 100.41000000000004, + "527": 108.30000000000014, + "528": 97.75000000000003, + "529": 101.45000000000006, + "530": 104.58000000000004, + "531": 96.37000000000006, + "532": 101.28000000000009, + "533": 86.12999999999995, + "534": 102.7, + "535": 88.80000000000001, + "536": 108.61000000000008, + "537": 97.45, + "538": 110.11000000000013, + "539": 108.78000000000017, + "540": 113.25000000000004, + "541": 109.77000000000012, + "542": 96.29999999999998, + "543": 88.44999999999999, + "544": 94.60000000000011, + "545": 98.88000000000008, + "546": 110.74000000000015, + "547": 105.46000000000004, + "548": 83.77000000000001, + "549": 100.25000000000007, + "550": 91.17, + "551": 99.69000000000004, + "552": 107.77000000000007, + "553": 113.67000000000016, + "554": 82.26, + "555": 105.6100000000001, + "556": 79.78, + "557": 99.16999999999999, + "558": 106.8600000000001, + "559": 110.30000000000007, + "560": 104.71000000000004, + "561": 109.93000000000006, + "562": 112.36000000000008, + "563": 105.46000000000008, + "564": 107.00000000000009, + "565": 109.15000000000005, + "566": 106.38000000000007, + "567": 107.43000000000006, + "568": 102.70999999999997, + "569": 107.90000000000002, + "570": 107.95000000000013, + "571": 110.49000000000005, + "572": 111.50000000000004, + "573": 109.22000000000007, + "574": 111.53000000000011, + "575": 111.4400000000001, + "576": 104.82000000000002, + "577": 102.84000000000007, + "578": 115.38000000000011, + "579": 104.63000000000002, + "580": 111.78000000000006, + "581": 102.98000000000002, + "582": 111.0100000000001, + "583": 100.74000000000012, + "584": 100.21000000000012, + "585": 103.57000000000009, + "586": 107.10000000000005, + "587": 104.76000000000013, + "588": 108.14000000000014, + "589": 93.59, + "590": 104.14000000000006, + "591": 105.27000000000001, + "592": 103.49000000000004, + "593": 107.9300000000001, + "594": 107.10000000000005, + "595": 104.3500000000001, + "596": 104.07000000000014, + "597": 106.9700000000001, + "598": 96.24999999999999, + "599": 114.2200000000001, + "600": 113.6400000000001, + "601": 110.57000000000008, + "602": 106.33000000000011, + "603": 107.25000000000009, + "604": 112.94000000000014, + "605": 110.01000000000006, + "606": 98.16000000000001, + "607": 111.33000000000011, + "608": 108.16000000000004, + "609": 109.00000000000014, + "610": 98.04000000000005, + "611": 110.3500000000001, + "612": 105.82000000000005, + "613": 102.76000000000008, + "614": 105.03000000000004, + "615": 110.1100000000001, + "616": 108.51999999999998, + "617": 106.49000000000004, + "618": 102.74000000000008, + "619": 114.12000000000015, + "620": 108.3400000000001, + "621": 107.68000000000004, + "622": 99.74000000000004, + "623": 100.97000000000006, + "624": 105.48999999999997, + "625": 107.38000000000011, + "626": 104.3500000000001, + "627": 109.87000000000005, + "628": 91.75999999999999, + "629": 107.02000000000002, + "630": 112.2700000000001, + "631": 96.7100000000001, + "632": 100.31000000000004, + "633": 103.00000000000003, + "634": 111.66000000000001, + "635": 80.92000000000007, + "636": 99.47000000000003, + "637": 106.22000000000003, + "638": 103.48000000000009, + "639": 109.76000000000006, + "640": 110.54000000000012, + "641": 109.68000000000006, + "642": 92.05000000000004, + "643": 113.30000000000003, + "644": 110.03000000000006, + "645": 102.20000000000003, + "646": 98.50000000000003, + "647": 114.10000000000014, + "648": 91.05999999999999, + "649": 108.67000000000003, + "650": 112.97000000000014, + "651": 107.8000000000001, + "652": 94.73000000000009, + "653": 106.18000000000004, + "654": 112.23000000000006, + "655": 83.48999999999998, + "656": 110.7300000000001, + "657": 71.98000000000005, + "658": 107.25000000000014, + "659": 105.60000000000005, + "660": 101.80000000000011, + "661": 101.49, + "662": 106.28, + "663": 103.93000000000004, + "664": 108.05000000000007, + "665": 114.7700000000001, + "666": 111.87000000000008, + "667": 98.70000000000007, + "668": 109.99000000000005, + "669": 113.8000000000001, + "670": 94.97, + "671": 106.27000000000001, + "672": 105.40000000000009, + "673": 107.31000000000013, + "674": 108.15000000000009, + "675": 106.78000000000006, + "676": 108.41000000000001, + "677": 106.06000000000006, + "678": 106.75000000000007, + "679": 100.86000000000011, + "680": 104.76000000000006, + "681": 103.78000000000002, + "682": 107.38000000000004, + "683": 110.42000000000007, + "684": 107.21000000000004, + "685": 111.96000000000004, + "686": 106.49000000000005, + "687": 108.44000000000005, + "688": 109.15000000000012, + "689": 114.37000000000005, + "690": 109.39000000000006, + "691": 110.50000000000009, + "692": 112.94000000000005, + "693": 112.51000000000008, + "694": 110.92000000000007, + "695": 115.87000000000009, + "696": 108.00000000000003, + "697": 112.2900000000001, + "698": 110.18000000000009, + "699": 111.45000000000013, + "700": 111.44000000000005, + "701": 109.22000000000007, + "702": 111.16000000000004, + "703": 107.74000000000005, + "704": 112.84000000000006, + "705": 108.28000000000006, + "706": 107.16000000000004, + "707": 106.71000000000004, + "708": 108.19000000000001, + "709": 105.08000000000001, + "710": 92.66000000000005, + "711": 112.23000000000013, + "712": 106.73000000000006, + "713": 105.04000000000003, + "714": 113.18000000000009, + "715": 104.74000000000004, + "716": 109.30000000000014, + "717": 111.10000000000011, + "718": 103.91000000000004, + "719": 111.0200000000001, + "720": 110.90000000000006, + "721": 92.89000000000001, + "722": 97.37000000000005, + "723": 108.68000000000009, + "724": 106.5400000000001, + "725": 107.42000000000016, + "726": 110.66000000000005, + "727": 111.75000000000009, + "728": 107.36000000000008, + "729": 106.12000000000003, + "730": 108.72000000000007, + "731": 98.87000000000009, + "732": 87.60000000000011, + "733": 106.8100000000001, + "734": 112.60000000000007, + "735": 111.78000000000011, + "736": 107.37000000000003, + "737": 104.24000000000005, + "738": 102.13000000000007, + "739": 109.65000000000009, + "740": 108.16000000000004, + "741": 110.13000000000007, + "742": 105.16000000000005, + "743": 109.21000000000008, + "744": 110.57000000000012, + "745": 106.70000000000002, + "746": 111.31000000000006, + "747": 106.54000000000015, + "748": 110.40000000000006, + "749": 105.46000000000004, + "750": 111.22000000000007, + "751": 112.1700000000001, + "752": 110.99000000000005, + "753": 103.57000000000002, + "754": 112.07000000000008, + "755": 108.6000000000001, + "756": 111.07000000000014, + "757": 112.22000000000011, + "758": 108.28000000000006, + "759": 110.5, + "760": 113.14000000000006, + "761": 106.6000000000001, + "762": 105.99000000000005, + "763": 115.14000000000014, + "764": 110.64000000000007, + "765": 109.91000000000008, + "766": 102.49000000000005, + "767": 104.20000000000009, + "768": 109.21000000000008, + "769": 111.98000000000009, + "770": 112.25000000000007, + "771": 110.91000000000011, + "772": 97.54999999999998, + "773": 109.10000000000005, + "774": 103.70000000000016, + "775": 104.79000000000005, + "776": 106.46000000000008, + "777": 112.03000000000004, + "778": 109.82000000000008, + "779": 105.95000000000002, + "780": 106.43000000000006, + "781": 101.54000000000008, + "782": 113.92, + "783": 106.84000000000003, + "784": 100.78999999999999, + "785": 108.8000000000001, + "786": 98.99000000000007, + "787": 111.6100000000001, + "788": 97.76000000000002, + "789": 105.88000000000008, + "790": 99.95, + "791": 108.3500000000001, + "792": 102.41000000000012, + "793": 99.26000000000008, + "794": 109.28000000000009, + "795": 100.93000000000005, + "796": 97.67000000000002, + "797": 105.85000000000005, + "798": 103.58000000000004, + "799": 99.77000000000001, + "800": 109.51000000000015, + "801": 104.48000000000009, + "802": 72.75000000000003, + "803": 108.60000000000011, + "804": 109.8400000000001, + "805": 101.46, + "806": 110.68000000000006, + "807": 94.02000000000004, + "808": 104.19000000000003, + "809": 112.29000000000005, + "810": 107.88000000000002, + "811": 111.80000000000003, + "812": 105.55000000000007, + "813": 102.67000000000012, + "814": 111.6800000000001, + "815": 113.15000000000006, + "816": 110.65, + "817": 98.71000000000001, + "818": 99.51000000000005, + "819": 104.92000000000004, + "820": 103.23000000000016, + "821": 81.71000000000012, + "822": 111.62000000000003, + "823": 108.31000000000006, + "824": 110.76000000000003, + "825": 106.83000000000007, + "826": 104.3400000000001, + "827": 114.11000000000013, + "828": 109.90000000000009, + "829": 87.89999999999993, + "830": 113.59000000000007, + "831": 93.16000000000005, + "832": 108.37000000000003, + "833": 109.96000000000004, + "834": 92.66000000000001, + "835": 108.6000000000001, + "836": 112.46000000000004, + "837": 108.53000000000009, + "838": 99.01999999999998, + "839": 113.97000000000011, + "840": 92.99000000000015, + "841": 105.8500000000001, + "842": 105.11999999999998, + "843": 107.0200000000001, + "844": 108.45000000000007, + "845": 110.47000000000006, + "846": 100.60000000000005, + "847": 107.99000000000015, + "848": 104.96000000000004, + "849": 112.91000000000005, + "850": 99.45000000000005, + "851": 108.93000000000009, + "852": 108.18000000000004, + "853": 109.66000000000008, + "854": 105.36000000000008, + "855": 109.67000000000004, + "856": 110.97000000000006, + "857": 107.9, + "858": 109.82000000000005, + "859": 98.43999999999998, + "860": 108.69000000000005, + "861": 97.46000000000004, + "862": 98.47000000000001, + "863": 111.45000000000009, + "864": 112.10000000000005, + "865": 112.04000000000008, + "866": 108.97000000000011, + "867": 101.16, + "868": 106.69000000000003, + "869": 105.97000000000011, + "870": 109.78000000000004, + "871": 112.31000000000003, + "872": 111.87000000000008, + "873": 110.96000000000006, + "874": 105.75000000000004, + "875": 111.66000000000015, + "876": 107.80000000000007, + "877": 114.75000000000011, + "878": 84.64000000000006, + "879": 110.96000000000011, + "880": 112.99000000000005, + "881": 109.45000000000012, + "882": 99.55000000000004, + "883": 110.3900000000001, + "884": 110.4400000000001, + "885": 101.73000000000008, + "886": 115.60000000000007, + "887": 112.6700000000001, + "888": 108.83000000000004, + "889": 104.18000000000004, + "890": 111.51000000000006, + "891": 114.57000000000005, + "892": 114.82000000000008, + "893": 93.14000000000007, + "894": 113.74000000000005, + "895": 107.98000000000005, + "896": 111.7200000000001, + "897": 112.29000000000005, + "898": 103.41000000000005, + "899": 106.65, + "900": 111.28000000000009, + "901": 107.85000000000002, + "902": 108.26000000000003, + "903": 93.25000000000004, + "904": 106.71000000000012, + "905": 114.47000000000007, + "906": 98.98000000000005, + "907": 99.62000000000008, + "908": 114.88000000000008, + "909": 113.71000000000012, + "910": 108.98000000000006, + "911": 114.90000000000012, + "912": 111.01000000000006, + "913": 108.01000000000002, + "914": 111.03000000000011, + "915": 111.74000000000005, + "916": 98.9000000000001, + "917": 112.35000000000007, + "918": 97.42000000000002, + "919": 102.79000000000003, + "920": 111.12000000000012, + "921": 110.23000000000013, + "922": 89.48000000000006, + "923": 106.17000000000003, + "924": 105.37000000000003, + "925": 112.7700000000001, + "926": 96.89000000000001, + "927": 102.64000000000007, + "928": 110.0600000000001, + "929": 105.78000000000009, + "930": 92.89999999999999, + "931": 99.15000000000002, + "932": 111.03000000000009, + "933": 89.11000000000004, + "934": 98.07000000000008, + "935": 110.65000000000012, + "936": 91.85000000000001, + "937": 108.01000000000008, + "938": 108.98000000000006, + "939": 105.23000000000009, + "940": 109.27000000000007, + "941": 105.19000000000005, + "942": 106.67000000000004, + "943": 105.75000000000011, + "944": 104.85999999999999, + "945": 101.17999999999999, + "946": 107.9800000000001, + "947": 102.76000000000003, + "948": 106.5200000000001, + "949": 85.75000000000007, + "950": 102.25000000000003, + "951": 107.78000000000004, + "952": 106.57000000000002, + "953": 104.24000000000005, + "954": 105.66000000000015, + "955": 106.97000000000011, + "956": 107.14000000000006, + "957": 105.2, + "958": 97.76000000000002, + "959": 105.34000000000003, + "960": 110.05000000000007, + "961": 109.75000000000004, + "962": 91.37000000000005, + "963": 104.97000000000006, + "964": 96.37, + "965": 101.5000000000001, + "966": 95.70000000000013, + "967": 110.66000000000008, + "968": 108.66000000000008, + "969": 111.66000000000004, + "970": 103.81000000000002, + "971": 105.74000000000008, + "972": 99.71000000000004, + "973": 107.3900000000001, + "974": 113.6800000000001, + "975": 114.65000000000013, + "976": 103.64000000000006, + "977": 105.91000000000005, + "978": 112.49000000000005, + "979": 110.54000000000008, + "980": 103.63000000000004, + "981": 108.63000000000007, + "982": 95.24000000000002, + "983": 111.87000000000005, + "984": 104.40000000000009, + "985": 84.48999999999998, + "986": 93.33000000000004, + "987": 108.59000000000017, + "988": 112.27000000000002, + "989": 102.25000000000006, + "990": 110.26000000000003, + "991": 109.51000000000008, + "992": 98.45000000000005, + "993": 108.23000000000005, + "994": 114.27000000000012, + "995": 95.12000000000005, + "996": 110.10000000000007, + "997": 113.11000000000008, + "998": 107.65000000000005, + "999": 111.74000000000005, + "1000": 108.76000000000013 + }, + "session_total_reward_per_episode": { + "1": { + "1": -12.399999999999993, + "2": -20.699999999999964, + "3": -7.899999999999991, + "4": -19.549999999999965, + "5": -12.999999999999982, + "6": -22.649999999999952, + "7": -31.350000000000023, + "8": -35.75000000000003, + "9": -67.30000000000007, + "10": -44.900000000000055, + "11": -18.199999999999978, + "12": -21.199999999999957, + "13": -15.599999999999977, + "14": -19.749999999999964, + "15": -18.149999999999988, + "16": -28.000000000000014, + "17": -83.05000000000001, + "18": -39.05000000000012, + "19": -46.800000000000146, + "20": -21.199999999999957, + "21": -23.64999999999999, + "22": -15.999999999999968, + "23": -65.90000000000008, + "24": -35.700000000000024, + "25": -65.04999999999995, + "26": -20.349999999999962, + "27": -18.899999999999963, + "28": -78.39999999999998, + "29": -23.799999999999947, + "30": -96.1, + "31": -60.1, + "32": -31.350000000000023, + "33": -87.05000000000001, + "34": -33.35000000000002, + "35": -15.399999999999983, + "36": -58.40000000000001, + "37": -22.949999999999953, + "38": -12.249999999999986, + "39": -7.000000000000012, + "40": -55.90000000000002, + "41": 3.1499999999999906, + "42": -18.499999999999968, + "43": -84.3, + "44": -10.99999999999999, + "45": -9.54999999999999, + "46": -12.199999999999992, + "47": -16.74999999999997, + "48": -19.499999999999964, + "49": -16.84999999999997, + "50": -77.3, + "51": -19.14999999999997, + "52": -95.29999999999997, + "53": -102.55, + "54": -6.549999999999996, + "55": -18.049999999999965, + "56": -11.849999999999984, + "57": -17.149999999999974, + "58": -20.74999999999996, + "59": -16.64999999999997, + "60": -16.049999999999958, + "61": -64.80000000000005, + "62": -19.299999999999958, + "63": -16.799999999999976, + "64": -70.55000000000004, + "65": -17.799999999999972, + "66": -28.050000000000022, + "67": -12.949999999999989, + "68": -19.699999999999964, + "69": -17.89999999999997, + "70": -11.599999999999989, + "71": -86.5500000000001, + "72": -18.34999999999997, + "73": -20.84999999999996, + "74": -19.549999999999958, + "75": -22.149999999999956, + "76": -2.899999999999988, + "77": -19.949999999999964, + "78": -22.74999999999995, + "79": -23.249999999999968, + "80": -50.50000000000011, + "81": -59.499999999999964, + "82": -16.299999999999976, + "83": -7.649999999999995, + "84": -19.999999999999968, + "85": -22.049999999999955, + "86": 1.0000000000000304, + "87": -18.19999999999997, + "88": -16.44999999999998, + "89": -16.099999999999973, + "90": -14.299999999999983, + "91": -4.149999999999981, + "92": -22.399999999999952, + "93": -13.44999999999999, + "94": -8.649999999999999, + "95": -16.449999999999978, + "96": -14.599999999999984, + "97": -6.500000000000002, + "98": -16.649999999999974, + "99": -22.99999999999995, + "100": -20.74999999999996, + "101": -22.649999999999952, + "102": -11.699999999999989, + "103": -15.749999999999972, + "104": -40.099999999999966, + "105": -81.95000000000002, + "106": -19.249999999999947, + "107": -8.699999999999989, + "108": -6.399999999999987, + "109": -72.85000000000001, + "110": 5.900000000000017, + "111": -18.599999999999966, + "112": -15.19999999999998, + "113": -19.199999999999964, + "114": -7.949999999999991, + "115": -18.699999999999967, + "116": -16.899999999999974, + "117": -6.499999999999993, + "118": -61.44999999999998, + "119": -63.95, + "120": -13.249999999999982, + "121": -64.65000000000002, + "122": -10.949999999999996, + "123": -9.149999999999997, + "124": -15.249999999999972, + "125": -22.199999999999953, + "126": 4.699999999999991, + "127": -15.349999999999977, + "128": 13.55000000000005, + "129": -14.349999999999985, + "130": -19.249999999999964, + "131": -10.299999999999995, + "132": -19.04999999999997, + "133": 7.149999999999976, + "134": -7.7999999999999865, + "135": -3.7999999999999776, + "136": -12.799999999999986, + "137": -0.4999999999999678, + "138": -8.250000000000018, + "139": -18.249999999999968, + "140": -14.649999999999983, + "141": -13.949999999999985, + "142": 9.25000000000005, + "143": -7.849999999999999, + "144": -87.00000000000001, + "145": -28.99999999999997, + "146": 2.4000000000000288, + "147": -74.05, + "148": -10.199999999999992, + "149": -10.4, + "150": -12.799999999999986, + "151": -15.849999999999978, + "152": 3.419486915845482e-14, + "153": -5.649999999999984, + "154": -10.999999999999993, + "155": -59.55, + "156": 15.600000000000001, + "157": -2.6499999999999977, + "158": -79.10000000000001, + "159": -90.7, + "160": -4.049999999999983, + "161": -12.949999999999989, + "162": 4.100000000000027, + "163": -5.849999999999999, + "164": -84.40000000000012, + "165": -21.599999999999955, + "166": -10.049999999999985, + "167": -11.649999999999993, + "168": 9.35000000000003, + "169": -13.049999999999986, + "170": -68.10000000000001, + "171": -75.90000000000008, + "172": -45.750000000000085, + "173": -68.35000000000002, + "174": 6.100000000000035, + "175": -9.650000000000002, + "176": -13.499999999999984, + "177": -7.049999999999989, + "178": -10.249999999999991, + "179": -21.249999999999957, + "180": -21.849999999999987, + "181": -47.150000000000055, + "182": -0.6999999999999749, + "183": -14.250000000000018, + "184": -23.700000000000017, + "185": 5.250000000000005, + "186": -3.249999999999984, + "187": -63.14999999999999, + "188": -12.349999999999996, + "189": -93.65, + "190": -6.199999999999985, + "191": 6.500000000000043, + "192": -10.29999999999999, + "193": 2.100000000000028, + "194": -86.95, + "195": -37.900000000000034, + "196": -6.2499999999999885, + "197": 7.350000000000065, + "198": -10.550000000000011, + "199": -20.39999999999996, + "200": -13.24999999999998, + "201": 14.24999999999979, + "202": -19.899999999999963, + "203": -0.6499999999999813, + "204": -9.049999999999997, + "205": -4.549999999999979, + "206": 20.949999999999967, + "207": -5.949999999999997, + "208": 4.650000000000053, + "209": -8.399999999999999, + "210": -86.19999999999996, + "211": -84.75000000000001, + "212": 6.550000000000047, + "213": -4.64999999999998, + "214": -85.5, + "215": -82.0, + "216": -16.099999999999977, + "217": 11.40000000000002, + "218": -43.05000000000001, + "219": -86.60000000000002, + "220": -36.45000000000005, + "221": -74.3, + "222": -75.05000000000001, + "223": -2.5999999999999712, + "224": -5.649999999999983, + "225": -2.1999999999999726, + "226": -9.299999999999999, + "227": -82.40000000000003, + "228": -13.899999999999986, + "229": -14.849999999999971, + "230": -17.399999999999995, + "231": 19.24999999999998, + "232": -19.449999999999964, + "233": -17.899999999999967, + "234": -78.0, + "235": -84.49999999999996, + "236": -50.5, + "237": -13.899999999999979, + "238": -99.1, + "239": -1.300000000000021, + "240": -6.949999999999983, + "241": -43.550000000000004, + "242": -17.249999999999975, + "243": -18.29999999999997, + "244": -10.099999999999998, + "245": -60.100000000000016, + "246": -22.499999999999954, + "247": 39.84999999999994, + "248": -17.449999999999974, + "249": 16.30000000000005, + "250": -21.34999999999996, + "251": 7.900000000000035, + "252": -75.19999999999999, + "253": 37.09999999999979, + "254": 2.7000000000000215, + "255": -28.19999999999994, + "256": -17.499999999999975, + "257": 4.050000000000029, + "258": 29.249999999999872, + "259": -39.55000000000011, + "260": -29.10000000000001, + "261": -5.900000000000009, + "262": -16.849999999999973, + "263": 7.100000000000022, + "264": -1.5999999999999779, + "265": 19.650000000000006, + "266": -19.249999999999964, + "267": -39.949999999999996, + "268": 8.100000000000056, + "269": -19.99999999999997, + "270": 2.149999999999996, + "271": 10.749999999999979, + "272": -0.4000000000000108, + "273": -29.14999999999997, + "274": 35.349999999999824, + "275": -0.700000000000006, + "276": -22.24999999999998, + "277": -34.349999999999966, + "278": -6.4499999999999815, + "279": -12.549999999999992, + "280": -27.050000000000033, + "281": 16.00000000000003, + "282": -89.19999999999999, + "283": -72.59999999999998, + "284": -2.7999999999999767, + "285": -16.599999999999994, + "286": -17.79999999999997, + "287": -20.74999999999996, + "288": 13.3, + "289": 25.099999999999927, + "290": 22.550000000000026, + "291": 18.85000000000002, + "292": -5.199999999999991, + "293": 9.349999999999993, + "294": 83.85000000000025, + "295": -30.299999999999997, + "296": -8.999999999999995, + "297": 65.15000000000002, + "298": -71.30000000000001, + "299": -6.5499999999999865, + "300": -13.699999999999983, + "301": 26.649999999999853, + "302": 97.05000000000015, + "303": 22.650000000000027, + "304": -76.44999999999999, + "305": 4.95000000000001, + "306": -22.050000000000075, + "307": 15.899999999999999, + "308": 47.69999999999985, + "309": 28.29999999999986, + "310": 51.449999999999854, + "311": -87.54999999999998, + "312": -10.69999999999999, + "313": -7.1999999999999815, + "314": -54.400000000000006, + "315": 107.70000000000014, + "316": 18.600000000000023, + "317": 92.05000000000007, + "318": -73.39999999999998, + "319": 10.899999999999991, + "320": 29.049999999999837, + "321": 10.450000000000026, + "322": -16.349999999999973, + "323": 30.999999999999783, + "324": 6.6500000000000234, + "325": 12.599999999999998, + "326": 2.4500000000000295, + "327": 27.39999999999995, + "328": -8.999999999999988, + "329": 68.24999999999997, + "330": 0.6499999999999742, + "331": 16.15000000000002, + "332": 27.599999999999874, + "333": 32.34999999999984, + "334": 83.74999999999997, + "335": -34.599999999999994, + "336": 58.94999999999986, + "337": 4.549999999999995, + "338": 39.549999999999976, + "339": 49.74999999999994, + "340": 19.099999999999998, + "341": 92.40000000000009, + "342": 37.749999999999986, + "343": 22.399999999999977, + "344": 57.49999999999985, + "345": 46.44999999999981, + "346": -31.65, + "347": 102.05000000000013, + "348": 0.20000000000003948, + "349": 79.90000000000002, + "350": 73.34999999999998, + "351": 50.84999999999999, + "352": 28.549999999999986, + "353": 7.899999999999988, + "354": 10.69999999999997, + "355": -3.350000000000004, + "356": 18.95000000000005, + "357": 89.69999999999995, + "358": 62.199999999999896, + "359": 12.700000000000014, + "360": 54.449999999999775, + "361": 27.449999999999992, + "362": 6.300000000000015, + "363": 26.649999999999945, + "364": 60.29999999999981, + "365": 5.000000000000007, + "366": 74.94999999999995, + "367": 43.849999999999824, + "368": -7.199999999999981, + "369": 37.99999999999982, + "370": 91.05000000000014, + "371": 92.75000000000024, + "372": 64.34999999999992, + "373": 81.34999999999998, + "374": 14.050000000000011, + "375": 74.25000000000004, + "376": 87.95000000000005, + "377": 91.59999999999995, + "378": 91.8999999999999, + "379": 71.79999999999993, + "380": 94.39999999999989, + "381": 62.44999999999998, + "382": 107.20000000000012, + "383": 117.20000000000024, + "384": 111.75000000000026, + "385": 100.3000000000001, + "386": 112.84999999999995, + "387": 67.35000000000002, + "388": 97.35000000000011, + "389": 68.2500000000001, + "390": 94.60000000000002, + "391": 94.35000000000005, + "392": 59.09999999999998, + "393": -13.54999999999998, + "394": 90.10000000000008, + "395": 96.84999999999995, + "396": 37.34999999999992, + "397": 75.80000000000004, + "398": 52.65000000000003, + "399": 113.35000000000021, + "400": 110.59999999999988, + "401": 100.95, + "402": 107.10000000000004, + "403": 27.799999999999926, + "404": 92.4499999999999, + "405": 105.54999999999998, + "406": 118.05000000000013, + "407": 105.75000000000016, + "408": 65.79999999999993, + "409": 53.94999999999991, + "410": 83.95000000000002, + "411": 103.20000000000022, + "412": 111.35000000000018, + "413": 87.30000000000001, + "414": 95.10000000000018, + "415": 95.55000000000017, + "416": 114.0000000000001, + "417": 68.10000000000008, + "418": 92.40000000000002, + "419": 38.1499999999998, + "420": 94.69999999999995, + "421": 107.0000000000002, + "422": 32.449999999999996, + "423": 112.9500000000002, + "424": -4.749999999999992, + "425": 38.60000000000001, + "426": 113.05000000000014, + "427": 111.30000000000003, + "428": 107.14999999999992, + "429": 83.45000000000006, + "430": 93.34999999999985, + "431": 22.45000000000001, + "432": 107.60000000000007, + "433": 118.6, + "434": 117.35, + "435": 7.150000000000011, + "436": 79.89999999999986, + "437": 110.05000000000008, + "438": 51.04999999999984, + "439": 116.25000000000001, + "440": 111.30000000000024, + "441": 113.10000000000014, + "442": 55.8999999999998, + "443": 105.30000000000011, + "444": 98.55000000000008, + "445": 51.449999999999896, + "446": 103.65000000000002, + "447": 103.10000000000008, + "448": 116.99999999999999, + "449": 115.80000000000018, + "450": 102.3, + "451": 51.0499999999998, + "452": 119.7, + "453": 110.9000000000001, + "454": 73.89999999999986, + "455": 113.40000000000008, + "456": 89.10000000000001, + "457": 114.34999999999997, + "458": 101.69999999999989, + "459": 17.450000000000053, + "460": 109.80000000000011, + "461": 119.55000000000031, + "462": 114.30000000000005, + "463": 25.74999999999999, + "464": 108.55000000000011, + "465": 61.54999999999984, + "466": 119.55000000000013, + "467": 87.30000000000008, + "468": 90.54999999999995, + "469": 119.80000000000017, + "470": 104.70000000000002, + "471": 84.9, + "472": 110.55000000000008, + "473": 95.35000000000004, + "474": 101.95000000000007, + "475": 101.84999999999995, + "476": 97.75000000000011, + "477": 60.99999999999984, + "478": 108.65000000000003, + "479": 118.85000000000004, + "480": 55.34999999999983, + "481": 111.85000000000005, + "482": 88.30000000000004, + "483": 106.24999999999989, + "484": 120.45000000000006, + "485": 120.14999999999999, + "486": 72.29999999999988, + "487": 113.50000000000007, + "488": 111.54999999999991, + "489": 107.04999999999998, + "490": 117.60000000000021, + "491": 104.45000000000002, + "492": 50.0499999999998, + "493": 104.90000000000006, + "494": 87.15000000000008, + "495": 109.15000000000018, + "496": 111.0, + "497": 112.45000000000013, + "498": 111.80000000000001, + "499": 120.60000000000008, + "500": 106.60000000000001, + "501": 114.75, + "502": 103.4000000000002, + "503": 101.75000000000004, + "504": 97.2000000000002, + "505": 58.49999999999997, + "506": 110.45000000000009, + "507": 115.84999999999997, + "508": 36.3499999999998, + "509": 101.74999999999999, + "510": 114.35000000000014, + "511": 109.30000000000008, + "512": 94.70000000000014, + "513": 116.35000000000005, + "514": 54.049999999999855, + "515": 92.25000000000009, + "516": 107.3000000000002, + "517": 110.10000000000004, + "518": 119.45000000000012, + "519": 112.24999999999997, + "520": 20.849999999999973, + "521": 119.65000000000009, + "522": 99.05000000000007, + "523": 107.70000000000003, + "524": 16.850000000000062, + "525": 61.54999999999993, + "526": 112.90000000000012, + "527": 105.25000000000006, + "528": 119.00000000000009, + "529": 116.45, + "530": 106.40000000000018, + "531": 76.70000000000007, + "532": 102.69999999999999, + "533": 95.19999999999992, + "534": 106.59999999999995, + "535": 27.099999999999937, + "536": 109.60000000000008, + "537": 98.54999999999987, + "538": 117.20000000000026, + "539": 102.00000000000017, + "540": 117.50000000000011, + "541": 112.05000000000001, + "542": 116.35000000000004, + "543": 110.20000000000007, + "544": 93.35000000000015, + "545": 101.20000000000005, + "546": 113.75000000000014, + "547": 117.30000000000005, + "548": 47.199999999999896, + "549": 100.19999999999995, + "550": 106.05000000000004, + "551": 116.80000000000014, + "552": 92.64999999999995, + "553": 113.14999999999996, + "554": 105.79999999999993, + "555": 106.0500000000001, + "556": -10.649999999999986, + "557": 108.35000000000005, + "558": 115.00000000000013, + "559": 115.60000000000002, + "560": 116.35000000000012, + "561": 108.49999999999991, + "562": 116.35000000000012, + "563": 112.90000000000015, + "564": 114.29999999999997, + "565": 113.00000000000006, + "566": 121.75000000000007, + "567": 111.8, + "568": 117.30000000000004, + "569": 112.15000000000008, + "570": 109.10000000000008, + "571": 108.85000000000016, + "572": 117.25000000000004, + "573": 107.89999999999998, + "574": 113.05000000000005, + "575": 116.6000000000001, + "576": 106.24999999999991, + "577": 103.60000000000004, + "578": 122.80000000000003, + "579": 110.54999999999997, + "580": 112.90000000000012, + "581": 115.5, + "582": 113.00000000000006, + "583": 111.10000000000004, + "584": 113.80000000000013, + "585": 98.29999999999998, + "586": 112.35000000000012, + "587": 111.20000000000013, + "588": 106.15000000000013, + "589": 119.45000000000007, + "590": 109.69999999999999, + "591": 103.24999999999996, + "592": 113.60000000000011, + "593": 115.20000000000002, + "594": 120.35000000000001, + "595": 115.75, + "596": 106.90000000000015, + "597": 105.29999999999998, + "598": 113.50000000000001, + "599": 113.85000000000001, + "600": 110.00000000000023, + "601": 116.50000000000011, + "602": 107.90000000000008, + "603": 103.75, + "604": 112.35000000000018, + "605": 114.1500000000002, + "606": 115.70000000000009, + "607": 114.50000000000011, + "608": 113.25000000000001, + "609": 112.80000000000007, + "610": 113.15000000000002, + "611": 113.25000000000016, + "612": 112.7000000000002, + "613": 78.10000000000002, + "614": 109.95000000000003, + "615": 107.6000000000001, + "616": 113.35000000000002, + "617": 105.85000000000005, + "618": 112.00000000000016, + "619": 119.6000000000001, + "620": 109.8500000000002, + "621": 102.50000000000001, + "622": 86.3, + "623": 113.30000000000013, + "624": 109.44999999999996, + "625": 114.10000000000021, + "626": 115.10000000000012, + "627": 112.75000000000013, + "628": 70.34999999999984, + "629": 100.29999999999994, + "630": 118.85000000000011, + "631": 105.20000000000006, + "632": 109.19999999999993, + "633": 120.49999999999999, + "634": 106.60000000000002, + "635": 108.3500000000001, + "636": 109.85000000000007, + "637": 102.4500000000001, + "638": 116.25000000000024, + "639": 115.85000000000005, + "640": 114.55000000000007, + "641": 111.30000000000011, + "642": 106.90000000000003, + "643": 111.3500000000001, + "644": 115.00000000000009, + "645": 95.64999999999995, + "646": 104.05000000000011, + "647": 114.45000000000019, + "648": 97.54999999999993, + "649": 111.9500000000001, + "650": 117.60000000000015, + "651": 106.10000000000012, + "652": 107.50000000000007, + "653": 102.00000000000013, + "654": 118.95000000000009, + "655": 59.199999999999896, + "656": 111.35000000000012, + "657": 117.70000000000022, + "658": 90.95000000000012, + "659": 84.05000000000013, + "660": 109.90000000000015, + "661": 113.04999999999998, + "662": 109.45000000000006, + "663": 90.80000000000015, + "664": 110.90000000000002, + "665": 115.65000000000002, + "666": 101.94999999999996, + "667": 101.65000000000002, + "668": 115.35, + "669": 112.2, + "670": 98.49999999999997, + "671": 105.30000000000005, + "672": 111.10000000000011, + "673": 95.8000000000001, + "674": 108.20000000000014, + "675": 107.05000000000005, + "676": 113.05000000000004, + "677": 103.0500000000001, + "678": 111.00000000000004, + "679": 95.05000000000021, + "680": 105.79999999999998, + "681": 97.00000000000016, + "682": 112.60000000000011, + "683": 111.5500000000001, + "684": 110.19999999999999, + "685": 100.45000000000014, + "686": 107.90000000000015, + "687": 102.90000000000009, + "688": 98.55000000000015, + "689": 119.99999999999997, + "690": 105.25000000000009, + "691": 99.15000000000003, + "692": 116.1, + "693": 104.85000000000007, + "694": 112.20000000000009, + "695": 121.20000000000006, + "696": 111.10000000000014, + "697": 112.7500000000001, + "698": 109.10000000000002, + "699": 114.0000000000001, + "700": 99.35, + "701": 110.45000000000005, + "702": 119.75, + "703": 105.50000000000006, + "704": 116.30000000000004, + "705": 111.00000000000014, + "706": 114.95000000000002, + "707": 100.50000000000011, + "708": 100.59999999999998, + "709": 100.79999999999991, + "710": 23.449999999999942, + "711": 109.70000000000007, + "712": 99.65000000000005, + "713": 105.9, + "714": 112.3500000000001, + "715": 111.80000000000011, + "716": 110.00000000000013, + "717": 117.60000000000005, + "718": 110.54999999999997, + "719": 110.80000000000008, + "720": 106.6, + "721": 20.300000000000026, + "722": 112.80000000000018, + "723": 112.55, + "724": 103.85000000000002, + "725": 106.40000000000019, + "726": 106.95000000000009, + "727": 109.10000000000005, + "728": 113.94999999999996, + "729": 108.00000000000007, + "730": 113.5500000000001, + "731": 103.0500000000002, + "732": 109.80000000000007, + "733": 109.60000000000011, + "734": 112.2500000000001, + "735": 116.65000000000012, + "736": 106.7, + "737": 100.1000000000001, + "738": 112.14999999999999, + "739": 119.19999999999999, + "740": 117.10000000000015, + "741": 114.30000000000015, + "742": 108.24999999999997, + "743": 106.65000000000013, + "744": 107.75, + "745": 107.55000000000001, + "746": 110.50000000000004, + "747": 111.95000000000022, + "748": 105.25000000000004, + "749": 105.35000000000004, + "750": 106.15000000000008, + "751": 117.40000000000002, + "752": 114.1, + "753": 105.04999999999998, + "754": 109.2, + "755": 113.05000000000015, + "756": 116.65000000000015, + "757": 114.5000000000001, + "758": 111.70000000000009, + "759": 109.44999999999997, + "760": 114.1, + "761": 106.14999999999989, + "762": 112.60000000000001, + "763": 109.15000000000003, + "764": 116.9500000000001, + "765": 113.10000000000022, + "766": 111.35000000000022, + "767": 109.65000000000018, + "768": 115.50000000000009, + "769": 112.95000000000006, + "770": 114.85000000000012, + "771": 111.55000000000017, + "772": 117.20000000000003, + "773": 104.95000000000007, + "774": 112.75000000000014, + "775": 119.75000000000011, + "776": 113.20000000000019, + "777": 110.45000000000019, + "778": 108.89999999999996, + "779": 105.75000000000007, + "780": 103.25000000000004, + "781": 111.1, + "782": 111.15000000000003, + "783": 119.55, + "784": 107.20000000000012, + "785": 112.65000000000013, + "786": 114.50000000000003, + "787": 111.39999999999998, + "788": 116.00000000000003, + "789": 112.00000000000007, + "790": 113.35000000000012, + "791": 113.90000000000012, + "792": 108.85000000000012, + "793": 118.50000000000003, + "794": 108.40000000000002, + "795": 119.75000000000011, + "796": 106.30000000000007, + "797": 113.85000000000002, + "798": 103.85000000000004, + "799": 109.0, + "800": 108.70000000000012, + "801": 116.25000000000009, + "802": 113.45000000000005, + "803": 107.50000000000011, + "804": 113.4000000000001, + "805": 115.90000000000006, + "806": 114.40000000000012, + "807": 106.39999999999996, + "808": 119.05000000000018, + "809": 115.65000000000013, + "810": 107.95000000000003, + "811": 112.55000000000003, + "812": 101.39999999999992, + "813": 101.80000000000013, + "814": 114.80000000000024, + "815": 118.25000000000016, + "816": 102.65000000000005, + "817": 100.65000000000018, + "818": 109.05000000000005, + "819": 117.95000000000005, + "820": 109.4500000000001, + "821": 110.15000000000019, + "822": 117.75, + "823": 115.49999999999996, + "824": 116.1, + "825": 107.70000000000019, + "826": 109.8500000000001, + "827": 116.00000000000009, + "828": 113.05000000000001, + "829": 96.65000000000006, + "830": 115.65000000000005, + "831": 21.94999999999994, + "832": 116.70000000000002, + "833": 113.50000000000007, + "834": 104.89999999999999, + "835": 116.85000000000011, + "836": 112.10000000000005, + "837": 112.20000000000017, + "838": 110.5999999999999, + "839": 111.95000000000005, + "840": 108.0000000000002, + "841": 111.25000000000009, + "842": 91.79999999999998, + "843": 100.95, + "844": 103.74999999999994, + "845": 109.74999999999997, + "846": 104.45000000000012, + "847": 114.30000000000024, + "848": 107.35000000000012, + "849": 115.10000000000008, + "850": 99.60000000000005, + "851": 110.74999999999997, + "852": 108.50000000000007, + "853": 103.5500000000001, + "854": 109.10000000000001, + "855": 107.75000000000006, + "856": 106.40000000000012, + "857": 107.20000000000013, + "858": 119.35000000000016, + "859": 111.55000000000013, + "860": 122.65, + "861": 41.69999999999987, + "862": 106.80000000000008, + "863": 107.04999999999991, + "864": 120.45000000000002, + "865": 110.30000000000018, + "866": 103.40000000000016, + "867": 69.89999999999992, + "868": 105.0000000000001, + "869": 98.49999999999996, + "870": 105.35000000000012, + "871": 107.14999999999999, + "872": 112.40000000000009, + "873": 119.85000000000002, + "874": 112.60000000000007, + "875": 103.20000000000009, + "876": 104.80000000000008, + "877": 114.20000000000014, + "878": 119.55000000000021, + "879": 113.60000000000008, + "880": 105.70000000000012, + "881": 103.85000000000007, + "882": 81.50000000000006, + "883": 107.95000000000013, + "884": 110.60000000000005, + "885": 84.35000000000015, + "886": 116.34999999999998, + "887": 110.55000000000004, + "888": 103.35000000000012, + "889": 115.0000000000002, + "890": 111.44999999999993, + "891": 114.30000000000004, + "892": 109.00000000000009, + "893": 26.599999999999866, + "894": 118.70000000000005, + "895": 105.55000000000007, + "896": 106.45000000000013, + "897": 113.55000000000008, + "898": 115.15000000000008, + "899": 111.00000000000006, + "900": 114.35000000000012, + "901": 100.40000000000005, + "902": 95.25, + "903": 112.00000000000006, + "904": 86.00000000000014, + "905": 118.00000000000009, + "906": 117.69999999999999, + "907": 65.64999999999999, + "908": 115.65000000000002, + "909": 114.65000000000006, + "910": 110.20000000000012, + "911": 111.55000000000005, + "912": 108.55000000000008, + "913": 106.05000000000001, + "914": 118.55000000000011, + "915": 107.6000000000001, + "916": 113.75000000000009, + "917": 118.45000000000016, + "918": 38.69999999999993, + "919": 114.35000000000004, + "920": 107.75000000000006, + "921": 114.25000000000026, + "922": 23.799999999999976, + "923": 108.50000000000006, + "924": 111.05000000000005, + "925": 117.20000000000007, + "926": 116.95000000000005, + "927": 107.64999999999999, + "928": 100.40000000000012, + "929": 118.2500000000001, + "930": 110.55000000000003, + "931": 104.20000000000012, + "932": 108.45000000000009, + "933": 15.89999999999998, + "934": 75.99999999999999, + "935": 109.35000000000001, + "936": 102.99999999999997, + "937": 105.79999999999998, + "938": 108.05000000000003, + "939": 93.95000000000002, + "940": 111.45, + "941": 100.19999999999999, + "942": 111.05000000000011, + "943": 103.00000000000004, + "944": 109.14999999999998, + "945": 99.74999999999993, + "946": 104.70000000000005, + "947": 59.94999999999983, + "948": 110.45000000000017, + "949": 94.14999999999996, + "950": 113.30000000000008, + "951": 99.79999999999994, + "952": 101.09999999999992, + "953": 98.99999999999999, + "954": 102.25000000000024, + "955": 97.50000000000006, + "956": 96.35000000000012, + "957": 108.15000000000005, + "958": 59.19999999999992, + "959": 105.30000000000008, + "960": 114.04999999999997, + "961": 113.85000000000001, + "962": 11.299999999999983, + "963": 91.60000000000005, + "964": 77.45000000000002, + "965": 76.10000000000014, + "966": 68.80000000000015, + "967": 105.7000000000001, + "968": 113.05000000000004, + "969": 107.95000000000006, + "970": 101.30000000000005, + "971": 88.2500000000001, + "972": 85.65000000000015, + "973": 97.85000000000021, + "974": 113.70000000000016, + "975": 119.55000000000014, + "976": 93.80000000000013, + "977": 109.15000000000003, + "978": 114.50000000000013, + "979": 116.75000000000006, + "980": 103.55000000000011, + "981": 107.50000000000013, + "982": 102.20000000000013, + "983": 113.05000000000008, + "984": 107.0500000000001, + "985": 28.14999999999998, + "986": 101.99999999999991, + "987": 112.60000000000015, + "988": 101.59999999999998, + "989": 101.40000000000006, + "990": 104.55000000000005, + "991": 105.40000000000002, + "992": 112.05000000000008, + "993": 106.9500000000001, + "994": 114.30000000000005, + "995": 94.95000000000007, + "996": 113.15000000000002, + "997": 120.80000000000018, + "998": 92.00000000000006, + "999": 112.00000000000009, + "1000": 102.55000000000008 + }, + "2": { + "1": -53.55000000000008, + "2": -17.099999999999987, + "3": -21.049999999999958, + "4": -37.20000000000004, + "5": -45.20000000000007, + "6": -24.89999999999996, + "7": -43.05000000000009, + "8": -15.94999999999998, + "9": -17.94999999999997, + "10": -75.29999999999997, + "11": -94.85, + "12": -42.24999999999996, + "13": -14.349999999999975, + "14": -29.55000000000002, + "15": -10.199999999999996, + "16": -79.89999999999986, + "17": -45.30000000000006, + "18": -9.099999999999996, + "19": -19.099999999999966, + "20": -50.75000000000007, + "21": -21.549999999999958, + "22": -18.449999999999967, + "23": -32.49999999999998, + "24": -65.20000000000009, + "25": -47.05000000000006, + "26": -83.09999999999984, + "27": -33.84999999999999, + "28": -20.64999999999996, + "29": -23.04999999999995, + "30": -15.349999999999971, + "31": -14.499999999999986, + "32": -51.60000000000007, + "33": -9.349999999999982, + "34": -22.549999999999955, + "35": -69.75000000000006, + "36": -44.799999999999976, + "37": -14.19999999999996, + "38": -12.749999999999993, + "39": -30.74999999999994, + "40": -22.049999999999955, + "41": -58.500000000000114, + "42": -16.64999999999997, + "43": -17.39999999999997, + "44": -20.999999999999957, + "45": -16.099999999999973, + "46": -20.099999999999962, + "47": -30.350000000000005, + "48": -21.699999999999957, + "49": -21.549999999999958, + "50": -17.649999999999974, + "51": -19.299999999999965, + "52": -7.099999999999988, + "53": -21.899999999999952, + "54": -50.250000000000156, + "55": -29.15000000000002, + "56": -17.149999999999977, + "57": -15.699999999999966, + "58": -19.549999999999965, + "59": -16.74999999999997, + "60": -11.549999999999994, + "61": -17.099999999999973, + "62": -17.449999999999967, + "63": -22.099999999999955, + "64": -18.499999999999968, + "65": -14.499999999999982, + "66": -57.450000000000095, + "67": -22.699999999999953, + "68": -20.69999999999996, + "69": -13.34999999999998, + "70": -10.450000000000001, + "71": -14.449999999999989, + "72": -10.299999999999997, + "73": -35.15000000000007, + "74": -19.099999999999966, + "75": -21.54999999999996, + "76": -64.9000000000001, + "77": -68.85000000000005, + "78": -16.399999999999974, + "79": -30.30000000000002, + "80": -10.899999999999999, + "81": -15.949999999999978, + "82": -20.59999999999996, + "83": -67.40000000000016, + "84": -18.899999999999963, + "85": -100.85, + "86": -9.849999999999985, + "87": -18.54999999999997, + "88": -13.999999999999998, + "89": -0.49999999999997136, + "90": -19.699999999999964, + "91": -88.14999999999998, + "92": -18.199999999999967, + "93": -18.29999999999997, + "94": -14.29999999999999, + "95": -12.74999999999999, + "96": -15.399999999999975, + "97": -9.949999999999996, + "98": -19.099999999999966, + "99": -19.74999999999999, + "100": -14.299999999999974, + "101": -11.64999999999999, + "102": -21.399999999999956, + "103": -21.999999999999954, + "104": -19.79999999999996, + "105": -21.599999999999948, + "106": -5.5000000000000036, + "107": -19.99999999999996, + "108": -10.399999999999993, + "109": -8.30000000000001, + "110": -21.39999999999996, + "111": -19.849999999999962, + "112": -20.199999999999964, + "113": -19.149999999999967, + "114": -14.999999999999952, + "115": -14.899999999999975, + "116": -4.149999999999977, + "117": -18.299999999999965, + "118": -34.99999999999995, + "119": 9.900000000000063, + "120": -23.14999999999995, + "121": -89.55, + "122": -7.34999999999999, + "123": -3.950000000000001, + "124": -1.4999999999999765, + "125": -19.099999999999966, + "126": -3.3999999999999773, + "127": -20.39999999999996, + "128": -18.19999999999996, + "129": -13.199999999999985, + "130": 16.449999999999942, + "131": -15.349999999999982, + "132": -21.649999999999956, + "133": -22.899999999999952, + "134": -42.650000000000134, + "135": -10.249999999999988, + "136": -20.149999999999963, + "137": -18.249999999999968, + "138": -18.54999999999996, + "139": -44.050000000000054, + "140": -6.9499999999999895, + "141": -15.19999999999998, + "142": -70.4, + "143": -3.7999999999999794, + "144": -0.45000000000000084, + "145": -11.19999999999999, + "146": -41.10000000000004, + "147": -47.00000000000011, + "148": -14.299999999999985, + "149": -3.1999999999999886, + "150": 4.700000000000002, + "151": -11.19999999999997, + "152": -19.79999999999996, + "153": -5.899999999999985, + "154": -58.599999999999994, + "155": -19.649999999999967, + "156": -17.94999999999997, + "157": -13.599999999999987, + "158": -22.64999999999996, + "159": -15.399999999999979, + "160": 0.2500000000000384, + "161": -4.849999999999978, + "162": -10.300000000000006, + "163": -3.9999999999999796, + "164": -13.099999999999989, + "165": -13.44999999999997, + "166": -27.24999999999995, + "167": 16.550000000000054, + "168": -7.850000000000002, + "169": -5.600000000000016, + "170": -13.349999999999989, + "171": -3.5500000000000016, + "172": -1.5000000000000102, + "173": -83.24999999999997, + "174": -43.350000000000136, + "175": -38.00000000000008, + "176": -88.75000000000001, + "177": -1.8500000000000005, + "178": 11.999999999999993, + "179": 23.049999999999937, + "180": -2.6499999999999684, + "181": 0.7000000000000337, + "182": 14.499999999999982, + "183": -10.300000000000004, + "184": -35.699999999999974, + "185": -77.99999999999997, + "186": -10.74999999999999, + "187": -0.15000000000000013, + "188": -33.60000000000003, + "189": 3.100000000000029, + "190": -14.79999999999998, + "191": -10.049999999999992, + "192": -32.30000000000006, + "193": -61.70000000000005, + "194": 2.3500000000000254, + "195": -34.849999999999945, + "196": -58.000000000000036, + "197": -1.9000000000000652, + "198": 23.049999999999958, + "199": -14.24999999999999, + "200": -67.4, + "201": -15.19999999999997, + "202": -12.849999999999993, + "203": -61.79999999999995, + "204": 2.4500000000000224, + "205": -17.94999999999997, + "206": -34.3, + "207": -47.349999999999994, + "208": -72.7, + "209": -34.75000000000003, + "210": -4.1000000000000085, + "211": 13.549999999999958, + "212": -84.04999999999994, + "213": -11.449999999999987, + "214": -34.79999999999997, + "215": -65.20000000000007, + "216": 2.1999999999999824, + "217": 28.799999999999972, + "218": -29.499999999999964, + "219": -11.149999999999988, + "220": 5.600000000000037, + "221": -10.899999999999988, + "222": 2.250000000000001, + "223": 69.20000000000003, + "224": 2.2499999999999885, + "225": -13.14999999999999, + "226": 33.799999999999784, + "227": 7.100000000000029, + "228": 1.2500000000000346, + "229": -57.70000000000001, + "230": -34.800000000000004, + "231": 30.249999999999932, + "232": 40.09999999999975, + "233": -48.65, + "234": -1.049999999999974, + "235": -75.80000000000001, + "236": -26.949999999999925, + "237": 21.14999999999999, + "238": -0.6999999999999761, + "239": 44.99999999999984, + "240": 42.64999999999988, + "241": -1.5999999999999654, + "242": 16.349999999999962, + "243": -3.6999999999999567, + "244": 42.2499999999999, + "245": -71.9, + "246": -3.5499999999999794, + "247": -50.24999999999999, + "248": -71.99999999999997, + "249": -79.04999999999995, + "250": -32.749999999999986, + "251": 38.34999999999986, + "252": 25.94999999999995, + "253": 21.24999999999999, + "254": -7.150000000000038, + "255": -67.64999999999998, + "256": 23.400000000000002, + "257": 20.950000000000035, + "258": 2.149999999999986, + "259": 7.350000000000016, + "260": -6.250000000000009, + "261": 41.39999999999999, + "262": 23.699999999999957, + "263": 1.1500000000000201, + "264": -55.04999999999996, + "265": 19.35000000000001, + "266": 14.750000000000071, + "267": -14.449999999999985, + "268": 5.399999999999991, + "269": 49.44999999999996, + "270": -2.399999999999986, + "271": -11.249999999999948, + "272": 1.8000000000000265, + "273": -20.900000000000055, + "274": -8.749999999999995, + "275": -77.44999999999999, + "276": 12.699999999999989, + "277": 6.200000000000016, + "278": -7.000000000000002, + "279": 22.10000000000002, + "280": 40.049999999999784, + "281": -75.80000000000001, + "282": 8.050000000000043, + "283": -21.149999999999995, + "284": 40.8999999999998, + "285": 92.9500000000001, + "286": -82.79999999999995, + "287": 60.34999999999996, + "288": 25.449999999999996, + "289": -79.64999999999998, + "290": -75.74999999999994, + "291": 17.44999999999997, + "292": -31.50000000000003, + "293": 39.69999999999993, + "294": -37.09999999999999, + "295": 21.84999999999992, + "296": 12.29999999999999, + "297": 87.2, + "298": -32.6, + "299": 23.449999999999953, + "300": -13.450000000000014, + "301": -15.00000000000004, + "302": -79.65, + "303": -44.89999999999997, + "304": 56.34999999999976, + "305": 11.850000000000051, + "306": 8.649999999999984, + "307": 38.64999999999991, + "308": 50.19999999999997, + "309": -10.750000000000018, + "310": 3.400000000000026, + "311": 29.350000000000033, + "312": 4.79999999999999, + "313": -4.250000000000017, + "314": 93.40000000000008, + "315": 33.19999999999999, + "316": 28.60000000000003, + "317": 16.9, + "318": 63.89999999999988, + "319": -21.850000000000005, + "320": -33.95000000000007, + "321": -79.15, + "322": -24.549999999999976, + "323": 41.79999999999999, + "324": 60.79999999999991, + "325": 1.0000000000000018, + "326": 103.05000000000011, + "327": 111.1, + "328": 28.099999999999948, + "329": 29.84999999999998, + "330": -9.6, + "331": -8.800000000000004, + "332": 50.84999999999994, + "333": 29.949999999999807, + "334": 59.30000000000007, + "335": 88.20000000000007, + "336": 56.34999999999995, + "337": 84.80000000000004, + "338": 55.69999999999988, + "339": 11.250000000000005, + "340": 80.34999999999991, + "341": 116.60000000000018, + "342": 57.849999999999966, + "343": -66.39999999999995, + "344": -6.800000000000019, + "345": 36.40000000000008, + "346": 19.55, + "347": 80.49999999999989, + "348": 98.40000000000023, + "349": 74.00000000000014, + "350": 104.09999999999998, + "351": 105.55000000000011, + "352": 99.00000000000016, + "353": 90.75000000000003, + "354": 19.899999999999892, + "355": 88.5500000000001, + "356": 11.500000000000043, + "357": 20.10000000000002, + "358": 90.89999999999995, + "359": 38.15, + "360": 112.2000000000002, + "361": 100.5500000000002, + "362": 97.45000000000019, + "363": 101.10000000000018, + "364": 45.15000000000002, + "365": 54.44999999999993, + "366": -46.44999999999998, + "367": 90.8000000000001, + "368": 51.399999999999935, + "369": 103.90000000000025, + "370": 64.05000000000005, + "371": 94.0, + "372": 75.45000000000002, + "373": 92.15000000000003, + "374": 17.249999999999925, + "375": 61.74999999999988, + "376": 103.60000000000008, + "377": 96.79999999999981, + "378": 104.60000000000016, + "379": 111.59999999999995, + "380": 95.15000000000009, + "381": 117.00000000000016, + "382": 67.44999999999995, + "383": 59.24999999999986, + "384": 72.74999999999991, + "385": 75.5, + "386": 42.74999999999994, + "387": 88.45000000000002, + "388": 119.75000000000034, + "389": 83.30000000000008, + "390": 93.20000000000014, + "391": 102.35000000000008, + "392": 66.10000000000001, + "393": 99.6000000000001, + "394": 66.75, + "395": 73.34999999999998, + "396": 60.200000000000045, + "397": 82.00000000000003, + "398": 104.55000000000005, + "399": -49.050000000000004, + "400": 108.95000000000006, + "401": 102.45000000000023, + "402": 112.9500000000001, + "403": 59.34999999999997, + "404": 97.69999999999993, + "405": 107.79999999999995, + "406": 63.34999999999991, + "407": 67.85000000000007, + "408": 112.34999999999997, + "409": 103.09999999999994, + "410": 114.90000000000013, + "411": 98.94999999999996, + "412": 105.20000000000019, + "413": 58.799999999999834, + "414": 109.40000000000013, + "415": 84.45000000000002, + "416": 105.05000000000003, + "417": 46.79999999999989, + "418": 85.09999999999997, + "419": 90.19999999999989, + "420": 101.85000000000008, + "421": 59.14999999999989, + "422": 32.500000000000014, + "423": 3.350000000000037, + "424": 49.149999999999885, + "425": 56.349999999999724, + "426": 109.9000000000002, + "427": 102.90000000000022, + "428": -8.999999999999991, + "429": 108.34999999999982, + "430": 118.75000000000021, + "431": 80.45000000000005, + "432": 90.35000000000004, + "433": 106.40000000000016, + "434": 79.55000000000003, + "435": 90.35000000000005, + "436": 85.35000000000004, + "437": 3.4000000000000643, + "438": 118.35000000000002, + "439": 106.9999999999999, + "440": 99.30000000000003, + "441": 69.29999999999993, + "442": 113.29999999999995, + "443": 103.09999999999991, + "444": 106.25000000000011, + "445": 5.250000000000016, + "446": 110.7000000000001, + "447": 97.44999999999978, + "448": 106.45000000000009, + "449": 110.69999999999999, + "450": 108.2500000000002, + "451": 90.40000000000013, + "452": 29.29999999999997, + "453": 3.7500000000000253, + "454": 84.05000000000008, + "455": 38.349999999999774, + "456": 108.20000000000014, + "457": 112.20000000000006, + "458": 96.09999999999982, + "459": 113.10000000000001, + "460": 74.90000000000002, + "461": 104.35000000000022, + "462": 117.14999999999998, + "463": 112.65000000000015, + "464": 116.40000000000006, + "465": 94.20000000000009, + "466": -19.74999999999996, + "467": 101.04999999999997, + "468": 96.25000000000011, + "469": 101.95000000000006, + "470": 92.99999999999993, + "471": 107.65000000000018, + "472": 67.89999999999974, + "473": 104.85, + "474": 99.65000000000012, + "475": -19.949999999999992, + "476": 86.3000000000001, + "477": 79.49999999999996, + "478": 90.29999999999993, + "479": 115.30000000000021, + "480": 107.00000000000027, + "481": 115.20000000000023, + "482": 103.00000000000004, + "483": 110.90000000000009, + "484": 103.10000000000007, + "485": 78.4500000000001, + "486": 78.69999999999979, + "487": 118.20000000000014, + "488": 88.25000000000006, + "489": 81.44999999999997, + "490": 81.10000000000026, + "491": 89.80000000000008, + "492": 91.94999999999999, + "493": 112.70000000000005, + "494": 116.30000000000005, + "495": 114.6, + "496": 85.95000000000002, + "497": -10.349999999999975, + "498": 94.7499999999999, + "499": 92.15000000000003, + "500": 92.8999999999998, + "501": 112.50000000000006, + "502": 93.1000000000001, + "503": 99.60000000000001, + "504": 101.40000000000016, + "505": 112.95000000000002, + "506": 91.99999999999994, + "507": 108.39999999999992, + "508": 103.00000000000018, + "509": 74.40000000000008, + "510": 115.50000000000027, + "511": 91.39999999999993, + "512": 93.49999999999997, + "513": 114.8500000000001, + "514": 67.54999999999991, + "515": 94.04999999999995, + "516": 97.65000000000003, + "517": 97.3499999999999, + "518": 110.85000000000005, + "519": 82.85000000000008, + "520": 79.20000000000012, + "521": 102.70000000000012, + "522": 99.90000000000006, + "523": 76.10000000000004, + "524": 92.10000000000018, + "525": 47.90000000000001, + "526": 96.25000000000009, + "527": 115.45000000000023, + "528": 106.00000000000004, + "529": 52.149999999999885, + "530": 75.04999999999997, + "531": 82.70000000000006, + "532": 105.65000000000012, + "533": 110.95000000000006, + "534": 91.30000000000005, + "535": 94.84999999999995, + "536": 103.50000000000016, + "537": 79.24999999999997, + "538": 95.50000000000009, + "539": 117.40000000000015, + "540": 112.39999999999989, + "541": 109.0500000000002, + "542": 98.55000000000005, + "543": 63.249999999999886, + "544": 97.15000000000025, + "545": 106.20000000000017, + "546": 108.4500000000001, + "547": 86.44999999999992, + "548": 83.0499999999999, + "549": 88.89999999999996, + "550": 111.10000000000018, + "551": 102.64999999999998, + "552": 117.30000000000011, + "553": 117.55000000000035, + "554": 101.59999999999977, + "555": 89.35000000000004, + "556": 103.0500000000001, + "557": 93.84999999999994, + "558": 78.15000000000012, + "559": 96.50000000000016, + "560": 108.54999999999998, + "561": 111.20000000000005, + "562": 118.30000000000005, + "563": 98.90000000000013, + "564": 90.30000000000004, + "565": 115.30000000000014, + "566": 108.25000000000007, + "567": 94.60000000000001, + "568": 99.40000000000012, + "569": 97.19999999999979, + "570": 95.05000000000027, + "571": 112.7000000000001, + "572": 110.64999999999999, + "573": 119.65000000000022, + "574": 108.00000000000013, + "575": 108.00000000000011, + "576": 98.5500000000001, + "577": 100.70000000000009, + "578": 113.40000000000012, + "579": 100.19999999999999, + "580": 111.05000000000005, + "581": 72.74999999999994, + "582": 107.55000000000014, + "583": 115.05000000000022, + "584": 113.75000000000017, + "585": 112.90000000000019, + "586": 87.89999999999989, + "587": 106.40000000000006, + "588": 111.85000000000021, + "589": 90.85000000000007, + "590": 107.19999999999999, + "591": 107.15000000000023, + "592": 115.10000000000002, + "593": 115.00000000000009, + "594": 80.19999999999995, + "595": 116.10000000000018, + "596": 109.7000000000001, + "597": 109.10000000000005, + "598": 107.85000000000002, + "599": 116.70000000000016, + "600": 119.3000000000001, + "601": 108.75000000000003, + "602": 116.40000000000018, + "603": 112.75000000000021, + "604": 116.50000000000004, + "605": 102.29999999999994, + "606": 63.99999999999988, + "607": 111.45000000000022, + "608": 98.59999999999991, + "609": 104.90000000000023, + "610": 115.95000000000029, + "611": 102.9, + "612": 112.65000000000008, + "613": 107.95000000000013, + "614": 119.30000000000018, + "615": 116.50000000000001, + "616": 122.75000000000004, + "617": 113.25000000000006, + "618": 111.00000000000023, + "619": 114.10000000000025, + "620": 98.24999999999997, + "621": 109.75000000000016, + "622": 87.24999999999999, + "623": 87.44999999999996, + "624": 101.59999999999984, + "625": 98.30000000000005, + "626": 108.25000000000004, + "627": 111.40000000000013, + "628": 111.15000000000002, + "629": 114.95000000000012, + "630": 112.25000000000009, + "631": 71.40000000000013, + "632": 88.05000000000001, + "633": 119.15000000000006, + "634": 110.6500000000001, + "635": -6.400000000000002, + "636": 67.84999999999991, + "637": 121.65000000000009, + "638": 116.00000000000009, + "639": 105.70000000000002, + "640": 115.2500000000002, + "641": 99.14999999999995, + "642": 111.10000000000002, + "643": 110.35000000000024, + "644": 109.85000000000014, + "645": 113.5500000000001, + "646": 113.70000000000006, + "647": 113.55000000000017, + "648": 39.69999999999996, + "649": 106.75000000000001, + "650": 111.10000000000022, + "651": 115.25000000000004, + "652": 114.0000000000001, + "653": 108.40000000000006, + "654": 100.94999999999992, + "655": 32.3999999999998, + "656": 113.80000000000014, + "657": 94.09999999999997, + "658": 109.55, + "659": 113.45000000000003, + "660": 109.10000000000011, + "661": 114.85000000000011, + "662": 100.4499999999999, + "663": 110.85000000000004, + "664": 119.80000000000004, + "665": 120.40000000000008, + "666": 119.05000000000018, + "667": 74.29999999999997, + "668": 109.40000000000023, + "669": 116.10000000000018, + "670": 71.39999999999992, + "671": 110.0, + "672": 87.35, + "673": 113.4000000000001, + "674": 115.65000000000008, + "675": 98.29999999999994, + "676": 108.55000000000001, + "677": 114.95000000000014, + "678": 105.35000000000005, + "679": 82.89999999999995, + "680": 113.60000000000014, + "681": 111.95000000000007, + "682": 113.40000000000013, + "683": 118.25000000000023, + "684": 112.4000000000001, + "685": 110.15000000000005, + "686": 120.05, + "687": 116.55000000000005, + "688": 118.1000000000001, + "689": 114.50000000000003, + "690": 104.8000000000001, + "691": 118.10000000000015, + "692": 115.45000000000013, + "693": 118.0500000000001, + "694": 107.19999999999989, + "695": 113.80000000000013, + "696": 103.94999999999993, + "697": 113.05000000000015, + "698": 109.9500000000001, + "699": 113.25000000000018, + "700": 112.20000000000006, + "701": 104.35000000000007, + "702": 103.75000000000006, + "703": 108.15000000000006, + "704": 111.0500000000002, + "705": 96.15000000000002, + "706": 120.50000000000006, + "707": 101.24999999999996, + "708": 117.90000000000009, + "709": 99.35000000000012, + "710": 105.8499999999999, + "711": 110.10000000000012, + "712": 108.35000000000012, + "713": 82.49999999999997, + "714": 118.3000000000001, + "715": 106.25, + "716": 116.25000000000017, + "717": 105.15000000000006, + "718": 97.20000000000009, + "719": 112.10000000000018, + "720": 108.15000000000008, + "721": 115.15000000000003, + "722": 33.94999999999976, + "723": 108.95000000000014, + "724": 97.10000000000012, + "725": 111.90000000000019, + "726": 103.50000000000003, + "727": 116.6500000000001, + "728": 107.95000000000016, + "729": 105.2000000000001, + "730": 112.65000000000009, + "731": 112.60000000000018, + "732": 102.1000000000001, + "733": 107.89999999999995, + "734": 114.25000000000001, + "735": 106.80000000000007, + "736": 103.05000000000005, + "737": 104.49999999999996, + "738": 112.65000000000016, + "739": 100.05000000000017, + "740": 100.00000000000004, + "741": 116.35000000000007, + "742": 111.15000000000008, + "743": 106.54999999999997, + "744": 110.95, + "745": 107.20000000000007, + "746": 109.45000000000003, + "747": 108.70000000000014, + "748": 110.40000000000002, + "749": 113.15000000000003, + "750": 120.05000000000018, + "751": 111.45000000000009, + "752": 111.90000000000009, + "753": 85.50000000000004, + "754": 117.45000000000009, + "755": 112.40000000000018, + "756": 112.5500000000001, + "757": 110.35000000000007, + "758": 115.85000000000002, + "759": 98.94999999999987, + "760": 110.70000000000007, + "761": 112.15000000000015, + "762": 93.0000000000002, + "763": 115.75000000000028, + "764": 108.70000000000002, + "765": 111.25000000000004, + "766": 102.65, + "767": 102.14999999999995, + "768": 107.70000000000003, + "769": 115.99999999999997, + "770": 110.05000000000001, + "771": 116.70000000000007, + "772": 112.80000000000007, + "773": 112.70000000000005, + "774": 116.20000000000017, + "775": 112.70000000000014, + "776": 110.05000000000003, + "777": 117.25000000000006, + "778": 110.45, + "779": 111.20000000000009, + "780": 107.29999999999997, + "781": 108.45000000000013, + "782": 117.20000000000006, + "783": 111.05000000000007, + "784": 101.80000000000003, + "785": 115.05000000000004, + "786": 114.05000000000022, + "787": 110.4500000000002, + "788": 107.40000000000009, + "789": 107.85000000000014, + "790": 110.80000000000008, + "791": 106.39999999999993, + "792": 106.85000000000014, + "793": 112.3000000000001, + "794": 106.35000000000002, + "795": 111.90000000000005, + "796": 101.4, + "797": 115.3500000000001, + "798": 116.60000000000004, + "799": 112.64999999999996, + "800": 102.80000000000008, + "801": 114.60000000000016, + "802": 36.05000000000011, + "803": 109.45000000000016, + "804": 110.70000000000009, + "805": 107.1, + "806": 106.99999999999999, + "807": 116.80000000000004, + "808": 107.00000000000013, + "809": 115.60000000000008, + "810": 104.19999999999997, + "811": 119.10000000000002, + "812": 111.75000000000009, + "813": 118.95000000000019, + "814": 111.80000000000003, + "815": 118.05000000000004, + "816": 115.85000000000004, + "817": 108.85000000000012, + "818": 115.25000000000007, + "819": 114.55000000000003, + "820": 99.50000000000004, + "821": 114.00000000000003, + "822": 108.94999999999999, + "823": 104.25, + "824": 112.85000000000002, + "825": 102.94999999999995, + "826": 109.65000000000016, + "827": 113.55000000000024, + "828": 108.80000000000001, + "829": 103.44999999999983, + "830": 119.60000000000007, + "831": 116.20000000000003, + "832": 113.49999999999999, + "833": 119.50000000000006, + "834": 97.15000000000008, + "835": 98.99999999999996, + "836": 111.65000000000013, + "837": 110.20000000000013, + "838": 108.74999999999996, + "839": 114.65000000000012, + "840": 25.849999999999994, + "841": 108.05000000000013, + "842": 111.00000000000009, + "843": 107.90000000000018, + "844": 117.85000000000002, + "845": 110.40000000000012, + "846": 105.40000000000002, + "847": 99.85000000000008, + "848": 110.19999999999996, + "849": 113.24999999999996, + "850": 108.00000000000003, + "851": 109.75000000000001, + "852": 113.85000000000008, + "853": 108.79999999999997, + "854": 110.80000000000011, + "855": 116.00000000000007, + "856": 109.15000000000015, + "857": 110.50000000000006, + "858": 110.15000000000006, + "859": 108.40000000000002, + "860": 115.4000000000001, + "861": 112.05000000000004, + "862": 84.90000000000009, + "863": 110.65000000000002, + "864": 114.3500000000001, + "865": 118.80000000000001, + "866": 110.85000000000005, + "867": 106.49999999999996, + "868": 106.59999999999991, + "869": 103.20000000000013, + "870": 114.40000000000005, + "871": 122.30000000000007, + "872": 104.10000000000007, + "873": 115.15000000000016, + "874": 109.95000000000014, + "875": 113.7000000000001, + "876": 106.40000000000015, + "877": 115.30000000000013, + "878": 113.95000000000002, + "879": 112.69999999999999, + "880": 111.65, + "881": 115.15000000000016, + "882": 115.1, + "883": 114.20000000000007, + "884": 113.30000000000021, + "885": 110.70000000000009, + "886": 113.35000000000004, + "887": 111.94999999999999, + "888": 104.15000000000003, + "889": 118.05, + "890": 109.90000000000002, + "891": 117.95000000000006, + "892": 117.10000000000012, + "893": 115.40000000000015, + "894": 110.90000000000006, + "895": 110.74999999999994, + "896": 112.14999999999995, + "897": 110.20000000000005, + "898": 110.45000000000006, + "899": 115.65000000000013, + "900": 114.9000000000001, + "901": 108.89999999999996, + "902": 116.0500000000002, + "903": 114.65000000000003, + "904": 112.55000000000001, + "905": 113.05000000000001, + "906": 113.90000000000005, + "907": 109.95000000000014, + "908": 117.20000000000006, + "909": 111.05000000000014, + "910": 111.30000000000008, + "911": 116.85000000000014, + "912": 119.70000000000006, + "913": 117.45000000000013, + "914": 112.15000000000023, + "915": 113.1500000000001, + "916": 115.45000000000019, + "917": 108.04999999999998, + "918": 109.85000000000007, + "919": 108.50000000000001, + "920": 103.55000000000005, + "921": 113.10000000000022, + "922": 112.19999999999997, + "923": 107.09999999999994, + "924": 102.65, + "925": 110.85000000000012, + "926": 107.40000000000002, + "927": 112.40000000000002, + "928": 115.40000000000002, + "929": 109.85000000000014, + "930": 54.79999999999994, + "931": 108.34999999999994, + "932": 107.65000000000009, + "933": 108.5500000000001, + "934": 99.30000000000007, + "935": 118.10000000000014, + "936": 108.35000000000002, + "937": 106.90000000000015, + "938": 112.35000000000018, + "939": 101.5000000000001, + "940": 111.25000000000007, + "941": 113.30000000000011, + "942": 117.8500000000001, + "943": 116.30000000000018, + "944": 105.89999999999986, + "945": 112.85000000000007, + "946": 107.20000000000009, + "947": 108.00000000000013, + "948": 111.25000000000011, + "949": 106.65000000000005, + "950": 110.90000000000016, + "951": 109.60000000000007, + "952": 119.00000000000014, + "953": 114.35000000000004, + "954": 115.00000000000031, + "955": 106.55000000000005, + "956": 111.35000000000002, + "957": 111.85000000000008, + "958": 114.3500000000002, + "959": 114.25000000000006, + "960": 109.44999999999999, + "961": 109.15000000000003, + "962": 118.45000000000003, + "963": 108.50000000000017, + "964": 105.45000000000005, + "965": 113.95000000000013, + "966": 107.55000000000004, + "967": 111.25000000000007, + "968": 101.80000000000015, + "969": 109.99999999999997, + "970": 110.45000000000012, + "971": 110.7500000000001, + "972": 99.64999999999985, + "973": 104.50000000000006, + "974": 111.65000000000009, + "975": 112.9000000000001, + "976": 102.69999999999995, + "977": 108.34999999999994, + "978": 103.45000000000003, + "979": 104.8500000000002, + "980": 115.65, + "981": 105.25000000000001, + "982": 109.30000000000011, + "983": 106.49999999999996, + "984": 90.30000000000004, + "985": 111.20000000000005, + "986": 114.80000000000007, + "987": 116.50000000000004, + "988": 115.1000000000001, + "989": 108.54999999999998, + "990": 111.50000000000011, + "991": 109.10000000000011, + "992": 111.10000000000018, + "993": 105.65, + "994": 111.40000000000012, + "995": 108.1000000000001, + "996": 113.80000000000015, + "997": 112.3000000000001, + "998": 112.35000000000011, + "999": 110.30000000000007, + "1000": 118.05000000000011 + }, + "3": { + "1": -56.35000000000008, + "2": -16.69999999999997, + "3": -68.30000000000007, + "4": -55.55000000000008, + "5": -26.899999999999995, + "6": -33.05000000000004, + "7": -15.299999999999981, + "8": -18.999999999999964, + "9": -85.54999999999984, + "10": -15.699999999999974, + "11": -47.25000000000006, + "12": -47.75000000000001, + "13": -105.9, + "14": -23.599999999999948, + "15": -21.799999999999955, + "16": -35.24999999999999, + "17": -39.45000000000013, + "18": -11.3, + "19": -10.65, + "20": -15.949999999999976, + "21": -4.799999999999984, + "22": -23.69999999999995, + "23": 1.0000000000000446, + "24": -16.79999999999997, + "25": -5.8499999999999845, + "26": -28.649999999999963, + "27": -3.1999999999999753, + "28": -16.049999999999983, + "29": -30.549999999999944, + "30": -28.699999999999996, + "31": -19.04999999999997, + "32": -62.650000000000105, + "33": -11.199999999999985, + "34": -0.600000000000001, + "35": -16.04999999999998, + "36": -17.399999999999974, + "37": -21.049999999999958, + "38": -20.54999999999996, + "39": -18.849999999999966, + "40": -31.100000000000023, + "41": -13.39999999999999, + "42": -16.399999999999977, + "43": -19.54999999999997, + "44": -70.65000000000005, + "45": -23.19999999999995, + "46": -21.749999999999957, + "47": -99.5, + "48": -15.149999999999975, + "49": -22.750000000000007, + "50": -19.449999999999964, + "51": -19.599999999999966, + "52": -25.19999999999994, + "53": -94.59999999999997, + "54": -90.89999999999999, + "55": -15.599999999999964, + "56": -10.050000000000008, + "57": -47.40000000000007, + "58": -17.49999999999997, + "59": -36.050000000000104, + "60": -22.799999999999955, + "61": -4.29999999999998, + "62": -18.84999999999997, + "63": -27.49999999999995, + "64": -1.3499999999999772, + "65": -19.699999999999964, + "66": -41.450000000000024, + "67": -12.09999999999998, + "68": -19.599999999999966, + "69": -13.499999999999988, + "70": -22.249999999999954, + "71": 12.100000000000009, + "72": -20.149999999999963, + "73": -17.44999999999996, + "74": -17.099999999999973, + "75": -11.449999999999989, + "76": -18.699999999999978, + "77": -19.949999999999964, + "78": -8.899999999999991, + "79": -33.45000000000001, + "80": -15.299999999999978, + "81": -5.699999999999976, + "82": -87.80000000000001, + "83": -12.199999999999996, + "84": -99.44999999999999, + "85": 14.650000000000052, + "86": -9.099999999999998, + "87": -14.099999999999985, + "88": -13.89999999999999, + "89": -96.1, + "90": 3.0000000000000275, + "91": -4.049999999999979, + "92": -11.299999999999985, + "93": -19.549999999999965, + "94": -51.95000000000009, + "95": -14.199999999999982, + "96": -6.999999999999993, + "97": -9.999999999999993, + "98": 5.100000000000041, + "99": -27.149999999999963, + "100": -12.899999999999979, + "101": 18.000000000000004, + "102": -81.50000000000006, + "103": -53.50000000000008, + "104": -85.05, + "105": -20.59999999999996, + "106": -16.199999999999974, + "107": -20.749999999999957, + "108": 22.349999999999966, + "109": -20.299999999999965, + "110": -74.4, + "111": -4.849999999999994, + "112": 1.1500000000000503, + "113": 32.7499999999998, + "114": -76.44999999999997, + "115": -19.59999999999996, + "116": -13.699999999999994, + "117": -61.00000000000003, + "118": -82.14999999999996, + "119": 2.9000000000000217, + "120": -19.099999999999977, + "121": -10.450000000000001, + "122": 11.900000000000006, + "123": -31.649999999999967, + "124": -7.05, + "125": -61.65000000000004, + "126": -52.599999999999994, + "127": 14.450000000000024, + "128": -16.299999999999976, + "129": 0.2000000000000306, + "130": -75.35000000000002, + "131": -0.9999999999999869, + "132": -41.94999999999999, + "133": -0.099999999999975, + "134": -76.6, + "135": 19.799999999999997, + "136": -21.249999999999957, + "137": -84.5, + "138": -8.699999999999992, + "139": 16.400000000000055, + "140": -43.89999999999998, + "141": -23.549999999999947, + "142": -21.699999999999957, + "143": -96.1, + "144": -8.749999999999998, + "145": -1.099999999999996, + "146": 0.3500000000000114, + "147": 19.549999999999972, + "148": -6.300000000000003, + "149": -80.99999999999997, + "150": -90.60000000000001, + "151": -6.799999999999982, + "152": -5.949999999999982, + "153": -1.9499999999999629, + "154": 20.149999999999935, + "155": 26.65, + "156": -69.44999999999997, + "157": 14.35000000000004, + "158": -17.549999999999976, + "159": -18.449999999999967, + "160": -17.249999999999975, + "161": -14.299999999999969, + "162": -11.149999999999986, + "163": -79.35, + "164": -15.149999999999988, + "165": -77.25, + "166": 2.4499999999999957, + "167": -13.699999999999976, + "168": -85.0, + "169": -6.999999999999998, + "170": 21.34999999999995, + "171": -92.5, + "172": -12.649999999999983, + "173": -5.999999999999974, + "174": 20.55, + "175": -73.64999999999993, + "176": 42.449999999999804, + "177": 12.899999999999999, + "178": -65.25000000000007, + "179": -17.999999999999975, + "180": -52.80000000000008, + "181": -73.55000000000001, + "182": 47.14999999999987, + "183": -50.60000000000009, + "184": -84.80000000000001, + "185": -60.59999999999998, + "186": -51.54999999999996, + "187": -0.25000000000000977, + "188": -12.449999999999998, + "189": -3.94999999999998, + "190": 4.350000000000004, + "191": 36.04999999999978, + "192": -81.5, + "193": 8.850000000000076, + "194": -35.29999999999999, + "195": 14.600000000000005, + "196": -21.34999999999996, + "197": -92.85, + "198": 40.999999999999744, + "199": -102.6, + "200": 6.700000000000043, + "201": -17.099999999999973, + "202": -60.9, + "203": -10.100000000000017, + "204": -9.04999999999999, + "205": 19.999999999999943, + "206": -84.59999999999997, + "207": -14.29999999999994, + "208": 21.699999999999974, + "209": -10.549999999999992, + "210": -0.9499999999999902, + "211": -71.80000000000003, + "212": 71.4, + "213": -29.999999999999993, + "214": 21.949999999999935, + "215": -1.1499999999999844, + "216": -74.6, + "217": 3.3000000000000043, + "218": 5.600000000000062, + "219": -15.699999999999982, + "220": -47.19999999999999, + "221": 0.8000000000000482, + "222": -70.55000000000003, + "223": -63.250000000000014, + "224": -19.099999999999994, + "225": 40.39999999999979, + "226": -94.19999999999996, + "227": -20.35, + "228": 15.600000000000094, + "229": -70.25, + "230": 82.40000000000005, + "231": 21.899999999999938, + "232": -56.50000000000004, + "233": -8.999999999999991, + "234": 12.550000000000058, + "235": 2.750000000000033, + "236": 9.399999999999938, + "237": -8.450000000000017, + "238": -49.150000000000006, + "239": -8.500000000000027, + "240": -56.89999999999999, + "241": 0.7499999999999989, + "242": -0.6999999999999784, + "243": -41.89999999999998, + "244": -91.6, + "245": 40.79999999999988, + "246": -9.949999999999987, + "247": -14.099999999999984, + "248": 8.300000000000026, + "249": -18.049999999999972, + "250": -73.04999999999998, + "251": -93.50000000000006, + "252": 3.300000000000035, + "253": -19.399999999999967, + "254": -64.70000000000003, + "255": -23.150000000000002, + "256": -16.59999999999998, + "257": -20.39999999999998, + "258": 42.799999999999784, + "259": 3.049999999999982, + "260": -69.55000000000001, + "261": -9.399999999999995, + "262": -2.3999999999999897, + "263": 0.6500000000000241, + "264": -9.750000000000044, + "265": 53.7999999999999, + "266": 0.3500000000000505, + "267": -69.49999999999999, + "268": -11.499999999999995, + "269": -69.19999999999997, + "270": 40.09999999999976, + "271": -75.04999999999995, + "272": 15.450000000000028, + "273": -85.94999999999999, + "274": 16.099999999999937, + "275": -13.199999999999989, + "276": 33.49999999999981, + "277": -79.65, + "278": -11.900000000000007, + "279": 65.29999999999998, + "280": 14.550000000000079, + "281": -74.00000000000001, + "282": 49.09999999999979, + "283": -22.349999999999994, + "284": -15.54999999999996, + "285": -9.499999999999995, + "286": -78.05000000000001, + "287": -10.34999999999999, + "288": 0.8500000000000418, + "289": -2.5500000000000176, + "290": -54.19999999999996, + "291": 7.650000000000061, + "292": -21.200000000000006, + "293": -67.25, + "294": -24.299999999999972, + "295": -21.600000000000012, + "296": -13.59999999999999, + "297": 3.750000000000041, + "298": -80.85, + "299": -2.800000000000021, + "300": 21.749999999999957, + "301": -9.450000000000031, + "302": -9.050000000000004, + "303": 18.900000000000002, + "304": -5.199999999999986, + "305": 12.549999999999995, + "306": 3.099999999999995, + "307": 8.35000000000002, + "308": -9.350000000000001, + "309": 18.500000000000018, + "310": -37.35000000000003, + "311": 30.049999999999947, + "312": -40.400000000000034, + "313": -69.89999999999999, + "314": -2.6999999999999176, + "315": -64.79999999999993, + "316": -49.350000000000016, + "317": 66.44999999999993, + "318": 103.95000000000017, + "319": 52.04999999999989, + "320": 90.85000000000022, + "321": 41.24999999999989, + "322": 0.5999999999999952, + "323": -6.849999999999985, + "324": -12.85000000000003, + "325": -13.150000000000034, + "326": -39.550000000000054, + "327": 59.899999999999835, + "328": 10.150000000000011, + "329": -4.650000000000022, + "330": 19.349999999999994, + "331": 91.60000000000015, + "332": 1.9500000000000075, + "333": -17.099999999999977, + "334": 33.149999999999956, + "335": -69.75000000000001, + "336": 33.69999999999994, + "337": -18.650000000000002, + "338": 63.049999999999976, + "339": -29.75000000000002, + "340": 14.05000000000004, + "341": 27.499999999999954, + "342": -10.450000000000005, + "343": 67.04999999999976, + "344": -78.64999999999999, + "345": 5.2500000000000195, + "346": -58.349999999999916, + "347": 23.44999999999997, + "348": 65.74999999999987, + "349": 63.75000000000005, + "350": -10.250000000000004, + "351": 81.09999999999995, + "352": 76.85000000000014, + "353": 24.599999999999998, + "354": 72.95000000000006, + "355": 45.94999999999999, + "356": 78.95000000000007, + "357": 108.10000000000014, + "358": 45.19999999999994, + "359": 107.55000000000021, + "360": -15.000000000000012, + "361": 44.899999999999885, + "362": 22.849999999999923, + "363": 106.75000000000024, + "364": -34.54999999999997, + "365": 112.10000000000024, + "366": 89.85000000000012, + "367": 82.30000000000007, + "368": 95.04999999999995, + "369": 65.39999999999993, + "370": 39.049999999999955, + "371": 57.99999999999983, + "372": 84.70000000000006, + "373": 34.74999999999996, + "374": 88.10000000000001, + "375": 64.79999999999993, + "376": 66.2499999999998, + "377": 60.19999999999985, + "378": 13.750000000000068, + "379": 30.449999999999974, + "380": -20.35000000000001, + "381": 77.84999999999995, + "382": 24.40000000000001, + "383": 113.7500000000003, + "384": 72.55000000000007, + "385": 0.20000000000001217, + "386": 47.29999999999996, + "387": 74.04999999999987, + "388": 33.89999999999996, + "389": -6.949999999999993, + "390": 87.45000000000007, + "391": 115.05000000000025, + "392": 97.15000000000018, + "393": 74.95000000000007, + "394": 107.95, + "395": 84.79999999999997, + "396": 86.60000000000025, + "397": 93.40000000000005, + "398": 99.0000000000002, + "399": 3.8499999999999814, + "400": 109.70000000000022, + "401": 78.29999999999994, + "402": 87.59999999999995, + "403": 66.04999999999995, + "404": 39.999999999999964, + "405": 112.00000000000024, + "406": -8.249999999999986, + "407": 48.7499999999999, + "408": 47.79999999999987, + "409": 107.65000000000018, + "410": 104.10000000000021, + "411": 84.59999999999998, + "412": 108.05000000000004, + "413": 62.24999999999991, + "414": 82.50000000000017, + "415": 108.85000000000016, + "416": 113.3000000000001, + "417": 114.5500000000002, + "418": 46.44999999999994, + "419": 36.6, + "420": 81.6, + "421": 77.95000000000003, + "422": 91.30000000000008, + "423": 64.84999999999994, + "424": 106.90000000000016, + "425": 93.6000000000001, + "426": 100.95000000000024, + "427": 44.69999999999999, + "428": 111.40000000000026, + "429": 115.55000000000025, + "430": 99.8500000000001, + "431": 45.34999999999979, + "432": 112.60000000000025, + "433": -61.549999999999955, + "434": 96.6500000000001, + "435": 108.45000000000023, + "436": -8.34999999999999, + "437": 14.999999999999948, + "438": 94.8000000000001, + "439": 101.75000000000017, + "440": 88.8000000000001, + "441": 119.90000000000009, + "442": 86.30000000000004, + "443": 91.54999999999978, + "444": 88.09999999999981, + "445": 112.70000000000017, + "446": 62.79999999999996, + "447": 101.40000000000016, + "448": 111.75000000000007, + "449": 112.05000000000003, + "450": 99.65000000000026, + "451": 116.00000000000024, + "452": 105.40000000000019, + "453": 28.09999999999999, + "454": 81.7500000000002, + "455": 103.85000000000024, + "456": 114.50000000000027, + "457": 92.29999999999997, + "458": 117.25000000000028, + "459": 100.80000000000017, + "460": 109.95000000000023, + "461": 112.05000000000014, + "462": 88.20000000000014, + "463": 68.54999999999987, + "464": 68.09999999999977, + "465": 67.34999999999994, + "466": 25.299999999999976, + "467": 27.349999999999923, + "468": 111.40000000000012, + "469": 67.79999999999994, + "470": 118.05000000000027, + "471": -3.75000000000003, + "472": 114.45000000000026, + "473": 120.00000000000028, + "474": 91.50000000000007, + "475": 103.6999999999999, + "476": 60.89999999999992, + "477": 111.75000000000023, + "478": 66.94999999999999, + "479": 98.74999999999991, + "480": 119.40000000000028, + "481": 97.0, + "482": 117.0500000000003, + "483": 116.9500000000002, + "484": 117.20000000000024, + "485": 93.94999999999997, + "486": 106.90000000000008, + "487": 99.0500000000001, + "488": 111.65000000000002, + "489": 83.75000000000009, + "490": 2.750000000000017, + "491": 99.65000000000012, + "492": 96.10000000000012, + "493": 32.24999999999996, + "494": 85.90000000000006, + "495": 95.60000000000004, + "496": 119.75000000000017, + "497": 88.39999999999985, + "498": 114.85000000000016, + "499": 42.09999999999992, + "500": 103.95000000000027, + "501": 95.15000000000005, + "502": 81.95000000000002, + "503": 80.30000000000011, + "504": 96.65000000000012, + "505": 116.15000000000006, + "506": 110.75000000000021, + "507": 95.84999999999998, + "508": 54.99999999999988, + "509": 106.35000000000007, + "510": 115.80000000000025, + "511": 101.69999999999982, + "512": 99.55000000000011, + "513": -71.49999999999989, + "514": 101.95000000000007, + "515": 81.44999999999996, + "516": 97.45000000000007, + "517": 109.90000000000002, + "518": 119.9, + "519": 89.9000000000001, + "520": 113.85000000000025, + "521": 78.19999999999987, + "522": 98.0000000000001, + "523": 98.65000000000009, + "524": 107.24999999999999, + "525": 81.45000000000007, + "526": 71.0499999999999, + "527": 93.5500000000002, + "528": 49.149999999999885, + "529": 114.60000000000014, + "530": 115.45000000000002, + "531": 113.15000000000018, + "532": 81.90000000000003, + "533": 88.15, + "534": 102.15000000000005, + "535": 98.95000000000022, + "536": 104.30000000000018, + "537": 106.00000000000003, + "538": 115.95000000000012, + "539": 115.05000000000027, + "540": 109.85000000000001, + "541": 108.7000000000001, + "542": 86.70000000000002, + "543": 49.29999999999997, + "544": 81.99999999999999, + "545": 79.9, + "546": 104.7, + "547": 100.75000000000011, + "548": 105.69999999999999, + "549": 92.05000000000011, + "550": 64.29999999999988, + "551": 83.25000000000003, + "552": 111.00000000000016, + "553": 115.20000000000026, + "554": -21.750000000000014, + "555": 116.20000000000016, + "556": 96.80000000000005, + "557": 113.20000000000005, + "558": 112.70000000000007, + "559": 122.35000000000007, + "560": 109.6, + "561": 109.7000000000001, + "562": 111.85000000000002, + "563": 94.5500000000002, + "564": 109.4000000000002, + "565": 93.10000000000005, + "566": 77.35000000000001, + "567": 103.7500000000001, + "568": 94.04999999999991, + "569": 98.55000000000008, + "570": 108.10000000000001, + "571": 111.35000000000001, + "572": 113.85000000000007, + "573": 110.4000000000001, + "574": 105.74999999999996, + "575": 105.39999999999988, + "576": 107.3999999999999, + "577": 95.50000000000004, + "578": 114.90000000000026, + "579": 87.65000000000006, + "580": 116.75000000000003, + "581": 122.55000000000003, + "582": 105.95000000000003, + "583": 108.00000000000016, + "584": 110.25000000000016, + "585": 90.95000000000009, + "586": 116.4000000000002, + "587": 111.6000000000001, + "588": 108.30000000000004, + "589": 88.84999999999995, + "590": 100.2500000000001, + "591": 109.75000000000004, + "592": 109.95000000000006, + "593": 93.50000000000013, + "594": 116.70000000000009, + "595": 113.00000000000007, + "596": 91.30000000000015, + "597": 106.50000000000003, + "598": 94.50000000000003, + "599": 117.8500000000002, + "600": 114.50000000000003, + "601": 103.90000000000002, + "602": 101.80000000000013, + "603": 99.30000000000007, + "604": 116.80000000000015, + "605": 115.70000000000003, + "606": 113.5, + "607": 105.25000000000013, + "608": 108.65, + "609": 105.94999999999997, + "610": 103.65, + "611": 111.40000000000023, + "612": 112.89999999999998, + "613": 98.60000000000001, + "614": 91.74999999999996, + "615": 114.5000000000001, + "616": 91.54999999999994, + "617": 95.00000000000011, + "618": 74.99999999999986, + "619": 110.00000000000011, + "620": 112.25000000000013, + "621": 108.05000000000011, + "622": 116.80000000000003, + "623": 92.35000000000011, + "624": 108.69999999999995, + "625": 109.8000000000001, + "626": 101.1, + "627": 103.49999999999996, + "628": 54.04999999999981, + "629": 95.85, + "630": 114.30000000000017, + "631": 93.10000000000015, + "632": 90.60000000000016, + "633": 72.44999999999986, + "634": 115.69999999999996, + "635": 73.34999999999987, + "636": 121.45000000000007, + "637": 89.75, + "638": 79.55000000000004, + "639": 110.19999999999997, + "640": 108.50000000000004, + "641": 114.95000000000005, + "642": 107.25000000000003, + "643": 121.95000000000003, + "644": 118.90000000000012, + "645": 115.35, + "646": 102.3500000000001, + "647": 113.00000000000014, + "648": 103.65000000000003, + "649": 118.55000000000005, + "650": 108.55000000000008, + "651": 120.95, + "652": 101.50000000000018, + "653": 109.60000000000016, + "654": 115.90000000000005, + "655": 106.50000000000001, + "656": 114.40000000000006, + "657": 101.94999999999996, + "658": 116.50000000000013, + "659": 119.05000000000004, + "660": 99.15000000000003, + "661": 51.64999999999985, + "662": 102.20000000000006, + "663": 103.09999999999995, + "664": 112.70000000000016, + "665": 106.75000000000001, + "666": 112.20000000000006, + "667": 108.5, + "668": 102.99999999999999, + "669": 115.70000000000012, + "670": 107.15000000000006, + "671": 98.25000000000001, + "672": 118.05000000000017, + "673": 112.70000000000012, + "674": 109.1000000000001, + "675": 117.05, + "676": 107.35000000000007, + "677": 108.10000000000008, + "678": 104.10000000000001, + "679": 100.0000000000001, + "680": 91.24999999999996, + "681": 107.65000000000003, + "682": 114.10000000000002, + "683": 115.25000000000004, + "684": 108.94999999999996, + "685": 120.94999999999997, + "686": 88.65000000000002, + "687": 103.35000000000002, + "688": 109.75000000000013, + "689": 112.30000000000013, + "690": 112.30000000000015, + "691": 117.65000000000008, + "692": 114.3000000000001, + "693": 111.05000000000025, + "694": 112.80000000000017, + "695": 112.15, + "696": 111.34999999999995, + "697": 111.95000000000005, + "698": 113.60000000000004, + "699": 108.05000000000011, + "700": 118.95000000000003, + "701": 110.10000000000014, + "702": 118.25000000000016, + "703": 109.75000000000009, + "704": 110.35000000000005, + "705": 108.95000000000006, + "706": 104.15000000000006, + "707": 116.25, + "708": 109.10000000000021, + "709": 115.8, + "710": 111.50000000000017, + "711": 118.20000000000013, + "712": 114.70000000000003, + "713": 115.30000000000014, + "714": 114.00000000000007, + "715": 100.19999999999995, + "716": 108.15000000000015, + "717": 111.00000000000021, + "718": 99.05000000000001, + "719": 110.84999999999998, + "720": 121.30000000000004, + "721": 112.10000000000007, + "722": 110.15000000000002, + "723": 98.00000000000007, + "724": 116.25000000000006, + "725": 99.55000000000005, + "726": 116.10000000000008, + "727": 112.10000000000008, + "728": 103.80000000000011, + "729": 109.30000000000008, + "730": 100.40000000000005, + "731": 101.14999999999996, + "732": -2.499999999999968, + "733": 114.30000000000017, + "734": 110.45, + "735": 113.00000000000023, + "736": 117.05000000000015, + "737": 109.20000000000007, + "738": 65.09999999999992, + "739": 114.85000000000014, + "740": 110.0, + "741": 110.4500000000001, + "742": 114.45000000000012, + "743": 112.2000000000001, + "744": 107.30000000000017, + "745": 109.05000000000005, + "746": 111.10000000000001, + "747": 116.25000000000023, + "748": 108.75, + "749": 95.89999999999999, + "750": 112.05000000000004, + "751": 111.60000000000005, + "752": 111.3500000000001, + "753": 111.90000000000009, + "754": 105.60000000000007, + "755": 104.59999999999998, + "756": 115.75000000000017, + "757": 114.20000000000007, + "758": 117.85000000000005, + "759": 119.05000000000003, + "760": 107.65000000000003, + "761": 106.8500000000002, + "762": 107.19999999999995, + "763": 114.60000000000002, + "764": 102.80000000000004, + "765": 111.55000000000005, + "766": 82.74999999999999, + "767": 104.5500000000001, + "768": 114.85000000000008, + "769": 115.00000000000009, + "770": 109.79999999999995, + "771": 113.95000000000005, + "772": 51.149999999999814, + "773": 103.64999999999998, + "774": 103.55000000000011, + "775": 117.65000000000005, + "776": 111.3999999999999, + "777": 112.40000000000009, + "778": 113.6500000000001, + "779": 124.85000000000012, + "780": 112.75000000000014, + "781": 106.2500000000001, + "782": 121.00000000000003, + "783": 114.15, + "784": 112.60000000000004, + "785": 108.85000000000015, + "786": 107.85000000000008, + "787": 115.40000000000009, + "788": 114.30000000000008, + "789": 119.55000000000007, + "790": 113.69999999999997, + "791": 108.05000000000018, + "792": 109.55000000000011, + "793": 112.0000000000002, + "794": 112.25000000000009, + "795": 111.75000000000017, + "796": 106.49999999999996, + "797": 104.55000000000004, + "798": 119.15000000000002, + "799": 113.50000000000016, + "800": 112.0500000000001, + "801": 109.1000000000001, + "802": 112.59999999999998, + "803": 114.30000000000018, + "804": 114.85000000000001, + "805": 113.35000000000005, + "806": 108.30000000000015, + "807": 116.75000000000009, + "808": 112.84999999999997, + "809": 117.94999999999999, + "810": 111.49999999999999, + "811": 112.24999999999997, + "812": 115.2500000000001, + "813": 110.05000000000003, + "814": 117.55000000000014, + "815": 101.80000000000001, + "816": 107.49999999999996, + "817": 109.49999999999993, + "818": 109.24999999999999, + "819": 111.25000000000004, + "820": 106.60000000000008, + "821": 106.20000000000009, + "822": 105.74999999999999, + "823": 98.6000000000001, + "824": 109.60000000000005, + "825": 114.70000000000005, + "826": 99.55000000000005, + "827": 112.2500000000001, + "828": 111.4000000000002, + "829": 91.00000000000004, + "830": 108.55000000000004, + "831": 113.35000000000018, + "832": 118.69999999999999, + "833": 113.85000000000004, + "834": 105.55000000000008, + "835": 113.1500000000001, + "836": 114.34999999999994, + "837": 97.65000000000005, + "838": 116.75000000000003, + "839": 110.55000000000013, + "840": 116.25000000000021, + "841": 103.20000000000007, + "842": 120.94999999999999, + "843": 112.00000000000013, + "844": 99.30000000000008, + "845": 116.00000000000024, + "846": 110.2500000000001, + "847": 102.95000000000005, + "848": 110.00000000000003, + "849": 110.15000000000012, + "850": 112.40000000000013, + "851": 111.50000000000016, + "852": 106.74999999999991, + "853": 119.45000000000006, + "854": 85.55000000000007, + "855": 116.85000000000014, + "856": 107.8, + "857": 108.1499999999999, + "858": 106.89999999999988, + "859": 102.8499999999999, + "860": 109.90000000000018, + "861": 114.00000000000003, + "862": 102.84999999999992, + "863": 114.9000000000001, + "864": 114.74999999999994, + "865": 111.85000000000008, + "866": 108.00000000000006, + "867": 110.55000000000001, + "868": 116.59999999999995, + "869": 113.55000000000022, + "870": 118.90000000000006, + "871": 112.75000000000001, + "872": 116.25, + "873": 107.60000000000002, + "874": 114.90000000000008, + "875": 116.45000000000009, + "876": 109.90000000000008, + "877": 108.90000000000013, + "878": 118.80000000000014, + "879": 102.80000000000008, + "880": 116.10000000000004, + "881": 106.45000000000014, + "882": 77.75, + "883": 109.25000000000014, + "884": 106.30000000000011, + "885": 113.00000000000011, + "886": 112.90000000000009, + "887": 115.80000000000003, + "888": 107.15000000000006, + "889": 112.20000000000009, + "890": 111.55000000000013, + "891": 117.10000000000014, + "892": 111.95000000000002, + "893": 92.45000000000005, + "894": 108.84999999999992, + "895": 98.10000000000007, + "896": 116.20000000000009, + "897": 106.44999999999999, + "898": 103.00000000000014, + "899": 105.69999999999995, + "900": 112.05000000000001, + "901": 110.49999999999999, + "902": 104.89999999999999, + "903": 119.3000000000001, + "904": 115.4000000000002, + "905": 106.50000000000014, + "906": 105.60000000000016, + "907": 110.35000000000004, + "908": 114.90000000000005, + "909": 116.80000000000018, + "910": 112.30000000000003, + "911": 115.25000000000003, + "912": 116.60000000000011, + "913": 108.65000000000006, + "914": 106.75000000000016, + "915": 112.25000000000001, + "916": 107.45000000000022, + "917": 112.0, + "918": 109.34999999999995, + "919": 109.15000000000013, + "920": 118.65000000000013, + "921": 104.80000000000013, + "922": 108.24999999999991, + "923": 110.30000000000013, + "924": 107.45000000000009, + "925": 110.90000000000006, + "926": 104.55000000000004, + "927": 109.00000000000013, + "928": 122.10000000000014, + "929": 116.9, + "930": 117.35000000000004, + "931": 110.90000000000012, + "932": 109.80000000000013, + "933": 113.55000000000003, + "934": 113.7500000000001, + "935": 107.30000000000004, + "936": 113.10000000000007, + "937": 109.65000000000016, + "938": 111.80000000000008, + "939": 108.40000000000018, + "940": 115.15000000000015, + "941": 109.40000000000009, + "942": 112.4, + "943": 111.64999999999996, + "944": 103.94999999999996, + "945": 103.00000000000007, + "946": 106.55000000000008, + "947": 118.5500000000001, + "948": 118.05000000000022, + "949": 108.85000000000012, + "950": 69.24999999999997, + "951": 118.3, + "952": 106.74999999999993, + "953": 112.00000000000018, + "954": 93.65000000000003, + "955": 109.60000000000024, + "956": 110.80000000000014, + "957": 102.65000000000003, + "958": 104.24999999999996, + "959": 109.6, + "960": 115.80000000000011, + "961": 102.69999999999995, + "962": 112.65000000000006, + "963": 106.04999999999991, + "964": 117.90000000000002, + "965": 116.30000000000007, + "966": 113.70000000000007, + "967": 110.55000000000008, + "968": 107.75000000000004, + "969": 111.1, + "970": 104.84999999999988, + "971": 108.7500000000001, + "972": 107.75000000000004, + "973": 116.75000000000004, + "974": 117.50000000000006, + "975": 111.10000000000016, + "976": 105.90000000000006, + "977": 105.80000000000008, + "978": 113.45000000000009, + "979": 107.90000000000009, + "980": 110.74999999999994, + "981": 111.8500000000001, + "982": 117.55000000000004, + "983": 113.90000000000009, + "984": 103.55000000000005, + "985": 113.84999999999998, + "986": 104.8500000000001, + "987": 114.15000000000022, + "988": 112.00000000000007, + "989": 109.10000000000008, + "990": 111.49999999999996, + "991": 112.90000000000009, + "992": 69.09999999999988, + "993": 106.49999999999999, + "994": 111.00000000000016, + "995": 40.449999999999946, + "996": 104.59999999999994, + "997": 117.10000000000007, + "998": 107.10000000000012, + "999": 118.44999999999996, + "1000": 108.20000000000029 + }, + "4": { + "1": -51.95000000000008, + "2": -19.94999999999998, + "3": -60.0500000000001, + "4": -56.90000000000009, + "5": -27.900000000000013, + "6": -40.25000000000004, + "7": -28.29999999999997, + "8": -49.30000000000007, + "9": -58.75000000000002, + "10": -74.15, + "11": -22.249999999999947, + "12": -25.399999999999952, + "13": -28.19999999999998, + "14": -45.250000000000014, + "15": -21.649999999999988, + "16": -56.80000000000011, + "17": -69.20000000000006, + "18": -19.99999999999996, + "19": -59.75000000000009, + "20": -53.40000000000016, + "21": -42.35000000000004, + "22": -11.699999999999989, + "23": -23.599999999999948, + "24": -35.45000000000003, + "25": -20.59999999999996, + "26": -55.55000000000008, + "27": -27.099999999999955, + "28": -44.400000000000055, + "29": -46.90000000000016, + "30": -56.300000000000125, + "31": -95.0, + "32": -107.35, + "33": -16.699999999999985, + "34": -16.599999999999977, + "35": -25.350000000000012, + "36": -72.94999999999999, + "37": -30.400000000000016, + "38": -10.649999999999983, + "39": -21.599999999999955, + "40": -17.499999999999975, + "41": -13.349999999999977, + "42": -27.249999999999932, + "43": -16.899999999999974, + "44": -66.54999999999997, + "45": -6.950000000000002, + "46": -18.34999999999997, + "47": -44.0000000000001, + "48": -41.95000000000005, + "49": -20.84999999999996, + "50": -17.249999999999968, + "51": -18.699999999999967, + "52": -4.899999999999997, + "53": -14.29999999999999, + "54": -75.94999999999997, + "55": -13.899999999999986, + "56": -18.09999999999995, + "57": -6.899999999999999, + "58": -22.79999999999995, + "59": -6.249999999999991, + "60": -12.749999999999973, + "61": -19.099999999999966, + "62": -19.499999999999964, + "63": -10.199999999999992, + "64": 15.55000000000003, + "65": -21.050000000000026, + "66": -16.099999999999977, + "67": -11.350000000000003, + "68": -21.949999999999957, + "69": -13.949999999999994, + "70": -22.449999999999953, + "71": -37.6000000000001, + "72": -16.449999999999978, + "73": -21.999999999999954, + "74": 13.299999999999997, + "75": -10.349999999999982, + "76": -20.44999999999996, + "77": -18.049999999999958, + "78": -87.3, + "79": -9.549999999999986, + "80": 2.2000000000000144, + "81": -13.399999999999986, + "82": -9.300000000000002, + "83": 7.800000000000039, + "84": -9.499999999999995, + "85": -1.7999999999999956, + "86": -19.79999999999996, + "87": -18.999999999999964, + "88": -28.300000000000026, + "89": -11.049999999999988, + "90": -3.599999999999988, + "91": -57.05000000000006, + "92": -21.349999999999955, + "93": -8.3, + "94": -33.24999999999998, + "95": -16.949999999999964, + "96": -1.9999999999999973, + "97": -96.30000000000001, + "98": 7.90000000000003, + "99": -71.85, + "100": 1.600000000000041, + "101": -7.950000000000026, + "102": -17.84999999999997, + "103": -15.999999999999973, + "104": -8.199999999999994, + "105": 9.75000000000005, + "106": 7.000000000000074, + "107": -1.499999999999996, + "108": -11.699999999999985, + "109": -30.049999999999986, + "110": -17.549999999999972, + "111": 20.25000000000002, + "112": -23.79999999999997, + "113": 52.849999999999866, + "114": -90.39999999999995, + "115": -12.499999999999982, + "116": 30.199999999999832, + "117": 15.149999999999949, + "118": -50.39999999999998, + "119": 4.150000000000036, + "120": 12.500000000000025, + "121": 19.149999999999984, + "122": 3.199999999999987, + "123": -13.499999999999984, + "124": -10.999999999999993, + "125": -33.90000000000001, + "126": -80.6, + "127": 7.450000000000011, + "128": -15.549999999999962, + "129": 22.699999999999864, + "130": -96.25, + "131": 21.39999999999999, + "132": -6.499999999999986, + "133": 49.249999999999815, + "134": -18.89999999999996, + "135": 19.49999999999998, + "136": -19.099999999999966, + "137": 9.350000000000058, + "138": 12.300000000000008, + "139": 14.60000000000002, + "140": -11.899999999999993, + "141": -25.400000000000027, + "142": -11.64999999999999, + "143": 35.34999999999992, + "144": 7.05000000000006, + "145": 1.2499999999999956, + "146": -8.749999999999988, + "147": -74.20000000000002, + "148": -34.350000000000044, + "149": -8.999999999999975, + "150": -79.3, + "151": 11.850000000000076, + "152": -18.09999999999997, + "153": 9.200000000000069, + "154": -19.79999999999996, + "155": -73.19999999999999, + "156": -82.35000000000002, + "157": -8.350000000000007, + "158": -22.799999999999958, + "159": 82.0999999999999, + "160": 18.149999999999952, + "161": -26.249999999999968, + "162": 84.65, + "163": -24.849999999999977, + "164": 34.64999999999978, + "165": 39.24999999999988, + "166": -90.84999999999998, + "167": -34.3, + "168": 38.299999999999855, + "169": -29.050000000000004, + "170": -59.000000000000014, + "171": -10.39999999999999, + "172": -11.849999999999993, + "173": -5.8499999999999845, + "174": 29.35000000000004, + "175": 26.199999999999942, + "176": -15.1, + "177": 33.49999999999988, + "178": -72.50000000000001, + "179": 18.29999999999993, + "180": -34.50000000000004, + "181": 26.650000000000023, + "182": -56.69999999999998, + "183": 0.3500000000000256, + "184": -43.34999999999998, + "185": 3.950000000000012, + "186": 27.800000000000022, + "187": -9.949999999999994, + "188": 40.60000000000003, + "189": 46.499999999999766, + "190": 4.800000000000043, + "191": -9.649999999999997, + "192": -60.749999999999986, + "193": -7.949999999999993, + "194": -11.54999999999998, + "195": 2.8500000000000263, + "196": -9.399999999999988, + "197": -13.399999999999993, + "198": 19.79999999999999, + "199": 46.29999999999978, + "200": -39.899999999999984, + "201": 47.04999999999983, + "202": 23.650000000000013, + "203": -5.950000000000013, + "204": 24.550000000000068, + "205": 45.24999999999988, + "206": 99.04999999999974, + "207": 2.5500000000000207, + "208": -57.44999999999994, + "209": 9.150000000000016, + "210": 3.0499999999998817, + "211": 79.69999999999983, + "212": 47.59999999999991, + "213": 38.199999999999996, + "214": 23.900000000000023, + "215": 44.34999999999995, + "216": 65.04999999999987, + "217": 74.59999999999975, + "218": 64.44999999999975, + "219": 66.54999999999977, + "220": 22.899999999999913, + "221": 9.599999999999941, + "222": 24.550000000000036, + "223": -30.44999999999999, + "224": 75.14999999999984, + "225": 43.849999999999795, + "226": 82.9500000000001, + "227": 29.649999999999984, + "228": 90.35000000000012, + "229": -87.2, + "230": -20.500000000000075, + "231": 67.14999999999972, + "232": 25.59999999999999, + "233": -75.95000000000002, + "234": 9.950000000000038, + "235": 79.4999999999998, + "236": 22.500000000000057, + "237": 31.899999999999988, + "238": -9.749999999999972, + "239": 51.64999999999997, + "240": 72.0499999999998, + "241": 29.250000000000057, + "242": 63.9499999999999, + "243": 24.999999999999826, + "244": -23.650000000000006, + "245": 80.94999999999995, + "246": 54.499999999999915, + "247": 27.450000000000003, + "248": 41.550000000000004, + "249": 61.44999999999976, + "250": 33.70000000000005, + "251": 38.64999999999997, + "252": 104.3500000000002, + "253": 84.75000000000007, + "254": -8.349999999999989, + "255": 38.34999999999975, + "256": 63.6499999999998, + "257": 70.74999999999983, + "258": 89.39999999999975, + "259": 75.79999999999986, + "260": 62.74999999999992, + "261": 89.90000000000006, + "262": 58.59999999999977, + "263": 65.54999999999983, + "264": 95.89999999999998, + "265": 15.400000000000073, + "266": 94.49999999999974, + "267": 10.950000000000067, + "268": 103.70000000000026, + "269": 89.69999999999982, + "270": 93.34999999999977, + "271": 99.54999999999973, + "272": 105.04999999999977, + "273": -11.050000000000011, + "274": 97.24999999999991, + "275": 94.09999999999974, + "276": 69.84999999999982, + "277": 57.54999999999991, + "278": -58.29999999999998, + "279": 69.94999999999979, + "280": 44.14999999999976, + "281": -9.899999999999993, + "282": 111.95000000000013, + "283": 79.04999999999986, + "284": 23.00000000000004, + "285": 70.74999999999973, + "286": 93.55000000000004, + "287": 73.54999999999991, + "288": 90.7500000000001, + "289": 71.79999999999973, + "290": 72.74999999999986, + "291": 107.69999999999982, + "292": 58.49999999999977, + "293": 36.84999999999997, + "294": 92.94999999999979, + "295": 101.39999999999974, + "296": 105.75000000000013, + "297": 102.54999999999976, + "298": 41.94999999999994, + "299": 47.299999999999926, + "300": 96.54999999999983, + "301": 58.4999999999998, + "302": 84.25000000000003, + "303": 100.14999999999976, + "304": 60.99999999999973, + "305": 106.14999999999984, + "306": 115.55000000000021, + "307": 117.90000000000026, + "308": 104.34999999999981, + "309": 73.3000000000001, + "310": 95.09999999999975, + "311": 40.24999999999997, + "312": 96.39999999999988, + "313": 107.60000000000021, + "314": 90.59999999999978, + "315": 107.7500000000001, + "316": 73.90000000000008, + "317": 44.799999999999955, + "318": 97.64999999999978, + "319": 83.29999999999983, + "320": 105.30000000000022, + "321": 73.89999999999998, + "322": 62.34999999999992, + "323": 103.79999999999978, + "324": 97.24999999999974, + "325": 23.200000000000056, + "326": 12.34999999999999, + "327": 52.649999999999984, + "328": 84.5499999999998, + "329": 78.99999999999996, + "330": 71.84999999999985, + "331": 81.64999999999984, + "332": 112.29999999999997, + "333": 105.95000000000012, + "334": 107.84999999999974, + "335": 108.1, + "336": -43.70000000000001, + "337": 82.94999999999979, + "338": 110.20000000000023, + "339": 90.55000000000001, + "340": 102.80000000000018, + "341": 101.64999999999976, + "342": 44.94999999999998, + "343": 58.799999999999855, + "344": 104.5000000000001, + "345": 74.50000000000001, + "346": 71.79999999999997, + "347": 71.84999999999988, + "348": 49.79999999999999, + "349": 103.44999999999999, + "350": 101.20000000000002, + "351": 113.25000000000018, + "352": 112.1500000000001, + "353": 95.19999999999986, + "354": 105.20000000000005, + "355": 108.7499999999998, + "356": 104.59999999999995, + "357": 107.50000000000016, + "358": 114.8000000000001, + "359": 95.69999999999982, + "360": 100.89999999999974, + "361": 88.19999999999975, + "362": 95.8, + "363": 96.25000000000013, + "364": 108.85000000000021, + "365": 115.50000000000027, + "366": 82.25000000000001, + "367": 90.79999999999994, + "368": 109.14999999999979, + "369": 107.34999999999977, + "370": 70.29999999999995, + "371": 112.80000000000021, + "372": 97.90000000000005, + "373": 95.50000000000001, + "374": 110.85000000000014, + "375": 110.79999999999997, + "376": 89.90000000000002, + "377": 109.89999999999989, + "378": 113.65000000000016, + "379": 101.50000000000017, + "380": 83.80000000000005, + "381": 109.10000000000004, + "382": 95.00000000000004, + "383": 97.79999999999998, + "384": 83.70000000000003, + "385": 103.95000000000014, + "386": 105.60000000000012, + "387": 103.5500000000001, + "388": 114.55000000000027, + "389": 106.00000000000013, + "390": 114.45000000000023, + "391": 103.44999999999973, + "392": 104.29999999999986, + "393": 110.09999999999988, + "394": 110.85000000000012, + "395": 111.90000000000012, + "396": 111.30000000000011, + "397": 109.89999999999996, + "398": 112.50000000000004, + "399": 82.3999999999999, + "400": 107.6, + "401": 94.84999999999984, + "402": 111.75000000000001, + "403": 90.79999999999991, + "404": 82.85000000000002, + "405": 107.45000000000013, + "406": 107.10000000000011, + "407": 99.2999999999999, + "408": 97.80000000000008, + "409": 91.39999999999986, + "410": 79.74999999999999, + "411": 111.70000000000019, + "412": 110.70000000000012, + "413": 110.15000000000016, + "414": 105.94999999999978, + "415": 104.14999999999988, + "416": 108.20000000000002, + "417": 95.35000000000008, + "418": 100.89999999999976, + "419": 115.60000000000025, + "420": 102.80000000000018, + "421": 110.35000000000015, + "422": 108.6999999999999, + "423": 100.29999999999997, + "424": 113.00000000000021, + "425": 88.84999999999992, + "426": 110.09999999999988, + "427": 111.70000000000026, + "428": 107.50000000000021, + "429": 110.95000000000002, + "430": 96.00000000000001, + "431": 105.44999999999999, + "432": 108.94999999999979, + "433": 110.14999999999993, + "434": 107.64999999999998, + "435": 52.399999999999864, + "436": 100.30000000000015, + "437": 112.9000000000001, + "438": 100.89999999999986, + "439": 110.15000000000012, + "440": 113.20000000000017, + "441": 109.1000000000002, + "442": 109.35000000000021, + "443": 113.70000000000022, + "444": 97.94999999999995, + "445": 84.60000000000005, + "446": 69.34999999999987, + "447": 107.29999999999974, + "448": 112.04999999999998, + "449": 110.80000000000008, + "450": 79.95, + "451": 107.25000000000014, + "452": 106.5499999999999, + "453": 113.15000000000012, + "454": 112.05000000000018, + "455": 60.749999999999986, + "456": 112.45000000000006, + "457": 109.89999999999999, + "458": 103.89999999999988, + "459": 113.6500000000002, + "460": 109.60000000000001, + "461": 108.3000000000002, + "462": 112.85000000000022, + "463": 102.80000000000007, + "464": 112.15000000000006, + "465": 106.30000000000015, + "466": 111.0000000000001, + "467": 114.75000000000009, + "468": 100.24999999999996, + "469": 109.45000000000007, + "470": 47.54999999999989, + "471": 107.49999999999993, + "472": 109.04999999999993, + "473": 108.50000000000016, + "474": 111.24999999999999, + "475": 102.19999999999993, + "476": 92.0000000000001, + "477": 113.90000000000002, + "478": 81.79999999999998, + "479": 100.1499999999998, + "480": 110.9500000000002, + "481": 109.4999999999999, + "482": 108.75000000000004, + "483": 105.89999999999993, + "484": 114.55000000000022, + "485": 88.44999999999983, + "486": 111.85000000000011, + "487": 110.45000000000006, + "488": 100.70000000000013, + "489": 26.449999999999964, + "490": 90.34999999999998, + "491": 107.15000000000019, + "492": 99.04999999999998, + "493": 107.8000000000002, + "494": 114.65000000000026, + "495": 113.15000000000013, + "496": 111.45000000000012, + "497": 101.49999999999996, + "498": 112.25000000000001, + "499": 116.85000000000028, + "500": 100.55000000000007, + "501": 108.05000000000024, + "502": 100.24999999999987, + "503": 103.80000000000018, + "504": 107.85000000000001, + "505": 100.70000000000016, + "506": 107.24999999999993, + "507": 105.55000000000005, + "508": 110.19999999999987, + "509": 105.60000000000001, + "510": 112.50000000000017, + "511": 113.70000000000012, + "512": 99.70000000000002, + "513": 100.5000000000001, + "514": 108.54999999999986, + "515": 105.5500000000002, + "516": 113.95000000000023, + "517": 100.64999999999993, + "518": 99.74999999999991, + "519": 91.99999999999977, + "520": 98.50000000000006, + "521": 113.20000000000007, + "522": 106.05000000000014, + "523": 109.89999999999989, + "524": 113.20000000000013, + "525": 109.89999999999988, + "526": 110.35000000000007, + "527": 115.20000000000014, + "528": 101.65000000000016, + "529": 114.85000000000025, + "530": 115.80000000000003, + "531": 93.85000000000007, + "532": 102.55000000000011, + "533": 98.94999999999996, + "534": 94.19999999999985, + "535": 112.10000000000005, + "536": 105.89999999999988, + "537": 91.05000000000003, + "538": 101.90000000000005, + "539": 105.60000000000021, + "540": 114.15000000000022, + "541": 103.45000000000014, + "542": 61.199999999999775, + "543": 109.05000000000003, + "544": 83.65, + "545": 99.3500000000001, + "546": 114.30000000000022, + "547": 108.34999999999988, + "548": 74.00000000000004, + "549": 109.80000000000014, + "550": 66.79999999999991, + "551": 81.2499999999999, + "552": 103.65000000000009, + "553": 108.55000000000017, + "554": 111.80000000000022, + "555": 101.69999999999997, + "556": 100.54999999999974, + "557": 75.29999999999995, + "558": 108.75000000000009, + "559": 101.05000000000011, + "560": 86.35, + "561": 104.90000000000009, + "562": 105.60000000000002, + "563": 110.04999999999993, + "564": 108.39999999999999, + "565": 107.34999999999995, + "566": 112.85000000000011, + "567": 110.05000000000011, + "568": 98.2, + "569": 111.65000000000008, + "570": 117.7500000000003, + "571": 99.70000000000003, + "572": 107.20000000000013, + "573": 113.10000000000015, + "574": 111.05000000000018, + "575": 111.80000000000018, + "576": 107.70000000000014, + "577": 103.80000000000007, + "578": 113.99999999999991, + "579": 107.75000000000004, + "580": 106.45000000000007, + "581": 100.54999999999993, + "582": 112.85000000000024, + "583": 57.24999999999994, + "584": 116.2000000000002, + "585": 101.60000000000008, + "586": 108.94999999999997, + "587": 87.55000000000015, + "588": 101.60000000000015, + "589": 63.9499999999999, + "590": 103.40000000000018, + "591": 103.54999999999981, + "592": 87.20000000000005, + "593": 107.6500000000002, + "594": 107.70000000000016, + "595": 89.79999999999993, + "596": 103.15000000000023, + "597": 113.00000000000023, + "598": 54.54999999999992, + "599": 112.00000000000003, + "600": 107.09999999999994, + "601": 110.55000000000005, + "602": 88.15000000000006, + "603": 111.05000000000014, + "604": 101.00000000000014, + "605": 107.95000000000012, + "606": 88.75, + "607": 110.4000000000001, + "608": 103.8500000000001, + "609": 114.85000000000026, + "610": 98.1500000000001, + "611": 111.95000000000003, + "612": 82.79999999999995, + "613": 113.05000000000022, + "614": 98.04999999999994, + "615": 106.75000000000023, + "616": 107.04999999999988, + "617": 101.5499999999999, + "618": 104.79999999999998, + "619": 108.25000000000016, + "620": 112.0000000000001, + "621": 107.04999999999993, + "622": 97.50000000000004, + "623": 102.70000000000016, + "624": 97.75000000000001, + "625": 109.55000000000008, + "626": 88.05000000000021, + "627": 111.89999999999998, + "628": 111.10000000000011, + "629": 111.84999999999995, + "630": 108.9500000000002, + "631": 105.15, + "632": 100.95000000000009, + "633": 95.15000000000009, + "634": 110.04999999999998, + "635": 110.40000000000019, + "636": 84.2, + "637": 112.24999999999994, + "638": 90.54999999999986, + "639": 106.00000000000017, + "640": 108.6500000000002, + "641": 102.00000000000011, + "642": 23.099999999999994, + "643": 99.84999999999977, + "644": 97.25, + "645": 110.30000000000004, + "646": 63.39999999999992, + "647": 113.50000000000017, + "648": 99.60000000000002, + "649": 100.40000000000005, + "650": 109.95000000000009, + "651": 93.80000000000011, + "652": 40.85000000000004, + "653": 103.70000000000005, + "654": 114.85000000000016, + "655": 104.30000000000014, + "656": 98.80000000000014, + "657": -71.14999999999998, + "658": 106.55000000000022, + "659": 105.09999999999998, + "660": 80.05000000000025, + "661": 112.35000000000005, + "662": 110.59999999999992, + "663": 108.60000000000008, + "664": 89.25000000000007, + "665": 113.95000000000019, + "666": 109.9500000000001, + "667": 96.75000000000013, + "668": 109.89999999999996, + "669": 107.15000000000018, + "670": 94.04999999999993, + "671": 106.74999999999987, + "672": 102.20000000000013, + "673": 104.80000000000018, + "674": 95.8, + "675": 95.15000000000008, + "676": 109.14999999999998, + "677": 100.89999999999998, + "678": 106.10000000000018, + "679": 109.6500000000002, + "680": 110.35000000000008, + "681": 100.44999999999995, + "682": 95.24999999999999, + "683": 109.45, + "684": 97.25000000000004, + "685": 109.54999999999998, + "686": 96.60000000000004, + "687": 111.80000000000015, + "688": 103.75000000000006, + "689": 110.90000000000009, + "690": 108.3999999999998, + "691": 108.25000000000004, + "692": 112.15000000000016, + "693": 109.64999999999986, + "694": 113.60000000000014, + "695": 114.95000000000016, + "696": 95.75, + "697": 107.65000000000018, + "698": 112.30000000000025, + "699": 117.95000000000027, + "700": 112.1000000000001, + "701": 114.0000000000002, + "702": 100.1499999999999, + "703": 106.85000000000015, + "704": 108.29999999999994, + "705": 108.15000000000009, + "706": 107.60000000000014, + "707": 101.80000000000008, + "708": 103.49999999999974, + "709": 97.05000000000003, + "710": 115.35000000000025, + "711": 107.35000000000015, + "712": 91.89999999999995, + "713": 108.09999999999991, + "714": 105.10000000000007, + "715": 94.94999999999996, + "716": 103.6000000000002, + "717": 112.85000000000007, + "718": 97.25000000000009, + "719": 100.05000000000007, + "720": 108.95000000000017, + "721": 110.7499999999999, + "722": 113.55000000000021, + "723": 109.2500000000001, + "724": 103.00000000000018, + "725": 111.05000000000022, + "726": 109.20000000000009, + "727": 108.85000000000001, + "728": 107.25000000000013, + "729": 106.39999999999996, + "730": 104.55000000000004, + "731": 70.09999999999994, + "732": 115.45000000000026, + "733": 94.9000000000001, + "734": 113.65000000000015, + "735": 107.75000000000004, + "736": 109.04999999999997, + "737": 92.45000000000006, + "738": 107.40000000000018, + "739": 108.10000000000012, + "740": 105.5999999999998, + "741": 109.25, + "742": 78.50000000000001, + "743": 112.90000000000023, + "744": 113.50000000000023, + "745": 93.89999999999988, + "746": 108.45000000000017, + "747": 83.70000000000002, + "748": 113.0000000000001, + "749": 111.3500000000001, + "750": 108.94999999999993, + "751": 109.25000000000028, + "752": 106.79999999999998, + "753": 112.75000000000011, + "754": 109.35000000000011, + "755": 110.60000000000011, + "756": 108.65000000000019, + "757": 112.35000000000014, + "758": 101.85000000000015, + "759": 116.35000000000026, + "760": 114.05000000000018, + "761": 110.25000000000018, + "762": 108.85, + "763": 122.00000000000028, + "764": 113.30000000000001, + "765": 104.6500000000001, + "766": 101.0999999999999, + "767": 102.05000000000005, + "768": 99.40000000000015, + "769": 109.85000000000016, + "770": 112.45000000000022, + "771": 104.75000000000013, + "772": 92.00000000000006, + "773": 112.40000000000015, + "774": 75.45000000000026, + "775": 68.2499999999999, + "776": 87.8000000000002, + "777": 108.79999999999981, + "778": 102.25000000000016, + "779": 81.04999999999995, + "780": 101.10000000000012, + "781": 73.85000000000004, + "782": 108.94999999999993, + "783": 77.54999999999993, + "784": 86.5999999999998, + "785": 98.2500000000001, + "786": 49.949999999999875, + "787": 116.00000000000017, + "788": 45.09999999999978, + "789": 82.15000000000025, + "790": 45.399999999999835, + "791": 107.80000000000025, + "792": 70.65000000000012, + "793": 45.64999999999995, + "794": 108.25000000000021, + "795": 48.099999999999845, + "796": 59.14999999999985, + "797": 89.00000000000016, + "798": 73.9, + "799": 52.79999999999985, + "800": 109.65000000000018, + "801": 66.89999999999995, + "802": -10.949999999999992, + "803": 97.30000000000007, + "804": 100.85000000000018, + "805": 61.599999999999795, + "806": 113.60000000000008, + "807": 27.549999999999955, + "808": 69.44999999999992, + "809": 105.35000000000001, + "810": 109.70000000000005, + "811": 99.75000000000011, + "812": 105.0000000000002, + "813": 66.50000000000023, + "814": 101.29999999999994, + "815": 121.65000000000009, + "816": 109.85000000000004, + "817": 54.69999999999976, + "818": 46.34999999999989, + "819": 82.65000000000015, + "820": 84.85000000000025, + "821": 111.75000000000021, + "822": 111.69999999999996, + "823": 110.60000000000026, + "824": 107.65, + "825": 105.0500000000002, + "826": 88.69999999999999, + "827": 112.75000000000006, + "828": 110.65000000000016, + "829": 38.74999999999978, + "830": 113.45000000000014, + "831": 102.95000000000003, + "832": 75.14999999999999, + "833": 103.05000000000008, + "834": 50.549999999999926, + "835": 103.45000000000026, + "836": 113.60000000000002, + "837": 106.40000000000005, + "838": 42.0499999999999, + "839": 117.40000000000019, + "840": 110.25000000000016, + "841": 99.00000000000003, + "842": 89.49999999999997, + "843": 108.00000000000006, + "844": 107.9000000000001, + "845": 107.59999999999998, + "846": 75.40000000000003, + "847": 103.20000000000023, + "848": 85.69999999999992, + "849": 117.80000000000008, + "850": 70.89999999999985, + "851": 113.10000000000011, + "852": 98.80000000000003, + "853": 103.10000000000018, + "854": 111.5000000000001, + "855": 90.35, + "856": 117.99999999999999, + "857": 112.24999999999999, + "858": 101.24999999999997, + "859": 91.4, + "860": 85.84999999999991, + "861": 106.40000000000003, + "862": 89.19999999999999, + "863": 115.50000000000024, + "864": 95.2500000000001, + "865": 110.65000000000006, + "866": 110.15000000000015, + "867": 103.95, + "868": 101.00000000000007, + "869": 109.75000000000014, + "870": 98.9, + "871": 106.40000000000012, + "872": 112.25000000000001, + "873": 108.30000000000004, + "874": 75.74999999999991, + "875": 113.75000000000028, + "876": 109.24999999999996, + "877": 115.90000000000005, + "878": -37.09999999999996, + "879": 117.05000000000024, + "880": 113.95000000000014, + "881": 113.19999999999999, + "882": 108.6500000000001, + "883": 116.35000000000007, + "884": 109.5, + "885": 90.85000000000007, + "886": 121.20000000000009, + "887": 110.60000000000021, + "888": 111.10000000000007, + "889": 68.54999999999986, + "890": 109.70000000000006, + "891": 118.10000000000001, + "892": 113.60000000000014, + "893": 112.95000000000017, + "894": 116.80000000000001, + "895": 111.64999999999998, + "896": 108.70000000000009, + "897": 116.20000000000003, + "898": 83.35000000000005, + "899": 104.55, + "900": 112.7000000000001, + "901": 106.24999999999997, + "902": 115.35000000000007, + "903": 9.649999999999993, + "904": 109.90000000000008, + "905": 115.60000000000016, + "906": 94.25000000000004, + "907": 96.25000000000013, + "908": 110.85000000000007, + "909": 116.90000000000013, + "910": 99.89999999999998, + "911": 109.55000000000017, + "912": 102.0500000000001, + "913": 99.69999999999993, + "914": 109.25000000000003, + "915": 114.40000000000003, + "916": 117.30000000000013, + "917": 109.2000000000001, + "918": 112.29999999999997, + "919": 78.0000000000001, + "920": 106.00000000000007, + "921": 107.14999999999996, + "922": 86.60000000000025, + "923": 106.49999999999999, + "924": 89.15000000000002, + "925": 109.3500000000001, + "926": 110.40000000000005, + "927": 106.45000000000006, + "928": 103.40000000000012, + "929": 101.95000000000006, + "930": 113.85000000000011, + "931": 108.7500000000001, + "932": 114.70000000000007, + "933": 121.44999999999999, + "934": 95.45000000000013, + "935": 107.35000000000007, + "936": 27.199999999999935, + "937": 105.3, + "938": 104.15000000000009, + "939": 102.30000000000017, + "940": 119.50000000000011, + "941": 113.50000000000013, + "942": 102.24999999999999, + "943": 115.45000000000032, + "944": 107.60000000000002, + "945": 105.65000000000002, + "946": 109.25000000000011, + "947": 105.80000000000011, + "948": 78.7, + "949": 113.30000000000017, + "950": 100.69999999999992, + "951": 100.30000000000015, + "952": 104.04999999999991, + "953": 100.95, + "954": 104.55000000000007, + "955": 108.35000000000007, + "956": 103.85, + "957": 94.09999999999984, + "958": 102.65000000000003, + "959": 94.15000000000008, + "960": 100.25000000000013, + "961": 114.0000000000001, + "962": 103.80000000000007, + "963": 102.85000000000007, + "964": 70.89999999999993, + "965": 97.70000000000002, + "966": 104.50000000000021, + "967": 105.35000000000015, + "968": 111.65000000000006, + "969": 110.20000000000005, + "970": 103.84999999999998, + "971": 104.60000000000002, + "972": 109.80000000000008, + "973": 109.29999999999994, + "974": 106.90000000000009, + "975": 115.15000000000006, + "976": 107.40000000000013, + "977": 101.60000000000008, + "978": 119.50000000000007, + "979": 109.20000000000002, + "980": 105.70000000000006, + "981": 112.15000000000002, + "982": 107.44999999999996, + "983": 120.95000000000005, + "984": 108.60000000000026, + "985": 60.44999999999998, + "986": 31.599999999999927, + "987": 88.95000000000019, + "988": 113.80000000000001, + "989": 75.25000000000004, + "990": 109.00000000000007, + "991": 107.25000000000006, + "992": 93.40000000000002, + "993": 117.5500000000002, + "994": 117.6000000000001, + "995": 117.9, + "996": 105.35000000000014, + "997": 120.05000000000003, + "998": 119.90000000000016, + "999": 99.50000000000009, + "1000": 98.70000000000006 + }, + "5": { + "1": -19.49999999999996, + "2": -15.049999999999978, + "3": -28.85000000000002, + "4": -76.64999999999992, + "5": -66.55000000000011, + "6": -18.79999999999997, + "7": -22.149999999999956, + "8": -60.350000000000115, + "9": -48.850000000000065, + "10": -40.20000000000005, + "11": -11.699999999999992, + "12": -38.40000000000004, + "13": -17.099999999999955, + "14": -55.70000000000008, + "15": -50.04999999999995, + "16": -29.699999999999967, + "17": -28.54999999999999, + "18": -28.799999999999944, + "19": -23.49999999999997, + "20": -34.35000000000003, + "21": -39.400000000000134, + "22": -21.09999999999996, + "23": -22.64999999999995, + "24": -21.549999999999958, + "25": -9.799999999999994, + "26": 10.350000000000051, + "27": -39.20000000000004, + "28": -21.499999999999957, + "29": -52.10000000000008, + "30": -19.149999999999967, + "31": -16.199999999999978, + "32": -17.59999999999997, + "33": -13.699999999999987, + "34": -1.3500000000000056, + "35": -54.15000000000016, + "36": -19.849999999999966, + "37": -22.199999999999953, + "38": -15.44999999999998, + "39": -17.44999999999997, + "40": -15.499999999999975, + "41": -21.89999999999996, + "42": -100.2, + "43": -17.099999999999973, + "44": -87.35, + "45": -2.849999999999997, + "46": -42.45000000000005, + "47": -3.6999999999999966, + "48": -6.700000000000007, + "49": -39.900000000000034, + "50": -17.899999999999974, + "51": -17.14999999999997, + "52": -11.649999999999988, + "53": -56.45000000000008, + "54": -20.84999999999996, + "55": -15.24999999999997, + "56": -8.450000000000015, + "57": -26.650000000000023, + "58": -19.099999999999966, + "59": -22.549999999999986, + "60": -11.099999999999994, + "61": -19.249999999999964, + "62": -9.149999999999988, + "63": -18.849999999999966, + "64": -15.299999999999981, + "65": -21.249999999999957, + "66": -11.449999999999994, + "67": -19.599999999999962, + "68": -7.399999999999988, + "69": -22.149999999999956, + "70": 9.300000000000047, + "71": -9.849999999999994, + "72": -19.74999999999996, + "73": -56.15, + "74": -18.89999999999999, + "75": -4.399999999999982, + "76": -37.700000000000045, + "77": -5.599999999999986, + "78": -13.299999999999988, + "79": -93.80000000000001, + "80": -91.05, + "81": 16.55000000000003, + "82": 22.249999999999982, + "83": 8.400000000000034, + "84": 0.6499999999999975, + "85": 7.050000000000032, + "86": -0.9499999999999684, + "87": -15.099999999999975, + "88": -85.10000000000001, + "89": -83.1, + "90": -6.849999999999995, + "91": -57.35000000000001, + "92": -49.05000000000013, + "93": 15.30000000000004, + "94": -21.649999999999956, + "95": -8.45, + "96": -87.89999999999995, + "97": -15.89999999999998, + "98": 11.750000000000046, + "99": -4.799999999999984, + "100": -6.099999999999992, + "101": -71.7, + "102": -14.949999999999982, + "103": -26.650000000000006, + "104": -21.600000000000037, + "105": -18.14999999999997, + "106": -3.399999999999979, + "107": -22.99999999999998, + "108": -11.299999999999992, + "109": -84.39999999999999, + "110": -21.599999999999955, + "111": -12.449999999999985, + "112": -8.499999999999995, + "113": -38.00000000000011, + "114": -70.44999999999997, + "115": -14.349999999999993, + "116": 2.2500000000000133, + "117": 38.64999999999998, + "118": 34.049999999999876, + "119": -58.99999999999995, + "120": -8.699999999999996, + "121": 35.05000000000002, + "122": 13.000000000000064, + "123": -11.44999999999999, + "124": -68.3, + "125": -6.099999999999999, + "126": 21.700000000000003, + "127": -34.65000000000009, + "128": -19.949999999999964, + "129": 14.350000000000046, + "130": -28.649999999999995, + "131": -21.89999999999995, + "132": -13.449999999999985, + "133": 8.800000000000034, + "134": -6.94999999999998, + "135": -2.8499999999999712, + "136": -17.19999999999997, + "137": -4.2499999999999725, + "138": 57.39999999999983, + "139": -11.449999999999989, + "140": 0.9000000000000461, + "141": 54.04999999999982, + "142": -58.20000000000001, + "143": -0.4500000000000308, + "144": 18.500000000000018, + "145": 1.8000000000000196, + "146": -76.94999999999999, + "147": 8.550000000000004, + "148": -79.64999999999988, + "149": 14.050000000000047, + "150": -26.399999999999984, + "151": -24.95000000000002, + "152": 31.699999999999996, + "153": -59.949999999999996, + "154": -16.50000000000001, + "155": -49.8, + "156": -75.40000000000003, + "157": -13.749999999999984, + "158": -66.49999999999996, + "159": -55.64999999999997, + "160": -61.599999999999916, + "161": 5.850000000000056, + "162": 12.55000000000007, + "163": -66.39999999999993, + "164": -40.19999999999999, + "165": -92.09999999999991, + "166": 10.95000000000002, + "167": 21.099999999999987, + "168": 26.59999999999986, + "169": 3.6500000000000146, + "170": 6.900000000000036, + "171": -18.54999999999997, + "172": 39.19999999999985, + "173": 48.59999999999985, + "174": 31.499999999999748, + "175": -11.749999999999966, + "176": -75.95000000000003, + "177": -19.550000000000036, + "178": -69.95000000000003, + "179": 22.65, + "180": 44.74999999999977, + "181": -57.80000000000005, + "182": -71.50000000000003, + "183": 9.40000000000001, + "184": -31.900000000000002, + "185": -73.95000000000002, + "186": 47.50000000000004, + "187": -7.700000000000012, + "188": 20.250000000000032, + "189": 50.14999999999985, + "190": -12.850000000000039, + "191": 9.150000000000018, + "192": 53.34999999999986, + "193": -15.400000000000007, + "194": 36.399999999999835, + "195": -35.20000000000003, + "196": 30.34999999999993, + "197": 31.249999999999957, + "198": -22.350000000000023, + "199": 22.15000000000009, + "200": -60.14999999999998, + "201": 20.349999999999984, + "202": -39.85, + "203": 1.6000000000000045, + "204": -29.99999999999997, + "205": 38.39999999999981, + "206": -55.35000000000001, + "207": 48.74999999999989, + "208": 6.9499999999999975, + "209": -67.44999999999999, + "210": -76.40000000000002, + "211": -69.75000000000001, + "212": -1.549999999999995, + "213": -21.249999999999957, + "214": 37.79999999999992, + "215": -54.60000000000001, + "216": -73.54999999999988, + "217": 53.44999999999983, + "218": -74.8, + "219": -16.400000000000002, + "220": 48.3999999999999, + "221": 13.000000000000053, + "222": 14.60000000000003, + "223": -96.94999999999999, + "224": -8.499999999999986, + "225": 51.39999999999996, + "226": 81.29999999999993, + "227": 21.44999999999992, + "228": 29.399999999999828, + "229": 10.550000000000061, + "230": -7.400000000000019, + "231": 35.549999999999855, + "232": 56.69999999999993, + "233": -15.649999999999977, + "234": 69.99999999999983, + "235": 38.500000000000014, + "236": 47.59999999999978, + "237": -33.70000000000002, + "238": -39.150000000000055, + "239": 93.05000000000008, + "240": -27.05000000000003, + "241": 36.399999999999835, + "242": 28.749999999999968, + "243": 83.84999999999998, + "244": -27.400000000000013, + "245": 93.34999999999982, + "246": -7.400000000000004, + "247": 35.95000000000002, + "248": -31.20000000000001, + "249": -32.59999999999999, + "250": 67.35000000000004, + "251": -10.749999999999979, + "252": -20.29999999999996, + "253": 93.89999999999976, + "254": 9.800000000000018, + "255": 21.999999999999982, + "256": 33.25, + "257": 82.50000000000023, + "258": 68.4, + "259": 42.699999999999896, + "260": 81.94999999999999, + "261": 54.49999999999989, + "262": 73.89999999999982, + "263": 27.89999999999999, + "264": 55.499999999999886, + "265": -26.750000000000007, + "266": 43.99999999999979, + "267": 39.49999999999998, + "268": 73.04999999999991, + "269": 98.79999999999981, + "270": 65.7999999999999, + "271": 91.49999999999976, + "272": 50.29999999999991, + "273": 52.14999999999978, + "274": 87.85000000000002, + "275": 53.55000000000002, + "276": -9.60000000000003, + "277": -61.10000000000003, + "278": -38.39999999999999, + "279": 3.2499999999999645, + "280": -70.74999999999999, + "281": 24.24999999999995, + "282": 99.79999999999981, + "283": 91.65000000000003, + "284": 67.99999999999994, + "285": 103.39999999999978, + "286": 19.900000000000055, + "287": 64.29999999999993, + "288": 107.4500000000001, + "289": 55.29999999999992, + "290": 41.799999999999805, + "291": 44.499999999999964, + "292": -26.400000000000023, + "293": 82.95000000000005, + "294": 41.45000000000004, + "295": 60.24999999999991, + "296": 81.00000000000004, + "297": 53.49999999999988, + "298": 102.54999999999994, + "299": 75.25000000000009, + "300": 95.54999999999983, + "301": 43.599999999999916, + "302": 88.45000000000005, + "303": 88.30000000000011, + "304": 102.40000000000002, + "305": 112.1000000000002, + "306": 71.7999999999998, + "307": 94.10000000000007, + "308": 66.29999999999993, + "309": 102.60000000000015, + "310": -63.1999999999999, + "311": 61.49999999999986, + "312": 94.45000000000012, + "313": 98.50000000000017, + "314": 52.09999999999988, + "315": 22.59999999999999, + "316": 114.2000000000001, + "317": 77.54999999999998, + "318": 96.90000000000006, + "319": 87.05000000000008, + "320": 106.84999999999972, + "321": 95.64999999999993, + "322": 72.99999999999994, + "323": 84.99999999999974, + "324": 71.30000000000005, + "325": 13.55000000000005, + "326": 87.65000000000009, + "327": 94.15000000000013, + "328": 71.14999999999989, + "329": 78.70000000000022, + "330": 100.60000000000001, + "331": 94.05000000000015, + "332": 71.45000000000026, + "333": 92.20000000000009, + "334": 53.149999999999814, + "335": 98.75000000000018, + "336": 102.70000000000014, + "337": 103.19999999999996, + "338": 56.349999999999824, + "339": 110.15000000000006, + "340": 84.59999999999997, + "341": 113.05000000000014, + "342": 113.80000000000004, + "343": 99.90000000000008, + "344": 56.84999999999995, + "345": 103.50000000000023, + "346": 110.25000000000013, + "347": 104.49999999999999, + "348": 110.00000000000009, + "349": 67.4999999999999, + "350": -13.949999999999983, + "351": 112.05000000000005, + "352": 90.3000000000001, + "353": 103.8000000000001, + "354": 69.80000000000003, + "355": 116.90000000000018, + "356": 106.40000000000009, + "357": 114.55, + "358": 106.3500000000002, + "359": 114.3000000000001, + "360": 82.04999999999998, + "361": 101.0000000000002, + "362": 113.85000000000002, + "363": 89.14999999999999, + "364": 105.65000000000016, + "365": -3.4000000000000026, + "366": 111.30000000000008, + "367": 115.55000000000011, + "368": 105.09999999999995, + "369": 26.60000000000002, + "370": 106.79999999999993, + "371": 109.25, + "372": 102.0, + "373": 111.70000000000014, + "374": 60.09999999999991, + "375": 96.4999999999998, + "376": 80.45000000000006, + "377": 93.95000000000009, + "378": 105.25000000000009, + "379": 105.70000000000007, + "380": 111.7500000000001, + "381": 108.30000000000011, + "382": 101.20000000000009, + "383": 117.40000000000008, + "384": 111.6, + "385": 22.09999999999992, + "386": 110.19999999999992, + "387": 105.65000000000012, + "388": 102.59999999999988, + "389": 113.10000000000004, + "390": 108.94999999999995, + "391": 104.00000000000003, + "392": 96.65000000000006, + "393": 107.9000000000001, + "394": 95.80000000000007, + "395": 112.40000000000002, + "396": 115.20000000000012, + "397": 113.29999999999993, + "398": 121.60000000000004, + "399": 107.00000000000004, + "400": 120.25000000000011, + "401": 112.50000000000009, + "402": 24.10000000000005, + "403": 115.85, + "404": 114.79999999999997, + "405": 95.64999999999986, + "406": 112.30000000000013, + "407": 110.00000000000001, + "408": 95.75, + "409": 80.34999999999998, + "410": 106.00000000000003, + "411": 105.94999999999999, + "412": 118.25000000000003, + "413": 108.4000000000001, + "414": 111.20000000000006, + "415": 85.75, + "416": 118.70000000000009, + "417": 113.50000000000003, + "418": 60.449999999999946, + "419": 113.0500000000001, + "420": 116.30000000000008, + "421": 115.6500000000001, + "422": 109.85000000000014, + "423": 106.20000000000006, + "424": 113.39999999999999, + "425": 110.05000000000014, + "426": 116.0500000000001, + "427": 105.54999999999988, + "428": 66.64999999999996, + "429": 112.95000000000013, + "430": 112.45000000000012, + "431": 108.85000000000004, + "432": 109.45000000000007, + "433": 103.80000000000005, + "434": 98.15000000000009, + "435": 114.19999999999996, + "436": 107.15000000000015, + "437": 109.70000000000009, + "438": 109.20000000000007, + "439": 80.25000000000004, + "440": 117.00000000000001, + "441": 106.5500000000002, + "442": 106.19999999999995, + "443": 113.40000000000009, + "444": 105.15000000000002, + "445": 72.94999999999993, + "446": 113.15000000000009, + "447": 106.70000000000019, + "448": 101.45, + "449": 96.2500000000001, + "450": 118.35000000000011, + "451": 107.9000000000001, + "452": 107.34999999999995, + "453": 109.95000000000009, + "454": 123.40000000000006, + "455": 97.00000000000007, + "456": 96.55000000000004, + "457": 119.05000000000004, + "458": 108.00000000000009, + "459": 106.35000000000018, + "460": 114.65000000000012, + "461": 116.30000000000005, + "462": 120.35000000000022, + "463": 106.85000000000008, + "464": 111.6000000000001, + "465": 111.94999999999997, + "466": 110.60000000000014, + "467": 109.20000000000007, + "468": 104.15000000000005, + "469": 110.05000000000003, + "470": 117.29999999999998, + "471": 98.20000000000005, + "472": 112.80000000000022, + "473": 107.50000000000013, + "474": 90.05000000000007, + "475": 105.50000000000018, + "476": 106.65000000000009, + "477": 114.65000000000013, + "478": 115.8000000000001, + "479": 103.80000000000007, + "480": 100.35000000000007, + "481": 112.89999999999999, + "482": 105.70000000000005, + "483": 96.1500000000002, + "484": 77.05000000000001, + "485": 109.65000000000012, + "486": 105.65000000000008, + "487": 116.89999999999996, + "488": 116.04999999999997, + "489": 102.6999999999999, + "490": 117.1500000000001, + "491": 8.200000000000056, + "492": 114.70000000000005, + "493": -66.89999999999992, + "494": 113.40000000000013, + "495": 105.79999999999994, + "496": 115.0500000000002, + "497": 106.35000000000005, + "498": 103.05000000000013, + "499": 107.10000000000016, + "500": 112.40000000000002, + "501": 111.15, + "502": 115.50000000000001, + "503": 118.90000000000015, + "504": -69.24999999999989, + "505": 111.45000000000006, + "506": 106.15000000000005, + "507": 105.45000000000014, + "508": 107.45000000000003, + "509": 116.20000000000009, + "510": 104.2500000000001, + "511": 108.70000000000003, + "512": 56.39999999999984, + "513": 89.50000000000017, + "514": 112.10000000000001, + "515": 112.45000000000009, + "516": 115.54999999999991, + "517": 116.55000000000007, + "518": 112.50000000000026, + "519": 88.6000000000001, + "520": 114.30000000000007, + "521": 113.69999999999999, + "522": 112.15000000000005, + "523": 110.0999999999999, + "524": 100.09999999999994, + "525": 106.70000000000009, + "526": 111.50000000000001, + "527": 112.05000000000008, + "528": 112.95000000000003, + "529": 109.19999999999999, + "530": 110.20000000000002, + "531": 115.44999999999995, + "532": 113.60000000000016, + "533": 37.39999999999986, + "534": 119.25000000000011, + "535": 110.99999999999994, + "536": 119.75000000000014, + "537": 112.40000000000015, + "538": 120.00000000000013, + "539": 103.85000000000008, + "540": 112.35000000000007, + "541": 115.60000000000015, + "542": 118.69999999999999, + "543": 110.44999999999997, + "544": 116.8500000000001, + "545": 107.75000000000016, + "546": 112.50000000000017, + "547": 114.45000000000017, + "548": 108.9000000000002, + "549": 110.30000000000018, + "550": 107.60000000000005, + "551": 114.50000000000016, + "552": 114.25000000000009, + "553": 113.90000000000006, + "554": 113.85000000000007, + "555": 114.75000000000018, + "556": 109.15000000000006, + "557": 105.14999999999999, + "558": 119.70000000000007, + "559": 115.99999999999997, + "560": 102.70000000000003, + "561": 115.35000000000008, + "562": 109.70000000000013, + "563": 110.9, + "564": 112.6000000000002, + "565": 117.00000000000011, + "566": 111.7000000000001, + "567": 116.95000000000009, + "568": 104.59999999999982, + "569": 119.95000000000007, + "570": 109.7500000000001, + "571": 119.84999999999998, + "572": 108.55, + "573": 95.05000000000001, + "574": 119.80000000000018, + "575": 115.4000000000002, + "576": 104.20000000000005, + "577": 110.60000000000012, + "578": 111.80000000000014, + "579": 117.0000000000001, + "580": 111.75000000000009, + "581": 103.55000000000014, + "582": 115.70000000000005, + "583": 112.30000000000022, + "584": 47.04999999999993, + "585": 114.10000000000011, + "586": 109.90000000000008, + "587": 107.05000000000015, + "588": 112.80000000000013, + "589": 104.85000000000004, + "590": 100.14999999999993, + "591": 102.64999999999999, + "592": 91.59999999999995, + "593": 108.30000000000008, + "594": 110.55000000000004, + "595": 87.1000000000002, + "596": 109.3000000000001, + "597": 100.95000000000012, + "598": 110.85000000000001, + "599": 110.70000000000009, + "600": 117.30000000000013, + "601": 113.1500000000001, + "602": 117.40000000000012, + "603": 109.39999999999998, + "604": 118.05000000000022, + "605": 109.95000000000003, + "606": 108.85000000000011, + "607": 115.05000000000004, + "608": 116.45000000000016, + "609": 106.50000000000013, + "610": 59.29999999999985, + "611": 112.25000000000004, + "612": 108.05000000000005, + "613": 116.10000000000008, + "614": 106.10000000000005, + "615": 105.20000000000006, + "616": 107.89999999999998, + "617": 116.80000000000001, + "618": 110.90000000000016, + "619": 118.65000000000009, + "620": 109.3500000000001, + "621": 111.05, + "622": 110.85000000000011, + "623": 109.04999999999991, + "624": 109.95000000000009, + "625": 105.15000000000006, + "626": 109.25000000000011, + "627": 109.80000000000008, + "628": 112.15000000000023, + "629": 112.15000000000018, + "630": 106.99999999999991, + "631": 108.70000000000009, + "632": 112.75, + "633": 107.75000000000007, + "634": 115.30000000000007, + "635": 118.90000000000019, + "636": 114.00000000000009, + "637": 105.00000000000003, + "638": 115.05000000000014, + "639": 111.05000000000003, + "640": 105.75000000000011, + "641": 121.00000000000016, + "642": 111.9000000000001, + "643": 123.00000000000003, + "644": 109.15000000000002, + "645": 76.15000000000003, + "646": 108.99999999999999, + "647": 116.00000000000003, + "648": 114.80000000000004, + "649": 105.69999999999993, + "650": 117.65000000000018, + "651": 102.90000000000012, + "652": 109.80000000000008, + "653": 107.19999999999985, + "654": 110.50000000000009, + "655": 115.05000000000003, + "656": 115.30000000000015, + "657": 117.30000000000011, + "658": 112.70000000000017, + "659": 106.35000000000014, + "660": 110.8, + "661": 115.55000000000003, + "662": 108.70000000000007, + "663": 106.29999999999997, + "664": 107.60000000000004, + "665": 117.10000000000012, + "666": 116.20000000000007, + "667": 112.30000000000021, + "668": 112.30000000000004, + "669": 117.85000000000001, + "670": 103.75000000000011, + "671": 111.0500000000001, + "672": 108.30000000000008, + "673": 109.85000000000016, + "674": 112.0000000000001, + "675": 116.35000000000022, + "676": 103.95000000000003, + "677": 103.30000000000003, + "678": 107.20000000000005, + "679": 116.70000000000012, + "680": 102.80000000000013, + "681": 101.84999999999995, + "682": 101.54999999999997, + "683": 97.60000000000002, + "684": 107.25000000000007, + "685": 118.70000000000003, + "686": 119.25000000000007, + "687": 107.59999999999994, + "688": 115.60000000000011, + "689": 114.15000000000006, + "690": 116.2000000000001, + "691": 109.35000000000008, + "692": 106.69999999999983, + "693": 118.95000000000016, + "694": 108.80000000000005, + "695": 117.2500000000001, + "696": 117.85000000000004, + "697": 116.05000000000007, + "698": 105.95000000000002, + "699": 104.0, + "700": 114.60000000000014, + "701": 107.19999999999987, + "702": 113.90000000000008, + "703": 108.44999999999997, + "704": 118.2000000000001, + "705": 117.15000000000009, + "706": 88.59999999999992, + "707": 113.7500000000001, + "708": 109.85000000000004, + "709": 112.40000000000006, + "710": 107.15000000000002, + "711": 115.8000000000002, + "712": 119.05000000000017, + "713": 113.4000000000001, + "714": 116.15000000000013, + "715": 110.50000000000007, + "716": 108.50000000000004, + "717": 108.90000000000012, + "718": 115.50000000000001, + "719": 121.30000000000022, + "720": 109.50000000000011, + "721": 106.15000000000006, + "722": 116.4000000000001, + "723": 114.65000000000005, + "724": 112.50000000000017, + "725": 108.20000000000016, + "726": 117.55000000000004, + "727": 112.05000000000014, + "728": 103.85000000000008, + "729": 101.69999999999999, + "730": 112.45, + "731": 107.45000000000009, + "732": 113.15000000000009, + "733": 107.3500000000002, + "734": 112.40000000000005, + "735": 114.70000000000016, + "736": 101.00000000000001, + "737": 114.95000000000005, + "738": 113.35000000000004, + "739": 106.05000000000004, + "740": 108.10000000000022, + "741": 100.29999999999998, + "742": 113.45000000000014, + "743": 107.75, + "744": 113.35000000000014, + "745": 115.80000000000014, + "746": 117.0500000000001, + "747": 112.10000000000018, + "748": 114.60000000000015, + "749": 101.55000000000005, + "750": 108.9000000000001, + "751": 111.15000000000005, + "752": 110.80000000000001, + "753": 102.6499999999999, + "754": 118.75000000000016, + "755": 102.35000000000005, + "756": 101.75000000000014, + "757": 109.70000000000016, + "758": 94.15000000000003, + "759": 108.69999999999993, + "760": 119.20000000000005, + "761": 97.60000000000014, + "762": 108.30000000000014, + "763": 114.20000000000005, + "764": 111.45000000000017, + "765": 109.00000000000004, + "766": 114.6000000000001, + "767": 102.60000000000014, + "768": 108.60000000000012, + "769": 106.10000000000014, + "770": 114.10000000000002, + "771": 107.6000000000001, + "772": 114.59999999999998, + "773": 111.80000000000003, + "774": 110.55000000000003, + "775": 105.60000000000002, + "776": 109.85000000000007, + "777": 111.24999999999997, + "778": 113.85000000000008, + "779": 106.8999999999999, + "780": 107.75000000000001, + "781": 108.05000000000014, + "782": 111.29999999999995, + "783": 111.90000000000008, + "784": 95.74999999999994, + "785": 109.2000000000001, + "786": 108.60000000000015, + "787": 104.80000000000005, + "788": 106.00000000000007, + "789": 107.84999999999992, + "790": 116.5, + "791": 105.6, + "792": 116.15000000000008, + "793": 107.85000000000011, + "794": 111.15000000000013, + "795": 113.1500000000001, + "796": 115.00000000000016, + "797": 106.49999999999997, + "798": 104.40000000000006, + "799": 110.90000000000009, + "800": 114.35000000000026, + "801": 115.5500000000002, + "802": 112.59999999999998, + "803": 114.45000000000002, + "804": 109.40000000000012, + "805": 109.35000000000005, + "806": 110.1, + "807": 102.6000000000002, + "808": 112.59999999999997, + "809": 106.90000000000005, + "810": 106.05000000000003, + "811": 115.35000000000004, + "812": 94.34999999999998, + "813": 116.04999999999995, + "814": 112.95000000000017, + "815": 106.00000000000001, + "816": 117.39999999999995, + "817": 119.8500000000001, + "818": 117.6500000000002, + "819": 98.2, + "820": 115.75000000000023, + "821": -33.549999999999976, + "822": 113.9500000000001, + "823": 112.60000000000004, + "824": 107.60000000000011, + "825": 103.74999999999999, + "826": 113.95000000000017, + "827": 116.00000000000017, + "828": 105.60000000000008, + "829": 109.64999999999995, + "830": 110.70000000000002, + "831": 111.35000000000005, + "832": 117.80000000000017, + "833": 99.9, + "834": 105.14999999999998, + "835": 110.55000000000004, + "836": 110.60000000000001, + "837": 116.2, + "838": 116.95000000000013, + "839": 115.30000000000004, + "840": 104.60000000000014, + "841": 107.75000000000009, + "842": 112.34999999999997, + "843": 106.2500000000001, + "844": 113.45000000000026, + "845": 108.59999999999998, + "846": 107.5, + "847": 119.65000000000012, + "848": 111.55000000000014, + "849": 108.25000000000007, + "850": 106.35000000000016, + "851": 99.55000000000015, + "852": 113.00000000000018, + "853": 113.40000000000006, + "854": 109.85000000000008, + "855": 117.40000000000002, + "856": 113.5, + "857": 101.39999999999993, + "858": 111.45000000000012, + "859": 77.99999999999986, + "860": 109.65000000000006, + "861": 113.15000000000019, + "862": 108.60000000000001, + "863": 109.15000000000016, + "864": 115.70000000000002, + "865": 108.60000000000004, + "866": 112.45000000000016, + "867": 114.90000000000008, + "868": 104.25000000000014, + "869": 104.85000000000011, + "870": 111.35, + "871": 112.9500000000001, + "872": 114.35000000000018, + "873": 103.90000000000012, + "874": 115.55000000000011, + "875": 111.20000000000016, + "876": 108.65000000000009, + "877": 119.45000000000013, + "878": 107.99999999999991, + "879": 108.65000000000015, + "880": 117.55000000000001, + "881": 108.60000000000024, + "882": 114.7500000000001, + "883": 104.2000000000001, + "884": 112.50000000000014, + "885": 109.74999999999993, + "886": 114.20000000000006, + "887": 114.45000000000024, + "888": 118.39999999999992, + "889": 107.1000000000001, + "890": 114.95000000000013, + "891": 105.40000000000002, + "892": 122.45, + "893": 118.30000000000013, + "894": 113.45000000000024, + "895": 113.85000000000011, + "896": 115.10000000000018, + "897": 115.05000000000014, + "898": 105.10000000000005, + "899": 96.3499999999999, + "900": 102.40000000000006, + "901": 113.20000000000014, + "902": 109.74999999999997, + "903": 110.65000000000006, + "904": 109.70000000000013, + "905": 119.19999999999999, + "906": 63.450000000000024, + "907": 115.90000000000006, + "908": 115.8000000000002, + "909": 109.15000000000009, + "910": 111.20000000000007, + "911": 121.30000000000021, + "912": 108.14999999999993, + "913": 108.19999999999995, + "914": 108.4500000000001, + "915": 111.29999999999995, + "916": 40.54999999999992, + "917": 114.0500000000001, + "918": 116.90000000000013, + "919": 103.94999999999986, + "920": 119.65000000000025, + "921": 111.85000000000011, + "922": 116.55000000000021, + "923": 98.4500000000001, + "924": 116.55, + "925": 115.55000000000008, + "926": 45.149999999999956, + "927": 77.70000000000017, + "928": 109.00000000000013, + "929": 81.95000000000012, + "930": 67.94999999999989, + "931": 63.54999999999981, + "932": 114.55000000000011, + "933": 86.10000000000014, + "934": 105.85000000000005, + "935": 111.1500000000003, + "936": 107.6000000000001, + "937": 112.4000000000001, + "938": 108.55000000000001, + "939": 120.00000000000004, + "940": 89.00000000000003, + "941": 89.54999999999994, + "942": 89.80000000000008, + "943": 82.35000000000004, + "944": 97.70000000000013, + "945": 84.64999999999985, + "946": 112.20000000000016, + "947": 121.50000000000003, + "948": 114.14999999999993, + "949": 5.8000000000000185, + "950": 117.10000000000002, + "951": 110.90000000000009, + "952": 101.95000000000016, + "953": 94.90000000000008, + "954": 112.85000000000012, + "955": 112.85000000000014, + "956": 113.35000000000001, + "957": 109.25000000000006, + "958": 108.34999999999997, + "959": 103.39999999999998, + "960": 110.70000000000019, + "961": 109.05000000000017, + "962": 110.65000000000009, + "963": 115.85000000000001, + "964": 110.15000000000002, + "965": 103.4500000000001, + "966": 83.95000000000017, + "967": 120.45000000000003, + "968": 109.05000000000005, + "969": 119.05000000000011, + "970": 98.60000000000005, + "971": 116.3500000000001, + "972": 95.70000000000006, + "973": 108.55000000000021, + "974": 118.65000000000012, + "975": 114.55000000000013, + "976": 108.4, + "977": 104.65000000000019, + "978": 111.55000000000001, + "979": 113.99999999999997, + "980": 82.50000000000011, + "981": 106.40000000000002, + "982": 39.69999999999989, + "983": 104.95000000000007, + "984": 112.49999999999994, + "985": 108.79999999999988, + "986": 113.40000000000018, + "987": 110.7500000000002, + "988": 118.85000000000001, + "989": 116.9500000000001, + "990": 114.75000000000003, + "991": 112.9000000000001, + "992": 106.60000000000008, + "993": 104.49999999999997, + "994": 117.05000000000014, + "995": 114.20000000000013, + "996": 113.60000000000016, + "997": 95.30000000000013, + "998": 106.89999999999982, + "999": 118.45000000000007, + "1000": 116.3000000000001 + } + }, + "config": { + "io_settings": { + "save_agent_actions": true, + "save_step_metadata": false, + "save_pcap_logs": false, + "save_sys_logs": false, + "sys_log_level": "WARNING" + }, + "game": { + "max_episode_length": 128, + "ports": [ + "HTTP", + "POSTGRES_SERVER" + ], + "protocols": [ + "ICMP", + "TCP", + "UDP" + ], + "thresholds": { + "nmne": { + "high": 10, + "medium": 5, + "low": 0 + } + } + }, + "agents": [ + { + "ref": "client_2_green_user", + "team": "GREEN", + "type": "ProbabilisticAgent", + "agent_settings": { + "action_probabilities": { + "0": 0.3, + "1": 0.6, + "2": 0.1 + } + }, + "observation_space": null, + "action_space": { + "action_list": [ + { + "type": "DONOTHING" + }, + { + "type": "NODE_APPLICATION_EXECUTE" + } + ], + "options": { + "nodes": [ + { + "node_name": "client_2", + "applications": [ + { + "application_name": "WebBrowser" + }, + { + "application_name": "DatabaseClient" + } + ] + } + ], + "max_folders_per_node": 1, + "max_files_per_folder": 1, + "max_services_per_node": 1, + "max_applications_per_node": 2 + }, + "action_map": { + "0": { + "action": "DONOTHING", + "options": {} + }, + "1": { + "action": "NODE_APPLICATION_EXECUTE", + "options": { + "node_id": 0, + "application_id": 0 + } + }, + "2": { + "action": "NODE_APPLICATION_EXECUTE", + "options": { + "node_id": 0, + "application_id": 1 + } + } + } + }, + "reward_function": { + "reward_components": [ + { + "type": "WEBPAGE_UNAVAILABLE_PENALTY", + "weight": 0.25, + "options": { + "node_hostname": "client_2" + } + }, + { + "type": "GREEN_ADMIN_DATABASE_UNREACHABLE_PENALTY", + "weight": 0.05, + "options": { + "node_hostname": "client_2" + } + } + ] + } + }, + { + "ref": "client_1_green_user", + "team": "GREEN", + "type": "ProbabilisticAgent", + "agent_settings": { + "action_probabilities": { + "0": 0.3, + "1": 0.6, + "2": 0.1 + } + }, + "observation_space": null, + "action_space": { + "action_list": [ + { + "type": "DONOTHING" + }, + { + "type": "NODE_APPLICATION_EXECUTE" + } + ], + "options": { + "nodes": [ + { + "node_name": "client_1", + "applications": [ + { + "application_name": "WebBrowser" + }, + { + "application_name": "DatabaseClient" + } + ] + } + ], + "max_folders_per_node": 1, + "max_files_per_folder": 1, + "max_services_per_node": 1, + "max_applications_per_node": 2 + }, + "action_map": { + "0": { + "action": "DONOTHING", + "options": {} + }, + "1": { + "action": "NODE_APPLICATION_EXECUTE", + "options": { + "node_id": 0, + "application_id": 0 + } + }, + "2": { + "action": "NODE_APPLICATION_EXECUTE", + "options": { + "node_id": 0, + "application_id": 1 + } + } + } + }, + "reward_function": { + "reward_components": [ + { + "type": "WEBPAGE_UNAVAILABLE_PENALTY", + "weight": 0.25, + "options": { + "node_hostname": "client_1" + } + }, + { + "type": "GREEN_ADMIN_DATABASE_UNREACHABLE_PENALTY", + "weight": 0.05, + "options": { + "node_hostname": "client_1" + } + } + ] + } + }, + { + "ref": "data_manipulation_attacker", + "team": "RED", + "type": "RedDatabaseCorruptingAgent", + "observation_space": null, + "action_space": { + "action_list": [ + { + "type": "DONOTHING" + }, + { + "type": "NODE_APPLICATION_EXECUTE" + } + ], + "options": { + "nodes": [ + { + "node_name": "client_1", + "applications": [ + { + "application_name": "DataManipulationBot" + } + ] + }, + { + "node_name": "client_2", + "applications": [ + { + "application_name": "DataManipulationBot" + } + ] + } + ], + "max_folders_per_node": 1, + "max_files_per_folder": 1, + "max_services_per_node": 1 + } + }, + "reward_function": { + "reward_components": [ + { + "type": "DUMMY" + } + ] + }, + "agent_settings": { + "start_settings": { + "start_step": 25, + "frequency": 20, + "variance": 5 + } + } + }, + { + "ref": "defender", + "team": "BLUE", + "type": "ProxyAgent", + "observation_space": { + "type": "CUSTOM", + "options": { + "components": [ + { + "type": "NODES", + "label": "NODES", + "options": { + "hosts": [ + { + "hostname": "domain_controller" + }, + { + "hostname": "web_server", + "services": [ + { + "service_name": "WebServer" + } + ] + }, + { + "hostname": "database_server", + "folders": [ + { + "folder_name": "database", + "files": [ + { + "file_name": "database.db" + } + ] + } + ] + }, + { + "hostname": "backup_server" + }, + { + "hostname": "security_suite" + }, + { + "hostname": "client_1" + }, + { + "hostname": "client_2" + } + ], + "num_services": 1, + "num_applications": 0, + "num_folders": 1, + "num_files": 1, + "num_nics": 2, + "include_num_access": false, + "include_nmne": true, + "monitored_traffic": { + "icmp": [ + "NONE" + ], + "tcp": [ + "DNS" + ] + }, + "routers": [ + { + "hostname": "router_1" + } + ], + "num_ports": 0, + "ip_list": [ + "192.168.1.10", + "192.168.1.12", + "192.168.1.14", + "192.168.1.16", + "192.168.1.110", + "192.168.10.21", + "192.168.10.22", + "192.168.10.110" + ], + "wildcard_list": [ + "0.0.0.1" + ], + "port_list": [ + 80, + 5432 + ], + "protocol_list": [ + "ICMP", + "TCP", + "UDP" + ], + "num_rules": 10 + } + }, + { + "type": "LINKS", + "label": "LINKS", + "options": { + "link_references": [ + "router_1:eth-1<->switch_1:eth-8", + "router_1:eth-2<->switch_2:eth-8", + "switch_1:eth-1<->domain_controller:eth-1", + "switch_1:eth-2<->web_server:eth-1", + "switch_1:eth-3<->database_server:eth-1", + "switch_1:eth-4<->backup_server:eth-1", + "switch_1:eth-7<->security_suite:eth-1", + "switch_2:eth-1<->client_1:eth-1", + "switch_2:eth-2<->client_2:eth-1", + "switch_2:eth-7<->security_suite:eth-2" + ] + } + }, + { + "type": "NONE", + "label": "ICS", + "options": {} + } + ] + } + }, + "action_space": { + "action_list": [ + { + "type": "DONOTHING" + }, + { + "type": "NODE_SERVICE_SCAN" + }, + { + "type": "NODE_SERVICE_STOP" + }, + { + "type": "NODE_SERVICE_START" + }, + { + "type": "NODE_SERVICE_PAUSE" + }, + { + "type": "NODE_SERVICE_RESUME" + }, + { + "type": "NODE_SERVICE_RESTART" + }, + { + "type": "NODE_SERVICE_DISABLE" + }, + { + "type": "NODE_SERVICE_ENABLE" + }, + { + "type": "NODE_SERVICE_FIX" + }, + { + "type": "NODE_FILE_SCAN" + }, + { + "type": "NODE_FILE_CHECKHASH" + }, + { + "type": "NODE_FILE_DELETE" + }, + { + "type": "NODE_FILE_REPAIR" + }, + { + "type": "NODE_FILE_RESTORE" + }, + { + "type": "NODE_FOLDER_SCAN" + }, + { + "type": "NODE_FOLDER_CHECKHASH" + }, + { + "type": "NODE_FOLDER_REPAIR" + }, + { + "type": "NODE_FOLDER_RESTORE" + }, + { + "type": "NODE_OS_SCAN" + }, + { + "type": "NODE_SHUTDOWN" + }, + { + "type": "NODE_STARTUP" + }, + { + "type": "NODE_RESET" + }, + { + "type": "ROUTER_ACL_ADDRULE" + }, + { + "type": "ROUTER_ACL_REMOVERULE" + }, + { + "type": "HOST_NIC_ENABLE" + }, + { + "type": "HOST_NIC_DISABLE" + } + ], + "action_map": { + "0": { + "action": "DONOTHING", + "options": {} + }, + "1": { + "action": "NODE_SERVICE_SCAN", + "options": { + "node_id": 1, + "service_id": 0 + } + }, + "2": { + "action": "NODE_SERVICE_STOP", + "options": { + "node_id": 1, + "service_id": 0 + } + }, + "3": { + "action": "NODE_SERVICE_START", + "options": { + "node_id": 1, + "service_id": 0 + } + }, + "4": { + "action": "NODE_SERVICE_PAUSE", + "options": { + "node_id": 1, + "service_id": 0 + } + }, + "5": { + "action": "NODE_SERVICE_RESUME", + "options": { + "node_id": 1, + "service_id": 0 + } + }, + "6": { + "action": "NODE_SERVICE_RESTART", + "options": { + "node_id": 1, + "service_id": 0 + } + }, + "7": { + "action": "NODE_SERVICE_DISABLE", + "options": { + "node_id": 1, + "service_id": 0 + } + }, + "8": { + "action": "NODE_SERVICE_ENABLE", + "options": { + "node_id": 1, + "service_id": 0 + } + }, + "9": { + "action": "NODE_FILE_SCAN", + "options": { + "node_id": 2, + "folder_id": 0, + "file_id": 0 + } + }, + "10": { + "action": "NODE_FILE_CHECKHASH", + "options": { + "node_id": 2, + "folder_id": 0, + "file_id": 0 + } + }, + "11": { + "action": "NODE_FILE_DELETE", + "options": { + "node_id": 2, + "folder_id": 0, + "file_id": 0 + } + }, + "12": { + "action": "NODE_FILE_REPAIR", + "options": { + "node_id": 2, + "folder_id": 0, + "file_id": 0 + } + }, + "13": { + "action": "NODE_SERVICE_FIX", + "options": { + "node_id": 2, + "service_id": 0 + } + }, + "14": { + "action": "NODE_FOLDER_SCAN", + "options": { + "node_id": 2, + "folder_id": 0 + } + }, + "15": { + "action": "NODE_FOLDER_CHECKHASH", + "options": { + "node_id": 2, + "folder_id": 0 + } + }, + "16": { + "action": "NODE_FOLDER_REPAIR", + "options": { + "node_id": 2, + "folder_id": 0 + } + }, + "17": { + "action": "NODE_FOLDER_RESTORE", + "options": { + "node_id": 2, + "folder_id": 0 + } + }, + "18": { + "action": "NODE_OS_SCAN", + "options": { + "node_id": 0 + } + }, + "19": { + "action": "NODE_SHUTDOWN", + "options": { + "node_id": 0 + } + }, + "20": { + "action": "NODE_STARTUP", + "options": { + "node_id": 0 + } + }, + "21": { + "action": "NODE_RESET", + "options": { + "node_id": 0 + } + }, + "22": { + "action": "NODE_OS_SCAN", + "options": { + "node_id": 1 + } + }, + "23": { + "action": "NODE_SHUTDOWN", + "options": { + "node_id": 1 + } + }, + "24": { + "action": "NODE_STARTUP", + "options": { + "node_id": 1 + } + }, + "25": { + "action": "NODE_RESET", + "options": { + "node_id": 1 + } + }, + "26": { + "action": "NODE_OS_SCAN", + "options": { + "node_id": 2 + } + }, + "27": { + "action": "NODE_SHUTDOWN", + "options": { + "node_id": 2 + } + }, + "28": { + "action": "NODE_STARTUP", + "options": { + "node_id": 2 + } + }, + "29": { + "action": "NODE_RESET", + "options": { + "node_id": 2 + } + }, + "30": { + "action": "NODE_OS_SCAN", + "options": { + "node_id": 3 + } + }, + "31": { + "action": "NODE_SHUTDOWN", + "options": { + "node_id": 3 + } + }, + "32": { + "action": "NODE_STARTUP", + "options": { + "node_id": 3 + } + }, + "33": { + "action": "NODE_RESET", + "options": { + "node_id": 3 + } + }, + "34": { + "action": "NODE_OS_SCAN", + "options": { + "node_id": 4 + } + }, + "35": { + "action": "NODE_SHUTDOWN", + "options": { + "node_id": 4 + } + }, + "36": { + "action": "NODE_STARTUP", + "options": { + "node_id": 4 + } + }, + "37": { + "action": "NODE_RESET", + "options": { + "node_id": 4 + } + }, + "38": { + "action": "NODE_OS_SCAN", + "options": { + "node_id": 5 + } + }, + "39": { + "action": "NODE_SHUTDOWN", + "options": { + "node_id": 5 + } + }, + "40": { + "action": "NODE_STARTUP", + "options": { + "node_id": 5 + } + }, + "41": { + "action": "NODE_RESET", + "options": { + "node_id": 5 + } + }, + "42": { + "action": "NODE_OS_SCAN", + "options": { + "node_id": 6 + } + }, + "43": { + "action": "NODE_SHUTDOWN", + "options": { + "node_id": 6 + } + }, + "44": { + "action": "NODE_STARTUP", + "options": { + "node_id": 6 + } + }, + "45": { + "action": "NODE_RESET", + "options": { + "node_id": 6 + } + }, + "46": { + "action": "ROUTER_ACL_ADDRULE", + "options": { + "target_router": "router_1", + "position": 1, + "permission": 2, + "source_ip_id": 7, + "dest_ip_id": 1, + "source_port_id": 1, + "dest_port_id": 1, + "protocol_id": 1, + "source_wildcard_id": 0, + "dest_wildcard_id": 0 + } + }, + "47": { + "action": "ROUTER_ACL_ADDRULE", + "options": { + "target_router": "router_1", + "position": 2, + "permission": 2, + "source_ip_id": 8, + "dest_ip_id": 1, + "source_port_id": 1, + "dest_port_id": 1, + "protocol_id": 1, + "source_wildcard_id": 0, + "dest_wildcard_id": 0 + } + }, + "48": { + "action": "ROUTER_ACL_ADDRULE", + "options": { + "target_router": "router_1", + "position": 3, + "permission": 2, + "source_ip_id": 7, + "dest_ip_id": 3, + "source_port_id": 1, + "dest_port_id": 1, + "protocol_id": 3, + "source_wildcard_id": 0, + "dest_wildcard_id": 0 + } + }, + "49": { + "action": "ROUTER_ACL_ADDRULE", + "options": { + "target_router": "router_1", + "position": 4, + "permission": 2, + "source_ip_id": 8, + "dest_ip_id": 3, + "source_port_id": 1, + "dest_port_id": 1, + "protocol_id": 3, + "source_wildcard_id": 0, + "dest_wildcard_id": 0 + } + }, + "50": { + "action": "ROUTER_ACL_ADDRULE", + "options": { + "target_router": "router_1", + "position": 5, + "permission": 2, + "source_ip_id": 7, + "dest_ip_id": 4, + "source_port_id": 1, + "dest_port_id": 1, + "protocol_id": 3, + "source_wildcard_id": 0, + "dest_wildcard_id": 0 + } + }, + "51": { + "action": "ROUTER_ACL_ADDRULE", + "options": { + "target_router": "router_1", + "position": 6, + "permission": 2, + "source_ip_id": 8, + "dest_ip_id": 4, + "source_port_id": 1, + "dest_port_id": 1, + "protocol_id": 3, + "source_wildcard_id": 0, + "dest_wildcard_id": 0 + } + }, + "52": { + "action": "ROUTER_ACL_REMOVERULE", + "options": { + "target_router": "router_1", + "position": 0 + } + }, + "53": { + "action": "ROUTER_ACL_REMOVERULE", + "options": { + "target_router": "router_1", + "position": 1 + } + }, + "54": { + "action": "ROUTER_ACL_REMOVERULE", + "options": { + "target_router": "router_1", + "position": 2 + } + }, + "55": { + "action": "ROUTER_ACL_REMOVERULE", + "options": { + "target_router": "router_1", + "position": 3 + } + }, + "56": { + "action": "ROUTER_ACL_REMOVERULE", + "options": { + "target_router": "router_1", + "position": 4 + } + }, + "57": { + "action": "ROUTER_ACL_REMOVERULE", + "options": { + "target_router": "router_1", + "position": 5 + } + }, + "58": { + "action": "ROUTER_ACL_REMOVERULE", + "options": { + "target_router": "router_1", + "position": 6 + } + }, + "59": { + "action": "ROUTER_ACL_REMOVERULE", + "options": { + "target_router": "router_1", + "position": 7 + } + }, + "60": { + "action": "ROUTER_ACL_REMOVERULE", + "options": { + "target_router": "router_1", + "position": 8 + } + }, + "61": { + "action": "ROUTER_ACL_REMOVERULE", + "options": { + "target_router": "router_1", + "position": 9 + } + }, + "62": { + "action": "HOST_NIC_DISABLE", + "options": { + "node_id": 0, + "nic_id": 0 + } + }, + "63": { + "action": "HOST_NIC_ENABLE", + "options": { + "node_id": 0, + "nic_id": 0 + } + }, + "64": { + "action": "HOST_NIC_DISABLE", + "options": { + "node_id": 1, + "nic_id": 0 + } + }, + "65": { + "action": "HOST_NIC_ENABLE", + "options": { + "node_id": 1, + "nic_id": 0 + } + }, + "66": { + "action": "HOST_NIC_DISABLE", + "options": { + "node_id": 2, + "nic_id": 0 + } + }, + "67": { + "action": "HOST_NIC_ENABLE", + "options": { + "node_id": 2, + "nic_id": 0 + } + }, + "68": { + "action": "HOST_NIC_DISABLE", + "options": { + "node_id": 3, + "nic_id": 0 + } + }, + "69": { + "action": "HOST_NIC_ENABLE", + "options": { + "node_id": 3, + "nic_id": 0 + } + }, + "70": { + "action": "HOST_NIC_DISABLE", + "options": { + "node_id": 4, + "nic_id": 0 + } + }, + "71": { + "action": "HOST_NIC_ENABLE", + "options": { + "node_id": 4, + "nic_id": 0 + } + }, + "72": { + "action": "HOST_NIC_DISABLE", + "options": { + "node_id": 4, + "nic_id": 1 + } + }, + "73": { + "action": "HOST_NIC_ENABLE", + "options": { + "node_id": 4, + "nic_id": 1 + } + }, + "74": { + "action": "HOST_NIC_DISABLE", + "options": { + "node_id": 5, + "nic_id": 0 + } + }, + "75": { + "action": "HOST_NIC_ENABLE", + "options": { + "node_id": 5, + "nic_id": 0 + } + }, + "76": { + "action": "HOST_NIC_DISABLE", + "options": { + "node_id": 6, + "nic_id": 0 + } + }, + "77": { + "action": "HOST_NIC_ENABLE", + "options": { + "node_id": 6, + "nic_id": 0 + } + } + }, + "options": { + "nodes": [ + { + "node_name": "domain_controller" + }, + { + "node_name": "web_server", + "applications": [ + { + "application_name": "DatabaseClient" + } + ], + "services": [ + { + "service_name": "WebServer" + } + ] + }, + { + "node_name": "database_server", + "folders": [ + { + "folder_name": "database", + "files": [ + { + "file_name": "database.db" + } + ] + } + ], + "services": [ + { + "service_name": "DatabaseService" + } + ] + }, + { + "node_name": "backup_server" + }, + { + "node_name": "security_suite" + }, + { + "node_name": "client_1" + }, + { + "node_name": "client_2" + } + ], + "max_folders_per_node": 2, + "max_files_per_folder": 2, + "max_services_per_node": 2, + "max_nics_per_node": 8, + "max_acl_rules": 10, + "ip_list": [ + "192.168.1.10", + "192.168.1.12", + "192.168.1.14", + "192.168.1.16", + "192.168.1.110", + "192.168.10.21", + "192.168.10.22", + "192.168.10.110" + ] + } + }, + "reward_function": { + "reward_components": [ + { + "type": "DATABASE_FILE_INTEGRITY", + "weight": 0.4, + "options": { + "node_hostname": "database_server", + "folder_name": "database", + "file_name": "database.db" + } + }, + { + "type": "SHARED_REWARD", + "weight": 1.0, + "options": { + "agent_name": "client_1_green_user" + } + }, + { + "type": "SHARED_REWARD", + "weight": 1.0, + "options": { + "agent_name": "client_2_green_user" + } + } + ] + }, + "agent_settings": { + "flatten_obs": true + } + } + ], + "simulation": { + "network": { + "nmne_config": { + "capture_nmne": true, + "nmne_capture_keywords": [ + "DELETE" + ] + }, + "nodes": [ + { + "hostname": "router_1", + "type": "router", + "num_ports": 5, + "ports": { + "1": { + "ip_address": "192.168.1.1", + "subnet_mask": "255.255.255.0" + }, + "2": { + "ip_address": "192.168.10.1", + "subnet_mask": "255.255.255.0" + } + }, + "acl": { + "18": { + "action": "PERMIT", + "src_port": "POSTGRES_SERVER", + "dst_port": "POSTGRES_SERVER" + }, + "19": { + "action": "PERMIT", + "src_port": "DNS", + "dst_port": "DNS" + }, + "20": { + "action": "PERMIT", + "src_port": "FTP", + "dst_port": "FTP" + }, + "21": { + "action": "PERMIT", + "src_port": "HTTP", + "dst_port": "HTTP" + }, + "22": { + "action": "PERMIT", + "src_port": "ARP", + "dst_port": "ARP" + }, + "23": { + "action": "PERMIT", + "protocol": "ICMP" + } + } + }, + { + "hostname": "switch_1", + "type": "switch", + "num_ports": 8 + }, + { + "hostname": "switch_2", + "type": "switch", + "num_ports": 8 + }, + { + "hostname": "domain_controller", + "type": "server", + "ip_address": "192.168.1.10", + "subnet_mask": "255.255.255.0", + "default_gateway": "192.168.1.1", + "services": [ + { + "type": "DNSServer", + "options": { + "domain_mapping": { + "arcd.com": "192.168.1.12" + } + } + } + ] + }, + { + "hostname": "web_server", + "type": "server", + "ip_address": "192.168.1.12", + "subnet_mask": "255.255.255.0", + "default_gateway": "192.168.1.1", + "dns_server": "192.168.1.10", + "services": [ + { + "type": "WebServer" + } + ], + "applications": [ + { + "type": "DatabaseClient", + "options": { + "db_server_ip": "192.168.1.14" + } + } + ] + }, + { + "hostname": "database_server", + "type": "server", + "ip_address": "192.168.1.14", + "subnet_mask": "255.255.255.0", + "default_gateway": "192.168.1.1", + "dns_server": "192.168.1.10", + "services": [ + { + "type": "DatabaseService", + "options": { + "backup_server_ip": "192.168.1.16" + } + }, + { + "type": "FTPClient" + } + ] + }, + { + "hostname": "backup_server", + "type": "server", + "ip_address": "192.168.1.16", + "subnet_mask": "255.255.255.0", + "default_gateway": "192.168.1.1", + "dns_server": "192.168.1.10", + "services": [ + { + "type": "FTPServer" + } + ] + }, + { + "hostname": "security_suite", + "type": "server", + "ip_address": "192.168.1.110", + "subnet_mask": "255.255.255.0", + "default_gateway": "192.168.1.1", + "dns_server": "192.168.1.10", + "network_interfaces": { + "2": { + "ip_address": "192.168.10.110", + "subnet_mask": "255.255.255.0" + } + } + }, + { + "hostname": "client_1", + "type": "computer", + "ip_address": "192.168.10.21", + "subnet_mask": "255.255.255.0", + "default_gateway": "192.168.10.1", + "dns_server": "192.168.1.10", + "applications": [ + { + "type": "DataManipulationBot", + "options": { + "port_scan_p_of_success": 0.8, + "data_manipulation_p_of_success": 0.8, + "payload": "DELETE", + "server_ip": "192.168.1.14" + } + }, + { + "type": "WebBrowser", + "options": { + "target_url": "http://arcd.com/users/" + } + }, + { + "type": "DatabaseClient", + "options": { + "db_server_ip": "192.168.1.14" + } + } + ], + "services": [ + { + "type": "DNSClient" + } + ] + }, + { + "hostname": "client_2", + "type": "computer", + "ip_address": "192.168.10.22", + "subnet_mask": "255.255.255.0", + "default_gateway": "192.168.10.1", + "dns_server": "192.168.1.10", + "applications": [ + { + "type": "WebBrowser", + "options": { + "target_url": "http://arcd.com/users/" + } + }, + { + "type": "DataManipulationBot", + "options": { + "port_scan_p_of_success": 0.8, + "data_manipulation_p_of_success": 0.8, + "payload": "DELETE", + "server_ip": "192.168.1.14" + } + }, + { + "type": "DatabaseClient", + "options": { + "db_server_ip": "192.168.1.14" + } + } + ], + "services": [ + { + "type": "DNSClient" + } + ] + } + ], + "links": [ + { + "endpoint_a_hostname": "router_1", + "endpoint_a_port": 1, + "endpoint_b_hostname": "switch_1", + "endpoint_b_port": 8 + }, + { + "endpoint_a_hostname": "router_1", + "endpoint_a_port": 2, + "endpoint_b_hostname": "switch_2", + "endpoint_b_port": 8 + }, + { + "endpoint_a_hostname": "switch_1", + "endpoint_a_port": 1, + "endpoint_b_hostname": "domain_controller", + "endpoint_b_port": 1 + }, + { + "endpoint_a_hostname": "switch_1", + "endpoint_a_port": 2, + "endpoint_b_hostname": "web_server", + "endpoint_b_port": 1 + }, + { + "endpoint_a_hostname": "switch_1", + "endpoint_a_port": 3, + "endpoint_b_hostname": "database_server", + "endpoint_b_port": 1 + }, + { + "endpoint_a_hostname": "switch_1", + "endpoint_a_port": 4, + "endpoint_b_hostname": "backup_server", + "endpoint_b_port": 1 + }, + { + "endpoint_a_hostname": "switch_1", + "endpoint_a_port": 7, + "endpoint_b_hostname": "security_suite", + "endpoint_b_port": 1 + }, + { + "endpoint_a_hostname": "switch_2", + "endpoint_a_port": 1, + "endpoint_b_hostname": "client_1", + "endpoint_b_port": 1 + }, + { + "endpoint_a_hostname": "switch_2", + "endpoint_a_port": 2, + "endpoint_b_hostname": "client_2", + "endpoint_b_port": 1 + }, + { + "endpoint_a_hostname": "switch_2", + "endpoint_a_port": 7, + "endpoint_b_hostname": "security_suite", + "endpoint_b_port": 2 + } + ] + } + } + } +} \ No newline at end of file diff --git a/copyright_clause_pre_commit_hook.py b/copyright_clause_pre_commit_hook.py new file mode 100644 index 00000000..66958688 --- /dev/null +++ b/copyright_clause_pre_commit_hook.py @@ -0,0 +1,154 @@ +# -*- coding: utf-8 -*- +import datetime +import sys +from pathlib import Path + +# Constants +CURRENT_YEAR = datetime.date.today().year +COPYRIGHT_PY_STR = f"# © Crown-owned copyright {CURRENT_YEAR}, Defence Science and Technology Laboratory UK" +COPYRIGHT_RST_LINES = [ + ".. only:: comment", + "", + f" © Crown-owned copyright {CURRENT_YEAR}, Defence Science and Technology Laboratory UK", +] +PATHS = {Path("./src"), Path("./tests"), Path("./docs"), Path("./benchmark")} +EXTENSIONS = {".py", ".rst"} + + +def _is_copyright_line(line: str) -> bool: + """ + Check if a line is a copyright line. + + :param line: The line to check. + :return: True if the line is a copyright line, False otherwise. + """ + return line.startswith("#") and "copyright" in line.lower() + + +def _is_rst_copyright_lines(lines: list) -> bool: + """ + Check if the lines match the RST copyright format. + + :param lines: The lines to check. + :return: True if the lines match the RST copyright format, False otherwise. + """ + return len(lines) >= 3 and lines[0] == ".. only:: comment" and "copyright" in lines[2].lower() + + +def process_py_file(file_path: Path) -> bool: + """ + Process a Python file to check and add/update the copyright clause. + + :param file_path: The path to the file to check and update. + :return: True if the file was modified, False otherwise. + """ + modified = False + try: + content = file_path.read_text(encoding="utf-8") + lines = content.splitlines(keepends=True) # Keep line endings + + if lines and _is_copyright_line(lines[0]): + if lines[0].strip() != COPYRIGHT_PY_STR: + lines[0] = COPYRIGHT_PY_STR + "\n" + modified = True + print(f"Updated copyright clause in {file_path}") + else: + lines.insert(0, COPYRIGHT_PY_STR + "\n") + modified = True + print(f"Added copyright clause to {file_path}") + + if modified: + file_path.write_text("".join(lines), encoding="utf-8") + except Exception as e: + print(f"Failed to process {file_path}: {e}") + return False + + return modified + + +def process_rst_file(file_path: Path) -> bool: + """ + Process an RST file to check and add/update the copyright clause. + + :param file_path: The path to the file to check and update. + :return: True if the file was modified, False otherwise. + """ + modified = False + try: + content = file_path.read_text(encoding="utf-8") + lines = content.splitlines(keepends=True) # Keep line endings + + existing_block = any(".. only:: comment" in line for line in lines) + + if existing_block: + # Check if the block is correct + for i, line in enumerate(lines): + if line.strip() == ".. only:: comment": + if lines[i : i + 3] != [ + COPYRIGHT_RST_LINES[0] + "\n", + COPYRIGHT_RST_LINES[1] + "\n", + COPYRIGHT_RST_LINES[2] + "\n", + ]: + # Update the incorrect block + lines[i : i + 3] = [ + COPYRIGHT_RST_LINES[0] + "\n", + COPYRIGHT_RST_LINES[1] + "\n", + COPYRIGHT_RST_LINES[2] + "\n", + ] + modified = True + print(f"Updated copyright clause in {file_path}") + break + else: + # Insert new copyright block + lines = [line + "\n" for line in COPYRIGHT_RST_LINES] + ["\n"] + lines + modified = True + print(f"Added copyright clause to {file_path}") + + if modified: + file_path.write_text("".join(lines), encoding="utf-8") + except Exception as e: + print(f"Failed to process {file_path}: {e}") + return False + + return modified + + +def process_file(file_path: Path) -> bool: + """ + Check if a file has the correct copyright clause and add or update it if necessary. + + :param file_path: The path to the file to check and update. + :return: True if the file was modified, False otherwise. + """ + if file_path.suffix == ".py": + return process_py_file(file_path) + elif file_path.suffix == ".rst": + return process_rst_file(file_path) + return False + + +def main() -> int: + """ + Main function to walk through the root directories, check files, and update the copyright clause. + + :return: 1 if any file was modified, 0 otherwise. + """ + files_checked = 0 + files_modified = 0 + any_file_modified = False + for path in PATHS: + for file_path in path.rglob("*"): + if file_path.suffix in EXTENSIONS: + files_checked += 1 + if process_file(file_path): + files_modified += 1 + any_file_modified = True + + if any_file_modified: + print(f"Files Checked: {files_checked}. Files Modified: {files_modified}") + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/docs/Makefile b/docs/Makefile index fcf64a6a..99e19d16 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK # Minimal makefile for Sphinx documentation # You can set these variables from the command line, and also # from the environment for the first two. diff --git a/docs/_templates/custom-class-template.rst b/docs/_templates/custom-class-template.rst index 66acd325..920158d5 100644 --- a/docs/_templates/custom-class-template.rst +++ b/docs/_templates/custom-class-template.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. Credit to https://github.com/JamesALeedham/Sphinx-Autosummary-Recursion for the custom templates. diff --git a/docs/_templates/custom-module-template.rst b/docs/_templates/custom-module-template.rst index 64ac520a..98627e43 100644 --- a/docs/_templates/custom-module-template.rst +++ b/docs/_templates/custom-module-template.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. Credit to https://github.com/JamesALeedham/Sphinx-Autosummary-Recursion for the custom templates. diff --git a/docs/api.rst b/docs/api.rst index e74be627..977f9e87 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -2,7 +2,7 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. DO NOT DELETE THIS FILE! It contains the all-important `.. autosummary::` directive with `:recursive:` option, without diff --git a/docs/build-sphinx-docs-to-github-pages.sh b/docs/build-sphinx-docs-to-github-pages.sh index f1d40647..9e43a2b4 100644 --- a/docs/build-sphinx-docs-to-github-pages.sh +++ b/docs/build-sphinx-docs-to-github-pages.sh @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK #!/bin/bash set -x @@ -42,7 +43,7 @@ touch .nojekyll # Add README cat > README.md < Any: This allows developers to create new notebooks without having to worry about updating documentation when a new notebook is included within PrimAITE. """ - notebook_asset_types = [".ipynb", ".png"] + notebook_asset_types = [".ipynb", ".png", ".svg"] notebook_directories = [] # find paths where notebooks are contained diff --git a/docs/make.bat b/docs/make.bat index a341af57..807fe3da 100644 --- a/docs/make.bat +++ b/docs/make.bat @@ -1,4 +1,5 @@ @ECHO OFF +REM © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK setlocal EnableDelayedExpansion diff --git a/docs/source/configuration/agents.rst b/docs/source/configuration/agents.rst index 5acf17a4..2fe35ac7 100644 --- a/docs/source/configuration/agents.rst +++ b/docs/source/configuration/agents.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK ``agents`` diff --git a/docs/source/configuration/game.rst b/docs/source/configuration/game.rst index 828571a7..02ee8110 100644 --- a/docs/source/configuration/game.rst +++ b/docs/source/configuration/game.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK ``game`` diff --git a/docs/source/configuration/io_settings.rst b/docs/source/configuration/io_settings.rst index 46b2f1b2..82fd7408 100644 --- a/docs/source/configuration/io_settings.rst +++ b/docs/source/configuration/io_settings.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK ``io_settings`` diff --git a/docs/source/configuration/simulation.rst b/docs/source/configuration/simulation.rst index b19574f4..2bcc8b66 100644 --- a/docs/source/configuration/simulation.rst +++ b/docs/source/configuration/simulation.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK ``simulation`` diff --git a/docs/source/configuration/simulation/nodes/common/common.rst b/docs/source/configuration/simulation/nodes/common/common.rst index d1c8f307..a0f2eb13 100644 --- a/docs/source/configuration/simulation/nodes/common/common.rst +++ b/docs/source/configuration/simulation/nodes/common/common.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _Node Attributes: diff --git a/docs/source/configuration/simulation/nodes/common/common_host_node_attributes.rst b/docs/source/configuration/simulation/nodes/common/common_host_node_attributes.rst index 929d5714..bb3b2a52 100644 --- a/docs/source/configuration/simulation/nodes/common/common_host_node_attributes.rst +++ b/docs/source/configuration/simulation/nodes/common/common_host_node_attributes.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _common_host_node_attributes: diff --git a/docs/source/configuration/simulation/nodes/common/common_network_node_attributes.rst b/docs/source/configuration/simulation/nodes/common/common_network_node_attributes.rst index 1161059f..d556e2dc 100644 --- a/docs/source/configuration/simulation/nodes/common/common_network_node_attributes.rst +++ b/docs/source/configuration/simulation/nodes/common/common_network_node_attributes.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _common_network_node_attributes: diff --git a/docs/source/configuration/simulation/nodes/common/common_node_attributes.rst b/docs/source/configuration/simulation/nodes/common/common_node_attributes.rst index 34519adc..e648e4a1 100644 --- a/docs/source/configuration/simulation/nodes/common/common_node_attributes.rst +++ b/docs/source/configuration/simulation/nodes/common/common_node_attributes.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _common_node_attributes: diff --git a/docs/source/configuration/simulation/nodes/common/node_type_list.rst b/docs/source/configuration/simulation/nodes/common/node_type_list.rst index ceee8207..1ec496d9 100644 --- a/docs/source/configuration/simulation/nodes/common/node_type_list.rst +++ b/docs/source/configuration/simulation/nodes/common/node_type_list.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK ``type`` -------- diff --git a/docs/source/configuration/simulation/nodes/computer.rst b/docs/source/configuration/simulation/nodes/computer.rst index 04a45766..32e0b2b9 100644 --- a/docs/source/configuration/simulation/nodes/computer.rst +++ b/docs/source/configuration/simulation/nodes/computer.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _computer_configuration: diff --git a/docs/source/configuration/simulation/nodes/firewall.rst b/docs/source/configuration/simulation/nodes/firewall.rst index 77e6cd12..775ffabd 100644 --- a/docs/source/configuration/simulation/nodes/firewall.rst +++ b/docs/source/configuration/simulation/nodes/firewall.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _firewall_configuration: diff --git a/docs/source/configuration/simulation/nodes/network_examples.rst b/docs/source/configuration/simulation/nodes/network_examples.rst index c1036c97..2a34a206 100644 --- a/docs/source/configuration/simulation/nodes/network_examples.rst +++ b/docs/source/configuration/simulation/nodes/network_examples.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _network_examples: diff --git a/docs/source/configuration/simulation/nodes/router.rst b/docs/source/configuration/simulation/nodes/router.rst index b9ba1ad5..ac9d6411 100644 --- a/docs/source/configuration/simulation/nodes/router.rst +++ b/docs/source/configuration/simulation/nodes/router.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _router_configuration: diff --git a/docs/source/configuration/simulation/nodes/server.rst b/docs/source/configuration/simulation/nodes/server.rst index dbc32235..92b33ca7 100644 --- a/docs/source/configuration/simulation/nodes/server.rst +++ b/docs/source/configuration/simulation/nodes/server.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _server_configuration: diff --git a/docs/source/configuration/simulation/nodes/switch.rst b/docs/source/configuration/simulation/nodes/switch.rst index 263bedbb..17cf76f9 100644 --- a/docs/source/configuration/simulation/nodes/switch.rst +++ b/docs/source/configuration/simulation/nodes/switch.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _switch_configuration: diff --git a/docs/source/configuration/simulation/software/applications.rst b/docs/source/configuration/simulation/software/applications.rst index 90ae3ec1..8c590d53 100644 --- a/docs/source/configuration/simulation/software/applications.rst +++ b/docs/source/configuration/simulation/software/applications.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK ``applications`` ---------------- diff --git a/docs/source/configuration/simulation/software/services.rst b/docs/source/configuration/simulation/software/services.rst index 88957001..fafdf2e8 100644 --- a/docs/source/configuration/simulation/software/services.rst +++ b/docs/source/configuration/simulation/software/services.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK ``services`` ------------ diff --git a/docs/source/customising_scenarios.rst b/docs/source/customising_scenarios.rst index 709f032a..092f306b 100644 --- a/docs/source/customising_scenarios.rst +++ b/docs/source/customising_scenarios.rst @@ -1,3 +1,7 @@ +.. only:: comment + + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK + Customising Agents ****************** diff --git a/docs/source/environment.rst b/docs/source/environment.rst index 2b76572d..a282c09e 100644 --- a/docs/source/environment.rst +++ b/docs/source/environment.rst @@ -1,3 +1,7 @@ +.. only:: comment + + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK + RL Environments *************** diff --git a/docs/source/example_notebooks.rst b/docs/source/example_notebooks.rst index 731ea566..466beca3 100644 --- a/docs/source/example_notebooks.rst +++ b/docs/source/example_notebooks.rst @@ -77,6 +77,6 @@ The following extensions should now be installed :width: 300 :align: center -VSCode will then ask for a Python environment version to use. PrimAITE is compatible with Python versions 3.8 - 3.11 +VSCode will then ask for a Python environment version to use. PrimAITE is compatible with Python versions 3.9 - 3.11 You should now be able to interact with the notebook. diff --git a/docs/source/game_layer.rst b/docs/source/game_layer.rst index 68984a1b..2fa6639f 100644 --- a/docs/source/game_layer.rst +++ b/docs/source/game_layer.rst @@ -1,3 +1,7 @@ +.. only:: comment + + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK + PrimAITE Game layer ******************* @@ -81,7 +85,6 @@ blue_agent: weight: 1.0 options: agent_name: client_2_green_user - ``` When defining agent reward sharing, users must be careful to avoid circular references, as that would lead to an infinite calculation loop. PrimAITE will prevent circular dependencies and provide a helpful error message if they are detected in the yaml. diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index 28630cb4..ded92c60 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -113,7 +113,7 @@ For example: .. code-block:: bash - git clone https://github.com/Autonomous-Resilient-Cyber-Defence/PrimAITE + git clone https://github.com/{todo:fill in URL}/PrimAITE cd primaite 2. Create and activate your Python virtual environment (venv) diff --git a/docs/source/notebooks/executed_notebooks.rst b/docs/source/notebooks/executed_notebooks.rst index f99b13bb..3431d344 100644 --- a/docs/source/notebooks/executed_notebooks.rst +++ b/docs/source/notebooks/executed_notebooks.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _Executed Notebooks: diff --git a/docs/source/primaite-dependencies.rst b/docs/source/primaite-dependencies.rst index c70a299d..e7333b53 100644 --- a/docs/source/primaite-dependencies.rst +++ b/docs/source/primaite-dependencies.rst @@ -1,3 +1,7 @@ +.. only:: comment + + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK + +-------------------+---------+------------------------------------+-------------------------------------------------------------------------------------------------------+----------------------------------------------+ | Name | Version | License | Description | URL | +===================+=========+====================================+=======================================================================================================+==============================================+ diff --git a/docs/source/simulation_components/network/base_hardware.rst b/docs/source/simulation_components/network/base_hardware.rst index 1b83f3f4..9e42b1de 100644 --- a/docs/source/simulation_components/network/base_hardware.rst +++ b/docs/source/simulation_components/network/base_hardware.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK ############# Base Hardware diff --git a/docs/source/simulation_components/network/network.rst b/docs/source/simulation_components/network/network.rst index 36e8ee48..636ffbcc 100644 --- a/docs/source/simulation_components/network/network.rst +++ b/docs/source/simulation_components/network/network.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _network: diff --git a/docs/source/simulation_components/network/network_interfaces.rst b/docs/source/simulation_components/network/network_interfaces.rst index f50a1baa..c6b97a8e 100644 --- a/docs/source/simulation_components/network/network_interfaces.rst +++ b/docs/source/simulation_components/network/network_interfaces.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK ################################# Network Interface Hierarchy Model diff --git a/docs/source/simulation_components/network/nodes/firewall.rst b/docs/source/simulation_components/network/nodes/firewall.rst index 2f948081..149d3e67 100644 --- a/docs/source/simulation_components/network/nodes/firewall.rst +++ b/docs/source/simulation_components/network/nodes/firewall.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK ######## Firewall diff --git a/docs/source/simulation_components/network/nodes/host_node.rst b/docs/source/simulation_components/network/nodes/host_node.rst index bc3c13a5..301cd783 100644 --- a/docs/source/simulation_components/network/nodes/host_node.rst +++ b/docs/source/simulation_components/network/nodes/host_node.rst @@ -1,3 +1,7 @@ +.. only:: comment + + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK + ######### Host Node diff --git a/docs/source/simulation_components/network/nodes/network_node.rst b/docs/source/simulation_components/network/nodes/network_node.rst index 33bcea5b..e1fa976c 100644 --- a/docs/source/simulation_components/network/nodes/network_node.rst +++ b/docs/source/simulation_components/network/nodes/network_node.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK ############ Network Node diff --git a/docs/source/simulation_components/network/nodes/router.rst b/docs/source/simulation_components/network/nodes/router.rst index 7679baa0..5d3de60f 100644 --- a/docs/source/simulation_components/network/nodes/router.rst +++ b/docs/source/simulation_components/network/nodes/router.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK ###### Router diff --git a/docs/source/simulation_components/network/nodes/switch.rst b/docs/source/simulation_components/network/nodes/switch.rst index 0595f363..0ecbcbf3 100644 --- a/docs/source/simulation_components/network/nodes/switch.rst +++ b/docs/source/simulation_components/network/nodes/switch.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK ###### Switch diff --git a/docs/source/simulation_components/network/nodes/wireless_router.rst b/docs/source/simulation_components/network/nodes/wireless_router.rst index 75cbe0f7..29110a52 100644 --- a/docs/source/simulation_components/network/nodes/wireless_router.rst +++ b/docs/source/simulation_components/network/nodes/wireless_router.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK ###### Router diff --git a/docs/source/simulation_components/network/transport_to_data_link_layer.rst b/docs/source/simulation_components/network/transport_to_data_link_layer.rst index 0220ec45..cc546021 100644 --- a/docs/source/simulation_components/network/transport_to_data_link_layer.rst +++ b/docs/source/simulation_components/network/transport_to_data_link_layer.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK Transport Layer to Data Link Layer ================================== diff --git a/docs/source/simulation_components/system/applications/data_manipulation_bot.rst b/docs/source/simulation_components/system/applications/data_manipulation_bot.rst index 9188733b..8bcbb265 100644 --- a/docs/source/simulation_components/system/applications/data_manipulation_bot.rst +++ b/docs/source/simulation_components/system/applications/data_manipulation_bot.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _DataManipulationBot: diff --git a/docs/source/simulation_components/system/applications/database_client.rst b/docs/source/simulation_components/system/applications/database_client.rst index 363c4f4e..d51465b2 100644 --- a/docs/source/simulation_components/system/applications/database_client.rst +++ b/docs/source/simulation_components/system/applications/database_client.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _DatabaseClient: diff --git a/docs/source/simulation_components/system/applications/dos_bot.rst b/docs/source/simulation_components/system/applications/dos_bot.rst index 6ddbac72..2a26a971 100644 --- a/docs/source/simulation_components/system/applications/dos_bot.rst +++ b/docs/source/simulation_components/system/applications/dos_bot.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _DoSBot: diff --git a/docs/source/simulation_components/system/applications/nmap.rst b/docs/source/simulation_components/system/applications/nmap.rst new file mode 100644 index 00000000..9ea0c60e --- /dev/null +++ b/docs/source/simulation_components/system/applications/nmap.rst @@ -0,0 +1,347 @@ +.. only:: comment + + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK + +.. _NMAP: + +NMAP +==== + +Overview +-------- + +The NMAP application is used to simulate network scanning activities. NMAP is a powerful tool that helps in discovering +hosts and services on a network. It provides functionalities such as ping scans to discover active hosts and port scans +to detect open ports on those hosts. + +The NMAP application is essential for network administrators and security professionals to map out a network's +structure, identify active devices, and find potential vulnerabilities by discovering open ports and running services. +However, it is also a tool frequently used by attackers during the reconnaissance stage of a cyber attack to gather +information about the target network. + +Scan Types +---------- + +Ping Scan +^^^^^^^^^ + +A ping scan is used to identify which hosts on a network are active and reachable. This is achieved by sending ICMP +Echo Request packets (ping) to the target IP addresses. If a host responds with an ICMP Echo Reply, it is considered +active. Ping scans are useful for quickly mapping out live hosts in a network. + +Port Scan +^^^^^^^^^ + +A port scan is used to detect open ports on a target host or range of hosts. Open ports can indicate running services +that might be exploitable or require securing. Port scans help in understanding the services available on a network and +identifying potential entry points for attacks. There are three types of port scans based on the scope: + +- **Horizontal Port Scan**: This scan targets a specific port across a range of IP addresses. It helps in identifying + which hosts have a particular service running. + +- **Vertical Port Scan**: This scan targets multiple ports on a single IP address. It provides detailed information + about the services running on a specific host. + +- **Box Scan**: This combines both horizontal and vertical scans, targeting multiple ports across multiple IP addresses. + It gives a comprehensive view of the network's service landscape. + +Example Usage +------------- + +The network we use for these examples is defined below: + +.. code-block:: python + + from ipaddress import IPv4Network + + from primaite.simulator.network.container import Network + from primaite.simulator.network.hardware.nodes.host.computer import Computer + from primaite.simulator.network.hardware.nodes.network.router import Router + from primaite.simulator.network.hardware.nodes.network.switch import Switch + from primaite.simulator.system.applications.nmap import NMAP + from primaite.simulator.system.services.database.database_service import DatabaseService + + # Initialize the network + network = Network() + + # Set up the router + router = Router(hostname="router", start_up_duration=0) + router.power_on() + router.configure_port(port=1, ip_address="192.168.1.1", subnet_mask="255.255.255.0") + + # Set up PC 1 + pc_1 = Computer( + hostname="pc_1", + ip_address="192.168.1.11", + subnet_mask="255.255.255.0", + default_gateway="192.168.1.1", + start_up_duration=0 + ) + pc_1.power_on() + + # Set up PC 2 + pc_2 = Computer( + hostname="pc_2", + ip_address="192.168.1.12", + subnet_mask="255.255.255.0", + default_gateway="192.168.1.1", + start_up_duration=0 + ) + pc_2.power_on() + pc_2.software_manager.install(DatabaseService) + pc_2.software_manager.software["DatabaseService"].start() # start the postgres server + + # Set up PC 3 + pc_3 = Computer( + hostname="pc_3", + ip_address="192.168.1.13", + subnet_mask="255.255.255.0", + default_gateway="192.168.1.1", + start_up_duration=0 + ) + # Don't power on PC 3 + + # Set up the switch + switch = Switch(hostname="switch", start_up_duration=0) + switch.power_on() + + # Connect devices + network.connect(router.network_interface[1], switch.network_interface[24]) + network.connect(switch.network_interface[1], pc_1.network_interface[1]) + network.connect(switch.network_interface[2], pc_2.network_interface[1]) + network.connect(switch.network_interface[3], pc_3.network_interface[1]) + + + pc_1_nmap: NMAP = pc_1.software_manager.software["NMAP"] + + +Ping Scan +^^^^^^^^^ + +Perform a ping scan to find active hosts in the `192.168.1.0/24` subnet: + +.. code-block:: python + :caption: Ping Scan Code + + active_hosts = pc_1_nmap.ping_scan(target_ip_address=IPv4Network("192.168.1.0/24")) + +.. code-block:: python + :caption: Ping Scan Return Value + + [ + IPv4Address('192.168.1.11'), + IPv4Address('192.168.1.12'), + IPv4Address('192.168.1.1') + ] + +.. code-block:: text + :caption: Ping Scan Output + + +-------------------------+ + | pc_1 NMAP Ping Scan | + +--------------+----------+ + | IP Address | Can Ping | + +--------------+----------+ + | 192.168.1.1 | True | + | 192.168.1.11 | True | + | 192.168.1.12 | True | + +--------------+----------+ + +Horizontal Port Scan +^^^^^^^^^^^^^^^^^^^^ + +Perform a horizontal port scan on port 5432 across multiple IP addresses: + +.. code-block:: python + :caption: Horizontal Port Scan Code + + horizontal_scan_results = pc_1_nmap.port_scan( + target_ip_address=[IPv4Address("192.168.1.12"), IPv4Address("192.168.1.13")], + target_port=Port(5432 ) + ) + +.. code-block:: python + :caption: Horizontal Port Scan Return Value + + { + IPv4Address('192.168.1.12'): { + : [ + + ] + } + } + +.. code-block:: text + :caption: Horizontal Port Scan Output + + +--------------------------------------------------+ + | pc_1 NMAP Port Scan (Horizontal) | + +--------------+------+-----------------+----------+ + | IP Address | Port | Name | Protocol | + +--------------+------+-----------------+----------+ + | 192.168.1.12 | 5432 | POSTGRES_SERVER | TCP | + +--------------+------+-----------------+----------+ + +Vertical Post Scan +^^^^^^^^^^^^^^^^^^ + +Perform a vertical port scan on multiple ports on a single IP address: + +.. code-block:: python + :caption: Vertical Port Scan Code + + vertical_scan_results = pc_1_nmap.port_scan( + target_ip_address=[IPv4Address("192.168.1.12")], + target_port=[Port(21), Port(22), Port(80), Port(443)] + ) + +.. code-block:: python + :caption: Vertical Port Scan Return Value + + { + IPv4Address('192.168.1.12'): { + : [ + , + + ] + } + } + +.. code-block:: text + :caption: Vertical Port Scan Output + + +---------------------------------------+ + | pc_1 NMAP Port Scan (Vertical) | + +--------------+------+------+----------+ + | IP Address | Port | Name | Protocol | + +--------------+------+------+----------+ + | 192.168.1.12 | 21 | FTP | TCP | + | 192.168.1.12 | 80 | HTTP | TCP | + +--------------+------+------+----------+ + +Box Scan +^^^^^^^^ + +Perform a box scan on multiple ports across multiple IP addresses: + +.. code-block:: python + :caption: Box Port Scan Code + + # Power PC 3 on before performing the box scan + pc_3.power_on() + + + box_scan_results = pc_1_nmap.port_scan( + target_ip_address=[IPv4Address("192.168.1.12"), IPv4Address("192.168.1.13")], + target_port=[Port(21), Port(22), Port(80), Port(443)] + ) + +.. code-block:: python + :caption: Box Port Scan Return Value + + { + IPv4Address('192.168.1.13'): { + : [ + , + + ] + }, + IPv4Address('192.168.1.12'): { + : [ + , + + ] + } + } + +.. code-block:: text + :caption: Box Port Scan Output + + +---------------------------------------+ + | pc_1 NMAP Port Scan (Box) | + +--------------+------+------+----------+ + | IP Address | Port | Name | Protocol | + +--------------+------+------+----------+ + | 192.168.1.12 | 21 | FTP | TCP | + | 192.168.1.12 | 80 | HTTP | TCP | + | 192.168.1.13 | 21 | FTP | TCP | + | 192.168.1.13 | 80 | HTTP | TCP | + +--------------+------+------+----------+ + +Full Box Scan +^^^^^^^^^^^^^ + +Perform a full box scan on all ports, over both TCP and UDP, on a whole subnet: + +.. code-block:: python + :caption: Box Port Scan Code + + # Power PC 3 on before performing the full box scan + pc_3.power_on() + + + full_box_scan_results = pc_1_nmap.port_scan( + target_ip_address=IPv4Network("192.168.1.0/24"), + ) + +.. code-block:: python + :caption: Box Port Scan Return Value + + { + IPv4Address('192.168.1.11'): { + : [ + + ] + }, + IPv4Address('192.168.1.1'): { + : [ + + ] + }, + IPv4Address('192.168.1.12'): { + : [ + , + , + , + + ], + : [ + , + + ] + }, + IPv4Address('192.168.1.13'): { + : [ + , + , + + ], + : [ + , + + ] + } + } + +.. code-block:: text + :caption: Box Port Scan Output + + +--------------------------------------------------+ + | pc_1 NMAP Port Scan (Box) | + +--------------+------+-----------------+----------+ + | IP Address | Port | Name | Protocol | + +--------------+------+-----------------+----------+ + | 192.168.1.1 | 219 | ARP | UDP | + | 192.168.1.11 | 219 | ARP | UDP | + | 192.168.1.12 | 21 | FTP | TCP | + | 192.168.1.12 | 53 | DNS | TCP | + | 192.168.1.12 | 80 | HTTP | TCP | + | 192.168.1.12 | 123 | NTP | UDP | + | 192.168.1.12 | 219 | ARP | UDP | + | 192.168.1.12 | 5432 | POSTGRES_SERVER | TCP | + | 192.168.1.13 | 21 | FTP | TCP | + | 192.168.1.13 | 53 | DNS | TCP | + | 192.168.1.13 | 80 | HTTP | TCP | + | 192.168.1.13 | 123 | NTP | UDP | + | 192.168.1.13 | 219 | ARP | UDP | + +--------------+------+-----------------+----------+ diff --git a/docs/source/simulation_components/system/applications/web_browser.rst b/docs/source/simulation_components/system/applications/web_browser.rst index c46089ba..162463a0 100644 --- a/docs/source/simulation_components/system/applications/web_browser.rst +++ b/docs/source/simulation_components/system/applications/web_browser.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _WebBrowser: diff --git a/docs/source/simulation_components/system/common/common_configuration.rst b/docs/source/simulation_components/system/common/common_configuration.rst index 27625407..7a5b6ab5 100644 --- a/docs/source/simulation_components/system/common/common_configuration.rst +++ b/docs/source/simulation_components/system/common/common_configuration.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK ``ref`` ======= diff --git a/docs/source/simulation_components/system/common/db_payload_list.rst b/docs/source/simulation_components/system/common/db_payload_list.rst index f51227c6..0930f09d 100644 --- a/docs/source/simulation_components/system/common/db_payload_list.rst +++ b/docs/source/simulation_components/system/common/db_payload_list.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _Database Payload List: diff --git a/docs/source/simulation_components/system/internal_frame_processing.rst b/docs/source/simulation_components/system/internal_frame_processing.rst index 9c5356cc..65336f9b 100644 --- a/docs/source/simulation_components/system/internal_frame_processing.rst +++ b/docs/source/simulation_components/system/internal_frame_processing.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _internal_frame_processing: diff --git a/docs/source/simulation_components/system/list_of_applications.rst b/docs/source/simulation_components/system/list_of_applications.rst index 8f792e4c..a1d8bfd4 100644 --- a/docs/source/simulation_components/system/list_of_applications.rst +++ b/docs/source/simulation_components/system/list_of_applications.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. toctree:: :maxdepth: 1 diff --git a/docs/source/simulation_components/system/list_of_services.rst b/docs/source/simulation_components/system/list_of_services.rst index 9f1c9fe2..b6995647 100644 --- a/docs/source/simulation_components/system/list_of_services.rst +++ b/docs/source/simulation_components/system/list_of_services.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. toctree:: :maxdepth: 1 diff --git a/docs/source/simulation_components/system/list_of_system_applications.rst b/docs/source/simulation_components/system/list_of_system_applications.rst index 193b3dc6..c8807ef0 100644 --- a/docs/source/simulation_components/system/list_of_system_applications.rst +++ b/docs/source/simulation_components/system/list_of_system_applications.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK ``system applications`` """"""""""""""""""""""" diff --git a/docs/source/simulation_components/system/list_of_system_services.rst b/docs/source/simulation_components/system/list_of_system_services.rst index 5acfc12e..9b5c3265 100644 --- a/docs/source/simulation_components/system/list_of_system_services.rst +++ b/docs/source/simulation_components/system/list_of_system_services.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK ``system services`` """"""""""""""""""" diff --git a/docs/source/simulation_components/system/pcap.rst b/docs/source/simulation_components/system/pcap.rst index 7d7bff0f..830c28bd 100644 --- a/docs/source/simulation_components/system/pcap.rst +++ b/docs/source/simulation_components/system/pcap.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK PCAP ==== diff --git a/docs/source/simulation_components/system/services/database_service.rst b/docs/source/simulation_components/system/services/database_service.rst index dd6dec41..2f0452f0 100644 --- a/docs/source/simulation_components/system/services/database_service.rst +++ b/docs/source/simulation_components/system/services/database_service.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _DatabaseService: diff --git a/docs/source/simulation_components/system/services/dns_client.rst b/docs/source/simulation_components/system/services/dns_client.rst index 91461590..c0025114 100644 --- a/docs/source/simulation_components/system/services/dns_client.rst +++ b/docs/source/simulation_components/system/services/dns_client.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _DNSClient: diff --git a/docs/source/simulation_components/system/services/dns_server.rst b/docs/source/simulation_components/system/services/dns_server.rst index 89ce7fc1..b681f32f 100644 --- a/docs/source/simulation_components/system/services/dns_server.rst +++ b/docs/source/simulation_components/system/services/dns_server.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _DNSServer: diff --git a/docs/source/simulation_components/system/services/ftp_client.rst b/docs/source/simulation_components/system/services/ftp_client.rst index 259a626d..889a2c36 100644 --- a/docs/source/simulation_components/system/services/ftp_client.rst +++ b/docs/source/simulation_components/system/services/ftp_client.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _FTPClient: diff --git a/docs/source/simulation_components/system/services/ftp_server.rst b/docs/source/simulation_components/system/services/ftp_server.rst index fb57a762..9b26157d 100644 --- a/docs/source/simulation_components/system/services/ftp_server.rst +++ b/docs/source/simulation_components/system/services/ftp_server.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _FTPServer: diff --git a/docs/source/simulation_components/system/services/ntp_client.rst b/docs/source/simulation_components/system/services/ntp_client.rst index aaba3261..6faad108 100644 --- a/docs/source/simulation_components/system/services/ntp_client.rst +++ b/docs/source/simulation_components/system/services/ntp_client.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _NTPClient: diff --git a/docs/source/simulation_components/system/services/ntp_server.rst b/docs/source/simulation_components/system/services/ntp_server.rst index 0025b428..0369cd15 100644 --- a/docs/source/simulation_components/system/services/ntp_server.rst +++ b/docs/source/simulation_components/system/services/ntp_server.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _NTPServer: diff --git a/docs/source/simulation_components/system/services/web_server.rst b/docs/source/simulation_components/system/services/web_server.rst index 62b1d090..5b205f5e 100644 --- a/docs/source/simulation_components/system/services/web_server.rst +++ b/docs/source/simulation_components/system/services/web_server.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK .. _WebServer: diff --git a/docs/source/simulation_components/system/session_and_software_manager.rst b/docs/source/simulation_components/system/session_and_software_manager.rst index 8af96e87..230f6687 100644 --- a/docs/source/simulation_components/system/session_and_software_manager.rst +++ b/docs/source/simulation_components/system/session_and_software_manager.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK Session and Software Manager ============================ diff --git a/docs/source/simulation_components/system/software.rst b/docs/source/simulation_components/system/software.rst index 2ba8e841..3acfb9b4 100644 --- a/docs/source/simulation_components/system/software.rst +++ b/docs/source/simulation_components/system/software.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK Software diff --git a/docs/source/simulation_components/system/sys_log.rst b/docs/source/simulation_components/system/sys_log.rst index a638060c..cdf19faa 100644 --- a/docs/source/simulation_components/system/sys_log.rst +++ b/docs/source/simulation_components/system/sys_log.rst @@ -1,6 +1,6 @@ .. only:: comment - © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK SysLog ====== diff --git a/pyproject.toml b/pyproject.toml index 290720bc..31ce5312 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,17 +7,15 @@ name = "primaite" description = "PrimAITE (Primary-level AI Training Environment) is a simulation environment for training AI under the ARCD programme." authors = [{name="Defence Science and Technology Laboratory UK", email="oss@dstl.gov.uk"}] license = {file = "LICENSE"} -requires-python = ">=3.8, <3.12" +requires-python = ">=3.9, <3.12" dynamic = ["version", "readme"] classifiers = [ - "License :: OSI Approved :: MIT License", "Development Status :: 5 - Production/Stable", "Operating System :: Microsoft :: Windows", "Operating System :: MacOS", "Operating System :: POSIX :: Linux", "Operating System :: Unix", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -91,7 +89,7 @@ order_by_type = "False" line-length = 120 [project.urls] -Homepage = "https://github.com/Autonomous-Resilient-Cyber-Defence/PrimAITE" -Documentation = "https://Autonomous-Resilient-Cyber-Defence.github.io/PrimAITE/" -Repository = "https://github.com/Autonomous-Resilient-Cyber-Defence/PrimAITE" -Changelog = "https://github.com/Autonomous-Resilient-Cyber-Defence/PrimAITE/blob/dev/CHANGELOG.md" +Homepage = "https://github.com/{todo:fill in URL}/PrimAITE" +Documentation = "https://{todo:fill in URL}.github.io/PrimAITE" +Repository = "https://github.com/{todo:fill in URL}/PrimAITE" +Changelog = "https://github.com/{todo:fill in URL}/PrimAITE/blob/main/CHANGELOG.md" diff --git a/setup.cfg b/setup.cfg index e46aafd6..9c0cb0e6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,4 +1,4 @@ [metadata] -url = https://github.com/Autonomous-Resilient-Cyber-Defence/PrimAITE +url = https://github.com/{todo:fill in URL}/PrimAITE author = Defence Science and Technology Laboratory UK author_email = oss@dstl.gov.uk diff --git a/src/primaite/VERSION b/src/primaite/VERSION index 4a36342f..fd2a0186 100644 --- a/src/primaite/VERSION +++ b/src/primaite/VERSION @@ -1 +1 @@ -3.0.0 +3.1.0 diff --git a/src/primaite/__init__.py b/src/primaite/__init__.py index 98612040..8dd84428 100644 --- a/src/primaite/__init__.py +++ b/src/primaite/__init__.py @@ -1,4 +1,4 @@ -# © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import datetime as datetime import logging import logging.config @@ -203,3 +203,6 @@ def getLogger(name: str) -> Logger: # noqa logger.setLevel(PRIMAITE_CONFIG["logging"]["log_level"]) return logger + + +DEFAULT_BANDWIDTH: Final[int] = 100 diff --git a/src/primaite/cli.py b/src/primaite/cli.py index e2e5f8f6..4fbbdec9 100644 --- a/src/primaite/cli.py +++ b/src/primaite/cli.py @@ -1,4 +1,4 @@ -# © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK """Provides a CLI using Typer as an entry point.""" import logging import os diff --git a/src/primaite/config/__init__.py b/src/primaite/config/__init__.py index 92f5a7d2..c2ae1b5b 100644 --- a/src/primaite/config/__init__.py +++ b/src/primaite/config/__init__.py @@ -1,2 +1,2 @@ -# © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK """Configuration parameters for running experiments.""" diff --git a/src/primaite/config/_package_data/data_manipulation.yaml b/src/primaite/config/_package_data/data_manipulation.yaml index e3d68706..1ff24abe 100644 --- a/src/primaite/config/_package_data/data_manipulation.yaml +++ b/src/primaite/config/_package_data/data_manipulation.yaml @@ -188,6 +188,11 @@ agents: num_nics: 2 include_num_access: false include_nmne: true + monitored_traffic: + icmp: + - NONE + tcp: + - DNS routers: - hostname: router_1 num_ports: 0 @@ -471,7 +476,7 @@ agents: 46: # old action num: 22 # "ACL: ADDRULE - Block outgoing traffic from client 1" action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -484,7 +489,7 @@ agents: 47: # old action num: 23 # "ACL: ADDRULE - Block outgoing traffic from client 2" action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -497,7 +502,7 @@ agents: 48: # old action num: 24 # block tcp traffic from client 1 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -510,7 +515,7 @@ agents: 49: # old action num: 25 # block tcp traffic from client 2 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -523,7 +528,7 @@ agents: 50: # old action num: 26 action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -536,7 +541,7 @@ agents: 51: # old action num: 27 action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -549,52 +554,52 @@ agents: 52: # old action num: 28 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 0 53: # old action num: 29 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 54: # old action num: 30 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 55: # old action num: 31 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 56: # old action num: 32 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 57: # old action num: 33 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 58: # old action num: 34 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 59: # old action num: 35 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 7 60: # old action num: 36 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 8 61: # old action num: 37 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 9 62: # old action num: 38 action: "HOST_NIC_DISABLE" diff --git a/src/primaite/config/_package_data/data_manipulation_marl.yaml b/src/primaite/config/_package_data/data_manipulation_marl.yaml index 45779036..2e8221a0 100644 --- a/src/primaite/config/_package_data/data_manipulation_marl.yaml +++ b/src/primaite/config/_package_data/data_manipulation_marl.yaml @@ -470,7 +470,7 @@ agents: 46: # old action num: 22 # "ACL: ADDRULE - Block outgoing traffic from client 1" action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -483,7 +483,7 @@ agents: 47: # old action num: 23 # "ACL: ADDRULE - Block outgoing traffic from client 2" action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -496,7 +496,7 @@ agents: 48: # old action num: 24 # block tcp traffic from client 1 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -509,7 +509,7 @@ agents: 49: # old action num: 25 # block tcp traffic from client 2 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -522,7 +522,7 @@ agents: 50: # old action num: 26 action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -535,7 +535,7 @@ agents: 51: # old action num: 27 action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -548,52 +548,52 @@ agents: 52: # old action num: 28 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 0 53: # old action num: 29 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 54: # old action num: 30 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 55: # old action num: 31 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 56: # old action num: 32 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 57: # old action num: 33 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 58: # old action num: 34 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 59: # old action num: 35 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 7 60: # old action num: 36 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 8 61: # old action num: 37 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 9 62: # old action num: 38 action: "HOST_NIC_DISABLE" @@ -834,10 +834,10 @@ agents: - type: NODE_RESET - type: ROUTER_ACL_ADDRULE options: - target_router_nodename: router_1 + target_router: router_1 - type: ROUTER_ACL_REMOVERULE options: - target_router_nodename: router_1 + target_router: router_1 - type: HOST_NIC_ENABLE - type: HOST_NIC_DISABLE @@ -1053,7 +1053,7 @@ agents: 46: # old action num: 22 # "ACL: ADDRULE - Block outgoing traffic from client 1" action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -1066,7 +1066,7 @@ agents: 47: # old action num: 23 # "ACL: ADDRULE - Block outgoing traffic from client 2" action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -1079,7 +1079,7 @@ agents: 48: # old action num: 24 # block tcp traffic from client 1 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -1092,7 +1092,7 @@ agents: 49: # old action num: 25 # block tcp traffic from client 2 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -1105,7 +1105,7 @@ agents: 50: # old action num: 26 action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -1118,7 +1118,7 @@ agents: 51: # old action num: 27 action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -1131,52 +1131,52 @@ agents: 52: # old action num: 28 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 0 53: # old action num: 29 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 54: # old action num: 30 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 55: # old action num: 31 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 56: # old action num: 32 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 57: # old action num: 33 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 58: # old action num: 34 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 59: # old action num: 35 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 7 60: # old action num: 36 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 8 61: # old action num: 37 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 9 62: # old action num: 38 action: "HOST_NIC_DISABLE" diff --git a/src/primaite/config/_package_data/mini_scenario_with_simulation_variation/base_scenario.yaml b/src/primaite/config/_package_data/mini_scenario_with_simulation_variation/base_scenario.yaml new file mode 100644 index 00000000..b4457a28 --- /dev/null +++ b/src/primaite/config/_package_data/mini_scenario_with_simulation_variation/base_scenario.yaml @@ -0,0 +1,86 @@ +game: + max_episode_length: 128 + ports: [] + protocols: [] + +agents: + - ref: RL_Agent + type: ProxyAgent + observation_space: null + action_space: + action_list: + - type: DONOTHING + - type: NODE_SHUTDOWN + - type: NODE_STARTUP + - type: HOST_NIC_ENABLE + - type: HOST_NIC_DISABLE + action_map: + 0: + action: DONOTHING + options: {} + 1: + action: NODE_SHUTDOWN + options: + node_id: 0 + 2: + action: NODE_SHUTDOWN + options: + node_id: 1 + 3: + action: NODE_STARTUP + options: + node_id: 0 + 4: + action: NODE_STARTUP + options: + node_id: 1 + 5: + action: HOST_NIC_DISABLE + options: + node_id: 0 + nic_id: 0 + 6: + action: HOST_NIC_DISABLE + options: + node_id: 1 + nic_id: 0 + 7: + action: HOST_NIC_ENABLE + options: + node_id: 0 + nic_id: 0 + 8: + action: HOST_NIC_ENABLE + options: + node_id: 1 + nic_id: 0 + options: + nodes: + - node_name: client_1 + - node_name: server + max_folders_per_node: 0 + max_files_per_folder: 0 + max_services_per_node: 0 + max_nics_per_node: 1 + max_acl_rules: 0 + ip_list: + - 192.168.1.2 + - 192.168.1.3 + reward_function: + reward_components: [] + +simulation: + network: + nodes: + - hostname: server + type: server + ip_address: 192.168.1.2 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.1.1 + services: *server_services + - hostname: client_1 + type: computer + ip_address: 192.168.1.3 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.1.1 + applications: *client_applications diff --git a/src/primaite/config/_package_data/mini_scenario_with_simulation_variation/schedule.yaml b/src/primaite/config/_package_data/mini_scenario_with_simulation_variation/schedule.yaml new file mode 100644 index 00000000..59da7646 --- /dev/null +++ b/src/primaite/config/_package_data/mini_scenario_with_simulation_variation/schedule.yaml @@ -0,0 +1,6 @@ +base_scenario: base_scenario.yaml +schedule: + 0: + - simulation_variant_1.yaml + 1: + - simulation_variant_2.yaml diff --git a/src/primaite/config/_package_data/mini_scenario_with_simulation_variation/simulation_variant_1.yaml b/src/primaite/config/_package_data/mini_scenario_with_simulation_variation/simulation_variant_1.yaml new file mode 100644 index 00000000..3e27cc27 --- /dev/null +++ b/src/primaite/config/_package_data/mini_scenario_with_simulation_variation/simulation_variant_1.yaml @@ -0,0 +1,5 @@ +server_services: &server_services + - type: DatabaseService + +client_applications: &client_applications + - type: DatabaseClient diff --git a/src/primaite/config/_package_data/mini_scenario_with_simulation_variation/simulation_variant_2.yaml b/src/primaite/config/_package_data/mini_scenario_with_simulation_variation/simulation_variant_2.yaml new file mode 100644 index 00000000..207e0c73 --- /dev/null +++ b/src/primaite/config/_package_data/mini_scenario_with_simulation_variation/simulation_variant_2.yaml @@ -0,0 +1,5 @@ +server_services: &server_services + - type: FTPServer + +client_applications: &client_applications + - type: RansomwareScript diff --git a/src/primaite/config/load.py b/src/primaite/config/load.py index d5acd690..3483fc87 100644 --- a/src/primaite/config/load.py +++ b/src/primaite/config/load.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from pathlib import Path from typing import Dict, Final, Union diff --git a/src/primaite/exceptions.py b/src/primaite/exceptions.py index ad9e6e5b..afc55271 100644 --- a/src/primaite/exceptions.py +++ b/src/primaite/exceptions.py @@ -1,4 +1,4 @@ -# © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK class PrimaiteError(Exception): """The root PrimAITE Error.""" diff --git a/src/primaite/game/__init__.py b/src/primaite/game/__init__.py index 5d7a721f..39034e92 100644 --- a/src/primaite/game/__init__.py +++ b/src/primaite/game/__init__.py @@ -1 +1,2 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK """PrimAITE Game Layer.""" diff --git a/src/primaite/game/agent/__init__.py b/src/primaite/game/agent/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/game/agent/__init__.py +++ b/src/primaite/game/agent/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/game/agent/actions.py b/src/primaite/game/agent/actions.py index 7707df2b..e165c9ad 100644 --- a/src/primaite/game/agent/actions.py +++ b/src/primaite/game/agent/actions.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK """ This module contains the ActionManager class which belongs to the Agent class. @@ -10,9 +11,10 @@ AbstractAction. The ActionManager is responsible for: """ import itertools from abc import ABC, abstractmethod -from typing import Dict, List, Optional, Tuple, TYPE_CHECKING +from typing import Dict, List, Literal, Optional, Tuple, TYPE_CHECKING, Union from gymnasium import spaces +from pydantic import BaseModel, Field, field_validator, ValidationInfo from primaite import getLogger @@ -320,12 +322,12 @@ class NodeFileCreateAction(AbstractAction): super().__init__(manager, num_nodes=num_nodes, num_folders=num_folders, **kwargs) self.verb: str = "create" - def form_request(self, node_id: int, folder_name: str, file_name: str) -> List[str]: + def form_request(self, node_id: int, folder_name: str, file_name: str, force: Optional[bool] = False) -> List[str]: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" node_name = self.manager.get_node_name_by_idx(node_id) if node_name is None or folder_name is None or file_name is None: return ["do_nothing"] - return ["network", "node", node_name, "file_system", "create", "file", folder_name, file_name] + return ["network", "node", node_name, "file_system", "create", "file", folder_name, file_name, force] class NodeFolderCreateAction(AbstractAction): @@ -492,6 +494,47 @@ class NodeResetAction(NodeAbstractAction): class RouterACLAddRuleAction(AbstractAction): """Action which adds a rule to a router's ACL.""" + class ACLRuleOptions(BaseModel): + """Validator for ACL_ADD_RULE options.""" + + target_router: str + """On which router to add the rule, must be specified.""" + position: int + """At what position to add the rule, must be specified.""" + permission: Literal[1, 2] + """Whether to allow or deny traffic, must be specified. 1 = PERMIT, 2 = DENY.""" + source_ip_id: int = Field(default=1, ge=1) + """Rule source IP address. By default, all ip addresses.""" + source_wildcard_id: int = Field(default=0, ge=0) + """Rule source IP wildcard. By default, use the wildcard at index 0 from action manager.""" + source_port_id: int = Field(default=1, ge=1) + """Rule source port. By default, all source ports.""" + dest_ip_id: int = Field(default=1, ge=1) + """Rule destination IP address. By default, all ip addresses.""" + dest_wildcard_id: int = Field(default=0, ge=0) + """Rule destination IP wildcard. By default, use the wildcard at index 0 from action manager.""" + dest_port_id: int = Field(default=1, ge=1) + """Rule destination port. By default, all destination ports.""" + protocol_id: int = Field(default=1, ge=1) + """Rule protocol. By default, all protocols.""" + + @field_validator( + "source_ip_id", + "source_port_id", + "source_wildcard_id", + "dest_ip_id", + "dest_port_id", + "dest_wildcard_id", + "protocol_id", + mode="before", + ) + @classmethod + def not_none(cls, v: str, info: ValidationInfo) -> int: + """If None is passed, use the default value instead.""" + if v is None: + return cls.model_fields[info.field_name].default + return v + def __init__( self, manager: "ActionManager", @@ -528,7 +571,7 @@ class RouterACLAddRuleAction(AbstractAction): def form_request( self, - target_router_nodename: str, + target_router: str, position: int, permission: int, source_ip_id: int, @@ -540,62 +583,63 @@ class RouterACLAddRuleAction(AbstractAction): protocol_id: int, ) -> List[str]: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" - if permission == 0: - permission_str = "UNUSED" - return ["do_nothing"] # NOT SUPPORTED, JUST DO NOTHING IF WE COME ACROSS THIS - elif permission == 1: + # Validate incoming data. + parsed_options = RouterACLAddRuleAction.ACLRuleOptions( + target_router=target_router, + position=position, + permission=permission, + source_ip_id=source_ip_id, + source_wildcard_id=source_wildcard_id, + dest_ip_id=dest_ip_id, + dest_wildcard_id=dest_wildcard_id, + source_port_id=source_port_id, + dest_port_id=dest_port_id, + protocol_id=protocol_id, + ) + if parsed_options.permission == 1: permission_str = "PERMIT" - elif permission == 2: + elif parsed_options.permission == 2: permission_str = "DENY" else: _LOGGER.warning(f"{self.__class__} received permission {permission}, expected 0 or 1.") - if protocol_id == 0: - return ["do_nothing"] # NOT SUPPORTED, JUST DO NOTHING IF WE COME ACROSS THIS - - if protocol_id == 1: + if parsed_options.protocol_id == 1: protocol = "ALL" else: - protocol = self.manager.get_internet_protocol_by_idx(protocol_id - 2) + protocol = self.manager.get_internet_protocol_by_idx(parsed_options.protocol_id - 2) # subtract 2 to account for UNUSED=0 and ALL=1. - if source_ip_id == 0: - return ["do_nothing"] # invalid formulation - elif source_ip_id == 1: + if parsed_options.source_ip_id == 1: src_ip = "ALL" else: - src_ip = self.manager.get_ip_address_by_idx(source_ip_id - 2) + src_ip = self.manager.get_ip_address_by_idx(parsed_options.source_ip_id - 2) # subtract 2 to account for UNUSED=0, and ALL=1 - src_wildcard = self.manager.get_wildcard_by_idx(source_wildcard_id) - if source_port_id == 0: - return ["do_nothing"] # invalid formulation - elif source_port_id == 1: + + src_wildcard = self.manager.get_wildcard_by_idx(parsed_options.source_wildcard_id) + + if parsed_options.source_port_id == 1: src_port = "ALL" else: - src_port = self.manager.get_port_by_idx(source_port_id - 2) + src_port = self.manager.get_port_by_idx(parsed_options.source_port_id - 2) # subtract 2 to account for UNUSED=0, and ALL=1 - if dest_ip_id == 0: - return ["do_nothing"] # invalid formulation - elif dest_ip_id == 1: + if parsed_options.dest_ip_id == 1: dst_ip = "ALL" else: - dst_ip = self.manager.get_ip_address_by_idx(dest_ip_id - 2) + dst_ip = self.manager.get_ip_address_by_idx(parsed_options.dest_ip_id - 2) # subtract 2 to account for UNUSED=0, and ALL=1 - dst_wildcard = self.manager.get_wildcard_by_idx(dest_wildcard_id) + dst_wildcard = self.manager.get_wildcard_by_idx(parsed_options.dest_wildcard_id) - if dest_port_id == 0: - return ["do_nothing"] # invalid formulation - elif dest_port_id == 1: + if parsed_options.dest_port_id == 1: dst_port = "ALL" else: - dst_port = self.manager.get_port_by_idx(dest_port_id - 2) + dst_port = self.manager.get_port_by_idx(parsed_options.dest_port_id - 2) # subtract 2 to account for UNUSED=0, and ALL=1 return [ "network", "node", - target_router_nodename, + target_router, "acl", "add_rule", permission_str, @@ -624,9 +668,9 @@ class RouterACLRemoveRuleAction(AbstractAction): super().__init__(manager=manager) self.shape: Dict[str, int] = {"position": max_acl_rules} - def form_request(self, target_router_nodename: str, position: int) -> List[str]: + def form_request(self, target_router: str, position: int) -> List[str]: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" - return ["network", "node", target_router_nodename, "acl", "remove_rule", position] + return ["network", "node", target_router, "acl", "remove_rule", position] class FirewallACLAddRuleAction(AbstractAction): @@ -870,6 +914,89 @@ class NetworkPortDisableAction(AbstractAction): return ["network", "node", target_nodename, "network_interface", port_id, "disable"] +class NodeNMAPPingScanAction(AbstractAction): + """Action which performs an NMAP ping scan.""" + + def __init__(self, manager: "ActionManager", **kwargs) -> None: + super().__init__(manager=manager) + + def form_request( + self, source_node: str, target_ip_address: Union[str, List[str]], show: Optional[bool] = False + ) -> List[str]: # noqa + """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" + return [ + "network", + "node", + source_node, + "application", + "NMAP", + "ping_scan", + {"target_ip_address": target_ip_address, "show": show}, + ] + + +class NodeNMAPPortScanAction(AbstractAction): + """Action which performs an NMAP port scan.""" + + def __init__(self, manager: "ActionManager", **kwargs) -> None: + super().__init__(manager=manager) + + def form_request( + self, + source_node: str, + target_ip_address: Union[str, List[str]], + target_protocol: Optional[Union[str, List[str]]] = None, + target_port: Optional[Union[str, List[str]]] = None, + show: Optional[bool] = False, + ) -> List[str]: # noqa + """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" + return [ + "network", + "node", + source_node, + "application", + "NMAP", + "port_scan", + { + "target_ip_address": target_ip_address, + "target_port": target_port, + "target_protocol": target_protocol, + "show": show, + }, + ] + + +class NodeNetworkServiceReconAction(AbstractAction): + """Action which performs an NMAP network service recon (ping scan followed by port scan).""" + + def __init__(self, manager: "ActionManager", **kwargs) -> None: + super().__init__(manager=manager) + + def form_request( + self, + source_node: str, + target_ip_address: Union[str, List[str]], + target_protocol: Optional[Union[str, List[str]]] = None, + target_port: Optional[Union[str, List[str]]] = None, + show: Optional[bool] = False, + ) -> List[str]: # noqa + """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" + return [ + "network", + "node", + source_node, + "application", + "NMAP", + "network_service_recon", + { + "target_ip_address": target_ip_address, + "target_port": target_port, + "target_protocol": target_protocol, + "show": show, + }, + ] + + class ActionManager: """Class which manages the action space for an agent.""" @@ -915,6 +1042,9 @@ class ActionManager: "HOST_NIC_DISABLE": HostNICDisableAction, "NETWORK_PORT_ENABLE": NetworkPortEnableAction, "NETWORK_PORT_DISABLE": NetworkPortDisableAction, + "NODE_NMAP_PING_SCAN": NodeNMAPPingScanAction, + "NODE_NMAP_PORT_SCAN": NodeNMAPPortScanAction, + "NODE_NMAP_NETWORK_SERVICE_RECON": NodeNetworkServiceReconAction, } """Dictionary which maps action type strings to the corresponding action class.""" diff --git a/src/primaite/game/agent/interface.py b/src/primaite/game/agent/interface.py index 444aa4f7..95468331 100644 --- a/src/primaite/game/agent/interface.py +++ b/src/primaite/game/agent/interface.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK """Interface for agents.""" from abc import ABC, abstractmethod from typing import Any, Dict, List, Optional, Tuple, TYPE_CHECKING @@ -106,6 +107,8 @@ class AbstractAgent(ABC): :type observation_space: Optional[ObservationSpace] :param reward_function: Reward function for the agent. :type reward_function: Optional[RewardFunction] + :param agent_settings: Configurable Options for Abstracted Agents + :type agent_settings: Optional[AgentSettings] """ self.agent_name: str = agent_name or "unnamed_agent" self.action_manager: Optional[ActionManager] = action_space diff --git a/src/primaite/game/agent/observations/__init__.py b/src/primaite/game/agent/observations/__init__.py index 15fdf7ed..6c88f844 100644 --- a/src/primaite/game/agent/observations/__init__.py +++ b/src/primaite/game/agent/observations/__init__.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK # flake8: noqa # Pre-import all the observations when we load up the observations module so that they can be resolved by the parser. from primaite.game.agent.observations.acl_observation import ACLObservation diff --git a/src/primaite/game/agent/observations/acl_observation.py b/src/primaite/game/agent/observations/acl_observation.py index 934d688e..41af5a8f 100644 --- a/src/primaite/game/agent/observations/acl_observation.py +++ b/src/primaite/game/agent/observations/acl_observation.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations from ipaddress import IPv4Address diff --git a/src/primaite/game/agent/observations/file_system_observations.py b/src/primaite/game/agent/observations/file_system_observations.py index baf27660..cb48fe7d 100644 --- a/src/primaite/game/agent/observations/file_system_observations.py +++ b/src/primaite/game/agent/observations/file_system_observations.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations from typing import Dict, Iterable, List, Optional diff --git a/src/primaite/game/agent/observations/firewall_observation.py b/src/primaite/game/agent/observations/firewall_observation.py index 97a8f814..4f1a9d90 100644 --- a/src/primaite/game/agent/observations/firewall_observation.py +++ b/src/primaite/game/agent/observations/firewall_observation.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations from typing import Dict, List, Optional diff --git a/src/primaite/game/agent/observations/host_observations.py b/src/primaite/game/agent/observations/host_observations.py index 02c0d17f..f9fd9b1a 100644 --- a/src/primaite/game/agent/observations/host_observations.py +++ b/src/primaite/game/agent/observations/host_observations.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations from typing import Dict, List, Optional @@ -43,6 +44,8 @@ class HostObservation(AbstractObservation, identifier="HOST"): """Number of spaces for network interface observations on this host.""" include_nmne: Optional[bool] = None """Whether network interface observations should include number of malicious network events.""" + monitored_traffic: Optional[Dict] = None + """A dict containing which traffic types are to be included in the observation.""" include_num_access: Optional[bool] = None """Whether to include the number of accesses to files observations on this host.""" @@ -59,6 +62,7 @@ class HostObservation(AbstractObservation, identifier="HOST"): num_files: int, num_nics: int, include_nmne: bool, + monitored_traffic: Optional[Dict], include_num_access: bool, ) -> None: """ @@ -87,6 +91,8 @@ class HostObservation(AbstractObservation, identifier="HOST"): :type num_nics: int :param include_nmne: Flag to include network metrics and errors. :type include_nmne: bool + :param monitored_traffic: Dict which contains the protocol and ports to observe + :type monitored_traffic: Dict :param include_num_access: Flag to include the number of accesses to files. :type include_num_access: bool """ @@ -123,7 +129,7 @@ class HostObservation(AbstractObservation, identifier="HOST"): self.nics: List[NICObservation] = network_interfaces while len(self.nics) < num_nics: - self.nics.append(NICObservation(where=None, include_nmne=include_nmne)) + self.nics.append(NICObservation(where=None, include_nmne=include_nmne, monitored_traffic=monitored_traffic)) while len(self.nics) > num_nics: truncated_nic = self.nics.pop() msg = f"Too many network_interfaces in Node observation space for node. Truncating {truncated_nic.where}" @@ -231,7 +237,9 @@ class HostObservation(AbstractObservation, identifier="HOST"): # monitor the first N interfaces. Network interface numbering starts at 1. count = 1 while len(nics) < config.num_nics: - nic_config = NICObservation.ConfigSchema(nic_num=count, include_nmne=config.include_nmne) + nic_config = NICObservation.ConfigSchema( + nic_num=count, include_nmne=config.include_nmne, monitored_traffic=config.monitored_traffic + ) nics.append(NICObservation.from_config(config=nic_config, parent_where=where)) count += 1 @@ -247,5 +255,6 @@ class HostObservation(AbstractObservation, identifier="HOST"): num_files=config.num_files, num_nics=config.num_nics, include_nmne=config.include_nmne, + monitored_traffic=config.monitored_traffic, include_num_access=config.include_num_access, ) diff --git a/src/primaite/game/agent/observations/link_observation.py b/src/primaite/game/agent/observations/link_observation.py index 50dc1105..9af39a22 100644 --- a/src/primaite/game/agent/observations/link_observation.py +++ b/src/primaite/game/agent/observations/link_observation.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations from typing import Any, Dict, List diff --git a/src/primaite/game/agent/observations/nic_observations.py b/src/primaite/game/agent/observations/nic_observations.py index afce9095..002ee4da 100644 --- a/src/primaite/game/agent/observations/nic_observations.py +++ b/src/primaite/game/agent/observations/nic_observations.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations from typing import Dict, Optional @@ -7,6 +8,7 @@ from gymnasium.core import ObsType from primaite.game.agent.observations.observations import AbstractObservation, WhereType from primaite.game.agent.utils import access_from_nested_dict, NOT_PRESENT_IN_STATE +from primaite.simulator.network.transmission.transport_layer import Port class NICObservation(AbstractObservation, identifier="NETWORK_INTERFACE"): @@ -19,12 +21,10 @@ class NICObservation(AbstractObservation, identifier="NETWORK_INTERFACE"): """Number of the network interface.""" include_nmne: Optional[bool] = None """Whether to include number of malicious network events (NMNE) in the observation.""" + monitored_traffic: Optional[Dict] = None + """A dict containing which traffic types are to be included in the observation.""" - def __init__( - self, - where: WhereType, - include_nmne: bool, - ) -> None: + def __init__(self, where: WhereType, include_nmne: bool, monitored_traffic: Optional[Dict] = None) -> None: """ Initialise a network interface observation instance. @@ -49,6 +49,28 @@ class NICObservation(AbstractObservation, identifier="NETWORK_INTERFACE"): self.med_nmne_threshold = 5 self.low_nmne_threshold = 0 + self.monitored_traffic = monitored_traffic + if self.monitored_traffic: + self.default_observation.update( + self._default_monitored_traffic_observation(monitored_traffic_config=monitored_traffic) + ) + + def _default_monitored_traffic_observation(self, monitored_traffic_config: Dict) -> Dict: + default_traffic_obs = {"TRAFFIC": {}} + + for protocol in monitored_traffic_config: + protocol = str(protocol).lower() + default_traffic_obs["TRAFFIC"][protocol] = {} + + if protocol == "icmp": + default_traffic_obs["TRAFFIC"]["icmp"] = {"inbound": 0, "outbound": 0} + else: + default_traffic_obs["TRAFFIC"][protocol] = {} + for port in monitored_traffic_config[protocol]: + default_traffic_obs["TRAFFIC"][protocol][Port[port].value] = {"inbound": 0, "outbound": 0} + + return default_traffic_obs + def _categorise_mne_count(self, nmne_count: int) -> int: """ Categorise the number of Malicious Network Events (NMNEs) into discrete bins. @@ -72,6 +94,16 @@ class NICObservation(AbstractObservation, identifier="NETWORK_INTERFACE"): return 1 return 0 + def _categorise_traffic(self, traffic_value: float, nic_state: Dict) -> int: + """Categorise the traffic into discrete categories.""" + if traffic_value == 0: + return 0 + + nic_max_bandwidth = nic_state.get("speed") + + bandwidth_utilisation = traffic_value / nic_max_bandwidth + return int(bandwidth_utilisation * 9) + 1 + def observe(self, state: Dict) -> ObsType: """ Generate observation based on the current state of the simulation. @@ -87,6 +119,51 @@ class NICObservation(AbstractObservation, identifier="NETWORK_INTERFACE"): return self.default_observation obs = {"nic_status": 1 if nic_state["enabled"] else 2} + + # if the observation was configured to monitor traffic from ports/protocols + if self.monitored_traffic: + obs["TRAFFIC"] = {} + + # iterate through the protocols + for protocol in self.monitored_traffic: + protocol = str(protocol).lower() + obs["TRAFFIC"][protocol] = {} + # check if the nic has seen traffic with this protocol + if nic_state["traffic"].get(protocol): + # deal with icmp + if protocol == "icmp": + obs["TRAFFIC"][protocol] = { + "inbound": self._categorise_traffic( + traffic_value=nic_state["traffic"]["icmp"]["inbound"], nic_state=nic_state + ), + "outbound": self._categorise_traffic( + traffic_value=nic_state["traffic"]["icmp"]["outbound"], nic_state=nic_state + ), + } + else: + for port in self.monitored_traffic[protocol]: + port_enum = Port[port] + obs["TRAFFIC"][protocol][port_enum.value] = {} + traffic = {"inbound": 0, "outbound": 0} + + if nic_state["traffic"][protocol].get(port_enum.value) is not None: + traffic = nic_state["traffic"][protocol][port_enum.value] + + obs["TRAFFIC"][protocol][port_enum.value]["inbound"] = self._categorise_traffic( + traffic_value=traffic["inbound"], nic_state=nic_state + ) + obs["TRAFFIC"][protocol][port_enum.value]["outbound"] = self._categorise_traffic( + traffic_value=traffic["outbound"], nic_state=nic_state + ) + + # set all the ports under the protocol to 0 + else: + if protocol == "icmp": + obs["TRAFFIC"]["icmp"] = {"inbound": 0, "outbound": 0} + else: + for port in self.monitored_traffic[protocol]: + obs["TRAFFIC"][protocol][Port[port].value] = {"inbound": 0, "outbound": 0} + if self.include_nmne: obs.update({"NMNE": {}}) direction_dict = nic_state["nmne"].get("direction", {}) @@ -113,6 +190,21 @@ class NICObservation(AbstractObservation, identifier="NETWORK_INTERFACE"): if self.include_nmne: space["NMNE"] = spaces.Dict({"inbound": spaces.Discrete(4), "outbound": spaces.Discrete(4)}) + if self.monitored_traffic: + space["TRAFFIC"] = spaces.Dict({}) + for protocol in self.monitored_traffic: + protocol = str(protocol).lower() + if protocol == "icmp": + space["TRAFFIC"]["icmp"] = spaces.Dict( + {"inbound": spaces.Discrete(11), "outbound": spaces.Discrete(11)} + ) + else: + space["TRAFFIC"][protocol] = spaces.Dict({}) + for port in self.monitored_traffic[protocol]: + space["TRAFFIC"][protocol][Port[port].value] = spaces.Dict( + {"inbound": spaces.Discrete(11), "outbound": spaces.Discrete(11)} + ) + return space @classmethod @@ -128,7 +220,11 @@ class NICObservation(AbstractObservation, identifier="NETWORK_INTERFACE"): :return: Constructed network interface observation instance. :rtype: NICObservation """ - return cls(where=parent_where + ["NICs", config.nic_num], include_nmne=config.include_nmne) + return cls( + where=parent_where + ["NICs", config.nic_num], + include_nmne=config.include_nmne, + monitored_traffic=config.monitored_traffic, + ) class PortObservation(AbstractObservation, identifier="PORT"): diff --git a/src/primaite/game/agent/observations/node_observations.py b/src/primaite/game/agent/observations/node_observations.py index 8f7ac0fc..f7bfcc99 100644 --- a/src/primaite/game/agent/observations/node_observations.py +++ b/src/primaite/game/agent/observations/node_observations.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations from typing import Dict, List, Optional @@ -39,6 +40,8 @@ class NodesObservation(AbstractObservation, identifier="NODES"): """Number of network interface cards (NICs).""" include_nmne: Optional[bool] = None """Flag to include nmne.""" + monitored_traffic: Optional[Dict] = None + """A dict containing which traffic types are to be included in the observation.""" include_num_access: Optional[bool] = None """Flag to include the number of accesses.""" num_ports: Optional[int] = None @@ -180,6 +183,8 @@ class NodesObservation(AbstractObservation, identifier="NODES"): host_config.num_nics = config.num_nics if host_config.include_nmne is None: host_config.include_nmne = config.include_nmne + if host_config.monitored_traffic is None: + host_config.monitored_traffic = config.monitored_traffic if host_config.include_num_access is None: host_config.include_num_access = config.include_num_access diff --git a/src/primaite/game/agent/observations/observation_manager.py b/src/primaite/game/agent/observations/observation_manager.py index 352003d6..9b20fdcb 100644 --- a/src/primaite/game/agent/observations/observation_manager.py +++ b/src/primaite/game/agent/observations/observation_manager.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations from typing import Any, Dict, List, Optional diff --git a/src/primaite/game/agent/observations/observations.py b/src/primaite/game/agent/observations/observations.py index 1ba87a30..a9663c56 100644 --- a/src/primaite/game/agent/observations/observations.py +++ b/src/primaite/game/agent/observations/observations.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK """Manages the observation space for the agent.""" from abc import ABC, abstractmethod from typing import Any, Dict, Iterable, Optional, Type, Union diff --git a/src/primaite/game/agent/observations/router_observation.py b/src/primaite/game/agent/observations/router_observation.py index 3f7e6494..f1d4ec8e 100644 --- a/src/primaite/game/agent/observations/router_observation.py +++ b/src/primaite/game/agent/observations/router_observation.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations from typing import Dict, List, Optional diff --git a/src/primaite/game/agent/observations/software_observation.py b/src/primaite/game/agent/observations/software_observation.py index f943f540..15cd2447 100644 --- a/src/primaite/game/agent/observations/software_observation.py +++ b/src/primaite/game/agent/observations/software_observation.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations from typing import Dict diff --git a/src/primaite/game/agent/rewards.py b/src/primaite/game/agent/rewards.py index d77640d1..cabea5f4 100644 --- a/src/primaite/game/agent/rewards.py +++ b/src/primaite/game/agent/rewards.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK """ Manages the reward function for the agent. diff --git a/src/primaite/game/agent/scripted_agents/__init__.py b/src/primaite/game/agent/scripted_agents/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/game/agent/scripted_agents/__init__.py +++ b/src/primaite/game/agent/scripted_agents/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/game/agent/scripted_agents/data_manipulation_bot.py b/src/primaite/game/agent/scripted_agents/data_manipulation_bot.py index d3ec19cb..3a91f1fe 100644 --- a/src/primaite/game/agent/scripted_agents/data_manipulation_bot.py +++ b/src/primaite/game/agent/scripted_agents/data_manipulation_bot.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import random from typing import Dict, Tuple diff --git a/src/primaite/game/agent/scripted_agents/probabilistic_agent.py b/src/primaite/game/agent/scripted_agents/probabilistic_agent.py index 9cddc978..fc168687 100644 --- a/src/primaite/game/agent/scripted_agents/probabilistic_agent.py +++ b/src/primaite/game/agent/scripted_agents/probabilistic_agent.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK """Agents with predefined behaviours.""" from typing import Dict, Optional, Tuple diff --git a/src/primaite/game/agent/scripted_agents/random_agent.py b/src/primaite/game/agent/scripted_agents/random_agent.py index 5021a832..df9273f7 100644 --- a/src/primaite/game/agent/scripted_agents/random_agent.py +++ b/src/primaite/game/agent/scripted_agents/random_agent.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import random from typing import Dict, Optional, Tuple diff --git a/src/primaite/game/agent/scripted_agents/tap001.py b/src/primaite/game/agent/scripted_agents/tap001.py index 88fa37cf..b1a378ef 100644 --- a/src/primaite/game/agent/scripted_agents/tap001.py +++ b/src/primaite/game/agent/scripted_agents/tap001.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import random from typing import Dict, Tuple diff --git a/src/primaite/game/agent/utils.py b/src/primaite/game/agent/utils.py index 42e8f30b..15efd0b6 100644 --- a/src/primaite/game/agent/utils.py +++ b/src/primaite/game/agent/utils.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from typing import Any, Dict, Hashable, Optional, Sequence NOT_PRESENT_IN_STATE = object() diff --git a/src/primaite/game/game.py b/src/primaite/game/game.py index 772ab5aa..8a79d068 100644 --- a/src/primaite/game/game.py +++ b/src/primaite/game/game.py @@ -1,10 +1,11 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK """PrimAITE game - Encapsulates the simulation and agents.""" from ipaddress import IPv4Address from typing import Dict, List, Optional from pydantic import BaseModel, ConfigDict -from primaite import getLogger +from primaite import DEFAULT_BANDWIDTH, getLogger from primaite.game.agent.actions import ActionManager from primaite.game.agent.interface import AbstractAgent, AgentSettings, ProxyAgent from primaite.game.agent.observations.observation_manager import ObservationManager @@ -360,11 +361,6 @@ class PrimaiteGame: server_ip_address=IPv4Address(opt.get("server_ip")), server_password=opt.get("server_password"), payload=opt.get("payload", "ENCRYPT"), - c2_beacon_p_of_success=float(opt.get("c2_beacon_p_of_success", "0.5")), - target_scan_p_of_success=float(opt.get("target_scan_p_of_success", "0.1")), - ransomware_encrypt_p_of_success=float( - opt.get("ransomware_encrypt_p_of_success", "0.1") - ), ) elif application_type == "DatabaseClient": if "options" in application_cfg: @@ -410,7 +406,7 @@ class PrimaiteGame: for link_cfg in links_cfg: node_a = net.get_node_by_hostname(link_cfg["endpoint_a_hostname"]) node_b = net.get_node_by_hostname(link_cfg["endpoint_b_hostname"]) - bandwidth = link_cfg.get("bandwidth", 100) # default value if not configured + bandwidth = link_cfg.get("bandwidth", DEFAULT_BANDWIDTH) # default value if not configured if isinstance(node_a, Switch): endpoint_a = node_a.network_interface[link_cfg["endpoint_a_port"]] diff --git a/src/primaite/game/science.py b/src/primaite/game/science.py index 908b326f..8d8949df 100644 --- a/src/primaite/game/science.py +++ b/src/primaite/game/science.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from random import random from typing import Any, Iterable, Mapping diff --git a/src/primaite/interface/__init__.py b/src/primaite/interface/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/interface/__init__.py +++ b/src/primaite/interface/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/interface/request.py b/src/primaite/interface/request.py index bc076599..1a9f0e5f 100644 --- a/src/primaite/interface/request.py +++ b/src/primaite/interface/request.py @@ -1,8 +1,9 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from typing import Dict, ForwardRef, List, Literal, Union -from pydantic import BaseModel, ConfigDict, StrictBool, validate_call +from pydantic import BaseModel, ConfigDict, StrictBool # , validate_call -RequestFormat = List[Union[str, int, float]] +RequestFormat = List[Union[str, int, float, Dict]] RequestResponse = ForwardRef("RequestResponse") """This makes it possible to type-hint RequestResponse.from_bool return type.""" @@ -30,7 +31,7 @@ class RequestResponse(BaseModel): # much. However, in the future we might consider making them mandatory. @classmethod - @validate_call + # @validate_call # this slows down execution quite a bit. def from_bool(cls, status_bool: StrictBool) -> RequestResponse: """ Construct a basic request response from a boolean. diff --git a/src/primaite/notebooks/Data-Manipulation-Customising-Red-Agent.ipynb b/src/primaite/notebooks/Data-Manipulation-Customising-Red-Agent.ipynb index 33d56fb0..dd5def9e 100644 --- a/src/primaite/notebooks/Data-Manipulation-Customising-Red-Agent.ipynb +++ b/src/primaite/notebooks/Data-Manipulation-Customising-Red-Agent.ipynb @@ -458,7 +458,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.12" + "version": "3.10.11" } }, "nbformat": 4, diff --git a/src/primaite/notebooks/Requests-and-Responses.ipynb b/src/primaite/notebooks/Requests-and-Responses.ipynb index ca9f02f5..da614c93 100644 --- a/src/primaite/notebooks/Requests-and-Responses.ipynb +++ b/src/primaite/notebooks/Requests-and-Responses.ipynb @@ -6,9 +6,9 @@ "source": [ "# Requests and Responses\n", "\n", - "Agents interact with the PrimAITE simulation via the Request system.\n", + "© Crown-owned copyright 2024, Defence Science and Technology Laboratory UK\n", "\n", - "© Crown-owned copyright 2024, Defence Science and Technology Laboratory UK\n" + "Agents interact with the PrimAITE simulation via the Request system.\n" ] }, { diff --git a/src/primaite/notebooks/Training-an-SB3-Agent.ipynb b/src/primaite/notebooks/Training-an-SB3-Agent.ipynb index 8a5b852b..892736fe 100644 --- a/src/primaite/notebooks/Training-an-SB3-Agent.ipynb +++ b/src/primaite/notebooks/Training-an-SB3-Agent.ipynb @@ -168,7 +168,7 @@ ], "metadata": { "kernelspec": { - "display_name": "venv", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, diff --git a/src/primaite/notebooks/Using-Episode-Schedules.ipynb b/src/primaite/notebooks/Using-Episode-Schedules.ipynb index 0d0f1a4a..14012264 100644 --- a/src/primaite/notebooks/Using-Episode-Schedules.ipynb +++ b/src/primaite/notebooks/Using-Episode-Schedules.ipynb @@ -310,6 +310,101 @@ "source": [ "env.reset(); # semicolon suppresses jupyter outputting the observation space.\n" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Other uses\n", + "\n", + "Since the episode schedules make use of yaml aliases and anchors, it's possible to use them in any part of the config, not just agent definitions. For instance, we can vary the simulation setup by changing what software is installed on hosts, how that software is configured, or even change the nodes themselves.\n", + "\n", + "As an example, we will vary what software is installed on nodes in a basic test network." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mini_scenario_path = PRIMAITE_PATHS.user_config_path / \"example_config/mini_scenario_with_simulation_variation\"\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's open the base scenario to see the placeholders. client_1 and server both have placeholders in the software installed on them. The server has a placeholder called `*server_services` and the client has `*client_applications`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "with open(mini_scenario_path/\"base_scenario.yaml\") as f:\n", + " print(f.read())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the 0th episode, simulation_variant_1.yaml is loaded in and the server gets a `DatabaseService`, while client_1 gets `DatabaseClient`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "with open(mini_scenario_path/\"simulation_variant_1.yaml\") as f:\n", + " print(f.read())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "env = PrimaiteGymEnv(env_config=mini_scenario_path)\n", + "print(f\"Episode: {env.episode_counter}\")\n", + "env.game.simulation.network.get_node_by_hostname('server').software_manager.show()\n", + "env.game.simulation.network.get_node_by_hostname('client_1').software_manager.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the 1st episode, `simulation_variant_2.yaml` is loaded in, therefore the server gets a `FTPServer` and client_1 gets a `RansomwareScript`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "with open(mini_scenario_path/\"simulation_variant_2.yaml\") as f:\n", + " print(f.read())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "env.reset()\n", + "print(f\"Episode: {env.episode_counter}\")\n", + "env.game.simulation.network.get_node_by_hostname('server').software_manager.show()\n", + "env.game.simulation.network.get_node_by_hostname('client_1').software_manager.show()" + ] } ], "metadata": { @@ -328,7 +423,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.12" + "version": "3.10.11" } }, "nbformat": 4, diff --git a/src/primaite/session/__init__.py b/src/primaite/session/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/session/__init__.py +++ b/src/primaite/session/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/session/environment.py b/src/primaite/session/environment.py index 8fd39f40..6cc1282f 100644 --- a/src/primaite/session/environment.py +++ b/src/primaite/session/environment.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import json from os import PathLike from typing import Any, Dict, Optional, SupportsFloat, Tuple, Union @@ -59,7 +60,7 @@ class PrimaiteGymEnv(gymnasium.Env): next_obs = self._get_obs() # this doesn't update observation, just gets the current observation reward = self.agent.reward_function.current_reward - _LOGGER.info(f"step: {self.game.step_counter}, Blue reward: {reward}") + _LOGGER.debug(f"step: {self.game.step_counter}, Blue reward: {reward}") terminated = False truncated = self.game.calculate_truncated() info = { diff --git a/src/primaite/session/episode_schedule.py b/src/primaite/session/episode_schedule.py index c009fa09..ad4d38e9 100644 --- a/src/primaite/session/episode_schedule.py +++ b/src/primaite/session/episode_schedule.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import copy from abc import ABC, abstractmethod from itertools import chain diff --git a/src/primaite/session/io.py b/src/primaite/session/io.py index 2901457f..7bfd16f1 100644 --- a/src/primaite/session/io.py +++ b/src/primaite/session/io.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import json from datetime import datetime from pathlib import Path diff --git a/src/primaite/session/ray_envs.py b/src/primaite/session/ray_envs.py index f9ab3405..fc5d73d8 100644 --- a/src/primaite/session/ray_envs.py +++ b/src/primaite/session/ray_envs.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import json from typing import Dict, SupportsFloat, Tuple diff --git a/src/primaite/setup/__init__.py b/src/primaite/setup/__init__.py index 12b77f1e..12e7c4e7 100644 --- a/src/primaite/setup/__init__.py +++ b/src/primaite/setup/__init__.py @@ -1,2 +1,2 @@ -# © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK """Utilities to prepare the user's data folders.""" diff --git a/src/primaite/setup/reset_demo_notebooks.py b/src/primaite/setup/reset_demo_notebooks.py index bcf89b6a..f17fb211 100644 --- a/src/primaite/setup/reset_demo_notebooks.py +++ b/src/primaite/setup/reset_demo_notebooks.py @@ -1,4 +1,4 @@ -# © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import filecmp import shutil from logging import Logger @@ -45,11 +45,7 @@ def run(overwrite_existing: bool = True) -> None: shutil.copy2(src_fp, dst_fp) _LOGGER.info(f"Reset example notebook: {dst_fp}") - for src_fp in primaite_root.glob("notebooks/_package_data/*"): - dst_fp = example_notebooks_user_dir / "_package_data" / src_fp.name - if should_copy_file(src_fp, dst_fp, overwrite_existing): - if not Path.exists(example_notebooks_user_dir / "_package_data/"): - Path.mkdir(example_notebooks_user_dir / "_package_data/") - print(dst_fp) - shutil.copy2(src_fp, dst_fp) - _LOGGER.info(f"Copied notebook resource to: {dst_fp}") + src = primaite_root / "notebooks/_package_data/" + dst = example_notebooks_user_dir / "_package_data/" + + shutil.copytree(src, dst, dirs_exist_ok=True) diff --git a/src/primaite/setup/reset_example_configs.py b/src/primaite/setup/reset_example_configs.py index 41345853..c7eeecd5 100644 --- a/src/primaite/setup/reset_example_configs.py +++ b/src/primaite/setup/reset_example_configs.py @@ -1,4 +1,4 @@ -# © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import filecmp import os import shutil diff --git a/src/primaite/simulator/__init__.py b/src/primaite/simulator/__init__.py index d2993b34..e5fe3cb7 100644 --- a/src/primaite/simulator/__init__.py +++ b/src/primaite/simulator/__init__.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK """Warning: SIM_OUTPUT is a mutable global variable for the simulation output directory.""" from datetime import datetime from enum import IntEnum diff --git a/src/primaite/simulator/core.py b/src/primaite/simulator/core.py index 835f24fe..8c7d64c9 100644 --- a/src/primaite/simulator/core.py +++ b/src/primaite/simulator/core.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK # flake8: noqa """Core of the PrimAITE Simulator.""" import warnings @@ -220,8 +221,8 @@ class SimComponent(BaseModel): } return state - @validate_call - def apply_request(self, request: RequestFormat, context: Dict = {}) -> RequestResponse: + # @validate_call # this slows down execution quite a bit. + def apply_request(self, request: RequestFormat, context: Optional[Dict] = None) -> RequestResponse: """ Apply a request to a simulation component. Request data is passed in as a 'namespaced' list of strings. @@ -239,6 +240,8 @@ class SimComponent(BaseModel): :param: context: Dict containing context for requests :type context: Dict """ + if not context: + context = None if self._request_manager is None: return return self._request_manager(request, context) diff --git a/src/primaite/simulator/domain/__init__.py b/src/primaite/simulator/domain/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/domain/__init__.py +++ b/src/primaite/simulator/domain/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/domain/account.py b/src/primaite/simulator/domain/account.py index 186caf5b..d955cf55 100644 --- a/src/primaite/simulator/domain/account.py +++ b/src/primaite/simulator/domain/account.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK """User account simulation.""" from enum import Enum from typing import Dict diff --git a/src/primaite/simulator/domain/controller.py b/src/primaite/simulator/domain/controller.py index 82312dd3..37e60aaa 100644 --- a/src/primaite/simulator/domain/controller.py +++ b/src/primaite/simulator/domain/controller.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from enum import Enum from typing import Dict, Final, List, Literal, Tuple diff --git a/src/primaite/simulator/file_system/__init__.py b/src/primaite/simulator/file_system/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/file_system/__init__.py +++ b/src/primaite/simulator/file_system/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/file_system/file.py b/src/primaite/simulator/file_system/file.py index 328b052b..ba39c791 100644 --- a/src/primaite/simulator/file_system/file.py +++ b/src/primaite/simulator/file_system/file.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations import hashlib @@ -5,6 +6,8 @@ import json import warnings from typing import Dict, Optional +from prettytable import MARKDOWN, PrettyTable + from primaite import getLogger from primaite.simulator.file_system.file_system_item_abc import FileSystemItemABC, FileSystemItemHealthStatus from primaite.simulator.file_system.file_type import FileType, get_file_type_from_extension @@ -202,3 +205,18 @@ class File(FileSystemItemABC): self.deleted = True self.sys_log.info(f"File deleted {self.folder_name}/{self.name}") return True + + def show(self, markdown: bool = False): + """ + Prints a table of the file, displaying the file type, name and the file's access count. + + :param markdown: Flag indicating if output should be in markdown format. + """ + headers = ["File Name", "File Type", "Number of Accesses"] + table = PrettyTable(headers) + if markdown: + table.set_style(MARKDOWN) + table.align = "l" + table.title = f"{self.name}" + table.add_row([self.name, self.file_type.name, self.num_access]) + print(table) diff --git a/src/primaite/simulator/file_system/file_system.py b/src/primaite/simulator/file_system/file_system.py index 40a74e68..456b800c 100644 --- a/src/primaite/simulator/file_system/file_system.py +++ b/src/primaite/simulator/file_system/file_system.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations from pathlib import Path @@ -66,7 +67,7 @@ class FileSystem(SimComponent): self._create_manager = RequestManager() def _create_file_action(request: List[Any], context: Any) -> RequestResponse: - file = self.create_file(folder_name=request[0], file_name=request[1]) + file = self.create_file(folder_name=request[0], file_name=request[1], force=request[2]) if not file: return RequestResponse.from_bool(False) return RequestResponse( @@ -74,7 +75,7 @@ class FileSystem(SimComponent): data={ "file_name": file.name, "folder_name": file.folder_name, - "file_type": file.file_type, + "file_type": file.file_type.name, "file_size": file.size, }, ) @@ -110,9 +111,9 @@ class FileSystem(SimComponent): data={ "file_name": file.name, "folder_name": file.folder_name, - "file_type": file.file_type, + "file_type": file.file_type.name, "file_size": file.size, - "file_status": file.health_status, + "file_status": file.health_status.name, }, ) return RequestResponse.from_bool(False) @@ -159,6 +160,21 @@ class FileSystem(SimComponent): """ return sum(folder.size for folder in self.folders.values()) + def show_num_files(self, markdown: bool = False): + """ + Prints a table showing a host's number of file creations & deletions. + + :param markdown: Flag indicating if output should be in markdown format. + """ + headers = ["File creations", "File deletions"] + table = PrettyTable(headers) + if markdown: + table.set_style(MARKDOWN) + table.align = "l" + table.title = f"{self.sys_log.hostname} Number of Creations & Deletions" + table.add_row([self.num_file_creations, self.num_file_deletions]) + print(table) + def show(self, markdown: bool = False, full: bool = False): """ Prints a table of the FileSystem, displaying either just folders or full files. @@ -166,7 +182,7 @@ class FileSystem(SimComponent): :param markdown: Flag indicating if output should be in markdown format. :param full: Flag indicating if to show full files. """ - headers = ["Folder", "Size", "Deleted"] + headers = ["Folder", "Size", "Health status", "Visible health status", "Deleted"] if full: headers[0] = "File Path" table = PrettyTable(headers) @@ -177,14 +193,38 @@ class FileSystem(SimComponent): folders = {**self.folders, **self.deleted_folders} for folder in folders.values(): if not full: - table.add_row([folder.name, folder.size_str, folder.deleted]) + table.add_row( + [ + folder.name, + folder.size_str, + folder.health_status.name, + folder.visible_health_status.name, + folder.deleted, + ] + ) else: files = {**folder.files, **folder.deleted_files} if not files: - table.add_row([folder.name, folder.size_str, folder.deleted]) + table.add_row( + [ + folder.name, + folder.size_str, + folder.health_status.name, + folder.visible_health_status.name, + folder.deleted, + ] + ) else: for file in files.values(): - table.add_row([file.path, file.size_str, file.deleted]) + table.add_row( + [ + file.path, + file.size_str, + file.health_status.name, + file.visible_health_status.name, + file.deleted, + ] + ) if full: print(table.get_string(sortby="File Path")) else: @@ -200,15 +240,15 @@ class FileSystem(SimComponent): :param folder_name: The name of the folder. """ # check if folder with name already exists - if self.get_folder(folder_name): - raise Exception(f"Cannot create folder as it already exists: {folder_name}") - - folder = Folder(name=folder_name, sys_log=self.sys_log) - + folder = self.get_folder(folder_name) + if folder: + self.sys_log.info(f"Cannot create folder as it already exists: {folder_name}") + else: + folder = Folder(name=folder_name, sys_log=self.sys_log) + self._folder_request_manager.add_request( + name=folder.name, request_type=RequestType(func=folder._request_manager) + ) self.folders[folder.uuid] = folder - self._folder_request_manager.add_request( - name=folder.name, request_type=RequestType(func=folder._request_manager) - ) return folder def delete_folder(self, folder_name: str) -> bool: @@ -288,6 +328,7 @@ class FileSystem(SimComponent): size: Optional[int] = None, file_type: Optional[FileType] = None, folder_name: Optional[str] = None, + force: Optional[bool] = False, ) -> File: """ Creates a File and adds it to the list of files. @@ -296,6 +337,7 @@ class FileSystem(SimComponent): :param size: The size the file takes on disk in bytes. :param file_type: The type of the file. :param folder_name: The folder to add the file to. + :param force: Replaces the file if it already exists. """ if folder_name: # check if file with name already exists @@ -307,17 +349,23 @@ class FileSystem(SimComponent): # Use root folder if folder_name not supplied folder = self.get_folder("root") - # Create the file and add it to the folder - file = File( - name=file_name, - sim_size=size, - file_type=file_type, - folder_id=folder.uuid, - folder_name=folder.name, - sim_root=self.sim_root, - sys_log=self.sys_log, - ) - folder.add_file(file) + file = self.get_file(folder, file_name) + if file: + self.sys_log.info(f"Cannot create file {file_name} as it already exists.") + if force: + self.sys_log.info(f"Replacing {file_name}") + else: + # Create the file and add it to the folder + file = File( + name=file_name, + sim_size=size, + file_type=file_type, + folder_id=folder.uuid, + folder_name=folder.name, + sim_root=self.sim_root, + sys_log=self.sys_log, + ) + folder.add_file(file, force=force) self._file_request_manager.add_request(name=file.name, request_type=RequestType(func=file._request_manager)) # increment file creation self.num_file_creations += 1 diff --git a/src/primaite/simulator/file_system/file_system_item_abc.py b/src/primaite/simulator/file_system/file_system_item_abc.py index c89152b4..a9db8825 100644 --- a/src/primaite/simulator/file_system/file_system_item_abc.py +++ b/src/primaite/simulator/file_system/file_system_item_abc.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations import math diff --git a/src/primaite/simulator/file_system/file_type.py b/src/primaite/simulator/file_system/file_type.py index f87cd86f..8f0cb778 100644 --- a/src/primaite/simulator/file_system/file_type.py +++ b/src/primaite/simulator/file_system/file_type.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations from enum import Enum @@ -95,6 +96,20 @@ class FileType(Enum): DB = 32 "Generic DB file. Used by sqlite3." + # Script file types + PS1 = 33 + "A Powershell script. Used in Windows operating systems." + BAT = 34 + "Windows batch file. Used in Windows operating systems." + SH = 35 + "Linux shell script. Used in Unix based operating systems." + + # Executable file types + PE = 36 + "Portable Executable. Used in Windows operating systems." + ELF = 37 + "Executable and Linkable Format. Used in Unix based operating systems." + @classmethod def _missing_(cls, value: Any) -> FileType: return cls.UNKNOWN @@ -115,8 +130,11 @@ class FileType(Enum): Returns 0 if a default size does not exist. """ - size = file_type_sizes_bytes[self] - return size if size else 0 + try: + size = file_type_sizes_bytes[self] + return size + except KeyError: + return 0 def get_file_type_from_extension(file_type_extension: str) -> FileType: diff --git a/src/primaite/simulator/file_system/folder.py b/src/primaite/simulator/file_system/folder.py index 90ad4425..dd2a4c70 100644 --- a/src/primaite/simulator/file_system/folder.py +++ b/src/primaite/simulator/file_system/folder.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations import warnings diff --git a/src/primaite/simulator/network/__init__.py b/src/primaite/simulator/network/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/network/__init__.py +++ b/src/primaite/simulator/network/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/network/airspace.py b/src/primaite/simulator/network/airspace.py index 907ab233..5fec098b 100644 --- a/src/primaite/simulator/network/airspace.py +++ b/src/primaite/simulator/network/airspace.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations from abc import ABC, abstractmethod diff --git a/src/primaite/simulator/network/container.py b/src/primaite/simulator/network/container.py index 91ea3c71..2b9f3e53 100644 --- a/src/primaite/simulator/network/container.py +++ b/src/primaite/simulator/network/container.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address from typing import Any, Dict, List, Optional diff --git a/src/primaite/simulator/network/creation.py b/src/primaite/simulator/network/creation.py index f4475bec..61a37a90 100644 --- a/src/primaite/simulator/network/creation.py +++ b/src/primaite/simulator/network/creation.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address from typing import Optional diff --git a/src/primaite/simulator/network/hardware/__init__.py b/src/primaite/simulator/network/hardware/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/network/hardware/__init__.py +++ b/src/primaite/simulator/network/hardware/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/network/hardware/base.py b/src/primaite/simulator/network/hardware/base.py index a515ce58..01745215 100644 --- a/src/primaite/simulator/network/hardware/base.py +++ b/src/primaite/simulator/network/hardware/base.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations import re @@ -10,6 +11,7 @@ from typing import Any, Dict, Optional, Type, TypeVar, Union from prettytable import MARKDOWN, PrettyTable from pydantic import BaseModel, Field +import primaite.simulator.network.nmne from primaite import getLogger from primaite.exceptions import NetworkError from primaite.interface.request import RequestResponse @@ -28,6 +30,7 @@ from primaite.simulator.network.nmne import ( NMNE_CAPTURE_KEYWORDS, ) from primaite.simulator.network.transmission.data_link_layer import Frame +from primaite.simulator.network.transmission.network_layer import IPProtocol from primaite.simulator.system.applications.application import Application from primaite.simulator.system.core.packet_capture import PacketCapture from primaite.simulator.system.core.session_manager import SessionManager @@ -36,6 +39,7 @@ from primaite.simulator.system.core.sys_log import SysLog from primaite.simulator.system.processes.process import Process from primaite.simulator.system.services.service import Service from primaite.simulator.system.software import IOSoftware +from primaite.utils.converters import convert_dict_enum_keys_to_enum_values from primaite.utils.validators import IPV4Address IOSoftwareClass = TypeVar("IOSoftwareClass", bound=IOSoftware) @@ -107,10 +111,14 @@ class NetworkInterface(SimComponent, ABC): nmne: Dict = Field(default_factory=lambda: {}) "A dict containing details of the number of malicious network events captured." + traffic: Dict = Field(default_factory=lambda: {}) + "A dict containing details of the inbound and outbound traffic by port and protocol." + def setup_for_episode(self, episode: int): """Reset the original state of the SimComponent.""" super().setup_for_episode(episode=episode) self.nmne = {} + self.traffic = {} if episode and self.pcap and SIM_OUTPUT.save_pcap_logs: self.pcap.current_episode = episode self.pcap.setup_logger() @@ -146,6 +154,7 @@ class NetworkInterface(SimComponent, ABC): ) if CAPTURE_NMNE: state.update({"nmne": {k: v for k, v in self.nmne.items()}}) + state.update({"traffic": convert_dict_enum_keys_to_enum_values(self.traffic)}) return state @abstractmethod @@ -236,6 +245,47 @@ class NetworkInterface(SimComponent, ABC): # Increment a generic counter if keyword capturing is not enabled keyword_level["*"] = keyword_level.get("*", 0) + 1 + def _capture_traffic(self, frame: Frame, inbound: bool = True): + """ + Capture traffic statistics at the Network Interface. + + :param frame: The network frame containing the traffic data. + :type frame: Frame + :param inbound: Flag indicating if the traffic is inbound or outbound. Defaults to True. + :type inbound: bool + """ + # Determine the direction of the traffic + direction = "inbound" if inbound else "outbound" + + # Initialize protocol and port variables + protocol = None + port = None + + # Identify the protocol and port from the frame + if frame.tcp: + protocol = IPProtocol.TCP + port = frame.tcp.dst_port + elif frame.udp: + protocol = IPProtocol.UDP + port = frame.udp.dst_port + elif frame.icmp: + protocol = IPProtocol.ICMP + + # Ensure the protocol is in the capture dict + if protocol not in self.traffic: + self.traffic[protocol] = {} + + # Handle non-ICMP protocols that use ports + if protocol != IPProtocol.ICMP: + if port not in self.traffic[protocol]: + self.traffic[protocol][port] = {"inbound": 0, "outbound": 0} + self.traffic[protocol][port][direction] += frame.size_Mbits + else: + # Handle ICMP protocol separately (ICMP does not use ports) + if not self.traffic[protocol]: + self.traffic[protocol] = {"inbound": 0, "outbound": 0} + self.traffic[protocol][direction] += frame.size_Mbits + @abstractmethod def send_frame(self, frame: Frame) -> bool: """ @@ -245,6 +295,7 @@ class NetworkInterface(SimComponent, ABC): :return: A boolean indicating whether the frame was successfully sent. """ self._capture_nmne(frame, inbound=False) + self._capture_traffic(frame, inbound=False) @abstractmethod def receive_frame(self, frame: Frame) -> bool: @@ -255,6 +306,7 @@ class NetworkInterface(SimComponent, ABC): :return: A boolean indicating whether the frame was successfully received. """ self._capture_nmne(frame, inbound=True) + self._capture_traffic(frame, inbound=True) def __str__(self) -> str: """ @@ -275,6 +327,11 @@ class NetworkInterface(SimComponent, ABC): """ super().apply_timestep(timestep=timestep) + def pre_timestep(self, timestep: int) -> None: + """Apply pre-timestep logic.""" + super().pre_timestep(timestep) + self.traffic = {} + class WiredNetworkInterface(NetworkInterface, ABC): """ @@ -766,6 +823,24 @@ class Node(SimComponent): self.session_manager.software_manager = self.software_manager self._install_system_software() + def ip_is_network_interface(self, ip_address: IPv4Address, enabled_only: bool = False) -> bool: + """ + Checks if a given IP address belongs to any of the nodes interfaces. + + :param ip_address: The IP address to check. + :param enabled_only: If True, only considers enabled network interfaces. + :return: True if the IP address is assigned to one of the nodes interfaces; False otherwise. + """ + for network_interface in self.network_interface.values(): + if not hasattr(network_interface, "ip_address"): + continue + if network_interface.ip_address == ip_address: + if enabled_only: + return network_interface.enabled + else: + return True + return False + def setup_for_episode(self, episode: int): """Reset the original state of the SimComponent.""" super().setup_for_episode(episode=episode) @@ -975,7 +1050,7 @@ class Node(SimComponent): def show_nic(self, markdown: bool = False): """Prints a table of the NICs on the Node.""" - table = PrettyTable(["Port", "Type", "MAC Address", "Address", "Speed", "Status"]) + table = PrettyTable(["Port", "Type", "MAC Address", "Address", "Speed", "Status", "NMNE"]) if markdown: table.set_style(MARKDOWN) table.align = "l" @@ -992,6 +1067,7 @@ class Node(SimComponent): ip_address, network_interface.speed, "Enabled" if network_interface.enabled else "Disabled", + network_interface.nmne if primaite.simulator.network.nmne.CAPTURE_NMNE else "Disabled", ] ) print(table) diff --git a/src/primaite/simulator/network/hardware/network_interface/__init__.py b/src/primaite/simulator/network/hardware/network_interface/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/network/hardware/network_interface/__init__.py +++ b/src/primaite/simulator/network/hardware/network_interface/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/network/hardware/network_interface/wireless/__init__.py b/src/primaite/simulator/network/hardware/network_interface/wireless/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/network/hardware/network_interface/wireless/__init__.py +++ b/src/primaite/simulator/network/hardware/network_interface/wireless/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/network/hardware/network_interface/wireless/wireless_access_point.py b/src/primaite/simulator/network/hardware/network_interface/wireless/wireless_access_point.py index 4b73b6a8..a9a31768 100644 --- a/src/primaite/simulator/network/hardware/network_interface/wireless/wireless_access_point.py +++ b/src/primaite/simulator/network/hardware/network_interface/wireless/wireless_access_point.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from typing import Dict from primaite.simulator.network.hardware.base import ( diff --git a/src/primaite/simulator/network/hardware/network_interface/wireless/wireless_nic.py b/src/primaite/simulator/network/hardware/network_interface/wireless/wireless_nic.py index 2e0a1823..eebaedc5 100644 --- a/src/primaite/simulator/network/hardware/network_interface/wireless/wireless_nic.py +++ b/src/primaite/simulator/network/hardware/network_interface/wireless/wireless_nic.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from typing import Dict from primaite.simulator.network.hardware.base import ( diff --git a/src/primaite/simulator/network/hardware/node_operating_state.py b/src/primaite/simulator/network/hardware/node_operating_state.py index 1fd1225f..e64ef08b 100644 --- a/src/primaite/simulator/network/hardware/node_operating_state.py +++ b/src/primaite/simulator/network/hardware/node_operating_state.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from enum import Enum diff --git a/src/primaite/simulator/network/hardware/nodes/__init__.py b/src/primaite/simulator/network/hardware/nodes/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/network/hardware/nodes/__init__.py +++ b/src/primaite/simulator/network/hardware/nodes/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/network/hardware/nodes/host/__init__.py b/src/primaite/simulator/network/hardware/nodes/host/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/network/hardware/nodes/host/__init__.py +++ b/src/primaite/simulator/network/hardware/nodes/host/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/network/hardware/nodes/host/computer.py b/src/primaite/simulator/network/hardware/nodes/host/computer.py index 7ce64867..68c72554 100644 --- a/src/primaite/simulator/network/hardware/nodes/host/computer.py +++ b/src/primaite/simulator/network/hardware/nodes/host/computer.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from typing import ClassVar, Dict from primaite.simulator.network.hardware.nodes.host.host_node import HostNode diff --git a/src/primaite/simulator/network/hardware/nodes/host/host_node.py b/src/primaite/simulator/network/hardware/nodes/host/host_node.py index caea2dd7..fdb28339 100644 --- a/src/primaite/simulator/network/hardware/nodes/host/host_node.py +++ b/src/primaite/simulator/network/hardware/nodes/host/host_node.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations from ipaddress import IPv4Address @@ -7,6 +8,8 @@ from primaite import getLogger from primaite.simulator.network.hardware.base import IPWiredNetworkInterface, Link, Node from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState from primaite.simulator.network.transmission.data_link_layer import Frame +from primaite.simulator.system.applications.application import ApplicationOperatingState +from primaite.simulator.system.applications.nmap import NMAP from primaite.simulator.system.applications.web_browser import WebBrowser from primaite.simulator.system.services.arp.arp import ARP, ARPPacket from primaite.simulator.system.services.dns.dns_client import DNSClient @@ -302,6 +305,7 @@ class HostNode(Node): "DNSClient": DNSClient, "NTPClient": NTPClient, "WebBrowser": WebBrowser, + "NMAP": NMAP, } """List of system software that is automatically installed on nodes.""" @@ -314,6 +318,16 @@ class HostNode(Node): super().__init__(**kwargs) self.connect_nic(NIC(ip_address=ip_address, subnet_mask=subnet_mask)) + @property + def nmap(self) -> Optional[NMAP]: + """ + Return the NMAP application installed on the Node. + + :return: NMAP application installed on the Node. + :rtype: Optional[NMAP] + """ + return self.software_manager.software.get("NMAP") + @property def arp(self) -> Optional[ARP]: """ @@ -365,8 +379,15 @@ class HostNode(Node): elif frame.udp: dst_port = frame.udp.dst_port + can_accept_nmap = False + if self.software_manager.software.get("NMAP"): + if self.software_manager.software["NMAP"].operating_state == ApplicationOperatingState.RUNNING: + can_accept_nmap = True + + accept_nmap = can_accept_nmap and frame.payload.__class__.__name__ == "PortScanPayload" + accept_frame = False - if frame.icmp or dst_port in self.software_manager.get_open_ports(): + if frame.icmp or dst_port in self.software_manager.get_open_ports() or accept_nmap: # accept the frame as the port is open or if it's an ICMP frame accept_frame = True diff --git a/src/primaite/simulator/network/hardware/nodes/host/server.py b/src/primaite/simulator/network/hardware/nodes/host/server.py index 593cd0dd..379c9927 100644 --- a/src/primaite/simulator/network/hardware/nodes/host/server.py +++ b/src/primaite/simulator/network/hardware/nodes/host/server.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from primaite.simulator.network.hardware.nodes.host.host_node import HostNode diff --git a/src/primaite/simulator/network/hardware/nodes/network/__init__.py b/src/primaite/simulator/network/hardware/nodes/network/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/network/hardware/nodes/network/__init__.py +++ b/src/primaite/simulator/network/hardware/nodes/network/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/network/hardware/nodes/network/firewall.py b/src/primaite/simulator/network/hardware/nodes/network/firewall.py index abdaf323..4510eac0 100644 --- a/src/primaite/simulator/network/hardware/nodes/network/firewall.py +++ b/src/primaite/simulator/network/hardware/nodes/network/firewall.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address from typing import Dict, Final, Union diff --git a/src/primaite/simulator/network/hardware/nodes/network/network_node.py b/src/primaite/simulator/network/hardware/nodes/network/network_node.py index 0474ca08..5ff791cc 100644 --- a/src/primaite/simulator/network/hardware/nodes/network/network_node.py +++ b/src/primaite/simulator/network/hardware/nodes/network/network_node.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from abc import abstractmethod from typing import Optional diff --git a/src/primaite/simulator/network/hardware/nodes/network/router.py b/src/primaite/simulator/network/hardware/nodes/network/router.py index 53bb4827..61b7b96a 100644 --- a/src/primaite/simulator/network/hardware/nodes/network/router.py +++ b/src/primaite/simulator/network/hardware/nodes/network/router.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations import secrets @@ -18,6 +19,7 @@ from primaite.simulator.network.protocols.icmp import ICMPPacket, ICMPType from primaite.simulator.network.transmission.data_link_layer import Frame from primaite.simulator.network.transmission.network_layer import IPProtocol from primaite.simulator.network.transmission.transport_layer import Port +from primaite.simulator.system.applications.nmap import NMAP from primaite.simulator.system.core.session_manager import SessionManager from primaite.simulator.system.core.sys_log import SysLog from primaite.simulator.system.services.arp.arp import ARP @@ -1238,6 +1240,7 @@ class Router(NetworkNode): icmp.router = self self.software_manager.install(RouterARP) self.arp.router = self + self.software_manager.install(NMAP) def _set_default_acl(self): """ diff --git a/src/primaite/simulator/network/hardware/nodes/network/switch.py b/src/primaite/simulator/network/hardware/nodes/network/switch.py index db1863e0..6eee0d40 100644 --- a/src/primaite/simulator/network/hardware/nodes/network/switch.py +++ b/src/primaite/simulator/network/hardware/nodes/network/switch.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations from typing import Dict, Optional diff --git a/src/primaite/simulator/network/hardware/nodes/network/wireless_router.py b/src/primaite/simulator/network/hardware/nodes/network/wireless_router.py index 9e5d4dd4..e329f7a1 100644 --- a/src/primaite/simulator/network/hardware/nodes/network/wireless_router.py +++ b/src/primaite/simulator/network/hardware/nodes/network/wireless_router.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address from typing import Any, Dict, Union diff --git a/src/primaite/simulator/network/networks.py b/src/primaite/simulator/network/networks.py index f3d43e5b..cb0965eb 100644 --- a/src/primaite/simulator/network/networks.py +++ b/src/primaite/simulator/network/networks.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address import yaml @@ -184,7 +185,10 @@ def arcd_uc2_network() -> Network: db_client_2.run() web_browser_2 = client_2.software_manager.software.get("WebBrowser") web_browser_2.target_url = "http://arcd.com/users/" - network.connect(endpoint_b=client_2.network_interface[1], endpoint_a=switch_2.network_interface[2]) + network.connect( + endpoint_b=client_2.network_interface[1], + endpoint_a=switch_2.network_interface[2], + ) # Domain Controller domain_controller = Server( diff --git a/src/primaite/simulator/network/nmne.py b/src/primaite/simulator/network/nmne.py index 1b3d838d..5c0c657b 100644 --- a/src/primaite/simulator/network/nmne.py +++ b/src/primaite/simulator/network/nmne.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from typing import Dict, Final, List CAPTURE_NMNE: bool = True diff --git a/src/primaite/simulator/network/protocols/__init__.py b/src/primaite/simulator/network/protocols/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/network/protocols/__init__.py +++ b/src/primaite/simulator/network/protocols/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/network/protocols/arp.py b/src/primaite/simulator/network/protocols/arp.py index 2e44884a..9e7f7ebe 100644 --- a/src/primaite/simulator/network/protocols/arp.py +++ b/src/primaite/simulator/network/protocols/arp.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations from ipaddress import IPv4Address diff --git a/src/primaite/simulator/network/protocols/dns.py b/src/primaite/simulator/network/protocols/dns.py index 4f9be51b..eb7b74ad 100644 --- a/src/primaite/simulator/network/protocols/dns.py +++ b/src/primaite/simulator/network/protocols/dns.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations from ipaddress import IPv4Address diff --git a/src/primaite/simulator/network/protocols/ftp.py b/src/primaite/simulator/network/protocols/ftp.py index 0fd3fe43..c570a634 100644 --- a/src/primaite/simulator/network/protocols/ftp.py +++ b/src/primaite/simulator/network/protocols/ftp.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from enum import Enum from typing import Any, Optional, Union diff --git a/src/primaite/simulator/network/protocols/http.py b/src/primaite/simulator/network/protocols/http.py index b88916a9..5390cd26 100644 --- a/src/primaite/simulator/network/protocols/http.py +++ b/src/primaite/simulator/network/protocols/http.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from enum import Enum, IntEnum from primaite.simulator.network.protocols.packet import DataPacket diff --git a/src/primaite/simulator/network/protocols/icmp.py b/src/primaite/simulator/network/protocols/icmp.py index 35b0a05d..743e2375 100644 --- a/src/primaite/simulator/network/protocols/icmp.py +++ b/src/primaite/simulator/network/protocols/icmp.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import secrets from enum import Enum from typing import Union diff --git a/src/primaite/simulator/network/protocols/ntp.py b/src/primaite/simulator/network/protocols/ntp.py index 55353265..74e02dab 100644 --- a/src/primaite/simulator/network/protocols/ntp.py +++ b/src/primaite/simulator/network/protocols/ntp.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations from datetime import datetime diff --git a/src/primaite/simulator/network/protocols/packet.py b/src/primaite/simulator/network/protocols/packet.py index 3c99aa68..7eeec13b 100644 --- a/src/primaite/simulator/network/protocols/packet.py +++ b/src/primaite/simulator/network/protocols/packet.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from typing import Any from pydantic import BaseModel diff --git a/src/primaite/simulator/network/transmission/__init__.py b/src/primaite/simulator/network/transmission/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/network/transmission/__init__.py +++ b/src/primaite/simulator/network/transmission/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/network/transmission/data_link_layer.py b/src/primaite/simulator/network/transmission/data_link_layer.py index e3189cd8..776a5bfb 100644 --- a/src/primaite/simulator/network/transmission/data_link_layer.py +++ b/src/primaite/simulator/network/transmission/data_link_layer.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from datetime import datetime from typing import Any, Optional diff --git a/src/primaite/simulator/network/transmission/network_layer.py b/src/primaite/simulator/network/transmission/network_layer.py index 8ee0b4af..d493cbdf 100644 --- a/src/primaite/simulator/network/transmission/network_layer.py +++ b/src/primaite/simulator/network/transmission/network_layer.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from enum import Enum from pydantic import BaseModel @@ -24,6 +25,10 @@ class IPProtocol(Enum): ICMP = "icmp" """Internet Control Message Protocol.""" + def model_dump(self) -> str: + """Return as JSON-serialisable string.""" + return self.name + class Precedence(Enum): """ diff --git a/src/primaite/simulator/network/transmission/primaite_layer.py b/src/primaite/simulator/network/transmission/primaite_layer.py index 4c90c14c..981b6fbc 100644 --- a/src/primaite/simulator/network/transmission/primaite_layer.py +++ b/src/primaite/simulator/network/transmission/primaite_layer.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from enum import Enum from pydantic import BaseModel diff --git a/src/primaite/simulator/network/transmission/transport_layer.py b/src/primaite/simulator/network/transmission/transport_layer.py index bf739ad1..7f0d2d7a 100644 --- a/src/primaite/simulator/network/transmission/transport_layer.py +++ b/src/primaite/simulator/network/transmission/transport_layer.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from enum import Enum from typing import List, Union @@ -71,6 +72,10 @@ class Port(Enum): POSTGRES_SERVER = 5432 "Postgres SQL Server." + def model_dump(self) -> str: + """Return a json-serialisable string.""" + return self.name + class UDPHeader(BaseModel): """ diff --git a/src/primaite/simulator/network/utils.py b/src/primaite/simulator/network/utils.py index 33085bd6..4fd1834a 100644 --- a/src/primaite/simulator/network/utils.py +++ b/src/primaite/simulator/network/utils.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from typing import Union diff --git a/src/primaite/simulator/sim_container.py b/src/primaite/simulator/sim_container.py index 9e2e5da4..809b52db 100644 --- a/src/primaite/simulator/sim_container.py +++ b/src/primaite/simulator/sim_container.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from typing import Dict from primaite.interface.request import RequestResponse diff --git a/src/primaite/simulator/system/__init__.py b/src/primaite/simulator/system/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/system/__init__.py +++ b/src/primaite/simulator/system/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/system/applications/__init__.py b/src/primaite/simulator/system/applications/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/system/applications/__init__.py +++ b/src/primaite/simulator/system/applications/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/system/applications/application.py b/src/primaite/simulator/system/applications/application.py index 294de27b..1b9a9657 100644 --- a/src/primaite/simulator/system/applications/application.py +++ b/src/primaite/simulator/system/applications/application.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from abc import abstractmethod from enum import Enum from typing import Any, Dict, Optional, Set diff --git a/src/primaite/simulator/system/applications/database_client.py b/src/primaite/simulator/system/applications/database_client.py index c9661272..bae2139b 100644 --- a/src/primaite/simulator/system/applications/database_client.py +++ b/src/primaite/simulator/system/applications/database_client.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations from ipaddress import IPv4Address @@ -270,9 +271,16 @@ class DatabaseClient(Application): Calls disconnect on all client connections to ensure that both client and server connections are killed. """ - while self.client_connections.values(): - client_connection = self.client_connections[next(iter(self.client_connections.keys()))] - client_connection.disconnect() + while self.client_connections: + conn_key = next(iter(self.client_connections.keys())) + conn_obj: DatabaseClientConnection = self.client_connections[conn_key] + conn_obj.disconnect() + if conn_obj.is_active or conn_key in self.client_connections: + self.sys_log.error( + "Attempted to uninstall database client but could not drop active connections. " + "Forcing uninstall anyway." + ) + self.client_connections.pop(conn_key, None) super().uninstall() def get_new_connection(self) -> Optional[DatabaseClientConnection]: diff --git a/src/primaite/simulator/system/applications/nmap.py b/src/primaite/simulator/system/applications/nmap.py new file mode 100644 index 00000000..d8af1b7b --- /dev/null +++ b/src/primaite/simulator/system/applications/nmap.py @@ -0,0 +1,454 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK +from ipaddress import IPv4Address, IPv4Network +from typing import Any, Dict, Final, List, Optional, Set, Tuple, Union + +from prettytable import PrettyTable +from pydantic import validate_call + +from primaite.interface.request import RequestResponse +from primaite.simulator.core import RequestManager, RequestType, SimComponent +from primaite.simulator.network.transmission.network_layer import IPProtocol +from primaite.simulator.network.transmission.transport_layer import Port +from primaite.simulator.system.applications.application import Application +from primaite.utils.validators import IPV4Address + + +class PortScanPayload(SimComponent): + """ + A class representing the payload for a port scan. + + :ivar ip_address: The target IP address for the port scan. + :ivar port: The target port for the port scan. + :ivar protocol: The protocol used for the port scan. + :ivar request:Flag to indicate whether this is a request or not. + """ + + ip_address: IPV4Address + port: Port + protocol: IPProtocol + request: bool = True + + def describe_state(self) -> Dict: + """ + Describe the state of the port scan payload. + + :return: A dictionary representation of the port scan payload state. + :rtype: Dict + """ + state = super().describe_state() + state["ip_address"] = str(self.ip_address) + state["port"] = self.port.value + state["protocol"] = self.protocol.value + state["request"] = self.request + + return state + + +class NMAP(Application): + """ + A class representing the NMAP application for network scanning. + + NMAP is a network scanning tool used to discover hosts and services on a network. It provides functionalities such + as ping scans to discover active hosts and port scans to detect open ports on those hosts. + """ + + _active_port_scans: Dict[str, PortScanPayload] = {} + _port_scan_responses: Dict[str, PortScanPayload] = {} + + _PORT_SCAN_TYPE_MAP: Final[Dict[Tuple[bool, bool], str]] = { + (True, True): "Box", + (True, False): "Horizontal", + (False, True): "Vertical", + (False, False): "Port", + } + + def __init__(self, **kwargs): + kwargs["name"] = "NMAP" + kwargs["port"] = Port.NONE + kwargs["protocol"] = IPProtocol.NONE + super().__init__(**kwargs) + + def _can_perform_network_action(self) -> bool: + """ + Checks if the NMAP application can perform outbound network actions. + + This is done by checking the parent application can_per_action functionality. Then checking if there is an + enabled NIC that can be used for outbound traffic. + + :return: True if outbound network actions can be performed, otherwise False. + """ + if not super()._can_perform_action(): + return False + + for nic in self.software_manager.node.network_interface.values(): + if nic.enabled: + return True + return False + + def _init_request_manager(self) -> RequestManager: + def _ping_scan_action(request: List[Any], context: Any) -> RequestResponse: + results = self.ping_scan( + target_ip_address=request[0]["target_ip_address"], show=request[0]["show"], json_serializable=True + ) + if not self._can_perform_network_action(): + return RequestResponse.from_bool(False) + return RequestResponse( + status="success", + data={"live_hosts": results}, + ) + + def _port_scan_action(request: List[Any], context: Any) -> RequestResponse: + results = self.port_scan(**request[0], json_serializable=True) + if not self._can_perform_network_action(): + return RequestResponse.from_bool(False) + return RequestResponse( + status="success", + data=results, + ) + + def _network_service_recon_action(request: List[Any], context: Any) -> RequestResponse: + results = self.network_service_recon(**request[0], json_serializable=True) + if not self._can_perform_network_action(): + return RequestResponse.from_bool(False) + return RequestResponse( + status="success", + data=results, + ) + + rm = RequestManager() + + rm.add_request( + name="ping_scan", + request_type=RequestType(func=_ping_scan_action), + ) + + rm.add_request( + name="port_scan", + request_type=RequestType(func=_port_scan_action), + ) + + rm.add_request( + name="network_service_recon", + request_type=RequestType(func=_network_service_recon_action), + ) + + return rm + + def describe_state(self) -> Dict: + """ + Describe the state of the NMAP application. + + :return: A dictionary representation of the NMAP application's state. + :rtype: Dict + """ + return super().describe_state() + + @staticmethod + def _explode_ip_address_network_array( + target_ip_address: Union[IPV4Address, List[IPV4Address], IPv4Network, List[IPv4Network]] + ) -> Set[IPv4Address]: + """ + Explode a mixed array of IP addresses and networks into a set of individual IP addresses. + + This method takes a combination of single and lists of IPv4 addresses and IPv4 networks, expands any networks + into their constituent subnet useable IP addresses, and returns a set of unique IP addresses. Broadcast and + network addresses are excluded from the result. + + :param target_ip_address: A single or list of IPv4 addresses and networks. + :type target_ip_address: Union[IPV4Address, List[IPV4Address], IPv4Network, List[IPv4Network]] + :return: A set of unique IPv4 addresses expanded from the input. + :rtype: Set[IPv4Address] + """ + if isinstance(target_ip_address, IPv4Address) or isinstance(target_ip_address, IPv4Network): + target_ip_address = [target_ip_address] + ip_addresses: List[IPV4Address] = [] + for ip_address in target_ip_address: + if isinstance(ip_address, IPv4Network): + ip_addresses += [ + ip + for ip in ip_address.hosts() + if not ip == ip_address.broadcast_address and not ip == ip_address.network_address + ] + else: + ip_addresses.append(ip_address) + return set(ip_addresses) + + @validate_call() + def ping_scan( + self, + target_ip_address: Union[IPV4Address, List[IPV4Address], IPv4Network, List[IPv4Network]], + show: bool = True, + show_online_only: bool = True, + json_serializable: bool = False, + ) -> Union[List[IPV4Address], List[str]]: + """ + Perform a ping scan on the target IP address(es). + + :param target_ip_address: The target IP address(es) or network(s) for the ping scan. + :type target_ip_address: Union[IPV4Address, List[IPV4Address], IPv4Network, List[IPv4Network]] + :param show: Flag indicating whether to display the scan results. Defaults to True. + :type show: bool + :param show_online_only: Flag indicating whether to show only the online hosts. Defaults to True. + :type show_online_only: bool + :param json_serializable: Flag indicating whether the return value should be json serializable. Defaults to + False. + :type json_serializable: bool + + :return: A list of active IP addresses that responded to the ping. + :rtype: Union[List[IPV4Address], List[str]] + """ + active_nodes = [] + if show: + table = PrettyTable(["IP Address", "Can Ping"]) + table.align = "l" + table.title = f"{self.software_manager.node.hostname} NMAP Ping Scan" + + ip_addresses = self._explode_ip_address_network_array(target_ip_address) + + for ip_address in ip_addresses: + # Prevent ping scan on this node + if self.software_manager.node.ip_is_network_interface(ip_address=ip_address): + continue + can_ping = self.software_manager.icmp.ping(ip_address) + if can_ping: + active_nodes.append(ip_address if not json_serializable else str(ip_address)) + if show and (can_ping or not show_online_only): + table.add_row([ip_address, can_ping]) + if show: + print(table.get_string(sortby="IP Address")) + return active_nodes + + def _determine_port_scan_type(self, target_ip_addresses: List[IPV4Address], target_ports: List[Port]) -> str: + """ + Determine the type of port scan based on the number of target IP addresses and ports. + + :param target_ip_addresses: The list of target IP addresses. + :type target_ip_addresses: List[IPV4Address] + :param target_ports: The list of target ports. + :type target_ports: List[Port] + + :return: The type of port scan. + :rtype: str + """ + vertical_scan = len(target_ports) > 1 + horizontal_scan = len(target_ip_addresses) > 1 + + return self._PORT_SCAN_TYPE_MAP[horizontal_scan, vertical_scan] + + def _check_port_open_on_ip_address( + self, + ip_address: IPv4Address, + port: Port, + protocol: IPProtocol, + is_re_attempt: bool = False, + port_scan_uuid: Optional[str] = None, + ) -> bool: + """ + Check if a port is open on a specific IP address. + + :param ip_address: The target IP address. + :type ip_address: IPv4Address + :param port: The target port. + :type port: Port + :param protocol: The protocol used for the port scan. + :type protocol: IPProtocol + :param is_re_attempt: Flag indicating if this is a reattempt. Defaults to False. + :type is_re_attempt: bool + :param port_scan_uuid: The UUID of the port scan payload. Defaults to None. + :type port_scan_uuid: Optional[str] + + :return: True if the port is open, False otherwise. + :rtype: bool + """ + # The recursive base case + if is_re_attempt: + # Return True if a response has been received, otherwise return False + if port_scan_uuid in self._port_scan_responses: + self._port_scan_responses.pop(port_scan_uuid) + return True + return False + + # Send the port scan request + payload = PortScanPayload(ip_address=ip_address, port=port, protocol=protocol) + self._active_port_scans[payload.uuid] = payload + self.sys_log.info( + f"{self.name}: Sending port scan request over {payload.protocol.name} on port {payload.port.value} " + f"({payload.port.name}) to {payload.ip_address}" + ) + self.software_manager.send_payload_to_session_manager( + payload=payload, dest_ip_address=ip_address, src_port=port, dest_port=port, ip_protocol=protocol + ) + + # Recursively call this function with as a reattempt + return self._check_port_open_on_ip_address( + ip_address=ip_address, port=port, protocol=protocol, is_re_attempt=True, port_scan_uuid=payload.uuid + ) + + def _process_port_scan_response(self, payload: PortScanPayload): + """ + Process the response to a port scan request. + + :param payload: The port scan payload received in response. + :type payload: PortScanPayload + """ + if payload.uuid in self._active_port_scans: + self._active_port_scans.pop(payload.uuid) + self._port_scan_responses[payload.uuid] = payload + self.sys_log.info( + f"{self.name}: Received port scan response from {payload.ip_address} on port {payload.port.value} " + f"({payload.port.name}) over {payload.protocol.name}" + ) + + def _process_port_scan_request(self, payload: PortScanPayload, session_id: str) -> None: + """ + Process a port scan request. + + :param payload: The port scan payload received in the request. + :type payload: PortScanPayload + :param session_id: The session ID for the port scan request. + :type session_id: str + """ + if self.software_manager.check_port_is_open(port=payload.port, protocol=payload.protocol): + payload.request = False + self.sys_log.info( + f"{self.name}: Responding to port scan request for port {payload.port.value} " + f"({payload.port.name}) over {payload.protocol.name}", + ) + self.software_manager.send_payload_to_session_manager(payload=payload, session_id=session_id) + + @validate_call() + def port_scan( + self, + target_ip_address: Union[IPV4Address, List[IPV4Address], IPv4Network, List[IPv4Network]], + target_protocol: Optional[Union[IPProtocol, List[IPProtocol]]] = None, + target_port: Optional[Union[Port, List[Port]]] = None, + show: bool = True, + json_serializable: bool = False, + ) -> Dict[IPv4Address, Dict[IPProtocol, List[Port]]]: + """ + Perform a port scan on the target IP address(es). + + :param target_ip_address: The target IP address(es) or network(s) for the port scan. + :type target_ip_address: Union[IPV4Address, List[IPV4Address], IPv4Network, List[IPv4Network]] + :param target_protocol: The protocol(s) to use for the port scan. Defaults to None, which includes TCP and UDP. + :type target_protocol: Optional[Union[IPProtocol, List[IPProtocol]]] + :param target_port: The port(s) to scan. Defaults to None, which includes all valid ports. + :type target_port: Optional[Union[Port, List[Port]]] + :param show: Flag indicating whether to display the scan results. Defaults to True. + :type show: bool + :param json_serializable: Flag indicating whether the return value should be JSON serializable. Defaults to + False. + :type json_serializable: bool + + :return: A dictionary mapping IP addresses to protocols and lists of open ports. + :rtype: Dict[IPv4Address, Dict[IPProtocol, List[Port]]] + """ + ip_addresses = self._explode_ip_address_network_array(target_ip_address) + + if isinstance(target_port, Port): + target_port = [target_port] + elif target_port is None: + target_port = [port for port in Port if port not in {Port.NONE, Port.UNUSED}] + + if isinstance(target_protocol, IPProtocol): + target_protocol = [target_protocol] + elif target_protocol is None: + target_protocol = [IPProtocol.TCP, IPProtocol.UDP] + + scan_type = self._determine_port_scan_type(list(ip_addresses), target_port) + active_ports = {} + if show: + table = PrettyTable(["IP Address", "Port", "Name", "Protocol"]) + table.align = "l" + table.title = f"{self.software_manager.node.hostname} NMAP Port Scan ({scan_type})" + self.sys_log.info(f"{self.name}: Starting port scan") + for ip_address in ip_addresses: + # Prevent port scan on this node + if self.software_manager.node.ip_is_network_interface(ip_address=ip_address): + continue + for protocol in target_protocol: + for port in set(target_port): + port_open = self._check_port_open_on_ip_address(ip_address=ip_address, port=port, protocol=protocol) + + if port_open: + if show: + table.add_row([ip_address, port.value, port.name, protocol.name]) + _ip_address = ip_address if not json_serializable else str(ip_address) + _protocol = protocol if not json_serializable else protocol.value + _port = port if not json_serializable else port.value + if _ip_address not in active_ports: + active_ports[_ip_address] = dict() + if _protocol not in active_ports[_ip_address]: + active_ports[_ip_address][_protocol] = [] + active_ports[_ip_address][_protocol].append(_port) + + if show: + print(table.get_string(sortby="IP Address")) + + return active_ports + + def network_service_recon( + self, + target_ip_address: Union[IPV4Address, List[IPV4Address], IPv4Network, List[IPv4Network]], + target_protocol: Optional[Union[IPProtocol, List[IPProtocol]]] = None, + target_port: Optional[Union[Port, List[Port]]] = None, + show: bool = True, + show_online_only: bool = True, + json_serializable: bool = False, + ) -> Dict[IPv4Address, Dict[IPProtocol, List[Port]]]: + """ + Perform a network service reconnaissance which includes a ping scan followed by a port scan. + + This method combines the functionalities of a ping scan and a port scan to provide a comprehensive + overview of the services on the network. It first identifies active hosts in the target IP range by performing + a ping scan. Once the active hosts are identified, it performs a port scan on these hosts to identify open + ports and running services. This two-step process ensures that the port scan is performed only on live hosts, + optimising the scanning process and providing accurate results. + + :param target_ip_address: The target IP address(es) or network(s) for the port scan. + :type target_ip_address: Union[IPV4Address, List[IPV4Address], IPv4Network, List[IPv4Network]] + :param target_protocol: The protocol(s) to use for the port scan. Defaults to None, which includes TCP and UDP. + :type target_protocol: Optional[Union[IPProtocol, List[IPProtocol]]] + :param target_port: The port(s) to scan. Defaults to None, which includes all valid ports. + :type target_port: Optional[Union[Port, List[Port]]] + :param show: Flag indicating whether to display the scan results. Defaults to True. + :type show: bool + :param show_online_only: Flag indicating whether to show only the online hosts. Defaults to True. + :type show_online_only: bool + :param json_serializable: Flag indicating whether the return value should be JSON serializable. Defaults to + False. + :type json_serializable: bool + + :return: A dictionary mapping IP addresses to protocols and lists of open ports. + :rtype: Dict[IPv4Address, Dict[IPProtocol, List[Port]]] + """ + ping_scan_results = self.ping_scan( + target_ip_address=target_ip_address, show=show, show_online_only=show_online_only, json_serializable=False + ) + return self.port_scan( + target_ip_address=ping_scan_results, + target_protocol=target_protocol, + target_port=target_port, + show=show, + json_serializable=json_serializable, + ) + + def receive(self, payload: Any, session_id: str, **kwargs) -> bool: + """ + Receive and process a payload. + + :param payload: The payload to be processed. + :type payload: Any + :param session_id: The session ID associated with the payload. + :type session_id: str + + :return: True if the payload was successfully processed, False otherwise. + :rtype: bool + """ + if isinstance(payload, PortScanPayload): + if payload.request: + self._process_port_scan_request(payload=payload, session_id=session_id) + else: + self._process_port_scan_response(payload=payload) + + return True diff --git a/src/primaite/simulator/system/applications/red_applications/__init__.py b/src/primaite/simulator/system/applications/red_applications/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/system/applications/red_applications/__init__.py +++ b/src/primaite/simulator/system/applications/red_applications/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/system/applications/red_applications/data_manipulation_bot.py b/src/primaite/simulator/system/applications/red_applications/data_manipulation_bot.py index 44ffda09..cf03d901 100644 --- a/src/primaite/simulator/system/applications/red_applications/data_manipulation_bot.py +++ b/src/primaite/simulator/system/applications/red_applications/data_manipulation_bot.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from enum import IntEnum from ipaddress import IPv4Address from typing import Dict, Optional diff --git a/src/primaite/simulator/system/applications/red_applications/dos_bot.py b/src/primaite/simulator/system/applications/red_applications/dos_bot.py index 0e45aad9..65e34227 100644 --- a/src/primaite/simulator/system/applications/red_applications/dos_bot.py +++ b/src/primaite/simulator/system/applications/red_applications/dos_bot.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from enum import IntEnum from ipaddress import IPv4Address from typing import Optional diff --git a/src/primaite/simulator/system/applications/red_applications/ransomware_script.py b/src/primaite/simulator/system/applications/red_applications/ransomware_script.py index 8acc07b4..af4a59d4 100644 --- a/src/primaite/simulator/system/applications/red_applications/ransomware_script.py +++ b/src/primaite/simulator/system/applications/red_applications/ransomware_script.py @@ -1,8 +1,7 @@ -from enum import IntEnum +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address from typing import Dict, Optional -from primaite.game.science import simulate_trial from primaite.interface.request import RequestResponse from primaite.simulator.core import RequestManager, RequestType from primaite.simulator.network.transmission.network_layer import IPProtocol @@ -11,43 +10,10 @@ from primaite.simulator.system.applications.application import Application from primaite.simulator.system.applications.database_client import DatabaseClient, DatabaseClientConnection -class RansomwareAttackStage(IntEnum): - """ - Enumeration representing different attack stages of the ransomware script. - - This enumeration defines the various stages a data manipulation attack can be in during its lifecycle - in the simulation. - Each stage represents a specific phase in the attack process. - """ - - NOT_STARTED = 0 - "Indicates that the attack has not started yet." - DOWNLOAD = 1 - "Installing the Encryption Script - Testing" - INSTALL = 2 - "The stage where logon procedures are simulated." - ACTIVATE = 3 - "Operating Status Changes" - PROPAGATE = 4 - "Represents the stage of performing a horizontal port scan on the target." - COMMAND_AND_CONTROL = 5 - "Represents the stage of setting up a rely C2 Beacon (Not Implemented)" - PAYLOAD = 6 - "Stage of actively attacking the target." - SUCCEEDED = 7 - "Indicates the attack has been successfully completed." - FAILED = 8 - "Signifies that the attack has failed." - - class RansomwareScript(Application): """Ransomware Kill Chain - Designed to be used by the TAP001 Agent on the example layout Network. - :ivar payload: The attack stage query payload. (Default Corrupt) - :ivar target_scan_p_of_success: The probability of success for the target scan stage. - :ivar c2_beacon_p_of_success: The probability of success for the c2_beacon stage - :ivar ransomware_encrypt_p_of_success: The probability of success for the ransomware 'attack' (encrypt) stage. - :ivar repeat: Whether to repeat attacking once finished. + :ivar payload: The attack stage query payload. (Default ENCRYPT) """ server_ip_address: Optional[IPv4Address] = None @@ -56,16 +22,6 @@ class RansomwareScript(Application): """Password required to access the database.""" payload: Optional[str] = "ENCRYPT" "Payload String for the payload stage" - target_scan_p_of_success: float = 0.9 - "Probability of the target scan succeeding: Default 0.9" - c2_beacon_p_of_success: float = 0.9 - "Probability of the c2 beacon setup stage succeeding: Default 0.9" - ransomware_encrypt_p_of_success: float = 0.9 - "Probability of the ransomware attack succeeding: Default 0.9" - repeat: bool = False - "If true, the Denial of Service bot will keep performing the attack." - attack_stage: RansomwareAttackStage = RansomwareAttackStage.NOT_STARTED - "The ransomware attack stage. See RansomwareAttackStage Class" def __init__(self, **kwargs): kwargs["name"] = "RansomwareScript" @@ -90,7 +46,7 @@ class RansomwareScript(Application): @property def _host_db_client(self) -> DatabaseClient: """Return the database client that is installed on the same machine as the Ransomware Script.""" - db_client = self.software_manager.software.get("DatabaseClient") + db_client: DatabaseClient = self.software_manager.software.get("DatabaseClient") if db_client is None: self.sys_log.warning(f"{self.__class__.__name__} cannot find a database client on its host.") return db_client @@ -108,16 +64,6 @@ class RansomwareScript(Application): ) return rm - def _activate(self): - """ - Simulate the install process as the initial stage of the attack. - - Advances the attack stage to 'ACTIVATE' attack state. - """ - if self.attack_stage == RansomwareAttackStage.INSTALL: - self.sys_log.info(f"{self.name}: Activated!") - self.attack_stage = RansomwareAttackStage.ACTIVATE - def run(self) -> bool: """Calls the parent classes execute method before starting the application loop.""" super().run() @@ -133,20 +79,9 @@ class RansomwareScript(Application): return False if self.server_ip_address and self.payload: self.sys_log.info(f"{self.name}: Running") - self.attack_stage = RansomwareAttackStage.NOT_STARTED - self._local_download() - self._install() - self._activate() - self._perform_target_scan() - self._setup_beacon() - self._perform_ransomware_encrypt() - - if self.repeat and self.attack_stage in ( - RansomwareAttackStage.SUCCEEDED, - RansomwareAttackStage.FAILED, - ): - self.attack_stage = RansomwareAttackStage.NOT_STARTED - return True + if self._perform_ransomware_encrypt(): + return True + return False else: self.sys_log.warning(f"{self.name}: Failed to start as it requires both a target_ip_address and payload.") return False @@ -156,10 +91,6 @@ class RansomwareScript(Application): server_ip_address: IPv4Address, server_password: Optional[str] = None, payload: Optional[str] = None, - target_scan_p_of_success: Optional[float] = None, - c2_beacon_p_of_success: Optional[float] = None, - ransomware_encrypt_p_of_success: Optional[float] = None, - repeat: bool = True, ): """ Configure the Ransomware Script to communicate with a DatabaseService. @@ -167,10 +98,6 @@ class RansomwareScript(Application): :param server_ip_address: The IP address of the Node the DatabaseService is on. :param server_password: The password on the DatabaseService. :param payload: The attack stage query (Encrypt / Delete) - :param target_scan_p_of_success: The probability of success for the target scan stage. - :param c2_beacon_p_of_success: The probability of success for the c2_beacon stage - :param ransomware_encrypt_p_of_success: The probability of success for the ransomware 'attack' (encrypt) stage. - :param repeat: Whether to repeat attacking once finished. """ if server_ip_address: self.server_ip_address = server_ip_address @@ -178,74 +105,15 @@ class RansomwareScript(Application): self.server_password = server_password if payload: self.payload = payload - if target_scan_p_of_success: - self.target_scan_p_of_success = target_scan_p_of_success - if c2_beacon_p_of_success: - self.c2_beacon_p_of_success = c2_beacon_p_of_success - if ransomware_encrypt_p_of_success: - self.ransomware_encrypt_p_of_success = ransomware_encrypt_p_of_success - if repeat: - self.repeat = repeat self.sys_log.info( - f"{self.name}: Configured the {self.name} with {server_ip_address=}, {payload=}, {server_password=}, " - f"{repeat=}." + f"{self.name}: Configured the {self.name} with {server_ip_address=}, {payload=}, {server_password=}." ) - def _install(self): - """ - Simulate the install stage in the kill-chain. - - Advances the attack stage to 'ACTIVATE' if successful. - - From this attack stage onwards. - the ransomware application is now visible from this point onwardin the observation space. - """ - if self.attack_stage == RansomwareAttackStage.DOWNLOAD: - self.sys_log.info(f"{self.name}: Malware installed on the local file system") - downloads_folder = self.file_system.get_folder(folder_name="downloads") - ransomware_file = downloads_folder.get_file(file_name="ransom_script.pdf") - ransomware_file.num_access += 1 - self.attack_stage = RansomwareAttackStage.INSTALL - - def _setup_beacon(self): - """ - Simulates setting up a c2 beacon; currently a pseudo step for increasing red variance. - - Advances the attack stage to 'COMMAND AND CONTROL` if successful. - - :param p_of_sucess: Probability of a successful c2 setup (Advancing this step), - by default the success rate is 0.5 - """ - if self.attack_stage == RansomwareAttackStage.PROPAGATE: - self.sys_log.info(f"{self.name} Attempting to set up C&C Beacon - Scan 1/2") - if simulate_trial(self.c2_beacon_p_of_success): - self.sys_log.info(f"{self.name} C&C Successful setup - Scan 2/2") - c2c_setup = True # TODO Implement the c2c step via an FTP Application/Service - if c2c_setup: - self.attack_stage = RansomwareAttackStage.COMMAND_AND_CONTROL - - def _perform_target_scan(self): - """ - Perform a simulated port scan to check for open SQL ports. - - Advances the attack stage to `PROPAGATE` if successful. - - :param p_of_success: Probability of successful port scan, by default 0.1. - """ - if self.attack_stage == RansomwareAttackStage.ACTIVATE: - # perform a port scan to identify that the SQL port is open on the server - self.sys_log.info(f"{self.name}: Scanning for vulnerable databases - Scan 0/2") - if simulate_trial(self.target_scan_p_of_success): - self.sys_log.info(f"{self.name}: Found a target database! Scan 1/2") - port_is_open = True # TODO Implement a NNME Triggering scan as a seperate Red Application - if port_is_open: - self.attack_stage = RansomwareAttackStage.PROPAGATE - def attack(self) -> bool: """Perform the attack steps after opening the application.""" + self.run() if not self._can_perform_action(): self.sys_log.warning("Ransomware application is unable to perform it's actions.") - self.run() self.num_executions += 1 return self._application_loop() @@ -254,57 +122,30 @@ class RansomwareScript(Application): self._db_connection = self._host_db_client.get_new_connection() return True if self._db_connection else False - def _perform_ransomware_encrypt(self): + def _perform_ransomware_encrypt(self) -> bool: """ Execute the Ransomware Encrypt payload on the target. Advances the attack stage to `COMPLETE` if successful, or 'FAILED' if unsuccessful. - :param p_of_success: Probability of successfully performing ransomware encryption, by default 0.1. """ if self._host_db_client is None: self.sys_log.info(f"{self.name}: Failed to connect to db_client - Ransomware Script") - self.attack_stage = RansomwareAttackStage.FAILED - return + return False self._host_db_client.server_ip_address = self.server_ip_address self._host_db_client.server_password = self.server_password - if self.attack_stage == RansomwareAttackStage.COMMAND_AND_CONTROL: - if simulate_trial(self.ransomware_encrypt_p_of_success): - self.sys_log.info(f"{self.name}: Attempting to launch payload") - if not self._db_connection: - self._establish_db_connection() - if self._db_connection: - attack_successful = self._db_connection.query(self.payload) - self.sys_log.info(f"{self.name} Payload delivered: {self.payload}") - if attack_successful: - self.sys_log.info(f"{self.name}: Payload Successful") - self.attack_stage = RansomwareAttackStage.SUCCEEDED - else: - self.sys_log.info(f"{self.name}: Payload failed") - self.attack_stage = RansomwareAttackStage.FAILED + self.sys_log.info(f"{self.name}: Attempting to launch payload") + if not self._db_connection: + self._establish_db_connection() + if self._db_connection: + attack_successful = self._db_connection.query(self.payload) + self.sys_log.info(f"{self.name} Payload delivered: {self.payload}") + if attack_successful: + self.sys_log.info(f"{self.name}: Payload Successful") + return True + else: + self.sys_log.info(f"{self.name}: Payload failed") + return False else: self.sys_log.warning("Attack Attempted to launch too quickly") - self.attack_stage = RansomwareAttackStage.FAILED - - def _local_download(self): - """Downloads itself via the onto the local file_system.""" - if self.attack_stage == RansomwareAttackStage.NOT_STARTED: - if self._local_download_verify(): - self.attack_stage = RansomwareAttackStage.DOWNLOAD - else: - self.sys_log.info("Malware failed to create a installation location") - self.attack_stage = RansomwareAttackStage.FAILED - else: - self.sys_log.info("Malware failed to download") - self.attack_stage = RansomwareAttackStage.FAILED - - def _local_download_verify(self) -> bool: - """Verifies a download location - Creates one if needed.""" - for folder in self.file_system.folders: - if self.file_system.folders[folder].name == "downloads": - self.file_system.num_file_creations += 1 - return True - - self.file_system.create_folder("downloads") - self.file_system.create_file(folder_name="downloads", file_name="ransom_script.pdf") - return True + return False diff --git a/src/primaite/simulator/system/applications/web_browser.py b/src/primaite/simulator/system/applications/web_browser.py index 0e6fec00..19cc4065 100644 --- a/src/primaite/simulator/system/applications/web_browser.py +++ b/src/primaite/simulator/system/applications/web_browser.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from enum import Enum from ipaddress import IPv4Address from typing import Dict, List, Optional diff --git a/src/primaite/simulator/system/core/__init__.py b/src/primaite/simulator/system/core/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/system/core/__init__.py +++ b/src/primaite/simulator/system/core/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/system/core/packet_capture.py b/src/primaite/simulator/system/core/packet_capture.py index bc8a0584..ea8b00a5 100644 --- a/src/primaite/simulator/system/core/packet_capture.py +++ b/src/primaite/simulator/system/core/packet_capture.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import json import logging from pathlib import Path diff --git a/src/primaite/simulator/system/core/session_manager.py b/src/primaite/simulator/system/core/session_manager.py index 68f44dca..b7e2c021 100644 --- a/src/primaite/simulator/system/core/session_manager.py +++ b/src/primaite/simulator/system/core/session_manager.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations from ipaddress import IPv4Address, IPv4Network diff --git a/src/primaite/simulator/system/core/software_manager.py b/src/primaite/simulator/system/core/software_manager.py index 0487cb7b..e2266c2d 100644 --- a/src/primaite/simulator/system/core/software_manager.py +++ b/src/primaite/simulator/system/core/software_manager.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address, IPv4Network from typing import Any, Dict, List, Optional, Tuple, TYPE_CHECKING, Union @@ -78,6 +79,31 @@ class SoftwareManager: open_ports.append(software.port) return open_ports + def check_port_is_open(self, port: Port, protocol: IPProtocol) -> bool: + """ + Check if a specific port is open and running a service using the specified protocol. + + This method iterates through all installed software on the node and checks if any of them + are using the specified port and protocol and are currently in a running state. It returns True if any software + is found running on the specified port and protocol, otherwise False. + + + :param port: The port to check. + :type port: Port + :param protocol: The protocol to check (e.g., TCP, UDP). + :type protocol: IPProtocol + :return: True if the port is open and a service is running on it using the specified protocol, False otherwise. + :rtype: bool + """ + for software in self.software.values(): + if ( + software.port == port + and software.protocol == protocol + and software.operating_state in {ApplicationOperatingState.RUNNING, ServiceOperatingState.RUNNING} + ): + return True + return False + def install(self, software_class: Type[IOSoftwareClass]): """ Install an Application or Service. @@ -150,6 +176,7 @@ class SoftwareManager: self, payload: Any, dest_ip_address: Optional[Union[IPv4Address, IPv4Network]] = None, + src_port: Optional[Port] = None, dest_port: Optional[Port] = None, ip_protocol: IPProtocol = IPProtocol.TCP, session_id: Optional[str] = None, @@ -170,6 +197,7 @@ class SoftwareManager: return self.session_manager.receive_payload_from_software_manager( payload=payload, dst_ip_address=dest_ip_address, + src_port=src_port, dst_port=dest_port, ip_protocol=ip_protocol, session_id=session_id, @@ -190,6 +218,9 @@ class SoftwareManager: :param payload: The payload being received. :param session: The transport session the payload originates from. """ + if payload.__class__.__name__ == "PortScanPayload": + self.software.get("NMAP").receive(payload=payload, session_id=session_id) + return receiver: Optional[Union[Service, Application]] = self.port_protocol_mapping.get((port, protocol), None) if receiver: receiver.receive( diff --git a/src/primaite/simulator/system/core/sys_log.py b/src/primaite/simulator/system/core/sys_log.py index cf68b674..9e22696d 100644 --- a/src/primaite/simulator/system/core/sys_log.py +++ b/src/primaite/simulator/system/core/sys_log.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import logging from pathlib import Path diff --git a/src/primaite/simulator/system/processes/__init__.py b/src/primaite/simulator/system/processes/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/system/processes/__init__.py +++ b/src/primaite/simulator/system/processes/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/system/processes/process.py b/src/primaite/simulator/system/processes/process.py index 458a6b5c..225505c8 100644 --- a/src/primaite/simulator/system/processes/process.py +++ b/src/primaite/simulator/system/processes/process.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from abc import abstractmethod from enum import Enum from typing import Dict diff --git a/src/primaite/simulator/system/services/__init__.py b/src/primaite/simulator/system/services/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/system/services/__init__.py +++ b/src/primaite/simulator/system/services/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/system/services/arp/__init__.py b/src/primaite/simulator/system/services/arp/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/system/services/arp/__init__.py +++ b/src/primaite/simulator/system/services/arp/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/system/services/arp/arp.py b/src/primaite/simulator/system/services/arp/arp.py index bfbc8c9c..efadf189 100644 --- a/src/primaite/simulator/system/services/arp/arp.py +++ b/src/primaite/simulator/system/services/arp/arp.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from __future__ import annotations from abc import abstractmethod @@ -137,6 +138,14 @@ class ARP(Service): target_ip_address ) if outbound_network_interface: + # ensure we are not attempting to find the network address or broadcast address (not useable IPs) + if target_ip_address == outbound_network_interface.ip_network.network_address: + self.sys_log.info(f"Cannot send ARP request to a network address {str(target_ip_address)}") + return + if target_ip_address == outbound_network_interface.ip_network.broadcast_address: + self.sys_log.info(f"Cannot send ARP request to a broadcast address {str(target_ip_address)}") + return + self.sys_log.info(f"Sending ARP request from NIC {outbound_network_interface} for ip {target_ip_address}") arp_packet = ARPPacket( sender_ip_address=outbound_network_interface.ip_address, diff --git a/src/primaite/simulator/system/services/database/__init__.py b/src/primaite/simulator/system/services/database/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/system/services/database/__init__.py +++ b/src/primaite/simulator/system/services/database/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/system/services/database/database_service.py b/src/primaite/simulator/system/services/database/database_service.py index 861b5c7d..cbd640f6 100644 --- a/src/primaite/simulator/system/services/database/database_service.py +++ b/src/primaite/simulator/system/services/database/database_service.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address from typing import Any, Dict, List, Literal, Optional, Union from uuid import uuid4 diff --git a/src/primaite/simulator/system/services/dns/__init__.py b/src/primaite/simulator/system/services/dns/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/system/services/dns/__init__.py +++ b/src/primaite/simulator/system/services/dns/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/system/services/dns/dns_client.py b/src/primaite/simulator/system/services/dns/dns_client.py index 063ff74f..d7ba0cd4 100644 --- a/src/primaite/simulator/system/services/dns/dns_client.py +++ b/src/primaite/simulator/system/services/dns/dns_client.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address from typing import Dict, Optional diff --git a/src/primaite/simulator/system/services/dns/dns_server.py b/src/primaite/simulator/system/services/dns/dns_server.py index 7dbc5d60..8a4bbaed 100644 --- a/src/primaite/simulator/system/services/dns/dns_server.py +++ b/src/primaite/simulator/system/services/dns/dns_server.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address from typing import Any, Dict, Optional diff --git a/src/primaite/simulator/system/services/ftp/__init__.py b/src/primaite/simulator/system/services/ftp/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/system/services/ftp/__init__.py +++ b/src/primaite/simulator/system/services/ftp/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/system/services/ftp/ftp_client.py b/src/primaite/simulator/system/services/ftp/ftp_client.py index 4eb18f6a..28a591dd 100644 --- a/src/primaite/simulator/system/services/ftp/ftp_client.py +++ b/src/primaite/simulator/system/services/ftp/ftp_client.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address from typing import Optional diff --git a/src/primaite/simulator/system/services/ftp/ftp_server.py b/src/primaite/simulator/system/services/ftp/ftp_server.py index a361b0ee..f02d01f4 100644 --- a/src/primaite/simulator/system/services/ftp/ftp_server.py +++ b/src/primaite/simulator/system/services/ftp/ftp_server.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from typing import Any, Optional from primaite import getLogger diff --git a/src/primaite/simulator/system/services/ftp/ftp_service.py b/src/primaite/simulator/system/services/ftp/ftp_service.py index b89ae1a2..689a3da7 100644 --- a/src/primaite/simulator/system/services/ftp/ftp_service.py +++ b/src/primaite/simulator/system/services/ftp/ftp_service.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from abc import ABC from ipaddress import IPv4Address from typing import Dict, Optional diff --git a/src/primaite/simulator/system/services/icmp/__init__.py b/src/primaite/simulator/system/services/icmp/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/system/services/icmp/__init__.py +++ b/src/primaite/simulator/system/services/icmp/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/system/services/icmp/icmp.py b/src/primaite/simulator/system/services/icmp/icmp.py index c4b4173f..6741d86a 100644 --- a/src/primaite/simulator/system/services/icmp/icmp.py +++ b/src/primaite/simulator/system/services/icmp/icmp.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import secrets from ipaddress import IPv4Address from typing import Any, Dict, Optional, Tuple, Union @@ -60,7 +61,7 @@ class ICMP(Service): if target_ip_address.is_loopback: self.sys_log.info("Pinging loopback address") return any(network_interface.enabled for network_interface in self.network_interfaces.values()) - self.sys_log.info(f"Pinging {target_ip_address}:", to_terminal=True) + self.sys_log.info(f"Pinging {target_ip_address}:", to_terminal=False) sequence, identifier = 0, None while sequence < pings: sequence, identifier = self._send_icmp_echo_request(target_ip_address, sequence, identifier, pings) @@ -76,7 +77,7 @@ class ICMP(Service): f"Received = {request_replies}, " f"Lost = {pings - request_replies} ({(pings - request_replies) / pings * 100}% loss)" ) - self.sys_log.info(output, to_terminal=True) + self.sys_log.info(output, to_terminal=False) return passed @@ -166,7 +167,7 @@ class ICMP(Service): f"bytes={len(frame.payload)}, " f"time={time_str}, " f"TTL={frame.ip.ttl}", - to_terminal=True, + to_terminal=False, ) if not self.request_replies.get(frame.icmp.identifier): self.request_replies[frame.icmp.identifier] = 0 diff --git a/src/primaite/simulator/system/services/icmp/router_icmp.py b/src/primaite/simulator/system/services/icmp/router_icmp.py index 5dcba3f1..4fdc6baa 100644 --- a/src/primaite/simulator/system/services/icmp/router_icmp.py +++ b/src/primaite/simulator/system/services/icmp/router_icmp.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK # class RouterICMP(ICMP): # """ # A class to represent a router's Internet Control Message Protocol (ICMP) handler. diff --git a/src/primaite/simulator/system/services/ntp/__init__.py b/src/primaite/simulator/system/services/ntp/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/system/services/ntp/__init__.py +++ b/src/primaite/simulator/system/services/ntp/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/system/services/ntp/ntp_client.py b/src/primaite/simulator/system/services/ntp/ntp_client.py index dcc502c7..8924a821 100644 --- a/src/primaite/simulator/system/services/ntp/ntp_client.py +++ b/src/primaite/simulator/system/services/ntp/ntp_client.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from datetime import datetime from ipaddress import IPv4Address from typing import Dict, Optional diff --git a/src/primaite/simulator/system/services/ntp/ntp_server.py b/src/primaite/simulator/system/services/ntp/ntp_server.py index 01d10b84..547bbc06 100644 --- a/src/primaite/simulator/system/services/ntp/ntp_server.py +++ b/src/primaite/simulator/system/services/ntp/ntp_server.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from datetime import datetime from typing import Dict, Optional diff --git a/src/primaite/simulator/system/services/service.py b/src/primaite/simulator/system/services/service.py index caaefc06..e6ce2c87 100644 --- a/src/primaite/simulator/system/services/service.py +++ b/src/primaite/simulator/system/services/service.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from abc import abstractmethod from enum import Enum from typing import Any, Dict, Optional diff --git a/src/primaite/simulator/system/services/web_server/__init__.py b/src/primaite/simulator/system/services/web_server/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/simulator/system/services/web_server/__init__.py +++ b/src/primaite/simulator/system/services/web_server/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/simulator/system/services/web_server/web_server.py b/src/primaite/simulator/system/services/web_server/web_server.py index 3141a697..6f6fa335 100644 --- a/src/primaite/simulator/system/services/web_server/web_server.py +++ b/src/primaite/simulator/system/services/web_server/web_server.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address from typing import Any, Dict, Optional from urllib.parse import urlparse diff --git a/src/primaite/simulator/system/software.py b/src/primaite/simulator/system/software.py index b533f7c0..7ea67dcd 100644 --- a/src/primaite/simulator/system/software.py +++ b/src/primaite/simulator/system/software.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import copy from abc import abstractmethod from datetime import datetime diff --git a/src/primaite/utils/__init__.py b/src/primaite/utils/__init__.py index 4f9deb13..4d7c430e 100644 --- a/src/primaite/utils/__init__.py +++ b/src/primaite/utils/__init__.py @@ -1,2 +1,2 @@ -# © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK """Utilities for PrimAITE.""" diff --git a/src/primaite/utils/cli/__init__.py b/src/primaite/utils/cli/__init__.py index e69de29b..be6c00e7 100644 --- a/src/primaite/utils/cli/__init__.py +++ b/src/primaite/utils/cli/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/src/primaite/utils/cli/dev_cli.py b/src/primaite/utils/cli/dev_cli.py index d2c8e370..15adacb3 100644 --- a/src/primaite/utils/cli/dev_cli.py +++ b/src/primaite/utils/cli/dev_cli.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import click import typer from rich import print diff --git a/src/primaite/utils/cli/primaite_config_utils.py b/src/primaite/utils/cli/primaite_config_utils.py index fa9b68ff..635be5a7 100644 --- a/src/primaite/utils/cli/primaite_config_utils.py +++ b/src/primaite/utils/cli/primaite_config_utils.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from typing import Dict, Optional import yaml diff --git a/src/primaite/utils/converters.py b/src/primaite/utils/converters.py new file mode 100644 index 00000000..f803851d --- /dev/null +++ b/src/primaite/utils/converters.py @@ -0,0 +1,26 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK +from enum import Enum +from typing import Any, Dict + + +def convert_dict_enum_keys_to_enum_values(d: Dict[Any, Any]) -> Dict[Any, Any]: + """ + Convert dictionary keys from enums to their corresponding values. + + :param d: dict + The dictionary with enum keys to be converted. + :return: dict + The dictionary with enum values as keys. + """ + result = {} + for key, value in d.items(): + if isinstance(key, Enum): + new_key = key.value + else: + new_key = key + + if isinstance(value, dict): + result[new_key] = convert_dict_enum_keys_to_enum_values(value) + else: + result[new_key] = value + return result diff --git a/src/primaite/utils/package_data.py b/src/primaite/utils/package_data.py index ac41e8bc..af0252f9 100644 --- a/src/primaite/utils/package_data.py +++ b/src/primaite/utils/package_data.py @@ -1,4 +1,4 @@ -# © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import os from logging import Logger from pathlib import Path diff --git a/src/primaite/utils/session_metadata_parser.py b/src/primaite/utils/session_metadata_parser.py index 083d55ba..f6594666 100644 --- a/src/primaite/utils/session_metadata_parser.py +++ b/src/primaite/utils/session_metadata_parser.py @@ -1,8 +1,8 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK # flake8: noqa raise DeprecationWarning( "Benchmarking depends on deprecated functionality and it has not been updated to primaite v3 yet." ) -# © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK import json from pathlib import Path from typing import Any, Dict, Union diff --git a/src/primaite/utils/session_output_reader.py b/src/primaite/utils/session_output_reader.py index c6eb2f7b..b9ad68a1 100644 --- a/src/primaite/utils/session_output_reader.py +++ b/src/primaite/utils/session_output_reader.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK # flake8: noqa raise DeprecationWarning( "Benchmarking depends on deprecated functionality and it has not been updated to primaite v3 yet." diff --git a/src/primaite/utils/session_output_writer.py b/src/primaite/utils/session_output_writer.py index a5acdee6..75a97f60 100644 --- a/src/primaite/utils/session_output_writer.py +++ b/src/primaite/utils/session_output_writer.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK # flake8: noqa raise DeprecationWarning( "Benchmarking depends on deprecated functionality and it has not been updated to primaite v3 yet." diff --git a/src/primaite/utils/validators.py b/src/primaite/utils/validators.py index fb7abb29..139d303c 100644 --- a/src/primaite/utils/validators.py +++ b/src/primaite/utils/validators.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address from typing import Any, Final diff --git a/tests/__init__.py b/tests/__init__.py index 5a06b646..846ec808 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,4 +1,4 @@ -# © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from pathlib import Path from typing import Final diff --git a/tests/assets/configs/bad_primaite_session.yaml b/tests/assets/configs/bad_primaite_session.yaml index 231c69ab..8cbd3ae9 100644 --- a/tests/assets/configs/bad_primaite_session.yaml +++ b/tests/assets/configs/bad_primaite_session.yaml @@ -286,7 +286,7 @@ agents: 22: # "ACL: ADDRULE - Block outgoing traffic from client 1" (not supported in Primaite) action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -299,7 +299,7 @@ agents: 23: # "ACL: ADDRULE - Block outgoing traffic from client 2" (not supported in Primaite) action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -312,7 +312,7 @@ agents: 24: # block tcp traffic from client 1 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -325,7 +325,7 @@ agents: 25: # block tcp traffic from client 2 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -338,7 +338,7 @@ agents: 26: action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -351,7 +351,7 @@ agents: 27: action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -364,52 +364,52 @@ agents: 28: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 0 29: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 30: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 31: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 32: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 33: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 34: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 35: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 7 36: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 8 37: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 9 38: action: "HOST_NIC_DISABLE" diff --git a/tests/assets/configs/basic_switched_network.yaml b/tests/assets/configs/basic_switched_network.yaml index 0cbaefdb..7d40075d 100644 --- a/tests/assets/configs/basic_switched_network.yaml +++ b/tests/assets/configs/basic_switched_network.yaml @@ -84,6 +84,11 @@ agents: num_files: 1 num_nics: 2 include_num_access: false + monitored_traffic: + icmp: + - NONE + tcp: + - DNS include_nmne: true routers: - hostname: router_1 diff --git a/tests/assets/configs/eval_only_primaite_session.yaml b/tests/assets/configs/eval_only_primaite_session.yaml index 4cf0e68c..de861dcc 100644 --- a/tests/assets/configs/eval_only_primaite_session.yaml +++ b/tests/assets/configs/eval_only_primaite_session.yaml @@ -298,7 +298,7 @@ agents: 22: # "ACL: ADDRULE - Block outgoing traffic from client 1" (not supported in Primaite) action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -311,7 +311,7 @@ agents: 23: # "ACL: ADDRULE - Block outgoing traffic from client 2" (not supported in Primaite) action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -324,7 +324,7 @@ agents: 24: # block tcp traffic from client 1 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -337,7 +337,7 @@ agents: 25: # block tcp traffic from client 2 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -350,7 +350,7 @@ agents: 26: action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -363,7 +363,7 @@ agents: 27: action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -376,52 +376,52 @@ agents: 28: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 0 29: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 30: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 31: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 32: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 33: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 34: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 35: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 7 36: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 8 37: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 9 38: action: "HOST_NIC_DISABLE" diff --git a/tests/assets/configs/multi_agent_session.yaml b/tests/assets/configs/multi_agent_session.yaml index 0c89bef4..971f36f8 100644 --- a/tests/assets/configs/multi_agent_session.yaml +++ b/tests/assets/configs/multi_agent_session.yaml @@ -289,7 +289,7 @@ agents: 22: # "ACL: ADDRULE - Block outgoing traffic from client 1" (not supported in Primaite) action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -302,7 +302,7 @@ agents: 23: # "ACL: ADDRULE - Block outgoing traffic from client 2" (not supported in Primaite) action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -315,7 +315,7 @@ agents: 24: # block tcp traffic from client 1 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -328,7 +328,7 @@ agents: 25: # block tcp traffic from client 2 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -341,7 +341,7 @@ agents: 26: action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -354,7 +354,7 @@ agents: 27: action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -367,52 +367,52 @@ agents: 28: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 0 29: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 30: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 31: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 32: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 33: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 34: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 35: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 7 36: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 8 37: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 9 38: action: "HOST_NIC_DISABLE" @@ -759,7 +759,7 @@ agents: 22: # "ACL: ADDRULE - Block outgoing traffic from client 1" (not supported in Primaite) action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -772,7 +772,7 @@ agents: 23: # "ACL: ADDRULE - Block outgoing traffic from client 2" (not supported in Primaite) action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -785,7 +785,7 @@ agents: 24: # block tcp traffic from client 1 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -798,7 +798,7 @@ agents: 25: # block tcp traffic from client 2 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -811,7 +811,7 @@ agents: 26: action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -824,7 +824,7 @@ agents: 27: action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -837,52 +837,52 @@ agents: 28: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 0 29: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 30: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 31: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 32: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 33: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 34: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 35: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 7 36: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 8 37: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 9 diff --git a/tests/assets/configs/nmap_network_service_recon_red_agent_config.yaml b/tests/assets/configs/nmap_network_service_recon_red_agent_config.yaml new file mode 100644 index 00000000..c5508f13 --- /dev/null +++ b/tests/assets/configs/nmap_network_service_recon_red_agent_config.yaml @@ -0,0 +1,137 @@ +io_settings: + save_step_metadata: false + save_pcap_logs: true + save_sys_logs: true + sys_log_level: WARNING + + + +game: + max_episode_length: 256 + ports: + - ARP + - DNS + - HTTP + - POSTGRES_SERVER + protocols: + - ICMP + - TCP + - UDP + +agents: + - ref: client_1_red_nmap + team: RED + type: ProbabilisticAgent + observation_space: null + action_space: + options: + nodes: + - node_name: client_1 + applications: + - application_name: NMAP + max_folders_per_node: 1 + max_files_per_folder: 1 + max_services_per_node: 1 + max_applications_per_node: 1 + action_list: + - type: NODE_NMAP_NETWORK_SERVICE_RECON + action_map: + 0: + action: NODE_NMAP_NETWORK_SERVICE_RECON + options: + source_node: client_1 + target_ip_address: 192.168.10.0/24 + target_port: 80 + target_protocol: tcp + + reward_function: + reward_components: + - type: DUMMY + + agent_settings: + action_probabilities: + 0: 1.0 + + + +simulation: + network: + nodes: + - hostname: switch_1 + num_ports: 8 + type: switch + + - hostname: switch_2 + num_ports: 8 + type: switch + + - hostname: router_1 + type: router + ports: + 1: + ip_address: 192.168.1.1 + subnet_mask: 255.255.255.0 + 2: + ip_address: 192.168.10.1 + subnet_mask: 255.255.255.0 + acl: + 1: + action: PERMIT + + - hostname: client_1 + type: computer + ip_address: 192.168.10.21 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.10.1 + + - hostname: client_2 + type: computer + ip_address: 192.168.10.22 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.10.1 + + - hostname: server_1 + type: server + ip_address: 192.168.1.10 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.1.1 + + - hostname: server_2 + type: server + ip_address: 192.168.1.14 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.1.1 + + + + + links: + - endpoint_a_hostname: router_1 + endpoint_a_port: 1 + endpoint_b_hostname: switch_1 + endpoint_b_port: 8 + + - endpoint_a_hostname: router_1 + endpoint_a_port: 2 + endpoint_b_hostname: switch_2 + endpoint_b_port: 8 + + - endpoint_a_hostname: client_1 + endpoint_a_port: 1 + endpoint_b_hostname: switch_2 + endpoint_b_port: 1 + + - endpoint_a_hostname: client_2 + endpoint_a_port: 1 + endpoint_b_hostname: switch_2 + endpoint_b_port: 2 + + - endpoint_a_hostname: server_1 + endpoint_a_port: 1 + endpoint_b_hostname: switch_1 + endpoint_b_port: 1 + + - endpoint_a_hostname: server_2 + endpoint_a_port: 1 + endpoint_b_hostname: switch_1 + endpoint_b_port: 2 diff --git a/tests/assets/configs/nmap_ping_scan_red_agent_config.yaml b/tests/assets/configs/nmap_ping_scan_red_agent_config.yaml new file mode 100644 index 00000000..33ba3d19 --- /dev/null +++ b/tests/assets/configs/nmap_ping_scan_red_agent_config.yaml @@ -0,0 +1,135 @@ +io_settings: + save_step_metadata: false + save_pcap_logs: true + save_sys_logs: true + sys_log_level: WARNING + + + +game: + max_episode_length: 256 + ports: + - ARP + - DNS + - HTTP + - POSTGRES_SERVER + protocols: + - ICMP + - TCP + - UDP + +agents: + - ref: client_1_red_nmap + team: RED + type: ProbabilisticAgent + observation_space: null + action_space: + options: + nodes: + - node_name: client_1 + applications: + - application_name: NMAP + max_folders_per_node: 1 + max_files_per_folder: 1 + max_services_per_node: 1 + max_applications_per_node: 1 + action_list: + - type: NODE_NMAP_PING_SCAN + action_map: + 0: + action: NODE_NMAP_PING_SCAN + options: + source_node: client_1 + target_ip_address: 192.168.1.0/24 + + reward_function: + reward_components: + - type: DUMMY + + agent_settings: + action_probabilities: + 0: 1.0 + + + +simulation: + network: + nodes: + - hostname: switch_1 + num_ports: 8 + type: switch + + - hostname: switch_2 + num_ports: 8 + type: switch + + - hostname: router_1 + type: router + ports: + 1: + ip_address: 192.168.1.1 + subnet_mask: 255.255.255.0 + 2: + ip_address: 192.168.10.1 + subnet_mask: 255.255.255.0 + acl: + 1: + action: PERMIT + + - hostname: client_1 + type: computer + ip_address: 192.168.10.21 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.10.1 + + - hostname: client_2 + type: computer + ip_address: 192.168.10.22 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.10.1 + + - hostname: server_1 + type: server + ip_address: 192.168.1.10 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.1.1 + + - hostname: server_2 + type: server + ip_address: 192.168.1.14 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.1.1 + + + + + links: + - endpoint_a_hostname: router_1 + endpoint_a_port: 1 + endpoint_b_hostname: switch_1 + endpoint_b_port: 8 + + - endpoint_a_hostname: router_1 + endpoint_a_port: 2 + endpoint_b_hostname: switch_2 + endpoint_b_port: 8 + + - endpoint_a_hostname: client_1 + endpoint_a_port: 1 + endpoint_b_hostname: switch_2 + endpoint_b_port: 1 + + - endpoint_a_hostname: client_2 + endpoint_a_port: 1 + endpoint_b_hostname: switch_2 + endpoint_b_port: 2 + + - endpoint_a_hostname: server_1 + endpoint_a_port: 1 + endpoint_b_hostname: switch_1 + endpoint_b_port: 1 + + - endpoint_a_hostname: server_2 + endpoint_a_port: 1 + endpoint_b_hostname: switch_1 + endpoint_b_port: 2 diff --git a/tests/assets/configs/nmap_port_scan_red_agent_config.yaml b/tests/assets/configs/nmap_port_scan_red_agent_config.yaml new file mode 100644 index 00000000..08944ee5 --- /dev/null +++ b/tests/assets/configs/nmap_port_scan_red_agent_config.yaml @@ -0,0 +1,135 @@ +io_settings: + save_step_metadata: false + save_pcap_logs: true + save_sys_logs: true + sys_log_level: WARNING + + + +game: + max_episode_length: 256 + ports: + - ARP + - DNS + - HTTP + - POSTGRES_SERVER + protocols: + - ICMP + - TCP + - UDP + +agents: + - ref: client_1_red_nmap + team: RED + type: ProbabilisticAgent + observation_space: null + action_space: + options: + nodes: + - node_name: client_1 + applications: + - application_name: NMAP + max_folders_per_node: 1 + max_files_per_folder: 1 + max_services_per_node: 1 + max_applications_per_node: 1 + action_list: + - type: NODE_NMAP_PORT_SCAN + action_map: + 0: + action: NODE_NMAP_PORT_SCAN + options: + source_node: client_1 + target_ip_address: 192.168.10.0/24 + + reward_function: + reward_components: + - type: DUMMY + + agent_settings: + action_probabilities: + 0: 1.0 + + + +simulation: + network: + nodes: + - hostname: switch_1 + num_ports: 8 + type: switch + + - hostname: switch_2 + num_ports: 8 + type: switch + + - hostname: router_1 + type: router + ports: + 1: + ip_address: 192.168.1.1 + subnet_mask: 255.255.255.0 + 2: + ip_address: 192.168.10.1 + subnet_mask: 255.255.255.0 + acl: + 1: + action: PERMIT + + - hostname: client_1 + type: computer + ip_address: 192.168.10.21 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.10.1 + + - hostname: client_2 + type: computer + ip_address: 192.168.10.22 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.10.1 + + - hostname: server_1 + type: server + ip_address: 192.168.1.10 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.1.1 + + - hostname: server_2 + type: server + ip_address: 192.168.1.14 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.1.1 + + + + + links: + - endpoint_a_hostname: router_1 + endpoint_a_port: 1 + endpoint_b_hostname: switch_1 + endpoint_b_port: 8 + + - endpoint_a_hostname: router_1 + endpoint_a_port: 2 + endpoint_b_hostname: switch_2 + endpoint_b_port: 8 + + - endpoint_a_hostname: client_1 + endpoint_a_port: 1 + endpoint_b_hostname: switch_2 + endpoint_b_port: 1 + + - endpoint_a_hostname: client_2 + endpoint_a_port: 1 + endpoint_b_hostname: switch_2 + endpoint_b_port: 2 + + - endpoint_a_hostname: server_1 + endpoint_a_port: 1 + endpoint_b_hostname: switch_1 + endpoint_b_port: 1 + + - endpoint_a_hostname: server_2 + endpoint_a_port: 1 + endpoint_b_hostname: switch_1 + endpoint_b_port: 2 diff --git a/tests/assets/configs/shared_rewards.yaml b/tests/assets/configs/shared_rewards.yaml index c90e1cc2..81cb85f7 100644 --- a/tests/assets/configs/shared_rewards.yaml +++ b/tests/assets/configs/shared_rewards.yaml @@ -466,7 +466,7 @@ agents: 46: # old action num: 22 # "ACL: ADDRULE - Block outgoing traffic from client 1" action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -479,7 +479,7 @@ agents: 47: # old action num: 23 # "ACL: ADDRULE - Block outgoing traffic from client 2" action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -492,7 +492,7 @@ agents: 48: # old action num: 24 # block tcp traffic from client 1 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -505,7 +505,7 @@ agents: 49: # old action num: 25 # block tcp traffic from client 2 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -518,7 +518,7 @@ agents: 50: # old action num: 26 action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -531,7 +531,7 @@ agents: 51: # old action num: 27 action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -544,52 +544,52 @@ agents: 52: # old action num: 28 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 0 53: # old action num: 29 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 54: # old action num: 30 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 55: # old action num: 31 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 56: # old action num: 32 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 57: # old action num: 33 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 58: # old action num: 34 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 59: # old action num: 35 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 7 60: # old action num: 36 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 8 61: # old action num: 37 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 9 62: # old action num: 38 action: "HOST_NIC_DISABLE" diff --git a/tests/assets/configs/test_primaite_session.yaml b/tests/assets/configs/test_primaite_session.yaml index f41ef475..54143af0 100644 --- a/tests/assets/configs/test_primaite_session.yaml +++ b/tests/assets/configs/test_primaite_session.yaml @@ -307,7 +307,7 @@ agents: 22: # "ACL: ADDRULE - Block outgoing traffic from client 1" (not supported in Primaite) action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -320,7 +320,7 @@ agents: 23: # "ACL: ADDRULE - Block outgoing traffic from client 2" (not supported in Primaite) action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -333,7 +333,7 @@ agents: 24: # block tcp traffic from client 1 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -346,7 +346,7 @@ agents: 25: # block tcp traffic from client 2 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -359,7 +359,7 @@ agents: 26: action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -372,7 +372,7 @@ agents: 27: action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -385,52 +385,52 @@ agents: 28: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 0 29: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 30: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 31: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 32: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 33: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 34: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 35: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 7 36: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 8 37: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 9 38: action: "HOST_NIC_DISABLE" diff --git a/tests/conftest.py b/tests/conftest.py index a20822f3..b8359323 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,4 @@ -# © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from typing import Any, Dict, Tuple import pytest diff --git a/tests/e2e_integration_tests/__init__.py b/tests/e2e_integration_tests/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/e2e_integration_tests/__init__.py +++ b/tests/e2e_integration_tests/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/e2e_integration_tests/environments/__init__.py b/tests/e2e_integration_tests/environments/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/e2e_integration_tests/environments/__init__.py +++ b/tests/e2e_integration_tests/environments/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/e2e_integration_tests/environments/test_rllib_multi_agent_environment.py b/tests/e2e_integration_tests/environments/test_rllib_multi_agent_environment.py index 9b550dd2..96ec799c 100644 --- a/tests/e2e_integration_tests/environments/test_rllib_multi_agent_environment.py +++ b/tests/e2e_integration_tests/environments/test_rllib_multi_agent_environment.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import ray import yaml from ray import air, tune @@ -38,3 +39,4 @@ def test_rllib_multi_agent_compatibility(): ), param_space=config, ).fit() + ray.shutdown() diff --git a/tests/e2e_integration_tests/environments/test_rllib_single_agent_environment.py b/tests/e2e_integration_tests/environments/test_rllib_single_agent_environment.py index f56f0f85..d6cacfd2 100644 --- a/tests/e2e_integration_tests/environments/test_rllib_single_agent_environment.py +++ b/tests/e2e_integration_tests/environments/test_rllib_single_agent_environment.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import tempfile from pathlib import Path @@ -40,3 +41,4 @@ def test_rllib_single_agent_compatibility(): assert save_file.exists() save_file.unlink() # clean up + ray.shutdown() diff --git a/tests/e2e_integration_tests/environments/test_sb3_environment.py b/tests/e2e_integration_tests/environments/test_sb3_environment.py index f654234b..27fb134b 100644 --- a/tests/e2e_integration_tests/environments/test_sb3_environment.py +++ b/tests/e2e_integration_tests/environments/test_sb3_environment.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK """Test that we can create a primaite environment and train sb3 agent with no crash.""" import tempfile from pathlib import Path diff --git a/tests/e2e_integration_tests/test_environment.py b/tests/e2e_integration_tests/test_environment.py index 0a2c6add..c8238aba 100644 --- a/tests/e2e_integration_tests/test_environment.py +++ b/tests/e2e_integration_tests/test_environment.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import pydantic import pytest import yaml diff --git a/tests/e2e_integration_tests/test_uc2_data_manipulation_scenario.py b/tests/e2e_integration_tests/test_uc2_data_manipulation_scenario.py index 5df8f964..e6cd113f 100644 --- a/tests/e2e_integration_tests/test_uc2_data_manipulation_scenario.py +++ b/tests/e2e_integration_tests/test_uc2_data_manipulation_scenario.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import yaml from primaite.game.game import PrimaiteGame diff --git a/tests/integration_tests/__init__.py b/tests/integration_tests/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/integration_tests/__init__.py +++ b/tests/integration_tests/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/integration_tests/cli/__init__.py b/tests/integration_tests/cli/__init__.py index 07487650..cfce7ae6 100644 --- a/tests/integration_tests/cli/__init__.py +++ b/tests/integration_tests/cli/__init__.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from typing import List from typer.testing import CliRunner, Result diff --git a/tests/integration_tests/cli/test_dev_cli.py b/tests/integration_tests/cli/test_dev_cli.py index 8f1bdec6..43f623a5 100644 --- a/tests/integration_tests/cli/test_dev_cli.py +++ b/tests/integration_tests/cli/test_dev_cli.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import os import shutil import tempfile diff --git a/tests/integration_tests/component_creation/__init__.py b/tests/integration_tests/component_creation/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/integration_tests/component_creation/__init__.py +++ b/tests/integration_tests/component_creation/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/integration_tests/component_creation/test_action_integration.py b/tests/integration_tests/component_creation/test_action_integration.py index e7c9fcc6..a6f09436 100644 --- a/tests/integration_tests/component_creation/test_action_integration.py +++ b/tests/integration_tests/component_creation/test_action_integration.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from primaite.simulator.core import RequestType from primaite.simulator.network.hardware.nodes.host.computer import Computer from primaite.simulator.network.hardware.nodes.host.server import Server diff --git a/tests/integration_tests/component_creation/test_permission_system.py b/tests/integration_tests/component_creation/test_permission_system.py index bcadebb4..baf75523 100644 --- a/tests/integration_tests/component_creation/test_permission_system.py +++ b/tests/integration_tests/component_creation/test_permission_system.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from enum import Enum from typing import Dict, List, Literal diff --git a/tests/integration_tests/configuration_file_parsing/__init__.py b/tests/integration_tests/configuration_file_parsing/__init__.py index be21c036..7e23a4c2 100644 --- a/tests/integration_tests/configuration_file_parsing/__init__.py +++ b/tests/integration_tests/configuration_file_parsing/__init__.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from pathlib import Path from typing import Union diff --git a/tests/integration_tests/configuration_file_parsing/nodes/__init__.py b/tests/integration_tests/configuration_file_parsing/nodes/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/integration_tests/configuration_file_parsing/nodes/__init__.py +++ b/tests/integration_tests/configuration_file_parsing/nodes/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/integration_tests/configuration_file_parsing/nodes/network/__init__.py b/tests/integration_tests/configuration_file_parsing/nodes/network/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/integration_tests/configuration_file_parsing/nodes/network/__init__.py +++ b/tests/integration_tests/configuration_file_parsing/nodes/network/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/integration_tests/configuration_file_parsing/nodes/network/test_firewall_config.py b/tests/integration_tests/configuration_file_parsing/nodes/network/test_firewall_config.py index fc6e05ec..457fdb42 100644 --- a/tests/integration_tests/configuration_file_parsing/nodes/network/test_firewall_config.py +++ b/tests/integration_tests/configuration_file_parsing/nodes/network/test_firewall_config.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address import pytest diff --git a/tests/integration_tests/configuration_file_parsing/nodes/network/test_router_config.py b/tests/integration_tests/configuration_file_parsing/nodes/network/test_router_config.py index 4382cc30..ccde3a02 100644 --- a/tests/integration_tests/configuration_file_parsing/nodes/network/test_router_config.py +++ b/tests/integration_tests/configuration_file_parsing/nodes/network/test_router_config.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import pytest from primaite.simulator.network.container import Network diff --git a/tests/integration_tests/configuration_file_parsing/nodes/test_node_config.py b/tests/integration_tests/configuration_file_parsing/nodes/test_node_config.py index b71c0c9c..8526ab78 100644 --- a/tests/integration_tests/configuration_file_parsing/nodes/test_node_config.py +++ b/tests/integration_tests/configuration_file_parsing/nodes/test_node_config.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from primaite.config.load import data_manipulation_config_path from primaite.simulator.network.container import Network from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState @@ -44,5 +45,7 @@ def test_basic_config(): client_3: Computer = network.get_node_by_hostname("client_3") assert client_3.operating_state == NodeOperatingState.OFF + # Bandwidth should have non-default values + for link in network.links: assert network.links[link].bandwidth == 200 diff --git a/tests/integration_tests/configuration_file_parsing/software_installation_and_configuration.py b/tests/integration_tests/configuration_file_parsing/software_installation_and_configuration.py index a5fcb372..4da1b674 100644 --- a/tests/integration_tests/configuration_file_parsing/software_installation_and_configuration.py +++ b/tests/integration_tests/configuration_file_parsing/software_installation_and_configuration.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address from pathlib import Path from typing import Union diff --git a/tests/integration_tests/configuration_file_parsing/test_episode_scheduler.py b/tests/integration_tests/configuration_file_parsing/test_episode_scheduler.py index c6fd1a2f..13be830b 100644 --- a/tests/integration_tests/configuration_file_parsing/test_episode_scheduler.py +++ b/tests/integration_tests/configuration_file_parsing/test_episode_scheduler.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import pytest import yaml diff --git a/tests/integration_tests/configuration_file_parsing/test_game_options_config.py b/tests/integration_tests/configuration_file_parsing/test_game_options_config.py index adbbf2b5..32d88c92 100644 --- a/tests/integration_tests/configuration_file_parsing/test_game_options_config.py +++ b/tests/integration_tests/configuration_file_parsing/test_game_options_config.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from pathlib import Path from typing import Union diff --git a/tests/integration_tests/configuration_file_parsing/test_io_settings.py b/tests/integration_tests/configuration_file_parsing/test_io_settings.py index 21f56e97..ebaa4956 100644 --- a/tests/integration_tests/configuration_file_parsing/test_io_settings.py +++ b/tests/integration_tests/configuration_file_parsing/test_io_settings.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from pathlib import Path from typing import Union diff --git a/tests/integration_tests/configuration_file_parsing/test_no_nodes_links_agents_config.py b/tests/integration_tests/configuration_file_parsing/test_no_nodes_links_agents_config.py index 5c9b0cb9..26fc562d 100644 --- a/tests/integration_tests/configuration_file_parsing/test_no_nodes_links_agents_config.py +++ b/tests/integration_tests/configuration_file_parsing/test_no_nodes_links_agents_config.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import yaml from primaite.game.game import PrimaiteGame diff --git a/tests/integration_tests/game_layer/observations/__init__.py b/tests/integration_tests/game_layer/observations/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/integration_tests/game_layer/observations/__init__.py +++ b/tests/integration_tests/game_layer/observations/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/integration_tests/game_layer/observations/test_acl_observations.py b/tests/integration_tests/game_layer/observations/test_acl_observations.py index 5aa2ec2a..f1d9d416 100644 --- a/tests/integration_tests/game_layer/observations/test_acl_observations.py +++ b/tests/integration_tests/game_layer/observations/test_acl_observations.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import pytest from primaite.game.agent.observations.acl_observation import ACLObservation diff --git a/tests/integration_tests/game_layer/observations/test_file_system_observations.py b/tests/integration_tests/game_layer/observations/test_file_system_observations.py index cb83ac5e..1031dcb0 100644 --- a/tests/integration_tests/game_layer/observations/test_file_system_observations.py +++ b/tests/integration_tests/game_layer/observations/test_file_system_observations.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import pytest from gymnasium import spaces diff --git a/tests/integration_tests/game_layer/observations/test_firewall_observation.py b/tests/integration_tests/game_layer/observations/test_firewall_observation.py index 959e30f6..99417e33 100644 --- a/tests/integration_tests/game_layer/observations/test_firewall_observation.py +++ b/tests/integration_tests/game_layer/observations/test_firewall_observation.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from primaite.game.agent.observations.firewall_observation import FirewallObservation from primaite.simulator.network.container import Network from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState diff --git a/tests/integration_tests/game_layer/observations/test_link_observations.py b/tests/integration_tests/game_layer/observations/test_link_observations.py index dce7b23d..7d1c1939 100644 --- a/tests/integration_tests/game_layer/observations/test_link_observations.py +++ b/tests/integration_tests/game_layer/observations/test_link_observations.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import pytest from gymnasium import spaces diff --git a/tests/integration_tests/game_layer/observations/test_nic_observations.py b/tests/integration_tests/game_layer/observations/test_nic_observations.py index 66b7df55..f1a8ea92 100644 --- a/tests/integration_tests/game_layer/observations/test_nic_observations.py +++ b/tests/integration_tests/game_layer/observations/test_nic_observations.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from pathlib import Path from typing import Union @@ -5,12 +6,18 @@ import pytest import yaml from gymnasium import spaces +from primaite.game.agent.interface import ProxyAgent from primaite.game.agent.observations.nic_observations import NICObservation from primaite.game.game import PrimaiteGame from primaite.simulator.network.hardware.nodes.host.computer import Computer from primaite.simulator.network.hardware.nodes.host.host_node import NIC -from primaite.simulator.network.nmne import CAPTURE_NMNE +from primaite.simulator.network.hardware.nodes.host.server import Server from primaite.simulator.sim_container import Simulation +from primaite.simulator.system.applications.database_client import DatabaseClient +from primaite.simulator.system.applications.web_browser import WebBrowser +from primaite.simulator.system.services.dns.dns_client import DNSClient +from primaite.simulator.system.services.dns.dns_server import DNSServer +from primaite.simulator.system.services.web_server.web_server import WebServer from tests import TEST_ASSETS_ROOT BASIC_CONFIG = TEST_ASSETS_ROOT / "configs/basic_switched_network.yaml" @@ -31,6 +38,32 @@ def simulation(example_network) -> Simulation: # set simulation network as example network sim.network = example_network + computer: Computer = example_network.get_node_by_hostname("client_1") + server: Server = example_network.get_node_by_hostname("server_1") + + web_browser: WebBrowser = computer.software_manager.software.get("WebBrowser") + web_browser.run() + + # Install DNS Client service on computer + computer.software_manager.install(DNSClient) + dns_client: DNSClient = computer.software_manager.software.get("DNSClient") + # set dns server + dns_client.dns_server = server.network_interface[1].ip_address + + # Install Web Server service on server + server.software_manager.install(WebServer) + web_server_service: WebServer = server.software_manager.software.get("WebServer") + web_server_service.start() + + # Install DNS Server service on server + server.software_manager.install(DNSServer) + dns_server: DNSServer = server.software_manager.software.get("DNSServer") + # register arcd.com to DNS + dns_server.dns_register( + domain_name="arcd.com", + domain_ip_address=server.network_interfaces[next(iter(server.network_interfaces))].ip_address, + ) + return sim @@ -102,3 +135,71 @@ def test_config_nic_categories(simulation): high_nmne_threshold=9, include_nmne=True, ) + + +def test_nic_monitored_traffic(simulation): + monitored_traffic = {"icmp": ["NONE"], "tcp": ["DNS"]} + + pc: Computer = simulation.network.get_node_by_hostname("client_1") + pc2: Computer = simulation.network.get_node_by_hostname("client_2") + + nic_obs = NICObservation( + where=["network", "nodes", pc.hostname, "NICs", 1], include_nmne=True, monitored_traffic=monitored_traffic + ) + + simulation.pre_timestep(0) # apply timestep to whole sim + simulation.apply_timestep(0) # apply timestep to whole sim + traffic_obs = nic_obs.observe(simulation.describe_state()).get("TRAFFIC") + + assert traffic_obs["icmp"]["inbound"] == 0 + assert traffic_obs["icmp"]["outbound"] == 0 + + # send a ping + pc.ping(target_ip_address=pc2.network_interface[1].ip_address) + traffic_obs = nic_obs.observe(simulation.describe_state()).get("TRAFFIC") + + assert traffic_obs["icmp"]["inbound"] == 1 + assert traffic_obs["icmp"]["outbound"] == 1 + + simulation.pre_timestep(1) # apply timestep to whole sim + simulation.apply_timestep(1) # apply timestep to whole sim + traffic_obs = nic_obs.observe(simulation.describe_state()).get("TRAFFIC") + + assert traffic_obs["icmp"]["inbound"] == 0 + assert traffic_obs["icmp"]["outbound"] == 0 + assert traffic_obs["tcp"][53]["inbound"] == 0 + assert traffic_obs["tcp"][53]["outbound"] == 0 + + # send a database query + browser: WebBrowser = pc.software_manager.software.get("WebBrowser") + browser.target_url = f"http://arcd.com/" + browser.get_webpage() + + traffic_obs = nic_obs.observe(simulation.describe_state()).get("TRAFFIC") + assert traffic_obs["icmp"]["inbound"] == 0 + assert traffic_obs["icmp"]["outbound"] == 0 + assert traffic_obs["tcp"][53]["inbound"] == 0 + assert traffic_obs["tcp"][53]["outbound"] == 1 # getting a webpage sent a dns request out + + simulation.pre_timestep(2) # apply timestep to whole sim + simulation.apply_timestep(2) # apply timestep to whole sim + traffic_obs = nic_obs.observe(simulation.describe_state()).get("TRAFFIC") + + assert traffic_obs["icmp"]["inbound"] == 0 + assert traffic_obs["icmp"]["outbound"] == 0 + assert traffic_obs["tcp"][53]["inbound"] == 0 + assert traffic_obs["tcp"][53]["outbound"] == 0 + + +def test_nic_monitored_traffic_config(): + """Test that the config loads the monitored traffic config correctly.""" + game: PrimaiteGame = load_config(BASIC_CONFIG) + + # should have icmp and DNS + defender_agent: ProxyAgent = game.agents.get("defender") + cur_obs = defender_agent.observation_manager.current_observation + + assert cur_obs["NODES"]["HOST0"]["NICS"][1]["TRAFFIC"] == { + "icmp": {"inbound": 0, "outbound": 0}, + "tcp": {53: {"inbound": 0, "outbound": 0}}, + } diff --git a/tests/integration_tests/game_layer/observations/test_node_observations.py b/tests/integration_tests/game_layer/observations/test_node_observations.py index 458cf0ab..8a36ea5c 100644 --- a/tests/integration_tests/game_layer/observations/test_node_observations.py +++ b/tests/integration_tests/game_layer/observations/test_node_observations.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import copy from uuid import uuid4 @@ -32,6 +33,7 @@ def test_host_observation(simulation): num_services=1, include_num_access=False, include_nmne=False, + monitored_traffic=None, services=[], applications=[], folders=[], diff --git a/tests/integration_tests/game_layer/observations/test_router_observation.py b/tests/integration_tests/game_layer/observations/test_router_observation.py index 55471676..c534307f 100644 --- a/tests/integration_tests/game_layer/observations/test_router_observation.py +++ b/tests/integration_tests/game_layer/observations/test_router_observation.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from pprint import pprint from primaite.game.agent.observations.acl_observation import ACLObservation diff --git a/tests/integration_tests/game_layer/observations/test_software_observations.py b/tests/integration_tests/game_layer/observations/test_software_observations.py index 4ae0701e..998aa755 100644 --- a/tests/integration_tests/game_layer/observations/test_software_observations.py +++ b/tests/integration_tests/game_layer/observations/test_software_observations.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import pytest from gymnasium import spaces diff --git a/tests/integration_tests/game_layer/test_actions.py b/tests/integration_tests/game_layer/test_actions.py index 43987c38..0dcf125d 100644 --- a/tests/integration_tests/game_layer/test_actions.py +++ b/tests/integration_tests/game_layer/test_actions.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK # Plan for creating integration tests for the actions: # I need to test that the requests coming out of the actions have the intended effect on the simulation. # I can do this by creating a simulation, and then running the action on the simulation, and then checking @@ -122,7 +123,7 @@ def test_router_acl_addrule_integration(game_and_agent: Tuple[PrimaiteGame, Prox action = ( "ROUTER_ACL_ADDRULE", { - "target_router_nodename": "router", + "target_router": "router", "position": 4, # 4th rule "permission": 2, # DENY "source_ip_id": 3, # 10.0.1.2 (client_1) @@ -149,7 +150,7 @@ def test_router_acl_addrule_integration(game_and_agent: Tuple[PrimaiteGame, Prox action = ( "ROUTER_ACL_ADDRULE", { - "target_router_nodename": "router", + "target_router": "router", "position": 5, # 5th rule "permission": 2, # DENY "source_ip_id": 5, # 10.0.2.2 (server_1) @@ -187,7 +188,7 @@ def test_router_acl_removerule_integration(game_and_agent: Tuple[PrimaiteGame, P action = ( "ROUTER_ACL_REMOVERULE", { - "target_router_nodename": "router", + "target_router": "router", "position": 3, # 4th rule }, ) diff --git a/tests/integration_tests/game_layer/test_observations.py b/tests/integration_tests/game_layer/test_observations.py index ed07e030..ff83c532 100644 --- a/tests/integration_tests/game_layer/test_observations.py +++ b/tests/integration_tests/game_layer/test_observations.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from gymnasium import spaces from primaite.game.agent.observations.file_system_observations import FileObservation diff --git a/tests/integration_tests/game_layer/test_rewards.py b/tests/integration_tests/game_layer/test_rewards.py index dff536de..db2b0c3a 100644 --- a/tests/integration_tests/game_layer/test_rewards.py +++ b/tests/integration_tests/game_layer/test_rewards.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import yaml from primaite.game.agent.interface import AgentHistoryItem diff --git a/tests/integration_tests/network/__init__.py b/tests/integration_tests/network/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/integration_tests/network/__init__.py +++ b/tests/integration_tests/network/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/integration_tests/network/test_broadcast.py b/tests/integration_tests/network/test_broadcast.py index 6b6deb93..8f65344f 100644 --- a/tests/integration_tests/network/test_broadcast.py +++ b/tests/integration_tests/network/test_broadcast.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address, IPv4Network from typing import Any, Dict, List, Tuple diff --git a/tests/integration_tests/network/test_capture_nmne.py b/tests/integration_tests/network/test_capture_nmne.py index fccd580d..a8f1f245 100644 --- a/tests/integration_tests/network/test_capture_nmne.py +++ b/tests/integration_tests/network/test_capture_nmne.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from primaite.game.agent.observations.nic_observations import NICObservation from primaite.simulator.network.hardware.nodes.host.server import Server from primaite.simulator.network.nmne import set_nmne_config diff --git a/tests/integration_tests/network/test_firewall.py b/tests/integration_tests/network/test_firewall.py index 846699f0..b15ee51a 100644 --- a/tests/integration_tests/network/test_firewall.py +++ b/tests/integration_tests/network/test_firewall.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address import pytest diff --git a/tests/integration_tests/network/test_frame_transmission.py b/tests/integration_tests/network/test_frame_transmission.py index eb30a245..fc2d146e 100644 --- a/tests/integration_tests/network/test_frame_transmission.py +++ b/tests/integration_tests/network/test_frame_transmission.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from primaite.simulator.network.container import Network from primaite.simulator.network.hardware.nodes.host.computer import Computer from primaite.simulator.network.hardware.nodes.host.host_node import NIC diff --git a/tests/integration_tests/network/test_multi_lan_internet_example_network.py b/tests/integration_tests/network/test_multi_lan_internet_example_network.py index f6d702d8..fa290b79 100644 --- a/tests/integration_tests/network/test_multi_lan_internet_example_network.py +++ b/tests/integration_tests/network/test_multi_lan_internet_example_network.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from primaite.simulator.network.hardware.nodes.host.computer import Computer from primaite.simulator.network.hardware.nodes.host.server import Server from primaite.simulator.network.networks import multi_lan_internet_network_example diff --git a/tests/integration_tests/network/test_network_creation.py b/tests/integration_tests/network/test_network_creation.py index 5cf36bce..794ddde5 100644 --- a/tests/integration_tests/network/test_network_creation.py +++ b/tests/integration_tests/network/test_network_creation.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from primaite.simulator.network.container import Network from primaite.simulator.network.hardware.nodes.host.computer import Computer from primaite.simulator.network.hardware.nodes.host.host_node import NIC diff --git a/tests/integration_tests/network/test_nic_link_connection.py b/tests/integration_tests/network/test_nic_link_connection.py index f13248a2..ab9160c8 100644 --- a/tests/integration_tests/network/test_nic_link_connection.py +++ b/tests/integration_tests/network/test_nic_link_connection.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import pytest from primaite.simulator.network.hardware.base import Link diff --git a/tests/integration_tests/network/test_routing.py b/tests/integration_tests/network/test_routing.py index 267b9b53..62b58cbd 100644 --- a/tests/integration_tests/network/test_routing.py +++ b/tests/integration_tests/network/test_routing.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from typing import Tuple import pytest diff --git a/tests/integration_tests/network/test_switched_network.py b/tests/integration_tests/network/test_switched_network.py index 98f36df6..ae0aa8a7 100644 --- a/tests/integration_tests/network/test_switched_network.py +++ b/tests/integration_tests/network/test_switched_network.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK def test_switched_network(client_switch_server): """Tests a node can ping another node via the switch.""" computer, switch, server = client_switch_server diff --git a/tests/integration_tests/network/test_wireless_router.py b/tests/integration_tests/network/test_wireless_router.py index d739bd0b..733de6f6 100644 --- a/tests/integration_tests/network/test_wireless_router.py +++ b/tests/integration_tests/network/test_wireless_router.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import pytest import yaml diff --git a/tests/integration_tests/system/__init__.py b/tests/integration_tests/system/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/integration_tests/system/__init__.py +++ b/tests/integration_tests/system/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/integration_tests/system/red_applications/test_data_manipulation_bot_and_server.py b/tests/integration_tests/system/red_applications/test_data_manipulation_bot_and_server.py index 69d14b46..a01cffbe 100644 --- a/tests/integration_tests/system/red_applications/test_data_manipulation_bot_and_server.py +++ b/tests/integration_tests/system/red_applications/test_data_manipulation_bot_and_server.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address from typing import Tuple diff --git a/tests/integration_tests/system/red_applications/test_dos_bot_and_server.py b/tests/integration_tests/system/red_applications/test_dos_bot_and_server.py index 8ed10da6..68c1fbfe 100644 --- a/tests/integration_tests/system/red_applications/test_dos_bot_and_server.py +++ b/tests/integration_tests/system/red_applications/test_dos_bot_and_server.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address from typing import Tuple diff --git a/tests/integration_tests/system/red_applications/test_ransomware_script.py b/tests/integration_tests/system/red_applications/test_ransomware_script.py index 9a04610b..2e3a0b1c 100644 --- a/tests/integration_tests/system/red_applications/test_ransomware_script.py +++ b/tests/integration_tests/system/red_applications/test_ransomware_script.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address from typing import Tuple @@ -9,12 +10,8 @@ from primaite.simulator.network.hardware.nodes.host.computer import Computer from primaite.simulator.network.hardware.nodes.host.server import Server from primaite.simulator.network.hardware.nodes.network.router import ACLAction, Router from primaite.simulator.network.transmission.transport_layer import Port -from primaite.simulator.system.applications.application import ApplicationOperatingState from primaite.simulator.system.applications.database_client import DatabaseClient, DatabaseClientConnection -from primaite.simulator.system.applications.red_applications.ransomware_script import ( - RansomwareAttackStage, - RansomwareScript, -) +from primaite.simulator.system.applications.red_applications.ransomware_script import RansomwareScript from primaite.simulator.system.services.database.database_service import DatabaseService from primaite.simulator.system.software import SoftwareHealthState @@ -85,54 +82,24 @@ def ransomware_script_db_server_green_client(example_network) -> Network: return network -def test_repeating_ransomware_script_attack(ransomware_script_and_db_server): +def test_ransomware_script_attack(ransomware_script_and_db_server): """Test a repeating data manipulation attack.""" RansomwareScript, computer, db_server_service, server = ransomware_script_and_db_server + computer.apply_timestep(timestep=0) + server.apply_timestep(timestep=0) assert db_server_service.health_state_actual is SoftwareHealthState.GOOD - assert computer.file_system.num_file_creations == 0 + assert server.file_system.num_file_creations == 1 - RansomwareScript.target_scan_p_of_success = 1 - RansomwareScript.c2_beacon_p_of_success = 1 - RansomwareScript.ransomware_encrypt_p_of_success = 1 - RansomwareScript.repeat = True RansomwareScript.attack() - assert RansomwareScript.attack_stage == RansomwareAttackStage.NOT_STARTED - assert db_server_service.db_file.health_status is FileSystemItemHealthStatus.COMPROMISED - assert computer.file_system.num_file_creations == 1 + assert db_server_service.db_file.health_status is FileSystemItemHealthStatus.CORRUPT + assert server.file_system.num_file_creations == 2 computer.apply_timestep(timestep=1) server.apply_timestep(timestep=1) - assert RansomwareScript.attack_stage == RansomwareAttackStage.NOT_STARTED - assert db_server_service.db_file.health_status is FileSystemItemHealthStatus.COMPROMISED - - -def test_repeating_ransomware_script_attack(ransomware_script_and_db_server): - """Test a repeating ransowmare script attack.""" - RansomwareScript, computer, db_server_service, server = ransomware_script_and_db_server - - assert db_server_service.health_state_actual is SoftwareHealthState.GOOD - - RansomwareScript.target_scan_p_of_success = 1 - RansomwareScript.c2_beacon_p_of_success = 1 - RansomwareScript.ransomware_encrypt_p_of_success = 1 - RansomwareScript.repeat = False - RansomwareScript.attack() - - assert RansomwareScript.attack_stage == RansomwareAttackStage.SUCCEEDED assert db_server_service.db_file.health_status is FileSystemItemHealthStatus.CORRUPT - assert computer.file_system.num_file_creations == 1 - - computer.apply_timestep(timestep=1) - computer.pre_timestep(timestep=1) - server.apply_timestep(timestep=1) - server.pre_timestep(timestep=1) - - assert RansomwareScript.attack_stage == RansomwareAttackStage.SUCCEEDED - assert db_server_service.db_file.health_status is FileSystemItemHealthStatus.CORRUPT - assert computer.file_system.num_file_creations == 0 def test_ransomware_disrupts_green_agent_connection(ransomware_script_db_server_green_client): @@ -153,10 +120,6 @@ def test_ransomware_disrupts_green_agent_connection(ransomware_script_db_server_ assert green_db_client_connection.query("SELECT") assert green_db_client.last_query_response.get("status_code") == 200 - ransomware_script_application.target_scan_p_of_success = 1 - ransomware_script_application.ransomware_encrypt_p_of_success = 1 - ransomware_script_application.c2_beacon_p_of_success = 1 - ransomware_script_application.repeat = False ransomware_script_application.attack() assert db_server_service.db_file.health_status is FileSystemItemHealthStatus.CORRUPT diff --git a/tests/integration_tests/system/test_application_on_node.py b/tests/integration_tests/system/test_application_on_node.py index 6a493955..275646c6 100644 --- a/tests/integration_tests/system/test_application_on_node.py +++ b/tests/integration_tests/system/test_application_on_node.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from typing import Tuple import pytest diff --git a/tests/integration_tests/system/test_arp.py b/tests/integration_tests/system/test_arp.py new file mode 100644 index 00000000..be8656aa --- /dev/null +++ b/tests/integration_tests/system/test_arp.py @@ -0,0 +1,50 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK +from primaite.simulator.network.hardware.nodes.network.router import RouterARP +from primaite.simulator.system.services.arp.arp import ARP +from tests.integration_tests.network.test_routing import multi_hop_network + + +def test_arp_from_host_to_default_gateway(multi_hop_network): + pc_a = multi_hop_network.get_node_by_hostname("pc_a") + router_1 = multi_hop_network.get_node_by_hostname("router_1") + + pc_a_arp: ARP = pc_a.software_manager.arp + + expected_result = router_1.network_interface[2].mac_address + actual_result = pc_a_arp.get_arp_cache_mac_address(router_1.network_interface[2].ip_address) + + assert actual_result == expected_result + + +def test_arp_from_router_to_router(multi_hop_network): + router_1 = multi_hop_network.get_node_by_hostname("router_1") + router_2 = multi_hop_network.get_node_by_hostname("router_2") + + router_1_arp: RouterARP = router_1.software_manager.arp + + expected_result = router_2.network_interface[1].mac_address + actual_result = router_1_arp.get_arp_cache_mac_address(router_2.network_interface[1].ip_address) + + assert actual_result == expected_result + + +def test_arp_fails_for_broadcast_address_between_routers(multi_hop_network): + router_1 = multi_hop_network.get_node_by_hostname("router_1") + + router_1_arp: RouterARP = router_1.software_manager.arp + + expected_result = None + actual_result = router_1_arp.get_arp_cache_mac_address(router_1.network_interface[1].ip_network.broadcast_address) + + assert actual_result == expected_result + + +def test_arp_fails_for_network_address_between_routers(multi_hop_network): + router_1 = multi_hop_network.get_node_by_hostname("router_1") + + router_1_arp: RouterARP = router_1.software_manager.arp + + expected_result = None + actual_result = router_1_arp.get_arp_cache_mac_address(router_1.network_interface[1].ip_network.network_address) + + assert actual_result == expected_result diff --git a/tests/integration_tests/system/test_database_on_node.py b/tests/integration_tests/system/test_database_on_node.py index ea7d7aae..8da3bb1a 100644 --- a/tests/integration_tests/system/test_database_on_node.py +++ b/tests/integration_tests/system/test_database_on_node.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address from typing import Tuple diff --git a/tests/integration_tests/system/test_dns_client_server.py b/tests/integration_tests/system/test_dns_client_server.py index e6275459..480a90bc 100644 --- a/tests/integration_tests/system/test_dns_client_server.py +++ b/tests/integration_tests/system/test_dns_client_server.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address from typing import Tuple diff --git a/tests/integration_tests/system/test_ftp_client_server.py b/tests/integration_tests/system/test_ftp_client_server.py index 6b46e302..fcd13609 100644 --- a/tests/integration_tests/system/test_ftp_client_server.py +++ b/tests/integration_tests/system/test_ftp_client_server.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from typing import Tuple import pytest diff --git a/tests/integration_tests/system/test_nmap.py b/tests/integration_tests/system/test_nmap.py new file mode 100644 index 00000000..bbfa4f43 --- /dev/null +++ b/tests/integration_tests/system/test_nmap.py @@ -0,0 +1,186 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK +from enum import Enum +from ipaddress import IPv4Address, IPv4Network + +import yaml + +from primaite.game.game import PrimaiteGame +from primaite.simulator.network.transmission.network_layer import IPProtocol +from primaite.simulator.network.transmission.transport_layer import Port +from primaite.simulator.system.applications.nmap import NMAP +from tests import TEST_ASSETS_ROOT + + +def test_ping_scan_all_on(example_network): + network = example_network + + client_1 = network.get_node_by_hostname("client_1") + client_1_nmap: NMAP = client_1.software_manager.software["NMAP"] # noqa + + expected_result = [IPv4Address("192.168.1.10"), IPv4Address("192.168.1.14")] + actual_result = client_1_nmap.ping_scan(target_ip_address=["192.168.1.10", "192.168.1.14"]) + + assert sorted(actual_result) == sorted(expected_result) + + +def test_ping_scan_all_on_full_network(example_network): + network = example_network + + client_1 = network.get_node_by_hostname("client_1") + client_1_nmap: NMAP = client_1.software_manager.software["NMAP"] # noqa + + expected_result = [IPv4Address("192.168.1.1"), IPv4Address("192.168.1.10"), IPv4Address("192.168.1.14")] + actual_result = client_1_nmap.ping_scan(target_ip_address=IPv4Network("192.168.1.0/24")) + + assert sorted(actual_result) == sorted(expected_result) + + +def test_ping_scan_some_on(example_network): + network = example_network + + client_1 = network.get_node_by_hostname("client_1") + client_1_nmap: NMAP = client_1.software_manager.software["NMAP"] # noqa + + network.get_node_by_hostname("server_2").power_off() + + expected_result = [IPv4Address("192.168.1.1"), IPv4Address("192.168.1.10")] + actual_result = client_1_nmap.ping_scan(target_ip_address=IPv4Network("192.168.1.0/24")) + + assert sorted(actual_result) == sorted(expected_result) + + +def test_ping_scan_all_off(example_network): + network = example_network + + client_1 = network.get_node_by_hostname("client_1") + client_1_nmap: NMAP = client_1.software_manager.software["NMAP"] # noqa + + network.get_node_by_hostname("server_1").power_off() + network.get_node_by_hostname("server_2").power_off() + + expected_result = [] + actual_result = client_1_nmap.ping_scan(target_ip_address=["192.168.1.10", "192.168.1.14"]) + + assert sorted(actual_result) == sorted(expected_result) + + +def test_port_scan_one_node_one_port(example_network): + network = example_network + + client_1 = network.get_node_by_hostname("client_1") + client_1_nmap: NMAP = client_1.software_manager.software["NMAP"] # noqa + + client_2 = network.get_node_by_hostname("client_2") + + actual_result = client_1_nmap.port_scan( + target_ip_address=client_2.network_interface[1].ip_address, target_port=Port.DNS, target_protocol=IPProtocol.TCP + ) + + expected_result = {IPv4Address("192.168.10.22"): {IPProtocol.TCP: [Port.DNS]}} + + assert actual_result == expected_result + + +def sort_dict(d): + """Recursively sorts a dictionary.""" + if isinstance(d, dict): + return {k: sort_dict(v) for k, v in sorted(d.items(), key=lambda item: str(item[0]))} + elif isinstance(d, list): + return sorted(d, key=lambda item: str(item) if isinstance(item, Enum) else item) + elif isinstance(d, Enum): + return str(d) + else: + return d + + +def test_port_scan_full_subnet_all_ports_and_protocols(example_network): + network = example_network + + client_1 = network.get_node_by_hostname("client_1") + client_1_nmap: NMAP = client_1.software_manager.software["NMAP"] # noqa + + actual_result = client_1_nmap.port_scan( + target_ip_address=IPv4Network("192.168.10.0/24"), + ) + + expected_result = { + IPv4Address("192.168.10.1"): {IPProtocol.UDP: [Port.ARP]}, + IPv4Address("192.168.10.22"): { + IPProtocol.TCP: [Port.HTTP, Port.FTP, Port.DNS], + IPProtocol.UDP: [Port.ARP, Port.NTP], + }, + } + + assert sort_dict(actual_result) == sort_dict(expected_result) + + +def test_network_service_recon_all_ports_and_protocols(example_network): + network = example_network + + client_1 = network.get_node_by_hostname("client_1") + client_1_nmap: NMAP = client_1.software_manager.software["NMAP"] # noqa + + actual_result = client_1_nmap.network_service_recon( + target_ip_address=IPv4Network("192.168.10.0/24"), target_port=Port.HTTP, target_protocol=IPProtocol.TCP + ) + + expected_result = {IPv4Address("192.168.10.22"): {IPProtocol.TCP: [Port.HTTP]}} + + assert sort_dict(actual_result) == sort_dict(expected_result) + + +def test_ping_scan_red_agent(): + with open(TEST_ASSETS_ROOT / "configs/nmap_ping_scan_red_agent_config.yaml", "r") as file: + cfg = yaml.safe_load(file) + + game = PrimaiteGame.from_config(cfg) + + game.step() + + expected_result = ["192.168.1.1", "192.168.1.10", "192.168.1.14"] + + action_history = game.agents["client_1_red_nmap"].history + assert len(action_history) == 1 + actual_result = action_history[0].response.data["live_hosts"] + + assert sorted(actual_result) == sorted(expected_result) + + +def test_port_scan_red_agent(): + with open(TEST_ASSETS_ROOT / "configs/nmap_port_scan_red_agent_config.yaml", "r") as file: + cfg = yaml.safe_load(file) + + game = PrimaiteGame.from_config(cfg) + + game.step() + + expected_result = { + "192.168.10.1": {"udp": [219]}, + "192.168.10.22": { + "tcp": [80, 21, 53], + "udp": [219, 123], + }, + } + + action_history = game.agents["client_1_red_nmap"].history + assert len(action_history) == 1 + actual_result = action_history[0].response.data + + assert sorted(actual_result) == sorted(expected_result) + + +def test_network_service_recon_red_agent(): + with open(TEST_ASSETS_ROOT / "configs/nmap_network_service_recon_red_agent_config.yaml", "r") as file: + cfg = yaml.safe_load(file) + + game = PrimaiteGame.from_config(cfg) + + game.step() + + expected_result = {"192.168.10.22": {"tcp": [80]}} + + action_history = game.agents["client_1_red_nmap"].history + assert len(action_history) == 1 + actual_result = action_history[0].response.data + + assert sorted(actual_result) == sorted(expected_result) diff --git a/tests/integration_tests/system/test_ntp_client_server.py b/tests/integration_tests/system/test_ntp_client_server.py index 7e52377b..957c1aeb 100644 --- a/tests/integration_tests/system/test_ntp_client_server.py +++ b/tests/integration_tests/system/test_ntp_client_server.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address from time import sleep from typing import Tuple diff --git a/tests/integration_tests/system/test_service_on_node.py b/tests/integration_tests/system/test_service_on_node.py index 44d045c2..15dbaf1d 100644 --- a/tests/integration_tests/system/test_service_on_node.py +++ b/tests/integration_tests/system/test_service_on_node.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from typing import Tuple import pytest diff --git a/tests/integration_tests/system/test_web_client_server.py b/tests/integration_tests/system/test_web_client_server.py index 5e3ff544..05cbae4f 100644 --- a/tests/integration_tests/system/test_web_client_server.py +++ b/tests/integration_tests/system/test_web_client_server.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from typing import Tuple import pytest diff --git a/tests/integration_tests/system/test_web_client_server_and_database.py b/tests/integration_tests/system/test_web_client_server_and_database.py index 0d1bb584..3fe77fa0 100644 --- a/tests/integration_tests/system/test_web_client_server_and_database.py +++ b/tests/integration_tests/system/test_web_client_server_and_database.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address from typing import Tuple diff --git a/tests/integration_tests/test_simulation/__init__.py b/tests/integration_tests/test_simulation/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/integration_tests/test_simulation/__init__.py +++ b/tests/integration_tests/test_simulation/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/integration_tests/test_simulation/test_request_response.py b/tests/integration_tests/test_simulation/test_request_response.py index a18f0336..79c72339 100644 --- a/tests/integration_tests/test_simulation/test_request_response.py +++ b/tests/integration_tests/test_simulation/test_request_response.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK # some test cases: # 0. test that sending a request to a valid target results in a success # 1. test that sending a request to a component that doesn't exist results in a failure @@ -20,7 +21,9 @@ def test_successful_node_file_system_creation_request(example_network): client_1 = example_network.get_node_by_hostname("client_1") assert client_1.file_system.get_file(folder_name="root", file_name="test.txt") is None - response = example_network.apply_request(["node", "client_1", "file_system", "create", "file", "", "test.txt"]) + response = example_network.apply_request( + ["node", "client_1", "file_system", "create", "file", "", "test.txt", "false"] + ) assert response assert client_1.file_system.get_file(folder_name="root", file_name="test.txt") diff --git a/tests/mock_and_patch/__init__.py b/tests/mock_and_patch/__init__.py index e0315ce3..be6c00e7 100644 --- a/tests/mock_and_patch/__init__.py +++ b/tests/mock_and_patch/__init__.py @@ -1 +1 @@ -# © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/mock_and_patch/get_session_path_mock.py b/tests/mock_and_patch/get_session_path_mock.py index 06fe5893..f315fca4 100644 --- a/tests/mock_and_patch/get_session_path_mock.py +++ b/tests/mock_and_patch/get_session_path_mock.py @@ -1,4 +1,4 @@ -# © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import tempfile from datetime import datetime from pathlib import Path diff --git a/tests/unit_tests/__init__.py b/tests/unit_tests/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/unit_tests/__init__.py +++ b/tests/unit_tests/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/unit_tests/_primaite/__init__.py b/tests/unit_tests/_primaite/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/unit_tests/_primaite/__init__.py +++ b/tests/unit_tests/_primaite/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/unit_tests/_primaite/_game/__init__.py b/tests/unit_tests/_primaite/_game/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/unit_tests/_primaite/_game/__init__.py +++ b/tests/unit_tests/_primaite/_game/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/unit_tests/_primaite/_game/_agent/__init__.py b/tests/unit_tests/_primaite/_game/_agent/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/unit_tests/_primaite/_game/_agent/__init__.py +++ b/tests/unit_tests/_primaite/_game/_agent/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/unit_tests/_primaite/_game/_agent/test_actions.py b/tests/unit_tests/_primaite/_game/_agent/test_actions.py index b41e22c9..c2d31ee1 100644 --- a/tests/unit_tests/_primaite/_game/_agent/test_actions.py +++ b/tests/unit_tests/_primaite/_game/_agent/test_actions.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from unittest.mock import Mock import pytest diff --git a/tests/unit_tests/_primaite/_game/_agent/test_probabilistic_agent.py b/tests/unit_tests/_primaite/_game/_agent/test_probabilistic_agent.py index 7eacb30d..f3b3c6eb 100644 --- a/tests/unit_tests/_primaite/_game/_agent/test_probabilistic_agent.py +++ b/tests/unit_tests/_primaite/_game/_agent/test_probabilistic_agent.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from primaite.game.agent.actions import ActionManager from primaite.game.agent.observations.observation_manager import NestedObservation, ObservationManager from primaite.game.agent.rewards import RewardFunction diff --git a/tests/unit_tests/_primaite/_interface/__init__.py b/tests/unit_tests/_primaite/_interface/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/unit_tests/_primaite/_interface/__init__.py +++ b/tests/unit_tests/_primaite/_interface/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/unit_tests/_primaite/_interface/test_request.py b/tests/unit_tests/_primaite/_interface/test_request.py index 5c65b572..6067f9e4 100644 --- a/tests/unit_tests/_primaite/_interface/test_request.py +++ b/tests/unit_tests/_primaite/_interface/test_request.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import pytest from pydantic import ValidationError @@ -24,6 +25,10 @@ def test_creating_response_from_boolean(): r2 = RequestResponse.from_bool(False) assert r2.status == "failure" + +@pytest.mark.skip("Disable validation due to performance hit.") +def test_response_from_invalid_options(): + """Test that we get a validation error if a non-boolean is passed.""" with pytest.raises(ValidationError): r3 = RequestResponse.from_bool(1) with pytest.raises(ValidationError): diff --git a/tests/unit_tests/_primaite/_session/__init__.py b/tests/unit_tests/_primaite/_session/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/unit_tests/_primaite/_session/__init__.py +++ b/tests/unit_tests/_primaite/_session/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/unit_tests/_primaite/_session/test_episode_schedule.py b/tests/unit_tests/_primaite/_session/test_episode_schedule.py index 25a68cbb..21448339 100644 --- a/tests/unit_tests/_primaite/_session/test_episode_schedule.py +++ b/tests/unit_tests/_primaite/_session/test_episode_schedule.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import pytest import yaml diff --git a/tests/unit_tests/_primaite/_simulator/__init__.py b/tests/unit_tests/_primaite/_simulator/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/unit_tests/_primaite/_simulator/__init__.py +++ b/tests/unit_tests/_primaite/_simulator/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/unit_tests/_primaite/_simulator/_domain/__init__.py b/tests/unit_tests/_primaite/_simulator/_domain/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/unit_tests/_primaite/_simulator/_domain/__init__.py +++ b/tests/unit_tests/_primaite/_simulator/_domain/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/unit_tests/_primaite/_simulator/_domain/test_account.py b/tests/unit_tests/_primaite/_simulator/_domain/test_account.py index 786fe851..8db68565 100644 --- a/tests/unit_tests/_primaite/_simulator/_domain/test_account.py +++ b/tests/unit_tests/_primaite/_simulator/_domain/test_account.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK """Test the account module of the simulator.""" import pytest diff --git a/tests/unit_tests/_primaite/_simulator/_domain/test_controller.py b/tests/unit_tests/_primaite/_simulator/_domain/test_controller.py index e69de29b..be6c00e7 100644 --- a/tests/unit_tests/_primaite/_simulator/_domain/test_controller.py +++ b/tests/unit_tests/_primaite/_simulator/_domain/test_controller.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/unit_tests/_primaite/_simulator/_file_system/__init__.py b/tests/unit_tests/_primaite/_simulator/_file_system/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/unit_tests/_primaite/_simulator/_file_system/__init__.py +++ b/tests/unit_tests/_primaite/_simulator/_file_system/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/unit_tests/_primaite/_simulator/_file_system/test_file.py b/tests/unit_tests/_primaite/_simulator/_file_system/test_file.py index 72a5889e..0b9bdc8e 100644 --- a/tests/unit_tests/_primaite/_simulator/_file_system/test_file.py +++ b/tests/unit_tests/_primaite/_simulator/_file_system/test_file.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import warnings import pytest diff --git a/tests/unit_tests/_primaite/_simulator/_file_system/test_file_actions.py b/tests/unit_tests/_primaite/_simulator/_file_system/test_file_actions.py index efa49134..295bca08 100644 --- a/tests/unit_tests/_primaite/_simulator/_file_system/test_file_actions.py +++ b/tests/unit_tests/_primaite/_simulator/_file_system/test_file_actions.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from typing import Tuple import pytest diff --git a/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system.py b/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system.py index 0cb7dce7..4eb0dd10 100644 --- a/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system.py +++ b/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import pytest from primaite.simulator.file_system.file import File @@ -107,8 +108,9 @@ def test_create_duplicate_folder(file_system): file_system.create_folder(folder_name="test_folder") assert len(file_system.folders) is 2 - with pytest.raises(Exception): - file_system.create_folder(folder_name="test_folder") + # We no longer through exceptions on making duplicate folders. + # with pytest.raises(Exception): + # file_system.create_folder(folder_name="test_folder") assert len(file_system.folders) is 2 diff --git a/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system_actions.py b/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system_actions.py index 62af93c4..209668c4 100644 --- a/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system_actions.py +++ b/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system_actions.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from typing import Tuple import pytest diff --git a/tests/unit_tests/_primaite/_simulator/_file_system/test_folder.py b/tests/unit_tests/_primaite/_simulator/_file_system/test_folder.py index 1d9f2d9c..724d7903 100644 --- a/tests/unit_tests/_primaite/_simulator/_file_system/test_folder.py +++ b/tests/unit_tests/_primaite/_simulator/_file_system/test_folder.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import pytest from primaite.simulator.file_system.file import File diff --git a/tests/unit_tests/_primaite/_simulator/_file_system/test_folder_actions.py b/tests/unit_tests/_primaite/_simulator/_file_system/test_folder_actions.py index 11043844..40f1e78b 100644 --- a/tests/unit_tests/_primaite/_simulator/_file_system/test_folder_actions.py +++ b/tests/unit_tests/_primaite/_simulator/_file_system/test_folder_actions.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import warnings from typing import Tuple diff --git a/tests/unit_tests/_primaite/_simulator/_network/__init__.py b/tests/unit_tests/_primaite/_simulator/_network/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/unit_tests/_primaite/_simulator/_network/__init__.py +++ b/tests/unit_tests/_primaite/_simulator/_network/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/unit_tests/_primaite/_simulator/_network/_hardware/__init__.py b/tests/unit_tests/_primaite/_simulator/_network/_hardware/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/unit_tests/_primaite/_simulator/_network/_hardware/__init__.py +++ b/tests/unit_tests/_primaite/_simulator/_network/_hardware/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/unit_tests/_primaite/_simulator/_network/_hardware/nodes/__init__.py b/tests/unit_tests/_primaite/_simulator/_network/_hardware/nodes/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/unit_tests/_primaite/_simulator/_network/_hardware/nodes/__init__.py +++ b/tests/unit_tests/_primaite/_simulator/_network/_hardware/nodes/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/unit_tests/_primaite/_simulator/_network/_hardware/nodes/test_acl.py b/tests/unit_tests/_primaite/_simulator/_network/_hardware/nodes/test_acl.py index 8b1aa9be..9bc1abfd 100644 --- a/tests/unit_tests/_primaite/_simulator/_network/_hardware/nodes/test_acl.py +++ b/tests/unit_tests/_primaite/_simulator/_network/_hardware/nodes/test_acl.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address import pytest diff --git a/tests/unit_tests/_primaite/_simulator/_network/_hardware/nodes/test_router.py b/tests/unit_tests/_primaite/_simulator/_network/_hardware/nodes/test_router.py index be74a721..d4e38ded 100644 --- a/tests/unit_tests/_primaite/_simulator/_network/_hardware/nodes/test_router.py +++ b/tests/unit_tests/_primaite/_simulator/_network/_hardware/nodes/test_router.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address from primaite.simulator.network.hardware.nodes.network.router import ACLAction, Router diff --git a/tests/unit_tests/_primaite/_simulator/_network/_hardware/nodes/test_switch.py b/tests/unit_tests/_primaite/_simulator/_network/_hardware/nodes/test_switch.py index a65f591e..2613d536 100644 --- a/tests/unit_tests/_primaite/_simulator/_network/_hardware/nodes/test_switch.py +++ b/tests/unit_tests/_primaite/_simulator/_network/_hardware/nodes/test_switch.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import pytest from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState diff --git a/tests/unit_tests/_primaite/_simulator/_network/_hardware/test_nic.py b/tests/unit_tests/_primaite/_simulator/_network/_hardware/test_nic.py index d0738c64..29d5ec67 100644 --- a/tests/unit_tests/_primaite/_simulator/_network/_hardware/test_nic.py +++ b/tests/unit_tests/_primaite/_simulator/_network/_hardware/test_nic.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import re from ipaddress import IPv4Address diff --git a/tests/unit_tests/_primaite/_simulator/_network/_hardware/test_node_actions.py b/tests/unit_tests/_primaite/_simulator/_network/_hardware/test_node_actions.py index a1b8a6c1..57d6cecb 100644 --- a/tests/unit_tests/_primaite/_simulator/_network/_hardware/test_node_actions.py +++ b/tests/unit_tests/_primaite/_simulator/_network/_hardware/test_node_actions.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import pytest from primaite.simulator.file_system.file import File diff --git a/tests/unit_tests/_primaite/_simulator/_network/_transmission/__init__.py b/tests/unit_tests/_primaite/_simulator/_network/_transmission/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/unit_tests/_primaite/_simulator/_network/_transmission/__init__.py +++ b/tests/unit_tests/_primaite/_simulator/_network/_transmission/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/unit_tests/_primaite/_simulator/_network/_transmission/test_data_link_layer.py b/tests/unit_tests/_primaite/_simulator/_network/_transmission/test_data_link_layer.py index 1fbbd1c1..92618baa 100644 --- a/tests/unit_tests/_primaite/_simulator/_network/_transmission/test_data_link_layer.py +++ b/tests/unit_tests/_primaite/_simulator/_network/_transmission/test_data_link_layer.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import pytest from primaite.simulator.network.protocols.icmp import ICMPPacket diff --git a/tests/unit_tests/_primaite/_simulator/_network/_transmission/test_network_layer.py b/tests/unit_tests/_primaite/_simulator/_network/_transmission/test_network_layer.py index 0ea98107..658726b5 100644 --- a/tests/unit_tests/_primaite/_simulator/_network/_transmission/test_network_layer.py +++ b/tests/unit_tests/_primaite/_simulator/_network/_transmission/test_network_layer.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import pytest from primaite.simulator.network.protocols.icmp import ICMPPacket, ICMPType diff --git a/tests/unit_tests/_primaite/_simulator/_network/test_container.py b/tests/unit_tests/_primaite/_simulator/_network/test_container.py index f0e386b8..f764f9b5 100644 --- a/tests/unit_tests/_primaite/_simulator/_network/test_container.py +++ b/tests/unit_tests/_primaite/_simulator/_network/test_container.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import json import pytest diff --git a/tests/unit_tests/_primaite/_simulator/_network/test_utils.py b/tests/unit_tests/_primaite/_simulator/_network/test_utils.py index a0c1da45..c80189c1 100644 --- a/tests/unit_tests/_primaite/_simulator/_network/test_utils.py +++ b/tests/unit_tests/_primaite/_simulator/_network/test_utils.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from primaite.simulator.network.utils import convert_bytes_to_megabits, convert_megabits_to_bytes diff --git a/tests/unit_tests/_primaite/_simulator/_system/__init__.py b/tests/unit_tests/_primaite/_simulator/_system/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/unit_tests/_primaite/_simulator/_system/__init__.py +++ b/tests/unit_tests/_primaite/_simulator/_system/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/unit_tests/_primaite/_simulator/_system/_applications/__init__.py b/tests/unit_tests/_primaite/_simulator/_system/_applications/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/unit_tests/_primaite/_simulator/_system/_applications/__init__.py +++ b/tests/unit_tests/_primaite/_simulator/_system/_applications/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/unit_tests/_primaite/_simulator/_system/_applications/_red_applications/__init__.py b/tests/unit_tests/_primaite/_simulator/_system/_applications/_red_applications/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/unit_tests/_primaite/_simulator/_system/_applications/_red_applications/__init__.py +++ b/tests/unit_tests/_primaite/_simulator/_system/_applications/_red_applications/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/unit_tests/_primaite/_simulator/_system/_applications/_red_applications/test_data_manipulation_bot.py b/tests/unit_tests/_primaite/_simulator/_system/_applications/_red_applications/test_data_manipulation_bot.py index 1937363a..0811d2a0 100644 --- a/tests/unit_tests/_primaite/_simulator/_system/_applications/_red_applications/test_data_manipulation_bot.py +++ b/tests/unit_tests/_primaite/_simulator/_system/_applications/_red_applications/test_data_manipulation_bot.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import pytest from primaite.simulator.network.hardware.base import Node diff --git a/tests/unit_tests/_primaite/_simulator/_system/_applications/_red_applications/test_dos_bot.py b/tests/unit_tests/_primaite/_simulator/_system/_applications/_red_applications/test_dos_bot.py index 4bfd28d0..2acd991a 100644 --- a/tests/unit_tests/_primaite/_simulator/_system/_applications/_red_applications/test_dos_bot.py +++ b/tests/unit_tests/_primaite/_simulator/_system/_applications/_red_applications/test_dos_bot.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address import pytest diff --git a/tests/unit_tests/_primaite/_simulator/_system/_applications/test_application_actions.py b/tests/unit_tests/_primaite/_simulator/_system/_applications/test_application_actions.py index e69de29b..be6c00e7 100644 --- a/tests/unit_tests/_primaite/_simulator/_system/_applications/test_application_actions.py +++ b/tests/unit_tests/_primaite/_simulator/_system/_applications/test_application_actions.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/unit_tests/_primaite/_simulator/_system/_applications/test_applications.py b/tests/unit_tests/_primaite/_simulator/_system/_applications/test_applications.py index 90c3f303..aef5d6d1 100644 --- a/tests/unit_tests/_primaite/_simulator/_system/_applications/test_applications.py +++ b/tests/unit_tests/_primaite/_simulator/_system/_applications/test_applications.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from primaite.simulator.system.applications.application import ApplicationOperatingState from primaite.simulator.system.software import SoftwareHealthState diff --git a/tests/unit_tests/_primaite/_simulator/_system/_applications/test_database_client.py b/tests/unit_tests/_primaite/_simulator/_system/_applications/test_database_client.py index 13b11589..e456ed78 100644 --- a/tests/unit_tests/_primaite/_simulator/_system/_applications/test_database_client.py +++ b/tests/unit_tests/_primaite/_simulator/_system/_applications/test_database_client.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address from typing import Tuple from uuid import uuid4 diff --git a/tests/unit_tests/_primaite/_simulator/_system/_applications/test_web_browser.py b/tests/unit_tests/_primaite/_simulator/_system/_applications/test_web_browser.py index 1300c33a..ce98d164 100644 --- a/tests/unit_tests/_primaite/_simulator/_system/_applications/test_web_browser.py +++ b/tests/unit_tests/_primaite/_simulator/_system/_applications/test_web_browser.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import pytest from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState diff --git a/tests/unit_tests/_primaite/_simulator/_system/_services/__init__.py b/tests/unit_tests/_primaite/_simulator/_system/_services/__init__.py index e69de29b..be6c00e7 100644 --- a/tests/unit_tests/_primaite/_simulator/_system/_services/__init__.py +++ b/tests/unit_tests/_primaite/_simulator/_system/_services/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/unit_tests/_primaite/_simulator/_system/_services/test_database.py b/tests/unit_tests/_primaite/_simulator/_system/_services/test_database.py index 0df6cf27..9e7ab1d2 100644 --- a/tests/unit_tests/_primaite/_simulator/_system/_services/test_database.py +++ b/tests/unit_tests/_primaite/_simulator/_system/_services/test_database.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import pytest from primaite.simulator.network.hardware.base import Node diff --git a/tests/unit_tests/_primaite/_simulator/_system/_services/test_dns_client.py b/tests/unit_tests/_primaite/_simulator/_system/_services/test_dns_client.py index bc11d278..e9ce4884 100644 --- a/tests/unit_tests/_primaite/_simulator/_system/_services/test_dns_client.py +++ b/tests/unit_tests/_primaite/_simulator/_system/_services/test_dns_client.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address import pytest diff --git a/tests/unit_tests/_primaite/_simulator/_system/_services/test_dns_server.py b/tests/unit_tests/_primaite/_simulator/_system/_services/test_dns_server.py index 469c52f3..4658fe76 100644 --- a/tests/unit_tests/_primaite/_simulator/_system/_services/test_dns_server.py +++ b/tests/unit_tests/_primaite/_simulator/_system/_services/test_dns_server.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address import pytest diff --git a/tests/unit_tests/_primaite/_simulator/_system/_services/test_ftp_client.py b/tests/unit_tests/_primaite/_simulator/_system/_services/test_ftp_client.py index 69b2f296..3ce4d8ee 100644 --- a/tests/unit_tests/_primaite/_simulator/_system/_services/test_ftp_client.py +++ b/tests/unit_tests/_primaite/_simulator/_system/_services/test_ftp_client.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address import pytest diff --git a/tests/unit_tests/_primaite/_simulator/_system/_services/test_ftp_server.py b/tests/unit_tests/_primaite/_simulator/_system/_services/test_ftp_server.py index f4e635d6..a1c2ba59 100644 --- a/tests/unit_tests/_primaite/_simulator/_system/_services/test_ftp_server.py +++ b/tests/unit_tests/_primaite/_simulator/_system/_services/test_ftp_server.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import pytest from primaite.simulator.file_system.file_system_item_abc import FileSystemItemHealthStatus diff --git a/tests/unit_tests/_primaite/_simulator/_system/_services/test_service_actions.py b/tests/unit_tests/_primaite/_simulator/_system/_services/test_service_actions.py index edc111e3..2d9a6c52 100644 --- a/tests/unit_tests/_primaite/_simulator/_system/_services/test_service_actions.py +++ b/tests/unit_tests/_primaite/_simulator/_system/_services/test_service_actions.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from primaite.simulator.system.services.service import ServiceOperatingState from primaite.simulator.system.software import SoftwareHealthState diff --git a/tests/unit_tests/_primaite/_simulator/_system/_services/test_services.py b/tests/unit_tests/_primaite/_simulator/_system/_services/test_services.py index 765922fd..8c12adaa 100644 --- a/tests/unit_tests/_primaite/_simulator/_system/_services/test_services.py +++ b/tests/unit_tests/_primaite/_simulator/_system/_services/test_services.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from uuid import uuid4 import pytest diff --git a/tests/unit_tests/_primaite/_simulator/_system/_services/test_web_server.py b/tests/unit_tests/_primaite/_simulator/_system/_services/test_web_server.py index 6fac0bcf..9af176be 100644 --- a/tests/unit_tests/_primaite/_simulator/_system/_services/test_web_server.py +++ b/tests/unit_tests/_primaite/_simulator/_system/_services/test_web_server.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import pytest from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState diff --git a/tests/unit_tests/_primaite/_simulator/_system/core/test_sys_log.py b/tests/unit_tests/_primaite/_simulator/_system/core/test_sys_log.py index 1009adc3..053211cd 100644 --- a/tests/unit_tests/_primaite/_simulator/_system/core/test_sys_log.py +++ b/tests/unit_tests/_primaite/_simulator/_system/core/test_sys_log.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from uuid import uuid4 import pytest diff --git a/tests/unit_tests/_primaite/_simulator/_system/test_software.py b/tests/unit_tests/_primaite/_simulator/_system/test_software.py index 6f680012..4cf83370 100644 --- a/tests/unit_tests/_primaite/_simulator/_system/test_software.py +++ b/tests/unit_tests/_primaite/_simulator/_system/test_software.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from typing import Dict import pytest diff --git a/tests/unit_tests/_primaite/_simulator/test_core.py b/tests/unit_tests/_primaite/_simulator/test_core.py index 069e6ea2..02960978 100644 --- a/tests/unit_tests/_primaite/_simulator/test_core.py +++ b/tests/unit_tests/_primaite/_simulator/test_core.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from typing import Callable, Dict, List, Literal, Tuple import pytest diff --git a/tests/unit_tests/_primaite/_simulator/test_sim_container.py b/tests/unit_tests/_primaite/_simulator/test_sim_container.py index 4543259d..fe702307 100644 --- a/tests/unit_tests/_primaite/_simulator/test_sim_container.py +++ b/tests/unit_tests/_primaite/_simulator/test_sim_container.py @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from primaite.simulator.sim_container import Simulation diff --git a/tests/unit_tests/_primaite/_utils/__init__.py b/tests/unit_tests/_primaite/_utils/__init__.py new file mode 100644 index 00000000..be6c00e7 --- /dev/null +++ b/tests/unit_tests/_primaite/_utils/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/unit_tests/_primaite/_utils/test_dict_enum_keys_conversion.py b/tests/unit_tests/_primaite/_utils/test_dict_enum_keys_conversion.py new file mode 100644 index 00000000..a8fb0a3a --- /dev/null +++ b/tests/unit_tests/_primaite/_utils/test_dict_enum_keys_conversion.py @@ -0,0 +1,84 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK +from primaite.simulator.network.transmission.network_layer import IPProtocol +from primaite.simulator.network.transmission.transport_layer import Port +from primaite.utils.converters import convert_dict_enum_keys_to_enum_values + + +def test_simple_conversion(): + """ + Test conversion of a simple dictionary with enum keys to enum values. + + The original dictionary contains one level of nested dictionary with enums as keys. + The expected output should have string values of enums as keys. + """ + original_dict = {IPProtocol.UDP: {Port.ARP: {"inbound": 0, "outbound": 1016.0}}} + expected_dict = {"udp": {219: {"inbound": 0, "outbound": 1016.0}}} + assert convert_dict_enum_keys_to_enum_values(original_dict) == expected_dict + + +def test_no_enums(): + """ + Test conversion of a dictionary with no enum keys. + + The original dictionary contains only string keys. + The expected output should be identical to the original dictionary. + """ + original_dict = {"protocol": {"port": {"inbound": 0, "outbound": 1016.0}}} + expected_dict = {"protocol": {"port": {"inbound": 0, "outbound": 1016.0}}} + assert convert_dict_enum_keys_to_enum_values(original_dict) == expected_dict + + +def test_mixed_keys(): + """ + Test conversion of a dictionary with a mix of enum and string keys. + + The original dictionary contains both enums and strings as keys. + The expected output should have string values of enums and original string keys. + """ + original_dict = { + IPProtocol.TCP: {"port": {"inbound": 0, "outbound": 1016.0}}, + "protocol": {Port.HTTP: {"inbound": 10, "outbound": 2020.0}}, + } + expected_dict = { + "tcp": {"port": {"inbound": 0, "outbound": 1016.0}}, + "protocol": {80: {"inbound": 10, "outbound": 2020.0}}, + } + assert convert_dict_enum_keys_to_enum_values(original_dict) == expected_dict + + +def test_empty_dict(): + """ + Test conversion of an empty dictionary. + + The original dictionary is empty. + The expected output should also be an empty dictionary. + """ + original_dict = {} + expected_dict = {} + assert convert_dict_enum_keys_to_enum_values(original_dict) == expected_dict + + +def test_nested_dicts(): + """ + Test conversion of a nested dictionary with multiple levels of nested dictionaries and enums as keys. + + The original dictionary contains nested dictionaries with enums as keys at different levels. + The expected output should have string values of enums as keys at all levels. + """ + original_dict = { + IPProtocol.UDP: {Port.ARP: {"inbound": 0, "outbound": 1016.0, "details": {IPProtocol.TCP: {"latency": "low"}}}} + } + expected_dict = {"udp": {219: {"inbound": 0, "outbound": 1016.0, "details": {"tcp": {"latency": "low"}}}}} + assert convert_dict_enum_keys_to_enum_values(original_dict) == expected_dict + + +def test_non_dict_values(): + """ + Test conversion of a dictionary where some values are not dictionaries. + + The original dictionary contains lists and tuples as values. + The expected output should preserve these non-dictionary values while converting enum keys to string values. + """ + original_dict = {IPProtocol.UDP: [Port.ARP, Port.HTTP], "protocols": (IPProtocol.TCP, IPProtocol.UDP)} + expected_dict = {"udp": [Port.ARP, Port.HTTP], "protocols": (IPProtocol.TCP, IPProtocol.UDP)} + assert convert_dict_enum_keys_to_enum_values(original_dict) == expected_dict