Skip to content
This repository was archived by the owner on Oct 11, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 26 additions & 21 deletions libs/gw2_analytics/src/gw2_analytics/ei_compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from gw2_analytics.initial_buffs import extract_initial_buffs
from gw2_analytics.rotation import build_skill_rotation
from gw2_core import (
Agent,
BlockEvent,
BoonApplyEvent,
BuffApplyEvent,
Expand Down Expand Up @@ -236,7 +237,10 @@ def compare_elite_insights( # noqa: PLR0912, PLR0915
agents_by_account = {
agent.account_name.lstrip(":"): agent for agent in fight.agents if agent.account_name
}
agents_by_instance = {agent.instance_id: agent for agent in fight.agents if agent.instance_id}
agents_by_instance: dict[int, Agent] = {}
for fight_agent in fight.agents:
if fight_agent.instance_id:
agents_by_instance.setdefault(fight_agent.instance_id, fight_agent)
agent_ids_by_instance: dict[int, set[int]] = defaultdict(set)
for fight_agent in fight.agents:
if fight_agent.instance_id:
Expand Down Expand Up @@ -298,7 +302,7 @@ def compare_elite_insights( # noqa: PLR0912, PLR0915
continue
account = player["account"]
instance_id = player.get("instanceID")
agent = agents_by_account.get(account)
agent: Agent | None = agents_by_account.get(account)
if agent is None and isinstance(instance_id, int):
agent = agents_by_instance.get(instance_id)
if agent is None:
Expand Down Expand Up @@ -362,6 +366,13 @@ def compare_elite_insights( # noqa: PLR0912, PLR0915
for event in event_list
if isinstance(event, DownEvent) and event.source_agent_id in agent_ids
]
outcome_downs = {
event.time_ms
for event in event_list
if isinstance(event, CombatOutcomeEvent)
and event.outcome == "downed"
and event.target_agent_id in agent_ids
}
defense_values = {
"damageTaken": sum(event.damage for event in taken),
"damageTakenCount": sum(_connected(event) for event in taken),
Expand All @@ -379,36 +390,30 @@ def compare_elite_insights( # noqa: PLR0912, PLR0915
isinstance(event, DodgeEvent) and event.source_agent_id == agent.id
for event in event_list
),
"downCount": len(
{
event.time_ms
for event in event_list
if isinstance(event, BoonApplyEvent)
and event.kind == "apply"
and event.skill_id == 770
and event.target_agent_id in agent_ids
}
)
or (
len(downed)
if anonymous
"downCount": (
len(outcome_downs)
if outcome_downs and not anonymous
else len(
{
event.time_ms
for event in event_list
if (
isinstance(event, CombatOutcomeEvent)
and event.outcome == "downed"
and event.target_agent_id in agent_ids
)
if isinstance(event, BoonApplyEvent)
and event.kind == "apply"
and event.skill_id == 770
and event.target_agent_id in agent_ids
}
)
)
or (
len(downed)
if anonymous
else len(outcome_downs)
if not has_downed_buff_applies
else 0
),
"downDuration": sum(event.downtime_ms for event in downed),
"deadCount": sum(
isinstance(event, DeathEvent) and event.source_agent_id == agent.id
isinstance(event, DeathEvent) and event.source_agent_id in agent_ids
for event in event_list
),
}
Expand Down
113 changes: 113 additions & 0 deletions libs/gw2_analytics/tests/test_ei_compare.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
from __future__ import annotations

from typing import Any

from gw2_analytics.ei_compare import compare_elite_insights
from gw2_core import (
Agent,
BoonApplyEvent,
CombatOutcomeEvent,
DeathEvent,
EliteSpec,
Fight,
Profession,
)


def test_compare_elite_insights_keeps_first_anonymous_agent_for_shared_instance() -> None:
fight = Fight(
id="fight",
agents=[
Agent(
id=1,
name="Chronomancienne",
profession=Profession.MESMER,
elite=EliteSpec.CHRONOMANCER,
is_player=True,
instance_id=3994,
),
Agent(
id=2,
name="Virtuose",
profession=Profession.MESMER,
elite=EliteSpec.VIRTUOSO,
is_player=True,
instance_id=3994,
),
],
)
expected: dict[str, Any] = {
"players": [
{
"account": "Non Squad Player 5",
"instanceID": 3994,
"name": "Chronomancer pl-3994",
"defenses": [{"deadCount": 2}],
}
]
}
events = [
DeathEvent(time_ms=1, source_agent_id=1, target_agent_id=0, skill_id=0),
DeathEvent(time_ms=2, source_agent_id=2, target_agent_id=0, skill_id=0),
]

result = compare_elite_insights(fight, expected, events)

assert result["differences"] == {}


def test_compare_elite_insights_prefers_outcome_downs_for_named_players() -> None:
fight = Fight(
id="fight",
agents=[
Agent(
id=1,
name="Player",
profession=Profession.MESMER,
elite=EliteSpec.CHRONOMANCER,
is_player=True,
account_name=":Player.1234",
instance_id=1111,
)
],
)
expected: dict[str, Any] = {
"players": [
{
"account": "Player.1234",
"name": "Player",
"defenses": [{"downCount": 1}],
}
]
}
events = [
CombatOutcomeEvent(
time_ms=100,
source_agent_id=2,
target_agent_id=1,
skill_id=42,
outcome="downed",
),
BoonApplyEvent(
time_ms=100,
source_agent_id=0,
target_agent_id=1,
skill_id=770,
duration_ms=2_147_483_647,
stacks=1,
kind="apply",
),
BoonApplyEvent(
time_ms=200,
source_agent_id=0,
target_agent_id=1,
skill_id=770,
duration_ms=2_147_483_647,
stacks=1,
kind="apply",
),
]

result = compare_elite_insights(fight, expected, events)

assert result["differences"] == {}
Loading