| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419 |
- package match
- import (
- "encoding/json"
- "os"
- "sort"
- "sync"
- "time"
- "bet24.com/log"
- "bet24.com/servers/common"
- "bet24.com/servers/micros/guess/handler/team"
- pb "bet24.com/servers/micros/guess/proto"
- platformconfig "bet24.com/servers/micros/platformconfig/proto"
- )
- const config_key = "guess_config"
- var mgr *matchmgr
- // 赛事
- type matchmgr struct {
- matchList map[string]*match
- lock *sync.RWMutex
- configString string
- pb.GuessCfg // 竞猜配置
- }
- func getMatchManager() *matchmgr {
- if mgr == nil {
- mgr = new(matchmgr)
- mgr.ctor()
- }
- return mgr
- }
- func (this *matchmgr) ctor() {
- mgr.matchList = make(map[string]*match)
- mgr.lock = &sync.RWMutex{}
- this.readConf()
- this.loadMatchList()
- mgr.doCheck()
- log.Debug("matchmgr.ctor starting ...")
- return
- }
- func (this *matchmgr) readConf() {
- time.AfterFunc(time.Second*600, this.readConf)
- configString := platformconfig.GetConfig(config_key)
- if configString == "" {
- data, err := os.ReadFile("serviceconf/guess_config.json")
- if err != nil {
- log.Release("matchmgr.readConf read config failed")
- return
- }
- configString = string(data)
- if configString != "" {
- platformconfig.SetConfig(config_key, configString)
- }
- }
- if configString == this.configString {
- return
- }
- this.configString = configString
- // 读取配置
- err := json.Unmarshal([]byte(configString), &this.GuessCfg)
- if err != nil {
- log.Release("matchmgr.readConf Unmarshal failed %s", configString)
- }
- }
- // 获取赛事配置
- func (this *matchmgr) getConfig() pb.GuessCfg {
- return this.GuessCfg
- }
- // 加载赛事列表
- func (this *matchmgr) loadMatchList() {
- list := trans_GetMatchList()
- for _, sn := range list {
- this.getMatch(sn)
- }
- return
- }
- func (this *matchmgr) doCheck() {
- ticker := time.NewTicker(1 * time.Second)
- go func(t *time.Ticker) {
- for {
- select {
- case <-t.C:
- go this.checkMatchExpire()
- }
- }
- }(ticker)
- }
- // 获取赛事
- func (this *matchmgr) getMatch(serialNumber string) *match {
- if serialNumber == "" {
- log.Release("matchmgr.getMatch serialNumber is invalid")
- return nil
- }
- this.lock.RLock()
- m, ok := this.matchList[serialNumber]
- this.lock.RUnlock()
- if ok {
- return m
- }
- m = newMatch(serialNumber)
- // 无效数据
- if m.isInvalid() {
- return m
- }
- this.lock.Lock()
- this.matchList[serialNumber] = m
- this.lock.Unlock()
- return m
- }
- // 是否允许修改
- func (this *matchmgr) isMatchUpdate(serialNumber string) bool {
- this.lock.RLock()
- m, ok := this.matchList[serialNumber]
- this.lock.RUnlock()
- if !ok {
- return true
- }
- // 赛事开始了,不允许修改
- if m.StartAt <= common.GetTimeStamp() {
- return false
- }
- return true
- }
- // 刷新赛事
- func (this *matchmgr) refreshMatch(serialNumber string) {
- this.lock.RLock()
- _, ok := this.matchList[serialNumber]
- this.lock.RUnlock()
- if !ok {
- return
- }
- // 删除
- this.lock.Lock()
- delete(this.matchList, serialNumber)
- this.lock.Unlock()
- // 重新获取
- this.getMatch(serialNumber)
- return
- }
- // 检查赛事
- func (this *matchmgr) checkMatchExpire() {
- this.lock.Lock()
- defer this.lock.Unlock()
- for _, v := range this.matchList {
- if !v.isExpire() {
- continue
- }
- delete(this.matchList, v.SerialNumber)
- log.Debug("matchmgr.checkMatchExpire serialNumber=%s 已完成清理", v.SerialNumber)
- }
- return
- }
- // 获取赛事列表(0=所有赛事 1=展示的赛事 2=正在进行的赛事 3=结束的赛事 4=预热的赛事
- func (this *matchmgr) getMatchList(userId, matchType int) []pb.Response_Match {
- var list []pb.Response_Match
- for _, v := range this.matchList {
- // 赛事类型
- if !v.getMatchType(matchType) {
- continue
- }
- list = append(list, this.getMatchInfo(userId, v.SerialNumber))
- }
- sort.SliceStable(list, func(i, j int) bool {
- return list[i].StartAt > list[j].StartAt
- })
- return list
- }
- // 获取赛事信息
- func (this *matchmgr) getMatchInfo(userId int, serialNumber string) pb.Response_Match {
- //log.Debug("getMatchInfo userId=%d serialNumber=%s", userId, serialNumber)
- m := this.getMatch(serialNumber)
- if m == nil {
- log.Debug("matchmgr.getMatchInfo serialNumber=%s is not exist", serialNumber)
- return pb.Response_Match{}
- }
- var userBets []pb.UserBet
- if userId > 0 {
- userBets = this.getUserBet(userId, m.SerialNumber)
- }
- return pb.Response_Match{
- Match: m.getInfo(),
- UserBets: userBets,
- }
- }
- // 获取用户投注
- func (this *matchmgr) getUserBet(userId int, serialNumber string) []pb.UserBet {
- m := this.getMatch(serialNumber)
- if m == nil {
- log.Debug("matchmgr.getUserBet serialNumber=%s is not exist", serialNumber)
- return nil
- }
- return m.getUserBet(userId)
- }
- // 投注
- func (this *matchmgr) bet(serialNumber string, userId, betId, amount int, ipAddress string) (ret pb.RetMsg) {
- m := this.getMatch(serialNumber)
- if m == nil {
- log.Debug("matchmgr.bet serialNumber=%s is not exist", serialNumber)
- return
- }
- return m.bet(userId, betId, amount, ipAddress)
- }
- // 设置结果
- func (this *matchmgr) setResult(serialNumber string, betId int, result string, op pb.OpUser) (ret pb.RetMsg) {
- m := this.getMatch(serialNumber)
- if m == nil {
- log.Debug("matchmgr.setResult serialNumber=%s is not exist", serialNumber)
- return
- }
- return m.setResult(betId, result, op)
- }
- // 派奖
- func (this *matchmgr) award(serialNumber string, op pb.OpUser) (ret pb.RetMsg) {
- m := this.getMatch(serialNumber)
- if m == nil {
- log.Debug("matchmgr.award serialNumber=%s is not exist", serialNumber)
- return
- }
- return m.award(op, this.GuessCfg)
- }
- // 添加赛事
- func (this *matchmgr) addMatch(title, startAt, endAt, showStartAt, showEndAt string, op pb.OpUser) pb.RetMsg {
- return trans_AddMatch(title, startAt, endAt, showStartAt, showEndAt, op)
- }
- // 修改赛事
- func (this *matchmgr) updateMatch(serialNumber, title, startAt, endAt, showStartAt, showEndAt string, op pb.OpUser) pb.RetMsg {
- // 判断是否允许修改
- if !this.isMatchUpdate(serialNumber) {
- return pb.RetMsg{
- RetCode: 500,
- Message: "The event has started and cannot be modified",
- }
- }
- // 修改完后
- defer this.refreshMatch(serialNumber)
- return trans_UpdateMatch(serialNumber, title, startAt, endAt, showStartAt, showEndAt, op)
- }
- // 添加赛事球队
- func (this *matchmgr) addMatchTeam(serialNumber string, teamId int, op pb.OpUser) pb.RetMsg {
- if info := team.GetTeam(teamId); info.Id <= 0 {
- return pb.RetMsg{
- RetCode: 501,
- Message: "",
- }
- }
- return trans_AddMatchTeam(serialNumber, teamId, op)
- }
- // 修改赛事球队
- func (this *matchmgr) updateMatchTeam(rId int, serialNumber string, teamId int, op pb.OpUser) pb.RetMsg {
- // 判断是否允许修改
- if !this.isMatchUpdate(serialNumber) {
- return pb.RetMsg{
- RetCode: 500,
- Message: "The event has started and cannot be modified",
- }
- }
- if info := team.GetTeam(teamId); info.Id <= 0 {
- return pb.RetMsg{
- RetCode: 501,
- Message: "",
- }
- }
- // 修改完后
- defer this.refreshMatch(serialNumber)
- return trans_UpdateMatchTeam(rId, serialNumber, teamId, op)
- }
- // 刷新赛事球队
- func (this *matchmgr) refreshMatchTeam(teamId int) {
- for _, m := range this.matchList {
- m.refreshTeam(teamId)
- }
- return
- }
- // 添加赛事投注选项
- func (this *matchmgr) addMatchBet(serialNumber, betName string, betOdds float64, op pb.OpUser) pb.RetMsg {
- return trans_AddMatchBet(serialNumber, betName, betOdds, op)
- }
- // 修改赛事投注选项
- func (this *matchmgr) updateMatchBet(betId int, serialNumber, betName string, betOdds float64, op pb.OpUser) pb.RetMsg {
- // 判断是否允许修改
- if !this.isMatchUpdate(serialNumber) {
- return pb.RetMsg{
- RetCode: 500,
- Message: "The event has started and cannot be modified",
- }
- }
- // 修改完后
- defer this.refreshMatch(serialNumber)
- return trans_UpdateMatchBet(betId, serialNumber, betName, betOdds, op)
- }
- // 设置赛事开启
- func (this *matchmgr) setMatchOpen(serialNumber string, status int) (ret pb.RetMsg) {
- // TODO:数据库处理
- if retCode := trans_UpdateMatchStatus(serialNumber, status); retCode != 1 {
- ret.RetCode = 501
- ret.Message = "Setting open failed"
- return
- }
- // 设置完后
- this.refreshMatch(serialNumber)
- ret.RetCode = 1
- ret.Message = "success"
- return
- }
- // 获取用户投注记录
- func (this *matchmgr) getUserBetRecordList(userId, pageIndex, pageSize int) (int, []pb.BetRecord) {
- // TODO:数据库处理
- recordCount, list := trans_GetUserBetRecordList(userId, "", pageIndex, pageSize)
- for k, v := range list {
- m := this.getMatch(v.SerialNumber)
- if m == nil {
- continue
- }
- list[k].Title = m.Title
- list[k].StartTime = m.StartAt
- list[k].Status = m.Status
- list[k].Teams = m.Teams
- list[k].Result = m.Result
- info := m.getBetInfo(v.BetId)
- if info.Id <= 0 {
- continue
- }
- list[k].BetName = info.Name
- }
- return recordCount, list
- }
- // 打印赛事
- func (this *matchmgr) dumpMatch(param1 string) {
- var sn string
- if param1 != "" {
- sn = param1
- }
- log.Debug(" ^_^ 开始打印赛事数据,房间(%d)个", len(this.matchList))
- this.lock.RLock()
- for k, v := range this.matchList {
- if sn != "" && k != sn {
- continue
- }
- v.dump()
- }
- this.lock.RUnlock()
- log.Debug("完成赛事数据打印 ^_^")
- }
|