[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [calligra] plan: Cache performance data (bcws/bcwp/acwp)
From:       Dag Andersen <danders () get2net ! dk>
Date:       2012-08-28 9:56:33
Message-ID: 20120828095633.D22DDA60A6 () git ! kde ! org
[Download RAW message or body]

Git commit 900b95e0c138bbd94ffcff07159f07f66cf074f8 by Dag Andersen.
Committed on 27/08/2012 at 09:33.
Pushed by danders into branch 'master'.

Cache performance data (bcws/bcwp/acwp)

M  +2    -2    plan/kptpart.cpp
M  +82   -24   plan/libs/kernel/kptnode.cpp
M  +24   -4    plan/libs/kernel/kptnode.h
M  +42   -34   plan/libs/kernel/kptproject.cpp
M  +3    -3    plan/libs/kernel/kptproject.h
M  +18   -7    plan/libs/kernel/kptschedule.cpp
M  +25   -1    plan/libs/kernel/kptschedule.h
M  +106  -87   plan/libs/kernel/kpttask.cpp
M  +7    -4    plan/libs/kernel/kpttask.h

http://commits.kde.org/calligra/900b95e0c138bbd94ffcff07159f07f66cf074f8

diff --git a/plan/kptpart.cpp b/plan/kptpart.cpp
index 6b832e0..b774bba 100644
--- a/plan/kptpart.cpp
+++ b/plan/kptpart.cpp
@@ -145,12 +145,12 @@ void Part::configChanged()
 void Part::setProject( Project *project )
 {
     if ( m_project ) {
-        disconnect( m_project, SIGNAL( changed() ), this, SIGNAL( changed() ) );
+        disconnect( m_project, SIGNAL( projectChanged() ), this, SIGNAL( changed() ) );
         delete m_project;
     }
     m_project = project;
     if ( m_project ) {
-        connect( m_project, SIGNAL( changed() ), this, SIGNAL( changed() ) );
+        connect( m_project, SIGNAL( projectChanged() ), this, SIGNAL( changed() ) );
 //        m_project->setConfig( config() );
         m_project->setSchedulerPlugins( m_schedulerPlugins );
     }
diff --git a/plan/libs/kernel/kptnode.cpp b/plan/libs/kernel/kptnode.cpp
index 82e8d88..ee5039a 100644
--- a/plan/libs/kernel/kptnode.cpp
+++ b/plan/libs/kernel/kptnode.cpp
@@ -197,7 +197,7 @@ void Node::takeChildNode( Node *node) {
     }
     node->setParentNode(0);
     if ( t != type() ) {
-//        changed(); Note: handled by project
+        changed( Type );
     }
 }
 
@@ -211,7 +211,7 @@ void Node::takeChildNode( int number ) {
         }
     }
     if ( t != type() ) {
-//        changed(); Note: handled by project
+        changed( Type );
     }
 }
 
@@ -223,7 +223,7 @@ void Node::insertChildNode( int index, Node *node ) {
         m_nodes.insert(index,node);
     node->setParentNode( this );
     if ( t != type() ) {
-//        changed(); Note: handled by project
+        changed( Type );
     }
 }
 
@@ -234,14 +234,14 @@ void Node::addChildNode( Node *node, Node *after) {
         m_nodes.append(node);
         node->setParentNode( this );
         if ( t != type() ) {
-//        changed(); Note: handled by project
+            changed( Type );
         }
         return;
     }
     m_nodes.insert(index+1, node);
     node->setParentNode(this);
     if ( t != type() ) {
-//        changed(); Note: handled by project
+        changed( Type );
     }
 }
 
@@ -1187,7 +1187,7 @@ void Node::setCurrentSchedule(long id) {
 void Node::setStartupCost(double cost)
 {
     m_startupCost = cost;
-    changed();
+    changed(StartupCost);
 }
 
 void Node::setStartupAccount(Account *acc)
@@ -1203,7 +1203,7 @@ void Node::setStartupAccount(Account *acc)
 void Node::setShutdownCost(double cost)
 {
     m_shutdownCost = cost;
-    changed();
+    changed(ShutdownCost);
 }
 
 void Node::setShutdownAccount(Account *acc)
@@ -1226,9 +1226,28 @@ void Node::setRunningAccount(Account *acc)
     changed();
 }
 
-void Node::changed(Node *node) {
-    if (m_parent)
-        m_parent->changed(node);
+void Node::changed(Node *node, int property) {
+    switch ( property) {
+        case Type:
+        case StartupCost:
+        case ShutdownCost:
+        case CompletionEntry:
+        case CompletionStarted:
+        case CompletionFinished:
+        case CompletionStartTime:
+        case CompletionFinishTime:
+        case CompletionPercentage:
+        case CompletionRemainingEffort:
+        case CompletionActualEffort:
+            foreach ( Schedule *s, m_schedules ) {
+                s->clearPerformanceCache();
+            }
+        break;
+        default: break;
+    }
+    if (m_parent) {
+        m_parent->changed(node, property);
+    }
 }
 
 Duration Node::plannedEffort( const Resource *resource, long id, EffortCostCalculationType type ) const
@@ -1267,31 +1286,70 @@ EffortCost Node::plannedCost( long id, EffortCostCalculationType type ) const
     return ec;
 }
 
-EffortCostMap Node::bcwsPrDay( long int id, KPlato::EffortCostCalculationType type ) const
+EffortCostMap Node::bcwsPrDay( long int id, EffortCostCalculationType type ) const
 {
-    EffortCostMap ec;
-    foreach ( Node *n, m_nodes ) {
-        ec += n->bcwsPrDay( id, type );
+    return const_cast<Node*>( this )->bcwsPrDay( id, type );
+}
+
+EffortCostMap Node::bcwsPrDay( long int id, EffortCostCalculationType type )
+{
+    Schedule *s = schedule( id );
+    if ( s == 0 ) {
+        return EffortCostMap();
     }
-    return ec;
+    EffortCostCache &ec = s->bcwsPrDayCache( type );
+    if ( ! ec.cached ) {
+        ec.effortcostmap = EffortCostMap();
+        foreach ( Node *n, m_nodes ) {
+            ec.effortcostmap += n->bcwsPrDay( id, type );
+        }
+        ec.cached = true;
+    }
+    return ec.effortcostmap;
 }
 
-EffortCostMap Node::bcwpPrDay( long int id, KPlato::EffortCostCalculationType type ) const
+EffortCostMap Node::bcwpPrDay( long int id, EffortCostCalculationType type ) const
 {
-    EffortCostMap ec;
-    foreach ( Node *n, m_nodes ) {
-        ec += n->bcwpPrDay( id, type );
+    return const_cast<Node*>( this )->bcwpPrDay( id, type);
+}
+
+EffortCostMap Node::bcwpPrDay( long int id, EffortCostCalculationType type )
+{
+    Schedule *s = schedule( id );
+    if ( s == 0 ) {
+        return EffortCostMap();
     }
-    return ec;
+    EffortCostCache &ec = s->bcwpPrDayCache( type );
+    if ( ! ec.cached ) {
+        ec.effortcostmap = EffortCostMap();
+        foreach ( Node *n, m_nodes ) {
+            ec.effortcostmap += n->bcwpPrDay( id, type );
+        }
+        ec.cached = true;
+    }
+    return ec.effortcostmap;
 }
 
 EffortCostMap Node::acwp( long id, EffortCostCalculationType type ) const
 {
-    EffortCostMap ec;
-    foreach ( Node *n, m_nodes ) {
-        ec += n->acwp( id, type );
+    return const_cast<Node*>( this )->acwp( id, type );
+}
+
+EffortCostMap Node::acwp( long id, EffortCostCalculationType type )
+{
+    Schedule *s = schedule( id );
+    if ( s == 0 ) {
+        return EffortCostMap();
     }
-    return ec;
+    EffortCostCache &ec = s->acwpCache( type );
+    if ( ! ec.cached ) {
+        ec.effortcostmap = EffortCostMap();
+        foreach ( Node *n, m_nodes ) {
+            ec.effortcostmap += n->acwp( id, type );
+        }
+        ec.cached = true;
+    }
+    return ec.effortcostmap;
 }
 
 EffortCost Node::acwp( const QDate &date, long id ) const
diff --git a/plan/libs/kernel/kptnode.h b/plan/libs/kernel/kptnode.h
index 671458b..119b006 100644
--- a/plan/libs/kernel/kptnode.h
+++ b/plan/libs/kernel/kptnode.h
@@ -84,6 +84,20 @@ public:
         State_NotScheduled = 2048
     };
 
+    enum Properties {
+        Type,
+        StartupCost,
+        ShutdownCost,
+        CompletionEntry,
+        CompletionStarted,
+        CompletionFinished,
+        CompletionStartTime,
+        CompletionFinishTime,
+        CompletionPercentage,
+        CompletionRemainingEffort,
+        CompletionActualEffort
+    };
+
     Node(Node *parent = 0);
     Node(const Node &node, Node *parent = 0);
 
@@ -333,22 +347,28 @@ public:
     virtual double budgetedCostPerformed( const QDate &, long = CURRENTSCHEDULE ) const { return 0.0; };
 
     /// Return map of Budgeted Cost of Work Scheduled pr day
+    virtual EffortCostMap bcwsPrDay( long id = CURRENTSCHEDULE, EffortCostCalculationType type = \
ECCT_All ); +    /// Return map of Budgeted Cost of Work Scheduled pr day
     virtual EffortCostMap bcwsPrDay( long id = CURRENTSCHEDULE, EffortCostCalculationType type = \
ECCT_All ) const;  /// Budgeted Cost of Work Scheduled
     virtual double bcws( const QDate &/*date*/, long id = CURRENTSCHEDULE ) const { Q_UNUSED(id); return \
0.0; }  
     /// Return map of Budgeted Cost of Work Scheduled pr day (also includes bcws pr day)
+    virtual EffortCostMap bcwpPrDay( long id = CURRENTSCHEDULE, EffortCostCalculationType type = \
ECCT_All ); +    /// Return map of Budgeted Cost of Work Scheduled pr day (also includes bcws pr day)
     virtual EffortCostMap bcwpPrDay( long id = CURRENTSCHEDULE, EffortCostCalculationType type = \
ECCT_All ) const;  /// Budgeted Cost of Work Performed
     virtual double bcwp( long id ) const { Q_UNUSED(id); return 0.0; }
     /// Budgeted Cost of Work Performed ( up to @p date )
     virtual double bcwp( const QDate &/*date*/, long id = CURRENTSCHEDULE ) const { Q_UNUSED(id); return \
                0.0; }
-    
+
+    /// Return a map of Actual effort and Cost of Work Performed
+    virtual EffortCostMap acwp( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All );
     /// Return a map of Actual effort and Cost of Work Performed
     virtual EffortCostMap acwp( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All ) \
const;  /// Return Actual effort and Cost of Work Performed upto @date
     virtual EffortCost acwp( const QDate &date, long id = CURRENTSCHEDULE ) const;
-    
+
     /// Effort based performance index
     virtual double effortPerformanceIndex(const QDate &/*date*/, long /*id*/ = CURRENTSCHEDULE ) const { \
return 0.0; }  /// Schedule performance index
@@ -583,7 +603,7 @@ public:
     virtual void addParentProxyRelation(Node *, const Relation *) {}
     virtual void addChildProxyRelation(Node *, const Relation *) {}
     
-    virtual void changed() { changed( this ); }
+    virtual void changed( int property = -1 ) { changed( this, property ); }
     Duration getmDurationForward(){ return this->m_durationForward;}
 
 public slots:
@@ -600,7 +620,7 @@ protected:
 
     // NOTE: Cannot use setCurrentSchedule() due to overload/casting problems
     void setCurrentSchedulePtr(Schedule *schedule) { m_currentSchedule = schedule; }
-    virtual void changed(Node *node);
+    virtual void changed(Node *node, int property = -1 );
     
     QList<Node*> m_nodes;
     QList<Relation*> m_dependChildNodes;
diff --git a/plan/libs/kernel/kptproject.cpp b/plan/libs/kernel/kptproject.cpp
index ee92e50..33854c3 100644
--- a/plan/libs/kernel/kptproject.cpp
+++ b/plan/libs/kernel/kptproject.cpp
@@ -200,7 +200,7 @@ void Project::calculate( const DateTime &dt )
         cs->notScheduled = false;
         calcFreeFloat();
         emit scheduleChanged( cs );
-        emit changed();
+        emit projectChanged();
     } else if ( type() == Type_Subproject ) {
         kWarning() << "Subprojects not implemented";
     } else {
@@ -241,7 +241,7 @@ void Project::calculate( ScheduleManager &sm )
     emit sigCalculationFinished( this, &sm );
     emit scheduleManagerChanged( &sm );
     emit projectCalculated( &sm );
-    emit changed();
+    emit projectChanged();
     sm.setScheduling( false );
 }
 
@@ -352,7 +352,7 @@ void Project::calculate()
         cs->notScheduled = false;
         calcFreeFloat();
         emit scheduleChanged( cs );
-        emit changed();
+        emit projectChanged();
     } else if ( type() == Type_Subproject ) {
         kWarning() << "Subprojects not implemented";
     } else {
@@ -368,7 +368,7 @@ void Project::finishCalculation( ScheduleManager &sm )
     cs->notScheduled = false;
     calcFreeFloat();
     emit scheduleChanged( cs );
-    emit changed();
+    emit projectChanged();
 }
 
 void Project::setProgress( int progress, ScheduleManager *sm )
@@ -1265,7 +1265,7 @@ void Project::addResourceGroup( ResourceGroup *group, int index )
         r->setProject( this );
     }
     emit resourceGroupAdded( group );
-    emit changed();
+    emit projectChanged();
 }
 
 ResourceGroup *Project::takeResourceGroup( ResourceGroup *group )
@@ -1285,7 +1285,7 @@ ResourceGroup *Project::takeResourceGroup( ResourceGroup *group )
         removeResourceId( r->id() );
     }
     emit resourceGroupRemoved( g );
-    emit changed();
+    emit projectChanged();
     return g;
 }
 
@@ -1301,7 +1301,7 @@ void Project::addResource( ResourceGroup *group, Resource *resource, int index )
     group->addResource( i, resource, 0 );
     setResourceId( resource );
     emit resourceAdded( resource );
-    emit changed();
+    emit projectChanged();
 }
 
 Resource *Project::takeResource( ResourceGroup *group, Resource *resource )
@@ -1319,7 +1319,7 @@ Resource *Project::takeResource( ResourceGroup *group, Resource *resource )
         kWarning() << "Cound not take resource from group";
     }
     emit resourceRemoved( resource );
-    emit changed();
+    emit projectChanged();
     return r;
 }
 
@@ -1400,7 +1400,7 @@ bool Project::addSubTask( Node* task, int index, Node* parent, bool emitSignal )
     connect( this, SIGNAL( standardWorktimeChanged( StandardWorktime* ) ), task, SLOT( \
slotStandardWorktimeChanged( StandardWorktime* ) ) );  if ( emitSignal ) {
         emit nodeAdded( task );
-        emit changed();
+        emit projectChanged();
         if ( p != this && p->numChildren() == 1 ) {
             emit nodeChanged( p );
         }
@@ -1422,7 +1422,7 @@ void Project::takeTask( Node *node, bool emitSignal )
     parent->takeChildNode( node );
     if ( emitSignal ) {
         emit nodeRemoved( node );
-        emit changed();
+        emit projectChanged();
         if ( parent != this && parent->type() != Node::Type_Summarytask ) {
             emit nodeChanged( parent );
         }
@@ -1858,6 +1858,10 @@ QStringList Project::resourceNameList() const
 EffortCostMap Project::plannedEffortCostPrDay( const QDate & start, const QDate &end, long id, \
EffortCostCalculationType typ ) const  {
     //kDebug(planDbg())<<start<<end<<id;
+    Schedule *s = schedule( id );
+    if ( s == 0 ) {
+        return EffortCostMap();
+    }
     EffortCostMap ec;
     QListIterator<Node*> it( childNodeIterator() );
     while ( it.hasNext() ) {
@@ -2087,7 +2091,7 @@ void Project::addCalendar( Calendar *calendar, Calendar *parent, int index )
     }
     setCalendarId( calendar );
     emit calendarAdded( calendar );
-    emit changed();
+    emit projectChanged();
 }
 
 void Project::takeCalendar( Calendar *calendar )
@@ -2107,7 +2111,7 @@ void Project::takeCalendar( Calendar *calendar )
     }
     emit calendarRemoved( calendar );
     calendar->setProject( 0 );
-    emit changed();
+    emit projectChanged();
 }
 
 int Project::indexOf( const Calendar *calendar ) const
@@ -2191,7 +2195,7 @@ void Project::setDefaultCalendar( Calendar *cal )
         cal->setDefault( true );
     }
     emit defaultCalendarChanged( cal );
-    emit changed();
+    emit projectChanged();
 }
 
 void Project::setStandardWorktime( StandardWorktime * worktime )
@@ -2306,7 +2310,7 @@ void Project::setWbsDefinition( const WBSDefinition &def )
     //kDebug(planDbg());
     m_wbsDefinition = def;
     emit wbsDefinitionChanged();
-    emit changed();
+    emit projectChanged();
 }
 
 QString Project::generateWBSCode( QList<int> &indexes ) const
@@ -2338,7 +2342,7 @@ void Project::setCurrentSchedule( long id )
         r->setCurrentSchedule( id );
     }
     emit currentScheduleChanged();
-    emit changed();
+    emit projectChanged();
 }
 
 ScheduleManager *Project::scheduleManager( long id ) const
@@ -2417,7 +2421,7 @@ void Project::addScheduleManager( ScheduleManager *sm, ScheduleManager *parent,
     m_managerIdMap.insert( sm->managerId(), sm );
 
     emit scheduleManagerAdded( sm );
-    emit changed();
+    emit projectChanged();
     //kDebug(planDbg())<<"Added:"<<sm->name()<<", now"<<m_managers.count();
 }
 
@@ -2437,7 +2441,7 @@ int Project::takeScheduleManager( ScheduleManager *sm )
             sm->setParentManager( 0 );
             m_managerIdMap.remove( sm->managerId() );
             emit scheduleManagerRemoved( sm );
-            emit changed();
+            emit projectChanged();
         }
     } else {
         index = indexOf( sm );
@@ -2446,7 +2450,7 @@ int Project::takeScheduleManager( ScheduleManager *sm )
             m_managers.removeAt( indexOf( sm ) );
             m_managerIdMap.remove( sm->managerId() );
             emit scheduleManagerRemoved( sm );
-            emit changed();
+            emit projectChanged();
         }
     }
     return index;
@@ -2553,34 +2557,38 @@ void Project::insertCalendarId( const QString &id, Calendar *calendar )
     calendarIdDict.insert( id, calendar );
 }
 
-void Project::changed( Node *node )
+void Project::changed( Node *node, int property )
 {
     if ( m_parent == 0 ) {
-        emit nodeChanged( node );
-        emit changed();
+        Node::changed( node, property ); // reset cache
+        if ( property != Node::Type ) {
+            // add/remove node is handled elsewhere
+            emit nodeChanged( node );
+            emit projectChanged();
+        }
         return;
     }
-    Node::changed( node );
+    Node::changed( node, property );
 }
 
 void Project::changed( ResourceGroup *group )
 {
     //kDebug(planDbg());
     emit resourceGroupChanged( group );
-    emit changed();
+    emit projectChanged();
 }
 
 void Project::changed( ScheduleManager *sm )
 {
     emit scheduleManagerChanged( sm );
-    emit changed();
+    emit projectChanged();
 }
 
 void Project::changed( MainSchedule *sch )
 {
     //kDebug(planDbg())<<sch->id();
     emit scheduleChanged( sch );
-    emit changed();
+    emit projectChanged();
 }
 
 void Project::sendScheduleToBeAdded( const ScheduleManager *sm, int row )
@@ -2592,7 +2600,7 @@ void Project::sendScheduleAdded( const MainSchedule *sch )
 {
     //kDebug(planDbg())<<sch->id();
     emit scheduleAdded( sch );
-    emit changed();
+    emit projectChanged();
 }
 
 void Project::sendScheduleToBeRemoved( const MainSchedule *sch )
@@ -2605,25 +2613,25 @@ void Project::sendScheduleRemoved( const MainSchedule *sch )
 {
     //kDebug(planDbg())<<sch->id();
     emit scheduleRemoved( sch );
-    emit changed();
+    emit projectChanged();
 }
 
 void Project::changed( Resource *resource )
 {
     emit resourceChanged( resource );
-    emit changed();
+    emit projectChanged();
 }
 
 void Project::changed( Calendar *cal )
 {
     emit calendarChanged( cal );
-    emit changed();
+    emit projectChanged();
 }
 
 void Project::changed( StandardWorktime *w )
 {
     emit standardWorktimeChanged( w );
-    emit changed();
+    emit projectChanged();
 }
 
 bool Project::addRelation( Relation *rel, bool check )
@@ -2638,7 +2646,7 @@ bool Project::addRelation( Relation *rel, bool check )
     rel->parent()->addDependChildNode( rel );
     rel->child()->addDependParentNode( rel );
     emit relationAdded( rel );
-    emit changed();
+    emit projectChanged();
     return true;
 }
 
@@ -2648,7 +2656,7 @@ void Project::takeRelation( Relation *rel )
     rel->parent() ->takeDependChildNode( rel );
     rel->child() ->takeDependParentNode( rel );
     emit relationRemoved( rel );
-    emit changed();
+    emit projectChanged();
 }
 
 void Project::setRelationType( Relation *rel, Relation::Type type )
@@ -2656,7 +2664,7 @@ void Project::setRelationType( Relation *rel, Relation::Type type )
     emit relationToBeModified( rel );
     rel->setType( type );
     emit relationModified( rel );
-    emit changed();
+    emit projectChanged();
 }
 
 void Project::setRelationLag( Relation *rel, const Duration &lag )
@@ -2664,7 +2672,7 @@ void Project::setRelationLag( Relation *rel, const Duration &lag )
     emit relationToBeModified( rel );
     rel->setLag( lag );
     emit relationModified( rel );
-    emit changed();
+    emit projectChanged();
 }
 
 QList<Node*> Project::flatNodeList( Node *parent )
diff --git a/plan/libs/kernel/kptproject.h b/plan/libs/kernel/kptproject.h
index 82aa0dd..b278438 100644
--- a/plan/libs/kernel/kptproject.h
+++ b/plan/libs/kernel/kptproject.h
@@ -520,7 +520,7 @@ public slots:
 
 signals:
     /// Emitted when anything in the project is changed (use with care)
-    void changed();
+    void projectChanged();
     /// Emitted when the WBS code definition has changed. This may change all nodes.
     void wbsDefinitionChanged();
     /// Emitted when a schedule has been calculated
@@ -638,8 +638,8 @@ protected:
 
 protected:
     friend class KPlatoXmlLoaderBase;
-
-    virtual void changed(Node *node);
+    using Node::changed;
+    virtual void changed(Node *node, int property = -1);
     
     Accounts m_accounts;
     QList<ResourceGroup*> m_resourceGroups;
diff --git a/plan/libs/kernel/kptschedule.cpp b/plan/libs/kernel/kptschedule.cpp
index 10ee3d0..0682bb8 100644
--- a/plan/libs/kernel/kptschedule.cpp
+++ b/plan/libs/kernel/kptschedule.cpp
@@ -233,8 +233,6 @@ void Schedule::initiateCalculation()
     effortNotMet = false;
     workStartTime = DateTime();
     workEndTime = DateTime();
-
-
 }
 
 void Schedule::calcResourceOverbooked()
@@ -518,15 +516,21 @@ void Schedule::copyAppointments( Schedule::CalculationMode from, Schedule::Calcu
     }
 }
 
-
 EffortCostMap Schedule::bcwsPrDay( EffortCostCalculationType type ) const
 {
+    return const_cast<Schedule*>( this )->bcwsPrDay( type );
+}
+
+EffortCostMap Schedule::bcwsPrDay( EffortCostCalculationType type )
+{
     //kDebug(planDbg())<<m_name<<m_appointments;
-    EffortCostMap ec;
-    foreach ( Appointment *a, m_appointments ) {
-        ec += a->plannedPrDay( a->startTime().date(), a->endTime().date(), type );
+    EffortCostCache &ec = m_bcwsPrDay[ (int)type ];
+    if ( ! ec.cached ) {
+        foreach ( Appointment *a, m_appointments ) {
+            ec.effortcostmap += a->plannedPrDay( a->startTime().date(), a->endTime().date(), type );
+        }
     }
-    return ec;
+    return ec.effortcostmap;
 }
 
 EffortCostMap Schedule::plannedEffortCostPrDay( const QDate &start, const QDate &end, \
EffortCostCalculationType type ) const @@ -669,6 +673,13 @@ QString Schedule::Log::formatMsg() const
     return s;
 }
 
+void Schedule::clearPerformanceCache()
+{
+    m_bcwsPrDay.clear();
+    m_bcwpPrDay.clear();
+    m_acwp.clear();
+}
+
 //-------------------------------------------------
 NodeSchedule::NodeSchedule()
         : Schedule(),
diff --git a/plan/libs/kernel/kptschedule.h b/plan/libs/kernel/kptschedule.h
index dabcd1c..05d4d40 100644
--- a/plan/libs/kernel/kptschedule.h
+++ b/plan/libs/kernel/kptschedule.h
@@ -51,6 +51,14 @@ class XMLLoaderObject;
 class SchedulerPlugin;
 class KPlatoXmlLoaderBase;
 
+/// Caches effortcost data (bcws, bcwp, acwp)
+class EffortCostCache {
+public:
+    EffortCostCache() : cached( false ) {}
+    bool cached;
+    EffortCostMap effortcostmap;
+};
+
 /**
  * The Schedule class holds data calculated during project
  * calculation and scheduling, eg start- and end-times and
@@ -153,7 +161,8 @@ public:
     virtual QList<Resource*> resources() const;
     /// Return the resource names that has appointments to this schedule
     virtual QStringList resourceNameList() const;
-    
+
+    virtual EffortCostMap bcwsPrDay( EffortCostCalculationType type = ECCT_All );
     virtual EffortCostMap bcwsPrDay( EffortCostCalculationType type = ECCT_All ) const;
     virtual EffortCostMap plannedEffortCostPrDay( const QDate &start, const QDate &end, \
                EffortCostCalculationType type = ECCT_All ) const;
     virtual EffortCostMap plannedEffortCostPrDay( const Resource *resource, const QDate &start, const \
QDate &end, EffortCostCalculationType type = ECCT_All ) const; @@ -250,6 +259,8 @@ public:
     
     virtual void incProgress() { if ( m_parent ) m_parent->incProgress(); }
 
+    void clearPerformanceCache();
+
 protected:
     virtual void changed( Schedule * /*sch*/ ) {}
     
@@ -334,6 +345,19 @@ protected:
     Duration positiveFloat;
     Duration negativeFloat;
     Duration freeFloat;
+
+    EffortCostCache &bcwsPrDayCache( int type ) {
+        return m_bcwsPrDay[ type ];
+    }
+    EffortCostCache &bcwpPrDayCache( int type ) {
+        return m_bcwpPrDay[ type ];
+    }
+    EffortCostCache &acwpCache( int type ) {
+        return m_acwp[ type ];
+    }
+    QMap<int, EffortCostCache> m_bcwsPrDay;
+    QMap<int, EffortCostCache> m_bcwpPrDay;
+    QMap<int, EffortCostCache> m_acwp;
 };
 
 /**
diff --git a/plan/libs/kernel/kpttask.cpp b/plan/libs/kernel/kpttask.cpp
index 26981b8..23ae2ab 100644
--- a/plan/libs/kernel/kpttask.cpp
+++ b/plan/libs/kernel/kpttask.cpp
@@ -747,7 +747,7 @@ double Task::bcws( const QDate &date, long id ) const
     return c;
 }
 
-EffortCostMap Task::bcwsPrDay( long int id, KPlato::EffortCostCalculationType typ ) const
+EffortCostMap Task::bcwsPrDay( long int id, EffortCostCalculationType typ )
 {
     //kDebug(planDbg());
     if (type() == Node::Type_Summarytask) {
@@ -757,17 +757,22 @@ EffortCostMap Task::bcwsPrDay( long int id, KPlato::EffortCostCalculationType ty
     if ( s == 0 ) {
         return EffortCostMap();
     }
-    EffortCostMap ec = s->bcwsPrDay( typ );
-    if ( m_startupCost > 0.0 ) {
-        ec.add( s->startTime.date(), Duration::zeroDuration, m_startupCost );
-    }
-    if ( m_shutdownCost > 0.0 ) {
-        ec.add( s->endTime.date(), Duration::zeroDuration, m_shutdownCost );
+    EffortCostCache &cache = s->bcwsPrDayCache( typ );
+    if ( ! cache.cached ) {
+        EffortCostMap ec = s->bcwsPrDay( typ );
+        if ( m_startupCost > 0.0 ) {
+            ec.add( s->startTime.date(), Duration::zeroDuration, m_startupCost );
+        }
+        if ( m_shutdownCost > 0.0 ) {
+            ec.add( s->endTime.date(), Duration::zeroDuration, m_shutdownCost );
+        }
+        cache.effortcostmap = ec;
+        cache.cached = true;
     }
-    return ec;
+    return cache.effortcostmap;
 }
 
-EffortCostMap Task::bcwpPrDay( long int id, KPlato::EffortCostCalculationType typ ) const
+EffortCostMap Task::bcwpPrDay( long int id, EffortCostCalculationType typ )
 {
     //kDebug(planDbg());
     if ( type() == Node::Type_Summarytask ) {
@@ -777,59 +782,64 @@ EffortCostMap Task::bcwpPrDay( long int id, KPlato::EffortCostCalculationType ty
     if ( s == 0 ) {
         return EffortCostMap();
     }
-    EffortCostMap e = s->bcwsPrDay( typ );
-    if ( completion().isStarted() && ! e.isEmpty() ) {
-        // calculate bcwp on bases of bcws *without* startup/shutdown cost
-        double totEff = e.totalEffort().toDouble( Duration::Unit_h );
-        double totCost = e.totalCost();
-        QDate sd = completion().entries().keys().value( 0 );
-        if ( ! sd.isValid() || e.startDate() < sd ) {
-            sd = e.startDate();
-        }
-        QDate ed = qMax( e.endDate(), completion().entryDate() );
-        for ( QDate d = sd; d <= ed; d = d.addDays( 1 ) ) {
-            double p = (double)(completion().percentFinished( d )) / 100.0;
-            EffortCost ec = e.days()[ d ];
-            ec.setBcwpEffort( totEff  * p );
-            ec.setBcwpCost( totCost  * p );
-            e.insert( d, ec );
-        }
-    }
-    if ( typ != ECCT_Work ) {
-        // add bcws startup/shutdown cost
-        if ( m_startupCost > 0.0 ) {
-            e.add( s->startTime.date(), Duration::zeroDuration, m_startupCost );
-        }
-        if ( m_shutdownCost > 0.0 ) {
-            e.add( s->endTime.date(), Duration::zeroDuration, m_shutdownCost );
-        }
-        // add bcwp startup/shutdown cost
-        if ( m_shutdownCost > 0.0 && completion().finishIsValid() ) {
-            QDate finish = completion().finishTime().date();
-            e.addBcwpCost( finish, m_shutdownCost );
-            kDebug(planDbg())<<"addBcwpCost:"<<finish<<m_shutdownCost;
-            // bcwp is cumulative so add to all entries after finish (in case task finished early)
-            for ( EffortCostDayMap::const_iterator it = e.days().constBegin(); it != \
                e.days().constEnd(); ++it ) {
-                const QDate date = it.key();
-                if ( date > finish ) {
-                    e.addBcwpCost( date, m_shutdownCost );
-                    kDebug(planDbg())<<"addBcwpCost:"<<date<<m_shutdownCost;
+    EffortCostCache cache = s->bcwpPrDayCache( typ );
+    if ( ! cache.cached ) {
+        EffortCostMap e = bcwsPrDay( id, typ );
+        if ( completion().isStarted() && ! e.isEmpty() ) {
+            // calculate bcwp on bases of bcws *without* startup/shutdown cost
+            double totEff = e.totalEffort().toDouble( Duration::Unit_h );
+            double totCost = e.totalCost();
+            QDate sd = completion().entries().keys().value( 0 );
+            if ( ! sd.isValid() || e.startDate() < sd ) {
+                sd = e.startDate();
+            }
+            QDate ed = qMax( e.endDate(), completion().entryDate() );
+            for ( QDate d = sd; d <= ed; d = d.addDays( 1 ) ) {
+                double p = (double)(completion().percentFinished( d )) / 100.0;
+                EffortCost ec = e.days()[ d ];
+                ec.setBcwpEffort( totEff  * p );
+                ec.setBcwpCost( totCost  * p );
+                e.insert( d, ec );
+            }
+        }
+        if ( typ != ECCT_Work ) {
+            // add bcws startup/shutdown cost
+            if ( m_startupCost > 0.0 ) {
+                e.add( s->startTime.date(), Duration::zeroDuration, m_startupCost );
+            }
+            if ( m_shutdownCost > 0.0 ) {
+                e.add( s->endTime.date(), Duration::zeroDuration, m_shutdownCost );
+            }
+            // add bcwp startup/shutdown cost
+            if ( m_shutdownCost > 0.0 && completion().finishIsValid() ) {
+                QDate finish = completion().finishTime().date();
+                e.addBcwpCost( finish, m_shutdownCost );
+                kDebug(planDbg())<<"addBcwpCost:"<<finish<<m_shutdownCost;
+                // bcwp is cumulative so add to all entries after finish (in case task finished early)
+                for ( EffortCostDayMap::const_iterator it = e.days().constBegin(); it != \
e.days().constEnd(); ++it ) { +                    const QDate date = it.key();
+                    if ( date > finish ) {
+                        e.addBcwpCost( date, m_shutdownCost );
+                        kDebug(planDbg())<<"addBcwpCost:"<<date<<m_shutdownCost;
+                    }
                 }
             }
-        }
-        if ( m_startupCost > 0.0 && completion().startIsValid() ) {
-            QDate start = completion().startTime().date();
-            e.addBcwpCost( start, m_startupCost );
-            // bcwp is cumulative so add to all entries after start
-            for ( EffortCostDayMap::const_iterator it = e.days().constBegin(); it != \
                e.days().constEnd(); ++it ) {
-                const QDate date = it.key();
-                if ( date > start ) {
-                    e.addBcwpCost( date, m_startupCost );
+            if ( m_startupCost > 0.0 && completion().startIsValid() ) {
+                QDate start = completion().startTime().date();
+                e.addBcwpCost( start, m_startupCost );
+                // bcwp is cumulative so add to all entries after start
+                for ( EffortCostDayMap::const_iterator it = e.days().constBegin(); it != \
e.days().constEnd(); ++it ) { +                    const QDate date = it.key();
+                    if ( date > start ) {
+                        e.addBcwpCost( date, m_startupCost );
+                    }
                 }
             }
         }
+        cache.effortcostmap = e;
+        cache.cached = true;
     }
-    return e;
+    return cache.effortcostmap;
 }
 
 Duration Task::budgetedWorkPerformed( const QDate &date, long id ) const
@@ -880,34 +890,43 @@ double Task::bcwp( const QDate &date, long id ) const
     return budgetedCostPerformed( date, id );
 }
 
-EffortCostMap Task::acwp( long int id, KPlato::EffortCostCalculationType typ ) const
+EffortCostMap Task::acwp( long int id, KPlato::EffortCostCalculationType typ )
 {
     if ( type() == Node::Type_Summarytask ) {
         return Node::acwp( id, typ );
     }
-    //kDebug(planDbg())<<m_name<<completion().entrymode();
-    switch ( completion().entrymode() ) {
-        case Completion::FollowPlan:
-            //TODO
-            break;
-        case Completion::EnterCompleted:
-            //hmmm
-        default: {
-            EffortCostMap m = completion().actualEffortCost( id );
-            if ( completion().isStarted() ) {
-                EffortCost e;
-                e.setCost( m_startupCost );
-                m.add( completion().startTime().date(), e );
-            }
-            if ( completion().isFinished() ) {
-                EffortCost e;
-                e.setCost( m_shutdownCost );
-                m.add( completion().finishTime().date(), e );
+    Schedule *s = schedule( id );
+    if ( s == 0 ) {
+        return EffortCostMap();
+    }
+    EffortCostCache ec = s->acwpCache( typ );
+    if ( ! ec.cached ) {
+        //kDebug(planDbg())<<m_name<<completion().entrymode();
+        EffortCostMap m;
+        switch ( completion().entrymode() ) {
+            case Completion::FollowPlan:
+                //TODO
+                break;
+            case Completion::EnterCompleted:
+                //hmmm
+            default: {
+                m = completion().actualEffortCost( id );
+                if ( completion().isStarted() ) {
+                    EffortCost e;
+                    e.setCost( m_startupCost );
+                    m.add( completion().startTime().date(), e );
+                }
+                if ( completion().isFinished() ) {
+                    EffortCost e;
+                    e.setCost( m_shutdownCost );
+                    m.add( completion().finishTime().date(), e );
+                }
             }
-            return m;
         }
+        ec.effortcostmap = m;
+        ec.cached = true;
     }
-    return EffortCostMap();
+    return ec.effortcostmap;
 }
 
 EffortCost Task::acwp( const QDate &date, long id ) const
@@ -2894,35 +2913,35 @@ Completion &Completion::operator=( const Completion &p )
     return *this;
 }
 
-void Completion::changed()
+void Completion::changed( int property)
 {
     if ( m_node ) {
-        m_node->changed();
+        m_node->changed(property);
     }
 }
 
 void Completion::setStarted( bool on )
 {
      m_started = on;
-     changed();
+     changed(Node::CompletionStarted);
 }
 
 void Completion::setFinished( bool on )
 {
      m_finished = on;
-     changed();
+     changed(Node::CompletionFinished);
 }
 
 void Completion::setStartTime( const DateTime &dt )
 {
      m_startTime = dt;
-     changed();
+     changed(Node::CompletionStartTime);
 }
 
 void Completion::setFinishTime( const DateTime &dt )
 {
      m_finishTime = dt;
-     changed();
+     changed(Node::CompletionFinishTime);
 }
 
 void Completion::setPercentFinished( const QDate &date, int value )
@@ -2935,7 +2954,7 @@ void Completion::setPercentFinished( const QDate &date, int value )
         m_entries[ date ] = e;
     }
     e->percentFinished = value;
-    changed();
+    changed(Node::CompletionPercentage);
 }
 
 void Completion::setRemainingEffort( const QDate &date, const Duration &value )
@@ -2948,7 +2967,7 @@ void Completion::setRemainingEffort( const QDate &date, const Duration &value )
         m_entries[ date ] = e;
     }
     e->remainingEffort = value;
-    changed();
+    changed(Node::CompletionRemainingEffort);
 }
 
 void Completion::setActualEffort( const QDate &date, const Duration &value )
@@ -2961,14 +2980,14 @@ void Completion::setActualEffort( const QDate &date, const Duration &value )
         m_entries[ date ] = e;
     }
     e->totalPerformed = value;
-    changed();
+    changed(Node::CompletionActualEffort);
 }
 
 void Completion::addEntry( const QDate &date, Entry *entry )
 {
      m_entries.insert( date, entry );
      //kDebug(planDbg())<<m_entries.count()<<" added:"<<date;
-     changed();
+     changed(Node::CompletionEntry);
 }
 
 QDate Completion::entryDate() const
diff --git a/plan/libs/kernel/kpttask.h b/plan/libs/kernel/kpttask.h
index 60cfb8f..57a045c 100644
--- a/plan/libs/kernel/kpttask.h
+++ b/plan/libs/kernel/kpttask.h
@@ -214,7 +214,7 @@ public:
     UsedEffort *usedEffort( const Resource *r ) const { return m_usedEffort.value( \
                const_cast<Resource*>( r ) ); }
     const ResourceUsedEffortMap &usedEffortMap() const { return m_usedEffort; }
     
-    void changed();
+    void changed( int propert = -1 );
     Node *node() const { return m_node; }
     void setNode( Node *node ) { m_node = node; }
     
@@ -459,21 +459,24 @@ public:
     /// Returns the cost planned to be used to reach the actual percent finished
     virtual double budgetedCostPerformed( const QDate &date, long id = CURRENTSCHEDULE ) const;
 
+    using Node::bcwsPrDay;
     /// Return map of Budgeted Cost of Work Scheduled pr day
-    virtual EffortCostMap bcwsPrDay( long id = CURRENTSCHEDULE, EffortCostCalculationType type = \
ECCT_All ) const; +    virtual EffortCostMap bcwsPrDay( long id = CURRENTSCHEDULE, \
EffortCostCalculationType type = ECCT_All );  
     /// Budgeted Cost of Work Scheduled
     virtual double bcws( const QDate &date, long id = CURRENTSCHEDULE ) const;
 
+    using Node::bcwpPrDay;
     /// Return map of Budgeted Cost of Work Performed pr day (also includes bcwsPrDay)
-    virtual EffortCostMap bcwpPrDay( long id = CURRENTSCHEDULE, EffortCostCalculationType type = \
ECCT_All ) const; +    virtual EffortCostMap bcwpPrDay( long id = CURRENTSCHEDULE, \
EffortCostCalculationType type = ECCT_All );  /// Budgeted Cost of Work Performed
     virtual double bcwp( long id = CURRENTSCHEDULE ) const;
     /// Budgeted Cost of Work Performed ( up to @p date )
     virtual double bcwp( const QDate &date, long id = CURRENTSCHEDULE ) const;
 
+    using Node::acwp;
     /// Map of Actual Cost of Work Performed
-    virtual EffortCostMap acwp( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All ) \
const; +    virtual EffortCostMap acwp( long id = CURRENTSCHEDULE, EffortCostCalculationType type = \
ECCT_All );  /// Actual Cost of Work Performed up to dat
     virtual EffortCost acwp( const QDate &date, long id = CURRENTSCHEDULE ) const;
 


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic