presentation/widgets/common/wheel_spinner library

Classes

WheelPointerClicker
The fixed pointer of a WheelSpinner: flicks about its top anchor by angle (radians), which the wheel derives from its own rotation — this widget owns no timer or controller.
WheelSegment
One slice of a WheelSpinner — caller-supplied, same convention as LeaderboardEntry/VictoryCardTemplate.statLines: this widget never invents reward values or odds, it only renders and animates.
WheelSpinner
A candy-styled "wheel of fortune" — draws its own pie-slice wheel via CustomPaint (no extra package dependency), spins to whatever index controller requests, and reports the landed WheelSegment via onSpinEnd. A fixed pointer marks the winning slice at the top; the wheel itself is the only thing that rotates.
WheelSpinnerController
Plain ChangeNotifier the caller creates and owns (like a TextEditingController, same pattern as ScreenShakeController in screen_shake.dart) — triggers a spin on the WheelSpinner it's attached to.
WheelSpinnerPainter
Public (rather than the usual underscore-private painter convention in this file's siblings) so a widget test can pull .segments back off the mounted CustomPaint — same testability reason as SpotlightOverlay's SpotlightHolePainter.

Functions

wheelPointerBounceAngle({required double velocity, required double secondsSinceCrossing, required int segmentCount}) → double
Pointer deflection (radians) shortly after a segment crossing: a damped sine kick opposing the wheel's motion, scaled by angular velocity (radians/second) and capped to a fraction of one segment so the pointer never swings past the neighbouring slice.
wheelSegmentCrossingCount({required double previousRotation, required double currentRotation, required int segmentCount}) → int
Number of segment boundaries a wheel passed between two unwrapped rotations (radians). Boundaries sit every 2π / segmentCount; the previous rotation is exclusive and the current one inclusive, so a frame resting exactly on a boundary neither double-counts nor misses it.