22#include "kptproject.h"
23#include "kpttaskdialog.h"
24#include "kptduration.h"
25#include "kptrelation.h"
26#include "kptdatetime.h"
27#include "kptcalendar.h"
28#include "kpteffortcostmap.h"
29#include "kptschedule.h"
38Task::Task(Node *parent) : Node(parent), m_resource() {
40 m_resource.setAutoDelete(
true);
42 m_effort =
new Effort(d);
43 m_effort->setOptimisticRatio(-10);
44 m_effort->setPessimisticRatio(20);
48 m_leader = m_parent->leader();
50 m_schedules.setAutoDelete(
true);
51 m_parentProxyRelations.setAutoDelete(
true);
52 m_childProxyRelations.setAutoDelete(
true);
55Task::Task(Task &task, Node *parent)
59 m_resource.setAutoDelete(
true);
61 m_parentProxyRelations.setAutoDelete(
true);
62 m_childProxyRelations.setAutoDelete(
true);
65 m_effort = task.effort() ?
new Effort(*(task.effort()))
74int Task::type()
const {
75 if ( numChildren() > 0) {
76 return Node::Type_Summarytask;
78 else if ( 0 == effort()->expected().seconds() ) {
79 return Node::Type_Milestone;
82 return Node::Type_Task;
91 return m_currentSchedule ?
new Duration(m_currentSchedule->duration) :
new Duration();
98ResourceGroupRequest *Task::resourceGroupRequest(
ResourceGroup *group)
const {
100 return m_requests->find(group);
104void Task::clearResourceRequests() {
109void Task::addRequest(ResourceGroup *group,
int numResources) {
110 addRequest(
new ResourceGroupRequest(group, numResources));
113void Task::addRequest(ResourceGroupRequest *request) {
115 m_requests =
new ResourceRequestCollection(*
this);
116 m_requests->addRequest(request);
119void Task::takeRequest(ResourceGroupRequest *request) {
121 m_requests->takeRequest(request);
122 if (m_requests->isEmpty()) {
129int Task::units()
const {
132 return m_requests->units();
135int Task::workUnits()
const {
138 return m_requests->workUnits();
141void Task::makeAppointments() {
142 if (m_currentSchedule == 0)
144 if (type() == Node::Type_Task) {
147 m_requests->makeAppointments(m_currentSchedule);
150 }
else if (type() == Node::Type_Summarytask) {
151 TQPtrListIterator<Node> nit(m_nodes);
152 for ( ; nit.current(); ++nit ) {
153 nit.current()->makeAppointments();
155 }
else if (type() == Node::Type_Milestone) {
161void Task::calcResourceOverbooked() {
162 if (m_currentSchedule)
163 m_currentSchedule->calcResourceOverbooked();
167void Task::setConstraint(Node::ConstraintType type) {
172bool Task::load(TQDomElement &element,
Project &project) {
176 m_id = element.attribute(
"id");
178 m_name = element.attribute(
"name");
179 m_leader = element.attribute(
"leader");
180 m_description = element.attribute(
"description");
184 TQString constraint = element.attribute(
"scheduling",
"0");
185 m_constraint = (Node::ConstraintType)constraint.toInt(&ok);
187 Node::setConstraint(constraint);
189 s = element.attribute(
"constraint-starttime");
191 m_constraintStartTime = DateTime::fromString(s);
192 s = element.attribute(
"constraint-endtime");
194 m_constraintEndTime = DateTime::fromString(s);
196 m_startupCost = element.attribute(
"startup-cost",
"0.0").toDouble();
197 m_shutdownCost = element.attribute(
"shutdown-cost",
"0.0").toDouble();
199 m_wbs = element.attribute(
"wbs",
"");
202 TQDomNodeList list = element.childNodes();
203 for (
unsigned int i=0; i<list.count(); ++i) {
204 if (list.item(i).isElement()) {
205 TQDomElement e = list.item(i).toElement();
207 if (e.tagName() ==
"project") {
210 if (child->load(e)) {
211 if (!project.addSubTask(child,
this)) {
218 }
else if (e.tagName() ==
"task") {
221 if (child->
load(e, project)) {
222 if (!project.addSubTask(child,
this)) {
229 }
else if (e.tagName() ==
"resource") {
231 }
else if (e.tagName() ==
"effort") {
234 }
else if (e.tagName() ==
"resourcegroup-request") {
236 ResourceGroupRequest *r =
new ResourceGroupRequest();
237 if (r->load(e, project)) {
240 kdError()<<k_funcinfo<<
"Failed to load resource request"<<endl;
243 }
else if (e.tagName() ==
"progress") {
244 m_progress.started = (bool)e.attribute(
"started",
"0").toInt();
245 m_progress.finished = (bool)e.attribute(
"finished",
"0").toInt();
247 s = e.attribute(
"startTime");
249 m_progress.startTime = DateTime::fromString(s);
250 s = e.attribute(
"finishTime");
252 m_progress.finishTime = DateTime::fromString(s);
253 m_progress.percentFinished = e.attribute(
"percent-finished",
"0").toInt();
254 m_progress.remainingEffort = Duration::fromString(e.attribute(
"remaining-effort"));
255 m_progress.totalPerformed = Duration::fromString(e.attribute(
"performed-effort"));
256 }
else if (e.tagName() ==
"schedules") {
257 TQDomNodeList lst = e.childNodes();
258 for (
unsigned int i=0; i<lst.count(); ++i) {
259 if (lst.item(i).isElement()) {
260 TQDomElement el = lst.item(i).toElement();
261 if (el.tagName() ==
"schedule") {
263 if (sch->loadXML(el)) {
267 kdError()<<k_funcinfo<<
"Failed to load schedule"<<endl;
281void Task::save(TQDomElement &element)
const {
282 TQDomElement me = element.ownerDocument().createElement(
"task");
283 element.appendChild(me);
286 me.setAttribute(
"id", m_id);
287 me.setAttribute(
"name", m_name);
288 me.setAttribute(
"leader", m_leader);
289 me.setAttribute(
"description", m_description);
291 me.setAttribute(
"scheduling",constraintToString());
292 me.setAttribute(
"constraint-starttime",m_constraintStartTime.toString(TQt::ISODate));
293 me.setAttribute(
"constraint-endtime",m_constraintEndTime.toString(TQt::ISODate));
295 me.setAttribute(
"startup-cost", m_startupCost);
296 me.setAttribute(
"shutdown-cost", m_shutdownCost);
298 me.setAttribute(
"wbs", m_wbs);
302 TQDomElement el = me.ownerDocument().createElement(
"progress");
304 el.setAttribute(
"started", m_progress.started);
305 el.setAttribute(
"finished", m_progress.finished);
306 el.setAttribute(
"startTime", m_progress.startTime.toString(TQt::ISODate));
307 el.setAttribute(
"finishTime", m_progress.finishTime.toString(TQt::ISODate));
308 el.setAttribute(
"percent-finished", m_progress.percentFinished);
309 el.setAttribute(
"remaining-effort", m_progress.remainingEffort.toString());
310 el.setAttribute(
"performed-effort", m_progress.totalPerformed.toString());
312 if (!m_schedules.isEmpty()) {
313 TQDomElement schs = me.ownerDocument().createElement(
"schedules");
314 me.appendChild(schs);
315 TQIntDictIterator<Schedule> it = m_schedules;
316 for (; it.current(); ++it) {
317 if (!it.current()->isDeleted()) {
318 it.current()->saveXML(schs);
323 m_requests->save(me);
325 for (
int i=0; i<numChildren(); i++) {
326 getChildNode(i)->save(me);
330void Task::saveAppointments(TQDomElement &element,
long id)
const {
334 sch->saveAppointments(element);
336 TQPtrListIterator<Node> it(m_nodes);
337 for (; it.current(); ++it ) {
338 it.current()->saveAppointments(element,
id);
342EffortCostMap Task::plannedEffortCostPrDay(
const TQDate &start,
const TQDate &end)
const {
344 if (m_currentSchedule) {
345 return m_currentSchedule->plannedEffortCostPrDay(start, end);
347 return EffortCostMap();
354 if (type() == Node::Type_Summarytask) {
355 TQPtrListIterator<Node> it(childNodeIterator());
356 for (; it.current(); ++it) {
357 eff += it.current()->plannedEffort();
359 }
else if (m_currentSchedule) {
360 eff = m_currentSchedule->plannedEffort();
369 if (type() == Node::Type_Summarytask) {
370 TQPtrListIterator<Node> it(childNodeIterator());
371 for (; it.current(); ++it) {
372 eff += it.current()->plannedEffort(date);
374 }
else if (m_currentSchedule) {
375 eff = m_currentSchedule->plannedEffort(date);
381Duration Task::plannedEffortTo(
const TQDate &date) {
384 if (type() == Node::Type_Summarytask) {
385 TQPtrListIterator<Node> it(childNodeIterator());
386 for (; it.current(); ++it) {
387 eff += it.current()->plannedEffortTo(date);
389 }
else if (m_currentSchedule) {
390 eff = m_currentSchedule->plannedEffortTo(date);
399 if (type() == Node::Type_Summarytask) {
400 TQPtrListIterator<Node> it(childNodeIterator());
401 for (; it.current(); ++it) {
402 eff += it.current()->actualEffort();
405 eff = m_progress.totalPerformed;
418 if (type() == Node::Type_Summarytask) {
419 TQPtrListIterator<Node> it(childNodeIterator());
420 for (; it.current(); ++it) {
421 eff += it.current()->actualEffort(date);
423 }
else if (m_currentSchedule) {
424 eff = m_currentSchedule->actualEffort(date);
433 if (type() == Node::Type_Summarytask) {
434 TQPtrListIterator<Node> it(childNodeIterator());
435 for (; it.current(); ++it) {
436 eff += it.current()->actualEffortTo(date);
438 }
else if (m_currentSchedule) {
439 eff = m_currentSchedule->actualEffortTo(date);
444double Task::plannedCost() {
447 if (type() == Node::Type_Summarytask) {
448 TQPtrListIterator<Node> it(childNodeIterator());
449 for (; it.current(); ++it) {
450 c += it.current()->plannedCost();
452 }
else if (m_currentSchedule) {
453 c = m_currentSchedule->plannedCost();
458double Task::plannedCost(
const TQDate &date) {
461 if (type() == Node::Type_Summarytask) {
462 TQPtrListIterator<Node> it(childNodeIterator());
463 for (; it.current(); ++it) {
464 c += it.current()->plannedCost(date);
466 }
else if (m_currentSchedule) {
467 c = m_currentSchedule->plannedCost(date);
472double Task::plannedCostTo(
const TQDate &date) {
475 if (type() == Node::Type_Summarytask) {
476 TQPtrListIterator<Node> it(childNodeIterator());
477 for (; it.current(); ++it) {
478 c += it.current()->plannedCostTo(date);
480 }
else if (m_currentSchedule) {
481 c = m_currentSchedule->plannedCostTo(date);
486double Task::actualCost() {
489 if (type() == Node::Type_Summarytask) {
490 TQPtrListIterator<Node> it(childNodeIterator());
491 for (; it.current(); ++it) {
492 c += it.current()->actualCost();
494 }
else if (m_currentSchedule) {
495 c = m_currentSchedule->actualCost();
500double Task::actualCost(
const TQDate &date) {
503 if (type() == Node::Type_Summarytask) {
504 TQPtrListIterator<Node> it(childNodeIterator());
505 for (; it.current(); ++it) {
506 c += it.current()->actualCost(date);
508 }
else if (m_currentSchedule) {
509 c = m_currentSchedule->actualCost(date);
514double Task::actualCostTo(
const TQDate &date) {
517 if (type() == Node::Type_Summarytask) {
518 TQPtrListIterator<Node> it(childNodeIterator());
519 for (; it.current(); ++it) {
520 c += it.current()->actualCostTo(date);
522 }
else if (m_currentSchedule) {
523 c = m_currentSchedule->actualCostTo(date);
529double Task::effortPerformanceIndex(
const TQDate &date,
bool *error) {
533 bool e = (ae == Duration::zeroDuration || m_progress.percentFinished == 0);
538 res = (plannedEffortTo(date).toDouble() * ((double)m_progress.percentFinished/100.0) / ae.toDouble());
544double Task::costPerformanceIndex(
const TQDate &date,
bool *error) {
546 Duration ac = TQ_INT64(actualCostTo(date));
548 bool e = (ac == Duration::zeroDuration || m_progress.percentFinished == 0);
553 res = (plannedCostTo(date) * m_progress.percentFinished)/(100 * actualCostTo(date));
558void Task::initiateCalculation(
Schedule &sch) {
560 m_visitedForward =
false;
561 m_visitedBackward =
false;
562 m_currentSchedule = createSchedule(&sch);
563 m_currentSchedule->initiateCalculation();
564 clearProxyRelations();
565 Node::initiateCalculation(sch);
569void Task::initiateCalculationLists(TQPtrList<Node> &startnodes, TQPtrList<Node> &endnodes, TQPtrList<Node> &summarytasks) {
571 if (type() == Node::Type_Summarytask) {
572 summarytasks.append(
this);
575 TQPtrListIterator<Node> nodes = m_nodes;
576 for (; nodes.current(); ++nodes) {
577 if (!dependParentNodes().isEmpty())
578 nodes.current()->addParentProxyRelations(dependParentNodes());
579 if (!dependChildNodes().isEmpty())
580 nodes.current()->addChildProxyRelations(dependChildNodes());
581 nodes.current()->initiateCalculationLists(startnodes, endnodes, summarytasks);
585 endnodes.append(
this);
589 startnodes.append(
this);
595DateTime Task::calculatePredeccessors(
const TQPtrList<Relation> &list,
int use) {
597 TQPtrListIterator<Relation> it = list;
598 for (; it.current(); ++it) {
599 if (it.current()->parent()->type() == Type_Summarytask) {
603 DateTime t = it.current()->parent()->calculateForward(use);
604 switch (it.current()->type()) {
605 case Relation::StartStart:
607 t = it.current()->parent()->getEarliestStart() + it.current()->lag();
609 case Relation::FinishFinish:
612 t += it.current()->lag();
613 t -= duration(t, use,
true);
616 t += it.current()->lag();
619 if (!time.isValid() || t > time)
627 if (m_currentSchedule == 0) {
631 if (m_visitedForward) {
636 if (!dependParentNodes().isEmpty()) {
637 DateTime time = calculatePredeccessors(dependParentNodes(), use);
642 if (!m_parentProxyRelations.isEmpty()) {
643 DateTime time = calculatePredeccessors(m_parentProxyRelations, use);
648 if (type() == Node::Type_Task) {
649 m_durationForward = m_effort->effort(use);
650 switch (constraint()) {
657 case Node::MustFinishOn:
658 m_durationForward = duration(m_constraintEndTime, use,
true);
661 case Node::FinishNotLater:
663 if (cs->
earliestStart + m_durationForward > m_constraintEndTime) {
664 m_durationForward = duration(m_constraintEndTime, use,
true);
668 case Node::MustStartOn:
672 case Node::StartNotEarlier:
678 case Node::FixedInterval: {
680 m_durationForward = m_constraintEndTime - m_constraintStartTime;
684 }
else if (type() == Node::Type_Milestone) {
685 m_durationForward = Duration::zeroDuration;
686 switch (constraint()) {
687 case Node::MustFinishOn:
690 case Node::FinishNotLater:
695 case Node::MustStartOn:
698 case Node::StartNotEarlier:
703 case Node::FixedInterval:
710 }
else if (type() == Node::Type_Summarytask) {
711 kdWarning()<<k_funcinfo<<
"Summarytasks should not be calculated here: "<<m_name<<endl;
713 m_durationForward = Duration::zeroDuration;
717 m_visitedForward =
true;
721DateTime Task::calculateSuccessors(
const TQPtrList<Relation> &list,
int use) {
723 TQPtrListIterator<Relation> it = list;
724 for (; it.current(); ++it) {
725 if (it.current()->child()->type() == Type_Summarytask) {
729 DateTime t = it.current()->child()->calculateBackward(use);
730 switch (it.current()->type()) {
731 case Relation::StartStart:
734 t -= it.current()->lag();
735 t += duration(t, use,
false);
737 case Relation::FinishFinish:
740 t = it.current()->child()->getLatestFinish() - it.current()->lag();
743 t -= it.current()->lag();
746 if (!time.isValid() || t < time)
754 if (m_currentSchedule == 0) {
758 if (m_visitedBackward) {
763 if (!dependChildNodes().isEmpty()) {
764 DateTime time = calculateSuccessors(dependChildNodes(), use);
765 if (time.isValid() && time < cs->latestFinish) {
769 if (!m_childProxyRelations.isEmpty()) {
770 DateTime time = calculateSuccessors(m_childProxyRelations, use);
771 if (time.isValid() && time < cs->latestFinish) {
776 if (type() == Node::Type_Task) {
777 m_durationBackward = m_effort->effort(use);
778 switch (constraint()) {
782 m_durationBackward = duration(cs->
latestFinish, use,
true);
784 case Node::MustStartOn:
785 m_durationBackward = duration(m_constraintStartTime, use,
false);
786 cs->
latestFinish = m_constraintStartTime + m_durationBackward;
788 case Node::StartNotEarlier:
789 m_durationBackward = duration(cs->
latestFinish, use,
true);
790 if (cs->
latestFinish - m_durationBackward < m_constraintStartTime) {
791 m_durationBackward = duration(m_constraintStartTime, use,
false);
792 cs->
latestFinish = m_constraintStartTime + m_durationBackward;
795 case Node::MustFinishOn:
797 m_durationBackward = duration(cs->
latestFinish, use,
true);
799 case Node::FinishNotLater:
803 m_durationBackward = duration(cs->
latestFinish, use,
true);
805 case Node::FixedInterval: {
807 m_durationBackward = m_constraintEndTime - m_constraintStartTime;
811 }
else if (type() == Node::Type_Milestone) {
812 m_durationBackward = Duration::zeroDuration;
813 switch (constraint()) {
814 case Node::MustFinishOn:
817 case Node::FinishNotLater:
822 case Node::MustStartOn:
825 case Node::StartNotEarlier:
830 case Node::FixedInterval:
837 }
else if (type() == Node::Type_Summarytask) {
838 kdWarning()<<k_funcinfo<<
"Summarytasks should not be calculated here: "<<m_name<<endl;
840 m_durationBackward = Duration::zeroDuration;
843 m_visitedBackward =
true;
847DateTime Task::schedulePredeccessors(
const TQPtrList<Relation> &list,
int use) {
849 TQPtrListIterator<Relation> it = list;
850 for (; it.current(); ++it) {
851 if (it.current()->parent()->type() == Type_Summarytask) {
856 DateTime earliest = it.current()->parent()->getEarliestStart();
857 DateTime t = it.current()->parent()->scheduleForward(earliest, use);
858 switch (it.current()->type()) {
859 case Relation::StartStart:
861 t = it.current()->parent()->startTime() + it.current()->lag();
863 case Relation::FinishFinish:
866 t -= duration(t + it.current()->lag(), use,
true);
869 t += it.current()->lag();
872 if (!time.isValid() || t > time)
881 if (m_currentSchedule == 0) {
885 if (m_visitedForward) {
891 DateTime time = schedulePredeccessors(dependParentNodes(), use);
892 if (time.isValid() && time > cs->
startTime) {
897 time = schedulePredeccessors(m_parentProxyRelations, use);
898 if (time.isValid() && time > cs->
startTime) {
903 if(type() == Node::Type_Task) {
904 cs->
duration = m_effort->effort(use);
905 switch (m_constraint) {
921 case Node::StartNotEarlier:
924 if (cs->
startTime < m_constraintStartTime) {
934 case Node::FinishNotLater:
939 if (cs->
endTime > m_constraintEndTime) {
941 cs->
endTime = m_constraintEndTime;
946 case Node::MustStartOn:
949 if (m_constraintStartTime < cs->startTime ||
950 m_constraintStartTime > cs->
latestFinish - m_durationBackward) {
957 case Node::MustFinishOn:
961 m_constraintEndTime < cs->earliestStart + m_durationForward) {
964 cs->
endTime = m_constraintEndTime;
968 case Node::FixedInterval: {
975 cs->
endTime = m_constraintEndTime;
977 cs->workStartTime = m_constraintStartTime;
978 cs->workEndTime = m_constraintEndTime;
988 }
else if (type() == Node::Type_Milestone) {
989 switch (m_constraint) {
999 case Node::MustStartOn:
1000 case Node::FixedInterval:
1002 if (m_constraintStartTime < cs->startTime ||
1007 cs->
endTime = m_constraintStartTime;
1009 case Node::MustFinishOn:
1010 if (m_constraintEndTime < cs->startTime ||
1015 cs->
endTime = m_constraintEndTime;
1017 case Node::StartNotEarlier:
1018 if (cs->
startTime < m_constraintStartTime) {
1023 case Node::FinishNotLater:
1024 if (cs->
startTime > m_constraintEndTime) {
1032 cs->
duration = Duration::zeroDuration;
1034 }
else if (type() == Node::Type_Summarytask) {
1038 kdWarning()<<k_funcinfo<<
"Summarytasks should not be calculated here: "<<m_name<<endl;
1041 m_visitedForward =
true;
1045DateTime Task::scheduleSuccessors(
const TQPtrList<Relation> &list,
int use) {
1047 TQPtrListIterator<Relation> it = list;
1048 for (; it.current(); ++it) {
1049 if (it.current()->child()->type() == Type_Summarytask) {
1054 DateTime latest = it.current()->child()->getLatestFinish();
1055 DateTime t = it.current()->child()->scheduleBackward(latest, use);
1056 switch (it.current()->type()) {
1057 case Relation::StartStart:
1060 t += duration(t - it.current()->lag(), use,
false);
1062 case Relation::FinishFinish:
1063 t = it.current()->child()->endTime() - it.current()->lag();
1066 t -= it.current()->lag();
1069 if (!time.isValid() || t < time)
1076 if (m_currentSchedule == 0) {
1080 if (m_visitedBackward) {
1086 DateTime time = scheduleSuccessors(dependChildNodes(), use);
1087 if (time.isValid() && time < cs->endTime) {
1091 time = scheduleSuccessors(m_childProxyRelations, use);
1092 if (time.isValid() && time < cs->endTime) {
1095 if (type() == Node::Type_Task) {
1096 cs->
duration = m_effort->effort(use);
1097 switch (m_constraint) {
1120 case Node::StartNotEarlier:
1126 if (cs->
startTime < m_constraintStartTime) {
1133 case Node::FinishNotLater:
1136 if (cs->
endTime > m_constraintEndTime) {
1138 cs->
endTime = m_constraintEndTime;
1144 case Node::MustStartOn:
1147 if (m_constraintStartTime < cs->earliestStart ||
1148 m_constraintStartTime > cs->
latestFinish - m_durationBackward) {
1155 case Node::MustFinishOn:
1159 m_constraintEndTime < cs->earliestStart + m_durationForward) {
1162 cs->
endTime = m_constraintEndTime;
1166 case Node::FixedInterval: {
1169 if (m_constraintEndTime > cs->
endTime) {
1174 cs->
endTime = m_constraintEndTime;
1176 cs->workStartTime = m_constraintStartTime;
1177 cs->workEndTime = m_constraintEndTime;
1186 }
else if (type() == Node::Type_Milestone) {
1187 switch (m_constraint) {
1196 case Node::MustStartOn:
1197 case Node::FixedInterval:
1198 if (m_constraintStartTime < cs->earliestStart ||
1199 m_constraintStartTime > cs->
endTime) {
1205 case Node::MustFinishOn:
1206 if (m_constraintEndTime < cs->earliestStart ||
1207 m_constraintEndTime > cs->
endTime) {
1213 case Node::StartNotEarlier:
1214 if (m_constraintStartTime > cs->
endTime) {
1219 case Node::FinishNotLater:
1220 if (m_constraintEndTime < cs->endTime) {
1228 cs->
duration = Duration::zeroDuration;
1229 }
else if (type() == Node::Type_Summarytask) {
1233 kdWarning()<<k_funcinfo<<
"Summarytasks should not be calculated here: "<<m_name<<endl;
1236 m_visitedBackward =
true;
1240void Task::adjustSummarytask() {
1241 if (m_currentSchedule == 0)
1243 if (type() == Type_Summarytask) {
1244 DateTime start = m_currentSchedule->latestFinish;
1245 DateTime end = m_currentSchedule->earliestStart;
1246 TQPtrListIterator<Node> it(m_nodes);
1247 for (; it.current(); ++it) {
1248 it.current()->adjustSummarytask();
1249 if (it.current()->startTime() < start)
1250 start = it.current()->startTime();
1251 if (it.current()->endTime() > end)
1252 end = it.current()->endTime();
1254 m_currentSchedule->startTime = start;
1255 m_currentSchedule->endTime = end;
1256 m_currentSchedule->duration = end - start;
1257 m_currentSchedule->notScheduled =
false;
1267 if (m_effort->type() == Effort::Type_Effort) {
1268 if (m_requests == 0 || m_requests->isEmpty()) {
1269 m_currentSchedule->resourceError =
true;
1272 dur = m_requests->duration(time, effort, backward);
1273 if (dur == Duration::zeroDuration) {
1274 kdWarning()<<k_funcinfo<<
"zero duration: Resource not available"<<endl;
1275 m_currentSchedule->resourceNotAvailable =
true;
1280 if (m_effort->type() == Effort::Type_FixedDuration) {
1284 kdError()<<k_funcinfo<<
"Unsupported effort type: "<<m_effort->type()<<endl;
1288void Task::clearProxyRelations() {
1289 m_parentProxyRelations.clear();
1290 m_childProxyRelations.clear();
1293void Task::addParentProxyRelations(TQPtrList<Relation> &list) {
1295 if (type() == Type_Summarytask) {
1298 TQPtrListIterator<Node> nodes = m_nodes;
1299 for (; nodes.current(); ++nodes) {
1300 nodes.current()->addParentProxyRelations(list);
1301 nodes.current()->addParentProxyRelations(dependParentNodes());
1306 TQPtrListIterator<Relation> it = list;
1307 for (; it.current(); ++it) {
1308 it.current()->parent()->addChildProxyRelation(
this, it.current());
1310 addParentProxyRelation(it.current()->parent(), it.current());
1315void Task::addChildProxyRelations(TQPtrList<Relation> &list) {
1317 if (type() == Type_Summarytask) {
1320 TQPtrListIterator<Node> nodes = m_nodes;
1321 for (; nodes.current(); ++nodes) {
1322 nodes.current()->addChildProxyRelations(list);
1323 nodes.current()->addChildProxyRelations(dependChildNodes());
1328 TQPtrListIterator<Relation> it = list;
1329 for (; it.current(); ++it) {
1330 it.current()->child()->addParentProxyRelation(
this, it.current());
1332 addChildProxyRelation(it.current()->child(), it.current());
1337void Task::addParentProxyRelation(Node *node,
const Relation *rel) {
1338 if (node->type() != Type_Summarytask) {
1339 if (type() == Type_Summarytask) {
1341 TQPtrListIterator<Node> nodes = m_nodes;
1342 for (; nodes.current(); ++nodes) {
1343 nodes.current()->addParentProxyRelation(node, rel);
1347 m_parentProxyRelations.append(
new ProxyRelation(node,
this, rel->type(), rel->lag()));
1352void Task::addChildProxyRelation(Node *node,
const Relation *rel) {
1353 if (node->type() != Type_Summarytask) {
1354 if (type() == Type_Summarytask) {
1356 TQPtrListIterator<Node> nodes = m_nodes;
1357 for (; nodes.current(); ++nodes) {
1358 nodes.current()->addChildProxyRelation(node, rel);
1362 m_childProxyRelations.append(
new ProxyRelation(
this, node, rel->type(), rel->lag()));
1367bool Task::isEndNode()
const {
1368 TQPtrListIterator<Relation> it = m_dependChildNodes;
1369 for (; it.current(); ++it) {
1370 if (it.current()->type() == Relation::FinishStart)
1373 TQPtrListIterator<Relation> pit = m_childProxyRelations;
1374 for (; pit.current(); ++pit) {
1375 if (pit.current()->type() == Relation::FinishStart)
1380bool Task::isStartNode()
const {
1381 TQPtrListIterator<Relation> it = m_dependParentNodes;
1382 for (; it.current(); ++it) {
1383 if (it.current()->type() == Relation::FinishStart ||
1384 it.current()->type() == Relation::StartStart)
1387 TQPtrListIterator<Relation> pit = m_parentProxyRelations;
1388 for (; pit.current(); ++pit) {
1389 if (pit.current()->type() == Relation::FinishStart ||
1390 pit.current()->type() == Relation::StartStart)
1397 if (m_currentSchedule == 0)
1400 return m_currentSchedule->workStartTime;
1401 return m_currentSchedule->startTime;
1405 if (m_currentSchedule == 0)
1407 return m_currentSchedule->endTime;
1412 DateTime t = m_requests->availableAfter(dt);
1413 return t.isValid() ? t : dt;
1418DateTime Task::workFinishBefore(
const DateTime &dt) {
1420 return m_requests->availableBefore(dt);
1426 if (m_currentSchedule == 0 ||
1427 m_currentSchedule->schedulingError ||
1429 return Duration::zeroDuration;
1432 if (type() == Node::Type_Milestone) {
1433 if (m_currentSchedule->startTime < m_currentSchedule->latestFinish) {
1434 f = m_currentSchedule->latestFinish - m_currentSchedule->startTime;
1436 }
else if (m_effort->type() == Effort::Type_FixedDuration) {
1437 if (m_currentSchedule->endTime.isValid()) {
1438 if (m_currentSchedule->endTime < m_currentSchedule->latestFinish) {
1439 f = m_currentSchedule->latestFinish - m_currentSchedule->endTime;
1443 if (m_currentSchedule->workEndTime.isValid())
1444 if (m_currentSchedule->workEndTime < m_currentSchedule->latestFinish) {
1445 f = m_currentSchedule->latestFinish - m_currentSchedule->workEndTime;
1446 }
else if (m_currentSchedule->endTime.isValid()) {
1447 if (m_currentSchedule->endTime < m_currentSchedule->latestFinish) {
1448 f = m_currentSchedule->latestFinish - m_currentSchedule->endTime;
1456bool Task::isCritical() {
1464bool Task::calcCriticalPath(
bool fromEnd) {
1465 if (m_currentSchedule == 0)
1468 if (m_currentSchedule->inCriticalPath) {
1471 if (!isCritical()) {
1476 m_currentSchedule->inCriticalPath =
true;
1480 TQPtrListIterator<Relation> it(m_childProxyRelations);
1481 for (; it.current(); ++it) {
1482 if (it.current()->child()->calcCriticalPath(fromEnd)) {
1483 m_currentSchedule->inCriticalPath =
true;
1486 TQPtrListIterator<Relation> pit(m_dependChildNodes);
1487 for (; pit.current(); ++pit) {
1488 if (pit.current()->child()->calcCriticalPath(fromEnd)) {
1489 m_currentSchedule->inCriticalPath =
true;
1493 if (isStartNode()) {
1494 m_currentSchedule->inCriticalPath =
true;
1498 TQPtrListIterator<Relation> it(m_parentProxyRelations);
1499 for (; it.current(); ++it) {
1500 if (it.current()->parent()->calcCriticalPath(fromEnd)) {
1501 m_currentSchedule->inCriticalPath =
true;
1504 TQPtrListIterator<Relation> pit(m_dependParentNodes);
1505 for (; pit.current(); ++pit) {
1506 if (pit.current()->parent()->calcCriticalPath(fromEnd)) {
1507 m_currentSchedule->inCriticalPath =
true;
1512 return m_currentSchedule->inCriticalPath;
1515void Task::setCurrentSchedule(
long id) {
1516 setCurrentSchedulePtr(findSchedule(
id));
1517 Node::setCurrentSchedule(
id);
1520bool Task::effortMetError()
const {
1521 if (m_currentSchedule->notScheduled) {
1524 return m_currentSchedule->plannedEffort() < effort()->effort(
static_cast<Effort::Use
>(
static_cast<int>(m_currentSchedule->type())));
1528void Task::printDebug(
bool children, TQCString indent) {
1529 kdDebug()<<indent<<
"+ Task node: "<<name()<<
" type="<<type()<<endl;
1531 kdDebug()<<indent<<
"Requested resources (total): "<<units()<<
"%"<<endl;
1532 kdDebug()<<indent<<
"Requested resources (work): "<<workUnits()<<
"%"<<endl;
1534 m_requests->printDebug(indent);
1536 Node::printDebug(children, indent);
DateTime is a TQDateTime which knows about Duration.
The duration class can be used to store a timespan in a convenient format.
NodeSchedule holds scheduling information for a node (task).
Project is the main node in a project, it contains child nodes and possibly sub-projects.
This class represents a group of similar resources to be assigned to a task e.g.
The Schedule class holds data calculated during project calculation and scheduling,...
DateTime startTime
startTime is the scheduled start time.
Duration duration
duration is the scheduled duration which depends on e.g.
DateTime latestFinish
latestFinish is calculated by PERT/CPM.
bool notScheduled
Set if the node has not been scheduled.
DateTime endTime
m_endTime is the scheduled finish time.
DateTime earliestStart
earliestStart is calculated by PERT/CPM.
bool schedulingError
Set if the task cannot be scheduled to fullfill all the constraints.
A task in the scheduling software is represented by this class.
virtual bool load(TQDomElement &element, Project &project)
Load from document.