kplato

kptappointment.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2005 Dag Andersen <danders@get2net.dk>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation;
7 version 2 of the License.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18*/
19
20#include "kptappointment.h"
21
22#include "kptproject.h"
23#include "kpttask.h"
24#include "kptdatetime.h"
25#include "kptcalendar.h"
26#include "kpteffortcostmap.h"
27#include "kptschedule.h"
28
29#include <kdebug.h>
30
31namespace KPlato
32{
33
34class Resource;
35
36AppointmentInterval::AppointmentInterval() {
37 m_load = 100.0;
38}
39AppointmentInterval::AppointmentInterval(const AppointmentInterval &interval) {
40 //kdDebug()<<k_funcinfo<<endl;
41 m_start = interval.startTime();
42 m_end = interval.endTime();
43 m_load = interval.load();
44}
45AppointmentInterval::AppointmentInterval(const DateTime &start, const DateTime end, double load) {
46 //kdDebug()<<k_funcinfo<<endl;
47 m_start = start;
48 m_end = end;
49 m_load = load;
50}
51AppointmentInterval::~AppointmentInterval() {
52 //kdDebug()<<k_funcinfo<<endl;
53}
54
55Duration AppointmentInterval::effort(const DateTime &start, const DateTime end) const {
56 if (start >= m_end || end <= m_start) {
58 }
59 DateTime s = (start > m_start ? start : m_start);
60 DateTime e = (end < m_end ? end : m_end);
61 return (e - s) * m_load / 100;
62}
63
64Duration AppointmentInterval::effort(const DateTime &time, bool upto) const {
65 if (upto) {
66 if (time <= m_start) {
68 }
69 DateTime e = (time < m_end ? time : m_end);
70 return (e - m_start) * m_load / 100;
71 }
72 // from time till end
73 if (time >= m_end) {
75 }
76 DateTime s = (time > m_start ? time : m_start);
77 return (m_end - s) * m_load / 100;
78}
79
80bool AppointmentInterval::loadXML(TQDomElement &element) {
81 //kdDebug()<<k_funcinfo<<endl;
82 bool ok;
83 TQString s = element.attribute("start");
84 if (s != "")
85 m_start = DateTime::fromString(s);
86 s = element.attribute("end");
87 if (s != "")
88 m_end = DateTime::fromString(s);
89 m_load = element.attribute("load", "100").toDouble(&ok);
90 if (!ok) m_load = 100;
91 return m_start.isValid() && m_end.isValid();
92}
93
94void AppointmentInterval::saveXML(TQDomElement &element) const {
95 TQDomElement me = element.ownerDocument().createElement("interval");
96 element.appendChild(me);
97
98 me.setAttribute("start", m_start.toString(TQt::ISODate));
99 me.setAttribute("end", m_end.toString(TQt::ISODate));
100 me.setAttribute("load", m_load);
101}
102
103bool AppointmentInterval::isValid() const {
104 return m_start.isValid() && m_end.isValid();
105}
106
107AppointmentInterval AppointmentInterval::firstInterval(const AppointmentInterval &interval, const DateTime &from) const {
108 //kdDebug()<<k_funcinfo<<interval.startTime().toString()<<" - "<<interval.endTime().toString()<<" from="<<from.toString()<<endl;
109 DateTime f = from;
110 DateTime s1 = m_start;
111 DateTime e1 = m_end;
112 DateTime s2 = interval.startTime();
113 DateTime e2 = interval.endTime();
114 AppointmentInterval a;
115 if (f.isValid() && f >= e1 && f >= e2) {
116 return a;
117 }
118 if (f.isValid()) {
119 if (s1 < f && f < e1) {
120 s1 = f;
121 }
122 if (s2 < f && f < e2) {
123 s2 = f;
124 }
125 } else {
126 f = s1 < s2 ? s1 : s2;
127 }
128 if (s1 < s2) {
129 a.setStartTime(s1);
130 if (e1 <= s2) {
131 a.setEndTime(e1);
132 } else {
133 a.setEndTime(s2);
134 }
135 a.setLoad(m_load);
136 } else if (s1 > s2) {
137 a.setStartTime(s2);
138 if (e2 <= s1) {
139 a.setEndTime(e2);
140 } else {
141 a.setEndTime(s1);
142 }
143 a.setLoad(interval.load());
144 } else {
145 a.setStartTime(s1);
146 if (e1 <= e2)
147 a.setEndTime(e1);
148 else
149 a.setEndTime(e2);
150 a.setLoad(m_load + interval.load());
151 }
152 //kdDebug()<<k_funcinfo<<a.startTime().toString()<<" - "<<a.endTime().toString()<<" load="<<a.load()<<endl;
153 return a;
154}
155
157
158Appointment::UsedEffortItem::UsedEffortItem(TQDate date, Duration effort, bool overtime) {
159 m_date = date;
160 m_effort = effort;
161 m_overtime = overtime;
162}
163TQDate Appointment::UsedEffortItem::date() {
164 return m_date;
165}
166Duration Appointment::UsedEffortItem::effort() {
167 return m_effort;
168}
169bool Appointment::UsedEffortItem::isOvertime() {
170 return m_overtime;
171}
172
173Appointment::UsedEffort::UsedEffort() {
174 setAutoDelete(true);
175}
176
177void Appointment::UsedEffort::inSort(TQDate date, Duration effort, bool overtime) {
178 UsedEffortItem *item = new UsedEffortItem(date, effort, overtime);
179 TQPtrList<UsedEffortItem>::inSort(item);
180}
181
182Duration Appointment::UsedEffort::usedEffort(bool includeOvertime) const {
183 Duration eff;
184 TQPtrListIterator<UsedEffortItem> it(*this);
185 for (; it.current(); ++it) {
186 if (includeOvertime || !it.current()->isOvertime()) {
187 eff += it.current()->effort();
188 }
189 }
190 return eff;
191}
192
193Duration Appointment::UsedEffort::usedEffort(const TQDate &date, bool includeOvertime) const {
194 Duration eff;
195 TQPtrListIterator<UsedEffortItem> it(*this);
196 for (; it.current(); ++it) {
197 if ((includeOvertime || !it.current()->isOvertime()) &&
198 it.current()->date() == date) {
199 eff += it.current()->effort();
200 }
201 }
202 return eff;
203}
204
205Duration Appointment::UsedEffort::usedEffortTo(const TQDate &date, bool includeOvertime) const {
206 Duration eff;
207 TQPtrListIterator<UsedEffortItem> it(*this);
208 for (; it.current(); ++it) {
209 if ((includeOvertime || !it.current()->isOvertime()) &&
210 it.current()->date() <= date) {
211 eff += it.current()->effort();
212 }
213 }
214 return eff;
215}
216
217Duration Appointment::UsedEffort::usedOvertime() const {
218 UsedEffortItem *item = getFirst();
219 return item==0 ? Duration::zeroDuration : usedOvertime(item->date());
220}
221
222Duration Appointment::UsedEffort::usedOvertime(const TQDate &date) const {
223 Duration eff;
224 TQPtrListIterator<UsedEffortItem> it(*this);
225 for (; it.current(); ++it) {
226 if (it.current()->isOvertime() && it.current()->date() == date) {
227 eff += it.current()->effort();
228 }
229 }
230 return eff;
231}
232
233Duration Appointment::UsedEffort::usedOvertimeTo(const TQDate &date) const {
234 Duration eff;
235 TQPtrListIterator<UsedEffortItem> it(*this);
236 for (; it.current(); ++it) {
237 if (it.current()->isOvertime() && it.current()->date() <= date) {
238 eff += it.current()->effort();
239 }
240 }
241 return eff;
242}
243
244bool Appointment::UsedEffort::load(TQDomElement &element) {
245 TQString s;
246 TQDomNodeList list = element.childNodes();
247 for (unsigned int i=0; i<list.count(); ++i) {
248 if (list.item(i).isElement()) {
249 TQDomElement e = list.item(i).toElement();
250 if (e.tagName() == "actual-effort") {
251 TQDate date;
252 s = e.attribute("date");
253 if (s != "")
254 date = TQDate::fromString(s, TQt::ISODate);
255 Duration eff = Duration::fromString(e.attribute("effort"));
256 bool ot = e.attribute("overtime", "0").toInt();
257 if (date.isValid()) {
258 inSort(date, eff, ot);
259 } else {
260 kdError()<<k_funcinfo<<"Load failed, illegal date: "<<e.attribute("date")<<endl;
261 }
262 }
263 }
264 }
265 return true;
266}
267
268void Appointment::UsedEffort::save(TQDomElement &element) const {
269 if (isEmpty()) return;
270 TQPtrListIterator<UsedEffortItem> it = *this;
271 for (; it.current(); ++it) {
272 TQDomElement me = element.ownerDocument().createElement("actual-effort");
273 element.appendChild(me);
274 me.setAttribute("date",it.current()->date().toString(TQt::ISODate));
275 me.setAttribute("effort",it.current()->effort().toString());
276 me.setAttribute("overtime",it.current()->isOvertime());
277 }
278}
279
280int Appointment::UsedEffort::compareItems(TQPtrCollection::Item item1, TQPtrCollection::Item item2) {
281 TQDate d1 = static_cast<UsedEffortItem*>(item1)->date();
282 TQDate d2 = static_cast<UsedEffortItem*>(item2)->date();
283 if (d1 > d2) return 1;
284 if (d1 < d2) return -1;
285 return 0;
286}
287
289Appointment::Appointment()
290 : m_extraRepeats(), m_skipRepeats() {
291 //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
292 m_resource=0;
293 m_node=0;
294 m_repeatInterval=Duration();
295 m_repeatCount=0;
296
297 m_intervals.setAutoDelete(true);
298}
299
300Appointment::Appointment(Schedule *resource, Schedule *node, DateTime start, DateTime end, double load)
301 : m_extraRepeats(),
302 m_skipRepeats() {
303 //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
304 m_node = node;
305 m_resource = resource;
306 m_repeatInterval = Duration();
307 m_repeatCount = 0;
308
309 addInterval(start, end, load);
310
311 m_intervals.setAutoDelete(true);
312}
313
314Appointment::Appointment(Schedule *resource, Schedule *node, DateTime start, Duration duration, double load)
315 : m_extraRepeats(),
316 m_skipRepeats() {
317 //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
318 m_node = node;
319 m_resource = resource;
320 m_repeatInterval = Duration();
321 m_repeatCount = 0;
322
323 addInterval(start, duration, load);
324
325 m_intervals.setAutoDelete(true);
326}
327
328Appointment::~Appointment() {
329 //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
330 detach();
331}
332
333void Appointment::addInterval(AppointmentInterval *a) {
334 //kdDebug()<<k_funcinfo<<m_resource->name()<<" to "<<m_node->name()<<endl;
335 m_intervals.inSort(a);
336}
337void Appointment::addInterval(const DateTime &start, const DateTime &end, double load) {
338 addInterval(new AppointmentInterval(start, end, load));
339}
340void Appointment::addInterval(const DateTime &start, const Duration &duration, double load) {
341 DateTime e = start+duration;
342 addInterval(start, e, load);
343}
344
345double Appointment::maxLoad() const {
346 double v = 0.0;
347 TQPtrListIterator<AppointmentInterval> it = m_intervals;
348 for (; it.current(); ++it) {
349 if (v < it.current()->load())
350 v = it.current()->load();
351 }
352 return v;
353}
354
355DateTime Appointment::startTime() const {
356 DateTime t;
357 TQPtrListIterator<AppointmentInterval> it = m_intervals;
358 for (; it.current(); ++it) {
359 if (!t.isValid() || t > it.current()->startTime())
360 t = it.current()->startTime();
361 }
362 return t;
363}
364
365DateTime Appointment::endTime() const {
366 DateTime t;
367 TQPtrListIterator<AppointmentInterval> it = m_intervals;
368 for (; it.current(); ++it) {
369 if (!t.isValid() || t < it.current()->endTime())
370 t = it.current()->endTime();
371 }
372 return t;
373}
374
375void Appointment::deleteAppointmentFromRepeatList(DateTime) {
376}
377
378void Appointment::addAppointmentToRepeatList(DateTime) {
379}
380
381bool Appointment::isBusy(const DateTime &/*start*/, const DateTime &/*end*/) {
382 return false;
383}
384
385bool Appointment::loadXML(TQDomElement &element, Project &project, Schedule &sch) {
386 //kdDebug()<<k_funcinfo<<endl;
387 TQDictIterator<Node> it = project.nodeDict();
388/* for (; it.current(); ++it) {
389 kdDebug()<<" Node="<<it.current()->name()<<" id="<<it.currentKey()<<endl;
390 }*/
391 Node *node = project.findNode(element.attribute("task-id"));
392 if (node == 0) {
393 kdError()<<k_funcinfo<<"The referenced task does not exists: "<<element.attribute("task-id")<<endl;
394 return false;
395 }
396 Resource *res = project.resource(element.attribute("resource-id"));
397 if (res == 0) {
398 kdError()<<k_funcinfo<<"The referenced resource does not exists: resource id="<<element.attribute("resource-id")<<endl;
399 return false;
400 }
401 if (!res->addAppointment(this, sch)) {
402 kdError()<<k_funcinfo<<"Failed to add appointment to resource: "<<res->name()<<endl;
403 return false;
404 }
405 if (!node->addAppointment(this, sch)) {
406 kdError()<<k_funcinfo<<"Failed to add appointment to node: "<<node->name()<<endl;
407 m_resource->takeAppointment(this);
408 return false;
409 }
410 //kdDebug()<<k_funcinfo<<"res="<<m_resource<<" node="<<m_node<<endl;
411 TQDomNodeList list = element.childNodes();
412 for (unsigned int i=0; i<list.count(); ++i) {
413 if (list.item(i).isElement()) {
414 TQDomElement e = list.item(i).toElement();
415 if (e.tagName() == "interval") {
416 AppointmentInterval *a = new AppointmentInterval();
417 if (a->loadXML(e)) {
418 addInterval(a);
419 } else {
420 kdError()<<k_funcinfo<<"Could not load interval"<<endl;
421 delete a;
422 }
423 }
424 }
425 }
426 if (m_intervals.isEmpty()) {
427 return false;
428 }
429 m_actualEffort.load(element);
430 return true;
431}
432
433void Appointment::saveXML(TQDomElement &element) const {
434 if (m_intervals.isEmpty()) {
435 kdError()<<k_funcinfo<<"Incomplete appointment data: No intervals"<<endl;
436 }
437 if (m_resource == 0 || m_resource->resource() == 0) {
438 kdError()<<k_funcinfo<<"Incomplete appointment data: No resource"<<endl;
439 return;
440 }
441 if (m_node == 0 || m_node->node() == 0) {
442 kdError()<<k_funcinfo<<"Incomplete appointment data: No node"<<endl;
443 return; // shouldn't happen
444 }
445 //kdDebug()<<k_funcinfo<<endl;
446 TQDomElement me = element.ownerDocument().createElement("appointment");
447 element.appendChild(me);
448
449 me.setAttribute("resource-id", m_resource->resource()->id());
450 me.setAttribute("task-id", m_node->node()->id());
451 TQPtrListIterator<AppointmentInterval> it = m_intervals;
452 for (; it.current(); ++it) {
453 it.current()->saveXML(me);
454 }
455 m_actualEffort.save(me);
456}
457
458// Returns the total actual effort for this appointment
459Duration Appointment::plannedEffort() const {
460 Duration d;
461 TQPtrListIterator<AppointmentInterval> it = m_intervals;
462 for (; it.current(); ++it) {
463 d += it.current()->effort();
464 }
465 return d;
466}
467
468// Returns the planned effort on the date
469Duration Appointment::plannedEffort(const TQDate &date) const {
470 Duration d;
471 DateTime s(date);
472 DateTime e(date.addDays(1));
473 TQPtrListIterator<AppointmentInterval> it = m_intervals;
474 for (; it.current(); ++it) {
475 d += it.current()->effort(s, e);
476 }
477 return d;
478}
479
480// Returns the planned effort upto and including the date
481Duration Appointment::plannedEffortTo(const TQDate& date) const {
482 Duration d;
483 DateTime e(date.addDays(1));
484 TQPtrListIterator<AppointmentInterval> it = m_intervals;
485 for (; it.current(); ++it) {
486 d += it.current()->effort(e, true);
487 }
488 return d;
489}
490
491// Returns a list of efforts pr day for interval start, end inclusive
492// The list only includes days with any planned effort
493EffortCostMap Appointment::plannedPrDay(const TQDate& start, const TQDate& end) const {
494 //kdDebug()<<k_funcinfo<<m_node->id()<<", "<<m_resource->id()<<endl;
495 EffortCostMap ec;
496 Duration eff;
497 DateTime dt(start);
498 DateTime ndt(dt.addDays(1));
499 double rate = m_resource->normalRatePrHour();
500 AppointmentIntervalListIterator it = m_intervals;
501 for (; it.current(); ++it) {
502 DateTime st = it.current()->startTime();
503 DateTime e = it.current()->endTime();
504 if (end < st.date())
505 break;
506 if (dt.date() < st.date()) {
507 dt.setDate(st.date());
508 }
509 ndt = TQDateTime(dt.addDays(1));
510 while (dt.date() <= e.date()) {
511 eff = it.current()->effort(dt, ndt);
512 ec.add(dt.date(), eff, eff.toDouble(Duration::Unit_h) * rate);
513 if (dt.date() < e.date() ) {
514 // loop trough the interval (it spans dates)
515 dt = ndt;
516 ndt = TQDateTime(ndt.addDays(1));
517 } else {
518 break;
519 }
520 }
521 }
522 return ec;
523}
524
525
526// Returns the total actual effort for this appointment
527Duration Appointment::actualEffort() const {
528 return m_actualEffort.usedEffort();
529}
530
531// Returns the actual effort on the date
532Duration Appointment::actualEffort(const TQDate &date) const {
533 return m_actualEffort.usedEffort(date);
534}
535
536// Returns the actual effort upto and including date
537Duration Appointment::actualEffortTo(const TQDate &date) const {
538 return m_actualEffort.usedEffortTo(date);
539}
540
541double Appointment::plannedCost() {
542 if (m_resource && m_resource->resource()) {
543 return plannedEffort().toDouble(Duration::Unit_h) * m_resource->resource()->normalRate(); //FIXME overtime
544 }
545 return 0.0;
546}
547
548//Calculates the planned cost on date
549double Appointment::plannedCost(const TQDate &date) {
550 if (m_resource && m_resource->resource()) {
551 return plannedEffort(date).toDouble(Duration::Unit_h) * m_resource->resource()->normalRate(); //FIXME overtime
552 }
553 return 0.0;
554}
555
556//Calculates the planned cost upto and including date
557double Appointment::plannedCostTo(const TQDate &date) {
558 if (m_resource && m_resource->resource()) {
559 return plannedEffortTo(date).toDouble(Duration::Unit_h) * m_resource->resource()->normalRate(); //FIXME overtime
560 }
561 return 0.0;
562}
563
564// Calculates the total actual cost for this appointment
565double Appointment::actualCost() {
566 //kdDebug()<<k_funcinfo<<m_actualEffort.usedEffort(false /*ex. overtime*/).toDouble(Duration::Unit_h)<<endl;
567 if (m_resource && m_resource->resource()) {
568 return (m_actualEffort.usedEffort(false /*ex. overtime*/).toDouble(Duration::Unit_h)*m_resource->resource()->normalRate()) + (m_actualEffort.usedOvertime().toDouble(Duration::Unit_h)*m_resource->resource()->overtimeRate());
569 }
570 return 0.0;
571}
572
573// Calculates the actual cost on date
574double Appointment::actualCost(const TQDate &date) {
575 if (m_resource && m_resource->resource()) {
576 return (m_actualEffort.usedEffort(date, false /*ex. overtime*/).toDouble(Duration::Unit_h)*m_resource->resource()->normalRate()) + (m_actualEffort.usedOvertime(date).toDouble(Duration::Unit_h)*m_resource->resource()->overtimeRate());
577 }
578 return 0.0;
579}
580
581// Calculates the actual cost upto and including date
582double Appointment::actualCostTo(const TQDate &date) {
583 if (m_resource && m_resource->resource()) {
584 return (m_actualEffort.usedEffortTo(date, false /*ex. overtime*/).toDouble(Duration::Unit_h)*m_resource->resource()->normalRate()) + (m_actualEffort.usedOvertimeTo(date).toDouble(Duration::Unit_h)*m_resource->resource()->overtimeRate());
585 }
586 return 0.0;
587}
588
589void Appointment::addActualEffort(TQDate date, Duration effort, bool overtime) {
590 m_actualEffort.inSort(date, effort, overtime);
591}
592
593bool Appointment::attach() {
594 //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
595 if (m_resource && m_node) {
596 m_resource->add(this);
597 m_node->add(this);
598 return true;
599 }
600 kdWarning()<<k_funcinfo<<"Failed: "<<(m_resource ? "" : "resource=0 ")
601 <<(m_node ? "" : "node=0")<<endl;
602 return false;
603}
604
605void Appointment::detach() {
606 //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
607 if (m_resource) {
608 m_resource->takeAppointment(this); // takes from node also
609 }
610 if (m_node) {
611 m_node->takeAppointment(this); // to make it robust
612 }
613}
614
615// Returns the effort from start to end
616Duration Appointment::effort(const DateTime &start, const DateTime &end) const {
617 Duration d;
618 TQPtrListIterator<AppointmentInterval> it = m_intervals;
619 for (; it.current(); ++it) {
620 d += it.current()->effort(start, end);
621 }
622 return d;
623}
624// Returns the effort from start for the duration
625Duration Appointment::effort(const DateTime &start, const Duration &duration) const {
626 Duration d;
627 TQPtrListIterator<AppointmentInterval> it = m_intervals;
628 for (; it.current(); ++it) {
629 d += it.current()->effort(start, start+duration);
630 }
631 return d;
632}
633// Returns the effort upto time / from time
634Duration Appointment::effortFrom(const DateTime &time) const {
635 Duration d;
636 TQPtrListIterator<AppointmentInterval> it = m_intervals;
637 for (; it.current(); ++it) {
638 d += it.current()->effort(time, false);
639 }
640 return d;
641}
642
643Appointment &Appointment::operator=(const Appointment &app) {
644 m_resource = app.resource();
645 m_node = app.node();
646 m_repeatInterval = app.repeatInterval();
647 m_repeatCount = app.repeatCount();
648
649 m_intervals.clear();
650 TQPtrListIterator<AppointmentInterval> it = app.intervals();
651 for (; it.current(); ++it) {
652 addInterval(new AppointmentInterval(*(it.current())));
653 }
654 return *this;
655}
656
657Appointment &Appointment::operator+=(const Appointment &app) {
658 *this = *this + app;
659 return *this;
660}
661
662Appointment Appointment::operator+(const Appointment &app) {
663 Appointment a;
664 AppointmentIntervalList ai = app.intervals();
665 AppointmentInterval i;
666 AppointmentInterval *i1 = m_intervals.first();
667 AppointmentInterval *i2 = ai.first();
668 DateTime from;
669 while (i1 || i2) {
670 if (!i1) {
671 if (!from.isValid() || from < i2->startTime())
672 from = i2->startTime();
673 a.addInterval(from, i2->endTime(), i2->load());
674 //kdDebug()<<"Interval+ (i2): "<<from.toString()<<" - "<<i2->endTime().toString()<<endl;
675 from = i2->endTime();
676 i2 = ai.next();
677 continue;
678 }
679 if (!i2) {
680 if (!from.isValid() || from < i1->startTime())
681 from = i1->startTime();
682 a.addInterval(from, i1->endTime(), i1->load());
683 //kdDebug()<<"Interval+ (i1): "<<from.toString()<<" - "<<i1->endTime().toString()<<endl;
684 from = i1->endTime();
685 i1 = m_intervals.next();
686 continue;
687 }
688 i = i1->firstInterval(*i2, from);
689 if (!i.isValid()) {
690 break;
691 }
692 a.addInterval(i);
693 from = i.endTime();
694 //kdDebug()<<"Interval+ (i): "<<i.startTime().toString()<<" - "<<i.endTime().toString()<<" load="<<i.load()<<endl;
695 if (i1 && a.endTime() >= i1->endTime()) {
696 i1 = m_intervals.next();
697 }
698 if (i2 && a.endTime() >= i2->endTime()) {
699 i2 = ai.next();
700 }
701 }
702 return a;
703}
704
705#ifndef NDEBUG
706void Appointment::printDebug(TQString indent)
707{
708 bool err = false;
709 if (m_node == 0) {
710 kdDebug()<<indent<<" No node schedule"<<endl;
711 err = true;
712 } else if (m_node->node() == 0) {
713 kdDebug()<<indent<<" No node"<<endl;
714 err = true;
715 }
716 if (m_resource == 0) {
717 kdDebug()<<indent<<" No resource schedule"<<endl;
718 err = true;
719 } else if (m_resource->resource() == 0) {
720 kdDebug()<<indent<<" No resource"<<endl;
721 err = true;
722 }
723 if (err)
724 return;
725 kdDebug()<<indent<<" + Appointment to schedule: "<<m_node->name()<<" ("<<m_node->type()<<")"<<" resource: "<<m_resource->resource()->name()<<endl;
726 indent += " ! ";
727 TQPtrListIterator<AppointmentInterval> it = intervals();
728 for (; it.current(); ++it) {
729 kdDebug()<<indent<<it.current()->startTime().toString()<<" - "<<it.current()->endTime().toString()<<" load="<<it.current()->load()<<endl;
730 }
731}
732#endif
733
734} //KPlato namespace
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.
Definition kptdatetime.h:33
The duration class can be used to store a timespan in a convenient format.
Definition kptduration.h:34
static const Duration zeroDuration
This is useful for occasions where we need a zero duration.