tablesink_impl.go 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183
  1. package gamelogic
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "sort"
  6. "time"
  7. "bet24.com/log"
  8. "bet24.com/servers/games/masharie_table/common"
  9. "bet24.com/servers/games/masharie_table/config"
  10. userservices "bet24.com/servers/micros/userservices/proto"
  11. waterpool "bet24.com/servers/micros/waterpool/proto"
  12. "bet24.com/servers/transaction"
  13. "bet24.com/servers/user"
  14. "bet24.com/utils"
  15. )
  16. func (ts *tablesink) startPeriod() {
  17. delaySecond := 0
  18. switch ts.roomInfo.State {
  19. case common.GameState_Open:
  20. //开奖阶段结束了
  21. ts.lock.RLock()
  22. var prizeArea = ts.prizeArea
  23. ts.lock.RUnlock()
  24. //判断是否有彩池
  25. if prizeArea >= 0 {
  26. delaySecond = ts.roomInfo.PrizesTime
  27. ts.roomInfo.State = common.GameState_Prizes
  28. } else {
  29. delaySecond = ts.roomInfo.BetTime
  30. ts.finishOpenState()
  31. }
  32. case common.GameState_Bet:
  33. delaySecond = ts.roomInfo.OpenTime
  34. ts.roomInfo.State = common.GameState_Open
  35. if ts.bankerInfo.UserId != 0 {
  36. ts.bankerInfo.SetCount++
  37. }
  38. //开奖时刷新配置
  39. common.ResetProjectMultiple(ts.roomInfo.ProjectMultiple)
  40. case common.GameState_Prizes:
  41. delaySecond = ts.roomInfo.BetTime
  42. ts.finishOpenState()
  43. default:
  44. log.Release("startPeriod failed state = %d", ts.roomInfo.State)
  45. return
  46. }
  47. ts.LastStateTick = time.Now()
  48. ts.onStateChanged()
  49. time.AfterFunc(time.Duration(delaySecond)*time.Second, ts.startPeriod)
  50. log.Debug("tablesink.startPeriod %v:%d,State = %d", ts.roomInfo.RoomName, delaySecond, ts.roomInfo.State)
  51. }
  52. func (ts *tablesink) getStateSecond() int {
  53. return int(time.Since(ts.LastStateTick).Seconds())
  54. }
  55. // 下注剩余时间
  56. func (ts *tablesink) getBetRemainingSecond() int {
  57. return ts.roomInfo.BetTime - ts.getStateSecond()
  58. }
  59. // 完成开奖阶段后
  60. func (ts *tablesink) finishOpenState() {
  61. ts.roomInfo.TotalBet = 0
  62. ts.roomInfo.State = common.GameState_Bet
  63. ts.lock.Lock()
  64. // 洗牌,发牌
  65. ts.logic.shuffle(false, 0)
  66. ts.trumpCard = ts.logic.trumpCard
  67. ts.bankerCards = common.GetInvalidHandCards(HAND_CARD_COUNT, CARD_COUNT)
  68. ts.diamondCards = common.GetInvalidHandCards(HAND_CARD_COUNT, CARD_COUNT)
  69. ts.clubCards = common.GetInvalidHandCards(HAND_CARD_COUNT, CARD_COUNT)
  70. ts.heartCards = common.GetInvalidHandCards(HAND_CARD_COUNT, CARD_COUNT)
  71. ts.spadeCards = common.GetInvalidHandCards(HAND_CARD_COUNT, CARD_COUNT)
  72. ts.areaResult = make([]int, 0)
  73. ts.bankerSettle = 0
  74. ts.score_users.PrizeLuckyStarUsers = []common.ScoreUser{}
  75. ts.lock.Unlock()
  76. }
  77. func (ts *tablesink) onStateChanged() {
  78. switch ts.roomInfo.State {
  79. case common.GameState_Bet:
  80. now := time.Now()
  81. serialNumber := now.Minute() + now.Hour()*100 + now.Day()*10000 + int(now.Month())*1000000 + (now.Year()%10)*100000000
  82. serialNumber = serialNumber*100 + now.Second()
  83. ts.lock.Lock()
  84. ts.userBetList = make(map[int][]common.Bet)
  85. ts.roomInfo.SerialNumber = serialNumber
  86. ts.diamondAmount = 0
  87. ts.clubAmount = 0
  88. ts.heartAmount = 0
  89. ts.spadeAmount = 0
  90. ts.prizeArea = -1
  91. ts.lock.Unlock()
  92. log.Debug("onStateChanged SerialNumber = %d", ts.roomInfo.SerialNumber)
  93. go ts.arrangeRobotActions()
  94. case common.GameState_Open:
  95. go ts.stopRobotPoll()
  96. // 如果是开奖阶段
  97. controlType := 0
  98. //必须是系统庄家
  99. if ts.bankerInfo.UserId == -1 {
  100. controlType = waterpool.GetControlType(0, false, common.GAMEID)
  101. log.Release("onStateChanged waterpool.GetControlType 控制类型:%v", controlType)
  102. }
  103. ts.enterOpenState(controlType, false)
  104. case common.GameState_Prizes:
  105. ts.enterPrizeState()
  106. default:
  107. log.Release("onStateChanged failed state = %d", ts.roomInfo.State)
  108. return
  109. }
  110. ts.table.NotifySceneChanged(-1)
  111. //ts.refreshRoomInfo()
  112. }
  113. func (ts *tablesink) getStateData() string {
  114. var state common.GameState
  115. state.Sec = ts.getStateSecond()
  116. ts.lock.RLock()
  117. state.State = ts.roomInfo.State
  118. ts.roomInfo.StateSec = state.Sec
  119. state.TrumpCard = ts.trumpCard // 主牌(投注阶段下发)
  120. state.BankerCards = ts.bankerCards // 庄家手牌
  121. state.DiamondCards = ts.diamondCards // 方块手牌
  122. state.ClubCards = ts.clubCards // 梅花手牌
  123. state.HeartCards = ts.heartCards // 红心手牌
  124. state.SpadeCards = ts.spadeCards // 黑桃手牌
  125. state.AreaResult = ts.areaResult // 区域结果
  126. state.BankerSettle = ts.bankerSettle
  127. state.Historys = ts.roomInfo.Historys
  128. state.TableUser = *ts.score_users
  129. state.PrizePool = ts.prizePool.getPrizePool()
  130. state.PrizeArea = ts.prizeArea
  131. state.BankerInfo = ts.bankerInfo
  132. //state.RichList = ts.richList
  133. //state.BetList = ts.betList
  134. state.SerialNumber = ts.roomInfo.SerialNumber
  135. if len(ts.scores) > 0 {
  136. state.Scores = append(state.Scores, ts.scores...)
  137. } else {
  138. state.Scores = []common.UserSetScore{}
  139. }
  140. if state.State == common.GameState_Bet {
  141. for _, v := range ts.userBetList {
  142. state.BetCmds = append(state.BetCmds, v...)
  143. }
  144. }
  145. ts.lock.RUnlock()
  146. data, _ := json.Marshal(state)
  147. return string(data)
  148. }
  149. func (ts *tablesink) isCanBet(bet common.Bet) (bool, string) {
  150. amount := bet.Amount
  151. userId := bet.UserId
  152. betId := bet.BetId
  153. if ts.roomInfo.State != common.GameState_Bet {
  154. return false, "Bet failed,Please wait for next round"
  155. }
  156. if amount < ts.roomInfo.MinBet || amount > ts.roomInfo.MaxBet {
  157. return false, "Bet amount exceeded"
  158. }
  159. bidType := common.BidType(betId)
  160. if bidType >= common.BidType_Max || bidType < common.BidType_Diamond {
  161. log.Release("isCanBet invalid bet %d,%d", bidType, common.BidType_Max)
  162. return false, "invalid bet"
  163. }
  164. // 检查已下注金额
  165. myAmount := 0
  166. ts.lock.RLock()
  167. betList, ok := ts.userBetList[userId]
  168. if ok {
  169. for _, v := range betList {
  170. myAmount += v.Amount
  171. }
  172. }
  173. ts.lock.RUnlock()
  174. maxBet := ts.roomInfo.MaxBet
  175. totalMaxBet := ts.roomInfo.TotalMax
  176. //如果不是系统庄 则金额不能超过当前玩家携带金币
  177. if ts.bankerInfo.UserId != -1 {
  178. bankerGold := ts.bankerInfo.Gold
  179. totalMaxBet = bankerGold / ts.roomInfo.MaxBetRate
  180. }
  181. totalBet := ts.roomInfo.TotalBet
  182. if myAmount+amount > maxBet {
  183. return false, "Bet amount user exceeded"
  184. }
  185. // 检查全体下注
  186. if amount+totalBet > totalMaxBet {
  187. return false, "Bet amount section exceeded"
  188. }
  189. //目前上庄也不考虑赔付
  190. return true, ""
  191. }
  192. // 检查个人下注
  193. func (ts *tablesink) checkGold(bet common.Bet) (bool, string) {
  194. amount := bet.Amount
  195. userId := bet.UserId
  196. myAmount := 0
  197. ts.lock.RLock()
  198. betList, ok := ts.userBetList[userId]
  199. if ok {
  200. for _, v := range betList {
  201. myAmount += v.Amount
  202. }
  203. }
  204. ts.lock.RUnlock()
  205. personalBetRatio := ts.roomInfo.PersonalBetRatio
  206. freeChip := 0
  207. userGold := ts.table.GetUserChipOrGoldByUserId(userId)
  208. //下注金额+已经下注金额 /(以下注金额+身上的钱) = 是否超过限制
  209. if bet.IsFree {
  210. //如果是免费下注则加上剩余免费卷的钱
  211. //检查免费筹码数量
  212. freeChip, _ = ts.freeChips.checkFreeChipsNum(userId)
  213. if freeChip < amount {
  214. log.Debug("checkGold.checkFreeChipsNum Not enough free chip amount:%v,freeChip:%v", amount, freeChip)
  215. return false, "Not enough free chip!"
  216. }
  217. userGold += freeChip
  218. }
  219. if myAmount+userGold == 0 {
  220. return false, "Bet failure, user has no gold"
  221. }
  222. if (amount+myAmount)/(myAmount+userGold) > personalBetRatio {
  223. return false, "Bet failure exceeds the limit"
  224. }
  225. if ts.bankerInfo.UserId == -1 {
  226. return true, ""
  227. }
  228. //目前上庄也不考虑赔付
  229. return true, ""
  230. }
  231. func (ts *tablesink) addBet(bet common.Bet) (bool, string) {
  232. ok, errMsg := ts.isCanBet(bet)
  233. if !ok {
  234. return ok, errMsg
  235. }
  236. ts.lock.Lock()
  237. ts.roomInfo.TotalBet += bet.Amount
  238. betList, ok := ts.userBetList[bet.UserId]
  239. // 合并之前下注
  240. found := false
  241. if ok {
  242. for i := 0; i < len(betList); i++ {
  243. if !betList[i].IsSameBet(&bet) {
  244. continue
  245. }
  246. betList[i].Amount += bet.Amount
  247. // 合并下注
  248. found = true
  249. break
  250. }
  251. }
  252. //log.Debug("tablesink.addBet %v", ts.userBetList)
  253. if !found {
  254. ts.userBetList[bet.UserId] = append(ts.userBetList[bet.UserId], bet)
  255. }
  256. ts.lock.Unlock()
  257. betAmount := bet.Amount
  258. if !bet.IsFree {
  259. ts.userList.addBet(bet.UserId, betAmount, bet.BetId)
  260. }
  261. return true, ""
  262. }
  263. // 开奖 controlType 1表示扣减,2表示放水
  264. func (ts *tablesink) enterOpenState(controlType int, isReset bool) {
  265. //默认按顺序获取结果
  266. ts.logic.curDeckIndex = 0
  267. var areaDeck []common.CardDeck
  268. for i := 0; i < CARD_DECK_COUNT; i++ {
  269. deck := ts.logic.getHandCardsByIndex()
  270. areaDeck = append(areaDeck, deck)
  271. }
  272. if areaDeck == nil {
  273. log.Error("tableSink.enterOpenState areaDeck == nil")
  274. return
  275. }
  276. if areaDeck[common.Area_Banker].Ranking == 1 && isReset && ts.isBankerAllKill {
  277. ts.logic.shuffle(false, 0)
  278. ts.enterOpenState(controlType, false)
  279. }
  280. if areaDeck[common.Area_Banker].Ranking == 1 {
  281. ts.isBankerAllKill = true
  282. } else {
  283. ts.isBankerAllKill = false
  284. }
  285. //按顺序分配手牌
  286. settlementOrder, areaResult := ts.assignAreaCards(areaDeck)
  287. bankerBetAmount := 0
  288. areaTotalBet := make(map[int]int)
  289. realAreaTotalBet := make(map[int]int) //剔除机器人的
  290. ts.lock.RLock()
  291. bankerCards := ts.bankerCards
  292. bankerOdds := common.GetMultiple(bankerCards.Project)
  293. //计算所有区域的下注总额
  294. for _, betList := range ts.userBetList {
  295. if len(betList) == 0 {
  296. continue
  297. }
  298. for _, v := range betList {
  299. areaTotalBet[v.BetId] += v.Amount
  300. bankerBetAmount += v.Amount
  301. if v.IsRobot && !ts.roomInfo.Test {
  302. //机器人跳过
  303. continue
  304. }
  305. realAreaTotalBet[v.BetId] += v.Amount
  306. }
  307. }
  308. ts.lock.RUnlock()
  309. //只重置一次
  310. if controlType != 0 && !isReset {
  311. //1表示扣减,2表示放水
  312. // 检查非机器人的下注结果
  313. simulateBetResults := 0
  314. for _, betBid := range settlementOrder {
  315. simulateBetResults += realAreaTotalBet[betBid]
  316. if areaResult[betBid] == common.Win {
  317. odds := common.GetMultiple(areaDeck[betBid].Project) + 1
  318. simulateBetResults -= int(odds * float64(realAreaTotalBet[betBid]))
  319. } else if bankerOdds > 1 {
  320. simulateBetResults += int((bankerOdds - 1) * float64(realAreaTotalBet[betBid]))
  321. }
  322. }
  323. log.Release("tableSink.enterOpenState controlType:%v,isReset:%v,simulateBetResults:%v", controlType, isReset, simulateBetResults)
  324. if controlType == 1 && simulateBetResults < 0 {
  325. ts.logic.shuffle(false, 0)
  326. ts.enterOpenState(controlType, false)
  327. return
  328. } else if controlType == 2 && simulateBetResults > 0 {
  329. // 放水不出翻倍牌型
  330. ts.logic.shuffle(false, 1)
  331. ts.enterOpenState(controlType, false)
  332. return
  333. }
  334. }
  335. //写历史记录
  336. ts.addHistory()
  337. bankerLoseRate := 1.0
  338. bankerDeck := areaDeck[common.Area_Banker]
  339. ts.lock.RLock()
  340. bankerId := ts.bankerInfo.UserId
  341. trumpCard := ts.trumpCard
  342. ts.lock.RUnlock()
  343. //基础投注备注
  344. baseBetDesc := fmt.Sprintf("B:[%v,R:%v]M:%v", getHandCardsHex(bankerDeck.HandCards, true), bankerDeck.Ranking, getCardHex(trumpCard, true))
  345. bankerBetDesc := baseBetDesc
  346. ts.lock.RLock()
  347. settleInfo := make(map[int]*common.SettleInfo)
  348. for userId, betList := range ts.userBetList {
  349. if len(betList) == 0 {
  350. continue
  351. }
  352. //判断一下之前有没有创建
  353. if settleInfo[userId] == nil {
  354. settleInfo[userId] = &common.SettleInfo{}
  355. //BetDesc 初始化时加入庄家的牌
  356. settleInfo[userId].BetDesc = baseBetDesc
  357. }
  358. }
  359. ts.lock.RUnlock()
  360. bankerTotalBet := []int{0, 0, 0, 0}
  361. bankerTotalWin := []int{0, 0, 0, 0}
  362. bankerTotalLose := []int{0, 0, 0, 0}
  363. prizeTotalBet := 0
  364. var refreshFreeChips = make([]int, 0)
  365. //处理玩家输的部分
  366. settleInfo, prizeTotalBet, refreshFreeChips, bankerTotalBet, bankerTotalWin = ts.handleLoss(areaDeck, settlementOrder, settleInfo, prizeTotalBet, bankerTotalBet, bankerTotalWin)
  367. if bankerId != -1 {
  368. //如果不是系统庄 则需要预估赔付比例
  369. bankerWin := 0
  370. //计算庄家实际赢的
  371. for _, win := range bankerTotalWin {
  372. bankerWin += win
  373. }
  374. ts.lock.RLock()
  375. bankerGold := ts.bankerInfo.Gold
  376. ts.lock.RUnlock()
  377. bankerLoseRate = ts.calcBankerLoseRate(bankerGold, areaTotalBet, areaDeck, areaResult, settlementOrder, bankerWin)
  378. } else {
  379. bankerBetAmount = 0 //系统庄不统计
  380. }
  381. // 处理玩家赢的部分
  382. settleInfo, prizeTotalBet, bankerTotalBet, bankerTotalLose = ts.handleWin(areaDeck, settlementOrder, settleInfo, prizeTotalBet, bankerTotalBet, bankerTotalLose, bankerLoseRate)
  383. bankerSettle := ts.settleResults(settleInfo, bankerLoseRate)
  384. ts.lock.RLock()
  385. delaySecond := ts.roomInfo.OpenTime - 1 //换庄等待时间
  386. if prizeTotalBet > 0 {
  387. ts.prizeTotalBet = prizeTotalBet
  388. delaySecond += ts.roomInfo.PrizesTime - 1
  389. }
  390. ts.lock.RUnlock()
  391. checkBankerTime := time.Duration(delaySecond) * time.Second
  392. // 写庄家投注日志
  393. for betId, amount := range bankerTotalBet {
  394. betDesc := fmt.Sprintf("[%s:%s]", common.GetBetDesc(betId), utils.FormatScore(amount))
  395. winDesc := fmt.Sprintf("[%s:%s]", common.GetBetDesc(betId), utils.FormatScore(bankerTotalWin[betId]))
  396. loseDesc := fmt.Sprintf("[%s:%s]", common.GetBetDesc(betId), utils.FormatScore(bankerTotalLose[betId]))
  397. bankerBetDesc = fmt.Sprintf("%s %s,win:%s lose:%s", bankerBetDesc, betDesc, winDesc, loseDesc)
  398. }
  399. bankerSettle = ts.calculateBankerScore(bankerId, bankerBetAmount, bankerSettle, bankerBetDesc)
  400. ts.dayBetRank.betPoolToRedis()
  401. ts.weekBetRank.betPoolToRedis()
  402. //ts.userList.dump()
  403. // 结算完毕,计算连胜榜
  404. ts.lock.Lock()
  405. ts.bankerSettle = bankerSettle
  406. // ts.richList = ts.refreshRichList(20)
  407. //先清空数据
  408. ts.score_users.LuckyStarUsers = []common.ScoreUser{}
  409. ts.score_users.BetGoldRankingUsers = []common.ScoreUser{}
  410. ts.score_users.WinGoldRankingUsers = []common.ScoreUser{}
  411. ts.score_users.LuckyStarUsers = ts.userList.getLuckyStarUsers(1, ts.bankerInfo.UserId)
  412. ts.score_users.BetGoldRankingUsers = ts.userList.getBetGoldRankingUsers(7)
  413. ts.score_users.WinGoldRankingUsers = ts.userList.getWinGoldRankingUsers(1, ts.bankerSettle, ts.bankerInfo.UserId, ts.bankerInfo.FaceId, ts.bankerInfo.FaceUrl)
  414. ts.userList.clearBetStatus(ts.roomInfo.SerialNumber)
  415. ts.lock.Unlock()
  416. if len(refreshFreeChips) > 0 {
  417. //刷新免费筹码
  418. for _, userId := range refreshFreeChips {
  419. usr := ts.table.GetUserByUserId(userId)
  420. if usr == nil {
  421. continue
  422. }
  423. go ts.onCheckFreeChip(usr.GetUserIndex(), userId, FreeChip, "")
  424. }
  425. }
  426. if prizeTotalBet <= 0 {
  427. ts.clearLeaveUser()
  428. }
  429. // 下庄
  430. time.AfterFunc(checkBankerTime, ts.checkBankerQuality)
  431. }
  432. // 根据类型洗牌 HACK:删除这部分逻辑控制不在因为调控修改牌
  433. func (ts *tablesink) handleControlType(controlType int) []common.CardDeck {
  434. //HACK: 删除这部分逻辑控制不在因为调控修改牌
  435. var areaDeck []common.CardDeck
  436. maxAmount, minAmount, maxType := ts.getBetMaxAndMin()
  437. if controlType == 0 {
  438. //必须是系统庄家
  439. if ts.bankerInfo.UserId == -1 && (maxAmount > 0 || minAmount > 0) {
  440. controlType = waterpool.GetControlType(0, false, common.GAMEID)
  441. log.Release("tableSink.handleControlType waterpool.GetControlType 控制类型:%v", controlType)
  442. }
  443. //不需要控制
  444. // else if ts.bankerInfo.UserId != -1 {
  445. // //非系统庄时 不触发奖池牌型
  446. // if ts.logic.checkAwardCardDeck() {
  447. // ts.logic.shuffle(false, 3)
  448. // ts.enterOpenState(controlType)
  449. // return nil
  450. // }
  451. // }
  452. }
  453. //根据情况判断是否需要重新开奖
  454. if controlType == 1 {
  455. //全部等级,不去重
  456. ranking := ts.logic.getAllRanking()
  457. // 1.收水允许有翻倍的情况存在
  458. // 2.最大下注区域给排名最小的牌,其他3个区域和庄家随机获取名次
  459. min := 2
  460. min, ranking = getRanking(ranking, Min)
  461. for i := 0; i < CARD_DECK_COUNT; i++ {
  462. if common.AreaHandCards(i) == maxType {
  463. deck := ts.logic.getHandCardsByRanking(min)
  464. areaDeck = append(areaDeck, deck)
  465. } else {
  466. randomRank, newRanking := getRanking(ranking, Random)
  467. ranking = newRanking
  468. deck := ts.logic.getHandCardsByRanking(randomRank)
  469. areaDeck = append(areaDeck, deck)
  470. }
  471. }
  472. return areaDeck
  473. } else if controlType == 2 {
  474. //重洗
  475. //判断是否还有翻倍
  476. if ts.logic.checkMultipleCardDeck() {
  477. ts.logic.shuffle(false, 1)
  478. ts.enterOpenState(controlType, true)
  479. return nil
  480. }
  481. ranking := ts.logic.getAllRanking()
  482. //1.放水时所有牌不能有翻倍,如果遇到有翻倍则重新洗
  483. //2.放水区域给排名最大的牌,其他3个区域和庄家随机获取名次
  484. max := 1
  485. max, ranking = getRanking(ranking, Max)
  486. for i := 0; i < CARD_DECK_COUNT; i++ {
  487. if common.AreaHandCards(i) == maxType {
  488. deck := ts.logic.getHandCardsByRanking(max)
  489. areaDeck = append(areaDeck, deck)
  490. } else {
  491. randomRank, newRanking := getRanking(ranking, Random)
  492. ranking = newRanking
  493. deck := ts.logic.getHandCardsByRanking(randomRank)
  494. areaDeck = append(areaDeck, deck)
  495. }
  496. }
  497. return areaDeck
  498. }
  499. //默认按顺序获取结果
  500. ts.logic.curDeckIndex = 0
  501. for i := 0; i < CARD_DECK_COUNT; i++ {
  502. deck := ts.logic.getHandCardsByIndex()
  503. areaDeck = append(areaDeck, deck)
  504. }
  505. return areaDeck
  506. }
  507. // 给每个区域分配手牌
  508. func (ts *tablesink) assignAreaCards(areaDeck []common.CardDeck) ([]int, []int) {
  509. var areaResult []int
  510. var prizeProject = common.Project_Base
  511. bankerRanking := areaDeck[common.Area_Banker].Ranking
  512. bankerDeck := areaDeck[common.Area_Banker]
  513. ts.bankerCards = bankerDeck.HandCards
  514. diamondDeck := areaDeck[common.Area_Diamond]
  515. ts.diamondCards = diamondDeck.HandCards
  516. clubDeck := areaDeck[common.Area_Club]
  517. ts.clubCards = clubDeck.HandCards
  518. heartDeck := areaDeck[common.Area_Heart]
  519. ts.heartCards = heartDeck.HandCards
  520. spadeDeck := areaDeck[common.Area_Spade]
  521. ts.spadeCards = spadeDeck.HandCards
  522. winAreas := make([]int, 0) // Areas where banker won
  523. loseAreas := make([]int, 0) // Areas where banker lost
  524. prizeArea := -1
  525. for i := 0; i < CARD_DECK_COUNT-1; i++ {
  526. result := common.Lose
  527. //排名小于庄家的则算赢
  528. if areaDeck[i].Ranking < bankerRanking {
  529. result = common.Win
  530. winAreas = append(winAreas, i)
  531. } else {
  532. loseAreas = append(loseAreas, i)
  533. }
  534. areaResult = append(areaResult, result)
  535. if areaDeck[i].Project >= common.Project_Fifty && areaDeck[i].Project >= prizeProject {
  536. //如果相同则取最大的
  537. if prizeArea != -1 && areaDeck[i].Project == prizeProject && areaDeck[i].Ranking > areaDeck[prizeArea].Ranking {
  538. continue
  539. }
  540. prizeArea = i
  541. prizeProject = areaDeck[i].Project
  542. }
  543. }
  544. // 开奖
  545. ts.lock.Lock()
  546. ts.areaResult = areaResult
  547. ts.prizeArea = prizeArea
  548. ts.prizeProject = prizeProject
  549. ts.lock.Unlock()
  550. settlementOrder := append(loseAreas, winAreas...)
  551. return settlementOrder, areaResult
  552. }
  553. // 预估庄家赔付比例
  554. func (ts *tablesink) calcBankerLoseRate(bankerGold int, areaTotalBet map[int]int, areaDeck []common.CardDeck, areaResult []int, settlementOrder []int, bankerWin int) float64 {
  555. bankerLoseRate := 1.0
  556. //庄家赔付
  557. bankerLose := 0
  558. //庄家底注
  559. base := 0
  560. for _, betBid := range settlementOrder {
  561. base += int(areaTotalBet[betBid]) //底注
  562. if areaResult[betBid] == common.Win {
  563. odds := common.GetMultiple(areaDeck[betBid].Project) + 1
  564. bankerLose += int(odds * float64(areaTotalBet[betBid]))
  565. }
  566. }
  567. settle := bankerGold + base + bankerWin
  568. //预估结算
  569. if bankerLose > settle {
  570. //庄家金币不足
  571. bankerLoseRate = float64(settle) / float64(bankerLose)
  572. log.Release("enterOpenState.calcBankerLoseRate bankerGold not enough bankerGold:%v,bankerWin:%v,settle:%v,bankerLose:%v, bankerLoseRate:%v", bankerGold, bankerWin, settle, bankerLose, bankerLoseRate)
  573. }
  574. return bankerLoseRate
  575. }
  576. // 处理玩家输的情况(因为非系统庄需要考虑玩家实际输的金额,所以区分成了两个方法)
  577. func (ts *tablesink) handleLoss(areaDeck []common.CardDeck, settlementOrder []int, settleInfo map[int]*common.SettleInfo, prizeTotalBet int, bankerTotalBet, bankerTotalWin []int) (map[int]*common.SettleInfo, int, []int, []int, []int) {
  578. // 处理输的情况的代码
  579. //记录需要刷新的免费筹码的用户id
  580. refreshFreeChips := make([]int, 0)
  581. ts.lock.Lock()
  582. bankerCards := ts.bankerCards
  583. prizeArea := ts.prizeArea
  584. areaResult := ts.areaResult
  585. diamondCards := ts.diamondCards
  586. clubCards := ts.clubCards
  587. heartCards := ts.heartCards
  588. spadeCards := ts.spadeCards
  589. bankerOdds := common.GetMultiple(bankerCards.Project)
  590. for _, betBid := range settlementOrder {
  591. if areaResult[betBid] == common.Win {
  592. continue
  593. }
  594. for userId, betList := range ts.userBetList {
  595. if len(betList) == 0 {
  596. continue
  597. }
  598. actualModifyAmount := 0
  599. //庄家赔率
  600. var odds float64 = 0
  601. odds = bankerOdds
  602. for _, v := range betList {
  603. if v.BetId != betBid {
  604. continue
  605. }
  606. var result common.Result
  607. result.UserId = v.UserId
  608. result.Bet = v
  609. result.AreaResult = areaResult
  610. result.Amount = v.Amount
  611. betAmount := v.Amount
  612. if v.BetId == prizeArea {
  613. prizeTotalBet += betAmount
  614. }
  615. bankerTotalBet[result.BetId] += betAmount
  616. settleInfo[userId].ActualBetAmount += betAmount
  617. if v.IsFree {
  618. betAmount = 0
  619. }
  620. settleInfo[userId].BetAmount += betAmount
  621. deductedAmount := 0 //记录免费卷抵扣的金额
  622. result.LoseAmount = 0
  623. result.WinAmount = 0
  624. if odds > 1 {
  625. //庄赢超过一倍
  626. result.LoseAmount = int((odds - 1) * float64(result.Amount))
  627. //考虑免费卷抵扣的情况
  628. if v.IsFree {
  629. freeChip, _ := ts.freeChips.checkFreeChipsNum(userId)
  630. //log.Release("enterOpenState.checkFreeChipsNum freeChip:%v,LoseAmount:%v", freeChip, result.LoseAmount)
  631. if freeChip > 0 {
  632. //免费筹码有多少扣多少
  633. _, deductedAmount = ts.freeChips.useFreeChipsFromInventory(userId, result.LoseAmount)
  634. //记录需要刷新的免费筹码的用户id
  635. refreshFreeChips = append(refreshFreeChips, userId)
  636. }
  637. result.LoseAmount -= deductedAmount
  638. log.Release("enterOpenState.useFreeChipsFromInventory deductedAmount:%v,LoseAmount:%v", deductedAmount, result.LoseAmount)
  639. }
  640. }
  641. usr := ts.table.GetUserByUserId(userId)
  642. //得到实际扣除的金额
  643. actualModifyAmount = ts.handleResult(result, usr)
  644. absActualModifyAmount := actualModifyAmount
  645. if actualModifyAmount < 0 {
  646. absActualModifyAmount = actualModifyAmount * -1
  647. }
  648. if result.LoseAmount > 0 || deductedAmount > 0 {
  649. // 玩家不够输的情况
  650. settleInfo[userId].LoseAmount += result.LoseAmount + deductedAmount
  651. bankerTotalWin[result.BetId] += result.LoseAmount + deductedAmount
  652. if absActualModifyAmount < result.LoseAmount {
  653. //如果存在玩家不够扣的情况
  654. settleInfo[userId].LoseAmount -= result.LoseAmount - absActualModifyAmount
  655. bankerTotalWin[result.BetId] -= result.LoseAmount - absActualModifyAmount
  656. }
  657. }
  658. actualDesc := utils.FormatScore(actualModifyAmount)
  659. if v.IsFree {
  660. actualDesc = fmt.Sprintf("F%s(%s)", utils.FormatScore(actualModifyAmount), utils.FormatScore(deductedAmount))
  661. }
  662. betDesc := fmt.Sprintf("[%s:%s[%s]]", ts.getBetDesc(result.Bet), utils.FormatScore(v.Amount), actualDesc)
  663. settleInfo[userId].BetDesc = fmt.Sprintf("%s %s", settleInfo[userId].BetDesc, betDesc)
  664. //判断是否没有数据
  665. if len(settleInfo[userId].ResultDesc) == 0 {
  666. settleInfo[userId].ResultDesc = ts.getResultDesc(areaResult, diamondCards, clubCards, heartCards, spadeCards)
  667. }
  668. }
  669. //log.Debug("GetResultOdds odds= %v, BetId = %v", odds, result.BetId)
  670. }
  671. }
  672. ts.lock.Unlock()
  673. return settleInfo, prizeTotalBet, refreshFreeChips, bankerTotalBet, bankerTotalWin
  674. }
  675. // 处理玩家赢的情况
  676. func (ts *tablesink) handleWin(areaDeck []common.CardDeck, settlementOrder []int, settleInfo map[int]*common.SettleInfo, prizeTotalBet int, bankerTotalBet, bankerTotalLose []int, bankerLoseRate float64) (map[int]*common.SettleInfo, int, []int, []int) {
  677. ts.lock.Lock()
  678. prizeArea := ts.prizeArea
  679. areaResult := ts.areaResult
  680. diamondCards := ts.diamondCards
  681. clubCards := ts.clubCards
  682. heartCards := ts.heartCards
  683. spadeCards := ts.spadeCards
  684. taxRate := ts.roomInfo.TaxRate
  685. for _, betBid := range settlementOrder {
  686. if areaResult[betBid] == common.Lose {
  687. continue
  688. }
  689. for userId, betList := range ts.userBetList {
  690. if len(betList) == 0 {
  691. continue
  692. }
  693. actualModifyAmount := 0
  694. //庄家赔率
  695. var odds float64 = 0
  696. for _, v := range betList {
  697. if v.BetId != betBid {
  698. continue
  699. }
  700. var result common.Result
  701. result.UserId = v.UserId
  702. result.Bet = v
  703. result.AreaResult = areaResult
  704. result.Amount = v.Amount
  705. betAmount := v.Amount
  706. if v.BetId == prizeArea {
  707. prizeTotalBet += betAmount
  708. }
  709. bankerTotalBet[result.BetId] += betAmount
  710. settleInfo[userId].ActualBetAmount += betAmount
  711. if v.IsFree {
  712. betAmount = 0
  713. }
  714. settleInfo[userId].BetAmount += betAmount
  715. deductedAmount := 0 //记录免费卷抵扣的金额
  716. result.LoseAmount = 0
  717. result.WinAmount = 0
  718. if common.Win == areaResult[result.BetId] {
  719. odds = common.GetMultiple(areaDeck[result.BetId].Project) + 1
  720. result.WinAmount = int(odds * float64(result.Amount))
  721. settleInfo[userId].ActualWinAmount += result.WinAmount
  722. bankerTotalLose[result.BetId] += result.WinAmount
  723. //免费的也需要扣本金
  724. realWin := result.WinAmount - result.Amount
  725. if realWin > 0 {
  726. result.Tax = realWin * taxRate / 100
  727. }
  728. result.WinAmount -= result.Tax
  729. settleInfo[userId].TaxAmount += result.Tax
  730. settleInfo[userId].WinAmount += int(float64(result.WinAmount) * bankerLoseRate) //玩家要算完台费才扣
  731. settleInfo[userId].TotalOdds += odds
  732. }
  733. usr := ts.table.GetUserByUserId(userId)
  734. //得到实际扣除的金额
  735. actualModifyAmount = ts.handleResult(result, usr)
  736. actualDesc := utils.FormatScore(actualModifyAmount)
  737. if v.IsFree {
  738. actualDesc = fmt.Sprintf("F%s(%s)", utils.FormatScore(actualModifyAmount), utils.FormatScore(deductedAmount))
  739. }
  740. betDesc := fmt.Sprintf("[%s:%s[%s]]", ts.getBetDesc(result.Bet), utils.FormatScore(v.Amount), actualDesc)
  741. settleInfo[userId].BetDesc = fmt.Sprintf("%s %s", settleInfo[userId].BetDesc, betDesc)
  742. //判断是否没有数据
  743. if len(settleInfo[userId].ResultDesc) == 0 {
  744. settleInfo[userId].ResultDesc = ts.getResultDesc(areaResult, diamondCards, clubCards, heartCards, spadeCards)
  745. }
  746. }
  747. //log.Debug("GetResultOdds odds= %v, BetId = %v", odds, result.BetId)
  748. }
  749. }
  750. ts.lock.Unlock()
  751. return settleInfo, prizeTotalBet, bankerTotalBet, bankerTotalLose
  752. }
  753. // 结算结果
  754. func (ts *tablesink) settleResults(settleInfo map[int]*common.SettleInfo, bankerLoseRate float64) int {
  755. bankerSettle := 0
  756. ts.lock.Lock()
  757. ts.scores = []common.UserSetScore{}
  758. poolValue := waterpool.GetInventoryValue(common.GAMEID, waterpool.RoomType_Hundred, config.Room.RoomName)
  759. //先判断是否为空
  760. if len(settleInfo) != 0 {
  761. //根据settleInfo进行结算
  762. for userId, total := range settleInfo {
  763. //记录实际输赢 总赢金-总投注-总输 0-100-100
  764. totalResult := total.WinAmount - total.BetAmount - total.LoseAmount
  765. //记录庄家输赢 用户总输 +总投注额 - 用户总赢金
  766. bankerSettle += int(float64(total.LoseAmount+total.ActualBetAmount-total.ActualWinAmount) * bankerLoseRate)
  767. //log.Release("enterOpenState.settleResults bankerSettle:%v,LoseAmount:%v,ActualBetAmount:%v,ActualWinAmount:%v,bankerLoseRate:%v", bankerSettle, total.LoseAmount, total.ActualBetAmount, total.ActualWinAmount, bankerLoseRate)
  768. // 纪录输赢
  769. if ts.roomInfo.Test {
  770. bets := []int{}
  771. betList, ok := ts.userBetList[userId]
  772. if ok {
  773. for n := 0; n < len(betList); n++ {
  774. bets = append(bets, betList[n].BetId)
  775. }
  776. }
  777. if len(bets) > 0 {
  778. ts.stat.lists = append(ts.stat.lists, Statistics{
  779. betAmount: total.BetAmount,
  780. winOrLossAmount: totalResult,
  781. betArea: bets,
  782. waterpool: poolValue,
  783. })
  784. }
  785. }
  786. go ts.table.WriteBetRecordWithPlayTime(userId, total.BetAmount, total.WinAmount-total.LoseAmount, total.TotalOdds,
  787. settleInfo[userId].BetDesc, settleInfo[userId].ResultDesc, ts.roomInfo.RoomName, ts.roomInfo.BetTime)
  788. ts.userList.addResult(userId, ts.roomInfo.SerialNumber, total.BetAmount, total.WinAmount, -total.LoseAmount, totalResult)
  789. //有上榜的玩家才发
  790. if common.IsInTopN(ts.score_users.LuckyStarUsers, userId, 1) || common.IsInTopN(ts.score_users.BetGoldRankingUsers, userId, 7) {
  791. ts.scores = append(ts.scores, common.UserSetScore{UserId: userId, Score: totalResult})
  792. }
  793. usr := ts.table.GetUserByUserId(userId)
  794. if usr == nil {
  795. //检查是否为机器人
  796. if !userservices.IsRobot(userId) || ts.roomInfo.Test {
  797. ts.settleStats(userId, total.BetAmount, totalResult, total.TaxAmount)
  798. }
  799. continue
  800. } else if !usr.IsRobot() || ts.roomInfo.Test {
  801. ts.settleStats(userId, total.BetAmount, totalResult, total.TaxAmount)
  802. }
  803. // 只返回具体的金额 用于飘分
  804. data := fmt.Sprint(totalResult)
  805. ts.table.SendGameData(usr.GetUserIndex(), TotalResult, data)
  806. }
  807. }
  808. ts.lock.Unlock()
  809. return bankerSettle
  810. }
  811. // 结算统计
  812. func (ts *tablesink) settleStats(userId, betAmount, winAmount, totalTax int) {
  813. if betAmount > 0 {
  814. ts.dayBetRank.addBetPool(userId, betAmount)
  815. ts.weekBetRank.addBetPool(userId, betAmount)
  816. ts.prizePool.updatePrizePool(betAmount)
  817. }
  818. //上报水池
  819. go waterpool.AddBet(0, betAmount, false, common.GAMEID)
  820. if winAmount != 0 {
  821. go waterpool.ReducePool(0, winAmount+betAmount, false, common.GAMEID)
  822. }
  823. }
  824. // 计算庄家分数
  825. func (ts *tablesink) calculateBankerScore(bankerId, bankerBetAmount, bankerSettle int, bankerBetDesc string) int {
  826. if bankerId == -1 {
  827. return bankerSettle
  828. }
  829. // 庄家写分
  830. banker := ts.table.GetUserByUserId(bankerId)
  831. if banker != nil {
  832. ts.lock.Lock()
  833. // 得到庄家的输赢
  834. bankerGold := ts.bankerInfo.Gold
  835. // 判断庄家赢的钱是否超过自身金额 这个游戏允许超过自身的钱
  836. // if bankerSettle > bankerGold {
  837. // bankerSettle = bankerGold
  838. // }
  839. //判断是否输破产
  840. if bankerGold+bankerSettle < 0 {
  841. bankerSettle = -bankerGold
  842. log.Release("enterOpenState.calculateBankerScore Bankruptcy bankerGold:%v,bankerSettle:%v", bankerGold, bankerSettle)
  843. }
  844. //计算台费
  845. bankerTax := 0
  846. if bankerSettle > 0 {
  847. bankerTax = bankerSettle * ts.roomInfo.BankerTaxRate / 100
  848. bankerSettle -= bankerTax
  849. log.Release("enterOpenState.calculateBankerScore Calculate station fees bankerTax:%v,bankerSettle:%v", bankerTax, bankerSettle)
  850. }
  851. ts.bankerInfo.Tax += bankerTax
  852. // 庄家分数最后写
  853. ts.bankerInfo.Score += bankerSettle
  854. ts.bankerInfo.Gold += bankerSettle
  855. ts.scores = append(ts.scores, common.UserSetScore{UserId: ts.bankerInfo.UserId, Score: bankerSettle})
  856. ts.dayBetRank.addBetPool(ts.bankerInfo.UserId, bankerBetAmount)
  857. ts.weekBetRank.addBetPool(ts.bankerInfo.UserId, bankerBetAmount)
  858. log.Debug("enterOpenState UserId= %d, bankerGold = %d,bankerBetAmount = %d,bankerSettle = %d", ts.bankerInfo.UserId, bankerGold, bankerBetAmount, bankerSettle)
  859. go ts.table.WriteBetRecordWithPlayTime(ts.bankerInfo.UserId, 0, bankerSettle, 0,
  860. fmt.Sprintf("banker bet(%d)", bankerBetAmount), fmt.Sprintf("banker result(%d) %s ", bankerSettle, bankerBetDesc), ts.roomInfo.RoomName, ts.roomInfo.BetTime)
  861. go ts.updateBankerGold()
  862. ts.lock.Unlock()
  863. }
  864. return bankerSettle
  865. }
  866. // 发彩池
  867. func (ts *tablesink) enterPrizeState() {
  868. // 如果是发奖阶段
  869. ts.lock.Lock()
  870. var prizeArea = ts.prizeArea
  871. var prizeProject = ts.prizeProject
  872. var prizeTotalBet = ts.prizeTotalBet
  873. var projectRate = GetProjectRate(prizeProject)
  874. //总奖池
  875. var prizePool = ts.prizePool.getPrizePool()
  876. //奖池比例
  877. var prizeRate = float64(prizePool * projectRate / 100)
  878. //(区域下注总金额/区域总下注金额) * (总奖池*项目比例/100)(1000/10000)*(1000000*20%)=20000
  879. ts.scores = []common.UserSetScore{}
  880. prizeStateDesc := fmt.Sprintf("PrizeArea:[%v] PrizeProject:[%v] PrizeTotalBet:[%v] ProjectRate:[%v] PrizePool:[%v] PrizeRate:[%v]", prizeArea, prizeProject, prizeTotalBet, projectRate, prizePool, prizeRate)
  881. maxBetAmount := 0
  882. for userId, betList := range ts.userBetList {
  883. // usr := ts.table.GetUserByUserId(userId)
  884. var total struct {
  885. UserId int
  886. BetAmount int
  887. Prize int
  888. }
  889. total.UserId = userId
  890. total.Prize = 0
  891. for _, v := range betList {
  892. // 判断是否买了这个区域
  893. if prizeArea != v.BetId {
  894. continue
  895. }
  896. //奖金
  897. prize := int(float64(v.Amount) / float64(prizeTotalBet) * prizeRate)
  898. total.Prize += prize
  899. total.BetAmount += v.Amount
  900. prizeStateDesc = fmt.Sprintf("%s [%d %d[%d:%d]]", prizeStateDesc, userId, v.BetId, v.Amount, prize)
  901. }
  902. if total.Prize <= 0 {
  903. continue
  904. }
  905. if total.BetAmount > maxBetAmount {
  906. maxBetAmount = total.BetAmount
  907. }
  908. totalResult := total.Prize
  909. go ts.prizePool.deductJackpot(totalResult)
  910. go ts.table.WriteUserMoney(userId, totalResult, 0, 2, 2+common.GAMEID*100, ts.roomInfo.RoomName)
  911. // 写用户纪录
  912. d, _ := json.Marshal(total)
  913. go transaction.WriteGameRecord(userId, common.GAMEID, ts.roomInfo.RoomName, string(d))
  914. ts.scores = append(ts.scores, common.UserSetScore{UserId: userId, Score: totalResult})
  915. }
  916. //排序分数越大越靠前
  917. sort.Slice(ts.scores, func(i, j int) bool {
  918. return ts.scores[i].Score > ts.scores[j].Score
  919. })
  920. scoreUserList := []common.ScoreUser{}
  921. //第一名存储起来
  922. if len(ts.scores) > 0 {
  923. //第一名就是下注最大的
  924. var userId = ts.scores[0].UserId
  925. var score = ts.scores[0].Score
  926. ts.prizePool.updatePrizeRank(userId, score, maxBetAmount)
  927. user := userservices.GetUserInfo(userId)
  928. info := make([]int, 0, 1)
  929. info = append(info, score)
  930. scoreUser := common.ScoreUser{
  931. UserId: userId,
  932. BetAmount: maxBetAmount,
  933. NickName: "",
  934. FaceId: 0,
  935. FaceUrl: "",
  936. VipLevel: 0,
  937. VipExpire: 0,
  938. Decorations: nil,
  939. Info: info,
  940. }
  941. if user != nil {
  942. scoreUser.NickName = user.NickName
  943. scoreUser.FaceId = user.FaceId
  944. scoreUser.FaceUrl = user.FaceUrl
  945. scoreUser.VipLevel = user.Vip
  946. scoreUser.VipExpire = user.VipExpire
  947. scoreUser.Decorations = user.Decorations
  948. }
  949. scoreUserList = append(scoreUserList, scoreUser)
  950. }
  951. ts.score_users.PrizeLuckyStarUsers = scoreUserList
  952. ts.lock.Unlock()
  953. log.Release("----enterPrizeState---- %v", prizeStateDesc)
  954. //清除已经离开的用户
  955. ts.clearLeaveUser()
  956. }
  957. // 清除已经离开的用户
  958. func (ts *tablesink) clearLeaveUser() {
  959. ts.lock.Lock()
  960. bankerId := ts.bankerInfo.UserId
  961. for userId, betList := range ts.userBetList {
  962. //庄家忽略
  963. if bankerId == userId {
  964. continue
  965. }
  966. if len(betList) == 0 {
  967. continue
  968. }
  969. usr := ts.table.GetUserByUserId(userId)
  970. if usr == nil {
  971. ts.userList.removeUser(userId)
  972. if ts.removeCandidate(userId) {
  973. ts.broadcastBankerInfo()
  974. }
  975. }
  976. }
  977. ts.lock.Unlock()
  978. }
  979. // 找到投注额的最大值和最小值
  980. func (ts *tablesink) getBetMaxAndMin() (int, int, common.AreaHandCards) {
  981. maxAmount := ts.diamondAmount
  982. minAmount := ts.diamondAmount
  983. var maxType common.AreaHandCards
  984. maxType = common.Area_Diamond //默认选中0
  985. typeAmount := []int{ts.diamondAmount, ts.clubAmount, ts.heartAmount, ts.spadeAmount}
  986. for i, f := range typeAmount {
  987. if f > maxAmount {
  988. maxAmount = f
  989. maxType = common.AreaHandCards(i + 1)
  990. }
  991. if f < minAmount {
  992. minAmount = f
  993. //minType = common.BidType(i+ 1)
  994. }
  995. }
  996. return maxAmount, minAmount, maxType
  997. }
  998. func (ts *tablesink) addHistory() {
  999. Historys := config.OpenHistory{AreaResult: ts.areaResult, SerialNumber: ts.roomInfo.SerialNumber}
  1000. ts.lock.Lock()
  1001. defer ts.lock.Unlock()
  1002. // log.Debug("addHistory ts.roomInfo:%v", ts.roomInfo)
  1003. log.Debug("addHistory Historys:%v", Historys)
  1004. ts.roomInfo.Historys = append(ts.roomInfo.Historys, Historys)
  1005. if len(ts.roomInfo.Historys) > ts.roomInfo.HistoryCount {
  1006. ts.roomInfo.Historys = ts.roomInfo.Historys[1:]
  1007. }
  1008. }
  1009. // 处理结算
  1010. func (ts *tablesink) handleResult(result common.Result, usr *user.UserInfo) int {
  1011. data, _ := json.Marshal(result)
  1012. if usr != nil {
  1013. go ts.table.SendGameData(usr.GetUserIndex(), Result, string(data))
  1014. }
  1015. actualModifyAmount := result.WinAmount
  1016. //这个游戏比较特殊,写分要用WriteUserMoneyWithModifyAmount
  1017. if result.LoseAmount > 0 {
  1018. //输的写分
  1019. actualModifyAmount = ts.table.WriteUserMoneyWithModifyAmount(result.UserId, -result.LoseAmount, result.Tax, 2, 2+common.GAMEID*100, ts.roomInfo.RoomName)
  1020. } else {
  1021. go ts.table.WriteUserMoney(result.UserId, result.WinAmount, result.Tax, 2, 2+common.GAMEID*100, ts.roomInfo.RoomName)
  1022. }
  1023. // 写用户纪录
  1024. var record common.RecordInfo
  1025. record.Result = result
  1026. record.SerialNumber = ts.roomInfo.SerialNumber
  1027. d, _ := json.Marshal(record)
  1028. go transaction.WriteGameRecord(result.UserId, common.GAMEID, ts.roomInfo.RoomName, string(d))
  1029. return actualModifyAmount
  1030. }
  1031. func (ts *tablesink) getHistory() string {
  1032. ts.lock.RLock()
  1033. defer ts.lock.RUnlock()
  1034. data, _ := json.Marshal(ts.roomInfo.Historys)
  1035. return string(data)
  1036. }
  1037. func (ts *tablesink) getBetDesc(bet common.Bet) string {
  1038. return common.GetBetDesc(bet.BetId)
  1039. }
  1040. func (ts *tablesink) getResultDesc(areaResult []int, diamondCards, clubCards, heartCards, spadeCards common.HandCards) string {
  1041. resultDesc := ""
  1042. for i, v := range areaResult {
  1043. resultDesc += " ["
  1044. resultDesc += common.GetResultDesc(i, v)
  1045. if common.BidType(i) == common.BidType_Diamond {
  1046. resultDesc += getHandCardsHex(diamondCards, true)
  1047. } else if common.BidType(i) == common.BidType_Club {
  1048. resultDesc += getHandCardsHex(clubCards, true)
  1049. } else if common.BidType(i) == common.BidType_Heart {
  1050. resultDesc += getHandCardsHex(heartCards, true)
  1051. } else if common.BidType(i) == common.BidType_Spade {
  1052. resultDesc += getHandCardsHex(spadeCards, true)
  1053. }
  1054. resultDesc += "] "
  1055. }
  1056. return resultDesc
  1057. }
  1058. // 广播免费筹码变化
  1059. func (ts *tablesink) onFreeChipsChange() {
  1060. ts.table.SendGameData(-1, FreeChipChange, "")
  1061. }