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.
2.2 kB · 61 lines
TypeScript
at main
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162// CrewBorrow — a one-way crew substitution policy.//// The project remains the source of truth for task duration and static// resource demand. For each governed task, serial-SGS derives two modes:// home first, then the same demand with the declared home resource replaced// by the borrow resource. Because mode order is preference, borrowing occurs// only when it lets the task start strictly earlier.
import { z } from "zod";
import type { CrewBorrowConstraint } from "../level-core/types.ts";
import type { ConstraintBlock, MiniZincFragment } from "./types.ts";
export const CrewBorrowInputSchema = z .strictObject({ taskUniqueIds: z.array(z.number().int()).min(1), homeResourceUniqueId: z.number().int(), borrowResourceUniqueId: z.number().int(), }) .refine( (input) => new Set(input.taskUniqueIds).size === input.taskUniqueIds.length, { message: "taskUniqueIds must be unique", path: ["taskUniqueIds"], }, ) .refine( (input) => input.homeResourceUniqueId !== input.borrowResourceUniqueId, { message: "borrowResourceUniqueId must differ from homeResourceUniqueId", path: ["borrowResourceUniqueId"], }, );
export type CrewBorrowInput = z.infer<typeof CrewBorrowInputSchema>;
const CrewBorrowOutputSchema: z.ZodType<CrewBorrowConstraint> = z.object({ kind: z.literal("CrewBorrow"), taskUniqueIds: z.array(z.number().int()), homeResourceUniqueId: z.number().int(), borrowResourceUniqueId: z.number().int(),});
export const CrewBorrowBlock: ConstraintBlock<CrewBorrowInput> = { id: "CrewBorrow", schema: { input: CrewBorrowInputSchema, output: CrewBorrowOutputSchema }, apply: (input): CrewBorrowConstraint => ({ kind: "CrewBorrow", ...input }), toMiniZinc: ({ taskUniqueIds }): MiniZincFragment => ({ text: taskUniqueIds .map( (taskUniqueId) => `constraint mode[${String(taskUniqueId)}] in {0,1};`, ) .join("\n"), }), doc: { nl: "Listed tasks prefer their static home-crew assignment, but may substitute the borrow crew when that starts the task earlier.", pseudocode: "modes(task) = [static demand, static demand with home resource replaced by borrow]", },};