OSDN Git Service

- Rewrote scheduler to be more accurate
authorcs <cs@e1914e07-63f8-0310-9059-d6d858d7cdca>
Thu, 6 Dec 2001 09:07:54 +0000 (09:07 +0000)
committercs <cs@e1914e07-63f8-0310-9059-d6d858d7cdca>
Thu, 6 Dec 2001 09:07:54 +0000 (09:07 +0000)
- Added some more properties to Reference documentation

git-svn-id: https://www.taskjuggler.org/svn/taskjuggler/trunk@10 e1914e07-63f8-0310-9059-d6d858d7cdca

15 files changed:
taskjuggler/Account.h
taskjuggler/Project.cpp
taskjuggler/Project.h
taskjuggler/ProjectFile.cpp
taskjuggler/ResourceList.cpp
taskjuggler/ResourceList.h
taskjuggler/Task.cpp
taskjuggler/Task.h
taskjuggler/Utility.cpp
taskjuggler/Utility.h
taskjuggler/VacationList.cpp
taskjuggler/VacationList.h
taskjuggler/docs/en/Reference.txt
taskjuggler/main.cpp
taskjuggler/test.task

index c08efbc..c559a1c 100644 (file)
@@ -55,7 +55,10 @@ class Account
 {
 public:
        Account(const QString& i, const QString& n)
-               : id(i), name(n), openingBalance(0.0) { }
+               : id(i), name(n), openingBalance(0.0)
+       {
+               kotrusId = "";
+       }
        ~Account() { };
 
        const QString& getId() const { return id; }
index 4395580..aa3c313 100644 (file)
@@ -21,7 +21,8 @@
 #define COL_DEFAULT "#fffadd"
 #define COL_WEEKEND "#ffec80"
 #define COL_BOOKED "#ffc0a3"
-#define COL_HEADER "a5c2ff"
+#define COL_HEADER "#a5c2ff"
+#define COL_MILESTONE "#ff2a2a"
 
 Project::Project()
 {
@@ -75,14 +76,15 @@ Project::pass2()
        sortedTasks.setSorting(TaskList::PrioDown);
        sortedTasks.sort();
 
-       for (int day = start; day < end; day += 60 * 60 * 24)
+       const time_t scheduleGranularity = ONEHOUR;
+       for (int day = start; day < end; day += scheduleGranularity)
        {
                bool done;
                do
                {
                        done = TRUE;
                        for (Task* t = sortedTasks.first(); t != 0; t = sortedTasks.next())
-                               if (!t->schedule(day))
+                               if (!t->schedule(day, scheduleGranularity))
                                        done = FALSE;
                } while (!done);
        }
@@ -314,9 +316,11 @@ Project::reportHTMLTaskList()
                                {
                                        double load = t->getLoadOnDay(day);
                                        QString bgCol = COL_DEFAULT;
-                                       if (isWeekend(day))
+                                       if (t->isMilestone() && t->isActiveToday(day))
+                                               bgCol = COL_MILESTONE;
+                                       else if (isWeekend(day))
                                                bgCol = COL_WEEKEND;
-                                       else if (load > 0.0)
+                                       else if (t->isActiveToday(day))
                                                bgCol = COL_BOOKED;
                                        if (load > 0.0)
                                                fprintf(f,
@@ -399,7 +403,7 @@ Project::reportHTMLResourceList()
                fprintf(f, "</tr>\n");
 
                for (Task* t = taskList.first(); t != 0; t = taskList.next())
-                       if (r->isBusyWith(t))
+                       if (r->isAssignedTo(t))
                        {
                                fprintf(f, "<tr>");
                                fprintf(f, "<td nowrap>&nbsp;&nbsp;&nbsp;&nbsp;<font size=\"-1\">%s</font></td>",
index a846e2a..2775f51 100644 (file)
@@ -61,8 +61,8 @@ public:
        void addVacation(const QString& n, time_t s, time_t e)
        {
                vacationList.add(n, s, e);
-       };
-       bool isVacationDay(time_t d) { return vacationList.isVacationDay(d); }
+       }
+       bool isVacation(time_t d) { return vacationList.isVacation(d); }
 
        void addResource(Resource* r)
        {
@@ -112,6 +112,11 @@ public:
        {
                return allowedFlags.contains(flag) > 0;
        }
+
+       double convertToDailyLoad(long secs)
+       {
+               return ((double) secs / (8 * ONEHOUR));
+       }
        
 private:
        bool checkSchedule();
index c6f5bde..2eda3da 100644 (file)
@@ -905,7 +905,7 @@ ProjectFile::readResource()
                return FALSE;
        }
 
-       Resource* r = new Resource(id, name, proj->getMinEffort(),
+       Resource* r = new Resource(proj, id, name, proj->getMinEffort(),
                                                           proj->getMaxEffort(), proj->getRate());
        TokenType tt;
        QString token;
@@ -1207,6 +1207,6 @@ ProjectFile::date2time(const QString& date)
                d = 1;
        }
 
-       struct tm t = { 0, 0, 0, d, m - 1, y - 1900, 0, 0, 0 };
+       struct tm t = { 0, 0, 0, d, m - 1, y - 1900, 0, 0, -1, 0, 0 };
        return mktime(&t);
 }
index 39030fd..c04a38d 100644 (file)
 #include "Task.h"
 #include "Project.h"
 
-double
-Resource::isAvailable(time_t date)
+Resource::Resource(Project* p, const QString& i, const QString& n,
+                                  double mie, double mae, double r) :
+       project(p), id(i), name(n), minEffort(mie), maxEffort(mae), rate(r)
 {
-       double bookedEffort = 0.0;
-       for (Booking* b = jobs.first(); b != 0; b = jobs.next())
-               if (date == b->getDate())
-                       bookedEffort += b->getEffort();
-       return (maxEffort - bookedEffort);
+       // Monday
+       workingHours[1].append(new Interval(8 * ONEHOUR, 12 * ONEHOUR));
+       workingHours[1].append(new Interval(13 * ONEHOUR, 17 * ONEHOUR));
+       // Tuesday
+       workingHours[2].append(new Interval(8 * ONEHOUR, 12 * ONEHOUR));
+       workingHours[2].append(new Interval(13 * ONEHOUR, 17 * ONEHOUR));
+       // Wednesday
+       workingHours[3].append(new Interval(8 * ONEHOUR, 12 * ONEHOUR));
+       workingHours[3].append(new Interval(13 * ONEHOUR, 17 * ONEHOUR));
+       // Thursday
+       workingHours[4].append(new Interval(8 * ONEHOUR, 12 * ONEHOUR));
+       workingHours[4].append(new Interval(13 * ONEHOUR, 17 * ONEHOUR));
+       // Friday
+       workingHours[5].append(new Interval(8 * ONEHOUR, 12 * ONEHOUR));
+       workingHours[5].append(new Interval(13 * ONEHOUR, 17 * ONEHOUR));
 }
 
 bool
-Resource::book(Booking* b)
+Resource::isAvailable(time_t date, time_t duration, Interval& interval)
 {
-       jobs.append(b);
-       return TRUE;
+       // Make sure that we don't overload the resource.
+       time_t bookedTime = duration;
+       Interval day = Interval(midnight(date), midnight(date) + ONEDAY - 1);
+       for (Booking* b = jobs.first(); b != 0; b = jobs.next())
+               if (day.contains(b->getInterval()))
+                       bookedTime += b->getDuration();
+       if (project->convertToDailyLoad(bookedTime) > maxEffort)
+               return FALSE;
+
+       // Iterate through all the work time intervals for the week day.
+       const int dow = dayOfWeek(date);
+       for (Interval* i = workingHours[dow].first(); i != 0;
+                i = workingHours[dow].next())
+       {
+               interval = Interval(midnight(date), midnight(date));
+               interval.add(*i);
+               /* If there is an overlap between working time and the requested
+                * interval we exclude the time starting with the first busy
+                * interval in that working time. */
+               if (interval.overlap(Interval(date, date + duration - 1)))
+               {
+                       for (Booking* b = jobs.first(); b != 0; b = jobs.next())
+                               if (!interval.exclude(b->getInterval()))
+                                       return FALSE;
+                       return TRUE;
+               }
+       }
+       return FALSE;
 }
 
-double
-Resource::getLoadOnDay(time_t date)
+bool
+Resource::book(Booking* nb)
 {
-       double load = 0.0;
-
+       // Try first to append the booking 
        for (Booking* b = jobs.first(); b != 0; b = jobs.next())
-               if (date == b->getDate())
-                       load += b->getEffort();
-       return load;
+               if (b->getTask() == nb->getTask() &&
+                       b->getProjectId() == nb->getProjectId() &&
+                       b->getInterval().append(nb->getInterval()))
+               {
+                       // booking appended
+                       delete nb;
+                       return TRUE;
+               }
+       jobs.append(nb);
+       return TRUE;
 }
 
 double
 Resource::getLoadOnDay(time_t date, Task* task)
 {
-       double load = 0.0;
+       time_t bookedTime = 0;
 
+       const Interval day(midnight(date), midnight(date) + ONEDAY - 1);
        for (Booking* b = jobs.first(); b != 0; b = jobs.next())
-               if (date == b->getDate() && task == b->getTask())
-                       load += b->getEffort();
-       return load;
+       {
+               if (day.contains(b->getInterval()) &&
+                       (task == 0 || task == b->getTask()))
+                       bookedTime += b->getDuration();
+       }
+       return project->convertToDailyLoad(bookedTime);
 }
 
 bool
-Resource::isBusyWith(Task* task)
+Resource::isAssignedTo(Task* task)
 {
        for (Booking* b = jobs.first(); b != 0; b = jobs.next())
                if (task == b->getTask())
@@ -76,21 +123,13 @@ ResourceList::compareItems(QCollection::Item i1, QCollection::Item i2)
 Resource*
 ResourceList::getResource(const QString& id)
 {
-       Resource key(id, "");
+       Resource key(0, id, "");
        return at(find(&key));
 }
 
 void
 Resource::printText()
 {
-       printf("ID: %s\n", id.latin1());
-       printf("Name: %s\n", name.latin1());
-       printf("MinEffort: %3.2f  MaxEffort: %3.2f  Rate: %7.2f\n",
-                  minEffort, maxEffort, rate);
-       for (Booking* j = jobs.first(); j != 0; j = jobs.next())
-               printf("%s %5.2f %s\n", time2ISO(j->getDate()).latin1(),
-                          j->getEffort(),
-                          j->getTask()->getId().latin1());
 }
 
 void
index 5def99a..f429896 100644 (file)
@@ -17,6 +17,7 @@
 #include <qlist.h>
 #include <qstring.h>
 
+#include "Interval.h"
 #include "VacationList.h"
 
 class Project;
@@ -25,12 +26,17 @@ class Task;
 class Booking
 {
 public:
-       Booking(time_t d, Task* t, double e) : date(d), task(t), effort(e) { }
+       Booking(const Interval& iv, Task* t, QString a = "",
+                       QString i = "")
+               : interval(iv), task(t), account(a), projectId(i) { }
        ~Booking() { }
 
-       time_t getDate() const { return date; }
+       time_t getStart() const { return interval.getStart(); }
+       time_t getEnd() const { return interval.getEnd(); }
+       time_t getDuration() const { return interval.getDuration(); }
+       Interval& getInterval() { return interval; }
+
        Task* getTask() const { return task; }
-       double getEffort() const { return effort; }
 
        void setAccount(const QString a) { account = a; }
        const QString& getAccount() const { return account; }
@@ -39,12 +45,10 @@ public:
        const QString& getProjectId() const { return projectId; }
 
 private:
-       // The day of the booking
-       time_t date;
+       // The booked time period.
+       Interval interval;
        // A pointer to the task that caused the booking
        Task* task;
-       // The effort (in man days) the resource is used that day.
-       double effort;
        // String identifying the KoTrus account the effort is credited to.
        QString account;
        // The Project ID
@@ -54,9 +58,8 @@ private:
 class Resource
 {
 public:
-       Resource(const QString& i, const QString& n, double mie = 0.0,
-                        double mae = 1.0, double r = 0.0) :
-               id(i), name(n), minEffort(mie), maxEffort(mae), rate(r) { }
+       Resource(Project* p, const QString& i, const QString& n, double mie = 0.0,
+                        double mae = 1.0, double r = 0.0);
        virtual ~Resource() { }
 
        const QString& getId() const { return id; }
@@ -71,19 +74,20 @@ public:
        void setRate(double r) { rate = r; }
        double getRate() const { return rate; }
 
-       double isAvailable(time_t date);
+       bool isAvailable(time_t day, time_t duration, Interval& i);
        bool book(Booking* b);
 
-       double getLoadOnDay(time_t date);
-       double getLoadOnDay(time_t date, Task* task);
+       double getLoadOnDay(time_t date, Task* task = 0);
 
-       bool isBusyWith(Task* t);
+       bool isAssignedTo(Task* t);
        void setKotrusId(const QString k) { kotrusId = k; }
        const QString& getKotrusId() const { return kotrusId; }
 
        void printText();
 
 private:
+       Project* project;
+
        // The ID of the resource. Must be unique in the project.
        QString id;
        // The resource name. E. g. real name or room number.
@@ -99,6 +103,7 @@ private:
        // KoTrus ID, ID by which the resource is known to KoTrus.
        QString kotrusId;
 
+       QList<Interval> workingHours[7];
        // List of all intervals the resource is not available.
        VacationList vacationList;
        // A list of all uses of the resource.
index 888d07f..2256a0c 100644 (file)
@@ -56,7 +56,7 @@ Task::fatalError(const QString& msg) const
 }
 
 bool
-Task::schedule(time_t day)
+Task::schedule(time_t date, time_t duration)
 {
        // Task is already scheduled.
        if (start != 0 && end != 0)
@@ -79,14 +79,15 @@ Task::schedule(time_t day)
                {
                        start = project->getStart();
                }
-               else
+               else if (earliestStart() > 0)
                {
                        start = earliestStart();
+                       done = 0.0;
+                       costs = 0.0;
+                       workStarted = FALSE;
+                       tentativeEnd = date;
                }
-               done = 0.0;
-               costs = 0.0;
-               workStarted = FALSE;
-               if (start == 0)
+               else
                        return TRUE;    // Task cannot be scheduled yet.
        }
 
@@ -105,6 +106,10 @@ Task::schedule(time_t day)
        }
        else if (effort > 0)
        {
+               /* Do not schedule anything before the start date lies within
+                * the interval. */
+               if (date + duration <= start || project->isVacation(date))
+                       return TRUE;
                /* The effort of the task has been specified. We have to look
                 * how much the resources can contribute over the following
                 * workings days until we have reached the specified
@@ -114,28 +119,21 @@ Task::schedule(time_t day)
                        fatalError("No allocations specified for effort based task");
                        return TRUE;
                }
-               double dailyCosts = 0.0;
-               if (isWorkingDay(day))
-               {
-                       if (!bookResources(day, dailyCosts))
+               if (!bookResources(date, duration))
 //                                             fprintf(stderr,
 //                                                     "No resource available for task '%s' on %s\n",
 //                                                     id.latin1(),
-//                                                     time2ISO(day).latin1())
+//                                                     time2ISO(date).latin1())
                                ;
-               }
-               /* If an account has been specified load account with the
-                * accumulated costs of this day. */
-               if (account)
-                       account->book(new Transaction(day, -costs, this));
                if (done >= effort)
                {
-                       end = day;
+                       end = tentativeEnd;
                        return FALSE;
                }
        }
        else
        {
+               printf("%s %s\n", id.latin1(), time2ISO(start).latin1());
                // Task is a milestone.
                end = start;
                return FALSE;
@@ -153,94 +151,94 @@ Task::scheduleContainer()
        // Check that this is really a container task
        if ((t = subTasks.first()) && (t != 0))
        {
-               if (t->getStart() > 0)
-                       nstart = t->getStart();
-               if (t->getEnd() > 0)
-                       nend = t->getEnd();
+               /* Make sure that all sub tasks have been scheduled. If not we
+                * can't yet schedule this task. */
+               if (t->getStart() == 0 || t->getEnd() == 0)
+                       return TRUE;
+               nstart = t->getStart();
+               nend = t->getEnd();
        }
        else
                return TRUE;
 
        for (t = subTasks.next() ; t != 0; t = subTasks.next())
        {
-               if (t->getStart() < start)
+               /* Make sure that all sub tasks have been scheduled. If not we
+                * can't yet schedule this task. */
+               if (t->getStart() == 0 || t->getEnd() == 0)
+                       return TRUE;
+
+               if (t->getStart() < nstart)
                        nstart = t->getStart();
-               if (t->getEnd() > end)
+               if (t->getEnd() > nend)
                        nend = t->getEnd();
        }
 
-       /* Make sure that all sub tasks have been scheduled. If not we can't
-        * yet schedule this task. */
-       if (nstart > 0 && nend > 0)
-       {
-               start = nstart;
-               end = nend;
-               return FALSE;
-       }
-
-       return TRUE;
+       start = nstart;
+       end = nend;
+       return FALSE;
 }
 
 bool
-Task::bookResources(time_t day, double& dailyCosts)
+Task::bookResources(time_t date, time_t duration)
 {
        bool allocFound = FALSE;
 
        for (Allocation* a = allocations.first(); a != 0;
                 a = allocations.next())
        {
-               /* Move the start date to make sure that there is
-                * some work going on on the start date. */
-               if (!workStarted)
-                       start = day;
-               double remaining;
-               if ((remaining = a->getResource()->isAvailable(day)) > 0.0)
-               {
-                       if (remaining > (a->getLoad() / 100.0))
-                               remaining = a->getLoad() / 100.0;
-                       if (remaining > (effort - done))
-                               remaining = effort - done;
-                       if (a->getResource()->book(new Booking(
-                               day, this, remaining)))
-                       {
-                               addBookedResource(a->getResource());
-                               done += remaining;
-                               dailyCosts += a->getResource()->getRate() * remaining;
-                       }
+               if (bookResource(a->getResource(), date, duration))
                        allocFound = TRUE;
-               }
                else
                {
 //                     fprintf(stderr,
 //                                     "Resource %s cannot be used for task '%s' on %s.\n",
 //                                     a->getResource()->getId().latin1(),
-//                                     id.latin1(), time2ISO(day).latin1());
+//                                     id.latin1(), time2ISO(date).latin1());
                        for (Resource* r = a->first(); r != 0; r = a->next())
-                               if ((remaining = r->isAvailable(day)) > 0.0)
+                               if (bookResource(r, date, duration))
                                {
-                                       if (remaining > (a->getLoad() / 100.0))
-                                               remaining = a->getLoad() / 100.0;
-                                       if (remaining > (effort - done))
-                                               remaining = effort - done;
-                                       if (r->book(new Booking(
-                                               day, this, remaining)))
-                                       {
-                                               addBookedResource(a->getResource());
-                                               done += remaining;
-                                               dailyCosts += r->getRate() * remaining;
-                                       }
                                        allocFound = TRUE;
                                        break;
                                }
                }
        }
-       if (allocFound)
-               workStarted = TRUE;
 
        return allocFound;
 }
 
 bool
+Task::bookResource(Resource* r, time_t date, time_t duration)
+{
+       Interval interval;
+
+       if (r->isAvailable(date, duration, interval))
+       {
+               double intervalLoad = project->convertToDailyLoad(
+                       interval.getDuration());
+               r->book(new Booking(interval, this,
+                                                       account ? account->getKotrusId() : QString(""),
+                                                       project->getId()));
+               addBookedResource(r);
+
+               /* Move the start date to make sure that there is
+                * some work going on on the start date. */
+               if (!workStarted)
+               {
+                       start = date;
+                       workStarted = TRUE;
+               }
+
+               tentativeEnd = interval.getEnd();
+               done += intervalLoad;
+               //costs += r->getRate() * intervalLoad;
+
+               return TRUE;
+       }
+       return FALSE;
+}
+
+bool
 Task::isScheduled()
 {
        return ((start != 0 && end != 0) || !subTasks.isEmpty());
@@ -249,29 +247,29 @@ Task::isScheduled()
 time_t
 Task::earliestStart()
 {
-       time_t day = 0;
+       time_t date = 0;
        for (Task* t = previous.first(); t != 0; t = previous.next())
-               if (t->getEnd() > day)
-                       day = t->getEnd();
+               if (t->getEnd() > date)
+                       date = t->getEnd() + 1;
 
        /* If the task duration is enforced by length (and not effort) a task
         * starts the next working day after the previous tasks have been
         * finished. With effort based scheduling we can schedule multiple
-        * tasks per day. */
-       if (day > 0 && length > 0)
-               day = nextWorkingDay(day);
+        * tasks per date. */
+       if (date > 0 && length > 0)
+               date = nextWorkingDay(date);
 
-       return day;
+       return date;
 }
 
 double
-Task::getLoadOnDay(time_t day)
+Task::getLoadOnDay(time_t date)
 {
        double load = 0.0;
        for (Resource* r = bookedResources.first(); r != 0;
                 r = bookedResources.next())
        {
-               load += r->getLoadOnDay(day, this);
+               load += r->getLoadOnDay(date, this);
        }
        return load;
 }
@@ -340,7 +338,7 @@ Task::isWorkingDay(time_t d) const
        if (tms->tm_wday < 1 || tms->tm_wday > 5)
                return FALSE;
 
-       return !project->isVacationDay(d);
+       return !project->isVacation(d);
 }
 
 time_t
index f2fe0b1..35f1877 100644 (file)
@@ -142,10 +142,18 @@ public:
 
        bool xRef(QDict<Task>& hash);
        QString resolveId(QString relId);
-       bool schedule(time_t reqStart);
+       bool schedule(time_t reqStart, time_t duration);
        bool isScheduled();
        bool scheduleOK();
 
+       bool isMilestone() const { return start != 0 && start == end; }
+       bool isActiveToday(time_t date) const
+       {
+               Interval day(midnight(date), midnight(date) + ONEDAY - 1);
+               Interval work(start, end);
+               return day.overlap(work);
+       }
+
        void setAccount(Account* a) { account = a; }
 
        void addFlag(QString flag)
@@ -164,7 +172,8 @@ public:
 
 private:
        bool scheduleContainer();
-       bool bookResources(time_t day, double& costs);
+       bool bookResource(Resource* r, time_t day, time_t duration);
+       bool bookResources(time_t day, time_t duration);
        bool isWorkingDay(time_t day) const;
        time_t nextWorkingDay(time_t day) const;
        time_t earliestStart();
@@ -215,10 +224,11 @@ private:
        // Percentage of completion of the task
        int complete;
 
-       // The following 3 variables are used during scheduling.
+       // The following 4 variables are used during scheduling.
        double costs;
        double done;
        bool workStarted;
+       time_t tentativeEnd;
 
        // Account where the costs of the task are credited to.
        Account* account;
index 80af99a..6524951 100644 (file)
@@ -48,12 +48,27 @@ dayOfMonth(time_t t)
        return tms->tm_mday;
 }
 
+int
+dayOfWeek(time_t t)
+{
+       struct tm* tms = localtime(&t);
+       return tms->tm_wday;
+}
+
+time_t
+midnight(time_t t)
+{
+       struct tm* tms = localtime(&t);
+       tms->tm_sec = tms->tm_min = tms->tm_hour = 0;
+       return mktime(tms);
+}
+
 QString time2ISO(time_t t)
 {
        struct tm* tms = localtime(&t);
        static QString s;
-       s.sprintf("%04d-%02d-%02d", 1900 + tms->tm_year, 1 + tms->tm_mon,
-                         tms->tm_mday);
+       s.sprintf("%04d-%02d-%02d %02d:%02d", 1900 + tms->tm_year, 1 + tms->tm_mon,
+                         tms->tm_mday, tms->tm_hour, tms->tm_min);
        return s;
 }
 
index 9bdae60..73843b1 100644 (file)
@@ -17,6 +17,8 @@
 #include <qstring.h>
 
 #define MAXTIME 0x7FFFFFFF
+#define ONEDAY (60 * 60 * 24)
+#define ONEHOUR (60 * 60)
 
 const char* monthAndYear(time_t d);
 
@@ -26,6 +28,10 @@ bool isWeekend(time_t d);
 
 int dayOfMonth(time_t d);
 
+int dayOfWeek(time_t d);
+
+time_t midnight(time_t t);
+
 QString time2ISO(time_t t);
 
 #endif
index 293cc0c..9dc2e35 100644 (file)
@@ -18,23 +18,23 @@ VacationList::compareItems(QCollection::Item it1, QCollection::Item it2)
        Interval* i1 = static_cast<Interval*>(it1);
        Interval* i2 = static_cast<Interval*>(it2);
 
-       if (i1->start == i2->start)
+       if (i1->getStart() == i2->getStart())
        {
-               if (i1->end == i2->end)
+               if (i1->getEnd() == i2->getEnd())
                        return 0;
                else
-                       return i1->end - i2->end;
+                       return i1->getEnd() - i2->getEnd();
        }
        else
-               return i1->start - i2->start;
+               return i1->getStart() - i2->getStart();
 }
 
 bool
-VacationList::isVacationDay(time_t day)
+VacationList::isVacation(time_t date)
 {
-       Interval* i;
-       for (i = first(); i != 0 && day <= i->getEnd(); i = next())
-               if (i->getStart() <= day && day <= i->getEnd())
+       VacationInterval* i;
+       for (i = first(); i != 0 && date <= i->getEnd(); i = next())
+               if (i->contains(date))
                        return TRUE;
 
        return FALSE;
index 3bc92bf..d13ab19 100644 (file)
 #include <qlist.h>
 #include <qstring.h>
 
-class Interval
+#include "Interval.h"
+
+class VacationInterval : public Interval
 {
 public:
-       Interval() { start = 0; end = 0; }
-       Interval(const QString& n, time_t s, time_t e)
-               : name(n), start(s), end(e) { }
-       virtual ~Interval() { }
+       VacationInterval() { }
+
+       VacationInterval(const QString& n, time_t s, time_t e)
+               : Interval(s, e), name(n) { }
+       virtual ~VacationInterval() { }
 
        const QString& getName() const { return name; }
-       time_t getStart() const { return start; }
-       time_t getEnd() const { return end; }
 
+private:
        QString name;
-       time_t start;
-       time_t end;
 } ;
 
-class VacationList : protected QList<Interval>
+class VacationList : protected QList<VacationInterval>
 {
 public:
        VacationList() { setAutoDelete(TRUE); }
@@ -43,9 +43,9 @@ public:
 
        void add(const QString& name, time_t start, time_t end)
        {
-               inSort(new Interval(name, start, end));
+               inSort(new VacationInterval(name, start, end));
        }
-       bool isVacationDay(time_t day);
+       bool isVacation(time_t date);
 
 protected:
        virtual int compareItems(QCollection::Item i1, QCollection::Item i2);
index f3452a0..83af0e8 100644 (file)
@@ -21,6 +21,8 @@ DATE: A DATE is an ISO compliant date YYYY-MM-DD[-hh[:mm[:ss]]]. Hour,
 minute and second are optional. If not specified the values are set to
 0.
 
+TIME: A time in the format HH:MM.
+
 UNIT: May be
 h for hours,
 d for days,
@@ -28,6 +30,15 @@ w for weeks,
 m for months,
 y for years.
 
+WEEKDAY: May be
+Mon for Monday
+Tue for Tuesday
+Wed for Wednesday
+Thu for Thursday
+Fri for Friday
+Sat for Saturday
+Sun for Sunday
+
 INTEGER: An integer number.
 
 REAL: A real number (e.g. 3.14).
@@ -299,6 +310,15 @@ Specifies a vacation for a resource. The to value is NOT included in
 the vacation.
 
 -------------------------------------------------------------------------------
+hours <weekday> <from>-<to>[,<from>-<to>]
+weekday: WEEKDAY
+from: TIME
+to: TIME
+
+Sets the working hours to the specified intervals. If no hours are
+specified for a day, the global definitions are used.
+
+-------------------------------------------------------------------------------
 
 ===============================================================================
 vacation name <start> [- <end>]
@@ -311,9 +331,27 @@ of the vacation. So 2001-12-24 - 2001-12-25 specifies one day of
 vacation, not two days.
 
 ===============================================================================
-priority <value>
+hours <weekday> <from>-<to>[,<from>-<to>]
+weekday: WEEKDAY
+from: TIME
+to: TIME
+
+Sets the working hours to the specified intervals. The values are used
+as default values for all resources defined afterwards. The default
+values are 08:00-12:00 and 13:00-17:00 from Mon - Fri.
+
+===============================================================================
+workingHoursPerDay <value>
 value: INTEGER
 
+Specifies the number of working hours per day. This value is used to
+calculate the daily load from the number of booked hours. If
+workingHoursPerDay is set to 8 and a resource is used for 12 hours on
+a day, the daily load is 1.5.
+
+===============================================================================
+priority <value> value: INTEGER
+
 The default scheduling priority for tasks. The value must be between 1
 and 1000 and is inherited by all tasks if no other priority is
 specified.
@@ -386,6 +424,13 @@ Declares the specified flags. Flags can be assigned to tasks to be
 used as filters during report generation.
 
 ===============================================================================
+timingResolution <value> <unit>
+value: INTERGER
+unit: UNIT
+
+Sets the minimum timing resolution. The smaller the value, the longer the schedulings process needs. The default is 1 hour.
+
+===============================================================================
 htmlTaskReport <filename>
 filename: STRING
 
index 3fd23bb..4ce3e9f 100644 (file)
@@ -17,7 +17,6 @@
 
 int main(int argc, char *argv[])
 {
-       
        QApplication a(argc, argv, false);
 
        Project p;
index b90428d..aa79fea 100644 (file)
@@ -3,7 +3,7 @@
 project sl80 "SuSE Linux 8.0" "$Id$" 2001-09-28 2002-04-01
 
 htmlTaskReport "test.html" {
-  columns  no, name, start, end, daily
+  columns  no, name, start, end, minStart, daily
   start 2001-10-01
   end 2002-04-01
 }
@@ -87,7 +87,7 @@ vacation "Xmas" 2001-12-21 - 2002-01-04
 
 account acc1 "Work" { kotrusId "SuSE Linux" balance 1000.0 }
 
-resource ro "Ruediger Oertel" # Dies ist ein Kommentar
+resource ro "Ruediger Oertel"
 resource kukuk "Thorsten Kukuk"
 resource cs "Chris Schlaeger"
 resource mem "Muhamed Memovic"