wait.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  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. roomUserIDList, err = p.getRoomUserIDList(room.ID)
  157. if err != nil {
  158. logrus.Error(err)
  159. return err
  160. }
  161. logrus.Infof("未选取的用户,开始自动选取")
  162. for _, userID := range roomUserIDList {
  163. userItem, exists := p.PlayerMap[userID]
  164. if !exists {
  165. logrus.Error("not exist:", userID)
  166. continue
  167. }
  168. if userItem.Status != PlayerStatusChooseMaster {
  169. continue
  170. }
  171. userItem.Status = PlayerStatusChooseMul
  172. userItem.Mul = 1
  173. p.PlayerMap[userID] = userItem
  174. p.EventInfo(userID, "选倍数", "默认倍数1")
  175. //通知
  176. for _, sendToUserID := range roomUserIDList {
  177. var cardList []uint32
  178. if userID == sendToUserID {
  179. cardList = GetNNCardList(userItem.CardList)
  180. }
  181. nxd.SendMsgToUserK(uint32(sendToUserID), gameproto.NotifyTypeEnum_NotifyTypeChooseMul, &gameproto.ChooseMul{
  182. UserID: uint32(userID),
  183. Mul: uint32(1),
  184. RoomID: uint32(room.ID),
  185. CardList: cardList,
  186. })
  187. }
  188. }
  189. logrus.Infof("通知选择倍数完成, 用户数:%d", len(roomUserIDList))
  190. //通知
  191. nxd.SendMsgToUserList(roomUserIDList, gameproto.NotifyTypeEnum_NotifyTypeChooseMulFinish, &gameproto.ChooseMulFinish{
  192. RoomID: uint32(room.ID),
  193. })
  194. return nil
  195. }
  196. func (p *Game) WaitOpen(room Room) error {
  197. p.locker.Lock()
  198. {
  199. room.Status = RoomStatusOpen
  200. room.StatusStartTime = time.Now().Unix()
  201. p.RoomMap[room.ID] = room
  202. }
  203. p.locker.Unlock()
  204. select {
  205. case <-room.OpenCh:
  206. //
  207. case <-time.After(15 * time.Second):
  208. //
  209. }
  210. p.locker.Lock()
  211. defer p.locker.Unlock()
  212. roomUserIDList, err := p.getRoomUserIDList(room.ID)
  213. if err != nil {
  214. logrus.Error(err)
  215. return err
  216. }
  217. userIDList, err := p.getRoomUserIDListWithStatus(room.ID, PlayerStatusChooseMul)
  218. if err != nil {
  219. logrus.Error(err)
  220. return err
  221. }
  222. for _, userID := range userIDList {
  223. userItem, exists := p.PlayerMap[userID]
  224. if !exists {
  225. logrus.Error("not exist:", userID)
  226. continue
  227. }
  228. userItem.Status = PlayerStatusOpen
  229. p.PlayerMap[userID] = userItem
  230. p.EventInfo(userID, "开牌", "默认开牌")
  231. //通知
  232. nxd.SendMsgToUserList(roomUserIDList, gameproto.NotifyTypeEnum_NotifyTypeOpen, &gameproto.Open{
  233. RoomID: uint32(room.ID),
  234. UserID: uint32(userID),
  235. CardList: GetNNCardList(userItem.CardList),
  236. })
  237. }
  238. userIDList, err = p.getRoomUserIDListWithStatus(room.ID, PlayerStatusOpen)
  239. if err != nil {
  240. logrus.Error(err)
  241. return err
  242. }
  243. //获取庄家的牌
  244. var masterPlayerItem Player
  245. for _, userID := range userIDList {
  246. playerItem := p.PlayerMap[userID]
  247. if !playerItem.IsMaster {
  248. continue
  249. }
  250. masterPlayerItem = playerItem
  251. break
  252. }
  253. masterCardList := GetNNCardList(masterPlayerItem.CardList)
  254. masterTotalWinAmount := decimal.NewFromInt(0)
  255. timeNow := time.Now()
  256. msg := &gameproto.OpenFinish{
  257. RoomID: uint32(room.ID),
  258. PayoutInfoList: []*gameproto.PayoutInfo{},
  259. }
  260. err = db.GetDB().Transaction(func(tx *gorm.DB) error {
  261. defer func() {
  262. if err := recover(); err != nil {
  263. logrus.Error(err)
  264. fmt.Println("stacktrace from panic: \n" + string(debug.Stack()))
  265. }
  266. }()
  267. for _, userID := range userIDList {
  268. if userID == masterPlayerItem.ID {
  269. continue
  270. }
  271. userItem, exists := p.PlayerMap[userID]
  272. if !exists {
  273. logrus.Error("not exist:", userID)
  274. continue
  275. }
  276. var isWin bool
  277. var winAmount decimal.Decimal
  278. userCardList := GetNNCardList(userItem.CardList)
  279. masterWin, isEqual, cardLevel := WinLevel(masterCardList, userCardList)
  280. if !masterWin {
  281. _, _, cardLevel = WinLevel(userCardList, masterCardList)
  282. }
  283. if isEqual {
  284. isWin = false
  285. winAmount = decimal.NewFromInt(0)
  286. } else {
  287. if !masterWin {
  288. isWin = true
  289. //赢庄家
  290. winAmount = room.BaseAmount.Mul(decimal.NewFromInt(int64(masterPlayerItem.MasterMul))).Mul(decimal.NewFromInt(int64(userItem.Mul))).Mul(decimal.NewFromInt(int64(cardLevel)))
  291. } else {
  292. isWin = false
  293. //输给庄家
  294. winAmount = room.BaseAmount.Mul(decimal.NewFromInt(int64(masterPlayerItem.MasterMul))).Mul(decimal.NewFromInt(int64(userItem.Mul))).Mul(decimal.NewFromInt(-1)).Mul(decimal.NewFromInt(int64(cardLevel)))
  295. }
  296. }
  297. err = tx.Model(model.User{}).Where("id = ? and balance + ? > 0", userID, winAmount).
  298. Update("balance", gorm.Expr("balance + ?", winAmount)).Error
  299. if err != nil {
  300. return err
  301. }
  302. //设置注单
  303. err = tx.Model(model.GameOrder{}).Where("issue = ? and user_id = ?", room.Issue, userID).Updates(map[string]interface{}{
  304. "is_draw": 1,
  305. "draw_time": &timeNow,
  306. "is_win": isWin,
  307. "win_amount": winAmount,
  308. }).Error
  309. if err != nil {
  310. return err
  311. }
  312. currUserModel := model.User{}
  313. err = tx.Model(model.User{}).Where("id = ?", userID).First(&currUserModel).Error
  314. if err != nil {
  315. return err
  316. }
  317. userItem.Balance = currUserModel.Balance
  318. p.PlayerMap[userID] = userItem
  319. //设置结算信息
  320. userBalance, _ := userItem.Balance.Round(2).Float64()
  321. msg.PayoutInfoList = append(msg.PayoutInfoList, &gameproto.PayoutInfo{
  322. UserID: uint32(userID),
  323. WinAmount: float32(winAmount.Mul(decimal.NewFromInt(100)).IntPart()) / 100,
  324. IsMaster: false,
  325. Balance: userBalance,
  326. })
  327. masterTotalWinAmount = masterTotalWinAmount.Add(winAmount.Mul(decimal.NewFromInt(-1)))
  328. }
  329. err = tx.Model(model.User{}).Where("id = ? and balance + ? > 0", masterPlayerItem.ID, masterTotalWinAmount).
  330. Update("balance", gorm.Expr("balance + ?", masterTotalWinAmount)).Error
  331. if err != nil {
  332. logrus.Error(err)
  333. return err
  334. }
  335. err = tx.Model(model.GameOrder{}).Where("issue = ? and user_id = ?", room.Issue, masterPlayerItem.ID).Updates(map[string]interface{}{
  336. "is_draw": 1,
  337. "draw_time": &timeNow,
  338. "is_win": masterTotalWinAmount.GreaterThan(decimal.Zero),
  339. "win_amount": masterTotalWinAmount,
  340. }).Error
  341. //设置master结算信息,更新余额
  342. currUserModel := model.User{}
  343. err = tx.Model(model.User{}).Where("id = ?", masterPlayerItem.ID).First(&currUserModel).Error
  344. if err != nil {
  345. logrus.Error(err)
  346. return err
  347. }
  348. masterPlayerItem.Balance = currUserModel.Balance
  349. p.PlayerMap[masterPlayerItem.ID] = masterPlayerItem
  350. masterBalance, _ := masterPlayerItem.Balance.Round(2).Float64()
  351. msg.PayoutInfoList = append(msg.PayoutInfoList, &gameproto.PayoutInfo{
  352. UserID: uint32(masterPlayerItem.ID),
  353. WinAmount: float32(masterTotalWinAmount.Mul(decimal.NewFromInt(100)).IntPart()) / 100,
  354. IsMaster: true,
  355. Balance: masterBalance,
  356. })
  357. return nil
  358. })
  359. if err != nil {
  360. logrus.Error(err, "===============")
  361. return err
  362. }
  363. //更新一下用户信息
  364. userModelList := make([]model.User, 0)
  365. err = db.GetDB().Model(model.User{}).Where("id in ?", roomUserIDList).Scan(&userModelList).Error
  366. if err != nil {
  367. logrus.Error(err)
  368. return err
  369. }
  370. for _, userModel := range userModelList {
  371. userID := int32(userModel.ID)
  372. userItem := p.PlayerMap[userID]
  373. userItem.Balance = userModel.Balance
  374. userItem.HeadImg = userModel.HeadImg
  375. userItem.Name = userModel.Name
  376. userItem.IsMaster = false
  377. userItem.Status = PlayerStatusWaitReady
  378. p.EventInfo(userID, "开牌", "更新用户状态为等待开牌")
  379. p.PlayerMap[userID] = userItem
  380. }
  381. room.Status = RoomStatusWaitReady
  382. room.StatusStartTime = time.Now().Unix()
  383. p.RoomMap[room.ID] = room
  384. //通知
  385. roomUserIDList, err = p.getRoomUserIDList(room.ID)
  386. if err != nil {
  387. logrus.Error(err)
  388. return err
  389. }
  390. nxd.SendMsgToUserList(roomUserIDList, gameproto.NotifyTypeEnum_NotifyTypeOpenFinish, msg)
  391. return nil
  392. }
  393. func (p *Game) getRoomUserIDListWithStatus(roomID int32, status PlayerStatus) ([]int32, error) {
  394. roomItem, exists := p.RoomMap[roomID]
  395. if !exists {
  396. return nil, errors.New("room not exists")
  397. }
  398. userIDList := make([]int32, 0)
  399. for _, chairItem := range roomItem.ChairList {
  400. if chairItem.PlayerID == 0 {
  401. continue
  402. }
  403. playerItem, exists := p.PlayerMap[chairItem.PlayerID]
  404. if !exists {
  405. continue
  406. }
  407. if playerItem.Status != status {
  408. continue
  409. }
  410. userIDList = append(userIDList, chairItem.PlayerID)
  411. }
  412. return userIDList, nil
  413. }
  414. func (p *Game) getRoomUserIDList(roomID int32) ([]int32, error) {
  415. roomItem, exists := p.RoomMap[roomID]
  416. if !exists {
  417. return nil, errors.New("room not exists")
  418. }
  419. userIDList := make([]int32, 0)
  420. for _, chairItem := range roomItem.ChairList {
  421. if chairItem.PlayerID == 0 {
  422. continue
  423. }
  424. userIDList = append(userIDList, chairItem.PlayerID)
  425. }
  426. return userIDList, nil
  427. }