Pool#

The workers that may be assigned, each a project resource with its skills. A Pool is the second argument of slots. Build it with a struct literal, or start from Pool::default() (no workers). The pool isn't stored in the project: pass it again on every slots call.

Declaration#

#[derive(Clone, Debug, Default, PartialEq)]
pub struct Pool {
    pub workers: Vec<Worker>,
}

Fields#

workers#

pub workers: Vec<Worker>

The candidate workers, one Worker per resource. The order is the tie-break preference: a slot's allowed list keeps the matching workers in pool order. A resource missing from the pool is never a candidate.

Default: empty.

Errors#

slots checks the pool before the requirements and returns Err(MatchError::Invalid) with the path below.

When it occurs Path
the worker's resource isn't a resource of the project pool.workers[i].resource
two workers name the same resource (ids compare by Id key) pool.workers[i].resource

Errors in a worker's skill list are on Worker.

Example#

use plen_assign::{slots, Pool, Requirement, Skill, SkillMatch, Worker};
use plen_core::{DateTime, Project, ProjectData, ResourceData, SolveOptions, TaskData};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut task = TaskData::new("api");
    task.start_date = DateTime::from_ymd_hm(2026, 8, 10, 8, 0);
    task.duration = Some(2.0);
    let data = ProjectData {
        tasks: vec![task],
        resources: ["ann", "bob"]
            .map(|id| ResourceData { id: id.into(), capacity: None, calendar_id: None })
            .to_vec(),
        ..Default::default()
    };
    let mut project = Project::default();
    project.solve(Some(data), &SolveOptions::default())?;

    // "bob" comes first, so he is preferred on ties.
    let pool = Pool {
        workers: vec![
            Worker { resource: "bob".into(), skills: vec![Skill { id: "backend".into(), value: 1.0 }] },
            Worker { resource: "ann".into(), skills: vec![Skill { id: "backend".into(), value: 1.0 }] },
        ],
    };
    let requirements = [Requirement::new("be", "api", vec![SkillMatch::at_least("backend", 1.0)])];

    for slot in slots(&project, &pool, &requirements)? {
        let allowed: Vec<String> = slot.allowed.iter().map(|id| id.to_string()).collect();
        println!("{}: {allowed:?}", slot.id);
    }
    Ok(())
}

Output:

be#1: ["bob", "ann"]