Something went wrong. Try again.
A functional toolkit for authoring resource-leveling algorithms — compose constraint and scoring blocks, enumerate feasible schedules
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788import type { ProjectFile } from "../model/Project.ts";import { escapeCsvField } from "./escapeField.ts";import { formatProjectDate } from "../dateTime.ts";
export interface CsvWriterOptions { /** Include summary (parent) tasks. Default: false (leaf tasks only). */ includeSummaryTasks?: boolean; /** Include a Resources column resolved from assignments. Default: true. */ includeResources?: boolean;}
const HEADERS_BASE = [ "ID", "Task Name", "WBS", "Start", "Finish", "Duration", "% Complete", "Critical", "Milestone",];
export class CsvWriter { write(project: ProjectFile, options?: CsvWriterOptions): string { const includeSummary = options?.includeSummaryTasks === true; const includeResources = options?.includeResources !== false;
const headers = includeResources ? [...HEADERS_BASE, "Resources"] : [...HEADERS_BASE];
const resourceNames = new Map<number, string>(); for (const resource of project.resources) { if (resource.uniqueId !== null && resource.name !== null) { resourceNames.set(resource.uniqueId, resource.name); } }
const taskResources = new Map<number, string[]>(); for (const assignment of project.assignments) { if ( assignment.taskUniqueId === null || assignment.resourceUniqueId === null ) continue; const name = resourceNames.get(assignment.resourceUniqueId); if (!name) continue; const existing = taskResources.get(assignment.taskUniqueId); if (existing) { if (!existing.includes(name)) existing.push(name); } else { taskResources.set(assignment.taskUniqueId, [name]); } }
const tasks = includeSummary ? project.tasks.filter((t) => t.id !== null) : project.tasks.filter((t) => t.summary === false && t.id !== null);
const lines = [headers.map((h) => escapeCsvField(h)).join(",")];
for (const task of tasks) { const fields: unknown[] = [ task.id, task.name, task.wbs, formatProjectDate(task.start), formatProjectDate(task.finish), task.duration?.toSimpleString() ?? null, task.percentComplete, task.critical ? "Yes" : "No", task.milestone ? "Yes" : "No", ];
if (includeResources) { const names = task.uniqueId !== null ? taskResources.get(task.uniqueId) : undefined; fields.push(names ? names.join(",") : null); }
lines.push(fields.map((f) => escapeCsvField(f)).join(",")); }
return lines.join("\n") + "\n"; }}