ProjectData#

One snapshot of a project: the scheduling config plus the lists of calendars, tasks, links, resources and assignments. Build one with new ProjectData() and an object initializer, then pass it to Project.Solve, Project.Analyze or Engine.Schedule. Each list keeps input order.

Declaration#

public sealed class ProjectData : IDeepCloneable<ProjectData>
{
    public SchedulingConfig Config { get; set; } = new();
    public List<CalendarData> Calendars { get; set; } = [];
    public List<TaskData> Tasks { get; set; } = [];
    public List<LinkData> Links { get; set; } = [];
    public List<ResourceData> Resources { get; set; } = [];
    public List<AssignmentData> Assignments { get; set; } = [];

    public ProjectData DeepClone();
    public override string ToString();
}

ProjectData doesn't implement IEquatable<ProjectData>, so Equals compares references.

Constructors#

ProjectData()#

public ProjectData()

Creates an empty snapshot: default SchedulingConfig and empty lists.

Properties#

Property Type Default Description
Config SchedulingConfig new() Project-wide scheduling settings.
Calendars List<CalendarData> empty Working calendars that tasks and resources reference by CalendarId. An empty list means only the built-in "global" calendar (Mon-Fri, 08:00-12:00 and 13:00-17:00).
Tasks List<TaskData> empty Tasks, summaries and milestones.
Links List<LinkData> empty Dependency links between tasks.
Resources List<ResourceData> empty Resources that assignments book.
Assignments List<AssignmentData> empty Task-to-resource bookings.

Config#

public SchedulingConfig Config { get; set; } = new();

Scheduling settings for the whole project: constraints, direction, calendars, duration unit, project bounds and root id. See SchedulingConfig.

Calendars#

public List<CalendarData> Calendars { get; set; } = [];

Calendars by id. A calendar with id "global" replaces the built-in default calendar. Each CalendarId on a task or resource must name a calendar in this list or "global".

Tasks#

public List<TaskData> Tasks { get; set; } = [];

Every task of the project, flat. The hierarchy comes from each task's Parent, which must name another task in this list. A Parent equal to Config.RootId means no parent.

public List<LinkData> Links { get; set; } = [];

Dependency links. A link whose Source or Target isn't in Tasks is dropped and reported as a Note.DroppedLink in the result.

Resources#

public List<ResourceData> Resources { get; set; } = [];

Resources with their capacity and calendar.

Assignments#

public List<AssignmentData> Assignments { get; set; } = [];

Bookings of a resource on a task. Each Task and Resource must name an entry in Tasks and Resources.

Methods#

DeepClone#

public ProjectData DeepClone()

Returns a copy that shares no list or nested record with this instance.

Returns - a new ProjectData with deep copies of Config and of every list item.

ToString#

public override string ToString()

Returns a debug dump of all six properties.

Validation#

The calls that take a ProjectData validate it as a whole. In strict mode (the default, set by ProjectOptions.Validation) they throw an InputException whose Path uses the JSON field names, for example tasks[3].constraint_date. Checks that span the lists:

Rule Path
Ids are unique within Calendars, Tasks, Links, Resources and Assignments calendars[i], tasks[i].id, links[i].id, resources[i].id, assignments[i].id
A task's Parent names a task in Tasks, and parents form no cycle tasks[i].parent
A summary has its own dates or at least one dated child tasks[i]
A CalendarId on a task or resource names a calendar tasks[i].calendar_id, resources[i].calendar_id
An assignment's Task and Resource name existing records assignments[i].task, assignments[i].resource

Field-level rules (dates, durations, lags, capacities, pauses, worktime) are listed on each record's page. In repair mode a duplicate id replaces the earlier record and keeps its position; see Validation.

Example#

using Plen;

var data = new ProjectData
{
    Config = new SchedulingConfig { DurationUnit = TimeUnit.Day },
    Tasks =
    {
        new TaskData("design") { StartDate = Moment.FromYmdHm(2026, 3, 2, 8, 0), Duration = 3 },
        new TaskData("build") { StartDate = Moment.FromYmdHm(2026, 3, 2, 8, 0), Duration = 5 },
    },
    Links =
    {
        new LinkData { Id = "l1", Source = "design", Target = "build" },
    },
};

ScheduleResult result = Engine.Schedule(data, new SolveOptions());