wait.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. package qznn
  2. import (
  3. "errors"
  4. "fmt"
  5. "math/rand"
  6. "runtime/debug"
  7. "time"
  8. "github.com/shopspring/decimal"
  9. "github.com/sirupsen/logrus"
  10. "gogs.daxia.dev/huanan/pkg.daxia.dev/db"
  11. "gorm.io/gorm"
  12. "nn.daxia.dev/gameproto"
  13. "nn.daxia.dev/model"
  14. "nn.daxia.dev/nxd"
  15. )
  16. func (p *Game) WaitReady(room Room) error {
  17. select {
  18. case <-room.ReadyCh:
  19. //
  20. case <-time.After(5 * time.Second):
  21. //
  22. }
  23. return nil
  24. }
  25. func (p *Game) WaitChooseMaster(room Room) error {
  26. select {
  27. case <-room.ChooseMasterCh:
  28. //
  29. case <-time.After(7 * time.Second):
  30. //
  31. }
  32. p.locker.Lock()
  33. defer p.locker.Unlock()
  34. roomUserIDList, err := p.getRoomUserIDList(room.ID)
  35. if err != nil {
  36. logrus.Error(err)
  37. return err
  38. }
  39. //设置状态
  40. userIDList, err := p.getRoomUserIDListWithStatus(room.ID, PlayerStatusReady)
  41. if err != nil {
  42. logrus.Error(err)
  43. return err
  44. }
  45. for _, userID := range userIDList {
  46. userItem := p.PlayerMap[userID]
  47. userItem.Status = PlayerStatusChooseMaster
  48. userItem.MasterMul = 0
  49. p.PlayerMap[userID] = userItem
  50. p.EventInfo(userID, "选庄", "通知默认不抢")
  51. nxd.SendMsgToUserList(roomUserIDList, gameproto.NotifyTypeEnum_NotifyTypeChooseMaster, &gameproto.ChooseMaster{
  52. UserID: uint32(userID),
  53. Mul: uint32(0),
  54. RoomID: uint32(room.ID),
  55. })
  56. }
  57. //获取修正后的状态用户
  58. userIDList, err = p.getRoomUserIDListWithStatus(room.ID, PlayerStatusChooseMaster)
  59. if err != nil {
  60. logrus.Error(err)
  61. return err
  62. }
  63. maxMasterMul := 0
  64. for _, userID := range userIDList {
  65. userItem := p.PlayerMap[userID]
  66. if userItem.MasterMul > maxMasterMul {
  67. maxMasterMul = userItem.MasterMul
  68. }
  69. }
  70. masterIDList := make([]int32, 0)
  71. for _, userID := range userIDList {
  72. userItem := p.PlayerMap[userID]
  73. if userItem.MasterMul != maxMasterMul {
  74. continue
  75. }
  76. masterIDList = append(masterIDList, userID)
  77. }
  78. //更新用户,选取庄家
  79. index := rand.Intn(len(masterIDList))
  80. masterUserID := masterIDList[index]
  81. p.EventInfo(masterUserID, "选庄", "选为庄家")
  82. userItem := p.PlayerMap[masterUserID]
  83. userItem.IsMaster = true
  84. if userItem.MasterMul == 0 {
  85. userItem.MasterMul = 1
  86. }
  87. p.PlayerMap[masterUserID] = userItem
  88. //更新
  89. err = db.GetDB().Model(model.GameOrder{}).Where("user_id = ? and issue = ?", masterUserID, room.Issue).Update("is_master", 1).Error
  90. if err != nil {
  91. logrus.Error(err)
  92. return err
  93. }
  94. //通知
  95. nxd.SendMsgToUserList(roomUserIDList, gameproto.NotifyTypeEnum_NotifyTypeChooseMasterFinish, &gameproto.ChooseMasterFinish{
  96. MasterUserID: uint32(masterUserID),
  97. MulList: []uint32{1, 4, 8, 11, 15},
  98. RoomID: uint32(room.ID),
  99. })
  100. return nil
  101. }
  102. func (p *Game) WaitChooseMul(room Room) error {
  103. p.locker.Lock()
  104. {
  105. room.Status = RoomStatusChooseMul
  106. room.StatusStartTime = time.Now().Unix()
  107. p.RoomMap[room.ID] = room
  108. }
  109. //master直接发送,跳过开牌流程
  110. userIDList, err := p.getRoomUserIDListWithStatus(room.ID, PlayerStatusChooseMaster)
  111. if err != nil {
  112. logrus.Error(err)
  113. //FOCUS:UnLock
  114. p.locker.Unlock()
  115. return err
  116. }
  117. roomUserIDList, err := p.getRoomUserIDList(room.ID)
  118. if err != nil {
  119. logrus.Error(err)
  120. //FOCUS:UnLock
  121. p.locker.Unlock()
  122. return err
  123. }
  124. //master提前发送
  125. for _, userID := range userIDList {
  126. userItem, exists := p.PlayerMap[userID]
  127. if !exists {
  128. logrus.Error("not exist:", userID)
  129. continue
  130. }
  131. if !userItem.IsMaster {
  132. continue
  133. }
  134. userItem.Status = PlayerStatusChooseMul
  135. userItem.Mul = 1
  136. p.PlayerMap[userID] = userItem
  137. p.EventInfo(userID, "选倍数", "庄家默认倍数1")
  138. nxd.SendMsgToUserK(uint32(userID), gameproto.NotifyTypeEnum_NotifyTypeChooseMul, &gameproto.ChooseMul{
  139. UserID: uint32(userID),
  140. Mul: uint32(1),
  141. RoomID: uint32(room.ID),
  142. CardList: GetNNCardList(userItem.CardList),
  143. })
  144. break
  145. }
  146. p.locker.Unlock()
  147. logrus.Infof("等待选择倍数")
  148. select {
  149. case <-room.ChooseMulCh:
  150. //
  151. case <-time.After(7 * time.Second):
  152. //
  153. }
  154. p.locker.Lock()
  155. defer p.locker.Unlock()
  156. logrus.Infof("未选取的用户,开始自动选取")
  157. for _, userID := range userIDList {
  158. userItem, exists := p.PlayerMap[userID]
  159. if !exists {
  160. logrus.Error("not exist:", userID)
  161. continue
  162. }
  163. if userItem.Status != PlayerStatusChooseMaster {
  164. continue
  165. }
  166. userItem.Status = PlayerStatusChooseMul
  167. userItem.Mul = 1
  168. p.PlayerMap[userID] = userItem
  169. p.EventInfo(userID, "选倍数", "默认倍数1")
  170. //通知
  171. for _, sendToUserID := range roomUserIDList {
  172. var cardList []uint32
  173. if userID == sendToUserID {
  174. cardList = GetNNCardList(userItem.CardList)
  175. }
  176. nxd.SendMsgToUserK(uint32(sendToUserID), gameproto.NotifyTypeEnum_NotifyTypeChooseMul, &gameproto.ChooseMul{
  177. UserID: uint32(userID),
  178. Mul: uint32(1),
  179. RoomID: uint32(room.ID),
  180. CardList: cardList,
  181. })
  182. }
  183. }
  184. logrus.Infof("通知选择倍数完成, 用户数:%d", len(roomUserIDList))
  185. //通知
  186. nxd.SendMsgToUserList(roomUserIDList, gameproto.NotifyTypeEnum_NotifyTypeChooseMulFinish, &gameproto.ChooseMulFinish{
  187. RoomID: uint32(room.ID),
  188. })
  189. return nil
  190. }
  191. func (p *Game) WaitOpen(room Room) error {
  192. p.locker.Lock()
  193. {
  194. room.Status = RoomStatusOpen
  195. room.StatusStartTime = time.Now().Unix()
  196. p.RoomMap[room.ID] = room
  197. }
  198. p.locker.Unlock()
  199. select {
  200. case <-room.OpenCh:
  201. //
  202. case <-time.After(15 * time.Second):
  203. //
  204. }
  205. p.locker.Lock()
  206. defer p.locker.Unlock()
  207. roomUserIDList, err := p.getRoomUserIDList(room.ID)
  208. if err != nil {
  209. logrus.Error(err)
  210. return err
  211. }
  212. userIDList, err := p.getRoomUserIDListWithStatus(room.ID, PlayerStatusChooseMul)
  213. if err != nil {
  214. logrus.Error(err)
  215. return err
  216. }
  217. for _, userID := range userIDList {
  218. userItem, exists := p.PlayerMap[userID]
  219. if !exists {
  220. logrus.Error("not exist:", userID)
  221. continue
  222. }
  223. userItem.Status = PlayerStatusOpen
  224. p.PlayerMap[userID] = userItem
  225. p.EventInfo(userID, "开牌", "默认开牌")
  226. //通知
  227. nxd.SendMsgToUserList(roomUserIDList, gameproto.NotifyTypeEnum_NotifyTypeOpen, &gameproto.Open{
  228. RoomID: uint32(room.ID),
  229. UserID: uint32(userID),
  230. CardList: GetNNCardList(userItem.CardList),
  231. })
  232. }
  233. userIDList, err = p.getRoomUserIDListWithStatus(room.ID, PlayerStatusOpen)
  234. if err != nil {
  235. logrus.Error(err)
  236. return err
  237. }
  238. //获取庄家的牌
  239. var masterPlayerItem Player
  240. for _, userID := range userIDList {
  241. playerItem := p.PlayerMap[userID]
  242. if !playerItem.IsMaster {
  243. continue
  244. }
  245. masterPlayerItem = playerItem
  246. break
  247. }
  248. masterCardList := GetNNCardList(masterPlayerItem.CardList)
  249. masterTotalWinAmount := decimal.NewFromInt(0)
  250. timeNow := time.Now()
  251. msg := &gameproto.OpenFinish{
  252. RoomID: uint32(room.ID),
  253. PayoutInfoList: []*gameproto.PayoutInfo{},
  254. }
  255. err = db.GetDB().Transaction(func(tx *gorm.DB) error {
  256. defer func() {
  257. if err := recover(); err != nil {
  258. logrus.Error(err)
  259. fmt.Println("stacktrace from panic: \n" + string(debug.Stack()))
  260. }
  261. }()
  262. for _, userID := range userIDList {
  263. if userID == masterPlayerItem.ID {
  264. continue
  265. }
  266. userItem, exists := p.PlayerMap[userID]
  267. if !exists {
  268. logrus.Error("not exist:", userID)
  269. continue
  270. }
  271. var isWin bool
  272. var winAmount decimal.Decimal
  273. userCardList := GetNNCardList(userItem.CardList)
  274. masterWin, isEqual, cardLevel := WinLevel(masterCardList, userCardList)
  275. if cardLevel == 0 {
  276. cardLevel = 1
  277. }
  278. if !masterWin {
  279. isWin = true
  280. //赢庄家
  281. winAmount = room.BaseAmount.Mul(decimal.NewFromInt(int64(masterPlayerItem.MasterMul))).Mul(decimal.NewFromInt(int64(userItem.Mul))).Mul(decimal.NewFromInt(int64(cardLevel)))
  282. } else {
  283. isWin = false
  284. //输给庄家
  285. winAmount = room.BaseAmount.Mul(decimal.NewFromInt(int64(masterPlayerItem.MasterMul))).Mul(decimal.NewFromInt(int64(userItem.Mul))).Mul(decimal.NewFromInt(-1)).Mul(decimal.NewFromInt(int64(cardLevel)))
  286. }
  287. if isEqual {
  288. isWin = false
  289. winAmount = decimal.NewFromInt(0)
  290. }
  291. err = tx.Model(model.User{}).Where("id = ? and balance + ? > 0", userID, winAmount).
  292. Update("balance", gorm.Expr("balance + ?", winAmount)).Error
  293. if err != nil {
  294. return err
  295. }
  296. //设置注单
  297. err = tx.Model(model.GameOrder{}).Where("issue = ? and user_id = ?", room.Issue, userID).Updates(map[string]interface{}{
  298. "is_draw": 1,
  299. "draw_time": &timeNow,
  300. "is_win": isWin,
  301. "win_amount": winAmount,
  302. }).Error
  303. if err != nil {
  304. return err
  305. }
  306. currUserModel := model.User{}
  307. err = tx.Model(model.User{}).Where("id = ?", userID).First(&currUserModel).Error
  308. if err != nil {
  309. return err
  310. }
  311. userItem.Balance = currUserModel.Balance
  312. p.PlayerMap[userID] = userItem
  313. //设置结算信息
  314. userBalance, _ := userItem.Balance.Round(2).Float64()
  315. msg.PayoutInfoList = append(msg.PayoutInfoList, &gameproto.PayoutInfo{
  316. UserID: uint32(userID),
  317. WinAmount: float32(winAmount.Mul(decimal.NewFromInt(100)).IntPart()) / 100,
  318. IsMaster: false,
  319. Balance: userBalance,
  320. })
  321. masterTotalWinAmount = masterTotalWinAmount.Add(winAmount.Mul(decimal.NewFromInt(-1)))
  322. }
  323. err = tx.Model(model.User{}).Where("id = ? and balance + ? > 0", masterPlayerItem.ID, masterTotalWinAmount).
  324. Update("balance", gorm.Expr("balance + ?", masterTotalWinAmount)).Error
  325. if err != nil {
  326. logrus.Error(err)
  327. return err
  328. }
  329. err = tx.Model(model.GameOrder{}).Where("issue = ? and user_id = ?", room.Issue, masterPlayerItem.ID).Updates(map[string]interface{}{
  330. "is_draw": 1,
  331. "draw_time": &timeNow,
  332. "is_win": masterTotalWinAmount.GreaterThan(decimal.Zero),
  333. "win_amount": masterTotalWinAmount,
  334. }).Error
  335. //设置master结算信息,更新余额
  336. currUserModel := model.User{}
  337. err = tx.Model(model.User{}).Where("id = ?", masterPlayerItem.ID).First(&currUserModel).Error
  338. if err != nil {
  339. logrus.Error(err)
  340. return err
  341. }
  342. masterPlayerItem.Balance = currUserModel.Balance
  343. p.PlayerMap[masterPlayerItem.ID] = masterPlayerItem
  344. masterBalance, _ := masterPlayerItem.Balance.Round(2).Float64()
  345. msg.PayoutInfoList = append(msg.PayoutInfoList, &gameproto.PayoutInfo{
  346. UserID: uint32(masterPlayerItem.ID),
  347. WinAmount: float32(masterTotalWinAmount.Mul(decimal.NewFromInt(100)).IntPart()) / 100,
  348. IsMaster: true,
  349. Balance: masterBalance,
  350. })
  351. return nil
  352. })
  353. if err != nil {
  354. logrus.Error(err, "===============")
  355. return err
  356. }
  357. //更新一下用户信息
  358. userModelList := make([]model.User, 0)
  359. err = db.GetDB().Model(model.User{}).Where("id in ?", roomUserIDList).Scan(&userModelList).Error
  360. if err != nil {
  361. logrus.Error(err)
  362. return err
  363. }
  364. for _, userModel := range userModelList {
  365. userID := int32(userModel.ID)
  366. userItem := p.PlayerMap[userID]
  367. userItem.Balance = userModel.Balance
  368. userItem.HeadImg = userModel.HeadImg
  369. userItem.Name = userModel.Name
  370. userItem.IsMaster = false
  371. userItem.Status = PlayerStatusWaitReady
  372. p.EventInfo(userID, "开牌", "更新用户状态为等待开牌")
  373. p.PlayerMap[userID] = userItem
  374. }
  375. room.Status = RoomStatusWaitReady
  376. room.StatusStartTime = time.Now().Unix()
  377. p.RoomMap[room.ID] = room
  378. //通知
  379. roomUserIDList, err = p.getRoomUserIDList(room.ID)
  380. if err != nil {
  381. logrus.Error(err)
  382. return err
  383. }
  384. nxd.SendMsgToUserList(roomUserIDList, gameproto.NotifyTypeEnum_NotifyTypeOpenFinish, msg)
  385. return nil
  386. }
  387. func (p *Game) getRoomUserIDListWithStatus(roomID int32, status PlayerStatus) ([]int32, error) {
  388. roomItem, exists := p.RoomMap[roomID]
  389. if !exists {
  390. return nil, errors.New("room not exists")
  391. }
  392. userIDList := make([]int32, 0)
  393. for _, chairItem := range roomItem.ChairList {
  394. if chairItem.PlayerID == 0 {
  395. continue
  396. }
  397. playerItem, exists := p.PlayerMap[chairItem.PlayerID]
  398. if !exists {
  399. continue
  400. }
  401. if playerItem.Status != status {
  402. continue
  403. }
  404. userIDList = append(userIDList, chairItem.PlayerID)
  405. }
  406. return userIDList, nil
  407. }
  408. func (p *Game) getRoomUserIDList(roomID int32) ([]int32, error) {
  409. roomItem, exists := p.RoomMap[roomID]
  410. if !exists {
  411. return nil, errors.New("room not exists")
  412. }
  413. userIDList := make([]int32, 0)
  414. for _, chairItem := range roomItem.ChairList {
  415. if chairItem.PlayerID == 0 {
  416. continue
  417. }
  418. userIDList = append(userIDList, chairItem.PlayerID)
  419. }
  420. return userIDList, nil
  421. }