import { findIndex, find, map, propEq, reduce, sort, concat } from 'rambda'; import type { JobId } from '../../types'; import { max, remove, slice } from 'ramda'; type JobTime = { jobId: JobId, t: number, d: number, }; const findLateJob = (jobTimes: JobTime[]) => find(({ c, d }: JobTime) => c > d, jobTimes); const findMaxTJob = (jobTimes: JobTime[]) => reduce( (maxTJob: JobTime, jobTime: JobTime) => maxTJob.t > jobTime.t ? maxTJob : jobTime, { t: -Infinity }, jobTimes ); const updateCTime = (jobTimes: JobTime[]) => { let prev = 0; const cj = map((jobTime: JobTime) => { prev += jobTime.t; return { ...jobTime, c: prev }; }, jobTimes); return cj; }; export const fillCorrupted = (jobs: JobTime[]) => map( ({ d, ...rest }) => ({ ...rest, d: d || 1000 }), jobs); export const createSchedule = (jobs: JobTime[]) => { jobs = fillCorrupted(jobs); const F = sort((a: JobTime, b: JobTime) => a.d - b.d, jobs); const L = []; let cj = updateCTime(F); let lateJob; while (lateJob = findLateJob(cj)) { const lateJobIndex = findIndex(propEq('jobId', lateJob.jobId), cj); const jobsBeforeLateJob = slice(0, lateJobIndex + 1, cj); const maxTJob = findMaxTJob(jobsBeforeLateJob); const maxTJobIndex = findIndex(propEq('jobId', maxTJob.jobId), cj); cj = remove(maxTJobIndex, 1, cj); cj = updateCTime(cj); L.push(maxTJob); } const schedule = concat(cj, L); return updateCTime(schedule); }; export default (jobs: JobTime[]) => { const schedule = createSchedule(jobs); const normalizedSchedule = map((jobTime: JobTime) => ({ processor: 1, startTime: jobTime.c - jobTime.t, endTime: jobTime.c, delayed: max(0, jobTime.c - jobTime.d) }), schedule); return [normalizedSchedule]; };