@@ -66,7 +66,7 @@ const (
6666 decayHalfLife = 30.0
6767
6868 // slapCooldown prevents rapid-fire audio playback.
69- slapCooldown = 500 * time .Millisecond
69+ slapCooldown = 750 * time .Millisecond
7070
7171 // sensorPollInterval is how often we check for new accelerometer data.
7272 sensorPollInterval = 10 * time .Millisecond
@@ -130,12 +130,13 @@ type slapTracker struct {
130130}
131131
132132func newSlapTracker (pack * soundPack ) * slapTracker {
133- // scale is derived so that the theoretical max steady-state score
134- // (at peak slap rate with slapCooldown) maps to approximately the
135- // second-to-last file, making the last file asymptotically unreachable.
133+ // scale maps the exponential curve so that sustained max-rate
134+ // slapping (one per cooldown) reaches the final file. At steady
135+ // state the score converges to ssMax; we set scale so that score
136+ // maps to the last index.
136137 cooldownSec := slapCooldown .Seconds ()
137138 ssMax := 1.0 / (1.0 - math .Pow (0.5 , cooldownSec / decayHalfLife ))
138- scale := (ssMax - 1 ) / math .Log (float64 (len (pack .files )))
139+ scale := (ssMax - 1 ) / math .Log (float64 (len (pack .files )+ 1 ))
139140 return & slapTracker {
140141 halfLife : decayHalfLife ,
141142 scale : scale ,
@@ -162,10 +163,11 @@ func (st *slapTracker) getFile(score float64) string {
162163 return st .pack .files [rand .Intn (len (st .pack .files ))]
163164 }
164165
165- // Escalation: 1-exp(-x) curve asymptotically approaches the top
166- // without ever reaching it. Slap faster to climb; slow down to decay.
166+ // Escalation: 1-exp(-x) curve maps score to file index.
167+ // At sustained max slap rate, score reaches ssMax which maps
168+ // to the final file.
167169 maxIdx := len (st .pack .files ) - 1
168- idx := int (float64 (maxIdx ) * (1.0 - math .Exp (- (score - 1 )/ st .scale )))
170+ idx := int (float64 (len ( st . pack . files ) ) * (1.0 - math .Exp (- (score - 1 )/ st .scale )))
169171 if idx > maxIdx {
170172 idx = maxIdx
171173 }
0 commit comments