1- import { ref } from 'tsx-vanilla' ;
2- import { REPO_NAME } from '../constants/other' ;
3- import { IndividualSimUI } from '../individual_sim_ui' ;
4- import { DetailedResultsUpdate , SimRun , SimRunData } from '../proto/ui' ;
1+ import { SimRun , SimRunData } from '../proto/ui' ;
52import { SimResult } from '../proto_utils/sim_result' ;
63import { SimUI } from '../sim_ui' ;
74import { TypedEvent } from '../typed_event' ;
8- import { isDevMode } from '../utils' ;
95import { Component } from './component' ;
106import { AuraMetricsTable } from './detailed_results/aura_metrics' ;
117import { CastMetricsTable } from './detailed_results/cast_metrics' ;
@@ -24,6 +20,9 @@ import { ToplineResults } from './detailed_results/topline_results';
2420import { RaidSimResultsManager } from './raid_sim_action' ;
2521import { StickyToolbar } from './sticky_toolbar' ;
2622import i18n from '../../i18n/config' ;
23+ import { ref } from 'tsx-vanilla' ;
24+ import { isDevMode } from '../utils' ;
25+ import { IndividualSimUI } from '../individual_sim_ui' ;
2726
2827type Tab = {
2928 isActive ?: boolean ;
@@ -75,24 +74,27 @@ const tabs: Tab[] = [
7574 } ,
7675] ;
7776
78- export abstract class DetailedResults extends Component {
79- protected readonly simUI : SimUI | null ;
77+ export class DetailedResults extends Component {
78+ protected readonly simUI : SimUI ;
8079 protected latestRun : SimRunData | null = null ;
81- protected latestDeathSeeds : BigInt [ ] = [ ] ;
80+ protected latestDeathSeeds : bigint [ ] = [ ] ;
8281 protected recentlyEditedSeed : boolean = false ;
8382
8483 private currentSimResult : SimResult | null = null ;
8584 private resultsEmitter : TypedEvent < SimResultData | null > = new TypedEvent < SimResultData | null > ( ) ;
8685 private resultsFilter : ResultsFilter ;
87- private rootDiv : HTMLElement ;
86+ private rootDiv : Element ;
8887
89- constructor ( parent : HTMLElement , simUI : SimUI | null , cssScheme : string ) {
88+ constructor ( parent : HTMLElement , simUI : SimUI , simResultsManager : RaidSimResultsManager ) {
9089 super ( parent , 'detailed-results-manager-root' ) ;
9190
92- this . rootElem . appendChild (
91+ this . simUI = simUI ;
92+
93+ this . rootDiv = (
9394 < div className = "dr-root dr-no-results" >
94- < div className = "dr-toolbar sticky-toolbar " >
95+ < div className = "dr-toolbar" >
9596 < div className = "results-filter" > </ div >
97+ < div className = "tabs-filler" > </ div >
9698 < ul className = "nav nav-tabs" attributes = { { role : 'tablist' } } >
9799 { tabs . map ( ( { label, targetId, isActive, classes } ) => (
98100 < li className = { `nav-item dr-tab-tab ${ classes ?. join ( ' ' ) || '' } ` } attributes = { { role : 'presentation' } } >
@@ -183,12 +185,27 @@ export abstract class DetailedResults extends Component {
183185 </ div >
184186 </ div >
185187 </ div >
186- </ div > ,
188+ </ div >
189+ ) ;
190+
191+ const simButtonRef = ref < HTMLButtonElement > ( ) ;
192+ const deathButtonRef = ref < HTMLButtonElement > ( ) ;
193+
194+ this . rootElem . appendChild (
195+ < >
196+ < div className = "detailed-results-controls-div" >
197+ < button className = "detailed-results-1-iteration-button btn btn-primary" ref = { simButtonRef } disabled = { simUI . disabled } >
198+ { i18n . t ( 'results_tab.details.sim_1_iteration' ) }
199+ </ button >
200+ < button className = "detailed-results-death-iteration-button btn btn-primary" ref = { deathButtonRef } disabled = { true } >
201+ { i18n . t ( 'results_tab.details.sim_1_death' ) }
202+ </ button >
203+ </ div >
204+ { this . rootDiv }
205+ </ > ,
187206 ) ;
188- this . rootDiv = this . rootElem . querySelector ( '.dr-root' ) ! ;
189- this . simUI = simUI ;
190207
191- this . simUI ? .sim . settingsChangeEmitter . on ( async ( ) => await this . updateSettings ( ) ) ;
208+ this . simUI . sim . settingsChangeEmitter . on ( ( ) => this . updateSettings ( ) ) ;
192209
193210 // Allow styling the sticky toolbar
194211 const toolbar = document . querySelector < HTMLElement > ( '.dr-toolbar' ) ! ;
@@ -256,7 +273,6 @@ export abstract class DetailedResults extends Component {
256273
257274 const timeline = new Timeline ( {
258275 parent : this . rootElem . querySelector ( '.timeline' ) ! ,
259- cssScheme : cssScheme ,
260276 resultsEmitter : this . resultsEmitter ,
261277 secondaryResource : ( simUI as IndividualSimUI < any > ) ?. player ?. secondaryResource ,
262278 } ) ;
@@ -268,13 +284,12 @@ export abstract class DetailedResults extends Component {
268284
269285 new LogRunner ( {
270286 parent : this . rootElem . querySelector ( '.log' ) ! ,
271- cssScheme : cssScheme ,
272287 resultsEmitter : this . resultsEmitter ,
273288 } ) ;
274289
275- this . rootElem . classList . add ( 'hide-threat-metrics' , 'hide-threat-metrics' ) ;
290+ this . rootElem . classList . add ( 'hide-threat-metrics' ) ;
276291
277- this . resultsFilter . changeEmitter . on ( ( ) => this . updateResults ( ) ) ;
292+ this . resultsFilter . changeEmitter . on ( async ( ) => await this . updateResults ( this . latestRun ) ) ;
278293
279294 this . resultsEmitter . on ( ( _ , resultData ) => {
280295 if ( resultData ?. filter . player || resultData ?. filter . player === 0 ) {
@@ -285,12 +300,68 @@ export abstract class DetailedResults extends Component {
285300 this . rootDiv . classList . remove ( 'single-player' ) ;
286301 }
287302 } ) ;
303+
304+ const simButton = simButtonRef . value ! ;
305+ simButton ?. addEventListener ( 'click' , ( ) => {
306+ this . simUI ?. runSimOnce ( ) ;
307+ } ) ;
308+
309+ const deathButton = deathButtonRef . value ! ;
310+ deathButton ?. addEventListener ( 'click' , ( ) => {
311+ if ( this . latestDeathSeeds . length > 1 ) {
312+ this . simUI ?. sim . setFixedRngSeed ( TypedEvent . nextEventID ( ) , Number ( this . latestDeathSeeds . pop ( ) ) ) ;
313+ this . recentlyEditedSeed = true ;
314+
315+ if ( isDevMode ( ) ) {
316+ console . log ( 'Setting fixed seed:' ) ;
317+ console . log ( this . simUI ?. sim . getFixedRngSeed ( ) ) ;
318+ }
319+ }
320+
321+ this . simUI ?. runSimOnce ( ) ;
322+ } ) ;
323+
324+ simResultsManager . currentChangeEmitter . on ( async ( ) => {
325+ const runData = simResultsManager . getRunData ( ) ;
326+ if ( runData ) {
327+ this . updateSettings ( ) ;
328+ await this . updateResults ( runData ) ;
329+ }
330+
331+ deathButton . disabled = this . latestDeathSeeds . length < 2 ;
332+ } ) ;
288333 }
289334
290- abstract postMessage ( update : DetailedResultsUpdate ) : Promise < void > ;
335+ private updateSettings ( ) {
336+ const settings = this . simUI ?. sim . toProto ( ) ;
337+ if ( ! settings ) return ;
338+
339+ if ( settings . showDamageMetrics ) {
340+ this . rootElem . classList . remove ( 'hide-damage-metrics' ) ;
341+ } else {
342+ this . rootElem . classList . add ( 'hide-damage-metrics' ) ;
343+ const damageTabEl = document . getElementById ( 'damageTab' ) ! ;
344+ const healingTabEl = document . getElementById ( 'healingTab' ) ! ;
345+ if ( damageTabEl . classList . contains ( 'active' ) ) {
346+ damageTabEl . classList . remove ( 'active' , 'show' ) ;
347+ healingTabEl . classList . add ( 'active' , 'show' ) ;
348+
349+ const toolbar = document . getElementsByClassName ( 'dr-toolbar' ) [ 0 ] as HTMLElement ;
350+ toolbar . querySelector ( '.damage-metrics' ) ?. children [ 0 ] . classList . remove ( 'active' ) ;
351+ toolbar . querySelector ( '.healing-metrics' ) ?. children [ 0 ] . classList . add ( 'active' ) ;
352+ }
353+ }
354+ this . rootElem . classList [ settings . showThreatMetrics ? 'remove' : 'add' ] ( 'hide-threat-metrics' ) ;
355+ this . rootElem . classList [ settings . showHealingMetrics ? 'remove' : 'add' ] ( 'hide-healing-metrics' ) ;
356+ this . rootElem . classList [ settings . showExperimental ? 'remove' : 'add' ] ( 'hide-experimental' ) ;
357+ }
358+
359+ private async updateResults ( simRunData : SimRunData | null ) {
360+ if ( simRunData ?. run ?. request ?. requestId !== this . latestRun ?. run ?. request ?. requestId ) {
361+ this . latestRun = simRunData ;
362+ this . currentSimResult = await SimResult . fromProto ( simRunData ?. run || SimRun . create ( ) ) ;
363+ }
291364
292- protected async setSimRunData ( simRunData : SimRunData ) {
293- this . latestRun = simRunData ;
294365 const latestSimResult = this . latestRun ?. run ?. result ;
295366 const playerMetrics = latestSimResult ?. raidMetrics ?. parties . map ( party => party . players ) . flat ( ) ;
296367
@@ -302,7 +373,7 @@ export abstract class DetailedResults extends Component {
302373 if ( playerMetrics ?. length ) {
303374 const deathSeeds = playerMetrics [ 0 ] . deathSeeds ;
304375
305- if ( isDevMode ( ) && deathSeeds . length > 0 ) {
376+ if ( isDevMode ( ) && ! ! deathSeeds . length ) {
306377 console . log ( 'Found death seeds:' ) ;
307378 console . log ( deathSeeds ) ;
308379 }
@@ -312,35 +383,6 @@ export abstract class DetailedResults extends Component {
312383 }
313384 }
314385
315- await this . postMessage (
316- DetailedResultsUpdate . create ( {
317- data : {
318- oneofKind : 'runData' ,
319- runData : simRunData ,
320- } ,
321- } ) ,
322- ) ;
323- }
324-
325- protected async updateSettings ( ) {
326- if ( ! this . simUI ) return ;
327-
328- if ( this . recentlyEditedSeed ) {
329- this . simUI . sim . setFixedRngSeed ( TypedEvent . nextEventID ( ) , 0 ) ;
330- this . recentlyEditedSeed = false ;
331- }
332-
333- await this . postMessage (
334- DetailedResultsUpdate . create ( {
335- data : {
336- oneofKind : 'settings' ,
337- settings : this . simUI . sim . toProto ( ) ,
338- } ,
339- } ) ,
340- ) ;
341- }
342-
343- private updateResults ( ) {
344386 const eventID = TypedEvent . nextEventID ( ) ;
345387 if ( this . currentSimResult == null ) {
346388 this . rootDiv . classList . add ( 'dr-no-results' ) ;
@@ -354,133 +396,4 @@ export abstract class DetailedResults extends Component {
354396 } ) ;
355397 }
356398 }
357-
358- protected async handleMessage ( data : DetailedResultsUpdate ) {
359- switch ( data . data . oneofKind ) {
360- case 'runData' :
361- const runData = data . data . runData ;
362- this . currentSimResult = await SimResult . fromProto ( runData . run || SimRun . create ( ) ) ;
363- this . updateResults ( ) ;
364- break ;
365- case 'settings' :
366- const settings = data . data . settings ;
367- if ( settings . showDamageMetrics ) {
368- this . rootElem . classList . remove ( 'hide-damage-metrics' ) ;
369- } else {
370- this . rootElem . classList . add ( 'hide-damage-metrics' ) ;
371- const damageTabEl = document . getElementById ( 'damageTab' ) ! ;
372- const healingTabEl = document . getElementById ( 'healingTab' ) ! ;
373- if ( damageTabEl . classList . contains ( 'active' ) ) {
374- damageTabEl . classList . remove ( 'active' , 'show' ) ;
375- healingTabEl . classList . add ( 'active' , 'show' ) ;
376-
377- const toolbar = document . getElementsByClassName ( 'dr-toolbar' ) [ 0 ] as HTMLElement ;
378- toolbar . querySelector ( '.damage-metrics' ) ?. children [ 0 ] . classList . remove ( 'active' ) ;
379- toolbar . querySelector ( '.healing-metrics' ) ?. children [ 0 ] . classList . add ( 'active' ) ;
380- }
381- }
382- this . rootElem . classList [ settings . showThreatMetrics ? 'remove' : 'add' ] ( 'hide-threat-metrics' ) ;
383- this . rootElem . classList [ settings . showHealingMetrics ? 'remove' : 'add' ] ( 'hide-healing-metrics' ) ;
384- this . rootElem . classList [ settings . showExperimental ? 'remove' : 'add' ] ( 'hide-experimental' ) ;
385- break ;
386- }
387- }
388- }
389-
390- export class WindowedDetailedResults extends DetailedResults {
391- constructor ( parent : HTMLElement ) {
392- super ( parent , null , new URLSearchParams ( window . location . search ) . get ( 'cssScheme' ) ?? '' ) ;
393-
394- window . addEventListener ( 'message' , async event => await this . handleMessage ( DetailedResultsUpdate . fromJson ( event . data ) ) ) ;
395-
396- this . rootElem . insertAdjacentHTML ( 'beforeend' , `<div class="sim-bg"></div>` ) ;
397- }
398-
399- async postMessage ( update : DetailedResultsUpdate ) : Promise < void > {
400- await this . handleMessage ( update ) ;
401- }
402- }
403-
404- export class EmbeddedDetailedResults extends DetailedResults {
405- private tabWindow : Window | null = null ;
406-
407- constructor ( parent : HTMLElement , simUI : SimUI , simResultsManager : RaidSimResultsManager ) {
408- super ( parent , simUI , simUI . config . cssScheme ) ;
409-
410- const newTabButtonRef = ref < HTMLButtonElement > ( ) ;
411- const simButtonRef = ref < HTMLButtonElement > ( ) ;
412- const deathButtonRef = ref < HTMLButtonElement > ( ) ;
413-
414- this . rootElem . prepend (
415- < div className = "detailed-results-controls-div" >
416- < button className = "detailed-results-new-tab-button btn btn-primary" ref = { newTabButtonRef } disabled = { simUI . disabled } >
417- { i18n . t ( 'results_tab.details.view_in_separate_tab' ) }
418- </ button >
419- < button className = "detailed-results-1-iteration-button btn btn-primary" ref = { simButtonRef } disabled = { simUI . disabled } >
420- { i18n . t ( 'results_tab.details.sim_1_iteration' ) }
421- </ button >
422- < button className = "detailed-results-death-iteration-button btn btn-primary" ref = { deathButtonRef } disabled = { true } >
423- { i18n . t ( 'results_tab.details.sim_1_death' ) }
424- </ button >
425- </ div > ,
426- ) ;
427-
428- const url = new URL ( `${ window . location . protocol } //${ window . location . host } /${ REPO_NAME } /results/detailed/index.html` ) ;
429- url . searchParams . append ( 'cssClass' , simUI . config . cssClass ) ;
430-
431- if ( simUI . isIndividualSim ( ) ) {
432- url . searchParams . append ( 'isIndividualSim' , '' ) ;
433- this . rootElem . classList . add ( 'individual-sim' ) ;
434- }
435-
436- const newTabButton = newTabButtonRef . value ! ;
437- newTabButton ?. addEventListener ( 'click' , ( ) => {
438- if ( this . tabWindow == null || this . tabWindow . closed ) {
439- this . tabWindow = window . open ( url . href , 'Detailed Results' ) ;
440- this . tabWindow ! . addEventListener ( 'load' , async ( ) => {
441- if ( this . latestRun ) {
442- await Promise . all ( [ this . updateSettings ( ) , this . setSimRunData ( this . latestRun ) ] ) ;
443- }
444- } ) ;
445- } else {
446- this . tabWindow . focus ( ) ;
447- }
448- } ) ;
449-
450- const simButton = simButtonRef . value ! ;
451- simButton ?. addEventListener ( 'click' , ( ) => {
452- ( window . opener || window . parent ) ! . postMessage ( 'runOnce' , '*' ) ;
453- } ) ;
454-
455- const deathButton = deathButtonRef . value ! ;
456- deathButton ?. addEventListener ( 'click' , ( ) => {
457- if ( this . latestDeathSeeds . length > 1 ) {
458- this . simUI ?. sim . setFixedRngSeed ( TypedEvent . nextEventID ( ) , Number ( this . latestDeathSeeds . pop ( ) ) ) ;
459- this . recentlyEditedSeed = true ;
460-
461- if ( isDevMode ( ) ) {
462- console . log ( 'Setting fixed seed:' ) ;
463- console . log ( this . simUI ?. sim . getFixedRngSeed ( ) ) ;
464- }
465- }
466-
467- ( window . opener || window . parent ) ! . postMessage ( 'runOnce' , '*' ) ;
468- } ) ;
469-
470- simResultsManager . currentChangeEmitter . on ( async ( ) => {
471- const runData = simResultsManager . getRunData ( ) ;
472- if ( runData ) {
473- await Promise . all ( [ this . updateSettings ( ) , this . setSimRunData ( runData ) ] ) ;
474- }
475-
476- deathButton . disabled = this . latestDeathSeeds . length < 2 ;
477- } ) ;
478- }
479-
480- async postMessage ( update : DetailedResultsUpdate ) {
481- if ( this . tabWindow ) {
482- this . tabWindow . postMessage ( DetailedResultsUpdate . toJson ( update ) , '*' ) ;
483- }
484- await this . handleMessage ( update ) ;
485- }
486399}
0 commit comments