| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378 |
- package pointmatch
- import (
- "os"
- "bet24.com/log"
- "bet24.com/servers/common"
- micro_common "bet24.com/servers/micros/common"
- "encoding/json"
- "fmt"
- "strconv"
- "sync"
- "time"
- "bet24.com/servers/micros/matches/handler/matchbase"
- cash "bet24.com/servers/micros/money/proto"
- platformconfig "bet24.com/servers/micros/platformconfig/proto"
- privateroom "bet24.com/servers/micros/privateroom/proto"
- )
- const (
- match_timeout_not_playing = 1800
- match_timeout_started = 14400
- match_timeout_ended = 120
- )
- const config_key = "pointmatch_config"
- const refresh_config_sec = 600
- type matchmanager struct {
- lock *sync.RWMutex
- matches map[int]*matchinstance
- TaxRate int
- Timeout_Play int64
- Timeout_Free int64
- Timeout_End int64
- MatchConfigs []*matchconfig
- }
- var mgr *matchmanager
- func getMatchManager() *matchmanager {
- if mgr == nil {
- mgr = new(matchmanager)
- mgr.ctor()
- }
- return mgr
- }
- func (mm *matchmanager) ctor() {
- log.Debug("pointmatch.matchmanager.ctor")
- }
- func (mm *matchmanager) run() {
- mm.lock = &sync.RWMutex{}
- mm.matches = make(map[int]*matchinstance)
- mm.loadConfig()
- log.Release("pointmatchmanager.run taxRate = %d", mm.TaxRate)
- go mm.checkTimeout()
- go privateroom.RegisterServerStatus(mm, mm, micro_common.GetServicePort(), "pointmatch")
- }
- func (mm *matchmanager) loadConfig() {
- defer func() {
- time.AfterFunc(refresh_config_sec*time.Second, mm.loadConfig)
- }()
- configString := platformconfig.GetConfig(config_key)
- if configString == "" {
- data, err := os.ReadFile("serviceconf/pointmatch.json")
- if err != nil {
- log.Release("pointmatch.pointmatchmanager.loadData read json failed")
- return
- }
- configString = string(data)
- platformconfig.SetConfig(config_key, configString)
- }
- err := json.Unmarshal([]byte(configString), mm)
- if err != nil {
- log.Release("pointmatch.simplamatchmanager.loadData Unmarshal failed err:%v", err)
- return
- }
- //log.Release("matchmanager.loadConfig ok %v", mm.MatchConfigs)
- if mm.Timeout_Free == 0 {
- mm.Timeout_Free = match_timeout_not_playing
- }
- if mm.Timeout_Play == 0 {
- mm.Timeout_Play = match_timeout_started
- }
- if mm.Timeout_End == 0 {
- mm.Timeout_End = match_timeout_ended
- }
- }
- func (mm *matchmanager) checkTimeout() {
- time.AfterFunc(30*time.Second, mm.checkTimeout)
- var toRemove []int
- mm.lock.RLock()
- for _, v := range mm.matches {
- if v.isTimeout(mm.Timeout_Free, mm.Timeout_Play, mm.Timeout_End) {
- toRemove = append(toRemove, v.MatchNo)
- }
- }
- mm.lock.RUnlock()
- if len(toRemove) <= 0 {
- return
- }
- log.Debug("pointmatchmanager.checkTimeout removing matches %v", toRemove)
- for _, v := range toRemove {
- mm.closeMatch(v, "timeout")
- mm.lock.Lock()
- delete(mm.matches, v)
- mm.lock.Unlock()
- }
- }
- func (mm *matchmanager) getMatchNumber() int {
- return matchbase.GetMatchNo()
- }
- func (mm *matchmanager) getMatch(matchNo int) *matchinstance {
- mm.lock.RLock()
- mi, ok := mm.matches[matchNo]
- mm.lock.RUnlock()
- if !ok {
- return nil
- }
- return mi
- }
- func (mm *matchmanager) getMatchInfo(matchNo int) string {
- mi := mm.getMatch(matchNo)
- if mi == nil {
- return ""
- }
- mi.resetSecToShrink()
- d, _ := json.Marshal(mi)
- return string(d)
- }
- func (mm *matchmanager) closeMatchByOwner(userId int, matchNo int) (bool, string) {
- mi := mm.getMatch(matchNo)
- if mi == nil {
- log.Release("matchmanager.closeMatch failed matchNo[%d] not exist", matchNo)
- return false, "Invalid MatchNo"
- }
- ok, errMsg := mi.closeByOwner(userId)
- return ok, errMsg
- }
- func (mm *matchmanager) closeMatch(matchNo int, reason string) (bool, string) {
- mi := mm.getMatch(matchNo)
- if mi == nil {
- log.Release("matchmanager.closeMatch failed matchNo[%d] not exist", matchNo)
- return false, "Invalid MatchNo"
- }
- mi.closeMatch(reason)
- return true, "ok"
- }
- func (mm *matchmanager) createMatch(userId int, gameId int, gameRule string, totalUserCount int,
- tableUserCount int, enrollFee int, prize int, playTimeout int,
- eliminateScore, shrinkSec, shrinkScore, winnerCount int) (matchNo int, errMsg string) {
- matchNo = 0
- errMsg = "ok"
- // 自己校验
- mc := mm.getGameRule(gameId)
- if mc == nil {
- log.Release("matchmanager.createMatch gameId[%d] not config match", gameId)
- errMsg = "Invalid GameId"
- return
- }
- if !mc.isValidParams(gameRule, totalUserCount, tableUserCount, playTimeout, eliminateScore, shrinkSec, shrinkScore, winnerCount) {
- errMsg = "Invalid GameRule"
- return
- }
- // 扣钱,userId == -1 表示系统创建
- if prize > 0 && userId > 0 && !cash.ReduceMoney(userId, prize, common.LOGTYPE_POINTMATCH_CREATE, "pointmatch", "create", "") {
- errMsg = fmt.Sprintf("not enough cash for create match prize[%d]", prize)
- log.Release("createMatch failed %s", errMsg)
- return
- }
- matchNo = mm.getMatchNumber()
- mi := newMatchInstance(matchNo, userId, gameId, gameRule, totalUserCount, tableUserCount, enrollFee, prize, playTimeout, mc,
- eliminateScore, shrinkSec, shrinkScore, winnerCount)
- mm.lock.Lock()
- mm.matches[matchNo] = mi
- mm.lock.Unlock()
- return
- }
- func (mm *matchmanager) enrollMatch(userId int, nickname string, faceId int, faceUrl string, matchNo int) (bool, string) {
- mi := mm.getMatch(matchNo)
- if mi == nil {
- log.Release("matchmanager.enrollMatch user[%d] matchNo[%d] not exist", userId, matchNo)
- return false, fmt.Sprintf("MatchNo[%d] not found", matchNo)
- }
- ok, err := mi.addUser(userId, nickname, faceId, faceUrl)
- if ok {
- postUserEnterNotification(userId, matchNo, nickname, faceId, faceUrl)
- return ok, err
- }
- return ok, err
- }
- func (mm *matchmanager) quitMatch(userId int, matchNo int) bool {
- mi := mm.getMatch(matchNo)
- if mi == nil {
- log.Release("matchmanager.quitMatch user[%d] matchNo[%d] not exist", userId, matchNo)
- return false
- }
- if mi.removeUser(userId) {
- postUserExitNotification(userId, matchNo)
- return true
- }
- return false
- }
- func (mm *matchmanager) getUserMatches(userId int) string {
- var ret []matchinstance
- mm.lock.RLock()
- for _, v := range mm.matches {
- if v.Owner == userId {
- ret = append(ret, *v)
- }
- }
- mm.lock.RUnlock()
- d, _ := json.Marshal(ret)
- return string(d)
- }
- func (mm *matchmanager) dump(param1, param2 string) {
- log.Release("-------------------------------")
- log.Release("pointmatch.matchmanager.dump[%s,%s]", param1, param2)
- defer func() {
- log.Release("+++++++++++++++++++++++++++++++")
- log.Release("")
- }()
- if param1 == "rules" {
- for _, v := range mm.MatchConfigs {
- v.dump()
- }
- return
- }
- if param1 == "" {
- mm.lock.RLock()
- for _, v := range mm.matches {
- v.dump()
- }
- mm.lock.RUnlock()
- return
- }
- matchNo, err := strconv.Atoi(param1)
- if err != nil {
- log.Release(" atoi error %v", err)
- return
- }
- match := mm.getMatch(matchNo)
- if match == nil {
- log.Release(" match[%d] not exist", matchNo)
- return
- }
- match.dump()
- }
- func (mm *matchmanager) OnGameRuleRegistered(gameId int, gameRule string, desc string, targetOptions []int, userOptions []int, playTimeOptions []int) {
- for _, v := range mm.MatchConfigs {
- if v.GameId == gameId {
- v.addGameRule(gameRule, desc, targetOptions, userOptions, playTimeOptions)
- }
- }
- }
- func (mm *matchmanager) OnGameRuleDeregistered(gameId int, gameRule string) {
- log.Debug("matchmanager.OnGameRuleDeregistered gameId[%d] gameRule[%s]", gameId, gameRule)
- }
- func (mm *matchmanager) getGameRule(gameId int) *matchconfig {
- for _, v := range mm.MatchConfigs {
- if v.GameId == gameId {
- return v
- }
- }
- return nil
- }
- func (mm *matchmanager) getMatchConfigs() string {
- d, _ := json.Marshal(mm.MatchConfigs)
- return string(d)
- }
- func (mm *matchmanager) getEnrolledMatch(userId int) string {
- var matches []int
- mm.lock.RLock()
- for _, v := range mm.matches {
- if v.getUser(userId) != nil {
- matches = append(matches, v.MatchNo)
- }
- }
- mm.lock.RUnlock()
- d, _ := json.Marshal(matches)
- return string(d)
- }
- func (mm *matchmanager) getMatchInstance(matchNo int) matchbase.MatchInstance {
- ret := mm.getMatch(matchNo)
- if ret == nil {
- log.Debug("pointmatch.matchmanager.getMatchInstance [%d] is nil", matchNo)
- return nil
- }
- return ret
- }
- func (mm *matchmanager) dismissMatch(matchNo int) {
- mi := mm.getMatch(matchNo)
- if mi == nil {
- log.Release("matchmanager.dismissMatch failed matchNo[%d] not exist", matchNo)
- return
- }
- mi.dismiss()
- }
- func (mm *matchmanager) OnRoomStart(roomNo int) {
- //log.Debug("pointmatchmanager.OnRoomStart %d", roomNo)
- mm.lock.RLock()
- for _, v := range mm.matches {
- go func(m *matchinstance) {
- m.OnRoomStart(roomNo)
- }(v)
- }
- mm.lock.RUnlock()
- }
- func (mm *matchmanager) OnRoomEnd(roomNo int, winners []int) {
- //log.Debug("pointmatchmanager.OnRoomEnd %d winners%v", roomNo, winners)
- mm.lock.RLock()
- for _, v := range mm.matches {
- go func(m *matchinstance) {
- m.OnRoomEnd(roomNo, winners)
- }(v)
- }
- mm.lock.RUnlock()
- }
- func (mm *matchmanager) OnRoomUserScoreChanged(roomNo int, userId int, score int) {
- //log.Debug("pointmatchmanager.OnRoomUserScoreChanged %d UserId[%d] score[%d]", roomNo, userId, score)
- mm.lock.RLock()
- for _, v := range mm.matches {
- go func(m *matchinstance) {
- m.OnRoomUserScoreChanged(roomNo, userId, score)
- }(v)
- }
- mm.lock.RUnlock()
- }
- func (mm *matchmanager) OnRoomStatusChanged(roomNo int, old, new int) {
- //log.Debug("pointmatchmanager.OnRoomStatusChanged %d %d->%d", roomNo, old, new)
- mm.lock.RLock()
- for _, v := range mm.matches {
- go func(m *matchinstance) {
- m.OnRoomStatusChanged(roomNo, old, new)
- }(v)
- }
- mm.lock.RUnlock()
- }
|