1 /* This file is part of the KDE project
2    Copyright (C) 2001 Thomas Zander zander@kde.org
3    Copyright (C) 2004 - 2007 Dag Andersen <danders@get2net.dk>
4    Copyright (C) 2007 Florian Piquemal <flotueur@yahoo.fr>
5    Copyright (C) 2007 Alexis Ménard <darktears31@gmail.com>
6 
7    This library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Library General Public
9    License as published by the Free Software Foundation; either
10    version 2 of the License, or (at your option) any later version.
11 
12    This library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Library General Public License for more details.
16 
17    You should have received a copy of the GNU Library General Public License
18    along with this library; see the file COPYING.LIB.  If not, write to
19    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21 */
22 
23 #ifndef KPTTASK_H
24 #define KPTTASK_H
25 
26 #include "plankernel_export.h"
27 
28 #include "kptnode.h"
29 #include "kptglobal.h"
30 #include "kptdatetime.h"
31 #include "kptduration.h"
32 #include "kptresource.h"
33 
34 #include <QList>
35 #include <QMap>
36 #include <utility>
37 
38 /// The main namespace.
39 namespace KPlato
40 {
41 
42 class Completion;
43 class XmlSaveContext;
44 
45 /**
46  * The Completion class holds information about the tasks progress.
47  */
48 class PLANKERNEL_EXPORT Completion
49 {
50 
51 public:
52     class PLANKERNEL_EXPORT UsedEffort
53     {
54         public:
55             class PLANKERNEL_EXPORT ActualEffort : public std::pair<Duration, Duration>
56             {
57                 public:
58                     explicit ActualEffort(KPlato::Duration ne = Duration::zeroDuration, KPlato::Duration oe = Duration::zeroDuration)
59                         : std::pair<Duration, Duration>(ne, oe)
60                     {}
ActualEffort(const ActualEffort & e)61                     ActualEffort(const ActualEffort &e)
62                         : std::pair<Duration, Duration>(e.first, e.second)
63                     {}
~ActualEffort()64                     ~ActualEffort() {}
isNull()65                     bool isNull() const { return (first + second) == Duration::zeroDuration; }
normalEffort()66                     Duration normalEffort() const { return first; }
setNormalEffort(KPlato::Duration e)67                     void setNormalEffort(KPlato::Duration e) { first = e; }
overtimeEffort()68                     Duration overtimeEffort() const { return second; }
setOvertimeEffort(KPlato::Duration e)69                     void setOvertimeEffort(KPlato::Duration e) { second = e; }
70                     /// Returns the sum of normalEffort + overtimeEffort
effort()71                     Duration effort() const { return first + second; }
72                     void setEffort(KPlato::Duration ne, KPlato::Duration oe = Duration::zeroDuration) { first = ne; second = oe; }
73             };
74             UsedEffort();
75             UsedEffort(const UsedEffort &e);
76             ~UsedEffort();
77             bool operator==(const UsedEffort &e) const;
78             bool operator!=(const UsedEffort &e) const { return !operator==(e); }
79             void mergeEffort(const UsedEffort &value);
80             void setEffort(QDate date, const ActualEffort &value);
81             /// Returns the total effort up to @p date
82             Duration effortTo(QDate date) const;
83             /// Returns the total effort on @p date
effort(QDate date)84             ActualEffort effort(QDate date) const { return m_actual.value(date); }
takeEffort(QDate date)85             ActualEffort takeEffort(QDate date) { return m_actual.take(date); }
86             /// Returns the total effort for all registered dates
87             Duration effort() const;
firstDate()88             QDate firstDate() const { return m_actual.firstKey(); }
lastDate()89             QDate lastDate() const { return m_actual.lastKey(); }
actualEffortMap()90             QMap<QDate, ActualEffort> actualEffortMap() const { return m_actual; }
91 
92             /// Load from document
93             bool loadXML(KoXmlElement &element, XMLLoaderObject &status);
94             /// Save to document
95             void saveXML(QDomElement &element) const;
contains(QDate date)96             bool contains(QDate date) const { return m_actual.contains(date); }
97 
98         private:
99             QMap<QDate, ActualEffort> m_actual;
100     };
101     typedef QMap<QDate, UsedEffort::ActualEffort> DateUsedEffortMap;
102 
103     class PLANKERNEL_EXPORT Entry
104     {
105         public:
Entry()106             Entry()
107             : percentFinished(0),
108               remainingEffort(Duration::zeroDuration),
109               totalPerformed(Duration::zeroDuration)
110             {}
Entry(int percent,Duration remaining,Duration performed)111             Entry(int percent,  Duration remaining, Duration performed)
112             : percentFinished(percent),
113               remainingEffort(remaining),
114               totalPerformed(performed)
115             {}
Entry(const Entry & e)116             Entry(const Entry &e) { copy(e); }
117             bool operator==(const Entry &e) const {
118                 return percentFinished == e.percentFinished
119                     && remainingEffort == e.remainingEffort
120                     && totalPerformed == e.totalPerformed
121                     && note == e.note;
122             }
123             bool operator!=(const Entry &e) const { return ! operator==(e); }
124             Entry &operator=(const Entry &e) { copy(e); return *this; }
125 
126             int percentFinished;
127             Duration remainingEffort;
128             Duration totalPerformed;
129             QString note;
130         protected:
copy(const Entry & e)131             void copy(const Entry &e) {
132                 percentFinished = e.percentFinished;
133                 remainingEffort = e.remainingEffort;
134                 totalPerformed = e.totalPerformed;
135                 note = e.note;
136             }
137     };
138     typedef QMap<QDate, Entry*> EntryList;
139 
140     typedef QHash<const Resource*, UsedEffort*> ResourceUsedEffortMap;
141 
142     explicit Completion(Node *node = 0);  // review * or &, or at all?
143     Completion(const Completion &copy);
144     virtual ~Completion();
145 
146     bool operator==(const Completion &p);
147     bool operator!=(Completion &p) { return !(*this == p); }
148     Completion &operator=(const Completion &p);
149 
150     /// Load from document
151     bool loadXML(KoXmlElement &element, XMLLoaderObject &status);
152     /// Save to document
153     void saveXML(QDomElement &element) const;
154 
startIsValid()155     bool startIsValid() const { return m_started && m_startTime.isValid(); }
isStarted()156     bool isStarted() const { return m_started; }
157     void setStarted(bool on);
finishIsValid()158     bool finishIsValid() const { return m_finished && m_finishTime.isValid(); }
isFinished()159     bool isFinished() const { return m_finished; }
160     void setFinished(bool on);
startTime()161     DateTime startTime() const { return m_startTime; }
162     void setStartTime(const DateTime &dt);
finishTime()163     DateTime finishTime() const { return m_finishTime; }
164     void setFinishTime(const DateTime &dt);
165     void setPercentFinished(QDate date, int value);
166     void setRemainingEffort(QDate date, Duration value);
167     void setActualEffort(QDate date, Duration value);
168 
169     /// Return a list of the resource that has done any work on this task
resources()170     QList<const Resource*> resources() const { return m_usedEffort.keys(); }
171 
entries()172     const EntryList &entries() const { return m_entries; }
173     void addEntry(QDate date, Entry *entry);
takeEntry(QDate date)174     Entry *takeEntry(QDate date) { return m_entries.take(date); changed(); }
entry(QDate date)175     Entry *entry(QDate date) const { return m_entries[ date ]; }
176 
177     /// Returns the date of the latest entry
178     QDate entryDate() const;
179     /// Returns the percentFinished of the latest entry
180     int percentFinished() const;
181     /// Returns the percentFinished on @p date
182     int percentFinished(QDate date) const;
183     /// Returns the estimated remaining effort
184     Duration remainingEffort() const;
185     /// Returns the estimated remaining effort on @p date
186     Duration remainingEffort(QDate date) const;
187     /// Returns the total actual effort
188     Duration actualEffort() const;
189     /// Returns the total actual effort on @p date
190     Duration actualEffort(QDate date) const;
191     /// Returns the total actual effort upto and including @p date
192     Duration actualEffortTo(QDate date) const;
193     /// Returns the actual effort for @p resource on @p date
194     Duration actualEffort(const Resource *resource, QDate date) const;
195     /// TODO
196     QString note() const;
197     /// TODO
198     void setNote(const QString &str);
199 
200     /// Returns the total actual cost
201     double actualCost() const;
202     /// Returns the actual cost for @p resource
203     double actualCost(const Resource *resource) const;
204     /// Returns the actual cost on @p date
205     double actualCost(QDate date) const;
206     /// Returns the total actual cost for @p resource on @p date
207     double actualCost(const Resource *resource, QDate date) const;
208     /// Returns the total actual effort and cost upto and including @p date
209     EffortCost actualCostTo(long int id, QDate date) const;
210 
211     /**
212      * Returns a map of all actual effort and cost entered
213      */
214     virtual EffortCostMap actualEffortCost(long id, EffortCostCalculationType type = ECCT_All) const;
215 
216     void addUsedEffort(const Resource *resource, UsedEffort *value = 0);
takeUsedEffort(const Resource * r)217     UsedEffort *takeUsedEffort(const Resource *r) { return m_usedEffort.take(const_cast<Resource*>(r) ); changed(); }
usedEffort(const Resource * r)218     UsedEffort *usedEffort(const Resource *r) const { return m_usedEffort.value(const_cast<Resource*>(r) ); }
usedEffortMap()219     const ResourceUsedEffortMap &usedEffortMap() const { return m_usedEffort; }
220 
221     void setActualEffort(Resource *resource, const QDate &date, const UsedEffort::ActualEffort &value);
222     // FIXME name clash
223     UsedEffort::ActualEffort getActualEffort(Resource *resource, const QDate &date) const;
224 
225     void changed(int property = -1);
node()226     Node *node() const { return m_node; }
setNode(Node * node)227     void setNode(Node *node) { m_node = node; }
228 
229     enum Entrymode { FollowPlan, EnterCompleted, EnterEffortPerTask, EnterEffortPerResource };
setEntrymode(Entrymode mode)230     void setEntrymode(Entrymode mode) { m_entrymode = mode; }
entrymode()231     Entrymode entrymode() const { return m_entrymode; }
232     void setEntrymode(const QString &mode);
233     QString entryModeToString() const;
234     QStringList entrymodeList() const;
235 
236     EffortCostMap effortCostPrDay(QDate start, QDate end, long id = -1) const;
237     /// Returns the actual effort and cost pr day used by @p resource
238     EffortCostMap effortCostPrDay(const Resource *resource, QDate start, QDate end, long id = CURRENTSCHEDULE) const;
239 
240 protected:
241     void copy(const Completion &copy);
242     double averageCostPrHour(QDate date, long id) const;
243     std::pair<QDate, QDate> actualStartEndDates() const;
244 
245 private:
246     Node *m_node;
247     bool m_started, m_finished;
248     DateTime m_startTime, m_finishTime;
249     EntryList m_entries;
250     ResourceUsedEffortMap m_usedEffort;
251     Entrymode m_entrymode;
252 
253 #ifndef NDEBUG
254 public:
255     void printDebug(const QByteArray &ident) const;
256 #endif
257 };
258 
259 /**
260  * The WorkPackage class controls work flow for a task
261  */
262 class PLANKERNEL_EXPORT WorkPackage
263 {
264 public:
265 
266     /// @enum WPTransmitionStatus describes if this package was sent or received
267     enum WPTransmitionStatus {
268         TS_None,        /// Not sent nor received
269         TS_Send,        /// Package was sent to resource
270         TS_Receive,     /// Package was received from resource
271         TS_Rejected     /// Received package was rejected by project manager
272     };
273 
274     explicit WorkPackage(Task *task = 0);
275     explicit WorkPackage(const WorkPackage &wp);
276     virtual ~WorkPackage();
277 
parentTask()278     Task *parentTask() const { return m_task; }
setParentTask(Task * task)279     void setParentTask(Task *task) { m_task = task; }
280 
281     /// Returns the transmission status of this package
transmitionStatus()282     WPTransmitionStatus transmitionStatus() const { return m_transmitionStatus; }
setTransmitionStatus(WPTransmitionStatus sts)283     void setTransmitionStatus(WPTransmitionStatus sts) { m_transmitionStatus = sts; }
284     static QString transmitionStatusToString(WPTransmitionStatus sts, bool trans = false);
285     static WPTransmitionStatus transmitionStatusFromString(const QString &sts);
286 
287     /// Load from document
288     virtual bool loadXML(KoXmlElement &element, XMLLoaderObject &status);
289     /// Save the full workpackage
290     virtual void saveXML(QDomElement &element) const;
291 
292     /// Load from document
293     virtual bool loadLoggedXML(KoXmlElement &element, XMLLoaderObject &status);
294     /// Save the full workpackage
295     virtual void saveLoggedXML(QDomElement &element) const;
296 
297     /// Set schedule manager
298     void setScheduleManager(ScheduleManager *sm);
299     /// Return schedule manager
scheduleManager()300     ScheduleManager *scheduleManager() const { return m_manager; }
301     /// Return the schedule id, or NOTSCHEDULED if no schedule manager is set
id()302     long id() const { return m_manager ? m_manager->scheduleId() : NOTSCHEDULED; }
303 
304     Completion &completion();
305     const Completion &completion() const;
306 
307     void addLogEntry(DateTime &dt, const QString &str);
308     QMap<DateTime, QString> log() const;
309     QStringList log();
310 
311     /// Return a list of resources fetched from the appointments or requests
312     /// merged with resources added to completion
313     QList<Resource*> fetchResources();
314 
315     /// Return a list of resources fetched from the appointments or requests
316     /// merged with resources added to completion
317     QList<Resource*> fetchResources(long id);
318 
319     /// Returns id of the resource that owns this package. If empty, task leader owns it.
ownerId()320     QString ownerId() const { return m_ownerId; }
321     /// Set the resource that owns this package to @p owner. If empty, task leader owns it.
setOwnerId(const QString & id)322     void setOwnerId(const QString &id) { m_ownerId = id; }
323 
324     /// Returns the name of the resource that owns this package.
ownerName()325     QString ownerName() const { return m_ownerName; }
326     /// Set the name of the resource that owns this package.
setOwnerName(const QString & name)327     void setOwnerName(const QString &name) { m_ownerName = name; }
328 
transmitionTime()329     DateTime transmitionTime() const { return m_transmitionTime; }
setTransmitionTime(const DateTime & dt)330     void setTransmitionTime(const DateTime &dt) { m_transmitionTime = dt; }
331 
332     /// Clear workpackage data
333     void clear();
334 
335 private:
336     Task *m_task;
337     ScheduleManager *m_manager;
338     Completion m_completion;
339     QString m_ownerName;
340     QString m_ownerId;
341     WPTransmitionStatus m_transmitionStatus;
342     DateTime m_transmitionTime;
343 
344     QMap<DateTime, QString> m_log;
345 };
346 
347 class PLANKERNEL_EXPORT WorkPackageSettings
348 {
349 public:
350     WorkPackageSettings();
351     bool loadXML(const KoXmlElement &element);
352     void saveXML(QDomElement &element) const;
353     bool operator==(WorkPackageSettings settings) const;
354     bool operator!=(WorkPackageSettings settings) const;
355     bool usedEffort;
356     bool progress;
357     bool documents;
358     bool remainingEffort;
359 };
360 
361 /**
362   * A task in the scheduling software is represented by this class. A task
363   * can be anything from 'build house' to 'drill hole' It will always mean
364   * an activity.
365   */
366 class PLANKERNEL_EXPORT Task : public Node {
367     Q_OBJECT
368 public:
369     explicit Task(Node *parent = 0);
370     explicit Task(const Task &task, Node *parent = 0);
371     ~Task() override;
372 
373     /// Return task type. Can be Type_Task, Type_Summarytask ot Type_Milestone.
374     int type() const override;
375 
376     /**
377      * Instead of using the expected duration, generate a random value using
378      * the Distribution of each Task. This can be used for Monte-Carlo
379      * estimation of Project duration.
380      */
381     Duration *getRandomDuration() override;
382 
383     /**
384      * Return the resource request made to group
385      * (There should be only one)
386      */
387     ResourceGroupRequest *resourceGroupRequest(const ResourceGroup *group) const override;
388     void clearResourceRequests();
389     void addRequest(ResourceGroup *group, int numResources);
390     void addRequest(ResourceGroupRequest *request);
391     void takeRequest(ResourceGroupRequest *request);
392     void makeAppointments() override;
393     QStringList requestNameList() const override;
394     virtual QList<Resource*> requestedResources() const;
395     bool containsRequest(const QString &/*identity*/) const override;
396     ResourceRequest *resourceRequest(const QString &/*name*/) const override;
397 
398     /// Return the list of resources assigned to this task
399     QStringList assignedNameList(long id = CURRENTSCHEDULE) const override;
400 
401     /**
402      * Calculates if the assigned resource is overbooked
403      * within the duration of this task
404      */
405     void calcResourceOverbooked() override;
406 
407     /// Load from document
408     bool load(KoXmlElement &element, XMLLoaderObject &status) override;
409     /// Save to document
410     void save(QDomElement &element, const XmlSaveContext &context) const override;
411     /// Save appointments for schedule with id
412     void saveAppointments(QDomElement &element, long id) const override;
413 
414     /// Save a workpackage document with schedule identity @p id
415     void saveWorkPackageXML(QDomElement &element, long id) const override;
416 
417     /**
418      * Returns a list of planned effort and cost for this task
419      * for the interval start, end inclusive
420      */
421     EffortCostMap plannedEffortCostPrDay(QDate start, QDate end,  long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All) const override;
422     /**
423      * Returns a list of planned effort and cost for the @p resource
424      * for the interval @p start, @p end inclusive, useng schedule with identity @p id
425      */
426     EffortCostMap plannedEffortCostPrDay(const Resource *resource, QDate start, QDate end,  long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All) const override;
427 
428     /// Returns the total planned effort for @p resource on this task (or subtasks)
429     Duration plannedEffort(const Resource *resource, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All) const override;
430     /// Returns the total planned effort for this task (or subtasks)
431     Duration plannedEffort(long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All) const override;
432     /// Returns the total planned effort for this task (or subtasks) on date
433     Duration plannedEffort(QDate date, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All) const override;
434     /// Returns the total planned effort for @p resource on this task (or subtasks) on date
435     Duration plannedEffort(const Resource *resource, QDate date, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All) const override;
436     /// Returns the planned effort up to and including date
437     Duration plannedEffortTo(QDate date, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All) const override;
438     /// Returns the planned effort for @p resource up to and including date
439     Duration plannedEffortTo(const Resource *resource, QDate date, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All) const override;
440 
441     /// Returns the total actual effort for this task (or subtasks)
442     Duration actualEffort() const override;
443     /// Returns the total actual effort for this task (or subtasks) on date
444     Duration actualEffort(QDate date) const override;
445     /// Returns the actual effort up to and including date
446     Duration actualEffortTo(QDate date) const override;
447 
448     /**
449      * Returns the total planned cost for this task (or subtasks)
450      */
451     EffortCost plannedCost(long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All) const override;
452     /// Planned cost up to and including date
453     double plannedCostTo(QDate /*date*/, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All) const override;
454 
455     /// Returns actual effort and cost up to and including @p date
456     EffortCost actualCostTo(long int id, QDate date) const override;
457 
458     /**
459      * Returns a list of actual effort and cost for this task
460      * for the interval start, end inclusive
461      */
462     EffortCostMap actualEffortCostPrDay(QDate start, QDate end,  long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All) const override;
463     /// Returns the actual effort and cost pr day used by @p resource
464     EffortCostMap actualEffortCostPrDay(const Resource *resource, QDate start, QDate end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All) const override;
465 
466     /// Returns the effort planned to be used to reach the actual percent finished
467     Duration budgetedWorkPerformed(QDate date, long id = CURRENTSCHEDULE) const override;
468 
469     /// Returns the cost planned to be used to reach the actual percent finished
470     double budgetedCostPerformed(QDate date, long id = CURRENTSCHEDULE) const override;
471 
472     using Node::bcwsPrDay;
473     /// Return map of Budgeted Cost of Work Scheduled pr day
474     EffortCostMap bcwsPrDay(long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All) override;
475 
476     /// Budgeted Cost of Work Scheduled
477     double bcws(QDate date, long id = CURRENTSCHEDULE) const override;
478 
479     using Node::bcwpPrDay;
480     /// Return map of Budgeted Cost of Work Performed pr day (also includes bcwsPrDay)
481     EffortCostMap bcwpPrDay(long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All) override;
482     /// Budgeted Cost of Work Performed
483     double bcwp(long id = CURRENTSCHEDULE) const override;
484     /// Budgeted Cost of Work Performed (up to @p date)
485     double bcwp(QDate date, long id = CURRENTSCHEDULE) const override;
486 
487     using Node::acwp;
488     /// Map of Actual Cost of Work Performed
489     EffortCostMap acwp(long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All) override;
490     /// Actual Cost of Work Performed up to dat
491     EffortCost acwp(QDate date, long id = CURRENTSCHEDULE) const override;
492 
493     /// Effort based performance index
494     double effortPerformanceIndex(QDate date, long id = CURRENTSCHEDULE) const override;
495 
496     /// Schedule performance index
497     double schedulePerformanceIndex(QDate date, long id = CURRENTSCHEDULE) const override;
498     /// Cost performance index
499     double costPerformanceIndex(long int id, QDate date, bool *error=0) const override;
500 
501     /**
502      * Return the duration that an activity's start can be delayed
503      * without affecting the project completion date.
504      * An activity with positive float is not on the critical path.
505      * @param id Schedule identity. If id is CURRENTSCHEDULE, use current schedule.
506      */
507     Duration positiveFloat(long id = CURRENTSCHEDULE) const;
508     void setPositiveFloat(Duration fl, long id = CURRENTSCHEDULE) const;
509     /**
510      * Return the duration by which the duration of an activity or path
511      * has to be reduced in order to fulfill a timing- or dependency constraint.
512      * @param id Schedule identity. If id is CURRENTSCHEDULE, use current schedule.
513      */
514     Duration negativeFloat(long id = CURRENTSCHEDULE) const;
515     void setNegativeFloat(Duration fl, long id = CURRENTSCHEDULE) const;
516     /**
517      * Return the duration by which an activity can be delayed or extended
518      * without affecting the start of any succeeding activity.
519      * @param id Schedule identity. If id is CURRENTSCHEDULE, use current schedule.
520      */
521     Duration freeFloat(long id = CURRENTSCHEDULE) const;
522     void setFreeFloat(Duration fl, long id = CURRENTSCHEDULE) const;
523     /**
524      * Return the duration from Early Start to Late Start.
525      * @param id Schedule identity. If id is CURRENTSCHEDULE, use current schedule.
526      */
527     Duration startFloat(long id = CURRENTSCHEDULE) const;
528     /**
529      * Return the duration from Early Finish to Late Finish.
530      * @param id Schedule identity. If id is CURRENTSCHEDULE, use current schedule.
531      */
532     Duration finishFloat(long id = CURRENTSCHEDULE) const;
533 
534     /**
535      * A task is critical if positive float equals 0
536      * @param id Schedule identity. If id is CURRENTSCHEDULE, use current schedule.
537      */
538     bool isCritical(long id = CURRENTSCHEDULE) const override;
539 
540     /**
541      * Set current schedule to schedule with identity id, for me and my children.
542      * @param id Schedule identity
543      */
544     void setCurrentSchedule(long id) override;
545 
546     /**
547      * The assigned resources can not fulfill the estimated effort.
548      * @param id Schedule identity. If id is CURRENTSCHEDULE, use current schedule.
549      */
550     bool effortMetError(long id = CURRENTSCHEDULE) const override;
551 
552     /// @return true if this task has been started
553     bool isStarted() const;
554 
completion()555     Completion &completion() { return m_workPackage.completion(); }
completion()556     const Completion &completion() const { return m_workPackage.completion(); }
557 
workPackage()558     WorkPackage &workPackage() { return m_workPackage; }
workPackage()559     const WorkPackage &workPackage() const { return m_workPackage; }
560 
workPackageLogCount()561     int workPackageLogCount() const { return m_packageLog.count(); }
workPackageLog()562     QList<WorkPackage*> workPackageLog() const { return m_packageLog; }
563     void addWorkPackage(WorkPackage *wp);
564     void removeWorkPackage(WorkPackage *wp);
565     WorkPackage *workPackageAt(int index) const;
566 
567     QString wpOwnerName() const;
568     WorkPackage::WPTransmitionStatus wpTransmitionStatus() const;
569     DateTime wpTransmitionTime() const;
570 
571     /**
572      * Returns the state of the task
573      * @param id The identity of the schedule used when calculating the state
574      */
575     uint state(long id = CURRENTSCHEDULE) const override;
576 
577     /// Check if this node has any dependent child nodes
578     bool isEndNode() const override;
579     /// Check if this node has any dependent parent nodes
580     bool isStartNode() const override;
581 
parentProxyRelations()582     QList<Relation*> parentProxyRelations() const { return  m_parentProxyRelations; }
childProxyRelations()583     QList<Relation*> childProxyRelations() const { return  m_childProxyRelations; }
584 
585     /**
586      * Calculates and returns the duration of the node.
587      * Uses the correct expected-, optimistic- or pessimistic effort
588      * dependent on @p use.
589      * @param time Where to start calculation.
590      * @param use Calculate using expected-, optimistic- or pessimistic estimate.
591      * @param backward If true, time specifies when the task should end.
592      */
593     Duration duration(const DateTime &time, int use, bool backward) override;
594 
595     /**
596      * Return the duration calculated on bases of the estimates calendar
597      */
598     Duration length(const DateTime &time, Duration duration, bool backward);
599     Duration length(const DateTime &time, Duration uration, Schedule *sch, bool backward);
600 
601     /// Copy info from parent schedule
602     void copySchedule();
603     /// Copy intervals from parent schedule
604     void copyAppointments();
605     /// Copy intervals from parent schedule in the range @p start, @p end
606     /// All interval loads are scaled with @p factor
607     void copyAppointments(const DateTime &start, const DateTime &end = DateTime(), qreal factor = 1.0);
608 
609 Q_SIGNALS:
610     void workPackageToBeAdded(KPlato::Node *node, int row);
611     void workPackageAdded(KPlato::Node *node);
612     void workPackageToBeRemoved(KPlato::Node *node, int row);
613     void workPackageRemoved(KPlato::Node *node);
614 
615 public:
616     void initiateCalculation(MainSchedule &sch) override;
617     /**
618      * Sets up the lists used for calculation.
619      * This includes adding summarytasks relations to subtasks
620      * and lists for start- and endnodes.
621      */
622     void initiateCalculationLists(MainSchedule &sch) override;
623     /**
624      * Calculates early start and early finish, first for all predeccessors,
625      * then for this task.
626      * @param use Calculate using expected-, optimistic- or pessimistic estimate.
627      */
628     DateTime calculateForward(int use) override;
629     /**
630      * Calculates ref m_durationForward from ref earliestStart and
631      * returns the resulting end time (early finish),
632      * which will be used as the successors ref earliestStart.
633      *
634      * @param use Calculate using expected-, optimistic- or pessimistic estimate.
635      */
636     DateTime calculateEarlyFinish(int use) override;
637     /**
638      * Calculates late start and late finish, first for all successors,
639      * then for this task.
640      * @param use Calculate using expected-, optimistic- or pessimistic estimate.
641      */
642     DateTime calculateBackward(int use) override;
643     /**
644      * Calculates ref m_durationBackward from ref latestFinish and
645      * returns the resulting start time (late start),
646      * which will be used as the predecessors ref latestFinish.
647      *
648      * @param use Calculate using expected-, optimistic- or pessimistic estimate.
649      */
650     DateTime calculateLateStart(int use) override;
651     /**
652      * Schedules the task within the limits of earliestStart and latestFinish.
653      * Calculates ref m_startTime, ref m_endTime and ref m_duration,
654      * Assumes ref calculateForward() and ref calculateBackward() has been run.
655      *
656      * @param earliest The task is not scheduled to start earlier than this
657      * @param use Calculate using expected-, optimistic- or pessimistic estimate.
658      * @return The tasks endtime which can be used for scheduling the successor.
659      */
660     DateTime scheduleForward(const DateTime &earliest, int use) override;
661     /**
662      * Schedules the task within the limits of start time and latestFinish,
663      * Calculates end time and duration.
664      * Assumes ref calculateForward() and ref calculateBackward() has been run.
665      *
666      * @param use Calculate using expected-, optimistic- or pessimistic estimate.
667      * @return The tasks endtime which can be used for scheduling the successor.
668      */
669     DateTime scheduleFromStartTime(int use) override;
670     /**
671      * Schedules the task within the limits of earliestStart and latestFinish.
672      * Calculates ref m_startTime, ref m_endTime and ref m_duration,
673      * Assumes ref calculateForward() and ref calculateBackward() has been run.
674      *
675      * @param latest The task is not scheduled to end later than this
676      * @param use Calculate using expected-, optimistic- or pessimistic estimate.
677      * @return The tasks starttime which can be used for scheduling the predeccessor.
678      */
679     DateTime scheduleBackward(const DateTime &latest, int use) override;
680     /**
681      * Schedules the task within the limits of end time and latestFinish.
682      * Calculates endTime and duration.
683      * Assumes ref calculateForward() and ref calculateBackward() has been run.
684      *
685      * @param use Calculate using expected-, optimistic- or pessimistic estimate.
686      * @return The tasks starttime which can be used for scheduling the predeccessor.
687      */
688     DateTime scheduleFromEndTime(int use) override;
689 
690     /**
691      * Summarytasks (with milestones) need special treatment because
692      * milestones are always 'glued' to their predecessors.
693      */
694     void adjustSummarytask() override;
695 
696     /// Calculate the critical path
697     bool calcCriticalPath(bool fromEnd) override;
698     void calcFreeFloat() override;
699 
700     // Proxy relations are relations to/from summarytasks.
701     // These relations are distributed to the child tasks before calculation.
702     void clearProxyRelations() override;
703     void addParentProxyRelations(const QList<Relation*> &) override;
704     void addChildProxyRelations(const QList<Relation*> &) override;
705     void addParentProxyRelation(Node *, const Relation *) override;
706     void addChildProxyRelation(Node *, const Relation *) override;
707 
708 public:
709     DateTime earlyStartDate();
710     void setEarlyStartDate(DateTime value);
711 
712     DateTime earlyFinishDate();
713     void setEarlyFinishDate(DateTime value);
714 
715     DateTime lateStartDate();
716     void setLateStartDate(DateTime value);
717 
718     DateTime lateFinishDate();
719     void setLateFinishDate(DateTime value);
720 
721     int activitySlack();
722     void setActivitySlack(int value);
723 
724     int activityFreeMargin();
725     void setActivityFreeMargin(int value);
726 
727 protected:
728     /**
729      * Return the duration calculated on bases of the requested resources
730      */
731     Duration calcDuration(const DateTime &time, Duration effort, bool backward);
732 
733 private:
734     DateTime calculateSuccessors(const QList<Relation*> &list, int use);
735     DateTime calculatePredeccessors(const QList<Relation*> &list, int use);
736     DateTime scheduleSuccessors(const QList<Relation*> &list, int use);
737     DateTime schedulePredeccessors(const QList<Relation*> &list, int use);
738 
739     /// Fixed duration: Returns @p dt
740     /// Duration with calendar: Returns first available after @p dt
741     /// Has working resource(s) allocated: Returns the earliest time a resource can start work after @p dt, and checks appointments if @p sch is not null.
742     DateTime workTimeAfter(const DateTime &dt, Schedule *sch = 0) const;
743     /// Fixed duration: Returns @p dt
744     /// Duration with calendar: Returns first available before @p dt
745     /// Has working resource(s) allocated: Returns the latest time a resource can finish work, and checks appointments if @p sch is not null.
746     DateTime workTimeBefore(const DateTime &dt, Schedule *sch = 0) const;
747 
748 private:
749     QList<ResourceGroup*> m_resource;
750 
751     QList<Relation*> m_parentProxyRelations;
752     QList<Relation*> m_childProxyRelations;
753 
754     // This list store pointers to linked task
755     QList<Node*> m_requiredTasks;
756 
757     WorkPackage m_workPackage;
758     QList<WorkPackage*> m_packageLog;
759 
760     bool m_calculateForwardRun;
761     bool m_calculateBackwardRun;
762     bool m_scheduleForwardRun;
763     bool m_scheduleBackwardRun;
764 };
765 
766 }  //KPlato namespace
767 
768 Q_DECLARE_METATYPE(KPlato::Completion::UsedEffort::ActualEffort)
769 
770 #ifndef QT_NO_DEBUG_STREAM
771 PLANKERNEL_EXPORT QDebug operator<<(QDebug dbg, const KPlato::Completion::UsedEffort::ActualEffort &ae);
772 #endif
773 
774 #endif
775