home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
msysjour
/
vol04
/
02b
/
project
/
classes
/
project.cls
< prev
next >
Wrap
Text File
|
1988-11-30
|
7KB
|
291 lines
/* A Project is a network of Task and Milestone nodes to
manage CPM or PERT networks. A project knows how to
calculate its critical path, keep track of costs etc.
Since Project descends from Network, it inherits all of
Network's instance variables, e.g. start, end, name, desc.
*/!!
inherit(Network, #Project, #(cost /* sum of all costs */
resources /* used by tasks */
autoCalc /* boolean is recalc on? */
), 2, nil)!!
now(ProjectClass)!!
now(Project)!!
/* Return only the tasks in the project. */
Def tasks(self)
{
^extract(nodes(self),
{using(node)
class(node) <> Milestone;
});
}!!
/* Returns a collection of lines summarizing useful information. */
Def getInfoLines(self | tc)
{
tc := new(OrderedCollection, 6);
add(tc, loadString(PW_PROJECT) + ": " + field(name, 8)+ " " + desc);
add(tc, "");
add(tc, loadString(PW_PROJT1));
add(tc, "--------------------------------------------");
add(tc, loadString(PW_START))
+ field(asString(getEarlyStart(self)), 8) + " "
+ field(asString(getLateStart(self)), 8) + " "
+ field(asString(getCost(self)), 6) + " "
+ field(asString(getTime(self)), 6) + " "
+ field(asString(getSlack(self)), 4);
add(tc, loadString(PW_FINISH))
+ field(asString(getEarlyFinish(self)), 8) + " "
+ field(asString(getLateFinish(self)), 8);
^tc;
}!!
/* Return the resource if the name exists in the
resources collection, otherwise return false and
display an error message. */
Def checkResExists(self, resName | res)
{
if not(res := resExists(self, resName))
beep();
errorBox(loadString(PW_RESINVAL),
loadString(PW_RESOURCE) + " " + resName +
loadString(PW_NOTEXIST));
endif;
^res;
}!!
/* Return the resources collection. */
Def resources(self)
{
^resources;
}!!
/* Return the resource of the name resName if
it exists, otherwise return false. Use
checkResExists for error checking. */
Def resExists(self, resName | res)
{
^resName in resources;
}!!
/* Parse a string of resNames and return a set of
resources. If the resource doesn't exist, a new
one is created. */
Def parseResNames(self, resNames | names, res, aRes)
{
names := words(resNames);
res := new(OrderedCollection, 6);
do(names,
{using(name)
if not(aRes := resExists(self, name)) /* create it */
aRes := new(Resource);
setName(aRes, name);
if editInfo(aRes) == IDOK
add(resources, getName(aRes), aRes);
add(res, aRes);
endif;
else
add(res, aRes);
endif;
});
^res;
}!!
/* Return a sorted collection of activities in the project.
Sort by earlyStart, time, name for unique order.
This uses early binding and dot notation for speed. */
Def sortedActivities(self| sorted)
{
sorted := new(SortedCollection, 10);
setCompareBlock(sorted, {using(a,b)
if a.earlyStart = b.earlyStart
if getTime(a) = getTime(b)
a.name < b.name
else
getTime(a) < getTime(b)
endif
else
a.earlyStart < b.earlyStart
endif});
do(nodeNames,
{using(aNode)
add(sorted:SortedCollection, aNode);
});
^sorted;
}!!
/* Return the type of nodes that start and end should be.*/
Def nodeClass(self)
{
^Milestone;
}!!
/* Return the current cost which is always up to date. */
Def getCost(self)
{
^cost;
}!!
/* Get the user set late finish date. */
Def getUserLateFinish(self)
{
^getUserLateFinish(end);
}!!
/* Get the user set early start date. */
Def getUserEarlyStart(self)
{
^getUserEarlyStart(start);
} !!
/* Return a string to be used as a window caption. */
Def makeCaption(self)
{
^loadString(PW_PROJECT) + ": " + name;
}!!
/* Set the values of a project.
Values is an array of name, desc,
userEarlyStart, userLateFinish.
This message is sent after editing. */
Def setValues(self, values)
{
name := values[0];
desc := values[1];
if getEarlyStart(self) <> values[2]
setEarlyStart(self, values[2]);
endif;
if getLateFinish(self) <> values[3]
setLateFinish(self, values[3]);
endif;
}!!
/* Display and edit the project information.
The dialog should define methods run() and setEditItem().
*/
Def editInfo(self | dlg, retValue)
{
showWaitCurs();
dlg := new(ProjDialog);
setEditItem(dlg, self);
retValue := run(dlg, ThePort);
showOldCurs();
^retValue;
}!!
/* Project slack is defined as the slack at the end node.
This could be introduced if the user sets a lateFinish. */
Def getSlack(self)
{
^getSlack(end);
}!!
/* Return the current cost which is always up to date. */
Def calcCost(self)
{
^cost;
}!!
/* Update the cost based on a change to a Task. */
Def updateCost(self, change)
{
cost := cost + change;
}!!
/* Do the backwards pass only starting from the end node.
The end node is always critical.
*/
Def recalc2(self)
{
recalc2(end);
end.critical := true;
}!!
/* Turn automatic calculation on or off.
Force recalculation if turned on. */
Def setAutoCalc(self, mode)
{
if (autoCalc := mode) /* true or false */
recalc(self);
endif;
}!!
/* Recalculate the entire network. First invalidate all nodes
so that a full recalc will be forced. Then do both the
forward and backwards recalc passes. The forward pass must
be entirely completed before doing the backwards pass. */
Def recalc(self)
{
invalidate(start, new(Set,10)); /* clear all nodes */
recalc1(start, true); /* force entire recalc */
recalc2(self); /* backwards pass */
}!!
/* Get the project lateStart date. */
Def getLateStart(self)
{
^getLateStart(start);
}!!
/* Get the project earlyStart date. */
Def getEarlyStart(self)
{
^getEarlyStart(start);
} !!
/* Get the project early finish date. */
Def getEarlyFinish(self)
{
^getEarlyFinish(end);
}!!
/* Get the project late finish date. */
Def getLateFinish(self)
{
^getLateFinish(end);
}!!
/* Return the status of autoCalc mode. */
Def autoCalc(self)
{
^autoCalc;
}!!
/* The user can enter an early start date. */
Def setEarlyStart(self, aDate)
{
setEarlyStart(start,aDate);
}!!
/* The user can enter a late finish date. */
Def setLateFinish(self, aDate)
{
setLateFinish(end,aDate);
}!!
/* Calculate the project time. If negative (e.g. project
isn't fully hooked up yet) return 0. */
Def getTime(self)
{ ^max(0, getEarlyFinish(self) - getEarlyStart(self));
}!!
/* Initialize a new Project. Uses ancestor init.
The nodeClass method determines the node type
for start and end. */
Def init(self)
{
init(self:Network); /* use ancestor init */
cost := 0;
resources := new(Dictionary, 10);
setEarlyStart(start, /* set default project start */
date(1,1,1988));
}!!