[kplato] Some code for KPTProject::getDuration()

Thomas Zander kplato@kde.org
Sat, 25 Aug 2001 23:48:44 +0200


--PNTmBPCT7hxwcZjr
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Sat, Aug 25, 2001 at 10:09:24PM +0100, John D Lamb wrote:
> Thomas Zander wrote:
> >=20
> > Hmm, I think you should know that I am not really a c++ programmer,
> > I know c and java. And learned some c++ tricks over the time ;)
> >
> Actually that makes a lot of sense. I mainly use C++. Java is a very
> moralistic language. And one of my motivations for learning it was to
> improve the quality of my C++. Java doesn't let you do things like
> operator overloading and multiple inheritance that are usually a bad
> idea. My guess is that you'll be much better than me at handling
> concurrency and GUIs. :-)

Hehe ;)
We'll see.

> >=20
> > I don't mind making the core QT free, its just that I can't do it. I do=
n't
> > have _any_ experience with STL, I never use the class string for exampl=
e.
> > If you can provide the STL implementation of KPTDuration and friends,
> > i'm fine with it.
>=20
> I looked at QList and QListIterator. I can't extend these to STL
> containers and iterators or create a container or iterator to emulate
> them. So I think it's best to leave them as they are in QTNode. Most of
> what is needed for PERT/CPM can be generated as needed within KPTNode as
> it is.

Well, then the dependency on QT exists, and it boils down to use 'the=20
correct tool for the job'

> I'm not yet sure what the purpose of KPTRelation is. This may be
> ignorance on my part. What is clear is that it encapsulates the idea
> that (say) Node A comes before Node B in a Project. My instinct would be
> to encapsulate this by listing B as a time-dependent child of A and A as
> a parent of B. I think any other information can be calculated
> efficiently or encapsulated by a node ... of course if I've got this
> wrong, its much easier to work with a KPTRelation than without it. ;-)

The current solve is correct, take a step back and see it like this;


        X --- (lag=3D10) --- Y


item X has a relation with item Y, but there is a dependency (call it
direction or in this case lag) in the relation.=20
Then the data of that relation should either be stored in the relation=20
itself,  or in _both_ the item X and item Y.

I have chosen for the latter since we dont want duplication info.

Other then that; it is possible to add more then one dependency between
2 nodes, and at the moment you create 2 lists which should be in sync with
each other (one list for the child-nodes and one for their relation) you
should look if it is not wiser to create a class to combine that data.

> I've thought of a sensible way to prevent unnecessary recalculations of
> durations, floats, earliest starts, etc. Give each node a flag called
> recalculate. Define in KPTNode a function
> void setRecalculate(){
>   recalculate =3D true;
>   for_each( child )
>     setRecalculate();
> }

This has as disadvantage that when a node changes a value which would
cause a recalculation you have to find the project it belongs to, and=20
recalculate far to much. (since lots of values don't change and can be used
again)

What about the opposite; where a node stores if it should be recalculated
and a parent node asks all its children if anyone has a recalculate flag
set.

This keeps the 'changed-bool' data local to the change and thus prevents ex=
tra=20
calculations.

getDuration() {
    if(objectIsDirty()) {
        // calc duration=20
    }
    return duration
}

boolean objectIsDirty() {
    if I am a leaf-node, return dirtyFlag
    while(childnode)
        if(childnode++ -> objectIsDirty()) return true;
    return false;
}

> > My comment was from a data structure POV, if the user signals task A ha=
s=20
> > ended, we update the data structure to reflect that, in this case by
> > setting the endtime to that specific data.
> >
> > The PERT analytical will then tell us that B will start at the same tim=
e as
> > A ended (we know that exact time) and allow C to start at that time
> > as well.
> >
> > The user can then tell KPlato to start, which will set the starttime of=
 node
> > C to that exact time, again changing the of the PERT.
> >
> > Will that do?
>=20
> How about a flags userStarted and userFinished on each Node to say that
> whether the user has specified a start or finish time? with a check on
> dependent parent nodes before allowing the user to set something. Then
> the start time, end time and duration are either user fixed or estimated
> by PERT/CPM. If the user has specified anything, that gives an earliest
> starttime that PERT/CPM can use. Otherwise, use 0?

Excelent, and we can leave the flag out since checking if the m_startTime
(=3DuserStarted) is zero means it is not set.

Oh, wait, that was my initial design as well ;)


> I suggest we add (in a struct?) earliest_start, latest_finish as
> QDateTimes.=20

Just a comment; _dont use structs_. C++ has classes for that :)

These are the calculated values, right? Yes these should be added,=20
just as members of the kptNode class seems fine to me though.


> I thinks that would be enough. Also, rather than having
> separate functions for expected, random, optimistic, etc. times, why not
> create another KPTNode enumerated type (or even a set of empty classes
> if you want to be smug and gain efficiency by getting all the actual
> functions resolved at compile time) something like
> enum calcType { expected, random, optimistic };
> Then define (say)
> ... getDuration( KPTNode::calcType CalcType =3D KPTNode::expected );
> and get the functions themselves to work out what to do. This is likely
> to be especially useful at say Project level:
> getDuration(KPTNode::calcType CalcType =3D KPTNode::expected ){
>   ...
>  for_each( child )
>     child->getDuration( CalcType );
>  ...
> }
> Will that cause more problems than it solves?

I think this is a nice addition, and basically I like it, but not
as a replacement.
So I think we should use operator overloading to create an extra method
which does the above, but let the original methods exist.

Then you have the choice of implementing the logic in that one method
and use the others as 'shortcuts' or the other way around, where the
3 methods implement the logic each for the different duration time.

> Any thoughts?
> JDL

Just that it is too hot to do anything intelligent here... (Holland/Europe)

--=20
Thomas Zander                                            zander@earthling.n=
et
The only thing worse than failure is the fear of trying something new

--PNTmBPCT7hxwcZjr
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org

iD8DBQE7iB08CojCW6H2z/QRAgP3AJ9RHtqGyP+Go9F/YiUDNUaeUmRNDwCg5nND
y4fG9mDZS9B95Twb0YT7xA8=
=RFAN
-----END PGP SIGNATURE-----

--PNTmBPCT7hxwcZjr--