import { Injectable } from '@angular/core'; import { EntryType, RunHistory } from './time-tracker.service'; import { Plan } from '../_models/plan'; export interface RunStat { zoneName: string; entryTime: string; estimatedExit: string; estimatedTimeSpent: string; } export interface AggregateRunStat { zoneName: string; aggregateFirstEntry: string; aggregateLastExit: string; aggregateTimeSpent: string; aggregateNumEntries: string; } export interface UnformattedAggregateRunStat { zoneId: string; aggregateFirstEntry: number; aggregateLastExit: number; aggregateTimeSpent: number; aggregateNumEntries: number; } export interface UnformattedAggregationData { aggregation: UnformattedAggregateRunStat[]; aggregateNAId: string; } export interface UnformattedRunStat { zoneId: string; entryTime: number; estimatedExit?: number; estimatedTimeSpent?: number; entryType: EntryType; } export type RunStatType = RunStat | AggregateRunStat; @Injectable({ providedIn: 'root' }) export class RunStatService { /// practically which zone can't have a last exit time as last exit is not determinable for the last entry aggregateNAId?: string; constructor() { } calcAggregated(data: RunHistory): UnformattedAggregationData { const aggregation = new Map(); this.aggregateNAId = data.entries[data.entries.length - 1].zone; data.entries.forEach((entry, index) => { const hasExit = !(data.entries.length - 1 === index); let aggregate: UnformattedAggregateRunStat = { zoneId: entry.zone, aggregateFirstEntry: entry.current_elapsed_millis, aggregateLastExit: hasExit ? data.entries[index + 1].current_elapsed_millis : 0, aggregateTimeSpent: hasExit ? (data.entries[index + 1].current_elapsed_millis - data.entries[index].current_elapsed_millis) : 0, aggregateNumEntries: 1, } const existing = aggregation.get(entry.zone); if (existing) { existing.aggregateLastExit = aggregate.aggregateLastExit; existing.aggregateTimeSpent += aggregate.aggregateTimeSpent; existing.aggregateNumEntries++; } aggregation.set(entry.zone, existing ?? aggregate); }); return { aggregation: Array.from(aggregation.values()), aggregateNAId: this.aggregateNAId }; } calcDirect(data: RunHistory): UnformattedRunStat[] { return data.entries.map((entry, index) => { const hasExit = !(data.entries.length - 1 === index); return { zoneId: entry.zone, entryTime: entry.current_elapsed_millis, estimatedExit: hasExit ? data.entries[index + 1].current_elapsed_millis : undefined, estimatedTimeSpent: hasExit ? (data.entries[index + 1].current_elapsed_millis - data.entries[index].current_elapsed_millis) : undefined, entryType: entry.type, } }) } insertTimesAtCheckpoints(history: RunHistory, plan: Plan) { const data = this.calcDirect(history); let fakeCurrent = 0; console.log("history", history); data.forEach(entry => { switch (entry.entryType) { case EntryType.PlanForceNext: fakeCurrent++; break; case EntryType.PlanForcePrev: fakeCurrent--; break; case EntryType.ZoneEnter: if (plan.isNext(entry.zoneId, fakeCurrent)) { fakeCurrent++; if (plan.plan[fakeCurrent].checkpoint) { plan.plan[fakeCurrent].checkpoint_millis = entry.entryTime; } } break; } }); if (fakeCurrent < plan.plan.length - 1) { for (let current = fakeCurrent; current < plan.plan.length; current++) { if (plan.plan[current].checkpoint) { plan.plan[current].checkpoint_millis = -1; } } } console.log("Inserted checkpoint times", plan); } }