OSDN Git Service

adjust integer's signedness
[tjqt4port/tj2qt4.git] / taskjuggler / Task.h
1 /*
2  * task.h - TaskJuggler
3  *
4  * Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006
5  * Chris Schlaeger <cs@kde.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of version 2 of the GNU General Public License as
9  * published by the Free Software Foundation.
10  *
11  * $Id$
12  */
13
14 #ifndef _Task_h_
15 #define _Task_h_
16
17 #include <config.h>
18
19 #include <stdarg.h>
20
21 #include <qdom.h>
22 //Added by qt3to4:
23 #include <Q3PtrList>
24
25 #include "debug.h"
26 #include "TaskList.h"
27 #include "TaskScenario.h"
28 #include "ShiftSelectionList.h"
29 #include "LoopDetectorInfo.h"
30 #include "TaskDependency.h"
31 #include "Journal.h"
32
33 class Project;
34 class Resource;
35 class Account;
36 class Shift;
37 class TaskList;
38 class QDomElement;
39 class QDomDocument;
40 class Allocation;
41 class Interval;
42 class UsageLimits;
43
44 /**
45  * This class stores all task related information and provides methods to
46  * manipulte them. It provides fundamental functions like the scheduler.
47  *
48  * @short The class that holds all task related information.
49  * @see Resource
50  * @see CoreAttributes
51  * @author Chris Schlaeger <cs@kde.org>
52  */
53 class Task : public CoreAttributes
54 {
55     friend int TaskList::compareItemsLevel(CoreAttributes*, CoreAttributes*,
56                                            int);
57
58 public:
59     Task(Project* prj, const QString& id_, const QString& n, Task* p,
60          const QString& f, int l);
61     virtual ~Task();
62
63     virtual CAType getType() const { return CA_Task; }
64
65     Task* getParent() const { return static_cast<Task*>(parent); }
66
67     TaskListIterator getSubListIterator() const
68     {
69         return TaskListIterator(*sub);
70     }
71
72     enum SchedulingInfo { ASAP, ALAP };
73
74     void inheritValues();
75
76     void setProjectId(const QString& i) { projectId = i; }
77     const QString& getProjectId() const { return projectId; }
78
79     void setNote(const QString& d) { note = d; }
80     const QString& getNote() const { return note; }
81
82     void addJournalEntry(JournalEntry* entry);
83
84     bool hasJournal() const { return !journal.isEmpty(); }
85
86     Journal::Iterator getJournalIterator() const;
87
88     void setReference(const QString& r, const QString& l)
89     {
90         ref = r;
91         refLabel = l;
92     }
93     const QString& getReference() const { return ref; }
94     const QString& getReferenceLabel() const { return refLabel; }
95
96     void setScheduling(SchedulingInfo si) { scheduling = si; }
97     SchedulingInfo getScheduling() const { return scheduling; }
98
99     void setPriority(int p) { priority = p; }
100     int getPriority() const { return priority; }
101
102     void setResponsible(Resource* r) { responsible = r; }
103     Resource* getResponsible() const { return responsible; }
104
105     void setMilestone(bool ms = true) { milestone = ms; }
106     bool isMilestone() const { return milestone; }
107
108     void setAccount(Account* a) { account = a; }
109     Account* getAccount() const { return account; }
110
111     TaskDependency* addDepends(const QString& id);
112     Q3PtrListIterator<TaskDependency> getDependsIterator() const
113     {
114         return Q3PtrListIterator<TaskDependency>(depends);
115     }
116     TaskDependency* addPrecedes(const QString& id);
117     Q3PtrListIterator<TaskDependency> getPrecedesIterator() const
118     {
119         return Q3PtrListIterator<TaskDependency>(precedes);
120     }
121     bool addShift(const Interval& i, Shift* s);
122
123     void addAllocation(Allocation* a) { allocations.append(a); }
124     void purgeAllocations() { allocations.clear(); }
125     Q3PtrListIterator<Allocation> getAllocationIterator() const
126     {
127         return Q3PtrListIterator<Allocation>(allocations);
128     }
129
130     TaskListIterator getPreviousIterator() const
131     {
132         return TaskListIterator(previous);
133     }
134     bool hasPrevious() const { return !previous.isEmpty(); }
135
136     TaskListIterator getFollowersIterator() const
137     {
138         return TaskListIterator(followers);
139     }
140     bool hasFollowers() const { return !followers.isEmpty(); }
141
142     bool hasPrevious(const Task* t) { return previous.findRef(t) != -1; }
143     bool hasFollower(const Task* t) { return followers.findRef(t) != -1; }
144
145     void collectDependencies(TaskList& list, long depth) const;
146
147     // The following group of functions operates only on scenario variables.
148     void setSpecifiedStart(int sc, time_t s)
149     {
150         scenarios[sc].specifiedStart = s;
151     }
152     time_t getSpecifiedStart(int sc)
153     {
154         return scenarios[sc].specifiedStart;
155     }
156     void setStart(int sc, time_t s) { scenarios[sc].start = s; }
157     time_t getStart(int sc) const { return scenarios[sc].start; }
158
159     void setSpecifiedEnd(int sc, time_t s)
160     {
161         scenarios[sc].specifiedEnd = s;
162     }
163     time_t getSpecifiedEnd(int sc)
164     {
165         return scenarios[sc].specifiedEnd;
166     }
167     void setEnd(int sc, time_t s) { scenarios[sc].end = s; }
168     time_t getEnd(int sc) const { return scenarios[sc].end; }
169
170     void setSpecifiedPeriod(int sc, const Interval& iv)
171     {
172         scenarios[sc].specifiedStart = iv.getStart();
173         scenarios[sc].specifiedEnd = iv.getEnd();
174     }
175
176     time_t getStartBufferEnd(int sc) const
177     {
178         return scenarios[sc].startBufferEnd;
179     }
180     time_t getEndBufferStart(int sc) const
181     {
182         return scenarios[sc].endBufferStart;
183     }
184
185     void setMinStart(int sc, time_t s) { scenarios[sc].minStart = s; }
186     time_t getMinStart(int sc) const { return scenarios[sc].minStart; }
187
188     void setMaxStart(int sc, time_t s) { scenarios[sc].maxStart = s; }
189     time_t getMaxStart(int sc) const { return scenarios[sc].maxStart; }
190
191     void setMinEnd(int sc, time_t e) { scenarios[sc].minEnd = e; }
192     time_t getMinEnd(int sc) const { return scenarios[sc].minEnd; }
193
194     void setMaxEnd(int sc, time_t e) { scenarios[sc].maxEnd = e; }
195     time_t getMaxEnd(int sc) const { return scenarios[sc].maxEnd; }
196
197     void setLength(int sc, double days) { scenarios[sc].length = days; }
198     double getLength(int sc) const { return scenarios[sc].length; }
199
200     void setEffort(int sc, double e) { scenarios[sc].effort = e; }
201     double getEffort(int sc) const { return scenarios[sc].effort; }
202
203     void setDuration(int sc, double d) { scenarios[sc].duration = d; }
204     double getDuration(int sc) const { return scenarios[sc].duration; }
205
206     bool isStartOk(int sc) const
207     {
208         return scenarios[sc].isStartOk();
209     }
210     bool isEndOk(int sc) const
211     {
212         return scenarios[sc].isEndOk();
213     }
214
215     bool isBuffer(int sc, const Interval& iv) const;
216
217     void setComplete(int sc, double c) { scenarios[sc].reportedCompletion = c; }
218     double getComplete(int sc) const
219     {
220         return scenarios[sc].reportedCompletion;
221     }
222
223     void setStatusNote(int sc, const QString& d)
224     {
225         scenarios[sc].statusNote = d;
226     }
227     const QString& getStatusNote(int sc) const
228     {
229         return scenarios[sc].statusNote;
230     }
231
232     void setStartBuffer(int sc, double p) { scenarios[sc].startBuffer = p; }
233     double getStartBuffer(int sc) const { return scenarios[sc].startBuffer; }
234
235     void setEndBuffer(int sc, double p) { scenarios[sc]. endBuffer = p; }
236     double getEndBuffer(int sc) const { return scenarios[sc].endBuffer; }
237
238     void setStartCredit(int sc, double c) { scenarios[sc].startCredit = c; }
239     double getStartCredit(int sc) const { return scenarios[sc].startCredit; }
240
241     void setEndCredit(int sc, double c) { scenarios[sc].endCredit = c; }
242     double getEndCredit(int sc) const { return scenarios[sc].endCredit; }
243
244     double getCalcEffort(int sc) const;
245     double getCalcDuration(int sc) const;
246
247     double getCredits(int sc, const Interval& period, AccountType acctType,
248                       const Resource* resource = 0, bool recursive = true)
249         const;
250
251     bool isActive(int sc, const Interval& period) const;
252     TaskStatus getStatus(int sc) const { return scenarios[sc].status; }
253     QString getStatusText(int sc) const;
254
255     QString getSchedulingText() const;
256
257     bool isCompleted(int sc, time_t date) const;
258     void calcCompletionDegree(int sc);
259     void calcContainerCompletionDegree(int sc, time_t now);
260     double getCompletionDegree(int sc) const;
261     double getCalcedCompletionDegree(int sc) const;
262     TaskStatus getCompletionStatus(int sc) const
263     {
264         return scenarios[sc].status;
265     }
266     double getCompletedLoad(int sc) const;
267     double getRemainingLoad(int sc) const;
268
269     double getLoad(int sc, const Interval& period, const Resource* resource = 0)
270         const;
271     long getAllocatedTime(int sc, const Interval& period,
272                           const Resource* resource = 0) const;
273     double getAllocatedTimeLoad(int sc, const Interval& period,
274                                 const Resource* resource = 0) const;
275
276     void addBookedResource(int sc, Resource* r)
277     {
278         if (scenarios[sc].bookedResources.findRef((CoreAttributes*) r) == -1)
279             scenarios[sc].bookedResources.inSort((CoreAttributes*) r);
280     }
281     bool isBookedResource(int sc, const Resource* r) const
282     {
283         return scenarios[sc].bookedResources.find((CoreAttributes*) r) != -1;
284     }
285     ResourceListIterator getBookedResourcesIterator(int sc) const
286     {
287         return ResourceListIterator(scenarios[sc].bookedResources);
288     }
289     ResourceList getBookedResources(int sc) const
290     {
291         return scenarios[sc].bookedResources;
292     }
293     void setSpecifiedScheduled(int sc, bool ps)
294     {
295         scenarios[sc].specifiedScheduled = ps;
296     }
297     bool getSpecifiedScheduled(int sc) const
298     {
299         return scenarios[sc].specifiedScheduled;
300     } 
301     void setScheduled(int sc, bool ps) { scenarios[sc].scheduled = ps; }
302     bool getScheduled(int sc) const { return scenarios[sc].scheduled; }
303
304     bool isDutyOf(int sc, const Resource* r) const
305     {
306         return scenarios[sc].isDutyOf(r);
307     }
308
309     void overlayScenario(int base, int sc);
310     void prepareScenario(int sc);
311     void finishScenario(int sc);
312     void computeCriticalness(int sc);
313     double getCriticalness(int sc) const { return scenarios[sc].criticalness; }
314     void checkAndMarkCriticalPath(int sc, double minSlack, time_t maxEnd);
315
316     double computePathCriticalness(int sc);
317     double getPathCriticalness(int sc) const
318     {
319         return scenarios[sc].pathCriticalness;
320     }
321
322     bool isOnCriticalPath(int sc, bool leavesOnly = true) const
323     {
324         if (!isLeaf() && leavesOnly)
325             return false;
326
327         return scenarios[sc].isOnCriticalPath;
328     }
329
330     bool hasCriticalLinkTo(int sc, const Task* t) const
331     {
332         return scenarios[sc].criticalLinks.containsRef(t);
333     }
334
335     /**
336      * @retval true if itself or one of its subtasks (recursively) is on the critical path
337      * @retval false otherwise.
338      */
339     bool isOrHasDescendantOnCriticalPath(int sc) const;
340
341     bool isContainer() const { return !sub->isEmpty(); }
342
343     bool xRef(Q3Dict<Task>& hash);
344     void implicitXRef();
345     void sortAllocations();
346     void saveSpecifiedBookedResources();
347     QString resolveId(QString relId);
348
349     bool preScheduleOk(int sc);
350     bool scheduleOk(int sc) const;
351     /**
352      * Checks for loops in task interdependencies starting with the current
353      * task.
354      * @param ckedTaskList The list of already checked tasks. Will be appended
355      * to.
356      * @retval true if a loop was detected.
357      * @retval false otherwise.
358      */
359     bool loopDetector(LDIList& chkedTaskList) const;
360     bool checkDetermination(int sc) const;
361     void computeBuffers();
362     time_t nextSlot(time_t slotDuration) const;
363     bool isReadyForScheduling() const;
364     bool schedule(int sc, time_t& reqStart, time_t duration);
365     void propagateInitialValues(int sc);
366     void setRunaway();
367     bool isRunaway() const;
368
369     bool isSubTask(const Task* t) const;
370
371     bool isSchedulingDone() const { return schedulingDone; }
372
373     void errorMessage(const QString& msg) const;
374     void warningMessage(const QString& msg) const;
375
376     QDomElement xmlElement( QDomDocument& doc, bool absId = true );
377
378     void setSvgGanttReportIndex(int sc, int i) { scenarios[sc].svgGanttReportIndex = i; }
379     int getSvgGanttReportIndex(int sc) { return scenarios[sc].svgGanttReportIndex;  }
380
381 private:
382     void propagateStart(int sc, time_t date);
383     void propagateEnd(int sc, time_t date);
384     /**
385      * Checks for loops in task interdependencies starting with the current
386      * task under ASAP or ALAP scheduling.
387      * @param ckedTaskList The list of already checked tasks. Will be appended
388      * to.
389      * @retval true if a loop was detected.
390      * @retval false otherwise.
391      */
392     bool loopDetection(LDIList& list, LDIList& chkedTaskList, bool atEnd,
393                        bool fromOutside) const;
394     bool checkPathForLoops(LDIList& list, bool atEnd) const;
395     bool scheduleContainer(int sc);
396     Task* subFirst() { return (Task*) sub->first(); }
397     Task* subNext() { return (Task*) sub->next(); }
398     bool bookResource(Resource* r, time_t day, time_t duration,
399                       int& slotsToLimit, bool& encounteredBooked);
400     void bookResources(int sc, time_t day, time_t duration);
401     void addBookedResource(Resource* r)
402     {
403         if (bookedResources.findRef((CoreAttributes*) r) == -1)
404             bookedResources.inSort((CoreAttributes*) r);
405     }
406     Q3PtrList<Resource> createCandidateList(int sc, time_t date, Allocation* a);
407     time_t earliestStart(int sc) const;
408     time_t latestEnd(int sc) const;
409
410     bool startCanBeDetermined(LDIList& list, int sc) const;
411     bool endCanBeDetermined(LDIList& list, int sc) const;
412
413     bool hasStartDependency(int sc) const;
414     bool hasEndDependency(int sc) const;
415
416     bool hasStartDependency() const;
417     bool hasEndDependency() const;
418
419     bool analyzePath(int sc, double minSlack, time_t pathStart, long busyTime,
420                      long worstMinSlackTime, long& checked, long& found);
421     void collectTransientFollowers(TaskList& list);
422
423     bool countMilestones(int sc, time_t now, int& totalMilestones,
424                          int& completedMilestones,
425                          int& reportedCompletedMilestones);
426     bool sumUpEffort(int sc, time_t now, double& totalEffort,
427                      double& completedEffort,
428                      double& reportedCompletedEffort);
429
430     /// A longer description of the task.
431     QString note;
432
433     /// List of notes with a date attached.
434     Journal journal;
435
436     /// A reference to an external document
437     QString ref;
438
439     /// A label used instead of the reference
440     QString refLabel;
441
442     /**
443      * The dependencies of the task are stored twice. depends and precedes
444      * store the information specified in the project file. For convenience we
445      * also store the backward dependency together with the specified
446      * dependencies in predecessors and successors.
447      */
448     Q3PtrList<TaskDependency> depends;
449
450     /// @see depends
451     Q3PtrList<TaskDependency> precedes;
452
453     /**
454      * A list of tasks that must precede this task.
455      */
456     TaskList predecessors;
457
458     /**
459      * A list of tasks that must follow this task.
460      */
461     TaskList successors;
462
463     /**
464      * A list of all tasks that preceed this task. It's the combination of
465      * depends and predecessors. This is redundant information but stored for
466      * conveniance. Interdependent tasks are linked in a doubly linked list.
467      */
468     TaskList previous;
469
470     /**
471      * A list of all tasks that follow this task. It's the combination of
472      * precedes and successors. This is redundant information but stored for
473      * conveniance. Interdependent tasks are linked in a doubly linked list.
474      */
475     TaskList followers;
476
477     /**
478      * The ID of the project this task belongs to. This is only
479      * meaningful if multiple projects are joined to create a big
480      * project. */
481     QString projectId;
482
483     /// True if the task is a milestone.
484     bool milestone;
485
486     /**
487      * The priority is used during scheduling. The higher the priority
488      * the more likely the task will get the requested resources. */
489     int priority;
490
491     /// The scheduling policy of the task.
492     SchedulingInfo scheduling;
493
494     /// ID of responsible resource.
495     Resource* responsible;
496
497     /// Tasks may only be worked on during the specified shifts.
498     ShiftSelectionList shifts;
499
500     /// List of resource allocations requested by the task
501     Q3PtrList<Allocation> allocations;
502
503     /// Account where the credits of the task are credited to.
504     Account* account;
505
506     TaskScenario* scenarios;
507
508     /* The following group of variables store values generated during a
509      * scheduler run. They might be initialized by other values and/or
510      * they might contain results of the scheduling run. But they should
511      * never be initialized directly or read out directly. They should have
512      * corresponding scenario variables. The get/set interface functions
513      * should only access the scenario variables. */
514
515     /// Day when the task should start
516     time_t start;
517
518     /// Day when the task should end
519     time_t end;
520
521     /// Length in working days
522     double length;
523
524     /// Effort (in man days) needed to complete the task
525     double effort;
526
527     /// Duration in calender days
528     double duration;
529
530     /// The already completed effort in a scheduler run.
531     double doneEffort;
532
533     /// The already completed length in a scheduler run.
534     double doneLength;
535
536     /// The already completed duration in a scheduler run.
537     double doneDuration;
538
539     /**
540      * Set to true when the first time slots have with resource usage
541      * have been allocated. */
542     bool workStarted;
543
544     /**
545      * Since the full time slot might not be available we need to
546      * store the tentative start of a task in a seperate
547      * variable. Storing the information in 'start' would mark the
548      * task as fully scheduled which might not yet be the case. */
549     time_t tentativeStart;
550
551     /**
552      * Since the full time slot might not be available we need to
553      * store the tentative end of a task in a seperate
554      * variable. Storing the information in 'end' would mark the task
555      * as fully scheduled which might not yet be the case. */
556     time_t tentativeEnd;
557
558     /**
559      * Depending on the scheduling policy the tasks need to be scheduled
560      * from one end the other in a continuous way. No timeslot may be
561      * scheduled twice. This variable stores information about the last
562      * allocation, so we can make sure the next slot is exactly adjacent
563      * the the previous one. */
564     time_t lastSlot;
565
566     /// This variable is set to true when the task has been scheduled.
567     bool schedulingDone;
568
569     /** This flag is set when the task does not fit into the project time
570      * frame. */
571     bool runAway;
572
573     /// A list of all the resources booked for this task.
574     ResourceList bookedResources;
575 } ;
576
577 #endif