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 }