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