Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[UI] Results table refactor #931

Merged
merged 45 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
df87731
Add spells chool colors
1337LutZ Aug 10, 2024
f2695d7
Damage / healing / dtps table metrics WIP
1337LutZ Aug 10, 2024
2281e39
Add metrics combined totals tooltip
1337LutZ Aug 11, 2024
825688c
Add isPeriodic bool and fix spellschools
1337LutZ Aug 11, 2024
779821c
Add SpellType filtering & concat Metrics options
1337LutZ Aug 12, 2024
affd1ef
Add isProc check to ActionMetrics and pet resolvers
1337LutZ Aug 12, 2024
a7f6962
Add damage/healing crits
1337LutZ Aug 12, 2024
6d67945
Add damage done metric & dtps miss concat
1337LutZ Aug 12, 2024
009ce42
Merge branch 'master' into feature/results-refactor
1337LutZ Aug 12, 2024
2a8fd53
Merge threat metrics
1337LutZ Aug 13, 2024
6e6c581
Remove unused metrics
1337LutZ Aug 13, 2024
04112a0
Remove console log
1337LutZ Aug 13, 2024
efa11b2
Fix typo
1337LutZ Aug 13, 2024
161074f
Fix healing prop missing
1337LutZ Aug 13, 2024
56fd1f4
de-compact H/DPS values & only ignore moving pets
1337LutZ Aug 13, 2024
ac56896
Add healing hit/crit metric & Unholy Strength crits
1337LutZ Aug 13, 2024
6d46845
Updated tests due to Unholy Strength heals being able to crit
1337LutZ Aug 13, 2024
4aa86a4
Add DPET and fallback string to formatter
1337LutZ Aug 13, 2024
22204b6
Fix aura pet movement filter
1337LutZ Aug 13, 2024
5b67e05
Remove DPASP & refactor topline results to table
1337LutZ Aug 13, 2024
bfa6624
Change field tmi to old dpasp field number
1337LutZ Aug 14, 2024
ab583eb
Add IsPassiveAction
1337LutZ Aug 14, 2024
e5e8098
PR Feedback
1337LutZ Aug 15, 2024
7c3457a
Add more PassiveSpell flags
1337LutZ Aug 15, 2024
b711226
Normalize cast / hits
1337LutZ Aug 15, 2024
2332ab0
Add glancing, blocks, crit blocked damage
1337LutZ Aug 15, 2024
4c8d8ef
Add accidental removed shoulder name
1337LutZ Aug 15, 2024
5506eb5
Add missing CritBlocks metric
1337LutZ Aug 15, 2024
46d756a
Fix descriptive comments
1337LutZ Aug 15, 2024
c30c5c0
WIP adding ticks/crit ticks
1337LutZ Aug 15, 2024
b0af6a7
Add Dot tick metrics
1337LutZ Aug 15, 2024
f98e933
Remove spelltype, add proxy spell outcomes for non-hit additions and …
1337LutZ Aug 16, 2024
e68e45c
Fix summon action ID names
1337LutZ Aug 16, 2024
3fb97e1
PR feedback: hardcode spellschools in FE
1337LutZ Aug 16, 2024
a5b3086
Fix logs layout & add NoCounter outcomes
1337LutZ Aug 16, 2024
bbb1a38
Disabled recuperate heal dot
1337LutZ Aug 16, 2024
4a3f100
Fix Casts column & update subtlety test
1337LutZ Aug 16, 2024
909c393
a few style tweaks on results refactor
kayla-glick Aug 17, 2024
2fe7782
Merge pull request #934 from wowsims/feature/results-refactor-style-t…
kayla-glick Aug 17, 2024
1b8f714
Fix InDebt findings
1337LutZ Aug 17, 2024
42bbda4
Fix mind sear metrics
1337LutZ Aug 17, 2024
2fffcfe
[Metrics] Add correct cast time metrics for channels
Aug 18, 2024
0fee7ef
Fix TotalCastTime metric for channels being 0
1337LutZ Aug 18, 2024
fadaaa8
Merge branch 'master' into feature/results-refactor
1337LutZ Aug 19, 2024
40342d8
Merge branch 'master' into feature/results-refactor
1337LutZ Aug 20, 2024
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
16 changes: 16 additions & 0 deletions proto/api.proto
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,13 @@ message SimOptions {
bool use_labeled_rands = 9; // Use test level RNG.
}

enum SpellType {
SpellTypeCast = 0;
1337LutZ marked this conversation as resolved.
Show resolved Hide resolved
SpellTypePeriodic = 1;
// Needed for Frontend
SpellTypeAll = 2;
}

// The aggregated results from all uses of a particular action.
message ActionMetrics {
ActionID id = 1;
Expand All @@ -154,6 +161,9 @@ message ActionMetrics {
// Note that some spells are untargeted, these will always have a single
// element in this array.
repeated TargetedActionMetrics targets = 3;

int32 spell_school = 4;
SpellType spell_type = 5;
}

// Metrics for a specific action, when cast at a particular target.
Expand Down Expand Up @@ -188,12 +198,18 @@ message TargetedActionMetrics {
// Total damage done to this target by this action.
double damage = 9;

// Total critical damage done to this target by this action.
double crit_damage = 15;

// Total threat done to this target by this action.
double threat = 10;

// Total healing done to this target by this action.
double healing = 11;

// Total critical healing done to this target by this action.
double crit_healing = 16;

// Total shielding done to this target by this action.
double shielding = 13;

Expand Down
73 changes: 45 additions & 28 deletions sim/core/metrics_aggregator.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,13 @@ type CharacterIterationMetrics struct {
}

type ActionMetrics struct {
IsMelee bool // True if melee action, false if spell action.
IsMelee bool // True if melee action, false if spell action.
SpellType proto.SpellType // Spell is cast, periodic (DoT or HoT) or both

// Metrics for this action, for each possible target.
Targets []TargetedActionMetrics

SpellSchool SpellSchool
1337LutZ marked this conversation as resolved.
Show resolved Hide resolved
}

type tmiListItem struct {
Expand All @@ -137,9 +140,11 @@ func (actionMetrics *ActionMetrics) ToProto(actionID ActionID) *proto.ActionMetr
}

return &proto.ActionMetrics{
Id: actionID.ToProto(),
IsMelee: actionMetrics.IsMelee,
Targets: targetMetrics,
Id: actionID.ToProto(),
IsMelee: actionMetrics.IsMelee,
SpellType: actionMetrics.SpellType,
Targets: targetMetrics,
SpellSchool: int32(actionMetrics.SpellSchool),
}
}

Expand All @@ -155,11 +160,13 @@ type SpellMetrics struct {
Parries int32
Blocks int32

TotalDamage float64 // Damage done by all casts of this spell.
TotalThreat float64 // Threat generated by all casts of this spell.
TotalHealing float64 // Healing done by all casts of this spell.
TotalShielding float64 // Shielding done by all casts of this spell.
TotalCastTime time.Duration
TotalDamage float64 // Damage done by all casts of this spell.
TotalCritDamage float64 // Damage done by all critical casts of this spell.
TotalThreat float64 // Threat generated by all casts of this spell.
TotalHealing float64 // Healing done by all casts of this spell.
TotalCritHealing float64 // Healing done by all critical casts of this spell.
TotalShielding float64 // Shielding done by all casts of this spell.
TotalCastTime time.Duration
}

type TargetedActionMetrics struct {
Expand All @@ -174,30 +181,34 @@ type TargetedActionMetrics struct {
Blocks int32
Glances int32

Damage float64
Threat float64
Healing float64
Shielding float64
CastTime time.Duration
Damage float64
CritDamage float64
Threat float64
Healing float64
CritHealing float64
Shielding float64
CastTime time.Duration
}

func (tam *TargetedActionMetrics) ToProto() *proto.TargetedActionMetrics {
return &proto.TargetedActionMetrics{
UnitIndex: tam.UnitIndex,

Casts: tam.Casts,
Hits: tam.Hits,
Crits: tam.Crits,
Misses: tam.Misses,
Dodges: tam.Dodges,
Parries: tam.Parries,
Blocks: tam.Blocks,
Glances: tam.Glances,
Damage: tam.Damage,
Threat: tam.Threat,
Healing: tam.Healing,
Shielding: tam.Shielding,
CastTimeMs: float64(tam.CastTime.Milliseconds()),
Casts: tam.Casts,
Hits: tam.Hits,
Crits: tam.Crits,
Misses: tam.Misses,
Dodges: tam.Dodges,
Parries: tam.Parries,
Blocks: tam.Blocks,
Glances: tam.Glances,
Damage: tam.Damage,
CritDamage: tam.CritDamage,
Threat: tam.Threat,
Healing: tam.Healing,
CritHealing: tam.CritHealing,
Shielding: tam.Shielding,
CastTimeMs: float64(tam.CastTime.Milliseconds()),
}
}

Expand Down Expand Up @@ -308,7 +319,11 @@ func (unitMetrics *UnitMetrics) addSpellMetrics(spell *Spell, actionID ActionID,
}

if !ok {
actionMetrics = &ActionMetrics{IsMelee: spell.Flags.Matches(SpellFlagMeleeMetrics)}
spellType := proto.SpellType_SpellTypeCast
if spell.dots != nil {
1337LutZ marked this conversation as resolved.
Show resolved Hide resolved
spellType = proto.SpellType_SpellTypePeriodic
}
actionMetrics = &ActionMetrics{IsMelee: spell.Flags.Matches(SpellFlagMeleeMetrics), SpellType: spellType, SpellSchool: spell.SpellSchool}
unitMetrics.actions[actionID] = actionMetrics
}

Expand All @@ -331,8 +346,10 @@ func (unitMetrics *UnitMetrics) addSpellMetrics(spell *Spell, actionID ActionID,
tam.Blocks += spellTargetMetrics.Blocks
tam.Glances += spellTargetMetrics.Glances
tam.Damage += spellTargetMetrics.TotalDamage
tam.CritDamage += spellTargetMetrics.TotalCritDamage
tam.Threat += spellTargetMetrics.TotalThreat
tam.Healing += spellTargetMetrics.TotalHealing
tam.CritHealing += spellTargetMetrics.TotalCritHealing
tam.Shielding += spellTargetMetrics.TotalShielding
tam.CastTime += spellTargetMetrics.TotalCastTime

Expand Down
10 changes: 7 additions & 3 deletions sim/core/sim_concurrent.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,11 @@ func (rsrc *raidSimResultCombiner) addActionMetrics(unit *proto.UnitMetrics, add

if am == nil {
am = &proto.ActionMetrics{
Id: add.Id,
IsMelee: add.IsMelee,
Targets: make([]*proto.TargetedActionMetrics, len(add.Targets)),
Id: add.Id,
IsMelee: add.IsMelee,
SpellType: add.SpellType,
Targets: make([]*proto.TargetedActionMetrics, len(add.Targets)),
SpellSchool: add.SpellSchool,
}
for i, addTgt := range add.Targets {
am.Targets[i] = &proto.TargetedActionMetrics{
Expand All @@ -178,8 +180,10 @@ func (rsrc *raidSimResultCombiner) addActionMetrics(unit *proto.UnitMetrics, add
baseTgt.Blocks += addTgt.Blocks
baseTgt.Glances += addTgt.Glances
baseTgt.Damage += addTgt.Damage
baseTgt.CritDamage += addTgt.CritDamage
baseTgt.Threat += addTgt.Threat
baseTgt.Healing += addTgt.Healing
baseTgt.CritHealing += addTgt.CritHealing
baseTgt.Shielding += addTgt.Shielding
baseTgt.CastTimeMs += addTgt.CastTimeMs
}
Expand Down
10 changes: 8 additions & 2 deletions sim/core/spell_result.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,9 @@ func (spell *Spell) CalcAndDealOutcome(sim *Simulation, target *Unit, outcomeApp
func (spell *Spell) dealDamageInternal(sim *Simulation, isPeriodic bool, result *SpellResult) {
if sim.CurrentTime >= 0 {
spell.SpellMetrics[result.Target.UnitIndex].TotalDamage += result.Damage
if result.DidCrit() {
spell.SpellMetrics[result.Target.UnitIndex].TotalCritDamage += result.Damage
}
spell.SpellMetrics[result.Target.UnitIndex].TotalThreat += result.Threat
}

Expand All @@ -291,9 +294,9 @@ func (spell *Spell) dealDamageInternal(sim *Simulation, isPeriodic bool, result

if sim.Log != nil {
if isPeriodic {
spell.Unit.Log(sim, "%s %s tick %s. (Threat: %0.3f)", result.Target.LogLabel(), spell.ActionID, result.DamageString(), result.Threat)
spell.Unit.Log(sim, "%s %s tick %s (SpellSchool: %d). (Threat: %0.3f)", result.Target.LogLabel(), spell.ActionID, result.DamageString(), spell.SpellSchool, result.Threat)
} else {
spell.Unit.Log(sim, "%s %s %s. (Threat: %0.3f)", result.Target.LogLabel(), spell.ActionID, result.DamageString(), result.Threat)
spell.Unit.Log(sim, "%s %s %s (SpellSchool: %d). (Threat: %0.3f)", result.Target.LogLabel(), spell.ActionID, result.DamageString(), spell.SpellSchool, result.Threat)
}
}

Expand Down Expand Up @@ -399,6 +402,9 @@ func (dot *Dot) SnapshotHeal(target *Unit, baseHealing float64) {

// Applies the fully computed spell result to the sim.
func (spell *Spell) dealHealingInternal(sim *Simulation, isPeriodic bool, result *SpellResult) {
if result.DidCrit() {
spell.SpellMetrics[result.Target.UnitIndex].TotalCritHealing += result.Damage
}
spell.SpellMetrics[result.Target.UnitIndex].TotalHealing += result.Damage
spell.SpellMetrics[result.Target.UnitIndex].TotalThreat += result.Threat
if result.Target.HasHealthBar() {
Expand Down
2 changes: 1 addition & 1 deletion sim/death_knight/blood/blood.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func (bdk *BloodDeathKnight) ApplyTalents() {
shieldSpell := bdk.GetOrRegisterSpell(core.SpellConfig{
ActionID: core.ActionID{SpellID: 77535},
ProcMask: core.ProcMaskSpellHealing,
SpellSchool: core.SpellSchoolPhysical,
SpellSchool: core.SpellSchoolShadow,

DamageMultiplier: 1,
ThreatMultiplier: 1,
Expand Down
2 changes: 1 addition & 1 deletion sim/death_knight/death_strike.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func (dk *DeathKnight) registerDeathStrikeSpell() {
ClassSpellMask: DeathKnightSpellDeathStrikeHeal,

DamageMultiplier: 1,
ThreatMultiplier: 1,
rosenrusinov marked this conversation as resolved.
Show resolved Hide resolved
ThreatMultiplier: 0,
})

doHealing := func(sim *core.Simulation, value float64) {
Expand Down
41 changes: 15 additions & 26 deletions ui/core/components/detailed_results.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { ref } from 'tsx-vanilla';

import { REPO_NAME } from '../constants/other';
import { DetailedResultsUpdate, SimRun, SimRunData } from '../proto/ui';
import { SimResult } from '../proto_utils/sim_result';
Expand All @@ -8,18 +6,16 @@ import { TypedEvent } from '../typed_event';
import { Component } from './component';
import { AuraMetricsTable } from './detailed_results/aura_metrics';
import { CastMetricsTable } from './detailed_results/cast_metrics';
import { DamageMetricsTable } from './detailed_results/damage_metrics';
import { DpsHistogram } from './detailed_results/dps_histogram';
import { DtpsMeleeMetricsTable } from './detailed_results/dtps_melee_metrics';
import { DtpsSpellMetricsTable } from './detailed_results/dtps_spell_metrics';
import { DtpsMetricsTable } from './detailed_results/dtps_metrics';
import { HealingMetricsTable } from './detailed_results/healing_metrics';
import { LogRunner } from './detailed_results/log_runner';
import { MeleeMetricsTable } from './detailed_results/melee_metrics';
import { PlayerDamageMetricsTable } from './detailed_results/player_damage';
import { PlayerDamageTakenMetricsTable } from './detailed_results/player_damage_taken';
import { ResourceMetricsTable } from './detailed_results/resource_metrics';
import { SimResultData } from './detailed_results/result_component';
import { ResultsFilter } from './detailed_results/results_filter';
import { SpellMetricsTable } from './detailed_results/spell_metrics';
import { Timeline } from './detailed_results/timeline';
import { ToplineResults } from './detailed_results/topline_results';
import { RaidSimResultsManager } from './raid_sim_action';
Expand All @@ -38,17 +34,17 @@ const tabs: Tab[] = [
isActive: true,
targetId: 'damageTab',
label: 'Damage',
classes: ['damage-metrics'],
classes: ['damage-metrics-tab'],
},
{
targetId: 'healingTab',
label: 'Healing',
classes: ['healing-metrics'],
classes: ['healing-metrics-tab'],
},
{
targetId: 'damageTakenTab',
label: 'Damage Taken',
classes: ['threat-metrics'],
classes: ['threat-metrics-tab'],
},
{
targetId: 'buffsTab',
Expand Down Expand Up @@ -125,11 +121,14 @@ export abstract class DetailedResults extends Component {
<div className="player-damage-metrics" />
</div>
<div className="dr-row single-player-only">
<div className="damage-metrics" />
</div>
{/* <div className="dr-row single-player-only">
<div className="melee-metrics" />
</div>
<div className="dr-row single-player-only">
<div className="spell-metrics" />
</div>
</div> */}
<div className="dr-row dps-histogram" />
</div>
<div id="healingTab" className="tab-pane dr-tab-content healing-content fade">
Expand All @@ -145,10 +144,7 @@ export abstract class DetailedResults extends Component {
<div className="player-damage-taken-metrics" />
</div>
<div className="dr-row single-player-only">
<div className="dtps-melee-metrics" />
</div>
<div className="dr-row single-player-only">
<div className="dtps-spell-metrics" />
<div className="dtps-metrics" />
</div>
<div className="dr-row damage-taken-histogram single-player-only" />
</div>
Expand Down Expand Up @@ -218,14 +214,11 @@ export abstract class DetailedResults extends Component {
parent: this.rootElem.querySelector('.cast-metrics')!,
resultsEmitter: this.resultsEmitter,
});
new MeleeMetricsTable({
parent: this.rootElem.querySelector('.melee-metrics')!,
resultsEmitter: this.resultsEmitter,
});
new SpellMetricsTable({
parent: this.rootElem.querySelector('.spell-metrics')!,
new DamageMetricsTable({
parent: this.rootElem.querySelector('.damage-metrics')!,
resultsEmitter: this.resultsEmitter,
});

new HealingMetricsTable({
parent: this.rootElem.querySelector('.healing-spell-metrics')!,
resultsEmitter: this.resultsEmitter,
Expand Down Expand Up @@ -262,12 +255,8 @@ export abstract class DetailedResults extends Component {
resultsEmitter: this.resultsEmitter,
});

new DtpsMeleeMetricsTable({
parent: this.rootElem.querySelector('.dtps-melee-metrics')!,
resultsEmitter: this.resultsEmitter,
});
new DtpsSpellMetricsTable({
parent: this.rootElem.querySelector('.dtps-spell-metrics')!,
new DtpsMetricsTable({
parent: this.rootElem.querySelector('.dtps-metrics')!,
resultsEmitter: this.resultsEmitter,
});

Expand Down
17 changes: 12 additions & 5 deletions ui/core/components/detailed_results/aura_metrics.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { OtherAction } from '../../proto/common';
import { AuraMetrics, SimResult, SimResultFilter } from '../../proto_utils/sim_result';
import { ColumnSortType, MetricsTable } from './metrics_table';
import { ColumnSortType, MetricsTable } from './metrics_table/metrics_table';
import { ResultComponent, ResultComponentConfig, SimResultData } from './result_component';

export class AuraMetricsTable extends MetricsTable<AuraMetrics> {
Expand Down Expand Up @@ -52,19 +53,25 @@ export class AuraMetricsTable extends MetricsTable<AuraMetrics> {
}
const player = players[0];

const auras = player.auras;
const auras = this.filterMetrics(player.auras);
const actionGroups = AuraMetrics.groupById(auras);
const petGroups = player.pets.map(pet => pet.auras);

const petGroups = player.pets.map(pet => this.filterMetrics(pet.auras));
return actionGroups.concat(petGroups);
}
}

mergeMetrics(metrics: Array<AuraMetrics>): AuraMetrics {
return AuraMetrics.merge(metrics, true, metrics[0].unit?.petActionId || undefined);
return AuraMetrics.merge(metrics, {
removeTag: true,
actionIdOverride: metrics[0].unit?.petActionId || undefined,
});
}

shouldCollapse(metric: AuraMetrics): boolean {
return !metric.unit?.isPet;
}

filterMetrics(metrics: Array<AuraMetrics>): Array<AuraMetrics> {
return metrics.filter(aura => aura.actionId.otherId !== OtherAction.OtherActionMove);
}
1337LutZ marked this conversation as resolved.
Show resolved Hide resolved
}
Loading
Loading