00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kpttask.h"
00022 #include "kptproject.h"
00023 #include "kpttaskdialog.h"
00024 #include "kptduration.h"
00025 #include "kptrelation.h"
00026 #include "kptdatetime.h"
00027 #include "kptcalendar.h"
00028 #include "kpteffortcostmap.h"
00029 #include "kptschedule.h"
00030
00031 #include <qdom.h>
00032 #include <qbrush.h>
00033 #include <kdebug.h>
00034
00035 namespace KPlato
00036 {
00037
00038 Task::Task(Node *parent) : Node(parent), m_resource() {
00039
00040 m_resource.setAutoDelete(true);
00041 Duration d(1, 0, 0);
00042 m_effort = new Effort(d);
00043 m_effort->setOptimisticRatio(-10);
00044 m_effort->setPessimisticRatio(20);
00045 m_requests = 0;
00046
00047 if (m_parent)
00048 m_leader = m_parent->leader();
00049
00050 m_schedules.setAutoDelete(true);
00051 m_parentProxyRelations.setAutoDelete(true);
00052 m_childProxyRelations.setAutoDelete(true);
00053 }
00054
00055 Task::Task(Task &task, Node *parent)
00056 : Node(task, parent),
00057 m_resource() {
00058
00059 m_resource.setAutoDelete(true);
00060
00061 m_parentProxyRelations.setAutoDelete(true);
00062 m_childProxyRelations.setAutoDelete(true);
00063 m_requests = 0;
00064
00065 m_effort = task.effort() ? new Effort(*(task.effort()))
00066 : new Effort();
00067 }
00068
00069
00070 Task::~Task() {
00071 delete m_effort;
00072 }
00073
00074 int Task::type() const {
00075 if ( numChildren() > 0) {
00076 return Node::Type_Summarytask;
00077 }
00078 else if ( 0 == effort()->expected().seconds() ) {
00079 return Node::Type_Milestone;
00080 }
00081 else {
00082 return Node::Type_Task;
00083 }
00084 }
00085
00086
00087
00088 Duration *Task::getExpectedDuration() {
00089
00090
00091 return m_currentSchedule ? new Duration(m_currentSchedule->duration) : new Duration();
00092 }
00093
00094 Duration *Task::getRandomDuration() {
00095 return 0L;
00096 }
00097
00098 ResourceGroupRequest *Task::resourceGroupRequest(ResourceGroup *group) const {
00099 if (m_requests)
00100 return m_requests->find(group);
00101 return 0;
00102 }
00103
00104 void Task::clearResourceRequests() {
00105 if (m_requests)
00106 m_requests->clear();
00107 }
00108
00109 void Task::addRequest(ResourceGroup *group, int numResources) {
00110 addRequest(new ResourceGroupRequest(group, numResources));
00111 }
00112
00113 void Task::addRequest(ResourceGroupRequest *request) {
00114 if (!m_requests)
00115 m_requests = new ResourceRequestCollection(*this);
00116 m_requests->addRequest(request);
00117 }
00118
00119 void Task::takeRequest(ResourceGroupRequest *request) {
00120 if (m_requests) {
00121 m_requests->takeRequest(request);
00122 if (m_requests->isEmpty()) {
00123 delete m_requests;
00124 m_requests = 0;
00125 }
00126 }
00127 }
00128
00129 int Task::units() const {
00130 if (!m_requests)
00131 return 0;
00132 return m_requests->units();
00133 }
00134
00135 int Task::workUnits() const {
00136 if (!m_requests)
00137 return 0;
00138 return m_requests->workUnits();
00139 }
00140
00141 void Task::makeAppointments() {
00142 if (m_currentSchedule == 0)
00143 return;
00144 if (type() == Node::Type_Task) {
00145 if (m_requests) {
00146
00147 m_requests->makeAppointments(m_currentSchedule);
00148
00149 }
00150 } else if (type() == Node::Type_Summarytask) {
00151 QPtrListIterator<Node> nit(m_nodes);
00152 for ( ; nit.current(); ++nit ) {
00153 nit.current()->makeAppointments();
00154 }
00155 } else if (type() == Node::Type_Milestone) {
00156
00157
00158 }
00159 }
00160
00161 void Task::calcResourceOverbooked() {
00162 if (m_currentSchedule)
00163 m_currentSchedule->calcResourceOverbooked();
00164 }
00165
00166
00167 void Task::setConstraint(Node::ConstraintType type) {
00168 m_constraint = type;
00169 }
00170
00171
00172 bool Task::load(QDomElement &element, Project &project) {
00173
00174 QString s;
00175 bool ok = false;
00176 m_id = element.attribute("id");
00177
00178 m_name = element.attribute("name");
00179 m_leader = element.attribute("leader");
00180 m_description = element.attribute("description");
00181
00182
00183
00184 QString constraint = element.attribute("scheduling","0");
00185 m_constraint = (Node::ConstraintType)constraint.toInt(&ok);
00186 if (!ok)
00187 Node::setConstraint(constraint);
00188
00189 s = element.attribute("constraint-starttime");
00190 if (s != "")
00191 m_constraintStartTime = DateTime::fromString(s);
00192 s = element.attribute("constraint-endtime");
00193 if ( s != "")
00194 m_constraintEndTime = DateTime::fromString(s);
00195
00196 m_startupCost = element.attribute("startup-cost", "0.0").toDouble();
00197 m_shutdownCost = element.attribute("shutdown-cost", "0.0").toDouble();
00198
00199 m_wbs = element.attribute("wbs", "");
00200
00201
00202 QDomNodeList list = element.childNodes();
00203 for (unsigned int i=0; i<list.count(); ++i) {
00204 if (list.item(i).isElement()) {
00205 QDomElement e = list.item(i).toElement();
00206
00207 if (e.tagName() == "project") {
00208
00209 Project *child = new Project(this);
00210 if (child->load(e)) {
00211 if (!project.addSubTask(child, this)) {
00212 delete child;
00213 }
00214 } else {
00215
00216 delete child;
00217 }
00218 } else if (e.tagName() == "task") {
00219
00220 Task *child = new Task(this);
00221 if (child->load(e, project)) {
00222 if (!project.addSubTask(child, this)) {
00223 delete child;
00224 }
00225 } else {
00226
00227 delete child;
00228 }
00229 } else if (e.tagName() == "resource") {
00230
00231 } else if (e.tagName() == "effort") {
00232
00233 m_effort->load(e);
00234 } else if (e.tagName() == "resourcegroup-request") {
00235
00236 ResourceGroupRequest *r = new ResourceGroupRequest();
00237 if (r->load(e, project)) {
00238 addRequest(r);
00239 } else {
00240 kdError()<<k_funcinfo<<"Failed to load resource request"<<endl;
00241 delete r;
00242 }
00243 } else if (e.tagName() == "progress") {
00244 m_progress.started = (bool)e.attribute("started", "0").toInt();
00245 m_progress.finished = (bool)e.attribute("finished", "0").toInt();
00246
00247 s = e.attribute("startTime");
00248 if (s != "")
00249 m_progress.startTime = DateTime::fromString(s);
00250 s = e.attribute("finishTime");
00251 if (s != "")
00252 m_progress.finishTime = DateTime::fromString(s);
00253 m_progress.percentFinished = e.attribute("percent-finished", "0").toInt();
00254 m_progress.remainingEffort = Duration::fromString(e.attribute("remaining-effort"));
00255 m_progress.totalPerformed = Duration::fromString(e.attribute("performed-effort"));
00256 } else if (e.tagName() == "schedules") {
00257 QDomNodeList lst = e.childNodes();
00258 for (unsigned int i=0; i<lst.count(); ++i) {
00259 if (lst.item(i).isElement()) {
00260 QDomElement el = lst.item(i).toElement();
00261 if (el.tagName() == "schedule") {
00262 NodeSchedule *sch = new NodeSchedule();
00263 if (sch->loadXML(el)) {
00264 sch->setNode(this);
00265 addSchedule(sch);
00266 } else {
00267 kdError()<<k_funcinfo<<"Failed to load schedule"<<endl;
00268 delete sch;
00269 }
00270 }
00271 }
00272 }
00273 }
00274 }
00275 }
00276
00277 return true;
00278 }
00279
00280
00281 void Task::save(QDomElement &element) const {
00282 QDomElement me = element.ownerDocument().createElement("task");
00283 element.appendChild(me);
00284
00285
00286 me.setAttribute("id", m_id);
00287 me.setAttribute("name", m_name);
00288 me.setAttribute("leader", m_leader);
00289 me.setAttribute("description", m_description);
00290
00291 me.setAttribute("scheduling",constraintToString());
00292 me.setAttribute("constraint-starttime",m_constraintStartTime.toString(Qt::ISODate));
00293 me.setAttribute("constraint-endtime",m_constraintEndTime.toString(Qt::ISODate));
00294
00295 me.setAttribute("startup-cost", m_startupCost);
00296 me.setAttribute("shutdown-cost", m_shutdownCost);
00297
00298 me.setAttribute("wbs", m_wbs);
00299
00300 m_effort->save(me);
00301
00302 QDomElement el = me.ownerDocument().createElement("progress");
00303 me.appendChild(el);
00304 el.setAttribute("started", m_progress.started);
00305 el.setAttribute("finished", m_progress.finished);
00306 el.setAttribute("startTime", m_progress.startTime.toString(Qt::ISODate));
00307 el.setAttribute("finishTime", m_progress.finishTime.toString(Qt::ISODate));
00308 el.setAttribute("percent-finished", m_progress.percentFinished);
00309 el.setAttribute("remaining-effort", m_progress.remainingEffort.toString());
00310 el.setAttribute("performed-effort", m_progress.totalPerformed.toString());
00311
00312 if (!m_schedules.isEmpty()) {
00313 QDomElement schs = me.ownerDocument().createElement("schedules");
00314 me.appendChild(schs);
00315 QIntDictIterator<Schedule> it = m_schedules;
00316 for (; it.current(); ++it) {
00317 if (!it.current()->isDeleted()) {
00318 it.current()->saveXML(schs);
00319 }
00320 }
00321 }
00322 if (m_requests) {
00323 m_requests->save(me);
00324 }
00325 for (int i=0; i<numChildren(); i++) {
00326 getChildNode(i)->save(me);
00327 }
00328 }
00329
00330 void Task::saveAppointments(QDomElement &element, long id) const {
00331
00332 Schedule *sch = findSchedule(id);
00333 if (sch) {
00334 sch->saveAppointments(element);
00335 }
00336 QPtrListIterator<Node> it(m_nodes);
00337 for (; it.current(); ++it ) {
00338 it.current()->saveAppointments(element, id);
00339 }
00340 }
00341
00342 EffortCostMap Task::plannedEffortCostPrDay(const QDate &start, const QDate &end) const {
00343
00344 if (m_currentSchedule) {
00345 return m_currentSchedule->plannedEffortCostPrDay(start, end);
00346 }
00347 return EffortCostMap();
00348 }
00349
00350
00351 Duration Task::plannedEffort() {
00352
00353 Duration eff;
00354 if (type() == Node::Type_Summarytask) {
00355 QPtrListIterator<Node> it(childNodeIterator());
00356 for (; it.current(); ++it) {
00357 eff += it.current()->plannedEffort();
00358 }
00359 } else if (m_currentSchedule) {
00360 eff = m_currentSchedule->plannedEffort();
00361 }
00362 return eff;
00363 }
00364
00365
00366 Duration Task::plannedEffort(const QDate &date) {
00367
00368 Duration eff;
00369 if (type() == Node::Type_Summarytask) {
00370 QPtrListIterator<Node> it(childNodeIterator());
00371 for (; it.current(); ++it) {
00372 eff += it.current()->plannedEffort(date);
00373 }
00374 } else if (m_currentSchedule) {
00375 eff = m_currentSchedule->plannedEffort(date);
00376 }
00377 return eff;
00378 }
00379
00380
00381 Duration Task::plannedEffortTo(const QDate &date) {
00382
00383 Duration eff;
00384 if (type() == Node::Type_Summarytask) {
00385 QPtrListIterator<Node> it(childNodeIterator());
00386 for (; it.current(); ++it) {
00387 eff += it.current()->plannedEffortTo(date);
00388 }
00389 } else if (m_currentSchedule) {
00390 eff = m_currentSchedule->plannedEffortTo(date);
00391 }
00392 return eff;
00393 }
00394
00395
00396 Duration Task::actualEffort() {
00397
00398 Duration eff;
00399 if (type() == Node::Type_Summarytask) {
00400 QPtrListIterator<Node> it(childNodeIterator());
00401 for (; it.current(); ++it) {
00402 eff += it.current()->actualEffort();
00403 }
00404 } else {
00405 eff = m_progress.totalPerformed;
00406 }
00407
00408
00409
00410
00411 return eff;
00412 }
00413
00414
00415 Duration Task::actualEffort(const QDate &date) {
00416
00417 Duration eff;
00418 if (type() == Node::Type_Summarytask) {
00419 QPtrListIterator<Node> it(childNodeIterator());
00420 for (; it.current(); ++it) {
00421 eff += it.current()->actualEffort(date);
00422 }
00423 } else if (m_currentSchedule) {
00424 eff = m_currentSchedule->actualEffort(date);
00425 }
00426 return eff;
00427 }
00428
00429
00430 Duration Task::actualEffortTo(const QDate &date) {
00431
00432 Duration eff;
00433 if (type() == Node::Type_Summarytask) {
00434 QPtrListIterator<Node> it(childNodeIterator());
00435 for (; it.current(); ++it) {
00436 eff += it.current()->actualEffortTo(date);
00437 }
00438 } else if (m_currentSchedule) {
00439 eff = m_currentSchedule->actualEffortTo(date);
00440 }
00441 return eff;
00442 }
00443
00444 double Task::plannedCost() {
00445
00446 double c = 0;
00447 if (type() == Node::Type_Summarytask) {
00448 QPtrListIterator<Node> it(childNodeIterator());
00449 for (; it.current(); ++it) {
00450 c += it.current()->plannedCost();
00451 }
00452 } else if (m_currentSchedule) {
00453 c = m_currentSchedule->plannedCost();
00454 }
00455 return c;
00456 }
00457
00458 double Task::plannedCost(const QDate &date) {
00459
00460 double c = 0;
00461 if (type() == Node::Type_Summarytask) {
00462 QPtrListIterator<Node> it(childNodeIterator());
00463 for (; it.current(); ++it) {
00464 c += it.current()->plannedCost(date);
00465 }
00466 } else if (m_currentSchedule) {
00467 c = m_currentSchedule->plannedCost(date);
00468 }
00469 return c;
00470 }
00471
00472 double Task::plannedCostTo(const QDate &date) {
00473
00474 double c = 0;
00475 if (type() == Node::Type_Summarytask) {
00476 QPtrListIterator<Node> it(childNodeIterator());
00477 for (; it.current(); ++it) {
00478 c += it.current()->plannedCostTo(date);
00479 }
00480 } else if (m_currentSchedule) {
00481 c = m_currentSchedule->plannedCostTo(date);
00482 }
00483 return c;
00484 }
00485
00486 double Task::actualCost() {
00487
00488 double c = 0;
00489 if (type() == Node::Type_Summarytask) {
00490 QPtrListIterator<Node> it(childNodeIterator());
00491 for (; it.current(); ++it) {
00492 c += it.current()->actualCost();
00493 }
00494 } else if (m_currentSchedule) {
00495 c = m_currentSchedule->actualCost();
00496 }
00497 return c;
00498 }
00499
00500 double Task::actualCost(const QDate &date) {
00501
00502 double c = 0;
00503 if (type() == Node::Type_Summarytask) {
00504 QPtrListIterator<Node> it(childNodeIterator());
00505 for (; it.current(); ++it) {
00506 c += it.current()->actualCost(date);
00507 }
00508 } else if (m_currentSchedule) {
00509 c = m_currentSchedule->actualCost(date);
00510 }
00511 return c;
00512 }
00513
00514 double Task::actualCostTo(const QDate &date) {
00515
00516 double c = 0;
00517 if (type() == Node::Type_Summarytask) {
00518 QPtrListIterator<Node> it(childNodeIterator());
00519 for (; it.current(); ++it) {
00520 c += it.current()->actualCostTo(date);
00521 }
00522 } else if (m_currentSchedule) {
00523 c = m_currentSchedule->actualCostTo(date);
00524 }
00525 return c;
00526 }
00527
00528
00529 double Task::effortPerformanceIndex(const QDate &date, bool *error) {
00530 double res = 0.0;
00531 Duration ae = actualEffortTo(date);
00532
00533 bool e = (ae == Duration::zeroDuration || m_progress.percentFinished == 0);
00534 if (error) {
00535 *error = e;
00536 }
00537 if (!e) {
00538 res = (plannedEffortTo(date).toDouble() * ((double)m_progress.percentFinished/100.0) / ae.toDouble());
00539 }
00540 return res;
00541 }
00542
00543
00544 double Task::costPerformanceIndex(const QDate &date, bool *error) {
00545 double res = 0.0;
00546 Duration ac = Q_INT64(actualCostTo(date));
00547
00548 bool e = (ac == Duration::zeroDuration || m_progress.percentFinished == 0);
00549 if (error) {
00550 *error = e;
00551 }
00552 if (!e) {
00553 res = (plannedCostTo(date) * m_progress.percentFinished)/(100 * actualCostTo(date));
00554 }
00555 return res;
00556 }
00557
00558 void Task::initiateCalculation(Schedule &sch) {
00559
00560 m_visitedForward = false;
00561 m_visitedBackward = false;
00562 m_currentSchedule = createSchedule(&sch);
00563 m_currentSchedule->initiateCalculation();
00564 clearProxyRelations();
00565 Node::initiateCalculation(sch);
00566 }
00567
00568
00569 void Task::initiateCalculationLists(QPtrList<Node> &startnodes, QPtrList<Node> &endnodes, QPtrList<Node> &summarytasks) {
00570
00571 if (type() == Node::Type_Summarytask) {
00572 summarytasks.append(this);
00573
00574
00575 QPtrListIterator<Node> nodes = m_nodes;
00576 for (; nodes.current(); ++nodes) {
00577 if (!dependParentNodes().isEmpty())
00578 nodes.current()->addParentProxyRelations(dependParentNodes());
00579 if (!dependChildNodes().isEmpty())
00580 nodes.current()->addChildProxyRelations(dependChildNodes());
00581 nodes.current()->initiateCalculationLists(startnodes, endnodes, summarytasks);
00582 }
00583 } else {
00584 if (isEndNode()) {
00585 endnodes.append(this);
00586
00587 }
00588 if (isStartNode()) {
00589 startnodes.append(this);
00590
00591 }
00592 }
00593 }
00594
00595 DateTime Task::calculatePredeccessors(const QPtrList<Relation> &list, int use) {
00596 DateTime time;
00597 QPtrListIterator<Relation> it = list;
00598 for (; it.current(); ++it) {
00599 if (it.current()->parent()->type() == Type_Summarytask) {
00600
00601 continue;
00602 }
00603 DateTime t = it.current()->parent()->calculateForward(use);
00604 switch (it.current()->type()) {
00605 case Relation::StartStart:
00606
00607 t = it.current()->parent()->getEarliestStart() + it.current()->lag();
00608 break;
00609 case Relation::FinishFinish:
00610
00611
00612 t += it.current()->lag();
00613 t -= duration(t, use, true);
00614 break;
00615 default:
00616 t += it.current()->lag();
00617 break;
00618 }
00619 if (!time.isValid() || t > time)
00620 time = t;
00621 }
00622
00623 return time;
00624 }
00625 DateTime Task::calculateForward(int use) {
00626
00627 if (m_currentSchedule == 0) {
00628 return DateTime();
00629 }
00630 Schedule *cs = m_currentSchedule;
00631 if (m_visitedForward) {
00632
00633 return cs->earliestStart + m_durationForward;
00634 }
00635
00636 if (!dependParentNodes().isEmpty()) {
00637 DateTime time = calculatePredeccessors(dependParentNodes(), use);
00638 if (time.isValid() && time > cs->earliestStart) {
00639 cs->earliestStart = time;
00640 }
00641 }
00642 if (!m_parentProxyRelations.isEmpty()) {
00643 DateTime time = calculatePredeccessors(m_parentProxyRelations, use);
00644 if (time.isValid() && time > cs->earliestStart) {
00645 cs->earliestStart = time;
00646 }
00647 }
00648 if (type() == Node::Type_Task) {
00649 m_durationForward = m_effort->effort(use);
00650 switch (constraint()) {
00651 case Node::ASAP:
00652 case Node::ALAP:
00653 cs->earliestStart = workStartAfter(cs->earliestStart);
00654 m_durationForward = duration(cs->earliestStart, use, false);
00655
00656 break;
00657 case Node::MustFinishOn:
00658 m_durationForward = duration(m_constraintEndTime, use, true);
00659 cs->earliestStart = m_constraintEndTime - m_durationForward;
00660 break;
00661 case Node::FinishNotLater:
00662 m_durationForward = duration(cs->earliestStart, use, false);
00663 if (cs->earliestStart + m_durationForward > m_constraintEndTime) {
00664 m_durationForward = duration(m_constraintEndTime, use, true);
00665 cs->earliestStart = m_constraintEndTime - m_durationForward;
00666 }
00667 break;
00668 case Node::MustStartOn:
00669 cs->earliestStart = m_constraintStartTime;
00670 m_durationForward = duration(cs->earliestStart, use, false);
00671 break;
00672 case Node::StartNotEarlier:
00673 if (cs->earliestStart < m_constraintStartTime) {
00674 cs->earliestStart = m_constraintStartTime;
00675 }
00676 m_durationForward = duration(cs->earliestStart, use, false);
00677 break;
00678 case Node::FixedInterval: {
00679 cs->earliestStart = m_constraintStartTime;
00680 m_durationForward = m_constraintEndTime - m_constraintStartTime;
00681 break;
00682 }
00683 }
00684 } else if (type() == Node::Type_Milestone) {
00685 m_durationForward = Duration::zeroDuration;
00686 switch (constraint()) {
00687 case Node::MustFinishOn:
00688 cs->earliestStart = m_constraintEndTime;
00689 break;
00690 case Node::FinishNotLater:
00691 if (cs->earliestStart > m_constraintEndTime) {
00692 cs->earliestStart = m_constraintEndTime;
00693 }
00694 break;
00695 case Node::MustStartOn:
00696 cs->earliestStart = m_constraintStartTime;
00697 break;
00698 case Node::StartNotEarlier:
00699 if (cs->earliestStart < m_constraintStartTime) {
00700 cs->earliestStart = m_constraintStartTime;
00701 }
00702 break;
00703 case Node::FixedInterval:
00704 cs->earliestStart = m_constraintStartTime;
00705 break;
00706 default:
00707 break;
00708 }
00709
00710 } else if (type() == Node::Type_Summarytask) {
00711 kdWarning()<<k_funcinfo<<"Summarytasks should not be calculated here: "<<m_name<<endl;
00712 } else {
00713 m_durationForward = Duration::zeroDuration;
00714 }
00715
00716
00717 m_visitedForward = true;
00718 return cs->earliestStart + m_durationForward;
00719 }
00720
00721 DateTime Task::calculateSuccessors(const QPtrList<Relation> &list, int use) {
00722 DateTime time;
00723 QPtrListIterator<Relation> it = list;
00724 for (; it.current(); ++it) {
00725 if (it.current()->child()->type() == Type_Summarytask) {
00726
00727 continue;
00728 }
00729 DateTime t = it.current()->child()->calculateBackward(use);
00730 switch (it.current()->type()) {
00731 case Relation::StartStart:
00732
00733
00734 t -= it.current()->lag();
00735 t += duration(t, use, false);
00736 break;
00737 case Relation::FinishFinish:
00738
00739
00740 t = it.current()->child()->getLatestFinish() - it.current()->lag();
00741 break;
00742 default:
00743 t -= it.current()->lag();
00744 break;
00745 }
00746 if (!time.isValid() || t < time)
00747 time = t;
00748 }
00749
00750 return time;
00751 }
00752 DateTime Task::calculateBackward(int use) {
00753
00754 if (m_currentSchedule == 0) {
00755 return DateTime();
00756 }
00757 Schedule *cs = m_currentSchedule;
00758 if (m_visitedBackward) {
00759
00760 return cs->latestFinish - m_durationBackward;
00761 }
00762
00763 if (!dependChildNodes().isEmpty()) {
00764 DateTime time = calculateSuccessors(dependChildNodes(), use);
00765 if (time.isValid() && time < cs->latestFinish) {
00766 cs->latestFinish = time;
00767 }
00768 }
00769 if (!m_childProxyRelations.isEmpty()) {
00770 DateTime time = calculateSuccessors(m_childProxyRelations, use);
00771 if (time.isValid() && time < cs->latestFinish) {
00772 cs->latestFinish = time;
00773 }
00774 }
00775
00776 if (type() == Node::Type_Task) {
00777 m_durationBackward = m_effort->effort(use);
00778 switch (constraint()) {
00779 case Node::ASAP:
00780 case Node::ALAP:
00781 cs->latestFinish = workFinishBefore(cs->latestFinish);
00782 m_durationBackward = duration(cs->latestFinish, use, true);
00783 break;
00784 case Node::MustStartOn:
00785 m_durationBackward = duration(m_constraintStartTime, use, false);
00786 cs->latestFinish = m_constraintStartTime + m_durationBackward;
00787 break;
00788 case Node::StartNotEarlier:
00789 m_durationBackward = duration(cs->latestFinish, use, true);
00790 if (cs->latestFinish - m_durationBackward < m_constraintStartTime) {
00791 m_durationBackward = duration(m_constraintStartTime, use, false);
00792 cs->latestFinish = m_constraintStartTime + m_durationBackward;
00793 }
00794 break;
00795 case Node::MustFinishOn:
00796 cs->latestFinish = m_constraintEndTime;
00797 m_durationBackward = duration(cs->latestFinish, use, true);
00798 break;
00799 case Node::FinishNotLater:
00800 if (cs->latestFinish > m_constraintEndTime) {
00801 cs->latestFinish = m_constraintEndTime;
00802 }
00803 m_durationBackward = duration(cs->latestFinish, use, true);
00804 break;
00805 case Node::FixedInterval: {
00806 cs->latestFinish = m_constraintEndTime;
00807 m_durationBackward = m_constraintEndTime - m_constraintStartTime;
00808 break;
00809 }
00810 }
00811 } else if (type() == Node::Type_Milestone) {
00812 m_durationBackward = Duration::zeroDuration;
00813 switch (constraint()) {
00814 case Node::MustFinishOn:
00815 cs->latestFinish = m_constraintEndTime;
00816 break;
00817 case Node::FinishNotLater:
00818 if (cs->latestFinish > m_constraintEndTime) {
00819 cs->latestFinish = m_constraintEndTime;
00820 }
00821 break;
00822 case Node::MustStartOn:
00823 cs->latestFinish = m_constraintStartTime;
00824 break;
00825 case Node::StartNotEarlier:
00826 if (cs->latestFinish < m_constraintStartTime) {
00827 cs->latestFinish = m_constraintStartTime;
00828 }
00829 break;
00830 case Node::FixedInterval:
00831 cs->latestFinish = m_constraintEndTime;
00832 break;
00833 default:
00834 break;
00835 }
00836
00837 } else if (type() == Node::Type_Summarytask) {
00838 kdWarning()<<k_funcinfo<<"Summarytasks should not be calculated here: "<<m_name<<endl;
00839 } else {
00840 m_durationBackward = Duration::zeroDuration;
00841 }
00842
00843 m_visitedBackward = true;
00844 return cs->latestFinish - m_durationBackward;
00845 }
00846
00847 DateTime Task::schedulePredeccessors(const QPtrList<Relation> &list, int use) {
00848 DateTime time;
00849 QPtrListIterator<Relation> it = list;
00850 for (; it.current(); ++it) {
00851 if (it.current()->parent()->type() == Type_Summarytask) {
00852
00853 continue;
00854 }
00855
00856 DateTime earliest = it.current()->parent()->getEarliestStart();
00857 DateTime t = it.current()->parent()->scheduleForward(earliest, use);
00858 switch (it.current()->type()) {
00859 case Relation::StartStart:
00860
00861 t = it.current()->parent()->startTime() + it.current()->lag();
00862 break;
00863 case Relation::FinishFinish:
00864
00865
00866 t -= duration(t + it.current()->lag(), use, true);
00867 break;
00868 default:
00869 t += it.current()->lag();
00870 break;
00871 }
00872 if (!time.isValid() || t > time)
00873 time = t;
00874 }
00875
00876 return time;
00877 }
00878
00879 DateTime Task::scheduleForward(const DateTime &earliest, int use) {
00880
00881 if (m_currentSchedule == 0) {
00882 return DateTime();
00883 }
00884 Schedule *cs = m_currentSchedule;
00885 if (m_visitedForward) {
00886 return cs->endTime;
00887 }
00888 cs->notScheduled = false;
00889 cs->startTime = earliest > cs->earliestStart ? earliest : cs->earliestStart;
00890
00891 DateTime time = schedulePredeccessors(dependParentNodes(), use);
00892 if (time.isValid() && time > cs->startTime) {
00893 cs->startTime = time;
00894
00895 }
00896
00897 time = schedulePredeccessors(m_parentProxyRelations, use);
00898 if (time.isValid() && time > cs->startTime) {
00899 cs->startTime = time;
00900
00901 }
00902
00903 if(type() == Node::Type_Task) {
00904 cs->duration = m_effort->effort(use);
00905 switch (m_constraint) {
00906 case Node::ASAP:
00907
00908
00909 cs->startTime = workStartAfter(cs->startTime);
00910 cs->duration = duration(cs->startTime, use, false);
00911 cs->endTime = cs->startTime + cs->duration;
00912
00913 break;
00914 case Node::ALAP:
00915
00916 cs->duration = duration(cs->latestFinish, use, true);
00917 cs->endTime = cs->latestFinish;
00918 cs->startTime = cs->endTime - cs->duration;
00919
00920 break;
00921 case Node::StartNotEarlier:
00922
00923
00924 if (cs->startTime < m_constraintStartTime) {
00925 cs->startTime = m_constraintStartTime;
00926 }
00927 cs->startTime = workStartAfter(cs->startTime);
00928 cs->duration = duration(cs->startTime, use, false);
00929 cs->endTime = cs->startTime + cs->duration;
00930 if (cs->endTime > cs->latestFinish) {
00931 cs->schedulingError = true;
00932 }
00933 break;
00934 case Node::FinishNotLater:
00935
00936
00937 cs->duration = duration(cs->startTime, use, false);
00938 cs->endTime = cs->startTime + cs->duration;
00939 if (cs->endTime > m_constraintEndTime) {
00940 cs->schedulingError = true;
00941 cs->endTime = m_constraintEndTime;
00942 cs->duration = duration(cs->endTime, use, true);
00943 cs->startTime = cs->endTime - cs->duration;
00944 }
00945 break;
00946 case Node::MustStartOn:
00947
00948
00949 if (m_constraintStartTime < cs->startTime ||
00950 m_constraintStartTime > cs->latestFinish - m_durationBackward) {
00951 cs->schedulingError = true;
00952 }
00953 cs->startTime = m_constraintStartTime;
00954 cs->duration = duration(cs->startTime, use, false);
00955 cs->endTime = cs->startTime + cs->duration;
00956 break;
00957 case Node::MustFinishOn:
00958
00959
00960 if (m_constraintEndTime > cs->latestFinish ||
00961 m_constraintEndTime < cs->earliestStart + m_durationForward) {
00962 cs->schedulingError = true;
00963 }
00964 cs->endTime = m_constraintEndTime;
00965 cs->duration = duration(cs->endTime, use, true);
00966 cs->startTime = cs->endTime - cs->duration;
00967 break;
00968 case Node::FixedInterval: {
00969
00970
00971 if (cs->startTime < cs->earliestStart) {
00972 cs->schedulingError = true;
00973 }
00974 cs->startTime = m_constraintStartTime;
00975 cs->endTime = m_constraintEndTime;
00976 cs->duration = cs->endTime - cs->startTime;
00977 cs->workStartTime = m_constraintStartTime;
00978 cs->workEndTime = m_constraintEndTime;
00979
00980 break;
00981 }
00982 default:
00983 break;
00984 }
00985 if (m_requests) {
00986 m_requests->reserve(cs->startTime, cs->duration);
00987 }
00988 } else if (type() == Node::Type_Milestone) {
00989 switch (m_constraint) {
00990 case Node::ASAP: {
00991 cs->endTime = cs->startTime;
00992 break;
00993 }
00994 case Node::ALAP: {
00995 cs->startTime = cs->latestFinish;
00996 cs->endTime = cs->latestFinish;
00997 break;
00998 }
00999 case Node::MustStartOn:
01000 case Node::FixedInterval:
01001
01002 if (m_constraintStartTime < cs->startTime ||
01003 m_constraintStartTime > cs->latestFinish) {
01004 cs->schedulingError = true;
01005 }
01006 cs->startTime = m_constraintStartTime;
01007 cs->endTime = m_constraintStartTime;
01008 break;
01009 case Node::MustFinishOn:
01010 if (m_constraintEndTime < cs->startTime ||
01011 m_constraintEndTime > cs->latestFinish) {
01012 cs->schedulingError = true;
01013 }
01014 cs->startTime = m_constraintEndTime;
01015 cs->endTime = m_constraintEndTime;
01016 break;
01017 case Node::StartNotEarlier:
01018 if (cs->startTime < m_constraintStartTime) {
01019 cs->schedulingError = true;
01020 }
01021 cs->endTime = cs->startTime;
01022 break;
01023 case Node::FinishNotLater:
01024 if (cs->startTime > m_constraintEndTime) {
01025 cs->schedulingError = true;
01026 }
01027 cs->endTime = cs->startTime;
01028 break;
01029 default:
01030 break;
01031 }
01032 cs->duration = Duration::zeroDuration;
01033
01034 } else if (type() == Node::Type_Summarytask) {
01035
01036 cs->endTime = cs->startTime;
01037 cs->duration = cs->endTime - cs->startTime;
01038 kdWarning()<<k_funcinfo<<"Summarytasks should not be calculated here: "<<m_name<<endl;
01039 }
01040
01041 m_visitedForward = true;
01042 return cs->endTime;
01043 }
01044
01045 DateTime Task::scheduleSuccessors(const QPtrList<Relation> &list, int use) {
01046 DateTime time;
01047 QPtrListIterator<Relation> it = list;
01048 for (; it.current(); ++it) {
01049 if (it.current()->child()->type() == Type_Summarytask) {
01050
01051 continue;
01052 }
01053
01054 DateTime latest = it.current()->child()->getLatestFinish();
01055 DateTime t = it.current()->child()->scheduleBackward(latest, use);
01056 switch (it.current()->type()) {
01057 case Relation::StartStart:
01058
01059
01060 t += duration(t - it.current()->lag(), use, false);
01061 break;
01062 case Relation::FinishFinish:
01063 t = it.current()->child()->endTime() - it.current()->lag();
01064 break;
01065 default:
01066 t -= it.current()->lag();
01067 break;
01068 }
01069 if (!time.isValid() || t < time)
01070 time = t;
01071 }
01072 return time;
01073 }
01074 DateTime Task::scheduleBackward(const DateTime &latest, int use) {
01075
01076 if (m_currentSchedule == 0) {
01077 return DateTime();
01078 }
01079 Schedule *cs = m_currentSchedule;
01080 if (m_visitedBackward) {
01081 return cs->startTime;
01082 }
01083 cs->notScheduled = false;
01084 cs->endTime = latest < cs->latestFinish ? latest : cs->latestFinish;
01085
01086 DateTime time = scheduleSuccessors(dependChildNodes(), use);
01087 if (time.isValid() && time < cs->endTime) {
01088 cs->endTime = time;
01089 }
01090
01091 time = scheduleSuccessors(m_childProxyRelations, use);
01092 if (time.isValid() && time < cs->endTime) {
01093 cs->endTime = time;
01094 }
01095 if (type() == Node::Type_Task) {
01096 cs->duration = m_effort->effort(use);
01097 switch (m_constraint) {
01098 case Node::ASAP: {
01099
01100
01101 cs->endTime = workFinishBefore(cs->endTime);
01102 cs->duration = duration(cs->earliestStart, use, false);
01103 cs->startTime = cs->earliestStart;
01104 DateTime e = cs->startTime + cs->duration;
01105 if (e > cs->endTime) {
01106 cs->schedulingError = true;
01107 }
01108 cs->endTime = e;
01109
01110 break;
01111 }
01112 case Node::ALAP:
01113
01114
01115 cs->endTime = workFinishBefore(cs->endTime);
01116 cs->duration = duration(cs->endTime, use, true);
01117 cs->startTime = cs->endTime - cs->duration;
01118
01119 break;
01120 case Node::StartNotEarlier:
01121
01122
01123 cs->endTime = workFinishBefore(cs->endTime);
01124 cs->duration = duration(cs->endTime, use, true);
01125 cs->startTime = cs->endTime - cs->duration;
01126 if (cs->startTime < m_constraintStartTime) {
01127 cs->schedulingError = true;
01128 cs->startTime = m_constraintStartTime;
01129 cs->duration = duration(cs->startTime, use, false);
01130 cs->endTime = cs->startTime + cs->duration;
01131 }
01132 break;
01133 case Node::FinishNotLater:
01134
01135
01136 if (cs->endTime > m_constraintEndTime) {
01137 cs->schedulingError = true;
01138 cs->endTime = m_constraintEndTime;
01139 }
01140 cs->endTime = workFinishBefore(cs->endTime);
01141 cs->duration = duration(cs->endTime, use, true);
01142 cs->startTime = cs->endTime - cs->duration;
01143 break;
01144 case Node::MustStartOn:
01145
01146
01147 if (m_constraintStartTime < cs->earliestStart ||
01148 m_constraintStartTime > cs->latestFinish - m_durationBackward) {
01149 cs->schedulingError = true;
01150 }
01151 cs->startTime = m_constraintStartTime;
01152 cs->duration = duration(cs->startTime, use, false);
01153 cs->endTime = cs->startTime + cs->duration;
01154 break;
01155 case Node::MustFinishOn:
01156
01157
01158 if (m_constraintEndTime > cs->latestFinish ||
01159 m_constraintEndTime < cs->earliestStart + m_durationForward) {
01160 cs->schedulingError = true;
01161 }
01162 cs->endTime = m_constraintEndTime;
01163 cs->duration = duration(cs->endTime, use, true);
01164 cs->startTime = cs->endTime - cs->duration;
01165 break;
01166 case Node::FixedInterval: {
01167
01168
01169 if (m_constraintEndTime > cs->endTime) {
01170 cs->schedulingError = true;
01171
01172 }
01173 cs->startTime = m_constraintStartTime;
01174 cs->endTime = m_constraintEndTime;
01175 cs->duration = cs->endTime - cs->startTime;
01176 cs->workStartTime = m_constraintStartTime;
01177 cs->workEndTime = m_constraintEndTime;
01178 break;
01179 }
01180 default:
01181 break;
01182 }
01183 if (m_requests) {
01184 m_requests->reserve(cs->startTime, cs->duration);
01185 }
01186 } else if (type() == Node::Type_Milestone) {
01187 switch (m_constraint) {
01188 case Node::ASAP:
01189 cs->startTime = cs->earliestStart;
01190 cs->endTime = cs->earliestStart;
01191 break;
01192 case Node::ALAP:
01193 cs->startTime = cs->latestFinish;
01194 cs->endTime = cs->latestFinish;
01195 break;
01196 case Node::MustStartOn:
01197 case Node::FixedInterval:
01198 if (m_constraintStartTime < cs->earliestStart ||
01199 m_constraintStartTime > cs->endTime) {
01200 cs->schedulingError = true;
01201 }
01202 cs->startTime = cs->earliestStart;
01203 cs->endTime = cs->earliestStart;
01204 break;
01205 case Node::MustFinishOn:
01206 if (m_constraintEndTime < cs->earliestStart ||
01207 m_constraintEndTime > cs->endTime) {
01208 cs->schedulingError = true;
01209 }
01210 cs->startTime = cs->earliestStart;
01211 cs->endTime = cs->earliestStart;
01212 break;
01213 case Node::StartNotEarlier:
01214 if (m_constraintStartTime > cs->endTime) {
01215 cs->schedulingError = true;
01216 }
01217 cs->startTime = cs->endTime;
01218 break;
01219 case Node::FinishNotLater:
01220 if (m_constraintEndTime < cs->endTime) {
01221 cs->schedulingError = true;
01222 }
01223 cs->startTime = cs->endTime;
01224 break;
01225 default:
01226 break;
01227 }
01228 cs->duration = Duration::zeroDuration;
01229 } else if (type() == Node::Type_Summarytask) {
01230
01231 cs->startTime = cs->endTime;
01232 cs->duration = cs->endTime - cs->startTime;
01233 kdWarning()<<k_funcinfo<<"Summarytasks should not be calculated here: "<<m_name<<endl;
01234 }
01235
01236 m_visitedBackward = true;
01237 return cs->startTime;
01238 }
01239
01240 void Task::adjustSummarytask() {
01241 if (m_currentSchedule == 0)
01242 return;
01243 if (type() == Type_Summarytask) {
01244 DateTime start = m_currentSchedule->latestFinish;
01245 DateTime end = m_currentSchedule->earliestStart;
01246 QPtrListIterator<Node> it(m_nodes);
01247 for (; it.current(); ++it) {
01248 it.current()->adjustSummarytask();
01249 if (it.current()->startTime() < start)
01250 start = it.current()->startTime();
01251 if (it.current()->endTime() > end)
01252 end = it.current()->endTime();
01253 }
01254 m_currentSchedule->startTime = start;
01255 m_currentSchedule->endTime = end;
01256 m_currentSchedule->duration = end - start;
01257 m_currentSchedule->notScheduled = false;
01258
01259 }
01260 }
01261
01262 Duration Task::calcDuration(const DateTime &time, const Duration &effort, bool backward) {
01263
01264
01265
01266 Duration dur = effort;
01267 if (m_effort->type() == Effort::Type_Effort) {
01268 if (m_requests == 0 || m_requests->isEmpty()) {
01269 m_currentSchedule->resourceError = true;
01270 return effort;
01271 }
01272 dur = m_requests->duration(time, effort, backward);
01273 if (dur == Duration::zeroDuration) {
01274 kdWarning()<<k_funcinfo<<"zero duration: Resource not available"<<endl;
01275 m_currentSchedule->resourceNotAvailable = true;
01276 dur = effort;
01277 }
01278 return dur;
01279 }
01280 if (m_effort->type() == Effort::Type_FixedDuration) {
01281
01282 return dur;
01283 }
01284 kdError()<<k_funcinfo<<"Unsupported effort type: "<<m_effort->type()<<endl;
01285 return dur;
01286 }
01287
01288 void Task::clearProxyRelations() {
01289 m_parentProxyRelations.clear();
01290 m_childProxyRelations.clear();
01291 }
01292
01293 void Task::addParentProxyRelations(QPtrList<Relation> &list) {
01294
01295 if (type() == Type_Summarytask) {
01296
01297
01298 QPtrListIterator<Node> nodes = m_nodes;
01299 for (; nodes.current(); ++nodes) {
01300 nodes.current()->addParentProxyRelations(list);
01301 nodes.current()->addParentProxyRelations(dependParentNodes());
01302 }
01303 } else {
01304
01305
01306 QPtrListIterator<Relation> it = list;
01307 for (; it.current(); ++it) {
01308 it.current()->parent()->addChildProxyRelation(this, it.current());
01309
01310 addParentProxyRelation(it.current()->parent(), it.current());
01311 }
01312 }
01313 }
01314
01315 void Task::addChildProxyRelations(QPtrList<Relation> &list) {
01316
01317 if (type() == Type_Summarytask) {
01318
01319
01320 QPtrListIterator<Node> nodes = m_nodes;
01321 for (; nodes.current(); ++nodes) {
01322 nodes.current()->addChildProxyRelations(list);
01323 nodes.current()->addChildProxyRelations(dependChildNodes());
01324 }
01325 } else {
01326
01327
01328 QPtrListIterator<Relation> it = list;
01329 for (; it.current(); ++it) {
01330 it.current()->child()->addParentProxyRelation(this, it.current());
01331
01332 addChildProxyRelation(it.current()->child(), it.current());
01333 }
01334 }
01335 }
01336
01337 void Task::addParentProxyRelation(Node *node, const Relation *rel) {
01338 if (node->type() != Type_Summarytask) {
01339 if (type() == Type_Summarytask) {
01340
01341 QPtrListIterator<Node> nodes = m_nodes;
01342 for (; nodes.current(); ++nodes) {
01343 nodes.current()->addParentProxyRelation(node, rel);
01344 }
01345 } else {
01346
01347 m_parentProxyRelations.append(new ProxyRelation(node, this, rel->type(), rel->lag()));
01348 }
01349 }
01350 }
01351
01352 void Task::addChildProxyRelation(Node *node, const Relation *rel) {
01353 if (node->type() != Type_Summarytask) {
01354 if (type() == Type_Summarytask) {
01355
01356 QPtrListIterator<Node> nodes = m_nodes;
01357 for (; nodes.current(); ++nodes) {
01358 nodes.current()->addChildProxyRelation(node, rel);
01359 }
01360 } else {
01361
01362 m_childProxyRelations.append(new ProxyRelation(this, node, rel->type(), rel->lag()));
01363 }
01364 }
01365 }
01366
01367 bool Task::isEndNode() const {
01368 QPtrListIterator<Relation> it = m_dependChildNodes;
01369 for (; it.current(); ++it) {
01370 if (it.current()->type() == Relation::FinishStart)
01371 return false;
01372 }
01373 QPtrListIterator<Relation> pit = m_childProxyRelations;
01374 for (; pit.current(); ++pit) {
01375 if (pit.current()->type() == Relation::FinishStart)
01376 return false;
01377 }
01378 return true;
01379 }
01380 bool Task::isStartNode() const {
01381 QPtrListIterator<Relation> it = m_dependParentNodes;
01382 for (; it.current(); ++it) {
01383 if (it.current()->type() == Relation::FinishStart ||
01384 it.current()->type() == Relation::StartStart)
01385 return false;
01386 }
01387 QPtrListIterator<Relation> pit = m_parentProxyRelations;
01388 for (; pit.current(); ++pit) {
01389 if (pit.current()->type() == Relation::FinishStart ||
01390 pit.current()->type() == Relation::StartStart)
01391 return false;
01392 }
01393 return true;
01394 }
01395
01396 DateTime Task::workStartTime() const {
01397 if (m_currentSchedule == 0)
01398 return DateTime();
01399 if (m_requests)
01400 return m_currentSchedule->workStartTime;
01401 return m_currentSchedule->startTime;
01402 }
01403
01404 DateTime Task::workEndTime() const {
01405 if (m_currentSchedule == 0)
01406 return DateTime();
01407 return m_currentSchedule->endTime;
01408 }
01409
01410 DateTime Task::workStartAfter(const DateTime &dt) {
01411 if (m_requests) {
01412 DateTime t = m_requests->availableAfter(dt);
01413 return t.isValid() ? t : dt;
01414 }
01415 return dt;
01416 }
01417
01418 DateTime Task::workFinishBefore(const DateTime &dt) {
01419 if (m_requests) {
01420 return m_requests->availableBefore(dt);
01421 }
01422 return dt;
01423 }
01424
01425 Duration Task::positiveFloat() {
01426 if (m_currentSchedule == 0 ||
01427 m_currentSchedule->schedulingError ||
01428 effortMetError()) {
01429 return Duration::zeroDuration;
01430 }
01431 Duration f;
01432 if (type() == Node::Type_Milestone) {
01433 if (m_currentSchedule->startTime < m_currentSchedule->latestFinish) {
01434 f = m_currentSchedule->latestFinish - m_currentSchedule->startTime;
01435 }
01436 } else if (m_effort->type() == Effort::Type_FixedDuration) {
01437 if (m_currentSchedule->endTime.isValid()) {
01438 if (m_currentSchedule->endTime < m_currentSchedule->latestFinish) {
01439 f = m_currentSchedule->latestFinish - m_currentSchedule->endTime;
01440 }
01441 }
01442 } else {
01443 if (m_currentSchedule->workEndTime.isValid())
01444 if (m_currentSchedule->workEndTime < m_currentSchedule->latestFinish) {
01445 f = m_currentSchedule->latestFinish - m_currentSchedule->workEndTime;
01446 } else if (m_currentSchedule->endTime.isValid()) {
01447 if (m_currentSchedule->endTime < m_currentSchedule->latestFinish) {
01448 f = m_currentSchedule->latestFinish - m_currentSchedule->endTime;
01449 }
01450 }
01451 }
01452
01453 return f;
01454 }
01455
01456 bool Task::isCritical() {
01457 Schedule *cs = m_currentSchedule;
01458 if (cs == 0) {
01459 return false;
01460 }
01461 return cs->earliestStart >= cs->startTime && cs->latestFinish <= cs->endTime;
01462 }
01463
01464 bool Task::calcCriticalPath(bool fromEnd) {
01465 if (m_currentSchedule == 0)
01466 return false;
01467
01468 if (m_currentSchedule->inCriticalPath) {
01469 return true;
01470 }
01471 if (!isCritical()) {
01472 return false;
01473 }
01474 if (fromEnd) {
01475 if (isEndNode()) {
01476 m_currentSchedule->inCriticalPath = true;
01477
01478 return true;
01479 }
01480 QPtrListIterator<Relation> it(m_childProxyRelations);
01481 for (; it.current(); ++it) {
01482 if (it.current()->child()->calcCriticalPath(fromEnd)) {
01483 m_currentSchedule->inCriticalPath = true;
01484 }
01485 }
01486 QPtrListIterator<Relation> pit(m_dependChildNodes);
01487 for (; pit.current(); ++pit) {
01488 if (pit.current()->child()->calcCriticalPath(fromEnd)) {
01489 m_currentSchedule->inCriticalPath = true;
01490 }
01491 }
01492 } else {
01493 if (isStartNode()) {
01494 m_currentSchedule->inCriticalPath = true;
01495
01496 return true;
01497 }
01498 QPtrListIterator<Relation> it(m_parentProxyRelations);
01499 for (; it.current(); ++it) {
01500 if (it.current()->parent()->calcCriticalPath(fromEnd)) {
01501 m_currentSchedule->inCriticalPath = true;
01502 }
01503 }
01504 QPtrListIterator<Relation> pit(m_dependParentNodes);
01505 for (; pit.current(); ++pit) {
01506 if (pit.current()->parent()->calcCriticalPath(fromEnd)) {
01507 m_currentSchedule->inCriticalPath = true;
01508 }
01509 }
01510 }
01511
01512 return m_currentSchedule->inCriticalPath;
01513 }
01514
01515 void Task::setCurrentSchedule(long id) {
01516 setCurrentSchedulePtr(findSchedule(id));
01517 Node::setCurrentSchedule(id);
01518 }
01519
01520 bool Task::effortMetError() const {
01521 if (m_currentSchedule->notScheduled) {
01522 return false;
01523 }
01524 return m_currentSchedule->plannedEffort() < effort()->effort(static_cast<Effort::Use>(static_cast<int>(m_currentSchedule->type())));
01525 }
01526
01527 #ifndef NDEBUG
01528 void Task::printDebug(bool children, QCString indent) {
01529 kdDebug()<<indent<<"+ Task node: "<<name()<<" type="<<type()<<endl;
01530 indent += "! ";
01531 kdDebug()<<indent<<"Requested resources (total): "<<units()<<"%"<<endl;
01532 kdDebug()<<indent<<"Requested resources (work): "<<workUnits()<<"%"<<endl;
01533 if (m_requests)
01534 m_requests->printDebug(indent);
01535
01536 Node::printDebug(children, indent);
01537
01538 }
01539
01540 #endif
01541
01542 }