/* This file is part of the KDE project Copyright (C) 2005 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; version 2 of the License. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kptappointment.h" #include "kptproject.h" #include "kpttask.h" #include "kptdatetime.h" #include "kptcalendar.h" #include "kpteffortcostmap.h" #include "kptschedule.h" #include namespace KPlato { class Resource; AppointmentInterval::AppointmentInterval() { m_load = 100.0; } AppointmentInterval::AppointmentInterval(const AppointmentInterval &interval) { //kdDebug()<= m_end || end <= m_start) { return Duration::zeroDuration; } DateTime s = (start > m_start ? start : m_start); DateTime e = (end < m_end ? end : m_end); return (e - s) * m_load / 100; } Duration AppointmentInterval::effort(const DateTime &time, bool upto) const { if (upto) { if (time <= m_start) { return Duration::zeroDuration; } DateTime e = (time < m_end ? time : m_end); return (e - m_start) * m_load / 100; } // from time till end if (time >= m_end) { return Duration::zeroDuration; } DateTime s = (time > m_start ? time : m_start); return (m_end - s) * m_load / 100; } bool AppointmentInterval::loadXML(QDomElement &element) { //kdDebug()< it = *this; for (; it.current(); ++it) { QDomElement me = element.ownerDocument().createElement("actual-effort"); element.appendChild(me); me.setAttribute("date",it.current()->date().toString(Qt::ISODate)); me.setAttribute("effort",it.current()->effort().toString()); me.setAttribute("overtime",it.current()->isOvertime()); } } int Appointment::UsedEffort::compareItems(QPtrCollection::Item item1, QPtrCollection::Item item2) { QDate d1 = static_cast(item1)->date(); QDate d2 = static_cast(item2)->date(); if (d1 > d2) return 1; if (d1 < d2) return -1; return 0; } //// Appointment::Appointment() : m_extraRepeats(), m_skipRepeats() { //kdDebug()<name()<<" to "<name()< it = m_intervals; for (; it.current(); ++it) { if (v < it.current()->load()) v = it.current()->load(); } return v; } DateTime Appointment::startTime() const { DateTime t; QPtrListIterator it = m_intervals; for (; it.current(); ++it) { if (!t.isValid() || t > it.current()->startTime()) t = it.current()->startTime(); } return t; } DateTime Appointment::endTime() const { DateTime t; QPtrListIterator it = m_intervals; for (; it.current(); ++it) { if (!t.isValid() || t < it.current()->endTime()) t = it.current()->endTime(); } return t; } void Appointment::deleteAppointmentFromRepeatList(DateTime) { } void Appointment::addAppointmentToRepeatList(DateTime) { } bool Appointment::isBusy(const DateTime &/*start*/, const DateTime &/*end*/) { return false; } bool Appointment::loadXML(QDomElement &element, Project &project, Schedule &sch) { //kdDebug()< it = project.nodeDict(); /* for (; it.current(); ++it) { kdDebug()<<" Node="<name()<<" id="<addAppointment(this, sch)) { kdError()<name()<addAppointment(this, sch)) { kdError()<name()<takeAppointment(this); return false; } //kdDebug()<loadXML(e)) { addInterval(a); } else { kdError()<resource() == 0) { kdError()<node() == 0) { kdError()<resource()->id()); me.setAttribute("task-id", m_node->node()->id()); QPtrListIterator it = m_intervals; for (; it.current(); ++it) { it.current()->saveXML(me); } m_actualEffort.save(me); } // Returns the total actual effort for this appointment Duration Appointment::plannedEffort() const { Duration d; QPtrListIterator it = m_intervals; for (; it.current(); ++it) { d += it.current()->effort(); } return d; } // Returns the planned effort on the date Duration Appointment::plannedEffort(const QDate &date) const { Duration d; DateTime s(date); DateTime e(date.addDays(1)); QPtrListIterator it = m_intervals; for (; it.current(); ++it) { d += it.current()->effort(s, e); } return d; } // Returns the planned effort upto and including the date Duration Appointment::plannedEffortTo(const QDate& date) const { Duration d; DateTime e(date.addDays(1)); QPtrListIterator it = m_intervals; for (; it.current(); ++it) { d += it.current()->effort(e, true); } return d; } // Returns a list of efforts pr day for interval start, end inclusive // The list only includes days with any planned effort EffortCostMap Appointment::plannedPrDay(const QDate& start, const QDate& end) const { //kdDebug()<id()<<", "<id()<normalRatePrHour(); AppointmentIntervalListIterator it = m_intervals; for (; it.current(); ++it) { DateTime st = it.current()->startTime(); DateTime e = it.current()->endTime(); if (end < st.date()) break; if (dt.date() < st.date()) { dt.setDate(st.date()); } ndt = dt.addDays(1); while (dt.date() <= e.date()) { eff = it.current()->effort(dt, ndt); ec.add(dt.date(), eff, eff.toDouble(Duration::Unit_h) * rate); if (dt.date() < e.date() ) { // loop trough the interval (it spans dates) dt = ndt; ndt = ndt.addDays(1); } else { break; } } } return ec; } // Returns the total actual effort for this appointment Duration Appointment::actualEffort() const { return m_actualEffort.usedEffort(); } // Returns the actual effort on the date Duration Appointment::actualEffort(const QDate &date) const { return m_actualEffort.usedEffort(date); } // Returns the actual effort upto and including date Duration Appointment::actualEffortTo(const QDate &date) const { return m_actualEffort.usedEffortTo(date); } double Appointment::plannedCost() { if (m_resource && m_resource->resource()) { return plannedEffort().toDouble(Duration::Unit_h) * m_resource->resource()->normalRate(); //FIXME overtime } return 0.0; } //Calculates the planned cost on date double Appointment::plannedCost(const QDate &date) { if (m_resource && m_resource->resource()) { return plannedEffort(date).toDouble(Duration::Unit_h) * m_resource->resource()->normalRate(); //FIXME overtime } return 0.0; } //Calculates the planned cost upto and including date double Appointment::plannedCostTo(const QDate &date) { if (m_resource && m_resource->resource()) { return plannedEffortTo(date).toDouble(Duration::Unit_h) * m_resource->resource()->normalRate(); //FIXME overtime } return 0.0; } // Calculates the total actual cost for this appointment double Appointment::actualCost() { //kdDebug()<resource()) { 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()); } return 0.0; } // Calculates the actual cost on date double Appointment::actualCost(const QDate &date) { if (m_resource && m_resource->resource()) { 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()); } return 0.0; } // Calculates the actual cost upto and including date double Appointment::actualCostTo(const QDate &date) { if (m_resource && m_resource->resource()) { 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()); } return 0.0; } void Appointment::addActualEffort(QDate date, Duration effort, bool overtime) { m_actualEffort.inSort(date, effort, overtime); } bool Appointment::attach() { //kdDebug()<add(this); m_node->add(this); return true; } kdWarning()<takeAppointment(this); // takes from node also } if (m_node) { m_node->takeAppointment(this); // to make it robust } } // Returns the effort from start to end Duration Appointment::effort(const DateTime &start, const DateTime &end) const { Duration d; QPtrListIterator it = m_intervals; for (; it.current(); ++it) { d += it.current()->effort(start, end); } return d; } // Returns the effort from start for the duration Duration Appointment::effort(const DateTime &start, const Duration &duration) const { Duration d; QPtrListIterator it = m_intervals; for (; it.current(); ++it) { d += it.current()->effort(start, start+duration); } return d; } // Returns the effort upto time / from time Duration Appointment::effortFrom(const DateTime &time) const { Duration d; QPtrListIterator it = m_intervals; for (; it.current(); ++it) { d += it.current()->effort(time, false); } return d; } Appointment &Appointment::operator=(const Appointment &app) { m_resource = app.resource(); m_node = app.node(); m_repeatInterval = app.repeatInterval(); m_repeatCount = app.repeatCount(); m_intervals.clear(); QPtrListIterator it = app.intervals(); for (; it.current(); ++it) { addInterval(new AppointmentInterval(*(it.current()))); } return *this; } Appointment &Appointment::operator+=(const Appointment &app) { *this = *this + app; return *this; } Appointment Appointment::operator+(const Appointment &app) { Appointment a; AppointmentIntervalList ai = app.intervals(); AppointmentInterval i; AppointmentInterval *i1 = m_intervals.first(); AppointmentInterval *i2 = ai.first(); DateTime from; while (i1 || i2) { if (!i1) { if (!from.isValid() || from < i2->startTime()) from = i2->startTime(); a.addInterval(from, i2->endTime(), i2->load()); //kdDebug()<<"Interval+ (i2): "<endTime().toString()<endTime(); i2 = ai.next(); continue; } if (!i2) { if (!from.isValid() || from < i1->startTime()) from = i1->startTime(); a.addInterval(from, i1->endTime(), i1->load()); //kdDebug()<<"Interval+ (i1): "<endTime().toString()<endTime(); i1 = m_intervals.next(); continue; } i = i1->firstInterval(*i2, from); if (!i.isValid()) { break; } a.addInterval(i); from = i.endTime(); //kdDebug()<<"Interval+ (i): "<node() == 0) { kdDebug()<resource() == 0) { kdDebug()<name()<<" ("<type()<<")"<<" resource: "<resource()->name()< it = intervals(); for (; it.current(); ++it) { kdDebug()<startTime().toString()<<" - "<endTime().toString()<<" load="<load()<