fix room rocket in-room reward spread
This commit is contained in:
parent
1123821785
commit
b55a01c0d6
@ -1053,13 +1053,6 @@ func (s *Service) settleRoomRocketRewards(ctx context.Context, now time.Time, cu
|
||||
})
|
||||
return nil
|
||||
}
|
||||
addRandomReward := func(role string, userID int64, pool []RoomRocketRewardItem) error {
|
||||
item, ok := selectRoomRocketReward(launch.RocketID, role, userID, pool)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return addRewardItem(role, userID, item)
|
||||
}
|
||||
addAllRewards := func(role string, userID int64, pool []RoomRocketRewardItem) error {
|
||||
for _, item := range pool {
|
||||
if err := addRewardItem(role, userID, item); err != nil {
|
||||
@ -1069,9 +1062,14 @@ func (s *Service) settleRoomRocketRewards(ctx context.Context, now time.Time, cu
|
||||
return nil
|
||||
}
|
||||
|
||||
inRoomRewards := selectRoomRocketRewardsForUsers(launch.RocketID, roomRocketRewardInRoom, inRoomUserIDs, levelCfg.InRoomRewards)
|
||||
for _, userID := range inRoomUserIDs {
|
||||
// 在房奖励是大面积发放池,每个在线用户只按权重抽一个奖项,避免房间人数放大单次火箭成本。
|
||||
if err := addRandomReward(roomRocketRewardInRoom, userID, levelCfg.InRoomRewards); err != nil {
|
||||
// 在房奖励是大面积发放池,每个在线用户只拿一个奖项;同一枚火箭内按无放回周期分配,避免配置了金币和麦位声波时整房都落到同一个奖项。
|
||||
item, ok := inRoomRewards[userID]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if err := addRewardItem(roomRocketRewardInRoom, userID, item); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@ -1111,7 +1109,56 @@ func (s *Service) grantRoomRocketReward(ctx context.Context, _ time.Time, curren
|
||||
return resp.GetGrant().GetGrantId(), nil
|
||||
}
|
||||
|
||||
func validRoomRocketRewardPool(pool []RoomRocketRewardItem) []RoomRocketRewardItem {
|
||||
valid := make([]RoomRocketRewardItem, 0, len(pool))
|
||||
for _, item := range pool {
|
||||
if item.Weight <= 0 || item.ResourceGroupID <= 0 {
|
||||
continue
|
||||
}
|
||||
valid = append(valid, item)
|
||||
}
|
||||
return valid
|
||||
}
|
||||
|
||||
func selectRoomRocketRewardsForUsers(rocketID string, role string, userIDs []int64, pool []RoomRocketRewardItem) map[int64]RoomRocketRewardItem {
|
||||
assignments := make(map[int64]RoomRocketRewardItem, len(userIDs))
|
||||
if len(userIDs) == 0 {
|
||||
return assignments
|
||||
}
|
||||
basePool := validRoomRocketRewardPool(pool)
|
||||
if len(basePool) == 0 {
|
||||
return assignments
|
||||
}
|
||||
available := append([]RoomRocketRewardItem(nil), basePool...)
|
||||
cycle := 0
|
||||
for index, userID := range userIDs {
|
||||
if userID <= 0 {
|
||||
continue
|
||||
}
|
||||
if len(available) == 0 {
|
||||
// 一轮内每个配置项最多发一次;房间人数超过奖池大小时再开启下一轮,让大房间仍可继续按配置重复分配。
|
||||
available = append([]RoomRocketRewardItem(nil), basePool...)
|
||||
cycle++
|
||||
}
|
||||
selectedIndex, ok := selectRoomRocketRewardIndex(rocketID, role, userID, available, fmt.Sprintf("cycle:%d:index:%d", cycle, index))
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
assignments[userID] = available[selectedIndex]
|
||||
available = append(available[:selectedIndex], available[selectedIndex+1:]...)
|
||||
}
|
||||
return assignments
|
||||
}
|
||||
|
||||
func selectRoomRocketReward(rocketID string, role string, userID int64, pool []RoomRocketRewardItem) (RoomRocketRewardItem, bool) {
|
||||
index, ok := selectRoomRocketRewardIndex(rocketID, role, userID, pool, "")
|
||||
if !ok {
|
||||
return RoomRocketRewardItem{}, false
|
||||
}
|
||||
return pool[index], true
|
||||
}
|
||||
|
||||
func selectRoomRocketRewardIndex(rocketID string, role string, userID int64, pool []RoomRocketRewardItem, salt string) (int, bool) {
|
||||
total := int64(0)
|
||||
for _, item := range pool {
|
||||
if item.Weight > 0 && item.ResourceGroupID > 0 {
|
||||
@ -1119,21 +1166,26 @@ func selectRoomRocketReward(rocketID string, role string, userID int64, pool []R
|
||||
}
|
||||
}
|
||||
if total <= 0 {
|
||||
return RoomRocketRewardItem{}, false
|
||||
return -1, false
|
||||
}
|
||||
hash := sha256.Sum256([]byte(fmt.Sprintf("%s|%s|%d", rocketID, role, userID)))
|
||||
hash := sha256.Sum256([]byte(fmt.Sprintf("%s|%s|%d|%s", rocketID, role, userID, salt)))
|
||||
pick := int64(binary.BigEndian.Uint64(hash[:8]) % uint64(total))
|
||||
cursor := int64(0)
|
||||
for _, item := range pool {
|
||||
fallback := -1
|
||||
for index, item := range pool {
|
||||
if item.Weight <= 0 || item.ResourceGroupID <= 0 {
|
||||
continue
|
||||
}
|
||||
fallback = index
|
||||
cursor += item.Weight
|
||||
if pick < cursor {
|
||||
return item, true
|
||||
return index, true
|
||||
}
|
||||
}
|
||||
return pool[len(pool)-1], true
|
||||
if fallback >= 0 {
|
||||
return fallback, true
|
||||
}
|
||||
return -1, false
|
||||
}
|
||||
|
||||
func roomRocketGrantCommandID(rocketID string, role string, userID int64, rewardItemID string) string {
|
||||
|
||||
@ -566,6 +566,9 @@ func TestRoomRocketLaunchStacksAllSpecialPoolsAndRandomInRoomReward(t *testing.T
|
||||
if countRocketRewards(rewards, igniterID, "in_room") != 1 {
|
||||
t.Fatalf("top1 igniter must still receive exactly one random in-room reward: %+v", rewards)
|
||||
}
|
||||
if countRocketRewardsByRoleAndGroup(rewards, "in_room", 1001) != 1 || countRocketRewardsByRoleAndGroup(rewards, "in_room", 1101) != 1 {
|
||||
t.Fatalf("in-room rewards must spread across the configured pool before repeating an item: %+v", rewards)
|
||||
}
|
||||
if countRocketRewards(rewards, igniterID, "top1") != 2 || countRocketRewards(rewards, igniterID, "igniter") != 2 {
|
||||
t.Fatalf("top1 igniter must receive every configured special reward: %+v", rewards)
|
||||
}
|
||||
@ -828,6 +831,16 @@ func countRocketRewards(rewards []*roomv1.RoomRocketRewardGrant, userID int64, r
|
||||
return count
|
||||
}
|
||||
|
||||
func countRocketRewardsByRoleAndGroup(rewards []*roomv1.RoomRocketRewardGrant, role string, groupID int64) int {
|
||||
count := 0
|
||||
for _, reward := range rewards {
|
||||
if reward.GetRewardRole() == role && reward.GetResourceGroupId() == groupID {
|
||||
count++
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func rocketRewardUserIDs(rewards []*roomv1.RoomRocketRewardGrant) []int64 {
|
||||
userIDs := make([]int64, 0, len(rewards))
|
||||
for _, reward := range rewards {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user