giftmanager.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. package gift
  2. import (
  3. "bet24.com/log"
  4. "bet24.com/servers/common"
  5. coreClient "bet24.com/servers/coreservice/client"
  6. badge "bet24.com/servers/micros/badge/proto"
  7. pb "bet24.com/servers/micros/giftservice/proto"
  8. item "bet24.com/servers/micros/item_inventory/proto"
  9. money "bet24.com/servers/micros/money/proto"
  10. notification "bet24.com/servers/micros/notification/proto"
  11. user "bet24.com/servers/micros/userservices/proto"
  12. "encoding/json"
  13. "sync"
  14. "time"
  15. )
  16. var mgr *giftmanager
  17. func getGiftManager() *giftmanager {
  18. if mgr == nil {
  19. mgr = new(giftmanager)
  20. }
  21. return mgr
  22. }
  23. type chargeInfo struct {
  24. userId int
  25. toUserId int
  26. productId string
  27. }
  28. type giftmanager struct {
  29. giftlist []pb.Gift
  30. lastConfigString string
  31. penddingChargeList []pendingcharge
  32. lock *sync.RWMutex
  33. }
  34. func (gm *giftmanager) run() {
  35. log.Debug("giftmanager.run()")
  36. gm.lock = &sync.RWMutex{}
  37. gm.loadConfig()
  38. gm.checkPendingCharge()
  39. }
  40. func (gm *giftmanager) checkPendingCharge() {
  41. time.AfterFunc(1*time.Minute, gm.checkPendingCharge)
  42. gm.lock.Lock()
  43. defer gm.lock.Unlock()
  44. for i := 0; i < len(gm.penddingChargeList); {
  45. v := gm.penddingChargeList[i]
  46. if v.isTimeout() {
  47. log.Release("giftmanager.checkPendingCharge removing [%d->%d][%s]", v.userId, v.toUserId, v.productId)
  48. gm.penddingChargeList = append(gm.penddingChargeList[:i], gm.penddingChargeList[i+1:]...)
  49. } else {
  50. i++
  51. }
  52. }
  53. }
  54. func (gm *giftmanager) dump(cmd, param1 string) {
  55. switch cmd {
  56. case "sys":
  57. gm.dumpSys()
  58. case "pending":
  59. gm.dumpPendingCharge()
  60. default:
  61. log.Release("giftmanager.dump unhandled cmd %s %s", cmd, param1)
  62. }
  63. }
  64. func (gm *giftmanager) dumpSys() {
  65. log.Release("-------------------------------")
  66. log.Release("giftmanager.dumpSys gift count[%d]", len(gm.giftlist))
  67. defer func() {
  68. log.Release("+++++++++++++++++++++++++++++++")
  69. log.Release("")
  70. }()
  71. for _, v := range gm.giftlist {
  72. log.Release(" Id[%d]Name[%s]Price[%.1f]Charm[%d->%d]Items%v", v.GiftId, v.Name, v.Price,
  73. v.SenderCharm, v.ReceiverCharm, v.Items)
  74. }
  75. }
  76. func (gm *giftmanager) dumpPendingCharge() {
  77. gm.lock.RLock()
  78. defer gm.lock.RUnlock()
  79. log.Release("-------------------------------")
  80. log.Release("giftmanager.dumpPendingCharge gift count[%d]", len(gm.penddingChargeList))
  81. defer func() {
  82. log.Release("+++++++++++++++++++++++++++++++")
  83. log.Release("")
  84. }()
  85. now := time.Now().Unix()
  86. for _, v := range gm.penddingChargeList {
  87. log.Release(" Id[%d]ToUserId[%d]ProductId[%s]Created[%d]", v.userId, v.toUserId, v.productId,
  88. now-v.createTime)
  89. }
  90. }
  91. func (gm *giftmanager) getGiftList(userId int) []pb.Gift {
  92. if len(gm.giftlist) == 0 {
  93. return nil
  94. }
  95. return gm.giftlist
  96. }
  97. func (gm *giftmanager) getGiftListString(userId int) string {
  98. list := gm.getGiftList(userId)
  99. if list == nil {
  100. return ""
  101. }
  102. d, _ := json.Marshal(list)
  103. return string(d)
  104. }
  105. func (gm *giftmanager) getGift(giftId int, userId int) *pb.Gift {
  106. if len(gm.giftlist) == 0 {
  107. return nil
  108. }
  109. for _, v := range gm.giftlist {
  110. if v.GiftId != giftId {
  111. continue
  112. }
  113. ret := v
  114. return &ret
  115. }
  116. return nil
  117. }
  118. func (gm *giftmanager) getGiftByProductId(productId string) *pb.Gift {
  119. if len(gm.giftlist) == 0 {
  120. return nil
  121. }
  122. for _, v := range gm.giftlist {
  123. if v.ProductId != productId {
  124. continue
  125. }
  126. ret := v
  127. return &ret
  128. }
  129. return nil
  130. }
  131. func (gm *giftmanager) sendGift(userId int, toUserId int, giftId int) (int, string) {
  132. if userId == 0 || toUserId == 0 || userId == toUserId {
  133. log.Release("giftmanager.sendGift UserId[%d->%d] GiftId[%d] invalid userId", userId, toUserId, giftId)
  134. return pb.SendGiftRet_Failed, "invalid userId "
  135. }
  136. g := gm.getGift(giftId, userId)
  137. if g == nil {
  138. log.Release("giftmanager.sendGift UserId[%d->%d] GiftId[%d] not found", userId, toUserId, giftId)
  139. return pb.SendGiftRet_Failed, "invalid giftId"
  140. }
  141. // 如果是赠送需要充值的物品,先记录,等充值完毕后再查询进行赠送
  142. if g.PayType == pb.PayType_RMB {
  143. gm.addChargeList(userId, toUserId, g.ProductId)
  144. return pb.SendGiftRet_Charge, g.ProductId
  145. }
  146. if g.PayType == pb.PayType_Diamond {
  147. // 扣钻石
  148. if money.ReduceChip(userId, int(g.Price), common.LOGTYPE_GIFT_SEND, "giftservice", "sendGift", "") != 1 {
  149. return pb.SendGiftRet_Failed, "not enough diamond"
  150. }
  151. } else {
  152. // 扣金币
  153. if !money.ReduceMoney(userId, int(g.Price), common.LOGTYPE_GIFT_SEND, "giftservice", "sendGift", "") {
  154. return pb.SendGiftRet_Failed, "not enough gold"
  155. }
  156. // 徽章进度
  157. go badge.DoAction(userId, badge.Action_PropConsumeGold, int(g.Price), badge.Scope{})
  158. }
  159. gm.doSendGift(userId, toUserId, g)
  160. return pb.SendGiftRet_OK, ""
  161. }
  162. // 赠送礼物,没有需要充值的物品
  163. func (gm *giftmanager) sendGiftBulk(userId int, toUserIds []int, giftId, num int) (int, string, *pb.Gift) {
  164. if userId == 0 || len(toUserIds) == 0 || num <= 0 {
  165. log.Release("giftmanager.sendGiftBulk UserId[%d->%+v] GiftId[%d] num[%d] invalid userId", userId, toUserIds, giftId, num)
  166. return pb.SendGiftRet_Failed, "invalid userId ", nil
  167. }
  168. g := gm.getGift(giftId, userId)
  169. if g == nil {
  170. log.Release("giftmanager.sendGiftBulk UserId[%d->%+v] GiftId[%d] num[%d] not found", userId, toUserIds, giftId, num)
  171. return pb.SendGiftRet_Failed, "invalid giftId", nil
  172. }
  173. items := make([]item.ItemPack, len(g.Items))
  174. copy(items, g.Items)
  175. oneGift := &pb.Gift{
  176. GiftId: g.GiftId,
  177. GiftType: g.GiftType,
  178. Name: g.Name,
  179. Desc: g.Name,
  180. Price: g.Price,
  181. PayType: g.PayType,
  182. ProductId: g.ProductId,
  183. SenderCharm: g.SenderCharm,
  184. ReceiverCharm: g.ReceiverCharm,
  185. Icon: g.Icon,
  186. Items: items,
  187. AnimationType: g.AnimationType,
  188. UserType: g.UserType,
  189. IsBottom: g.IsBottom,
  190. }
  191. // 计算总价(总价=单价*礼物数量*人数)
  192. totalPrice := int(oneGift.Price * float64(num*len(toUserIds)))
  193. // 多个礼物,计算总额
  194. if num > 1 {
  195. for i := 0; i < len(oneGift.Items); i++ {
  196. oneGift.Items[i].Count = oneGift.Items[i].Count * num
  197. }
  198. }
  199. if oneGift.PayType == pb.PayType_Diamond {
  200. // 扣钻石
  201. if money.ReduceChip(userId, totalPrice, common.LOGTYPE_GIFT_SEND, "giftservice", "sendGift", "") != 1 {
  202. return pb.SendGiftRet_Failed, "not enough diamond", nil
  203. }
  204. } else {
  205. // 扣金币
  206. if !money.ReduceMoney(userId, totalPrice, common.LOGTYPE_GIFT_SEND, "giftservice", "sendGift", "") {
  207. return pb.SendGiftRet_Failed, "not enough gold", nil
  208. }
  209. }
  210. for _, toUserId := range toUserIds {
  211. gm.doSendGift(userId, toUserId, oneGift)
  212. }
  213. return pb.SendGiftRet_OK, "", oneGift
  214. }
  215. func (gm *giftmanager) addChargeList(userId, toUserId int, productId string) {
  216. // 去重
  217. idx := gm.getChargeIndex(userId, toUserId, productId)
  218. if idx == -1 {
  219. gm.lock.Lock()
  220. gm.penddingChargeList = append(gm.penddingChargeList,
  221. pendingcharge{userId: userId, toUserId: toUserId, productId: productId})
  222. gm.lock.Unlock()
  223. }
  224. }
  225. func (gm *giftmanager) getChargeIndex(userId, toUserId int, productId string) int {
  226. gm.lock.RLock()
  227. defer gm.lock.RUnlock()
  228. for k, v := range gm.penddingChargeList {
  229. if v.isSame(userId, toUserId, productId) {
  230. return k
  231. }
  232. }
  233. return -1
  234. }
  235. func (gm *giftmanager) removeChargeInfo(userId, toUserId int, productId string) {
  236. gm.lock.Lock()
  237. defer gm.lock.Unlock()
  238. for i := 0; i < len(gm.penddingChargeList); {
  239. if gm.penddingChargeList[i].isSame(userId, toUserId, productId) {
  240. gm.penddingChargeList = append(gm.penddingChargeList[:i], gm.penddingChargeList[i+1:]...)
  241. } else {
  242. i++
  243. }
  244. }
  245. }
  246. func (gm *giftmanager) getAndRemovePendingCharge(userId int, productId string) *pendingcharge {
  247. var ret *pendingcharge
  248. gm.lock.Lock()
  249. defer gm.lock.Unlock()
  250. for i := 0; i < len(gm.penddingChargeList); {
  251. if gm.penddingChargeList[i].isSame(userId, 0, productId) {
  252. ret = &pendingcharge{
  253. userId: userId,
  254. productId: productId,
  255. toUserId: gm.penddingChargeList[i].toUserId,
  256. }
  257. gm.penddingChargeList = append(gm.penddingChargeList[:i], gm.penddingChargeList[i+1:]...)
  258. } else {
  259. i++
  260. }
  261. }
  262. return ret
  263. }
  264. // 充值成功后看下是否为赠送
  265. func (gm *giftmanager) checkGiftCharge(userId int, productId string) bool {
  266. pc := gm.getAndRemovePendingCharge(userId, productId)
  267. // 找不到
  268. if pc == nil {
  269. return false
  270. }
  271. // 给对方发物品
  272. g := gm.getGiftByProductId(productId)
  273. if g == nil {
  274. log.Release("giftmanager.checkGiftCharge [%d] [%s] not found", userId, productId)
  275. return false
  276. }
  277. return gm.doSendGift(userId, pc.toUserId, g)
  278. }
  279. func (gm *giftmanager) doSendGift(userId, toUserId int, g *pb.Gift) bool {
  280. // 成功了,给对方加道具
  281. d, _ := json.Marshal(g.Items)
  282. ug := pb.UserGift{
  283. Sender: userId,
  284. Receiver: toUserId,
  285. GiftId: g.GiftId,
  286. Items: string(d),
  287. SendTime: int(time.Now().Unix()),
  288. }
  289. ug.Rid = addUserGift(ug, g.GiftType)
  290. // 加魅力值
  291. go user.AddUserCharm(userId, g.SenderCharm)
  292. go user.AddUserCharm(toUserId, g.ReceiverCharm)
  293. // 发送私聊信息
  294. // 语音房不发私聊
  295. ugData, _ := json.Marshal(ug)
  296. if pb.GiftType_AudioRoom != g.GiftType {
  297. coreClient.SendGiftMessage(userId, toUserId, string(ugData))
  298. }
  299. // 发通知给对方
  300. notification.AddNotification(userId, notification.Notification_GiftSent, string(ugData))
  301. if g.AnimationType == pb.AnimationType_Global {
  302. notification.AddNotification(-1, notification.Notification_ReceiveGift, string(ugData))
  303. } else {
  304. notification.AddNotification(toUserId, notification.Notification_ReceiveGift, string(ugData))
  305. }
  306. // 潜在好友
  307. go coreClient.FriendAddPotential(userId, toUserId, "send gift")
  308. go coreClient.FriendAddPotential(toUserId, userId, "receive gift")
  309. return true
  310. }
  311. func (gm *giftmanager) getUnclaimedGifts(userId int) []pb.UserGift {
  312. return getUnclaimedGifts(userId)
  313. }
  314. func (gm *giftmanager) claimGift(userId, rid int) string {
  315. itemString := claimUserGift(userId, rid, int(time.Now().Unix()))
  316. log.Debug("giftmanager.claimGift [%d][%d] returns %s", userId, rid, itemString)
  317. type tmpItems struct {
  318. Items string
  319. }
  320. var retItems []tmpItems
  321. err := json.Unmarshal([]byte(itemString), &retItems)
  322. if err != nil {
  323. log.Release("giftmanager.claimGift Unmarshal1 failed %s", itemString)
  324. return ""
  325. }
  326. if len(retItems) == 0 {
  327. return ""
  328. }
  329. var itms []item.ItemPack
  330. err = json.Unmarshal([]byte(retItems[0].Items), &itms)
  331. if err == nil && len(itms) > 0 {
  332. item.AddItems(userId, itms, "claim gift", common.LOGTYPE_GIFT_RECEIVE)
  333. } else {
  334. log.Release("giftmanager.claimGift Unmarshal2 failed %s", itemString)
  335. }
  336. return retItems[0].Items
  337. }
  338. func (gm *giftmanager) getReceivedGiftRecord(userId int) string {
  339. //log.Debug("giftmanager.getReceivedGiftRecord userId[%d]", userId)
  340. ret := getReceivedGiftHistory(userId, pb.GiftType_Nomal, 6)
  341. type tmpItems struct {
  342. GiftID int
  343. Items string
  344. }
  345. var itms []tmpItems
  346. err := json.Unmarshal([]byte(ret), &itms)
  347. if err != nil {
  348. log.Release("giftmanager.getReceivedGiftRecord Unmarshal failed %s", ret)
  349. return ""
  350. }
  351. //log.Debug("giftmanager.getReceivedGiftRecord userId[%d] itms[%s] ", userId, ret)
  352. type giftAndItems struct {
  353. GiftId int
  354. Items []item.ItemPack
  355. }
  356. var retItems []giftAndItems
  357. for _, v := range itms {
  358. var oneItems []item.ItemPack
  359. err := json.Unmarshal([]byte(v.Items), &oneItems)
  360. if err == nil {
  361. retItems = append(retItems, giftAndItems{GiftId: v.GiftID, Items: oneItems})
  362. } else {
  363. log.Debug("giftmanager.getReceivedGiftRecord userId[%d] Unmarshal failed[%s]", userId, v.Items)
  364. }
  365. }
  366. d, _ := json.Marshal(retItems)
  367. log.Debug("giftmanager.getReceivedGiftRecord userId[%d] ret[%s] ", userId, string(d))
  368. return string(d)
  369. }