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