kplato

kptappointment.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2005 Dag Andersen <danders@get2net.dk>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation;
00007    version 2 of the License.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "kptappointment.h"
00021 
00022 #include "kptproject.h"
00023 #include "kpttask.h"
00024 #include "kptdatetime.h"
00025 #include "kptcalendar.h"
00026 #include "kpteffortcostmap.h"
00027 #include "kptschedule.h"
00028 
00029 #include <kdebug.h>
00030 
00031 namespace KPlato
00032 {
00033 
00034 class Resource;
00035 
00036 AppointmentInterval::AppointmentInterval() {
00037     m_load = 100.0; 
00038 }
00039 AppointmentInterval::AppointmentInterval(const AppointmentInterval &interval) {
00040     //kdDebug()<<k_funcinfo<<endl;
00041     m_start = interval.startTime(); 
00042     m_end = interval.endTime(); 
00043     m_load = interval.load(); 
00044 }
00045 AppointmentInterval::AppointmentInterval(const DateTime &start, const DateTime end, double load) {
00046     //kdDebug()<<k_funcinfo<<endl;
00047     m_start = start; 
00048     m_end = end; 
00049     m_load = load; 
00050 }
00051 AppointmentInterval::~AppointmentInterval() {
00052     //kdDebug()<<k_funcinfo<<endl;
00053 }
00054 
00055 Duration AppointmentInterval::effort(const DateTime &start, const DateTime end) const {
00056     if (start >= m_end || end <= m_start) {
00057         return Duration::zeroDuration;
00058     }
00059     DateTime s = (start > m_start ? start : m_start);
00060     DateTime e = (end < m_end ? end : m_end);
00061     return (e - s) * m_load / 100;
00062 }
00063 
00064 Duration AppointmentInterval::effort(const DateTime &time, bool upto) const {
00065     if (upto) {
00066         if (time <= m_start) {
00067             return Duration::zeroDuration;
00068         }
00069         DateTime e = (time < m_end ? time : m_end);
00070         return (e - m_start) * m_load / 100;
00071     }
00072     // from time till end
00073     if (time >= m_end) {
00074         return Duration::zeroDuration;
00075     }
00076     DateTime s = (time > m_start ? time : m_start);
00077     return (m_end - s) * m_load / 100;
00078 }
00079 
00080 bool AppointmentInterval::loadXML(QDomElement &element) {
00081     //kdDebug()<<k_funcinfo<<endl;
00082     bool ok;
00083     QString s = element.attribute("start");
00084     if (s != "")
00085         m_start = DateTime::fromString(s);
00086     s = element.attribute("end");
00087     if (s != "")
00088         m_end = DateTime::fromString(s);
00089     m_load = element.attribute("load", "100").toDouble(&ok);
00090     if (!ok) m_load = 100;
00091     return m_start.isValid() && m_end.isValid();
00092 }
00093 
00094 void AppointmentInterval::saveXML(QDomElement &element) const {
00095     QDomElement me = element.ownerDocument().createElement("interval");
00096     element.appendChild(me);
00097 
00098     me.setAttribute("start", m_start.toString(Qt::ISODate));
00099     me.setAttribute("end", m_end.toString(Qt::ISODate));
00100     me.setAttribute("load", m_load);
00101 }
00102 
00103 bool AppointmentInterval::isValid() const {
00104     return m_start.isValid() && m_end.isValid();
00105 }
00106 
00107 AppointmentInterval AppointmentInterval::firstInterval(const AppointmentInterval &interval, const DateTime &from) const {
00108     //kdDebug()<<k_funcinfo<<interval.startTime().toString()<<" - "<<interval.endTime().toString()<<" from="<<from.toString()<<endl;
00109     DateTime f = from;
00110     DateTime s1 = m_start;
00111     DateTime e1 = m_end;
00112     DateTime s2 = interval.startTime();
00113     DateTime e2 = interval.endTime();
00114     AppointmentInterval a;
00115     if (f.isValid() && f >= e1 && f >= e2) {
00116         return a;
00117     }
00118     if (f.isValid()) {
00119         if (s1 < f && f < e1) {
00120             s1 = f;
00121         }
00122         if (s2 < f && f < e2) {
00123             s2 = f;
00124         }
00125     } else {
00126         f = s1 < s2 ? s1 : s2;
00127     }
00128     if (s1 < s2) {
00129         a.setStartTime(s1);
00130         if (e1 <= s2) {
00131             a.setEndTime(e1);
00132         } else {
00133             a.setEndTime(s2);
00134         }
00135         a.setLoad(m_load);
00136     } else if (s1 > s2) {
00137         a.setStartTime(s2);
00138         if (e2 <= s1) {
00139             a.setEndTime(e2);
00140         } else {
00141             a.setEndTime(s1);
00142         }
00143         a.setLoad(interval.load());
00144     } else {
00145         a.setStartTime(s1);
00146         if (e1 <= e2)
00147             a.setEndTime(e1);
00148         else 
00149             a.setEndTime(e2);
00150         a.setLoad(m_load + interval.load());
00151     }
00152     //kdDebug()<<k_funcinfo<<a.startTime().toString()<<" - "<<a.endTime().toString()<<" load="<<a.load()<<endl;
00153     return a;
00154 }
00155 
00157 
00158 Appointment::UsedEffortItem::UsedEffortItem(QDate date, Duration effort, bool overtime) {
00159     m_date = date;
00160     m_effort = effort;
00161     m_overtime = overtime;
00162 }
00163 QDate Appointment::UsedEffortItem::date() { 
00164     return m_date; 
00165 }
00166 Duration Appointment::UsedEffortItem::effort() {
00167     return m_effort; 
00168 }
00169 bool Appointment::UsedEffortItem::isOvertime() { 
00170     return m_overtime; 
00171 }
00172 
00173 Appointment::UsedEffort::UsedEffort() { 
00174     setAutoDelete(true); 
00175 }
00176 
00177 void Appointment::UsedEffort::inSort(QDate date, Duration effort, bool overtime) {
00178     UsedEffortItem *item = new UsedEffortItem(date, effort, overtime);
00179     QPtrList<UsedEffortItem>::inSort(item);
00180 }
00181 
00182 Duration Appointment::UsedEffort::usedEffort(bool includeOvertime) const {
00183     Duration eff;
00184     QPtrListIterator<UsedEffortItem> it(*this);
00185     for (; it.current(); ++it) {
00186         if (includeOvertime || !it.current()->isOvertime()) {
00187             eff += it.current()->effort();
00188         }
00189     }
00190     return eff;
00191 }
00192         
00193 Duration Appointment::UsedEffort::usedEffort(const QDate &date, bool includeOvertime) const {
00194     Duration eff;
00195     QPtrListIterator<UsedEffortItem> it(*this);
00196     for (; it.current(); ++it) {
00197         if ((includeOvertime || !it.current()->isOvertime()) && 
00198             it.current()->date() == date) {
00199             eff += it.current()->effort();
00200         }
00201     }
00202     return eff;
00203 }
00204 
00205 Duration Appointment::UsedEffort::usedEffortTo(const QDate &date, bool includeOvertime) const {
00206     Duration eff;
00207     QPtrListIterator<UsedEffortItem> it(*this);
00208     for (; it.current(); ++it) {
00209         if ((includeOvertime || !it.current()->isOvertime()) && 
00210             it.current()->date() <= date) {
00211             eff += it.current()->effort();
00212         }
00213     }
00214     return eff;
00215 }
00216 
00217 Duration Appointment::UsedEffort::usedOvertime() const {
00218     UsedEffortItem *item = getFirst();
00219     return item==0 ? Duration::zeroDuration : usedOvertime(item->date());
00220 }
00221 
00222 Duration Appointment::UsedEffort::usedOvertime(const QDate &date) const {
00223     Duration eff;
00224     QPtrListIterator<UsedEffortItem> it(*this);
00225     for (; it.current(); ++it) {
00226         if (it.current()->isOvertime() && it.current()->date() == date) {
00227             eff += it.current()->effort();
00228         }
00229     }
00230     return eff;
00231 }
00232 
00233 Duration Appointment::UsedEffort::usedOvertimeTo(const QDate &date) const {
00234     Duration eff;
00235     QPtrListIterator<UsedEffortItem> it(*this);
00236     for (; it.current(); ++it) {
00237         if (it.current()->isOvertime() && it.current()->date() <= date) {
00238             eff += it.current()->effort();
00239         }
00240     }
00241     return eff;
00242 }
00243 
00244 bool Appointment::UsedEffort::load(QDomElement &element) {
00245     QString s;
00246     QDomNodeList list = element.childNodes();
00247     for (unsigned int i=0; i<list.count(); ++i) {
00248         if (list.item(i).isElement()) {
00249             QDomElement e = list.item(i).toElement();
00250             if (e.tagName() == "actual-effort") {
00251                 QDate date;
00252                 s = e.attribute("date");
00253                 if (s != "")
00254                     date = QDate::fromString(s, Qt::ISODate);
00255                 Duration eff = Duration::fromString(e.attribute("effort"));
00256                 bool ot = e.attribute("overtime", "0").toInt();
00257                 if (date.isValid()) {
00258                     inSort(date, eff, ot);
00259                 } else {
00260                     kdError()<<k_funcinfo<<"Load failed, illegal date: "<<e.attribute("date")<<endl;
00261                 }
00262             }
00263         }   
00264     }
00265     return true;
00266 }
00267 
00268 void Appointment::UsedEffort::save(QDomElement &element) const {
00269     if (isEmpty()) return;
00270     QPtrListIterator<UsedEffortItem> it = *this;
00271     for (; it.current(); ++it) {
00272         QDomElement me = element.ownerDocument().createElement("actual-effort");
00273         element.appendChild(me);
00274         me.setAttribute("date",it.current()->date().toString(Qt::ISODate));
00275         me.setAttribute("effort",it.current()->effort().toString());
00276         me.setAttribute("overtime",it.current()->isOvertime());
00277     }
00278 }
00279 
00280 int Appointment::UsedEffort::compareItems(QPtrCollection::Item item1, QPtrCollection::Item item2) {
00281     QDate d1 = static_cast<UsedEffortItem*>(item1)->date();
00282     QDate d2 = static_cast<UsedEffortItem*>(item2)->date();
00283     if (d1 > d2) return 1;
00284     if (d1 < d2) return -1;
00285     return 0;
00286 }
00287 
00289 Appointment::Appointment() 
00290     : m_extraRepeats(), m_skipRepeats() {
00291     //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
00292     m_resource=0;
00293     m_node=0;
00294     m_repeatInterval=Duration();
00295     m_repeatCount=0;
00296 
00297     m_intervals.setAutoDelete(true);
00298 }
00299 
00300 Appointment::Appointment(Schedule *resource, Schedule *node, DateTime start, DateTime end, double load) 
00301     : m_extraRepeats(), 
00302       m_skipRepeats() {
00303     //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
00304     m_node = node;
00305     m_resource = resource;
00306     m_repeatInterval = Duration();
00307     m_repeatCount = 0;
00308 
00309     addInterval(start, end, load);
00310 
00311     m_intervals.setAutoDelete(true);
00312 }
00313 
00314 Appointment::Appointment(Schedule *resource, Schedule *node, DateTime start, Duration duration, double load) 
00315     : m_extraRepeats(), 
00316       m_skipRepeats() {
00317     //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
00318     m_node = node;
00319     m_resource = resource;
00320     m_repeatInterval = Duration();
00321     m_repeatCount = 0;
00322 
00323     addInterval(start, duration, load);
00324     
00325     m_intervals.setAutoDelete(true);
00326 }
00327 
00328 Appointment::~Appointment() {
00329     //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
00330     detach();
00331 }
00332 
00333 void Appointment::addInterval(AppointmentInterval *a) {
00334     //kdDebug()<<k_funcinfo<<m_resource->name()<<" to "<<m_node->name()<<endl;
00335     m_intervals.inSort(a);
00336 }
00337 void Appointment::addInterval(const DateTime &start, const DateTime &end, double load) {
00338     addInterval(new AppointmentInterval(start, end, load));
00339 }
00340 void Appointment::addInterval(const DateTime &start, const Duration &duration, double load) {
00341     DateTime e = start+duration;
00342     addInterval(start, e, load);
00343 }
00344 
00345 double Appointment::maxLoad() const {
00346     double v = 0.0;
00347     QPtrListIterator<AppointmentInterval> it = m_intervals;
00348     for (; it.current(); ++it) {
00349         if (v < it.current()->load())
00350             v = it.current()->load();
00351     }
00352     return v;
00353 }
00354 
00355 DateTime Appointment::startTime() const {
00356     DateTime t;
00357     QPtrListIterator<AppointmentInterval> it = m_intervals;
00358     for (; it.current(); ++it) {
00359         if (!t.isValid() || t > it.current()->startTime())
00360             t = it.current()->startTime();
00361     }
00362     return t;
00363 }
00364 
00365 DateTime Appointment::endTime() const {
00366     DateTime t;
00367     QPtrListIterator<AppointmentInterval> it = m_intervals;
00368     for (; it.current(); ++it) {
00369         if (!t.isValid() || t < it.current()->endTime())
00370             t = it.current()->endTime();
00371     }
00372     return t;
00373 }
00374 
00375 void Appointment::deleteAppointmentFromRepeatList(DateTime) {
00376 }
00377 
00378 void Appointment::addAppointmentToRepeatList(DateTime) {
00379 }
00380 
00381 bool Appointment::isBusy(const DateTime &/*start*/, const DateTime &/*end*/) {
00382     return false;
00383 }
00384 
00385 bool Appointment::loadXML(QDomElement &element, Project &project, Schedule &sch) {
00386     //kdDebug()<<k_funcinfo<<endl;
00387     QDictIterator<Node> it = project.nodeDict();
00388 /*    for (; it.current(); ++it) {
00389         kdDebug()<<" Node="<<it.current()->name()<<" id="<<it.currentKey()<<endl;
00390     }*/
00391     Node *node = project.findNode(element.attribute("task-id"));
00392     if (node == 0) {
00393         kdError()<<k_funcinfo<<"The referenced task does not exists: "<<element.attribute("task-id")<<endl;
00394         return false;
00395     }
00396     Resource *res = project.resource(element.attribute("resource-id"));
00397     if (res == 0) {
00398         kdError()<<k_funcinfo<<"The referenced resource does not exists: resource id="<<element.attribute("resource-id")<<endl;
00399         return false;
00400     }
00401     if (!res->addAppointment(this, sch)) {
00402         kdError()<<k_funcinfo<<"Failed to add appointment to resource: "<<res->name()<<endl;
00403         return false;
00404     }
00405     if (!node->addAppointment(this, sch)) {
00406         kdError()<<k_funcinfo<<"Failed to add appointment to node: "<<node->name()<<endl;
00407         m_resource->takeAppointment(this);
00408         return false;
00409     }
00410     //kdDebug()<<k_funcinfo<<"res="<<m_resource<<" node="<<m_node<<endl;
00411     QDomNodeList list = element.childNodes();
00412     for (unsigned int i=0; i<list.count(); ++i) {
00413         if (list.item(i).isElement()) {
00414             QDomElement e = list.item(i).toElement();
00415             if (e.tagName() == "interval") {
00416             AppointmentInterval *a = new AppointmentInterval();
00417                 if (a->loadXML(e)) {
00418                     addInterval(a);
00419                 } else {
00420                     kdError()<<k_funcinfo<<"Could not load interval"<<endl;
00421                     delete a;
00422                 }
00423             }
00424         }
00425     }
00426     if (m_intervals.isEmpty()) {
00427         return false; 
00428     }
00429     m_actualEffort.load(element);
00430     return true;
00431 }
00432 
00433 void Appointment::saveXML(QDomElement &element) const {
00434     if (m_intervals.isEmpty()) {
00435         kdError()<<k_funcinfo<<"Incomplete appointment data: No intervals"<<endl;
00436     }
00437     if (m_resource == 0 || m_resource->resource() == 0) {
00438         kdError()<<k_funcinfo<<"Incomplete appointment data: No resource"<<endl;
00439         return;
00440     }
00441     if (m_node == 0 || m_node->node() == 0) {
00442         kdError()<<k_funcinfo<<"Incomplete appointment data: No node"<<endl;
00443         return; // shouldn't happen
00444     }
00445     //kdDebug()<<k_funcinfo<<endl;
00446     QDomElement me = element.ownerDocument().createElement("appointment");
00447     element.appendChild(me);
00448 
00449     me.setAttribute("resource-id", m_resource->resource()->id());
00450     me.setAttribute("task-id", m_node->node()->id());
00451     QPtrListIterator<AppointmentInterval> it = m_intervals;
00452     for (; it.current(); ++it) {
00453         it.current()->saveXML(me);
00454     }
00455     m_actualEffort.save(me);
00456 }
00457 
00458 // Returns the total actual effort for this appointment
00459 Duration Appointment::plannedEffort() const {
00460     Duration d;
00461     QPtrListIterator<AppointmentInterval> it = m_intervals;
00462     for (; it.current(); ++it) {
00463         d += it.current()->effort();
00464     }
00465     return d;
00466 }
00467 
00468 // Returns the planned effort on the date
00469 Duration Appointment::plannedEffort(const QDate &date) const {
00470     Duration d;
00471     DateTime s(date);
00472     DateTime e(date.addDays(1));
00473     QPtrListIterator<AppointmentInterval> it = m_intervals;
00474     for (; it.current(); ++it) {
00475         d += it.current()->effort(s, e);
00476     }
00477     return d;
00478 }
00479 
00480 // Returns the planned effort upto and including the date
00481 Duration Appointment::plannedEffortTo(const QDate& date) const {
00482     Duration d;
00483     DateTime e(date.addDays(1));
00484     QPtrListIterator<AppointmentInterval> it = m_intervals;
00485     for (; it.current(); ++it) {
00486         d += it.current()->effort(e, true);
00487     }
00488     return d;
00489 }
00490 
00491 // Returns a list of efforts pr day for interval start, end inclusive
00492 // The list only includes days with any planned effort
00493 EffortCostMap Appointment::plannedPrDay(const QDate& start, const QDate& end) const {
00494     //kdDebug()<<k_funcinfo<<m_node->id()<<", "<<m_resource->id()<<endl;
00495     EffortCostMap ec;
00496     Duration eff;
00497     DateTime dt(start);
00498     DateTime ndt(dt.addDays(1));
00499     double rate = m_resource->normalRatePrHour();
00500     AppointmentIntervalListIterator it = m_intervals;
00501     for (; it.current(); ++it) {
00502         DateTime st = it.current()->startTime();
00503         DateTime e = it.current()->endTime();
00504         if (end < st.date())
00505             break;
00506         if (dt.date() < st.date()) {
00507             dt.setDate(st.date());
00508         }
00509         ndt = dt.addDays(1);
00510         while (dt.date() <= e.date()) {
00511             eff = it.current()->effort(dt, ndt);
00512             ec.add(dt.date(), eff, eff.toDouble(Duration::Unit_h) * rate);
00513             if (dt.date() < e.date() ) {
00514                 // loop trough the interval (it spans dates)
00515                 dt = ndt;
00516                 ndt = ndt.addDays(1);
00517             } else {
00518                 break;
00519             }
00520         }
00521     }
00522     return ec;
00523 }
00524 
00525 
00526 // Returns the total actual effort for this appointment
00527 Duration Appointment::actualEffort() const {
00528     return m_actualEffort.usedEffort();
00529 }
00530 
00531 // Returns the actual effort on the date
00532 Duration Appointment::actualEffort(const QDate &date) const {
00533     return m_actualEffort.usedEffort(date);
00534 }
00535 
00536 // Returns the actual effort upto and including date
00537 Duration Appointment::actualEffortTo(const QDate &date) const {
00538     return m_actualEffort.usedEffortTo(date);
00539 }
00540 
00541 double Appointment::plannedCost() {
00542     if (m_resource && m_resource->resource()) {
00543         return plannedEffort().toDouble(Duration::Unit_h) * m_resource->resource()->normalRate(); //FIXME overtime
00544     }
00545     return 0.0;
00546 }
00547 
00548 //Calculates the planned cost on date
00549 double Appointment::plannedCost(const QDate &date) {
00550     if (m_resource && m_resource->resource()) {
00551         return plannedEffort(date).toDouble(Duration::Unit_h) * m_resource->resource()->normalRate(); //FIXME overtime
00552     }
00553     return 0.0;
00554 }
00555 
00556 //Calculates the planned cost upto and including date
00557 double Appointment::plannedCostTo(const QDate &date) {
00558     if (m_resource && m_resource->resource()) {
00559         return plannedEffortTo(date).toDouble(Duration::Unit_h) * m_resource->resource()->normalRate(); //FIXME overtime
00560     }
00561     return 0.0;
00562 }
00563 
00564 // Calculates the total actual cost for this appointment
00565 double Appointment::actualCost() {
00566     //kdDebug()<<k_funcinfo<<m_actualEffort.usedEffort(false /*ex. overtime*/).toDouble(Duration::Unit_h)<<endl;
00567     if (m_resource && m_resource->resource()) {
00568         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());
00569     }
00570     return 0.0;
00571 }
00572 
00573 // Calculates the actual cost on date
00574 double Appointment::actualCost(const QDate &date) {
00575     if (m_resource && m_resource->resource()) {
00576         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());
00577     }
00578     return 0.0;
00579 }
00580 
00581 // Calculates the actual cost upto and including date
00582 double Appointment::actualCostTo(const QDate &date) {
00583     if (m_resource && m_resource->resource()) {
00584         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());
00585     }
00586     return 0.0;
00587 }
00588 
00589 void Appointment::addActualEffort(QDate date, Duration effort, bool overtime) {
00590     m_actualEffort.inSort(date, effort, overtime);
00591 }
00592 
00593 bool Appointment::attach() { 
00594     //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
00595     if (m_resource && m_node) {
00596         m_resource->add(this);
00597         m_node->add(this);
00598         return true;
00599     }
00600     kdWarning()<<k_funcinfo<<"Failed: "<<(m_resource ? "" : "resource=0 ") 
00601                                        <<(m_node ? "" : "node=0")<<endl;
00602     return false;
00603 }
00604 
00605 void Appointment::detach() {
00606     //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
00607     if (m_resource) {
00608         m_resource->takeAppointment(this); // takes from node also
00609     }
00610     if (m_node) {
00611         m_node->takeAppointment(this); // to make it robust
00612     }
00613 }
00614 
00615 // Returns the effort from start to end
00616 Duration Appointment::effort(const DateTime &start, const DateTime &end) const {
00617     Duration d;
00618     QPtrListIterator<AppointmentInterval> it = m_intervals;
00619     for (; it.current(); ++it) {
00620         d += it.current()->effort(start, end);
00621     }
00622     return d;
00623 }
00624 // Returns the effort from start for the duration
00625 Duration Appointment::effort(const DateTime &start, const Duration &duration) const {
00626     Duration d;
00627     QPtrListIterator<AppointmentInterval> it = m_intervals;
00628     for (; it.current(); ++it) {
00629         d += it.current()->effort(start, start+duration);
00630     }
00631     return d;
00632 }
00633 // Returns the effort upto time / from time 
00634 Duration Appointment::effortFrom(const DateTime &time) const {
00635     Duration d;
00636     QPtrListIterator<AppointmentInterval> it = m_intervals;
00637     for (; it.current(); ++it) {
00638         d += it.current()->effort(time, false);
00639     }
00640     return d;
00641 }
00642 
00643 Appointment &Appointment::operator=(const Appointment &app) {
00644     m_resource = app.resource();
00645     m_node = app.node();
00646     m_repeatInterval = app.repeatInterval();
00647     m_repeatCount = app.repeatCount();
00648 
00649     m_intervals.clear();
00650     QPtrListIterator<AppointmentInterval> it = app.intervals();
00651     for (; it.current(); ++it) {
00652         addInterval(new AppointmentInterval(*(it.current())));
00653     }
00654     return *this;
00655 }
00656 
00657 Appointment &Appointment::operator+=(const Appointment &app) {
00658     *this = *this + app;
00659     return *this;
00660 }
00661 
00662 Appointment Appointment::operator+(const Appointment &app) {
00663     Appointment a;
00664     AppointmentIntervalList ai = app.intervals();
00665     AppointmentInterval i;
00666     AppointmentInterval *i1 = m_intervals.first();
00667     AppointmentInterval *i2 = ai.first();
00668     DateTime from;
00669     while (i1 || i2) {
00670         if (!i1) {
00671             if (!from.isValid() || from < i2->startTime())
00672                 from = i2->startTime();
00673             a.addInterval(from, i2->endTime(), i2->load());
00674             //kdDebug()<<"Interval+ (i2): "<<from.toString()<<" - "<<i2->endTime().toString()<<endl;
00675             from = i2->endTime();
00676             i2 = ai.next();
00677             continue;
00678         }
00679         if (!i2) {
00680             if (!from.isValid() || from < i1->startTime())
00681                 from = i1->startTime();
00682             a.addInterval(from, i1->endTime(), i1->load());
00683             //kdDebug()<<"Interval+ (i1): "<<from.toString()<<" - "<<i1->endTime().toString()<<endl;
00684             from = i1->endTime();
00685             i1 = m_intervals.next();
00686             continue;
00687         }
00688         i =  i1->firstInterval(*i2, from);
00689         if (!i.isValid()) {
00690             break;
00691         }
00692         a.addInterval(i);
00693         from = i.endTime();
00694         //kdDebug()<<"Interval+ (i): "<<i.startTime().toString()<<" - "<<i.endTime().toString()<<" load="<<i.load()<<endl;
00695         if (i1 && a.endTime() >= i1->endTime()) {
00696             i1 = m_intervals.next();
00697         }
00698         if (i2 && a.endTime() >= i2->endTime()) {
00699             i2 = ai.next();
00700         }
00701     }
00702     return a;
00703 }
00704 
00705 #ifndef NDEBUG
00706 void Appointment::printDebug(QString indent)
00707 {
00708     bool err = false;
00709     if (m_node == 0) {
00710         kdDebug()<<indent<<"   No node schedule"<<endl;
00711         err = true;
00712     } else if (m_node->node() == 0) {
00713         kdDebug()<<indent<<"   No node"<<endl;
00714         err = true;
00715     }
00716     if (m_resource == 0) {
00717         kdDebug()<<indent<<"   No resource schedule"<<endl;
00718         err = true;
00719     } else if (m_resource->resource() == 0) {
00720         kdDebug()<<indent<<"   No resource"<<endl;
00721         err = true;
00722     }
00723     if (err)
00724         return;
00725     kdDebug()<<indent<<"  + Appointment to schedule: "<<m_node->name()<<" ("<<m_node->type()<<")"<<" resource: "<<m_resource->resource()->name()<<endl;
00726     indent += "  ! ";
00727     QPtrListIterator<AppointmentInterval> it = intervals();
00728     for (; it.current(); ++it) {
00729         kdDebug()<<indent<<it.current()->startTime().toString()<<" - "<<it.current()->endTime().toString()<<" load="<<it.current()->load()<<endl;
00730     }
00731 }
00732 #endif
00733 
00734 }  //KPlato namespace
KDE Home | KDE Accessibility Home | Description of Access Keys