Result delivery has several boundaries

BoundaryMeaningAccounting consequence
Avatar receiptCompact results are decoded, saved, published and acknowledged.Separate battle receipt from lobby presentation.
Account retrievalCached or streamed full result is retrieved.Retrieval success does not identify a new battle.
Service postingPresenter is stored by arena, notified, then onResultPosted fires.Repeated posts can replace the presenter and emit again.
Cached service requestRetained presenter is re-announced.No new post event is required; reopening is not another battle.
Additional-XP refreshResult data can change inside a retained Gameface presenter.A revision can occur without another onResultPosted.

Upsert result revisions

There is no single exactly-once final-result event covering all retrieval, presentation and refresh paths. Key persistent contribution by account and arena, keep a content revision/fingerprint where appropriate, and replace the prior contribution when the supported aggregate changes. Counting every post duplicates a battle; ignoring all later data for that arena loses revisions.

Separate presentation options from passivity. A UI-related flag does not establish that every downstream branch avoids creating or re-announcing a presenter. Trace the selected mode/controller and observe the actual cache owner. A result object or presenter can be replaced; reacquire it after refresh.

Totals and details are not additive peers

Vehicle summaries retain detailed records and can add separate avatar contributions for fields such as damage/kills. The summary iterator yields the total before its detail rows. Economics record iterators have the same aggregate-first shape. With detail values 100 and 50, iterating yields 150, 100 and 50; summing every row gives 300.

Use the provided total once or aggregate details with the separate contributions accounted for. Achievements can be unioned rather than summed, and summary respawns can be total rollouts minus one. An empty shared summary can consequently expose -1: treat that as missing meaningful summary data, not a negative server respawn.

The representative vehicle is a GUI-ordered detail record, not necessarily the first-used, last-used or final-life vehicle. Summary IDs, arena entity IDs, account IDs and type descriptors remain different domains. Zero-valued fallback identity/short-info records are not positive survival or roster-completeness evidence.

Economic columns are scenarios

Base, premium, premium-plus, additional-XP and subscription records are parallel account scenarios. Their presence does not establish active entitlement or multiple rewards to add together. Select the recorded actual-account scenario separately from comparison columns. Keep battle XP and free XP distinct.

Personal displayed XP, team-sort XP, penalty-adjusted ranking and raw replay economics can use different fields. For example, an ordinary team sort can use XP while another subtracts a penalty. A displayed nonnegative value also need not preserve a raw signed input. Retain the selected getter/scenario with exports rather than naming every result field simply XP.

Signed costs and currency scope

Normalized repair, ammunition and equipment expense records are already negative. The expense-aware extractor adds those signed records to income even though a configuration field is named subtractRecords. Subtracting them again increases the result incorrectly.

The credit headline getter selects income without every expense record, so it is not a profit getter. For example, income of 12,500 and credit expenses of 4,200 give an expense-adjusted total of 8,300. Choose the extractor that answers the question you are displaying.

Credits, gold and crystals have separate paths. Do not fold a gold outflow into credits without an explicit valuation policy. Some costs occur in both detailed currency streams and additional records; combining both can charge one expense twice. Missing/None and explicit-zero costs can all read as zero through a convenience accessor while retaining different provenance.

Dossier averages have specific denominators

Direct hits, enemy direct hits, penetrating hits and explosion hits are separate counters. The ordinary dossier hit ratio divides its directHits by shots, while the shared updater sources that counter from result directEnemyHits. Similar names across storage and result layers do not establish identical inclusion rules.

Assistance, blocked damage and stun averages can use different eligible-battle counts, including historical-version offsets or capability-based counts. Do not divide every career counter by total battles. Zero-denominator unavailable conventions are also mode-specific; one helper can return None while another returns zero.

A ratio helper need not clamp above one. Preserve the raw counter and its supported denominator, then format at the presentation boundary. An arithmetic result alone does not explain how the server generated the supplied counters.

Final aggregates cannot restore shot history

The inspected tracer interface has a shot ID, while damage feedback and final interaction counters do not expose one shared projectile key. Final interaction records preserve aggregates, not an ordered hit list or timestamps. Different synthetic damage sequences can produce the same packed totals.

Even a lookup can mutate: indexing a missing interaction tuple can create a default row and change later exports. Check membership or use the exported dictionary for passive parsing. Keep heuristic correlations explicitly inferred and reconcile only at the aggregate scope the format supports.

See delivery and replay lifecycle, baseline validity and battle data pipelines.