src/algorithms/campbel/index.js
fe944750
 import {
   addIndex,
   find,
   map,
   propEq,
   reduce,
   range,
   times,
   last
 } from 'rambda';
 import type { JobId } from '../../types';
 import { createSchedule as johnson, updateCTime } from '../johnson';
b681b265
 import { max } from 'ramda';
fe944750
 
 type JobOperations = {
   jobId: JobId,
   operations: Array<{ t: number }>
 };
 
 type JobOperationsWithC = {
   jobId: JobId,
   operations: Array<{ t: number, c: number }>
 };
 
b681b265
 export const fillCorrupted = (jobsOperations: JobOperations[]) => {
   const maxOperationsCount = reduce((acc, { operations }) => max(operations.length, acc), 0, jobsOperations);
 
   return map(
     ({ operations, ...rest }) => {
       const fixedOperations = [...operations];
       fixedOperations.length = maxOperationsCount;
 
       return {
         ...rest,
         operations: fixedOperations.fill({ t: 0 }, operations.length, maxOperationsCount)
       };
     },
     jobsOperations
   )
 };
 
fe944750
 export const createSchedule = (jobsOperations: JobOperations[], processorsCount: number): JobOperationsWithC[] => {
b681b265
   jobsOperations = fillCorrupted(jobsOperations);
 
fe944750
   const allSchedules = map(k => {
     const jobsOperationsForK = map((jobsOperation: JobOperations) => {
       const t1 = reduce((acc, i) => acc + jobsOperation.operations[i].t, 0, range(0, k));
       const t2 = reduce((acc, i) => acc + jobsOperation.operations[i].t, 0, range(processorsCount - k, processorsCount));
 
       const operations = [
         { t: t1 },
         { t: t2 }
       ];
       const newJobsOperations = { jobId: jobsOperation.jobId, operations };
       return newJobsOperations;
     }, jobsOperations);
 
     const jobsOperationsOrderTemplate = johnson(jobsOperationsForK);
 
     const mapWithIndex = addIndex(map);
     const jobsOperationsReordered = mapWithIndex((jobOperationTemplate, i) => {
       const { operations } = find(propEq('jobId', jobOperationTemplate.jobId), jobsOperations);
       return {
         jobId: jobOperationTemplate.jobId,
         operations
       };
     }, jobsOperationsOrderTemplate);
 
     const jobsOperationsReorderedWithC = updateCTime(jobsOperationsReordered, processorsCount);
 
     return jobsOperationsReorderedWithC;
   }, range(1, processorsCount));
 
   const bestSchedule = reduce((acc, schedule) => {
     const cmaxAcc = last(last(acc).operations).c;
     const cmax = last(last(schedule).operations).c;
 
     return (cmax < cmaxAcc) ? schedule : acc;
   }, [{ operations: [{ c: Infinity }] }], allSchedules);
 
   return bestSchedule;
 };
 
 export default (jobsOperations: JobOperations[], processorsCount: number) => {
   const schedule = createSchedule(jobsOperations, processorsCount);
 
   return times(i =>
     map((jobTime: JobOperationsWithC) => ({
       processor: i + 1,
       startTime: jobTime.operations[i].c - jobTime.operations[i].t,
       endTime: jobTime.operations[i].c,
     }), schedule)
   , processorsCount);
 };