import { map, reduce, times } from 'rambda'; import type { JobId } from '../../types'; import { groupBy, max } from 'ramda'; type JobTime = { jobId: JobId, t: number, name: string }; type JobTimeAssigned = JobTime | { processor: number, }; type JobTimeAssignedWithC = JobTimeAssigned | { c: number, }; export const updateCTime = (jobTimes: JobTimeAssigned[]) => { let prev = 0; let prevProcessor = 0; const cj = map((jobTime: JobTimeAssigned) => { if (jobTime.processor !== prevProcessor) { prev = 0; } prev += jobTime.t; prevProcessor = jobTime.processor; return { ...jobTime, c: prev }; }, jobTimes); return cj; }; export const createSchedule = (jobs: JobTime[], processorCount: number): JobTimeAssignedWithC[] => { let G = jobs; const sumT = reduce((acc, job) => acc + job.t, 0, G); const maxT = reduce((acc, job) => max(acc, job.t), -Infinity, G); const K = max(Math.ceil(sumT / processorCount), maxT); const R = []; let processorC = times(() => 0, processorCount + 1); let activeProcessor = 1; while (G.length) { if (processorC[activeProcessor] + G[0].t <= K) { processorC[activeProcessor] += G[0].t; R.push({ ...G[0], processor: activeProcessor }); [, ...G] = G; if (processorC[activeProcessor] === K) { activeProcessor++; } } else { const tDiff = processorC[activeProcessor] + G[0].t - K; R.push({ ...G[0], t: G[0].t - tDiff, processor: activeProcessor }); G[0].t = tDiff; activeProcessor++; } } const withC = updateCTime(R); return withC; }; export default (jobs: JobTime[], processorCount: number) => { const schedule = createSchedule(jobs, processorCount); const grouped = Object.values(groupBy(jobTime => jobTime.processor, schedule)); return map(map((job: JobTimeAssignedWithC) => ({ processor: job.processor, startTime: job.c - job.t, endTime: job.c, name: job.name })), grouped); };