package service import ( "blazing/cool" "blazing/modules/player/model" "sync" "github.com/gogf/gf/v2/frame/g" ) type CdkService struct { BaseService mu sync.RWMutex claimedCode map[uint32]struct{} cacheLoaded bool } func (s *CdkService) CanGet(id uint32) bool { if s.isClaimed(id) { return false } if err := s.loadClaimedCodes(); err != nil { exists, _ := s.dbm(s.Model).Where("code_id", id).Exist() if exists { s.markClaimed(id) } return !exists } return !s.isClaimed(id) } func (s *CdkService) Log(id uint32) { m := s.dbm(s.Model) data := g.Map{ "player_id": s.userid, "code_id": id, "is_vip": cool.Config.ServerInfo.IsVip, } if _, err := m.Data(data).Insert(); err == nil { s.markClaimed(id) } } func (s *CdkService) loadClaimedCodes() error { s.mu.RLock() if s.cacheLoaded { s.mu.RUnlock() return nil } s.mu.RUnlock() var logs []model.CdkLog if err := s.dbm(s.Model).Fields("code_id").Scan(&logs); err != nil { return err } s.mu.Lock() defer s.mu.Unlock() if s.cacheLoaded { return nil } s.claimedCode = make(map[uint32]struct{}, len(logs)) for _, log := range logs { s.claimedCode[log.CodeID] = struct{}{} } s.cacheLoaded = true return nil } func (s *CdkService) isClaimed(id uint32) bool { s.mu.RLock() defer s.mu.RUnlock() _, ok := s.claimedCode[id] return ok } func (s *CdkService) markClaimed(id uint32) { s.mu.Lock() defer s.mu.Unlock() if s.claimedCode == nil { s.claimedCode = make(map[uint32]struct{}) } s.claimedCode[id] = struct{}{} } func NewCdkService(id uint32) *CdkService { return &CdkService{ BaseService: BaseService{userid: id, Service: &cool.Service{Model: model.NewCdkLog()}, }, claimedCode: make(map[uint32]struct{}), } }