docs: document the whole public surface and deny(missing_docs)
80 undocumented public items, including three that are first contact:
`History::current_skill` — the method the crate's own first example calls
— `EventBuilder`, the type `h.event(t)` hands you, and `Gaussian::mu()`.
Now zero, and `#![deny(missing_docs)]` keeps it that way.
Several docs are measurements rather than readings of the code:
- `Outcome::Ranked` says ranks are used ordinally, so `[0, 1, 2]` and
`[0, 5, 90]` are the same observation. Measured: bit-identical
posteriors for both.
- `OwnedGame::log_evidence` says two identically-rated competitors give
exactly `ln(0.5)`. Written as a doctest, so it runs.
- `Member::weight` says zero and negative are accepted. Measured.
- `ConvergenceReport::final_step` is `(|Δmu|, |Δsigma|)` in skill units,
NOT natural parameters. That one had to be traced through
`Gaussian::delta` rather than assumed from the neighbouring vocabulary.
- `GameOptions::score_sigma` rejects non-positive and NaN but accepts
`+inf`, which is what the guard actually says.
README: it is the front door for a crate on a private registry, and it
opened with a link dump followed by 130 lines on drift. The first
`record_winner → converge → current_skill` block was at line 226 of 307.
It now leads with what the crate is, an install line, a quickstart, a
"which entry point?" table, and the `converge`-is-strict rationale that
was the crate's most opinionated recent decision and went unmentioned.
The two canonical examples disagreed on spelling (`History::default()`
vs `History::builder().build()`, `current_skill("a")` vs
`current_skill(&"a")`); they now agree. Five new README blocks are
doctested, taking the suite from 19 to 25.
`pub use smallvec;`. Four public items name `SmallVec` in their
signatures, and the only `Joint` example failed to compile from a
consumer crate with `unresolved import smallvec` — the dependency was in
the API but not reachable. Both worked examples now use the re-export,
so they teach the path that works downstream.
Vocabulary, from #75: "agent" was a fourth word for competitor, 200
occurrences, and it had reached public signatures before #73 un-exported
`TimeSlice`. Now zero.
Closes #77. Refs #75.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011hcFjNDmHXZF8URGLku5zZ
This commit is contained in:
+18
-10
@@ -95,7 +95,7 @@ pub(crate) struct Event {
|
||||
}
|
||||
|
||||
impl Event {
|
||||
pub(crate) fn iter_agents(&self) -> impl Iterator<Item = Index> + '_ {
|
||||
pub(crate) fn iter_competitors(&self) -> impl Iterator<Item = Index> + '_ {
|
||||
self.teams
|
||||
.iter()
|
||||
.flat_map(|t| t.items.iter().map(|it| it.competitor))
|
||||
@@ -255,7 +255,7 @@ impl<T: Time> TimeSlice<T> {
|
||||
}
|
||||
|
||||
let cg = color_greedy(n, |ev_idx| {
|
||||
self.events[ev_idx].iter_agents().collect::<Vec<_>>()
|
||||
self.events[ev_idx].iter_competitors().collect::<Vec<_>>()
|
||||
});
|
||||
|
||||
let mut reordered: Vec<Event> = Vec::with_capacity(n);
|
||||
@@ -292,7 +292,7 @@ impl<T: Time> TimeSlice<T> {
|
||||
) {
|
||||
let mut unique = Vec::with_capacity(10);
|
||||
|
||||
let this_agent = composition.iter().flatten().flatten().filter(|idx| {
|
||||
let these_competitors = composition.iter().flatten().flatten().filter(|idx| {
|
||||
if !unique.contains(idx) {
|
||||
unique.push(*idx);
|
||||
|
||||
@@ -302,7 +302,7 @@ impl<T: Time> TimeSlice<T> {
|
||||
false
|
||||
});
|
||||
|
||||
for idx in this_agent {
|
||||
for idx in these_competitors {
|
||||
let elapsed = compute_elapsed(competitors[*idx].last_time.as_ref(), &self.time);
|
||||
|
||||
let forward = competitors[*idx].receive(&self.time);
|
||||
@@ -1235,14 +1235,22 @@ mod tests {
|
||||
// Events at positions 0 and 1 (color 0) must be disjoint — verify by
|
||||
// checking that the competitor sets of self.events[0] and self.events[1] do
|
||||
// not include the competitor at self.events[2].
|
||||
let agents_in_ev2: Vec<Index> = ts.events[2].iter_agents().collect();
|
||||
let agents_in_ev0: Vec<Index> = ts.events[0].iter_agents().collect();
|
||||
let agents_in_ev1: Vec<Index> = ts.events[1].iter_agents().collect();
|
||||
let competitors_in_ev2: Vec<Index> = ts.events[2].iter_competitors().collect();
|
||||
let competitors_in_ev0: Vec<Index> = ts.events[0].iter_competitors().collect();
|
||||
let competitors_in_ev1: Vec<Index> = ts.events[1].iter_competitors().collect();
|
||||
// ev0 and ev1 must be disjoint from each other (color-0 invariant).
|
||||
assert!(agents_in_ev0.iter().all(|ag| !agents_in_ev1.contains(ag)));
|
||||
assert!(
|
||||
competitors_in_ev0
|
||||
.iter()
|
||||
.all(|ag| !competitors_in_ev1.contains(ag))
|
||||
);
|
||||
// ev2 must share an competitor with ev0 or ev1 (it needed its own color).
|
||||
let ev2_overlaps_ev0 = agents_in_ev2.iter().any(|ag| agents_in_ev0.contains(ag));
|
||||
let ev2_overlaps_ev1 = agents_in_ev2.iter().any(|ag| agents_in_ev1.contains(ag));
|
||||
let ev2_overlaps_ev0 = competitors_in_ev2
|
||||
.iter()
|
||||
.any(|ag| competitors_in_ev0.contains(ag));
|
||||
let ev2_overlaps_ev1 = competitors_in_ev2
|
||||
.iter()
|
||||
.any(|ag| competitors_in_ev1.contains(ag));
|
||||
assert!(ev2_overlaps_ev0 || ev2_overlaps_ev1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user