74 lines
1.8 KiB
Go
74 lines
1.8 KiB
Go
package wheel
|
|
|
|
import (
|
|
"math"
|
|
"testing"
|
|
|
|
"chatapp3-golang/internal/service/prizepool"
|
|
)
|
|
|
|
func TestPickRewardDistribution1000000Draws(t *testing.T) {
|
|
const (
|
|
draws = 1000000
|
|
maxAllowedDriftPercent = 1.0
|
|
)
|
|
|
|
rewards := []struct {
|
|
id int64
|
|
name string
|
|
probability int
|
|
}{
|
|
{id: 1, name: "Coral Crown", probability: 300000},
|
|
{id: 2, name: "Aurora Wing", probability: 220000},
|
|
{id: 3, name: "Moon Card", probability: 150000},
|
|
{id: 4, name: "Snow Pet", probability: 120000},
|
|
{id: 5, name: "Love Banner", probability: 90000},
|
|
{id: 6, name: "Emerald Ring", probability: 60000},
|
|
{id: 7, name: "Royal Chest", probability: 40000},
|
|
{id: 8, name: "Gold", probability: 20000},
|
|
}
|
|
items := make([]prizepool.PickResult, 0, len(rewards))
|
|
for index, reward := range rewards {
|
|
items = append(items, prizepool.PickResult{
|
|
Item: prizepool.Item{
|
|
ID: reward.id,
|
|
Enabled: true,
|
|
Weight: reward.probability,
|
|
},
|
|
Index: index,
|
|
})
|
|
}
|
|
|
|
counts := make(map[int64]int, len(rewards))
|
|
for index := 0; index < draws; index++ {
|
|
reward, err := prizepool.PickWeighted(items)
|
|
if err != nil {
|
|
t.Fatalf("PickWeighted() error = %v", err)
|
|
}
|
|
counts[reward.Item.ID]++
|
|
}
|
|
|
|
for _, reward := range rewards {
|
|
expectedPercent := float64(reward.probability) / probabilityTotal * 100
|
|
actualPercent := float64(counts[reward.id]) / draws * 100
|
|
driftPercent := math.Abs(actualPercent - expectedPercent)
|
|
t.Logf(
|
|
"reward=%s configured=%.2f%% actual=%.2f%% drift=%.2f%% hits=%d/%d",
|
|
reward.name,
|
|
expectedPercent,
|
|
actualPercent,
|
|
driftPercent,
|
|
counts[reward.id],
|
|
draws,
|
|
)
|
|
if driftPercent > maxAllowedDriftPercent {
|
|
t.Fatalf(
|
|
"reward %s probability drift %.2f%% exceeds %.2f%%",
|
|
reward.name,
|
|
driftPercent,
|
|
maxAllowedDriftPercent,
|
|
)
|
|
}
|
|
}
|
|
}
|