home *** CD-ROM | disk | FTP | other *** search
- (*-------------------------------------------------------------------*)
- (* *)
- (* Critical Path Method Project Scheduler - 18 Sept 83 - E. Dong *)
- (* Based on BASIC version, 'Hard Hat Management: Two On-Site *)
- (* Tools', by Richard Parry, INTERFACE AGE, February, 1981. *)
- (* *)
- (* Translated into CIC86 'C' by Edward V. Dong *)
- (* Retranslated into Turbo Pascal by E.V. Dong *)
- (* Last Update: 24-Mar-84 *)
- (*-------------------------------------------------------------------*)
-
- const
- SIZE = 100;
-
- var
- i, j, k, m, NumOfJobs: integer; (* Internal Integer Parms *)
- instring: string[80];
- filein, fileout: text; (* 'Standard' file definition*)
-
- c1, c2, du, l1, m1, m2, PathLen: integer;
- cp, sd, StartTime, From, d: array [1..SIZE] of integer;
- Earliest, LatestTime, Slack: array [1..SIZE] of integer;
- JobName: array [1..SIZE] of string[9]; (* Job names *)
-
- (* initialize arrays *)
- PROCEDURE InitCPM;
- var
- icount : integer;
- begin
- for icount := 1 to SIZE do
- begin
- StartTime[icount] := 0;
- From[icount] := 0;
- cp[icount] := 0;
- d[icount] := 0;
- Earliest[icount] := 0;
- LatestTime[icount] := 0;
- Slack[icount] := 0;
- JobName[icount] := ' ';
- end;
- end;
-
- (* setup file I/O *)
- PROCEDURE InitFile;
- var
- filename: string[20];
- answer: char;
- icount: integer;
- filetype: array [1..2] of string[6];
- begin
- filetype[1] := 'input';
- filetype[2] := 'output';
- for icount :=1 to 2 do
- begin
- write('Do you want ',filetype[icount],' at console? (Y/N): ');
- readln(answer);
- if (answer='Y') or (answer='y') then filename:='con:'
- else
- begin
- write('Enter filename: '); readln(filename);
- end;
- case icount of
- 1: begin assign(filein,filename); reset(filein) end;
- 2: begin assign(fileout,filename); rewrite(fileout) end;
- end;
- end;
- end;
-
- (* Sort Data Subroutine, Using Start Node as Key *)
- PROCEDURE PerformSort;
- var sw, temp: integer;
- BEGIN
- sw := 0;
- for i:=1 to NumOfJobs-1 do
- BEGIN
- j := i + 1;
- if (StartTime[i] > StartTime[j]) then
- BEGIN
- temp := StartTime[i];
- StartTime[i] := StartTime[j]; StartTime[j] := temp;
- temp := From[i]; From[i] := From[j]; From[j] := temp;
- temp := d[i]; d[i] := d[j]; d[j] := temp;
- sw := 1;
- END;
- END;
- if sw = 1 then PerformSort; (* sort again if needed *)
- END;
-
- PROCEDURE DoCPM;
- label cpm_test, cpm_exit;
- BEGIN
- writeln('--> CPM ANALYSIS IN PROGRESS <--'); writeln;
-
- (* compute earliest starting time *)
- c1 := 0; c2 := 0; PathLen := 0;
- for i:=1 to NumOfJobs do
- BEGIN
- m1 := Earliest[StartTime[i]] + d[i];
- if (Earliest[From[i]] <= m1) then Earliest[From[i]] := m1;
- END;
-
- (* compute latest finishing time *)
- LatestTime[From[NumOfJobs]] := Earliest[From[NumOfJobs]];
- for i:=NumOfJobs downto 1 do
- BEGIN
- l1 := StartTime[i]; m2 := LatestTime[From[i]] - d[i];
- if ((LatestTime[l1] >= m2) or (LatestTime[l1] = 0))
- then LatestTime[l1] := m2;
- END;
-
- (* compute float time & critical path length *)
- for i:=1 to NumOfJobs do
- BEGIN
- Slack[i] := LatestTime[From[i]] - Earliest[StartTime[i]] - d[i];
- if (Slack[i] = 0) then c1 := c1 + 1;
- if (LatestTime[From[i]] > PathLen) then PathLen := LatestTime[From[i]];
- END;
-
- (* output results of CP analysis *)
- writeln(fileout);
- writeln(fileout,'CP Analysis is:');
- writeln(fileout,' [EST = Earliest Starting Time]');
- writeln(fileout,' [LFT = Latest Finishing Time]');
- writeln(fileout,' [SLACK = Float or Slack Time]');
- writeln(fileout,'Name':9,'From':9,'To':9,'EST':9,'LFT':9,'SLACK':9);
- for i:=1 to NumOfJobs do
- BEGIN
- write(fileout,JobName[i]:9);
- write(fileout,StartTime[i]:9,From[i]:9);
- write(fileout,Earliest[StartTime[i]]:9);
- writeln(fileout,LatestTime[From[i]]:9,Slack[i]:9);
- END;
- writeln(fileout); writeln(fileout,'The Critical Path Length is ',PathLen);
-
- (* compute critical path *)
- i := 0;
- while (From[i] <> 0) do i:=i+1;
- cpm_test:
- c2 := c2 + 1; cp[i] := cp[i] + 1;
- if (i > NumOfJobs) then goto cpm_exit;
- for m:=1 to NumOfJobs do
- BEGIN
- if (StartTime[m] <> From[i]) then goto cpm_exit
- else if (Slack[m] <> 0) then goto cpm_exit
- else
- BEGIN
- i:=m;
- goto cpm_test;
- END;
- END;
- cpm_exit:
- if (c1 <> c2) then du := du + 1;
- END;
-
- (* Input Data Subroutine *)
- PROCEDURE GetData;
- var temp: integer;
- BEGIN
- write('Jobname: ');
- readln(filein,instring);JobName[i]:=instring;
- write('From:':9);
- readln(filein,temp); StartTime[i] := temp;
- write('To:':9);
- readln(filein,temp); From[i] := temp;
- write('Duration:':9);
- readln(filein,temp); d[i] := temp;
- while (From[i] > NumOfJobs)
- BEGIN
- write(fileout,'For Jobname: ',instring);
- write(fileout,' *** End Node # ',From[i]);
- writeln(fileout,'Not =< # ',NumOfJobs,' of Activities ***');
- write('To: ');
- readln(filein,From[i]);
- END;
- if (StartTime[i] >= From[i]) then
- BEGIN
- write(fileout,'For Jobname: ',instring);
- write(fileout,' *** Start Node ',StartTime[i]);
- writeln(fileout,'Must Be < End Node ',From[i],' ***');writeln(fileout);
- writeln(fileout,'*** Redo Entry ***');
- GetData;
- END;
- END;
-
- (* critical path printout *)
- PROCEDURE DoCPL;
- var iname, jname: integer;
-
- BEGIN
- iname := StartTime[i];
- jname := From[i];
- writeln(fileout,JobName[iname]:9,iname:9,JobName[jname]:9,jname:9);
- c2 := c2 + 1;
- if (i<=NumOfJobs) then
- BEGIN
- for m:=1 to NumOfJobs do
- BEGIN
- if ((StartTime[m]=From[i]) and (Slack[m]=0)) then
- BEGIN
- i := m;
- DoCPL;
- END;
- END;
- END;
- if (c1 <> c2) then writeln(fileout,'There is more than one critical path.');
- END;
-
- (* generate GANTT chart *)
- PROCEDURE DoGANTT;
- var
- linelen, scale, scale2: real;
- limit, z1, z2, z3: integer;
- symbol: char;
-
- BEGIN
- writeln(fileout);
- writeln(fileout,'GANTT Chart for Project:'); writeln(fileout);
- writeln(fileout,'Non-critical path is denoted as ====');
- writeln(fileout,' Critical path is denoted as ****');
- writeln(fileout,' Slack (if any) is denoted as ....');
- writeln(fileout);
-
- (* calculate chart scaling *)
- linelen := 60.0;
- scale := linelen/PathLen; scale2 := scale;
- z1 := trunc(scale);
- z2 := z1 - 1;
- z3 := 1;
- limit := 0;
- while limit <= 1 do
- BEGIN
- z3 := z3 * 10;
- limit := trunc(z3 * scale)
- END;
-
- (* generate ruler line for chart *)
- write(fileout,'0':10);
- j := 0;
- while j < trunc(linelen) do
- BEGIN
- for k := 1 to limit-1 do write(fileout,'-');
- write(fileout,'+');
- j := j + limit
- END;
- writeln(fileout);
-
- (* generate GANTT waterfall *)
- for j:=1 to NumOfJobs do
- BEGIN
- write(fileout,JobName[j]:9);
- limit := trunc(Earliest[StartTime[j]] * scale);
- for k:=0 to limit do write(fileout,' ');
- if (Slack[j]=0) then symbol := '*'
- else symbol := '=';
- limit := trunc(LatestTime[From[j]] * scale) - limit;
- for k:=0 to limit do write(fileout,symbol);
- if (Slack[j]<>0) then
- BEGIN
- symbol := '.';
- for k:=0 to trunc(Slack[j] * scale) do write(fileout,symbol);
- END;
- writeln(fileout);
- END;
- END;
-
- (* body of main portion of program==================================*)
-
- BEGIN
- writeln('CPM: Project Scheduler'); writeln; (* identify program *)
- InitFile; (* setup file I/O *)
- writeln(fileout,'CPM: Project Scheduler');
- writeln(fileout);
-
- (* initialize variables *)
- c1 := 0; c2 := 0; du := 0; m1 := 0; m2 := 0; PathLen := 0;
- InitCPM; (* initialize arrays *)
-
- (* get # of activities*)
- write('Enter number of events (activities): ');
- readln(filein,NumOfJobs);
-
- (* input routine *)
- for i:=1 to NumOfJobs do
- BEGIN
- writeln('Event No. ',i); GetData; writeln;
- END;
-
- (* call sort routine *)
- writeln(fileout); writeln(fileout,'--> SORTING IN PROGRESS <--');
- PerformSort;
- (* display sort *)
- write(fileout,'Event No':9,'Name':9);
- writeln(fileout,'From':9,'To ':9,'Duration');
- for i:=1 to NumOfJobs do
- BEGIN
- writeln(fileout,i:9,JobName[i]:9,StartTime[i]:9,From[i]:9,d[i]:9);
- END;
-
- DoCPM; (* do critical path analysis *)
- c2 := 0;
- writeln(fileout); writeln(fileout,'The Critical Path is:');
- writeln(fileout,'From',' ':18,'To');
- i:=1; while (Slack[i] <> 0) i:=i+1; (* locate start of critical path *)
- DoCPL; (* critical path printout *)
- DoGANTT; (* display GANTT chart *)
- close(fileout); (* close & save output *)
- END.
-