visitor (0 QPoints)
  • FR
  • EN
  • NL
  • DE
  • ES
315 experts, 1193 registered users, 1659 questions already answered
European Experts Exchange, the very best site for high-quality IT solutions

New Improved Search!

 


05/10/2011 1h30 : Steve Jobs is dead, the father of Apple ][ is gone, we are all orphaned.

Languages :: Delphi :: Project timeline (gantt chart)


By: bogiboy U.S.A.  Date: 30/09/2003 00:00:00  English  Points: 50 Status: Answered
Quality : Excellent
I don't want to use fancy controls that already exist for this purpose.
I just want to have a way to show tasks in something similar to MSProject's gantt chart - no need for D&D etc...

I was thinking about starting from DrawGrid but I am not sure if that's the right path.
Any comments?
By: VGR Date: 30/09/2003 04:37:00 English  Type : Comment
I did it... in Turbo pascal... :D
By: bogiboy Date: 30/09/2003 17:09:00 English  Type : Comment
Could you post some examples?
By: swift99 Date: 30/09/2003 18:07:00 English  Type : Comment
Presentation wise, Gantt chart is simply a bunch of rectangles (and other shapes) in a canvas. A DrawGrid is as good a choice for a starting point as any, and better than most.

In the event that draws a row, you want to interpret your row's data and present the appropriate shapes. It would be easy to have some performance problems, so pay attention to repeated and un-necessary work.
By: bogiboy Date: 30/09/2003 18:21:00 English  Type : Comment
I will display one column for every day (calculate based on Project start/end date)
and number of rows = number of resources.

If I create array of TShape rectangles 1...numberOfTasks and place them in appropriate cells, would it be memory intensive?

Or to go and draw using DrawGrid.OnCellDraw with grid.Canvas and TRect?
By: DragonSlayer Date: 01/10/2003 22:22:00 English  Type : Comment
get TurboPower Visual PlanIt <A HREF="http://sourceforge.net/projects/tpvplanit/">http://sourceforge.net/projects/tpvplanit/</a>
By: VGR Date: 01/10/2003 22:59:00 English  Type : Comment
yes. And my conversion/emulation "Graph" unit for Delphi enabled me to keep all TPascal programming unchanged. In stead of direct Video BIOS access, it's now drawn on a TPicture or TBitmap

I'll find the sources for you
By: VGR Date: 01/10/2003 23:06:00 English  Type : Answer
here they are. This is the 100% DOS program. It used to be good :D

Dated 27/01/1994, Turbo-Pascal 5.0, accents and diacritics were "eaten" by the PC437-Dos/ANSI-Win "conversion", but the program should work.

Look at the "TraceGANTT" procedure : it draws a "au plut tôt" (earlier) Gantt diagram

I also give you a sample data file

Program PERT; { (InPut, OutPut); }

{

programme SIMPLE !!!

ex‚cution : ALT-R R

sauvegarde aprŠs modif : F2

sortie de Turbo Pascal 5.0 : ALT-F Q ou ALT-X

nom de fichier : PERT.PAS, le projet par d‚faut ‚tant dans PERT.PPJ


L'entr‚e manuelle d'un nouveau projet est toujours possible;

L'extension DOS utilis‚e est .PPJ

}

{ Programme de GProjAO : Gestion de Projets Assist‚e par Ordinateur

Cr‚ation : 08 Juin 1993 AD
Releases : 1.00 le 08 Juin 1993 AD
1.10 le 30 Janvier 1994 AD
1.12 le 01 F‚vrier 1994 AD
1.13 le 27 Avril 1994 AD
Shareware le 30/01/94, consultez le fichier LISEZMOI.TXT

R‚visions : 1.10 : ajout de la pr‚sentation et des drivers et pilotes.
1.12 : changement de fonte de trac‚.
1.13 : Y+1 au trac‚ du rectangle-case PERT. (lignes 1096 et 1248)

Avertissement : la technique utilis‚e est la m‚thode MPM : M‚thode des
Potentiels Metra. Plus le PERT Cost (+optimisation) et le GANTT.


@1994 Hefiz. Tous droits r‚serv‚s pour tous pays.

Adresses ‚lectroniques en 1994 : 3614 CHEZ*HEFIZ, <SUITE>5 puis <ENVOI>
3615 AKELA, pseudo puis *BE HEFIZ
( accŠs 3614 : 195150660 )
3615 MENSA, pseudo puis *B

Rem : Unit‚s de programme en Turbo Pascal 5.0

}

{ d‚clarations d'unit‚s }
Uses Crt, Graph, ChargeToutGraphix, Printer, Dos, I_O, Imprimante, Graphiques;

Const cVer = '1.13';
cLegende = 'ShW @Hefiz 1993, 1994 : ';



{###########################################################################}
{###########################################################################}
{##### P A R T I E D E C L A R A T I V E #####}
{###########################################################################}
{###########################################################################}




{ Constantes de d‚finition des r‚seaux }
Const MaxTaches = 30;
FonteDeBase = SmallFont;
TailleDeBase = 4;

{ types de donn‚es }
Type
EchelleTemps = (heures,jours,semaines,mois,annees);
Durees = array [1..3] of Integer;
St20 = String[20];
St10 = String[10];
Dates = array [1..3] of St10;
ptTache = ^Tache;

Tache = Record

Libelle : string[20];

Temps_prevus : Durees;
Couts : array[1..2] Of Real;

RelTemps : array[1..2] of Integer;
Dates_prevues : Dates;
Marge_brute : Integer;
Marge_Libre : Integer;

Precedentes, Suivantes : array[1..10] of ptTache;
NbPrecs, NbSuivs : Integer;

End; { Record }


TacheWrk = Record
precede : Boolean;
{ niveau : Integer; }
End; { Record }

TypMat = array [1..MaxTaches+2,1..MaxTaches+2] of TacheWrk;
TypNiv = array [1..MaxTaches+2] Of Integer;
TypCPath = array [1..MaxTaches+2] of Boolean;


{ d‚claration des variables }
Var
MatTaches,
MatPropre : TypMat;
NivGraphe : Integer;
TacheNiv : TypNiv;
NbTaches : Integer;
Critical : TypCPath;
i, j : Integer; { compteurs }

ProjTitre : St20;
Projet : ptTache;
UniteTemps : EchelleTemps;

DateDepart : St10;

DureeTotale : Integer;

CoutTotal,
CoutMini,
Cout50 : Real;

{ menu }
Const OkCalcule : Boolean = False;
Const OkGraphx : Boolean = False;
Const OkDates : Boolean = False;
Const OkOptions : Boolean = False;

{ pr‚sence des donn‚es !!! }
Const OkDonnees : Boolean = False;

Var
Option : Byte;
rep : Char;
TravailEnCours : String;

{ graphique }
Const OptValue : Boolean = False;

{ clart‚ }
Const OptCycles : Boolean = False;


{###########################################################################}
{###########################################################################}
{##### P A R T I E E N T R E E D E S D O N N E E S #####}
{###########################################################################}
{###########################################################################}

Procedure InitialiseMatrice( Var MT : TypMat );
Begin
For i:=1 to MaxTaches+2 Do
For j:=1 to MaxTaches+2 Do
Begin
MT[i,j].precede:=False;
{ MT[i,j].niveau:=0; }
End; { For, For }

End; { InitialiseMatrice Procedure }




Procedure ChoixUniteTemps(Var UT);
Begin
End; { ChoixUniteTemps Procedure }



Procedure InitialiseTache(Var tache : ptTache );
Begin
New(tache);
With tache^ Do
Begin
NbPrecs:=0;
NbSuivs:=0;
Libelle:='';
Temps_prevus[1]:=0;
RelTemps[1]:=0;
RelTemps[2]:=0;
Dates_prevues[1]:='';
Marge_brute:=0;
End; { With }
End; { InitialiseTache Procedure }





Type TypProj = array[1..MaxTaches+2] Of ptTache;
Var ProjTab : TypProj;


Procedure EntreeProjetTab ( Var ProjTitr : St20; Var P : TypProj;
Var MT : TypMat;
Var nbt : Integer; Var DD : St10 );
Var numT : Integer;

Begin
ClrScr;
WriteLn('ATTENTION en cas de sauvegarde avort‚e avec "fin" (voir "sauvegarde")');
WriteLn('c''est le fichier partag‚ PERT.PPJ qui sera r‚-‚crit !');
WriteLn;
WriteLn;
WriteLn;
WriteLn(' Je vous conseille aussi de sauvegarder sous un nom bidon, PUIS, une');
WriteLn(' fois les CALCULS effectu‚s, le sauver sous le VRAI nom. (astuce+s‚curit‚)');
WriteLn;
WriteLn;
Write('Titre du Projet (ex : "Projet Bateau" en 20c ) : ? '); ReadLn(ProjTitr);
Repeat
Write('combien de tƒches ? ');
ReadLn(nbt);
If (nbt>MaxTaches) Then WriteLn(MaxTaches,' est la limite actuelle!');
If (nbt<2) Then WriteLn('Planifier autant de tƒches doit ˆtre ais‚!');
Until (nbt<=MaxTaches) AND (nbt>1);

{ ‚cran de saisie }
ClrScr;
WriteLn('PROJET : ',ProjTitr,' ( ',nbt,' tƒches )');
{ d‚limitations coquines }
GotoXY(1,4); WriteLn(Characters('-',79));
GotoXY(1,13); WriteLn(Characters('-',79));
GotoXY(1,16); WriteLn(Characters('-',79));
GotoXY(1,18); WriteLn(Characters('-',79));
{ au boulot }
For numT:= 1 to nbt Do { on d‚calera lors des r‚f‚rences }
Begin
{ trac‚ des tƒches d‚j… d‚finies }
If numT>1 Then
Begin
GotoXY(1+10*((numT-1) MOD 8),22+((numT-1) DIV 8));
Write(numT-1:2,' : ',Copy(P[numT]^.Libelle,1,3));
End;
{ entr‚e de la nouvelle tƒche...}
New(P[numT+1]);
GotoXY(1,3); ClrEol; WriteLn('entr‚e de la tƒche nø ',numT);
GotoXY(1,5); ClrEol; Write('Nom de cette tƒche nø ',numT,' (3c maxi conseill‚) : '); ReadLn(P[numT+1]^.Libelle);
GotoXY(1,7); ClrEol; Write('Nombre de tƒches ant‚c‚dentes ? '); ReadLn(P[numT+1]^.NbPrecs);
(* GotoXY(1,); Write('Nombre de tƒches post‚rieures ? '); ReadLn(P[numT+1]^.NbSuivs); *)
{ dur‚es ‚l‚mentaires }
GotoXY(1,9); ClrEol; Write('Dur‚e : pr‚vue, mini, maxi ? ');
For j:=1 to 3 Do
Begin
GotoXY(1,9+j); ClrEol; Write('Dur‚e ? '); ReadLn(P[numT+1]^.Temps_Prevus[j]);
End;
{ co–ts ‚l‚mentaires }
GotoXY(1,14); ClrEol; Write('Co–ts : de base / unit‚ de temps ( dur‚e pr‚vue ) : '); ReadLn(P[numT+1]^.Couts[1]);
GotoXY(1,15); ClrEol; Write('Co–ts : suppl‚mentaire / unit‚ de temps (au del…) : '); ReadLn(P[numT+1]^.Couts[2]);
{ les tƒches pr‚c‚dentes d'abord }
For i:=1 to P[numT+1]^.NbPrecs Do
Begin
GotoXY(1,17); ClrEol; Write('Num‚ro de la tƒche ant‚c‚dente nø ',i,' ? : '); ReadLn(j);
{ on affecte la matrice de pr‚c‚dence }
MT[j+1,numT+1].precede:=True; { ATTENTION au d‚calage sur J !!! }
End; { For (pr‚c‚dentes) }
If P[numT+1]^.NbPrecs=0 Then { "tƒche fictive" de d‚but, un comble en MPM ! }
MT[1,numT+1].precede:=True; { la tƒche 1 'd‚b' pr‚cŠde cette tƒche... }

(*
{ les suivantes maintenant }
For i:=1 to P[numT+1]^.NbSuivs Do
Begin
GotoXY(1,); ClrEol; Write('Num‚ro de la tƒche suivante nø ',i,' ? : '); ReadLn(j);
{ on affecte la matrice de pr‚c‚dence }
MT[numT+1,j+1].precede:=True;
End; { For (suivantes) }
*)

GotoXY(1,20); ClrEol; { inutile } Write('Tƒches d‚j… d‚finies : ');

End; { For tƒches "normales" }

{ tƒche fictive de d‚but }
New(P[1]);
P[1]^.Libelle:='d‚b';
P[1]^.NbPrecs:=0;
{ dur‚es ‚l‚mentaires }
For j:=1 to 3 Do
P[1]^.Temps_Prevus[j]:=0;
{ co–ts ‚l‚mentaires }
P[1]^.Couts[1]:=0.0;
P[1]^.Couts[2]:=0.0;

{ tƒche fictive de fin, un comble! }
{ trac‚ des tƒches d‚j… d‚finies }
GotoXY(1+10*((nbt+1-1) MOD 8),22+((nbt+1-1) DIV 8));
Write(nbt+1-1:2,' : ',Copy(P[nbt+2-1]^.Libelle,1,3));
{ entr‚e de la nouvelle tƒche...}
New(P[nbt+2]);
GotoXY(1,3); ClrEol; WriteLn('entr‚e de la tƒche nø ',nbt+1);
GotoXY(1,5); ClrEol;
Write('Nom de cette tƒche nø ',nbt+1,' (3c maxi conseill‚) : fin ("fin" et "d‚b" : jalons)');
P[nbt+2]^.Libelle:='fin';
Repeat
GotoXY(1,7); ClrEol; Write('Nombre de tƒches ant‚c‚dentes ? '); ReadLn(P[nbt+2]^.NbPrecs);
Until (P[nbt+2]^.NbPrecs>0);
(* GotoXY(1,); Write('Nombre de tƒches post‚rieures ? '); ReadLn(P[nbt+2]^.NbSuivs); *)
{ dur‚es ‚l‚mentaires }
GotoXY(1,9); ClrEol; Write('Dur‚e : pr‚vue, mini, maxi ? ');
For j:=1 to 3 Do
Begin
GotoXY(1,9+j); ClrEol; Write('Dur‚e ? 0'); P[nbt+2]^.Temps_Prevus[j]:=0;
End;
{ co–ts ‚l‚mentaires }
GotoXY(1,14); ClrEol; Write('Co–ts : de base / unit‚ de temps ( dur‚e pr‚vue ) : 0.0'); P[nbt+2]^.Couts[1]:=0.0;
GotoXY(1,15); ClrEol; Write('Co–ts : suppl‚mentaire / unit‚ de temps (au del…) : 0.0'); P[nbt+2]^.Couts[2]:=0.0;
{ les tƒches pr‚c‚dentes d'abord }
For i:=1 to P[nbt+2]^.NbPrecs Do
Begin
GotoXY(1,17); ClrEol; Write('Num‚ro de la tƒche ant‚c‚dente nø ',i,' ? : '); ReadLn(j);
{ on affecte la matrice de pr‚c‚dence }
MT[j+1,nbt+2].precede:=True; { ATTENTION au d‚calage de 1 sur J !!! }
End; { For (pr‚c‚dentes) }

nbt:=nbt+2; { pour que tout le monde soit d'accord. }

{ date de d‚part du projet entier }
GotoXY(1,3); ClrEol; {inut} Write('Date de d‚part du projet entier ? (10c)'); ReadLn(DD);

{ ici chaŒnage }

End; { EntreeProjetTab Procedure }




(*
Procedure EntreeProjet ( Var P : ptTache; Var MT : TypMat );
Var numT : Integer;
Begin
ClrScr;
InitialiseTache(P); { c'est la tƒche num‚ro 1 }
numT:=1;
Repeat
GotoXY(1,18); WriteLn('entr‚e de la tƒche nø ',numT);
GotoXY(1,20); Write('Nom de cette tƒche nø ',numT); ReadLn(P^.Libelle);
GotoXY(1,21); Write('Nombre de tƒches ant‚c‚dentes ? '); ReadLn(P^.NbPrecs);
GotoXY(1,22); Write('Nombre de tƒches post‚rieures ? '); ReadLn(P^.NbSuivs);
GotoXY(1,23); Write('Dur‚e pr‚vue ? '); ReadLn(P^.Temps_prevus[1]);
{ les tƒches pr‚c‚dentes d'abord }
For i:=1 to P^.NbPrecs Do
Begin
GotoXY(1,24); Write('Num‚ro de la tƒche ant‚c‚dente nø ',i,' ? : '); ReadLn(j);
{ on affecte la matrice de pr‚c‚dence }
MT[j,numT].precede:=True;
End; { For (pr‚c‚dentes) }
{ les suivantes maintenant }
For i:=1 to P^.NbSuivs Do
Begin
GotoXY(1,24); Write('Num‚ro de la tƒche suivante nø ',i,' ? : '); ReadLn(j);
{ on initialise le pointeur de la chaŒne du projet }
InitialiseTache(P^.Suivantes);
{ on affecte la matrice de pr‚c‚dence }
MT[numT,j].precede:=True;
Inc(numT); { est ex‚cut‚ sauf pour la derniŠre tƒche }
End; { For (suivantes) }

Until P^.NbSuivs=0; { indique qu'on a rentr‚ la derniŠre tƒche... }

End; { EntreeProjet Procedure }
*)





{###########################################################################}
{###########################################################################}
{##### P A R T I E C A L C U L S #####}
{###########################################################################}
{###########################################################################}


Procedure CalculeNiveaux( MT:TypMat; NbT : Integer;
Var NG : Integer; Var TNiv : TypNiv );

Var i, j : Integer; { compteurs }
Som : array[1..MaxTaches] of Integer; { somme par colonnes }
DejaVu : array [1..MaxTaches] of Boolean;
Nbtraites : Integer;

Begin
NG:=0;
Nbtraites:=0;
For i:=1 to NbT Do DejaVu:=False;
Repeat
Inc(NG);
{}Write(' ',NG,':',(100*Nbtraites/NbT):4:2);
For j:=1 to NbT Do
Begin
Som[j]:=0;
For i:=1 to NbT Do
Som[j]:=Som[j]+Ord(MT[i,j].precede);
End; { For }
{ on d‚termine les z‚ros => niveau NG }
For j:=1 to NbT Do
If (Som[j]=0) AND NOT DejaVu[j] Then
Begin
{ rangement }
TNiv[j]:=NG;
{ mise … "0" de la ligne }
For i:=1 to NbT Do MT[j,i].precede:=False;
{ passage … la suite }
Inc(Nbtraites);
DejaVu[j]:=True;
End; { If, For }
Until Nbtraites=NbT;

{ v‚rification des entr‚e et sortie }
j:=0;
For i:=1 to NbT Do
If TNiv=1 Then Inc(j);
If j<>1 Then WriteLn('WARNING : plus d''une tƒche de niveau 1... Introduisez une tƒche "d‚but" !');
j:=0;
For i:=1 to NbT Do
If TNiv=NG Then Inc(j);
If j<>1 Then WriteLn('WARNING : plus d''une tƒche de niveau final... Introduisez une tƒche "fin" !');

End; { CalculeNiveaux Procedure }





Procedure OteCycles( Var MT : TypMat; NbT : Integer );

Var j, k : Integer; { compteurs }
DejaVu : array [1..MaxTaches] of Boolean;
NbTraites : Integer;

Begin
Nbtraites:=0;
If NbT=0 Then Exit; { primitif }
For i:=1 to NbT Do DejaVu:=False;

Repeat
{ 1. on part d'un sommet X de S }
Inc(NbTraites);
{ 2. on parcourt les sommets N tq'il existe un arc (X,N) }
j:=0;
Repeat
Inc(j);
If MT[NbTraites,j].precede AND NOT DejaVu[j] Then
Begin
{ 3. si N est de Sø on passe sinon on explore les fils M de N }
k:=0;
Repeat
Inc(k);
If MT[j,k].precede Then
{ 4. s'il existe un arc (X,M) cet arc est inutile }
If MT[NbTraites,k].precede
Then Begin
MT[NbTraites,k].precede:=False;
End; { If arc inutile }
Until k=NbT;
End; { If arc (X,N) }
Until j=NbT;
{ 5. X va dans Sø }
DejaVu[NbTraites]:=True;
{ 6. on retourne en 1.) s'il reste des sommets dans S }
Until Nbtraites=NbT;

End; { OteCycles Procedure }





Function ValDate ( a : St10 ) : Integer;
Var z,t,poub : Integer;
p, q : St10;
Begin
p:=a;
{ jour }
q:=Copy(p,1,Pos('/',p));
p:=Copy(p,Pos('/',p)+1,Pos('/',p));
if q='' Then Begin ValDate:=0; Exit; { remonte d'un cran d'appel } End;
Val(q,z,poub);
{ mois }
q:=Copy(p,1,Pos('/',p));
p:=Copy(p,Pos('/',p)+1,Length(p)-Pos('/',p));
if q='' Then Begin ValDate:=0; Exit; { remonte d'un cran d'appel } End;
Val(q,t,poub);
z:=z+12*t;
{ ann‚e }
Val(p,t,poub);
z:=z+365*t;

{ retour }
ValDate:=z;
End; { ValDate St10 Function }

Function MaxDate ( a,b : St10 ) : St10;
Begin
If ValDate(a)>ValDate(b) Then MaxDate:=a Else MaxDate:=b;
End; { MaxDate St10 Function }



Function MaxNb ( a,b : Integer ) : Integer;
Begin
If a>b Then MaxNb:=a Else MaxNb:=b;
End; { MaxNb Integer Function }



Procedure CalculeDatesPlusTot;
Var i, n : Integer;
DateDebut : St10;
RelDebut : Integer;

Begin
DureeTotale:=0;
For n:=1 to NivGraphe Do
For i:=1 to NbTaches Do
Begin
RelDebut:=0;
If TacheNiv=n Then { on travaille la tƒche i }
Begin
DateDebut:='00/00/0000';
For j:=1 to NbTaches Do
If MatTaches[j,i].precede Then { la tƒche j pr‚cŠde la tƒche i }
RelDebut:=MaxNb(RelDebut,ProjTab[j]^.RelTemps[1]+ProjTab[j]^.Temps_Prevus[1]);
ProjTab^.RelTemps[1]:=RelDebut;

{ pour les dates en chaŒnes...
DateDebut:=MaxDate(DateDebut,ProjTab[j]^.Dates_Prevues[1]);
ProjTab^.Dates_Prevues[1]:=DateDebut;
}

If n=NivGraphe Then DureeTotale:=RelDebut+ProjTab^.Temps_prevus[1]; { planifi‚e }
{ ok SSI une seule tƒche de fin, mais dur‚e non nulle indiff‚rente. }

End; { If }
End; { For niveaux }
End; { CalculeDatesPlusTot Procedure }




Function MinNb ( a,b : Integer ) : Integer;
Begin
If a<b Then MinNb:=a Else MinNb:=b;
End; { MinNb Integer Function }


Procedure CalculeDatesPlusTardMarges;
Var i, n : Integer;
RelDebut : Integer;

Begin

For n:=NivGraphe DownTo 1 Do
For i:=1 to NbTaches Do
Begin
RelDebut:=DureeTotale-ProjTab[NbTaches]^.Temps_prevus[1]; { la derniŠre tƒche peut avoir une dur‚e... }
If TacheNiv=n Then { on travaille la tƒche i }
Begin
For j:=1 to NbTaches Do
If MatTaches[i,j].precede Then { la tƒche i pr‚cŠde la tƒche j }
RelDebut:=MinNb(RelDebut,ProjTab[j]^.RelTemps[2]-ProjTab^.Temps_Prevus[1]);
ProjTab^.RelTemps[2]:=RelDebut;
{ marge totale }
With ProjTab^ Do Marge_brute:=RelDebut-RelTemps[1];
End; { If }
End; { For niveaux }

{ marges libres }
For i:=1 to NbTaches Do
Begin
RelDebut:=MaxInt;
For j:=1 to NbTaches Do
If MatTaches[i,j].precede Then
RelDebut:=MinNb(RelDebut,ProjTab[j]^.RelTemps[1]-ProjTab^.RelTemps[1]-ProjTab^.Temps_prevus[1]);
ProjTab^.Marge_Libre:=RelDebut;
End; { For tƒches }
ProjTab[NbTaches]^.Marge_Libre:=0; { c'est la tƒche qui n'a plus de suivant }

End; { CalculeDatesPlusTardMarges Procedure }




Procedure TrouveCriticalPath ( PTab : TypProj; NbT : Integer; Var CP : TypCPath );
Var i : Integer;
Begin
For i:= 1 to NbT Do
CP:=(PTab^.RelTemps[1]=PTab^.RelTemps[2]);
End; { TrouveCriticalPath Procedure }




Procedure CalculeDates ( Var Projet );
Begin
End; { CalculeDates Procedure }



Function fTacheCoutMin ( ind : Integer ) : Real; Forward;

Procedure CalculeCouts; { bas‚ sur une courbe LINEAIRE (exponentielle normalement) d‚croissante }
Begin

{ on calcule le co–t total du projet, au plus t“t }
CoutTotal:=0;
For i:=1 to NbTaches Do
With ProjTab^ Do CoutTotal:=CoutTotal+Temps_prevus[1]*Couts[1];

{ maintenant on va ‚taler les dur‚es au maxi/minima }
CoutMini:=0;
For i:=1 to NbTaches Do
With ProjTab^ Do CoutMini:=CoutMini+fTacheCoutMin(i);
{ marge brute sans tenir compte de la dur‚e maxi : grosssse erreur!!!}

{ maintenant on va ‚taler moyennement les dur‚es }
Cout50:=0;
For i:=1 to NbTaches Do
With ProjTab^ Do Cout50:=(CoutTotal+CoutMini)/2.0;

End; { CalculeCouts Procedure }





{###########################################################################}
{###########################################################################}
{##### P A R T I E G R A P H I Q U E #####}
{###########################################################################}
{###########################################################################}


{ d‚clarations graphiques }

TYPE
ResolutionPreference = (Lower, Higher); { int‚rˆt nul ici... }

VAR
Xmax,
Ymax,
ViewXmax,
ViewYmax : INTEGER;

Ch : CHAR;
GraphDriver,
GraphMode : INTEGER;
MaxColors : WORD;
pal : PaletteType;

Const HardWareGrafBase : Word = $A000; { EGA, VGA et tutti quanti }


PROCEDURE Frame;
BEGIN
SetViewPort(0, 0, Xmax, Ymax-(TextHeight('M')+4)-1,ClipOn);
SetColor(MaxColors);
Rectangle(0, 0, Xmax-1, (Ymax-(TextHeight('M')+4)-1)-1);
SetViewPort(1, 1, Xmax-2, (Ymax-(TextHeight('M')+4)-1)-2,ClipOn);
END; { De Frame }

PROCEDURE FullPort;
{ D‚finit l'‚cran complet comme fenˆtre active (ViewPort) }
BEGIN
SetViewPort(0, 0, Xmax, Ymax, ClipOn);
END; { De FullPort }

PROCEDURE MessageFrame(Msg:STRING);
BEGIN
FullPort;
SetColor(MaxColors);
SetTextStyle(DefaultFont, HorizDir, 1);
SetTextJustify(CenterText, TopText);
SetLineStyle(SolidLn, 0, NormWidth);
SetFillStyle(EmptyFill, 0);
Bar(0, Ymax-(TextHeight('M')+4), Xmax, Ymax);
Rectangle(0, Ymax-(TextHeight('M')+4), Xmax, Ymax);
OutTextXY(Xmax div 2, Ymax-(TextHeight('M')+2), Msg);
{ Retour … la fenˆtre principale }
Frame;
SetTextStyle(FonteDeBase, HorizDir, TailleDeBase); { SmallFont }
END; { De MessageFrame }

PROCEDURE TestGraphError(GraphErr: INTEGER);
BEGIN
IF GraphErr <> grOk THEN
BEGIN
Writeln('Erreur graphique : ', GraphErrorMsg(GraphErr));
REPEAT UNTIL KeyPressed;
Ch := ReadKey;
Halt(1);
END;
END;



PROCEDURE Init;
VAR
Err, I : INTEGER;
StartX, StartY: INTEGER;
Resolution : ResolutionPreference;
s : STRING;
BEGIN
Ch := ' ';
Resolution:=Higher; { rajout‚ par moi }
GraphDriver := Detect;

(* … cause de chargetoutgraphix...
DetectGraph(GraphDriver, GraphMode);
TestGraphError(GraphResult);
CASE GraphDriver OF
CGA : BEGIN
GraphDriver := CGA;
GraphMode := CGAC1;
END;

MCGA : BEGIN
CASE GraphMode of
MCGAMed, MCGAHi: GraphMode := MCGAC1;
END;
END;

EGA : BEGIN
IF Resolution = Lower THEN
GraphMode := EGALo
ELSE
GraphMode := EGAHi;
END;

EGA64 : BEGIN
IF Resolution = Lower THEN
GraphMode := EGA64Lo
ELSE
GraphMode := EGA64Hi;
END;

HercMono : ;
EGAMono : ;
PC3270 : BEGIN
GraphDriver := CGA;
GraphMode := CGAC1;
END;


ATT400 : CASE GraphMode OF
ATT400C1,
ATT400C2,
ATT400Med,
ATT400Hi :
BEGIN
GraphMode := ATT400C1;
END;
END;

VGA : BEGIN
END;
END; { Du case GraphDriver }
*)

InitGraph(GraphDriver, GraphMode, '');
TestGraphError(GraphResult);
SetTextStyle(FonteDeBase, HorizDir, TailleDeBase); { SmallFont,2 }
SetTextJustify(LeftText, TopText);

MaxColors := GetMaxColor;
GetDefaultPalette(pal);

Xmax := GetMaxX;
Ymax := GetMaxY;
ViewXmax := Xmax-2;
ViewYmax := (Ymax-(TextHeight('M')+4)-1)-2;

END; { De Proc‚dure Init}


Procedure ReEnterGraphMode;
Begin
SetGraphMode(GraphMode);
End; { ReEnterGraphMode Procedure }


{si $I HardCopy : rajouter 2 1ers paramŠtres : XMax et Ymax }

{test impression }
Procedure TestPrint ( ch : Char; msg : String );
Begin
{ (inverse:boolean;mode:byte;page:boolean;laser:boolean;Delai:byte); EPSON }
If (UpCase(ch)='I') Then
If PrinterOk
Then Begin { depuis le changement AUTO de l‚gende... }
{ SetTextStyle(SmallFont,HorizDir,4); }
If msg<>'' Then MessageFrame(cLegende+msg); { sinon pas de changement }
PrintScreen(False,0,True,False,0) { pas laser, pas d'attente XOFF }
End
Else Begin
SetColor(LightRed);
SetTextJustify(CenterText,TopText);
SetTextStyle(SansSerifFont, HorizDir, 0); { on s'en fiche, du 0 }
SetUserCharSize(1,2,3,2); { rationnels sur les X et les Y }
OutTextXY(Xmax DIV 2, YMax DIV 2,'IMPRIMANTE PAS PRETE, d‚sol‚... Revenez aprŠs avoir r‚gl‚ le problŠme !');
Delay(3000);
End;

End; { TestPrint Procedure }

Procedure AttendMessageFrame ( msg : String );
Begin
MessageFrame('Frappez une touche. - '+msg+' - (I = imprime).');
End; { AttendMessageFrame Procedure }

{###########################################################################}
{###########################################################################}
{##### P R E S E N T A T I O N G R A P H I Q U E #####}
{###########################################################################}
{###########################################################################}

Procedure TraceLogoHefiz;
Begin
SetLineStyle(SolidLn,SolidFill,ThickWidth);
MoveTo(50,10);
LineRel(0,40);
LineRel(-40,-40);
LineRel(0,40);
MoveTo(10,30);
LineRel(40,0);
MoveTo(30,10);
LineRel(0,40);
SetLineStyle(SolidLn,EmptyFill,NormWidth);
End; { TraceLogoHefiz Procedure }

Procedure GraphPresente;
Var msg1, msg2 : String[40];
msg3 : String[80];
msg4, msg5 : String;
Begin
msg4:='Hefiz pr‚sente :';
msg5:='Dans la s‚rie : 0\Petits logiciels personnels\Gestion de Projets';
msg1:='PERT/MPM, GANTT, PERT Cost';
msg2:='version '+cVer;
msg3:='@1993 Hefiz. Ceci est un ShareWare. Tous droits r‚serv‚s pour tous pays.';
SetColor(MaxColors); { c'est un choix... }
SetTextJustify(CenterText, TopText);
SetLineStyle(SolidLn, 0, NormWidth);
TraceLogoHefiz;
SetTextStyle(TriplexFont, HorizDir, 4);
OutTextXY(MaxX DIV 2, MaxY DIV 2,msg1);
SetTextStyle(TriplexFont, HorizDir, 2);
OutTextXY(MaxX DIV 2, (MaxY DIV 2)+2*TextHeight('M'),msg2);
SetTextStyle(DefaultFont, HorizDir, 1);
OutTextXY(MaxX DIV 2, MaxY-2*TextHeight('M'),msg3);
SetTextStyle(GothicFont, HorizDir, 4);
OutTextXY(MaxX DIV 2, MaxY DIV 8,msg4);
SetTextStyle(SmallFont, HorizDir, 2);
OutTextXY(MaxX DIV 2, MaxY DIV 4,msg5);

{ on attend l'utilisateur }
Repeat Until KeyPressed;
Ch:=ReadKey;

TestPrint(Ch,''); { on peut vouloir imprimer la page de "garde"... }

End; { GraphPresente Procedure }

{###########################################################################}
{###########################################################################}
{##### A C C E S S O I R E S G R A P H I Q U E S #####}
{###########################################################################}
{###########################################################################}


PROCEDURE Draw(x1,y1,x2,y2,color:WORD);
BEGIN
SetColor(color);
Graph.Line(x1,y1,x2,y2);
END;



Var ColReserved : Integer;

Function NextColor ( col : Integer ) : Integer;
Begin
col:=Succ(col);
If col MOD (MaxColors+1)=0 Then col:=LightBlue;
If col MOD ColReserved=0 Then col:=Succ(col);
NextColor:=col;
End; { NextColor Integer Function }



Procedure Titre ( Msg : String );
Var TitreGauche : Word;
Begin { sont d‚finies : Gothic, Small, SansSerif, Triplex - Font }
TitreGauche:=XMax DIV 4;
SetColor(MaxColors);
SetTextStyle(DefaultFont, HorizDir, 2); { Gothic; on peut taille 2 car vectorielle }
SetTextJustify(CenterText, TopText);
SetLineStyle(SolidLn, 0, NormWidth);
SetFillStyle(WideDotFill, MaxColors); { aussi : Interleave - Fill }
Bar(TitreGauche, 3, Xmax-TitreGauche, 3+(TextHeight('M')+6));
Rectangle(TitreGauche, 3, Xmax-TitreGauche, 3+(TextHeight('M')+6));
OutTextXY(Xmax DIV 2, 6, Msg);
SetTextStyle(FonteDeBase, HorizDir, TailleDeBase); { SmallFont }
End; { Titre Procedure }




{###########################################################################}
{###########################################################################}
{##### D I A G R A M M E D E G A N T T au plus t“t #####}
{###########################################################################}
{###########################################################################}

Procedure TraceGANTT ( PTab : TypProj; NbT : Integer; DT : Integer ; TeC : String );
Var i, x1,x2,y1,y2 : Integer;
PasGraphik : Integer;
Color : Integer;
msg : St10;

Begin
{ couleur de d‚part }
If MaxColors>5 Then ColReserved:=LightRed Else ColReserved:=MaxColors;
Color:=-1; { toujours au moins d‚finie }
Color:=NextColor(Color);

{ on calcule le 'pas' graphique du trac‚ }
PasGraphik:=Xmax DIV DT;

{ on trace le GANTT au plus t“t }
{ trac‚ de l'axe des temps }
Draw(0,2,Xmax,2,ColReserved); { l'axe }
SetLineStyle(DashedLn,EmptyFill,NormWidth);
For j:=0 to DT Do { les graduations }
Begin
PutPixel(j*PasGraphik,3,ColReserved); { pour mieux voir }
PutPixel(j*PasGraphik,4,ColReserved); { pour mieux voir }

{ trac‚ d'axes verticaux tous les 5 unit‚s; … passer en 'options' !!! }
If (j MOD 5 = 0) Then Draw(j*PasGraphik,5,j*PasGraphik,Ymax,ColReserved);

End; { For graduations }

{ et GANTT proprement dit }
SetLineStyle(SolidLn,EmptyFill,NormWidth);
For i:=1 to NbT Do
Begin
x1:=PasGraphik*PTab^.RelTemps[1];
y1:=(Ymax DIV (NbT+1))*i;
x2:=x1+PasGraphik*PTab^.Temps_Prevus[1];
y2:=y1;
(* affiche num‚ro au lieu du libell‚ : Str(i,msg); *)
msg:=PTab^.Libelle;
If PTab^.RelTemps[1]=PTab^.RelTemps[2]
Then Draw(x1,y1,x2,y2,ColReserved) { une tƒche critique }
Else Begin Draw(x1,y1,x2,y2,Color); Color:= NextColor(Color); { normalement } End; { If }
For j:=0 to PTab^.Temps_Prevus[1] Do
PutPixel(x1+j*PasGraphik,y1-1,MaxColors); { pour mieux voir }
OutTextXY((x1+x2+4) DIV 2,y1+1,msg);
End;

{ on attend l'utilisateur }
Repeat Until KeyPressed;
Ch:=ReadKey;

{ impression si I ou i }
TestPrint(ch,TeC);

End; { TraceGANTT Procedure }






{###########################################################################}
{###########################################################################}
{##### P E R T et O U T I L S A S S O C I E S #####}
{###########################################################################}
{###########################################################################}



Procedure MonRectangle ( x1,y1,x2,y2,col : Word);
Begin
SetColor(col);
Graph.Rectangle(x1,y1,x2,y2);
End;

Procedure TraceFleche ( x1,y1,x2,y2 : Integer; Critical : Boolean;
Col, ColR : Integer );
Begin
{ selon Critical choisit ‚paisseur et couleur }
If Critical
Then Begin
SetLineStyle(SolidLn,EmptyFill,ThickWidth);
SetColor(ColR);
End
Else Begin
SetLineStyle(SolidLn,EmptyFill,NormWidth);
SetColor(Col);
End; { If, Then, Else }

{ trace ligne }
Graph.Line(x1,y1,x2,y2);

{ trace flŠche, toujours vers la droite }
Graph.Line(x2,y2,x2-3,y2-3);
Graph.Line(x2,y2,x2-3,y2+3);

End; { TraceFleche Procedure }



{###########################################################################}
{###########################################################################}
{##### P E R T T E M P S #####}
{###########################################################################}
{###########################################################################}


Procedure TracePERT ( PTab : TypProj; NbT : Integer; TN : TypNiv; NG : Integer;
CP : TypCPath; MT : TypMat; ValueArcs : Boolean ;
TeC : String );

Var i, x1,x2,y1,y2 : Integer;
PasX, PasY : Integer;
Color : Integer;
NbIci,
Deca, DecaY : Integer;
msg : St10;

x1s, y1s, x1e, y1e : array[1..MaxTaches] Of Word;
Col : array[1..MaxTaches] Of Byte;

Begin
{ couleur de d‚part }
Color:=MaxColors; { toujours au moins d‚finie }
If MaxColors>5 Then ColReserved:=LightRed Else ColReserved:=MaxColors;

{ on calcule le 'pas' graphique du trac‚ }
PasX:=Xmax DIV (NG+1); { pour aller de Niv=1 … NG sans problŠmes … l'‚cran }

{ et maintenant le pas du texte }
SetTextJustify(LeftText,TopText);
Deca:=TextWidth('M');
DecaY:=TextHeight('M');

{ on trace le PERT TEMPS (au plus t“t?sens?) }
{ trac‚ de l'axe des niveaux }
SetLineStyle(DashedLn,EmptyFill,NormWidth);
For j:=1 to NG Do { les repŠres verticaux }
Draw(j*PasX,0,j*PasX,YMax,ColReserved);

{ et PERT TEMPS proprement dit }
SetLineStyle(SolidLn,EmptyFill,NormWidth);
For i:=1 to NG Do
Begin
{ on d‚termine le nombre de tƒches … ce niveau => pas graphique sur Y }
NbIci:=0;
For j:=1 to NbT Do If TN[j]=i Then Inc(NbIci);
PasY:=Ymax DIV (NbIci+1); { mˆme raison que pour PasX }

{ on trace les tƒches de ce niveau }
NbIci:=0;
For j:=1 to NbT Do If TN[j]=i Then
Begin
Inc(NbIci);
{ position graphique }
x1:=PasX*i-3*Deca;
y1:=PasY*NbIci;
{ couleur associ‚e }
If CP[j] Then SetColor(ColReserved) Else SetColor(Color); { MaxColors); }

{ sort le libell‚ de tƒche }
OutTextXY(x1,y1,PTab[j]^.Libelle);
{ puis la dur‚e planifi‚e de la tƒche }
Str(PTab[j]^.Temps_prevus[1]:-3,msg);
OutTextXY(x1+3*Deca,y1,msg);
{ puis les dates au pus t“t et plus tard }
Str(PTab[j]^.RelTemps[1]:2,msg);
OutTextXY(x1,y1+2*DecaY,msg);
Str(PTab[j]^.RelTemps[2]:2,msg);
OutTextXY(x1+3*Deca,y1+2*DecaY,msg);

{ on trace son cadre }
Rectangle(x1-2,y1-2,x1+1+3*Deca+MaxNb(2*Deca,Deca*Length(PTab[j]^.Libelle)),y1+3*DecaY+1);

{ on m‚morise les coordonn‚es ET LA COULEUR pour arcs sortants et entrants }
x1s[j]:=x1+1+3*Deca+MaxNb(2*Deca,Deca*Length(PTab[j]^.Libelle));
y1s[j]:=y1+2*DecaY;
x1e[j]:=x1-3; { -2 seulement ? }
y1e[j]:=y1s[j]; { d'accord ? }
Col[j]:=Color;

(**)
Color:= NextColor(Color); { normalement }
(**)

End; { For tƒches … ce niveau }

End; { For niveaux }

{ on trace les arcs et le chemin critique }
SetTextJustify(CenterText,TopText);
For j:=1 to NbT Do
Begin
For i:=1 to NbT Do
If MT[j,i].precede Then { j pointe vers i }
Begin { … cause de l'option "ValueArcs?" }
{ on trace une flŠche ( ‚paisse et en rouge vif si critique ) }
TraceFleche(x1s[j],y1s[j],x1e,y1e,(CP[j] AND CP), Col[j], ColReserved);
If ValueArcs Then
Begin
Str(PTab[j]^.Temps_Prevus[1]:2,msg);
OutTextXY((x1s[j]+x1e)DIV 2,4+(y1s[j]+y1e)DIV 2,msg)
End; { If }
End; { If }
End; { For }

{ on attend l'utilisateur }
Repeat Until KeyPressed;
Ch:=ReadKey;

{ impression si I ou i }
TestPrint(ch,TeC);

End; { TracePERT Procedure }



{###########################################################################}
{###########################################################################}
{##### P E R T C O S T #####}
{###########################################################################}
{###########################################################################}


Function fTacheCout ( ind : Integer ) : Real;
Begin
With ProjTab[ind]^ Do fTacheCout:=Temps_prevus[1]*Couts[1];
End; { fTacheCout Real Function }

Function fTempsMax ( ind : Integer ) : Integer;
Begin
With ProjTab[ind]^ Do
If Critical[ind] Then fTempsMax:=Temps_prevus[1]
Else fTempsMax:=MinNb(Temps_prevus[1]+Marge_brute,Temps_prevus[3]);
End; { fTempsMax Integer Function }

Function fTacheCoutMin ( ind : Integer ) : Real;
Begin
With ProjTab[ind]^ Do fTacheCoutMin:=Temps_prevus[1]*Couts[1]+(fTempsMax(ind)-Temps_prevus[1])*Couts[2];
End; { fTacheCout Real Function }


Procedure PERT_Cost ( PTab : TypProj; NbT : Integer; TN : TypNiv; NG : Integer;
CP : TypCPath; MT : TypMat; ValueArcs : Boolean;
C1, C2, C3 : Real ; TeC : String );

Var i, x1,x2,y1,y2 : Integer;
PasX, PasY : Integer;
Color : Integer;
NbIci, PosD,
Deca, DecaY : Integer;
msg : St10;

x1s, y1s, x1e, y1e : array[1..MaxTaches] Of Word;
Col : array[1..MaxTaches] Of Byte;

Begin
{ couleur de d‚part }
Color:=MaxColors; { toujours au moins d‚finie }
If MaxColors>5 Then ColReserved:=LightRed Else ColReserved:=MaxColors;

{ on calcule le 'pas' graphique du trac‚ }
PasX:=Xmax DIV (NG+1); { pour aller de Niv=1 … NG sans problŠmes … l'‚cran }

{ et maintenant le pas du texte }
SetTextJustify(LeftText,TopText);
Deca:=TextWidth('M');
DecaY:=TextHeight('M');

{ on trace le PERT TEMPS au plus t“t }
{ trac‚ de l'axe des niveaux }
SetLineStyle(DashedLn,EmptyFill,NormWidth);
For j:=1 to NG Do { les repŠres verticaux }
Draw(j*PasX,0,j*PasX,YMax,ColReserved);

{ et PERT TEMPS proprement dit }
SetLineStyle(SolidLn,EmptyFill,NormWidth);
For i:=1 to NG Do
Begin
{ on d‚termine le nombre de tƒches … ce niveau => pas graphique sur Y }
NbIci:=0;
For j:=1 to NbT Do If TN[j]=i Then Inc(NbIci);
PasY:=Ymax DIV (NbIci+1); { mˆme raison que pour PasX }

{ on trace les tƒches de ce niveau }
NbIci:=0;
For j:=1 to NbT Do If TN[j]=i Then
Begin
Inc(NbIci);
{ position graphique }
x1:=PasX*i-3*Deca;
y1:=PasY*NbIci;
{ couleur associ‚e }
If CP[j] Then SetColor(ColReserved) Else SetColor(Color); { MaxColors); }

{ cadrage … gauche }
SetTextJustify(LeftText,TopText);

{ sort le libell‚ de tƒche }
OutTextXY(x1,y1,PTab[j]^.Libelle);

{ puis les dur‚es 'normale' et [mini … voir plus tard] maxi }
Str(PTab[j]^.Temps_prevus[1]:3,msg);
OutTextXY(x1,y1+2*DecaY,msg);
Str(fTempsMax(j):3,msg);
OutTextXY(x1,y1+3*DecaY,msg);

{ passage … la colonne de droite }
PosD:=x1+1+3*Deca+MaxNb(3*Deca,Deca*Length(PTab[j]^.Libelle));

{ cadrage … droite }
SetTextJustify(RightText,TopText);

{ puis sa dur‚e normale }
Str(PTab[j]^.Temps_prevus[1]:3,msg);
OutTextXY(PosD,y1,msg);

{ puis les co–ts 'normal' (pr‚vu) et mini [maxi plus tard possible aussi] }
Str(fTacheCout(j):4:0,msg);
OutTextXY(PosD,y1+2*DecaY,msg);
Str(fTacheCoutMin(j):4:0,msg);
OutTextXY(PosD,y1+3*DecaY,msg);

{ on trace son cadre }
Rectangle(x1-2,y1-2,PosD,y1+4*DecaY+1);

{ on m‚morise les coordonn‚es ET LA COULEUR pour arcs sortants et entrants }
x1s[j]:=PosD;
y1s[j]:=y1+2*DecaY;
x1e[j]:=x1-3; { -2 seulement ? }
y1e[j]:=y1s[j]; { d'accord ? }
Col[j]:=Color;

(**)
Color:= NextColor(Color); { normalement }
(**)

End; { For tƒches … ce niveau }

End; { For niveaux }

{ ici on trace la l‚gende et le r‚capitulatif du projet en termes de co–ts }
{ position graphique }
x1:=x1e[1]-5*Deca;
If x1<1 Then x1:=1;
y1:=y1e[1]-15*DecaY;
If y1<1 Then y1:=1;
PosD:=x1+1+12*Deca; { les en-tˆtes et les valeurs }
{ couleur associ‚e }
SetColor(ColReserved);
{ cadrage … gauche }
SetTextJustify(LeftText,TopText);
{ sort la l‚gende de tƒche }
OutTextXY(x1,y1,'Nom');
Line(x1,y1+2*DecaY,PosD,y1+2*DecaY);
OutTextXY(x1,y1+2*DecaY,'Dur‚e=');
OutTextXY(x1,y1+3*DecaY,'Maxi =');
{ passage … la colonne de droite }
{ cadrage … droite }
SetTextJustify(RightText,TopText);
{ puis sa dur‚e normale }
OutTextXY(PosD,y1,'Dur‚e');
OutTextXY(PosD,y1+DecaY,'(pr‚vue)');
OutTextXY(PosD,y1+2*DecaY,'Co–t');
OutTextXY(PosD,y1+3*DecaY,'Co–t');
OutTextXY(PosD,y1+4*DecaY,'(mini)');
{ on trace son cadre }
Rectangle(x1-2,y1-2,PosD,y1+5*DecaY);


{ position graphique }
x1:=x1e[NbTaches];
y1:=y1e[NbTaches]+6*DecaY;
If y1>(YMax-6*DecaY) Then y1:=YMax-6*DecaY;
{ couleur associ‚e }
SetColor(ColReserved);
{ cadrage … gauche }
SetTextJustify(LeftText,TopText);
{ sort le libell‚ de tƒche }
OutTextXY(x1,y1,'Dur‚e =');
{ puis les co–ts 'normal', mini et moyen. }
OutTextXY(x1,y1+DecaY,'co–ts :');
OutTextXY(x1,y1+2*DecaY,'norme ');
OutTextXY(x1,y1+3*DecaY,'mini ');
msg:='moyen '; { len = 6 }
OutTextXY(x1,y1+4*DecaY,msg);

{ passage … la colonne de droite }
PosD:=x1+1+7*Deca+6*Deca; { les en-tˆtes et les valeurs }

{ cadrage … droite }
SetTextJustify(RightText,TopText);

{ puis sa dur‚e normale }
Str(DureeTotale:4,msg);
OutTextXY(PosD,y1,msg+' u');

{ puis les co–ts 'normal' (pr‚vu) et mini [maxi plus tard possible aussi] }
Str(CoutTotal:6:1,msg);
OutTextXY(PosD,y1+2*DecaY,msg);
Str(CoutMini:6:1,msg);
OutTextXY(PosD,y1+3*DecaY,msg);
Str(Cout50:6:1,msg);
OutTextXY(PosD,y1+4*DecaY,msg);

{ on trace son cadre }
Rectangle(x1-2,y1-2,PosD,y1+5*DecaY);


{ on trace les arcs et le chemin critique }
SetTextJustify(CenterText,TopText);
For j:=1 to NbT Do
Begin
For i:=1 to NbT Do
If MT[j,i].precede Then { j pointe vers i }
Begin { … cause de l'option "ValueArcs?" }
{ on trace une flŠche ( ‚paisse et en rouge vif si critique ) }
TraceFleche(x1s[j],y1s[j],x1e,y1e,(CP[j] AND CP), Col[j], ColReserved);
If ValueArcs Then
Begin
Str(PTab[j]^.Temps_Prevus[1]:2,msg);
OutTextXY((x1s[j]+x1e)DIV 2,4+(y1s[j]+y1e)DIV 2,msg)
End; { If }
End; { If }
End; { For }

{ on attend l'utilisateur }
Repeat Until KeyPressed;
Ch:=ReadKey;

{ impression si I ou i }
TestPrint(ch,TeC);

End; { PERT_Cost Procedure }






{###########################################################################}
{###########################################################################}
{##### D O N N E E S D U P R O J E T #####}
{###########################################################################}
{###########################################################################}


Procedure TraceDonnees ( PTab : TypProj; NbT : Integer; TN : TypNiv; NG : Integer;
CP : TypCPath; MT : TypMat ; TeC : String );

(*
Var i, x1,x2,y1,y2 : Integer;
PasX, PasY : Integer;
NbIci,

Col : array[1..MaxTaches] Of Byte;
*)

Var y : Integer;
DecaX,
DecaY : Integer;
Color : Integer;
msg : St10;

IciPasY : Integer;

Begin
{ couleur de d‚part }
Color:=MaxColors; { toujours au moins d‚finie }
If MaxColors>5 Then ColReserved:=LightRed Else ColReserved:=MaxColors;

{ le style et le pas du texte }
SetTextStyle(DefaultFont,HorizDir,1);
SetTextJustify(LeftText,TopText);
DecaX:=TextWidth('M');
DecaY:=TextHeight('M');

{ on trace les donn‚es }
(*
{ trac‚ de l'axe des niveaux }
SetLineStyle(DashedLn,EmptyFill,NormWidth);
For j:=1 to NG Do { les repŠres verticaux }
Draw(j*PasX,0,j*PasX,YMax,ColReserved);
*)

{ et donn‚es proprement dites }
IciPasY:=Trunc(1.6*DecaY); { interligne standard }
y:=2*DecaY; { … cause du titre }
SetLineStyle(SolidLn,EmptyFill,NormWidth);

{ l‚gende }
SetColor(Color);
Inc(y,2*IciPasY);

{ nom de la tƒche }
OutTextXY(5,y,'Libell‚');
{ niveau de la tƒche }
OutTextXY(5+9*DecaX,y,'Niv');
{ liste des pr‚c‚dents }
OutTextXY(5+13*DecaX,y,'Ant.');
{ dur‚e planifi‚e et co–t pr‚vu }
OutTextXY(5+20*DecaX,y,'DP');
OutTextXY(5+26*DecaX,y,'CP');
{ indicateur critique? }
OutTextXY(5+32*DecaX,y,'C');
{ d‚buts au plus t“t et plus tard }
OutTextXY(5+34*DecaX,y,'DT“');
OutTextXY(5+38*DecaX,y,'DTa');
{ fins au plus t“t et plus tard }
OutTextXY(5+42*DecaX,y,'FT“');
OutTextXY(5+46*DecaX,y,'FTa');
{ marge libre }
OutTextXY(5+50*DecaX,y,'MgT');
{ marge totale }
OutTextXY(5+54*DecaX,y,'MgL');
{ dur‚e minimale et co–t }
{ dur‚es maximales et co–t }
OutTextXY(5+58*DecaX,y,'DPm');
OutTextXY(5+62*DecaX,y,'DPM');
OutTextXY(5+66*DecaX,y,'DMax');
OutTextXY(5+71*DecaX,y,'CMin');

{ tƒches successivement }
For i:=1 to NbT Do
Begin
Inc(y,IciPasY);
If CP Then SetColor(ColReserved) Else SetColor(Color);
{ nom de la tƒche }
OutTextXY(5,y,PTab^.Libelle);
{ niveau de la tƒche }
Str(TN,msg);
OutTextXY(5+10*DecaX,y,msg);
{ liste des pr‚c‚dents }
msg:='';
For j:=1 to NbT Do
If MT[j,i].precede Then msg:=msg+PTab[j]^.Libelle+',';
OutTextXY(5+12*DecaX,y,msg);
{ dur‚e planifi‚e et co–t pr‚vu }
Str(PTab^.Temps_prevus[1]:-3,msg);
OutTextXY(5+20*DecaX,y,msg);
Str(fTacheCout(i):7:2,msg);
OutTextXY(5+23*DecaX,y,msg);
{ indicateur critique? }
If CP Then msg:='*' Else msg:=' ';
OutTextXY(5+32*DecaX,y,msg);
{ d‚buts au plus t“t et plus tard }
Str(PTab^.RelTemps[1],msg);
OutTextXY(5+34*DecaX,y,msg);
Str(PTab^.RelTemps[2],msg);
OutTextXY(5+38*DecaX,y,msg);
{ fins au plus t“t et plus tard }
With PTab^ Do Str(RelTemps[1]+Temps_prevus[1],msg);
OutTextXY(5+42*DecaX,y,msg);
With PTab^ Do Str(RelTemps[2]+Temps_prevus[1],msg);
OutTextXY(5+46*DecaX,y,msg);
{ marge brute }
Str(PTab^.Marge_brute:3,msg);
OutTextXY(5+49*DecaX,y,msg); { … revoir }
{ marge libre }
Str(PTab^.Marge_libre:3,msg);
OutTextXY(5+53*DecaX,y,msg); { … revoir }
{ dur‚e minimale et co–t }
{ dur‚es maximales et co–t }
Str(PTab^.Temps_prevus[2]:3,msg);
OutTextXY(5+56*DecaX,y,msg); { … revoir }
Str(PTab^.Temps_prevus[3]:3,msg);
OutTextXY(5+60*DecaX,y,msg); { … revoir }
Str(fTempsMax(i):3,msg);
OutTextXY(5+64*DecaX,y,msg); { … revoir }
Str(fTacheCoutMin(i):7:2,msg);
OutTextXY(5+68*DecaX,y,msg); { … revoir }

End; { For tƒches }

{ on r‚capitule le projet }
SetColor(Color);
Inc(y,3*DecaY);
OutTextXY(5,y,'TOTAL projet');
{ puis sa dur‚e normale }
Str(DureeTotale:-3,msg);
OutTextXY(5+20*DecaX,y,msg);
Str(CoutTotal:7:2,msg);
OutTextXY(5+23*DecaX,y,msg);

{ d‚buts au plus t“t et plus tard }
OutTextXY(5+34*DecaX,y,'0');
OutTextXY(5+38*DecaX,y,'0');
{ fins au plus t“t et plus tard }
Str(DureeTotale:-3,msg);
OutTextXY(5+42*DecaX,y,msg);
OutTextXY(5+46*DecaX,y,msg);
{ marge libre }
OutTextXY(5+51*DecaX,y,'0');
{ marge totale }
OutTextXY(5+55*DecaX,y,'0');
{ dur‚e minimale et co–t }
{ dur‚es maximales et co–t }
Str(DureeTotale:3,msg);
OutTextXY(5+56*DecaX,y,msg);
OutTextXY(5+60*DecaX,y,msg);
OutTextXY(5+64*DecaX,y,msg);
Str(CoutMini:7:2,msg);
OutTextXY(5+68*DecaX,y,msg);

Str(Cout50:6:1,msg);
OutTextXY(5+50*DecaX,y+2*DecaY,'Co–t moyen = '+msg);

SetTextStyle(FonteDeBase,HorizDir,TailleDeBase);
(*
For i:=1 to NbT Do
If MT[j,i].precede Then { j pointe vers i }
Begin { … cause de l'option "ValueArcs?" }
{ on trace une flŠche ( ‚paisse et en rouge vif si critique ) }
TraceFleche(x1s[j],y1s[j],x1e,y1e,(CP[j] AND CP), Col[j], ColReserved);
If ValueArcs Then
Begin
Str(PTab[j]^.Temps_Prevus[1]:2,msg);
OutTextXY((x1s[j]+x1e)DIV 2,4+(y1s[j]+y1e)DIV 2,msg)
End; { If }
End; { If }
End; { For }
*)

{ on attend l'utilisateur }
Repeat Until KeyPressed;
Ch:=ReadKey;

{ impression si I ou i }
TestPrint(ch,TeC);

End; { TraceDONNEES Procedure }







{###########################################################################}
{###########################################################################}
{##### Annexe : M A T R I C E D E P R E C E D E N C E #####}
{###########################################################################}
{###########################################################################}



Procedure MatPrecedence ( NbT : Integer; MT : TypMat );
Var i,j : integer;
Begin
ClrScr;
WriteLn('<ABCDEFGHIJKLMNOPQRSTUVWXYZ>');
For i:=1 to NbT Do
Begin
For j:=1 to NbT Do
Begin
GotoXY(j,i+1);
If MT[i,j].precede Then Write('1') Else Write('0');
End; { For }
End; { For }

{on reluque la matrice de p‚c‚dence... }
repeat until keypressed; ch:=readkey;

End; { MATPRECEDENCE Procedure }


{###########################################################################}
{###########################################################################}
{##### M A N I P U L A T I O N S D E F I C H I E R S #####}
{###########################################################################}
{###########################################################################}


Procedure ListeProjets ( Lit : Boolean; Var OkCharge : Boolean; Var nom : String );
Var Info : SearchRec;
sortie : Text;

Begin
{ sortie du directoire .PPJ }
ClrScr;
i:=1;
GotoXY(1,3);
FindFirst('*.PPJ',Archive,Info);
While (DosError=0) Do
Begin
GotoXY(10*((i-1) DIV 20),3+((i-1) MOD 20)); { pas parfait. cf affichage. }
If Pos('.',Info.Name)=0 Then Writeln(Copy(Info.Name,1,8))
Else WriteLn(Copy(Info.Name,1,Pos('.',Info.Name)-1));
FindNext(Info);
Inc(i);
End;
If Lit Then { chargement d'un sujet }
Repeat
GotoXY(1,1);
ClrEol;
Write('Nom du Fichier (''fin'' pour sortir) : ');
Readln(nom);
If (StUpCase(nom)<>'FIN') Then
Begin
If Pos('.',nom)=0 Then nom:=nom+'.PPJ';
Assign(sortie,nom);
{$I-}
ReSet(sortie);
{$I+}
End;
Until (IOResult=0) OR (StUpCase(nom)='FIN')
Else
Repeat
GotoXY(1,1);
ClrEol;
Write('Nom du Fichier (''fin'' pour sortir) : ');
Readln(nom);
If (StUpCase(nom)<>'FIN') Then
Begin
If Pos('.',nom)=0 Then nom:=nom+'.PPJ';
Assign(sortie,nom);
{$I-}
ReSet(sortie);
{$I+}
End;
Until (IOResult<>0) OR (StUpCase(nom)='FIN'); { If }

OkCharge:=(StUpCase(nom)<>'FIN');

End; { ListeProjets Proc‚dure }




Procedure SauveProjetTab ( ProjTitr : St20; MT : TypMat; NT : TypNiv; NbT,NG : Integer; PT : TypProj );
Var fich : Text;
okch : Boolean;
poub : String; { nomfic aurait fait l'affaire... }

Begin
(* Assign (fich,'PERT.TXT'); *)
ListeProjets(False,okch,poub);
If okch Then Assign(fich,poub) Else Assign(fich,'PERT.PPJ');

ReWrite(fich); { on voit donc que PERT.PPJ doit toujours exister }
WriteLn(fich,ProjTitr);
WriteLn(fich,NbT);
WriteLn(fich,NG);
For i:=1 to NbT Do
Begin
For j:=1 to NbT Do
WriteLn(fich,MT[i,j].precede);
WriteLn(fich);
End; { For }

For i:=1 to NbT Do
Begin
{ niveau de la tƒche }
WriteLn(fich,NT);
{ intitul‚/code de la tƒche }
WriteLn(fich,PT^.Libelle);
{ dur‚e ‚l‚mentaire }
For j:=1 to 3 Do WriteLn(fich,PT^.Temps_Prevus[j]);
{ co–ts : base et ajustements }
WriteLn(fich,PT^.Couts[1]);
WriteLn(fich,PT^.Couts[2]);
End; { For NbT }
Close(fich);
End; { SauveProjTab Procedure }




Procedure ChargeProjetTab ( Var ProjTitr : St20; Var MT : TypMat;
Var NT : TypNiv; Var PT : TypProj;
Var NbT, NG : Integer );
Var fich : Text;
poub : String;
p2 : Integer;
okch : Boolean; { s‚lection du fichier }

Begin
(* Assign (fich,'PERT.TXT'); *)
ListeProjets(True,okch,poub);
If okch Then Assign(fich,poub) Else Assign(fich,'PERT.PPJ');

ReSet(fich); { on voit donc que PERT.PPJ doit toujours exister }
ReadLn(fich,ProjTitr);
ReadLn(fich,NbT);
For i:=1 to NbT Do InitialiseTache(PT);
ReadLn(fich,NG);
For i:=1 to NbT Do
Begin
For j:=1 to NbT Do
Begin
ReadLn(fich,poub);
MT[i,j].precede:=(poub='TRUE');
End; { For }
ReadLn(fich,poub); { ligne vide, de s‚paration... }
End; { For }

For i:=1 to NbT Do
Begin
{ niveau de la tƒche }
ReadLn(fich,poub);
Val(poub,NT,p2);
{ intitul‚/code de la tƒche }
ReadLn(fich,PT^.Libelle);
{ dur‚es ‚l‚mentaires }
For j:=1 to 3 Do
Begin
ReadLn(fich,poub);
Val(poub,PT^.Temps_Prevus[j],p2);
End; { For j }
{ co–ts }
ReadLn(fich,poub);
Val(poub,PT^.Couts[1],p2);
ReadLn(fich,poub);
Val(poub,PT^.Couts[2],p2);

End; { For }
Close(fich);
End; { ChargeProjTab Procedure }


{###########################################################################}
{###########################################################################}
{##### M E N U U T I L I S A T E U R #####}
{###########################################################################}
{###########################################################################}


Procedure Menu ( Var opt : Byte );
Var opt_prec : Byte;
lim : Byte;

Begin
{ m‚morisation de l'‚tat }
opt_prec:=opt;

{ passage en texte }
RestoreCrtMode;

{ trac‚ du menu }
lim:=8;
ClrScr;
WriteLn(' nouveau projet ');
WriteLn(' charge fichier ');
WriteLn(' sauve fichier ');
WriteLn(' modification tƒche ');
WriteLn(' matrice de pr‚c‚dence');
WriteLn(' OPTIONS ');
WriteLn(' calculs + GANTT ');
WriteLn(' calculs + PERT Temps ');
WriteLn(' calculs + PERT Co–ts ');
WriteLn(' fin, terminaison ');

{ choix d'une option }
Repeat
{ selon s‚lection, mise en ‚vidence }
GotoXY(1,opt+1); Write('>'); GotoXY(24,opt+1); Write('<');

{ d‚placement, s‚lection et sortie }
Repeat Until KeyPressed;
ch:=ReadKey;
If ch=#0 Then
Begin
ch:=ReadKey;
If ch=#72
Then Begin { flŠche vers le haut }
GotoXY(1,opt+1); Write(' '); GotoXY(24,opt+1); Write(' ');
If opt=0 Then opt:=0 Else Dec(opt);
GotoXY(1,opt+1); Write('>'); GotoXY(24,opt+1); Write('<');
End
Else Begin { vers le bas }
GotoXY(1,opt+1); Write(' '); GotoXY(24,opt+1); Write(' ');
If opt>lim Then opt:=lim+1 Else Inc(opt);
GotoXY(1,opt+1); Write('>'); GotoXY(24,opt+1); Write('<');
End; { If }
End; { bon : code de contr“le }

Until (ch=#13) OR (ch=#27);

If ch=#27 Then opt:=opt_prec; { sinon la s‚lection 'opt' est valid‚e }

End; { Menu Procedure }


{###########################################################################}
{###########################################################################}
{##### C O N T R O L E S #####}
{###########################################################################}
{###########################################################################}


Procedure ControleOptions;
Begin
If NOT OkOptions Then
Begin
If OptCycles Then OteCycles(MatTaches, NbTaches);

OkOptions:=True;
End; { If }
End;

Procedure ControleCalculs;
Begin
If NOT OkCalcule Then
Begin
CalculeNiveaux(MatTaches,NbTaches,NivGraphe,TacheNiv);

OkCalcule:=True;
End; { If }
End;

Procedure ControleDates;
Begin
If NOT OkDates Then
Begin
CalculeDatesPlusTot; { on en ressort avec DureeTotale }
CalculeDatesPlusTardMarges;

TrouveCriticalPath ( ProjTab, NbTaches, Critical );
CalculeDates(Projet);

{ ici les co–ts }
CalculeCouts; { bas‚ sur une courbe exponentielle d‚croissante }

OkDates:=True;
End; { If }
End;

Procedure ControleGraph;
Begin
If NOT OkGraphx Then
Begin
ReEnterGraphMode; { et pas Init; }
Frame;
OkGraphx:=True;
End; { If }
End;



{###########################################################################}
{###########################################################################}
{##### P R O G R A M M E P R I N C I P A L #####}
{###########################################################################}
{###########################################################################}


Begin

{ initialisations }
Init; { car l'Init dans la partie d'initialisation des unit‚s graphiques
est suivie d'un CloseGraph... }

{ pr‚sentation graphique : une nouveaut‚ !!! }
GraphPresente;

{ PROGRAMME AVEC MENU mode texte }
Option:=0;
Repeat
Menu(Option);
Case Option Of
0 : Begin { nouveau projet }
{ entr‚e ou saisie du nombre d'activit‚s/tƒches, avec leurs nom/libell‚,
nombre et num‚ros des tƒches ant‚rieures, RV ‚ventuels, dur‚es probable
et optimiste/pessimiste dans l'unit‚ de temps s‚lectionn‚e au d‚but.
}

InitialiseMatrice(MatTaches);
ChoixUniteTemps(UniteTemps);

(* InitialiseTache(Projet); *)

EntreeProjetTab(ProjTitre, ProjTab, MatTaches, NbTaches, DateDepart ); { sp‚cial }
{ (non-dynamique) }

OkCalcule:=False;
OkDates:=False;
OkOptions:=False;
OkDonnees:=True;

End;
1 : Begin { charge fichier }
ChargeProjetTab(ProjTitre,MatTaches,TacheNiv,ProjTab,NbTaches,NivGraphe); { fichier }
OkCalcule:=False; { pr‚cautions... }
OkDates:=False;
OkOptions:=False;
OkDonnees:=True;
End;
2: If OkDonnees Then
Begin { sauve fichier }
SauveProjetTab(ProjTitre,MatTaches,TacheNiv,NbTaches,NivGraphe,ProjTab); { sur un fichier temporaire }
End
Else Begin Write('D‚finissez auparavant votre projet!'); Delay(1000); End;

3 : Begin { modification tƒche }
{ lorsqu'impl‚ment‚e : OkCalcule:=False; OkDates:=False; }
WriteLn('non encore impl‚ment‚e.'); Delay(1000);
End;
4: If OkDonnees Then
Begin { matrice de pr‚c‚dence }
MatPrecedence(NbTaches,MatTaches);
End
Else Begin Write('D‚finissez auparavant votre projet!'); Delay(1000); End;

5 : Begin

i:=WhereX;

Write('Valuation des arcs du PERT ? (O/..) '); ReadLn(rep);
OptValue:=(UpCase(rep)='O');

GotoXY(i,WhereY); ClrEol;
Write('Suppression des arcs redondants (ie cycles) ? (O/..) '); ReadLn(rep);
OptCycles:=(UpCase(rep)='O');

OkOptions:=False; { par principe }

End; { options d'affichage et de trac‚ }
6: If OkDonnees Then
Begin { calculs + GANTT }
ControleCalculs;
ControleDates;
ControleGraph;
ControleOptions;

{ ici trac‚ graphique : du diagramme de GANTT dans un premier temps
By: bogiboy Date: 01/10/2003 23:51:00 English  Type : Comment
Huh, really detailed.
Let me give it a try. I will have to learn some French to understand it though...Good
By: VGR Date: 02/10/2003 00:32:00 English  Type : Comment
ask
By: swift99 Date: 02/10/2003 01:22:00 English  Type : Comment
Memory is cheap. At 0.10 USD per megabyte of RAM, it is rarely worth your time to worry about memory consumption. I have an app that supports 4,000,000 plus concurrent business objects in memory on a 256 MB machine, plus the Delphi IDE, Interbase server, and some other miscellaneous stuff.

I would be tempted to build the internal data structure like this:


type

TGanttItemType = (gtNoActivity, gtWorkInProgress, gtBenchmark, gtHeldForResource)

TGanttItem = class (TObject)
starts: TDateTime;
ends: TDateTime;
status: TGanttItemType
end;

TGanttRow = class (TList)
property Name: String;
property Item [ index ]: TGanttItem;
end;

TGanttProject = class (Tlist)
property Item [ index ]: TGanttRow;
end;

In your GUI, I would traverse the lists, map the vertical coordinates to the count of the row in the TGanttProject, map horizontal graphic cordinates to the TDateTime values in the TGanttItem, and interpret the status of the TGanttItem to determine what was drawn (rectangle, funky shape, dashed line, etc).

By: VGR Date: 09/10/2010 11:16:21 English  Type : Comment
for those interested in the Unit chargetoutgraphix, there is as of now a KB entry bearing that name and containing the source code.

Do register to be able to answer

EContact
browser fav
page generated in 311.166050 milliseconds

Why Google AdSense ads ?

compteur
 Ranking-Hits PageRank for this page