You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
580 lines
19 KiB
580 lines
19 KiB
/* This file is part of the KDE project
|
|
Copyright (C) 2001 Thomas Zander zander@kde.org
|
|
Copyright (C) 2004, 2005 Dag Andersen <danders@get2net.dk>
|
|
|
|
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.
|
|
*/
|
|
|
|
#ifndef KPTRESOURCE_H
|
|
#define KPTRESOURCE_H
|
|
|
|
#include "kptduration.h"
|
|
#include "kptdatetime.h"
|
|
|
|
#include <tqdom.h>
|
|
#include <tqintdict.h>
|
|
#include <tqstring.h>
|
|
#include <tqptrlist.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
class TQTime;
|
|
|
|
namespace KPlato
|
|
{
|
|
|
|
class Risk;
|
|
class Effort;
|
|
class Appointment;
|
|
class Task;
|
|
class Node;
|
|
class Project;
|
|
class Resource;
|
|
class ResourceRequest;
|
|
class ResourceGroupRequest;
|
|
class Calendar;
|
|
class ResourceRequestCollection;
|
|
class EffortCostMap;
|
|
class Schedule;
|
|
class ResourceSchedule;
|
|
class Schedule;
|
|
|
|
/**
|
|
* This class represents a group of similar resources to be assigned to a task
|
|
* e.g. The list of employees, computer resources, etc
|
|
*/
|
|
|
|
/* IDEA; lets create a resourceGroup that has the intelligence to import PIM schedules
|
|
* from the kroupware project and use the schedules to use the factory pattern to build
|
|
* Resources (probably a derived class) which returns values on getFirstAvailableTime
|
|
* and friends based on the schedules we got from the PIM projects.
|
|
* (Thomas Zander mrt-2003 by suggestion of Shaheed)
|
|
*/
|
|
class ResourceGroup {
|
|
public:
|
|
ResourceGroup(Project *project);
|
|
~ResourceGroup();
|
|
|
|
enum Type { Type_Work, Type_Material };
|
|
|
|
TQString id() const { return m_id; }
|
|
bool setId(TQString id);
|
|
void generateId();
|
|
|
|
Project *project() { return m_project; }
|
|
|
|
void setName(TQString n) {m_name=n;}
|
|
const TQString &name() const {return m_name;}
|
|
void setType(Type type) { m_type = type; }
|
|
//void setType(const TQString &type);
|
|
Type type() const { return m_type; }
|
|
|
|
/** Manage the resources in this list
|
|
* <p>At some point we will have to look at not mixing types of resources
|
|
* (e.g. you can't add a person to a list of computers
|
|
*
|
|
* <p>Risks must always be associated with a resource, so there is no option
|
|
* to manipulate risks (@ref Risk) seperately
|
|
*/
|
|
void addResource(Resource*, Risk*);
|
|
void insertResource( unsigned int index, Resource *resource );
|
|
void removeResource( Resource *resource );
|
|
Resource *takeResource( Resource *resource );
|
|
void removeResource(int);
|
|
|
|
Resource* getResource(int);
|
|
Risk* getRisk(int);
|
|
|
|
/** Get the "num" resources which is available in the time frame
|
|
* defined by "start" and "duration".
|
|
* @param start todo
|
|
* @param duration todo
|
|
* @param num todo
|
|
*/
|
|
TQPtrList<Resource> availableResources(const DateTime start, const Duration duration, int num);
|
|
/** Manage the dependent resources. This is a list of the resource
|
|
* groups that must have available resources for this resource to
|
|
* perform the work
|
|
* <p>see also @ref getRequiredResource, @ref getRequiredResource
|
|
*/
|
|
void addRequiredResource(ResourceGroup*);
|
|
/** Manage the dependent resources. This is a list of the resource
|
|
* groups that must have available resources for this resource to
|
|
* perform the work
|
|
* <p>see also @ref addRequiredResource, @ref getRequiredResource
|
|
*/
|
|
ResourceGroup* getRequiredResource(int);
|
|
/** Manage the dependent resources. This is a list of the resource
|
|
* groups that must have available resources for this resource to
|
|
* perform the work
|
|
* <p>see also @ref getRequiredResource, @ref addRequiredResource
|
|
*/
|
|
void removeRequiredResource(int);
|
|
int numResources() const { return m_resources.count(); }
|
|
TQPtrList<Resource> &resources() { return m_resources; }
|
|
|
|
bool load(TQDomElement &element);
|
|
void save(TQDomElement &element) const;
|
|
|
|
void initiateCalculation(Schedule &sch);
|
|
|
|
void addNode(const Node *node) { m_nodes.append(node); }
|
|
void clearNodes() { m_nodes.clear(); }
|
|
|
|
Calendar *defaultCalendar() { return m_defaultCalendar; }
|
|
|
|
int units();
|
|
|
|
void registerRequest(ResourceGroupRequest *request)
|
|
{ m_requests.append(request); }
|
|
void unregisterRequest(ResourceGroupRequest *request)
|
|
{ m_requests.removeRef(request); }
|
|
const TQPtrList<ResourceGroupRequest> &requests() const
|
|
{ return m_requests; }
|
|
|
|
ResourceGroup *findId() const { return findId(m_id); }
|
|
ResourceGroup *findId(const TQString &id) const;
|
|
bool removeId() { return removeId(m_id); }
|
|
bool removeId(const TQString &id);
|
|
void insertId(const TQString &id);
|
|
|
|
Appointment appointmentIntervals() const;
|
|
|
|
#ifndef NDEBUG
|
|
void printDebug(TQString ident);
|
|
#endif
|
|
|
|
private:
|
|
Project *m_project;
|
|
TQString m_id; // unique id
|
|
TQString m_name;
|
|
TQPtrList<Resource> m_resources;
|
|
TQPtrList<Risk> m_risks;
|
|
TQPtrList<ResourceGroup> m_requires;
|
|
|
|
TQPtrList<Node> m_nodes; //The nodes that want resources from us
|
|
|
|
Calendar *m_defaultCalendar;
|
|
Type m_type;
|
|
|
|
TQPtrList<ResourceGroupRequest> m_requests;
|
|
|
|
};
|
|
|
|
/**
|
|
* Any resource that is used by a task. A resource can be a worker, or maybe wood.
|
|
* If the resources is a worker or a piece of equiment which can be reused but
|
|
* can only be used by one node in time, then we can use the scheduling methods of the
|
|
* resource to schedule the resource available time for the project.
|
|
* The Idea is that all nodes which need this resource point to it and the scheduling
|
|
* code (partly implemented here) schedules the actual usage.
|
|
* See also @ref ResourceGroup
|
|
*/
|
|
|
|
class Resource {
|
|
public:
|
|
|
|
Resource(Project *project);
|
|
Resource(Resource *resource);
|
|
virtual ~Resource();
|
|
|
|
TQString id() const { return m_id; }
|
|
bool setId(TQString id);
|
|
void generateId();
|
|
|
|
enum Type { Type_Work, Type_Material };
|
|
void setType(Type type) { m_type = type; }
|
|
void setType(const TQString &type);
|
|
Type type() const { return m_type; }
|
|
TQString typeToString() const;
|
|
|
|
void setName(TQString n) {m_name=n;}
|
|
const TQString &name() const {return m_name;}
|
|
|
|
void setInitials(TQString initials) {m_initials=initials;}
|
|
const TQString &initials() const {return m_initials;}
|
|
|
|
void setEmail(TQString email) {m_email=email;}
|
|
const TQString &email() const {return m_email;}
|
|
|
|
void copy(Resource *resource);
|
|
|
|
/// Set the time from when the resource is available to this project
|
|
void setAvailableFrom(const TQDateTime &af) {m_availableFrom=af;}
|
|
/// Return the time when the resource is available to this project
|
|
const DateTime &availableFrom() const {return m_availableFrom;}
|
|
/// Set the time when the resource is no longer available to this project
|
|
void setAvailableUntil(const TQDateTime au) {m_availableUntil=au;}
|
|
/// Return the time when the resource is no longer available to this project.
|
|
const DateTime &availableUntil() const {return m_availableUntil;}
|
|
|
|
void addWorkingHour(TQTime from, TQTime until);
|
|
TQPtrList<TQTime> workingHours() { return m_workingHours; }
|
|
|
|
DateTime getFirstAvailableTime(DateTime after = DateTime());
|
|
DateTime getBestAvailableTime(Duration duration);
|
|
DateTime getBestAvailableTime(const DateTime after, const Duration duration);
|
|
|
|
bool load(TQDomElement &element);
|
|
void save(TQDomElement &element) const;
|
|
|
|
///Return the list of appointments for current schedule.
|
|
TQPtrList<Appointment> appointments();
|
|
|
|
Appointment *findAppointment(Node *node);
|
|
/// Adds appointment to current schedule
|
|
virtual bool addAppointment(Appointment *appointment);
|
|
/// Adds appointment to schedule sch
|
|
virtual bool addAppointment(Appointment *appointment, Schedule &main);
|
|
/// Adds appointment to both this resource and node
|
|
virtual void addAppointment(Schedule *node, DateTime &start, DateTime &end, double load=100);
|
|
|
|
void initiateCalculation(Schedule &sch);
|
|
bool isAvailable(Task *task);
|
|
void makeAppointment(Schedule *schedule);
|
|
|
|
bool isOverbooked() const;
|
|
bool isOverbooked(const TQDate &date) const;
|
|
bool isOverbooked(const DateTime &start, const DateTime &end) const;
|
|
|
|
double normalRate() const { return cost.normalRate; }
|
|
void setNormalRate(double rate) { cost.normalRate = rate; }
|
|
double overtimeRate() const { return cost.overtimeRate; }
|
|
void setOvertimeRate(double rate) { cost.overtimeRate = rate; }
|
|
double fixedCost() const { return cost.fixed; }
|
|
void setFixedCost(double value) { cost.fixed = value; }
|
|
|
|
/**
|
|
* Return available units in percent
|
|
*/
|
|
int units() const { return m_units; }
|
|
/**
|
|
* Set available units in percent
|
|
*/
|
|
void setUnits(int units) { m_units = units; }
|
|
|
|
Project *project() const { return m_project; }
|
|
|
|
/**
|
|
* Get the calendar for this resource.
|
|
* If local=false, check if there is a default calendar.
|
|
*/
|
|
Calendar *calendar(bool local=false) const;
|
|
Calendar *calendar(const TQString id) const;
|
|
void setCalendar(Calendar *calendar) { m_calendar = calendar; }
|
|
|
|
/**
|
|
* Used to clean up requests when the resource is deleted.
|
|
*/
|
|
void registerRequest(const ResourceRequest *request)
|
|
{ m_requests.append(request); }
|
|
void unregisterRequest(const ResourceRequest *request)
|
|
{ m_requests.removeRef(request); }
|
|
const TQPtrList<ResourceRequest> &requests() const
|
|
{ return m_requests; }
|
|
|
|
Duration effort(const DateTime &start, const Duration &duration, bool backward, bool *ok=0) const;
|
|
|
|
/**
|
|
* Find the first available time after time, within limit.
|
|
* Returns invalid DateTime if not available.
|
|
*/
|
|
DateTime availableAfter(const DateTime &time, const DateTime limit=DateTime(), bool checkAppointments=false) const;
|
|
/**
|
|
* Find the first available time before time, within limit.
|
|
* Returns invalid DateTime if not available.
|
|
*/
|
|
DateTime availableBefore(const DateTime &time, const DateTime limit=DateTime(), bool checkAppointments=false) const;
|
|
|
|
Resource *findId() const { return findId(m_id); }
|
|
Resource *findId(const TQString &id) const;
|
|
bool removeId() { return removeId(m_id); }
|
|
bool removeId(const TQString &id);
|
|
void insertId(const TQString &id);
|
|
|
|
Calendar *findCalendar(const TQString &id) const;
|
|
|
|
Appointment appointmentIntervals() const;
|
|
Duration plannedEffort(const TQDate &date) const;
|
|
|
|
void setCurrentSchedule(Schedule *schedule) { m_currentSchedule = schedule; }
|
|
void setCurrentSchedule(long id) { m_currentSchedule = findSchedule(id); }
|
|
Schedule *currentSchedule() const { return m_currentSchedule; }
|
|
|
|
TQIntDict<Schedule> &schedules() { return m_schedules; }
|
|
Schedule *findSchedule(long id) { return m_schedules[id]; }
|
|
/// Take, and delete.
|
|
void removeSchedule(Schedule *schedule);
|
|
/// Take, don't delete.
|
|
void takeSchedule(const Schedule *schedule);
|
|
void addSchedule(Schedule *schedule);
|
|
ResourceSchedule *createSchedule(TQString name, int type, long id);
|
|
ResourceSchedule *createSchedule(Schedule *parent);
|
|
|
|
protected:
|
|
void makeAppointment(Schedule *node, const DateTime &from, const DateTime &end);
|
|
|
|
private:
|
|
Project *m_project;
|
|
TQIntDict<Schedule> m_schedules;
|
|
TQString m_id; // unique id
|
|
TQString m_name;
|
|
TQString m_initials;
|
|
TQString m_email;
|
|
DateTime m_availableFrom;
|
|
DateTime m_availableUntil;
|
|
TQPtrList<TQTime> m_workingHours;
|
|
|
|
int m_units; // avalable units in percent
|
|
|
|
Type m_type;
|
|
|
|
struct Cost {
|
|
double normalRate;
|
|
double overtimeRate;
|
|
double fixed;
|
|
} cost;
|
|
|
|
Calendar *m_calendar;
|
|
TQPtrList<ResourceRequest> m_requests;
|
|
|
|
Schedule *m_currentSchedule;
|
|
|
|
public:
|
|
#ifndef NDEBUG
|
|
void printDebug(TQString ident);
|
|
#endif
|
|
};
|
|
|
|
|
|
/**
|
|
* Risk is associated with a resource/task pairing to indicate the planner's confidence in the
|
|
* estimated effort. Risk can be one of none, low, or high. Some factors that may be taken into
|
|
* account for risk are the experience of the person and the reliability of equipment.
|
|
*/
|
|
class Risk {
|
|
public:
|
|
|
|
enum RiskType {
|
|
NONE=0,
|
|
LOW=1,
|
|
HIGH=2
|
|
};
|
|
|
|
Risk(Node *n, Resource *r, RiskType rt=NONE);
|
|
~Risk();
|
|
|
|
RiskType riskType() { return m_riskType; }
|
|
|
|
Node *node() { return m_node; }
|
|
Resource *resource() { return m_resource; }
|
|
|
|
private:
|
|
Node *m_node;
|
|
Resource *m_resource;
|
|
RiskType m_riskType;
|
|
};
|
|
|
|
class ResourceRequest {
|
|
public:
|
|
ResourceRequest(Resource *resource=0, int units = 1);
|
|
|
|
~ResourceRequest();
|
|
|
|
ResourceGroupRequest *parent() const { return m_parent; }
|
|
void setParent(ResourceGroupRequest *parent) { m_parent = parent; }
|
|
|
|
Resource *resource() const { return m_resource; }
|
|
void setResource(Resource* resource) { m_resource = resource; }
|
|
|
|
bool load(TQDomElement &element, Project &project);
|
|
void save(TQDomElement &element) const;
|
|
|
|
/**
|
|
* Get amount of requested resource units in percent
|
|
*/
|
|
int units() const;
|
|
|
|
/**
|
|
* Get amount of requested work units in percent
|
|
*/
|
|
int workUnits() const;
|
|
|
|
void registerRequest() { if (m_resource) m_resource->registerRequest(this); }
|
|
void unregisterRequest() { if (m_resource) m_resource->unregisterRequest(this); }
|
|
|
|
void makeAppointment(Schedule *schedule) {
|
|
if (m_resource)
|
|
m_resource->makeAppointment(schedule);
|
|
}
|
|
Task *task() const;
|
|
|
|
private:
|
|
Resource *m_resource;
|
|
int m_units;
|
|
ResourceGroupRequest *m_parent;
|
|
|
|
#ifndef NDEBUG
|
|
public:
|
|
void printDebug(TQString ident);
|
|
#endif
|
|
};
|
|
|
|
class ResourceGroupRequest {
|
|
public:
|
|
ResourceGroupRequest(ResourceGroup *group=0, int units=0);
|
|
~ResourceGroupRequest();
|
|
|
|
void setParent(ResourceRequestCollection *parent) { m_parent = parent;}
|
|
ResourceRequestCollection *parent() const { return m_parent; }
|
|
|
|
ResourceGroup *group() const { return m_group; }
|
|
TQPtrList<ResourceRequest> &resourceRequests() { return m_resourceRequests; }
|
|
void addResourceRequest(ResourceRequest *request);
|
|
void removeResourceRequest(ResourceRequest *request) { m_resourceRequests.removeRef(request); }
|
|
ResourceRequest *takeResourceRequest(ResourceRequest *request);
|
|
ResourceRequest *find(Resource *resource) const;
|
|
|
|
bool load(TQDomElement &element, Project &project);
|
|
void save(TQDomElement &element) const;
|
|
|
|
/**
|
|
* Get total amount of resource units in percent
|
|
*/
|
|
int units() const;
|
|
|
|
/**
|
|
* Get amount of work units in percent
|
|
*/
|
|
int workUnits() const;
|
|
|
|
Duration effort(const DateTime &time, const Duration &duration, bool backward, bool *ok=0) const;
|
|
|
|
int numDays(const DateTime &time, bool backward) const;
|
|
|
|
/**
|
|
* Returns the duration needed to do the effort effort
|
|
* starting at start.
|
|
*/
|
|
Duration duration(const DateTime &start, const Duration &effort, bool backward=false);
|
|
|
|
DateTime availableAfter(const DateTime &time);
|
|
DateTime availableBefore(const DateTime &time);
|
|
|
|
/**
|
|
* Makes appointments for task @param task to the
|
|
* requested resources for the duration found in @ref duration().
|
|
*/
|
|
void makeAppointments(Schedule *schedule);
|
|
|
|
/**
|
|
* Reserves the requested resources for the specified interval
|
|
*/
|
|
void reserve(const DateTime &start, const Duration &duration);
|
|
|
|
bool isEmpty() const;
|
|
|
|
Task *task() const;
|
|
|
|
private:
|
|
ResourceGroup *m_group;
|
|
int m_units;
|
|
ResourceRequestCollection *m_parent;
|
|
|
|
TQPtrList<ResourceRequest> m_resourceRequests;
|
|
DateTime m_start;
|
|
Duration m_duration;
|
|
|
|
#ifndef NDEBUG
|
|
public:
|
|
void printDebug(TQString ident);
|
|
#endif
|
|
};
|
|
|
|
class ResourceRequestCollection {
|
|
public:
|
|
ResourceRequestCollection(Task &task);
|
|
~ResourceRequestCollection();
|
|
|
|
const TQPtrList<ResourceGroupRequest> &requests() const { return m_requests; }
|
|
void addRequest(ResourceGroupRequest *request) {
|
|
m_requests.append(request);
|
|
request->setParent(this);
|
|
}
|
|
void removeRequest(ResourceGroupRequest *request) { m_requests.removeRef(request); }
|
|
void takeRequest(ResourceGroupRequest *request) { m_requests.take(m_requests.findRef(request)); }
|
|
ResourceGroupRequest *find(ResourceGroup *resource) const;
|
|
ResourceRequest *find(Resource *resource) const;
|
|
bool isEmpty() const;
|
|
|
|
//bool load(TQDomElement &element, Project &project);
|
|
void save(TQDomElement &element) const;
|
|
|
|
void clear() { m_requests.clear(); }
|
|
|
|
/**
|
|
* Returns the total amount of resource units in percent
|
|
*/
|
|
int units() const;
|
|
|
|
/**
|
|
* Returns the amount of work units in percent
|
|
*/
|
|
int workUnits() const;
|
|
|
|
/**
|
|
* Returns the duration needed to do the effort @param effort
|
|
* starting at @param time.
|
|
*/
|
|
Duration duration(const DateTime &time, const Duration &effort, bool backward=false);
|
|
|
|
DateTime availableAfter(const DateTime &time);
|
|
DateTime availableBefore(const DateTime &time);
|
|
|
|
/**
|
|
* Makes appointments for the task @param task to the requested resources.
|
|
* Assumes that @ref duration() has been run.
|
|
*/
|
|
void makeAppointments(Schedule *schedule);
|
|
/**
|
|
* Reserves the requested resources for the specified interval
|
|
*/
|
|
void reserve(const DateTime &start, const Duration &duration);
|
|
|
|
Task &task() const { return m_task; }
|
|
|
|
protected:
|
|
struct Interval {
|
|
DateTime start;
|
|
DateTime end;
|
|
Duration effort;
|
|
};
|
|
|
|
|
|
private:
|
|
Task &m_task;
|
|
TQPtrList<ResourceGroupRequest> m_requests;
|
|
|
|
#ifndef NDEBUG
|
|
public:
|
|
void printDebug(TQString ident);
|
|
#endif
|
|
};
|
|
|
|
} //KPlato namespace
|
|
|
|
#endif
|