Tip: add nominal_volume, the rated working volume distinct from physical capacity#1102
Merged
Merged
Conversation
…hysical capacity Adds a `nominal_volume` field to `Tip` - the tip's rated working volume (what it is sold and named as), distinct from `maximal_volume`, the physical brim-full capacity. The rated volume previously lived only in the creator names and was discarded: `hamilton_tip_300uL` stored `maximal_volume=400`, so the "300" - the number a user thinks in, and the natural basis for default volumes and capacity checks - was unreadable from the `Tip`. - `nominal_volume: Optional[float] = None`; falls back to `maximal_volume` in `__post_init__` when omitted, so every tip always has a sensible value. - Informational only: the `VolumeTracker` is still bound by `maximal_volume`. No tracking or validation behaviour changes. - Added to `serialize`, `__hash__`, and `__eq__`. The `TipTracker` carries it through pickup/drop (it holds the `Tip` by reference) and across save/load (serialize now emits it, deserialize reads it). - Threaded through `HamiltonTip` and set on all 15 Hamilton creators, e.g. `nominal_volume=300` on `hamilton_tip_300uL` (max 400). Values are the manufacturer's rated volume, cross-checked against the Hamilton catalog (the CO-RE tip families are named by rated volume; cat. nos. 235966/235948 -> 50 uL, 235900/235901 -> 10 uL confirm it). Backward compatible: optional with a default, so no call site changes and no current tip's reported numbers change. Payloads predating the field deserialize fine (the missing key falls back to `maximal_volume`). It now participates in equality/hashing, but since the fallback makes an unset nominal equal to `maximal_volume`, only tips with a genuinely distinct rating differ. Follow-up (not in this PR): the same rated-vs-physical split applies to `Container`. Two pre-existing `maximal_volume` data questions surfaced while setting the values and are left untouched here - `hamilton_tip_10uL_filter` has `maximal_volume=10` (equal to its nominal, below the 15 uL non-filter), and `hamilton_tip_5000uL` / `_filter` share an identical max. Tests: defaults to `maximal_volume` when omitted; a payload missing the key falls back on deserialize; the updated serialize snapshots include the field. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Member
|
nice |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a
nominal_volumefield toTip- the tip's rated working volume (what it is sold and named as), distinct frommaximal_volume, the physical brim-full capacity.The rated volume previously lived only in the creator names and was discarded:
hamilton_tip_300uLstoredmaximal_volume=400, so the "300" - the number a user thinks in, and the natural basis for default volumes and capacity checks - was unreadable from theTip.nominal_volume: Optional[float] = None; falls back tomaximal_volumein__post_init__when omitted, so every tip always has a sensible value.VolumeTrackeris still bound bymaximal_volume. No tracking or validation behaviour changes.serialize,__hash__, and__eq__. TheTipTrackercarries it through pickup/drop (it holds theTipby reference) and across save/load (serialize now emits it, deserialize reads it).HamiltonTipand set on all 15 Hamilton creators, e.g.nominal_volume=300onhamilton_tip_300uL(max 400). Values are the manufacturer's rated volume, cross-checked against the Hamilton catalog (the CO-RE tip families are named by rated volume; cat. nos. 235966/235948 -> 50 uL, 235900/235901 -> 10 uL confirm it).Backward compatible: optional with a default, so no call site changes and no current tip's reported numbers change. Payloads predating the field deserialize fine (the missing key falls back to
maximal_volume). It now participates in equality/hashing, but since the fallback makes an unset nominal equal tomaximal_volume, only tips with a genuinely distinct rating differ.Follow-up (not in this PR): the same rated-vs-physical split applies to
Container. Two pre-existingmaximal_volumedata questions surfaced while setting the values and are left untouched here -hamilton_tip_10uL_filterhasmaximal_volume=10(equal to its nominal, below the 15 uL non-filter), andhamilton_tip_5000uL/_filtershare an identical max.Tests: defaults to
maximal_volumewhen omitted; a payload missing the key falls back on deserialize; the updated serialize snapshots include the field.🤖 Generated with Claude Code