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 !masterWin {
  276. _, _, cardLevel = WinLevel(userCardList, masterCardList)
  277. }
  278. if isEqual {
  279. isWin = false
  280. winAmount = decimal.NewFromInt(0)
  281. } else {
  282. if !masterWin {
  283. isWin = true
  284. //赢庄家
  285. winAmount = room.BaseAmount.Mul(decimal.NewFromInt(int64(masterPlayerItem.MasterMul))).Mul(decimal.NewFromInt(int64(userItem.Mul))).Mul(decimal.NewFromInt(int64(cardLevel)))
  286. } else {
  287. isWin = false
  288. //输给庄家
  289. winAmount = room.BaseAmount.Mul(decimal.NewFromInt(int64(masterPlayerItem.MasterMul))).Mul(decimal.NewFromInt(int64(userItem.Mul))).Mul(decimal.NewFromInt(-1)).Mul(decimal.NewFromInt(int64(cardLevel)))
  290. }
  291. }
  292. err = tx.Model(model.User{}).Where("id = ? and balance + ? > 0", userID, winAmount).
  293. Update("balance", gorm.Expr("balance + ?", winAmount)).Error
  294. if err != nil {
  295. return err
  296. }
  297. //设置注单
  298. err = tx.Model(model.GameOrder{}).Where("issue = ? and user_id = ?", room.Issue, userID).Updates(map[string]interface{}{
  299. "is_draw": 1,
  300. "draw_time": &timeNow,
  301. "is_win": isWin,
  302. "win_amount": winAmount,
  303. }).Error
  304. if err != nil {
  305. return err
  306. }
  307. currUserModel := model.User{}
  308. err = tx.Model(model.User{}).Where("id = ?", userID).First(&currUserModel).Error
  309. if err != nil {
  310. return err
  311. }
  312. userItem.Balance = currUserModel.Balance
  313. p.PlayerMap[userID] = userItem
  314. //设置结算信息
  315. userBalance, _ := userItem.Balance.Round(2).Float64()
  316. msg.PayoutInfoList = append(msg.PayoutInfoList, &gameproto.PayoutInfo{
  317. UserID: uint32(userID),
  318. WinAmount: float32(winAmount.Mul(decimal.NewFromInt(100)).IntPart()) / 100,
  319. IsMaster: false,
  320. Balance: userBalance,
  321. })
  322. masterTotalWinAmount = masterTotalWinAmount.Add(winAmount.Mul(decimal.NewFromInt(-1)))
  323. }
  324. err = tx.Model(model.User{}).Where("id = ? and balance + ? > 0", masterPlayerItem.ID, masterTotalWinAmount).
  325. Update("balance", gorm.Expr("balance + ?", masterTotalWinAmount)).Error
  326. if err != nil {
  327. logrus.Error(err)
  328. return err
  329. }
  330. err = tx.Model(model.GameOrder{}).Where("issue = ? and user_id = ?", room.Issue, masterPlayerItem.ID).Updates(map[string]interface{}{
  331. "is_draw": 1,
  332. "draw_time": &timeNow,
  333. "is_win": masterTotalWinAmount.GreaterThan(decimal.Zero),
  334. "win_amount": masterTotalWinAmount,
  335. }).Error
  336. //设置master结算信息,更新余额
  337. currUserModel := model.User{}
  338. err = tx.Model(model.User{}).Where("id = ?", masterPlayerItem.ID).First(&currUserModel).Error
  339. if err != nil {
  340. logrus.Error(err)
  341. return err
  342. }
  343. masterPlayerItem.Balance = currUserModel.Balance
  344. p.PlayerMap[masterPlayerItem.ID] = masterPlayerItem
  345. masterBalance, _ := masterPlayerItem.Balance.Round(2).Float64()
  346. msg.PayoutInfoList = append(msg.PayoutInfoList, &gameproto.PayoutInfo{
  347. UserID: uint32(masterPlayerItem.ID),
  348. WinAmount: float32(masterTotalWinAmount.Mul(decimal.NewFromInt(100)).IntPart()) / 100,
  349. IsMaster: true,
  350. Balance: masterBalance,
  351. })
  352. return nil
  353. })
  354. if err != nil {
  355. logrus.Error(err, "===============")
  356. return err
  357. }
  358. //更新一下用户信息
  359. userModelList := make([]model.User, 0)
  360. err = db.GetDB().Model(model.User{}).Where("id in ?", roomUserIDList).Scan(&userModelList).Error
  361. if err != nil {
  362. logrus.Error(err)
  363. return err
  364. }
  365. for _, userModel := range userModelList {
  366. userID := int32(userModel.ID)
  367. userItem := p.PlayerMap[userID]
  368. userItem.Balance = userModel.Balance
  369. userItem.HeadImg = userModel.HeadImg
  370. userItem.Name = userModel.Name
  371. userItem.IsMaster = false
  372. userItem.Status = PlayerStatusWaitReady
  373. p.EventInfo(userID, "开牌", "更新用户状态为等待开牌")
  374. p.PlayerMap[userID] = userItem
  375. }
  376. room.Status = RoomStatusWaitReady
  377. room.StatusStartTime = time.Now().Unix()
  378. p.RoomMap[room.ID] = room
  379. //通知
  380. roomUserIDList, err = p.getRoomUserIDList(room.ID)
  381. if err != nil {
  382. logrus.Error(err)
  383. return err
  384. }
  385. nxd.SendMsgToUserList(roomUserIDList, gameproto.NotifyTypeEnum_NotifyTypeOpenFinish, msg)
  386. return nil
  387. }
  388. func (p *Game) getRoomUserIDListWithStatus(roomID int32, status PlayerStatus) ([]int32, error) {
  389. roomItem, exists := p.RoomMap[roomID]
  390. if !exists {
  391. return nil, errors.New("room not exists")
  392. }
  393. userIDList := make([]int32, 0)
  394. for _, chairItem := range roomItem.ChairList {
  395. if chairItem.PlayerID == 0 {
  396. continue
  397. }
  398. playerItem, exists := p.PlayerMap[chairItem.PlayerID]
  399. if !exists {
  400. continue
  401. }
  402. if playerItem.Status != status {
  403. continue
  404. }
  405. userIDList = append(userIDList, chairItem.PlayerID)
  406. }
  407. return userIDList, nil
  408. }
  409. func (p *Game) getRoomUserIDList(roomID int32) ([]int32, error) {
  410. roomItem, exists := p.RoomMap[roomID]
  411. if !exists {
  412. return nil, errors.New("room not exists")
  413. }
  414. userIDList := make([]int32, 0)
  415. for _, chairItem := range roomItem.ChairList {
  416. if chairItem.PlayerID == 0 {
  417. continue
  418. }
  419. userIDList = append(userIDList, chairItem.PlayerID)
  420. }
  421. return userIDList, nil
  422. }