PureSkill.gg Assistant Coach
Shared Python library that loads PureSkill.gg CS2 coaching content and renders it into localized, data-filled assessments for downstream coaching services.
What it does
assistant-coach (published to PyPI as pureskillgg-assistant-coach) is a small, importable Python library. It reads the versioned coaching content authored elsewhere – departments, assignments, breakdowns, resources, facets, and data-science models – and turns it into the player-facing assessment objects (titles, bodies, breakdowns with substituted match data, and matched learning resources) that a coaching service returns to a user.
The single public surface is pureskillgg_assistant_coach.department, which exports:
Department – the core model. Construct one for a named department (a coaching domain, e.g. dexter in the fixtures) with a reader, a structured logger, an injectable create_ds_models factory, and an injectable create_id (defaults to uuid4, overridable for deterministic tests).
DepartmentReaderS3 – the production reader; loads content JSON from S3.
DepartmentReaderFs – the filesystem reader; loads the same JSON from a local root (tests and local dev).
create_breakdown and create_resource – factory helpers for the rendered Breakdown and Resource objects.
Loading. Department.load() pulls the department’s assessments and the global meta through its reader; Department.load_ds_models() lazily builds data-science models from the reader’s models JSON via the injected create_ds_models factory. Each reader fetches five per-department documents (assignments, resources, breakdowns, facets, models) plus a global meta document. On read, attach_content_to_assignment denormalizes every assignment by inlining the breakdown, resource, and facet definitions it references, dropping any resource whose createdAt is in the future (resource_is_current).
Querying and rendering. Given an assignment name and match data:
get_title and get_body return Translation objects.
get_breakdowns(name, data) validates that every requested breakdown label exists on the assignment (raising RuntimeError otherwise), then builds Breakdown objects with per-breakdown match data injected.
get_resources and get_single_resource build Resource objects.
get_facets returns the facet schema; is_assignment and get_ds_model round out the surface.
Translation is the templating engine. It walks a nested dict of per-language strings (keyed en, jp, sp, …), compiles each leaf string as a Handlebars template (via pybars3), and renders it with the stringified match data so coaching copy can interpolate values like round numbers. It registers a custom list helper that joins items into "a", "a & b", or "a, b & c" prose.
Resource.tags_match implements tag-based resource selection via tag_matcher: tags are grouped (AND across groups, OR within a group), ~-prefixed tags are negations, and a resource matches only when every group is satisfied – returning the deduped, sorted matched tags. Every rendered breakdown and resource gets a fresh id from create_id.
There is no CLI, server, or job runner here. It is purely an importable model and templating library, validated by pytest plus syrupy snapshot tests against fixtures/assessment.
Pipeline role
This is a leaf-node helper library, not a deployable service: there are no Lambdas, no serverless.yml, and no Terraform anywhere in the repo. It sits late in the pipeline, after a match has been parsed and analyzed.
Upstream of it: the coaching content is authored and deployed elsewhere (the csgo-assessment JSON) to an S3 bucket under the prefix csgo/<version>/.... The match-level inputs (the data passed into get_breakdowns / Translation) come from the data-science / coach layer.
Consumers: a coaching service imports Department and a reader, reads the versioned content, and asks this library to render the assessment objects. csgo-coach and csgo-progression use this abstraction to load tag-filtered coaching content and enrich evaluations and reports.
Major components
All live under pureskillgg_assistant_coach/department/:
Department (model.py) – core class. load() / load_ds_models() pull content and DS models via the reader; get_title / get_body / get_breakdowns / get_resources / get_single_resource / get_facets / is_assignment / get_ds_model build rendered, localized coaching objects for an assignment plus match data. Raises RuntimeError on an unknown breakdown label.
DepartmentReaderS3 (reader_s3.py) – production reader. Reads assignments / resources / breakdowns / facets / models / meta JSON from S3 via boto3, decodes with rapidjson, caches the resources document in memory, and denormalizes assignments through attach_content_to_assignment.
DepartmentReaderFs (reader_fs.py) – filesystem equivalent of the S3 reader, reading the same documents from a local root.
Translation (translation.py) – per-language Handlebars renderer; recursively walks nested translation dicts, compiles each leaf string, and renders it with stringified match data; registers the custom list prose-join helper.
create_breakdown / Breakdown (breakdown.py) – factory and class wrapping a breakdown definition: extracts resource labels and sentiment, renders its translated features with injected data, and emits an object with a generated id.
create_resource / Resource + tag_matcher (resource.py) – factory and class for a coaching resource (text / youtube / link / etc.); renders translated fields and exposes tags_match for tag-group resource selection.
attach_content_to_assignment (attach_content_to_assignment.py) – denormalizes an assignment by inlining referenced breakdown / resource / facet definitions; resource_is_current filters out resources whose createdAt is in the future.
AWS resources
The library touches exactly one AWS resource, and only to read it:
S3 content bucket (caller-supplied) – DepartmentReaderS3 constructs boto3.client("s3") and calls get_object against the bucket passed into its constructor. There is no literal bucket name in this repo; the consuming service injects it. Keys live under csgo/<version>/... – specifically csgo/<version>/meta.json and csgo/<version>/department/<name>/{assignments,resources,breakdowns,facets,models}.json.
There are no Lambdas, DynamoDB tables, SQS / DLQ queues, SNS topics, Step Functions, EventBridge rules, AppSync APIs, or API Gateways owned by this repo, and therefore no CloudWatch log groups of its own.
Logs and observability
This is a pure library, so it has no runtime infrastructure and no log groups, DLQs, or Sentry integration of its own.
Normal and error logs live in whichever service imports the package. The library accepts an injected structured logger (used via log.bind(...) in reader_s3.py and model.py) but never configures it, so log format, level, and destination are owned by the consumer (e.g. the CloudWatch log groups of csgo-coach / csgo-progression).
Errors surface as raised Python exceptions to the caller: botocore ClientError (e.g. NoSuchKey / AccessDenied) from S3 get_object; rapidjson.JSONDecodeError on malformed content JSON; and KeyError from attach_content_to_assignment when an assignment references a breakdown, resource, or facet key that is missing from the loaded documents. get_breakdowns raises RuntimeError for an unknown breakdown label. Retry, alerting, and DLQ behavior for any of these is the responsibility of the consuming service.
CI logs for this repo are in GitHub Actions.
Documentation
docs/content-model.md – the department content model: the five per-department documents and global meta, the csgo/<version>/... S3 layout and versioning, assignment denormalization, the multi-language Translation rendering engine, and the tag_matcher AND-of-OR resource-selection semantics.
Description
Models to generate assessments.
Installation
This package is registered on the Python Package Index (PyPI) as pureskillgg-assistant-coach.
Install it with
$ uv add pureskillgg-assistant-coach
Development and Testing
Quickstart
$ git clone https://github.com/pureskillgg/assistant-coach.git $ cd assistant-coach $ uv sync
Run each command below in a separate terminal window:
$ make watch
Primary development tasks are defined in the Makefile.
Source Code
The source code is hosted on GitHub. Clone the project with
$ git clone https://github.com/pureskillgg/assistant-coach.git
Requirements
You will need Python 3 and uv.
Install the development dependencies with
$ uv sync
Tests
Lint code with
$ make lint
Run tests with
$ make test
Run tests on changes with
$ make watch
Publishing
Use the uv version command to release a new version. Then run make version to commit and push a new git tag which will trigger a GitHub action.
Publishing may be triggered using on the web using a workflow_dispatch on GitHub Actions.
GitHub Actions
GitHub Actions should already be configured: this section is for reference only.
The following repository secrets must be set on GitHub Actions.
PYPI_API_TOKEN: API token for publishing on PyPI.
These must be set manually.
Secrets for Optional GitHub Actions
The version and format GitHub actions require a user with write access to the repository including access to read and write packages. Set these additional secrets to enable the action:
GH_USER: The GitHub user’s username.
GH_TOKEN: A personal access token for the user.
GIT_USER_NAME: The name to set for Git commits.
GIT_USER_EMAIL: The email to set for Git commits.
GPG_PRIVATE_KEY: The GPG private key.
GPG_PASSPHRASE: The GPG key passphrase.
Contributing
Please submit and comment on bug reports and feature requests.
To submit a patch:
Fork it (https://github.com/pureskillgg/assistant-coach/fork).
Create your feature branch (git checkout -b my-new-feature).
Make changes.
Commit your changes (git commit -am ‘Add some feature’).
Push to the branch (git push origin my-new-feature).
Create a new Pull Request.
License
This Python package is Copyright (c) 2019-2021 FPS Critic, Inc.
Warranty
This software is provided by the copyright holders and contributors “as is” and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the copyright holder or contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.
Metadata
Release files for pureskillgg-assistant-coach 4.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pureskillgg_assistant_coach-4.0.2.tar.gz | 11.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pureskillgg_assistant_coach-4.0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 27.7 kB
Release files / pureskillgg_assistant_coach-4.0.2.tar.gz
| Download URL | pureskillgg_assistant_coach-4.0.2.tar.gz |
|---|---|
| Size | 11.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0c283abcff01fbb8dd902c4926d7fab53d1b41b511bf861d946b32ab180c8646
|
|
BLAKE2b-256 checksum How to use checksums |
ef155d411f278fc1e908d00842fe5c694fa5cc6860a8c0f4de3df4a9b4822608
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / pureskillgg_assistant_coach-4.0.2-py3-none-any.whl
| Download URL | pureskillgg_assistant_coach-4.0.2-py3-none-any.whl |
|---|---|
| Size | 16.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e294b28ad564d61b14822fcb2b11cfefced6a7b3724a93a38bf49c2584344f4d
|
|
BLAKE2b-256 checksum How to use checksums |
43e7144c0234b29f0fb1e7f00dc822ccf84d3ae11b88c623517f0211ce2290a7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|