/* This file is part of the KDE project Copyright (C) 2001 Thomas zander Copyright (C) 2004, 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; either version 2 of the License, or (at your option) any later version. 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 "kptresource.h" #include "kptappointment.h" #include "kptproject.h" #include "kpttask.h" #include "kptdatetime.h" #include "kptcalendar.h" #include "kpteffortcostmap.h" #include "kptschedule.h" #include #include #include namespace KPlato { ResourceGroup::ResourceGroup(Project *project) { m_project = project; m_type = Type_Work; m_resources.setAutoDelete(true); generateId(); //kdDebug()<name()<name()<load(e)) addResource(child, 0); else // TODO: Complain about this delete child; } } } return true; } void ResourceGroup::save(TQDomElement &element) const { //kdDebug()< it(m_resources); for ( ; it.current(); ++it ) { it.current()->save(me); } } void ResourceGroup::initiateCalculation(Schedule &sch) { TQPtrListIterator it(m_resources); for (; it.current(); ++it) { it.current()->initiateCalculation(sch); } clearNodes(); } int ResourceGroup::units() { int u = 0; TQPtrListIterator it = m_resources; for (; it.current(); ++it) { u += it.current()->units(); } return u; } ResourceGroup *ResourceGroup::findId(const TQString &id) const { return m_project ? m_project->findResourceGroup(id) : 0; } bool ResourceGroup::removeId(const TQString &id) { return m_project ? m_project->removeResourceGroupId(id): false; } void ResourceGroup::insertId(const TQString &id) { if (m_project) m_project->insertResourceGroupId(id, this); } Appointment ResourceGroup::appointmentIntervals() const { Appointment a; TQPtrListIterator it = m_resources; for (; it.current(); ++it) { a += it.current()->appointmentIntervals(); } return a; } Resource::Resource(Project *project) : m_project(project), m_schedules(), m_workingHours() { m_type = Type_Work; m_units = 100; // % m_availableFrom = DateTime(TQDate::tqcurrentDate()); m_availableUntil = TQDateTime(m_availableFrom.addYears(2)); cost.normalRate = 100; cost.overtimeRate = 200; cost.fixed = 0; m_calendar = 0; m_currentSchedule = 0; generateId(); //kdDebug()< it = m_requests; for (; it.current(); ++it) { it.current()->setResource(0); // avoid the request to mess with my list } m_requests.first(); for (; m_requests.current(); m_requests.next()) { m_requests.current()->tqparent()->removeResourceRequest(m_requests.current()); // deletes the request } } bool Resource::setId(TQString id) { //kdDebug()<name()<name()<project(); //m_appointments = resource->appointments(); // Note m_id = resource->id(); m_name = resource->name(); m_initials = resource->initials(); m_email = resource->email(); m_availableFrom = resource->availableFrom(); m_availableUntil = resource->availableUntil(); m_workingHours.clear(); m_workingHours = resource->workingHours(); m_units = resource->units(); // available units in percent m_type = resource->type(); cost.normalRate = resource->normalRate(); cost.overtimeRate = resource->overtimeRate(); cost.fixed = resource->fixedCost(); m_calendar = resource->m_calendar; } void Resource::addWorkingHour(TQTime from, TQTime until) { //kdDebug()<isDeleted())) { return project()->defaultCalendar(); } if (m_calendar && m_calendar->isDeleted()) { return 0; } return m_calendar; } DateTime Resource::getFirstAvailableTime(DateTime /*after*/) { return DateTime(); } DateTime Resource::getBestAvailableTime(Duration /*duration*/) { return DateTime(); } DateTime Resource::getBestAvailableTime(const DateTime /*after*/, const Duration /*duration*/) { return DateTime(); } bool Resource::load(TQDomElement &element) { //kdDebug()<readMoney(element.attribute("normal-rate")); cost.overtimeRate = KGlobal::locale()->readMoney(element.attribute("overtime-rate")); return true; } void Resource::save(TQDomElement &element) const { //kdDebug()<id()); me.setAttribute("id", m_id); me.setAttribute("name", m_name); me.setAttribute("initials", m_initials); me.setAttribute("email", m_email); me.setAttribute("type", typeToString()); me.setAttribute("units", m_units); me.setAttribute("available-from", m_availableFrom.toString(Qt::ISODate)); me.setAttribute("available-until", m_availableUntil.toString(Qt::ISODate)); me.setAttribute("normal-rate", KGlobal::locale()->formatMoney(cost.normalRate)); me.setAttribute("overtime-rate", KGlobal::locale()->formatMoney(cost.overtimeRate)); } bool Resource::isAvailable(Task */*task*/) { bool busy = false; /* TQPtrListIterator it(m_appointments); for (; it.current(); ++it) { if (it.current()->isBusy(task->startTime(), task->endTime())) { busy = true; break; } }*/ return !busy; } TQPtrList Resource::appointments() { TQPtrList lst; if (m_currentSchedule) lst = m_currentSchedule->appointments(); //kdDebug()< it = m_appointments; for (; it.current(); ++it) { if (it.current()->node() == node) return it.current(); }*/ return 0; } bool Resource::addAppointment(Appointment *appointment) { if (m_currentSchedule) return m_currentSchedule->add(appointment); return false; } bool Resource::addAppointment(Appointment *appointment, Schedule &main) { Schedule *s = findSchedule(main.id()); if (s == 0) { s = createSchedule(&main); } appointment->setResource(s); return s->add(appointment); } void Resource::addAppointment(Schedule *node, DateTime &start, DateTime &end, double load) { //kdDebug()<id()); if (s == 0) { s = createSchedule(node->tqparent()); } s->addAppointment(node, start, end, load); } void Resource::initiateCalculation(Schedule &sch) { m_currentSchedule = createSchedule(&sch); } void Resource::removeSchedule(Schedule *schedule) { takeSchedule(schedule); delete schedule; } void Resource::takeSchedule(const Schedule *schedule) { if (schedule == 0) return; if (m_currentSchedule == schedule) m_currentSchedule = 0; m_schedules.take(schedule->id()); } void Resource::addSchedule(Schedule *schedule) { if (schedule == 0) return; m_schedules.tqreplace(schedule->id(), schedule); } ResourceSchedule *Resource::createSchedule(TQString name, int type, long id) { ResourceSchedule *sch = new ResourceSchedule(this, name, (Schedule::Type)type, id); addSchedule(sch); return sch; } ResourceSchedule *Resource::createSchedule(Schedule *tqparent) { ResourceSchedule *sch = new ResourceSchedule(tqparent, this); addSchedule(sch); return sch; } void Resource::makeAppointment(Schedule *node, const DateTime &from, const DateTime &end) { if (!from.isValid() || !end.isValid()) { kdWarning()<hasInterval(time, end)) { //kdDebug()<resourceNotAvailable = true; return; // nothing more to do } TQPair i = cal->firstInterval(time, end); if (!i.second.isValid()) { kdWarning()<workStartTime.isValid()) || i.first < node->workStartTime) node->workStartTime = i.first; if (!(node->workEndTime.isValid()) || i.second > node->workEndTime) node->workEndTime = i.second; time = i.second; } return; } void Resource::makeAppointment(Schedule *node) { //kdDebug()<node()->name()<<": "<startTime.toString()<<" dur "<duration.toString()<startTime.isValid()) { kdWarning()<endTime.isValid()) { kdWarning()<startTime, node->endTime); DateTime end = availableBefore(node->endTime, node->startTime); if (!from.isValid() || !end.isValid()) { return; } if (cal == 0) { // Allocate the whole period addAppointment(node, from, end, m_units); return; } makeAppointment(node, from, end); } if (!cal) { kdWarning()<startTime; DateTime end = node->endTime; time = availableAfter(time, end); if (!time.isValid()) { kdWarning()<resourceNotAvailable = true; return; } end = availableBefore(end, time); if (!end.isValid()) { kdWarning()<resourceNotAvailable = true; return; } //kdDebug()<effort(limit, t) * m_units)/100; } else { //kdDebug()<effort(t, limit) * m_units)/100; } } //kdDebug()<= lmt) { return t; } if (type() == Type_Material) { t = time > m_availableFrom ? time : m_availableFrom; //kdDebug()< time ? m_availableFrom : time; t = cal->firstAvailableAfter(t, lmt); if (checkAppointments) { //TODO } //kdDebug()< lmt) { lmt = limit; } if (time <= lmt) { return t; } if (type() == Type_Material) { t = time < m_availableUntil ? time : m_availableUntil; //kdDebug()<firstAvailableBefore(t, lmt); if (checkAppointments) { //TODO } //kdDebug()<findResource(id) : 0; } bool Resource::removeId(const TQString &id) { return m_project ? m_project->removeResourceId(id) : false; } void Resource::insertId(const TQString &id) { if (m_project) m_project->insertResourceId(id, this); } Calendar *Resource::findCalendar(const TQString &id) const { return (m_project ? m_project->findCalendar(id) : 0); } bool Resource::isOverbooked() const { return isOverbooked(DateTime(), DateTime()); } bool Resource::isOverbooked(const TQDate &date) const { return isOverbooked(DateTime(date), DateTime(date.addDays(1))); } bool Resource::isOverbooked(const DateTime &start, const DateTime &end) const { //kdDebug()<isOverbooked(start, end) : false; } Appointment Resource::appointmentIntervals() const { Appointment a; if (m_currentSchedule == 0) return a; TQPtrListIterator it = m_currentSchedule->appointments(); for (; it.current(); ++it) { a += *(it.current()); } return a; } Duration Resource::plannedEffort(const TQDate &date) const { return m_currentSchedule ? m_currentSchedule->plannedEffort(date) : Duration::zeroDuration; } ///////// Risk ///////// Risk::Risk(Node *n, Resource *r, RiskType rt) { m_node=n; m_resource=r; m_riskType=rt; } Risk::~Risk() { } ResourceRequest::ResourceRequest(Resource *resource, int units) : m_resource(resource), m_units(units), m_parent(0) { //kdDebug()<name() : TQString("None"))<name() : TQString("None"))<unregisterRequest(this); m_resource = 0; } bool ResourceRequest::load(TQDomElement &element, Project &project) { //kdDebug()<id()); me.setAttribute("units", m_units); } int ResourceRequest::units() const { //kdDebug()<name()<<": units="<type() == Resource::Type_Work) return units(); //kdDebug()<task() : 0; } ///////// ResourceGroupRequest::ResourceGroupRequest(ResourceGroup *group, int units) : m_group(group), m_units(units) { //kdDebug()<name() : TQString("None"))<registerRequest(this); m_resourceRequests.setAutoDelete(true); } ResourceGroupRequest::~ResourceGroupRequest() { //kdDebug()<name()<unregisterRequest(this); m_resourceRequests.clear(); } void ResourceGroupRequest::addResourceRequest(ResourceRequest *request) { //kdDebug()<name()<setParent(this); m_resourceRequests.append(request); request->registerRequest(); } ResourceRequest *ResourceGroupRequest::takeResourceRequest(ResourceRequest *request) { if (request) request->unregisterRequest(); return m_resourceRequests.take(m_resourceRequests.tqfindRef(request)); } ResourceRequest *ResourceGroupRequest::tqfind(Resource *resource) const { TQPtrListIterator it(m_resourceRequests); for (; it.current(); ++it) if (it.current()->resource() == resource) return it.current(); return 0; } bool ResourceGroupRequest::load(TQDomElement &element, Project &project) { //kdDebug()<registerRequest(this); m_units = element.attribute("units").toInt(); TQDomNodeList list = element.childNodes(); for (unsigned int i=0; iload(e, project)) addResourceRequest(r); else { kdError()<id()); me.setAttribute("units", m_units); TQPtrListIterator it(m_resourceRequests); for (; it.current(); ++it) it.current()->save(me); } int ResourceGroupRequest::units() const { int units = m_units; TQPtrListIterator it = m_resourceRequests; for (; it.current(); ++it) { units += it.current()->units(); } //kdDebug()<type() == ResourceGroup::Type_Work) units = m_units; TQPtrListIterator it = m_resourceRequests; for (; it.current(); ++it) { units += it.current()->workUnits(); } //kdDebug()< it = m_resourceRequests; for (; it.current(); ++it) { e += it.current()->resource()->effort(time, duration, backward, &sts); if (sts && ok) *ok = sts; //kdDebug()<resource()->name()<<": time="< it = m_resourceRequests; for (; it.current(); ++it) { t1 = it.current()->resource()->availableUntil(); if (!t2.isValid() || t2 < t1) t2 = t1; } //kdDebug()<"<<(backward?"(B) ":"(F) ")<name()<<" "< _effort) { break; } //kdDebug()<<"duration(ms)["<name():"No task")<<" "<name()<<": "<time?end-time:time-end); } DateTime ResourceGroupRequest::availableAfter(const DateTime &time) { DateTime start; TQPtrListIterator it = m_resourceRequests; for (; it.current(); ++it) { DateTime t = it.current()->resource()->availableAfter(time); if (t.isValid() && (!start.isValid() || t < start)) start = t; } if (start.isValid() && start < time) start = time; //kdDebug()<name()< it = m_resourceRequests; for (; it.current(); ++it) { DateTime t = it.current()->resource()->availableBefore(time); if (t.isValid() && (!end.isValid() || t > end)) end = t; } if (!end.isValid() || end > time) end = time; //kdDebug()<name()< it = m_resourceRequests; for (; it.current(); ++it) { it.current()->makeAppointment(schedule); } } void ResourceGroupRequest::reserve(const DateTime &start, const Duration &duration) { m_start = start; m_duration = duration; } bool ResourceGroupRequest::isEmpty() const { return m_resourceRequests.isEmpty() && m_units == 0; } Task *ResourceGroupRequest::task() const { return m_parent ? &(m_parent->task()) : 0; } ///////// ResourceRequestCollection::ResourceRequestCollection(Task &task) : m_task(task) { m_requests.setAutoDelete(true); } ResourceRequestCollection::~ResourceRequestCollection() { //kdDebug()<name()< it(m_requests); for (; it.current(); ++it) { if (it.current()->group() == group) return it.current(); // we assume only one request to the same group } return 0; } ResourceRequest *ResourceRequestCollection::tqfind(Resource *resource) const { ResourceRequest *req = 0; TQPtrListIterator it(m_requests); for (; !req && it.current(); ++it) { req = it.current()->tqfind(resource); } return req; } // bool ResourceRequestCollection::load(TQDomElement &element, Project &project) { // //kdDebug()< it(m_requests); for ( ; it.current(); ++it ) { it.current()->save(element); } } int ResourceRequestCollection::units() const { //kdDebug()< it = m_requests; for (; it.current(); ++it) { units += it.current()->units(); //kdDebug()<group()->name()<<" now="< it(m_requests); for (; it.current(); ++it) { units += it.current()->workUnits(); } //kdDebug()< it = m_requests; for (; it.current(); ++it) { DateTime t = it.current()->availableBefore(time); if (t.isValid() && (!end.isValid() ||t > end)) end = t; } if (!end.isValid() || end > time) end = time; return end; } void ResourceRequestCollection::makeAppointments(Schedule *schedule) { //kdDebug()< it(m_requests); for (; it.current(); ++it) { it.current()->makeAppointments(schedule); } } void ResourceRequestCollection::reserve(const DateTime &start, const Duration &duration) { //kdDebug()< it(m_requests); for (; it.current(); ++it) { it.current()->reserve(start, duration); } } bool ResourceRequestCollection::isEmpty() const { TQPtrListIterator it(m_requests); for (; it.current(); ++it) { if (!it.current()->isEmpty()) return false; } return true; } #ifndef NDEBUG void ResourceGroup::printDebug(TQString indent) { kdDebug()< it(m_resources); for ( ; it.current(); ++it) it.current()->printDebug(indent); } void Resource::printDebug(TQString indent) { kdDebug()<printDebug(indent); } indent += " !"; } void ResourceGroupRequest::printDebug(TQString indent) { kdDebug()<name() : "None")<<" units="< it(m_resourceRequests); for (; it.current(); ++it) { it.current()->printDebug(indent); } } void ResourceRequest::printDebug(TQString indent) { kdDebug()<name() : "None")<<" units="< it = m_requests; for (; it.current(); ++it) { it.current()->printDebug(indent+" "); } } #endif } //KPlato namespace