Languages :: Delphi :: Project timeline (gantt chart) |
|||
| By: bogiboy |
Date: 30/09/2003 00:00:00 |
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 | Type : Comment |
|
| I did it... in Turbo pascal... :D |
|||
| By: bogiboy | Date: 30/09/2003 17:09:00 | Type : Comment |
|
| Could you post some examples? |
|||
| By: swift99 | Date: 30/09/2003 18:07:00 | 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 | 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 | 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 | 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 | 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 | 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 | Type : Comment |
|
| ask |
|||
| By: swift99 | Date: 02/10/2003 01:22:00 | 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 | 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 |
|||
©2010 These pages are served without commercial sponsorship. (No popup ads, etc...). Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE.
Please DO link to this page!








