gem
v0.13.0

Models

Output dataclasses produced by gem.parse().

See also: Full Match Data, Quickstart

Notable recent fields

  • ParsedMatch.radiant_team_id / dire_team_id: int — tournament team ID (matches OpenDota /teams/{id} URL). 0 for pub games.
  • ParsedMatch.radiant_team_name / dire_team_name: str — team name (e.g. "Xtreme Gaming"). Empty string for pub games.
  • ParsedMatch.radiant_team_tag / dire_team_tag: str — team tag (e.g. "XG"). Empty string for pub games.
  • ParsedPlayer.steam_id: int — 64-bit Steam ID. 0 if unavailable.
  • ParsedPlayer.account_id: int — 32-bit account ID (the ID in OpenDota/Dotabuff player URLs). 0 if unavailable.
  • ParsedMatch.neutral_item_finds: list[NeutralItemFoundEvent] — replay-observed neutral item finds from DOTA_UM_FoundNeutralItem, including resolved item and enhancement keys.
  • ParsedMatch.vision_modifiers: list[VisionModifierEvent] (experimental) — evidence-preserving applications of direct reveals, reveal auras, and aura carriers.
  • ParsedMatch.vision_modifier_pairing_issues: list[VisionModifierPairingIssue] (experimental) — ambiguous/orphan removal evidence without fabricated applications.
  • ParsedMatch.hero_visibility_events: list[HeroVisibilityEvent] — authoritative, change-only visibility states for canonical player heroes, read from each team's replay bitset. unknown means the replay state was unavailable; it does not mean hidden.
  • ParsedMatch.entity_visibility_events: list[EntityVisibilityEvent] — identity-safe packet-boundary visibility and active lifecycle for networked Dota NPC entities.
  • ParsedMatch.tormentors: list[TormentorKill] — chronological Tormentor kill events.
  • ParsedMatch.shrines: list[ShrineKill] — chronological Shrine of Wisdom destruction events.
  • ParsedPlayer.damage_by_type: dict[str, int] — total damage dealt by damage type (physical, magical, pure).
  • ParsedPlayer.damage_taken_by_type: dict[str, int] — total damage taken by damage type.
  • ParsedPlayer.buyback_log: list[CombatLogEntry] — buyback events attributed to the player.
  • ParsedPlayer.lane_efficiency_pct: int — lane efficiency percentage derived from lane gold.

TormentorKill

  • tick: game tick of the kill.
  • killer: NPC name of the killing unit.
  • killer_player_id: player slot (0-9) of the killer when resolved, else -1.
  • kill_number: sequential Tormentor kill number in the match.

Generated API

Module gem.results.models

Output data models for gem replay parsing.

Source: src/gem/results/models.py

Top-level classes

VisibilityState

class VisibilityState(str, Enum)

A team's authoritative visibility state for one hero entity.

Source: src/gem/results/models.py:34

HeroVisibilityEvent

class HeroVisibilityEvent

A visibility-state transition for one canonical player hero identity.

Source: src/gem/results/models.py:51

Dataclass fields

NameTypeDefault
tickint-
player_idint-
hero_namestr-
entity_indexint-
entity_serialint-
radiant_stateVisibilityState-
dire_stateVisibilityState-

EntityVisibilityEvent

class EntityVisibilityEvent

Packet-boundary visibility evidence for one networked Dota NPC entity.

Source: src/gem/results/models.py:74

Dataclass fields

NameTypeDefault
tickint-
entity_indexint-
entity_serialint-
class_namestr-
npc_namestr-
teamint | None-
activebool-
radiant_stateVisibilityState-
dire_stateVisibilityState-

VisionModifierSemantic

class VisionModifierSemantic(str, Enum)

How a tracked modifier contributes vision evidence.

Source: src/gem/results/models.py:105

VisionModifierLifecycleStatus

class VisionModifierLifecycleStatus(str, Enum)

Best-supported lifecycle state for a modifier application.

Source: src/gem/results/models.py:116

VisionModifierCloseEvidence

class VisionModifierCloseEvidence(str, Enum)

Evidence supporting the lifecycle close classification.

Source: src/gem/results/models.py:127

VisionModifierPairingStatus

class VisionModifierPairingStatus(str, Enum)

Confidence with which a removal was paired to an application.

Source: src/gem/results/models.py:138

VisionModifierTeamSource

class VisionModifierTeamSource(str, Enum)

Evidence source used to attribute a modifier participant's team.

Source: src/gem/results/models.py:149

VisionModifierEvent

class VisionModifierEvent

One tracked vision-relevant modifier application and its evidence.

Source: src/gem/results/models.py:160

Dataclass fields

NameTypeDefault
tickint-
end_tickint | None-
modifier_namestr-
target_namestr-
caster_namestr-
caster_teamint-
semanticVisionModifierSemanticVisionModifierSemantic.DIRECT_TARGET_REVEAL
lifecycle_statusVisionModifierLifecycleStatusVisionModifierLifecycleStatus.OPEN
close_evidenceVisionModifierCloseEvidenceVisionModifierCloseEvidence.UNOBSERVED
pairing_statusVisionModifierPairingStatusVisionModifierPairingStatus.EXACT
target_is_heroboolTrue
caster_is_heroboolFalse
caster_is_illusionboolFalse
target_is_illusionboolFalse
caster_is_hero_presentboolFalse
target_is_hero_presentboolFalse
caster_is_illusion_presentboolFalse
target_is_illusion_presentboolFalse
target_teamint0
caster_team_sourceVisionModifierTeamSourceVisionModifierTeamSource.UNKNOWN
target_team_sourceVisionModifierTeamSourceVisionModifierTeamSource.UNKNOWN
add_attacker_teamint | NoneNone
add_target_teamint | NoneNone
remove_attacker_teamint | NoneNone
remove_target_teamint | NoneNone
add_sourceCombatLogSourceCombatLogSource.UNKNOWN
remove_sourceCombatLogSource | NoneNone
add_game_time_sint | NoneNone
remove_game_time_sint | NoneNone
add_modifier_duration_sfloat | NoneNone
remove_modifier_duration_sfloat | NoneNone
add_modifier_elapsed_duration_sfloat | NoneNone
remove_modifier_elapsed_duration_sfloat | NoneNone
add_aura_modifierbool | NoneNone
remove_aura_modifierbool | NoneNone
remove_modifier_purgedbool | NoneNone
remove_modifier_purged_duration_sfloat | NoneNone
remove_caster_namestr''
remove_caster_is_herobool | NoneNone
remove_target_is_herobool | NoneNone
remove_caster_is_illusionbool | NoneNone
remove_target_is_illusionbool | NoneNone
evidence_gapslist[str]field(...)

VisionModifierPairingIssue

class VisionModifierPairingIssue

Removal evidence that could not be paired to one application safely.

Source: src/gem/results/models.py:260

Dataclass fields

NameTypeDefault
tickint-
reasonstr-
modifier_namestr-
caster_namestr-
target_namestr-
sourceCombatLogSourceCombatLogSource.UNKNOWN
candidate_add_tickslist[int]field(...)
game_time_sint | NoneNone
modifier_duration_sfloat | NoneNone
modifier_elapsed_duration_sfloat | NoneNone
attacker_teamint | NoneNone
target_teamint | NoneNone
caster_is_herobool | NoneNone
target_is_herobool | NoneNone
caster_is_illusionbool | NoneNone
target_is_illusionbool | NoneNone
aura_modifierbool | NoneNone
modifier_purgedbool | NoneNone
modifier_purged_duration_sfloat | NoneNone

SmokeParticipant

class SmokeParticipant

One hero's observed Smoke of Deceit modifier lifecycle.

Source: src/gem/results/models.py:304

Dataclass fields

NameTypeDefault
hero_namestr-
player_idint | None-
applied_tickint-
removed_tickint | NoneNone
modifier_duration_sfloat | NoneNone
modifier_elapsed_duration_sfloat | NoneNone
applied_xfloat | NoneNone
applied_yfloat | NoneNone
removed_xfloat | NoneNone
removed_yfloat | NoneNone
applied_game_time_sint | NoneNone
removed_game_time_sint | NoneNone

SmokeEvent

class SmokeEvent

One Smoke of Deceit activation.

Source: src/gem/results/models.py:343

Dataclass fields

NameTypeDefault
tickint-
activatorstr-
teamint-
smokedlist[str]field(...)
xfloat | NoneNone
yfloat | NoneNone
activation_xfloat | NoneNone
activation_yfloat | NoneNone
participantslist[SmokeParticipant]field(...)
activation_game_time_sint | NoneNone

BuybackEvent

class BuybackEvent

One buyback and its gold cost.

Source: src/gem/results/models.py:378

Dataclass fields

NameTypeDefault
tickint-
player_slotint-
costint-
net_worthint-
cost_exactboolFalse
reliable_goldint | NoneNone
unreliable_goldint | NoneNone

GoldLedgerSnapshot

class GoldLedgerSnapshot

One reading of a player's gold ledger from the team data entity.

Source: src/gem/results/models.py:423

Dataclass fields

NameTypeDefault
tickint-
game_time_sint-
hero_kill_goldint0
creep_kill_goldint0
neutral_kill_goldint0
income_goldint0
building_goldint0
roshan_goldint0
bounty_goldint0
ward_kill_goldint0
courier_goldint0
ability_goldint0
comeback_goldint0
creep_deny_goldint0
other_goldint0
shared_goldint0
spent_on_itemsint0
spent_on_consumablesint0
spent_on_supportint0
spent_on_buybacksint0
lost_to_deathint0

GoldLedger

class GoldLedger

A player's gold ledger at game end and at every game minute.

Source: src/gem/results/models.py:493

Dataclass fields

NameTypeDefault
finalGoldLedgerSnapshot | NoneNone
per_minutelist[GoldLedgerSnapshot]field(...)

ChatEntry

class ChatEntry

A single chat message from the match.

Source: src/gem/results/models.py:509

Dataclass fields

NameTypeDefault
tickint-
player_slotint-
channelstr-
textstr-

NeutralItemFoundEvent

class NeutralItemFoundEvent

A neutral item found event emitted by DOTA_UM_FoundNeutralItem.

Source: src/gem/results/models.py:528

Dataclass fields

NameTypeDefault
tickint-
player_idint-
item_ability_idint-
item_keystr''
item_tierint0
tier_item_countint0
enhancement_ability_idint-1
enhancement_keystr''
enhancement_levelint0
trinket_levelint0

ParsedPlayer

class ParsedPlayer

Aggregated statistics for one player over a full match.

Source: src/gem/results/models.py:562

Dataclass fields

NameTypeDefault
player_idint-
hero_namestr''
player_namestr''
steam_idint0
account_idint0
teamint0
timeslist[int]field(...)
gold_tlist[int]field(...)
total_earned_gold_tlist[int]field(...)
net_worth_tlist[int]field(...)
lh_tlist[int]field(...)
dn_tlist[int]field(...)
xp_tlist[int]field(...)
times_minlist[int]field(...)
gold_t_minlist[int]field(...)
total_earned_gold_t_minlist[int]field(...)
total_earned_xp_t_minlist[int]field(...)
net_worth_t_minlist[int]field(...)
lh_t_minlist[int]field(...)
dn_t_minlist[int]field(...)
xp_t_minlist[int]field(...)
total_hero_damage_t_minlist[int]field(...)
total_hero_healing_t_minlist[int]field(...)
total_deaths_t_minlist[int]field(...)
total_stuns_t_minlist[float]field(...)
obs_loglist[WardEvent]field(...)
sen_loglist[WardEvent]field(...)
obs_left_loglist[dict[str, Any]]field(...)
sen_left_loglist[dict[str, Any]]field(...)
obsdict[str, dict[str, int]]field(...)
sendict[str, dict[str, int]]field(...)
damagedict[str, int]field(...)
damage_takendict[str, int]field(...)
damage_by_typedict[str, int]field(...)
damage_taken_by_typedict[str, int]field(...)
damage_inflictordict[str, int]field(...)
damage_inflictor_receiveddict[str, int]field(...)
damage_targetsdict[str, dict[str, int]]field(...)
ability_targetsdict[str, dict[str, int]]field(...)
hero_hitsdict[str, int]field(...)
max_hero_hitdict[str, Any] | NoneNone
healingdict[str, int]field(...)
ability_usesdict[str, int]field(...)
ability_upgrades_arrlist[int]field(...)
item_usesdict[str, int]field(...)
final_itemsdict[int, str]field(...)
gold_reasonsdict[str, int]field(...)
xp_reasonsdict[str, int]field(...)
kills_loglist[CombatLogEntry]field(...)
purchase_loglist[CombatLogEntry]field(...)
runes_loglist[CombatLogEntry]field(...)
buyback_loglist[CombatLogEntry]field(...)
buybackslist[BuybackEvent]field(...)
lane_posdict[str, dict[str, int]]field(...)
position_loglist[tuple[int, float, float]]field(...)
stuns_dealtfloat0.0
killsint0
deathsint0
assistsint0
laneint0
lane_roleint0
is_roamingboolFalse
lane_last_hitsint0
lane_deniesint0
lane_total_goldint0
lane_total_xpint0
lane_efficiency_pctint0
lane_gold_advint | NoneNone
lane_xp_advint | NoneNone
net_worthint0
last_hitsint0
deniesint0
camps_stackedint0
creeps_stackedint0
obs_placedint0
sen_placedint0
rune_pickupsint0
tower_killsint0
kdafloat0.0
buyback_countint0
is_radiantboolFalse
winint0
kills_per_minfloat0.0
hero_damageint0
tower_damageint0
hero_healingint0
gold_per_minint0
xp_per_minint0
total_goldint0
total_xpint0
killeddict[str, int]field(...)
ancient_killsint0
neutral_killsint0
lane_killsint0
courier_killsint0
observer_killsint0
sentry_killsint0
roshan_killsint0
hero_idint0
levelint0
gold_spentint0
life_state_deadint0
firstblood_claimedint0
teamfight_participationfloat0.0
purchasedict[str, int]field(...)
purchase_timedict[str, int]field(...)
first_purchase_timedict[str, int]field(...)
purchase_tpscrollint0
purchase_ward_observerint0
purchase_ward_sentryint0
observer_usesint0
sentry_usesint0
observers_placedint0
game_times_minlist[int]field(...)
aghanims_scepterint | NoneNone
aghanims_shardint | NoneNone
moonshardint | NoneNone
total_earned_xp_tlist[int]field(...)
goldint0
gold_ledgerGoldLedger | NoneNone
multi_killsdict[str, int]field(...)
kill_streaksdict[str, int]field(...)
killed_bydict[str, int]field(...)
hp_tlist[int]field(...)
max_hp_tlist[int]field(...)
mana_tlist[float]field(...)
max_mana_tlist[float]field(...)

ParsedMatch

class ParsedMatch

Top-level parsed output for a single Dota 2 replay.

Source: src/gem/results/models.py:1029

Dataclass fields

NameTypeDefault
match_idint0
game_modeint0
leagueidint0
radiant_winbool | NoneNone
radiant_team_idint0
radiant_team_namestr''
radiant_team_tagstr''
dire_team_idint0
dire_team_namestr''
dire_team_tagstr''
game_start_tickint | NoneNone
game_end_tickint0
durationint0
radiant_scoreint0
dire_scoreint0
first_blood_timeint0
pre_game_durationint0
playerslist[ParsedPlayer]field(...)
towerslist[TowerKill]field(...)
barrackslist[BarracksKill]field(...)
roshanslist[RoshanKill]field(...)
aegis_eventslist[AegisEvent]field(...)
tormentorslist[TormentorKill]field(...)
shrineslist[ShrineKill]field(...)
courier_deathslist[CourierDeath]field(...)
objectiveslist[dict[str, Any]]field(...)
tower_status_radiantint0
tower_status_direint0
barracks_status_radiantint0
barracks_status_direint0
wardslist[WardEvent]field(...)
radiant_gold_advlist[int]field(...)
radiant_xp_advlist[int]field(...)
combat_loglist[CombatLogEntry]field(...)
chatlist[ChatEntry]field(...)
courier_snapshotslist[CourierSnapshot]field(...)
neutral_item_findslist[NeutralItemFoundEvent]field(...)
smoke_eventslist[SmokeEvent]field(...)
draftlist[DraftEvent]field(...)
fightslist[Fight]field(...)
opendota_teamfightslist[OpenDotaTeamfight]field(...)
vision_modifierslist[VisionModifierEvent]field(...)
banner_plantslist[BannerPlant]field(...)
game_times_minlist[int]field(...)
hero_visibility_eventslist[HeroVisibilityEvent]field(...)
vision_modifier_pairing_issueslist[VisionModifierPairingIssue]field(...)
entity_visibility_eventslist[EntityVisibilityEvent]field(...)
post_game_tickint | NoneNone
game_clockGameClock | NoneNone
parse_errorstr | NoneNone
truncated_at_tickint | NoneNone
runeslist[Rune]field(...)

Properties

duration_seconds

Signature: def ParsedMatch.duration_seconds(self) -> float

Game duration in seconds, derived from game_start_tick and game_end_tick.

Source: src/gem/results/models.py:1205

duration_minutes

Signature: def ParsedMatch.duration_minutes(self) -> float

Game duration in minutes, derived from game_start_tick and game_end_tick.

Source: src/gem/results/models.py:1211

Module gem.state.game_clock

Pause-aware conversion between replay ticks and the in-game clock.

Source: src/gem/state/game_clock.py

Top-level functions

game_clock_for

def game_clock_for(match: object) -> GameClock

Return a match's game clock, or a tick-only fallback for older matches.

Source: src/gem/state/game_clock.py:186

Top-level classes

GamePause

class GamePause

One interval during which the in-game clock was stopped.

Source: src/gem/state/game_clock.py:40

Dataclass fields

NameTypeDefault
start_tickint-
end_tickint | None-

Properties

duration_ticks

Signature: def GamePause.duration_ticks(self) -> int | None

Paused length in ticks, or None for a pause that never ended.

Source: src/gem/state/game_clock.py:53

GameClock

class GameClock

Maps replay ticks to pause-aware in-game time and back.

Source: src/gem/state/game_clock.py:61

Dataclass fields

NameTypeDefault
game_start_tickint | NoneNone
pauseslist[GamePause]field(...)
game_start_time_sfloat | NoneNone
net_tick_offsetint0

Methods

paused_ticks_before

Signature: def GameClock.paused_ticks_before(self, tick: int) -> int

Return how many ticks of pause elapsed before tick.

Source: src/gem/state/game_clock.py:84

game_time_at

Signature: def GameClock.game_time_at(self, tick: int) -> float | None

Return the exact in-game clock reading at a replay tick.

Source: src/gem/state/game_clock.py:109

game_seconds_at

Signature: def GameClock.game_seconds_at(self, tick: int) -> int | None

Return whole in-game seconds at a replay tick, as OpenDota reports them.

Source: src/gem/state/game_clock.py:124

tick_at

Signature: def GameClock.tick_at(self, game_time_s: float) -> int | None

Return the first replay tick at which the in-game clock reads a time.

Source: src/gem/state/game_clock.py:146

format_tick

Signature: def GameClock.format_tick(self, tick: int) -> str

Format a replay tick as the in-game clock (MM:SS, -MM:SS pre-horn).

Source: src/gem/state/game_clock.py:169

GameClockTracker

class GameClockTracker

Builds the in-game clock while a replay is parsed.

Source: src/gem/state/game_clock.py:239

Methods

on_net_tick

Signature: def GameClockTracker.on_net_tick(self, net_tick: int) -> None

Record a CNETMsg_Tick.

Source: src/gem/state/game_clock.py:288

net_tick_offset

Signature: def GameClockTracker.net_tick_offset(self, tick: int) -> int

Return net_tick - tick, or 0 before any network tick.

Source: src/gem/state/game_clock.py:293

update

Signature: def GameClockTracker.update(self, entity: Entity, tick: int) -> None

Refresh the clock from the CDOTAGamerulesProxy entity.

Source: src/gem/state/game_clock.py:297

snapshot_tick_start

Signature: def GameClockTracker.snapshot_tick_start(self, entity: Entity | None) -> None

Record OpenDota's running clock at the start of an outer replay tick.

Source: src/gem/state/game_clock.py:328

observe_game_start

Signature: def GameClockTracker.observe_game_start(self, entity: Entity, tick: int) -> bool

Refresh the clock, and report whether the game has just started.

Source: src/gem/state/game_clock.py:352

track_pause

Signature: def GameClockTracker.track_pause(self, paused: bool, pause_start_net_tick: int | None, total_paused_ticks: int | None, tick: int) -> None

Record pause intervals from m_bGamePaused transitions.

Source: src/gem/state/game_clock.py:377

combat_log_time

Signature: def GameClockTracker.combat_log_time(self, timestamp: float | None, game_state: int | None) -> int | None

Return OpenDota-style game-relative time for a combat-log entry.

Source: src/gem/state/game_clock.py:413

finish

Signature: def GameClockTracker.finish(self) -> None

Close a pause still open when the replay ends.

Source: src/gem/state/game_clock.py:443

Module gem.results.serialization

JSON serialization and deserialization for :class:ParsedMatch.

Source: src/gem/results/serialization.py

Top-level functions

to_dict

def to_dict(value: Any) -> Any

Convert a supported dataclass or nested value to JSON-compatible data.

Source: src/gem/results/serialization.py:63

to_json

def to_json(match: ParsedMatch, *, analysis: MatchAnalysis | None = None, indent: int | None = None, sort_keys: bool = False) -> str

Serialize a :class:ParsedMatch to a JSON string.

Source: src/gem/results/serialization.py:82

from_dict

def from_dict(data: Mapping[str, Any]) -> ParsedMatch

Rebuild a :class:ParsedMatch from :func:to_json or :func:to_dict data.

Source: src/gem/results/serialization.py:117

load_json

def load_json(path: str | Path) -> ParsedMatch

Load a :class:ParsedMatch from a JSON file written by :func:to_json.

Source: src/gem/results/serialization.py:171