Skip to main content

solverforge_scoring/director/
traits.rs

1// Score director trait definition.
2
3use solverforge_core::domain::{PlanningSolution, SolutionDescriptor};
4
5/* The score director manages solution state and score calculation.
6
7It is responsible for:
8- Maintaining the working solution
9- Calculating scores (incrementally when possible)
10- Notifying about variable changes for incremental updates
11- Providing access to solution metadata via descriptors
12*/
13pub trait Director<S: PlanningSolution>: Send {
14    // Returns a reference to the working solution.
15    fn working_solution(&self) -> &S;
16
17    // Returns a mutable reference to the working solution.
18    fn working_solution_mut(&mut self) -> &mut S;
19
20    // Calculates and returns the current score.
21    fn calculate_score(&mut self) -> S::Score;
22
23    // Returns the solution descriptor for this solution type.
24    fn solution_descriptor(&self) -> &SolutionDescriptor;
25
26    // Clones the working solution.
27    fn clone_working_solution(&self) -> S;
28
29    // Called before a planning variable is changed.
30    fn before_variable_changed(&mut self, descriptor_index: usize, entity_index: usize);
31
32    // Called after a planning variable is changed.
33    fn after_variable_changed(&mut self, descriptor_index: usize, entity_index: usize);
34
35    // Returns the number of entities for a given descriptor index.
36    fn entity_count(&self, descriptor_index: usize) -> Option<usize>;
37
38    // Returns the total number of entities across all collections.
39    fn total_entity_count(&self) -> Option<usize>;
40
41    // Returns true if this score director supports incremental scoring.
42    fn is_incremental(&self) -> bool {
43        false
44    }
45
46    // Resets the score director state.
47    fn reset(&mut self) {}
48
49    /* Registers a typed undo closure.
50
51    Called by moves after applying changes to enable automatic undo.
52    The closure will be called in reverse order during `undo_changes()`.
53
54    Default implementation does nothing (for non-recording directors).
55    */
56    fn register_undo(&mut self, _undo: Box<dyn FnOnce(&mut S) + Send>) {
57        // Default: no-op - only RecordingDirector stores undo closures
58    }
59}