1 /* This file is part of the KDE project
2    Copyright (C) 2005 Dag Andersen <danders@get2net.dk>
3 
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public
6    License as published by the Free Software Foundation;
7    version 2 of the License.
8 
9    This library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13 
14    You should have received a copy of the GNU Library General Public License
15    along with this library; see the file COPYING.LIB.  If not, write to
16    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17    Boston, MA 02110-1301, USA.
18 */
19 
20 #ifndef KPTEFFORTCOST_H
21 #define KPTEFFORTCOST_H
22 
23 #include <QDate>
24 #include <QMap>
25 
26 #include "kptduration.h"
27 #include "kptdebug.h"
28 
29 #include <QDebug>
30 #include <QMetaType>
31 
32 namespace KPlato
33 {
34 
35 class PLANKERNEL_EXPORT EffortCost
36 {
37 public:
EffortCost()38     EffortCost()
39         : m_effort(Duration::zeroDuration),
40         m_cost(0),
41         m_bcwpEffort(0.0),
42         m_bcwpCost(0.0)
43     {}
EffortCost(KPlato::Duration effort,const double cost)44     EffortCost(KPlato::Duration effort, const double cost)
45         : m_effort(effort),
46         m_cost(cost),
47         m_bcwpEffort(0.0),
48         m_bcwpCost(0.0)
49     {
50         //debugPlan;
51     }
~EffortCost()52     ~EffortCost() {
53         //debugPlan;
54     }
hours()55     double hours() const { return m_effort.toDouble(Duration::Unit_h); }
effort()56     Duration effort() const { return m_effort; }
setEffort(KPlato::Duration effort)57     void setEffort(KPlato::Duration effort) { m_effort = effort; }
cost()58     double cost() const { return m_cost; }
setCost(double cost)59     void setCost(double cost) { m_cost = cost; }
setBcwpEffort(double value)60     void setBcwpEffort(double value) { m_bcwpEffort = value; }
bcwpEffort()61     double bcwpEffort() const { return m_bcwpEffort; }
setBcwpCost(double value)62     void setBcwpCost(double value) { m_bcwpCost = value; }
bcwpCost()63     double bcwpCost() const { return m_bcwpCost; }
64     void add(const Duration &effort, double cost, double bcwpEffort = 0.0, double bcwpCost = 0.0);
65     EffortCost &operator+=(const EffortCost &ec) {
66         add(ec.m_effort, ec.m_cost, ec.m_bcwpEffort, ec.m_bcwpCost);
67         return *this;
68     }
69 
70 #ifndef QT_NO_DEBUG_STREAM
71     QDebug debug(QDebug dbg) const;
72 #endif
73 
74 private:
75     Duration m_effort;
76     double m_cost;
77     double m_bcwpEffort;
78     double m_bcwpCost;
79 };
80 
81 typedef QMap<QDate, EffortCost> EffortCostDayMap;
82 class PLANKERNEL_EXPORT EffortCostMap
83 {
84 public:
EffortCostMap()85     EffortCostMap()
86         : m_days() {
87         //debugPlan;
88     }
89     EffortCostMap(const EffortCostMap &map);
90 
~EffortCostMap()91     ~EffortCostMap() {
92         //debugPlan;
93         m_days.clear();
94     }
95 
clear()96     void clear() { m_days.clear(); }
97 
effortCost(QDate date)98     EffortCost effortCost(QDate date) const {
99         EffortCost ec;
100         if (!date.isValid()) {
101             //errorPlan<<"Date not valid";
102             return ec;
103         }
104         EffortCostDayMap::const_iterator it = m_days.find(date);
105         if (it != m_days.end())
106             ec = it.value();
107         return ec;
108     }
109     void insert(const QDate &date, const EffortCost &ec);
110 
insert(QDate date,KPlato::Duration effort,const double cost)111     void insert(QDate date, KPlato::Duration effort, const double cost) {
112         if (!date.isValid()) {
113             //errorPlan<<"Date not valid";
114             return;
115         }
116         m_days.insert(date, EffortCost(effort, cost));
117     }
118     /**
119      * If data for this date already exists add the new values to the old,
120      * else the new values are inserted.
121      */
add(QDate date,KPlato::Duration effort,const double cost)122     EffortCost &add(QDate date, KPlato::Duration effort, const double cost) {
123         return add(date, EffortCost(effort, cost));
124     }
125     /**
126      * If data for this date already exists add the new values to the old,
127      * else the new value is inserted.
128      */
add(QDate date,const EffortCost & ec)129     EffortCost &add(QDate date, const EffortCost &ec) {
130         if (!date.isValid()) {
131             //errorPlan<<"Date not valid";
132             return zero();
133         }
134         //debugPlan<<date.toString();
135         return m_days[date] += ec;
136     }
137 
isEmpty()138     bool isEmpty() const {
139         return m_days.isEmpty();
140     }
141 
days()142     const EffortCostDayMap &days() const { return m_days; }
143 
144     EffortCostMap &operator=(const EffortCostMap &ec);
145     EffortCostMap &operator+=(const EffortCostMap &ec);
effortCostOnDate(QDate date)146     EffortCost &effortCostOnDate(QDate date) {
147         return m_days[date];
148     }
149     /// Return total cost for the next num days starting at date
150     double cost(QDate date, int num=7) {
151         double r=0.0;
152         for (int i=0; i < num; ++i) {
153             r += costOnDate(date.addDays(i));
154         }
155         return r;
156     }
costOnDate(QDate date)157     double costOnDate(QDate date) const {
158         if (!date.isValid()) {
159             //errorPlan<<"Date not valid";
160             return 0.0;
161         }
162         if (m_days.contains(date)) {
163             return m_days[date].cost();
164         }
165         return 0.0;
166     }
effortOnDate(QDate date)167     Duration effortOnDate(QDate date) const {
168         if (!date.isValid()) {
169             errorPlan<<"Date not valid";
170             return Duration::zeroDuration;
171         }
172         if (m_days.contains(date)) {
173             return m_days[date].effort();
174         }
175         return Duration::zeroDuration;
176     }
hoursOnDate(QDate date)177     double hoursOnDate(QDate date) const {
178         if (!date.isValid()) {
179             errorPlan<<"Date not valid";
180             return 0.0;
181         }
182         if (m_days.contains(date)) {
183             return m_days[date].hours();
184         }
185         return 0.0;
186     }
187     void addBcwpCost(const QDate &date, double cost);
188 
bcwpCostOnDate(QDate date)189     double bcwpCostOnDate(QDate date) const {
190         if (!date.isValid()) {
191             //errorPlan<<"Date not valid";
192             return 0.0;
193         }
194         if (m_days.contains(date)) {
195             return m_days[date].bcwpCost();
196         }
197         return 0.0;
198     }
bcwpEffortOnDate(QDate date)199     double bcwpEffortOnDate(QDate date) const {
200         if (!date.isValid()) {
201             //errorPlan<<"Date not valid";
202             return 0.0;
203         }
204         if (m_days.contains(date)) {
205             return m_days[date].bcwpEffort();
206         }
207         return 0.0;
208     }
totalCost()209     double totalCost() const {
210         double cost = 0.0;
211         EffortCostDayMap::const_iterator it;
212         for(it = m_days.constBegin(); it != m_days.constEnd(); ++it) {
213             cost += it.value().cost();
214         }
215         return cost;
216     }
totalEffort()217     Duration totalEffort() const {
218         Duration eff;
219         EffortCostDayMap::const_iterator it;
220         for(it = m_days.constBegin(); it != m_days.constEnd(); ++it) {
221             eff += it.value().effort();
222         }
223         return eff;
224     }
225 
costTo(QDate date)226     double costTo(QDate date) const {
227         double cost = 0.0;
228         EffortCostDayMap::const_iterator it;
229         for(it = m_days.constBegin(); it != m_days.constEnd(); ++it) {
230             if (it.key() > date) {
231                 break;
232             }
233             cost += it.value().cost();
234         }
235         return cost;
236     }
effortTo(QDate date)237     Duration effortTo(QDate date) const {
238         Duration eff;
239         EffortCostDayMap::const_iterator it;
240         for(it = m_days.constBegin(); it != m_days.constEnd(); ++it) {
241             if (it.key() > date) {
242                 break;
243             }
244             eff += it.value().effort();
245         }
246         return eff;
247     }
hoursTo(QDate date)248     double hoursTo(QDate date) const {
249         double eff = 0.0;
250         EffortCostDayMap::const_iterator it;
251         for(it = m_days.constBegin(); it != m_days.constEnd(); ++it) {
252             if (it.key() > date) {
253                 break;
254             }
255             eff += it.value().hours();
256         }
257         return eff;
258     }
259     /// Return the BCWP cost to @p date. (BSWP is cumulative)
260     double bcwpCost(const QDate &date) const;
261     /// Return the BCWP effort to @p date. (BSWP is cumulative)
262     double bcwpEffort(const QDate &date) const;
263     /// Return the BCWP total cost. Since BCWP is cumulative this is the last entry.
bcwpTotalCost()264     double bcwpTotalCost() const {
265         double cost = 0.0;
266         if (! m_days.isEmpty()) {
267             cost = m_days.last().bcwpCost();
268         }
269         return cost;
270     }
271     /// Return the BCWP total cost. Since BCWP is cumulative this is the last entry.
bcwpTotalEffort()272     double bcwpTotalEffort() const {
273         double eff = 0.0;
274         if (! m_days.isEmpty()) {
275             eff = m_days.last().bcwpEffort();
276         }
277         return eff;
278     }
279 
startDate()280     QDate startDate() const { return m_days.isEmpty() ? QDate() : m_days.firstKey(); }
endDate()281     QDate endDate() const { return m_days.isEmpty() ? QDate() : m_days.lastKey(); }
282 
283 #ifndef QT_NO_DEBUG_STREAM
284     QDebug debug(QDebug dbg) const;
285 #endif
286 
287 private:
zero()288     EffortCost &zero() { return m_zero; }
289 
290 private:
291     EffortCost m_zero;
292     EffortCostDayMap m_days;
293 };
294 
295 
296 } //namespace KPlato
297 
298 Q_DECLARE_METATYPE(KPlato::EffortCost)
299 Q_DECLARE_METATYPE(KPlato::EffortCostMap)
300 
301 #ifndef QT_NO_DEBUG_STREAM
302 PLANKERNEL_EXPORT QDebug operator<<(QDebug dbg, const KPlato::EffortCost &ec);
303 PLANKERNEL_EXPORT QDebug operator<<(QDebug dbg, const KPlato::EffortCost *ec);
304 PLANKERNEL_EXPORT QDebug operator<<(QDebug dbg, const KPlato::EffortCostMap &i);
305 #endif
306 
307 #endif
308