Skip to main content

Deterministic Weiss Schwarz simulator with a Rust core and Python bindings.

Project description

Weiss Schwarz Simulator (Rust core + Python bindings)

CI Wheels Benchmarks Security Docs PyPI Changelog Last Commit

Deterministic, RL-first Weiss Schwarz simulation: Rust runs the hot loop, advances until a decision point, and exposes a fixed action space + mask (and legal action ids) for efficient batched training. Python gets a thin EnvPool wrapper for stepping many environments in parallel.


Why this exists

Weiss Schwarz has hidden information, branching, and timing windows. For RL you typically want:

  • Determinism: reproduce episodes from a seed and action sequence.
  • Few boundary crossings: avoid Python↔Rust overhead for micro-steps.
  • Stable action space: fixed-size actions with legality masking.
  • Introspectability: canonical action descriptions, replays, and event logs.

This repo is built around those constraints.


Highlights

  • Advance-until-decision loop: engine runs internally until a player must act.
  • Canonical legal actions: ActionDesc list is the single truth source.
  • Fixed action id space + mask: derived from canonical actions and versioned (ACTION_ENCODING_VERSION).
  • Legal action ids (fast): use ids to avoid Python-side mask scans in hot loops.
  • Fixed-length observations: int32 arrays, versioned (OBS_ENCODING_VERSION).
  • Multicore stepping: EnvPool uses Rayon; Python binding releases the GIL.
  • Replays: deterministic, versioned, optional event stream, public-safe sanitization when enabled.
  • Curriculum switches: gate rules/features for training curricula.

Each environment is deterministic given its seed and action sequence. Parallel batch stepping does not change outcomes because envs are fully isolated.


Automation & Benchmarks

  • CI runs on every push/PR: Rust fmt/clippy/tests + Python ruff/pytest.
  • Wheels build on pushes to main (artifacts), and tags v* publish to GitHub Releases + PyPI.
  • Benchmarks run on pushes to main; history + charts are published via GitHub Pages.
  • Docs are published to GitHub Pages on pushes to main.

Latest benchmark history and charts: https://victorwp288.github.io/weiss-schwarz-simulator/benchmarks

Rust API docs: https://victorwp288.github.io/weiss-schwarz-simulator/rustdoc/

Note: with only 1–2 benchmark runs, charts can look “empty” until more points exist.

Releases

Release automation is handled by Release Please. To ensure downstream workflows (like Wheels) run automatically when a release tag is created, configure a fine-grained PAT as RELEASE_PLEASE_TOKEN in GitHub Actions secrets; otherwise you can manually run the Wheels workflow for the release tag.

Benchmark Snapshot (main, top 12)

Last updated: 2026-01-05 00:44 UTC

Benchmark Time
rust/advance_until_decision 63280 ns/iter
rust/step_batch_64 26268 ns/iter
rust/step_batch_fast_256_priority_off 111592 ns/iter
rust/step_batch_fast_256_priority_on 109646 ns/iter
rust/legal_actions 44 ns/iter
rust/legal_actions_forced 43 ns/iter
rust/on_reverse_decision_frequency_on 1534 ns/iter
rust/on_reverse_decision_frequency_off 1540 ns/iter
rust/observation_encode 228 ns/iter
rust/observation_encode_forced 233 ns/iter
rust/mask_construction 455 ns/iter
rust/mask_construction_forced 412 ns/iter

Repo layout

  • weiss_core/: Rust simulator core (state machine, legality, encoding, replay, pool)
  • weiss_py/: PyO3 extension module (weiss_sim) exposing EnvPool
  • python/weiss_sim/: Python wrapper that re-exports the extension
  • python/tests/: pytest smoke tests + fixture card DB

Installation

Python (local build via maturin)

Prerequisites:

  • Python: ≥ 3.10
  • Rust toolchain: stable (cargo, rustc)
  • Bindings: built with PyO3 0.24 + numpy 0.24 (Rust side)

Install (editable):

python -m pip install -U pip
python -m pip install -U maturin
python -m pip install -e .

Note (macOS/PyO3): if you build wheels locally, prefer an explicit interpreter to avoid linking errors and unsupported system Pythons:

maturin build --release --manifest-path weiss_py/Cargo.toml --interpreter .venv/bin/python -o dist

Sanity check:

python -c "import weiss_sim; print(weiss_sim.__version__, weiss_sim.EnvPool)"

Rust (core only)

cargo build -p weiss_core
cargo test -p weiss_core

Quickstart (Python): step with a trivial policy

The environment exposes a fixed action space and an action mask. You can select any index where mask==1. For speed, use legal action ids instead of scanning the full mask.

from pathlib import Path
import numpy as np
import weiss_sim

fixture_dir = Path("python/tests/fixtures")
db_path = fixture_dir / "cards.wsdb"

pool = weiss_sim.EnvPool.new_rl_train(
    1,
    str(db_path),
    deck_lists=[[1] * 50, [2] * 50],
    deck_ids=[1, 2],
    max_decisions=200,
    max_ticks=10_000,
    seed=123,
    num_threads=None,  # set to an int to pin a dedicated Rayon pool
)

buf = weiss_sim.EnvPoolBuffers(pool)
buf.reset()

for _ in range(10):
    ids_flat, offsets = buf.legal_action_ids()
    start, end = int(offsets[0]), int(offsets[1])
    action = int(ids_flat[start])
    actions = np.array([action], dtype=np.uint32)
    buf.step(actions)

Debug print (very lightweight):

print(pool.render_ansi(env_index=0, perspective=0))

Examples:

python python/examples/sb3_maskable_ppo.py
python python/examples/cleanrl_maskable_ppo.py
python python/examples/bench_python_boundary.py --num-envs 256 --steps 5000 --mode both

Python API (what you get)

The extension module is weiss_sim and the package re-exports it as import weiss_sim.

weiss_sim.EnvPool

Constructors (classmethods):

EnvPool.new_rl_train(
    num_envs: int,
    db_path: str,
    deck_lists: list[list[int]],
    deck_ids: list[int] | None = None,
    max_decisions: int = 10_000,
    max_ticks: int = 100_000,
    seed: int = 0,
    reward_json: str | None = None,
    num_threads: int | None = None,
)

EnvPool.new_rl_eval(...)
EnvPool.new_debug(...)

Minimal RL stepping uses BatchOutMinimal:

out = weiss_sim.BatchOutMinimal(num_envs)
pool.reset_into(out)
pool.step_into(actions, out)

Core methods:

  • reset_into(out: BatchOutMinimal) -> None
  • reset_indices_into(indices: list[int], out: BatchOutMinimal) -> None
  • reset_done_into(done_mask: np.ndarray[bool], out: BatchOutMinimal) -> None
  • step_into(actions: np.ndarray[uint32], out: BatchOutMinimal) -> None
  • step_debug_into(actions: np.ndarray[uint32], out: BatchOutDebug) -> None
  • reset_debug_into(out: BatchOutDebug) -> None
  • reset_indices_debug_into(indices: list[int], out: BatchOutDebug) -> None
  • legal_action_ids_into(ids: np.ndarray[uint16], offsets: np.ndarray[uint32]) -> int
  • auto_reset_on_error_codes_into(engine_status: np.ndarray[uint8], out: BatchOutMinimal) -> int
  • engine_error_reset_count() -> int
  • reset_engine_error_reset_count() -> None

Debug helpers:

  • action_lookup_batch() -> list[list[dict | None]]
  • describe_action_ids(action_ids: list[int]) -> list[dict | None]
  • decision_info_batch() -> list[dict]
  • state_fingerprint_batch() -> np.ndarray[uint64]
  • events_fingerprint_batch() -> np.ndarray[uint64]
  • render_ansi(env_index: int, perspective: int) -> str

Convenience properties:

  • action_space: int
  • obs_len: int
  • num_envs: int

Python helper:

  • EnvPoolBuffers(pool) allocates persistent numpy buffers and exposes reset(), step(), and legal_action_ids().
  • reset_rl(pool) / step_rl(pool, actions) return a RlStep dataclass with named fields.
  • pass_action_id_for_decision_kind(decision_kind) returns PASS_ACTION_ID for convenience.

Encodings (stable + versioned)

Encodings are deterministic and explicitly versioned:

  • weiss_sim.OBS_ENCODING_VERSION (currently 1)
  • weiss_sim.ACTION_ENCODING_VERSION (currently 1)

Observation tensor

Observations are fixed-length int32 arrays. Query the current length via:

  • weiss_sim.OBS_LEN or pool.obs_len

Visibility modes (observation_visibility):

  • "public": opponent hidden zones are masked (filled with -1).
  • "full": opponent hidden zones are revealed.

The header includes active player, phase, decision kind/player, last action, attack context, and choice pagination metadata. After the per-player blocks (perspective player first), the encoder appends:

  • Reason bits: public-safe flags for phase/resource/target gating.
  • Reveal history: recent revealed card ids for the observing player.
  • Context bits: priority/choice/stack/encore context.

Exact layout is defined in weiss_core/src/encode.rs and versioned by OBS_ENCODING_VERSION.

Action space

Actions are fixed to ACTION_SPACE_SIZE (pool.action_space). Families include:

  • pass (contextual; PASS_ACTION_ID)
  • mulligan confirm / mulligan select
  • clock
  • main play character/event/climax, moves, activated abilities
  • attack / counter
  • choice select + pagination
  • level up / encore
  • trigger order
  • concede (only legal when allow_concede=true)

The legal-action mask is derived from the canonical ActionDesc list and mapped to ids in a versioned way (ACTION_ENCODING_VERSION).


Performance & throughput

Rust core is already extremely fast; Python-side overhead can dominate.

Practical performance tips:

  • Use into-buffer APIs (reset_into, step_into) with preallocated buffers.
  • Prefer legal action ids over mask scans in Python.
  • Pin num_threads if you want repeatable multicore behavior.

RL-safe defaults (recommended)

  • EnvPool.new_rl_train(...) for training and EnvPool.new_rl_eval(...) for eval.
  • observation_visibility = Public
  • enable_visibility_policies = true
  • allow_concede = false
  • priority_allow_pass = true
  • strict_priority_mode = false
  • enable_priority_windows = false unless you explicitly train with priority timing windows
  • Treat timeouts as truncations (bootstrap value)

If you need to deviate, document the assumption and update the PPO guide.


Replays (WSR1)

Replays are binary WSR1 files written via ReplayWriter and serialized with postcard.

What gets recorded:

  • Header: obs/action encoding versions, replay schema version, seed, starting player, deck ids, curriculum id, config hash
  • Body: action sequence, per-step metadata (actor/decision kind/flags), optional event stream, final snapshot (terminal + state hash)

Replay sampling can be enabled from Rust (EnvPool::enable_replay_sampling). The Python binding does not currently expose replay sampling toggles.

Tooling:

cargo run -p weiss_core --bin replay_dump -- path/to/episode_00000000.wsr

Card database (WSDB)

The simulator loads a binary card DB:

  • Magic: WSDB
  • Schema version: u32 little-endian (WSDB_SCHEMA_VERSION = 1)
  • Payload: postcard-encoded CardDb

Pack JSON → WSDB:

cargo run -p weiss_core --bin carddb_pack -- cards.json cards.wsdb

See weiss_core/src/db.rs for the CardStatic schema and supported ability templates.

Scraper + converter pipeline (full card set)

The full EN card set is produced by the scraper + converter pipeline:

  • Scrape: scraper/scrape.pyscraper/out/cards.jsonl
  • Convert: scraper/convert.pyscraper/out/cards.json + scraper/out/cards_raw.json
  • Pack: carddb_packscraper/out/cards.wsdb

Smoke check with Python:

PYTHONPATH=python python python/wsdb_smoke.py

Project status (implemented vs simplified)

This is a simulator core built for RL training and determinism first. Some rule systems are intentionally simplified or diverge from the physical game.

Examples of current intentional simplifications/deviations:

  • local priority/stack model; official check-timing/play-timing subtleties are not fully replicated
  • card text is limited to implemented AbilityTemplate variants (no free-form text engine)
  • trigger icon semantics are simplified :
    • Draw is mandatory (not optional “may”)
    • Shot resolves as immediate 1 damage (not delayed on cancel)
    • Bounce returns a character from your stage (not opponent’s)
  • deck-top search/reveal modeled as top‑N reveal to controller

License

Dual-licensed under MIT OR Apache-2.0 (see workspace metadata in Cargo.toml).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

weiss_sim-0.1.3.tar.gz (154.7 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

weiss_sim-0.1.3-cp312-cp312-win_amd64.whl (620.3 kB view details)

Uploaded CPython 3.12Windows x86-64

weiss_sim-0.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (846.9 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

weiss_sim-0.1.3-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (1.5 MB view details)

Uploaded CPython 3.12macOS 10.12+ universal2 (ARM64, x86-64)macOS 10.12+ x86-64macOS 11.0+ ARM64

weiss_sim-0.1.3-cp311-cp311-win_amd64.whl (619.3 kB view details)

Uploaded CPython 3.11Windows x86-64

weiss_sim-0.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (846.2 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

weiss_sim-0.1.3-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (1.5 MB view details)

Uploaded CPython 3.11macOS 10.12+ universal2 (ARM64, x86-64)macOS 10.12+ x86-64macOS 11.0+ ARM64

weiss_sim-0.1.3-cp310-cp310-win_amd64.whl (619.3 kB view details)

Uploaded CPython 3.10Windows x86-64

weiss_sim-0.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (846.3 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

weiss_sim-0.1.3-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (1.5 MB view details)

Uploaded CPython 3.10macOS 10.12+ universal2 (ARM64, x86-64)macOS 10.12+ x86-64macOS 11.0+ ARM64

File details

Details for the file weiss_sim-0.1.3.tar.gz.

File metadata

  • Download URL: weiss_sim-0.1.3.tar.gz
  • Upload date:
  • Size: 154.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for weiss_sim-0.1.3.tar.gz
Algorithm Hash digest
SHA256 06d4abdad70c9c97afdea7da2f30ca7e378937efb6b6b3c10fcf247b6d975f6d
MD5 dfea8fe1da8ff48c658fad6f6cb27475
BLAKE2b-256 6ebba3f8c0be521db68b3025bf672b2afa368b69c3ae9ca834e6d5446e5c1adb

See more details on using hashes here.

Provenance

The following attestation bundles were made for weiss_sim-0.1.3.tar.gz:

Publisher: wheels.yml on victorwp288/weiss-schwarz-simulator

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file weiss_sim-0.1.3-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: weiss_sim-0.1.3-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 620.3 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for weiss_sim-0.1.3-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 f3318a7e854c9ee7bf4964a4c32e8c19e09f6a9544df2f407bf0f491efc0848c
MD5 7e85ff9f66a08ff10cc9107dcf52acc6
BLAKE2b-256 4a0aab20e47ccf396b72ace003d76bc02ba78f071e798b9211105b9454c23823

See more details on using hashes here.

Provenance

The following attestation bundles were made for weiss_sim-0.1.3-cp312-cp312-win_amd64.whl:

Publisher: wheels.yml on victorwp288/weiss-schwarz-simulator

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file weiss_sim-0.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for weiss_sim-0.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 74ae8a2b89da9b578ac722e5ae36a5648f939c028f12a709cbc497a4a084ff02
MD5 d89d014ac8426d7f4d68ac88bf2d0863
BLAKE2b-256 79480c60c7e9f0105058c63dfc73ad23c6682b2319677dad310fe0aefb48e7ee

See more details on using hashes here.

Provenance

The following attestation bundles were made for weiss_sim-0.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: wheels.yml on victorwp288/weiss-schwarz-simulator

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file weiss_sim-0.1.3-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for weiss_sim-0.1.3-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 320dfffdadabcd0108c5fbf69811b7f1b6f2134954b52c608848f1d213cba124
MD5 2e998e2174ff2e20e12647662d2e2479
BLAKE2b-256 b04d83ab816cfdd83c7d5cd6539fd256e9e66cd53dc34effbac4b682fdebd282

See more details on using hashes here.

Provenance

The following attestation bundles were made for weiss_sim-0.1.3-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl:

Publisher: wheels.yml on victorwp288/weiss-schwarz-simulator

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file weiss_sim-0.1.3-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: weiss_sim-0.1.3-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 619.3 kB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for weiss_sim-0.1.3-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 729fe72e9391bb56e1a5bafe91d14a6d723ad291e7df2e6750a53498ad250ac0
MD5 e61d03943ec43644f1e4e16b4fbf02ea
BLAKE2b-256 4dbe8d8a05c37d2d233eeca3e640d79145ab13b9b60b1e484a3d1f6fab1df49d

See more details on using hashes here.

Provenance

The following attestation bundles were made for weiss_sim-0.1.3-cp311-cp311-win_amd64.whl:

Publisher: wheels.yml on victorwp288/weiss-schwarz-simulator

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file weiss_sim-0.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for weiss_sim-0.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e7f4e4afd866d87291d9a33050909261cf164455b040062b8b628ff6d8b4feba
MD5 ea7ec75775f5e27b4e724aed2d3da20b
BLAKE2b-256 15f094e4a2032272e21d2becde4e9d8bf774d67a42d1c9ee6a2fcdedecd78c19

See more details on using hashes here.

Provenance

The following attestation bundles were made for weiss_sim-0.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: wheels.yml on victorwp288/weiss-schwarz-simulator

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file weiss_sim-0.1.3-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for weiss_sim-0.1.3-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 455440fdbcdb608257fb48eb05b31fbde51acc7a8f974c6aefc5ed5ea721f601
MD5 e608fad883b8f40e99789eb52ec04d09
BLAKE2b-256 cfa8bbf1bf4ac0ad323a559306f56828e441bdd67f8bf4115babd861cf6cb4a4

See more details on using hashes here.

Provenance

The following attestation bundles were made for weiss_sim-0.1.3-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl:

Publisher: wheels.yml on victorwp288/weiss-schwarz-simulator

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file weiss_sim-0.1.3-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: weiss_sim-0.1.3-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 619.3 kB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for weiss_sim-0.1.3-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 556da5271240431336debbc28aa55f69654356d46cd23e0f00cb600672415cdd
MD5 a4d923cbbdafcd2b041450e7d3f955bd
BLAKE2b-256 a506bf211a6359a8e388ae9a261f77940e3924214d4898dd2a3ed4bf80497a9b

See more details on using hashes here.

Provenance

The following attestation bundles were made for weiss_sim-0.1.3-cp310-cp310-win_amd64.whl:

Publisher: wheels.yml on victorwp288/weiss-schwarz-simulator

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file weiss_sim-0.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for weiss_sim-0.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 f8aa3ad193d9112509b3d8a6a45c6f655e1495d646f7208958b7f054da611e5e
MD5 f2e76f71a161ac2fc5d27b3820578bfc
BLAKE2b-256 9f4953f2413f609e7d7a02cd493452ff91c5e5a00963f9be12d7e5a637edf518

See more details on using hashes here.

Provenance

The following attestation bundles were made for weiss_sim-0.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: wheels.yml on victorwp288/weiss-schwarz-simulator

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file weiss_sim-0.1.3-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for weiss_sim-0.1.3-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 bac3b8e34ca186f3252e7fe6a395e1fa55bbbb11c5aeb58d1f18052b1bb8f34a
MD5 95706d7c0962f35e17938b5f4a814b91
BLAKE2b-256 f7f372b10148e8c38d6f6b6400036fdb16e7f6752414e8edc679638d800233cf

See more details on using hashes here.

Provenance

The following attestation bundles were made for weiss_sim-0.1.3-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl:

Publisher: wheels.yml on victorwp288/weiss-schwarz-simulator

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page