solverforge 0.12.0

SolverForge - A constraint solver in Rust
Documentation
// Integration test for constraint stream accessors generated by #[planning_solution]
// and convenience methods (penalize_hard, penalize_soft, etc.) on the Score trait.

use solverforge::prelude::*;
use solverforge::stream::{CollectionExtract, ConstraintFactory};
use solverforge::IncrementalConstraint;

#[path = "constraint_accessors/domain/mod.rs"]
mod domain;

use domain::Schedule;

#[test]
fn test_one_hard_returns_correct_score() {
    let hard = HardSoftScore::one_hard();
    assert_eq!(hard, HardSoftScore::of(1, 0));
}

#[test]
fn test_one_soft_returns_correct_score() {
    let soft = HardSoftScore::one_soft();
    assert_eq!(soft, HardSoftScore::of(0, 1));
}

#[test]
fn test_soft_score_one_soft() {
    let soft = SoftScore::one_soft();
    assert_eq!(soft, SoftScore::of(1));
}

#[test]
fn test_constraint_stream_accessors_compile() {
    let factory = ConstraintFactory::<Schedule, HardSoftScore>::new();
    let _shifts_stream = factory.for_each(Schedule::shifts());
    let factory3 = ConstraintFactory::<Schedule, HardSoftScore>::new();
    let _unassigned_stream = factory3.for_each(Schedule::shifts()).unassigned();

    let factory2 = ConstraintFactory::<Schedule, HardSoftScore>::new();
    let _employees_stream = factory2.for_each(Schedule::employees());
}

#[test]
fn generated_descriptor_stream_localizes_callbacks() {
    let mut constraint = ConstraintFactory::<Schedule, HardSoftScore>::new()
        .for_each(Schedule::shifts())
        .penalize_hard()
        .named("shift count");

    let schedule = Schedule {
        employees: vec![domain::Employee {
            id: 1,
            name: "Ada".to_string(),
        }],
        shifts: vec![
            domain::Shift {
                id: 1,
                employee: Some(1),
            },
            domain::Shift {
                id: 2,
                employee: None,
            },
        ],
        score: None,
    };

    assert_eq!(constraint.initialize(&schedule), HardSoftScore::of(-2, 0));
    assert_eq!(constraint.on_insert(&schedule, 0, 1), HardSoftScore::zero());
    assert_eq!(
        constraint.on_retract(&schedule, 0, 0),
        HardSoftScore::of(1, 0)
    );
}

#[test]
fn generated_model_sources_carry_descriptor_metadata() {
    let extractor = Schedule::shifts();
    assert!(extractor.change_source().owns_descriptor(0));

    let mut constraint = ConstraintFactory::<Schedule, HardSoftScore>::new()
        .for_each(extractor)
        .penalize_hard()
        .named("source aware shifts");

    let schedule = Schedule {
        employees: vec![domain::Employee {
            id: 1,
            name: "Ada".to_string(),
        }],
        shifts: vec![domain::Shift {
            id: 1,
            employee: Some(1),
        }],
        score: None,
    };

    assert_eq!(constraint.initialize(&schedule), HardSoftScore::of(-1, 0));
    assert_eq!(
        constraint.on_retract(&schedule, 0, 0),
        HardSoftScore::of(1, 0)
    );
}

#[test]
fn test_penalize_hard_compiles_on_stream() {
    let factory = ConstraintFactory::<Schedule, HardSoftScore>::new();
    let constraint = factory
        .for_each(Schedule::shifts())
        .penalize_hard()
        .named("Test penalize hard");

    let _ = constraint;
}

#[test]
fn test_penalize_soft_compiles_on_stream() {
    let factory = ConstraintFactory::<Schedule, HardSoftScore>::new();
    let constraint = factory
        .for_each(Schedule::shifts())
        .penalize_soft()
        .named("Test penalize soft");

    let _ = constraint;
}

#[test]
fn test_named_alias_compiles() {
    let factory = ConstraintFactory::<Schedule, HardSoftScore>::new();
    let constraint = factory
        .for_each(Schedule::shifts())
        .penalize_hard()
        .named("Test named alias");

    let _ = constraint;
}