20#include "kptschedule.h"
22#include "kptappointment.h"
23#include "kptdatetime.h"
24#include "kptduration.h"
29#include <tqstringlist.h>
44Schedule::Schedule(Schedule *parent)
52 m_name = parent->name();
53 m_type = parent->type();
56 m_appointments.setAutoDelete(
true);
60Schedule::Schedule(TQString name, Type type,
long id)
69 m_appointments.setAutoDelete(
true);
72Schedule::~Schedule() {
75void Schedule::setParent(Schedule *parent) {
79void Schedule::setDeleted(
bool on) {
84bool Schedule::isDeleted()
const {
85 return m_parent == 0 ? m_deleted : m_parent->isDeleted();
88void Schedule::setType(
const TQString type) {
90 if (type ==
"Expected")
92 else if (type ==
"Optimistic")
94 else if (type ==
"Pessimistic")
98TQString Schedule::typeToString(
bool translate)
const {
100 if (m_type == Expected)
101 return i18n(
"Expected");
102 if (m_type == Optimistic)
103 return i18n(
"Optimistic");
104 if (m_type == Pessimistic)
105 return i18n(
"Pessimistic");
106 return i18n(
"Expected");
108 if (m_type == Expected)
110 if (m_type == Optimistic)
112 if (m_type == Pessimistic)
113 return "Pessimistic";
118void Schedule::initiateCalculation() {
119 resourceError =
false;
120 resourceOverbooked =
false;
121 schedulingError =
false;
122 inCriticalPath =
false;
123 workStartTime = DateTime();
124 workEndTime = DateTime();
127void Schedule::calcResourceOverbooked() {
128 resourceOverbooked =
false;
129 TQPtrListIterator<Appointment> it = m_appointments;
130 for (; it.current(); ++it) {
131 if (it.current()->resource()->isOverbooked(startTime, endTime)) {
132 resourceOverbooked =
true;
138TQStringList Schedule::overbookedResources()
const {
140 TQPtrListIterator<Appointment> it = m_appointments;
141 for (; it.current(); ++it) {
142 if (it.current()->resource()->isOverbooked(it.current()->startTime(), it.current()->endTime())) {
143 rl += it.current()->resource()->resource()->name();
149bool Schedule::loadXML(
const TQDomElement &sch) {
150 m_name = sch.attribute(
"name");
151 setType(sch.attribute(
"type"));
152 m_id = sch.attribute(
"id").toLong();
156void Schedule::saveXML(TQDomElement &element)
const {
157 TQDomElement sch = element.ownerDocument().createElement(
"schedule");
158 element.appendChild(sch);
162void Schedule::saveCommonXML(TQDomElement &element)
const {
164 element.setAttribute(
"name", m_name);
165 element.setAttribute(
"type", typeToString());
166 element.setAttribute(
"id", m_id);
169void Schedule::saveAppointments(TQDomElement &element)
const {
171 TQPtrListIterator<Appointment> it = m_appointments;
172 for (; it.current(); ++it) {
173 it.current()->saveXML(element);
178 if (m_appointments.findRef(appointment) != -1) {
179 kdError()<<k_funcinfo<<
"Appointment allready exists"<<endl;
182 m_appointments.append(appointment);
194 int i = m_appointments.findRef(appointment);
196 m_appointments.take(i);
198 if (appointment->node())
206 TQPtrListIterator<Appointment> it = m_appointments;
207 for (; it.current(); ++it) {
208 if (it.current()->node() == node && it.current()->resource() == resource)
214EffortCostMap Schedule::plannedEffortCostPrDay(
const TQDate &start,
const TQDate &end)
const {
217 TQPtrListIterator<Appointment> it(m_appointments);
218 for (; it.current(); ++it) {
220 ec += it.current()->plannedPrDay(start, end);
228 TQPtrListIterator<Appointment> it(m_appointments);
229 for (; it.current(); ++it) {
230 eff += it.current()->plannedEffort();
238 TQPtrListIterator<Appointment> it(m_appointments);
239 for (; it.current(); ++it) {
240 eff += it.current()->plannedEffort(date);
248 TQPtrListIterator<Appointment> it(m_appointments);
249 for (; it.current(); ++it) {
250 eff += it.current()->plannedEffortTo(date);
258 TQPtrListIterator<Appointment> it(m_appointments);
259 for (; it.current(); ++it) {
260 eff += it.current()->actualEffort();
268 TQPtrListIterator<Appointment> it(m_appointments);
269 for (; it.current(); ++it) {
270 eff += it.current()->actualEffort(date);
278 TQPtrListIterator<Appointment> it(m_appointments);
279 for (; it.current(); ++it) {
280 eff += it.current()->actualEffortTo(date);
288 TQPtrListIterator<Appointment> it(m_appointments);
289 for (; it.current(); ++it) {
290 c += it.current()->plannedCost();
298 TQPtrListIterator<Appointment> it(m_appointments);
299 for (; it.current(); ++it) {
300 c += it.current()->plannedCost(date);
308 TQPtrListIterator<Appointment> it(m_appointments);
309 for (; it.current(); ++it) {
310 c += it.current()->plannedCostTo(date);
318 TQPtrListIterator<Appointment> it(m_appointments);
319 for (; it.current(); ++it) {
320 c += it.current()->actualCost();
328 TQPtrListIterator<Appointment> it(m_appointments);
329 for (; it.current(); ++it) {
330 c += it.current()->actualCost(date);
338 TQPtrListIterator<Appointment> it(m_appointments);
339 for (; it.current(); ++it) {
340 c += it.current()->actualCostTo(date);
346NodeSchedule::NodeSchedule()
353NodeSchedule::NodeSchedule(Node *node, TQString name, Schedule::Type type,
long id)
354 : Schedule(name, type, id),
368NodeSchedule::~NodeSchedule() {
372void NodeSchedule::init() {
378 inCriticalPath =
false;
381void NodeSchedule::setDeleted(
bool on) {
385 TQPtrListIterator<Appointment> it = m_appointments;
386 for (; it.current(); ++it) {
387 if (it.current()->resource()) {
388 it.current()->resource()->setDeleted(on);
393bool NodeSchedule::loadXML(
const TQDomElement &sch) {
396 Schedule::loadXML(sch);
397 s = sch.attribute(
"earlieststart");
400 s = sch.attribute(
"latestfinish");
403 s = sch.attribute(
"start");
406 s = sch.attribute(
"end");
408 endTime = DateTime::fromString(s);
409 s = sch.attribute(
"start-work");
411 workStartTime = DateTime::fromString(s);
412 s = sch.attribute(
"end-work");
414 workEndTime = DateTime::fromString(s);
415 duration = Duration::fromString(sch.attribute(
"duration"));
417 inCriticalPath = sch.attribute(
"in-critical-path",
"0").toInt();
418 resourceError = sch.attribute(
"resource-error",
"0").toInt();
422 notScheduled = sch.attribute(
"not-scheduled",
"1").toInt();
427void NodeSchedule::saveXML(TQDomElement &element)
const {
429 TQDomElement sch = element.ownerDocument().createElement(
"schedule");
430 element.appendChild(sch);
434 sch.setAttribute(
"earlieststart",
earliestStart.toString(TQt::ISODate));
436 sch.setAttribute(
"latestfinish",
latestFinish.toString(TQt::ISODate));
438 sch.setAttribute(
"start",
startTime.toString(TQt::ISODate));
440 sch.setAttribute(
"end",
endTime.toString(TQt::ISODate));
441 if (workStartTime.isValid())
442 sch.setAttribute(
"start-work", workStartTime.toString(TQt::ISODate));
443 if (workEndTime.isValid())
444 sch.setAttribute(
"end-work", workEndTime.toString(TQt::ISODate));
446 sch.setAttribute(
"duration",
duration.toString());
448 sch.setAttribute(
"in-critical-path",inCriticalPath);
461 a->addInterval(start, end, load);
464 a =
new Appointment(resource,
this, start, end, load);
468 if (!resource->add(a)) {
474ResourceSchedule::ResourceSchedule()
480ResourceSchedule::ResourceSchedule(Resource *resource, TQString name, Schedule::Type type,
long id)
481 : Schedule(name, type, id),
482 m_resource(resource),
489 m_resource(resource),
494ResourceSchedule::~ResourceSchedule() {
503 a->addInterval(start, end, load);
515bool ResourceSchedule::isOverbooked()
const {
519bool ResourceSchedule::isOverbooked(
const DateTime &start,
const DateTime &end)
const {
523 Appointment a = appointmentIntervals();
524 TQPtrListIterator<AppointmentInterval> it = a.intervals();
525 for (; it.current(); ++it) {
526 if ((!end.isValid() || it.current()->startTime() < end) &&
527 (!start.isValid() || it.current()->endTime() > start))
529 if (it.current()->load() > m_resource->
units()) {
534 if (it.current()->startTime() >= end)
541Appointment ResourceSchedule::appointmentIntervals()
const {
543 TQPtrListIterator<Appointment> it = m_appointments;
544 for (; it.current(); ++it) {
545 a += *(it.current());
550double ResourceSchedule::normalRatePrHour()
const {
551 return m_resource ? m_resource->normalRate() : 0.0;
555MainSchedule::MainSchedule()
561MainSchedule::MainSchedule(
Node *node, TQString name, Schedule::Type type,
long id)
567MainSchedule::~MainSchedule() {
571bool MainSchedule::loadXML(
const TQDomElement &sch,
Project &project) {
572 kdDebug()<<k_funcinfo<<endl;
574 Schedule::loadXML(sch);
576 s = sch.attribute(
"start");
579 s = sch.attribute(
"end");
581 endTime = DateTime::fromString(s);
583 TQDomNodeList al = sch.childNodes();
584 kdDebug()<<k_funcinfo<<
"No of appointments: "<<al.count()<<endl;
585 for (
unsigned int i=0; i<al.count(); ++i) {
586 if (al.item(i).isElement()) {
587 TQDomElement app = al.item(i).toElement();
588 if (app.tagName() ==
"appointment") {
591 Appointment *child =
new Appointment();
592 if (!child->loadXML(app, project, *
this)) {
594 kdError()<<k_funcinfo<<
"Failed to load appointment"<<endl;
603void MainSchedule::saveXML(TQDomElement &element)
const {
604 saveCommonXML(element);
606 element.setAttribute(
"start",
startTime.toString(TQt::ISODate));
607 element.setAttribute(
"end",
endTime.toString(TQt::ISODate));
611void Schedule::printDebug(TQString indent) {
612 kdDebug()<<indent<<
"Schedule["<<m_id<<
"] '"<<m_name<<
"' type: "<<typeToString()<<
" ("<<m_type<<
")"<<(isDeleted()?
" Deleted":
"")<<endl;
614void NodeSchedule::printDebug(TQString indent) {
615 Schedule::printDebug(indent);
618 kdDebug()<<indent<<
"No parent schedule!"<<endl;
620 if (node()) kdDebug()<<indent<<
"Node: "<<node()->name()<<endl;
621 else kdDebug()<<indent<<
"No parent node!"<<endl;
623 kdDebug()<<indent<<
"Not scheduled="<<
notScheduled<<endl;
624 kdDebug()<<indent<<
"Start time: "<<
startTime.toString()<<endl;
625 kdDebug()<<indent<<
"End time: " <<
endTime.toString()<<endl;
626 kdDebug()<<indent<<
"Duration: "<<
duration.seconds()<<TQCString(
" secs")<<
" ("<<
duration.toString()<<
")"<<endl;
627 kdDebug()<<indent<<
"Earliest start: "<<
earliestStart.toString()<<endl;
628 kdDebug()<<indent<<
"Latest finish: " <<
latestFinish.toString()<<endl;
634 kdDebug()<<indent<<
" "<<overbookedResources()<<endl;
636 kdDebug()<<indent<<
"inCriticalPath="<<inCriticalPath<<endl;
637 kdDebug()<<indent<<endl;
638 kdDebug()<<indent<<
"workStartTime="<<workStartTime.toString()<<endl;
639 kdDebug()<<indent<<
"workEndTime="<<workEndTime.toString()<<endl;
640 kdDebug()<<indent<<endl;
641 kdDebug()<<indent<<
"Appointments: "<<m_appointments.count()<<endl;
642 TQPtrListIterator<Appointment> it = m_appointments;
643 for (; it.current(); ++it) {
644 it.current()->printDebug(indent +
" ");
647void ResourceSchedule::printDebug(TQString indent) {
648 Schedule::printDebug(indent);
651 kdDebug()<<indent<<
"No parent schedule!"<<endl;
652 if (resource()) kdDebug()<<indent<<
"Resource: "<<resource()->name()<<endl;
653 else kdDebug()<<indent<<
"No parent resource!"<<endl;
654 kdDebug()<<indent<<endl;
655 kdDebug()<<indent<<
"Appointments: "<<m_appointments.count()<<endl;
658void MainSchedule::printDebug(TQString indent) {
659 Schedule::printDebug(indent);
661 if (node()) kdDebug()<<indent<<
"Node: "<<node()->name()<<endl;
662 else kdDebug()<<indent<<
"No parent node!"<<endl;
664 kdDebug()<<indent<<
"Not scheduled="<<
notScheduled<<endl;
665 kdDebug()<<indent<<
"Start time: "<<
startTime.toString()<<endl;
666 kdDebug()<<indent<<
"End time: " <<
endTime.toString()<<endl;
667 kdDebug()<<indent<<
"Duration: "<<
duration.seconds()<<TQCString(
" secs")<<
" ("<<
duration.toString()<<
")"<<endl;
668 kdDebug()<<indent<<
"Earliest start: "<<
earliestStart.toString()<<endl;
669 kdDebug()<<indent<<
"Latest finish: " <<
latestFinish.toString()<<endl;
671 kdDebug()<<indent<<endl;
672 kdDebug()<<indent<<
"Appointments: "<<m_appointments.count()<<endl;
673 TQPtrListIterator<Appointment> it = m_appointments;
674 for (; it.current(); ++it) {
675 it.current()->printDebug(indent +
" ");
A resource (Resource) can be scheduled to be used at any time, this is represented internally with Ap...
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).
virtual void addAppointment(Schedule *resource, DateTime &start, DateTime &end, double load=100)
Adds appointment to both this resource schedule and node schedule.
This class represents any node in the project, a node can be a project or a subproject or any task.
Project is the main node in a project, it contains child nodes and possibly sub-projects.
virtual void addAppointment(Schedule *node, DateTime &start, DateTime &end, double load=100)
Adds appointment to both this resource schedule and node schedule.
Any resource that is used by a task.
int units() const
Return available units in percent.
The Schedule class holds data calculated during project calculation and scheduling,...
virtual Duration plannedEffort() const
Returns the total planned effort for this task (or subtasks).
DateTime startTime
startTime is the scheduled start time.
virtual double plannedCostTo(const TQDate &date) const
Planned cost from start of activity up to and including date is the sum of all resource costs and oth...
bool resourceNotAvailable
Set if the requested resource is not available.
bool resourceOverbooked
Set if the assigned resource is overbooked.
void removeAppointment(Appointment *appointment)
removes appointment and deletes it (independent of setAutoDelete)
virtual double actualCostTo(const TQDate &date) const
Actual cost up to and including date.
virtual bool add(Appointment *appointment)
Adds appointment to this schedule only.
bool resourceError
Set if EffortType == Effort, but no resource is requested.
virtual Duration actualEffort() const
Returns the total actual effort for this task (or subtasks).
Duration duration
duration is the scheduled duration which depends on e.g.
DateTime latestFinish
latestFinish is calculated by PERT/CPM.
void takeAppointment(Appointment *appointment)
removes appointment without deleting it (independent of setAutoDelete)
virtual double actualCost() const
Actual cost is the sum total of the reported costs actually used for this node.
virtual double plannedCost() const
Planned cost is the sum total of all resources and other costs planned for this node.
bool notScheduled
Set if the node has not been scheduled.
DateTime endTime
m_endTime is the scheduled finish time.
virtual Duration actualEffortTo(const TQDate &date) const
Returns the total actual effort for this task (or subtasks) up to and including date.
DateTime earliestStart
earliestStart is calculated by PERT/CPM.
bool schedulingError
Set if the task cannot be scheduled to fullfill all the constraints.
virtual Duration plannedEffortTo(const TQDate &date) const
Returns the planned effort up to and including date.