75 lines
2.2 KiB
TypeScript
75 lines
2.2 KiB
TypeScript
import type { TimelineAssignmentEntry } from "./TimelineContext.js";
|
|
import type { ResourceCapacitySeries } from "./timelineCapacity.js";
|
|
|
|
export type ProjectDayMetric = {
|
|
projH: number;
|
|
totalH: number;
|
|
capacityH: number;
|
|
};
|
|
|
|
type ProjectMetricRow = {
|
|
resource: { id: string };
|
|
allocs: TimelineAssignmentEntry[];
|
|
};
|
|
|
|
type ProjectMetricGroup = {
|
|
id: string;
|
|
resourceRows: ProjectMetricRow[];
|
|
};
|
|
|
|
export function getProjectRowMetricsKey(projectId: string, resourceId: string): string {
|
|
return `${projectId}:${resourceId}`;
|
|
}
|
|
|
|
export function buildProjectRowMetrics(
|
|
dates: Date[],
|
|
projectGroups: ProjectMetricGroup[],
|
|
resourceTotalHoursById: Map<string, number[]>,
|
|
resourceCapacityById: Map<string, ResourceCapacitySeries>,
|
|
): Map<string, ProjectDayMetric[]> {
|
|
const dateIndexByTime = new Map<number, number>();
|
|
dates.forEach((date, index) => {
|
|
const normalized = new Date(date);
|
|
normalized.setHours(0, 0, 0, 0);
|
|
dateIndexByTime.set(normalized.getTime(), index);
|
|
});
|
|
|
|
const nextMetrics = new Map<string, ProjectDayMetric[]>();
|
|
|
|
for (const project of projectGroups) {
|
|
for (const { resource, allocs } of project.resourceRows) {
|
|
const projectHours = new Array<number>(dates.length).fill(0);
|
|
const capacity = resourceCapacityById.get(resource.id);
|
|
|
|
for (const alloc of allocs) {
|
|
const current = new Date(alloc.startDate);
|
|
current.setHours(0, 0, 0, 0);
|
|
const end = new Date(alloc.endDate);
|
|
end.setHours(0, 0, 0, 0);
|
|
|
|
while (current.getTime() <= end.getTime()) {
|
|
const dayIndex = dateIndexByTime.get(current.getTime());
|
|
if (dayIndex !== undefined) {
|
|
projectHours[dayIndex] =
|
|
(projectHours[dayIndex] ?? 0) +
|
|
alloc.hoursPerDay * (capacity?.bookingFactorsByDay[dayIndex] ?? 1);
|
|
}
|
|
current.setDate(current.getDate() + 1);
|
|
}
|
|
}
|
|
|
|
const totalHours = resourceTotalHoursById.get(resource.id);
|
|
nextMetrics.set(
|
|
getProjectRowMetricsKey(project.id, resource.id),
|
|
projectHours.map((projH, dayIndex) => ({
|
|
projH,
|
|
totalH: totalHours?.[dayIndex] ?? 0,
|
|
capacityH: capacity?.capacityHoursByDay[dayIndex] ?? 8,
|
|
})),
|
|
);
|
|
}
|
|
}
|
|
|
|
return nextMetrics;
|
|
}
|