competition_manager.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. package model
  2. //赛季玩法,骑士团
  3. import (
  4. "rocommon/service"
  5. "rocommon/util"
  6. "roserver/baseserver/model"
  7. "roserver/serverproto"
  8. "time"
  9. )
  10. type CompetitionSeasonManager struct {
  11. updateTimer util.ServerTimer //更新定时器
  12. initStartUp bool
  13. initSendFromDB bool
  14. initRecvFromDB bool
  15. initSendFromDBTime uint64
  16. serverCompetitionData []*serverproto.ServerCompetitionInfo
  17. preCompetitionId, curCompetitionId int32 //当前赛季和下一赛季
  18. curComStartTime, curComEndTime time.Time
  19. curComPeriodTimeList []time.Time //周期结算赛季时间
  20. curCompetitionSubId int32
  21. }
  22. func newCompetitionSeasonManager() *CompetitionSeasonManager {
  23. mag := &CompetitionSeasonManager{
  24. initStartUp: false,
  25. initSendFromDB: false,
  26. initRecvFromDB: false,
  27. }
  28. mag.updateTimer = util.NewDurationTimer(util.GetCurrentTime(), 5000)
  29. return mag
  30. }
  31. //根据开服时间计算开启和结束时间,重置开服时间需要重新初始化(重新启动服务器)
  32. func (this *CompetitionSeasonManager) initConvertCompetitionTime(startUptime uint64, nowTime uint64) {
  33. loc := util.GetLoc()
  34. //初始化当前属于第几赛季
  35. startUpTimeStr := time.Unix(int64(startUptime/1000), 0).In(loc).Format(util.DATE_FORMAT1)
  36. startUpDayTime := util.GetDayByTimeStr1(startUpTimeStr)
  37. //util.InfoF("startUpDayTime=%v", startUpDayTime)
  38. tempSTime := startUpDayTime
  39. //for _, data := range model.ConvertCompTimeIdList {
  40. // tempSTime1 := util.GetTimeByStr(tempSTime.Format(util.DATE_FORMAT1) + " " + data.BeginTimeStr)
  41. // tempETime1 := time.Unix(tempSTime.Unix()+int64(data.Duration-1)*DaySec, 0).In(loc)
  42. // tempETime1 = util.GetTimeByStr(tempETime1.Format(util.DATE_FORMAT1) + " " + data.EndTimeStr)
  43. // util.DebugF("%v | %v", tempSTime1, tempETime1)
  44. //
  45. // data.CalBeginTime = tempSTime1
  46. // data.CalEndTime = tempETime1
  47. //
  48. // for idx := 0; idx < len(data.PeriodEndStrList); idx++ {
  49. // periodDay := data.PeriodEndStrList[idx]
  50. // tempETime1 = time.Unix(tempSTime.Unix()+int64(periodDay-1)*DaySec, 0).In(loc)
  51. // tempETime1 = util.GetTimeByStr(tempETime1.Format(util.DATE_FORMAT1) + " " + data.EndTimeStr)
  52. // util.DebugF("rewardidx=%v", tempETime1)
  53. // data.PeriodEndTimeList = append(data.PeriodEndTimeList, tempETime1)
  54. // }
  55. //
  56. // tempSTime = time.Unix(tempSTime.Unix()+int64(data.Duration+data.ResetTime)*DaySec, 0).In(loc)
  57. //}
  58. nowTimeDate := util.GetTimeByUint64(nowTime)
  59. //下一个赛季根据上一个赛季的开启时间来决定(服务器开启时本赛季已经开启但是服务器赛季数
  60. // 据中没有开启记录,则以当前时间作为本赛季的开启时间)
  61. var serverCompID int32 = 0
  62. for idx := 0; idx < len(this.serverCompetitionData); idx++ {
  63. if this.serverCompetitionData[idx].CompetitionId > serverCompID {
  64. serverCompID = this.serverCompetitionData[idx].CompetitionId
  65. }
  66. }
  67. tmpStartUpDayTime := util.GetDayByTimeStr1(nowTimeDate.Format(util.DATE_FORMAT1))
  68. tempSTime = tmpStartUpDayTime
  69. for _, data := range model.ConvertCompTimeIdList {
  70. if data.CompetitionId <= serverCompID {
  71. for idx := 0; idx < len(this.serverCompetitionData); idx++ {
  72. if this.serverCompetitionData[idx].CompetitionId == data.CompetitionId {
  73. data.CalBeginTime = util.GetTimeByUint64(this.serverCompetitionData[idx].StartTime)
  74. data.CalEndTime = util.GetTimeByUint64(this.serverCompetitionData[idx].EndTime)
  75. util.DebugF("comid=%v %v | %v", data.CompetitionId, data.CalBeginTime, data.CalEndTime)
  76. tmpStartUpTimeStr := data.CalBeginTime.Format(util.DATE_FORMAT1)
  77. tmpStartUpDayTime = util.GetDayByTimeStr1(tmpStartUpTimeStr)
  78. tempSTime = tmpStartUpDayTime
  79. for k := 0; k < len(data.PeriodEndStrList); k++ {
  80. periodDay := data.PeriodEndStrList[k]
  81. tempETime1 := time.Unix(tempSTime.Unix()+int64(periodDay-1)*DaySec, 0).In(loc)
  82. tempETime1 = util.GetTimeByStr(tempETime1.Format(util.DATE_FORMAT1) + " " + data.EndTimeStr)
  83. util.DebugF("rewardidx=%v", tempETime1)
  84. data.PeriodEndTimeList = append(data.PeriodEndTimeList, tempETime1)
  85. }
  86. tempSTime = time.Unix(tempSTime.Unix()+int64(data.Duration+data.ResetTime)*DaySec, 0).In(loc)
  87. break
  88. }
  89. }
  90. } else {
  91. tempSTime1 := util.GetTimeByStr(tempSTime.Format(util.DATE_FORMAT1) + " " + data.BeginTimeStr)
  92. tempETime1 := time.Unix(tempSTime.Unix()+int64(data.Duration-1)*DaySec, 0).In(loc)
  93. tempETime1 = util.GetTimeByStr(tempETime1.Format(util.DATE_FORMAT1) + " " + data.EndTimeStr)
  94. util.DebugF("comid=%v %v | %v", data.CompetitionId, tempSTime1, tempETime1)
  95. //判断根据上个赛季的开始时间当前赛季是否已经开启,如果已经开启则设置当前赛季的
  96. // 开启时间为当前服务器时间,否则使用上个赛季的开启时间
  97. if nowTimeDate.After(tempSTime1) || nowTimeDate.Equal(tempSTime1) {
  98. tmpStartUpDayTime = util.GetDayByTimeStr1(nowTimeDate.Format(util.DATE_FORMAT1))
  99. tempSTime = tmpStartUpDayTime
  100. }
  101. tempSTime1 = util.GetTimeByStr(tempSTime.Format(util.DATE_FORMAT1) + " " + data.BeginTimeStr)
  102. tempETime1 = time.Unix(tempSTime.Unix()+int64(data.Duration-1)*DaySec, 0).In(loc)
  103. tempETime1 = util.GetTimeByStr(tempETime1.Format(util.DATE_FORMAT1) + " " + data.EndTimeStr)
  104. util.DebugF("comid=%v %v | %v", data.CompetitionId, tempSTime1, tempETime1)
  105. data.CalBeginTime = tempSTime1
  106. data.CalEndTime = tempETime1
  107. for idx := 0; idx < len(data.PeriodEndStrList); idx++ {
  108. periodDay := data.PeriodEndStrList[idx]
  109. tempETime1 = time.Unix(tempSTime.Unix()+int64(periodDay-1)*DaySec, 0).In(loc)
  110. tempETime1 = util.GetTimeByStr(tempETime1.Format(util.DATE_FORMAT1) + " " + data.EndTimeStr)
  111. util.DebugF("rewardidx=%v", tempETime1)
  112. data.PeriodEndTimeList = append(data.PeriodEndTimeList, tempETime1)
  113. }
  114. tempSTime = time.Unix(tempSTime.Unix()+int64(data.Duration+data.ResetTime)*DaySec, 0).In(loc)
  115. }
  116. }
  117. }
  118. func (this *CompetitionSeasonManager) init(ms, startUptime uint64) {
  119. if this.initStartUp {
  120. return
  121. }
  122. this.initStartUp = true
  123. //init competition by ServiceStartupTime
  124. this.initConvertCompetitionTime(startUptime, ms)
  125. //初始化当前属于第几赛季
  126. nowTimeDate := util.GetTimeByUint64(ms)
  127. for _, data := range model.ConvertCompTimeIdList {
  128. if (nowTimeDate.After(data.CalBeginTime) || nowTimeDate.Equal(data.CalBeginTime)) &&
  129. (nowTimeDate.Before(data.CalEndTime) || nowTimeDate.Equal(data.CalEndTime)) {
  130. this.curCompetitionId = data.CompetitionId
  131. this.curComStartTime = data.CalBeginTime
  132. this.curComEndTime = data.CalEndTime
  133. this.curComPeriodTimeList = data.PeriodEndTimeList
  134. for idx := 0; idx < len(this.curComPeriodTimeList); idx++ {
  135. tmpTime := this.curComPeriodTimeList[idx]
  136. this.curCompetitionSubId = int32(idx + 1)
  137. if nowTimeDate.Before(tmpTime) {
  138. break
  139. }
  140. }
  141. util.DebugF("CurCompId=%v stime=%v etime=%v subid=%v", this.curCompetitionId, this.curComStartTime,
  142. this.curComEndTime, this.curCompetitionSubId)
  143. //break
  144. continue //计算获得下一个赛季
  145. } else if nowTimeDate.Before(data.CalBeginTime) {
  146. break
  147. } else if nowTimeDate.After(data.CalEndTime) {
  148. this.preCompetitionId = data.CompetitionId
  149. }
  150. }
  151. this.serverCompetitionSaveNtf()
  152. }
  153. const initSendDurationTime uint64 = 1 * 60 * 1000
  154. //成功发送消息返回true
  155. func (this *CompetitionSeasonManager) initCompetitionInfoFromDB() bool {
  156. util.InfoF("initCompetitionInfoFromDB send to db")
  157. ssReqMsg := &serverproto.SSGetServerCompetitionReq{}
  158. if SendDb(ssReqMsg) {
  159. return true
  160. }
  161. return false
  162. }
  163. //获取当前已经开启的赛季ID(from db)
  164. func (this *CompetitionSeasonManager) DoUpdateCompetitionInfoFromDB(ssAckMsg *serverproto.SSGetServerCompetitionAck) {
  165. this.initRecvFromDB = true
  166. this.serverCompetitionData = append(this.serverCompetitionData, ssAckMsg.CompetitionDataList...)
  167. RuneShopMag.StRecRound = ssAckMsg.RounInfo
  168. }
  169. func (this *CompetitionSeasonManager) Update(ms uint64) {
  170. //获取当前服务器的赛季信息
  171. if !this.initSendFromDB {
  172. if this.initSendFromDBTime > 0 && ms-this.initSendFromDBTime <= 5*1000 {
  173. return
  174. }
  175. if this.initCompetitionInfoFromDB() {
  176. this.initSendFromDB = true
  177. this.initSendFromDBTime = ms
  178. }
  179. this.initSendFromDBTime = ms
  180. return
  181. }
  182. if !this.initRecvFromDB {
  183. if ms-this.initSendFromDBTime >= initSendDurationTime {
  184. this.initSendFromDB = false
  185. }
  186. return
  187. }
  188. //开服时间
  189. if !this.initStartUp {
  190. startUpTime := service.GetServiceStartupTime()
  191. if startUpTime > 0 {
  192. this.init(ms, startUpTime)
  193. }
  194. }
  195. if this.initStartUp && this.updateTimer.IsStart() && this.updateTimer.IsExpired(ms) {
  196. nowTimeDate := util.GetTimeByUint64(ms)
  197. if this.curCompetitionId > 0 {
  198. //logUtil.InfoF("curtCompetitionId:%v endTime:%v", this.curCompetitionId, this.curComEndTime)
  199. //赛季结算
  200. if nowTimeDate.After(this.curComEndTime) {
  201. util.InfoF("EndCompetitionSeasonManager id=%v subid=%v endtime=%v", this.curCompetitionId, this.curCompetitionSubId, this.curComEndTime)
  202. this.DoCompetitionReward(this.curCompetitionId, this.curCompetitionSubId)
  203. this.preCompetitionId = this.curCompetitionId
  204. this.curCompetitionId = 0
  205. this.curCompetitionSubId = 0
  206. } else {
  207. //赛季中间周期结算处理
  208. if nowTimeDate.After(this.curComPeriodTimeList[this.curCompetitionSubId-1]) {
  209. util.InfoF("EndCompetitionSeasonManager id=%v subid=%v endtime=%v",
  210. this.curCompetitionId, this.curCompetitionSubId, this.curComPeriodTimeList[this.curCompetitionSubId-1])
  211. this.DoCompetitionReward(this.curCompetitionId, this.curCompetitionSubId)
  212. this.curCompetitionSubId++
  213. }
  214. }
  215. } else {
  216. //开启新赛季
  217. ret, nextData, nextCompetitionId := this.getNexCompetitionTime()
  218. //ret, nextSTime, nextETime, nextCompetitionId := this.getNexCompetitionTime()
  219. if ret && nowTimeDate.After(nextData.CalBeginTime) {
  220. util.InfoF("NewCompetitionSeasonManager id=%v %v-%v", nextCompetitionId, nextData.CalBeginTime, nextData.CalEndTime)
  221. this.curCompetitionId = nextCompetitionId
  222. this.curComStartTime = nextData.CalBeginTime
  223. this.curComEndTime = nextData.CalEndTime
  224. this.curComPeriodTimeList = nextData.PeriodEndTimeList
  225. this.curCompetitionSubId = 1
  226. this.DoCompetitionRefresh()
  227. }
  228. }
  229. }
  230. }
  231. //当前是否处在赛季中(不管具体哪一个赛季)
  232. func (this *CompetitionSeasonManager) IsCompetitionOnline() bool {
  233. if this.curCompetitionId > 0 {
  234. nowTimeDate := util.GetTimeByUint64(util.GetTimeMilliseconds())
  235. if nowTimeDate.Before(this.curComEndTime) || nowTimeDate.Equal(this.curComEndTime) {
  236. return true
  237. }
  238. }
  239. return false
  240. }
  241. func (this *CompetitionSeasonManager) serverCompetitionSaveNtf() {
  242. if this.curCompetitionId > 0 {
  243. bFind := false
  244. for idx := 0; idx < len(this.serverCompetitionData); idx++ {
  245. if this.serverCompetitionData[idx].CompetitionId == this.curCompetitionId {
  246. bFind = true
  247. break
  248. }
  249. }
  250. if !bFind {
  251. addData := &serverproto.ServerCompetitionInfo{
  252. CompetitionId: this.curCompetitionId,
  253. StartTime: uint64(this.curComStartTime.UnixNano() / 1e6),
  254. EndTime: uint64(this.curComEndTime.UnixNano() / 1e6),
  255. }
  256. this.serverCompetitionData = append(this.serverCompetitionData, addData)
  257. ssNtfMsg := &serverproto.SSServerCompetitionInfoSaveNtf{
  258. CompetitionData: addData,
  259. }
  260. SendDb(ssNtfMsg)
  261. }
  262. }
  263. }
  264. func (this *CompetitionSeasonManager) getNexCompetitionTime() (bool, *model.CompetitionTimeData, int32) {
  265. retCompetitionId := this.preCompetitionId
  266. if this.curCompetitionId != 0 {
  267. retCompetitionId = this.curCompetitionId
  268. }
  269. bFind := false
  270. //确保赛季ID不是顺序添加时也生效,中间打断,而不是通过map来查找
  271. for _, data := range model.ConvertCompTimeIdList {
  272. if bFind || retCompetitionId == 0 {
  273. retCompetitionId = data.CompetitionId
  274. return true, data, retCompetitionId
  275. }
  276. if data.CompetitionId == retCompetitionId {
  277. bFind = true
  278. }
  279. }
  280. return false, nil, retCompetitionId
  281. }
  282. func (this *CompetitionSeasonManager) DoCompetitionReward(competitionId int32, subId int32) {
  283. convertData, ok := model.ConvertCompTimeList[competitionId]
  284. if !ok {
  285. util.DebugF("DoSeasonReward data not find competitionId=%v subId=%v", competitionId, subId)
  286. return
  287. }
  288. ssMsg := &serverproto.SSCompetitionRewardReq{
  289. CompetitionId: competitionId,
  290. CompetitionType: convertData.CompetitionType,
  291. CompetitionSubId: subId,
  292. }
  293. if len(convertData.PeriodEndTimeList) == int(subId) {
  294. ssMsg.EndSubId = true
  295. }
  296. for _, chRole := range RoleMag.channelRoleList {
  297. if chRole.GetState() == ROLE_STATE_ONLINE {
  298. ssMsg.RewardUidList = append(ssMsg.RewardUidList, &serverproto.KeyValueType64{
  299. Key: chRole.GetUUid(),
  300. Value: chRole.(*Role).GetRoleArena().GetArenaScore(),
  301. })
  302. if len(ssMsg.RewardUidList) >= 50 {
  303. SendRankService(ssMsg)
  304. ssMsg.RewardUidList = ssMsg.RewardUidList[:0]
  305. }
  306. }
  307. }
  308. //结算数据处理
  309. SendRankService(ssMsg)
  310. if convertData.CompetitionType == int32(model.CompetitionType_Idol) && subId == 3{
  311. this.SendFansReward(int32(model.CompetitionType_Idol), 3, convertData)
  312. }
  313. }
  314. func (this *CompetitionSeasonManager)GMSendReward() {
  315. convertData, ok := model.ConvertCompTimeList[int32(model.CompetitionType_Idol)]
  316. if !ok {
  317. util.DebugF("DoSeasonReward data not find competitionId=%v subId=%v", int32(model.CompetitionType_Idol), 3)
  318. return
  319. }
  320. if convertData.CompetitionType == int32(model.CompetitionType_Idol) {
  321. this.SendFansReward(int32(model.CompetitionType_Idol), 3, convertData)
  322. }
  323. }
  324. func (this *CompetitionSeasonManager) SendFansReward(competitionId int32, subId int32, convertData *model.CompetitionTimeData) {
  325. if convertData == nil {
  326. return
  327. }
  328. ssMsg := &serverproto.SSCompetitionFansGetAllRewardReq{
  329. CompetitionId: competitionId,
  330. CompetitionType: convertData.CompetitionType,
  331. CompetitionSubId: subId,
  332. IsFinish: false,
  333. }
  334. for _, chRole := range RoleMag.channelRoleList {
  335. if chRole.GetState() == ROLE_STATE_ONLINE {
  336. if chRole.(*Role).GetRoleCompetition().idolInfo == nil ||
  337. len(chRole.(*Role).GetRoleCompetition().idolInfo.VoteData) <= 0 {
  338. continue
  339. }
  340. fansData := &serverproto.FansVoteRewardData{
  341. Uid: chRole.GetUUid(),
  342. }
  343. for _, voteData := range chRole.(*Role).GetRoleCompetition().idolInfo.VoteData {
  344. fansData.IdolList = append(fansData.IdolList, &serverproto.KeyValueType64{
  345. Key: voteData.Key,
  346. })
  347. }
  348. ssMsg.Data = append(ssMsg.Data, fansData)
  349. if len(ssMsg.Data) >= 10 {
  350. SendRankService(ssMsg)
  351. ssMsg.Data = ssMsg.Data[:0]
  352. }
  353. }
  354. }
  355. ssMsg.IsFinish = true
  356. SendRankService(ssMsg)
  357. }
  358. func (this *CompetitionSeasonManager) DoCompetitionRefresh() {
  359. // 开启新赛季
  360. this.serverCompetitionSaveNtf()
  361. for _, chRole := range RoleMag.channelRoleList {
  362. if chRole.GetState() == ROLE_STATE_ONLINE {
  363. chRole.(*Role).GetRoleCompetition().CompetitionRefresh()
  364. }
  365. }
  366. }
  367. //给定时间获得可以获得奖励的赛季起始ID(返回的赛季的ID不算在内)
  368. func (this *CompetitionSeasonManager) GetCompetitionIdByTime(uTime uint64) int32 {
  369. var retCompetitionId int32 = 0
  370. uDayTime := util.GetTimeByUint64(uTime)
  371. //util.DebugF("GetCompetitionIdByTime=%v", uDayTime)
  372. for _, data := range model.ConvertCompTimeIdList {
  373. if uDayTime.After(data.CalEndTime) {
  374. retCompetitionId = data.CompetitionId
  375. }
  376. if uDayTime.Before(data.CalBeginTime) ||
  377. (uDayTime.After(data.CalBeginTime) && uDayTime.Before(data.CalEndTime)) {
  378. break
  379. }
  380. }
  381. return retCompetitionId
  382. }
  383. func (this *CompetitionSeasonManager) CompetitionItemCheck(configId int32) int32 {
  384. data, ok := model.ConvertCompTypeList[this.curCompetitionId]
  385. if !ok {
  386. return 0
  387. }
  388. if data.CompetitionItemList.Has(configId) && this.curComEndTime.Unix() > 0 {
  389. if util.GetTimeSeconds() > this.curComEndTime.Unix() {
  390. return 0
  391. }
  392. cfgData := GetItemCfg(configId)
  393. if cfgData != nil && cfgData.ItemTime == Item_Time_Type_Competition_4 {
  394. return -1
  395. }
  396. return int32(this.curComEndTime.Unix())
  397. }
  398. return 0
  399. }