MacProject Pro 1.5 scheduling rules

This page is docs/scheduling.md from the repository, published as written.

How MacProject Pro 1.5 calculates a schedule, worked out from the dates it stored in its 31 sample files and checked against its code. MPXKit's Scheduler implements these rules; SchedulerTests recomputes every sample and compares with the stored dates.

Result: 618 of 619 sample tasks match on all six stored fields (ES, EF, LS, LF, slack, critical). Summaries match on ES and LS (28 of 28) and on EF, LF and duration (27 of 28). The exceptions are under "Remaining mismatches".

Labels:

Fields

Task (task, and extk by the same layout):

Field Offset
Earliest Start +0x54
Earliest Finish +0x58
Actual Start +0x5c
Actual Finish +0x60
Start Constraint +0x6c
Finish Constraint +0x70
Task Duration (work seconds) +0x74
Start/Finish Constraint Type +0xa0 / +0xa1
Actual Start/Finish Type (non-zero = entered) +0xa4 / +0xa5
Latest Start +0xb2
Latest Finish +0xb6
actual duration +0xba
Slack (work seconds) +0xc2
% Done +0xc6
allocations +0xcc
calendar +0xd4
successor deps +0xd8
predecessor deps +0xdc
the allocation driving Duration (-1 = none) +0xfc
Critical +0x106.11

Dependency (idep):

Field Offset
successor +0x28
predecessor +0x2c
lag calendar +0x38
Lag (work seconds) +0x44
Lag Type +0x4a

Allocation (iall):

Field Offset
resource +0x6
Duration (work seconds on the resource's calendar) +0x46
Driving Resource flag +0x4c.d

The resource's calendar is rsrc +0x12.

Document (dcst):

Field Offset
project start +0x246
supertask start/finish in the master, for subprojects +0x20c/+0x210, +0x214/+0x218
critical-path threshold mode +0x230
custom threshold (work seconds) +0x21c
schedule from actuals (bit 0x20 of byte +0x112) +0x112.c

Calendars [data]

A cal record holds one week entry per weekday, Sunday first. Each entry is a 48-bit mask, first slot, last slot, slot count, working seconds, and a working-day flag:

+0xe6 days lists exceptions as (work seconds from 1904-01-01 to that date, date, working seconds that day).

Fields that don't affect dates:

Time arithmetic [data]

All scheduling runs on a work-time axis. W(t) is the number of working seconds from an epoch to instant t on a given calendar. Two conversions go back from a position w to an instant:

How a task with duration d lands:

Slack is W(LF) − W(finish) in work seconds, on the task's calendar. The finish is EF, or the Actual Finish when actuals drive (see below).

A task uses its own calendar (+0xd4); the default is the first cal . A lag is work time on the dependency's calendar (idep +0x38; every sample uses calendar 0, so the separate lag calendar is a guess).

Forward pass (topological order)

The bound t0 is an instant: the latest of the predecessors' terms.

A task with no predecessors starts at the project start, dcst +0x246 (6/1/92 in the templates, 1/25/93 in the tutorials). [data]

Start constraints apply next [code, FUN_00048b14].

Dates:

Duration is the task's +0x74, unless a driving resource is set (+0xfc ≥ 0). Then it is that allocation's Duration (+0x46) [data]. Magazine Publishing's "Draft Copy" stores 8 days, but its driving allocation is 10 days, and the file shows 10.

Actuals [code FUN_00047f18/FUN_0004805c, data Lessons 6-11]:

Backward pass (reverse order)

The bound t1 is an instant: the earliest of the successors' terms.

A task with no successors gets t1 = its own finish, so every chain's end has zero slack [code FUN_00048ca0: the pass starts unbounded; data: Software Development's "Translation Kit Released" ends 12/5 with LF 12/5, while the project runs to 1/2/95].

Finish constraints then apply, mirroring the start constraints on t1 (1 Finish On, 2 No Earlier Than, 3 No Later Than, 4 Late Finish). This is a guess; no sample has one.

Dates:

Critical [code FUN_00044fac/FUN_00044fe8, data]

A task is critical when slack ≤ limit. The limit depends on dcst +0x230:

Every sample uses mode 0.

Summaries [data]

Subprojects

Writing a file back

These are the working copies the scheduler leaves [data]:

Remaining mismatches

Not exercised by any sample: finish constraints, start constraints of types 2 and 3, critical-path modes 1 and 2, non-zero calendar exceptions, lag calendars other than calendar 0, resource leveling (Level During Calculate is off everywhere), and external tasks (extk, none in the samples).