Skip to content

Architecture

gem turns a raw .dem binary into structured Python objects in a single pass. This page shows how the modules fit together and what each layer produces.


Pipeline

flowchart TD
    A(["gem.parse()  /  gem.parse_to_dataframe()"])

    subgraph BINARY ["Binary decoding"]
        direction LR
        B["stream.py\nouter frames"] --> C["reader.py\nbits & varints"]
    end

    subgraph SCHEMA ["Schema & state"]
        direction LR
        D["sendtable.py\nserializer tree"] --> E["field_decoder.py\ntype dispatch"]
        D --> F["field_path.py\nHuffman paths"]
        G["string_table.py\nkey-value tables"]
        H["entities.py\ndelta updates"]
    end

    subgraph EVENTS ["Events"]
        direction LR
        I["game_events.py"]
        J["combatlog.py"]
    end

    subgraph EXTRACT ["Extractors"]
        direction LR
        X1["players"]
        X2["objectives"]
        X3["wards"]
        X4["courier"]
        X5["draft"]
        X6["teamfights"]
    end

    subgraph ASSEMBLE ["Assembly"]
        K["combat_aggregator.py"] --> L["match_builder.py"]
    end

    O(["ParsedMatch"])
    P(["dict[str, DataFrame]  /  JSON  /  Parquet"])

    A --> BINARY
    BINARY --> SCHEMA
    SCHEMA --> EVENTS
    SCHEMA --> EXTRACT
    EVENTS --> ASSEMBLE
    EXTRACT --> ASSEMBLE
    ASSEMBLE --> O
    O --> P

Layers at a glance

Entry points
gem.parse() gem.parse_to_dataframe() gem.parse_to_json() gem.parse_to_parquet()
Binary decoding
stream.py reader.py sendtable.py field_decoder.py field_path.py string_table.py entities.py
Events
game_events.py combatlog.py
Extractors
extractors/players.py extractors/objectives.py extractors/wards.py extractors/courier.py extractors/draft.py extractors/teamfights.py
Assembly
combat_aggregator.py match_builder.py
Output
models.py · ParsedMatch dataframes.py

Output model

gem.parse() returns a single ParsedMatch. Every field is either a scalar or a list of typed dataclasses — no raw dicts, no untyped payloads.

Field Type What it contains
players list[ParsedPlayer] One entry per player — KDA, gold/XP series, purchases, runes, buybacks, positions
draft list[DraftEvent] Chronological pick and ban events with hero name and team
combat_log list[CombatLogEntry] Every damage, kill, heal, ability-use, and modifier event
towers / barracks list[TowerKill / BarracksKill] Objective deaths with tick, team, and killer
roshans list[RoshanKill] Roshan kills with kill number and killer slot
tormentors / shrines list[TormentorKill / ShrineKill] Tormentor and Shrine of Wisdom destruction events
wards list[WardEvent] Ward placements with exact map coordinates
teamfights list[Teamfight] Detected fight windows with per-player damage, kills, and healing
smoke_events list[SmokeEvent] Smoke activations with grouped heroes and centroid position
aegis_events list[AegisEvent] Aegis pickups, steals, and denies
courier_snapshots list[CourierSnapshot] Courier state sampled each tick
chat list[ChatEntry] All-chat and team-chat messages
radiant_gold_adv / radiant_xp_adv list[int] Per-minute Radiant gold and XP advantage curves

For the full field listing see the Models reference and Full Match Data guide.