diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
commit | 8362bf63dea22bbf6736609b0f49c152f975eb63 (patch) | |
tree | 0eea3928e39e50fae91d4e68b21b1e6cbae25604 /kplato/kptnode.cc | |
download | koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip |
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kplato/kptnode.cc')
-rw-r--r-- | kplato/kptnode.cc | 1011 |
1 files changed, 1011 insertions, 0 deletions
diff --git a/kplato/kptnode.cc b/kplato/kptnode.cc new file mode 100644 index 00000000..cab767f8 --- /dev/null +++ b/kplato/kptnode.cc @@ -0,0 +1,1011 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Thomas zander <[email protected]> + Copyright (C) 2004, 2005 Dag Andersen <[email protected]> + + 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 "kptnode.h" + +#include "kptappointment.h" +#include "kptaccount.h" +#include "kptwbsdefinition.h" +#include "kptresource.h" +#include "kptschedule.h" + +#include <qptrlist.h> +#include <qdom.h> + +#include <klocale.h> +#include <kdebug.h> + +namespace KPlato +{ + +Node::Node(Node *parent) : m_nodes(), m_dependChildNodes(), m_dependParentNodes() { + //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl; + m_parent = parent; + init(); + m_id = QString(); // Not mapped +} + +Node::Node(Node &node, Node *parent) + : m_nodes(), + m_dependChildNodes(), + m_dependParentNodes() { + //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl; + m_parent = parent; + init(); + m_name = node.name(); + m_leader = node.leader(); + m_description = node.description(); + m_constraint = (ConstraintType) node.constraint(); + m_constraintStartTime = node.constraintStartTime(); + m_constraintEndTime = node.constraintEndTime(); + + m_dateOnlyStartDate = node.startDate(); + m_dateOnlyEndDate = node.endDate(); + + m_runningAccount = node.runningAccount(); + m_startupAccount = node.startupAccount(); + m_shutdownAccount = node.shutdownAccount(); + + m_startupCost = node.startupCost(); + m_shutdownCost = node.shutdownCost(); + + m_schedules.setAutoDelete(node.m_schedules.autoDelete()); +} + +Node::~Node() { + if (findNode() == this) { + removeId(); // only remove myself (I may be just a working copy) + } + Relation *rel = 0; + while ((rel = m_dependParentNodes.getFirst())) { + delete rel; + } + while ((rel = m_dependChildNodes.getFirst())) { + delete rel; + } + if (m_runningAccount) + m_runningAccount->removeRunning(*this); + if (m_startupAccount) + m_startupAccount->removeStartup(*this); + if (m_shutdownAccount) + m_shutdownAccount->removeShutdown(*this); +} + +void Node::init() { + m_currentSchedule = 0; + m_nodes.setAutoDelete(true); + m_name=""; + m_constraint = Node::ASAP; + m_effort = 0; + m_visitedForward = false; + m_visitedBackward = false; + + m_dateOnlyStartDate = m_dateOnlyEndDate = QDate::currentDate(); + m_dateOnlyDuration.addDays(1); + + m_runningAccount = 0; + m_startupAccount = 0; + m_shutdownAccount = 0; + m_startupCost = 0.0; + m_shutdownCost = 0.0; +} + +Node *Node::projectNode() { + if ((type() == Type_Project) || (type() == Type_Subproject)) { + return this; + } + if (m_parent) + return m_parent->projectNode(); + + kdError()<<k_funcinfo<<"Ooops, no parent and no project found"<<endl; + return 0; +} + +void Node::delChildNode( Node *node, bool remove) { + //kdDebug()<<k_funcinfo<<"find="<<m_nodes.findRef(node)<<endl; + if ( m_nodes.findRef(node) != -1 ) { + if(remove) + m_nodes.remove(); + else + m_nodes.take(); + } + node->setParent(0); +} + +void Node::delChildNode( int number, bool remove) { + Node *n = m_nodes.at(number); + //kdDebug()<<k_funcinfo<<(n?n->id():"null")<<" : "<<(n?n->name():"")<<endl; + if(remove) + m_nodes.remove(number); + else + m_nodes.take(number); + + if (n) { + n->setParent(0); + } +} + +void Node::insertChildNode( unsigned int index, Node *node) { + //kdDebug()<<k_funcinfo<<"insert id="<<node->id()<<": "<<node->name()<<endl; + m_nodes.insert(index,node); + node->setParent(this); +} + +void Node::addChildNode( Node *node, Node *after) { + //kdDebug()<<k_funcinfo<<endl; + int index = m_nodes.findRef(after); + if (index == -1) { + //kdDebug()<<k_funcinfo<<"append id="<<node->id()<<": "<<node->name()<<endl; + m_nodes.append(node); + node->setParent(this); + return; + } + //kdDebug()<<k_funcinfo<<"insert id="<<node->id()<<": "<<node->name()<<endl; + m_nodes.insert(index+1, node); + node->setParent(this); +} + +int Node::findChildNode( Node* node ) +{ + return m_nodes.findRef( node ); +} + + +const Node* Node::getChildNode(int number) const { + // Work around missing const at() method in QPtrList + const QPtrList<Node> &nodes = m_nodes; + return (const_cast<QPtrList<Node> &>(nodes)).at(number); +} + +Duration *Node::getDelay() { + /* TODO + Calculate the delay of this node. Use the calculated startTime and the setted startTime. + */ + return 0L; +} + +void Node::addDependChildNode( Node *node, Relation::Type p) { + addDependChildNode(node,p,Duration()); +} + +void Node::addDependChildNode( Node *node, Relation::Type p, Duration lag) { + Relation *relation = new Relation(this, node, p, lag); + if (node->addDependParentNode(relation)) + m_dependChildNodes.append(relation); + else + delete relation; +} + +void Node::insertDependChildNode( unsigned int index, Node *node, Relation::Type p) { + Relation *relation = new Relation(this, node, p, Duration()); + if (node->addDependParentNode(relation)) + m_dependChildNodes.insert(index, relation); + else + delete relation; +} + +bool Node::addDependChildNode( Relation *relation) { + if(m_dependChildNodes.findRef(relation) != -1) + return false; + m_dependChildNodes.append(relation); + return true; +} + +// These delDepend... methods look suspicious to me, can someone review? +void Node::delDependChildNode( Node *node, bool remove) { + if ( m_nodes.findRef(node) != -1 ) { + if(remove) + m_dependChildNodes.remove(); + else + m_dependChildNodes.take(); + } +} + +void Node::delDependChildNode( Relation *rel, bool remove) { + if ( m_dependChildNodes.findRef(rel) != -1 ) { + if(remove) + m_dependChildNodes.remove(); + else + m_dependChildNodes.take(); + } +} + +void Node::delDependChildNode( int number, bool remove) { + if(remove) + m_dependChildNodes.remove(number); + else + m_dependChildNodes.take(number); +} + +void Node::takeDependChildNode(Relation *rel) { + if (m_dependChildNodes.findRef(rel) != -1) { + m_dependChildNodes.take(); + } +} + +void Node::addDependParentNode( Node *node, Relation::Type p) { + addDependParentNode(node,p,Duration()); +} + +void Node::addDependParentNode( Node *node, Relation::Type p, Duration lag) { + Relation *relation = new Relation(node, this, p, lag); + if (node->addDependChildNode(relation)) + m_dependParentNodes.append(relation); + else + delete relation; +} + +void Node::insertDependParentNode( unsigned int index, Node *node, Relation::Type p) { + Relation *relation = new Relation(this, node, p, Duration()); + if (node->addDependChildNode(relation)) + m_dependParentNodes.insert(index,relation); + else + delete relation; +} + +bool Node::addDependParentNode( Relation *relation) { + if(m_dependParentNodes.findRef(relation) != -1) + return false; + m_dependParentNodes.append(relation); + return true; +} + +// These delDepend... methods look suspicious to me, can someone review? +void Node::delDependParentNode( Node *node, bool remove) { + if ( m_nodes.findRef(node) != -1 ) { + if(remove) + m_dependParentNodes.remove(); + else + m_dependParentNodes.take(); + } +} + +void Node::delDependParentNode( Relation *rel, bool remove) { + if ( m_dependParentNodes.findRef(rel) != -1 ) { + if(remove) + m_dependParentNodes.remove(); + else + m_dependParentNodes.take(); + } +} + +void Node::delDependParentNode( int number, bool remove) { + if(remove) + m_dependParentNodes.remove(number); + else + m_dependParentNodes.take(number); +} + +void Node::takeDependParentNode(Relation *rel) { + if (m_dependParentNodes.findRef(rel) != -1) { + rel = m_dependParentNodes.take(); + } +} + +bool Node::isParentOf(Node *node) { + if (m_nodes.findRef(node) != -1) + return true; + + QPtrListIterator<Node> nit(childNodeIterator()); + for ( ; nit.current(); ++nit ) { + if (nit.current()->isParentOf(node)) + return true; + } + return false; +} + +Relation *Node::findParentRelation(Node *node) { + for (int i=0; i<numDependParentNodes(); i++) { + Relation *rel = getDependParentNode(i); + if (rel->parent() == node) + return rel; + } + return (Relation *)0; +} + +Relation *Node::findChildRelation(Node *node) { + for (int i=0; i<numDependChildNodes(); i++) { + Relation *rel = getDependChildNode(i); + if (rel->child() == node) + return rel; + } + return (Relation *)0; +} + +Relation *Node::findRelation(Node *node) { + Relation *rel = findParentRelation(node); + if (!rel) + rel = findChildRelation(node); + return rel; +} + +bool Node::isDependChildOf(Node *node) { + //kdDebug()<<k_funcinfo<<" '"<<m_name<<"' checking against '"<<node->name()<<"'"<<endl; + for (int i=0; i<numDependParentNodes(); i++) { + Relation *rel = getDependParentNode(i); + if (rel->parent() == node) + return true; + if (rel->parent()->isDependChildOf(node)) + return true; + } + return false; +} + +Duration Node::duration(const DateTime &time, int use, bool backward) { + //kdDebug()<<k_funcinfo<<endl; + // TODO: handle risc + if (!time.isValid()) { + kdError()<<k_funcinfo<<"Time is invalid"<<endl; + return Duration::zeroDuration; + } + if (m_effort == 0) { + kdError()<<k_funcinfo<<"m_effort == 0"<<endl; + return Duration::zeroDuration; + } + if (m_currentSchedule == 0) { + return Duration::zeroDuration; + kdError()<<k_funcinfo<<"No current schedule"<<endl; + } + kdDebug()<<k_funcinfo<<m_name<<": Use="<<use<<endl; + return calcDuration(time, m_effort->effort(use), backward); +} + +void Node::makeAppointments() { + QPtrListIterator<Node> nit(m_nodes); + for ( ; nit.current(); ++nit ) { + nit.current()->makeAppointments(); + } +} + +void Node::calcResourceOverbooked() { + QPtrListIterator<Node> nit(m_nodes); + for ( ; nit.current(); ++nit ) { + nit.current()->calcResourceOverbooked(); + } +} + +QStringList Node::overbookedResources() const { + return m_currentSchedule ? m_currentSchedule->overbookedResources() : QStringList(); +} + +void Node::saveRelations(QDomElement &element) const { + QPtrListIterator<Relation> it(m_dependChildNodes); + for (; it.current(); ++it) { + it.current()->save(element); + } + QPtrListIterator<Node> nodes(m_nodes); + for ( ; nodes.current(); ++nodes ) { + nodes.current()->saveRelations(element); + } +} + +void Node::setConstraint(QString &type) { + // Do not i18n these, they are used in load() + if (type == "ASAP") + setConstraint(ASAP); + else if (type == "ALAP") + setConstraint(ALAP); + else if (type == "StartNotEarlier") + setConstraint(StartNotEarlier); + else if (type == "FinishNotLater") + setConstraint(FinishNotLater); + else if (type == "MustStartOn") + setConstraint(MustStartOn); + else if (type == "MustFinishOn") + setConstraint(MustFinishOn); + else if (type == "FixedInterval") + setConstraint(FixedInterval); + else + setConstraint(ASAP); // default +} + +QString Node::constraintToString() const { + // Do not i18n these, they are used in save() + if (m_constraint == ASAP) + return QString("ASAP"); + else if (m_constraint == ALAP) + return QString("ALAP"); + else if (m_constraint == StartNotEarlier) + return QString("StartNotEarlier"); + else if (m_constraint == FinishNotLater) + return QString("FinishNotLater"); + else if (m_constraint == MustStartOn) + return QString("MustStartOn"); + else if (m_constraint == MustFinishOn) + return QString("MustFinishOn"); + else if (m_constraint == FixedInterval) + return QString("FixedInterval"); + + return QString(); +} + +void Node::propagateEarliestStart(DateTime &time) { + if (m_currentSchedule == 0) + return; + m_currentSchedule->earliestStart = time; + //kdDebug()<<k_funcinfo<<m_name<<": "<<m_currentSchedule->earliestStart.toString()<<endl; + QPtrListIterator<Node> it = m_nodes; + for (; it.current(); ++it) { + it.current()->propagateEarliestStart(time); + } +} + +void Node::propagateLatestFinish(DateTime &time) { + if (m_currentSchedule == 0) + return; + m_currentSchedule->latestFinish = time; + //kdDebug()<<k_funcinfo<<m_name<<": "<<m_currentSchedule->latestFinish<<endl; + QPtrListIterator<Node> it = m_nodes; + for (; it.current(); ++it) { + it.current()->propagateLatestFinish(time); + } +} + +void Node::moveEarliestStart(DateTime &time) { + if (m_currentSchedule == 0) + return; + if (m_currentSchedule->earliestStart < time) + m_currentSchedule->earliestStart = time; + QPtrListIterator<Node> it = m_nodes; + for (; it.current(); ++it) { + it.current()->moveEarliestStart(time); + } +} + +void Node::moveLatestFinish(DateTime &time) { + if (m_currentSchedule == 0) + return; + if (m_currentSchedule->latestFinish > time) + m_currentSchedule->latestFinish = time; + QPtrListIterator<Node> it = m_nodes; + for (; it.current(); ++it) { + it.current()->moveLatestFinish(time); + } +} + +void Node::initiateCalculation(Schedule &sch) { + QPtrListIterator<Node> it = m_nodes; + for (; it.current(); ++it) { + it.current()->initiateCalculation(sch); + } +} + +void Node::resetVisited() { + m_visitedForward = false; + m_visitedBackward = false; + QPtrListIterator<Node> it = m_nodes; + for (; it.current(); ++it) { + it.current()->resetVisited(); + } +} + +Node *Node::siblingBefore() { + //kdDebug()<<k_funcinfo<<endl; + if (getParent()) + return getParent()->childBefore(this); + return 0; +} + +Node *Node::childBefore(Node *node) { + //kdDebug()<<k_funcinfo<<endl; + int index = m_nodes.findRef(node); + if (index > 0){ + return m_nodes.at(index-1); + } + return 0; +} + +Node *Node::siblingAfter() { + //kdDebug()<<k_funcinfo<<endl; + if (getParent()) + return getParent()->childAfter(this); + return 0; +} + +Node *Node::childAfter(Node *node) +{ + //kdDebug()<<k_funcinfo<<endl; + uint index = m_nodes.findRef(node); + if (index < m_nodes.count()-1) { + return m_nodes.at(index+1); } + return 0; +} + +bool Node::moveChildUp(Node* node) +{ + if (findChildNode(node) == -1) + return false; // not my node! + Node *sib = node->siblingBefore(); + if (!sib) + return false; + sib = sib->siblingBefore(); + delChildNode(node, false); + if (sib) { + addChildNode(node, sib); + } else { + insertChildNode(0, node); + } + return true; +} + +bool Node::moveChildDown(Node* node) +{ + if (findChildNode(node) == -1) + return false; // not my node! + Node *sib = node->siblingAfter(); + if (!sib) + return false; + delChildNode(node, false); + addChildNode(node, sib); + return true; +} + +bool Node::legalToLink(Node *node) { + Node *p = projectNode(); + if (p) + return p->legalToLink(this, node); + return false; +} + +bool Node::isEndNode() const { + return m_dependChildNodes.isEmpty(); +} +bool Node::isStartNode() const { + return m_dependParentNodes.isEmpty(); +} + +bool Node::setId(QString id) { + //kdDebug()<<k_funcinfo<<id<<endl; + if (id.isEmpty()) { + kdError()<<k_funcinfo<<"id is empty"<<endl; + m_id = id; + return false; + } + if (!m_id.isEmpty()) { + Node *n = findNode(); + if (n == this) { + //kdDebug()<<k_funcinfo<<"My id found, remove it"<<endl; + removeId(); + } else if (n) { + //Hmmm, shouldn't happen + kdError()<<k_funcinfo<<"My id '"<<m_id<<"' already used for different node: "<<n->name()<<endl; + } + } + if (findNode(id)) { + kdError()<<k_funcinfo<<"id '"<<id<<"' is already used for different node: "<<findNode(id)->name()<<endl; + m_id = QString(); // hmmm + return false; + } + m_id = id; + insertId(id); + //kdDebug()<<k_funcinfo<<m_name<<": inserted id="<<id<<endl; + return true; +} + +void Node::setStartTime(DateTime startTime) { + if (m_currentSchedule) + m_currentSchedule->startTime = startTime; + m_dateOnlyStartDate = startTime.date(); +} + +void Node::setEndTime(DateTime endTime) { + if (m_currentSchedule) + m_currentSchedule->endTime = endTime; + + m_dateOnlyEndDate = endTime.date(); + if (endTime.time().isNull() && m_dateOnlyEndDate > m_dateOnlyStartDate) + m_dateOnlyEndDate = m_dateOnlyEndDate.addDays(-1); +} + +void Node::saveAppointments(QDomElement &element, long id) const { + //kdDebug()<<k_funcinfo<<m_name<<" id="<<id<<endl; + QPtrListIterator<Node> it(m_nodes); + for (; it.current(); ++it ) { + it.current()->saveAppointments(element, id); + } +} + +QPtrList<Appointment> Node::appointments() { + QPtrList<Appointment> lst; + if (m_currentSchedule) + lst = m_currentSchedule->appointments(); + return lst; +} + +// Appointment *Node::findAppointment(Resource *resource) { +// if (m_currentSchedule) +// return m_currentSchedule->findAppointment(resource); +// return 0; +// } +bool Node::addAppointment(Appointment *appointment) { + if (m_currentSchedule) + return m_currentSchedule->add(appointment); + return false; +} + +bool Node::addAppointment(Appointment *appointment, Schedule &main) { + //kdDebug()<<k_funcinfo<<this<<endl; + Schedule *s = findSchedule(main.id()); + if (s == 0) { + s = createSchedule(&main); + } + appointment->setNode(s); + return s->add(appointment); +} + +void Node::addAppointment(ResourceSchedule *resource, DateTime &start, DateTime &end, double load) { + Schedule *node = findSchedule(resource->id()); + if (node == 0) { + node = createSchedule(resource->parent()); + } + node->addAppointment(resource, start, end, load); +} + +void Node::takeSchedule(const Schedule *schedule) { + if (schedule == 0) + return; + if (m_currentSchedule == schedule) + m_currentSchedule = 0; + m_schedules.take(schedule->id()); +} + +void Node::addSchedule(Schedule *schedule) { + if (schedule == 0) + return; + m_schedules.replace(schedule->id(), schedule); +} + +Schedule *Node::createSchedule(QString name, Schedule::Type type, long id) { + //kdDebug()<<k_funcinfo<<name<<" type="<<type<<" id="<<(int)id<<endl; + NodeSchedule *sch = new NodeSchedule(this, name, type, id); + addSchedule(sch); + return sch; +} + +Schedule *Node::createSchedule(Schedule *parent) { + //kdDebug()<<k_funcinfo<<name<<" type="<<type<<" id="<<(int)id<<endl; + NodeSchedule *sch = new NodeSchedule(parent, this); + addSchedule(sch); + return sch; +} + +Schedule *Node::findSchedule(const QString name, const Schedule::Type type) const { + QIntDictIterator<Schedule> it = m_schedules; + for (; it.current(); ++it) { + if (!it.current()->isDeleted() && + it.current()->name() == name && it.current()->type() == type) + return it.current(); + } + return 0; +} + +Schedule *Node::findSchedule(const Schedule::Type type) const { + //kdDebug()<<k_funcinfo<<m_name<<" find type="<<type<<" nr="<<m_schedules.count()<<endl; + QIntDictIterator<Schedule> it = m_schedules; + for (; it.current(); ++it) { + if (!it.current()->isDeleted() && it.current()->type() == type) { + return it.current(); + } + } + return 0; +} + +void Node::setScheduleDeleted(long id, bool on) { + Schedule *ns = findSchedule(id); + if (ns == 0) { + kdError()<<k_funcinfo<<m_name<<" Could not find schedule with id="<<id<<endl; + } else { + ns->setDeleted(on); + } +} + +void Node::setParentSchedule(Schedule *sch) { + Schedule *s = findSchedule(sch->id()); + if (s) { + s->setParent(sch); + } + QPtrListIterator<Node> it = m_nodes; + for (; it.current(); ++it) { + it.current()->setParentSchedule(sch); + } +} + +bool Node::calcCriticalPath(bool fromEnd) { + if (m_currentSchedule == 0) + return false; + //kdDebug()<<k_funcinfo<<m_name<<endl; + if (!isCritical()) { + return false; + } + if (!fromEnd && isStartNode()) { + m_currentSchedule->inCriticalPath = true; + return true; + } + if (fromEnd && isEndNode()) { + m_currentSchedule->inCriticalPath = true; + return true; + } + QPtrListIterator<Relation> pit(m_dependParentNodes); + for (; pit.current(); ++pit) { + if (pit.current()->parent()->calcCriticalPath(fromEnd)) { + m_currentSchedule->inCriticalPath = true; + } + } + return m_currentSchedule->inCriticalPath; +} + +int Node::level() { + Node *n = getParent(); + return n ? n->level() + 1 : 0; +} + +void Node::generateWBS(int count, WBSDefinition &def, QString wbs) { + m_wbs = wbs + def.code(count, level()); + //kdDebug()<<k_funcinfo<<m_name<<" wbs: "<<m_wbs<<endl; + QString w = wbs + def.wbs(count, level()); + QPtrListIterator<Node> it = m_nodes; + for (int i=0; it.current(); ++it) { + it.current()->generateWBS(++i, def, w); + } + +} + +void Node::setCurrentSchedule(long id) { + QPtrListIterator<Node> it = m_nodes; + for (; it.current(); ++it) { + it.current()->setCurrentSchedule(id); + } + //kdDebug()<<k_funcinfo<<m_name<<" id: "<<id<<"="<<m_currentSchedule<<endl; +} +////////////////////////// Effort ///////////////////////////////// + +Effort::Effort( Duration e, Duration p, Duration o) { + m_expectedEffort = e; + m_pessimisticEffort = p; + m_optimisticEffort = o; + m_type = Type_Effort; + m_risktype = Risk_None; +} + +Effort::Effort(const Effort &effort) { + set(effort.expected(), effort.pessimistic(), effort.optimistic()); + setType(effort.type()); + setRisktype(effort.risktype()); +} + +Effort::~Effort() { +} + +const Effort Effort::zeroEffort( Duration::zeroDuration, + Duration::zeroDuration, + Duration::zeroDuration ); + +void Effort::set( Duration e, Duration p, Duration o ) { + m_expectedEffort = e; + m_pessimisticEffort = (p == Duration::zeroDuration) ? e : p; + m_optimisticEffort = (o == Duration::zeroDuration) ? e : o; + //kdDebug()<<k_funcinfo<<" Expected: "<<m_expectedEffort.toString()<<endl; +} + +void Effort::set( int e, int p, int o ) { + m_expectedEffort = Duration(e); + m_pessimisticEffort = (p < 0) ? Duration(e) : Duration(p); + m_optimisticEffort = (o < 0) ? Duration(e) : Duration(o); + //kdDebug()<<k_funcinfo<<" Expected: "<<m_expectedEffort.toString()<<endl; + //kdDebug()<<k_funcinfo<<" Optimistic: "<<m_optimisticEffort.toString()<<endl; + //kdDebug()<<k_funcinfo<<" Pessimistic: "<<m_pessimisticEffort.toString()<<endl; + + //kdDebug()<<k_funcinfo<<" Expected: "<<m_expectedEffort.duration()<<" manseconds"<<endl; +} + +//TODO (?): effort is not really a duration, should maybe not use Duration for storage +void Effort::set(unsigned days, unsigned hours, unsigned minutes) { + Duration dur(days, hours, minutes); + set(dur); + //kdDebug()<<k_funcinfo<<"effort="<<dur.toString()<<endl; +} + +void Effort::expectedEffort(unsigned *days, unsigned *hours, unsigned *minutes) { + m_expectedEffort.get(days, hours, minutes); +} + +Duration Effort::variance() const { + return (m_pessimisticEffort - m_optimisticEffort)/6; +} +Duration Effort::pertExpected() const { + if (m_risktype == Risk_Low) { + return (m_optimisticEffort + m_pessimisticEffort + (m_expectedEffort*4))/6; + } else if (m_risktype == Risk_High) { + return (m_optimisticEffort + (m_pessimisticEffort*2) + (m_expectedEffort*4))/7; + } + return m_expectedEffort; // risk==none +} +Duration Effort::pertOptimistic() const { + if (m_risktype != Risk_None) { + return pertExpected() - variance(); + } + return m_optimisticEffort; +} +Duration Effort::pertPessimistic() const { + if (m_risktype != Risk_None) { + return pertExpected() + variance(); + } + return m_pessimisticEffort; +} + +Duration Effort::effort(int use) const { + if (use == Effort::Use_Expected) { + return pertExpected(); + } else if (use == Effort::Use_Optimistic) { + return pertOptimistic(); + } else if (use == Effort::Use_Pessimistic) + return pertPessimistic(); + + return m_expectedEffort; // default +} + +bool Effort::load(QDomElement &element) { + m_expectedEffort = Duration::fromString(element.attribute("expected")); + m_optimisticEffort = Duration::fromString(element.attribute("optimistic")); + m_pessimisticEffort = Duration::fromString(element.attribute("pessimistic")); + setType(element.attribute("type", "WorkBased")); + setRisktype(element.attribute("risk")); + return true; +} + +void Effort::save(QDomElement &element) const { + QDomElement me = element.ownerDocument().createElement("effort"); + element.appendChild(me); + me.setAttribute("expected", m_expectedEffort.toString()); + me.setAttribute("optimistic", m_optimisticEffort.toString()); + me.setAttribute("pessimistic", m_pessimisticEffort.toString()); + me.setAttribute("type", typeToString()); + me.setAttribute("risk", risktypeToString()); +} + +QString Effort::typeToString() const { + if (m_type == Type_Effort) + return QString("Effort"); + if (m_type == Type_FixedDuration) + return QString("Type_FixedDuration"); + + return QString(); +} + +void Effort::setType(QString type) { + if (type == "Effort") + setType(Type_Effort); + else if (type == "Type_FixedDuration") + setType(Type_FixedDuration); + else + setType(Type_Effort); // default +} + +QString Effort::risktypeToString() const { + if (m_risktype == Risk_None) + return QString("None"); + if (m_risktype == Risk_Low) + return QString("Low"); + if (m_risktype == Risk_High) + return QString("High"); + + return QString(); +} + +void Effort::setRisktype(QString type) { + if (type == "High") + setRisktype(Risk_High); + else if (type == "Low") + setRisktype(Risk_Low); + else + setRisktype(Risk_None); // default +} + +void Effort::setOptimisticRatio(int percent) +{ + int p = percent>0 ? -percent : percent; + m_optimisticEffort = m_expectedEffort*(100+p)/100; +} + +int Effort::optimisticRatio() const { + if (m_expectedEffort == Duration::zeroDuration) + return 0; + return (m_optimisticEffort.milliseconds()*100/m_expectedEffort.milliseconds())-100; +} + +void Effort::setPessimisticRatio(int percent) +{ + int p = percent<0 ? -percent : percent; + m_pessimisticEffort = m_expectedEffort*(100+p)/100; +} +int Effort::pessimisticRatio() const { + if (m_expectedEffort == Duration::zeroDuration) + return 0; + return m_pessimisticEffort.milliseconds()*100/m_expectedEffort.milliseconds()-100; +} + +// Debugging +#ifndef NDEBUG +void Node::printDebug(bool children, QCString indent) { + kdDebug()<<indent<<" Unique node identity="<<m_id<<endl; + if (m_effort) m_effort->printDebug(indent); + QString s = " Constraint: " + constraintToString(); + if (m_constraint == MustStartOn || m_constraint == StartNotEarlier || m_constraint == FixedInterval) + kdDebug()<<indent<<s<<" ("<<constraintStartTime().toString()<<")"<<endl; + if (m_constraint == MustFinishOn || m_constraint == FinishNotLater || m_constraint == FixedInterval) + kdDebug()<<indent<<s<<" ("<<constraintEndTime().toString()<<")"<<endl; + Schedule *cs = m_currentSchedule; + if (cs) { + kdDebug()<<indent<<" Current schedule: "<<"id="<<cs->id()<<" '"<<cs->name()<<"' type: "<<cs->type()<<endl; + } else { + kdDebug()<<indent<<" Current schedule: None"<<endl; + } + QIntDictIterator<Schedule> it = m_schedules; + for (; it.current(); ++it) { + it.current()->printDebug(indent+" "); + } + kdDebug()<<indent<<" Parent: "<<(m_parent ? m_parent->name() : QString("None"))<<endl; + kdDebug()<<indent<<" Level: "<<level()<<endl; + kdDebug()<<indent<<" No of predecessors: "<<m_dependParentNodes.count()<<endl; + QPtrListIterator<Relation> pit(m_dependParentNodes); + //kdDebug()<<indent<<" Dependant parents="<<pit.count()<<endl; + if (pit.count() > 0) { + for ( ; pit.current(); ++pit ) { + pit.current()->printDebug(indent); + } + } + kdDebug()<<indent<<" No of successors: "<<m_dependChildNodes.count()<<endl; + QPtrListIterator<Relation> cit(m_dependChildNodes); + //kdDebug()<<indent<<" Dependant children="<<cit.count()<<endl; + if (cit.count() > 0) { + for ( ; cit.current(); ++cit ) { + cit.current()->printDebug(indent); + } + } + + //kdDebug()<<indent<<endl; + indent += " "; + if (children) { + QPtrListIterator<Node> it(m_nodes); + for ( ; it.current(); ++it ) { + it.current()->printDebug(true,indent); + } + } + +} +#endif + + +#ifndef NDEBUG +void Effort::printDebug(QCString indent) { + kdDebug()<<indent<<" Effort:"<<endl; + indent += " "; + kdDebug()<<indent<<" Expected: "<<m_expectedEffort.toString()<<endl; + kdDebug()<<indent<<" Optimistic: "<<m_optimisticEffort.toString()<<endl; + kdDebug()<<indent<<" Pessimistic: "<<m_pessimisticEffort.toString()<<endl; + + kdDebug()<<indent<<" Risk: "<<risktypeToString()<<endl; + kdDebug()<<indent<<" Pert expected: "<<pertExpected().toString()<<endl; + kdDebug()<<indent<<" Pert optimistic: "<<pertOptimistic().toString()<<endl; + kdDebug()<<indent<<" Pert pessimistic: "<<pertPessimistic().toString()<<endl; + kdDebug()<<indent<<" Pert variance: "<<variance().toString()<<endl; +} +#endif + +} //KPlato namespace |