refactor!: replace emptiness-as-sentinel with Option for results and weights
Third of the five remaining items on #23. `add_events_with_prior` and `TimeSlice::add_events` took `Vec<Vec<f64>>` and `Vec<Vec<Vec<f64>>>` where an empty vec meant "not supplied" — so an empty outer vec and a genuinely empty event list were the same value, and every reader had to know which. Both are now `Option`, and the "not supplied" branches read as `None` arms rather than `is_empty()` checks. Two things fell out of the change that a sentinel would have hidden: The tie pre-check iterated `results` directly. Under `Option` it needs `.iter().flatten()`, which makes explicit that a `None` results list has no ties to reject — previously an empty vec silently skipped the same loop and looked identical to "checked, found nothing". `MismatchedShape.got` could no longer be `results.len()`, because at the point of the error there may be no vec to take a length from. It is now computed as `map_or(0, Vec::len)` before the error is built. MSRV note: my first draft used let-chains for the two validations. Those need Rust 1.88 and this crate pins 1.85 — it compiled locally on 1.98 and would have failed only in the MSRV CI job. Rewritten with `is_some_and`, and verified by installing 1.85.0 and building against it rather than by assuming the removal was complete. Breaking: `TimeSlice::add_events` is public. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T5SYDExxL4vZgvunrcNSMc
This commit is contained in:
+20
-21
@@ -277,8 +277,8 @@ impl<T: Time> TimeSlice<T> {
|
||||
pub fn add_events<D: Drift<T>>(
|
||||
&mut self,
|
||||
composition: Vec<Vec<Vec<Index>>>,
|
||||
results: Vec<Vec<f64>>,
|
||||
weights: Vec<Vec<Vec<f64>>>,
|
||||
results: Option<Vec<Vec<f64>>>,
|
||||
weights: Option<Vec<Vec<Vec<f64>>>>,
|
||||
kinds: Vec<EventKind>,
|
||||
agents: &CompetitorStore<T, D>,
|
||||
) {
|
||||
@@ -328,22 +328,21 @@ impl<T: Time> TimeSlice<T> {
|
||||
|
||||
Team {
|
||||
items,
|
||||
output: if results.is_empty() {
|
||||
(event.len() - (t + 1)) as f64
|
||||
} else {
|
||||
results[e][t]
|
||||
output: match &results {
|
||||
Some(results) => results[e][t],
|
||||
// No explicit result: rank by position, first team best.
|
||||
None => (event.len() - (t + 1)) as f64,
|
||||
},
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let weights = if weights.is_empty() {
|
||||
teams
|
||||
let weights = match &weights {
|
||||
Some(weights) => weights[e].clone(),
|
||||
None => teams
|
||||
.iter()
|
||||
.map(|team| vec![1.0; team.items.len()])
|
||||
.collect::<Vec<_>>()
|
||||
} else {
|
||||
weights[e].clone()
|
||||
.collect::<Vec<_>>(),
|
||||
};
|
||||
|
||||
Event {
|
||||
@@ -828,8 +827,8 @@ mod tests {
|
||||
vec![vec![c], vec![d]],
|
||||
vec![vec![e], vec![f]],
|
||||
],
|
||||
vec![vec![1.0, 0.0], vec![0.0, 1.0], vec![1.0, 0.0]],
|
||||
vec![],
|
||||
Some(vec![vec![1.0, 0.0], vec![0.0, 1.0], vec![1.0, 0.0]]),
|
||||
None,
|
||||
vec![EventKind::Ranked; 3],
|
||||
&agents,
|
||||
);
|
||||
@@ -905,8 +904,8 @@ mod tests {
|
||||
vec![vec![a], vec![c]],
|
||||
vec![vec![b], vec![c]],
|
||||
],
|
||||
vec![vec![1.0, 0.0], vec![0.0, 1.0], vec![1.0, 0.0]],
|
||||
vec![],
|
||||
Some(vec![vec![1.0, 0.0], vec![0.0, 1.0], vec![1.0, 0.0]]),
|
||||
None,
|
||||
vec![EventKind::Ranked; 3],
|
||||
&agents,
|
||||
);
|
||||
@@ -985,8 +984,8 @@ mod tests {
|
||||
vec![vec![a], vec![c]],
|
||||
vec![vec![b], vec![c]],
|
||||
],
|
||||
vec![vec![1.0, 0.0], vec![0.0, 1.0], vec![1.0, 0.0]],
|
||||
vec![],
|
||||
Some(vec![vec![1.0, 0.0], vec![0.0, 1.0], vec![1.0, 0.0]]),
|
||||
None,
|
||||
vec![EventKind::Ranked; 3],
|
||||
&agents,
|
||||
);
|
||||
@@ -1017,8 +1016,8 @@ mod tests {
|
||||
vec![vec![a], vec![c]],
|
||||
vec![vec![b], vec![c]],
|
||||
],
|
||||
vec![vec![1.0, 0.0], vec![0.0, 1.0], vec![1.0, 0.0]],
|
||||
vec![],
|
||||
Some(vec![vec![1.0, 0.0], vec![0.0, 1.0], vec![1.0, 0.0]]),
|
||||
None,
|
||||
vec![EventKind::Ranked; 3],
|
||||
&agents,
|
||||
);
|
||||
@@ -1088,8 +1087,8 @@ mod tests {
|
||||
vec![vec![c], vec![d]],
|
||||
vec![vec![a], vec![c]],
|
||||
],
|
||||
vec![vec![1.0, 0.0], vec![1.0, 0.0], vec![1.0, 0.0]],
|
||||
vec![],
|
||||
Some(vec![vec![1.0, 0.0], vec![1.0, 0.0], vec![1.0, 0.0]]),
|
||||
None,
|
||||
vec![EventKind::Ranked; 3],
|
||||
&agents,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user