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 <QDateTime> |
24 | #include <QMap> |
25 | |
26 | #include "kptduration.h" |
27 | |
28 | #include <kdebug.h> |
29 | |
30 | #include <QDebug> |
31 | #include <QMetaType> |
32 | |
33 | namespace KPlato |
34 | { |
35 | |
36 | class KPLATOKERNEL_EXPORT EffortCost |
37 | { |
38 | public: |
39 | EffortCost() |
40 | : m_effort(Duration::zeroDuration), |
41 | m_cost(0), |
42 | m_bcwpEffort(0.0), |
43 | m_bcwpCost(0.0) |
44 | {} |
45 | EffortCost(const Duration &effort, const double cost) |
46 | : m_effort(effort), |
47 | m_cost(cost), |
48 | m_bcwpEffort(0.0), |
49 | m_bcwpCost(0.0) |
50 | { |
51 | //kDebug(); |
52 | } |
53 | ~EffortCost() { |
54 | //kDebug(); |
55 | } |
56 | double hours() const { return m_effort.toDouble( Duration::Unit_h ); } |
57 | Duration effort() const { return m_effort; } |
58 | void setEffort( const Duration &effort ) { m_effort = effort; } |
59 | double cost() const { return m_cost; } |
60 | void setCost(double cost) { m_cost = cost; } |
61 | void setBcwpEffort( double value ) { m_bcwpEffort = value; } |
62 | double bcwpEffort() const { return m_bcwpEffort; } |
63 | void setBcwpCost( double value ) { m_bcwpCost = value; } |
64 | double bcwpCost() const { return m_bcwpCost; } |
65 | void add(const Duration &effort, double cost, double bcwpEffort = 0.0, double bcwpCost = 0.0 ); |
66 | EffortCost &operator+=(const EffortCost &ec) { |
67 | add(ec.m_effort, ec.m_cost, ec.m_bcwpEffort, ec.m_bcwpCost); |
68 | return *this; |
69 | } |
70 | |
71 | #ifndef QT_NO_DEBUG_STREAM |
72 | QDebug debug( QDebug dbg) const; |
73 | #endif |
74 | |
75 | private: |
76 | Duration m_effort; |
77 | double m_cost; |
78 | double m_bcwpEffort; |
79 | double m_bcwpCost; |
80 | }; |
81 | |
82 | typedef QMap<QDate, EffortCost> EffortCostDayMap; |
83 | class KPLATOKERNEL_EXPORT EffortCostMap |
84 | { |
85 | public: |
86 | EffortCostMap() |
87 | : m_days() { |
88 | //kDebug(); |
89 | } |
90 | EffortCostMap( const EffortCostMap &map ); |
91 | |
92 | ~EffortCostMap() { |
93 | //kDebug(); |
94 | m_days.clear(); |
95 | } |
96 | |
97 | void clear() { m_days.clear(); } |
98 | |
99 | EffortCost effortCost(const QDate &date) const { |
100 | EffortCost ec; |
101 | if (!date.isValid()) { |
102 | //kError()<<"Date not valid"; |
103 | return ec; |
104 | } |
105 | EffortCostDayMap::const_iterator it = m_days.find(date); |
106 | if (it != m_days.end()) |
107 | ec = it.value(); |
108 | return ec; |
109 | } |
110 | void insert(const QDate &date, const EffortCost &ec ); |
111 | |
112 | void insert(const QDate &date, const Duration &effort, const double cost) { |
113 | if (!date.isValid()) { |
114 | //kError()<<"Date not valid"; |
115 | return; |
116 | } |
117 | m_days.insert(date, EffortCost(effort, cost)); |
118 | } |
119 | /** |
120 | * If data for this date already exists add the new values to the old, |
121 | * else the new values are inserted. |
122 | */ |
123 | EffortCost &add(const QDate &date, const Duration &effort, const double cost) { |
124 | return add(date, EffortCost(effort, cost)); |
125 | } |
126 | /** |
127 | * If data for this date already exists add the new values to the old, |
128 | * else the new value is inserted. |
129 | */ |
130 | EffortCost &add(const QDate &date, const EffortCost &ec) { |
131 | if (!date.isValid()) { |
132 | //kError()<<"Date not valid"; |
133 | return zero(); |
134 | } |
135 | //kDebug()<<date.toString(); |
136 | return m_days[date] += ec; |
137 | } |
138 | |
139 | bool isEmpty() const { |
140 | return m_days.isEmpty(); |
141 | } |
142 | |
143 | const EffortCostDayMap &days() const { return m_days; } |
144 | |
145 | EffortCostMap &operator=(const EffortCostMap &ec); |
146 | EffortCostMap &operator+=(const EffortCostMap &ec); |
147 | EffortCost &effortCostOnDate(const QDate &date) { |
148 | return m_days[date]; |
149 | } |
150 | /// Return total cost for the next num days starting at date |
151 | double cost(const QDate &date, int num=7) { |
152 | double r=0.0; |
153 | for (int i=0; i < num; ++i) { |
154 | r += costOnDate(date.addDays(i)); |
155 | } |
156 | return r; |
157 | } |
158 | double costOnDate(const QDate &date) const { |
159 | if (!date.isValid()) { |
160 | //kError()<<"Date not valid"; |
161 | return 0.0; |
162 | } |
163 | if (m_days.contains(date)) { |
164 | return m_days[date].cost(); |
165 | } |
166 | return 0.0; |
167 | } |
168 | Duration effortOnDate(const QDate &date) const { |
169 | if (!date.isValid()) { |
170 | kError()<<"Date not valid" ; |
171 | return Duration::zeroDuration; |
172 | } |
173 | if (m_days.contains(date)) { |
174 | return m_days[date].effort(); |
175 | } |
176 | return Duration::zeroDuration; |
177 | } |
178 | double hoursOnDate(const QDate &date) const { |
179 | if (!date.isValid()) { |
180 | kError()<<"Date not valid" ; |
181 | return 0.0; |
182 | } |
183 | if (m_days.contains(date)) { |
184 | return m_days[date].hours(); |
185 | } |
186 | return 0.0; |
187 | } |
188 | void addBcwpCost( const QDate &date, double cost ); |
189 | |
190 | double bcwpCostOnDate(const QDate &date) const { |
191 | if (!date.isValid()) { |
192 | //kError()<<"Date not valid"; |
193 | return 0.0; |
194 | } |
195 | if (m_days.contains(date)) { |
196 | return m_days[date].bcwpCost(); |
197 | } |
198 | return 0.0; |
199 | } |
200 | double bcwpEffortOnDate(const QDate &date) const { |
201 | if (!date.isValid()) { |
202 | //kError()<<"Date not valid"; |
203 | return 0.0; |
204 | } |
205 | if (m_days.contains(date)) { |
206 | return m_days[date].bcwpEffort(); |
207 | } |
208 | return 0.0; |
209 | } |
210 | double totalCost() const { |
211 | double cost = 0.0; |
212 | EffortCostDayMap::const_iterator it; |
213 | for(it = m_days.constBegin(); it != m_days.constEnd(); ++it) { |
214 | cost += it.value().cost(); |
215 | } |
216 | return cost; |
217 | } |
218 | Duration totalEffort() const { |
219 | Duration eff; |
220 | EffortCostDayMap::const_iterator it; |
221 | for(it = m_days.constBegin(); it != m_days.constEnd(); ++it) { |
222 | eff += it.value().effort(); |
223 | } |
224 | return eff; |
225 | } |
226 | |
227 | double costTo( const QDate &date ) const { |
228 | double cost = 0.0; |
229 | EffortCostDayMap::const_iterator it; |
230 | for(it = m_days.constBegin(); it != m_days.constEnd(); ++it) { |
231 | if ( it.key() > date ) { |
232 | break; |
233 | } |
234 | cost += it.value().cost(); |
235 | } |
236 | return cost; |
237 | } |
238 | Duration effortTo( const QDate &date ) const { |
239 | Duration eff; |
240 | EffortCostDayMap::const_iterator it; |
241 | for(it = m_days.constBegin(); it != m_days.constEnd(); ++it) { |
242 | if ( it.key() > date ) { |
243 | break; |
244 | } |
245 | eff += it.value().effort(); |
246 | } |
247 | return eff; |
248 | } |
249 | double hoursTo( const QDate &date ) const { |
250 | double eff = 0.0; |
251 | EffortCostDayMap::const_iterator it; |
252 | for(it = m_days.constBegin(); it != m_days.constEnd(); ++it) { |
253 | if ( it.key() > date ) { |
254 | break; |
255 | } |
256 | eff += it.value().hours(); |
257 | } |
258 | return eff; |
259 | } |
260 | /// Return the BCWP cost to @p date. (BSWP is cumulative) |
261 | double bcwpCost( const QDate &date ) const; |
262 | /// Return the BCWP effort to @p date. (BSWP is cumulative) |
263 | double bcwpEffort( const QDate &date ) const; |
264 | /// Return the BCWP total cost. Since BCWP is cumulative this is the last entry. |
265 | double bcwpTotalCost() const { |
266 | double cost = 0.0; |
267 | if ( ! m_days.isEmpty() ) { |
268 | cost = m_days.values().last().bcwpCost(); |
269 | } |
270 | return cost; |
271 | } |
272 | /// Return the BCWP total cost. Since BCWP is cumulative this is the last entry. |
273 | double bcwpTotalEffort() const { |
274 | double eff = 0.0; |
275 | if ( ! m_days.isEmpty() ) { |
276 | eff = m_days.values().last().bcwpEffort(); |
277 | } |
278 | return eff; |
279 | } |
280 | |
281 | QDate startDate() const { return m_days.isEmpty() ? QDate() : m_days.keys().first(); } |
282 | QDate endDate() const { return m_days.isEmpty() ? QDate() : m_days.keys().last(); } |
283 | |
284 | #ifndef QT_NO_DEBUG_STREAM |
285 | QDebug debug( QDebug dbg) const; |
286 | #endif |
287 | |
288 | private: |
289 | EffortCost &zero() { return m_zero; } |
290 | |
291 | private: |
292 | EffortCost m_zero; |
293 | EffortCostDayMap m_days; |
294 | }; |
295 | |
296 | |
297 | } //namespace KPlato |
298 | |
299 | Q_DECLARE_METATYPE( KPlato::EffortCost ) |
300 | Q_DECLARE_METATYPE( KPlato::EffortCostMap ) |
301 | |
302 | #ifndef QT_NO_DEBUG_STREAM |
303 | KPLATOKERNEL_EXPORT QDebug operator<<( QDebug dbg, const KPlato::EffortCost &ec ); |
304 | KPLATOKERNEL_EXPORT QDebug operator<<( QDebug dbg, const KPlato::EffortCost *ec ); |
305 | KPLATOKERNEL_EXPORT QDebug operator<<( QDebug dbg, const KPlato::EffortCostMap &i ); |
306 | #endif |
307 | |
308 | #endif |
309 | |