Files
2026-08-14 13:17:03 +08:00

82 lines
2.3 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package service
import (
"math/rand"
"time"
"nl-game-api-gin/internal/database"
"nl-game-api-gin/internal/model"
)
// VipPeriodStart 计算当前周免周期的起点:最近一个已经到来的周五 12:00服务器本地时区
// 周免批次以该时间戳作随机种子,整周稳定,每周五中午自动轮换
func VipPeriodStart(now time.Time) time.Time {
t := time.Date(now.Year(), now.Month(), now.Day(), 12, 0, 0, 0, now.Location())
for t.Weekday() != time.Friday {
t = t.AddDate(0, 0, -1)
}
// 今天恰好是周五但还没到中午 12 点:仍属于上一周期
if t.After(now) {
t = t.AddDate(0, 0, -7)
}
return t
}
// VipNextRefresh 下一次周免刷新时间(当前周期起点 + 7 天)
func VipNextRefresh(now time.Time) time.Time {
return VipPeriodStart(now).AddDate(0, 0, 7)
}
// VipWeeklyPool 本周期的周免候选池:全部上架付费游戏按种子洗牌后的固定顺序
// 各等级按配额取前 N 款,等级越高批次越大(高等级天然包含低等级的周免)
func VipWeeklyPool(now time.Time) []model.Game {
var paid []model.Game
database.DB.Where("status = 1 AND price > 0").Order("id").Find(&paid)
seed := VipPeriodStart(now).Unix()
rng := rand.New(rand.NewSource(seed))
rng.Shuffle(len(paid), func(i, j int) { paid[i], paid[j] = paid[j], paid[i] })
return paid
}
// VipWeeklyBatch 指定等级本周的周免游戏列表等级≤0 返回空)
func VipWeeklyBatch(pool []model.Game, levels []model.VipLevel, level int) []model.Game {
if level <= 0 {
return nil
}
quota := 0
for _, l := range levels {
if l.Level == level {
quota = l.WeeklyFreeQuota
break
}
}
if quota > len(pool) {
quota = len(pool)
}
return pool[:quota]
}
// UserVipLevel 用户当前生效的 VIP 等级(已过期视为 0
func UserVipLevel(u *model.User, now time.Time) int {
if u.VipLevel > 0 && u.VipExpire > now.Unix() {
return u.VipLevel
}
return 0
}
// VipWeeklyFreeSet 用户本周可白嫖的付费游戏ID集合非VIP返回空集合
func VipWeeklyFreeSet(u *model.User, now time.Time) map[int]bool {
set := map[int]bool{}
level := UserVipLevel(u, now)
if level <= 0 {
return set
}
var levels []model.VipLevel
database.DB.Order("level").Find(&levels)
pool := VipWeeklyPool(now)
for _, g := range VipWeeklyBatch(pool, levels, level) {
set[g.ID] = true
}
return set
}