/* Heinz Trutnau */ /* Am Buchenbusch 82 */ /* 41 Duisburg 14 */ /* */ /*--------------------------------------------------------------------*/ /* */ /* ----- Netzplantechnik nach CPM ----- */ /* Version vom 7. 3. 87 */ /* */ /* Dieses Programm berechnet einen Netzplan nach CPM. */ /* Der eigentliche Netzplan muß vorher von Hand aufgestellt werden. */ /* Netzpläne nach CPM sind vorgangsorientiert, die Vorgänge liegen */ /* zwischen zwei Ereignissen. */ /* Eingegeben werden die Vorgänge als 'Von (Ereignis), Nach (Ereign.) */ /* und Dauer (des Vorgangs)'. Dazu muß der Netzplan (die Ereignisse) */ /* von Anfang (Ereignis 1) bis zum Ende aufsteigend durchnummeriert */ /* sein. */ /* */ /* Nach beendeter Eingabe kann man den Netzplan auf Diskette */ /* speichern (NETZDAT). */ /* */ /* Berechnet wird vom Programm folgendes: */ /* Bei Ereignissen : FZ = frühestmöglicher Zeitpunkt für Ereignis */ /* SZ = spätestmöglicher Zeitpunkt */ /* außerdem werden die Ereignisse, welche auf dem */ /* kritischen Weg liegen, gekennzeichnet. */ /* (der kritische Weg ist der Weg, auf dem Ver- */ /* zögerungen die gesamte Projektdauer verlängern). */ /* */ /* Bei Vorgängen : FA = frühestmöglicher Anfangszeitpunkt */ /* SA = spätestmöglicher Anfangszeitpunkt */ /* FE = frühestmögliches Ende */ /* SE = spätestmögliches Ende */ /* GP = Gesamtpufferzeit */ /* FP = freie Pufferzeit */ /* UP = unabhängige Pufferzeit */ /* */ /* FA ist der Zeitpunkt, an dem sämtliche Vorgänger-Vorgänge */ /* frühestens abgeschlossen sind. */ /* SA ist der Zeitpunkt, an dem der Vorgang spätestens begonnen */ /* werden muß, um nicht die Dauer des Gesamtprojektes zu verlängern. */ /* FE ist der Zeitpunkt, an dem dieser Vorgang frühestens und */ /* SE, wann er spätestens beendet sein wird. */ /* */ /* Pufferzeiten sind Zeiten, um die die Vorgänge verschoben werden */ /* können, ohne die Gesamtdauer zu verlängern. */ /* */ /* GP kann nur ausgenützt werden, wenn Vorgänger zum frühestmöglichen */ /* Zeitpunkt fertig wurden, und man annimmt, daß sämtliche Nachfolger */ /* ohne Verzögerungen fertig werden. Ausnützen des Gesamtpuffers kann */ /* kritisch werden. */ /* FP kann voll ausgenützt werden, wenn die Vorgänger zum frühest- */ /* möglichen Zeitpunkt fertig wurden. Ausnützen des freien Puffers */ /* hat keinen Einfluß auf Nachfolgevorgänge. */ /* UP kann voll ausgenützt werden. Er wird weder von Vorgängern be- */ /* einflußt, noch hat er Einfluß auf Nachfolger. */ /* */ /* */ /* Der Netzplan kann auch noch nach den Berechnungen auf Disk abge- */ /* legt werden, da sämtliche Zeiten gespeichert werden. */ /* */ /* */ /* Diesen Netzplan kann man dann auch noch ändern, um entweder Fehler */ /* zu beseitigen, oder um zu Testen, welchen Einfluß verschiedene */ /* Vorgangsdauern auf den Gesamtplan haben. Dadurch kann man den */ /* Netzplan optimieren, indem Vorgänge mit Pufferzeiten verlängert */ /* und die freigewordenen Kapazitäten dann auf dem kritischen Weg */ /* eingesetzt werden (wenn möglich). */ /* */ /*--------------------------------------------------------------------*/ S=5000; MODULE NETZPL; /* Netzplantechnik */ SYSTEM; TERM : A1 <->; EIN : A1(TFU=1) <-; DATEI : F0.NETZDAT <->; PRINT : LA ->; PROBLEM; SPC TERM DATION INOUT ALPHIC CONTROL(ALL); SPC EIN DATION IN ALPHIC CONTROL(ALL); SPC DATEI DATION INOUT ALPHIC CONTROL(ALL); SPC PRINT DATION OUT ALPHIC CONTROL(ALL); SPC (WRITE,READ) ENTRY GLOBAL; TYPE VORG STRUCT Ä VON FIXED, NACH FIXED, /* Typ fuer Vorgaenge */ DAUER FLOAT, FA FLOAT, FE FLOAT, SA FLOAT, SE FLOAT, GP FLOAT, UP FLOAT, FP FLOAT Ü; TYPE EREIG STRUCT Ä FZ FLOAT, SZ FLOAT Ü; /* Typ fuer Ereignisse */ DCL ERGLIS(500) EREIG; /* Liste aller Ereignisse */ DCL VORGLI(200) VORG; /* Liste aller Vorgaenge */ DCL VORGNR FIXED(10) INIT(1); /* Anzahl der Vorgaenge */ DCL ERGNR FIXED(10) INIT (1); /* Anzahl der Ereignisse */ DCL FRAGE FIXED(1); DCL ERWEIT BIT(1); /*-------------------------------------------------------------------*/ TAB : PROC (ANZAHL FIXED); /* Cursor um ANZAHL nach rechts */ FOR I TO ANZAHL REPEAT PUT TOCHAR(12) TO TERM BY A; END; END; /* TAB */ /*--------------------------------------------------------------------*/ EING : PROC; /* Eingabe der Vorgaenge */ DCL (NR,NACHFOLG) FIXED(10); PUT TOCHAR(27),'*' TO TERM BY (2)A; PUT 'Eingabe der Vorgaenge ' TO TERM BY SKIP,X(20),A,SKIP; PUT '(Beenden der Eingabe mit 0 )' TO TERM BY X(17),A,SKIP(2); IF ERWEIT=='0'B THEN VORGNR=1; FIN; REPEAT PUT 'Von ' TO TERM BY A; GET NR FROM TERM BY SKIP,F(10); IF NR==0 THEN GOTO AUSST; FIN; /* Ausstieg aus der Schleife */ VORGLI(VORGNR).VON = NR; CALL TAB(15); PUT 'nach ' TO TERM BY A; GET NACHFOLG FROM TERM BY SKIP,F(10); VORGLI(VORGNR).NACH = NACHFOLG; IF NACHFOLG >= ERGNR THEN ERGNR=NACHFOLG; FIN; CALL TAB(30); PUT 'Dauer ' TO TERM BY A; GET VORGLI(VORGNR).DAUER FROM TERM BY SKIP,F(23); PUT TO TERM BY SKIP; VORGNR=VORGNR+1; END; AUSST:VORGNR=VORGNR-1; END; /* EING */ /*--------------------------------------------------------------------*/ ZEITPT : PROC; /* FZ und SZ fuer jedes Ereignis berechnen */ DCL MAXZEIT FLOAT; DCL (DAUER,ZEIT) FLOAT; ERGLIS(1).FZ=0; ERGLIS(1).SZ=0; FOR I FROM 2 TO ERGNR REPEAT MAXZEIT=0; FOR K TO VORGNR REPEAT IF VORGLI(K).NACH==I THEN ZEIT=ERGLIS(VORGLI(K).VON).FZ+VORGLI(K).DAUER; IF ZEIT >= MAXZEIT THEN MAXZEIT=ZEIT; FIN; FIN; END; ERGLIS(I).FZ=MAXZEIT; END; ERGLIS(ERGNR).SZ=ERGLIS(ERGNR).FZ; FOR I FROM ERGNR-1 BY-1 TO 2 REPEAT MAXZEIT=1.0E38; FOR K TO VORGNR REPEAT IF VORGLI(K).VON==I THEN ZEIT=ERGLIS(VORGLI(K).NACH).SZ-VORGLI(K).DAUER; IF ZEIT <=MAXZEIT THEN MAXZEIT=ZEIT; FIN; FIN; END; ERGLIS(I).SZ=MAXZEIT; END; FOR I TO VORGNR REPEAT DAUER=VORGLI(I).DAUER; VORGLI(I).FA=ERGLIS(VORGLI(I).VON).FZ; VORGLI(I).FE=VORGLI(I).FA+DAUER; VORGLI(I).SE=ERGLIS(VORGLI(I).NACH).SZ; VORGLI(I).SA=VORGLI(I).SE-DAUER; VORGLI(I).GP=VORGLI(I).SE-VORGLI(I).FA-DAUER; IF VORGLI(I).GP<0 THEN VORGLI(I).GP=0; FIN; VORGLI(I).FP=ERGLIS(VORGLI(I).NACH).FZ-ERGLIS(VORGLI(I).VON).FZ; VORGLI(I).FP=VORGLI(I).FP-DAUER; IF VORGLI(I).FP<0 THEN VORGLI(I).FP=0; FIN; VORGLI(I).UP=ERGLIS(VORGLI(I).NACH).FZ-ERGLIS(VORGLI(I).VON).SZ; VORGLI(I).UP=VORGLI(I).UP-DAUER; IF VORGLI(I).UP<0 THEN VORGLI(I).UP=0; FIN; END; END; /* ZEITPT */ /*------------------------------------------------------------------*/ LOAD : PROC; /* Laedt Netzplan von Disk */ CALL REWIND(DATEI); CALL READ(DATEI,ERGLIS,VORGLI,VORGNR,ERGNR); END; /* LOAD */ /*------------------------------------------------------------------*/ SAVE : PROC; /* Sichert Netzplan auf Disk */ CALL REWIND(DATEI); CALL WRITE(DATEI,ERGLIS,VORGLI,VORGNR,ERGNR); CLOSE DATEI; END; /* SAVE */ /*------------------------------------------------------------------*/ EDIT : PROC; /* Aenderungen der Eingabedaten */ DCL WAHL CHAR(1); DCL (VON,NACH) FIXED; DCL DAUER FLOAT; PUT TOCHAR(27),'*' TO TERM BY (2)A,SKIP(3); PUT ' 1 = Vorgangsdauern aendern' TO TERM BY A,SKIP; PUT ' 2 = Vorgangsliste erweitern' TO TERM BY A,SKIP; PUT ' 3 = Kompletten Vorgang aendern' TO TERM BY A,SKIP; PUT ' Bitte waehlen ' TO TERM BY SKIP,A; GET FRAGE FROM EIN BY F(1); CASE FRAGE ALT PUT TOCHAR(27),'*' TO TERM BY (2)A,SKIP(2); PUT 'Alle Vorgaenge, welche geaendert werden sollen, eingeben.' TO TERM BY A,SKIP; PUT'(Beenden mit 0)' TO TERM BY A,SKIP(2); REPEAT PUT'Von ' TO TERM BY A; GET VON FROM TERM BY SKIP,F(10); IF VON == 0 THEN GOTO AUS; FIN; CALL TAB(15); PUT 'nach ' TO TERM BY A; GET NACH FROM TERM BY SKIP,F(10); CALL TAB(30); PUT'Dauer ' TO TERM BY A; GET DAUER FROM TERM BY SKIP,F(10); PUT TO TERM BY SKIP; FOR K TO VORGNR REPEAT IF (VORGLI(K).VON==VON) AND (VORGLI(K).NACH==NACH) THEN VORGLI(K).DAUER=DAUER; FIN; END; END; ALT ERWEIT='1'B; VORGNR=VORGNR+1; CALL EING; ALT PUT TOCHAR(27),'*' TO TERM BY (2)A,SKIP(2); PUT 'Alle Vorgaenge, welche geaendert werden sollen, eingeben.' TO TERM BY A,SKIP; PUT'(Beenden mit 0)' TO TERM BY A,SKIP(2); REPEAT PUT'Von ' TO TERM BY A; GET VON FROM TERM BY SKIP,F(10); IF VON == 0 THEN GOTO AUS; FIN; CALL TAB(15); PUT 'nach ' TO TERM BY A; GET NACH FROM TERM BY SKIP,F(10); PUT TO TERM BY SKIP; FOR K TO VORGNR REPEAT IF (VORGLI(K).VON==VON) AND (VORGLI(K).NACH==NACH) THEN PUT'Vorgang neu eingeben: ' TO TERM BY SKIP,A,SKIP; PUT'Von ' TO TERM BY A; GET VON FROM TERM BY SKIP,F(10); CALL TAB(15); PUT'nach ' TO TERM BY A; GET NACH FROM TERM BY SKIP,F(10); CALL TAB(30); PUT'Dauer ' TO TERM BY A; GET DAUER FROM TERM BY SKIP,F(10); PUT TO TERM BY SKIP; VORGLI(K).VON=VON; VORGLI(K).NACH=NACH; VORGLI(K).DAUER=DAUER; FIN; END; END; FIN; AUS: END; /* EDIT */ /*------------------------------------------------------------------*/ VORLIS : PROC; /* Listet alle Vorgaenge auf */ DCL WAHL CHAR(1); PUT TOCHAR(27),'*' TO TERM BY (2)A; PUT TOCHAR(27),'*' TO TERM BY (2)A; PUT' Anfangszeitpunkte Endzeitpunkte Pufferz eiten ' TO TERM BY A,SKIP; PUT'Vorgang Dauer FA SA FE SE GP FP UP 'TO TERM BY A,SKIP; FOR I TO VORGNR REPEAT PUT VORGLI(I).VON,'-',VORGLI(I).NACH,VORGLI(I).DAUER,VORGLI(I).FA, VORGLI(I).SA,VORGLI(I).FE,VORGLI(I).SE,VORGLI(I).GP,VORGLI(I).FP, VORGLI(I).UP TO TERM BY F(3),A,F(3),F(7),(7)(F(9)),SKIP; END; PUT 'zurueck zum Menue? ' TO TERM BY SKIP,A; GET WAHL FROM EIN BY SKIP,A; END; /* VORLIS */ /*-------------------------------------------------------------------*/ EREIGN : PROC; /* Listet alle Ereignisse auf */ DCL WAHL CHAR; PUT TOCHAR(27),'*' TO TERM BY (2)A,SKIP; FOR I TO ERGNR REPEAT PUT'Ereignis ',I,': FZ= ',ERGLIS(I).FZ,' SZ= ',ERGLIS(I).SZ TO TERM BY A,F(3),A,F(9,1),A,F(9,1); IF ERGLIS(I).FZ==ERGLIS(I).SZ THEN CALL TAB(10); PUT '---kritischer Weg---' TO TERM BY A,SKIP; ELSE PUT TO TERM BY SKIP; FIN; END; PUT 'zurueck zum Menue? ' TO TERM BY SKIP,A; GET WAHL FROM EIN BY SKIP,A; END; /* EREIGN */ /*------------------------------------------------------------------*/ DRUCK : PROC; /* Ausdruck aller Vorgaenge und Ereignisse */ /* Druckertyp: ITOH 8510 */ DCL ZEILE FIXED INIT(1); PUT TOCHAR(27),'E',TOCHAR(27),'L','0','1','0' TO PRINT BY (7)A; PUT TO PRINT BY SKIP(2); FOR I TO ERGNR REPEAT ZEILE=ZEILE+1; PUT 'Ereignis ',I,': FZ= ',ERGLIS(I).FZ,' SZ= ', ERGLIS(I).SZ TO PRINT BY A,F(3),A,F(10,1),A,F(10,1); IF ERGLIS(I).FZ==ERGLIS(I).SZ THEN PUT ' --- kritischer Weg ---' TO PRINT BY A,SKIP; ELSE PUT TO PRINT BY SKIP; FIN; IF ZEILE >= 63 THEN PUT TOCHAR(12) TO PRINT BY A; ZEILE=1; FIN; END; PUT TOCHAR(12) TO PRINT BY A; PUT TO PRINT BY SKIP(2); PUT'Anfangszeitpunkt','Endzeitpunkt','Pufferzeiten' TO PRINT BY X(18),A, X(8),A,X(13),A,SKIP; PUT'Vorgang Dauer FA SA FE SE GP FP UP' TO PRINT BY A,SKIP; ZEILE=1; FOR I TO VORGNR REPEAT ZEILE=ZEILE+1; PUT VORGLI(I).VON,'-',VORGLI(I).NACH,VORGLI(I).DAUER,VORGLI(I).FA, VORGLI(I).SA,VORGLI(I).FE,VORGLI(I).SE,VORGLI(I).GP,VORGLI(I).FP, VORGLI(I).UP TO PRINT BY F(3),A,F(3),F(7),(7)(F(10,1)),SKIP; IF ZEILE >=63 THEN PUT TOCHAR(12) TO PRINT BY A; ZEILE=1; FIN; END; END; /* PRINT */ /*------------------------------------------------------------------*/ NETZ : TASK; REPEAT ERWEIT='0'B; LOOP:PUT TOCHAR(27),'*' TO TERM BY (2)A; PUT 'Netzplantechnik nach CPM' TO TERM BY SKIP,X(30),A,SKIP; PUT'1 = Netzplan eingeben ' TO TERM BY SKIP,A; PUT'2 = Netzplan von Diskette laden ' TO TERM BY SKIP,A; PUT'3 = Netzplan auf Diskette speichern ' TO TERM BY SKIP,A; PUT'4 = Berechnen der Zeiten ' TO TERM BY SKIP,A; PUT'5 = Aendern des Netzplanes' TO TERM BY SKIP,A; PUT'6 = Vorgaenge auflisten ' TO TERM BY SKIP,A; PUT'7 = Ereignisse auflisten ' TO TERM BY SKIP,A; PUT'8 = Ergebnisse ausdrucken ' TO TERM BY SKIP,A; PUT'9 = Beenden des Programmes ' TO TERM BY SKIP,A,SKIP; PUT'Bitte waehlen ' TO TERM BY SKIP,A; GET FRAGE FROM EIN BY SKIP,F(1); CASE FRAGE ALT CALL EING; ALT CALL LOAD; ALT CALL SAVE; ALT CALL ZEITPT; ALT CALL EDIT; ALT CALL VORLIS; ALT CALL EREIGN; ALT CALL DRUCK; ALT GOTO AUSG; OUT GOTO LOOP; FIN; END; AUSG: PUT TO TERM BY SKIP(2); END; /*--------------------------------------------------------------------*/ MODEND;