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