00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kptnode.h"
00021
00022 #include "kptappointment.h"
00023 #include "kptaccount.h"
00024 #include "kptwbsdefinition.h"
00025 #include "kptresource.h"
00026 #include "kptschedule.h"
00027
00028 #include <QList>
00029 #include <QListIterator>
00030 #include <qdom.h>
00031
00032 #include <klocale.h>
00033 #include <kdebug.h>
00034
00035 namespace KPlato
00036 {
00037
00038 Node::Node(Node *parent) : m_nodes(), m_dependChildNodes(), m_dependParentNodes() {
00039
00040 m_parent = parent;
00041 init();
00042 m_id = QString();
00043 }
00044
00045 Node::Node(Node &node, Node *parent)
00046 : QObject( parent),
00047 m_nodes(),
00048 m_dependChildNodes(),
00049 m_dependParentNodes() {
00050
00051 m_parent = parent;
00052 init();
00053 m_name = node.name();
00054 m_leader = node.leader();
00055 m_description = node.description();
00056 m_constraint = (ConstraintType) node.constraint();
00057 m_constraintStartTime = node.constraintStartTime();
00058 m_constraintEndTime = node.constraintEndTime();
00059
00060 m_dateOnlyStartDate = node.startDate();
00061 m_dateOnlyEndDate = node.endDate();
00062
00063 m_runningAccount = node.runningAccount();
00064 m_startupAccount = node.startupAccount();
00065 m_shutdownAccount = node.shutdownAccount();
00066
00067 m_startupCost = node.startupCost();
00068 m_shutdownCost = node.shutdownCost();
00069
00070 }
00071
00072 Node::~Node() {
00073
00074 while (!m_nodes.isEmpty())
00075 delete m_nodes.takeFirst();
00076
00077 if (findNode() == this) {
00078 removeId();
00079 }
00080 Relation *rel = 0;
00081 while (!m_dependParentNodes.isEmpty()) {
00082 delete m_dependParentNodes.takeFirst();
00083 }
00084 while (!m_dependChildNodes.isEmpty()) {
00085 delete m_dependChildNodes.takeFirst();
00086 }
00087 if (m_runningAccount)
00088 m_runningAccount->removeRunning(*this);
00089 if (m_startupAccount)
00090 m_startupAccount->removeStartup(*this);
00091 if (m_shutdownAccount)
00092 m_shutdownAccount->removeShutdown(*this);
00093
00094 foreach (long key, m_schedules.keys()) {
00095 delete m_schedules.take(key);
00096 }
00097 m_parent = 0;
00098 }
00099
00100 void Node::init() {
00101 m_currentSchedule = 0;
00102 m_name="";
00103 m_constraint = Node::ASAP;
00104 m_effort = 0;
00105 m_visitedForward = false;
00106 m_visitedBackward = false;
00107
00108 m_dateOnlyStartDate = m_dateOnlyEndDate = QDate::currentDate();
00109 m_dateOnlyDuration.addDays(1);
00110
00111 m_runningAccount = 0;
00112 m_startupAccount = 0;
00113 m_shutdownAccount = 0;
00114 m_startupCost = 0.0;
00115 m_shutdownCost = 0.0;
00116 }
00117
00118 QString Node::typeToString( bool trans ) const {
00119 switch ( type() ) {
00120 case Type_Node: return trans ? i18n("Node") : "Node";
00121 case Type_Project: return trans ? i18n("") : "Project";
00122 case Type_Subproject: return trans ? i18n("Sub-Project") : "Sub-Project";
00123 case Type_Task: return trans ? i18n("Task") : "Task";
00124 case Type_Milestone: return trans ? i18n("Milestone") : "Milestone";
00125 case Type_Periodic: return trans ? i18n("Periodic") : "Periodic";
00126 case Type_Summarytask: return trans ? i18n("Summary") : "Summary-Task";
00127 }
00128 return QString();
00129 }
00130
00131 void Node::setName(const QString &n)
00132 {
00133 m_name = n;
00134 changed(this);
00135 }
00136
00137 void Node::setLeader(const QString &l)
00138 {
00139 m_leader = l;
00140 changed(this);
00141 }
00142
00143 void Node::setDescription(const QString &d)
00144 {
00145 m_description = d;
00146 changed(this);
00147 }
00148
00149 Node *Node::projectNode() {
00150 if ((type() == Type_Project) || (type() == Type_Subproject)) {
00151 return this;
00152 }
00153 if (m_parent)
00154 return m_parent->projectNode();
00155
00156 kError()<<k_funcinfo<<"Ooops, no parent and no project found"<<endl;
00157 return 0;
00158 }
00159
00160 void Node::takeChildNode( Node *node) {
00161
00162 int i = m_nodes.indexOf(node);
00163 if ( i != -1 ) {
00164 m_nodes.removeAt(i);
00165 }
00166 node->setParent(0);
00167 }
00168
00169 void Node::takeChildNode( int number ) {
00170 if (number >= 0 && number < m_nodes.size()) {
00171 Node *n = m_nodes.takeAt(number);
00172
00173 if (n) {
00174 n->setParent(0);
00175 }
00176 }
00177 }
00178
00179 void Node::insertChildNode( unsigned int index, Node *node) {
00180 if (index == -1)
00181 m_nodes.append(node);
00182 else
00183 m_nodes.insert(index,node);
00184 node->setParent(this);
00185 }
00186
00187 void Node::addChildNode( Node *node, Node *after) {
00188 int index = m_nodes.indexOf(after);
00189 if (index == -1) {
00190 m_nodes.append(node);
00191 node->setParent(this);
00192 return;
00193 }
00194 m_nodes.insert(index+1, node);
00195 node->setParent(this);
00196 }
00197
00198 int Node::findChildNode( Node* node )
00199 {
00200 return m_nodes.indexOf( node );
00201 }
00202
00203 bool Node::isChildOf( Node* node )
00204 {
00205 if ( node == 0 || m_parent == 0 ) {
00206 return false;
00207 }
00208 if ( node == m_parent ) {
00209 return true;
00210 }
00211 return m_parent->isChildOf( node );
00212 }
00213
00214
00215 const Node* Node::childNode(int number) const {
00216 return m_nodes.at(number);
00217 }
00218
00219 Duration *Node::getDelay() {
00220
00221
00222
00223 return 0L;
00224 }
00225
00226 void Node::addDependChildNode( Node *node, Relation::Type p) {
00227 addDependChildNode(node,p,Duration());
00228 }
00229
00230 void Node::addDependChildNode( Node *node, Relation::Type p, Duration lag) {
00231 Relation *relation = new Relation(this, node, p, lag);
00232 if (node->addDependParentNode(relation))
00233 m_dependChildNodes.append(relation);
00234 else
00235 delete relation;
00236 }
00237
00238 void Node::insertDependChildNode( unsigned int index, Node *node, Relation::Type p) {
00239 Relation *relation = new Relation(this, node, p, Duration());
00240 if (node->addDependParentNode(relation))
00241 m_dependChildNodes.insert(index, relation);
00242 else
00243 delete relation;
00244 }
00245
00246 bool Node::addDependChildNode( Relation *relation) {
00247 if(m_dependChildNodes.indexOf(relation) != -1)
00248 return false;
00249 m_dependChildNodes.append(relation);
00250 return true;
00251 }
00252
00253 void Node::takeDependChildNode( Relation *rel ) {
00254 int i = m_dependChildNodes.indexOf(rel);
00255 if ( i != -1 ) {
00256
00257 m_dependChildNodes.removeAt(i);
00258 }
00259 }
00260
00261 void Node::addDependParentNode( Node *node, Relation::Type p) {
00262 addDependParentNode(node,p,Duration());
00263 }
00264
00265 void Node::addDependParentNode( Node *node, Relation::Type p, Duration lag) {
00266 Relation *relation = new Relation(node, this, p, lag);
00267 if (node->addDependChildNode(relation))
00268 m_dependParentNodes.append(relation);
00269 else
00270 delete relation;
00271 }
00272
00273 void Node::insertDependParentNode( unsigned int index, Node *node, Relation::Type p) {
00274 Relation *relation = new Relation(this, node, p, Duration());
00275 if (node->addDependChildNode(relation))
00276 m_dependParentNodes.insert(index,relation);
00277 else
00278 delete relation;
00279 }
00280
00281 bool Node::addDependParentNode( Relation *relation) {
00282 if(m_dependParentNodes.indexOf(relation) != -1)
00283 return false;
00284 m_dependParentNodes.append(relation);
00285 return true;
00286 }
00287
00288 void Node::takeDependParentNode( Relation *rel ) {
00289 int i = m_dependParentNodes.indexOf(rel);
00290 if ( i != -1 ) {
00291
00292 m_dependParentNodes.removeAt(i);
00293 }
00294 }
00295
00296 bool Node::isParentOf(Node *node) {
00297 if (m_nodes.indexOf(node) != -1)
00298 return true;
00299
00300 QListIterator<Node*> nit(childNodeIterator());
00301 while (nit.hasNext()) {
00302 if (nit.next()->isParentOf(node))
00303 return true;
00304 }
00305 return false;
00306 }
00307
00308 Relation *Node::findParentRelation(Node *node) {
00309 for (int i=0; i<numDependParentNodes(); i++) {
00310 Relation *rel = getDependParentNode(i);
00311 if (rel->parent() == node)
00312 return rel;
00313 }
00314 return (Relation *)0;
00315 }
00316
00317 Relation *Node::findChildRelation(Node *node) {
00318 for (int i=0; i<numDependChildNodes(); i++) {
00319 Relation *rel = getDependChildNode(i);
00320 if (rel->child() == node)
00321 return rel;
00322 }
00323 return (Relation *)0;
00324 }
00325
00326 Relation *Node::findRelation(Node *node) {
00327 Relation *rel = findParentRelation(node);
00328 if (!rel)
00329 rel = findChildRelation(node);
00330 return rel;
00331 }
00332
00333 bool Node::isDependChildOf(Node *node) {
00334
00335 for (int i=0; i<numDependParentNodes(); i++) {
00336 Relation *rel = getDependParentNode(i);
00337 if (rel->parent() == node)
00338 return true;
00339 if (rel->parent()->isDependChildOf(node))
00340 return true;
00341 }
00342 return false;
00343 }
00344
00345 Duration Node::duration(const DateTime &time, int use, bool backward) {
00346
00347
00348 if (!time.isValid()) {
00349 kError()<<k_funcinfo<<"Time is invalid"<<endl;
00350 return Duration::zeroDuration;
00351 }
00352 if (m_effort == 0) {
00353 kError()<<k_funcinfo<<"m_effort == 0"<<endl;
00354 return Duration::zeroDuration;
00355 }
00356 if (m_currentSchedule == 0) {
00357 return Duration::zeroDuration;
00358 kError()<<k_funcinfo<<"No current schedule"<<endl;
00359 }
00360 kDebug()<<k_funcinfo<<m_name<<": Use="<<use<<endl;
00361 return calcDuration(time, m_effort->effort(use), backward);
00362 }
00363
00364 void Node::makeAppointments() {
00365 QListIterator<Node*> nit(m_nodes);
00366 while (nit.hasNext()) {
00367 nit.next()->makeAppointments();
00368 }
00369 }
00370
00371 void Node::calcResourceOverbooked() {
00372 QListIterator<Node*> nit(m_nodes);
00373 while (nit.hasNext()) {
00374 nit.next()->calcResourceOverbooked();
00375 }
00376 }
00377
00378 QStringList Node::overbookedResources() const {
00379 return m_currentSchedule ? m_currentSchedule->overbookedResources() : QStringList();
00380 }
00381
00382 void Node::saveRelations(QDomElement &element) const {
00383 QListIterator<Relation*> it(m_dependChildNodes);
00384 while (it.hasNext()) {
00385 it.next()->save(element);
00386 }
00387 QListIterator<Node*> nodes(m_nodes);
00388 while (nodes.hasNext()) {
00389 nodes.next()->saveRelations(element);
00390 }
00391 }
00392
00393 void Node::setConstraint(Node::ConstraintType type)
00394 {
00395 m_constraint = type;
00396 changed( this );
00397 }
00398
00399 void Node::setConstraint(QString &type) {
00400
00401 if (type == "ASAP")
00402 setConstraint(ASAP);
00403 else if (type == "ALAP")
00404 setConstraint(ALAP);
00405 else if (type == "StartNotEarlier")
00406 setConstraint(StartNotEarlier);
00407 else if (type == "FinishNotLater")
00408 setConstraint(FinishNotLater);
00409 else if (type == "MustStartOn")
00410 setConstraint(MustStartOn);
00411 else if (type == "MustFinishOn")
00412 setConstraint(MustFinishOn);
00413 else if (type == "FixedInterval")
00414 setConstraint(FixedInterval);
00415 else
00416 setConstraint(ASAP);
00417 }
00418
00419 QString Node::constraintToString( bool trans ) const {
00420 return constraintList( trans ).at( m_constraint );
00421 }
00422
00423 QStringList Node::constraintList( bool trans ) {
00424
00425 return QStringList()
00426 << (trans ? i18n("As Soon As Possible") : QString("ASAP"))
00427 << (trans ? i18n("As Late As Possible") : QString("ALAP"))
00428 << (trans ? i18n("Start Not Earlier") : QString("StartNotEarlier"))
00429 << (trans ? i18n("Finish Not Later") : QString("FinishNotLater"))
00430 << (trans ? i18n("Must Start On") : QString("MustStartOn"))
00431 << (trans ? i18n("Must Finish On") : QString("MustFinishOn"))
00432 << (trans ? i18n("Fixed Interval") : QString("FixedInterval"));
00433 }
00434
00435 void Node::propagateEarliestStart(DateTime &time) {
00436 if (m_currentSchedule == 0)
00437 return;
00438 m_currentSchedule->earliestStart = time;
00439
00440 QListIterator<Node*> it = m_nodes;
00441 while (it.hasNext()) {
00442 it.next()->propagateEarliestStart(time);
00443 }
00444 }
00445
00446 void Node::propagateLatestFinish(DateTime &time) {
00447 if (m_currentSchedule == 0)
00448 return;
00449 m_currentSchedule->latestFinish = time;
00450
00451 QListIterator<Node*> it = m_nodes;
00452 while (it.hasNext()) {
00453 it.next()->propagateLatestFinish(time);
00454 }
00455 }
00456
00457 void Node::moveEarliestStart(DateTime &time) {
00458 if (m_currentSchedule == 0)
00459 return;
00460 if (m_currentSchedule->earliestStart < time)
00461 m_currentSchedule->earliestStart = time;
00462 QListIterator<Node*> it = m_nodes;
00463 while (it.hasNext()) {
00464 it.next()->moveEarliestStart(time);
00465 }
00466 }
00467
00468 void Node::moveLatestFinish(DateTime &time) {
00469 if (m_currentSchedule == 0)
00470 return;
00471 if (m_currentSchedule->latestFinish > time)
00472 m_currentSchedule->latestFinish = time;
00473 QListIterator<Node*> it = m_nodes;
00474 while (it.hasNext()) {
00475 it.next()->moveLatestFinish(time);
00476 }
00477 }
00478
00479 void Node::initiateCalculation(Schedule &sch) {
00480 QListIterator<Node*> it = m_nodes;
00481 while (it.hasNext()) {
00482 it.next()->initiateCalculation(sch);
00483 }
00484 }
00485
00486 void Node::resetVisited() {
00487 m_visitedForward = false;
00488 m_visitedBackward = false;
00489 QListIterator<Node*> it = m_nodes;
00490 while (it.hasNext()) {
00491 it.next()->resetVisited();
00492 }
00493 }
00494
00495 Node *Node::siblingBefore() {
00496
00497 if (getParent())
00498 return getParent()->childBefore(this);
00499 return 0;
00500 }
00501
00502 Node *Node::childBefore(Node *node) {
00503
00504 int index = m_nodes.indexOf(node);
00505 if (index > 0){
00506 return m_nodes.at(index-1);
00507 }
00508 return 0;
00509 }
00510
00511 Node *Node::siblingAfter() {
00512
00513 if (getParent())
00514 return getParent()->childAfter(this);
00515 return 0;
00516 }
00517
00518 Node *Node::childAfter(Node *node)
00519 {
00520
00521 uint index = m_nodes.indexOf(node);
00522 if (index < m_nodes.count()-1) {
00523 return m_nodes.at(index+1); }
00524 return 0;
00525 }
00526
00527 bool Node::moveChildUp(Node* node)
00528 {
00529 if (findChildNode(node) == -1)
00530 return false;
00531 Node *sib = node->siblingBefore();
00532 if (!sib)
00533 return false;
00534 sib = sib->siblingBefore();
00535 takeChildNode(node);
00536 if (sib) {
00537 addChildNode(node, sib);
00538 } else {
00539 insertChildNode(0, node);
00540 }
00541 return true;
00542 }
00543
00544 bool Node::moveChildDown(Node* node)
00545 {
00546 if (findChildNode(node) == -1)
00547 return false;
00548 Node *sib = node->siblingAfter();
00549 if (!sib)
00550 return false;
00551 takeChildNode(node);
00552 addChildNode(node, sib);
00553 return true;
00554 }
00555
00556 bool Node::legalToLink(Node *node) {
00557 Node *p = projectNode();
00558 if (p)
00559 return p->legalToLink(this, node);
00560 return false;
00561 }
00562
00563 bool Node::isEndNode() const {
00564 return m_dependChildNodes.isEmpty();
00565 }
00566 bool Node::isStartNode() const {
00567 return m_dependParentNodes.isEmpty();
00568 }
00569
00570 bool Node::setId(QString id) {
00571
00572 if (id.isEmpty()) {
00573 kError()<<k_funcinfo<<"id is empty"<<endl;
00574 m_id = id;
00575 return false;
00576 }
00577 if (!m_id.isEmpty()) {
00578 Node *n = findNode();
00579 if (n == this) {
00580
00581 removeId();
00582 } else if (n) {
00583
00584 kError()<<k_funcinfo<<"My id '"<<m_id<<"' already used for different node: "<<n->name()<<endl;
00585 }
00586 }
00587 if (findNode(id)) {
00588 kError()<<k_funcinfo<<"id '"<<id<<"' is already used for different node: "<<findNode(id)->name()<<endl;
00589 m_id = QString();
00590 return false;
00591 }
00592 m_id = id;
00593 insertId(id);
00594
00595 return true;
00596 }
00597
00598 void Node::setStartTime(DateTime startTime) {
00599 if (m_currentSchedule)
00600 m_currentSchedule->startTime = startTime;
00601 m_dateOnlyStartDate = startTime.date();
00602 }
00603
00604 void Node::setEndTime(DateTime endTime) {
00605 if (m_currentSchedule)
00606 m_currentSchedule->endTime = endTime;
00607
00608 m_dateOnlyEndDate = endTime.date();
00609 if (endTime.time().isNull() && m_dateOnlyEndDate > m_dateOnlyStartDate)
00610 m_dateOnlyEndDate = m_dateOnlyEndDate.addDays(-1);
00611 }
00612
00613 void Node::saveAppointments(QDomElement &element, long id) const {
00614
00615 QListIterator<Node*> it(m_nodes);
00616 while (it.hasNext()) {
00617 it.next()->saveAppointments(element, id);
00618 }
00619 }
00620
00621 QList<Appointment*> Node::appointments() {
00622 QList<Appointment*> lst;
00623 if (m_currentSchedule)
00624 lst = m_currentSchedule->appointments();
00625 return lst;
00626 }
00627
00628
00629
00630
00631
00632
00633 bool Node::addAppointment(Appointment *appointment) {
00634 if (m_currentSchedule)
00635 return m_currentSchedule->add(appointment);
00636 return false;
00637 }
00638
00639 bool Node::addAppointment(Appointment *appointment, Schedule &main) {
00640
00641 Schedule *s = findSchedule(main.id());
00642 if (s == 0) {
00643 s = createSchedule(&main);
00644 }
00645 appointment->setNode(s);
00646 return s->add(appointment);
00647 }
00648
00649 void Node::addAppointment(ResourceSchedule *resource, DateTime &start, DateTime &end, double load) {
00650 Schedule *node = findSchedule(resource->id());
00651 if (node == 0) {
00652 node = createSchedule(resource->parent());
00653 }
00654 node->addAppointment(resource, start, end, load);
00655 }
00656
00657 void Node::takeSchedule(const Schedule *schedule) {
00658 if (schedule == 0)
00659 return;
00660 if (m_currentSchedule == schedule)
00661 m_currentSchedule = 0;
00662 m_schedules.take(schedule->id());
00663 }
00664
00665 void Node::addSchedule(Schedule *schedule) {
00666 if (schedule == 0)
00667 return;
00668 m_schedules.insert(schedule->id(), schedule);
00669 }
00670
00671 Schedule *Node::createSchedule(QString name, Schedule::Type type, long id) {
00672
00673 NodeSchedule *sch = new NodeSchedule(this, name, type, id);
00674 addSchedule(sch);
00675 return sch;
00676 }
00677
00678 Schedule *Node::createSchedule(Schedule *parent) {
00679
00680 NodeSchedule *sch = new NodeSchedule(parent, this);
00681 addSchedule(sch);
00682 return sch;
00683 }
00684
00685 Schedule *Node::findSchedule(const QString name, const Schedule::Type type) {
00686 QHash<long, Schedule*> it;
00687 foreach (Schedule *sch, it) {
00688 if (!sch->isDeleted() &&
00689 sch->name() == name && sch->type() == type)
00690 return sch;
00691 }
00692 return 0;
00693 }
00694
00695 Schedule *Node::findSchedule(const Schedule::Type type) {
00696
00697 QHash<long, Schedule*> hash;
00698 foreach (Schedule *sch, hash) {
00699 if (!sch->isDeleted() && sch->type() == type) {
00700 return sch;
00701 }
00702 }
00703 return 0;
00704 }
00705
00706 void Node::setScheduleDeleted(long id, bool on) {
00707 Schedule *ns = findSchedule(id);
00708 if (ns == 0) {
00709 kError()<<k_funcinfo<<m_name<<" Could not find schedule with id="<<id<<endl;
00710 } else {
00711 ns->setDeleted(on);
00712 }
00713 }
00714
00715 void Node::setParentSchedule(Schedule *sch) {
00716 Schedule *s = findSchedule(sch->id());
00717 if (s) {
00718 s->setParent(sch);
00719 }
00720 QListIterator<Node*> it = m_nodes;
00721 while (it.hasNext()) {
00722 it.next()->setParentSchedule(sch);
00723 }
00724 }
00725
00726 bool Node::calcCriticalPath(bool fromEnd) {
00727 if (m_currentSchedule == 0)
00728 return false;
00729
00730 if (!isCritical()) {
00731 return false;
00732 }
00733 if (!fromEnd && isStartNode()) {
00734 m_currentSchedule->inCriticalPath = true;
00735 return true;
00736 }
00737 if (fromEnd && isEndNode()) {
00738 m_currentSchedule->inCriticalPath = true;
00739 return true;
00740 }
00741 QListIterator<Relation*> pit(m_dependParentNodes);
00742 while (pit.hasNext()) {
00743 if (pit.next()->parent()->calcCriticalPath(fromEnd)) {
00744 m_currentSchedule->inCriticalPath = true;
00745 }
00746 }
00747 return m_currentSchedule->inCriticalPath;
00748 }
00749
00750 int Node::level() {
00751 Node *n = getParent();
00752 return n ? n->level() + 1 : 0;
00753 }
00754
00755 void Node::generateWBS(int count, WBSDefinition &def, QString wbs) {
00756 m_wbs = wbs + def.code(count, level());
00757
00758 QString w = wbs + def.wbs(count, level());
00759 QListIterator<Node*> it = m_nodes;
00760 int i=0;
00761 while (it.hasNext()) {
00762 it.next()->generateWBS(++i, def, w);
00763 }
00764
00765 }
00766
00767 void Node::setCurrentSchedule(long id) {
00768 QListIterator<Node*> it = m_nodes;
00769 while (it.hasNext()) {
00770 it.next()->setCurrentSchedule(id);
00771 }
00772
00773 }
00774
00775 void Node::changed(Node *node) {
00776 if (m_parent)
00777 m_parent->changed(this);
00778 }
00779
00780
00782
00783 Effort::Effort( Duration e, Duration p, Duration o) {
00784 m_expectedEffort = e;
00785 m_pessimisticEffort = p;
00786 m_optimisticEffort = o;
00787 m_type = Type_Effort;
00788 m_risktype = Risk_None;
00789 }
00790
00791 Effort::Effort(const Effort &effort) {
00792 set(effort.expected(), effort.pessimistic(), effort.optimistic());
00793 setType(effort.type());
00794 setRisktype(effort.risktype());
00795 }
00796
00797 Effort::~Effort() {
00798 }
00799
00800 const Effort Effort::zeroEffort( Duration::zeroDuration,
00801 Duration::zeroDuration,
00802 Duration::zeroDuration );
00803
00804 void Effort::set( Duration e, Duration p, Duration o ) {
00805 m_expectedEffort = e;
00806 m_pessimisticEffort = (p == Duration::zeroDuration) ? e : p;
00807 m_optimisticEffort = (o == Duration::zeroDuration) ? e : o;
00808
00809 }
00810
00811 void Effort::set( int e, int p, int o ) {
00812 m_expectedEffort = Duration(e);
00813 m_pessimisticEffort = (p < 0) ? Duration(e) : Duration(p);
00814 m_optimisticEffort = (o < 0) ? Duration(e) : Duration(o);
00815
00816
00817
00818
00819
00820 }
00821
00822
00823 void Effort::set(unsigned days, unsigned hours, unsigned minutes) {
00824 Duration dur(days, hours, minutes);
00825 set(dur);
00826
00827 }
00828
00829 void Effort::expectedEffort(unsigned *days, unsigned *hours, unsigned *minutes) {
00830 m_expectedEffort.get(days, hours, minutes);
00831 }
00832
00833 Duration Effort::variance() const {
00834 return (m_pessimisticEffort - m_optimisticEffort)/6;
00835 }
00836 Duration Effort::pertExpected() const {
00837 if (m_risktype == Risk_Low) {
00838 return (m_optimisticEffort + m_pessimisticEffort + (m_expectedEffort*4))/6;
00839 } else if (m_risktype == Risk_High) {
00840 return (m_optimisticEffort + (m_pessimisticEffort*2) + (m_expectedEffort*4))/7;
00841 }
00842 return m_expectedEffort;
00843 }
00844 Duration Effort::pertOptimistic() const {
00845 if (m_risktype != Risk_None) {
00846 return pertExpected() - variance();
00847 }
00848 return m_optimisticEffort;
00849 }
00850 Duration Effort::pertPessimistic() const {
00851 if (m_risktype != Risk_None) {
00852 return pertExpected() + variance();
00853 }
00854 return m_pessimisticEffort;
00855 }
00856
00857 Duration Effort::effort(int use) const {
00858 if (use == Effort::Use_Expected) {
00859 return pertExpected();
00860 } else if (use == Effort::Use_Optimistic) {
00861 return pertOptimistic();
00862 } else if (use == Effort::Use_Pessimistic)
00863 return pertPessimistic();
00864
00865 return m_expectedEffort;
00866 }
00867
00868 bool Effort::load(QDomElement &element) {
00869 m_expectedEffort = Duration::fromString(element.attribute("expected"));
00870 m_optimisticEffort = Duration::fromString(element.attribute("optimistic"));
00871 m_pessimisticEffort = Duration::fromString(element.attribute("pessimistic"));
00872 setType(element.attribute("type", "WorkBased"));
00873 setRisktype(element.attribute("risk"));
00874 return true;
00875 }
00876
00877 void Effort::save(QDomElement &element) const {
00878 QDomElement me = element.ownerDocument().createElement("effort");
00879 element.appendChild(me);
00880 me.setAttribute("expected", m_expectedEffort.toString());
00881 me.setAttribute("optimistic", m_optimisticEffort.toString());
00882 me.setAttribute("pessimistic", m_pessimisticEffort.toString());
00883 me.setAttribute("type", typeToString());
00884 me.setAttribute("risk", risktypeToString());
00885 }
00886
00887 QString Effort::typeToString( bool trans ) const {
00888 return typeToStringList( trans ).at( m_type );
00889 }
00890
00891 QStringList Effort::typeToStringList( bool trans ) {
00892 return QStringList()
00893 << (trans ? i18n("Effort") : QString("Effort"))
00894 << (trans ? i18n("FixedDuration") : QString("FixedDuration"));
00895 }
00896
00897 void Effort::setType(QString type) {
00898 if (type == "Effort")
00899 setType(Type_Effort);
00900 else if (type == "FixedDuration")
00901 setType(Type_FixedDuration);
00902 else if (type == "Type_FixedDuration")
00903 setType(Type_FixedDuration);
00904 else
00905 setType(Type_Effort);
00906 }
00907
00908 QString Effort::risktypeToString( bool trans ) const {
00909 return risktypeToStringList( trans ).at( m_risktype );
00910 }
00911
00912 QStringList Effort::risktypeToStringList( bool trans ) {
00913 return QStringList()
00914 << (trans ? i18n("None") : QString("None"))
00915 << (trans ? i18n("Low") : QString("Low"))
00916 << (trans ? i18n("High") : QString("High"));
00917 }
00918
00919 void Effort::setRisktype(QString type) {
00920 if (type == "High")
00921 setRisktype(Risk_High);
00922 else if (type == "Low")
00923 setRisktype(Risk_Low);
00924 else
00925 setRisktype(Risk_None);
00926 }
00927
00928 void Effort::setOptimisticRatio(int percent)
00929 {
00930 int p = percent>0 ? -percent : percent;
00931 m_optimisticEffort = m_expectedEffort*(100+p)/100;
00932 }
00933
00934 int Effort::optimisticRatio() const {
00935 if (m_expectedEffort == Duration::zeroDuration)
00936 return 0;
00937 return (m_optimisticEffort.milliseconds()*100/m_expectedEffort.milliseconds())-100;
00938 }
00939
00940 void Effort::setPessimisticRatio(int percent)
00941 {
00942 int p = percent<0 ? -percent : percent;
00943 m_pessimisticEffort = m_expectedEffort*(100+p)/100;
00944 }
00945 int Effort::pessimisticRatio() const {
00946 if (m_expectedEffort == Duration::zeroDuration)
00947 return 0;
00948 return m_pessimisticEffort.milliseconds()*100/m_expectedEffort.milliseconds()-100;
00949 }
00950
00951
00952 #ifndef NDEBUG
00953 void Node::printDebug(bool children, QByteArray indent) {
00954 kDebug()<<indent<<" Unique node identity="<<m_id<<endl;
00955 if (m_effort) m_effort->printDebug(indent);
00956 QString s = " Constraint: " + constraintToString();
00957 if (m_constraint == MustStartOn || m_constraint == StartNotEarlier || m_constraint == FixedInterval)
00958 kDebug()<<indent<<s<<" ("<<constraintStartTime().toString()<<")"<<endl;
00959 if (m_constraint == MustFinishOn || m_constraint == FinishNotLater || m_constraint == FixedInterval)
00960 kDebug()<<indent<<s<<" ("<<constraintEndTime().toString()<<")"<<endl;
00961 Schedule *cs = m_currentSchedule;
00962 if (cs) {
00963 kDebug()<<indent<<" Current schedule: "<<"id="<<cs->id()<<" '"<<cs->name()<<"' type: "<<cs->type()<<endl;
00964 } else {
00965 kDebug()<<indent<<" Current schedule: None"<<endl;
00966 }
00967 QHash<long, Schedule*> hash;
00968 foreach (Schedule *sch, hash) {
00969 sch->printDebug(indent+" ");
00970 }
00971 kDebug()<<indent<<" Parent: "<<(m_parent ? m_parent->name() : QString("None"))<<endl;
00972 kDebug()<<indent<<" Level: "<<level()<<endl;
00973 kDebug()<<indent<<" No of predecessors: "<<m_dependParentNodes.count()<<endl;
00974 QListIterator<Relation*> pit(m_dependParentNodes);
00975
00976 while (pit.hasNext()) {
00977 pit.next()->printDebug(indent);
00978 }
00979 kDebug()<<indent<<" No of successors: "<<m_dependChildNodes.count()<<endl;
00980 QListIterator<Relation*> cit(m_dependChildNodes);
00981
00982 while (cit.hasNext()) {
00983 cit.next()->printDebug(indent);
00984 }
00985
00986
00987 indent += " ";
00988 if (children) {
00989 QListIterator<Node*> it(m_nodes);
00990 while (it.hasNext()) {
00991 it.next()->printDebug(true,indent);
00992 }
00993 }
00994
00995 }
00996 #endif
00997
00998
00999 #ifndef NDEBUG
01000 void Effort::printDebug(QByteArray indent) {
01001 kDebug()<<indent<<" Effort:"<<endl;
01002 indent += " ";
01003 kDebug()<<indent<<" Expected: "<<m_expectedEffort.toString()<<endl;
01004 kDebug()<<indent<<" Optimistic: "<<m_optimisticEffort.toString()<<endl;
01005 kDebug()<<indent<<" Pessimistic: "<<m_pessimisticEffort.toString()<<endl;
01006
01007 kDebug()<<indent<<" Risk: "<<risktypeToString()<<endl;
01008 kDebug()<<indent<<" Pert expected: "<<pertExpected().toString()<<endl;
01009 kDebug()<<indent<<" Pert optimistic: "<<pertOptimistic().toString()<<endl;
01010 kDebug()<<indent<<" Pert pessimistic: "<<pertPessimistic().toString()<<endl;
01011 kDebug()<<indent<<" Pert variance: "<<variance().toString()<<endl;
01012 }
01013 #endif
01014
01015 }
01016
01017 #include "kptnode.moc"