feat(growth): add deterministic forecasting engine
This commit is contained in:
58
internal/growth/peer.go
Normal file
58
internal/growth/peer.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package growth
|
||||
|
||||
import "slices"
|
||||
|
||||
type PeerState string
|
||||
|
||||
const (
|
||||
PeerReady PeerState = "READY"
|
||||
PeerSuppressed PeerState = "SUPPRESSED"
|
||||
)
|
||||
|
||||
type PeerMerchantValue struct {
|
||||
PaidSessions int64 `json:"paidSessions"`
|
||||
SessionCount int64 `json:"sessionCount"`
|
||||
}
|
||||
|
||||
type PeerInput struct {
|
||||
TerminalScoped bool `json:"terminalScoped"`
|
||||
MerchantPaidSessions int64 `json:"merchantPaidSessions"`
|
||||
Peers []PeerMerchantValue `json:"peers"`
|
||||
}
|
||||
|
||||
type PeerResult struct {
|
||||
State PeerState `json:"state"`
|
||||
Reason SuppressionReason `json:"reason,omitempty"`
|
||||
EligiblePeerCount int `json:"eligiblePeerCount"`
|
||||
CombinedPeerSessions int64 `json:"combinedPeerSessions"`
|
||||
MedianPaidSessions int64 `json:"medianPaidSessions"`
|
||||
PercentileBPS int64 `json:"percentileBps"`
|
||||
}
|
||||
|
||||
func EvaluatePeer(input PeerInput) PeerResult {
|
||||
result := PeerResult{State: PeerSuppressed, EligiblePeerCount: len(input.Peers)}
|
||||
if input.TerminalScoped {
|
||||
result.Reason = SuppressionTerminalScope
|
||||
return result
|
||||
}
|
||||
values := make([]int64, 0, len(input.Peers))
|
||||
for _, peer := range input.Peers {
|
||||
result.CombinedPeerSessions += peer.SessionCount
|
||||
values = append(values, peer.PaidSessions)
|
||||
}
|
||||
if len(values) < 10 || result.CombinedPeerSessions < 1_000 {
|
||||
result.Reason = SuppressionInsufficientCohort
|
||||
return result
|
||||
}
|
||||
slices.Sort(values)
|
||||
result.State = PeerReady
|
||||
result.MedianPaidSessions = median(values)
|
||||
var atOrBelow int64
|
||||
for _, value := range values {
|
||||
if input.MerchantPaidSessions >= value {
|
||||
atOrBelow++
|
||||
}
|
||||
}
|
||||
result.PercentileBPS = atOrBelow * 10_000 / int64(len(values))
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user