src/algorithms/johnson/index.js
fe944750
 import {
b681b265
   findIndex, map, reduce, sort, concat,
   filter, reverse, equals, update, times
fe944750
 } from 'rambda';
 import type { JobId } from '../../types';
b681b265
 import { remove } from 'ramda';
 import { fillCorrupted } from '../campbel';
fe944750
 
 type JobOperations = {
   jobId: JobId,
8c7841d1
   operations: [{ t: number, name: string }, { t: number, name: string }]
fe944750
 };
 
 type JobOperationsWithC = {
   jobId: JobId,
8c7841d1
   operations: [{ t: number, c: number, name: string }, { t: number, c: number, name: string }]
fe944750
 };
 
 const findMinT = (operations) =>
   reduce(
     (t1, t2) => t1.t < t2.t ? t1 : t2,
     { t: Infinity },
     operations
   );
 
 const findMinJob = (jobsOperations: JobOperations[]): JobOperations =>
   reduce(
     (minJob: JobOperations, jobOperations: JobOperations) => {
       const minJobT = findMinT(minJob.operations);
       const jobOperationsT = findMinT(jobOperations.operations);
 
       return minJobT.t < jobOperationsT.t ? minJob : jobOperations;
     },
     { operations: [ { t: Infinity }, { t: Infinity } ] },
     jobsOperations
   );
 
 export const updateCTime = (jobsOperations: JobOperations[], processorCount: number): JobOperationsWithC[] => {
   let prev = 0;
   const cj = [];
 
   cj[0] = map((jobTime: JobOperations) => {
     prev += jobTime.operations[0].t;
     const operationC = { ...jobTime.operations[0], c: prev };
     const operations = update(0, operationC, jobTime.operations);
 
     return { ...jobTime, operations };
   }, jobsOperations);
 
   if (processorCount > 1) {
     times(i => {
       const processorI = i + 1;
       prev = cj[0][0].operations[0].c;
 
       cj[processorI] = map((jobTime: JobOperations) => {
         const conflicts = filter(({ c }) => prev < c, jobTime.operations);
         if (conflicts.length) {
           const maxConflict = sort((a, b) => b.c - a.c, conflicts)[0];
           prev = maxConflict.c;
         }
 
         prev += jobTime.operations[processorI].t;
 
         const operationC = { ...jobTime.operations[processorI], c: prev };
         const operations = update(processorI, operationC, jobTime.operations);
 
         return { ...jobTime, operations };
       }, cj[i]);
     }, processorCount - 1);
   }
 
   return cj[processorCount - 1];
 };
 
 export const createSchedule = (jobsOperations: JobOperations[]): JobOperationsWithC[] => {
8c7841d1
   jobsOperations = fillCorrupted(jobsOperations, 2);
b681b265
 
fe944750
   let I = jobsOperations;
   let L = [[], []];
 
   while (I.length) {
     const minTJob = findMinJob(I);
 
     const { t: minT } = findMinT(minTJob.operations);
     const operationIndex = findIndex(o => o.t === minT, minTJob.operations);
     const minTJobIndex = findIndex(equals(minTJob), I);
 
     L[operationIndex].push(minTJob);
     I = remove(minTJobIndex, 1, I);
   }
 
   const LFinal = concat(L[0], reverse(L[1]));
 
   return updateCTime(LFinal, 2);
 };
 
 export default (jobsOperations: JobOperations[]) => {
   const schedule = createSchedule(jobsOperations);
 
   return times(i =>
     map((jobTime: JobOperationsWithC) => ({
       processor: i + 1,
       startTime: jobTime.operations[i].c - jobTime.operations[i].t,
       endTime: jobTime.operations[i].c,
8c7841d1
       name: jobTime.operations[i].name
fe944750
     }), schedule)
   , 2);
 };