package prizepool import ( "encoding/json" "fmt" "math/rand" "os" "sync" "time" "bet24.com/log" ) type PrizePool_config struct { MinBulletId int // 最低子弹ID AddPoolPercent int // 击中鱼后进入奖池的百分比 AddEnergyPercent int // 击中Boss鱼如果没中奖池,子弹倍数万分比 增加到能量 BingoPercent int // 中奖概率 FullEnergy int // 能量上限 PoolInit int // 初始奖池金额 MaxPool int // 奖池封顶 } type PrizePool struct { PrizePool_config roomName string pool int lock *sync.RWMutex userLock *sync.RWMutex lastUpdatePool int userEnergy map[int]int } func NewPrizePool(roomName string, roomMinBulletId int) *PrizePool { fileName := fmt.Sprintf("fish/prizepool_%v.json", roomName) data, err := os.ReadFile(fileName) if err != nil { log.Release("read prizepool config failed %v", fileName) return nil } var p PrizePool err = json.Unmarshal(data, &p) if err != nil { log.Release("Unmarshal prizepool config failed err:%v", err) return nil } if roomMinBulletId < p.MinBulletId { return nil } log.Debug("NewPrizePool %v", p) p.lock = &sync.RWMutex{} p.userLock = &sync.RWMutex{} p.roomName = roomName p.userEnergy = make(map[int]int) p.loadPool() ticket := time.NewTicker(time.Duration(5) * time.Second) go func(t *time.Ticker) { for { //循环 select { case <-t.C: p.checkUpdatePool() } } }(ticket) return &p } func (p *PrizePool) loadPool() { // 从数据库读取奖池信息 // TODO pool := getInfo(p.roomName) if pool < p.PoolInit { pool = p.PoolInit } p.lock.Lock() defer p.lock.Unlock() p.pool = pool } func (p *PrizePool) updatePool(pool int) { // 写入数据库 // TODO update(p.roomName, p.pool) } func (p *PrizePool) checkUpdatePool() { p.lock.RLock() defer p.lock.RUnlock() if p.lastUpdatePool == p.pool { return } p.lastUpdatePool = p.pool go p.updatePool(p.pool) } func (p *PrizePool) AddPool(bulletOdds int) { p.lock.Lock() defer p.lock.Unlock() p.pool += bulletOdds / 100 * p.AddPoolPercent } func (p *PrizePool) Draw(userId int, bulletOdds int) (bool, int, int) { bingo := (rand.Intn(100) < p.BingoPercent) point := bulletOdds / 10000 if point+p.GetUserEnergy(userId) >= 10000 { bingo = true } if bingo { p.lock.Lock() point = bulletOdds * p.pool / 1000000 p.pool -= point if p.pool < p.PoolInit { p.pool = p.PoolInit } p.lock.Unlock() p.setEnergy(userId, 0) } else { p.addEnergy(userId, point) } log.Debug("PrizePool.Draw %d,%v,%d", userId, bingo, point) return bingo, point, p.pool } func (p *PrizePool) GetPoolValue() int { p.lock.RLock() defer p.lock.RUnlock() return p.pool } func (p *PrizePool) GetUserEnergy(userId int) int { p.userLock.RLock() ret, ok := p.userEnergy[userId] p.userLock.RUnlock() if ok { return ret } ret = getUserEnergy(userId, p.roomName) p.userLock.Lock() p.userEnergy[userId] = ret p.userLock.Unlock() return ret } func (p *PrizePool) setEnergy(userId, energy int) { if energy < 0 { energy = 0 } p.userLock.Lock() p.userEnergy[userId] = energy p.userLock.Unlock() go setUserEnergy(userId, p.roomName, energy) } func (p *PrizePool) addEnergy(userId, energy int) { energy += p.GetUserEnergy(userId) if energy < 0 { energy = 0 } p.userLock.Lock() p.userEnergy[userId] = energy p.userLock.Unlock() go setUserEnergy(userId, p.roomName, energy) }