123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569 |
- package qznn
- import (
- "errors"
- "fmt"
- "math/rand"
- "runtime/debug"
- "time"
- "github.com/shopspring/decimal"
- "github.com/sirupsen/logrus"
- "gogs.daxia.dev/huanan/pkg.daxia.dev/db"
- "gorm.io/gorm"
- "nn.daxia.dev/gameproto"
- "nn.daxia.dev/model"
- "nn.daxia.dev/nxd"
- )
- func (p *Game) WaitReady(room Room) error {
- select {
- case <-room.ReadyCh:
- //
- case <-time.After(5 * time.Second):
- //
- }
- return nil
- }
- func (p *Game) WaitChooseMaster(room Room) error {
- select {
- case <-room.ChooseMasterCh:
- //
- case <-time.After(7 * time.Second):
- //
- }
- p.locker.Lock()
- defer p.locker.Unlock()
- roomUserIDList, err := p.getRoomUserIDList(room.ID)
- if err != nil {
- logrus.Error(err)
- return err
- }
- //设置状态
- userIDList, err := p.getRoomUserIDListWithStatus(room.ID, PlayerStatusReady)
- if err != nil {
- logrus.Error(err)
- return err
- }
- for _, userID := range userIDList {
- userItem := p.PlayerMap[userID]
- userItem.Status = PlayerStatusChooseMaster
- userItem.MasterMul = 0
- p.PlayerMap[userID] = userItem
- p.EventInfo(userID, "选庄", "通知默认不抢")
- nxd.SendMsgToUserList(roomUserIDList, gameproto.NotifyTypeEnum_NotifyTypeChooseMaster, &gameproto.ChooseMaster{
- UserID: uint32(userID),
- Mul: uint32(0),
- RoomID: uint32(room.ID),
- })
- }
- //获取修正后的状态用户
- userIDList, err = p.getRoomUserIDListWithStatus(room.ID, PlayerStatusChooseMaster)
- if err != nil {
- logrus.Error(err)
- return err
- }
- maxMasterMul := 0
- for _, userID := range userIDList {
- userItem := p.PlayerMap[userID]
- if userItem.MasterMul > maxMasterMul {
- maxMasterMul = userItem.MasterMul
- }
- }
- masterIDList := make([]int32, 0)
- for _, userID := range userIDList {
- userItem := p.PlayerMap[userID]
- if userItem.MasterMul != maxMasterMul {
- continue
- }
- masterIDList = append(masterIDList, userID)
- }
- //更新用户,选取庄家
- index := rand.Intn(len(masterIDList))
- masterUserID := masterIDList[index]
- p.EventInfo(masterUserID, "选庄", "选为庄家")
- userItem := p.PlayerMap[masterUserID]
- userItem.IsMaster = true
- if userItem.MasterMul == 0 {
- userItem.MasterMul = 1
- }
- p.PlayerMap[masterUserID] = userItem
- //更新
- err = db.GetDB().Model(model.GameOrder{}).Where("user_id = ? and issue = ?", masterUserID, room.Issue).Update("is_master", 1).Error
- if err != nil {
- logrus.Error(err)
- return err
- }
- //通知
- nxd.SendMsgToUserList(roomUserIDList, gameproto.NotifyTypeEnum_NotifyTypeChooseMasterFinish, &gameproto.ChooseMasterFinish{
- MasterUserID: uint32(masterUserID),
- MulList: []uint32{1, 4, 8, 11, 15},
- RoomID: uint32(room.ID),
- })
- return nil
- }
- func (p *Game) WaitChooseMul(room Room) error {
- p.locker.Lock()
- {
- room.Status = RoomStatusChooseMul
- room.StatusStartTime = time.Now().Unix()
- p.RoomMap[room.ID] = room
- }
- //master直接发送,跳过开牌流程
- userIDList, err := p.getRoomUserIDListWithStatus(room.ID, PlayerStatusChooseMaster)
- if err != nil {
- logrus.Error(err)
- //FOCUS:UnLock
- p.locker.Unlock()
- return err
- }
- //master提前发送
- for _, userID := range userIDList {
- userItem, exists := p.PlayerMap[userID]
- if !exists {
- logrus.Error("not exist:", userID)
- continue
- }
- if !userItem.IsMaster {
- continue
- }
- userItem.Status = PlayerStatusChooseMul
- userItem.Mul = 1
- p.PlayerMap[userID] = userItem
- p.EventInfo(userID, "选倍数", "庄家默认倍数1")
- nxd.SendMsgToUserK(uint32(userID), gameproto.NotifyTypeEnum_NotifyTypeChooseMul, &gameproto.ChooseMul{
- UserID: uint32(userID),
- Mul: uint32(1),
- RoomID: uint32(room.ID),
- CardList: GetNNCardList(userItem.CardList),
- })
- break
- }
- p.locker.Unlock()
- logrus.Infof("等待选择倍数")
- select {
- case <-room.ChooseMulCh:
- //
- case <-time.After(7 * time.Second):
- //
- }
- p.locker.Lock()
- defer p.locker.Unlock()
- roomUserIDList, err := p.getRoomUserIDList(room.ID)
- if err != nil {
- logrus.Error(err)
- return err
- }
- logrus.Infof("未选取的用户,开始自动选取")
- for _, userID := range roomUserIDList {
- userItem, exists := p.PlayerMap[userID]
- if !exists {
- logrus.Error("not exist:", userID)
- continue
- }
- if userItem.Status != PlayerStatusChooseMaster {
- continue
- }
- userItem.Status = PlayerStatusChooseMul
- userItem.Mul = 1
- p.PlayerMap[userID] = userItem
- p.EventInfo(userID, "选倍数", "默认倍数1")
- //通知
- for _, sendToUserID := range roomUserIDList {
- var cardList []uint32
- if userID == sendToUserID {
- cardList = GetNNCardList(userItem.CardList)
- }
- nxd.SendMsgToUserK(uint32(sendToUserID), gameproto.NotifyTypeEnum_NotifyTypeChooseMul, &gameproto.ChooseMul{
- UserID: uint32(userID),
- Mul: uint32(1),
- RoomID: uint32(room.ID),
- CardList: cardList,
- })
- }
- }
- logrus.Infof("通知选择倍数完成, 用户数:%d", len(roomUserIDList))
- //通知
- nxd.SendMsgToUserList(roomUserIDList, gameproto.NotifyTypeEnum_NotifyTypeChooseMulFinish, &gameproto.ChooseMulFinish{
- RoomID: uint32(room.ID),
- })
- return nil
- }
- func (p *Game) WaitOpen(room Room) error {
- p.locker.Lock()
- {
- room.Status = RoomStatusOpen
- room.StatusStartTime = time.Now().Unix()
- p.RoomMap[room.ID] = room
- }
- p.locker.Unlock()
- select {
- case <-room.OpenCh:
- //
- case <-time.After(15 * time.Second):
- //
- }
- p.locker.Lock()
- defer func() {
- {
- userIDList, _ := p.getRoomUserIDList(room.ID)
- for _, userID := range userIDList {
- playerItem, exists := p.PlayerMap[userID]
- if !exists {
- continue
- }
- p.EventInfo(userID, "Run", fmt.Sprintf("执行完毕,状态:%d", playerItem.Status))
- if playerItem.Status != PlayerStatusWaitReady {
- logrus.Panicf("完成,但状态不对:%d-%d", userID, playerItem.Status)
- }
- }
- for _, userID := range userIDList {
- if UserIsOnline(uint(userID)) {
- continue
- }
- p.EventInfo(userID, "Run", "玩家离线,踢走")
- p.Leave(userID, false)
- }
- }
- p.locker.Unlock()
- }()
- roomUserIDList, err := p.getRoomUserIDList(room.ID)
- if err != nil {
- logrus.Error(err)
- return err
- }
- userIDList, err := p.getRoomUserIDListWithStatus(room.ID, PlayerStatusChooseMul)
- if err != nil {
- logrus.Error(err)
- return err
- }
- for _, userID := range userIDList {
- userItem, exists := p.PlayerMap[userID]
- if !exists {
- logrus.Error("not exist:", userID)
- continue
- }
- userItem.Status = PlayerStatusOpen
- p.PlayerMap[userID] = userItem
- p.EventInfo(userID, "开牌", "默认开牌")
- //通知
- nxd.SendMsgToUserList(roomUserIDList, gameproto.NotifyTypeEnum_NotifyTypeOpen, &gameproto.Open{
- RoomID: uint32(room.ID),
- UserID: uint32(userID),
- CardList: GetNNCardList(userItem.CardList),
- })
- }
- timeNow := time.Now()
- msg := &gameproto.OpenFinish{
- RoomID: uint32(room.ID),
- PayoutInfoList: []*gameproto.PayoutInfo{},
- }
- err = db.GetDB().Transaction(func(tx *gorm.DB) error {
- defer func() {
- if err := recover(); err != nil {
- logrus.Error(err)
- fmt.Println("stacktrace from panic: \n" + string(debug.Stack()))
- }
- }()
- payoutInfoList, err := p.payout(tx, room.BaseAmount, room.ID)
- if err != nil {
- return err
- }
- for _, payoutInfo := range payoutInfoList {
- userID := payoutInfo.PlayerID
- winAmount := payoutInfo.Amount
- userItem, exists := p.PlayerMap[userID]
- if !exists {
- logrus.Fatal("not exist:", userID)
- continue
- }
- beforeUserModel := model.User{}
- err := tx.Model(model.User{}).Where("id = ?", userID).First(&beforeUserModel).Error
- if err != nil {
- return err
- }
- if room.RoomType == int32(model.RoomTypeFree) {
- err = tx.Exec("update users as a, users as b set a.credits_qznn = 0, a.credits = b.credits + b.credits_qznn + ? where a.id = ? and b.id = ? and b.credits_qznn + ? >= 0",
- payoutInfo.Amount, userID, userID, payoutInfo.Amount).Error
- if err != nil {
- logrus.Error(err)
- return err
- }
- afterUserModel := model.User{}
- err = tx.Model(model.User{}).Where("id = ?", userID).First(&afterUserModel).Error
- if err != nil {
- return err
- }
- //设置注单
- err = tx.Model(model.GameOrder{}).Where("issue = ? and user_id = ?", room.Issue, userID).Updates(map[string]interface{}{
- "is_draw": 1,
- "draw_time": &timeNow,
- "is_win": payoutInfo.Amount.GreaterThan(decimal.Zero),
- "win_amount": payoutInfo.Amount,
- "before_amount": beforeUserModel.Credits.Add(beforeUserModel.CreditsQZNN),
- "after_amount": afterUserModel.Credits,
- }).Error
- if err != nil {
- return err
- }
- currUserModel := model.User{}
- err = tx.Model(model.User{}).Where("id = ?", userID).First(&currUserModel).Error
- if err != nil {
- return err
- }
- //这里已经解除冻结
- userItem.Credits = currUserModel.Credits
- p.PlayerMap[userID] = userItem
- //设置结算信息
- userCredist, _ := userItem.Credits.Round(2).Float64()
- msg.PayoutInfoList = append(msg.PayoutInfoList, &gameproto.PayoutInfo{
- UserID: uint32(userID),
- WinAmount: winAmount.StringFixed(2),
- IsMaster: payoutInfo.IsMaster,
- Credits: userCredist,
- })
- } else {
- err = tx.Exec("update users as a, users as b set a.balance_qznn = 0, a.balance = b.balance + b.balance_qznn + ? where a.id = ? and b.id = ? and b.balance_qznn + ? >= 0",
- payoutInfo.Amount, userID, userID, payoutInfo.Amount).Error
- if err != nil {
- logrus.Error(err)
- return err
- }
- afterUserModel := model.User{}
- err = tx.Model(model.User{}).Where("id = ?", userID).First(&afterUserModel).Error
- if err != nil {
- return err
- }
- //设置注单
- err = tx.Model(model.GameOrder{}).Where("issue = ? and user_id = ?", room.Issue, userID).Updates(map[string]interface{}{
- "is_draw": 1,
- "draw_time": &timeNow,
- "is_win": payoutInfo.Amount.GreaterThan(decimal.Zero),
- "win_amount": payoutInfo.Amount,
- "before_amount": beforeUserModel.Balance.Add(beforeUserModel.BalanceQZNN),
- "after_amount": afterUserModel.Balance,
- }).Error
- if err != nil {
- return err
- }
- currUserModel := model.User{}
- err = tx.Model(model.User{}).Where("id = ?", userID).First(&currUserModel).Error
- if err != nil {
- return err
- }
- //已经解除冻结
- userItem.Balance = currUserModel.Balance
- p.PlayerMap[userID] = userItem
- //设置结算信息
- userBalance, _ := userItem.Balance.Round(2).Float64()
- msg.PayoutInfoList = append(msg.PayoutInfoList, &gameproto.PayoutInfo{
- UserID: uint32(userID),
- WinAmount: winAmount.StringFixed(2),
- IsMaster: payoutInfo.IsMaster,
- Balance: userBalance,
- })
- }
- }
- return nil
- })
- if err != nil {
- logrus.Error(err, "===============")
- return err
- }
- roomUserIDList, _ = p.getRoomUserIDList(room.ID)
- //更新一下用户信息
- userModelList := make([]model.User, 0)
- err = db.GetDB().Model(model.User{}).Where("id in ?", roomUserIDList).Scan(&userModelList).Error
- if err != nil {
- logrus.Error(err)
- return err
- }
- if len(roomUserIDList) != len(userModelList) {
- logrus.Panicf("len(roomUserIDList) != len(userModelList), %d != %d, %v, %v",
- len(roomUserIDList), len(userModelList), roomUserIDList, userModelList)
- }
- for _, userID := range roomUserIDList {
- userItem := p.PlayerMap[userID]
- userItem.IsMaster = false
- userItem.Status = PlayerStatusWaitReady
- p.PlayerMap[userID] = userItem
- }
- for _, userModel := range userModelList {
- userID := int32(userModel.ID)
- userItem := p.PlayerMap[userID]
- userItem.Balance = userModel.Balance
- userItem.Credits = userModel.Credits
- userItem.HeadImg = userModel.HeadImg
- userItem.Name = userModel.Name
- userItem.IsMaster = false
- userItem.Status = PlayerStatusWaitReady
- p.EventInfo(userID, "开牌", "更新用户状态为等待开牌")
- p.PlayerMap[userID] = userItem
- }
- //清理新号,免得卡主
- close(room.ReadyCh)
- close(room.ChooseMasterCh)
- close(room.ChooseMulCh)
- close(room.OpenCh)
- room.ReadyCh = make(chan bool)
- room.ChooseMasterCh = make(chan bool)
- room.ChooseMulCh = make(chan bool)
- room.OpenCh = make(chan bool)
- room.Status = RoomStatusWaitReady
- room.StatusStartTime = time.Now().Unix()
- p.RoomMap[room.ID] = room
- //通知
- roomUserIDList, err = p.getRoomUserIDList(room.ID)
- if err != nil {
- logrus.Error(err)
- return err
- }
- nxd.SendMsgToUserList(roomUserIDList, gameproto.NotifyTypeEnum_NotifyTypeOpenFinish, msg)
- //判断是否满足准入,不满足,踢走
- for _, userID := range roomUserIDList {
- userItem := p.PlayerMap[userID]
- if room.RoomType == int32(model.RoomTypeNormal) {
- if userItem.Balance.LessThan(decimal.NewFromInt(10)) {
- p.LeaveRoomInner(userID, false)
- }
- } else {
- p.LeaveRoomInner(userID, false)
- }
- }
- return nil
- }
- func (p *Game) getRoomUserIDListWithStatus(roomID int32, status PlayerStatus) ([]int32, error) {
- roomItem, exists := p.RoomMap[roomID]
- if !exists {
- return nil, errors.New("room not exists")
- }
- userIDList := make([]int32, 0)
- for _, chairItem := range roomItem.ChairList {
- if chairItem.PlayerID == 0 {
- continue
- }
- playerItem, exists := p.PlayerMap[chairItem.PlayerID]
- if !exists {
- continue
- }
- if playerItem.Status != status {
- continue
- }
- userIDList = append(userIDList, chairItem.PlayerID)
- }
- return userIDList, nil
- }
- func (p *Game) getRoomUserIDList(roomID int32) ([]int32, error) {
- roomItem, exists := p.RoomMap[roomID]
- if !exists {
- return nil, errors.New("room not exists")
- }
- userIDList := make([]int32, 0)
- for _, chairItem := range roomItem.ChairList {
- if chairItem.PlayerID == 0 {
- continue
- }
- userIDList = append(userIDList, chairItem.PlayerID)
- }
- return userIDList, nil
- }
|