├── tests ├── __init__.py ├── mocks │ ├── goalkeepers_xgoals_payload.json │ ├── teams_payload.json │ ├── referees_payload.json │ ├── teams_salaries_payload.json │ ├── goalkeepers_goals_added_payload.json │ ├── managers_payload.json │ ├── teams_xgoals_payload.json │ ├── stadia_payload.json │ ├── teams_xpass_payload.json │ ├── games_payload.json │ └── players_payload.json └── test_client.py ├── itscalledsoccer └── __init__.py ├── .github ├── CODEOWNERS ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── feature-request.yml │ └── bug-report.yml ├── pull_request_template.md ├── dependabot.yml └── workflows │ ├── dependency-review.yml │ ├── gh-pages.yml │ ├── pypi-publish.yml │ ├── scorecard.yml │ ├── python-tests.yml │ └── codeql.yml ├── docs ├── reference.md ├── assets │ └── images │ │ └── logo.png └── index.md ├── .pre-commit-config.yaml ├── SECURITY.md ├── LICENSE ├── mkdocs.yml ├── pyproject.toml ├── .devcontainer └── devcontainer.json ├── README.md ├── .gitignore ├── CODE_OF_CONDUCT.md └── CONTRIBUTING.md /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /itscalledsoccer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @bgrnwd @tyler-richardett 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | patreon: americansocceranalysis 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /docs/reference.md: -------------------------------------------------------------------------------- 1 | # Reference 2 | 3 | ::: itscalledsoccer.client.AmericanSoccerAnalysis 4 | -------------------------------------------------------------------------------- /docs/assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/American-Soccer-Analysis/itscalledsoccer/HEAD/docs/assets/images/logo.png -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/gitleaks/gitleaks 3 | rev: v8.16.3 4 | hooks: 5 | - id: gitleaks 6 | - repo: https://github.com/pre-commit/pre-commit-hooks 7 | rev: v4.4.0 8 | hooks: 9 | - id: end-of-file-fixer 10 | - id: trailing-whitespace 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.yml: -------------------------------------------------------------------------------- 1 | name: ✨ Feature Request 2 | description: Submit a feature request 3 | title: "[Feature Request]: " 4 | labels: ["feature-request"] 5 | body: 6 | - type: textarea 7 | id: proposal 8 | attributes: 9 | label: What feature would you like to see? 10 | placeholder: Tell us what you want. 11 | validations: 12 | required: true 13 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ### Description 2 | 3 | Please explain the changes you made here. 4 | 5 | ### Checklist 6 | 7 | - [ ] Code compiles correctly 8 | - [ ] Created tests which fail without the change (if applicable) 9 | - [ ] All lint and unit tests passing 10 | - [ ] Extended the README / documentation, if necessary 11 | 12 | ### Additional Comments 13 | 14 | Anything else you'd like to add. 15 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "pip" 4 | directory: "/" 5 | schedule: 6 | interval: "monthly" 7 | groups: 8 | pip-deps: 9 | patterns: 10 | - "*" 11 | - package-ecosystem: "github-actions" 12 | directory: "/" 13 | schedule: 14 | interval: "monthly" 15 | groups: 16 | actions: 17 | patterns: 18 | - "*" 19 | - package-ecosystem: "devcontainers" 20 | directory: "/" 21 | schedule: 22 | interval: "monthly" 23 | groups: 24 | devcontainers: 25 | patterns: 26 | - "*" 27 | -------------------------------------------------------------------------------- /.github/workflows/dependency-review.yml: -------------------------------------------------------------------------------- 1 | # Dependency Review Action 2 | # 3 | # This Action will scan dependency manifest files that change as part of a Pull Request, 4 | # surfacing known-vulnerable versions of the packages declared or updated in the PR. 5 | # Once installed, if the workflow run is marked as required, 6 | # PRs introducing known-vulnerable packages will be blocked from merging. 7 | # 8 | # Source repository: https://github.com/actions/dependency-review-action 9 | name: 'Dependency Review' 10 | on: [pull_request] 11 | 12 | permissions: 13 | contents: read 14 | 15 | jobs: 16 | dependency-review: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Harden Runner 20 | uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 21 | with: 22 | egress-policy: audit 23 | 24 | - name: 'Checkout Repository' 25 | uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 26 | - name: 'Dependency Review' 27 | uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2 28 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | | Version | Supported | 6 | | -------- | ------------------ | 7 | | 1.x.x | :white_check_mark: | 8 | | <= 1.x.x | :x: | 9 | 10 | ## Reporting a Vulnerability 11 | 12 | Security bugs in `itscalledsoccer` are taken seriously. We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions. 13 | 14 | To report a security issue, please use the GitHub Security Advisory ["Report a Vulnerability"](https://github.com/American-Soccer-Analysis/itscalledsoccer/security/advisories/new) tab. 15 | 16 | A response will be sent indicating the next steps in handling your report. After the initial reply to your report, you will be kept informed of the progress towards a fix and full announcement, and may be asked for additional information or guidance. 17 | 18 | Report security bugs in third-party modules to the person or team maintaining the module. 19 | 20 | ## Attribution 21 | 22 | Adapted from the [Electron project's SECURITY.md](https://github.com/electron/electron/blob/main/SECURITY.md) 23 | -------------------------------------------------------------------------------- /.github/workflows/gh-pages.yml: -------------------------------------------------------------------------------- 1 | name: Deploy GitHub Pages 2 | on: 3 | push: 4 | branches: 5 | - main 6 | workflow_dispatch: ~ 7 | permissions: 8 | contents: read 9 | 10 | jobs: 11 | deploy: 12 | permissions: 13 | contents: write # for mkdocs gh-deploy to publish docs 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Harden Runner 17 | uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 18 | with: 19 | egress-policy: audit 20 | 21 | - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 22 | - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 23 | with: 24 | python-version: 3.12 25 | - name: Set up uv 26 | # Install a specific uv version using the installer 27 | run: | 28 | curl -LsSf https://astral.sh/uv/0.3.4/install.sh | sh 29 | uv venv 30 | uv pip install --upgrade setuptools wheel 31 | - name: Install the project 32 | run: uv sync --all-extras --dev 33 | - run: uv run mkdocs gh-deploy --force 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2021 itscalledsoccer authors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/workflows/pypi-publish.yml: -------------------------------------------------------------------------------- 1 | name: Upload Python Package 2 | 3 | on: 4 | workflow_dispatch: 5 | release: 6 | types: [published] 7 | 8 | permissions: 9 | contents: read 10 | 11 | jobs: 12 | deploy: 13 | runs-on: ubuntu-latest 14 | name: Upload release to PyPI 15 | permissions: 16 | # IMPORTANT: this permission is mandatory for trusted publishing 17 | id-token: write 18 | steps: 19 | - name: Harden Runner 20 | uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 21 | with: 22 | egress-policy: audit 23 | 24 | - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 25 | - name: Set up Python 26 | uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 27 | with: 28 | python-version: "3.x" 29 | - name: Install dependencies and build 30 | run: | 31 | python -m pip install --upgrade pip 32 | pip install setuptools wheel build 33 | python -m build 34 | - name: Publish a Python distribution to PyPi 35 | uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # release/v1 36 | with: 37 | attestations: true 38 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: itscalledsoccer 2 | repo_url: https://github.com/American-Soccer-Analysis/itscalledsoccer 3 | repo_name: itscalledsoccer 4 | theme: 5 | name: "material" 6 | logo: assets/images/logo.png 7 | icon: 8 | repo: fontawesome/brands/github 9 | favicon: assets/images/logo.png 10 | palette: 11 | # Palette toggle for automatic mode 12 | - media: "(prefers-color-scheme)" 13 | primary: green 14 | toggle: 15 | icon: material/brightness-auto 16 | name: Switch to light mode 17 | # Palette toggle for light mode 18 | - media: "(prefers-color-scheme: light)" 19 | scheme: default 20 | primary: green 21 | toggle: 22 | icon: material/brightness-7 23 | name: Switch to dark mode 24 | # Palette toggle for dark mode 25 | - media: "(prefers-color-scheme: dark)" 26 | scheme: slate 27 | primary: green 28 | toggle: 29 | icon: material/brightness-4 30 | name: Switch to system preference 31 | markdown_extensions: 32 | - pymdownx.highlight: 33 | anchor_linenums: true 34 | line_spans: __span 35 | pygments_lang_class: true 36 | - pymdownx.inlinehilite 37 | - pymdownx.snippets 38 | - pymdownx.superfences 39 | plugins: 40 | - search 41 | - mkdocstrings 42 | -------------------------------------------------------------------------------- /.github/workflows/scorecard.yml: -------------------------------------------------------------------------------- 1 | name: Scorecard supply-chain security 2 | on: 3 | branch_protection_rule: 4 | schedule: 5 | - cron: '32 23 * * 6' 6 | push: 7 | branches: [ "main" ] 8 | permissions: read-all 9 | jobs: 10 | analysis: 11 | name: Scorecard analysis 12 | runs-on: ubuntu-latest 13 | permissions: 14 | security-events: write 15 | id-token: write 16 | steps: 17 | - name: Harden Runner 18 | uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 19 | with: 20 | egress-policy: audit 21 | 22 | - name: "Checkout code" 23 | uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 24 | with: 25 | persist-credentials: false 26 | - name: "Run analysis" 27 | uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3 28 | with: 29 | results_file: results.sarif 30 | results_format: sarif 31 | publish_results: true 32 | - name: "Upload artifact" 33 | uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 34 | with: 35 | name: SARIF file 36 | path: results.sarif 37 | retention-days: 5 38 | - name: "Upload to code-scanning" 39 | uses: github/codeql-action/upload-sarif@fe4161a26a8629af62121b670040955b330f9af2 # v3.29.5 40 | with: 41 | sarif_file: results.sarif 42 | -------------------------------------------------------------------------------- /.github/workflows/python-tests.yml: -------------------------------------------------------------------------------- 1 | name: Python tests 2 | 3 | on: 4 | pull_request: 5 | branches: [main] 6 | 7 | permissions: 8 | contents: read 9 | 10 | jobs: 11 | python: 12 | runs-on: ubuntu-latest 13 | strategy: 14 | matrix: 15 | python-version: ["3.9", "3.10", "3.11", "3.12"] 16 | 17 | steps: 18 | - name: Harden Runner 19 | uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 20 | with: 21 | egress-policy: audit 22 | 23 | - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 24 | - name: Set up Python ${{ matrix.python-version }} 25 | uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 26 | with: 27 | python-version: ${{ matrix.python-version }} 28 | - name: Set up uv 29 | # Install a specific uv version using the installer 30 | run: | 31 | curl -LsSf https://astral.sh/uv/0.3.4/install.sh | sh 32 | - name: Install the project 33 | run: uv sync --all-extras --dev 34 | - name: Linting 35 | run: | 36 | uv run mypy itscalledsoccer 37 | uv run ruff check itscalledsoccer 38 | - name: Run Pytest and generate coverage file 39 | run: | 40 | uv run pytest --junitxml=pytest.xml --cov-report=term-missing:skip-covered --cov=itscalledsoccer tests/ | tee pytest-coverage.txt 41 | - name: Upload coverage to Codecov 42 | uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1 43 | env: 44 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 45 | 46 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "itscalledsoccer" 3 | description = "Programmatically interact with the American Soccer Analysis API" 4 | readme = "README.md" 5 | license = { text = "MIT" } 6 | requires-python = ">=3.9" 7 | authors = [ 8 | { name = "American Soccer Analysis", email = "americansocceranalysis@gmail.com" }, 9 | ] 10 | keywords = [ 11 | "stats", 12 | "soccer", 13 | "api", 14 | "football", 15 | "american", 16 | "machine learning", 17 | ] 18 | classifiers = [ 19 | "Programming Language :: Python", 20 | "Programming Language :: Python :: 3", 21 | "Programming Language :: Python :: 3.9", 22 | "Programming Language :: Python :: 3.10", 23 | "Programming Language :: Python :: 3.11", 24 | "Programming Language :: Python :: 3.12", 25 | ] 26 | dependencies = [ 27 | "requests>=2.31.0", 28 | "CacheControl>=0.13.1", 29 | "rapidfuzz>=3.2.0", 30 | "pandas>=2.1.0", 31 | ] 32 | version = "1.3.3" 33 | 34 | [project.urls] 35 | Repository = "https://github.com/American-Soccer-Analysis/itscalledsoccer" 36 | 37 | [tool.uv] 38 | dev-dependencies = [ 39 | "types-requests", 40 | "pytest", 41 | "pytest-cov", 42 | "mypy", 43 | "ruff", 44 | "mkdocs", 45 | "mkdocstrings[python]", 46 | "mkdocs-material" 47 | ] 48 | 49 | [build-system] 50 | requires = ["setuptools", "wheel"] 51 | build-backend = "setuptools.build_meta" 52 | 53 | [tool.setuptools.exclude-package-data] 54 | itscalledsoccer = ["tests", "tests.*"] 55 | 56 | [[tool.mypy.overrides]] 57 | module = [ 58 | "cachecontrol", 59 | "cachecontrol.heuristics", 60 | "fuzzywuzzy", 61 | "pandas", 62 | "setuptools", 63 | "rapidfuzz", 64 | ] 65 | ignore_missing_imports = true 66 | 67 | [tool.ruff.lint] 68 | ignore = ["E501"] 69 | extend-select = ["I"] 70 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.yml: -------------------------------------------------------------------------------- 1 | name: 🐛 Bug Report 2 | description: File a bug report 3 | title: "[Bug]: <title>" 4 | labels: ["bug"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for taking the time to fill out this bug report! 10 | - type: textarea 11 | id: what-happened 12 | attributes: 13 | label: What happened? 14 | description: Also tell us, what did you expect to happen? 15 | placeholder: Tell us what you see! 16 | value: "A bug happened!" 17 | validations: 18 | required: true 19 | - type: dropdown 20 | id: version 21 | attributes: 22 | label: Version 23 | description: What version of itscalledsoccer are you using? 24 | options: 25 | - 0.1.0 26 | - 0.1.1 27 | - 0.1.2 28 | - 0.1.3 29 | - 0.1.4 30 | - 0.2.0 31 | validations: 32 | required: true 33 | - type: dropdown 34 | id: python-versions 35 | attributes: 36 | label: What version of Python are you using? 37 | multiple: false 38 | options: 39 | - Python 3.7.x 40 | - Python 3.8.x 41 | - Python 3.9.x 42 | - Python 3.10.x 43 | - Python 3.11.x 44 | - Other 45 | validations: 46 | required: true 47 | - type: dropdown 48 | id: operating-system 49 | attributes: 50 | label: What operating system are you using? 51 | multiple: false 52 | options: 53 | - MacOS 54 | - Windows 55 | - Linux 56 | validations: 57 | required: true 58 | - type: textarea 59 | id: logs 60 | attributes: 61 | label: Relevant log output 62 | description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. 63 | render: sh 64 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # itscalledsoccer 2 | 3 | <!-- badges: start --> 4 | [![standard-readme compliant](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme) 5 | ![PyPi Version](https://img.shields.io/pypi/v/itscalledsoccer.svg) 6 | ![Python tests](https://github.com/American-Soccer-Analysis/itscalledsoccer/actions/workflows/python-tests.yml/badge.svg) 7 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 8 | [![PyPI download month](https://img.shields.io/pypi/dm/itscalledsoccer.svg)](https://pypi.python.org/pypi/itscalledsoccer/) 9 | <!-- badges: end --> 10 | 11 | --- 12 | 13 | ## Background 14 | 15 | `itscalledsoccer` is a wrapper around the same API that powers the [American Soccer Analysis app](https://app.americansocceranalysis.com/). It enables Python users to programmatically retrieve advanced analytics for their favorite [MLS](https://en.wikipedia.org/wiki/Major_League_Soccer), [NWSL](https://en.wikipedia.org/wiki/National_Women%27s_Soccer_League), and [USL](https://en.wikipedia.org/wiki/United_Soccer_League) players and teams. 16 | 17 | ## Install 18 | 19 | ```sh 20 | pip install itscalledsoccer 21 | ``` 22 | 23 | To install a development version, clone this repo and run the following command. 24 | 25 | ```sh 26 | pip install --editable . 27 | ``` 28 | 29 | ## Usage 30 | 31 | ```python 32 | from itscalledsoccer.client import AmericanSoccerAnalysis 33 | 34 | asa_client = AmericanSoccerAnalysis() 35 | ``` 36 | 37 | Any of the `get_*` methods can be used to retrieve the same data made available in the [American Soccer Analysis app](https://app.americansocceranalysis.com/). Partial matches or abbreviations are accepted for any player or team names. For most methods, arguments _must be named_. A few examples are below. 38 | 39 | ```python 40 | # Get all players named "Andre" 41 | asa_players = asa_client.get_players(names="Andre") 42 | ``` 43 | 44 | ## Contributing 45 | 46 | Feel free to open an issue or submit a pull request. 47 | 48 | ## License 49 | 50 | MIT © itscalledsoccer authors 51 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the 2 | // README at: https://github.com/devcontainers/templates/tree/main/src/python 3 | { 4 | "name": "itscalledsoccer (Python 3.12)", 5 | // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile 6 | "image": "mcr.microsoft.com/devcontainers/python:1-3.12-bullseye", 7 | // Features to add to the dev container. More info: https://containers.dev/features. 8 | "features": { 9 | "ghcr.io/devcontainers/features/git:1": {}, 10 | "ghcr.io/devcontainers/features/github-cli:1": {}, 11 | "ghcr.io/prulloac/devcontainer-features/pre-commit:1": {}, 12 | "ghcr.io/hspaans/devcontainer-features/pymarkdownlnt:2": {}, 13 | "ghcr.io/hspaans/devcontainer-features/pytest:2": {}, 14 | "ghcr.io/va-h/devcontainers-features/uv:1": {} 15 | }, 16 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 17 | // "forwardPorts": [], 18 | 19 | // Configure tool-specific properties. 20 | "customizations": { 21 | "vscode": { 22 | "extensions": [ 23 | "charliermarsh.ruff", 24 | "eamodio.gitlens", 25 | "ms-python.python", 26 | "njpwerner.autodocstring", 27 | "oderwat.indent-rainbow", 28 | "pkief.material-icon-theme", 29 | "yzhang.markdown-all-in-one" 30 | ], 31 | "settings": { 32 | "python.defaultInterpreterPath": "/root/.local/share/uv/python", 33 | "[python]": { 34 | "editor.defaultFormatter": "charliermarsh.ruff", 35 | "editor.codeActionsOnSave": { 36 | "source.fixAll.ruff": "explicit", 37 | "source.organizeImports.ruff": "explicit" 38 | }, 39 | "editor.formatOnSave": true 40 | }, 41 | "files.insertFinalNewline": true, 42 | "files.trimTrailingWhitespace": true 43 | } 44 | } 45 | }, 46 | // Use 'postCreateCommand' to run commands after the container is created. 47 | "postCreateCommand": "uv sync --dev" 48 | // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. 49 | // "remoteUser": "root" 50 | } 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | <!-- omit in toc --> 2 | # itscalledsoccer 3 | 4 | <div align="center"> 5 | <img src="https://raw.githubusercontent.com/American-Soccer-Analysis/itscalledsoccer-r/main/man/figures/logo.png" align="center" height="175"/> 6 | </div> 7 | 8 | <br> 9 | 10 | 11 | <!-- badges: start --> 12 | [![standard-readme compliant](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme) 13 | ![PyPi Version](https://img.shields.io/pypi/v/itscalledsoccer.svg) 14 | ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/itscalledsoccer) 15 | ![Python tests](https://github.com/American-Soccer-Analysis/itscalledsoccer/actions/workflows/python-tests.yml/badge.svg) 16 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 17 | [![PyPI download month](https://img.shields.io/pypi/dm/itscalledsoccer.svg)](https://pypi.python.org/pypi/itscalledsoccer/) 18 | [![codecov](https://codecov.io/github/American-Soccer-Analysis/itscalledsoccer/graph/badge.svg?token=RUWMM7ZLQ2)](https://codecov.io/github/American-Soccer-Analysis/itscalledsoccer) 19 | <!-- badges: end --> 20 | 21 | <!-- omit in toc --> 22 | ## Table of Contents 23 | 24 | - [Background](#background) 25 | - [Install](#install) 26 | - [Usage](#usage) 27 | - [Other versions](#other-versions) 28 | - [Contributing](#contributing) 29 | - [License](#license) 30 | 31 | ## Background 32 | 33 | `itscalledsoccer` is a wrapper around the same API that powers the [American Soccer Analysis app](https://app.americansocceranalysis.com/). It enables Python users to programmatically retrieve advanced analytics for their favorite [MLS](https://en.wikipedia.org/wiki/Major_League_Soccer), [NWSL](https://en.wikipedia.org/wiki/National_Women%27s_Soccer_League), and [USL](https://en.wikipedia.org/wiki/United_Soccer_League) players and teams. 34 | 35 | ## Install 36 | 37 | ```sh 38 | pip install itscalledsoccer 39 | ``` 40 | 41 | ## Usage 42 | 43 | ```python 44 | from itscalledsoccer.client import AmericanSoccerAnalysis 45 | 46 | asa_client = AmericanSoccerAnalysis() 47 | ``` 48 | 49 | Any of the `get_*` methods can be used to retrieve the same data made available in the [American Soccer Analysis app](https://app.americansocceranalysis.com/). Partial matches or abbreviations are accepted for any player or team names. For most methods, arguments _must be named_. 50 | 51 | For more information, check out the [documentation site](https://american-soccer-analysis.github.io/itscalledsoccer/reference). 52 | 53 | ## Other versions 54 | 55 | - [itscalledsoccer-r](https://github.com/American-Soccer-Analysis/itscalledsoccer-r) 56 | - [itscalledsoccer-js](https://github.com/American-Soccer-Analysis/itscalledsoccer-js) 57 | 58 | ## Contributing 59 | 60 | See [CONTRIBUTING.md](./CONTRIBUTING.md) 61 | 62 | ## License 63 | 64 | MIT © itscalledsoccer authors -------------------------------------------------------------------------------- /tests/mocks/goalkeepers_xgoals_payload.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "player_id": "0x5g1BmQ7O", 4 | "team_id": "9z5k7Yg5A3", 5 | "minutes_played": 879, 6 | "shots_faced": 33, 7 | "goals_conceded": 13, 8 | "saves": 17, 9 | "share_headed_shots": 0.2424, 10 | "xgoals_gk_faced": 11.3395, 11 | "goals_minus_xgoals_gk": 1.6605, 12 | "goals_divided_by_xgoals_gk": 1.1464 13 | }, 14 | { 15 | "player_id": "2lqRRj84qr", 16 | "team_id": "9z5k7Yg5A3", 17 | "minutes_played": 343, 18 | "shots_faced": 11, 19 | "goals_conceded": 5, 20 | "saves": 6, 21 | "share_headed_shots": 0.0909, 22 | "xgoals_gk_faced": 4.7403, 23 | "goals_minus_xgoals_gk": 0.2597, 24 | "goals_divided_by_xgoals_gk": 1.0548 25 | }, 26 | { 27 | "player_id": "2vQ1L20Oqr", 28 | "team_id": "9z5k7Yg5A3", 29 | "minutes_played": 2045, 30 | "shots_faced": 100, 31 | "goals_conceded": 33, 32 | "saves": 64, 33 | "share_headed_shots": 0.14, 34 | "xgoals_gk_faced": 30.2748, 35 | "goals_minus_xgoals_gk": 2.7252, 36 | "goals_divided_by_xgoals_gk": 1.09 37 | }, 38 | { 39 | "player_id": "315VXNkGQ9", 40 | "team_id": "9z5k7Yg5A3", 41 | "minutes_played": 351, 42 | "shots_faced": 11, 43 | "goals_conceded": 2, 44 | "saves": 9, 45 | "share_headed_shots": 0, 46 | "xgoals_gk_faced": 3.8287, 47 | "goals_minus_xgoals_gk": -1.8287, 48 | "goals_divided_by_xgoals_gk": 0.5224 49 | }, 50 | { 51 | "player_id": "7VqGmlO3Mv", 52 | "team_id": "9z5k7Yg5A3", 53 | "minutes_played": 97, 54 | "shots_faced": 5, 55 | "goals_conceded": 2, 56 | "saves": 2, 57 | "share_headed_shots": 0.4, 58 | "xgoals_gk_faced": 0.3417, 59 | "goals_minus_xgoals_gk": 1.6583, 60 | "goals_divided_by_xgoals_gk": 5.8528 61 | }, 62 | { 63 | "player_id": "7VqGmob3Mv", 64 | "team_id": "9z5k7Yg5A3", 65 | "minutes_played": 18408, 66 | "shots_faced": 836, 67 | "goals_conceded": 241, 68 | "saves": 583, 69 | "share_headed_shots": 0.1567, 70 | "xgoals_gk_faced": 241.04, 71 | "goals_minus_xgoals_gk": -0.0403, 72 | "goals_divided_by_xgoals_gk": 0.9998 73 | }, 74 | { 75 | "player_id": "BLMvl7ORqx", 76 | "team_id": "9z5k7Yg5A3", 77 | "minutes_played": 1157, 78 | "shots_faced": 51, 79 | "goals_conceded": 19, 80 | "saves": 31, 81 | "share_headed_shots": 0.1373, 82 | "xgoals_gk_faced": 18.5665, 83 | "goals_minus_xgoals_gk": 0.4335, 84 | "goals_divided_by_xgoals_gk": 1.0233 85 | }, 86 | { 87 | "player_id": "odMXRoXoqY", 88 | "team_id": "9z5k7Yg5A3", 89 | "minutes_played": 1238, 90 | "shots_faced": 51, 91 | "goals_conceded": 16, 92 | "saves": 32, 93 | "share_headed_shots": 0.1765, 94 | "xgoals_gk_faced": 13.355, 95 | "goals_minus_xgoals_gk": 2.645, 96 | "goals_divided_by_xgoals_gk": 1.1981 97 | }, 98 | { 99 | "player_id": "xW5pxy3l5g", 100 | "team_id": "9z5k7Yg5A3", 101 | "minutes_played": 6146, 102 | "shots_faced": 272, 103 | "goals_conceded": 87, 104 | "saves": 178, 105 | "share_headed_shots": 0.136, 106 | "xgoals_gk_faced": 88.1693, 107 | "goals_minus_xgoals_gk": -1.1693, 108 | "goals_divided_by_xgoals_gk": 0.9867 109 | } 110 | ] -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: ["main"] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: ["main"] 20 | schedule: 21 | - cron: "0 0 * * 1" 22 | 23 | permissions: 24 | contents: read 25 | 26 | jobs: 27 | analyze: 28 | name: Analyze 29 | runs-on: ubuntu-latest 30 | permissions: 31 | actions: read 32 | contents: read 33 | security-events: write 34 | 35 | strategy: 36 | fail-fast: false 37 | matrix: 38 | language: ["python"] 39 | # CodeQL supports [ $supported-codeql-languages ] 40 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 41 | 42 | steps: 43 | - name: Harden Runner 44 | uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 45 | with: 46 | egress-policy: audit 47 | 48 | - name: Checkout repository 49 | uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 50 | 51 | # Initializes the CodeQL tools for scanning. 52 | - name: Initialize CodeQL 53 | uses: github/codeql-action/init@fe4161a26a8629af62121b670040955b330f9af2 # v3.29.5 54 | with: 55 | languages: ${{ matrix.language }} 56 | # If you wish to specify custom queries, you can do so here or in a config file. 57 | # By default, queries listed here will override any specified in a config file. 58 | # Prefix the list here with "+" to use these queries and those in the config file. 59 | 60 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 61 | # If this step fails, then you should remove it and run the build manually (see below) 62 | - name: Autobuild 63 | uses: github/codeql-action/autobuild@fe4161a26a8629af62121b670040955b330f9af2 # v3.29.5 64 | 65 | # ℹ️ Command-line programs to run using the OS shell. 66 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 67 | 68 | # If the Autobuild fails above, remove it and uncomment the following three lines. 69 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 70 | 71 | # - run: | 72 | # echo "Run, Build Application using script" 73 | # ./location_of_script_within_repo/buildscript.sh 74 | 75 | - name: Perform CodeQL Analysis 76 | uses: github/codeql-action/analyze@fe4161a26a8629af62121b670040955b330f9af2 # v3.29.5 77 | with: 78 | category: "/language:${{matrix.language}}" 79 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | *.ipynb 81 | 82 | # IPython 83 | profile_default/ 84 | ipython_config.py 85 | 86 | # pyenv 87 | # For a library or package, you might want to ignore these files since the code is 88 | # intended to run in multiple environments; otherwise, check them in: 89 | # .python-version 90 | 91 | # pipenv 92 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 93 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 94 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 95 | # install all needed dependencies. 96 | #Pipfile.lock 97 | 98 | # poetry 99 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 100 | # This is especially recommended for binary packages to ensure reproducibility, and is more 101 | # commonly ignored for libraries. 102 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 103 | #poetry.lock 104 | 105 | # pdm 106 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 107 | #pdm.lock 108 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 109 | # in version control. 110 | # https://pdm.fming.dev/#use-with-ide 111 | .pdm.toml 112 | 113 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 114 | __pypackages__/ 115 | 116 | # Celery stuff 117 | celerybeat-schedule 118 | celerybeat.pid 119 | 120 | # SageMath parsed files 121 | *.sage.py 122 | 123 | # Environments 124 | .env 125 | .venv 126 | env/ 127 | venv/ 128 | ENV/ 129 | env.bak/ 130 | venv.bak/ 131 | 132 | # Spyder project settings 133 | .spyderproject 134 | .spyproject 135 | 136 | # Rope project settings 137 | .ropeproject 138 | 139 | # mkdocs documentation 140 | /site 141 | 142 | # mypy 143 | .mypy_cache/ 144 | .dmypy.json 145 | dmypy.json 146 | 147 | # Pyre type checker 148 | .pyre/ 149 | 150 | # pytype static type analyzer 151 | .pytype/ 152 | 153 | # Cython debug symbols 154 | cython_debug/ 155 | 156 | # PyCharm 157 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 158 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 159 | # and can be added to the global gitignore or merged into this file. For a more nuclear 160 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 161 | #.idea/ 162 | 163 | # Mac 164 | .DS_Store -------------------------------------------------------------------------------- /tests/mocks/teams_payload.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "team_id": "0KPqjA456v", 4 | "team_name": "San Jose Earthquakes", 5 | "team_short_name": "San Jose", 6 | "team_abbreviation": "SJE" 7 | }, 8 | { 9 | "team_id": "19vQ2095K6", 10 | "team_name": "New England Revolution", 11 | "team_short_name": "New England", 12 | "team_abbreviation": "NER" 13 | }, 14 | { 15 | "team_id": "4wM42l4qjB", 16 | "team_name": "Chivas USA", 17 | "team_short_name": "Chivas", 18 | "team_abbreviation": "CHV" 19 | }, 20 | { 21 | "team_id": "9z5k7Yg5A3", 22 | "team_name": "Philadelphia Union", 23 | "team_short_name": "Philadelphia", 24 | "team_abbreviation": "PHI" 25 | }, 26 | { 27 | "team_id": "a2lqR4JMr0", 28 | "team_name": "Real Salt Lake", 29 | "team_short_name": "Salt Lake", 30 | "team_abbreviation": "RSL" 31 | }, 32 | { 33 | "team_id": "a2lqRX2Mr0", 34 | "team_name": "New York Red Bulls", 35 | "team_short_name": "New York", 36 | "team_abbreviation": "NYRB" 37 | }, 38 | { 39 | "team_id": "APk5LGOMOW", 40 | "team_name": "CF Montréal", 41 | "team_short_name": "Montréal", 42 | "team_abbreviation": "MTL" 43 | }, 44 | { 45 | "team_id": "EKXMeX3Q64", 46 | "team_name": "D.C. United", 47 | "team_short_name": "D.C. United", 48 | "team_abbreviation": "DCU" 49 | }, 50 | { 51 | "team_id": "eVq3ya6MWO", 52 | "team_name": "Los Angeles FC", 53 | "team_short_name": "Los Angeles FC", 54 | "team_abbreviation": "LAFC" 55 | }, 56 | { 57 | "team_id": "gpMOLwl5zy", 58 | "team_name": "Austin FC", 59 | "team_short_name": "Austin", 60 | "team_abbreviation": "ATX" 61 | }, 62 | { 63 | "team_id": "jYQJ19EqGR", 64 | "team_name": "Seattle Sounders FC", 65 | "team_short_name": "Seattle", 66 | "team_abbreviation": "SEA" 67 | }, 68 | { 69 | "team_id": "jYQJ8EW5GR", 70 | "team_name": "Orlando City SC", 71 | "team_short_name": "Orlando City", 72 | "team_abbreviation": "ORL" 73 | }, 74 | { 75 | "team_id": "kaDQ0wRqEv", 76 | "team_name": "LA Galaxy", 77 | "team_short_name": "LA Galaxy", 78 | "team_abbreviation": "LAG" 79 | }, 80 | { 81 | "team_id": "KAqBN0Vqbg", 82 | "team_name": "Atlanta United FC", 83 | "team_short_name": "Atlanta", 84 | "team_abbreviation": "ATL" 85 | }, 86 | { 87 | "team_id": "kRQabn8MKZ", 88 | "team_name": "Toronto FC", 89 | "team_short_name": "Toronto", 90 | "team_abbreviation": "TOR" 91 | }, 92 | { 93 | "team_id": "kRQand1MKZ", 94 | "team_name": "Minnesota United FC", 95 | "team_short_name": "Minnesota", 96 | "team_abbreviation": "MIN" 97 | }, 98 | { 99 | "team_id": "lgpMOvnQzy", 100 | "team_name": "Vancouver Whitecaps FC", 101 | "team_short_name": "Vancouver", 102 | "team_abbreviation": "VAN" 103 | }, 104 | { 105 | "team_id": "mKAqBBmqbg", 106 | "team_name": "FC Dallas", 107 | "team_short_name": "Dallas", 108 | "team_abbreviation": "FCD" 109 | }, 110 | { 111 | "team_id": "mvzqoLZQap", 112 | "team_name": "Columbus Crew", 113 | "team_short_name": "Columbus", 114 | "team_abbreviation": "CLB" 115 | }, 116 | { 117 | "team_id": "NPqxKXZ59d", 118 | "team_name": "Charlotte FC", 119 | "team_short_name": "Charlotte", 120 | "team_abbreviation": "CLT" 121 | }, 122 | { 123 | "team_id": "NWMWlBK5lz", 124 | "team_name": "FC Cincinnati", 125 | "team_short_name": "Cincinnati", 126 | "team_abbreviation": "CIN" 127 | }, 128 | { 129 | "team_id": "pzeQZ6xQKw", 130 | "team_name": "Colorado Rapids", 131 | "team_short_name": "Colorado", 132 | "team_abbreviation": "COL" 133 | }, 134 | { 135 | "team_id": "Vj58weDM8n", 136 | "team_name": "New York City FC", 137 | "team_short_name": "New York City", 138 | "team_abbreviation": "NYC" 139 | }, 140 | { 141 | "team_id": "vzqoOgNqap", 142 | "team_name": "Nashville SC", 143 | "team_short_name": "Nashville", 144 | "team_abbreviation": "NSH" 145 | }, 146 | { 147 | "team_id": "WBLMvYAQxe", 148 | "team_name": "Portland Timbers FC", 149 | "team_short_name": "Portland", 150 | "team_abbreviation": "POR" 151 | }, 152 | { 153 | "team_id": "X0Oq66zq6D", 154 | "team_name": "Chicago Fire FC", 155 | "team_short_name": "Chicago", 156 | "team_abbreviation": "CHI" 157 | }, 158 | { 159 | "team_id": "YgOMngl5wN", 160 | "team_name": "Houston Dynamo FC", 161 | "team_short_name": "Houston", 162 | "team_abbreviation": "HOU" 163 | }, 164 | { 165 | "team_id": "Z2vQ1xlqrA", 166 | "team_name": "Sporting Kansas City", 167 | "team_short_name": "Kansas City", 168 | "team_abbreviation": "SKC" 169 | }, 170 | { 171 | "team_id": "zeQZkL1MKw", 172 | "team_name": "Inter Miami CF", 173 | "team_short_name": "Miami", 174 | "team_abbreviation": "MIA" 175 | } 176 | ] -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | 2 | # Contributor Covenant Code of Conduct 3 | 4 | ## Our Pledge 5 | 6 | We as members, contributors, and leaders pledge to make participation in our 7 | community a harassment-free experience for everyone, regardless of age, body 8 | size, visible or invisible disability, ethnicity, sex characteristics, gender 9 | identity and expression, level of experience, education, socio-economic status, 10 | nationality, personal appearance, race, caste, color, religion, or sexual 11 | identity and orientation. 12 | 13 | We pledge to act and interact in ways that contribute to an open, welcoming, 14 | diverse, inclusive, and healthy community. 15 | 16 | ## Our Standards 17 | 18 | Examples of behavior that contributes to a positive environment for our 19 | community include: 20 | 21 | * Demonstrating empathy and kindness toward other people 22 | * Being respectful of differing opinions, viewpoints, and experiences 23 | * Giving and gracefully accepting constructive feedback 24 | * Accepting responsibility and apologizing to those affected by our mistakes, 25 | and learning from the experience 26 | * Focusing on what is best not just for us as individuals, but for the overall 27 | community 28 | 29 | Examples of unacceptable behavior include: 30 | 31 | * The use of sexualized language or imagery, and sexual attention or advances of 32 | any kind 33 | * Trolling, insulting or derogatory comments, and personal or political attacks 34 | * Public or private harassment 35 | * Publishing others' private information, such as a physical or email address, 36 | without their explicit permission 37 | * Other conduct which could reasonably be considered inappropriate in a 38 | professional setting 39 | 40 | ## Enforcement Responsibilities 41 | 42 | Community leaders are responsible for clarifying and enforcing our standards of 43 | acceptable behavior and will take appropriate and fair corrective action in 44 | response to any behavior that they deem inappropriate, threatening, offensive, 45 | or harmful. 46 | 47 | Community leaders have the right and responsibility to remove, edit, or reject 48 | comments, commits, code, wiki edits, issues, and other contributions that are 49 | not aligned to this Code of Conduct, and will communicate reasons for moderation 50 | decisions when appropriate. 51 | 52 | ## Scope 53 | 54 | This Code of Conduct applies within all community spaces, and also applies when 55 | an individual is officially representing the community in public spaces. 56 | Examples of representing our community include using an official email address, 57 | posting via an official social media account, or acting as an appointed 58 | representative at an online or offline event. 59 | 60 | ## Enforcement 61 | 62 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 63 | reported to the community leaders responsible for enforcement at `americansocceranalysis@gmail.com`. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series of 86 | actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or permanent 93 | ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within the 113 | community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.1, available at 119 | [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. 120 | 121 | Community Impact Guidelines were inspired by 122 | [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. 123 | 124 | For answers to common questions about this code of conduct, see the FAQ at 125 | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at 126 | [https://www.contributor-covenant.org/translations][translations]. 127 | 128 | [homepage]: https://www.contributor-covenant.org 129 | [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html 130 | [Mozilla CoC]: https://github.com/mozilla/diversity 131 | [FAQ]: https://www.contributor-covenant.org/faq 132 | [translations]: https://www.contributor-covenant.org/translations -------------------------------------------------------------------------------- /tests/mocks/referees_payload.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "referee_id": "0Oq6037M6D", 4 | "referee_name": "Alan Kelly", 5 | "birth_date": "1975-04-09", 6 | "nationality": "Republic of Ireland" 7 | }, 8 | { 9 | "referee_id": "0Oq60rxM6D", 10 | "referee_name": "Matthew Foerster", 11 | "nationality": "USA" 12 | }, 13 | { 14 | "referee_id": "0Oq6mnX56D", 15 | "referee_name": "Michael Radchuk", 16 | "nationality": "USA" 17 | }, 18 | { 19 | "referee_id": "0Oq6vG2q6D", 20 | "referee_name": "Marcos de Oliveira", 21 | "nationality": "USA" 22 | }, 23 | { 24 | "referee_id": "2lqRG1WQr0", 25 | "referee_name": "Lukasz Szpala", 26 | "nationality": "USA" 27 | }, 28 | { 29 | "referee_id": "2lqRNx4qr0", 30 | "referee_name": "Geoff Gamble", 31 | "nationality": "USA" 32 | }, 33 | { 34 | "referee_id": "2lqRokLQr0", 35 | "referee_name": "Tori Penso", 36 | "nationality": "USA" 37 | }, 38 | { 39 | "referee_id": "2lqRymD5r0", 40 | "referee_name": "Victor Rivas", 41 | "nationality": "USA" 42 | }, 43 | { 44 | "referee_id": "315VrXb59x", 45 | "referee_name": "Kevin Stott", 46 | "birth_date": "1967-07-09", 47 | "nationality": "USA" 48 | }, 49 | { 50 | "referee_id": "4JMAYlPMKg", 51 | "referee_name": "Jon Freemon", 52 | "nationality": "USA" 53 | }, 54 | { 55 | "referee_id": "4wM40nzMjB", 56 | "referee_name": "Sorin Stoica", 57 | "birth_date": "1976-01-05", 58 | "nationality": "USA" 59 | }, 60 | { 61 | "referee_id": "4wM4voBqjB", 62 | "referee_name": "Ramy Touchan", 63 | "nationality": "USA" 64 | }, 65 | { 66 | "referee_id": "7VqG6KX5vW", 67 | "referee_name": "Nima Saghafi", 68 | "nationality": "USA" 69 | }, 70 | { 71 | "referee_id": "7VqG6Vj5vW", 72 | "referee_name": "Mathieu Bourdeau", 73 | "birth_date": "1980-04-24", 74 | "nationality": "Canada" 75 | }, 76 | { 77 | "referee_id": "7VqGEDAMvW", 78 | "referee_name": "Jaime Herrera", 79 | "nationality": "Mexico" 80 | }, 81 | { 82 | "referee_id": "7VqGGGzqvW", 83 | "referee_name": "Yader Reyes", 84 | "nationality": "USA" 85 | }, 86 | { 87 | "referee_id": "9vQ202r5K6", 88 | "referee_name": "Hilario Grajeda", 89 | "birth_date": "1967-09-02", 90 | "nationality": "USA" 91 | }, 92 | { 93 | "referee_id": "9vQ28gY5K6", 94 | "referee_name": "Elton García", 95 | "nationality": "USA" 96 | }, 97 | { 98 | "referee_id": "9vQ2mPaqK6", 99 | "referee_name": "Rosendo Mendoza", 100 | "nationality": "USA" 101 | }, 102 | { 103 | "referee_id": "9YqdEL9QvJ", 104 | "referee_name": "José Carlos Rivero", 105 | "birth_date": "1981-05-02", 106 | "nationality": "USA" 107 | }, 108 | { 109 | "referee_id": "9z5kJ7gMA3", 110 | "referee_name": "Jair Marrufo", 111 | "birth_date": "1977-06-17", 112 | "nationality": "USA" 113 | }, 114 | { 115 | "referee_id": "9z5kJJeMA3", 116 | "referee_name": "Elias Bazakos", 117 | "nationality": "USA" 118 | }, 119 | { 120 | "referee_id": "9z5kJRKMA3", 121 | "referee_name": "Ramon Hernandez", 122 | "nationality": "USA" 123 | }, 124 | { 125 | "referee_id": "a35r6KG5L6", 126 | "referee_name": "Mark Geiger", 127 | "birth_date": "1974-08-25", 128 | "nationality": "USA" 129 | }, 130 | { 131 | "referee_id": "a35rgjLqL6", 132 | "referee_name": "Ismir Pekmic", 133 | "nationality": "USA" 134 | }, 135 | { 136 | "referee_id": "aDQ00DRQEv", 137 | "referee_name": "Radu Petrescu", 138 | "birth_date": "1982-11-12", 139 | "nationality": "Romania" 140 | }, 141 | { 142 | "referee_id": "aDQ0mkPMEv", 143 | "referee_name": "Pierre-Luc Lauziere", 144 | "birth_date": "1985-08-12", 145 | "nationality": "Canada" 146 | }, 147 | { 148 | "referee_id": "e7MzPKXqr0", 149 | "referee_name": "Ismail Elfath", 150 | "birth_date": "1982-03-03", 151 | "nationality": "USA" 152 | }, 153 | { 154 | "referee_id": "EGMPLlxMaY", 155 | "referee_name": "Ted Unkel", 156 | "birth_date": "1978-02-28", 157 | "nationality": "USA" 158 | }, 159 | { 160 | "referee_id": "EGMPPnAMaY", 161 | "referee_name": "Baldomero Toledo", 162 | "birth_date": "1970-02-06", 163 | "nationality": "USA" 164 | }, 165 | { 166 | "referee_id": "eVq3vBj5WO", 167 | "referee_name": "Abbey Okulaja", 168 | "nationality": "USA" 169 | }, 170 | { 171 | "referee_id": "eVq3vbv5WO", 172 | "referee_name": "William Anderson", 173 | "nationality": "Puerto Rico" 174 | }, 175 | { 176 | "referee_id": "gjMNk4v5Kp", 177 | "referee_name": "Armando Villarreal", 178 | "birth_date": "1986-05-31", 179 | "nationality": "USA" 180 | }, 181 | { 182 | "referee_id": "gOMnB7AMwN", 183 | "referee_name": "David Gantar", 184 | "birth_date": "1975-06-27", 185 | "nationality": "Canada" 186 | }, 187 | { 188 | "referee_id": "gpMOPj15zy", 189 | "referee_name": "Ioannis Stavridis", 190 | "nationality": "Greece" 191 | }, 192 | { 193 | "referee_id": "jYQJnnZQGR", 194 | "referee_name": "Edvin Jurisevic", 195 | "birth_date": "1975-06-07", 196 | "nationality": "USA" 197 | }, 198 | { 199 | "referee_id": "jYQJnoVQGR", 200 | "referee_name": "Chris Penso", 201 | "birth_date": "1982-04-28", 202 | "nationality": "USA" 203 | }, 204 | { 205 | "referee_id": "KAqB3m7Qbg", 206 | "referee_name": "Robert Sibiga", 207 | "nationality": "USA" 208 | }, 209 | { 210 | "referee_id": "KPqjb74q6v", 211 | "referee_name": "Jorge Gonzalez", 212 | "birth_date": "1968-07-11", 213 | "nationality": "USA" 214 | }, 215 | { 216 | "referee_id": "KPqjDeNM6v", 217 | "referee_name": "Alex Chilowicz", 218 | "nationality": "USA" 219 | }, 220 | { 221 | "referee_id": "kRQa9k8QKZ", 222 | "referee_name": "Timothy Ford", 223 | "nationality": "USA" 224 | }, 225 | { 226 | "referee_id": "ljqEgwOMx0", 227 | "referee_name": "Andres Pfefferkorn", 228 | "nationality": "USA" 229 | }, 230 | { 231 | "referee_id": "ljqExYw5x0", 232 | "referee_name": "Rubiel Vazquez", 233 | "nationality": "USA" 234 | }, 235 | { 236 | "referee_id": "ljqEymNqx0", 237 | "referee_name": "Malik Badawi", 238 | "nationality": "USA" 239 | }, 240 | { 241 | "referee_id": "Oa5w93jQ14", 242 | "referee_name": "Kevin Morrison", 243 | "nationality": "Jamaica" 244 | }, 245 | { 246 | "referee_id": "Oa5w9R9Q14", 247 | "referee_name": "Juan Guzman", 248 | "birth_date": "1986-12-18", 249 | "nationality": "USA" 250 | }, 251 | { 252 | "referee_id": "odMX96a5YL", 253 | "referee_name": "Joseph Dickerson", 254 | "nationality": "USA" 255 | }, 256 | { 257 | "referee_id": "odMXjR0qYL", 258 | "referee_name": "Ricardo Salazar", 259 | "birth_date": "1972-09-06", 260 | "nationality": "USA" 261 | }, 262 | { 263 | "referee_id": "p6qbdV6M0G", 264 | "referee_name": "Alejandro Mariscal", 265 | "birth_date": "1980-09-14", 266 | "nationality": "USA" 267 | }, 268 | { 269 | "referee_id": "Pk5LRamQOW", 270 | "referee_name": "Daniel Fitzgerald", 271 | "birth_date": "1984-10-19", 272 | "nationality": "USA" 273 | }, 274 | { 275 | "referee_id": "Pk5LRpDQOW", 276 | "referee_name": "Drew Fischer", 277 | "birth_date": "1980-07-10", 278 | "nationality": "Canada" 279 | }, 280 | { 281 | "referee_id": "vzqoWjkqap", 282 | "referee_name": "Allen Chapman", 283 | "birth_date": "1974-08-18", 284 | "nationality": "USA" 285 | }, 286 | { 287 | "referee_id": "wvq9vKlQWn", 288 | "referee_name": "Guido Gonzales Jr.", 289 | "nationality": "USA" 290 | }, 291 | { 292 | "referee_id": "Xj5YrBaqbd", 293 | "referee_name": "Mark Kadlecik", 294 | "birth_date": "1977-01-04", 295 | "nationality": "USA" 296 | }, 297 | { 298 | "referee_id": "xW5pgWYMg1", 299 | "referee_name": "Carlos Rivera", 300 | "nationality": "Peru" 301 | }, 302 | { 303 | "referee_id": "xW5pW6RMg1", 304 | "referee_name": "Javier Santos", 305 | "nationality": "Puerto Rico" 306 | }, 307 | { 308 | "referee_id": "zeQZl7D5Kw", 309 | "referee_name": "Silviu Petrescu", 310 | "birth_date": "1968-10-06", 311 | "nationality": "Romania" 312 | }, 313 | { 314 | "referee_id": "zeQZlGK5Kw", 315 | "referee_name": "Fotis Bazakos", 316 | "birth_date": "1979-08-03", 317 | "nationality": "USA" 318 | }, 319 | { 320 | "referee_id": "zeQZlOr5Kw", 321 | "referee_name": "Jorge Luna Hernandez", 322 | "nationality": "USA" 323 | } 324 | ] -------------------------------------------------------------------------------- /tests/mocks/teams_salaries_payload.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "team_id": "0KPqjA456v", 4 | "count_players": 281, 5 | "total_guaranteed_compensation": 71816158, 6 | "avg_guaranteed_compensation": 255573.516, 7 | "median_guaranteed_compensation": 148333, 8 | "std_dev_guaranteed_compensation": 289424.9164 9 | }, 10 | { 11 | "team_id": "19vQ2095K6", 12 | "count_players": 258, 13 | "total_guaranteed_compensation": 75234971.6, 14 | "avg_guaranteed_compensation": 291608.4171, 15 | "median_guaranteed_compensation": 135833.5, 16 | "std_dev_guaranteed_compensation": 473794.2221 17 | }, 18 | { 19 | "team_id": "4wM42l4qjB", 20 | "count_players": 75, 21 | "total_guaranteed_compensation": 7861261, 22 | "avg_guaranteed_compensation": 104816.8133, 23 | "median_guaranteed_compensation": 80004, 24 | "std_dev_guaranteed_compensation": 81590.1739 25 | }, 26 | { 27 | "team_id": "9z5k7Yg5A3", 28 | "count_players": 283, 29 | "total_guaranteed_compensation": 68227593.8, 30 | "avg_guaranteed_compensation": 241086.9039, 31 | "median_guaranteed_compensation": 125093, 32 | "std_dev_guaranteed_compensation": 300566.1162 33 | }, 34 | { 35 | "team_id": "a2lqR4JMr0", 36 | "count_players": 277, 37 | "total_guaranteed_compensation": 72194717, 38 | "avg_guaranteed_compensation": 260630.7473, 39 | "median_guaranteed_compensation": 131254, 40 | "std_dev_guaranteed_compensation": 345715.5213 41 | }, 42 | { 43 | "team_id": "a2lqRX2Mr0", 44 | "count_players": 279, 45 | "total_guaranteed_compensation": 77644401, 46 | "avg_guaranteed_compensation": 278295.3441, 47 | "median_guaranteed_compensation": 123745, 48 | "std_dev_guaranteed_compensation": 514291.4914 49 | }, 50 | { 51 | "team_id": "APk5LGOMOW", 52 | "count_players": 299, 53 | "total_guaranteed_compensation": 86756836.2, 54 | "avg_guaranteed_compensation": 290156.6428, 55 | "median_guaranteed_compensation": 129811, 56 | "std_dev_guaranteed_compensation": 546371.6301 57 | }, 58 | { 59 | "team_id": "EKXMeX3Q64", 60 | "count_players": 279, 61 | "total_guaranteed_compensation": 68016325.6, 62 | "avg_guaranteed_compensation": 243786.1133, 63 | "median_guaranteed_compensation": 130000, 64 | "std_dev_guaranteed_compensation": 343623.0395 65 | }, 66 | { 67 | "team_id": "eVq3ya6MWO", 68 | "count_players": 131, 69 | "total_guaranteed_compensation": 62624937.1, 70 | "avg_guaranteed_compensation": 478052.955, 71 | "median_guaranteed_compensation": 170000, 72 | "std_dev_guaranteed_compensation": 1080858.2968 73 | }, 74 | { 75 | "team_id": "gpMOLwl5zy", 76 | "count_players": 32, 77 | "total_guaranteed_compensation": 12863851, 78 | "avg_guaranteed_compensation": 401995.3438, 79 | "median_guaranteed_compensation": 250000, 80 | "std_dev_guaranteed_compensation": 543257.7077 81 | }, 82 | { 83 | "team_id": "jYQJ19EqGR", 84 | "count_players": 278, 85 | "total_guaranteed_compensation": 115634784.3, 86 | "avg_guaranteed_compensation": 415952.4615, 87 | "median_guaranteed_compensation": 118500, 88 | "std_dev_guaranteed_compensation": 805985.2647 89 | }, 90 | { 91 | "team_id": "jYQJ8EW5GR", 92 | "count_players": 233, 93 | "total_guaranteed_compensation": 92525881.2, 94 | "avg_guaranteed_compensation": 397106.7863, 95 | "median_guaranteed_compensation": 137465, 96 | "std_dev_guaranteed_compensation": 974309.3102 97 | }, 98 | { 99 | "team_id": "kaDQ0wRqEv", 100 | "count_players": 279, 101 | "total_guaranteed_compensation": 154266728.7, 102 | "avg_guaranteed_compensation": 552927.343, 103 | "median_guaranteed_compensation": 130000, 104 | "std_dev_guaranteed_compensation": 1200049.5992 105 | }, 106 | { 107 | "team_id": "KAqBN0Vqbg", 108 | "count_players": 173, 109 | "total_guaranteed_compensation": 70284379.3, 110 | "avg_guaranteed_compensation": 406268.0884, 111 | "median_guaranteed_compensation": 150000, 112 | "std_dev_guaranteed_compensation": 643048.8733 113 | }, 114 | { 115 | "team_id": "kRQabn8MKZ", 116 | "count_players": 293, 117 | "total_guaranteed_compensation": 181850080.6, 118 | "avg_guaranteed_compensation": 620648.7392, 119 | "median_guaranteed_compensation": 125000, 120 | "std_dev_guaranteed_compensation": 1484337.5783 121 | }, 122 | { 123 | "team_id": "kRQand1MKZ", 124 | "count_players": 161, 125 | "total_guaranteed_compensation": 50572450, 126 | "avg_guaranteed_compensation": 314114.5963, 127 | "median_guaranteed_compensation": 208761, 128 | "std_dev_guaranteed_compensation": 343872.6602 129 | }, 130 | { 131 | "team_id": "lgpMOvnQzy", 132 | "count_players": 299, 133 | "total_guaranteed_compensation": 73381832.9, 134 | "avg_guaranteed_compensation": 245424.1903, 135 | "median_guaranteed_compensation": 132000, 136 | "std_dev_guaranteed_compensation": 305209.5286 137 | }, 138 | { 139 | "team_id": "mKAqBBmqbg", 140 | "count_players": 289, 141 | "total_guaranteed_compensation": 71359727.4, 142 | "avg_guaranteed_compensation": 246919.472, 143 | "median_guaranteed_compensation": 136000, 144 | "std_dev_guaranteed_compensation": 312902.3329 145 | }, 146 | { 147 | "team_id": "mvzqoLZQap", 148 | "count_players": 279, 149 | "total_guaranteed_compensation": 75267949, 150 | "avg_guaranteed_compensation": 269777.595, 151 | "median_guaranteed_compensation": 142500, 152 | "std_dev_guaranteed_compensation": 336064.6244 153 | }, 154 | { 155 | "team_id": "NPqxKXZ59d", 156 | "count_players": 2, 157 | "total_guaranteed_compensation": 154252, 158 | "avg_guaranteed_compensation": 77126, 159 | "median_guaranteed_compensation": 77126, 160 | "std_dev_guaranteed_compensation": 19203.606 161 | }, 162 | { 163 | "team_id": "NWMWlBK5lz", 164 | "count_players": 106, 165 | "total_guaranteed_compensation": 43576057.5, 166 | "avg_guaranteed_compensation": 411094.8821, 167 | "median_guaranteed_compensation": 214252, 168 | "std_dev_guaranteed_compensation": 537673.9568 169 | }, 170 | { 171 | "team_id": "pzeQZ6xQKw", 172 | "count_players": 279, 173 | "total_guaranteed_compensation": 69731088.3, 174 | "avg_guaranteed_compensation": 249932.2161, 175 | "median_guaranteed_compensation": 116625, 176 | "std_dev_guaranteed_compensation": 379786.2191 177 | }, 178 | { 179 | "team_id": "Vj58weDM8n", 180 | "count_players": 208, 181 | "total_guaranteed_compensation": 111550230.2, 182 | "avg_guaranteed_compensation": 536299.1837, 183 | "median_guaranteed_compensation": 170250, 184 | "std_dev_guaranteed_compensation": 1151005.6917 185 | }, 186 | { 187 | "team_id": "vzqoOgNqap", 188 | "count_players": 70, 189 | "total_guaranteed_compensation": 23219734.7, 190 | "avg_guaranteed_compensation": 331710.4957, 191 | "median_guaranteed_compensation": 155250, 192 | "std_dev_guaranteed_compensation": 368016.5913 193 | }, 194 | { 195 | "team_id": "WBLMvYAQxe", 196 | "count_players": 275, 197 | "total_guaranteed_compensation": 86438959.9, 198 | "avg_guaranteed_compensation": 314323.4905, 199 | "median_guaranteed_compensation": 150000, 200 | "std_dev_guaranteed_compensation": 448760.2808 201 | }, 202 | { 203 | "team_id": "X0Oq66zq6D", 204 | "count_players": 278, 205 | "total_guaranteed_compensation": 97256662.6, 206 | "avg_guaranteed_compensation": 349844.1101, 207 | "median_guaranteed_compensation": 125000, 208 | "std_dev_guaranteed_compensation": 710942.3653 209 | }, 210 | { 211 | "team_id": "YgOMngl5wN", 212 | "count_players": 272, 213 | "total_guaranteed_compensation": 62636020.1, 214 | "avg_guaranteed_compensation": 230279.4857, 215 | "median_guaranteed_compensation": 160625, 216 | "std_dev_guaranteed_compensation": 250005.2586 217 | }, 218 | { 219 | "team_id": "Z2vQ1xlqrA", 220 | "count_players": 282, 221 | "total_guaranteed_compensation": 81893036.9, 222 | "avg_guaranteed_compensation": 290400.8401, 223 | "median_guaranteed_compensation": 128756, 224 | "std_dev_guaranteed_compensation": 366206.9294 225 | }, 226 | { 227 | "team_id": "zeQZkL1MKw", 228 | "count_players": 65, 229 | "total_guaranteed_compensation": 32602949, 230 | "avg_guaranteed_compensation": 501583.8308, 231 | "median_guaranteed_compensation": 170833, 232 | "std_dev_guaranteed_compensation": 932783.2593 233 | }, 234 | { 235 | "count_players": 47, 236 | "total_guaranteed_compensation": 20969896, 237 | "avg_guaranteed_compensation": 446168, 238 | "median_guaranteed_compensation": 85444, 239 | "std_dev_guaranteed_compensation": 1046093.7911 240 | } 241 | ] -------------------------------------------------------------------------------- /tests/test_client.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from unittest.mock import patch 3 | 4 | from pandas import DataFrame, read_json 5 | from pytest import fixture 6 | 7 | from itscalledsoccer.client import AmericanSoccerAnalysis 8 | 9 | 10 | @fixture(scope="session") 11 | @patch("itscalledsoccer.client.AmericanSoccerAnalysis._get_entity") 12 | def init_client(self): 13 | return AmericanSoccerAnalysis() 14 | 15 | 16 | class TestClient: 17 | def test_init(self, init_client): 18 | self.client = init_client 19 | assert self.client.API_VERSION == "v1" 20 | assert self.client.BASE_URL == "https://app.americansocceranalysis.com/api/v1/" 21 | assert self.client.MAX_API_LIMIT == 1000 22 | assert self.client.LEAGUES == ["nwsl", "mls", "uslc", "usl1", "nasl", "mlsnp"] 23 | assert self.client.LOGGER is not None 24 | assert self.client.LOGGER.getEffectiveLevel() == 30 25 | 26 | @patch("itscalledsoccer.client.AmericanSoccerAnalysis._get_entity") 27 | def test_proxy(self, mock_entity): 28 | proxies = {"http": "http://foo", "https": "https://bar"} 29 | self.client = AmericanSoccerAnalysis(proxies=proxies) 30 | assert self.client.session.proxies == proxies 31 | 32 | @patch("itscalledsoccer.client.AmericanSoccerAnalysis._get_entity") 33 | def test_logging_level(self, mock_entity): 34 | self.client = AmericanSoccerAnalysis(logging_level="DEBUG") 35 | assert self.client.LOGGER.getEffectiveLevel() == 10 36 | 37 | def load_mock_data(self, func_name: str): 38 | path = Path(__file__).parent 39 | file = Path(path, f"./mocks/{func_name}_payload.json") 40 | return read_json(file) 41 | 42 | def test_get_player_xgoals(self, init_client): 43 | self.client = init_client 44 | with patch( 45 | "itscalledsoccer.client.AmericanSoccerAnalysis._get_stats" 46 | ) as mock_stats: 47 | mock_stats.return_value = self.load_mock_data("players_xgoals") 48 | data = self.client.get_player_xgoals() 49 | assert data is not None 50 | assert isinstance(data, DataFrame) 51 | assert len(data) >= 2 52 | 53 | def test_get_player_xpass(self, init_client): 54 | self.client = init_client 55 | with patch( 56 | "itscalledsoccer.client.AmericanSoccerAnalysis._get_stats" 57 | ) as mock_stats: 58 | mock_stats.return_value = self.load_mock_data("players_xpass") 59 | data = self.client.get_player_xpass() 60 | assert data is not None 61 | assert isinstance(data, DataFrame) 62 | assert len(data) >= 2 63 | 64 | def test_get_player_goals_added(self, init_client): 65 | self.client = init_client 66 | with patch( 67 | "itscalledsoccer.client.AmericanSoccerAnalysis._get_stats" 68 | ) as mock_stats: 69 | mock_stats.return_value = self.load_mock_data("players_goals_added") 70 | data = self.client.get_player_goals_added() 71 | assert data is not None 72 | assert isinstance(data, DataFrame) 73 | assert len(data) >= 2 74 | 75 | def test_get_player_salaries(self, init_client): 76 | self.client = init_client 77 | with patch( 78 | "itscalledsoccer.client.AmericanSoccerAnalysis._get_stats" 79 | ) as mock_stats: 80 | mock_stats.return_value = self.load_mock_data("players_salaries") 81 | data = self.client.get_player_salaries() 82 | assert data is not None 83 | assert isinstance(data, DataFrame) 84 | assert len(data) >= 2 85 | 86 | def test_get_goalkeeper_xgoals(self, init_client): 87 | self.client = init_client 88 | with patch( 89 | "itscalledsoccer.client.AmericanSoccerAnalysis._get_stats" 90 | ) as mock_stats: 91 | mock_stats.return_value = self.load_mock_data("goalkeepers_xgoals") 92 | data = self.client.get_goalkeeper_xgoals() 93 | assert data is not None 94 | assert isinstance(data, DataFrame) 95 | assert len(data) >= 2 96 | 97 | def test_get_goalkeeper_goals_added(self, init_client): 98 | self.client = init_client 99 | with patch( 100 | "itscalledsoccer.client.AmericanSoccerAnalysis._get_stats" 101 | ) as mock_stats: 102 | mock_stats.return_value = self.load_mock_data("goalkeepers_goals_added") 103 | data = self.client.get_goalkeeper_goals_added() 104 | assert data is not None 105 | assert isinstance(data, DataFrame) 106 | assert len(data) >= 2 107 | 108 | def test_get_team_xgoals(self, init_client): 109 | self.client = init_client 110 | with patch( 111 | "itscalledsoccer.client.AmericanSoccerAnalysis._get_stats" 112 | ) as mock_stats: 113 | mock_stats.return_value = self.load_mock_data("teams_xgoals") 114 | data = self.client.get_team_xgoals() 115 | assert data is not None 116 | assert isinstance(data, DataFrame) 117 | assert len(data) >= 2 118 | 119 | def test_get_team_xpass(self, init_client): 120 | self.client = init_client 121 | with patch( 122 | "itscalledsoccer.client.AmericanSoccerAnalysis._get_stats" 123 | ) as mock_stats: 124 | mock_stats.return_value = self.load_mock_data("teams_xpass") 125 | data = self.client.get_team_xpass() 126 | assert data is not None 127 | assert isinstance(data, DataFrame) 128 | assert len(data) >= 2 129 | 130 | def test_get_team_goals_added(self, init_client): 131 | self.client = init_client 132 | with patch( 133 | "itscalledsoccer.client.AmericanSoccerAnalysis._get_stats" 134 | ) as mock_stats: 135 | mock_stats.return_value = self.load_mock_data("teams_goals_added") 136 | data = self.client.get_team_goals_added() 137 | assert data is not None 138 | assert isinstance(data, DataFrame) 139 | assert len(data) >= 2 140 | 141 | def test_get_team_salaries(self, init_client): 142 | self.client = init_client 143 | with patch( 144 | "itscalledsoccer.client.AmericanSoccerAnalysis._get_stats" 145 | ) as mock_stats: 146 | mock_stats.return_value = self.load_mock_data("teams_salaries") 147 | data = self.client.get_team_salaries() 148 | assert data is not None 149 | assert isinstance(data, DataFrame) 150 | assert len(data) >= 2 151 | 152 | def test_get_game_xgoals(self, init_client): 153 | self.client = init_client 154 | with patch( 155 | "itscalledsoccer.client.AmericanSoccerAnalysis._get_stats" 156 | ) as mock_stats: 157 | mock_stats.return_value = self.load_mock_data("games_xgoals") 158 | data = self.client.get_game_xgoals() 159 | assert data is not None 160 | assert isinstance(data, DataFrame) 161 | assert len(data) >= 2 162 | 163 | def test_get_stadia(self): 164 | with patch( 165 | "itscalledsoccer.client.AmericanSoccerAnalysis._get_entity" 166 | ) as mock_entity: 167 | mock_entity.return_value = self.load_mock_data("stadia") 168 | self.client = AmericanSoccerAnalysis() 169 | stadia = self.client.get_stadia() 170 | assert stadia is not None 171 | assert isinstance(stadia, DataFrame) 172 | assert len(stadia) >= 2 173 | 174 | def test_get_referees(self): 175 | with patch( 176 | "itscalledsoccer.client.AmericanSoccerAnalysis._get_entity" 177 | ) as mock_entity: 178 | mock_entity.return_value = self.load_mock_data("referees") 179 | self.client = AmericanSoccerAnalysis() 180 | referees = self.client.get_referees() 181 | assert referees is not None 182 | assert isinstance(referees, DataFrame) 183 | assert len(referees) >= 2 184 | 185 | def test_get_managers(self): 186 | with patch( 187 | "itscalledsoccer.client.AmericanSoccerAnalysis._get_entity" 188 | ) as mock_entity: 189 | mock_entity.return_value = self.load_mock_data("managers") 190 | self.client = AmericanSoccerAnalysis() 191 | managers = self.client.get_managers() 192 | assert managers is not None 193 | assert isinstance(managers, DataFrame) 194 | assert len(managers) >= 2 195 | 196 | def test_get_teams(self): 197 | with patch( 198 | "itscalledsoccer.client.AmericanSoccerAnalysis._get_entity" 199 | ) as mock_entity: 200 | mock_entity.return_value = self.load_mock_data("teams") 201 | self.client = AmericanSoccerAnalysis() 202 | teams = self.client.get_teams() 203 | assert teams is not None 204 | assert isinstance(teams, DataFrame) 205 | assert len(teams) >= 2 206 | 207 | def test_get_players(self): 208 | with patch( 209 | "itscalledsoccer.client.AmericanSoccerAnalysis._get_entity" 210 | ) as mock_entity: 211 | mock_entity.return_value = self.load_mock_data("players") 212 | self.client = AmericanSoccerAnalysis() 213 | players = self.client.get_players() 214 | assert players is not None 215 | assert isinstance(players, DataFrame) 216 | assert len(players) >= 2 217 | 218 | def test_get_games(self): 219 | with patch( 220 | "itscalledsoccer.client.AmericanSoccerAnalysis._get_entity" 221 | ) as mock_entity: 222 | mock_entity.return_value = self.load_mock_data("games") 223 | self.client = AmericanSoccerAnalysis() 224 | games = self.client.get_games() 225 | assert games is not None 226 | assert isinstance(games, DataFrame) 227 | assert len(games) >= 2 228 | -------------------------------------------------------------------------------- /tests/mocks/goalkeepers_goals_added_payload.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "player_id": "0x5g1BmQ7O", 4 | "team_id": "9z5k7Yg5A3", 5 | "minutes_played": 879, 6 | "data": [ 7 | { 8 | "action_type": "Claiming", 9 | "goals_added_raw": -0.0276, 10 | "goals_added_above_avg": -0.0188, 11 | "count_actions": 17 12 | }, 13 | { 14 | "action_type": "Fielding", 15 | "goals_added_raw": 0.0147, 16 | "goals_added_above_avg": 0.0667, 17 | "count_actions": 105 18 | }, 19 | { 20 | "action_type": "Handling", 21 | "goals_added_raw": -0.0269, 22 | "goals_added_above_avg": -0.0333, 23 | "count_actions": 17 24 | }, 25 | { 26 | "action_type": "Passing", 27 | "goals_added_raw": 0.5188, 28 | "goals_added_above_avg": -0.0627, 29 | "count_actions": 255 30 | }, 31 | { 32 | "action_type": "Shotstopping", 33 | "goals_added_raw": -1.6605, 34 | "goals_added_above_avg": -1.4141, 35 | "count_actions": 30 36 | }, 37 | { 38 | "action_type": "Sweeping", 39 | "goals_added_raw": 0.0376, 40 | "goals_added_above_avg": 0.0511, 41 | "count_actions": 20 42 | } 43 | ] 44 | }, 45 | { 46 | "player_id": "2lqRRj84qr", 47 | "team_id": "9z5k7Yg5A3", 48 | "minutes_played": 343, 49 | "data": [ 50 | { 51 | "action_type": "Claiming", 52 | "goals_added_raw": -0.2493, 53 | "goals_added_above_avg": -0.2459, 54 | "count_actions": 5 55 | }, 56 | { 57 | "action_type": "Fielding", 58 | "goals_added_raw": -0.0075, 59 | "goals_added_above_avg": 0.0127, 60 | "count_actions": 54 61 | }, 62 | { 63 | "action_type": "Handling", 64 | "goals_added_raw": -0.0242, 65 | "goals_added_above_avg": -0.0268, 66 | "count_actions": 6 67 | }, 68 | { 69 | "action_type": "Passing", 70 | "goals_added_raw": 0.2307, 71 | "goals_added_above_avg": 0.0038, 72 | "count_actions": 93 73 | }, 74 | { 75 | "action_type": "Shotstopping", 76 | "goals_added_raw": -0.2597, 77 | "goals_added_above_avg": -0.1636, 78 | "count_actions": 11 79 | }, 80 | { 81 | "action_type": "Sweeping", 82 | "goals_added_raw": -0.1467, 83 | "goals_added_above_avg": -0.1415, 84 | "count_actions": 4 85 | } 86 | ] 87 | }, 88 | { 89 | "player_id": "2vQ1L20Oqr", 90 | "team_id": "9z5k7Yg5A3", 91 | "minutes_played": 2045, 92 | "data": [ 93 | { 94 | "action_type": "Claiming", 95 | "goals_added_raw": -0.1851, 96 | "goals_added_above_avg": -0.1646, 97 | "count_actions": 33 98 | }, 99 | { 100 | "action_type": "Fielding", 101 | "goals_added_raw": -0.6927, 102 | "goals_added_above_avg": -0.5719, 103 | "count_actions": 189 104 | }, 105 | { 106 | "action_type": "Handling", 107 | "goals_added_raw": 0.0929, 108 | "goals_added_above_avg": 0.0779, 109 | "count_actions": 64 110 | }, 111 | { 112 | "action_type": "Passing", 113 | "goals_added_raw": 1.0303, 114 | "goals_added_above_avg": -0.3227, 115 | "count_actions": 555 116 | }, 117 | { 118 | "action_type": "Shotstopping", 119 | "goals_added_raw": -2.7252, 120 | "goals_added_above_avg": -2.1519, 121 | "count_actions": 97 122 | }, 123 | { 124 | "action_type": "Sweeping", 125 | "goals_added_raw": -0.3922, 126 | "goals_added_above_avg": -0.3609, 127 | "count_actions": 31 128 | } 129 | ] 130 | }, 131 | { 132 | "player_id": "315VXNkGQ9", 133 | "team_id": "9z5k7Yg5A3", 134 | "minutes_played": 351, 135 | "data": [ 136 | { 137 | "action_type": "Claiming", 138 | "goals_added_raw": -0.18, 139 | "goals_added_above_avg": -0.1765, 140 | "count_actions": 4 141 | }, 142 | { 143 | "action_type": "Fielding", 144 | "goals_added_raw": 0.022, 145 | "goals_added_above_avg": 0.0427, 146 | "count_actions": 47 147 | }, 148 | { 149 | "action_type": "Handling", 150 | "goals_added_raw": 0.01, 151 | "goals_added_above_avg": 0.0074, 152 | "count_actions": 9 153 | }, 154 | { 155 | "action_type": "Passing", 156 | "goals_added_raw": 0.2103, 157 | "goals_added_above_avg": -0.022, 158 | "count_actions": 100 159 | }, 160 | { 161 | "action_type": "Shotstopping", 162 | "goals_added_raw": 1.8287, 163 | "goals_added_above_avg": 1.9271, 164 | "count_actions": 11 165 | }, 166 | { 167 | "action_type": "Sweeping", 168 | "goals_added_raw": 0.0106, 169 | "goals_added_above_avg": 0.016, 170 | "count_actions": 11 171 | } 172 | ] 173 | }, 174 | { 175 | "player_id": "7VqGmlO3Mv", 176 | "team_id": "9z5k7Yg5A3", 177 | "minutes_played": 97, 178 | "data": [ 179 | { 180 | "action_type": "Claiming", 181 | "goals_added_raw": -0.1609, 182 | "goals_added_above_avg": -0.1599, 183 | "count_actions": 2 184 | }, 185 | { 186 | "action_type": "Fielding", 187 | "goals_added_raw": -0.0003, 188 | "goals_added_above_avg": 0.0055, 189 | "count_actions": 8 190 | }, 191 | { 192 | "action_type": "Handling", 193 | "goals_added_raw": 0.0272, 194 | "goals_added_above_avg": 0.0265, 195 | "count_actions": 2 196 | }, 197 | { 198 | "action_type": "Passing", 199 | "goals_added_raw": 0.0393, 200 | "goals_added_above_avg": -0.0249, 201 | "count_actions": 22 202 | }, 203 | { 204 | "action_type": "Shotstopping", 205 | "goals_added_raw": -1.6583, 206 | "goals_added_above_avg": -1.6311, 207 | "count_actions": 4 208 | }, 209 | { 210 | "action_type": "Sweeping", 211 | "goals_added_raw": -0.1943, 212 | "goals_added_above_avg": -0.1928, 213 | "count_actions": 2 214 | } 215 | ] 216 | }, 217 | { 218 | "player_id": "7VqGmob3Mv", 219 | "team_id": "9z5k7Yg5A3", 220 | "minutes_played": 18408, 221 | "data": [ 222 | { 223 | "action_type": "Claiming", 224 | "goals_added_raw": -0.2767, 225 | "goals_added_above_avg": -0.0921, 226 | "count_actions": 287 227 | }, 228 | { 229 | "action_type": "Fielding", 230 | "goals_added_raw": -1.1668, 231 | "goals_added_above_avg": -0.0791, 232 | "count_actions": 2343 233 | }, 234 | { 235 | "action_type": "Handling", 236 | "goals_added_raw": -0.7646, 237 | "goals_added_above_avg": -0.8999, 238 | "count_actions": 583 239 | }, 240 | { 241 | "action_type": "Passing", 242 | "goals_added_raw": 11.7034, 243 | "goals_added_above_avg": -0.4758, 244 | "count_actions": 5388 245 | }, 246 | { 247 | "action_type": "Shotstopping", 248 | "goals_added_raw": 0.0403, 249 | "goals_added_above_avg": 5.201, 250 | "count_actions": 824 251 | }, 252 | { 253 | "action_type": "Sweeping", 254 | "goals_added_raw": -0.4404, 255 | "goals_added_above_avg": -0.1582, 256 | "count_actions": 378 257 | } 258 | ] 259 | }, 260 | { 261 | "player_id": "BLMvl7ORqx", 262 | "team_id": "9z5k7Yg5A3", 263 | "minutes_played": 1157, 264 | "data": [ 265 | { 266 | "action_type": "Claiming", 267 | "goals_added_raw": -0.0236, 268 | "goals_added_above_avg": -0.012, 269 | "count_actions": 13 270 | }, 271 | { 272 | "action_type": "Fielding", 273 | "goals_added_raw": 0.0061, 274 | "goals_added_above_avg": 0.0744, 275 | "count_actions": 76 276 | }, 277 | { 278 | "action_type": "Handling", 279 | "goals_added_raw": 0.0489, 280 | "goals_added_above_avg": 0.0404, 281 | "count_actions": 31 282 | }, 283 | { 284 | "action_type": "Passing", 285 | "goals_added_raw": 0.6217, 286 | "goals_added_above_avg": -0.1438, 287 | "count_actions": 279 288 | }, 289 | { 290 | "action_type": "Shotstopping", 291 | "goals_added_raw": -0.4335, 292 | "goals_added_above_avg": -0.1091, 293 | "count_actions": 50 294 | }, 295 | { 296 | "action_type": "Sweeping", 297 | "goals_added_raw": 0.237, 298 | "goals_added_above_avg": 0.2548, 299 | "count_actions": 9 300 | } 301 | ] 302 | }, 303 | { 304 | "player_id": "odMXRoXoqY", 305 | "team_id": "9z5k7Yg5A3", 306 | "minutes_played": 1238, 307 | "data": [ 308 | { 309 | "action_type": "Claiming", 310 | "goals_added_raw": 0.0091, 311 | "goals_added_above_avg": 0.0216, 312 | "count_actions": 7 313 | }, 314 | { 315 | "action_type": "Fielding", 316 | "goals_added_raw": -0.3917, 317 | "goals_added_above_avg": -0.3185, 318 | "count_actions": 129 319 | }, 320 | { 321 | "action_type": "Handling", 322 | "goals_added_raw": 0.2471, 323 | "goals_added_above_avg": 0.238, 324 | "count_actions": 32 325 | }, 326 | { 327 | "action_type": "Passing", 328 | "goals_added_raw": 0.5948, 329 | "goals_added_above_avg": -0.2243, 330 | "count_actions": 312 331 | }, 332 | { 333 | "action_type": "Shotstopping", 334 | "goals_added_raw": -2.645, 335 | "goals_added_above_avg": -2.298, 336 | "count_actions": 48 337 | }, 338 | { 339 | "action_type": "Sweeping", 340 | "goals_added_raw": 0.0666, 341 | "goals_added_above_avg": 0.0855, 342 | "count_actions": 11 343 | } 344 | ] 345 | }, 346 | { 347 | "player_id": "xW5pxy3l5g", 348 | "team_id": "9z5k7Yg5A3", 349 | "minutes_played": 6146, 350 | "data": [ 351 | { 352 | "action_type": "Claiming", 353 | "goals_added_raw": -0.6566, 354 | "goals_added_above_avg": -0.5949, 355 | "count_actions": 140 356 | }, 357 | { 358 | "action_type": "Fielding", 359 | "goals_added_raw": -0.2031, 360 | "goals_added_above_avg": 0.1601, 361 | "count_actions": 829 362 | }, 363 | { 364 | "action_type": "Handling", 365 | "goals_added_raw": 0.9724, 366 | "goals_added_above_avg": 0.9272, 367 | "count_actions": 178 368 | }, 369 | { 370 | "action_type": "Passing", 371 | "goals_added_raw": 5.3227, 372 | "goals_added_above_avg": 1.2563, 373 | "count_actions": 1987 374 | }, 375 | { 376 | "action_type": "Shotstopping", 377 | "goals_added_raw": 1.1693, 378 | "goals_added_above_avg": 2.8923, 379 | "count_actions": 265 380 | }, 381 | { 382 | "action_type": "Sweeping", 383 | "goals_added_raw": 0.4773, 384 | "goals_added_above_avg": 0.5715, 385 | "count_actions": 199 386 | } 387 | ] 388 | } 389 | ] -------------------------------------------------------------------------------- /tests/mocks/managers_payload.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "manager_id": "0Oq6e7A56D", 4 | "manager_name": "Rob Valentino", 5 | "nationality": "USA" 6 | }, 7 | { 8 | "manager_id": "0Oq6mNP56D", 9 | "manager_name": "Josh Wolff", 10 | "nationality": "USA" 11 | }, 12 | { 13 | "manager_id": "0Oq6mxd56D", 14 | "manager_name": "Marc Dos Santos", 15 | "nationality": "Canada" 16 | }, 17 | { 18 | "manager_id": "0Oq6VPgq6D", 19 | "manager_name": "Robin Fraser", 20 | "nationality": "USA" 21 | }, 22 | { 23 | "manager_id": "0Oq6vPrq6D", 24 | "manager_name": "Jim Curtin", 25 | "nationality": "USA" 26 | }, 27 | { 28 | "manager_id": "0Oq6zkzq6D", 29 | "manager_name": "Bob Bradley", 30 | "nationality": "USA" 31 | }, 32 | { 33 | "manager_id": "0x5gDGXq7O", 34 | "manager_name": "Rémi Garde", 35 | "nationality": "France" 36 | }, 37 | { 38 | "manager_id": "0x5ggrR57O", 39 | "manager_name": "Stephen Glass", 40 | "nationality": "USA" 41 | }, 42 | { 43 | "manager_id": "0x5gN9PM7O", 44 | "manager_name": "Gregg Berhalter", 45 | "nationality": "USA" 46 | }, 47 | { 48 | "manager_id": "0x5gX4jq7O", 49 | "manager_name": "Kerry Zavagnin", 50 | "nationality": "USA" 51 | }, 52 | { 53 | "manager_id": "2lqRa4D5r0", 54 | "manager_name": "Ronny Deila", 55 | "nationality": "Norway" 56 | }, 57 | { 58 | "manager_id": "2lqREgJ5r0", 59 | "manager_name": "Steve Ralston", 60 | "nationality": "USA" 61 | }, 62 | { 63 | "manager_id": "2lqRNjxqr0", 64 | "manager_name": "José Luis Real", 65 | "nationality": "Mexico" 66 | }, 67 | { 68 | "manager_id": "2lqRo8AQr0", 69 | "manager_name": "Craig Dalrymple" 70 | }, 71 | { 72 | "manager_id": "2vQ10jwqrA", 73 | "manager_name": "Matías Almeyda", 74 | "nationality": "Argentina" 75 | }, 76 | { 77 | "manager_id": "2vQ1A60QrA", 78 | "manager_name": "Ezra Hendrickson", 79 | "nationality": "St. Vincent and the Grenadines" 80 | }, 81 | { 82 | "manager_id": "2vQ1m6bQrA", 83 | "manager_name": "Marco Ferruzzi", 84 | "nationality": "USA" 85 | }, 86 | { 87 | "manager_id": "2vQ1vgxMrA", 88 | "manager_name": "Jeff Cassar", 89 | "nationality": "USA" 90 | }, 91 | { 92 | "manager_id": "2vQ1vR0MrA", 93 | "manager_name": "Patrick Vieira", 94 | "nationality": "France" 95 | }, 96 | { 97 | "manager_id": "315V07YQ9x", 98 | "manager_name": "Davy Arnaud" 99 | }, 100 | { 101 | "manager_id": "315VavvM9x", 102 | "manager_name": "Robert Warzycha" 103 | }, 104 | { 105 | "manager_id": "315VKkEq9x", 106 | "manager_name": "Marco Schällibaum", 107 | "nationality": "Switzerland" 108 | }, 109 | { 110 | "manager_id": "4JMA4X9QKg", 111 | "manager_name": "Dominic Kinnear" 112 | }, 113 | { 114 | "manager_id": "4JMAEj1MKg", 115 | "manager_name": "Brad Friedel", 116 | "nationality": "USA" 117 | }, 118 | { 119 | "manager_id": "4wM4AAk5jB", 120 | "manager_name": "Tab Ramos", 121 | "nationality": "USA" 122 | }, 123 | { 124 | "manager_id": "4wM4vOAqjB", 125 | "manager_name": "Pablo Mastroeni", 126 | "nationality": "USA" 127 | }, 128 | { 129 | "manager_id": "4wM4zRlqjB", 130 | "manager_name": "Frank Yallop" 131 | }, 132 | { 133 | "manager_id": "7vQ7m6Y5D1", 134 | "manager_name": "Gonzalo Pineda", 135 | "nationality": "Mexico" 136 | }, 137 | { 138 | "manager_id": "7vQ7mJE5D1", 139 | "manager_name": "Daryl Shore", 140 | "nationality": "USA" 141 | }, 142 | { 143 | "manager_id": "7vQ7z0dqD1", 144 | "manager_name": "Gerardo Martino", 145 | "nationality": "Argentina" 146 | }, 147 | { 148 | "manager_id": "7VqG6WY5vW", 149 | "manager_name": "Diego Alonso", 150 | "nationality": "Uruguay" 151 | }, 152 | { 153 | "manager_id": "7VqGG2eqvW", 154 | "manager_name": "Mark Watson", 155 | "nationality": "Canada" 156 | }, 157 | { 158 | "manager_id": "7VqGPRYQvW", 159 | "manager_name": "Javier Perez", 160 | "nationality": "Spain" 161 | }, 162 | { 163 | "manager_id": "9vQ2z7xQK6", 164 | "manager_name": "Curt Onalfo" 165 | }, 166 | { 167 | "manager_id": "9Yqd8woqvJ", 168 | "manager_name": "Raphaël Wicky", 169 | "nationality": "Switzerland" 170 | }, 171 | { 172 | "manager_id": "9z5kJ0jMA3", 173 | "manager_name": "Jay Heaps", 174 | "nationality": "USA" 175 | }, 176 | { 177 | "manager_id": "9z5kKNb5A3", 178 | "manager_name": "Gerhard Struber", 179 | "nationality": "Austria" 180 | }, 181 | { 182 | "manager_id": "9z5krNlMA3" 183 | }, 184 | { 185 | "manager_id": "a35rDbGQL6", 186 | "manager_name": "Ron Jans", 187 | "nationality": "Netherlands" 188 | }, 189 | { 190 | "manager_id": "a35rDN4QL6", 191 | "manager_name": "Schellas Hyndman" 192 | }, 193 | { 194 | "manager_id": "aDQ009EQEv", 195 | "manager_name": "Mike Petke", 196 | "nationality": "USA" 197 | }, 198 | { 199 | "manager_id": "aDQ0rwR5Ev", 200 | "manager_name": "Conor Casey" 201 | }, 202 | { 203 | "manager_id": "aDQ0zmB5Ev", 204 | "manager_name": "José Luis Sánchez", 205 | "nationality": "Mexico" 206 | }, 207 | { 208 | "manager_id": "BLMvDGBqxe", 209 | "manager_name": "Yoann Damet" 210 | }, 211 | { 212 | "manager_id": "BLMvnZlMxe", 213 | "manager_name": "Bobby Murphy" 214 | }, 215 | { 216 | "manager_id": "BLMvXrjqxe", 217 | "manager_name": "Chris Leitch" 218 | }, 219 | { 220 | "manager_id": "e7Mz3GG5r0", 221 | "manager_name": "Frank de Boer", 222 | "nationality": "Netherlands" 223 | }, 224 | { 225 | "manager_id": "e7MzE8XQr0", 226 | "manager_name": "Hernán Pablo Losada", 227 | "nationality": "Argentina" 228 | }, 229 | { 230 | "manager_id": "e7MzXZPqr0", 231 | "manager_name": "Omid Namazi" 232 | }, 233 | { 234 | "manager_id": "EGMPL0yMaY", 235 | "manager_name": "Wilmer Cabrera", 236 | "nationality": "Colombia" 237 | }, 238 | { 239 | "manager_id": "eV5DNVJQKn", 240 | "manager_name": "Luchi Gonzalez", 241 | "nationality": "USA" 242 | }, 243 | { 244 | "manager_id": "eV5DWdEMKn", 245 | "manager_name": "Jaap Stam", 246 | "nationality": "Netherlands" 247 | }, 248 | { 249 | "manager_id": "eVq3ArXMWO", 250 | "manager_name": "Ian Russell", 251 | "nationality": "USA" 252 | }, 253 | { 254 | "manager_id": "eVq3mZVMWO", 255 | "manager_name": "James O’Connor", 256 | "nationality": "Republic of Ireland" 257 | }, 258 | { 259 | "manager_id": "eVq3zow5WO", 260 | "manager_name": "Jason Kreis" 261 | }, 262 | { 263 | "manager_id": "gjMNEpkQKp", 264 | "manager_name": "Alan Koch", 265 | "nationality": "South Africa" 266 | }, 267 | { 268 | "manager_id": "gjMNG4k5Kp", 269 | "manager_name": "Miguel Ángel Ramírez" 270 | }, 271 | { 272 | "manager_id": "gjMNk0Y5Kp", 273 | "manager_name": "Ryan Nelsen", 274 | "nationality": "New Zealand" 275 | }, 276 | { 277 | "manager_id": "gjMNk8v5Kp", 278 | "manager_name": "Oscar Pareja", 279 | "nationality": "Colombia" 280 | }, 281 | { 282 | "manager_id": "gOMnBPJMwN", 283 | "manager_name": "Frank Klopas", 284 | "nationality": "USA" 285 | }, 286 | { 287 | "manager_id": "gOMnDkAqwN", 288 | "manager_name": "Gary Smith", 289 | "nationality": "England" 290 | }, 291 | { 292 | "manager_id": "gOMnwJm5wN", 293 | "manager_name": "Wade Barrett", 294 | "nationality": "USA" 295 | }, 296 | { 297 | "manager_id": "gpMOYJ7qzy", 298 | "manager_name": "Phil Neville", 299 | "nationality": "England" 300 | }, 301 | { 302 | "manager_id": "gpMOYv1qzy", 303 | "manager_name": "Giovanni Savarese", 304 | "nationality": "Venezuela" 305 | }, 306 | { 307 | "manager_id": "jYQJA3yqGR", 308 | "manager_name": "Gabriel Heinze", 309 | "nationality": "Argentina" 310 | }, 311 | { 312 | "manager_id": "jYQJlGW5GR", 313 | "manager_name": "Paulo Nagamura", 314 | "nationality": "Brazil" 315 | }, 316 | { 317 | "manager_id": "jYQJozVMGR", 318 | "manager_name": "Domènec Torrent", 319 | "nationality": "Spain" 320 | }, 321 | { 322 | "manager_id": "KAqB3DmQbg", 323 | "manager_name": "Carl Robinson", 324 | "nationality": "Wales" 325 | }, 326 | { 327 | "manager_id": "KAqB4dVMbg", 328 | "manager_name": "Owen Coyle", 329 | "nationality": "Republic of Ireland" 330 | }, 331 | { 332 | "manager_id": "KAqBPJ7Mbg", 333 | "manager_name": "Mike Lapper" 334 | }, 335 | { 336 | "manager_id": "KAqBwv7Qbg", 337 | "manager_name": "Nico Estévez", 338 | "nationality": "Spain" 339 | }, 340 | { 341 | "manager_id": "KPqjO38Q6v", 342 | "manager_name": "Wilfried Nancy", 343 | "nationality": "France" 344 | }, 345 | { 346 | "manager_id": "kRQa99OQKZ", 347 | "manager_name": "Anthony Hudson", 348 | "nationality": "New Zealand" 349 | }, 350 | { 351 | "manager_id": "kRQa9zmQKZ", 352 | "manager_name": "Freddy Juarez", 353 | "nationality": "USA" 354 | }, 355 | { 356 | "manager_id": "kRQaRD1MKZ", 357 | "manager_name": "Brian Bliss" 358 | }, 359 | { 360 | "manager_id": "KXMeab1M64", 361 | "manager_name": "Siegfried Schmid" 362 | }, 363 | { 364 | "manager_id": "KXMeAPkM64", 365 | "manager_name": "John Hackworth", 366 | "nationality": "USA" 367 | }, 368 | { 369 | "manager_id": "LeVq3j5WOJ", 370 | "manager_name": "Bruce Arena", 371 | "nationality": "USA" 372 | }, 373 | { 374 | "manager_id": "ljqEkkAMx0", 375 | "manager_name": "Rob Valentino", 376 | "nationality": "USA" 377 | }, 378 | { 379 | "manager_id": "ljqEWzAMx0", 380 | "manager_name": "Martin Rennie", 381 | "nationality": "Scotland" 382 | }, 383 | { 384 | "manager_id": "ljqExEA5x0", 385 | "manager_name": "Veljko Paunovic", 386 | "nationality": "Serbia" 387 | }, 388 | { 389 | "manager_id": "N6MmpyLQEG", 390 | "manager_name": "Peter Vermes", 391 | "nationality": "USA" 392 | }, 393 | { 394 | "manager_id": "NPqxkDY59d", 395 | "manager_name": "Caleb Porter", 396 | "nationality": "USA" 397 | }, 398 | { 399 | "manager_id": "NWMWx1D5lz", 400 | "manager_name": "Mauro Biello", 401 | "nationality": "Canada" 402 | }, 403 | { 404 | "manager_id": "NWMWxKe5lz", 405 | "manager_name": "Steven Cherundolo", 406 | "nationality": "USA" 407 | }, 408 | { 409 | "manager_id": "odMXaNo5YL", 410 | "manager_name": "Tom Soehn", 411 | "nationality": "USA" 412 | }, 413 | { 414 | "manager_id": "odMXaYo5YL", 415 | "manager_name": "Mikael Stahre", 416 | "nationality": "Sweden" 417 | }, 418 | { 419 | "manager_id": "odMXxreMYL", 420 | "manager_name": "Brian Schmetzer", 421 | "nationality": "USA" 422 | }, 423 | { 424 | "manager_id": "OlMlYvy5Lz", 425 | "manager_name": "Adrian Heath", 426 | "nationality": "England" 427 | }, 428 | { 429 | "manager_id": "p6qbk3BQ0G", 430 | "manager_name": "Chad Ashton", 431 | "nationality": "USA" 432 | }, 433 | { 434 | "manager_id": "Pk5LWONMOW", 435 | "manager_name": "Vanni Sartini", 436 | "nationality": "Italy" 437 | }, 438 | { 439 | "manager_id": "Vj58mVDq8n", 440 | "manager_name": "Steve Cooke", 441 | "nationality": "USA" 442 | }, 443 | { 444 | "manager_id": "Vj58mwJq8n" 445 | }, 446 | { 447 | "manager_id": "vzqo2dv5ap", 448 | "manager_name": "Chris Armas", 449 | "nationality": "USA" 450 | }, 451 | { 452 | "manager_id": "vzqoAjJMap", 453 | "manager_name": "Ben Olsen", 454 | "nationality": "USA" 455 | }, 456 | { 457 | "manager_id": "vzqokNkqap", 458 | "manager_name": "Thierry Henry", 459 | "nationality": "France" 460 | }, 461 | { 462 | "manager_id": "vzqozWB5ap", 463 | "manager_name": "Pat Noonan" 464 | }, 465 | { 466 | "manager_id": "Xj5Yre0qbd", 467 | "manager_name": "Jesse Marsch", 468 | "nationality": "USA" 469 | }, 470 | { 471 | "manager_id": "Xj5Yrklqbd", 472 | "manager_name": "Guillermo Barros Schelotto", 473 | "nationality": "Argentina" 474 | }, 475 | { 476 | "manager_id": "Xj5Yx60Mbd", 477 | "manager_name": "Greg Vanney", 478 | "nationality": "USA" 479 | }, 480 | { 481 | "manager_id": "xW5pXLG5g1", 482 | "manager_name": "Tyrone Marshall", 483 | "nationality": "Jamaica" 484 | }, 485 | { 486 | "manager_id": "zeQZVw1QKw", 487 | "manager_name": "Bradley Carnell" 488 | } 489 | ] -------------------------------------------------------------------------------- /tests/mocks/teams_xgoals_payload.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "team_id": "0KPqjA456v", 4 | "count_games": 306, 5 | "shots_for": 4053, 6 | "shots_against": 4143, 7 | "goals_for": 373, 8 | "goals_against": 479, 9 | "goal_difference": -106, 10 | "xgoals_for": 403.966, 11 | "xgoals_against": 452.388, 12 | "xgoal_difference": -48.4214, 13 | "goal_difference_minus_xgoal_difference": -57.5786, 14 | "points": 355, 15 | "xpoints": 389.859 16 | }, 17 | { 18 | "team_id": "19vQ2095K6", 19 | "count_games": 316, 20 | "shots_for": 4209, 21 | "shots_against": 4094, 22 | "goals_for": 455, 23 | "goals_against": 447, 24 | "goal_difference": 8, 25 | "xgoals_for": 441.017, 26 | "xgoals_against": 451.393, 27 | "xgoal_difference": -10.3764, 28 | "goal_difference_minus_xgoal_difference": 18.3764, 29 | "points": 461, 30 | "xpoints": 414.525 31 | }, 32 | { 33 | "team_id": "4wM42l4qjB", 34 | "count_games": 68, 35 | "shots_for": 655, 36 | "shots_against": 961, 37 | "goals_for": 56, 38 | "goals_against": 127, 39 | "goal_difference": -71, 40 | "xgoals_for": 59.4626, 41 | "xgoals_against": 102.202, 42 | "xgoal_difference": -42.7398, 43 | "goal_difference_minus_xgoal_difference": -28.2602, 44 | "points": 59, 45 | "xpoints": 63.39 46 | }, 47 | { 48 | "team_id": "9z5k7Yg5A3", 49 | "count_games": 312, 50 | "shots_for": 4023, 51 | "shots_against": 3827, 52 | "goals_for": 447, 53 | "goals_against": 418, 54 | "goal_difference": 29, 55 | "xgoals_for": 443.711, 56 | "xgoals_against": 405.636, 57 | "xgoal_difference": 38.0759, 58 | "goal_difference_minus_xgoal_difference": -9.0759, 59 | "points": 444, 60 | "xpoints": 435.82 61 | }, 62 | { 63 | "team_id": "a2lqR4JMr0", 64 | "count_games": 318, 65 | "shots_for": 4124, 66 | "shots_against": 4085, 67 | "goals_for": 444, 68 | "goals_against": 443, 69 | "goal_difference": 1, 70 | "xgoals_for": 411.7, 71 | "xgoals_against": 460.875, 72 | "xgoal_difference": -49.1749, 73 | "goal_difference_minus_xgoal_difference": 50.1749, 74 | "points": 450, 75 | "xpoints": 393.638 76 | }, 77 | { 78 | "team_id": "a2lqRX2Mr0", 79 | "count_games": 324, 80 | "shots_for": 4196, 81 | "shots_against": 3793, 82 | "goals_for": 500, 83 | "goals_against": 400, 84 | "goal_difference": 100, 85 | "xgoals_for": 491.644, 86 | "xgoals_against": 418.884, 87 | "xgoal_difference": 72.7607, 88 | "goal_difference_minus_xgoal_difference": 27.2393, 89 | "points": 514, 90 | "xpoints": 455.607 91 | }, 92 | { 93 | "team_id": "APk5LGOMOW", 94 | "count_games": 313, 95 | "shots_for": 3776, 96 | "shots_against": 4110, 97 | "goals_for": 436, 98 | "goals_against": 487, 99 | "goal_difference": -51, 100 | "xgoals_for": 398.55, 101 | "xgoals_against": 432.579, 102 | "xgoal_difference": -34.029, 103 | "goal_difference_minus_xgoal_difference": -16.971, 104 | "points": 399, 105 | "xpoints": 394.378 106 | }, 107 | { 108 | "team_id": "EKXMeX3Q64", 109 | "count_games": 308, 110 | "shots_for": 3669, 111 | "shots_against": 4418, 112 | "goals_for": 384, 113 | "goals_against": 438, 114 | "goal_difference": -54, 115 | "xgoals_for": 379.751, 116 | "xgoals_against": 449.506, 117 | "xgoal_difference": -69.7551, 118 | "goal_difference_minus_xgoal_difference": 15.7551, 119 | "points": 386, 120 | "xpoints": 370.282 121 | }, 122 | { 123 | "team_id": "eVq3ya6MWO", 124 | "count_games": 136, 125 | "shots_for": 2209, 126 | "shots_against": 1491, 127 | "goals_for": 273, 128 | "goals_against": 192, 129 | "goal_difference": 81, 130 | "xgoals_for": 261.674, 131 | "xgoals_against": 162.771, 132 | "xgoal_difference": 98.9031, 133 | "goal_difference_minus_xgoal_difference": -17.9031, 134 | "points": 226, 135 | "xpoints": 236.803 136 | }, 137 | { 138 | "team_id": "gpMOLwl5zy", 139 | "count_games": 40, 140 | "shots_for": 534, 141 | "shots_against": 595, 142 | "goals_for": 47, 143 | "goals_against": 60, 144 | "goal_difference": -13, 145 | "xgoals_for": 50.9967, 146 | "xgoals_against": 63.0195, 147 | "xgoal_difference": -12.0228, 148 | "goal_difference_minus_xgoal_difference": -0.9772, 149 | "points": 42, 150 | "xpoints": 49.365 151 | }, 152 | { 153 | "team_id": "jYQJ19EqGR", 154 | "count_games": 332, 155 | "shots_for": 4189, 156 | "shots_against": 4201, 157 | "goals_for": 493, 158 | "goals_against": 387, 159 | "goal_difference": 106, 160 | "xgoals_for": 470.565, 161 | "xgoals_against": 410.267, 162 | "xgoal_difference": 60.2986, 163 | "goal_difference_minus_xgoal_difference": 45.7014, 164 | "points": 551, 165 | "xpoints": 447.516 166 | }, 167 | { 168 | "team_id": "jYQJ8EW5GR", 169 | "count_games": 241, 170 | "shots_for": 2892, 171 | "shots_against": 3162, 172 | "goals_for": 323, 173 | "goals_against": 379, 174 | "goal_difference": -56, 175 | "xgoals_for": 309.791, 176 | "xgoals_against": 350.81, 177 | "xgoal_difference": -41.0186, 178 | "goal_difference_minus_xgoal_difference": -14.9814, 179 | "points": 300, 180 | "xpoints": 299.074 181 | }, 182 | { 183 | "team_id": "kaDQ0wRqEv", 184 | "count_games": 313, 185 | "shots_for": 4036, 186 | "shots_against": 4198, 187 | "goals_for": 495, 188 | "goals_against": 460, 189 | "goal_difference": 35, 190 | "xgoals_for": 464.559, 191 | "xgoals_against": 424.915, 192 | "xgoal_difference": 39.6444, 193 | "goal_difference_minus_xgoal_difference": -4.6444, 194 | "points": 452, 195 | "xpoints": 437.928 196 | }, 197 | { 198 | "team_id": "KAqBN0Vqbg", 199 | "count_games": 176, 200 | "shots_for": 2356, 201 | "shots_against": 2065, 202 | "goals_for": 278, 203 | "goals_against": 204, 204 | "goal_difference": 74, 205 | "xgoals_for": 266.277, 206 | "xgoals_against": 216.849, 207 | "xgoal_difference": 49.4281, 208 | "goal_difference_minus_xgoal_difference": 24.5719, 209 | "points": 285, 210 | "xpoints": 253.907 211 | }, 212 | { 213 | "team_id": "kRQabn8MKZ", 214 | "count_games": 319, 215 | "shots_for": 4034, 216 | "shots_against": 3999, 217 | "goals_for": 476, 218 | "goals_against": 464, 219 | "goal_difference": 12, 220 | "xgoals_for": 449.859, 221 | "xgoals_against": 430.154, 222 | "xgoal_difference": 19.7053, 223 | "goal_difference_minus_xgoal_difference": -7.7053, 224 | "points": 439, 225 | "xpoints": 426.344 226 | }, 227 | { 228 | "team_id": "kRQand1MKZ", 229 | "count_games": 171, 230 | "shots_for": 2166, 231 | "shots_against": 2526, 232 | "goals_for": 238, 233 | "goals_against": 264, 234 | "goal_difference": -26, 235 | "xgoals_for": 237.608, 236 | "xgoals_against": 266.554, 237 | "xgoal_difference": -28.9467, 238 | "goal_difference_minus_xgoal_difference": 2.9467, 239 | "points": 226, 240 | "xpoints": 212.824 241 | }, 242 | { 243 | "team_id": "lgpMOvnQzy", 244 | "count_games": 310, 245 | "shots_for": 3627, 246 | "shots_against": 4669, 247 | "goals_for": 400, 248 | "goals_against": 444, 249 | "goal_difference": -44, 250 | "xgoals_for": 379.253, 251 | "xgoals_against": 447.682, 252 | "xgoal_difference": -68.4286, 253 | "goal_difference_minus_xgoal_difference": 24.4286, 254 | "points": 409, 255 | "xpoints": 377.639 256 | }, 257 | { 258 | "team_id": "mKAqBBmqbg", 259 | "count_games": 313, 260 | "shots_for": 4066, 261 | "shots_against": 3940, 262 | "goals_for": 447, 263 | "goals_against": 409, 264 | "goal_difference": 38, 265 | "xgoals_for": 430.445, 266 | "xgoals_against": 399.858, 267 | "xgoal_difference": 30.5876, 268 | "goal_difference_minus_xgoal_difference": 7.4124, 269 | "points": 460, 270 | "xpoints": 435.259 271 | }, 272 | { 273 | "team_id": "mvzqoLZQap", 274 | "count_games": 321, 275 | "shots_for": 4198, 276 | "shots_against": 4062, 277 | "goals_for": 440, 278 | "goals_against": 430, 279 | "goal_difference": 10, 280 | "xgoals_for": 442.945, 281 | "xgoals_against": 420.685, 282 | "xgoal_difference": 22.2604, 283 | "goal_difference_minus_xgoal_difference": -12.2604, 284 | "points": 449, 285 | "xpoints": 430.561 286 | }, 287 | { 288 | "team_id": "NPqxKXZ59d", 289 | "count_games": 7, 290 | "shots_for": 78, 291 | "shots_against": 103, 292 | "goals_for": 7, 293 | "goals_against": 9, 294 | "goal_difference": -2, 295 | "xgoals_for": 6.7037, 296 | "xgoals_against": 10.7169, 297 | "xgoal_difference": -4.0132, 298 | "goal_difference_minus_xgoal_difference": 2.0132, 299 | "points": 9, 300 | "xpoints": 6.37 301 | }, 302 | { 303 | "team_id": "NWMWlBK5lz", 304 | "count_games": 99, 305 | "shots_for": 1105, 306 | "shots_against": 1454, 307 | "goals_for": 84, 308 | "goals_against": 197, 309 | "goal_difference": -113, 310 | "xgoals_for": 107.832, 311 | "xgoals_against": 163.161, 312 | "xgoal_difference": -55.3291, 313 | "goal_difference_minus_xgoal_difference": -57.6709, 314 | "points": 68, 315 | "xpoints": 98.589 316 | }, 317 | { 318 | "team_id": "pzeQZ6xQKw", 319 | "count_games": 303, 320 | "shots_for": 3828, 321 | "shots_against": 3958, 322 | "goals_for": 369, 323 | "goals_against": 418, 324 | "goal_difference": -49, 325 | "xgoals_for": 357.028, 326 | "xgoals_against": 421.631, 327 | "xgoal_difference": -64.6024, 328 | "goal_difference_minus_xgoal_difference": 15.6024, 329 | "points": 384, 330 | "xpoints": 369.979 331 | }, 332 | { 333 | "team_id": "Vj58weDM8n", 334 | "count_games": 247, 335 | "shots_for": 3595, 336 | "shots_against": 3010, 337 | "goals_for": 402, 338 | "goals_against": 330, 339 | "goal_difference": 72, 340 | "xgoals_for": 375.888, 341 | "xgoals_against": 333.348, 342 | "xgoal_difference": 42.5397, 343 | "goal_difference_minus_xgoal_difference": 29.4603, 344 | "points": 380, 345 | "xpoints": 351.448 346 | }, 347 | { 348 | "team_id": "vzqoOgNqap", 349 | "count_games": 69, 350 | "shots_for": 871, 351 | "shots_against": 818, 352 | "goals_for": 94, 353 | "goals_against": 65, 354 | "goal_difference": 29, 355 | "xgoals_for": 85.7993, 356 | "xgoals_against": 76.2694, 357 | "xgoal_difference": 9.5299, 358 | "goal_difference_minus_xgoal_difference": 19.4701, 359 | "points": 107, 360 | "xpoints": 94.01 361 | }, 362 | { 363 | "team_id": "WBLMvYAQxe", 364 | "count_games": 331, 365 | "shots_for": 4514, 366 | "shots_against": 4471, 367 | "goals_for": 516, 368 | "goals_against": 445, 369 | "goal_difference": 71, 370 | "xgoals_for": 480.718, 371 | "xgoals_against": 454.055, 372 | "xgoal_difference": 26.6636, 373 | "goal_difference_minus_xgoal_difference": 44.3364, 374 | "points": 513, 375 | "xpoints": 433.557 376 | }, 377 | { 378 | "team_id": "X0Oq66zq6D", 379 | "count_games": 302, 380 | "shots_for": 3896, 381 | "shots_against": 3914, 382 | "goals_for": 399, 383 | "goals_against": 457, 384 | "goal_difference": -58, 385 | "xgoals_for": 401.789, 386 | "xgoals_against": 430.445, 387 | "xgoal_difference": -28.6561, 388 | "goal_difference_minus_xgoal_difference": -29.3439, 389 | "points": 341, 390 | "xpoints": 390.884 391 | }, 392 | { 393 | "team_id": "YgOMngl5wN", 394 | "count_games": 312, 395 | "shots_for": 4068, 396 | "shots_against": 4081, 397 | "goals_for": 400, 398 | "goals_against": 455, 399 | "goal_difference": -55, 400 | "xgoals_for": 419.486, 401 | "xgoals_against": 441.742, 402 | "xgoal_difference": -22.2558, 403 | "goal_difference_minus_xgoal_difference": -32.7442, 404 | "points": 372, 405 | "xpoints": 398.937 406 | }, 407 | { 408 | "team_id": "Z2vQ1xlqrA", 409 | "count_games": 319, 410 | "shots_for": 4622, 411 | "shots_against": 3423, 412 | "goals_for": 457, 413 | "goals_against": 387, 414 | "goal_difference": 70, 415 | "xgoals_for": 463.601, 416 | "xgoals_against": 377.74, 417 | "xgoal_difference": 85.8606, 418 | "goal_difference_minus_xgoal_difference": -15.8606, 419 | "points": 476, 420 | "xpoints": 459.4 421 | }, 422 | { 423 | "team_id": "zeQZkL1MKw", 424 | "count_games": 64, 425 | "shots_for": 717, 426 | "shots_against": 735, 427 | "goals_for": 65, 428 | "goals_against": 103, 429 | "goal_difference": -38, 430 | "xgoals_for": 69.8515, 431 | "xgoals_against": 86.3397, 432 | "xgoal_difference": -16.4882, 433 | "goal_difference_minus_xgoal_difference": -21.5118, 434 | "points": 69, 435 | "xpoints": 75.866 436 | } 437 | ] -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | <!-- omit in toc --> 2 | # Contributing to itscalledsoccer 3 | 4 | First off, thanks for taking the time to contribute! ❤️ 5 | 6 | All types of contributions are encouraged and valued. See the [Table of Contents](#table-of-contents) for different ways to help and details about how this project handles them. Please make sure to read the relevant section before making your contribution. It will make it a lot easier for us maintainers and smooth out the experience for all involved. The ASA community looks forward to your contributions. 🎉 7 | 8 | > And if you like the project, but just don't have time to contribute, that's fine. There are other easy ways to support the project and show your appreciation, which we would also be very happy about: 9 | > 10 | > - Star the project 11 | > - Tweet about it 12 | > - Refer this project in your project's README 13 | > - Mention the project at local meetups and tell your friends/colleagues 14 | 15 | <!-- omit in toc --> 16 | ## Table of Contents 17 | 18 | - [I Have a Question](#i-have-a-question) 19 | - [I Want To Contribute](#i-want-to-contribute) 20 | - [Reporting Bugs](#reporting-bugs) 21 | - [Suggesting Enhancements](#suggesting-enhancements) 22 | - [Your First Code Contribution](#your-first-code-contribution) 23 | - [Environment Setup](#environment-setup) 24 | - [Install `uv`](#install-uv) 25 | - [Install git](#install-git) 26 | - [Create and checkout a branch](#create-and-checkout-a-branch) 27 | - [Install development dependencies](#install-development-dependencies) 28 | - [Make your changes](#make-your-changes) 29 | - [Linting and formatting](#linting-and-formatting) 30 | - [Testing](#testing) 31 | - [Open a pull request](#open-a-pull-request) 32 | - [Improving The Documentation](#improving-the-documentation) 33 | - [Styleguides](#styleguides) 34 | - [Commit Messages](#commit-messages) 35 | 36 | ## I Have a Question 37 | 38 | > If you want to ask a question, we assume that you have read the available [Documentation](https://american-soccer-analysis.github.io/itscalledsoccer/). 39 | 40 | Before you ask a question, it is best to search for existing [Issues](https://github.com/American-Soccer-Analysis/itscalledsoccer/issues) that might help you. In case you have found a suitable issue and still need clarification, you can write your question in this issue. It is also advisable to search the internet for answers first. 41 | 42 | If you then still feel the need to ask a question and need clarification, we recommend the following: 43 | 44 | - Open an [Issue](https://github.com/American-Soccer-Analysis/itscalledsoccer/issues/new). 45 | - Provide as much context as you can about what you're running into. 46 | - Provide project and platform versions, depending on what seems relevant. 47 | 48 | We will then take care of the issue as soon as possible. 49 | 50 | ## I Want To Contribute 51 | 52 | > ### Legal Notice <!-- omit in toc --> 53 | > 54 | > When contributing to this project, you must agree that you have authored 100% of the content, that you have the necessary rights to the content and that the content you contribute may be provided under the project license. 55 | 56 | ### Reporting Bugs 57 | 58 | <!-- omit in toc --> 59 | #### Before Submitting a Bug Report 60 | 61 | A good bug report shouldn't leave others needing to chase you up for more information. Therefore, we ask you to investigate carefully, collect information and describe the issue in detail in your report. Please complete the following steps in advance to help us fix any potential bug as fast as possible. 62 | 63 | - Make sure that you are using the latest version. 64 | - Determine if your bug is really a bug and not an error on your side e.g. using incompatible environment components/versions (Make sure that you have read the [documentation](https://american-soccer-analysis.github.io/itscalledsoccer/). If you are looking for support, you might want to check [this section](#i-have-a-question)). 65 | - To see if other users have experienced (and potentially already solved) the same issue you are having, check if there is not already a bug report existing for your bug or error in the [bug tracker](https://github.com/American-Soccer-Analysis/itscalledsoccerissues?q=label%3Abug). 66 | - Also make sure to search the internet (including Stack Overflow) to see if users outside of the GitHub community have discussed the issue. 67 | - Collect information about the bug: 68 | - Stack trace (Traceback) 69 | - OS, Platform and Version (Windows, Linux, macOS, x86, ARM) 70 | - Version of the interpreter, compiler, SDK, runtime environment, package manager, depending on what seems relevant. 71 | - Possibly your input and the output 72 | - Can you reliably reproduce the issue? And can you also reproduce it with older versions? 73 | 74 | <!-- omit in toc --> 75 | #### How Do I Submit a Good Bug Report? 76 | 77 | > You must never report security related issues, vulnerabilities or bugs including sensitive information to the issue tracker, or elsewhere in public. Instead sensitive bugs must be submitted [here](https://github.com/American-Soccer-Analysis/itscalledsoccer/security/advisories/new). 78 | 79 | We use GitHub issues to track bugs and errors. If you run into an issue with the project: 80 | 81 | - Open an [Bug Report](https://github.com/American-Soccer-Analysis/itscalledsoccer/issues/new?assignees=&labels=bug&projects=&template=bug-report.yml&title=%5BBug%5D%3A+%3Ctitle%3E). 82 | - Explain the behavior you would expect and the actual behavior. 83 | - Please provide as much context as possible and describe the *reproduction steps* that someone else can follow to recreate the issue on their own. This usually includes your code. For good bug reports you should isolate the problem and create a reduced test case. 84 | - Provide the information you collected in the previous section. 85 | 86 | Once it's filed: 87 | 88 | - The project team will label the issue accordingly. 89 | - A team member will try to reproduce the issue with your provided steps. If there are no reproduction steps or no obvious way to reproduce the issue, the team will ask you for those steps. Bugs without reproduction steps will not be addressed until they are provided. 90 | - If the team is able to reproduce the issue, the issue will be left to be [implemented by someone](#your-first-code-contribution). 91 | 92 | ### Suggesting Enhancements 93 | 94 | This section guides you through submitting an enhancement suggestion for `itscalledsoccer`, **including completely new features and minor improvements to existing functionality**. Following these guidelines will help maintainers and the community to understand your suggestion and find related suggestions. 95 | 96 | <!-- omit in toc --> 97 | #### Before Submitting an Enhancement 98 | 99 | - Make sure that you are using the latest version. 100 | - Read the [documentation](https://american-soccer-analysis.github.io/itscalledsoccer/) carefully and find out if the functionality is already covered, maybe by an individual configuration. 101 | - Perform a [search](https://github.com/American-Soccer-Analysis/itscalledsoccer/issues) to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one. 102 | - Find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the project's developers of the merits of this feature. Keep in mind that we want features that will be useful to the majority of our users and not just a small subset. If you're just targeting a minority of users, consider writing an add-on/plugin library. 103 | 104 | <!-- omit in toc --> 105 | #### How Do I Submit a Good Enhancement Suggestion? 106 | 107 | Enhancement suggestions are tracked as [GitHub issues](https://github.com/American-Soccer-Analysis/itscalledsoccer/issues). 108 | 109 | - Use a **clear and descriptive title** for the issue to identify the suggestion. 110 | - Provide a **step-by-step description of the suggested enhancement** in as many details as possible. 111 | - **Describe the current behavior** and **explain which behavior you expected to see instead** and why. At this point you can also tell which alternatives do not work for you. 112 | - **Explain why this enhancement would be useful** to most `itscalledsoccer` users. You may also want to point out the other projects that solved it better and which could serve as inspiration. 113 | 114 | Include the above information in a new [Feature Request](https://github.com/American-Soccer-Analysis/itscalledsoccer/issues/new?assignees=&labels=feature-request&projects=&template=feature-request.yml&title=%5BFeature+Request%5D%3A+%3Ctitle%3E). 115 | 116 | ### Your First Code Contribution 117 | 118 | #### Environment Setup 119 | 120 | The first thing you'll want to do is [fork](https://github.com/American-Soccer-Analysis/itscalledsoccer/fork) the repository and then clone it down to the machine you're working on via SSH or HTTPS. 121 | 122 | ```sh 123 | # SSH 124 | git clone git@github.com:American-Soccer-Analysis/itscalledsoccer.git 125 | # HTTPS 126 | git clone https://github.com/American-Soccer-Analysis/itscalledsoccer.git 127 | ``` 128 | 129 | ##### Install `uv` 130 | 131 | Once the repository is successfully cloned, you'll want to install `uv` on your system. `uv` is an extremely fast Python package and project manager, that can install and manage Python versions. To install it, check out the documentation [here](https://docs.astral.sh/uv/getting-started/installation/). To check that `uv` is installed correctly, run 132 | 133 | ```sh 134 | uv --help 135 | ``` 136 | 137 | And to confirm Python is available, you can run the following: 138 | 139 | ```sh 140 | python --version 141 | # Or: 142 | python3 --version 143 | # On Windows (cmd.exe, with the Python Launcher for Windows): 144 | py --version 145 | ``` 146 | 147 | ##### Install git 148 | 149 | You'll also need [git](https://git-scm.com/) installed. If you don't have it installed, it can be downloaded [here](https://git-scm.com/downloads). To make sure it's installed correctly, you can run: 150 | 151 | ```sh 152 | git -v 153 | ``` 154 | 155 | ##### Create and checkout a branch 156 | 157 | You'll want to create a branch for your changes. You can do that via the `git` command. 158 | 159 | ```sh 160 | cd itscalledsoccer 161 | git branch BRANCH_NAME 162 | git checkout BRANCH_NAME 163 | ``` 164 | 165 | ##### Install development dependencies 166 | 167 | `uv` automatically creates a Python virtual environment, which isolates installed dependencies from other projects. To install the dependencies for `itscalledsoccer`, run: 168 | 169 | ```sh 170 | uv sync --all-extras --dev 171 | ``` 172 | 173 | For more information, see the [uv](https://docs.astral.sh/uv/reference/cli/#uv-sync) and [venv](https://docs.python.org/3/library/venv.html) documentation. 174 | 175 | #### Make your changes 176 | 177 | With the dependencies installed, you're now ready to make your changes. All of the logic for `itscalledsoccer` exists in `client.py`, so this is probably the only Python file you'll need to change. When you're finished with your changes, make sure the new code compiles correctly, all the lint and unit tests pass and you've made any necessary updates to the [documentation](#improving-the-documentation). 178 | 179 | ##### Linting and formatting 180 | 181 | `itscalledsoccer` uses [mypy](https://www.mypy-lang.org/) for static type checking. 182 | 183 | ```sh 184 | uv run mypy itscalledsoccer 185 | ``` 186 | 187 | `itscalledsoccer` uses [ruff](https://docs.astral.sh/ruff/) for formatting. 188 | 189 | ```sh 190 | uv run ruff check itscalledsoccer 191 | uv run ruff format itscalledsoccer 192 | ``` 193 | 194 | ##### Testing 195 | 196 | `itscalledsoccer` uses [pytest](https://docs.pytest.org/en/8.2.x/#) for testing. To run the test suite, run `pytest` from the root directory of the repository. 197 | 198 | ```sh 199 | uv run pytest 200 | ``` 201 | 202 | Whenever you add or modify code, you should ensure that your changes have test coverage. To create a test coverage report, run the below command. 203 | 204 | ```sh 205 | uv run pytest --cov=itscalledsoccer --cov-report=html 206 | ``` 207 | 208 | Open `htmlcov/index.html` in a browser and review the generated coverage report. 209 | 210 | #### Open a pull request 211 | 212 | Once the tests are in good shape and the code has been linted and formatted, you're ready to open a pull request (PR). The [GitHub docs](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request) provide great instructions on how to do just that. 213 | 214 | Once the PR is open, one of the `itscalledsoccer` maintainers will approve the CI workflow run if needed and review the code. 215 | 216 | ### Improving The Documentation 217 | 218 | We use [`Material for MkDocs`](https://squidfunk.github.io/mkdocs-material/) to generate our [documentation site](https://american-soccer-analysis.github.io/itscalledsoccer/). All of our documentation lives in the `docs` folder except for the documentation that is automatically generated from the docstrings by [`mkdocstrings`](https://mkdocstrings.github.io/). Our docstrings follow the [Google styleguide](https://google.github.io/styleguide/pyguide.html#s3.8-comments-and-docstrings). 219 | 220 | ## Styleguides 221 | 222 | ### Commit Messages 223 | 224 | We aim to follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) for our commit messages. 225 | 226 | <!-- omit in toc --> 227 | ## Attribution 228 | 229 | This guide is based on the **contributing-gen**. [Make your own](https://github.com/bttger/contributing-gen)! 230 | -------------------------------------------------------------------------------- /tests/mocks/stadia_payload.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "stadium_id": "0x5g6ojM7O", 4 | "stadium_name": "PNC Stadium", 5 | "capacity": 22039, 6 | "year_built": 2012, 7 | "roof": false, 8 | "turf": false, 9 | "street": "2200 Texas Avenue", 10 | "city": "Houston", 11 | "province": "Texas", 12 | "country": "USA", 13 | "postal_code": "77590", 14 | "latitude": 29.7522, 15 | "longitude": -95.3524, 16 | "field_x": 115, 17 | "field_y": 73 18 | }, 19 | { 20 | "stadium_id": "0x5gJZjM7O", 21 | "stadium_name": "DRV PNK Stadium", 22 | "capacity": 18000, 23 | "year_built": 2020, 24 | "roof": false, 25 | "turf": false, 26 | "street": "1350 NW 55th Street", 27 | "city": "Fort Lauderdale", 28 | "province": "Florida", 29 | "country": "USA", 30 | "postal_code": "33309", 31 | "latitude": 26.1931, 32 | "longitude": -80.1611 33 | }, 34 | { 35 | "stadium_id": "2lqRRVnqr0", 36 | "stadium_name": "BMO Field", 37 | "capacity": 30991, 38 | "year_built": 2007, 39 | "roof": false, 40 | "turf": false, 41 | "street": "170 Princes' Boulevard", 42 | "city": "Toronto", 43 | "province": "Ontario", 44 | "country": "Canada", 45 | "postal_code": "M6K 3C3", 46 | "latitude": 43.6328, 47 | "longitude": -79.4186, 48 | "field_x": 115, 49 | "field_y": 74 50 | }, 51 | { 52 | "stadium_id": "2vQ1eawQrA", 53 | "stadium_name": "Lower.com Field", 54 | "capacity": 20371, 55 | "year_built": 2021, 56 | "roof": false, 57 | "turf": false, 58 | "street": "96 Columbus Crew Way", 59 | "city": "Columbus", 60 | "province": "Ohio", 61 | "country": "USA", 62 | "postal_code": "43215", 63 | "latitude": 39.9685, 64 | "longitude": -83.0171, 65 | "field_x": 115, 66 | "field_y": 75 67 | }, 68 | { 69 | "stadium_id": "7vQ7xbOMD1", 70 | "stadium_name": "Banc of California Stadium", 71 | "capacity": 22000, 72 | "year_built": 2018, 73 | "roof": false, 74 | "turf": false, 75 | "street": "3939 South Figueroa Street", 76 | "city": "Los Angeles", 77 | "province": "California", 78 | "country": "USA", 79 | "postal_code": "90037", 80 | "latitude": 34.013, 81 | "longitude": -118.285 82 | }, 83 | { 84 | "stadium_id": "9vQ2dvm5K6", 85 | "stadium_name": "Stade Olympique (Montreal)", 86 | "capacity": 61004, 87 | "year_built": 1976, 88 | "roof": true, 89 | "turf": true, 90 | "street": "4545 Pierre-de-Coubertin Avenue", 91 | "city": "Montreal", 92 | "province": "Quebec", 93 | "country": "Canada", 94 | "postal_code": "H1V 0B2", 95 | "latitude": 45.558, 96 | "longitude": -73.552, 97 | "field_x": 120, 98 | "field_y": 77 99 | }, 100 | { 101 | "stadium_id": "9Yqda07QvJ", 102 | "stadium_name": "Lumen Field", 103 | "capacity": 38500, 104 | "year_built": 2002, 105 | "roof": false, 106 | "turf": true, 107 | "street": "800 Occidental Avenue South", 108 | "city": "Seattle", 109 | "province": "Washington", 110 | "country": "USA", 111 | "postal_code": "98134", 112 | "latitude": 47.5952, 113 | "longitude": -122.332, 114 | "field_x": 116, 115 | "field_y": 75 116 | }, 117 | { 118 | "stadium_id": "9YqdkYR5vJ", 119 | "stadium_name": "SeatGeek Stadium", 120 | "capacity": 20000, 121 | "year_built": 2006, 122 | "roof": false, 123 | "turf": false, 124 | "street": "7000 South Harlem Avenue", 125 | "city": "Bridgeview", 126 | "province": "Illinois", 127 | "country": "USA", 128 | "postal_code": "60455", 129 | "latitude": 41.7647, 130 | "longitude": -87.8061, 131 | "field_x": 120, 132 | "field_y": 75 133 | }, 134 | { 135 | "stadium_id": "9z5ka6gQA3", 136 | "stadium_name": "Dick's Sporting Goods Park", 137 | "capacity": 18081, 138 | "year_built": 2007, 139 | "roof": false, 140 | "turf": false, 141 | "street": "6000 Victory Way", 142 | "city": "Commerce City", 143 | "province": "Colorado", 144 | "country": "USA", 145 | "postal_code": "80022", 146 | "latitude": 39.8056, 147 | "longitude": -104.892, 148 | "field_x": 120, 149 | "field_y": 75 150 | }, 151 | { 152 | "stadium_id": "a35rBv45L6", 153 | "stadium_name": "Navy-Marine Corps Memorial Stadium", 154 | "capacity": 34000, 155 | "year_built": 1959, 156 | "roof": false, 157 | "turf": true, 158 | "street": "550 Taylor Avenue", 159 | "city": "Annapolis", 160 | "province": "Maryland", 161 | "country": "USA", 162 | "postal_code": "21401", 163 | "latitude": 38.985, 164 | "longitude": -76.507 165 | }, 166 | { 167 | "stadium_id": "BLMvlGBqxe", 168 | "stadium_name": "Pratt & Whitney Stadium at Rentschler Field", 169 | "capacity": 38066, 170 | "year_built": 2003, 171 | "roof": false, 172 | "turf": false, 173 | "street": "615 Silver Lane", 174 | "city": "East Hartford", 175 | "province": "Connecticut", 176 | "country": "USA", 177 | "postal_code": "06118", 178 | "latitude": 41.7597, 179 | "longitude": -72.6189 180 | }, 181 | { 182 | "stadium_id": "e7MzlRjqr0", 183 | "stadium_name": "Rio Tinto Stadium", 184 | "capacity": 20213, 185 | "year_built": 2008, 186 | "roof": false, 187 | "turf": false, 188 | "street": "9256 State Street", 189 | "city": "Sandy", 190 | "province": "Utah", 191 | "country": "USA", 192 | "postal_code": "84070", 193 | "latitude": 40.5829, 194 | "longitude": -111.893, 195 | "field_x": 120, 196 | "field_y": 75 197 | }, 198 | { 199 | "stadium_id": "EGMP1135aY", 200 | "stadium_name": "ESPN Wide World of Sports Complex", 201 | "year_built": 1997, 202 | "roof": false, 203 | "turf": false, 204 | "street": "700 S Victory Way", 205 | "city": "Reunion", 206 | "province": "Florida", 207 | "country": "USA", 208 | "postal_code": "34747", 209 | "latitude": 28.3371, 210 | "longitude": -81.556, 211 | "field_x": 120, 212 | "field_y": 75 213 | }, 214 | { 215 | "stadium_id": "eV5Dz2JQKn", 216 | "stadium_name": "Levi's Stadium", 217 | "capacity": 68500, 218 | "year_built": 2014, 219 | "roof": false, 220 | "turf": false, 221 | "street": "4900 Marie P DeBartolo Way", 222 | "city": "Santa Clara", 223 | "province": "California", 224 | "country": "USA", 225 | "postal_code": "95054", 226 | "latitude": 37.403, 227 | "longitude": -121.97 228 | }, 229 | { 230 | "stadium_id": "eV5DzVRQKn", 231 | "stadium_name": "TCF Bank Stadium", 232 | "capacity": 50805, 233 | "year_built": 2009, 234 | "roof": false, 235 | "turf": true, 236 | "street": "420 SE 23rd Avenue", 237 | "city": "Minneapolis", 238 | "province": "Minnesota", 239 | "country": "USA", 240 | "postal_code": "55455", 241 | "latitude": 44.976, 242 | "longitude": -93.225 243 | }, 244 | { 245 | "stadium_id": "eVq32yn5WO", 246 | "stadium_name": "Yankee Stadium", 247 | "capacity": 28743, 248 | "year_built": 2009, 249 | "roof": false, 250 | "turf": false, 251 | "street": "1 East 161st Street", 252 | "city": "The Bronx", 253 | "province": "New York", 254 | "country": "USA", 255 | "postal_code": "10451", 256 | "latitude": 40.8292, 257 | "longitude": -73.9264, 258 | "field_x": 110, 259 | "field_y": 70 260 | }, 261 | { 262 | "stadium_id": "eVq3alGMWO", 263 | "stadium_name": "Toyota Stadium", 264 | "capacity": 20500, 265 | "year_built": 2005, 266 | "roof": false, 267 | "turf": false, 268 | "street": "9200 World Cup Way", 269 | "city": "Frisco", 270 | "province": "Texas", 271 | "country": "USA", 272 | "postal_code": "75033", 273 | "latitude": 33.1544, 274 | "longitude": -96.8353, 275 | "field_x": 117, 276 | "field_y": 74 277 | }, 278 | { 279 | "stadium_id": "gOMnY6mQwN", 280 | "stadium_name": "Bobby Dodd Stadium", 281 | "capacity": 55000, 282 | "year_built": 1913, 283 | "roof": false, 284 | "turf": false, 285 | "street": "155 North Avenue Northwest", 286 | "city": "Atlanta", 287 | "province": "Georgia", 288 | "country": "USA", 289 | "postal_code": "30313", 290 | "latitude": 33.7725, 291 | "longitude": -84.3928 292 | }, 293 | { 294 | "stadium_id": "gpMOzdEQzy", 295 | "stadium_name": "Soldier Field", 296 | "capacity": 61500, 297 | "year_built": 1924, 298 | "roof": false, 299 | "turf": false, 300 | "street": "1410 S Museum Campus Drive", 301 | "city": "Chicago", 302 | "province": "Illinois", 303 | "country": "USA", 304 | "postal_code": "60605", 305 | "latitude": 41.8623, 306 | "longitude": -87.6167 307 | }, 308 | { 309 | "stadium_id": "gpMOzPrQzy", 310 | "stadium_name": "Camping World Stadium", 311 | "capacity": 19500, 312 | "year_built": 1936, 313 | "roof": false, 314 | "turf": true, 315 | "street": "1 Citrus Bowl Place", 316 | "city": "Orlando", 317 | "province": "Florida", 318 | "country": "USA", 319 | "postal_code": "32805", 320 | "latitude": 28.5389, 321 | "longitude": -81.4028, 322 | "field_x": 114, 323 | "field_y": 74 324 | }, 325 | { 326 | "stadium_id": "jYQJ1PBqGR", 327 | "stadium_name": "RFK Stadium", 328 | "capacity": 45596, 329 | "year_built": 1961, 330 | "roof": false, 331 | "turf": false, 332 | "street": "2400 East Capitol Street SE", 333 | "city": "Washington", 334 | "province": "District of Columbia", 335 | "country": "USA", 336 | "postal_code": "20003", 337 | "latitude": 38.89, 338 | "longitude": -76.972, 339 | "field_x": 110, 340 | "field_y": 72 341 | }, 342 | { 343 | "stadium_id": "jYQJZDDQGR", 344 | "stadium_name": "Q2 Stadium", 345 | "capacity": 20500, 346 | "year_built": 2021, 347 | "roof": false, 348 | "turf": false, 349 | "street": "10414 McKalla Place", 350 | "city": "Austin", 351 | "province": "Texas", 352 | "country": "USA", 353 | "postal_code": "78758", 354 | "latitude": 30.3882, 355 | "longitude": -97.7198 356 | }, 357 | { 358 | "stadium_id": "jYQJZPZQGR", 359 | "stadium_name": "Nashville SC Stadium" 360 | }, 361 | { 362 | "stadium_id": "KAqBkLJQbg", 363 | "stadium_name": "Nippert Stadium", 364 | "capacity": 32250, 365 | "year_built": 1915, 366 | "roof": false, 367 | "turf": true, 368 | "street": "2700 Bearcat Way", 369 | "city": "Cincinnati", 370 | "province": "Ohio", 371 | "country": "USA", 372 | "postal_code": "45219", 373 | "latitude": 39.131, 374 | "longitude": -84.516 375 | }, 376 | { 377 | "stadium_id": "KAqBVWBqbg", 378 | "stadium_name": "Citi Field", 379 | "capacity": 41922, 380 | "year_built": 2009, 381 | "roof": false, 382 | "turf": false, 383 | "street": "41 Seaver Way", 384 | "city": "Flushing", 385 | "province": "New York", 386 | "country": "USA", 387 | "postal_code": "11368", 388 | "latitude": 40.7569, 389 | "longitude": -73.8458 390 | }, 391 | { 392 | "stadium_id": "KPqjRnYq6v", 393 | "stadium_name": "FedExField", 394 | "capacity": 82000, 395 | "year_built": 1997, 396 | "roof": false, 397 | "turf": false, 398 | "street": "1600 FedEx Way", 399 | "city": "Landover", 400 | "province": "Maryland", 401 | "country": "USA", 402 | "postal_code": "20785", 403 | "latitude": 38.9078, 404 | "longitude": -76.8644 405 | }, 406 | { 407 | "stadium_id": "KXMe8pxQ64", 408 | "stadium_name": "Nissan Stadium", 409 | "capacity": 69143, 410 | "year_built": 1999, 411 | "roof": false, 412 | "turf": false, 413 | "street": "1 Titans Way", 414 | "city": "Nashville", 415 | "province": "Tennessee", 416 | "country": "USA", 417 | "postal_code": "37213", 418 | "latitude": 36.1664, 419 | "longitude": -86.7714 420 | }, 421 | { 422 | "stadium_id": "KXMeOR2q64", 423 | "stadium_name": "Bank of America Stadium" 424 | }, 425 | { 426 | "stadium_id": "ljqEDnO5x0", 427 | "stadium_name": "BC Place", 428 | "capacity": 22120, 429 | "year_built": 1983, 430 | "roof": true, 431 | "turf": true, 432 | "street": "777 Pacific Boulevard", 433 | "city": "Vancouver", 434 | "province": "British Columbia", 435 | "country": "Canada", 436 | "postal_code": "V6B 4Y8", 437 | "latitude": 49.2767, 438 | "longitude": -123.112, 439 | "field_x": 117, 440 | "field_y": 75 441 | }, 442 | { 443 | "stadium_id": "ljqEVDNQx0", 444 | "stadium_name": "Rogers Centre", 445 | "capacity": 47568, 446 | "year_built": 1989, 447 | "roof": true, 448 | "turf": true, 449 | "street": "1 Blue Jays Way", 450 | "city": "Toronto", 451 | "province": "Ontario", 452 | "country": "Canada", 453 | "postal_code": "M5V 0L7", 454 | "latitude": 43.6414, 455 | "longitude": -79.3892 456 | }, 457 | { 458 | "stadium_id": "NPqxy6XQ9d", 459 | "stadium_name": "Children's Mercy Park", 460 | "capacity": 18467, 461 | "year_built": 2011, 462 | "roof": false, 463 | "turf": false, 464 | "street": "1 Sporting Way", 465 | "city": "Kansas City", 466 | "province": "Kansas", 467 | "country": "USA", 468 | "postal_code": "66111", 469 | "latitude": 39.1214, 470 | "longitude": -94.821, 471 | "field_x": 120, 472 | "field_y": 75 473 | }, 474 | { 475 | "stadium_id": "NWMW84L5lz", 476 | "stadium_name": "Red Bull Arena", 477 | "capacity": 25000, 478 | "year_built": 2010, 479 | "roof": false, 480 | "turf": false, 481 | "street": "600 Cape May Street", 482 | "city": "Harrison", 483 | "province": "New Jersey", 484 | "country": "USA", 485 | "postal_code": "07029", 486 | "latitude": 40.7367, 487 | "longitude": -74.1503, 488 | "field_x": 120, 489 | "field_y": 75 490 | }, 491 | { 492 | "stadium_id": "NWMW8pj5lz", 493 | "stadium_name": "Stade Saputo", 494 | "capacity": 19619, 495 | "year_built": 2008, 496 | "roof": false, 497 | "turf": false, 498 | "street": "4750 Sherbrooke Street E", 499 | "city": "Montreal", 500 | "province": "Quebec", 501 | "country": "Canada", 502 | "postal_code": "H1V 3S8", 503 | "latitude": 45.5631, 504 | "longitude": -73.5525, 505 | "field_x": 120, 506 | "field_y": 77 507 | }, 508 | { 509 | "stadium_id": "NWMW8ZN5lz", 510 | "stadium_name": "Subaru Park", 511 | "capacity": 18500, 512 | "year_built": 2010, 513 | "roof": false, 514 | "turf": false, 515 | "street": "1 Stadium Drive", 516 | "city": "Chester", 517 | "province": "Pennsylvania", 518 | "country": "USA", 519 | "postal_code": "19013", 520 | "latitude": 39.8322, 521 | "longitude": -75.3789, 522 | "field_x": 120, 523 | "field_y": 75 524 | }, 525 | { 526 | "stadium_id": "NWMWoaeMlz", 527 | "stadium_name": "Mercedes-Benz Stadium", 528 | "capacity": 42500, 529 | "year_built": 2017, 530 | "roof": true, 531 | "turf": true, 532 | "street": "1 AMB Drive NW", 533 | "city": "Atlanta", 534 | "province": "Georgia", 535 | "country": "USA", 536 | "postal_code": "30313", 537 | "latitude": 33.7556, 538 | "longitude": -84.4, 539 | "field_x": 115, 540 | "field_y": 75 541 | }, 542 | { 543 | "stadium_id": "Oa5wKLY514", 544 | "stadium_name": "TQL Stadium", 545 | "capacity": 26000, 546 | "year_built": 2021, 547 | "roof": false, 548 | "turf": false, 549 | "street": "1501 Central Pkwy", 550 | "city": "Cincinnati", 551 | "province": "Ohio", 552 | "country": "USA", 553 | "postal_code": "45214", 554 | "latitude": 39.1114, 555 | "longitude": -84.5222 556 | }, 557 | { 558 | "stadium_id": "Oa5wY94Q14", 559 | "stadium_name": "Stanford Stadium", 560 | "capacity": 50424, 561 | "year_built": 2006, 562 | "roof": false, 563 | "turf": false, 564 | "street": "625 Nelson Road", 565 | "city": "Stanford", 566 | "province": "California", 567 | "country": "USA", 568 | "postal_code": "94305", 569 | "latitude": 37.4344, 570 | "longitude": -122.161 571 | }, 572 | { 573 | "stadium_id": "odMXGRrQYL", 574 | "stadium_name": "Allianz Field", 575 | "capacity": 19400, 576 | "year_built": 2019, 577 | "roof": false, 578 | "turf": false, 579 | "street": "400 Snelling Ave N", 580 | "city": "St Paul", 581 | "province": "Minnesota", 582 | "country": "USA", 583 | "postal_code": "55104", 584 | "latitude": 44.9528, 585 | "longitude": -93.165, 586 | "field_x": 120, 587 | "field_y": 75 588 | }, 589 | { 590 | "stadium_id": "p6qbeb850G", 591 | "stadium_name": "Historic Crew Stadium", 592 | "capacity": 19968, 593 | "year_built": 1999, 594 | "roof": false, 595 | "turf": false, 596 | "street": "1 Black and Gold Boulevard", 597 | "city": "Columbus", 598 | "province": "Ohio", 599 | "country": "USA", 600 | "postal_code": "43211", 601 | "latitude": 40.0094, 602 | "longitude": -82.9911, 603 | "field_x": 115, 604 | "field_y": 75 605 | }, 606 | { 607 | "stadium_id": "p6qbX06M0G", 608 | "stadium_name": "Providence Park", 609 | "capacity": 25218, 610 | "year_built": 1926, 611 | "roof": false, 612 | "turf": true, 613 | "street": "1844 SW Morrison St", 614 | "city": "Portland", 615 | "province": "Oregon", 616 | "country": "USA", 617 | "postal_code": "97205", 618 | "latitude": 45.5214, 619 | "longitude": -122.692, 620 | "field_x": 110, 621 | "field_y": 75 622 | }, 623 | { 624 | "stadium_id": "Vj58BPwQ8n", 625 | "stadium_name": "Buck Shaw Stadium", 626 | "capacity": 10525, 627 | "year_built": 1962, 628 | "roof": false, 629 | "turf": false, 630 | "street": "500 El Camino Real", 631 | "city": "Santa Clara", 632 | "province": "California", 633 | "country": "USA", 634 | "postal_code": "95053", 635 | "latitude": 37.3506, 636 | "longitude": -121.937, 637 | "field_x": 115, 638 | "field_y": 74 639 | }, 640 | { 641 | "stadium_id": "Vj58W84M8n", 642 | "stadium_name": "PayPal Park", 643 | "capacity": 18000, 644 | "year_built": 2015, 645 | "roof": false, 646 | "turf": false, 647 | "street": "1123 Coleman Avenue", 648 | "city": "San Jose", 649 | "province": "California", 650 | "country": "USA", 651 | "postal_code": "95110", 652 | "latitude": 37.3514, 653 | "longitude": -121.925, 654 | "field_x": 115, 655 | "field_y": 74 656 | }, 657 | { 658 | "stadium_id": "vzqoGO7qap", 659 | "stadium_name": "Maryland SoccerPlex", 660 | "capacity": 4000, 661 | "year_built": 2000, 662 | "roof": false, 663 | "turf": false, 664 | "street": "18031 Central Park Circle", 665 | "city": "Boyds", 666 | "province": "Maryland", 667 | "country": "USA", 668 | "postal_code": "20841", 669 | "latitude": 39.1528, 670 | "longitude": -77.3136, 671 | "field_x": 115, 672 | "field_y": 75 673 | }, 674 | { 675 | "stadium_id": "vzqoJrj5ap", 676 | "stadium_name": "Exploria Stadium", 677 | "capacity": 25500, 678 | "year_built": 2017, 679 | "roof": false, 680 | "turf": false, 681 | "street": "655 West Church Street", 682 | "city": "Orlando", 683 | "province": "Florida", 684 | "country": "USA", 685 | "postal_code": "32805", 686 | "latitude": 28.5411, 687 | "longitude": -81.3893, 688 | "field_x": 120, 689 | "field_y": 75 690 | }, 691 | { 692 | "stadium_id": "wvq9p1Y5Wn", 693 | "stadium_name": "Dignity Health Sports Park", 694 | "capacity": 27000, 695 | "year_built": 2003, 696 | "roof": false, 697 | "turf": false, 698 | "street": "18400 Avalon Boulevard", 699 | "city": "Carson", 700 | "province": "California", 701 | "country": "USA", 702 | "postal_code": "90746", 703 | "latitude": 33.864, 704 | "longitude": -118.261, 705 | "field_x": 120, 706 | "field_y": 75 707 | }, 708 | { 709 | "stadium_id": "wvq9p775Wn", 710 | "stadium_name": "Gillette Stadium", 711 | "capacity": 65878, 712 | "year_built": 2002, 713 | "roof": false, 714 | "turf": true, 715 | "street": "1 Patriot Place", 716 | "city": "Foxborough", 717 | "province": "Massachusetts", 718 | "country": "USA", 719 | "postal_code": "02035", 720 | "latitude": 42.091, 721 | "longitude": -71.264, 722 | "field_x": 116, 723 | "field_y": 75 724 | }, 725 | { 726 | "stadium_id": "xW5pwORMg1", 727 | "stadium_name": "Audi Field", 728 | "capacity": 20000, 729 | "year_built": 2018, 730 | "roof": false, 731 | "turf": false, 732 | "street": "100 Potomac Avenue SW", 733 | "city": "Washington", 734 | "province": "District of Columbia", 735 | "country": "USA", 736 | "postal_code": "20024", 737 | "latitude": 38.8683, 738 | "longitude": -77.0122, 739 | "field_x": 115, 740 | "field_y": 75 741 | } 742 | ] -------------------------------------------------------------------------------- /tests/mocks/teams_xpass_payload.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "team_id": "0KPqjA456v", 4 | "count_games": 306, 5 | "attempted_passes_for": 143760, 6 | "pass_completion_percentage_for": 0.7772, 7 | "xpass_completion_percentage_for": 0.777, 8 | "passes_completed_over_expected_for": 26.945, 9 | "passes_completed_over_expected_p100_for": 0.0187, 10 | "avg_vertical_distance_for": 7.5978, 11 | "attempted_passes_against": 138234, 12 | "pass_completion_percentage_against": 0.7731, 13 | "xpass_completion_percentage_against": 0.7687, 14 | "passes_completed_over_expected_against": 610.3086, 15 | "passes_completed_over_expected_p100_against": 0.4415, 16 | "avg_vertical_distance_against": 7.952, 17 | "passes_completed_over_expected_difference": -583.3636, 18 | "avg_vertical_distance_difference": -0.3542 19 | }, 20 | { 21 | "team_id": "19vQ2095K6", 22 | "count_games": 316, 23 | "attempted_passes_for": 141593, 24 | "pass_completion_percentage_for": 0.7543, 25 | "xpass_completion_percentage_for": 0.755, 26 | "passes_completed_over_expected_for": -96.7299, 27 | "passes_completed_over_expected_p100_for": -0.0683, 28 | "avg_vertical_distance_for": 8.6576, 29 | "attempted_passes_against": 151184, 30 | "pass_completion_percentage_against": 0.7698, 31 | "xpass_completion_percentage_against": 0.7694, 32 | "passes_completed_over_expected_against": 63.374, 33 | "passes_completed_over_expected_p100_against": 0.0419, 34 | "avg_vertical_distance_against": 7.9412, 35 | "passes_completed_over_expected_difference": -160.1039, 36 | "avg_vertical_distance_difference": 0.7164 37 | }, 38 | { 39 | "team_id": "4wM42l4qjB", 40 | "count_games": 68, 41 | "attempted_passes_for": 26757, 42 | "pass_completion_percentage_for": 0.7266, 43 | "xpass_completion_percentage_for": 0.7546, 44 | "passes_completed_over_expected_for": -749.5483, 45 | "passes_completed_over_expected_p100_for": -2.8013, 46 | "avg_vertical_distance_for": 9.5975, 47 | "attempted_passes_against": 34878, 48 | "pass_completion_percentage_against": 0.79, 49 | "xpass_completion_percentage_against": 0.7878, 50 | "passes_completed_over_expected_against": 79.818, 51 | "passes_completed_over_expected_p100_against": 0.2288, 52 | "avg_vertical_distance_against": 7.3749, 53 | "passes_completed_over_expected_difference": -829.3663, 54 | "avg_vertical_distance_difference": 2.2225 55 | }, 56 | { 57 | "team_id": "9z5k7Yg5A3", 58 | "count_games": 312, 59 | "attempted_passes_for": 141275, 60 | "pass_completion_percentage_for": 0.7563, 61 | "xpass_completion_percentage_for": 0.7583, 62 | "passes_completed_over_expected_for": -278.2897, 63 | "passes_completed_over_expected_p100_for": -0.197, 64 | "avg_vertical_distance_for": 8.1991, 65 | "attempted_passes_against": 150972, 66 | "pass_completion_percentage_against": 0.779, 67 | "xpass_completion_percentage_against": 0.779, 68 | "passes_completed_over_expected_against": 2.4779, 69 | "passes_completed_over_expected_p100_against": 0.0016, 70 | "avg_vertical_distance_against": 7.5222, 71 | "passes_completed_over_expected_difference": -280.7676, 72 | "avg_vertical_distance_difference": 0.6769 73 | }, 74 | { 75 | "team_id": "a2lqR4JMr0", 76 | "count_games": 318, 77 | "attempted_passes_for": 153177, 78 | "pass_completion_percentage_for": 0.7818, 79 | "xpass_completion_percentage_for": 0.781, 80 | "passes_completed_over_expected_for": 136.3774, 81 | "passes_completed_over_expected_p100_for": 0.089, 82 | "avg_vertical_distance_for": 7.478, 83 | "attempted_passes_against": 138002, 84 | "pass_completion_percentage_against": 0.7569, 85 | "xpass_completion_percentage_against": 0.7623, 86 | "passes_completed_over_expected_against": -752.1799, 87 | "passes_completed_over_expected_p100_against": -0.5451, 88 | "avg_vertical_distance_against": 8.2226, 89 | "passes_completed_over_expected_difference": 888.5573, 90 | "avg_vertical_distance_difference": -0.7445 91 | }, 92 | { 93 | "team_id": "a2lqRX2Mr0", 94 | "count_games": 324, 95 | "attempted_passes_for": 150242, 96 | "pass_completion_percentage_for": 0.7273, 97 | "xpass_completion_percentage_for": 0.7373, 98 | "passes_completed_over_expected_for": -1515.4852, 99 | "passes_completed_over_expected_p100_for": -1.0087, 100 | "avg_vertical_distance_for": 8.8335, 101 | "attempted_passes_against": 144892, 102 | "pass_completion_percentage_against": 0.725, 103 | "xpass_completion_percentage_against": 0.7473, 104 | "passes_completed_over_expected_against": -3229.133, 105 | "passes_completed_over_expected_p100_against": -2.2286, 106 | "avg_vertical_distance_against": 9.1295, 107 | "passes_completed_over_expected_difference": 1713.6478, 108 | "avg_vertical_distance_difference": -0.296 109 | }, 110 | { 111 | "team_id": "APk5LGOMOW", 112 | "count_games": 313, 113 | "attempted_passes_for": 144594, 114 | "pass_completion_percentage_for": 0.7857, 115 | "xpass_completion_percentage_for": 0.7908, 116 | "passes_completed_over_expected_for": -744.8451, 117 | "passes_completed_over_expected_p100_for": -0.5151, 118 | "avg_vertical_distance_for": 7.3182, 119 | "attempted_passes_against": 153884, 120 | "pass_completion_percentage_against": 0.7925, 121 | "xpass_completion_percentage_against": 0.7894, 122 | "passes_completed_over_expected_against": 480.0774, 123 | "passes_completed_over_expected_p100_against": 0.312, 124 | "avg_vertical_distance_against": 6.9921, 125 | "passes_completed_over_expected_difference": -1224.9226, 126 | "avg_vertical_distance_difference": 0.3261 127 | }, 128 | { 129 | "team_id": "EKXMeX3Q64", 130 | "count_games": 308, 131 | "attempted_passes_for": 138935, 132 | "pass_completion_percentage_for": 0.7537, 133 | "xpass_completion_percentage_for": 0.7602, 134 | "passes_completed_over_expected_for": -915.499, 135 | "passes_completed_over_expected_p100_for": -0.6589, 136 | "avg_vertical_distance_for": 8.423, 137 | "attempted_passes_against": 151207, 138 | "pass_completion_percentage_against": 0.7704, 139 | "xpass_completion_percentage_against": 0.7707, 140 | "passes_completed_over_expected_against": -54.8244, 141 | "passes_completed_over_expected_p100_against": -0.0363, 142 | "avg_vertical_distance_against": 7.5817, 143 | "passes_completed_over_expected_difference": -860.6746, 144 | "avg_vertical_distance_difference": 0.8413 145 | }, 146 | { 147 | "team_id": "eVq3ya6MWO", 148 | "count_games": 136, 149 | "attempted_passes_for": 71261, 150 | "pass_completion_percentage_for": 0.8126, 151 | "xpass_completion_percentage_for": 0.808, 152 | "passes_completed_over_expected_for": 327.2048, 153 | "passes_completed_over_expected_p100_for": 0.4592, 154 | "avg_vertical_distance_for": 6.0158, 155 | "attempted_passes_against": 60419, 156 | "pass_completion_percentage_against": 0.7661, 157 | "xpass_completion_percentage_against": 0.7774, 158 | "passes_completed_over_expected_against": -682.7978, 159 | "passes_completed_over_expected_p100_against": -1.1301, 160 | "avg_vertical_distance_against": 7.535, 161 | "passes_completed_over_expected_difference": 1010.0026, 162 | "avg_vertical_distance_difference": -1.5192 163 | }, 164 | { 165 | "team_id": "gpMOLwl5zy", 166 | "count_games": 40, 167 | "attempted_passes_for": 20741, 168 | "pass_completion_percentage_for": 0.8275, 169 | "xpass_completion_percentage_for": 0.8213, 170 | "passes_completed_over_expected_for": 130.0703, 171 | "passes_completed_over_expected_p100_for": 0.6271, 172 | "avg_vertical_distance_for": 5.3604, 173 | "attempted_passes_against": 17564, 174 | "pass_completion_percentage_against": 0.8066, 175 | "xpass_completion_percentage_against": 0.8012, 176 | "passes_completed_over_expected_against": 95.0064, 177 | "passes_completed_over_expected_p100_against": 0.5409, 178 | "avg_vertical_distance_against": 6.2783, 179 | "passes_completed_over_expected_difference": 35.0639, 180 | "avg_vertical_distance_difference": -0.9178 181 | }, 182 | { 183 | "team_id": "jYQJ19EqGR", 184 | "count_games": 332, 185 | "attempted_passes_for": 169881, 186 | "pass_completion_percentage_for": 0.7864, 187 | "xpass_completion_percentage_for": 0.7815, 188 | "passes_completed_over_expected_for": 833.75, 189 | "passes_completed_over_expected_p100_for": 0.4908, 190 | "avg_vertical_distance_for": 7.0384, 191 | "attempted_passes_against": 159948, 192 | "pass_completion_percentage_against": 0.7826, 193 | "xpass_completion_percentage_against": 0.7817, 194 | "passes_completed_over_expected_against": 147.366, 195 | "passes_completed_over_expected_p100_against": 0.0921, 196 | "avg_vertical_distance_against": 7.2644, 197 | "passes_completed_over_expected_difference": 686.384, 198 | "avg_vertical_distance_difference": -0.226 199 | }, 200 | { 201 | "team_id": "jYQJ8EW5GR", 202 | "count_games": 241, 203 | "attempted_passes_for": 114580, 204 | "pass_completion_percentage_for": 0.7981, 205 | "xpass_completion_percentage_for": 0.7926, 206 | "passes_completed_over_expected_for": 636.1656, 207 | "passes_completed_over_expected_p100_for": 0.5552, 208 | "avg_vertical_distance_for": 6.8496, 209 | "attempted_passes_against": 114148, 210 | "pass_completion_percentage_against": 0.795, 211 | "xpass_completion_percentage_against": 0.7888, 212 | "passes_completed_over_expected_against": 705.8879, 213 | "passes_completed_over_expected_p100_against": 0.6184, 214 | "avg_vertical_distance_against": 6.8382, 215 | "passes_completed_over_expected_difference": -69.7223, 216 | "avg_vertical_distance_difference": 0.0114 217 | }, 218 | { 219 | "team_id": "kaDQ0wRqEv", 220 | "count_games": 313, 221 | "attempted_passes_for": 153683, 222 | "pass_completion_percentage_for": 0.7874, 223 | "xpass_completion_percentage_for": 0.782, 224 | "passes_completed_over_expected_for": 829.0672, 225 | "passes_completed_over_expected_p100_for": 0.5395, 226 | "avg_vertical_distance_for": 7.1364, 227 | "attempted_passes_against": 147469, 228 | "pass_completion_percentage_against": 0.7838, 229 | "xpass_completion_percentage_against": 0.7818, 230 | "passes_completed_over_expected_against": 294.7966, 231 | "passes_completed_over_expected_p100_against": 0.1999, 232 | "avg_vertical_distance_against": 7.3781, 233 | "passes_completed_over_expected_difference": 534.2706, 234 | "avg_vertical_distance_difference": -0.2417 235 | }, 236 | { 237 | "team_id": "KAqBN0Vqbg", 238 | "count_games": 176, 239 | "attempted_passes_for": 92675, 240 | "pass_completion_percentage_for": 0.8137, 241 | "xpass_completion_percentage_for": 0.8143, 242 | "passes_completed_over_expected_for": -60.1931, 243 | "passes_completed_over_expected_p100_for": -0.065, 244 | "avg_vertical_distance_for": 5.6212, 245 | "attempted_passes_against": 74619, 246 | "pass_completion_percentage_against": 0.7747, 247 | "xpass_completion_percentage_against": 0.776, 248 | "passes_completed_over_expected_against": -94.6438, 249 | "passes_completed_over_expected_p100_against": -0.1268, 250 | "avg_vertical_distance_against": 7.5494, 251 | "passes_completed_over_expected_difference": 34.4507, 252 | "avg_vertical_distance_difference": -1.9282 253 | }, 254 | { 255 | "team_id": "kRQabn8MKZ", 256 | "count_games": 319, 257 | "attempted_passes_for": 159356, 258 | "pass_completion_percentage_for": 0.7894, 259 | "xpass_completion_percentage_for": 0.7842, 260 | "passes_completed_over_expected_for": 822.1967, 261 | "passes_completed_over_expected_p100_for": 0.5159, 262 | "avg_vertical_distance_for": 7.3522, 263 | "attempted_passes_against": 152974, 264 | "pass_completion_percentage_against": 0.778, 265 | "xpass_completion_percentage_against": 0.7787, 266 | "passes_completed_over_expected_against": -106.2762, 267 | "passes_completed_over_expected_p100_against": -0.0695, 268 | "avg_vertical_distance_against": 7.3849, 269 | "passes_completed_over_expected_difference": 928.473, 270 | "avg_vertical_distance_difference": -0.0327 271 | }, 272 | { 273 | "team_id": "kRQand1MKZ", 274 | "count_games": 171, 275 | "attempted_passes_for": 80355, 276 | "pass_completion_percentage_for": 0.7774, 277 | "xpass_completion_percentage_for": 0.7805, 278 | "passes_completed_over_expected_for": -245.2806, 279 | "passes_completed_over_expected_p100_for": -0.3052, 280 | "avg_vertical_distance_for": 7.2812, 281 | "attempted_passes_against": 89037, 282 | "pass_completion_percentage_against": 0.7996, 283 | "xpass_completion_percentage_against": 0.7955, 284 | "passes_completed_over_expected_against": 367.6606, 285 | "passes_completed_over_expected_p100_against": 0.4129, 286 | "avg_vertical_distance_against": 6.3365, 287 | "passes_completed_over_expected_difference": -612.9412, 288 | "avg_vertical_distance_difference": 0.9446 289 | }, 290 | { 291 | "team_id": "lgpMOvnQzy", 292 | "count_games": 310, 293 | "attempted_passes_for": 133339, 294 | "pass_completion_percentage_for": 0.7634, 295 | "xpass_completion_percentage_for": 0.7671, 296 | "passes_completed_over_expected_for": -487.075, 297 | "passes_completed_over_expected_p100_for": -0.3653, 298 | "avg_vertical_distance_for": 8.3617, 299 | "attempted_passes_against": 159597, 300 | "pass_completion_percentage_against": 0.7948, 301 | "xpass_completion_percentage_against": 0.7862, 302 | "passes_completed_over_expected_against": 1370.7871, 303 | "passes_completed_over_expected_p100_against": 0.8589, 304 | "avg_vertical_distance_against": 6.7735, 305 | "passes_completed_over_expected_difference": -1857.8621, 306 | "avg_vertical_distance_difference": 1.5883 307 | }, 308 | { 309 | "team_id": "mKAqBBmqbg", 310 | "count_games": 313, 311 | "attempted_passes_for": 144585, 312 | "pass_completion_percentage_for": 0.7788, 313 | "xpass_completion_percentage_for": 0.7806, 314 | "passes_completed_over_expected_for": -250.3814, 315 | "passes_completed_over_expected_p100_for": -0.1732, 316 | "avg_vertical_distance_for": 7.4033, 317 | "attempted_passes_against": 146217, 318 | "pass_completion_percentage_against": 0.7779, 319 | "xpass_completion_percentage_against": 0.7793, 320 | "passes_completed_over_expected_against": -203.4324, 321 | "passes_completed_over_expected_p100_against": -0.1391, 322 | "avg_vertical_distance_against": 7.529, 323 | "passes_completed_over_expected_difference": -46.9491, 324 | "avg_vertical_distance_difference": -0.1257 325 | }, 326 | { 327 | "team_id": "mvzqoLZQap", 328 | "count_games": 321, 329 | "attempted_passes_for": 160790, 330 | "pass_completion_percentage_for": 0.794, 331 | "xpass_completion_percentage_for": 0.7914, 332 | "passes_completed_over_expected_for": 422.5826, 333 | "passes_completed_over_expected_p100_for": 0.2628, 334 | "avg_vertical_distance_for": 7.0149, 335 | "attempted_passes_against": 148030, 336 | "pass_completion_percentage_against": 0.7761, 337 | "xpass_completion_percentage_against": 0.7783, 338 | "passes_completed_over_expected_against": -325.2871, 339 | "passes_completed_over_expected_p100_against": -0.2197, 340 | "avg_vertical_distance_against": 7.7152, 341 | "passes_completed_over_expected_difference": 747.8697, 342 | "avg_vertical_distance_difference": -0.7002 343 | }, 344 | { 345 | "team_id": "NPqxKXZ59d", 346 | "count_games": 7, 347 | "attempted_passes_for": 3403, 348 | "pass_completion_percentage_for": 0.7846, 349 | "xpass_completion_percentage_for": 0.7982, 350 | "passes_completed_over_expected_for": -46.2178, 351 | "passes_completed_over_expected_p100_for": -1.3581, 352 | "avg_vertical_distance_for": 6.0998, 353 | "attempted_passes_against": 3254, 354 | "pass_completion_percentage_against": 0.7846, 355 | "xpass_completion_percentage_against": 0.7853, 356 | "passes_completed_over_expected_against": -2.2315, 357 | "passes_completed_over_expected_p100_against": -0.0686, 358 | "avg_vertical_distance_against": 6.4054, 359 | "passes_completed_over_expected_difference": -43.9864, 360 | "avg_vertical_distance_difference": -0.3056 361 | }, 362 | { 363 | "team_id": "NWMWlBK5lz", 364 | "count_games": 99, 365 | "attempted_passes_for": 45572, 366 | "pass_completion_percentage_for": 0.7967, 367 | "xpass_completion_percentage_for": 0.8003, 368 | "passes_completed_over_expected_for": -166.083, 369 | "passes_completed_over_expected_p100_for": -0.3644, 370 | "avg_vertical_distance_for": 6.5047, 371 | "attempted_passes_against": 50096, 372 | "pass_completion_percentage_against": 0.8051, 373 | "xpass_completion_percentage_against": 0.8026, 374 | "passes_completed_over_expected_against": 128.4724, 375 | "passes_completed_over_expected_p100_against": 0.2565, 376 | "avg_vertical_distance_against": 5.8752, 377 | "passes_completed_over_expected_difference": -294.5554, 378 | "avg_vertical_distance_difference": 0.6294 379 | }, 380 | { 381 | "team_id": "pzeQZ6xQKw", 382 | "count_games": 303, 383 | "attempted_passes_for": 137092, 384 | "pass_completion_percentage_for": 0.7664, 385 | "xpass_completion_percentage_for": 0.7687, 386 | "passes_completed_over_expected_for": -308.7561, 387 | "passes_completed_over_expected_p100_for": -0.2252, 388 | "avg_vertical_distance_for": 8.2149, 389 | "attempted_passes_against": 149275, 390 | "pass_completion_percentage_against": 0.7845, 391 | "xpass_completion_percentage_against": 0.7849, 392 | "passes_completed_over_expected_against": -68.2264, 393 | "passes_completed_over_expected_p100_against": -0.0457, 394 | "avg_vertical_distance_against": 7.3446, 395 | "passes_completed_over_expected_difference": -240.5297, 396 | "avg_vertical_distance_difference": 0.8703 397 | }, 398 | { 399 | "team_id": "Vj58weDM8n", 400 | "count_games": 247, 401 | "attempted_passes_for": 130989, 402 | "pass_completion_percentage_for": 0.794, 403 | "xpass_completion_percentage_for": 0.7909, 404 | "passes_completed_over_expected_for": 397.7879, 405 | "passes_completed_over_expected_p100_for": 0.3037, 406 | "avg_vertical_distance_for": 6.6652, 407 | "attempted_passes_against": 105726, 408 | "pass_completion_percentage_against": 0.743, 409 | "xpass_completion_percentage_against": 0.7547, 410 | "passes_completed_over_expected_against": -1235.9439, 411 | "passes_completed_over_expected_p100_against": -1.169, 412 | "avg_vertical_distance_against": 8.4851, 413 | "passes_completed_over_expected_difference": 1633.7318, 414 | "avg_vertical_distance_difference": -1.8198 415 | }, 416 | { 417 | "team_id": "vzqoOgNqap", 418 | "count_games": 69, 419 | "attempted_passes_for": 31446, 420 | "pass_completion_percentage_for": 0.7857, 421 | "xpass_completion_percentage_for": 0.7813, 422 | "passes_completed_over_expected_for": 138.7941, 423 | "passes_completed_over_expected_p100_for": 0.4414, 424 | "avg_vertical_distance_for": 7.0663, 425 | "attempted_passes_against": 37841, 426 | "pass_completion_percentage_against": 0.8219, 427 | "xpass_completion_percentage_against": 0.8166, 428 | "passes_completed_over_expected_against": 203.6974, 429 | "passes_completed_over_expected_p100_against": 0.5383, 430 | "avg_vertical_distance_against": 5.4027, 431 | "passes_completed_over_expected_difference": -64.9033, 432 | "avg_vertical_distance_difference": 1.6635 433 | }, 434 | { 435 | "team_id": "WBLMvYAQxe", 436 | "count_games": 331, 437 | "attempted_passes_for": 152618, 438 | "pass_completion_percentage_for": 0.7753, 439 | "xpass_completion_percentage_for": 0.7723, 440 | "passes_completed_over_expected_for": 470.7418, 441 | "passes_completed_over_expected_p100_for": 0.3084, 442 | "avg_vertical_distance_for": 7.8723, 443 | "attempted_passes_against": 159213, 444 | "pass_completion_percentage_against": 0.7827, 445 | "xpass_completion_percentage_against": 0.7734, 446 | "passes_completed_over_expected_against": 1483.0648, 447 | "passes_completed_over_expected_p100_against": 0.9315, 448 | "avg_vertical_distance_against": 7.6643, 449 | "passes_completed_over_expected_difference": -1012.3231, 450 | "avg_vertical_distance_difference": 0.2079 451 | }, 452 | { 453 | "team_id": "X0Oq66zq6D", 454 | "count_games": 302, 455 | "attempted_passes_for": 136807, 456 | "pass_completion_percentage_for": 0.7653, 457 | "xpass_completion_percentage_for": 0.7719, 458 | "passes_completed_over_expected_for": -913.1294, 459 | "passes_completed_over_expected_p100_for": -0.6675, 460 | "avg_vertical_distance_for": 7.8284, 461 | "attempted_passes_against": 147795, 462 | "pass_completion_percentage_against": 0.7813, 463 | "xpass_completion_percentage_against": 0.7813, 464 | "passes_completed_over_expected_against": -3.3603, 465 | "passes_completed_over_expected_p100_against": -0.0023, 466 | "avg_vertical_distance_against": 7.3536, 467 | "passes_completed_over_expected_difference": -909.7691, 468 | "avg_vertical_distance_difference": 0.4748 469 | }, 470 | { 471 | "team_id": "YgOMngl5wN", 472 | "count_games": 312, 473 | "attempted_passes_for": 137368, 474 | "pass_completion_percentage_for": 0.7638, 475 | "xpass_completion_percentage_for": 0.7676, 476 | "passes_completed_over_expected_for": -522.94, 477 | "passes_completed_over_expected_p100_for": -0.3807, 478 | "avg_vertical_distance_for": 8.2341, 479 | "attempted_passes_against": 150556, 480 | "pass_completion_percentage_against": 0.7879, 481 | "xpass_completion_percentage_against": 0.7832, 482 | "passes_completed_over_expected_against": 706.8194, 483 | "passes_completed_over_expected_p100_against": 0.4695, 484 | "avg_vertical_distance_against": 7.3691, 485 | "passes_completed_over_expected_difference": -1229.7594, 486 | "avg_vertical_distance_difference": 0.865 487 | }, 488 | { 489 | "team_id": "Z2vQ1xlqrA", 490 | "count_games": 319, 491 | "attempted_passes_for": 159493, 492 | "pass_completion_percentage_for": 0.7888, 493 | "xpass_completion_percentage_for": 0.7893, 494 | "passes_completed_over_expected_for": -77.1761, 495 | "passes_completed_over_expected_p100_for": -0.0484, 496 | "avg_vertical_distance_for": 6.7382, 497 | "attempted_passes_against": 135599, 498 | "pass_completion_percentage_against": 0.7493, 499 | "xpass_completion_percentage_against": 0.7663, 500 | "passes_completed_over_expected_against": -2309.2044, 501 | "passes_completed_over_expected_p100_against": -1.703, 502 | "avg_vertical_distance_against": 8.6949, 503 | "passes_completed_over_expected_difference": 2232.0283, 504 | "avg_vertical_distance_difference": -1.9567 505 | }, 506 | { 507 | "team_id": "zeQZkL1MKw", 508 | "count_games": 64, 509 | "attempted_passes_for": 28284, 510 | "pass_completion_percentage_for": 0.7959, 511 | "xpass_completion_percentage_for": 0.7943, 512 | "passes_completed_over_expected_for": 45.6549, 513 | "passes_completed_over_expected_p100_for": 0.1614, 514 | "avg_vertical_distance_for": 6.4977, 515 | "attempted_passes_against": 32021, 516 | "pass_completion_percentage_against": 0.8211, 517 | "xpass_completion_percentage_against": 0.8159, 518 | "passes_completed_over_expected_against": 167.6352, 519 | "passes_completed_over_expected_p100_against": 0.5235, 520 | "avg_vertical_distance_against": 5.7636, 521 | "passes_completed_over_expected_difference": -121.9803, 522 | "avg_vertical_distance_difference": 0.7341 523 | } 524 | ] -------------------------------------------------------------------------------- /tests/mocks/games_payload.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "game_id": "2lqRG7bDQr", 4 | "date_time_utc": "2020-11-08 23:30:00 UTC", 5 | "home_score": 4, 6 | "away_score": 1, 7 | "home_team_id": "jYQJ19EqGR", 8 | "away_team_id": "0KPqjA456v", 9 | "referee_id": "9z5kJ7gMA3", 10 | "stadium_id": "9Yqda07QvJ", 11 | "home_manager_id": "odMXxreMYL", 12 | "away_manager_id": "2vQ10jwqrA", 13 | "expanded_minutes": 93, 14 | "season_name": "2020", 15 | "matchday": 24, 16 | "attendance": 0, 17 | "knockout_game": false, 18 | "last_updated_utc": "2020-11-12 08:20:17 UTC" 19 | }, 20 | { 21 | "game_id": "7VqGD32XQv", 22 | "date_time_utc": "2020-11-08 23:30:00 UTC", 23 | "home_score": 3, 24 | "away_score": 0, 25 | "home_team_id": "kRQand1MKZ", 26 | "away_team_id": "mKAqBBmqbg", 27 | "referee_id": "KAqB3m7Qbg", 28 | "stadium_id": "odMXGRrQYL", 29 | "home_manager_id": "OlMlYvy5Lz", 30 | "away_manager_id": "eV5DNVJQKn", 31 | "expanded_minutes": 98, 32 | "season_name": "2020", 33 | "matchday": 24, 34 | "attendance": 0, 35 | "knockout_game": false, 36 | "last_updated_utc": "2020-11-17 15:04:25 UTC" 37 | }, 38 | { 39 | "game_id": "KAqBPkl7Mb", 40 | "date_time_utc": "2020-11-08 23:30:00 UTC", 41 | "home_score": 1, 42 | "away_score": 2, 43 | "home_team_id": "YgOMngl5wN", 44 | "away_team_id": "pzeQZ6xQKw", 45 | "referee_id": "KPqjDeNM6v", 46 | "stadium_id": "0x5g6ojM7O", 47 | "home_manager_id": "4wM4AAk5jB", 48 | "away_manager_id": "0Oq6VPgq6D", 49 | "expanded_minutes": 96, 50 | "season_name": "2020", 51 | "matchday": 24, 52 | "attendance": 2327, 53 | "knockout_game": false, 54 | "last_updated_utc": "2020-11-13 13:58:48 UTC" 55 | }, 56 | { 57 | "game_id": "NWMWRoBzQl", 58 | "date_time_utc": "2020-11-08 23:30:00 UTC", 59 | "home_score": 1, 60 | "away_score": 1, 61 | "home_team_id": "eVq3ya6MWO", 62 | "away_team_id": "WBLMvYAQxe", 63 | "referee_id": "0Oq6037M6D", 64 | "stadium_id": "7vQ7xbOMD1", 65 | "home_manager_id": "0Oq6zkzq6D", 66 | "away_manager_id": "gpMOYv1qzy", 67 | "expanded_minutes": 98, 68 | "season_name": "2020", 69 | "matchday": 24, 70 | "attendance": 0, 71 | "knockout_game": false, 72 | "last_updated_utc": "2020-11-11 19:54:26 UTC" 73 | }, 74 | { 75 | "game_id": "vzqo2JXv5a", 76 | "date_time_utc": "2020-11-08 23:30:00 UTC", 77 | "home_score": 0, 78 | "away_score": 2, 79 | "home_team_id": "a2lqR4JMr0", 80 | "away_team_id": "Z2vQ1xlqrA", 81 | "referee_id": "315VrXb59x", 82 | "stadium_id": "e7MzlRjqr0", 83 | "home_manager_id": "kRQa9zmQKZ", 84 | "away_manager_id": "N6MmpyLQEG", 85 | "expanded_minutes": 95, 86 | "season_name": "2020", 87 | "matchday": 24, 88 | "attendance": 2770, 89 | "knockout_game": false, 90 | "last_updated_utc": "2020-11-12 11:21:31 UTC" 91 | }, 92 | { 93 | "game_id": "wvq9GXVlMW", 94 | "date_time_utc": "2020-11-08 23:30:00 UTC", 95 | "home_score": 3, 96 | "away_score": 0, 97 | "home_team_id": "lgpMOvnQzy", 98 | "away_team_id": "kaDQ0wRqEv", 99 | "referee_id": "odMX96a5YL", 100 | "stadium_id": "p6qbX06M0G", 101 | "home_manager_id": "0Oq6mxd56D", 102 | "away_manager_id": "4JMA4X9QKg", 103 | "expanded_minutes": 97, 104 | "season_name": "2020", 105 | "matchday": 24, 106 | "attendance": 0, 107 | "knockout_game": false, 108 | "last_updated_utc": "2020-11-12 09:03:46 UTC" 109 | }, 110 | { 111 | "game_id": "0Oq6BLR7q6", 112 | "date_time_utc": "2020-11-08 20:30:00 UTC", 113 | "home_score": 2, 114 | "away_score": 1, 115 | "home_team_id": "a2lqRX2Mr0", 116 | "away_team_id": "kRQabn8MKZ", 117 | "referee_id": "EGMPLlxMaY", 118 | "stadium_id": "NWMW84L5lz", 119 | "home_manager_id": "zeQZVw1QKw", 120 | "away_manager_id": "Xj5Yx60Mbd", 121 | "expanded_minutes": 98, 122 | "season_name": "2020", 123 | "matchday": 24, 124 | "attendance": 0, 125 | "knockout_game": false, 126 | "last_updated_utc": "2020-11-10 11:10:59 UTC" 127 | }, 128 | { 129 | "game_id": "0x5gXW7jq7", 130 | "date_time_utc": "2020-11-08 20:30:00 UTC", 131 | "home_score": 2, 132 | "away_score": 1, 133 | "home_team_id": "zeQZkL1MKw", 134 | "away_team_id": "NWMWlBK5lz", 135 | "referee_id": "wvq9vKlQWn", 136 | "stadium_id": "0x5gJZjM7O", 137 | "home_manager_id": "7VqG6WY5vW", 138 | "away_manager_id": "eV5DWdEMKn", 139 | "expanded_minutes": 97, 140 | "season_name": "2020", 141 | "matchday": 24, 142 | "attendance": 0, 143 | "knockout_game": false, 144 | "last_updated_utc": "2020-11-11 21:01:57 UTC" 145 | }, 146 | { 147 | "game_id": "eVq3JyOg5W", 148 | "date_time_utc": "2020-11-08 20:30:00 UTC", 149 | "home_score": 2, 150 | "away_score": 3, 151 | "home_team_id": "EKXMeX3Q64", 152 | "away_team_id": "APk5LGOMOW", 153 | "referee_id": "ljqExYw5x0", 154 | "stadium_id": "xW5pwORMg1", 155 | "home_manager_id": "p6qbk3BQ0G", 156 | "away_manager_id": "vzqokNkqap", 157 | "expanded_minutes": 108, 158 | "season_name": "2020", 159 | "matchday": 24, 160 | "attendance": 0, 161 | "knockout_game": false, 162 | "last_updated_utc": "2020-11-11 21:18:42 UTC" 163 | }, 164 | { 165 | "game_id": "gOMnXYexqw", 166 | "date_time_utc": "2020-11-08 20:30:00 UTC", 167 | "home_score": 2, 168 | "away_score": 0, 169 | "home_team_id": "9z5k7Yg5A3", 170 | "away_team_id": "19vQ2095K6", 171 | "referee_id": "Pk5LRpDQOW", 172 | "stadium_id": "NWMW8ZN5lz", 173 | "home_manager_id": "0Oq6vPrq6D", 174 | "away_manager_id": "LeVq3j5WOJ", 175 | "expanded_minutes": 101, 176 | "season_name": "2020", 177 | "matchday": 24, 178 | "attendance": 2775, 179 | "knockout_game": false, 180 | "last_updated_utc": "2020-11-11 22:21:41 UTC" 181 | }, 182 | { 183 | "game_id": "gpMOBeZRQz", 184 | "date_time_utc": "2020-11-08 20:30:00 UTC", 185 | "home_score": 2, 186 | "away_score": 3, 187 | "home_team_id": "jYQJ8EW5GR", 188 | "away_team_id": "vzqoOgNqap", 189 | "referee_id": "gOMnB7AMwN", 190 | "stadium_id": "vzqoJrj5ap", 191 | "home_manager_id": "gjMNk8v5Kp", 192 | "away_manager_id": "gOMnDkAqwN", 193 | "expanded_minutes": 99, 194 | "season_name": "2020", 195 | "matchday": 24, 196 | "attendance": 0, 197 | "knockout_game": false, 198 | "last_updated_utc": "2020-11-11 21:08:57 UTC" 199 | }, 200 | { 201 | "game_id": "jYQJlgjE5G", 202 | "date_time_utc": "2020-11-08 20:30:00 UTC", 203 | "home_score": 3, 204 | "away_score": 4, 205 | "home_team_id": "X0Oq66zq6D", 206 | "away_team_id": "Vj58weDM8n", 207 | "referee_id": "zeQZlGK5Kw", 208 | "stadium_id": "gpMOzdEQzy", 209 | "home_manager_id": "9Yqd8woqvJ", 210 | "away_manager_id": "2lqRa4D5r0", 211 | "expanded_minutes": 97, 212 | "season_name": "2020", 213 | "matchday": 24, 214 | "attendance": 0, 215 | "knockout_game": false, 216 | "last_updated_utc": "2020-11-11 20:17:22 UTC" 217 | }, 218 | { 219 | "game_id": "Oa5wXd4Xq1", 220 | "date_time_utc": "2020-11-08 20:30:00 UTC", 221 | "home_score": 2, 222 | "away_score": 1, 223 | "home_team_id": "mvzqoLZQap", 224 | "away_team_id": "KAqBN0Vqbg", 225 | "referee_id": "e7MzPKXqr0", 226 | "stadium_id": "p6qbeb850G", 227 | "home_manager_id": "NPqxkDY59d", 228 | "away_manager_id": "0x5ggrR57O", 229 | "expanded_minutes": 100, 230 | "season_name": "2020", 231 | "matchday": 24, 232 | "attendance": 1500, 233 | "knockout_game": false, 234 | "last_updated_utc": "2020-11-11 20:35:21 UTC" 235 | }, 236 | { 237 | "game_id": "KPqjAbaP56", 238 | "date_time_utc": "2020-11-05 04:00:00 UTC", 239 | "home_score": 1, 240 | "away_score": 1, 241 | "home_team_id": "kaDQ0wRqEv", 242 | "away_team_id": "jYQJ19EqGR", 243 | "referee_id": "zeQZl7D5Kw", 244 | "stadium_id": "wvq9p1Y5Wn", 245 | "home_manager_id": "4JMA4X9QKg", 246 | "away_manager_id": "odMXxreMYL", 247 | "expanded_minutes": 97, 248 | "season_name": "2020", 249 | "matchday": 23, 250 | "attendance": 0, 251 | "knockout_game": false, 252 | "last_updated_utc": "2020-11-08 03:58:32 UTC" 253 | }, 254 | { 255 | "game_id": "Oa5wX06Aq1", 256 | "date_time_utc": "2020-11-05 04:00:00 UTC", 257 | "home_score": 3, 258 | "away_score": 2, 259 | "home_team_id": "0KPqjA456v", 260 | "away_team_id": "eVq3ya6MWO", 261 | "referee_id": "kRQa9k8QKZ", 262 | "stadium_id": "Vj58W84M8n", 263 | "home_manager_id": "2vQ10jwqrA", 264 | "away_manager_id": "0Oq6zkzq6D", 265 | "expanded_minutes": 98, 266 | "season_name": "2020", 267 | "matchday": 23, 268 | "attendance": 0, 269 | "knockout_game": false, 270 | "last_updated_utc": "2020-11-08 04:04:18 UTC" 271 | }, 272 | { 273 | "game_id": "7VqGD3pYQv", 274 | "date_time_utc": "2020-11-05 03:00:00 UTC", 275 | "home_score": 0, 276 | "away_score": 1, 277 | "home_team_id": "WBLMvYAQxe", 278 | "away_team_id": "pzeQZ6xQKw", 279 | "referee_id": "odMX96a5YL", 280 | "stadium_id": "p6qbX06M0G", 281 | "home_manager_id": "gpMOYv1qzy", 282 | "away_manager_id": "0Oq6VPgq6D", 283 | "expanded_minutes": 99, 284 | "season_name": "2020", 285 | "matchday": 16, 286 | "attendance": 0, 287 | "knockout_game": false, 288 | "last_updated_utc": "2020-11-08 03:38:12 UTC" 289 | }, 290 | { 291 | "game_id": "Oa5wX9pDq1", 292 | "date_time_utc": "2020-11-05 01:30:00 UTC", 293 | "home_score": 0, 294 | "away_score": 1, 295 | "home_team_id": "vzqoOgNqap", 296 | "away_team_id": "mKAqBBmqbg", 297 | "referee_id": "0Oq6vG2q6D", 298 | "stadium_id": "KXMe8pxQ64", 299 | "home_manager_id": "gOMnDkAqwN", 300 | "away_manager_id": "eV5DNVJQKn", 301 | "expanded_minutes": 98, 302 | "season_name": "2020", 303 | "matchday": 7, 304 | "attendance": 3789, 305 | "knockout_game": false, 306 | "last_updated_utc": "2020-11-08 03:50:38 UTC" 307 | }, 308 | { 309 | "game_id": "p6qbrgv3q0", 310 | "date_time_utc": "2020-11-05 01:00:00 UTC", 311 | "home_score": 2, 312 | "away_score": 2, 313 | "home_team_id": "kRQand1MKZ", 314 | "away_team_id": "X0Oq66zq6D", 315 | "referee_id": "2lqRymD5r0", 316 | "stadium_id": "odMXGRrQYL", 317 | "home_manager_id": "OlMlYvy5Lz", 318 | "away_manager_id": "9Yqd8woqvJ", 319 | "expanded_minutes": 101, 320 | "season_name": "2020", 321 | "matchday": 18, 322 | "attendance": 0, 323 | "knockout_game": false, 324 | "last_updated_utc": "2020-11-08 03:46:28 UTC" 325 | }, 326 | { 327 | "game_id": "OlMlaB0R5L", 328 | "date_time_utc": "2020-11-05 00:30:00 UTC", 329 | "home_score": 2, 330 | "away_score": 1, 331 | "home_team_id": "jYQJ8EW5GR", 332 | "away_team_id": "mvzqoLZQap", 333 | "referee_id": "4wM4voBqjB", 334 | "stadium_id": "vzqoJrj5ap", 335 | "home_manager_id": "gjMNk8v5Kp", 336 | "away_manager_id": "NPqxkDY59d", 337 | "expanded_minutes": 103, 338 | "season_name": "2020", 339 | "matchday": 17, 340 | "attendance": 0, 341 | "knockout_game": false, 342 | "last_updated_utc": "2020-11-06 13:42:31 UTC" 343 | }, 344 | { 345 | "game_id": "N6MmXWdwQE", 346 | "date_time_utc": "2020-11-02 03:30:00 UTC", 347 | "home_score": 2, 348 | "away_score": 1, 349 | "home_team_id": "kaDQ0wRqEv", 350 | "away_team_id": "a2lqR4JMr0", 351 | "referee_id": "4JMAYlPMKg", 352 | "stadium_id": "wvq9p1Y5Wn", 353 | "home_manager_id": "4JMA4X9QKg", 354 | "away_manager_id": "kRQa9zmQKZ", 355 | "expanded_minutes": 94, 356 | "season_name": "2020", 357 | "matchday": 23, 358 | "attendance": 0, 359 | "knockout_game": false, 360 | "last_updated_utc": "2020-11-05 07:22:42 UTC" 361 | }, 362 | { 363 | "game_id": "e7MzXZKPqr", 364 | "date_time_utc": "2020-11-02 03:00:00 UTC", 365 | "home_score": 1, 366 | "away_score": 0, 367 | "home_team_id": "WBLMvYAQxe", 368 | "away_team_id": "lgpMOvnQzy", 369 | "referee_id": "gjMNk4v5Kp", 370 | "stadium_id": "p6qbX06M0G", 371 | "home_manager_id": "gpMOYv1qzy", 372 | "away_manager_id": "0Oq6mxd56D", 373 | "expanded_minutes": 101, 374 | "season_name": "2020", 375 | "matchday": 23, 376 | "attendance": 0, 377 | "knockout_game": false, 378 | "last_updated_utc": "2020-11-05 09:46:07 UTC" 379 | }, 380 | { 381 | "game_id": "ljqEyJeYqx", 382 | "date_time_utc": "2020-11-02 02:00:00 UTC", 383 | "home_score": 3, 384 | "away_score": 1, 385 | "home_team_id": "pzeQZ6xQKw", 386 | "away_team_id": "jYQJ19EqGR", 387 | "referee_id": "a35rgjLqL6", 388 | "stadium_id": "9z5ka6gQA3", 389 | "home_manager_id": "0Oq6VPgq6D", 390 | "away_manager_id": "odMXxreMYL", 391 | "expanded_minutes": 98, 392 | "season_name": "2020", 393 | "matchday": 23, 394 | "attendance": 0, 395 | "knockout_game": false, 396 | "last_updated_utc": "2020-11-05 06:51:27 UTC" 397 | }, 398 | { 399 | "game_id": "4JMAVkrP5K", 400 | "date_time_utc": "2020-11-02 00:30:00 UTC", 401 | "home_score": 0, 402 | "away_score": 1, 403 | "home_team_id": "APk5LGOMOW", 404 | "away_team_id": "jYQJ8EW5GR", 405 | "referee_id": "KAqB3m7Qbg", 406 | "stadium_id": "NWMW84L5lz", 407 | "home_manager_id": "vzqokNkqap", 408 | "away_manager_id": "gjMNk8v5Kp", 409 | "expanded_minutes": 97, 410 | "season_name": "2020", 411 | "matchday": 23, 412 | "attendance": 0, 413 | "knockout_game": false, 414 | "last_updated_utc": "2020-11-05 16:19:57 UTC" 415 | }, 416 | { 417 | "game_id": "BLMvX6A8qx", 418 | "date_time_utc": "2020-11-02 00:30:00 UTC", 419 | "home_score": 4, 420 | "away_score": 3, 421 | "home_team_id": "19vQ2095K6", 422 | "away_team_id": "EKXMeX3Q64", 423 | "referee_id": "gOMnB7AMwN", 424 | "stadium_id": "wvq9p775Wn", 425 | "home_manager_id": "LeVq3j5WOJ", 426 | "away_manager_id": "p6qbk3BQ0G", 427 | "expanded_minutes": 97, 428 | "season_name": "2020", 429 | "matchday": 23, 430 | "attendance": 0, 431 | "knockout_game": false, 432 | "last_updated_utc": "2020-11-05 06:17:12 UTC" 433 | }, 434 | { 435 | "game_id": "p6qbrgVaq0", 436 | "date_time_utc": "2020-11-02 00:30:00 UTC", 437 | "home_score": 2, 438 | "away_score": 1, 439 | "home_team_id": "kRQabn8MKZ", 440 | "away_team_id": "zeQZkL1MKw", 441 | "referee_id": "9vQ2mPaqK6", 442 | "stadium_id": "BLMvlGBqxe", 443 | "home_manager_id": "Xj5Yx60Mbd", 444 | "away_manager_id": "7VqG6WY5vW", 445 | "expanded_minutes": 97, 446 | "season_name": "2020", 447 | "matchday": 23, 448 | "attendance": 1394, 449 | "knockout_game": false, 450 | "last_updated_utc": "2020-11-05 06:54:42 UTC" 451 | }, 452 | { 453 | "game_id": "4wM4wEnBQj", 454 | "date_time_utc": "2020-11-02 00:00:00 UTC", 455 | "home_score": 5, 456 | "away_score": 2, 457 | "home_team_id": "Vj58weDM8n", 458 | "away_team_id": "a2lqRX2Mr0", 459 | "referee_id": "odMX96a5YL", 460 | "stadium_id": "eVq32yn5WO", 461 | "home_manager_id": "2lqRa4D5r0", 462 | "away_manager_id": "zeQZVw1QKw", 463 | "expanded_minutes": 96, 464 | "season_name": "2020", 465 | "matchday": 23, 466 | "attendance": 0, 467 | "knockout_game": false, 468 | "last_updated_utc": "2020-11-05 05:17:47 UTC" 469 | }, 470 | { 471 | "game_id": "kRQa1WkOQK", 472 | "date_time_utc": "2020-11-02 00:00:00 UTC", 473 | "home_score": 2, 474 | "away_score": 0, 475 | "home_team_id": "KAqBN0Vqbg", 476 | "away_team_id": "NWMWlBK5lz", 477 | "referee_id": "0Oq6037M6D", 478 | "stadium_id": "NWMWoaeMlz", 479 | "home_manager_id": "0x5ggrR57O", 480 | "away_manager_id": "eV5DWdEMKn", 481 | "expanded_minutes": 98, 482 | "season_name": "2020", 483 | "matchday": 23, 484 | "attendance": 6149, 485 | "knockout_game": false, 486 | "last_updated_utc": "2020-11-05 05:01:03 UTC" 487 | }, 488 | { 489 | "game_id": "zeQZVeGNQK", 490 | "date_time_utc": "2020-11-01 20:30:00 UTC", 491 | "home_score": 2, 492 | "away_score": 1, 493 | "home_team_id": "mvzqoLZQap", 494 | "away_team_id": "9z5k7Yg5A3", 495 | "referee_id": "vzqoWjkqap", 496 | "stadium_id": "p6qbeb850G", 497 | "home_manager_id": "NPqxkDY59d", 498 | "away_manager_id": "0Oq6vPrq6D", 499 | "expanded_minutes": 96, 500 | "season_name": "2020", 501 | "matchday": 23, 502 | "attendance": 1500, 503 | "knockout_game": false, 504 | "last_updated_utc": "2020-11-04 10:04:47 UTC" 505 | }, 506 | { 507 | "game_id": "xW5pXw205g", 508 | "date_time_utc": "2020-11-01 00:30:00 UTC", 509 | "home_score": 1, 510 | "away_score": 1, 511 | "home_team_id": "vzqoOgNqap", 512 | "away_team_id": "X0Oq66zq6D", 513 | "referee_id": "ljqEymNqx0", 514 | "stadium_id": "KXMe8pxQ64", 515 | "home_manager_id": "gOMnDkAqwN", 516 | "away_manager_id": "9Yqd8woqvJ", 517 | "expanded_minutes": 97, 518 | "season_name": "2020", 519 | "matchday": 23, 520 | "attendance": 3987, 521 | "knockout_game": false, 522 | "last_updated_utc": "2020-11-04 05:54:21 UTC" 523 | }, 524 | { 525 | "game_id": "KPqjAwrN56", 526 | "date_time_utc": "2020-10-31 19:30:00 UTC", 527 | "home_score": 3, 528 | "away_score": 0, 529 | "home_team_id": "mKAqBBmqbg", 530 | "away_team_id": "YgOMngl5wN", 531 | "referee_id": "9z5kJ7gMA3", 532 | "stadium_id": "eVq3alGMWO", 533 | "home_manager_id": "eV5DNVJQKn", 534 | "away_manager_id": "4wM4AAk5jB", 535 | "expanded_minutes": 99, 536 | "season_name": "2020", 537 | "matchday": 23, 538 | "attendance": 4028, 539 | "knockout_game": false, 540 | "last_updated_utc": "2020-11-03 08:39:00 UTC" 541 | }, 542 | { 543 | "game_id": "aDQ0rlgE5E", 544 | "date_time_utc": "2020-10-29 02:30:00 UTC", 545 | "home_score": 2, 546 | "away_score": 0, 547 | "home_team_id": "0KPqjA456v", 548 | "away_team_id": "a2lqR4JMr0", 549 | "referee_id": "9vQ28gY5K6", 550 | "stadium_id": "Vj58W84M8n", 551 | "home_manager_id": "2vQ10jwqrA", 552 | "away_manager_id": "kRQa9zmQKZ", 553 | "expanded_minutes": 98, 554 | "season_name": "2020", 555 | "matchday": 21, 556 | "attendance": 0, 557 | "knockout_game": false, 558 | "last_updated_utc": "2020-10-29 18:35:02 UTC" 559 | }, 560 | { 561 | "game_id": "NPqxXAZYq9", 562 | "date_time_utc": "2020-10-29 02:30:00 UTC", 563 | "home_score": 2, 564 | "away_score": 1, 565 | "home_team_id": "eVq3ya6MWO", 566 | "away_team_id": "YgOMngl5wN", 567 | "referee_id": "4wM4voBqjB", 568 | "stadium_id": "7vQ7xbOMD1", 569 | "home_manager_id": "0Oq6zkzq6D", 570 | "away_manager_id": "4wM4AAk5jB", 571 | "expanded_minutes": 100, 572 | "season_name": "2020", 573 | "matchday": 21, 574 | "attendance": 0, 575 | "knockout_game": false, 576 | "last_updated_utc": "2020-10-30 13:52:10 UTC" 577 | }, 578 | { 579 | "game_id": "9vQ2846e5K", 580 | "date_time_utc": "2020-10-29 02:00:00 UTC", 581 | "home_score": 5, 582 | "away_score": 2, 583 | "home_team_id": "WBLMvYAQxe", 584 | "away_team_id": "kaDQ0wRqEv", 585 | "referee_id": "Pk5LRpDQOW", 586 | "stadium_id": "p6qbX06M0G", 587 | "home_manager_id": "gpMOYv1qzy", 588 | "expanded_minutes": 95, 589 | "season_name": "2020", 590 | "matchday": 21, 591 | "attendance": 0, 592 | "knockout_game": false, 593 | "last_updated_utc": "2020-10-30 13:54:52 UTC" 594 | }, 595 | { 596 | "game_id": "odMX9EYG5Y", 597 | "date_time_utc": "2020-10-29 00:30:00 UTC", 598 | "home_score": 2, 599 | "away_score": 1, 600 | "home_team_id": "mKAqBBmqbg", 601 | "away_team_id": "zeQZkL1MKw", 602 | "referee_id": "2lqRymD5r0", 603 | "stadium_id": "eVq3alGMWO", 604 | "home_manager_id": "eV5DNVJQKn", 605 | "away_manager_id": "7VqG6WY5vW", 606 | "expanded_minutes": 99, 607 | "season_name": "2020", 608 | "matchday": 21, 609 | "attendance": 3233, 610 | "knockout_game": false, 611 | "last_updated_utc": "2020-10-30 14:59:35 UTC" 612 | }, 613 | { 614 | "game_id": "eV5DNkdmQK", 615 | "date_time_utc": "2020-10-29 00:00:00 UTC", 616 | "home_score": 1, 617 | "away_score": 0, 618 | "home_team_id": "EKXMeX3Q64", 619 | "away_team_id": "mvzqoLZQap", 620 | "referee_id": "zeQZl7D5Kw", 621 | "stadium_id": "xW5pwORMg1", 622 | "home_manager_id": "p6qbk3BQ0G", 623 | "away_manager_id": "NPqxkDY59d", 624 | "expanded_minutes": 99, 625 | "season_name": "2020", 626 | "matchday": 21, 627 | "attendance": 0, 628 | "knockout_game": false, 629 | "last_updated_utc": "2020-10-30 13:58:05 UTC" 630 | }, 631 | { 632 | "game_id": "KXMeY3N3M6", 633 | "date_time_utc": "2020-10-29 00:00:00 UTC", 634 | "home_score": 2, 635 | "away_score": 1, 636 | "home_team_id": "kRQand1MKZ", 637 | "away_team_id": "pzeQZ6xQKw", 638 | "referee_id": "2lqRokLQr0", 639 | "stadium_id": "odMXGRrQYL", 640 | "home_manager_id": "OlMlYvy5Lz", 641 | "away_manager_id": "0Oq6VPgq6D", 642 | "expanded_minutes": 100, 643 | "season_name": "2020", 644 | "matchday": 21, 645 | "attendance": 0, 646 | "knockout_game": false, 647 | "last_updated_utc": "2020-11-26 11:23:29 UTC" 648 | }, 649 | { 650 | "game_id": "a35rXB0KQL", 651 | "date_time_utc": "2020-10-28 23:30:00 UTC", 652 | "home_score": 0, 653 | "away_score": 1, 654 | "home_team_id": "NWMWlBK5lz", 655 | "away_team_id": "Z2vQ1xlqrA", 656 | "referee_id": "gOMnB7AMwN", 657 | "stadium_id": "KAqBkLJQbg", 658 | "home_manager_id": "eV5DWdEMKn", 659 | "away_manager_id": "N6MmpyLQEG", 660 | "expanded_minutes": 96, 661 | "season_name": "2020", 662 | "matchday": 21, 663 | "attendance": 0, 664 | "knockout_game": false, 665 | "last_updated_utc": "2020-10-30 14:39:20 UTC" 666 | }, 667 | { 668 | "game_id": "jYQJlYyB5G", 669 | "date_time_utc": "2020-10-28 23:30:00 UTC", 670 | "home_score": 0, 671 | "away_score": 1, 672 | "home_team_id": "kRQabn8MKZ", 673 | "away_team_id": "Vj58weDM8n", 674 | "referee_id": "7VqG6KX5vW", 675 | "stadium_id": "BLMvlGBqxe", 676 | "home_manager_id": "Xj5Yx60Mbd", 677 | "away_manager_id": "2lqRa4D5r0", 678 | "expanded_minutes": 97, 679 | "season_name": "2020", 680 | "matchday": 22, 681 | "attendance": 0, 682 | "knockout_game": false, 683 | "last_updated_utc": "2020-10-30 17:06:14 UTC" 684 | }, 685 | { 686 | "game_id": "OlMlaB8A5L", 687 | "date_time_utc": "2020-10-28 23:30:00 UTC", 688 | "home_score": 4, 689 | "away_score": 1, 690 | "home_team_id": "jYQJ8EW5GR", 691 | "away_team_id": "KAqBN0Vqbg", 692 | "referee_id": "KPqjDeNM6v", 693 | "stadium_id": "vzqoJrj5ap", 694 | "home_manager_id": "gjMNk8v5Kp", 695 | "away_manager_id": "0x5ggrR57O", 696 | "expanded_minutes": 98, 697 | "season_name": "2020", 698 | "matchday": 21, 699 | "attendance": 0, 700 | "knockout_game": false, 701 | "last_updated_utc": "2020-10-30 17:23:30 UTC" 702 | }, 703 | { 704 | "game_id": "Vj58glkwM8", 705 | "date_time_utc": "2020-10-28 23:30:00 UTC", 706 | "home_score": 2, 707 | "away_score": 1, 708 | "home_team_id": "9z5k7Yg5A3", 709 | "away_team_id": "X0Oq66zq6D", 710 | "referee_id": "wvq9vKlQWn", 711 | "stadium_id": "NWMW8ZN5lz", 712 | "home_manager_id": "0Oq6vPrq6D", 713 | "away_manager_id": "9Yqd8woqvJ", 714 | "expanded_minutes": 103, 715 | "season_name": "2020", 716 | "matchday": 21, 717 | "attendance": 0, 718 | "knockout_game": false, 719 | "last_updated_utc": "2020-10-31 00:51:53 UTC" 720 | }, 721 | { 722 | "game_id": "2vQ1ldGLqr", 723 | "date_time_utc": "2020-10-28 23:00:00 UTC", 724 | "home_score": 1, 725 | "away_score": 0, 726 | "home_team_id": "a2lqRX2Mr0", 727 | "away_team_id": "19vQ2095K6", 728 | "referee_id": "0Oq6037M6D", 729 | "stadium_id": "NWMW84L5lz", 730 | "home_manager_id": "9z5kKNb5A3", 731 | "away_manager_id": "LeVq3j5WOJ", 732 | "expanded_minutes": 98, 733 | "season_name": "2020", 734 | "matchday": 21, 735 | "attendance": 0, 736 | "knockout_game": false, 737 | "last_updated_utc": "2020-10-30 03:51:27 UTC" 738 | }, 739 | { 740 | "game_id": "7vQ7WxA8QD", 741 | "date_time_utc": "2020-10-28 02:00:00 UTC", 742 | "home_score": 0, 743 | "away_score": 2, 744 | "home_team_id": "lgpMOvnQzy", 745 | "away_team_id": "jYQJ19EqGR", 746 | "referee_id": "zeQZlGK5Kw", 747 | "stadium_id": "p6qbX06M0G", 748 | "home_manager_id": "0Oq6mxd56D", 749 | "away_manager_id": "odMXxreMYL", 750 | "expanded_minutes": 99, 751 | "season_name": "2020", 752 | "matchday": 21, 753 | "attendance": 0, 754 | "knockout_game": false, 755 | "last_updated_utc": "2020-10-28 20:07:42 UTC" 756 | } 757 | ] -------------------------------------------------------------------------------- /tests/mocks/players_payload.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "player_id": "0Oq6006M6D", 4 | "player_name": "Ugo Ihemelu", 5 | "birth_date": "1983-04-03", 6 | "height_ft": 6, 7 | "height_in": 0, 8 | "weight_lb": 179, 9 | "nationality": "USA", 10 | "season_name": {} 11 | }, 12 | { 13 | "player_id": "0Oq60APM6D", 14 | "player_name": "Jason Hernandez", 15 | "birth_date": "1983-08-26", 16 | "height_ft": 5, 17 | "height_in": 11, 18 | "weight_lb": 172, 19 | "nationality": "USA", 20 | "primary_broad_position": "DF", 21 | "primary_general_position": "CB", 22 | "season_name": [ 23 | "2013", 24 | "2014", 25 | "2015", 26 | "2016", 27 | "2017", 28 | "2018" 29 | ] 30 | }, 31 | { 32 | "player_id": "0Oq60VgM6D", 33 | "player_name": "Jeff Larentowicz", 34 | "birth_date": "1983-08-05", 35 | "height_ft": 6, 36 | "height_in": 1, 37 | "weight_lb": 176, 38 | "nationality": "USA", 39 | "primary_broad_position": "MF", 40 | "primary_general_position": "DM", 41 | "secondary_general_position": "CM", 42 | "season_name": [ 43 | "2013", 44 | "2014", 45 | "2015", 46 | "2016", 47 | "2017", 48 | "2018", 49 | "2019", 50 | "2020" 51 | ] 52 | }, 53 | { 54 | "player_id": "0Oq630dXQ6", 55 | "player_name": "Kevin Cabral", 56 | "birth_date": "1999-07-10", 57 | "nationality": "France", 58 | "primary_broad_position": "MF", 59 | "primary_general_position": "W", 60 | "season_name": [ 61 | "2021", 62 | "2022" 63 | ] 64 | }, 65 | { 66 | "player_id": "0Oq632k7Q6", 67 | "player_name": "Danny Leyva", 68 | "birth_date": "2003-05-05", 69 | "height_ft": 5, 70 | "height_in": 10, 71 | "weight_lb": 139, 72 | "nationality": "USA", 73 | "primary_broad_position": "MF", 74 | "primary_general_position": "DM", 75 | "secondary_general_position": "CM", 76 | "season_name": [ 77 | "2019", 78 | "2020", 79 | "2021", 80 | "2022" 81 | ] 82 | }, 83 | { 84 | "player_id": "0Oq633dAQ6", 85 | "player_name": "Griffin Yow", 86 | "birth_date": "2002-09-25", 87 | "height_ft": 5, 88 | "height_in": 8, 89 | "weight_lb": 141, 90 | "nationality": "USA", 91 | "primary_broad_position": "MF", 92 | "primary_general_position": "W", 93 | "season_name": [ 94 | "2019", 95 | "2020", 96 | "2021", 97 | "2022" 98 | ] 99 | }, 100 | { 101 | "player_id": "0Oq638a6Q6", 102 | "player_name": "Dominick Hernandez", 103 | "birth_date": "1998-09-21", 104 | "nationality": "USA", 105 | "season_name": {} 106 | }, 107 | { 108 | "player_id": "0Oq63JA7Q6", 109 | "player_name": "Wyatt Omsberg", 110 | "birth_date": "1995-09-21", 111 | "height_ft": 6, 112 | "height_in": 4, 113 | "weight_lb": 181, 114 | "nationality": "USA", 115 | "primary_broad_position": "DF", 116 | "primary_general_position": "CB", 117 | "season_name": [ 118 | "2018", 119 | "2020", 120 | "2021", 121 | "2022" 122 | ] 123 | }, 124 | { 125 | "player_id": "0Oq63n7Q6D", 126 | "player_name": "Eric Hassli", 127 | "birth_date": "1981-05-03", 128 | "height_ft": 6, 129 | "height_in": 4, 130 | "weight_lb": 201, 131 | "nationality": "France", 132 | "primary_broad_position": "FW", 133 | "primary_general_position": "ST", 134 | "season_name": "2013" 135 | }, 136 | { 137 | "player_id": "0Oq63oxzQ6", 138 | "player_name": "Aiden McFadden", 139 | "birth_date": "1998-09-28", 140 | "height_ft": 5, 141 | "height_in": 9, 142 | "weight_lb": 165, 143 | "nationality": "USA", 144 | "primary_broad_position": "FW", 145 | "primary_general_position": "W", 146 | "season_name": "2022" 147 | }, 148 | { 149 | "player_id": "0Oq63P32Q6", 150 | "player_name": "Nkosi Burgess", 151 | "birth_date": "1997-03-23", 152 | "height_ft": 6, 153 | "height_in": 4, 154 | "weight_lb": 185, 155 | "nationality": "USA", 156 | "primary_broad_position": "DF", 157 | "primary_general_position": "CB", 158 | "season_name": [ 159 | "2021", 160 | "2022" 161 | ] 162 | }, 163 | { 164 | "player_id": "0Oq63pJdQ6", 165 | "player_name": "Steeven Saba", 166 | "birth_date": "1993-02-24", 167 | "height_ft": 5, 168 | "height_in": 7, 169 | "nationality": "Haiti", 170 | "season_name": {} 171 | }, 172 | { 173 | "player_id": "0Oq63v4rQ6", 174 | "player_name": "Casey Walls", 175 | "birth_date": "2003-01-10", 176 | "height_ft": 6, 177 | "height_in": 2, 178 | "weight_lb": 172, 179 | "nationality": "USA", 180 | "season_name": {} 181 | }, 182 | { 183 | "player_id": "0Oq63Ym2Q6", 184 | "player_name": "Ryan Spaulding", 185 | "birth_date": "1998-09-10", 186 | "height_ft": 5, 187 | "height_in": 8, 188 | "weight_lb": 165, 189 | "nationality": "USA", 190 | "primary_broad_position": "DF", 191 | "primary_general_position": "FB", 192 | "season_name": "2022" 193 | }, 194 | { 195 | "player_id": "0Oq67EgQ6D", 196 | "player_name": "Matt Besler", 197 | "birth_date": "1987-02-11", 198 | "height_ft": 6, 199 | "height_in": 0, 200 | "weight_lb": 172, 201 | "nationality": "USA", 202 | "primary_broad_position": "DF", 203 | "primary_general_position": "CB", 204 | "season_name": [ 205 | "2013", 206 | "2014", 207 | "2015", 208 | "2016", 209 | "2017", 210 | "2018", 211 | "2019", 212 | "2020", 213 | "2021" 214 | ] 215 | }, 216 | { 217 | "player_id": "0Oq67k7Q6D", 218 | "player_name": "Tristan Bowen", 219 | "birth_date": "1991-01-31", 220 | "height_ft": 5, 221 | "height_in": 11, 222 | "weight_lb": 172, 223 | "nationality": "USA", 224 | "primary_broad_position": "FW", 225 | "primary_general_position": "ST", 226 | "secondary_broad_position": "MF", 227 | "secondary_general_position": "W", 228 | "season_name": [ 229 | "2013", 230 | "2014" 231 | ] 232 | }, 233 | { 234 | "player_id": "0Oq67xxQ6D", 235 | "player_name": "Brandon Barklage", 236 | "birth_date": "1986-11-02", 237 | "height_ft": 5, 238 | "height_in": 11, 239 | "weight_lb": 165, 240 | "nationality": "USA", 241 | "primary_broad_position": "DF", 242 | "primary_general_position": "FB", 243 | "season_name": [ 244 | "2013", 245 | "2014" 246 | ] 247 | }, 248 | { 249 | "player_id": "0Oq6aoX56D", 250 | "player_name": "Cedrick", 251 | "birth_date": "1992-03-08", 252 | "height_ft": 5, 253 | "height_in": 6, 254 | "weight_lb": 137, 255 | "nationality": "DR Congo", 256 | "primary_broad_position": "MF", 257 | "primary_general_position": "W", 258 | "season_name": [ 259 | "2015", 260 | "2016" 261 | ] 262 | }, 263 | { 264 | "player_id": "0Oq6bAPq6D", 265 | "player_name": "Douglas Costa", 266 | "birth_date": "1990-09-14", 267 | "height_ft": 5, 268 | "height_in": 8, 269 | "weight_lb": 154, 270 | "nationality": "Brazil", 271 | "primary_broad_position": "MF", 272 | "primary_general_position": "W", 273 | "season_name": "2022" 274 | }, 275 | { 276 | "player_id": "0Oq6BKAq6D", 277 | "player_name": "Caleb Patterson-Sewell", 278 | "birth_date": "1987-05-20", 279 | "height_ft": 6, 280 | "height_in": 3, 281 | "weight_lb": 183, 282 | "nationality": "USA", 283 | "season_name": {} 284 | }, 285 | { 286 | "player_id": "0Oq6ebd56D", 287 | "player_name": "Marco Pappa", 288 | "birth_date": "1987-11-15", 289 | "height_ft": 5, 290 | "height_in": 10, 291 | "weight_lb": 157, 292 | "nationality": "Guatemala", 293 | "primary_broad_position": "MF", 294 | "primary_general_position": "W", 295 | "season_name": [ 296 | "2014", 297 | "2015", 298 | "2016" 299 | ] 300 | }, 301 | { 302 | "player_id": "0Oq6ENn256", 303 | "player_name": "Danny Musovski", 304 | "birth_date": "1995-11-30", 305 | "height_ft": 6, 306 | "height_in": 0, 307 | "weight_lb": 161, 308 | "nationality": "USA", 309 | "primary_broad_position": "FW", 310 | "primary_general_position": "ST", 311 | "season_name": [ 312 | "2020", 313 | "2021", 314 | "2022" 315 | ] 316 | }, 317 | { 318 | "player_id": "0Oq6ERe256", 319 | "player_name": "Patrick Metcalfe", 320 | "birth_date": "1998-11-11", 321 | "height_ft": 5, 322 | "height_in": 8, 323 | "weight_lb": 165, 324 | "nationality": "Canada", 325 | "primary_broad_position": "MF", 326 | "primary_general_position": "CM", 327 | "season_name": [ 328 | "2020", 329 | "2021" 330 | ] 331 | }, 332 | { 333 | "player_id": "0Oq6Ervr56", 334 | "player_name": "Shaft Brewer", 335 | "birth_date": "1999-10-28", 336 | "height_ft": 5, 337 | "height_in": 9, 338 | "weight_lb": 154, 339 | "nationality": "USA", 340 | "primary_broad_position": "DF", 341 | "primary_general_position": "FB", 342 | "season_name": [ 343 | "2018", 344 | "2019" 345 | ] 346 | }, 347 | { 348 | "player_id": "0Oq6l2JzM6", 349 | "player_name": "Armando Cooper", 350 | "birth_date": "1987-11-26", 351 | "height_ft": 5, 352 | "height_in": 9, 353 | "weight_lb": 150, 354 | "nationality": "Panama", 355 | "primary_broad_position": "MF", 356 | "primary_general_position": "CM", 357 | "season_name": [ 358 | "2016", 359 | "2017" 360 | ] 361 | }, 362 | { 363 | "player_id": "0Oq6l8YgM6", 364 | "player_name": "Romain Métanire", 365 | "birth_date": "1990-03-28", 366 | "height_ft": 5, 367 | "height_in": 10, 368 | "weight_lb": 159, 369 | "nationality": "Madagascar", 370 | "primary_broad_position": "DF", 371 | "primary_general_position": "FB", 372 | "season_name": [ 373 | "2019", 374 | "2020", 375 | "2021", 376 | "2022" 377 | ] 378 | }, 379 | { 380 | "player_id": "0Oq6la47M6", 381 | "player_name": "Pecka", 382 | "birth_date": "1989-05-02", 383 | "height_ft": 5, 384 | "height_in": 8, 385 | "weight_lb": 152, 386 | "nationality": "Brazil", 387 | "primary_broad_position": "MF", 388 | "primary_general_position": "DM", 389 | "secondary_general_position": "CM", 390 | "season_name": "2015" 391 | }, 392 | { 393 | "player_id": "0Oq6lagAM6", 394 | "player_name": "Mark Pais", 395 | "birth_date": "1991-06-03", 396 | "height_ft": 6, 397 | "height_in": 4, 398 | "weight_lb": 201, 399 | "nationality": "USA", 400 | "season_name": {} 401 | }, 402 | { 403 | "player_id": "0Oq6lakAM6", 404 | "player_name": "Ben Newnam", 405 | "birth_date": "1991-04-18", 406 | "height_ft": 5, 407 | "height_in": 10, 408 | "weight_lb": 165, 409 | "nationality": "USA", 410 | "primary_broad_position": "DF", 411 | "primary_general_position": "FB", 412 | "season_name": "2015" 413 | }, 414 | { 415 | "player_id": "0Oq6lB9PM6", 416 | "player_name": "Christiano François", 417 | "birth_date": "1993-07-17", 418 | "height_ft": 5, 419 | "height_in": 7, 420 | "weight_lb": 141, 421 | "nationality": "USA", 422 | "season_name": {} 423 | }, 424 | { 425 | "player_id": "0Oq6lBP2M6", 426 | "player_name": "Schillo Tshuma", 427 | "birth_date": "1992-09-21", 428 | "height_ft": 5, 429 | "height_in": 10, 430 | "weight_lb": 161, 431 | "nationality": "Zimbabwe", 432 | "season_name": {} 433 | }, 434 | { 435 | "player_id": "0Oq6lDAgM6", 436 | "player_name": "Deian Boldor", 437 | "birth_date": "1995-02-03", 438 | "height_ft": 6, 439 | "height_in": 2, 440 | "weight_lb": 174, 441 | "nationality": "Romania", 442 | "primary_broad_position": "DF", 443 | "primary_general_position": "CB", 444 | "season_name": "2017" 445 | }, 446 | { 447 | "player_id": "0Oq6lE7xM6", 448 | "player_name": "Bernardo Añor", 449 | "birth_date": "1988-05-24", 450 | "height_ft": 6, 451 | "height_in": 1, 452 | "weight_lb": 179, 453 | "nationality": "Venezuela", 454 | "primary_broad_position": "MF", 455 | "primary_general_position": "W", 456 | "season_name": [ 457 | "2013", 458 | "2014", 459 | "2015" 460 | ] 461 | }, 462 | { 463 | "player_id": "0Oq6lgl6M6", 464 | "player_name": "Nicolai Næss", 465 | "birth_date": "1993-01-18", 466 | "height_ft": 6, 467 | "height_in": 0, 468 | "weight_lb": 181, 469 | "nationality": "Norway", 470 | "primary_broad_position": "DF", 471 | "primary_general_position": "CB", 472 | "season_name": [ 473 | "2016", 474 | "2017" 475 | ] 476 | }, 477 | { 478 | "player_id": "0Oq6lj26M6", 479 | "player_name": "Samuel", 480 | "birth_date": "1991-02-25", 481 | "height_ft": 6, 482 | "height_in": 1, 483 | "weight_lb": 192, 484 | "nationality": "Brazil", 485 | "primary_broad_position": "FW", 486 | "primary_general_position": "ST", 487 | "season_name": "2014" 488 | }, 489 | { 490 | "player_id": "0Oq6lJPzM6", 491 | "player_name": "Joe Corona", 492 | "birth_date": "1990-07-09", 493 | "height_ft": 5, 494 | "height_in": 8, 495 | "weight_lb": 161, 496 | "nationality": "USA", 497 | "primary_broad_position": "MF", 498 | "primary_general_position": "CM", 499 | "secondary_general_position": "DM", 500 | "season_name": [ 501 | "2019", 502 | "2020", 503 | "2021" 504 | ] 505 | }, 506 | { 507 | "player_id": "0Oq6lLZgM6", 508 | "player_name": "Maximiliano Urruti", 509 | "birth_date": "1991-02-22", 510 | "height_ft": 6, 511 | "height_in": 0, 512 | "weight_lb": 165, 513 | "nationality": "Argentina", 514 | "primary_broad_position": "FW", 515 | "primary_general_position": "ST", 516 | "season_name": [ 517 | "2013", 518 | "2014", 519 | "2015", 520 | "2016", 521 | "2017", 522 | "2018", 523 | "2019", 524 | "2020", 525 | "2021", 526 | "2022" 527 | ] 528 | }, 529 | { 530 | "player_id": "0Oq6lm4zM6", 531 | "player_name": "Rodolfo Pizarro", 532 | "birth_date": "1994-02-15", 533 | "height_ft": 5, 534 | "height_in": 10, 535 | "weight_lb": 143, 536 | "nationality": "Mexico", 537 | "primary_broad_position": "MF", 538 | "primary_general_position": "AM", 539 | "season_name": [ 540 | "2020", 541 | "2021" 542 | ] 543 | }, 544 | { 545 | "player_id": "0Oq6ln0zM6", 546 | "player_name": "Emery Welshman", 547 | "birth_date": "1991-11-09", 548 | "height_ft": 5, 549 | "height_in": 11, 550 | "weight_lb": 181, 551 | "nationality": "USA", 552 | "primary_broad_position": "FW", 553 | "primary_general_position": "ST", 554 | "season_name": "2013" 555 | }, 556 | { 557 | "player_id": "0Oq6lnBrM6", 558 | "player_name": "Luis Solignac", 559 | "birth_date": "1991-02-16", 560 | "height_ft": 6, 561 | "height_in": 0, 562 | "weight_lb": 176, 563 | "nationality": "Argentina", 564 | "primary_broad_position": "MF", 565 | "primary_general_position": "W", 566 | "secondary_broad_position": "FW", 567 | "secondary_general_position": "ST", 568 | "season_name": [ 569 | "2015", 570 | "2016", 571 | "2017", 572 | "2018" 573 | ] 574 | }, 575 | { 576 | "player_id": "0Oq6lnlrM6", 577 | "player_name": "José Van Rankin", 578 | "birth_date": "1993-03-14", 579 | "height_ft": 5, 580 | "height_in": 9, 581 | "weight_lb": 152, 582 | "nationality": "Mexico", 583 | "primary_broad_position": "DF", 584 | "primary_general_position": "FB", 585 | "season_name": [ 586 | "2021", 587 | "2022" 588 | ] 589 | }, 590 | { 591 | "player_id": "0Oq6lp3AM6", 592 | "player_name": "Antoine Hoppenot", 593 | "birth_date": "1990-11-23", 594 | "height_ft": 5, 595 | "height_in": 8, 596 | "weight_lb": 157, 597 | "nationality": "USA", 598 | "primary_broad_position": "FW", 599 | "primary_general_position": "ST", 600 | "secondary_broad_position": "MF", 601 | "secondary_general_position": "W", 602 | "season_name": [ 603 | "2013", 604 | "2014", 605 | "2015" 606 | ] 607 | }, 608 | { 609 | "player_id": "0Oq6lp3XM6", 610 | "player_name": "Enzo Martinez", 611 | "birth_date": "1990-09-29", 612 | "height_ft": 5, 613 | "height_in": 7, 614 | "weight_lb": 161, 615 | "nationality": "Uruguay", 616 | "primary_broad_position": "MF", 617 | "primary_general_position": "CM", 618 | "season_name": "2018" 619 | }, 620 | { 621 | "player_id": "0Oq6LpLgM6", 622 | "player_name": "Gino Portella", 623 | "birth_date": "2001-03-19", 624 | "nationality": "Italy", 625 | "season_name": {} 626 | }, 627 | { 628 | "player_id": "0Oq6lrerM6", 629 | "player_name": "Gastón Giménez", 630 | "birth_date": "1991-07-27", 631 | "height_ft": 6, 632 | "height_in": 2, 633 | "weight_lb": 181, 634 | "nationality": "Argentina", 635 | "primary_broad_position": "MF", 636 | "primary_general_position": "DM", 637 | "season_name": [ 638 | "2020", 639 | "2021", 640 | "2022" 641 | ] 642 | }, 643 | { 644 | "player_id": "0Oq6lw6M6D", 645 | "player_name": "Frank Lampard", 646 | "birth_date": "1978-06-20", 647 | "height_ft": 6, 648 | "height_in": 0, 649 | "weight_lb": 196, 650 | "nationality": "England", 651 | "primary_broad_position": "MF", 652 | "primary_general_position": "CM", 653 | "season_name": [ 654 | "2015", 655 | "2016" 656 | ] 657 | }, 658 | { 659 | "player_id": "0Oq6lWB2M6", 660 | "player_name": "Mohammed Saeid", 661 | "birth_date": "1990-12-24", 662 | "height_ft": 5, 663 | "height_in": 7, 664 | "weight_lb": 141, 665 | "nationality": "Sweden", 666 | "primary_broad_position": "MF", 667 | "primary_general_position": "DM", 668 | "season_name": [ 669 | "2015", 670 | "2016", 671 | "2017" 672 | ] 673 | }, 674 | { 675 | "player_id": "0Oq6lYbAM6", 676 | "player_name": "Luiz Camargo", 677 | "birth_date": "1987-05-04", 678 | "height_ft": 5, 679 | "height_in": 8, 680 | "weight_lb": 174, 681 | "nationality": "Brazil", 682 | "primary_broad_position": "MF", 683 | "primary_general_position": "CM", 684 | "season_name": "2013" 685 | }, 686 | { 687 | "player_id": "0Oq6lyNdM6", 688 | "player_name": "Wil Trapp", 689 | "birth_date": "1993-01-15", 690 | "height_ft": 5, 691 | "height_in": 8, 692 | "weight_lb": 152, 693 | "nationality": "USA", 694 | "primary_broad_position": "MF", 695 | "primary_general_position": "DM", 696 | "season_name": [ 697 | "2013", 698 | "2014", 699 | "2015", 700 | "2016", 701 | "2017", 702 | "2018", 703 | "2019", 704 | "2020", 705 | "2021", 706 | "2022" 707 | ] 708 | }, 709 | { 710 | "player_id": "0Oq6lyX7M6", 711 | "player_name": "Amando Moreno", 712 | "birth_date": "1995-09-10", 713 | "height_ft": 5, 714 | "height_in": 7, 715 | "weight_lb": 154, 716 | "nationality": "USA", 717 | "primary_broad_position": "MF", 718 | "primary_general_position": "W", 719 | "secondary_general_position": "DM", 720 | "season_name": [ 721 | "2013", 722 | "2019" 723 | ] 724 | }, 725 | { 726 | "player_id": "0Oq6m0z56D", 727 | "player_name": "Javier Morales", 728 | "birth_date": "1980-01-10", 729 | "height_ft": 5, 730 | "height_in": 9, 731 | "weight_lb": 152, 732 | "nationality": "Argentina", 733 | "primary_broad_position": "MF", 734 | "primary_general_position": "AM", 735 | "season_name": [ 736 | "2013", 737 | "2014", 738 | "2015", 739 | "2016", 740 | "2017" 741 | ] 742 | }, 743 | { 744 | "player_id": "0Oq6O0XQ6D", 745 | "player_name": "Emmanuel Ledesma", 746 | "birth_date": "1988-05-24", 747 | "height_ft": 5, 748 | "height_in": 11, 749 | "weight_lb": 170, 750 | "nationality": "Argentina", 751 | "primary_broad_position": "MF", 752 | "primary_general_position": "W", 753 | "season_name": "2019" 754 | }, 755 | { 756 | "player_id": "0Oq6oePQ6D", 757 | "player_name": "Arévalo Ríos", 758 | "birth_date": "1982-01-01", 759 | "height_ft": 5, 760 | "height_in": 7, 761 | "weight_lb": 150, 762 | "nationality": "Uruguay", 763 | "primary_broad_position": "MF", 764 | "primary_general_position": "CM", 765 | "season_name": "2013" 766 | }, 767 | { 768 | "player_id": "0Oq6w1LrQ6", 769 | "player_name": "Walter Cabrera", 770 | "birth_date": "1990-01-07", 771 | "height_ft": 6, 772 | "height_in": 0, 773 | "weight_lb": 176, 774 | "nationality": "Paraguay", 775 | "season_name": {} 776 | }, 777 | { 778 | "player_id": "0Oq6w947Q6", 779 | "player_name": "Michael Baldisimo", 780 | "birth_date": "2000-04-13", 781 | "height_ft": 5, 782 | "height_in": 6, 783 | "weight_lb": 154, 784 | "nationality": "Canada", 785 | "primary_broad_position": "MF", 786 | "primary_general_position": "DM", 787 | "secondary_general_position": "CM", 788 | "season_name": [ 789 | "2020", 790 | "2021", 791 | "2022" 792 | ] 793 | }, 794 | { 795 | "player_id": "0Oq6w9J2Q6", 796 | "player_name": "Augustine Williams", 797 | "birth_date": "1997-08-03", 798 | "height_ft": 6, 799 | "height_in": 2, 800 | "weight_lb": 165, 801 | "nationality": "Sierra Leone", 802 | "primary_broad_position": "FW", 803 | "primary_general_position": "ST", 804 | "season_name": "2021" 805 | }, 806 | { 807 | "player_id": "0Oq6wB7zQ6", 808 | "player_name": "Brady Scott", 809 | "birth_date": "1999-06-30", 810 | "height_ft": 6, 811 | "height_in": 2, 812 | "weight_lb": 174, 813 | "nationality": "USA", 814 | "season_name": {} 815 | }, 816 | { 817 | "player_id": "0Oq6we8zQ6", 818 | "player_name": "Joshua Drack", 819 | "birth_date": "1999-09-22", 820 | "height_ft": 5, 821 | "height_in": 8, 822 | "weight_lb": 152, 823 | "nationality": "USA", 824 | "primary_broad_position": "MF", 825 | "primary_general_position": "DM", 826 | "season_name": "2021" 827 | }, 828 | { 829 | "player_id": "0Oq6weerQ6", 830 | "player_name": "Andrew Wheeler-Omiunu", 831 | "birth_date": "1994-12-01", 832 | "height_ft": 5, 833 | "height_in": 9, 834 | "weight_lb": 174, 835 | "nationality": "USA", 836 | "primary_broad_position": "MF", 837 | "primary_general_position": "CM", 838 | "season_name": "2018" 839 | }, 840 | { 841 | "player_id": "0Oq6wel7Q6", 842 | "player_name": "Cameron Duke", 843 | "birth_date": "2001-02-13", 844 | "height_ft": 5, 845 | "height_in": 7, 846 | "weight_lb": 135, 847 | "nationality": "USA", 848 | "primary_broad_position": "MF", 849 | "primary_general_position": "CM", 850 | "season_name": [ 851 | "2020", 852 | "2021", 853 | "2022" 854 | ] 855 | }, 856 | { 857 | "player_id": "0Oq6weYXQ6", 858 | "player_name": "Bruno Miranda", 859 | "birth_date": "1998-02-10", 860 | "height_ft": 5, 861 | "height_in": 11, 862 | "weight_lb": 146, 863 | "nationality": "Bolivia", 864 | "primary_broad_position": "MF", 865 | "primary_general_position": "W", 866 | "secondary_general_position": "CM", 867 | "season_name": [ 868 | "2017", 869 | "2018" 870 | ] 871 | }, 872 | { 873 | "player_id": "0Oq6wjLrQ6", 874 | "player_name": "Jake Mulraney", 875 | "birth_date": "1996-04-05", 876 | "height_ft": 5, 877 | "height_in": 8, 878 | "weight_lb": 141, 879 | "nationality": "Republic of Ireland", 880 | "primary_broad_position": "DF", 881 | "primary_general_position": "FB", 882 | "secondary_broad_position": "MF", 883 | "secondary_general_position": "W", 884 | "season_name": [ 885 | "2020", 886 | "2021", 887 | "2022" 888 | ] 889 | }, 890 | { 891 | "player_id": "0Oq6wjlzQ6", 892 | "player_name": "Jack Skahan", 893 | "birth_date": "1998-02-07", 894 | "height_ft": 5, 895 | "height_in": 10, 896 | "weight_lb": 165, 897 | "nationality": "USA", 898 | "primary_broad_position": "MF", 899 | "primary_general_position": "CM", 900 | "season_name": [ 901 | "2020", 902 | "2021" 903 | ] 904 | }, 905 | { 906 | "player_id": "0Oq6wjm2Q6", 907 | "player_name": "Axel Sjöberg", 908 | "birth_date": "1992-09-15", 909 | "height_ft": 6, 910 | "height_in": 7, 911 | "weight_lb": 201, 912 | "nationality": "USA", 913 | "primary_broad_position": "DF", 914 | "primary_general_position": "CB", 915 | "season_name": [ 916 | "2015", 917 | "2016", 918 | "2017", 919 | "2018", 920 | "2019", 921 | "2020" 922 | ] 923 | }, 924 | { 925 | "player_id": "0Oq6wjvPQ6", 926 | "player_name": "James Rogers", 927 | "birth_date": "1993-06-27", 928 | "height_ft": 5, 929 | "height_in": 8, 930 | "weight_lb": 150, 931 | "nationality": "USA", 932 | "season_name": {} 933 | }, 934 | { 935 | "player_id": "0Oq6wjzgQ6", 936 | "player_name": "Abu Danladi", 937 | "birth_date": "1995-10-18", 938 | "height_ft": 5, 939 | "height_in": 10, 940 | "weight_lb": 170, 941 | "nationality": "Ghana", 942 | "primary_broad_position": "FW", 943 | "primary_general_position": "ST", 944 | "secondary_broad_position": "MF", 945 | "secondary_general_position": "W", 946 | "season_name": [ 947 | "2017", 948 | "2018", 949 | "2019", 950 | "2020", 951 | "2021", 952 | "2022" 953 | ] 954 | }, 955 | { 956 | "player_id": "0Oq6wl42Q6", 957 | "player_name": "Darwin Jones", 958 | "birth_date": "1992-04-04", 959 | "height_ft": 5, 960 | "height_in": 9, 961 | "weight_lb": 176, 962 | "nationality": "USA", 963 | "primary_broad_position": "FW", 964 | "primary_general_position": "ST", 965 | "season_name": [ 966 | "2015", 967 | "2016" 968 | ] 969 | }, 970 | { 971 | "player_id": "0Oq6woOxQ6", 972 | "player_name": "Maarten Paes", 973 | "birth_date": "1998-05-14", 974 | "height_ft": 6, 975 | "height_in": 3, 976 | "weight_lb": 181, 977 | "nationality": "Netherlands", 978 | "primary_broad_position": "GK", 979 | "primary_general_position": "GK", 980 | "season_name": "2022" 981 | }, 982 | { 983 | "player_id": "0Oq6wPXPQ6", 984 | "player_name": "Lamar Batista", 985 | "birth_date": "1998-03-07", 986 | "height_ft": 6, 987 | "height_in": 6, 988 | "weight_lb": 165, 989 | "nationality": "USA", 990 | "season_name": {} 991 | }, 992 | { 993 | "player_id": "0Oq6wRzgQ6", 994 | "player_name": "Billy Heavner", 995 | "birth_date": "1993-11-12", 996 | "nationality": "USA", 997 | "season_name": {} 998 | } 999 | ] --------------------------------------------------------------------------------