This document is the authoritative behavioral contract for Pizza Logs parsing. Tests and fixtures enforce it; presentation code must not silently redefine these metrics.
- Primary input: Warmane/WotLK 3.3.5a
WoWCombatLog.txtdata. - Skada-WoTLK defines the supported damage/healing event sets and effective-healing primitive.
- UwU-style views may be adopted as explicit analytical layers; they do not replace stored primitives.
- Missing, contradictory, or unsupported evidence remains
UNKNOWN, ambiguous, or unattributed.
Combat lines are parsed as bounded CSV-like records. Malformed lines are counted/skipped and surfaced as aggregate warnings rather than crashing the upload.
Calendar month/day and clock ranges are validated. Explicit dates determine elapsed time and session boundaries, so equal clock times on successive dates cannot merge separate raids. December-to-January advances the configured file year; other backwards dates or timestamps are counted as out-of-order input instead of inventing a day or year. Encounter and session ISO timestamps retain the inferred UTC year across that rollover.
Player GUIDs include:
- Warmane values beginning
0x06; - retail-style
Player-values; - compatible WotLK player-flag GUIDs.
Vehicle sources such as Gunship cannon GUIDs are not credited as player pets.
Useful ENCOUNTER_START/ENCOUNTER_END markers are consumed when present, but Warmane frequently omits or misreports them. Heuristic segmentation therefore remains required.
- Boss aliases/GUIDs identify relevant activity.
- A pull begins from normalized boss engagement evidence.
- The encounter window ends at the last boss-destination event, not a boss outgoing attack, stale marker, or unrelated post-fight trash.
- A kill ends at the boss
UNIT_DIEDtimestamp. - Lich King scripted finale/roleplay remains part of the same successful attempt.
- Gunship uses the fixture-protected Warmane crew-death success override.
Public reporting applies a separate, reversible short-pull counting policy to
stored encounters: a WIPE strictly under 60,000 ms with zero recorded participant
deaths is excluded by default. Kills, death-bearing wipes and UNKNOWN outcomes
remain included. Missing evidence is not assumed to be zero. The include-all view
restores the original attempts. This policy does not change parser segmentation,
stored outcomes, fingerprints, encounter primitives or full-session analytics; see
reading reports.
Tracked events match Skada Damage.lua:
SPELL_DAMAGE
SWING_DAMAGE
RANGE_DAMAGE
SPELL_PERIODIC_DAMAGE
DAMAGE_SHIELD
DAMAGE_SPLIT
SPELL_BUILDING_DAMAGE
For spell/range events, the raw amount is the event damage field. SWING_DAMAGE has shifted indexes because it has no spell fields:
parts[7] amount
parts[8] overkill
parts[12] absorbed
parts[13] critical
Headline encounter damage, participant damage, session Total Damage, and damage taken use the raw reported amount. Overkill and absorbed metadata may support separate useful/effective analysis but are not silently subtracted from the headline.
Damage includes every matched encounter destination, including adds/mechanics. Boss-only and target breakdowns are supplemental views.
Missed and environmental events do not add outgoing damage because they are outside the adopted Skada damage-done set or have no numeric damage amount.
ENVIRONMENTAL_DAMAGE does contribute incoming damage and death context for
player targets. Its shifted fields are environmental type at parts[7], raw
amount at parts[8], overkill at parts[9], school at parts[10], absorbed
metadata at parts[13], and critical evidence at parts[14]. Raw incoming
amounts include overkill; numeric absorbs remain separate and use the existing
shield-evidence rules. Environmental events never add outgoing player damage.
Tracked events match Skada Healing.lua:
SPELL_HEAL
SPELL_PERIODIC_HEAL
Field layout:
parts[10] gross amount
parts[11] overheal
parts[12] absorbed metadata
parts[13] critical
Effective healing is:
max(0, gross - overheal)
Every tracked heal counts; there is no invented ignored-heal list. SPELL_HEAL_ABSORBED is not healing done.
Player and known-owned-pet healing counts regardless of recipient type, including Valithria Dreamwalker, other NPCs, pets and totems. The recipient being a non-player must not remove effective healing from encounter, actor or spell totals. Source eligibility and pet-ownership evidence still apply; accepting an NPC recipient does not assign that NPC to the healer as a pet.
Absorbs remain separate from effective healing. Numeric absorbed amounts come from incoming damage events and are attributed only when supported shield-aura/source evidence exists.
- One supported active shield: attribute to its player source.
- Multiple supported shields: choose the newest eligible evidence and mark the hit ambiguous.
- A just-removed shield remains eligible for 0.5 seconds to cover combat-log ordering.
- Discipline critical-heal/Penance evidence may identify Divine Aegis ownership.
- Missing/non-player evidence remains in
unattributedAbsorbs. - Fully absorbed missed events without a numeric amount cannot be measured.
Participant output keeps totalHealing, totalAbsorbs, HPS, and APS separate. The Heal/H+A PS view equals effective healing plus attributed absorbs. This definition alone does not prove UwU attribution or display parity; see the measured parity contract.
- KILL: boss death minus pull start.
- WIPE/UNKNOWN: validated encounter end minus pull start.
dps = totalDamage / durationSecondshps = totalHealing / durationSecondsaps = totalAbsorbs / durationSeconds
Millisecond duration is preserved where available; display seconds are derived consistently.
Difficulty is classified independently per segmented attempt:
- aggregate boss-specific spell-rank evidence;
- accept one unambiguous mode;
- return
UNKNOWNon conflict; - apply explicit Ulduar encounter rules;
- use valid marker mode only as a documented supported fallback;
- otherwise remain
UNKNOWN.
Raid size alone does not imply Normal. Unsupported Hodir Hard Mode and Sartharion drake modes remain UNKNOWN. See difficulty-detector.md.
An apparent kill with unknown difficulty is retained as an attempt but not ranked as a valid kill.
SPELL_SUMMON and owner-exclusive spell evidence establish ownership. Once proven, stable creature identity may propagate ownership across repeated Warmane GUID instances. Generic player-to-pet healing is insufficient and must never steal ownership. Vehicle sources are excluded.
Fel Synergy (54181) is accepted only as SPELL_HEAL from a player to a
controlled permanent pet. Its owner-specific target is supported by the
pinned WotLK spell implementation.
An unverified spell ID or ordinary heal does not establish ownership.
- Spec is inferred only from observed WotLK spell signatures; ties/absence remain unknown.
- Role uses spec, healing share, output, and damage-taken evidence; weak evidence is not upgraded to certainty.
- Aura uptime records applications, observed seconds, and encounter percentage.
- Consumables are a curated subset of aura data.
- Power gains record energize amount/events/type by recipient and spell.
- Death events record the death offset and up to 15 seconds of prior observed incoming damage.
These paths do not alter damage/healing primitives.
Each parsed raid session stores one first-to-last-log-event Custom Slice including wipes, trash, and downtime. Total Damage, Heal, Damage Taken, and every per-player rate in that slice use the same duration.
Session Heal is explicitly effective healing plus attributed absorbs. Encounter primitives remain separate.
The report's main summary is a presentation rollup of selected stored encounters,
including their adds and mechanics. All Boss Attempts includes every recorded
KILL, WIPE and UNKNOWN attempt, including short pulls. Successful Boss Fights
selects KILL only. Its player rates divide summed primitives by the summed
duration of the same selected attempts, with valid legacy seconds used when precise
milliseconds are absent. Missing duration leaves rates unavailable. No kills means
an empty successful-fights view, not a fallback to wipes or full-session totals.
The short-pull control changes list visibility and counts without changing either
summary's totals or rates. No player or owned-pet primitives are counted twice. Original
first-to-last-event analytics remain available in a separate full-session section;
this reporting choice does not change parsing or stored data.
- File duplicate: SHA-256 of the complete received bytes.
- Encounter duplicate: SHA-256 over boss, difficulty, exact normalized pull start, and sorted participant names.
Exact starts prevent same-roster back-to-back pulls from colliding while remaining deterministic across copies of one pull.
The production web path uses POST /uploads/{uuid}/stream, with archive/resource validation and a bounded worker pool. The final payload includes the parser-observed byte count and is Zod-validated by the web service.
Legacy /parse, /parse-debug, and /parse-stream routes are disabled by default and are not used by public uploads. Arbitrary filesystem parsing is not supported.
parser/tests/test_parser_core.py- focused behavioral rulesparser/tests/test_fixtures.py- canonical fixture expectationsparser/tests/test_difficulty_detector.py- detector matrix and conflictsparser/tests/test_archive_upload.py- archive/resource safetyparser/tests/test_parser_service.py- HTTP/default-off legacy boundaryparser/tests/baselines/- frozen analytical outputparser/tests/test_uwu_parity_baseline.py- historical external-oracle integrity check (no paired source input)
Any behavior change needs focused evidence or a fixture plus the full parser suite. Historic database rows are not reparsed automatically.