yumi-golang/internal/service/wheel/probability_test.go
2026-05-15 09:58:01 +08:00

59 lines
1.9 KiB
Go

package wheel
import (
"math"
"testing"
"chatapp3-golang/internal/model"
)
func TestPickRewardDistribution1000000Draws(t *testing.T) {
const (
draws = 1000000
maxAllowedDriftPercent = 1.0
)
rewards := []model.WheelRewardConfig{
{ID: 1, Enabled: true, RewardType: rewardTypeResource, ResourceName: "Coral Crown", Probability: 3000},
{ID: 2, Enabled: true, RewardType: rewardTypeResource, ResourceName: "Aurora Wing", Probability: 2200},
{ID: 3, Enabled: true, RewardType: rewardTypeResource, ResourceName: "Moon Card", Probability: 1500},
{ID: 4, Enabled: true, RewardType: rewardTypeResource, ResourceName: "Snow Pet", Probability: 1200},
{ID: 5, Enabled: true, RewardType: rewardTypeResource, ResourceName: "Love Banner", Probability: 900},
{ID: 6, Enabled: true, RewardType: rewardTypeResource, ResourceName: "Emerald Ring", Probability: 600},
{ID: 7, Enabled: true, RewardType: rewardTypeResource, ResourceName: "Royal Chest", Probability: 400},
{ID: 8, Enabled: true, RewardType: rewardTypeGold, ResourceName: "Gold", Probability: 200},
}
counts := make(map[int64]int, len(rewards))
for index := 0; index < draws; index++ {
reward, err := pickReward(rewards)
if err != nil {
t.Fatalf("pickReward() error = %v", err)
}
counts[reward.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.ResourceName,
expectedPercent,
actualPercent,
driftPercent,
counts[reward.ID],
draws,
)
if driftPercent > maxAllowedDriftPercent {
t.Fatalf(
"reward %s probability drift %.2f%% exceeds %.2f%%",
reward.ResourceName,
driftPercent,
maxAllowedDriftPercent,
)
}
}
}