summaryrefslogtreecommitdiffstats
path: root/kplato/kptnode.h
blob: 95d7c24b7736cfee891aa3e8066b2635f6ca9e1d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
/* This file is part of the KDE project
   Copyright (C) 2001 Thomas Zander [email protected]
   Copyright (C) 2004, 2005 Dag Andersen <[email protected]>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
*/

#ifndef KPTNODE_H
#define KPTNODE_H

#include "kptrelation.h"
#include "kptduration.h"
#include "kptdatetime.h"
#include "kptschedule.h"

#include <tqintdict.h>
#include <tqrect.h>
#include <tqptrlist.h>
#include <tqstring.h>
#include <tqcanvas.h>

#include <vector>

class TQDomElement;

namespace KPlato
{

class Account;
class Project;
class Appointment;
class ResourceGroup;
class Resource;
class ResourceGroupRequest;
class Effort;
class WBSDefinition;
class EffortCostMap;

/**
 * This class represents any node in the project, a node can be a project or
 * a subproject or any task.
 * This class is basically an abstract interface to make the design more OO.
 */
class Node {

public:
    enum ConstraintType { ASAP, ALAP, MustStartOn, MustFinishOn, StartNotEarlier, FinishNotLater, FixedInterval };

    Node(Node *parent = 0);
    Node(Node &node, Node *parent = 0);


    // Declare the class abstract
    virtual ~Node() = 0;

    bool setId(TQString id);
    TQString id() const { return m_id; } // unique identity
    
    enum NodeTypes {
	  Type_Node = 0,
	  Type_Project = 1,
	  Type_Subproject = 2,
	  Type_Task = 3,
	  Type_Milestone = 4,
	  Type_Periodic = 5,
      Type_Summarytask = 6
    };

    virtual int type() const = 0;

    /**
     * Returns a pointer to the project node (main- or sub-project)
     * Returns 0 if no project exists.
     */
    virtual Node *projectNode();
    
    // The load and save methods
    virtual bool load(TQDomElement &) { return true; }
    virtual bool load(TQDomElement &, Project &) { return true; }
    virtual void save(TQDomElement &element) const  = 0;
    /// Save my and my tqchildrens relations.
    virtual void saveRelations(TQDomElement &element) const;

    // simple child node management
    // Child nodes are things like subtasks, basically a task can exists of
    // several sub-tasks. Creating a table has 4 subtasks, 1) measuring
    // 2) cutting 3) building 4) painting.
    Node *getParent() const { return m_parent; }
	void setParent( Node* newParent ) { m_parent = newParent;}
    const TQPtrList<Node> &childNodeIterator() const { return m_nodes; }
    int numChildren() const { return m_nodes.count(); }
    virtual void addChildNode(Node *node, Node *after=0);
    virtual void insertChildNode(unsigned int index, Node *node);
    void delChildNode(Node *node, bool remove=true);
    void delChildNode(int number, bool remove=true);
    Node* getChildNode(int number) { return m_nodes.at(number); }
    const Node* getChildNode(int number) const;
	int findChildNode( Node* node );

    // Time-dependent child-node-management.
    // list all nodes that are dependent upon this one.
    // Building a house requires the table to be finished, therefore the
    // house-building is time dependent on the table-building. So a child
    // of the table-building node is the house-building node.

    int numDependChildNodes() const { return m_dependChildNodes.count(); }
    /// Adds relation to both this node and address node
    virtual void addDependChildNode( Node *node, Relation::Type p=Relation::FinishStart);
    /// Adds relation to both this node and address node
    virtual void addDependChildNode( Node *node, Relation::Type p, Duration lag);
    /// Adds relation only to this node
    virtual bool addDependChildNode( Relation *relation);
    /// Inserts relation to this node at index address index and appends relation to address node
    virtual void insertDependChildNode( unsigned int index, Node *node, Relation::Type p=Relation::FinishStart);
    void delDependChildNode( Node *node, bool remove=false);
    void delDependChildNode( Relation *rel, bool remove=false);
    void delDependChildNode( int number, bool remove=false);
    Relation *getDependChildNode( int number) {
	return m_dependChildNodes.at(number);
    }
    TQPtrList<Relation> &dependChildNodes() { return m_dependChildNodes; }

    /**
     * Takes the relation rel from this node only.
     * Never deletes even when autoDelete = true.
     */
    void takeDependChildNode(Relation *rel);
    
    int numDependParentNodes() const { return m_dependParentNodes.count(); }
    /// Adds relation to both this node and node
    virtual void addDependParentNode(Node *node, Relation::Type p=Relation::FinishStart);
    /// Adds relation to both this node and node
    virtual void addDependParentNode( Node *node, Relation::Type p, Duration lag);
    /// Adds relation only to this node
    virtual bool addDependParentNode( Relation *relation);
    /// Inserts relation to this node at index and appends relation to node
    virtual void insertDependParentNode( unsigned int index, Node *node, Relation::Type p=Relation::FinishStart);
    void delDependParentNode( Node *node, bool remove=false);
    void delDependParentNode( Relation *rel, bool remove=false);
    void delDependParentNode( int number, bool remove=false);
    Relation *getDependParentNode( int number) {
	return m_dependParentNodes.at(number);
    }
    TQPtrList<Relation> &dependParentNodes() { return m_dependParentNodes; }
    
    /**
     * Takes the relation rel from this node only.
     * Never deletes even when autoDelete = true.
     */
    void takeDependParentNode(Relation *rel);

	bool isParentOf(Node *node);
    bool isDependChildOf(Node *node);

    Relation *findParentRelation(Node *node);
    Relation *findChildRelation(Node *node);
    Relation *findRelation(Node *node);

    void setStartTime(DateTime startTime);
    /// Return the scheduled start time
    virtual DateTime startTime() const
        { return m_currentSchedule ? m_currentSchedule->startTime : DateTime(); }
    const TQDate &startDate() const { return m_dateOnlyStartDate; }
    void setEndTime(DateTime endTime);
    /// Return the scheduled end time
    virtual DateTime endTime() const
        { return m_currentSchedule ? m_currentSchedule->endTime : DateTime(); }
    const TQDate &endDate() const { return m_dateOnlyEndDate; }

    void setEffort(Effort* e) { m_effort = e; }
    Effort* effort() const { return m_effort; }

    /**
     * Returns the (previously) calculated duration.
     */
    virtual Duration *getExpectedDuration() = 0;

    /**
     * Instead of using the expected duration, generate a random value using
     * the Distribution of each Task. This can be used for Monte-Carlo
     * estimation of Project duration.
     */
    virtual Duration *getRandomDuration() = 0;

    /**
     * Calculate the delay of this node. 
     * It is the difference between the actual startTime and scheduled startTime.
     */
    Duration *getDelay();

    /**
      * getEarliestStart() returns earliest time this node can start
      * given the constraints of the network.
      * @see earliestStart
      */
    DateTime getEarliestStart() const
        { return m_currentSchedule ? m_currentSchedule->earliestStart : DateTime(); }
    /**
      * setEarliestStart() sets earliest time this node can start
      * @see earliestStart
      */
    void setEarliestStart(const DateTime &dt) 
        { if (m_currentSchedule) m_currentSchedule->earliestStart = dt; }
    /**
      * getLatestFinish() returns latest time this node can finish
      * @see latestFinish
      */
    DateTime getLatestFinish() const 
        { return m_currentSchedule ? m_currentSchedule->latestFinish : DateTime(); }
    /**
      * setLatestFinish() sets latest time this node can finish
      * given the constraints of the network.
      * @see latestFinish
      */
    void setLatestFinish(const DateTime &dt) 
        { if (m_currentSchedule) m_currentSchedule->latestFinish = dt; }

    TQString &name() { return m_name; }
    TQString &leader() { return m_leader; }
    TQString &description() { return m_description; }
    const TQString &name() const { return m_name; }
    const TQString &leader() const { return m_leader; }
    const TQString &description() const { return m_description; }
    void setName(const TQString &n) { m_name = n; }
    void setLeader(const TQString &l) { m_leader = l; }
    void setDescription(const TQString &d) { m_description = d; }

    virtual void setConstraint(Node::ConstraintType type) { m_constraint = type; }
    void setConstraint(TQString &type);
    int constraint() const { return m_constraint; }
    TQString constraintToString() const;

    virtual void setConstraintStartTime(TQDateTime time) { m_constraintStartTime = time; }
    virtual void setConstraintEndTime(TQDateTime time) { m_constraintEndTime = time; }

    virtual DateTime constraintStartTime() const { return m_constraintStartTime; }
    virtual DateTime constraintEndTime() const { return m_constraintEndTime; }
    virtual DateTime startNotEarlier() const { return m_constraintStartTime; }
    virtual DateTime finishNotLater() const { return m_constraintEndTime; }
    virtual DateTime mustStartOn() const { return m_constraintStartTime; }
    virtual DateTime mustFinishOn() const { return m_constraintEndTime; }

    virtual ResourceGroupRequest *resourceRequest(ResourceGroup */*group*/) const { return 0; }
    virtual void makeAppointments();

    /// EffortType == Effort, but no resource is requested
    bool resourceError() const 
        { return m_currentSchedule ? m_currentSchedule->resourceError : false; }
    /// The assigned resource is overbooked
    virtual bool resourceOverbooked() const
        { return m_currentSchedule ? m_currentSchedule->resourceOverbooked : false; }
    /// Return a list of overbooked resources
    virtual TQStringList overbookedResources() const;
    /// Calculates if the assigned resource is overbooked 
    /// within the duration of this node
    virtual void calcResourceOverbooked();
    /// The requested resource is not available
    bool resourceNotAvailable() const
        { return m_currentSchedule ? m_currentSchedule->resourceNotAvailable : false; }
    /// The task cannot be scheduled to fullfill all the constraints
    virtual bool schedulingError() const
        { return m_currentSchedule ? m_currentSchedule->schedulingError : false; }
    /// The node has not been scheduled
    bool notScheduled() const
        { return m_currentSchedule == 0 || m_currentSchedule->isDeleted() || m_currentSchedule->notScheduled; }
    
    virtual EffortCostMap plannedEffortCostPrDay(const TQDate &start, const TQDate &end) const=0;
        
    /// Returns the total planned effort for this task (or subtasks) 
    virtual Duration plannedEffort() { return Duration::zeroDuration; }
    /// Returns the total planned effort for this task (or subtasks) on date
    virtual Duration plannedEffort(const TQDate &) { return Duration::zeroDuration; }
    /// Returns the planned effort up to and including date
    virtual Duration plannedEffortTo(const TQDate &) { return Duration::zeroDuration; }
    
    /// Returns the total actual effort for this task (or subtasks) 
    virtual Duration actualEffort() { return Duration::zeroDuration; }
    /// Returns the total actual effort for this task (or subtasks) on date
    virtual Duration actualEffort(const TQDate &/*date*/) { return Duration::zeroDuration; }
    /// Returns the total actual effort for this task (or subtasks) up to and including date
    virtual Duration actualEffortTo(const TQDate &/*date*/) { return Duration::zeroDuration; }
    
    /**
     * Planned cost is the sum total of all resources and other costs
     * planned for this node.
     */
    virtual double plannedCost() { return 0; }
    
    /// Planned cost on date
    virtual double plannedCost(const TQDate &/*date*/) { return 0; }
    /**
     * Planned cost from start of activity up to and including date
     * is the sum of all resource costs and other costs planned for this node.
     */
    virtual double plannedCostTo(const TQDate &/*date*/) { return 0; }
    /**
     * Actual cost is the sum total of the reported costs actually used
     * for this node.
     */
    virtual double actualCost() { return 0; }
    /// Actual cost on date
    virtual double actualCost(const TQDate &/*date*/) { return 0; }
    /// Actual cost up to and including date
    virtual double actualCostTo(const TQDate &/*date*/) { return 0; }
    
    /// Effort based performance index
    double effortPerformanceIndex(const TQDate &/*date*/, bool */*error=0*/) { return 0.0; }
    /// Cost performance index
    double costPerformanceIndex(const TQDate &/*date*/, bool */*error=0*/) { return 0.0; }
    
    virtual void initiateCalculationLists(TQPtrList<Node> &startnodes, TQPtrList<Node> &endnodes, TQPtrList<Node> &summarytasks) = 0;
    virtual DateTime calculateForward(int /*use*/) = 0;
    virtual DateTime calculateBackward(int /*use*/) = 0;
    virtual DateTime scheduleForward(const DateTime &, int /*use*/) = 0;
    virtual DateTime scheduleBackward(const DateTime &, int /*use*/) = 0;
    virtual void adjustSummarytask() = 0;

    virtual void initiateCalculation(Schedule &sch);
    virtual void resetVisited();
    void propagateEarliestStart(DateTime &time);
    void propagateLatestFinish(DateTime &time);
    void moveEarliestStart(DateTime &time);
    void moveLatestFinish(DateTime &time);
    // Reimplement this
    virtual Duration summarytaskDurationForward(const DateTime &/*time*/) 
        { return Duration::zeroDuration; }
    // Reimplement this
    virtual DateTime summarytaskEarliestStart() 
        { return DateTime(); }
    // Reimplement this
    virtual Duration summarytaskDurationBackward(const DateTime &/*time*/) 
        { return Duration::zeroDuration; }
    // Reimplement this
    virtual DateTime summarytaskLatestFinish() 
        { return DateTime(); }
    // Returns the (previously) calculated duration
    const Duration &duration()
        { return m_currentSchedule ? m_currentSchedule->duration : Duration::zeroDuration; }
    /**
     * Calculates and returns the duration of the node.
     * Uses the correct expected-, optimistic- or pessimistic effort
     * dependent on use.
     * @param time Where to start calculation.
     * @param use Calculate using expected-, optimistic- or pessimistic estimate.
     * @param backward If true, time specifies when the task should end.
     */
    Duration duration(const DateTime &time, int use, bool backward);
    // Reimplement this
    virtual Duration calcDuration(const DateTime &/*time*/, const Duration &/*effort*/, bool /*backward*/) { return Duration::zeroDuration;}

    Node *siblingBefore();
    Node *childBefore(Node *node);
    Node *siblingAfter();
    Node *childAfter(Node *node);
    bool moveChildUp(Node *node);
    bool moveChildDown(Node *node);
    
    /// Check if this node can be linked to node
    bool legalToLink(Node *node);
    /// Check if node par can be linked to node child. (Reimplement)
    virtual bool legalToLink(Node *, Node *) { return false; }
    /// Check if this node has any dependent child nodes
    virtual bool isEndNode() const;
    /// Check if this node has any dependent parent nodes
    virtual bool isStartNode() const;
    virtual void clearProxyRelations() {}
    virtual void addParentProxyRelations(TQPtrList<Relation> &) {}
    virtual void addChildProxyRelations(TQPtrList<Relation> &) {}
    virtual void addParentProxyRelation(Node *, const Relation *) {}
    virtual void addChildProxyRelation(Node *, const Relation *) {}

    /// Save appointments for schedule with id
    virtual void saveAppointments(TQDomElement &element, long id) const;
    ///Return the list of appointments for current schedule.
    TQPtrList<Appointment> appointments();
    /// Return appointment this node have with resource
//    Appointment *findAppointment(Resource *resource);
    /// Adds appointment to this node only (not to resource)
    virtual bool addAppointment(Appointment *appointment);
    /// Adds appointment to this node only (not to resource)
    virtual bool addAppointment(Appointment *appointment, Schedule &main);
    /// Adds appointment to both this node and resource
    virtual void addAppointment(ResourceSchedule *resource, DateTime &start, DateTime &end, double load=100);
    
    /// Find the node with my id
    virtual Node *findNode() const { return findNode(m_id); }
    /// Find the node with identity id
    virtual Node *findNode(const TQString &id) const
        { return (m_parent ? m_parent->findNode(id) : 0); }
    /// Remove myself from the id register
    virtual bool removeId()  { return removeId(m_id); }
    /// Remove the registered identity id
    virtual bool removeId(const TQString &id)
        { return (m_parent ? m_parent->removeId(id) : false); }
    /// Insert myself into the id register
    virtual void insertId(const TQString &id) { insertId(id, this); }
    /// Insert node with identity id into the register
    virtual void insertId(const TQString &id, const Node *node)
        { if (m_parent) m_parent->insertId(id, node); }
    
    /**
     * This is when work can start on this node in accordance with 
     * the calendar of allocated resources. Normally this is the same
     * as @ref startTime(), but may differ if timing constraints are set.
     */
    virtual DateTime workStartTime() const
        { return m_currentSchedule ? m_currentSchedule->workStartTime : DateTime(); }
    void setWorkStartTime(const DateTime &dt) 
        { if (m_currentSchedule) m_currentSchedule->workStartTime = dt; }
    
    /**
     * This is when work can finish on this node in accordance with 
     * the calendar of allocated resources. Normally this is the same
     * as @ref endTime(), but may differ if timing constraints are set.
     */
    virtual DateTime workEndTime() const 
        { return m_currentSchedule ? m_currentSchedule->workEndTime : DateTime(); }
    void setWorkEndTime(const DateTime &dt) 
        { if (m_currentSchedule) m_currentSchedule->workEndTime = dt; }
    
    virtual bool isCritical() const { return false; }
    virtual bool inCriticalPath() const
        { return m_currentSchedule ? m_currentSchedule->inCriticalPath : false; }
    virtual bool calcCriticalPath(bool fromEnd);
    
    /// Returns the level this node is in the hierarchy. Top node is level 0.
    virtual int level();
    /// Generate WBS
    virtual void generateWBS(int count, WBSDefinition &def, TQString wbs=TQString());
    TQString wbs() const { return m_wbs; }
    
    double startupCost() const { return m_startupCost; }
    void setStartupCost(double cost) { m_startupCost = cost; }
    
    Account *startupAccount() const { return m_startupAccount; }
    void setStartupAccount(Account *acc) { m_startupAccount = acc; }
    
    double shutdownCost() const { return m_shutdownCost; }
    void  setShutdownCost(double cost) { m_shutdownCost = cost; }
    
    Account *shutdownAccount() const { return m_shutdownAccount; }
    void setShutdownAccount(Account *acc) { m_shutdownAccount = acc; }
    
    Account *runningAccount() const { return m_runningAccount; }
    void setRunningAccount(Account *acc) { m_runningAccount = acc; }

    Schedule *currentSchedule() const { return m_currentSchedule; }
    /// Set current schedule to schedule with identity id, for me and my tqchildren
    virtual void setCurrentSchedule(long id);
    // NOTE: Cannot use setCurrentSchedule() due to overload/casting problems
    void setCurrentSchedulePtr(Schedule *schedule) { m_currentSchedule = schedule; }
    
    TQIntDict<Schedule> &schedules() { return m_schedules; }
    /// Find schedule matching name and type. Does not return deleted schedule.
    Schedule *findSchedule(const TQString name, const Schedule::Type type) const;
    /// Find schedule matching type.  Does not return deleted schedule.
    Schedule *findSchedule(const Schedule::Type type) const;
    /// Find schedule matching id.  Also returns deleted schedule.
    Schedule *findSchedule(long id) const { return m_schedules[id]; }
    /// Take, don't delete (as in destruct).
    void takeSchedule(const Schedule *schedule);
    /// Add schedule to list, replace if schedule with same id allready exists.
    void addSchedule(Schedule *schedule);
    /// Create a new schedule.
    Schedule *createSchedule(TQString name, Schedule::Type type, long id);
    /// Create a new schedule.
    Schedule *createSchedule(Schedule *parent);
    
    /// Set deleted = onoff for schedule with id
    void setScheduleDeleted(long id, bool onoff);
    /// Set parent schedule recursivly
    virtual void setParentSchedule(Schedule *sch);
    
    DateTime startTime()
        { return m_currentSchedule ? m_currentSchedule->startTime : DateTime(); }
    DateTime endTime()
        { return m_currentSchedule ? m_currentSchedule->endTime : DateTime(); }

protected:
    TQPtrList<Node> m_nodes;
    TQPtrList<Relation> m_dependChildNodes;
    TQPtrList<Relation> m_dependParentNodes;
    Node *m_parent;

    TQString m_id; // unique id
    TQString m_name;        // Name of this node
    TQString m_leader;      // Person or group responsible for this node
    TQString m_description; // Description of this node

    Effort* m_effort;
    

    ConstraintType m_constraint;

    /**
      * m_constraintTime is used if any of the constraints
      * FixedInterval, StartNotEarlier, MustStartOn or FixedInterval is selected
      */
    DateTime m_constraintStartTime;
    /**
      * m_constraintEndTime is used if any of the constraints
      * FixedInterval, FinishNotLater, MustFinishOn or FixedInterval is selected
      */
    DateTime m_constraintEndTime;

    bool m_visitedForward;
    bool m_visitedBackward;
    Duration m_durationForward;
    Duration m_durationBackward;
    
    TQDate m_dateOnlyStartDate;
    TQDate m_dateOnlyEndDate;
    Duration m_dateOnlyDuration;
 
    TQIntDict<Schedule> m_schedules;
    Schedule *m_currentSchedule;

    TQString m_wbs;
    
    double m_startupCost;
    Account *m_startupAccount;
    double m_shutdownCost;
    Account *m_shutdownAccount;
    Account *m_runningAccount;
    
private:
    void init();
        
#ifndef NDEBUG
public:
    virtual void printDebug(bool tqchildren, TQCString indent);
#endif

};

////////////////////////////////   Effort   ////////////////////////////////
/**
  * Any @ref Node will store how much time it takes to complete the node
  * (typically a @ref Task) in the traditional scheduling software the
  * effort which is needed to complete the node is not simply a timespan but
  * is stored as an optimistic, a pessimistic and an expected timespan.
  */
class Effort {
public:
    Effort ( Duration e = Duration::zeroDuration, Duration p = Duration::zeroDuration,
		Duration o = Duration::zeroDuration );

    Effort ( double e, double p = 0, double o = 0);
    
    Effort (const Effort &effort);
    ~Effort();

    enum Type { Type_Effort = 0,        // Changing amount of resources changes the task duration
                          Type_FixedDuration = 1     // Changing amount of resources will not change the tasks duration
     };
    Type type() const { return m_type; }
    void setType(Type type) { m_type = type; }
    void setType(TQString type);
    TQString typeToString() const;
    
    enum Risktype { Risk_None, Risk_Low, Risk_High };
    Risktype risktype() const { return m_risktype; }
    void setRisktype(Risktype type) { m_risktype = type; }
    void setRisktype(TQString type);
    TQString risktypeToString() const;

    enum Use { Use_Expected=0, Use_Optimistic=1, Use_Pessimistic=2 };
    Duration effort(int use) const;
    const Duration& optimistic() const {return m_optimisticEffort;}
    const Duration& pessimistic() const {return m_pessimisticEffort;}
    const Duration& expected() const {return m_expectedEffort;}

    void set( Duration e, Duration p = Duration::zeroDuration, Duration o = Duration::zeroDuration );
    void set( int e, int p = -1, int o = -1 );
    void set(unsigned days, unsigned hours, unsigned minutes);
    void expectedEffort(unsigned *days, unsigned *hours, unsigned *minutes);

    bool load(TQDomElement &element);
    void save(TQDomElement &element) const;

    /**
     * Set the optimistic duration
     * @param percent should be a negativ value.
     */
    void setOptimisticRatio(int percent);
    /**
     * Return the "optimistic" duration as deviation from "expected" in percent.
     * This should be a negativ value.
     */
    int optimisticRatio() const;
    /**
     * Set the pessimistic duration
     * @param percent should be a positive value.
     */
    void setPessimisticRatio(int percent);
    /**
     * Return the "pessimistic" duration as the deviation from "expected" in percent.
     * This should be a positive value.
     */
    int pessimisticRatio() const;

    /**
     * No effort.
     */
    static const Effort zeroEffort;

    Duration variance() const;
    Duration pertExpected() const;
    Duration pertOptimistic() const;
    Duration pertPessimistic() const;

private:
    Duration m_optimisticEffort;
    Duration m_pessimisticEffort;
    Duration m_expectedEffort;

    Type m_type;
    Risktype m_risktype;
    
#ifndef NDEBUG
public:
    void printDebug(TQCString indent);
#endif

};

}  //KPlato namespace

#endif