1/* This file is part of the KDE project
2 Copyright (C) 2001 Thomas Zander zander@kde.org
3 Copyright (C) 2004 - 2011 Dag Andersen <danders@get2net.dk>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19*/
20
21#ifndef KPTNODE_H
22#define KPTNODE_H
23
24#include "kplatokernel_export.h"
25
26#include "kptglobal.h"
27#include "kptrelation.h"
28#include "kptduration.h"
29#include "kptdatetime.h"
30#include "kptschedule.h"
31#include "kptdocuments.h"
32#include "kptresource.h"
33
34#include <QObject>
35#include <QHash>
36#include <QString>
37
38#include <KoXmlReader.h>
39
40class QDomElement;
41
42
43/// The main namespace.
44namespace KPlato
45{
46
47class Account;
48class Project;
49class Appointment;
50class ResourceGroup;
51class Resource;
52class ResourceGroupRequest;
53class Estimate;
54class WBSDefinition;
55class EffortCostMap;
56class EffortCost;
57class Calendar;
58class KPlatoXmlLoaderBase;
59
60/**
61 * This class represents any node in the project, a node can be a project or
62 * a subproject or any task.
63 * This class is basically an abstract interface to make the design more OO.
64 */
65class KPLATOKERNEL_EXPORT Node : public QObject
66{
67 Q_OBJECT
68public:
69 enum ConstraintType { ASAP, ALAP, MustStartOn, MustFinishOn, StartNotEarlier, FinishNotLater, FixedInterval };
70
71 enum State {
72 State_None = 0,
73 State_Started = 1,
74 State_StartedLate = 2,
75 State_StartedEarly = 4,
76 State_Finished = 8,
77 State_FinishedLate = 16,
78 State_FinishedEarly = 32,
79 State_Running = 64,
80 State_RunningLate = 128,
81 State_RunningEarly = 256,
82 State_ReadyToStart = 512, // all precceeding tasks finished (if any)
83 State_NotReadyToStart = 1024, // all precceeding tasks not finished (must be one or more)
84 State_NotScheduled = 2048,
85 State_Late = 4096
86 };
87
88 enum Properties {
89 Type,
90 StartupCost,
91 ShutdownCost,
92 CompletionEntry,
93 CompletionStarted,
94 CompletionFinished,
95 CompletionStartTime,
96 CompletionFinishTime,
97 CompletionPercentage,
98 CompletionRemainingEffort,
99 CompletionActualEffort,
100 CompletionUsedEffort
101 };
102
103 explicit Node(Node *parent = 0);
104 Node(const Node &node, Node *parent = 0);
105
106
107 // Declare the class abstract
108 virtual ~Node() = 0;
109
110 void setId(const QString& id);
111 QString id() const { return m_id; } // unique identity
112
113 enum NodeTypes {
114 Type_Node = 0,
115 Type_Project = 1,
116 Type_Subproject = 2,
117 Type_Task = 3,
118 Type_Milestone = 4,
119 Type_Periodic = 5,
120 Type_Summarytask = 6
121 };
122
123 virtual int type() const = 0;
124
125 QString typeToString( bool trans = false ) const;
126 static QString typeToString( NodeTypes typ, bool trans = false );
127 static QStringList typeToStringList( bool trans );
128 /**
129 * Returns a pointer to the project node (main- or sub-project)
130 * Returns 0 if no project exists.
131 */
132 virtual Node *projectNode();
133 /**
134 * Returns a pointer to the project node (main- or sub-project)
135 * Returns 0 if no project exists.
136 */
137 virtual const Node *projectNode() const;
138
139 // The load and save methods
140 virtual bool load(KoXmlElement &, XMLLoaderObject &) { return true; }
141 virtual void save(QDomElement &element) const = 0;
142 /// Save me and my childrens relations.
143 virtual void saveRelations(QDomElement &element) const;
144
145 /// Save a workpackage document containing @p node with schedule identity @p id
146 virtual void saveWorkPackageXML( QDomElement &element, long id ) const;
147
148 // simple child node management
149 // Child nodes are things like subtasks, basically a task can exists of
150 // several sub-tasks. Creating a table has 4 subtasks, 1) measuring
151 // 2) cutting 3) building 4) painting.
152 Node *parentNode() const { return m_parent; }
153 void setParentNode( Node* newParent ) { m_parent = newParent;}
154 const QList<Node*> &childNodeIterator() const { return m_nodes; }
155 int numChildren() const { return m_nodes.count(); }
156 virtual void addChildNode(Node *node, Node *after=0);
157 virtual void insertChildNode(int index, Node *node);
158 void takeChildNode(Node *node );
159 void takeChildNode(int number );
160 Node* childNode(int number);
161 const Node* childNode(int number) const;
162 int findChildNode( const Node* node ) const;
163 bool isChildOf( const Node *node ) const;
164 int indexOf( const Node *node ) const;
165
166 // Time-dependent child-node-management.
167 // list all nodes that are dependent upon this one.
168 // Building a house requires the table to be finished, therefore the
169 // house-building is time dependent on the table-building. So a child
170 // of the table-building node is the house-building node.
171
172 int numDependChildNodes() const { return m_dependChildNodes.count(); }
173 /// Adds relation of type @p p to both this node and @p node
174 virtual void addDependChildNode( Node *node, Relation::Type p=Relation::FinishStart);
175 /// Adds relation of type @p p with @p lag to both this node and @p node
176 virtual void addDependChildNode( Node *node, Relation::Type p, Duration lag);
177 /// Adds @p relation only to this node
178 virtual bool addDependChildNode( Relation *relation);
179 /// Inserts relation to this node at index @p index and appends relation to @p node
180 virtual void insertDependChildNode( unsigned int index, Node *node, Relation::Type p=Relation::FinishStart);
181 /**
182 * Takes the relation rel from this node only.
183 */
184 void takeDependChildNode( Relation *rel );
185 Relation *getDependChildNode( int number ) const {
186 return m_dependChildNodes.at(number);
187 }
188 QList<Relation*> dependChildNodes() const { return m_dependChildNodes; }
189
190 int numDependParentNodes() const { return m_dependParentNodes.count(); }
191 /// Adds relation if type @p to both this node and @p node
192 virtual void addDependParentNode(Node *node, Relation::Type p=Relation::FinishStart);
193 /// Adds relation to both this node and @p node
194 virtual void addDependParentNode( Node *node, Relation::Type p, Duration lag);
195 /// Adds relation only to this node
196 virtual bool addDependParentNode( Relation *relation);
197 /// Inserts relation to this node at index and appends relation to @p node
198 virtual void insertDependParentNode( unsigned int index, Node *node, Relation::Type p=Relation::FinishStart);
199 /**
200 * Takes the relation @p rel from this node only.
201 */
202 void takeDependParentNode( Relation *rel );
203 Relation *getDependParentNode( int number ) const {
204 return m_dependParentNodes.at(number);
205 }
206 QList<Relation*> dependParentNodes() const { return m_dependParentNodes; }
207 QList<Node*> getParentNodes();
208 bool isParentOf( const Node *node ) const;
209 bool isDependChildOf( const Node *node ) const;
210 virtual bool canMoveTo( const Node *newParent ) const;
211
212 Relation *findParentRelation( const Node *node) const;
213 Relation *findChildRelation( const Node *node ) const;
214 Relation *findRelation( const Node *node ) const;
215
216 /// Set the scheduled start time
217 void setStartTime(DateTime startTime, long id = CURRENTSCHEDULE );
218 /// Return the scheduled start time
219 virtual DateTime startTime( long id = CURRENTSCHEDULE ) const;
220 /// Set the scheduled end time
221 void setEndTime(DateTime endTime, long id = CURRENTSCHEDULE );
222 /// Return the scheduled end time
223 virtual DateTime endTime( long id = CURRENTSCHEDULE ) const;
224 /// Set the scheduled duration
225 void setDuration(const Duration &duration, long id = CURRENTSCHEDULE );
226
227 DateTime appointmentStartTime( long id = CURRENTSCHEDULE) const;
228 DateTime appointmentEndTime( long id = CURRENTSCHEDULE ) const;
229
230 /// Return the estimate for this node
231 Estimate *estimate() const { return m_estimate; }
232
233 /**
234 * Instead of using the expected duration, generate a random value using
235 * the Distribution of each Task. This can be used for Monte-Carlo
236 * estimation of Project duration.
237 */
238 virtual Duration *getRandomDuration() = 0;
239 /**
240 * Calculate the delay of this node.
241 * It is the difference between the actual startTime and scheduled startTime.
242 */
243 Duration *getDelay(); // TODO
244
245
246 QString &name() { return m_name; }
247 QString &leader() { return m_leader; }
248 QString &description() { return m_description; }
249 const QString &name() const { return m_name; }
250 const QString &leader() const { return m_leader; }
251 const QString &description() const { return m_description; }
252 void setName(const QString &n);
253 void setLeader(const QString &l);
254 void setDescription(const QString &d);
255
256 void setConstraint(Node::ConstraintType type);
257 void setConstraint(QString &type);
258 int constraint() const { return m_constraint; }
259 QString constraintToString( bool trans=false ) const;
260 static QStringList constraintList( bool trans );
261
262 virtual void setConstraintStartTime(const DateTime time)
263 { m_constraintStartTime = time; changed( this ); }
264 virtual void setConstraintEndTime(const DateTime time)
265 { m_constraintEndTime = time; changed( this ); }
266
267 virtual DateTime constraintStartTime() const { return m_constraintStartTime; }
268 virtual DateTime constraintEndTime() const { return m_constraintEndTime; }
269 virtual DateTime startNotEarlier() const { return m_constraintStartTime; }
270 virtual DateTime finishNotLater() const { return m_constraintEndTime; }
271 virtual DateTime mustStartOn() const { return m_constraintStartTime; }
272 virtual DateTime mustFinishOn() const { return m_constraintEndTime; }
273
274 virtual ResourceGroupRequest *resourceGroupRequest(const ResourceGroup * /*group*/) const { return 0; }
275 virtual QStringList requestNameList() const { return QStringList(); }
276 virtual bool containsRequest( const QString &/*identity*/ ) const { return false; }
277 virtual ResourceRequest *resourceRequest( const QString &/*name*/ ) const { return 0; }
278
279 /// Return the list of resources assigned to this task
280 virtual QStringList assignedNameList( long /*id*/ = CURRENTSCHEDULE ) const { return QStringList(); }
281
282 virtual void makeAppointments();
283 /// Calculates if the assigned resource is overbooked
284 /// within the duration of this node
285 virtual void calcResourceOverbooked();
286
287 /// Return the scheduling status of schedule @p id. If @p trans is true, text is translated
288 QStringList schedulingStatus( long id, bool trans = false ) const;
289 /// EstimateType == Estimate, but no resource is requested
290 bool resourceError( long id = CURRENTSCHEDULE ) const;
291 /// The assigned resource is overbooked
292 virtual bool resourceOverbooked( long id = CURRENTSCHEDULE ) const;
293 /// The requested resource is not available
294 bool resourceNotAvailable( long id = CURRENTSCHEDULE ) const;
295 /// The task cannot be scheduled to fullfil all the constraints
296 virtual bool constraintError( long id = CURRENTSCHEDULE ) const;
297 /// The task cannot be scheduled correctly
298 virtual bool schedulingError( long id = CURRENTSCHEDULE ) const;
299 /// The node has not been scheduled
300 bool notScheduled( long id = CURRENTSCHEDULE ) const;
301 /// Return a list of overbooked resources
302 virtual QStringList overbookedResources( long id = CURRENTSCHEDULE ) const;
303 /// The assigned resources can not fullfil the estimated effort.
304 virtual bool effortMetError( long /*id*/ = CURRENTSCHEDULE ) const { return false; }
305
306 virtual EffortCostMap plannedEffortCostPrDay(const QDate &start, const QDate &end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const=0;
307 virtual EffortCostMap plannedEffortCostPrDay(const Resource *resource, const QDate &start, const QDate &end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const=0;
308
309 /// Returns the total planned effort for @p resource on this task (or subtasks)
310 virtual Duration plannedEffort( const Resource *resource, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const;
311 /// Returns the total planned effort for this task (or subtasks)
312 virtual Duration plannedEffort( long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const { Q_UNUSED(id); return Duration::zeroDuration; }
313 /// Returns the total planned effort for this task (or subtasks) on date
314 virtual Duration plannedEffort(const QDate &, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const { Q_UNUSED(id); return Duration::zeroDuration; }
315 /// Returns the total planned effort for @p resource on this task (or subtasks) on date
316 virtual Duration plannedEffort( const Resource *resource, const QDate &date, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const;
317 /// Returns the planned effort up to and including date
318 virtual Duration plannedEffortTo(const QDate &, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const { Q_UNUSED(id); return Duration::zeroDuration; }
319 /// Returns the planned effort for @p resource up to and including date
320 virtual Duration plannedEffortTo( const Resource *resource, const QDate &date, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const;
321
322 /// Returns the total actual effort for this task (or subtasks)
323 virtual Duration actualEffort() const { return Duration::zeroDuration; }
324 /// Returns the total actual effort for this task (or subtasks) on date
325 virtual Duration actualEffort(const QDate &/*date*/ ) const { return Duration::zeroDuration; }
326 /// Returns the total actual effort for this task (or subtasks) up to and including date
327 virtual Duration actualEffortTo(const QDate &/*date*/ ) const { return Duration::zeroDuration; }
328 virtual EffortCostMap actualEffortCostPrDay(const QDate &start, const QDate &end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const=0;
329 /// Returns the actual effort and cost pr day used by @p resource
330 virtual EffortCostMap actualEffortCostPrDay(const Resource *resource, const QDate &start, const QDate &end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const=0;
331
332 /**
333 * Planned cost is the sum total of all resources and other costs
334 * planned for this node.
335 */
336 virtual EffortCost plannedCost( long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const;
337
338 /**
339 * Planned cost from start of activity up to and including date
340 * is the sum of all resource costs and other costs planned for this node.
341 */
342 virtual double plannedCostTo(const QDate &/*date*/, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const { Q_UNUSED(id); return 0; }
343 /// Actual cost up to and including date
344 virtual EffortCost actualCostTo( long int /*id*/, const QDate &/*date*/) const { return EffortCost(); }
345
346 /// Returns the effort planned to be used to reach the actual percent finished
347 virtual Duration budgetedWorkPerformed( const QDate &, long = CURRENTSCHEDULE ) const = 0;
348 /// Returns the cost planned to be used to reach the actual percent finished
349 virtual double budgetedCostPerformed( const QDate &, long = CURRENTSCHEDULE ) const { return 0.0; };
350
351 /// Return map of Budgeted Cost of Work Scheduled pr day
352 virtual EffortCostMap bcwsPrDay( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All );
353 /// Return map of Budgeted Cost of Work Scheduled pr day
354 virtual EffortCostMap bcwsPrDay( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All ) const;
355 /// Budgeted Cost of Work Scheduled
356 virtual double bcws( const QDate &/*date*/, long id = CURRENTSCHEDULE ) const { Q_UNUSED(id); return 0.0; }
357
358 /// Return map of Budgeted Cost of Work Scheduled pr day (also includes bcws pr day)
359 virtual EffortCostMap bcwpPrDay( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All );
360 /// Return map of Budgeted Cost of Work Scheduled pr day (also includes bcws pr day)
361 virtual EffortCostMap bcwpPrDay( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All ) const;
362 /// Budgeted Cost of Work Performed
363 virtual double bcwp( long id ) const { Q_UNUSED(id); return 0.0; }
364 /// Budgeted Cost of Work Performed ( up to @p date )
365 virtual double bcwp( const QDate &/*date*/, long id = CURRENTSCHEDULE ) const { Q_UNUSED(id); return 0.0; }
366
367 /// Return a map of Actual effort and Cost of Work Performed
368 virtual EffortCostMap acwp( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All );
369 /// Return a map of Actual effort and Cost of Work Performed
370 virtual EffortCostMap acwp( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All ) const;
371 /// Return Actual effort and Cost of Work Performed upto @date
372 virtual EffortCost acwp( const QDate &date, long id = CURRENTSCHEDULE ) const;
373
374 /// Effort based performance index
375 virtual double effortPerformanceIndex(const QDate &/*date*/, long /*id*/ = CURRENTSCHEDULE ) const { return 0.0; }
376 /// Schedule performance index
377 virtual double schedulePerformanceIndex(const QDate &/*date*/, long /*id*/ = CURRENTSCHEDULE ) const { return 0.0; }
378 /// Cost performance index
379 virtual double costPerformanceIndex( long int /*id*/, const QDate &/*date*/, bool * /*error=0*/ ) const { return 0.0; }
380
381 virtual void initiateCalculationLists(MainSchedule &sch) = 0;
382 virtual DateTime calculateForward(int /*use*/) = 0;
383 virtual DateTime calculateEarlyFinish(int /*use*/) { return DateTime(); }
384 virtual DateTime calculateBackward(int /*use*/) = 0;
385 virtual DateTime calculateLateStart(int /*use*/) { return DateTime(); }
386 virtual DateTime scheduleForward(const DateTime &, int /*use*/) = 0;
387 virtual DateTime scheduleFromStartTime(int /*use*/) { return DateTime(); }
388 virtual DateTime scheduleBackward(const DateTime &, int /*use*/) = 0;
389 virtual DateTime scheduleFromEndTime(int /*use*/) { return DateTime(); }
390 virtual void adjustSummarytask() = 0;
391
392 /// Returns the (previously) calculated duration
393 Duration duration( long id = CURRENTSCHEDULE ) const;
394
395 /**
396 * The variance is calculated based on
397 * the optimistic/pessimistic ratio specified for the estimate.
398 */
399 double variance( long id = CURRENTSCHEDULE, Duration::Unit unit = Duration::Unit_ms ) const;
400 /**
401 * The standard deviation is calculated based on
402 * the optimistic/pessimistic ratio specified for the estimate.
403 */
404 double deviation( long id = CURRENTSCHEDULE, Duration::Unit unit = Duration::Unit_ms ) const;
405
406 Node *siblingBefore();
407 Node *childBefore(Node *node);
408 Node *siblingAfter();
409 Node *childAfter(Node *node);
410 bool moveChildUp(Node *node);
411 bool moveChildDown(Node *node);
412
413 /// Check if this node can be linked to node
414 bool legalToLink( const Node *node ) const;
415 /// Check if node par can be linked to node child. (Reimplement)
416 virtual bool legalToLink( const Node *, const Node *) const { return false; }
417
418 /// Save appointments for schedule with id
419 virtual void saveAppointments(QDomElement &element, long id) const;
420 ///Return the list of appointments for schedule with id.
421 QList<Appointment*> appointments( long id = CURRENTSCHEDULE );
422 /// Adds appointment to this node only (not to resource)
423 virtual bool addAppointment(Appointment *appointment, Schedule &main);
424
425 /// Return list of all resources with appointments to this task for schedule with @p id.
426 QList<Resource*> assignedResources( long id ) const;
427
428 /// Find the node with my id
429 virtual Node *findNode() const { return findNode(m_id); }
430 /// Find the node with identity id
431 virtual Node *findNode(const QString &id) const
432 { return (m_parent ? m_parent->findNode(id) : 0); }
433 /// Remove myself from the id register
434 virtual bool removeId() { return removeId(m_id); }
435 /// Remove the registered identity @p id
436 virtual bool removeId(const QString &id)
437 { return (m_parent ? m_parent->removeId(id) : false); }
438
439 /**
440 * This is when work can start on this node in accordance with
441 * the calendar of allocated resources. Normally this is the same
442 * as @ref startTime(), but may differ if timing constraints are set.
443 */
444 virtual DateTime workStartTime( long id = CURRENTSCHEDULE ) const;
445 void setWorkStartTime(const DateTime &dt, long id = CURRENTSCHEDULE );
446
447 /**
448 * This is when work can finish on this node in accordance with
449 * the calendar of allocated resources. Normally this is the same
450 * as @ref endTime(), but may differ if timing constraints are set.
451 */
452 virtual DateTime workEndTime( long id = CURRENTSCHEDULE ) const;
453 void setWorkEndTime(const DateTime &dt, long id = CURRENTSCHEDULE );
454
455 /// Returns true if this node is critical
456 virtual bool isCritical( long id = CURRENTSCHEDULE ) const { Q_UNUSED(id); return false; }
457 /// Returns true if this node is in a critical path
458 virtual bool inCriticalPath( long id = CURRENTSCHEDULE ) const;
459
460 /// Returns the level this node is in the hierarchy. Top node is level 0.
461 virtual int level() const;
462 /// Generate WBS Code
463 virtual QString generateWBSCode( QList<int> &indexes ) const;
464 /// Returns the Work Breakdown Structure Code
465 QString wbsCode() const;
466
467 double startupCost() const { return m_startupCost; }
468 void setStartupCost(double cost);
469
470 Account *startupAccount() const { return m_startupAccount; }
471 void setStartupAccount(Account *acc);
472
473 double shutdownCost() const { return m_shutdownCost; }
474 void setShutdownCost(double cost);
475
476 Account *shutdownAccount() const { return m_shutdownAccount; }
477 void setShutdownAccount(Account *acc);
478
479 Account *runningAccount() const { return m_runningAccount; }
480 void setRunningAccount(Account *acc);
481
482 bool isBaselined( long int id = BASELINESCHEDULE ) const;
483 /**
484 * Return schedule with @p id
485 * If @p id == CURRENTSCHEDULE, return m_currentSchedule
486 * Return 0 if schedule with @p id doesn't exist.
487 */
488 Schedule *schedule( long id = CURRENTSCHEDULE ) const;
489 /// Return current schedule
490 Schedule *currentSchedule() const { return m_currentSchedule; }
491 /// Set current schedule to schedule with identity @p id, for me and my children
492 virtual void setCurrentSchedule(long id);
493 /// Return true if this node has a valid schedule with identity == @p id
494 bool isScheduled( long id = CURRENTSCHEDULE ) const;
495 /// Return the list of schedules for this node
496 QHash<long, Schedule*> &schedules() { return m_schedules; }
497 /// Find schedule matching name and type. Does not return deleted schedule.
498 Schedule *findSchedule(const QString name, const Schedule::Type type);
499 /// Find schedule matching name. Does not return deleted schedule.
500 Schedule *findSchedule(const QString name);
501 /// Find schedule matching type. Does not return deleted schedule.
502 Schedule *findSchedule(const Schedule::Type type);
503 /// Find schedule matching id. Also returns deleted schedule.
504 Schedule *findSchedule(long id) const;
505
506 /// Take, don't delete (as in destruct).
507 void takeSchedule(const Schedule *schedule);
508 /// Add schedule to list, replace if schedule with same id already exists.
509 void addSchedule(Schedule *schedule);
510 /// Create a new schedule.
511 Schedule *createSchedule(const QString& name, Schedule::Type type, long id);
512 /// Create a new schedule.
513 Schedule *createSchedule(Schedule *parent);
514
515 /// Set deleted = onoff for schedule with id
516 void setScheduleDeleted(long id, bool onoff);
517 /// Set parent schedule recursivly
518 virtual void setParentSchedule(Schedule *sch);
519
520 const ResourceRequestCollection &requests() const { return m_requests; }
521 ResourceRequestCollection &requests() { return m_requests; }
522
523 virtual uint state( long ) const { return State_None; }
524
525 const Documents &documents() const { return m_documents; }
526 Documents &documents() { return m_documents; }
527
528 virtual void emitDocumentAdded( Node *node, Document *doc, int idx );
529 virtual void emitDocumentRemoved( Node *node, Document *doc, int idx );
530 virtual void emitDocumentChanged( Node *node, Document *doc, int idx );
531
532public:
533 // These shouldn't be available to other than those who inherits
534 /// Calculate the critical path
535 virtual bool calcCriticalPath(bool fromEnd);
536 virtual void calcFreeFloat();
537
538 /// Check if this node has any dependent child nodes
539 virtual bool isEndNode() const;
540 /// Check if this node has any dependent parent nodes
541 virtual bool isStartNode() const;
542
543 virtual void initiateCalculation(MainSchedule &sch);
544 virtual void resetVisited();
545 void propagateEarliestStart(DateTime &time);
546 void propagateLatestFinish(DateTime &time);
547 void moveEarliestStart(DateTime &time);
548 void moveLatestFinish(DateTime &time);
549 // Reimplement this
550 virtual Duration summarytaskDurationForward(const DateTime &/*time*/)
551 { return Duration::zeroDuration; }
552 // Reimplement this
553 virtual DateTime summarytaskEarliestStart()
554 { return DateTime(); }
555 // Reimplement this
556 virtual Duration summarytaskDurationBackward(const DateTime &/*time*/)
557 { return Duration::zeroDuration; }
558 // Reimplement this
559 virtual DateTime summarytaskLatestFinish()
560 { return DateTime(); }
561
562 /**
563 * earlyStart() returns earliest time this node can start
564 * given the constraints of the network.
565 */
566 DateTime earlyStart( long id = CURRENTSCHEDULE ) const;
567 /**
568 * setEarlyStart() sets earliest time this node can start
569 */
570 void setEarlyStart(const DateTime &dt, long id = CURRENTSCHEDULE );
571 /**
572 * lateStart() returns latest time this node can start
573 * given the constraints of the network.
574 */
575 DateTime lateStart( long id = CURRENTSCHEDULE ) const;
576 /**
577 * setLateStart() sets the earliest time this node can start
578 */
579 void setLateStart(const DateTime &dt, long id = CURRENTSCHEDULE );
580 /**
581 * earlyFinish() returns earliest time this node can finish
582 * given the constraints of the network.
583 */
584 DateTime earlyFinish( long id = CURRENTSCHEDULE ) const;
585 /**
586 * setEarlyFinish() sets earliest time this node can finish
587 */
588 void setEarlyFinish(const DateTime &dt, long id = CURRENTSCHEDULE );
589 /**
590 * lateFinish() returns latest time this node can finish
591 * given the constraints of the network.
592 */
593 DateTime lateFinish( long id = CURRENTSCHEDULE ) const;
594 /**
595 * setLateFinish() sets latest time this node can finish
596 */
597 void setLateFinish(const DateTime &dt, long id = CURRENTSCHEDULE );
598
599 /// Adds appointment to both this node and resource
600 virtual void addAppointment(ResourceSchedule *resource, DateTime &start, DateTime &end, double load=100);
601
602 virtual void clearProxyRelations() {}
603 virtual void addParentProxyRelations( const QList<Relation*> & ) {}
604 virtual void addChildProxyRelations( const QList<Relation*> & ) {}
605 virtual void addParentProxyRelation(Node *, const Relation *) {}
606 virtual void addChildProxyRelation(Node *, const Relation *) {}
607
608 virtual void changed( int property = -1 ) { changed( this, property ); }
609 Duration getmDurationForward(){ return this->m_durationForward;}
610
611public slots:
612 void slotStandardWorktimeChanged( StandardWorktime* );
613
614protected:
615 friend class KPlatoXmlLoaderBase;
616 /**
617 * Calculates and returns the duration of the node.
618 * Reimplement.
619 */
620 virtual Duration duration(const DateTime &/*time*/, int /*use*/, bool /*backward*/)
621 { return Duration::zeroDuration; }
622
623 // NOTE: Cannot use setCurrentSchedule() due to overload/casting problems
624 void setCurrentSchedulePtr(Schedule *schedule) { m_currentSchedule = schedule; }
625 virtual void changed(Node *node, int property = -1 );
626
627 QList<Node*> m_nodes;
628 QList<Relation*> m_dependChildNodes;
629 QList<Relation*> m_dependParentNodes;
630 QList<Node*>m_parentNodes;
631 Node *m_parent;
632
633
634 QString m_id; // unique id
635 QString m_name; // Name of this node
636 QString m_leader; // Person or group responsible for this node
637 QString m_description; // Description of this node
638
639 Estimate *m_estimate;
640
641
642 ConstraintType m_constraint;
643
644 /**
645 * m_constraintTime is used if any of the constraints
646 * FixedInterval, StartNotEarlier, MustStartOn or FixedInterval is selected
647 */
648 DateTime m_constraintStartTime;
649 /**
650 * m_constraintEndTime is used if any of the constraints
651 * FixedInterval, FinishNotLater, MustFinishOn or FixedInterval is selected
652 */
653 DateTime m_constraintEndTime;
654
655 bool m_visitedForward;
656 bool m_visitedBackward;
657 Duration m_durationForward;
658 Duration m_durationBackward;
659 DateTime m_earlyStart;
660 DateTime m_earlyFinish;
661 DateTime m_lateFinish;
662
663 QHash<long, Schedule*> m_schedules;
664 Schedule *m_currentSchedule;
665
666 double m_startupCost;
667 Account *m_startupAccount;
668 double m_shutdownCost;
669 Account *m_shutdownAccount;
670 Account *m_runningAccount;
671
672 Documents m_documents;
673
674 ResourceRequestCollection m_requests;
675
676private:
677 void init();
678};
679
680//////////////////////////////// Estimate ////////////////////////////////
681/**
682 * The Estimate class stores how much time (or effort) it takes to complete a Task.
683 * The estimate which is needed to complete the task is not simply a single value but
684 * is stored as an optimistic, a pessimistic and an expected value.
685 * With statistical calculations using the PERT distribution, one can arrive at a more
686 * realistic estimate than when using the expected value alone.
687 */
688class KPLATOKERNEL_EXPORT Estimate {
689public:
690 /// Constructor
691 explicit Estimate( Node *parent = 0 );
692 /// Copy constructor.
693 Estimate (const Estimate &estimate, Node *parent = 0);
694 /// Destructor
695 ~Estimate();
696
697 /// Reset estimate
698 void clear();
699
700 /// Copy values from @p estimate
701 Estimate &operator=( const Estimate &estimate );
702
703 /// Type defines the types of estimates
704 enum Type {
705 Type_Effort, /// Changing amount of resources changes the task duration
706 Type_Duration /// Changing amount of resources will not change the tasks duration
707 };
708 /// Return the node that owns this Estimate
709 Node *parentNode() const { return m_parent; }
710 /// Set the node that owns this Estimate
711 void setParentNode( Node* parent ) { m_parent = parent; }
712
713 /// Return estimate Type
714 Type type() const { return m_type; }
715 /// Set estimate type to @p type
716 void setType(Type type);
717 /// Set estimate type to type represented by the string @p type
718 void setType(const QString& type);
719 /// Return estimate type as a string. If @p trans is true, it's translated
720 QString typeToString( bool trans=false ) const;
721 /// Return estimate type @p typ as a string. If @p trans is true, it's translated
722 static QString typeToString( Estimate::Type typ, bool trans=false );
723 /// Return a stringlist of all estimate types. Translated if @p trans = true.
724 static QStringList typeToStringList( bool trans=false );
725
726 /// Return the calendar used when Type is Duration
727 Calendar *calendar() const { return m_calendar; }
728 /// Set the calendar to be used when Type is Duration
729 void setCalendar( Calendar *calendar );
730
731 enum Risktype { Risk_None, Risk_Low, Risk_High };
732 Risktype risktype() const { return m_risktype; }
733 void setRisktype(Risktype type);
734 void setRisktype(const QString& type);
735 QString risktypeToString( bool trans=false ) const;
736 static QStringList risktypeToStringList( bool trans=false );
737
738 /// Use defines which value to access
739 enum Use { Use_Expected=0, Use_Optimistic=1, Use_Pessimistic=2 };
740
741 /// Return estimate (scaled) of type @p valueType.
742 /// If @p pert is true the pert value is calculated and returned
743 Duration value(int valueType, bool pert) const;
744
745 /// Return unscaled value
746 Duration optimisticValue() const;
747 /// Return unscaled value
748 Duration pessimisticValue() const;
749 /// Return unscaled value
750 Duration expectedValue() const;
751
752 /// The unit in which the estimates were entered.
753 Duration::Unit unit() const { return m_unit; }
754 /// Set display unit.
755 void setUnit( Duration::Unit unit );
756
757 /// Return the expected estimate (normally entered by user)
758 double expectedEstimate() const { return m_expectedEstimate; }
759 /// Return the optimistic estimate (normally entered by user)
760 double optimisticEstimate() const { return m_optimisticEstimate; }
761 /// Return the pessimistic estimate (normally entered by user)
762 double pessimisticEstimate() const { return m_pessimisticEstimate; }
763 /// Set the expected estimate
764 void setExpectedEstimate( double value );
765 /// Set the optimistic estimate
766 void setOptimisticEstimate( double value );
767 /// Set the pessimistic estimate
768 void setPessimisticEstimate( double value );
769
770 /**
771 * Set the optimistic estimate as a deviation from "expected" in percent
772 * @param percent should be a negative value.
773 */
774 void setOptimisticRatio(int percent);
775 /**
776 * Return the "optimistic" estimate as deviation from "expected" in percent.
777 * This should be a negative value.
778 */
779 int optimisticRatio() const;
780 /**
781 * Set the pessimistic estimate as a deviation from "expected" in percent
782 * @param percent should be a positive value.
783 */
784 void setPessimisticRatio(int percent);
785 /**
786 * Return the "pessimistic" estimate as the deviation from "expected" in percent.
787 * This should be a positive value.
788 */
789 int pessimisticRatio() const;
790
791 /**
792 * The variance is calculated based on
793 * the optimistic/pessimistic estimates, scaled to current unit.
794 */
795 double variance() const;
796 /**
797 * The variance is calculated based on
798 * the optimistic/pessimistic estimates, scaled to @p unit
799 */
800 double variance( Duration::Unit unit ) const;
801 /**
802 * The standard deviation is calculated based on
803 * the optimistic/pessimistic estimates, scaled to current unit.
804 */
805 double deviation() const;
806 /**
807 * The standard deviation is calculated based on
808 * the optimistic/pessimistic estimates, scaled to @p unit
809 */
810 double deviation( Duration::Unit unit ) const;
811
812 /// Returns the expected duration. Calculated based on the estimates expected, optimistic and pessimistic
813 Duration pertExpected() const;
814 /// Returns the most optimistic duration. Calculated based on the estimates expected, optimistic and pessimistic
815 Duration pertOptimistic() const;
816 /// Returns the most pessimistic duration. Calculated based on the estimates expected, optimistic and pessimistic
817 Duration pertPessimistic() const;
818
819 /// Convert the duration @p value (in milliseconds) to a value in @p unit, using the scaling factors in @p scales
820 static double scale( const Duration &value, Duration::Unit unit, const QList<qint64> &scales );
821 /// Convert the duration @p value (in @p unit) to a value in milliseconds (base unit), using the scaling factors in @p scales
822 static Duration scale( double value, Duration::Unit unit, const QList<qint64> &scales );
823
824 /// Return a list of default scales scaling factors
825 static QList<qint64> defaultScales();
826 /// Return a list of scaling factors fetched from the projects standard worktime
827 QList<qint64> scales() const;
828
829 /// Load from xml document
830 bool load(KoXmlElement &element, XMLLoaderObject &status);
831 /// Save to xml document
832 void save(QDomElement &element) const;
833
834protected:
835 /// Set (calculate) cached value
836 void setOptimisticValue();
837 /// Set (calculate) cached value
838 void setExpectedValue();
839 /// Set (calculate) cached value
840 void setPessimisticValue();
841 /// Notify parent of changes
842 void changed() { if ( m_parent ) m_parent->changed(); }
843 /// Copy @p estimate, parentNode is not copied
844 void copy( const Estimate &estimate );
845
846private:
847 friend class Node;
848 Node *m_parent;
849 /// Holds the unit entered by user
850 Duration::Unit m_unit;
851 /// Holds the value entered by user, in unit m_unit
852 double m_expectedEstimate;
853 /// Holds the value entered by user, in unit m_unit
854 double m_optimisticEstimate;
855 /// Holds the value entered by user, in unit m_unit
856 double m_pessimisticEstimate;
857
858 mutable bool m_expectedCached, m_optimisticCached, m_pessimisticCached, m_pertCached;
859 /// Cached value in base unit (milliseconds)
860 Duration m_expectedValue;
861 /// Cached value in base unit (milliseconds)
862 Duration m_optimisticValue;
863 /// Cached value in base unit (milliseconds)
864 Duration m_pessimisticValue;
865 /// Cached pert expected value
866 mutable Duration m_pertExpected;
867
868 Type m_type;
869 Risktype m_risktype;
870
871 /// Calendar may be used when Type is Type_Duration
872 Calendar *m_calendar;
873};
874
875} //KPlato namespace
876
877#endif
878