Mildly improved support for livesplit inspired functionality. Also initial beginnings of supporting an "aggregated" live stat for your ongoing run compared to another one.
parent
a8443964bc
commit
7c3e739f8d
@ -0,0 +1,4 @@
|
|||||||
|
<div>
|
||||||
|
Spent: {{currentSpent()}}
|
||||||
|
Compare spent: {{compareSpent()}}
|
||||||
|
</div>
|
@ -0,0 +1,21 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { AggregateDisplayComponent } from './aggregate-display.component';
|
||||||
|
|
||||||
|
describe('AggregateDisplayComponent', () => {
|
||||||
|
let component: AggregateDisplayComponent;
|
||||||
|
let fixture: ComponentFixture<AggregateDisplayComponent>;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [AggregateDisplayComponent]
|
||||||
|
});
|
||||||
|
fixture = TestBed.createComponent(AggregateDisplayComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,104 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { PlanService } from '../_services/plan.service';
|
||||||
|
import { EntryType, RunHistory, TimeTrackerService, TrackEntry } from '../_services/time-tracker.service';
|
||||||
|
import { Plan } from '../_models/plan';
|
||||||
|
import { ConfigService } from '../_services/config.service';
|
||||||
|
import { RunStatService, UnformattedAggregateRunStat, UnformattedAggregationData } from '../_services/run-stat.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-aggregate-display',
|
||||||
|
standalone: true,
|
||||||
|
imports: [CommonModule],
|
||||||
|
templateUrl: './aggregate-display.component.html',
|
||||||
|
styleUrls: ['./aggregate-display.component.scss']
|
||||||
|
})
|
||||||
|
export class AggregateDisplayComponent {
|
||||||
|
private aggregatedRunHistory?: UnformattedAggregationData;
|
||||||
|
private currentHistory?: RunHistory;
|
||||||
|
private latestEntry?: TrackEntry;
|
||||||
|
|
||||||
|
private compareAggregate?: Map<string, UnformattedAggregateRunStat>;
|
||||||
|
private currentAggregate?: Map<string, UnformattedAggregateRunStat>;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private planSerive: PlanService,
|
||||||
|
public timeTrackerService: TimeTrackerService,
|
||||||
|
private configService: ConfigService,
|
||||||
|
private runStatService: RunStatService
|
||||||
|
) {
|
||||||
|
this.timeTrackerService.getCurrentRunHistory().subscribe(history => {
|
||||||
|
this.currentHistory = history;
|
||||||
|
this.aggregatedRunHistory = this.runStatService.calcAggregated(history);
|
||||||
|
this.loadComparisonData();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.timeTrackerService.getLatestEntry().subscribe(entry => {
|
||||||
|
if (entry.type != EntryType.ZoneEnter) return;
|
||||||
|
|
||||||
|
if (this.latestEntry) {
|
||||||
|
this.expandAggregated(this.latestEntry, entry);
|
||||||
|
}
|
||||||
|
this.latestEntry = entry;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private loadComparisonData() {
|
||||||
|
if (!this.configService.config.runCompareHistory) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.timeTrackerService.loadHistory(this.configService.config.runCompareHistory).subscribe(history => {
|
||||||
|
if (history) {
|
||||||
|
this.aggregatedRunHistory = this.runStatService.calcAggregated(history);
|
||||||
|
this.compareAggregate = new Map<string, UnformattedAggregateRunStat>(this.aggregatedRunHistory.aggregation.map(agg => [agg.zoneId, agg]));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
expandAggregated(oldEntry: TrackEntry, newEntry: TrackEntry) {
|
||||||
|
if (!this.currentAggregate) return;
|
||||||
|
|
||||||
|
let aggregate: UnformattedAggregateRunStat = {
|
||||||
|
zoneId: oldEntry.zone,
|
||||||
|
aggregateFirstEntry: oldEntry.current_elapsed_millis,
|
||||||
|
aggregateLastExit: newEntry.current_elapsed_millis,
|
||||||
|
aggregateTimeSpent: (newEntry.current_elapsed_millis - oldEntry.current_elapsed_millis),
|
||||||
|
aggregateNumEntries: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
const existing = this.currentAggregate.get(oldEntry.zone);
|
||||||
|
if (existing) {
|
||||||
|
existing.aggregateLastExit = aggregate.aggregateLastExit;
|
||||||
|
existing.aggregateTimeSpent += aggregate.aggregateTimeSpent;
|
||||||
|
existing.aggregateNumEntries++;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentAggregate.set(aggregate.zoneId, existing ?? aggregate);
|
||||||
|
}
|
||||||
|
|
||||||
|
currentSpent() {
|
||||||
|
if (!this.latestEntry) return "N/A";
|
||||||
|
|
||||||
|
const value = this.currentAggregate?.get(this.latestEntry?.zone)?.aggregateTimeSpent ?? 0 + (this.timeTrackerService.elapsedTimeMillis - this.latestEntry?.current_elapsed_millis);
|
||||||
|
|
||||||
|
if(value) {
|
||||||
|
return this.timeTrackerService.hmsTimestamp(value);
|
||||||
|
} else {
|
||||||
|
return "N/A";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compareSpent() {
|
||||||
|
if (!this.latestEntry) return "N/A";
|
||||||
|
const value = this.compareAggregate?.get(this.latestEntry?.zone)?.aggregateTimeSpent;
|
||||||
|
|
||||||
|
if(value) {
|
||||||
|
return this.timeTrackerService.hmsTimestamp(value);
|
||||||
|
} else {
|
||||||
|
return "N/A";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in new issue