Dinner Split
Splitting a bill is arithmetic until it is not. Divide $100 three ways and the cents do not close: three shares of $33.33 sum to $99.99. Something has to absorb the difference, and the choice is a business rule, not a rounding mode.
Here the host absorbs it. Per-attendee :owes is rounded at the boundary, and
the host's share takes the drift so that the invariant holds:
Σ(round attendee.owes) == round(grandTotal)
That is enforced by the property test roundoff-host-absorbs-drift rather than
left as a comment. Arithmetic is double throughout, rounded once at the edge –
never accumulated pre-rounded.
Status
Core-only. core.cljc holds the bill math, the attendee/item shapes, and the
tempId to real-id mapping; app.cljs is a stub. There is no UI on this page
yet.
| Piece | Namespace | State |
|---|---|---|
| Pure logic | wal-sh.projects.dinner-split.core |
complete |
| Storage | wal-sh.projects.dinner-split.storage |
complete |
| SPA entry | wal-sh.projects.dinner-split.app |
stub |
24 example-based tests and 12 test.check properties are defined under
test/wal_sh/projects/dinner_split/.