--- /dev/null
+project prj "Project" "1.0" 2009-1-1 - 2009-6-30 {
+ timeformat "%Y-%m-%d"
+ now 2009-1-1
+ scenario plan "Plan" {
+ projection { strict }
+ scenario forcheck "Just for checking multi-scenario mode"
+ }
+}
+
+resource people "People" {
+ resource john "John"
+ resource team "Team of workers" {
+ resource joe "Joe"
+ resource jim "Jim"
+ }
+}
+
+task prj "My Project" {
+ task planning "Planning Phase" {
+ # no start date since it can be guessed to be the aligned on project start
+ effort 6d
+ allocate john
+ }
+ task mnm "Management & Meetings" {
+ # no start date since it can be guessed as aligned on project start
+ # no end date since it can be guessed as aligned on project end
+ priority 1000 # no other task should steal time on this one
+ allocate john {
+ limits { weeklymax 0.5d dailymax 1h } # 4h/w but for short weeks
+ alternative joe select maxloaded # Joe when John is on vacation
+ }
+ }
+ task support "Support" {
+ # no end date since it can be guessed as aligned on project end
+ depends !deployment
+ priority 1000 # no other task should steal time on this one
+ allocate team { limits { weeklymax 0.5d dailymax 1h } }
+ }
+ task design "Design Phase" {
+ depends !planning
+ allocate john
+ effort 15d
+ }
+ task development "Development Phase" {
+ depends !design
+ allocate team
+ effort 30d
+ }
+ task integration "Integration Phase" {
+ depends !development
+ # not yet decided, let it be a milestone until further details
+ }
+ task deployment "Deployment Phase" {
+ depends !integration
+ # not yet decided, let it be a milestone until further details
+ }
+ task userdoc "User Documentation" {
+ depends !design
+ allocate people
+ effort 10d
+ }
+ task admindoc "Administrator Documentation" {
+ depends !development
+ allocate people
+ effort 6d
+ }
+}
+
+taskreport "Gantt Chart" {
+ headline "Project Gantt Chart"
+ columns hierarchindex, name, start, end, effort, duration, chart
+ timeformat "%a %Y-%m-%d"
+ loadunit days
+ sorttasks tree,sequenceup
+}
for (TaskListIterator tli(taskList); *tli != 0; ++tli)
(*tli)->xRef(idHash);
+ /* Now we can copy the missing values from the plan scenario to the other
+ * scenarios. */
+ if (scenarioList.count() > 1)
+ {
+ for (ScenarioListIterator sli(scenarioList[0]->getSubListIterator());
+ *sli; ++sli)
+ overlayScenario(0, (*sli)->getSequenceNo() - 1);
+ }
+
for (TaskListIterator tli(taskList); *tli != 0; ++tli)
{
// Set dates according to implicit dependencies
for (ResourceListIterator rli(resourceList); *rli != 0; ++rli)
(*rli)->saveSpecifiedBookings();
- /* Now we can copy the missing values from the plan scenario to the other
- * scenarios. */
- if (scenarioList.count() > 1)
- {
- for (ScenarioListIterator sli(scenarioList[0]->getSubListIterator());
- *sli; ++sli)
- overlayScenario(0, (*sli)->getSequenceNo() - 1);
- }
-
// Now check that all tasks have sufficient data to be scheduled.
setProgressInfo(i18n("Checking scheduling data..."));
bool error = false;
if (!isMilestone() && isLeaf())
{
- /* Automatic milestone marker. As a convenience we convert tasks that
- * only have a start or end criteria as a milestone. This is handy
- * when in the early stage of a project draft, when you just want to
- * specify the project outline and fill in subtasks and details
- * later. */
- bool hasStartSpec = false;
- bool hasEndSpec = false;
- bool hasDurationSpec = false;
+ /* Automatic boundary guesser for tasks that are underspecified in
+ * term of start/end/duration. As a convenience we add start and or
+ * end boundaries to task that are likely to be aligned on project
+ * start or end dates, and convert tasks to milestones in worst
+ * cases (i.e. when dependecies disables the tasks to be aligned
+ * on the project boundaries).
+ * This is handy when in the early stage of a project draft, when
+ * you just want to specify the project outline and fill in
+ * subtasks and details later.
+ * This is also handy even after the early stage for tasks that are
+ * actually aligned on one or both project boundary. */
+ int milestoneBallots = 0;
for (int sc = 0; sc < project->getMaxScenarios(); ++sc)
{
- if (scenarios[sc].specifiedStart != 0 || !depends.isEmpty())
+ bool hasStartSpec = false;
+ bool hasEndSpec = false;
+ bool hasDurationSpec = false;
+ bool hasPreviousEvenInherited = false;
+ bool hasDependsEvenIhnerited = false;
+ bool hasFollowersEvenInherited = false;
+ bool hasPrecedesEvenInherited = false;
+ for (Task* task = this; task; task = task->getParent())
+ {
+ hasPreviousEvenInherited |= task->hasPrevious();
+ hasDependsEvenIhnerited |= !task->depends.isEmpty();
+ hasFollowersEvenInherited |= task->hasFollowers();
+ hasPrecedesEvenInherited |= !task ->precedes.isEmpty();
+ }
+ if (scenarios[sc].specifiedStart != 0 || hasDependsEvenIhnerited)
hasStartSpec = true;
- if (scenarios[sc].specifiedEnd != 0 || !precedes.isEmpty())
+ if (scenarios[sc].specifiedEnd != 0 || hasPrecedesEvenInherited)
hasEndSpec = true;
if (scenarios[sc].duration != 0 || scenarios[sc].length != 0 ||
scenarios[sc].effort != 0)
hasDurationSpec = true;
+ /*printf("O: %s/%d: (%g-%g %g) %d [%d %d] <-%d %d->\n", getId().ascii(),
+ sc, scenarios[sc].duration, scenarios[sc].length,
+ scenarios[sc].effort, (int)hasDurationSpec, (int)hasStartSpec,
+ (int)hasEndSpec, (int)hasPreviousEvenInherited,
+ (int)hasFollowersEvenInherited);*/
+ // ASAP tasks lacking start specification
+ // - --> * (no previous)
+ // - x-> * (no previous)
+ if (!hasPreviousEvenInherited && !hasStartSpec
+ && scheduling == ASAP)
+ {
+ hasStartSpec = true;
+ setSpecifiedStart(sc, project->getStart());
+ //printf("A: auto aligning %s on start date\n", getId().ascii());
+ }
+ // ALAP tasks lacking end specification
+ // * <-- - (no followers)
+ // * <-x - (no followers)
+ if (!hasFollowersEvenInherited && !hasEndSpec
+ && scheduling == ALAP)
+ {
+ hasEndSpec = true;
+ setSpecifiedEnd(sc, project->getEnd());
+ //printf("B: auto aligning %s on end date\n", getId().ascii());
+ }
+ // tasks with no duration spec and at most one boundary spec
+ if (!hasDurationSpec && !(hasStartSpec && hasEndSpec))
+ {
+ // ASAP tasks with neither end nor duration spec
+ // * --> - (no followers)
+ if (!hasFollowersEvenInherited && !hasEndSpec
+ && scheduling == ASAP)
+ {
+ setSpecifiedEnd(sc, project->getEnd());
+ //printf("C: auto aligning %s on end date\n", getId().ascii());
+ }
+ // ALAP tasks with neither start nor duration spec
+ // - <-- * (no previous)
+ else if (!hasPreviousEvenInherited && !hasStartSpec
+ && scheduling == ALAP)
+ {
+ setSpecifiedStart(sc, project->getStart());
+ //printf("D: auto aligning %s on start date\n", getId().ascii());
+ }
+ // other cases, e.g.:
+ // D --> D
+ // D <-- D
+ // | --> D (with previous)
+ // D <-- | (with followers)
+ else
+ {
+ ++milestoneBallots;
+ //printf("E: voting for %s conversion to milestone\n", getId().ascii());
+ }
+ }
}
- if (!hasDurationSpec && (hasStartSpec ^ hasEndSpec))
+ if (milestoneBallots == project->getMaxScenarios())
+ {
milestone = true;
+ //printf("F: auto converting %s to milestone\n", getId().ascii());
+ }
}
}