class RainbowFishGroup(object):
    """
    彩虹鱼鱼群
    """
    def __init__(self, table):
        self.table = table
        self._interval = 100            # 间隔
        self._totalTime = 0             # 总时间
        self._nextRainbowTimer = None	# 下一波彩虹鱼
        self._setRainbowTimer()

    def clearTimer(self):
        if self._nextRainbowTimer:
            self._nextRainbowTimer.cancel()
            self._nextRainbowTimer = None

    def _setRainbowTimer(self):
        """启动彩虹鱼定时器"""
        self.clearTimer()
        self._nextRainbowTimer = FTLoopTimer(self._interval, -1,  self._addRainbowFishGroup)
        self._nextRainbowTimer.start()

    def _addRainbowFishGroup(self):
        """添加彩虹鱼"""
        self._totalTime += self._interval
        if self._totalTime % 3 == 0:
            return
        rainbowGroupId = random.choice(self.table.runConfig.allRainbowGroupIds)
        if rainbowGroupId:
            if ftlog.is_debug():
                ftlog.debug("_addRainbowFishGroup", self.table.tableId, rainbowGroupId)
            self.table.insertFishGroup(rainbowGroupId)
 def _addUserCouponFishGroupNew(self, groupId, userId, totalBullet):
     """
     添加个人可见的奖券鱼
     """
     player = self.table.getPlayer(userId)
     self._clearPlayerTimer(userId)
     if player:
         playerBullet = player.couponConsumeClip
         if playerBullet < totalBullet:
             timer = FTLoopTimer(10, 0, self._addUserCouponFishGroupNew,
                                 groupId, userId, totalBullet)
             timer.start()
             self._playerCouponTimerDict[userId] = timer
             if ftlog.is_debug():
                 ftlog.debug(
                     "_addUserCouponFishGroupNew, check later, tableId =",
                     self.table.tableId, "userId =", userId,
                     "playerBullet =", playerBullet, "totalBullet =",
                     totalBullet)
         else:
             player.resetCouponConsumeClip()
             if ftlog.is_debug():
                 ftlog.debug("_addUserCouponFishGroupNew, tabId =",
                             self.table.tableId, "userId =", userId,
                             "groupId =", groupId)
             self.table.insertFishGroup(groupId,
                                        userId=userId,
                                        sendUserId=userId)
             self._checkUserConditionNew(userId)
示例#3
0
 def _addCouponFishGroup(self, userId):
     """
     添加红包券鱼
     """
     if ftlog.is_debug():
         ftlog.debug("_addCouponFishGroup", userId, self.table.tableId)
     player = self.table.getPlayer(userId)
     catchCouponFishCount = gamedata.getGameAttrInt(
         userId, FISH_GAMEID, GameData.catchCouponFishCount)
     if player and player.taskSystemUser and player.taskSystemUser.curTask:
         if catchCouponFishCount < 10 or player.taskSystemUser.curTask.taskConfig[
                 "type"] == TaskType.CatchRedPacketFishNum:
             taskId = player.taskSystemUser.getCurMainTaskId()
             newbieFishGroupConf = config.getPublic("newbieFishGroupConf",
                                                    {})
             couponFishGroups = newbieFishGroupConf.get(
                 str(taskId), {}).get("couponFishGroups", [])
             data = self._playerCouponTimerDict.get(userId)
             if couponFishGroups and (not data
                                      or data[1].getTimeOut() <= 0):
                 group = self.table.insertFishGroup(
                     random.choice(couponFishGroups),
                     userId=userId,
                     sendUserId=userId)
                 timer = FTLoopTimer(group.totalTime, 0,
                                     self._addCouponFishGroup, userId)
                 timer.start()
                 self._playerCouponTimerDict[userId] = [group, timer]
示例#4
0
class FishPlayerBuffer(object):
    """回馈赛的buffer"""
    def __init__(self, player, bufferId):
        self.player = player
        self.bufferId = bufferId
        self._state = BUFFER_STATE.NOEFFECT
        self.startTime = 0
        self.bufferConf = config.getPlayerBufferConf(bufferId)
        self.checkTimer = FTLoopTimer(self.bufferConf["delayTime"], -1,
                                      self._bufferStart)
        self.checkTimer.start()

        self.sendMsgTimer = None

    def getBufferId(self):
        return self.bufferId

    def isStart(self):
        return self._state == BUFFER_STATE.START

    def _bufferStart(self):
        if self.checkTimer:
            self.checkTimer.cancel()
        self._state = BUFFER_STATE.START
        self.startTime = int(time.time())
        pass
示例#5
0
def regPPSCounter(funCount):
    global _ppsTimer
    if callable(funCount):
        if _ppsTimer == None:
            _ppsTimer = FTLoopTimer(3, -1, _ppsCounter)
            _ppsTimer.start()
        if funCount not in _ppsFunCounts:
            _ppsFunCounts.append(funCount)
示例#6
0
def regPPSCounter(funCount):
    global _ppsTimer
    if callable(funCount):
        if _ppsTimer == None:
            _ppsTimer = FTLoopTimer(3, -1, _ppsCounter)
            _ppsTimer.start()
        if funCount not in _ppsFunCounts:
            _ppsFunCounts.append(funCount)
 def _newJoinTaskAfterTheStart(self, userId):
     """
     任务开始后加入任务
     """
     fun = self._funMap.get(self.currTask, None)
     if fun:
         timer = FTLoopTimer(1, 0, fun.newJoinTaskForAfterTheStart, userId)
         timer.start()
示例#8
0
文件: rpccore.py 项目: zhaozw/hall37
 def __init__(self, markParams, argl, argd):
     super(_FutureResultLocal, self).__init__()
     try:
         ftt = FTLoopTimer(0.01, 0, self._invokeLocal, markParams, argl, argd)
         ftt.start()
     except Exception, e:
         self._status = FutureResult.STATUS_ERROR
         self._exception = e
         ftlog.error()
 def _generalCategoryTimer(self):
     """
     生成并存储各类鱼的定时器
     """
     self.clearCategoryTimer()
     for categoryId, categoryConf in self.autofillFishConf.iteritems():
         interval = categoryConf["cSupplyInterval"]
         checkTimer = FTLoopTimer(interval, -1, self._checkCategoryAutoFillFish, categoryId)
         checkTimer.start()
         self._checkCategoryTimerList.append(checkTimer)
示例#10
0
def _initialize():
    ftlog.debug('endgame._initialize begin')
    global _inited
    if not _inited:
        _inited = True
        _reloadConf()
        pkeventbus.globalEventBus.subscribe(EventConfigure, _onConfChanged)
        loop_timer = FTLoopTimer(3600, -1, process_players)
        loop_timer.start()
    ftlog.debug('endgame._initialize end')
class PlatterFishGroup(object):
    """
    大盘鱼群
    """
    def __init__(self, table):
        self.table = table
        self._fishType = 0
        self._interval = 10
        self._platterGroupId = None
        self._nextPlatterTimer = None
        self._setPlatterTimer()

    def clearTimer(self):
        """清理定时器"""
        if self._nextPlatterTimer:
            self._nextPlatterTimer.cancel()
            self._nextPlatterTimer = None

    def _setPlatterTimer(self):
        """启动大盘鱼群定时器"""
        self.clearTimer()
        self._fishType, self._interval = self._randomFishTypeAndInterval()
        self._nextPlatterTimer = FTLoopTimer(self._interval, -1,
                                             self._addPlatterFishGroup)
        self._nextPlatterTimer.start()

    def _addPlatterFishGroup(self):
        """添加大盘鱼群"""
        if self._fishType not in self.table.runConfig.allPlatterGroupIds:
            return
        if self.table.hasTideFishGroup():  # 当前渔场存在鱼潮
            return
        platterGroupIds = self.table.runConfig.allPlatterGroupIds[
            self._fishType]
        if platterGroupIds:
            self._platterGroupId = random.choice(platterGroupIds)
            self.table.insertFishGroup(self._platterGroupId)
        self._fishType, _ = self._randomFishTypeAndInterval()

    def _randomFishTypeAndInterval(self):
        """随机鱼Id和间隔"""
        fishType = 0
        interval = 10
        randomNum = random.randint(1, 10000)
        for platterFishMap in config.getPlatterFishConf(
                self.table.runConfig.fishPool):
            probb = platterFishMap["probb"]
            if probb[0] <= randomNum <= probb[-1]:
                fishType = int(platterFishMap["fishType"])
                interval = int(platterFishMap["interval"])
                break
        if interval != self._interval and self._nextPlatterTimer is not None:
            self._interval = interval
            self._setPlatterTimer()
        return fishType, interval
示例#12
0
 def startAutofill(self, uid, taskId):
     """
     开始填充
     """
     if uid is None:
         uid = 0
     else:
         uid = int(uid)
     if taskId == 0 or taskId == self.taskId.get(uid):
         return
     if self.overTimeTimer.get(uid):
         self.overTimeTimer[uid].cancel()
         self.overTimeTimer.pop(uid)
     if self.autofillTimerList.get(uid):
         for _timer in self.autofillTimerList[uid]:
             if _timer:
                 _timer.cancel()
         self.autofillTimerList.pop(uid)
     taskConf = None  # 任务配置
     for val in self.tasks[:]:
         if int(val["taskId"]) == int(taskId):
             taskConf = val
             break
     if taskConf is None:
         ftlog.warn("TTAutofillFishGroup, uid =", uid, "taskId =", taskId,
                    "not find !")
         return
     if taskConf.get("taskType", 0) != 1:
         ftlog.warn("TTAutofillFishGroup, uid =", uid, "taskId =", taskId,
                    "type not match !")
         return
     self.taskId[uid] = taskId
     targets = taskConf.get("targets", {})
     target1 = targets.get("target1", 0)
     inter1 = targets.get("inter1", 0)
     target2 = targets.get("target2", 0)
     inter2 = targets.get("inter2", 0)
     if target1 and inter1:
         FTLoopTimer(0.1, 0, self._addAutofillFishGroup, target1).start()
         _timer = FTLoopTimer(inter1, -1, self._addAutofillFishGroup,
                              target1)
         _timer.start()
         self.autofillTimerList.setdefault(uid, []).append(_timer)
     if target2 and inter2:
         FTLoopTimer(0.1, 0, self._addAutofillFishGroup, target2).start()
         _timer = FTLoopTimer(inter2, -1, self._addAutofillFishGroup,
                              target2)
         _timer.start()
         self.autofillTimerList.setdefault(uid, []).append(_timer)
     self.overTimeTimer[uid] = FTLoopTimer(
         taskConf.get("timeLong", 60) + 5, 0, self._overTime, uid)
     self.overTimeTimer[uid].start()
     if ftlog.is_debug():
         ftlog.debug("TTAutofillFishGroup, start, uid =", uid, "taskId =",
                     self.taskId)
 def _generalShoalTimer(self):
     """
     生成并存储各类鱼的鱼群定时器
     """
     self.clearShoalTimer()
     for categoryId, categoryConf in self.autofillFishConf.iteritems():
         interval = categoryConf["sSupplyInterval"]
         if interval > 0:
             checkTimer = FTLoopTimer(interval, -1, self._checkAutoFillFishShoal, categoryId)
             checkTimer.start()
             self._checkShoalTimerList.append(checkTimer)
示例#14
0
class DizhuManagerPlayerTableRoom(DizhuTableRoom):
    def __init__(self, roomDefine, clearIdleInterval=10):
        super(DizhuManagerPlayerTableRoom, self).__init__(roomDefine)
        # 玩家map
        self._playerMap = {}
        # 空闲的玩家Map
        self._idlePlayerMap = LastUpdatedOrderedDict()
        # 定时器清理超时的player
        self._clearIdlePlayerTimer = FTLoopTimer(clearIdleInterval, -1,
                                                 self._clearIdlePlayes)
        self._clearIdlePlayerTimer.start()
        self._keyLock = KeyLock()

    @property
    def keyLock(self):
        return self._keyLock

    def _addPlayer(self, player):
        self._playerMap[player.userId] = player
        self._addIdlePlayer(player)
        self.fire(UserEnterRoomEvent(self, player))

    def _addIdlePlayer(self, player):
        player.idleTime = pktimestamp.getCurrentTimestamp()
        self._idlePlayerMap[player.userId] = player

    def _removeIdlePlayer(self, player):
        try:
            del self._idlePlayerMap[player.userId]
        except:
            pass

    def _leaveRoom(self, player, reason):
        assert (not player.seat)
        if player.isAI:
            return
        self._removeIdlePlayer(player)
        try:
            del self._playerMap[player.userId]
            self.fire(UserLeaveRoomEvent(self, player, reason))
            # ftlog.info('DizhuManagerPlayerTableRoom._leaveRoom',
            #            'roomId=', self.roomId,
            #            'userId=', player.userId,
            #            'reason=', reason)

            clientId = player.clientId
            bireport.reportGameEvent('LEAVE_ROOM', player.userId, self.gameId,
                                     self.roomId, 0, 0, 0, reason, 0, [],
                                     clientId, 0, 0)
        except Exception, e:
            ftlog.error('room_leave BI error', 'gameId=', self.gameId,
                        'roomId=', self.roomId, 'userId=', player.userId,
                        'err=', e.message)
 def _sendTaskInfoForReconnect(self, userId):
     """
     用户断线重连发送任务相关信息
     """
     if util.isRedRoom(self.table.typeName):
         return
     self._sendTaskInfo()
     player = self.table.getPlayer(userId)
     if player and player.currentTask:
         task = player.currentTask[0]
         fun = self._funMap.get(task, None)
         if fun:
             timer = FTLoopTimer(1, 0, fun.sendTaskInfoForReconnect, userId)
             timer.start()
class MultipleFishGroup(object):
    """
    倍率鱼群(回馈赛专用)
    """
    def __init__(self, table):
        self.table = table
        self._tableRank = 0
        self._nextGroupTimer = None

    def clearTimer(self):
        if self._nextGroupTimer:
            self._nextGroupTimer.cancel()
            self._nextGroupTimer = None

    def initGroup(self, tableRank):
        """初始化倍率鱼群"""
        self._tableRank = tableRank
        self._setNextGroupTimer()

    def _setNextGroupTimer(self):
        """启动倍率鱼定时器"""
        self.clearTimer()
        interval = random.randint(25, int((1 - self._tableRank) * 30 + 30))
        self._nextGroupTimer = FTLoopTimer(interval, 0,
                                           self._addMultipleFishGroup)
        self._nextGroupTimer.start()

    def _addMultipleFishGroup(self):
        """添加倍率鱼群"""
        randomNum = random.randint(1, 10000)
        for multipleFishMap in config.getRandomMultipleFishConf(
                self.table.runConfig.fishPool):
            probb = multipleFishMap["probb"]
            if probb[0] <= randomNum <= probb[-1]:
                fishType = multipleFishMap["fishType"]
                allMultipleGroupIds = self.table.runConfig.allMultipleGroupIds
                groupId = random.choice(allMultipleGroupIds[fishType])
                if ftlog.is_debug():
                    ftlog.debug("_addMultipleFishGroup", fishType,
                                allMultipleGroupIds, groupId)
                self.table.insertFishGroup(groupId)
                self._setNextGroupTimer()
                break

    def cancelNextGroupTimer(self):
        """取消定时器"""
        if self._nextGroupTimer:
            self._nextGroupTimer.cancel()
            self._nextGroupTimer = None
    def _sendTaskInfo(self):
        """
        发送任务倒计时信息
        """
        ftlog.debug("sendCmpttTaskInfo =", self.showCmpttInfo)
        # 发送夺宝赛倒计时信息
        if self.showCmpttInfo and self._cmpttTask:
            cmpttTimer = FTLoopTimer(1, 0, self._cmpttTask.sendCmpttTaskInfo)
            cmpttTimer.start()

        ftlog.debug("sendBonusTaskInfo =", self.showBonusInfo)
        # 发送奖金池倒计时信息
        if self.showBonusInfo and self._bonusTask:
            bonusTimer = FTLoopTimer(1, 0, self._bonusTask.sendBonusTaskInfo)
            bonusTimer.start()
示例#18
0
class SportOdds(object):
    '''欧指筛选'''
    ODDS = ['17', '308', '255', '256', '254']

    def __init__(self, sportlottery):
        self.sportlottery = sportlottery

        self.timer = FTLoopTimer(10, -1, self._getHttpOdds)
        self.timer.start()

        if ftlog.is_debug():
            ftlog.debug('SportOdds', 'sportObj=', self.sportlottery.toDict())

    def _getHttpOdds(self):
        if ftlog.is_debug():
            ftlog.debug('SportOdds', '_getHttpOdds=',
                        self.sportlottery.toDict())

        contents = http7Mgethdaoddsinfo(self.sportlottery.matchId)
        if not contents or len(contents) == 0:
            return

        if contents.get('GameId') != str(self.sportlottery.matchId):
            ftlog.warn('SportOdds httpOdds GameId not match', 'matchId=',
                       self.sportlottery.matchId, 'GameId=',
                       contents.get('GameId'))
            return

        Datas = contents.get('Datas')
        if not Datas or len(Datas) == 0:
            ftlog.warn('SportOdds httpOdds Datas empty', 'Datas=', Datas,
                       'contents=', contents)
            return

        tag = 0
        for data in Datas:
            if data.get('Cid') in self.ODDS:
                odds = data.get('Data', [])
                if odds and len(odds) >= 3:
                    self.sportlottery.odds = odds[:3]
                    self.sportlottery.save()
                    if self.timer:
                        self.timer.cancel()

                    tag = 1
                    break
        if self.sportlottery and tag == 1:
            self.sportlottery.clearSportOdds()
 def _checkUserConditionNew(self, userId):
     """
     检查个人可见奖券鱼出现条件是否满足
     """
     userCouponFishConf = config.getUserCouponFishConf(
         self.table.runConfig.fishPool)
     groupId, interval, totalBullet = self._isAppearUserCouponFishNew(
         userId, userCouponFishConf)
     if groupId:
         timer = FTLoopTimer(interval, 0, self._addUserCouponFishGroupNew,
                             groupId, userId, totalBullet)
         timer.start()
         self._playerCouponTimerDict[userId] = timer
         if ftlog.is_debug():
             ftlog.debug("_checkUserConditionNew->userId =", userId,
                         "groupId =", groupId, "interval =", interval,
                         "totalBullet =", totalBullet, "tableId =",
                         self.table.tableId)
示例#20
0
 def _addTerrorFishGroup(self, userId):
     """
     添加Terror鱼
     """
     if ftlog.is_debug():
         ftlog.debug("_addTerrorFishGroup", userId, self.table.tableId)
     player = self.table.getPlayer(userId)
     if player and player.taskSystemUser:
         taskId = player.taskSystemUser.getCurMainTaskId()
         newbieFishGroupConf = config.getPublic("newbieFishGroupConf", {})
         terrorFishGroups = newbieFishGroupConf.get(str(taskId), {}).get(
             "terrorFishGroups", [])
         data = self._playerTerrorTimerDict.get(userId)
         if terrorFishGroups and (not data or data[1].getTimeOut() <= 0):
             group = self.table.insertFishGroup(
                 random.choice(terrorFishGroups),
                 userId=userId,
                 sendUserId=userId)
             timer = FTLoopTimer(120, 0, self._addTerrorFishGroup, userId)
             timer.start()
             self._playerTerrorTimerDict[userId] = [group, timer]
示例#21
0
 def _setAutofillFishTimer(self):
     """
     设置自动填充鱼的定时器
     """
     for idx, fishConf in enumerate(self.autofillFishConf):
         self.fishTypeList.append(
             [fish["fishType"] for fish in fishConf["fish"]])
         interval = random.randint(fishConf["minInterval"],
                                   fishConf["maxInterval"])  # 自动添加鱼的时间间隔
         fishTimer = FTLoopTimer(interval, 0, self._addAutofillFishGroup,
                                 idx)
         fishTimer.start()
         self._nextTimerList.append(fishTimer)
         supplyInterval = fishConf["supplyInterval"]  # 补充鱼时间间隔
         checkTimer = FTLoopTimer(max(3, supplyInterval), -1,
                                  self._checkFishTypeCount, idx)
         checkTimer.start()
         self._checkCountTimerList.append(checkTimer)
     if ftlog.is_debug():
         ftlog.debug("_setAutofillFishTimer", "tableId =",
                     self.table.tableId, self.fishTypeList)
示例#22
0
 def _addSharkFishGroup(self, userId):
     """
     添加大白鲨
     """
     player = self.table.getPlayer(userId)
     if player and player.taskSystemUser:
         taskId = player.taskSystemUser.getCurMainTaskId()
         if ftlog.is_debug():
             ftlog.debug("_addSharkFishGroup", userId, self.table.tableId,
                         taskId)
         newbieFishGroupConf = config.getPublic("newbieFishGroupConf", {})
         sharkFishGroups = newbieFishGroupConf.get(str(taskId), {}).get(
             "sharkFishGroups", [])
         data = self._playerSharkTimerDict.get(userId)
         if sharkFishGroups and (not data or data[1].getTimeOut() <= 0):
             group = self.table.insertFishGroup(
                 random.choice(sharkFishGroups),
                 userId=userId,
                 sendUserId=userId)
             timer = FTLoopTimer(group.totalTime + 1, 0,
                                 self._addSharkFishGroup, userId)
             timer.start()
             self._playerSharkTimerDict[userId] = [group, timer]
示例#23
0
class GrandPrixFishGroup(object):
    """
    grandprix鱼群
    """
    def __init__(self, table):
        self._fishTypes = config.getGrandPrixConf("group").values()
        self._interval = 60
        self.table = table
        self._idx = 0
        self._nextGrandPrixTimer = None
        self._setGrandPrixTimer()

    def clearTimer(self):
        """清理定时器"""
        if self._nextGrandPrixTimer:
            self._nextGrandPrixTimer.cancel()
            self._nextGrandPrixTimer = None

    def _setGrandPrixTimer(self):
        """设置大奖赛定时器"""
        self._idx = 0
        self.clearTimer()
        self._nextGrandPrixTimer = FTLoopTimer(self._interval, -1,
                                               self._addGrandPrixFishGroup)
        self._nextGrandPrixTimer.start()

    def _addGrandPrixFishGroup(self):
        """增加大奖赛鱼群"""
        for _val in self._fishTypes:
            _fishType = _val[self._idx % len(_val)]
            if _fishType in self.table.runConfig.allGrandPrixGroupIds:
                grandPrixGroupIds = self.table.runConfig.allGrandPrixGroupIds[
                    _fishType]
                if grandPrixGroupIds:
                    grandPrixGroupId = random.choice(grandPrixGroupIds)
                    self.table.insertFishGroup(grandPrixGroupId)  # 召唤大奖赛鱼群
        self._idx += 1
class FishGrandPrixPlayer(FishMultiplePlayer):
    def _loadUserData(self):
        super(FishGrandPrixPlayer, self)._loadUserData()
        # 捕鱼积分
        self.grandPrixFishPoint = weakdata.getDayFishData(
            self.userId, WeakData.grandPrix_fishPoint, 0)
        # 大奖赛剩余开火次数
        self.grandPrixFireCount = weakdata.getDayFishData(
            self.userId, WeakData.grandPrix_fireCount, 0)
        # 大奖赛剩余技能使用次数
        self.grandPrixUseSkillTimes = weakdata.getDayFishData(
            self.userId, WeakData.grandPrix_useSkillTimes, [])
        # 大奖赛目标鱼捕获数量
        self.grandPrixTargetFish = weakdata.getDayFishData(
            self.userId, WeakData.grandPrix_targetFish, {})
        # 大奖赛火炮等级和倍率
        # self.grandPrixLevelFpMultiple = weakdata.getDayFishData(self.userId, WeakData.grandPrix_levelFpMultiple)
        # 大奖赛开始的时间戳
        self.grandPrixStartTS = weakdata.getDayFishData(
            self.userId, WeakData.grandPrix_startTS, 0)
        # 大奖赛结束定时器
        self.grandPrixEndTimer = None
        # 大奖赛提示定时器
        self.grandPrixTipTimer = None
        # 大奖赛阶段奖励
        self.grandPrixGetPointsInfo = weakdata.getDayFishData(
            self.userId, WeakData.grandPrix_getPointsInfo, [])
        self._freeTimes = weakdata.getDayFishData(self.userId,
                                                  WeakData.grandPrix_freeTimes,
                                                  0)

        self.multipleList = []  # 10、50、200、500
        for v in gdata.roomIdDefineMap().values():
            roomConf = v.configure
            if roomConf.get("typeName") not in [config.FISH_FRIEND]:
                continue
            self.multipleList.append(roomConf.get("multiple", 1))
        self.multipleList.sort()

        self._rankListCache = []  # 超越玩家的集合
        self._surpassUser = {}
        self.grandPrixSurpassCount = weakdata.getDayFishData(
            self.userId, WeakData.grandPrix_surpassCount, 0)  # 大奖赛超越自己次数
        self.bestPoint = weakdata.getDayFishData(self.userId,
                                                 WeakData.grandPrix_point, 0)
        self.inGameTimes = 0  # 游戏时长(分钟)

    def _incrGameTimer(self):
        """增加游戏时长"""
        if self.userId <= 0:
            return
        super(FishGrandPrixPlayer, self)._incrGameTimer()
        self.inGameTimes += 1

    def _checkSkillCondition(self, skillId, select, skillType=0):
        """
        检测技能使用条件
        """
        if self.isGrandPrixMode() and select:  # 大奖赛模式限制技能槽的使用次数
            for idx, val in enumerate(self.grandPrixUseSkillTimes):
                if val.get("skillId") == skillId and val.get("skillType",
                                                             0) == skillType:
                    if val.get("count") <= 0:
                        return 7
                    break
        return super(FishGrandPrixPlayer,
                     self)._checkSkillCondition(skillId, select, skillType)

    def addFire(self,
                bulletId,
                wpId,
                sendTimestamp,
                fpMultiple,
                gunMultiple=1,
                gunX=1,
                skill=None,
                power=None,
                clientFire=True,
                targetPos=None,
                fishType=None,
                costChip=0,
                superBullet=None):
        """添加开火信息"""
        super(FishGrandPrixPlayer,
              self).addFire(bulletId, wpId, sendTimestamp, fpMultiple,
                            gunMultiple, gunX, skill, power, clientFire,
                            targetPos, fishType, costChip, superBullet)
        if clientFire and skill is None and self.isGrandPrixMode():
            self.grandPrixFireCount -= 1  # 开火次数减少
            if self.grandPrixFireCount == 0:  # 结束比赛
                self.endGrandPrix()

    def _refreshSkillSlots(self, skillType=0):
        """
        刷新技能数据 安装技能槽
        """
        if skillType == 0:
            self.skillSlots = {}
        if self.grandPrixUseSkillTimes:
            for val in self.grandPrixUseSkillTimes:
                if isinstance(val, dict) and val.get("skillId"):
                    if val.get("skillType", 0) == skillType:
                        if skillType == 0:
                            self.skillSlots[val["skillId"]] = [
                                val["state"], val["star"], val["grade"]
                            ]
        else:
            super(FishGrandPrixPlayer, self)._refreshSkillSlots(skillType)

    def clearTimer(self):
        """清理提示和结束的定时器"""
        super(FishGrandPrixPlayer, self).clearTimer()
        if self.grandPrixEndTimer:
            self.grandPrixEndTimer.cancel()
            self.grandPrixEndTimer = None
        if self.grandPrixTipTimer:
            self.grandPrixTipTimer.cancel()
            self.grandPrixTipTimer = None
        if self.inGameTimes:
            bireport.reportGameEvent("BI_NFISH_GRAND_PRIX_INGAMETIMES",
                                     self.userId, FISH_GAMEID, 0, 0,
                                     self.grandPrixStartTS, self.inGameTimes,
                                     0, 0, [], util.getClientId(self.userId))

    def checkCanFire(self, fPos, wpId, bulletId, skillId, skillType):
        """
        检测玩家是否可以开火
        """
        canFire, reason, clip, costBullet, extends, skill = \
            super(FishGrandPrixPlayer, self).checkCanFire(fPos, wpId, bulletId, skillId, skillType)
        if canFire and self.isGrandPrixMode() and self.grandPrixFireCount <= 0:
            canFire, reason = False, 8
        return canFire, reason, clip, costBullet, extends, skill

    def sendFireMsg(self, userId, seatId, extends, params):
        """
        发送开火确认消息
        """
        fPos = params.get("fPos")
        wpId = params.get("wpId")
        bulletId = params.get("bulletId")
        skillId = params.get("skillId")
        timestamp = params.get("timestamp")
        canFire = params.get("canFire")
        reason = params.get("reason")
        clip = params.get("clip")
        skillType = params.get("skillType", 0)
        lockFId = params.get("lockFId", 0)
        fPosx, fPosy = fPos
        retMsg = MsgPack()
        retMsg.setCmd("fire")
        retMsg.setResult("gameId", FISH_GAMEID)
        retMsg.setResult("userId", userId)
        retMsg.setResult("wpId", wpId)
        retMsg.setResult("bulletId", bulletId)
        retMsg.setResult("skillId", skillId)
        retMsg.setResult("skillType", skillType)
        retMsg.setResult("extends", extends)
        retMsg.setResult("timestamp", timestamp)
        retMsg.setResult("reason", reason)
        retMsg.setResult("grandPrixFireCount",
                         self.grandPrixFireCount)  # 大奖赛剩余开火次数
        retMsg.setResult("clip", clip)
        retMsg.setResult("lockFId", lockFId)
        superBullet = self.getFire(bulletId).get(
            "superBullet", {})  # self.isSuperBullet(bulletId)
        retMsg.setResult("superBullet", 1 if superBullet else 0)  # 测试代码
        GameMsg.sendMsg(retMsg, userId)
        if canFire:
            retMsg.setResult("fPosx", fPosx)
            retMsg.setResult("fPosy", fPosy)
            retMsg.setResult("seatId", seatId)
            GameMsg.sendMsg(retMsg, self.table.getBroadcastUids(userId))

    def saveUserData(self):
        """保存用户数据"""
        super(FishGrandPrixPlayer, self).saveUserData()
        self.saveGrandPrixPoint()  # 保存大奖赛积分

    def getTargetFishs(self):
        """
        返回目标鱼(魔术炮技能召唤使用)
        """
        fishes = super(FishGrandPrixPlayer, self).getTargetFishs()
        targetFish = [
            int(ft) for ft, val in self.grandPrixTargetFish.iteritems()
            if val[0] < val[1]
        ]  # 0 < 5目标鱼数量
        if targetFish:
            fishes.extend(targetFish)
        return fishes

    def getMatchingFpMultiple(self, fpMultiple):
        """
        获取玩家渔场倍率对应的基础倍率
        """
        multiple = self.table.runConfig.multiple
        for mul in self.multipleList:
            if fpMultiple >= mul:
                multiple = mul
        return multiple

    def isGrandPrixMode(self):
        """
        大奖赛比赛模式
        """
        return self.grandPrixStartTS > 0

    def _calcuCatchFishGrandPrixPoint(self, fishPoint, gunX):
        """
        计算捕鱼积分 炮倍和vip的加成
        """
        if ftlog.is_debug():
            ftlog.debug('calcuCatchFishGrandPrixPoint', fishPoint, gunX)
        vipAddition = config.getVipConf(self.vipLevel).get(
            "grandPrixAddition", 0.)
        gunXAddition = self.getGunXAddition(gunX)
        if ftlog.is_debug():
            ftlog.debug('calcuCatchFishGrandPrixPoint1', vipAddition,
                        gunXAddition)
        point = fishPoint * 100
        points = point * (1 + vipAddition) * (1 + gunXAddition)
        return int(points)

    def getGunXAddition(self, gunX):
        """
        根据开火时候[炮倍 * 炮(单倍率|双倍率)]确定 加成值
        """
        gunMInfo = config.getGrandPrixConf("gunMultiAddition")
        for info in gunMInfo:
            if info["rangeList"][0] <= gunX <= info["rangeList"][1]:
                return info["addition"]
        return 0

    def saveGrandPrixPoint(self):
        """
        保存大奖赛积分
        """
        if not self.isGrandPrixMode():
            return 0, 0
        grandPrixFinalPoint = self.grandPrixFishPoint
        # 计入排行榜
        if grandPrixFinalPoint:
            ranking_system.refreshGrandPrixPoint(self.userId,
                                                 grandPrixFinalPoint)
        # 保存大奖赛数据
        self._saveGrandPrixData()
        return int(grandPrixFinalPoint)  # 最后的积分

    def cancelUsingSkills(self):
        """
        取消处于使用中的技能
        """
        if not self.usingSkill:  # 有之前技能记录
            return
        lastSkillId = self.usingSkill[-1].get("skillId")
        lastSkillType = self.usingSkill[-1].get("skillType", 0)
        lastSkill = self.getSkill(lastSkillId, lastSkillType)
        if not lastSkill:
            return
        if lastSkill.state == 1:
            lastSkill.use(0)
        else:
            self.removeUsingSkill(lastSkillId, lastSkillType)
            orgState = lastSkill.state
            lastSkill.state = 0
            self.table.broadcastSkillUse(lastSkill, 0, self.userId,
                                         orgState)  # 广播选中/取消技能消息
        self.table.broadcastGunChange(self)  # 广播玩家现在的火炮等级

    def unloadSkills(self):
        """
        下载所有技能
        """
        for _skillId in self.skills.keys():
            _skill = self.getSkill(_skillId, 0)
            if not _skill:
                continue
            _skill.clear()
            del _skill

    def startGrandPrix(self):
        """
        大奖赛开始 grandPrixStartTS=0 报名大奖赛/ grandPrixStartTS > 0 直接进入渔场
        """
        curTime = int(time.time())
        dayStartTimestamp = util.getDayStartTimestamp(curTime)
        remainGrandPrixTimeSeconds = util.timeStrToInt(
            config.getGrandPrixConf("openTimeRange")[1]) - (
                curTime - dayStartTimestamp)  # 大奖赛剩余时间
        # 当局进入大奖赛
        if self.grandPrixStartTS == 0:
            event = JoinGrandPrixEvent(self.userId, FISH_GAMEID,
                                       self.table.bigRoomId)  # 参加大奖赛事件
            TGFish.getEventBus().publishEvent(event)
            # 距离大奖赛结束不足10秒不可参赛
            if not grand_prix.isGrandPrixOpenTime(
            ) or remainGrandPrixTimeSeconds < 10:
                code = SignupCode.SC_NOT_OPEN
            elif config.getVipConf(self.vipLevel).get(
                    "grandPrixFreeTimes", 0) > self._freeTimes:  # 用免费次数报名
                self._freeTimes = weakdata.incrDayFishData(
                    self.userId, WeakData.grandPrix_freeTimes, 1)
                code = SignupCode.SC_SUCC
            else:
                # 扣除报名费
                fee = config.getGrandPrixConf("fee")[0]
                _consume = [{
                    "name": fee.get("name"),
                    "count": fee.get("count")
                }]
                _ret = util.consumeItems(self.userId, _consume, "ITEM_USE",
                                         self.table.roomId)
                if _ret:
                    code = SignupCode.SC_SUCC
                else:
                    code = SignupCode.SC_FEE_NOT_ENOUGH
            if code == SignupCode.SC_SUCC:
                # 选择目标鱼
                for _val in config.getGrandPrixConf(
                        "group").values():  # 1、2、3个组
                    idx = random.randint(0, len(_val) - 1)  # 一组鱼
                    _cnt = config.getGrandPrixConf("target").get(
                        str(_val[idx]), {}).get("count", 999)  # 某一种鱼 捕获数量
                    _point = config.getGrandPrixConf("target").get(
                        str(_val[idx]), {}).get("point", 0)  # 某一种鱼 获得的积分
                    self.grandPrixTargetFish[str(
                        _val[idx])] = [0, _cnt, _point]

                # 备份技能数据.
                self.grandPrixUseSkillTimes = []
                for i in range(skill_system.MAX_INSTALL_NUM - 1):
                    self.grandPrixUseSkillTimes.append({
                        "skillId":
                        0,
                        "state":
                        0,
                        "star":
                        0,
                        "grade":
                        0,
                        "count":
                        config.getGrandPrixConf("fireCount")[1],  # 技能使用次数3
                        "skillType":
                        0 if i < skill_system.MAX_INSTALL_NUM else
                        1  # 0主技能 1辅助技能
                    })

                for idx, _skillId in enumerate(self.skillSlots):
                    _skill = self.getSkill(_skillId, 0)
                    self.grandPrixUseSkillTimes[idx]["skillId"] = _skillId
                    self.grandPrixUseSkillTimes[idx][
                        "state"] = _skill.skillState
                    self.grandPrixUseSkillTimes[idx]["star"] = _skill.skillStar
                    self.grandPrixUseSkillTimes[idx][
                        "grade"] = _skill.skillGrade

                if self.inGameTimes:
                    bireport.reportGameEvent("BI_NFISH_GRAND_PRIX_INGAMETIMES",
                                             self.userId, FISH_GAMEID, 0, 0,
                                             self.grandPrixStartTS,
                                             self.inGameTimes, 0, 0, [],
                                             util.getClientId(self.userId))
                    self.inGameTimes = 0

                self.grandPrixFishPoint = 0
                self.grandPrixSurpassCount = 0
                self.grandPrixStartTS = curTime  # 大奖赛开始的时间戳
                self.grandPrixFireCount = config.getGrandPrixConf(
                    "fireCount")[0]
                self._saveGrandPrixData()  # 保存大奖赛数据
        else:
            if not grand_prix.isGrandPrixOpenTime():  # 现在不可参赛
                code = SignupCode.SC_NOT_OPEN
            elif not self.isGrandPrixMode():
                code = SignupCode.SC_SUCC
            else:
                code = SignupCode.SC_UNFINISH

        if code in [SignupCode.SC_SUCC, SignupCode.SC_UNFINISH]:
            interval = max(0.1, remainGrandPrixTimeSeconds)
            if self.grandPrixFireCount == 0:  # 3秒之后结束大奖赛
                interval = 0.1
            if self.grandPrixEndTimer:
                self.grandPrixEndTimer.cancel()
                self.grandPrixEndTimer = None
            self.grandPrixEndTimer = FTLoopTimer(interval, 0,
                                                 self.endGrandPrix)  # 启动结束定时器
            self.grandPrixEndTimer.start()
            # 取消处于使用中的技能,以免干扰技能使用次数计数
            if self.offline == 0:  # 玩家在线
                self.cancelUsingSkills()
                self.unloadSkills()
                self.loadAllSkillData()
                self.syncSkillSlots()
        elif code == SignupCode.SC_NOT_OPEN:  # 没开启
            self._resetGrandPrixData()  # 重置大奖赛相关数据

        self._getSurpassTarget()  # 获取要超越的玩家数据
        mo = MsgPack()
        mo.setCmd("start_grand_prix")
        mo.setResult("gameId", FISH_GAMEID)
        mo.setResult("userId", self.userId)
        mo.setResult("seatId", self.seatId)
        mo.setResult("fireCount", self.grandPrixFireCount)
        mo.setResult("fishPoint", self.grandPrixFishPoint)
        mo.setResult("targetFish", self.grandPrixTargetFish)
        mo.setResult(
            "useSkillTimes", {
                val.get("skillId", 0): val.get("count", 0)
                for val in self.grandPrixUseSkillTimes
            })
        mo.setResult("pointsInfo", grand_prix.getPointInfo(
            self.userId))  # 奖励积分 道具Id、道具数量、是否领取了奖励0|1
        mo.setResult("todayMaxPoints",
                     weakdata.getDayFishData(self.userId,
                                             WeakData.grandPrix_point,
                                             0))  # 今日最高积分
        GameMsg.sendMsg(mo, self.userId)

    def endGrandPrix(self):
        """
        大奖赛结束
        """
        if self.userId == 0:
            return

        if self.grandPrixEndTimer:
            self.grandPrixEndTimer.cancel()
            self.grandPrixEndTimer = None

        if not self.isGrandPrixMode():
            return

        grandPrixFinalPoint = self.saveGrandPrixPoint()
        # 完成大奖赛事件
        event = FinishGrandPrixEvent(self.userId, FISH_GAMEID,
                                     self.table.bigRoomId, grandPrixFinalPoint)
        TGFish.getEventBus().publishEvent(event)
        bireport.reportGameEvent("BI_NFISH_GRAND_PRIX_END", self.userId,
                                 FISH_GAMEID, 0, 0, grandPrixFinalPoint, 0, 0,
                                 0, [], util.getClientId(self.userId))
        if self.inGameTimes:
            bireport.reportGameEvent("BI_NFISH_GRAND_PRIX_INGAMETIMES",
                                     self.userId, FISH_GAMEID, 0, 0,
                                     self.grandPrixStartTS, self.inGameTimes,
                                     0, 0, [], util.getClientId(self.userId))
            self.inGameTimes = 0

        self.cancelUsingSkills()  # 恢复技能数据 取消处于使用中的技能
        self.unloadSkills()  # 下载所有技能
        self._resetGrandPrixData()  # 重置数据存档
        self.loadAllSkillData()  # 重新加载技能 读取并初始化所有技能数据
        self.syncSkillSlots()  # 同步技能槽消息
        rank, rankRewards = ranking_system.getUserRankAndRewards(
            RankType.TodayGrandPrix, self.userId)
        if ftlog.is_debug():
            ftlog.debug("endGrandPrix", self.grandPrixStartTS,
                        self.grandPrixFireCount, self.grandPrixFishPoint)
        mo = MsgPack()
        mo.setCmd("end_grand_prix")
        mo.setResult("gameId", FISH_GAMEID)
        mo.setResult("userId", self.userId)
        mo.setResult("seatId", self.seatId)
        mo.setResult("fishPoint", grandPrixFinalPoint)
        mo.setResult("rank", rank)
        mo.setResult("rankRewards", rankRewards)
        mo.setResult("fee", config.getGrandPrixConf("fee"))
        mo.setResult(
            "tabs",
            ranking_system.getRankingTabs(self.userId,
                                          util.getClientId(self.userId),
                                          RankType.TodayGrandPrix,
                                          rankDetail=True))
        GameMsg.sendMsg(mo, self.userId)
        self.sendGrandPrixInfo()
        self.table.clearPlayer(self)  # 从桌子中踢掉玩家

    def _resetGrandPrixData(self):
        """
        重置大奖赛相关数据
        """
        self.grandPrixStartTS = 0  # 大奖赛开始的时间戳
        self.grandPrixFireCount = 0  # 大奖赛剩余开火次数
        self.grandPrixTargetFish = {}  # 大奖赛目标鱼捕获数量
        self.grandPrixUseSkillTimes = []  # 大奖赛剩余技能使用次数
        self.grandPrixFishPoint = 0  # 捕鱼积分
        self.grandPrixSurpassCount = 0  # 大奖赛超越自己次数
        # self.grandPrixLevelFpMultiple = None        # 大奖赛火炮等级和倍率
        self._rankListCache = []  # 要超越的玩家缓存
        self._surpassUser = {}  # 要超越玩家数据
        self._saveGrandPrixData()  # 保存大奖赛信息
        weakdata.setDayFishData(self.userId, WeakData.grandPrix_surpassCount,
                                0)  # 大奖赛超越自己次数

    def _saveGrandPrixData(self):
        """
        保存大奖赛数据
        """
        weakdata.setDayFishData(self.userId, WeakData.grandPrix_startTS,
                                self.grandPrixStartTS)
        weakdata.setDayFishData(self.userId, WeakData.grandPrix_fireCount,
                                self.grandPrixFireCount)
        weakdata.setDayFishData(self.userId, WeakData.grandPrix_fishPoint,
                                self.grandPrixFishPoint)
        weakdata.setDayFishData(self.userId, WeakData.grandPrix_surpassCount,
                                self.grandPrixSurpassCount)
        weakdata.setDayFishData(self.userId, WeakData.grandPrix_useSkillTimes,
                                json.dumps(self.grandPrixUseSkillTimes))
        weakdata.setDayFishData(self.userId, WeakData.grandPrix_targetFish,
                                json.dumps(self.grandPrixTargetFish))
        # weakdata.setDayFishData(self.userId, WeakData.grandPrix_levelFpMultiple, json.dumps(self.grandPrixLevelFpMultiple))

    def sendGrandPrixInfo(self):
        """
        发送大奖赛信息 大奖赛相关信息(进入渔场后服务器主动推送)
        """
        if not grand_prix.isGrandPrixOpenTime():  # 是否为大奖赛开放时段 00:00 —— 23:00
            self._resetGrandPrixData()
            self._freeTimes = 0  # 免费次数
            weakdata.setDayFishData(self.userId,
                                    WeakData.grandPrix_getPointsInfo,
                                    json.dumps([]))
            weakdata.setDayFishData(self.userId, WeakData.grandPrix_freeTimes,
                                    self._freeTimes)
        if ftlog.is_debug():
            ftlog.debug("sendGrandPrixInfo", self.grandPrixStartTS,
                        self.isGrandPrixMode())
        signUpState = 1 if self.isGrandPrixMode() else 0  # 是否已经报名
        remainFreeTimes = config.getVipConf(self.vipLevel).get(
            "grandPrixFreeTimes", 0) - self._freeTimes  # 剩余免费次数
        openTime = "-".join(config.getGrandPrixConf("openTimeRange"))  # 时间范围
        mo = MsgPack()
        mo.setCmd("grand_prix_info")
        mo.setResult("gameId", FISH_GAMEID)
        mo.setResult("userId", self.userId)
        mo.setResult("seatId", self.seatId)
        mo.setResult("remainFreeTimes", remainFreeTimes)
        mo.setResult("fee", config.getGrandPrixConf("fee"))  # 报名费
        mo.setResult("openTime", openTime)  # 00:00 - 23:00
        mo.setResult(
            "isInOpenTime",
            1 if grand_prix.isGrandPrixOpenTime() else 0)  # 大奖在是否在开放时间段
        mo.setResult("signUpState", signUpState)  # 是否已报名大奖赛
        mo.setResult(
            "todayRankType",
            RankType.TodayGrandPrix)  # 今日榜Type,使用fish_ranking获取排行榜数据,下同
        mo.setResult("todayDate", util.timestampToStr(int(time.time()),
                                                      "%m/%d"))  # 今日榜时间
        mo.setResult("yesterdayRankType", RankType.LastGrandPrix)
        mo.setResult("yesterdayDate",
                     util.timestampToStr(int(time.time() - 86400), "%m/%d"))
        mo.setResult(
            "des",
            config.getMultiLangTextConf(
                config.getGrandPrixConf("info").get("des"),
                lang=self.lang))  # 每日积分超过2400送100珍珠,今日榜单每10分钟刷新1次,最终排名00:00公布
        mo.setResult("pointsInfo", grand_prix.getPointInfo(
            self.userId))  # 奖励积分 道具Id、道具数量、是否领取了奖励0|1
        mo.setResult("todayMaxPoints",
                     weakdata.getDayFishData(self.userId,
                                             WeakData.grandPrix_point,
                                             0))  # 今日最高积分
        GameMsg.sendMsg(mo, self.userId)
        if ftlog.is_debug():
            ftlog.debug("FishGrandPrixPlayer, userId =", self.userId, "mo =",
                        mo)

    def addGrandPrixFishPoint(self, fishPoint, fishType, gunX):
        """
        添加大奖赛捕鱼积分
        """
        if self.isGrandPrixMode():
            fishPoint = self._calcuCatchFishGrandPrixPoint(
                fishPoint, gunX)  # 计算捕获 vip加成 + 火炮倍率加成
            self.grandPrixFishPoint += fishPoint
            fishType = int(fishType) % 100
            for ft, val in self.grandPrixTargetFish.iteritems():  # 添加目标鱼积分
                if fishType == int(ft) % 100 and val[0] < val[1]:
                    self.grandPrixTargetFish[ft][0] += 1
                    if self.grandPrixTargetFish[ft][0] == val[1]:
                        self.grandPrixFishPoint += val[2]
                    break
            if self.grandPrixFishPoint > self.bestPoint:  # 最好的积分
                self.grandPrixSurpassCount += 1  # 大奖赛超越自己次数
                self._surpassTarget()
        else:
            fishPoint = 0
        return fishPoint

    def getPointReward(self, userId):
        """
        是否获取积分阶段奖励
        """
        rewards = []
        for info in config.getGrandPrixConf("stageInfo"):
            point = info["point"]
            reward = info["rewards"]
            if self.grandPrixFishPoint >= point and point not in self.grandPrixGetPointsInfo:
                rewards.extend(reward)
                self.grandPrixGetPointsInfo.append(point)
        if rewards:
            util.addRewards(userId, rewards,
                            "BI_GRAND_PRIX_POINT_REWARD")  # 添加奖励
            weakdata.setDayFishData(userId, WeakData.grandPrix_getPointsInfo,
                                    json.dumps(self.grandPrixGetPointsInfo))
        return rewards

    def sendGrandPrixCatch(self, catchFishPoints):
        """
        大奖赛捕获消息
        """
        mo = MsgPack()
        mo.setCmd("catch_grand_prix")
        mo.setResult("gameId", FISH_GAMEID)
        mo.setResult("userId", self.userId)
        mo.setResult("seatId", self.seatId)
        mo.setResult("catchFishPoints",
                     catchFishPoints)  # [{"fId": 10010, "point": 5},], # 捕鱼积分
        mo.setResult("fishPoint", self.grandPrixFishPoint)  # 捕鱼积分
        mo.setResult("targetFish", self.grandPrixTargetFish
                     )  # {"11011": [0, 10],},   # 大奖赛目标鱼:[捕获数量, 目标数量]
        mo.setResult(
            "rewards", self.getPointReward(self.userId)
        )  # [{"name": 101, "count": 1000}, {"name": 101, "count": 2000}], # 大奖赛积分奖励
        mo.setResult("pointsInfo", grand_prix.getPointInfo(
            self.userId))  # 奖励积分 道具Id、道具数量、是否领取了奖励0|1
        GameMsg.sendMsg(mo, self.userId)

    def setTipTimer(self):
        """
        设置比赛开始和结束的通知消息
        """
        if self.grandPrixTipTimer:
            self.grandPrixTipTimer.cancel()
            self.grandPrixTipTimer = None
            self.sendGrandPrixInfo()  # 发送大奖赛信息
        curTime = int(time.time())
        dayStartTS = util.getDayStartTimestamp(curTime)
        openTimeRange = config.getGrandPrixConf("openTimeRange")
        pastTime = curTime - dayStartTS  # 03:00|23:10
        beginTime = util.timeStrToInt(openTimeRange[0])  # 00:00
        endTime = util.timeStrToInt(openTimeRange[1])  # 23:00
        if pastTime < beginTime:
            interval = beginTime - pastTime + 5  # 开始的通知
        elif beginTime <= pastTime <= endTime:
            interval = endTime - pastTime + 5  # 结束的通知
        else:
            interval = 86400 + beginTime - pastTime + 5  # 开始的通知
        self.grandPrixTipTimer = FTLoopTimer(interval, 0,
                                             self.setTipTimer)  # 死循环
        self.grandPrixTipTimer.start()

    def _getSurpassTarget(self):
        """
        获取要超越的玩家数据
        """
        timestamp = pktimestamp.getCurrentTimestamp()
        rankClass = RankingBase(self.userId,
                                RankType.TodayGrandPrix,
                                RankDefineIndex.GrandPrix,
                                clientId=None,
                                httpRequest=False)
        if rankClass:
            rankingList = rankClass.getTopNRankUsers(timestamp)
            surpassTarget = config.getGrandPrixConf(
                "surpassTarget")  # [100、80、... 3、2、1]
            masterSurpassTargets = []
            for rank in surpassTarget:
                idx = rank - 1
                if 0 <= idx < len(rankingList.rankingUserList):
                    player = rankingList.rankingUserList[idx]
                    name = util.getNickname(player.userId)
                    avatar = userdata.getAttr(player.userId, "purl")
                    masterSurpassTargets.append({
                        "userId": player.userId,
                        "name": name,
                        "score": player.score,
                        "rank": player.rank + 1,
                        "avatar": avatar
                    })
            self._rankListCache = masterSurpassTargets

    def _surpassTarget(self):
        """请求大奖赛中超越玩家数据"""
        if self.userId:
            msg = MsgPack()
            msg.setCmd("g_surpass")
            msg.setResult("gameId", FISH_GAMEID)
            msg.setResult("roomId", self.table.roomId)
            msg.setResult("tableId", self.table.tableId)
            msg.setResult("userId", self.userId)
            if self.grandPrixSurpassCount <= 1 and self.bestPoint != 0:
                msg.setResult("bestScore", self.grandPrixFishPoint)
            if self._surpassUser.get(self.userId, None):
                if self.grandPrixFishPoint > self._surpassUser.get(
                        self.userId).get("score"):
                    msg.setResult("target", self._surpassUser.get(self.userId))
            if self.grandPrixSurpassCount <= 1 or self._surpassUser.get(
                    self.userId, None):
                GameMsg.sendMsg(msg, self.userId)
            self._updateSurpassUser()

    def _updateSurpassUser(self):
        """更新要超越的目标用户"""
        newTarget = None
        maxScore = max(self.grandPrixFishPoint, self.bestPoint)
        for tar in self._rankListCache:
            if maxScore < tar["score"] and tar["userId"] != self.userId:
                newTarget = tar
                break
        self._surpassUser[self.userId] = newTarget
示例#25
0
class TaskBase(object):

    def __init__(self, player, taskConf, taskSystem, taskData=None):
        self.player = player
        self.userId = player.userId
        self.taskId = taskConf["taskId"]
        self.taskConfig = taskConf

        self.taskSystem = taskSystem
        self.taskData = taskData or self._getInitMainData()
        self.taskInterval = taskConf["timeLong"]
        self.helpProgress = taskData.get("helpProgress", 0) if taskData else 0
        self.waitTime = taskData.get("waitTime", 0) if taskData else taskConf["waitTime"]
        self.taskActivateTimer = None       # 任务激活
        self.sendTaskInfoTimer = None       # 发送任务信息
        self.updateTaskInfoTimer = None     # 刷新任务进度
        self.userEndTaskTimer = None        # 任务结束倒计时
        self.isSendMsg = False
        self.receiveRewards = None
        self.catchBetNum = taskData.get("catchBetNum", 0) if taskData else 0
        self._reload()

    def clear(self):
        """清理定时器"""
        if self.taskActivateTimer:
            self.taskActivateTimer.cancel()
        if self.sendTaskInfoTimer:
            self.sendTaskInfoTimer.cancel()
        if self.updateTaskInfoTimer:
            self.updateTaskInfoTimer.cancel()
        if self.userEndTaskTimer:
            self.userEndTaskTimer.cancel()

    def _reload(self):
        self.recordStartTime = 0
        if not self.isTaskOver():
            if self.taskData.get("type", 0) and self.taskData.get("type", 0) != self.taskConfig["type"]:
                self.taskData = self._getInitMainData()
                return
            if self.taskConfig["target"] != self.taskData["target"]:        # 未完成的任务任务目标发生变化后重置存档
                self.taskData = self._getInitMainData()
                return
            if self.taskConfig["targetNum"] != self.taskData["targetNum"] and self.taskData.get("type", 0) not in [0, TaskType.HoldCoin]:
                self.taskData = self._getInitMainData()
                return

    def _getInitMainData(self):
        """获取初始化主线数据"""
        targetNum = self.taskConfig["targetNum"]
        if util.isNewbieRoom(self.player.table.typeName) and self.taskConfig["type"] == TaskType.HoldCoin:
            targetNum += self.player.allChip // 100 * 100
        return {
            "type": self.taskConfig["type"],
            "progress": 0,
            "state": TaskState.NotOpen,
            "failTime": 0,
            "targetNum": targetNum,
            "target": self.taskConfig["target"]
        }

    def _addProgress(self, value, isMe, progress=0, isTargetAddition=False):
        """增加任务进度"""
        assert (self.taskData)
        if value == 0 or self.taskData["state"] != TaskState.Update:                            # value
            return
        if ftlog.is_debug():
            ftlog.debug("_addProgress1", "value =", value, "isMe =", isMe, "progress =", progress, "isTargetAddition =", isTargetAddition, "helpProgress =", self.helpProgress)
        if isMe:
            value *= self.taskSystem.taskExpedite
            progress_ = min(self.taskData["progress"] + value, 999999999999)
            self._updateProgress(progress_, isMe)
        else:
            if progress > 0 or isTargetAddition:
                if progress:
                    self.helpProgress += progress
                else:
                    self.helpProgress += value
                progress_ = min(self.taskData["progress"] + value, 999999999999)
                self._updateProgress(progress_, isMe)
                if ftlog.is_debug():
                    ftlog.debug("_addProgress2", "helpProgress =", self.helpProgress, "totalProgress =", progress_)

    def _updateProgress(self, value, isMe):
        """
        更新任务进度
        """
        if self.taskData["progress"] != value:
            self.taskData["progress"] = value
            self.taskData["time"] = int(time.time())
            if self._isComplete():
                self.taskEnd()
            else:
                if isMe:
                    self.sendUserTaskInfo()
                else:                               # 好友助力任务进度延迟刷新
                    self.isSendMsg = True

    def _receiveTaskReward(self):
        """领取奖励"""
        assert (self.taskData)
        if self.isTaskOver():  # 已领取
            return 1, None
        targetCount = self.taskData["targetNum"]
        if self.taskData["progress"] < targetCount:  # 未达成
            return 1, None
        _rewards = self._getDropItems()
        if not _rewards:
            _rewards = self.taskConfig["rewards"]     # 普通奖励
        if _rewards and util.isChestRewardId(_rewards[0]["name"]):      # 宝箱奖励(新手宝箱奖励固定)
            if util.isNewbieRoom(self.player.table.typeName):
                _rewards = [
                    {"name": 101, "count": 500},
                    {"name": 1145, "count": 1},
                    {"name": 1149, "count": 1}
                    # {"name": 1137, "count": 3}
                ]
            else:
                from newfish.entity.chest import chest_system
                _rewards = chest_system.getChestRewards(self.userId, _rewards[0]["name"])

        rewards = []
        for _, reward in enumerate(_rewards):
            if reward["name"] <= 0:
                continue
            rwDict = {}
            rwDict["name"] = reward["name"]
            rwDict["count"] = reward["count"]
            rewards.append(rwDict)

        code = 0
        self.taskData["state"] = TaskState.Success  # 改变状态
        if rewards:
            code = util.addRewards(self.userId, rewards, "BI_NFISH_TABLE_TASK_REWARDS", int(self.taskId))
        return code, rewards

    def _getDropItems(self):
        """获取掉落的道具"""
        realRewards = []
        rewards = self.taskConfig["rewards"]
        for reward in rewards:
            dropId = reward["name"]
            dropConf = config.getDropConf(dropId)
            if dropConf:
                _, rds = drop_system.getDropItem(dropId)
                realRewards.append(rds)
        return realRewards

    def _getCatchFishCoin(self, event, target=0):
        """获取捕鱼的金币"""
        totalCoin = 0  # 总金币数不包括招财珠
        gunSkinMul = event.gunSkinMul
        fishCoins = {}
        outCoinsNum = 0
        for gainMap in event.gain:
            fishType = int(gainMap["fishType"])
            itemId = gainMap["itemId"]
            itemCount = gainMap["count"] / gunSkinMul
            if itemId == config.CHIP_KINDID:  # 金币
                totalCoin += itemCount
                if fishType // 1000 == 14:
                    fishType = fishType % 14000 + 11000
                fishCoins[str(fishType)] = fishCoins.setdefault(str(fishType), 0) + itemCount
                if target and itemCount >= target:
                    outCoinsNum += 1
        return totalCoin, fishCoins, outCoinsNum

    def dealCatchEvent(self, event, tableMultiple, coinAddition, playersNum):
        """
        处理捕鱼事件
        :param event: 捕获事件详情
        :param tableMultiple: 房间倍率
        :param coinAddition: 当处于累计捕获金币任务时的进度加成
        :param playersNum: 当前桌内玩家数量
        :return:
        """
        if self.taskConfig["type"] in [TaskType.UseSkillNum, TaskType.ComboNum]:
           return
        if self.taskData["state"] != TaskState.Update:
            return
        isMe = event.userId == self.userId
        fishTypes = event.fishTypes  # 鱼种类
        wpId = event.wpId
        gunSkinMul = event.gunSkinMul
        target = self.taskConfig["target"]
        progress = 0
        isTargetAddition = False
        if self.taskConfig["type"] in [TaskType.CatchFishCoin, TaskType.UseSkillCatchFishCoin]:
            progress = coinAddition
        elif self.taskConfig["type"] in [TaskType.CatchFishNum, TaskType.CatchBossNum,
                                         TaskType.FishNumCoinHigh, TaskType.BetFishNum,
                                         TaskType.CatchRainbowFishNum, TaskType.CatchRedPacketFishNum]:
            friendHelpPlayerMultiple = config.getCommonValueByKey("friendHelpPlayerMultiple", {}).get(str(playersNum - 1), 0)
            probb = (friendHelpPlayerMultiple * (self.taskData["targetNum"] + 5) / self.taskData["targetNum"]) * 10000
            randInt = random.randint(1, 10000)
            if randInt <= probb:
                isTargetAddition = True
        if self.taskConfig["type"] == TaskType.CatchFishCoin:  # 1捕获xx鱼达金币数
            totalCoin, fishCoins, _ = self._getCatchFishCoin(event)
            if target:
                self._addProgress(fishCoins.get(str(target), 0), isMe, progress=progress, isTargetAddition=isTargetAddition)
            else:
                self._addProgress(totalCoin, isMe, progress=progress, isTargetAddition=isTargetAddition)

        elif self.taskConfig["type"] == TaskType.CatchFishNum:  # 2捕获鱼个数
            if target:
                betTarget = 14000 + int(target) % 11000
                fishNum = fishTypes.count(target) + fishTypes.count(betTarget)
                self._addProgress(fishNum, isMe, progress=progress, isTargetAddition=isTargetAddition)
            else:
                self._addProgress(len(fishTypes), isMe, progress=progress, isTargetAddition=isTargetAddition)
            return
        elif self.taskConfig["type"] == TaskType.CatchBossNum:  # 3捕获boss个数
            bossNum = 0  # boss个数
            for fishType in fishTypes:
                fishConf = config.getFishConf(fishType, self.taskSystem.table.typeName, tableMultiple)
                if fishConf["type"] in config.BOSS_FISH_TYPE:
                    bossNum += 1
            self._addProgress(bossNum, isMe, progress=progress, isTargetAddition=isTargetAddition)
            return

        elif self.taskConfig["type"] == TaskType.FishNumCoinHigh:  # 4多少金币以上的鱼
            _, _, num = self._getCatchFishCoin(event, target)
            self._addProgress(num, isMe, progress=progress, isTargetAddition=isTargetAddition)
            return
        elif self.taskConfig["type"] == TaskType.BetFishNum: # 5--多少只倍率鱼
            betFishMap = {}
            for gainMap in event.gain:
                fishConf = config.getFishConf(gainMap["fishType"], self.taskSystem.table.typeName, tableMultiple)
                itemId = gainMap["itemId"]
                itemCount = gainMap["count"]

                if fishConf["type"] in config.MULTIPLE_FISH_TYPE:
                    if itemId == config.CHIP_KINDID:  # 金币
                        bet = itemCount / fishConf["score"] / tableMultiple / gunSkinMul
                        betFishMap[str(bet)] = betFishMap.get(str(bet), 0) + 1
            betNum = 0
            for bet in betFishMap:
                if int(bet) >= target:
                    betNum += betFishMap[bet]
            self._addProgress(betNum, isMe, progress=progress, isTargetAddition=isTargetAddition)

        elif self.taskConfig["type"] == TaskType.UseSkillCatchFishNum:  # 8 使用技能捕获鱼数
            wpType = util.getWeaponType(wpId)
            if wpType in [config.SKILL_WEAPON_TYPE,
                          config.RB_FIRE_WEAPON_TYPE,
                          config.RB_BOMB_WEAPON_TYPE]:
                if target:
                    self._addProgress(fishTypes.count(target), isMe, progress=progress, isTargetAddition=isTargetAddition)
                else:
                    self._addProgress(len(fishTypes), isMe, progress=progress, isTargetAddition=isTargetAddition)

        elif self.taskConfig["type"] == TaskType.UseSkillCatchFishCoin:  # 9 使用技能捕获XX金币类型的鱼数
            totalCoin, fishCoins, _ = self._getCatchFishCoin(event)  # 总金币数不包括招财珠
            wpType = util.getWeaponType(wpId)
            if wpType in [config.SKILL_WEAPON_TYPE,
                          config.RB_FIRE_WEAPON_TYPE,
                          config.RB_BOMB_WEAPON_TYPE]:
                if target:
                    self._addProgress(fishCoins.get(str(target), 0), isMe, progress=progress, isTargetAddition=isTargetAddition)
                else:
                    self._addProgress(totalCoin, isMe, progress=progress, isTargetAddition=isTargetAddition)
        elif self.taskConfig["type"] == TaskType.CatchFishNumByOneFire:  # 10 1网捕获多少鱼
            if len(fishTypes) >= target:
                value = 1
                if not isMe:
                    return
                self._addProgress(value, isMe, progress=progress, isTargetAddition=isTargetAddition)
        elif self.taskConfig["type"] == TaskType.CatchRainbowFishNum:   # 捕获彩虹鱼
            rainbowNum = 0
            for fishType in fishTypes:
                fishConf = config.getFishConf(fishType, self.taskSystem.table.typeName, tableMultiple)
                if fishConf["type"] in config.RAINBOW_FISH_TYPE:
                    rainbowNum += 1
            self._addProgress(rainbowNum, isMe, progress=progress, isTargetAddition=isTargetAddition)
        elif self.taskConfig["type"] == TaskType.CatchRedPacketFishNum: # 捕获红包券鱼
            redPacketNum = 0
            for fishType in fishTypes:
                fishConf = config.getFishConf(fishType, self.taskSystem.table.typeName, tableMultiple)
                if fishConf["type"] == 4:
                    redPacketNum += 1
            self._addProgress(redPacketNum, isMe, progress=progress, isTargetAddition=isTargetAddition)

    def dealUseSkillEvent(self, event):
        """使用技能事件"""
        if self.taskData["state"] != TaskState.Update:
            return
        if self.taskConfig["type"] == TaskType.UseSkillNum:
            target = self.taskConfig["target"]
            if target == 0:
                self._addProgress(1, event.userId == self.userId)
            else:
                if event.skillId == target:
                    self._addProgress(1, event.userId == self.userId)

    def dealUseSkillItem(self, event):
        """使用技能道具"""
        if self.taskData["state"] != TaskState.Update:
            return
        if self.taskConfig["type"] == TaskType.UserSkillItem:
            self._addProgress(1, event.userId == self.userId)

    def dealGetPearl(self, pearl):
        """获得珍珠"""
        if self.taskData["state"] != TaskState.Update:
            return
        if self.taskConfig["type"] == TaskType.CatchPearlNum:
            self._addProgress(pearl, True)

    def dealCommboEvent(self, event):
        """处理连击事件"""
        if self.taskData["state"] != TaskState.Update:
            return
        if self.taskConfig["type"] == TaskType.ComboNum:
            if event.comboNum >= self.taskConfig["target"]:
                self._addProgress(1, event.userId == self.userId)

    def refreshHoldCoin(self, coin):
        """刷新持有金币数量"""
        if self.taskData["state"] != TaskState.Update:
            return
        if ftlog.is_debug():
            ftlog.debug("refreshHoldCoin", self.userId, coin)
        if self.taskConfig["type"] == TaskType.HoldCoin:
            self._updateProgress(coin, True)

    def refreshLevel(self, level):
        """刷新等级"""
        if self.taskData["state"] != TaskState.Update:
            return
        ftlog.debug("refreshLevel", self.userId, level)
        if self.taskConfig["type"] == TaskType.UpgradeLevel:
            self._updateProgress(level, True)

    def getTaskId(self):
        """
        获取任务Id
        """
        return self.taskId

    def taskStart(self, interval=0, delay=0):
        """
        任务开始
        """
        if ftlog.is_debug():
            ftlog.debug("taskBase_______taskStart", self.taskId)

        if self.taskActivateTimer:
            self.taskActivateTimer.cancel()
        if delay > 0:
            taskActivateInterval = max(interval, Task_Delay_Ready_Time)
            self.taskActivateTimer = FTLoopTimer(taskActivateInterval, 0, self._taskActivate, delay)
            self.taskActivateTimer.start()
        elif self.taskConfig["timeLong"] > 0:
            if util.isNewbieRoom(self.player.table.typeName) and self.taskSystem.taskModel == TaskModel.Main:
                time_ = Task_Red_Ready_Time
            else:
                time_ = Task_Normal_Ready_Time
            taskActivateInterval = max(interval, time_)
            taskInfoInterval = max(interval - time_, 0)
            self.delaySendUserTaskInfo(taskInfoInterval)
            self.taskActivateTimer = FTLoopTimer(taskActivateInterval, 0, self._taskActivate)
            self.taskActivateTimer.start()
        else:
            self.taskActivateTimer = FTLoopTimer(interval, 0, self._taskActivate)
            self.taskActivateTimer.start()
        from newfish.game import TGFish
        from newfish.entity.event import TableTaskStartEvent
        event = TableTaskStartEvent(self.userId, FISH_GAMEID, self.taskSystem.table.tableId, self.getTaskId())
        TGFish.getEventBus().publishEvent(event)

    def _taskActivate(self, delay=0):
        """任务激活"""
        # 未完成前3个中期目标时不触发渔场任务.
        if self.taskSystem.needCheckMidTermTargetStates:
            if not self.taskSystem.top3MidTermTargetFinished:
                self.taskSystem.top3MidTermTargetFinished = True
                for taskClass in self.player.achieveSystem.holdAssetTasks:
                    if taskClass.taskId < 1003 or (taskClass.taskId == 1003 and not taskClass.isComplete()):
                        self.taskSystem.top3MidTermTargetFinished = False
                        break
            if not self.taskSystem.top3MidTermTargetFinished:
                if self.taskActivateTimer:
                    self.taskActivateTimer.cancel()
                self.taskActivateTimer = FTLoopTimer(60, 0, self._taskActivate)
                self.taskActivateTimer.start()
                if ftlog.is_debug():
                    ftlog.debug("_taskActivate, need delay !", self.player.userId, self.taskId)
                return
        if ftlog.is_debug():
            ftlog.debug("_taskActivate->", delay, self.waitTime)
        self.taskData["state"] = TaskState.Start
        if delay > 0:
            self.taskData["state"] = TaskState.Update
            self.taskInterval = delay
        self.recordStartTime = int(time.time())
        self.clear()
        if self.taskInterval != 0:
            self.userEndTaskTimer = FTLoopTimer(self.taskInterval, 0, self.taskEnd)
            self.userEndTaskTimer.start()
        if self.taskSystem.isFriendRoom():
            self.updateTaskInfoTimer = FTLoopTimer(1, -1, self.sendTimerUpdate)
            self.updateTaskInfoTimer.start()
        self.sendUserTaskInfo()
        self.taskData["state"] = TaskState.Update

    def getTaskFailTime(self):
        """
        当前任务已经失败多少次
        """
        return self.taskData["failTime"]

    def getTaskInfo(self):
        """
        获取返回给客户端的任务数据
        """
        progress = min(self.taskData["progress"], self.taskData["targetNum"])
        progress = int(progress) if progress - int(progress) == 0 else progress
        meProgress = progress - self.helpProgress
        meProgress = int(meProgress) if meProgress - int(meProgress) == 0 else meProgress
        taskInfo = {}
        taskInfo["taskId"] = self.taskConfig["taskId"]
        taskInfo["isLimitTime"] = self.isLimitTime()
        taskInfo["shareMode"] = 1   # 1 if not self.isLimitTime() or util.isLocationLimit(self.userId) else 0
        taskInfo["progress"] = [int(progress), int(meProgress), self.taskData["targetNum"]]
        taskInfo["state"] = self.taskData["state"]
        taskInfodescId = self.taskConfig["desc"]
        taskInfo["desc"] = config.getMultiLangTextConf(str(taskInfodescId), lang=util.getLanguage(self.userId))
        taskInfo["reward"] = self.taskConfig["rewards"]
        if self.receiveRewards:
            taskInfo["realReward"] = self.receiveRewards
        taskInfo["target"] = self.taskConfig["target"]
        taskInfo["suggestTarget"] = self.taskConfig["suggestTarget"]
        timeLeft = self.recordStartTime + self.taskInterval - int(time.time())
        taskInfo["timeLeft"] = timeLeft if timeLeft >= 0 else self.taskInterval
        taskInfo["timeLong"] = self.taskInterval
        taskInfo["failTimeConf"] = self.taskConfig["failTime"]
        taskInfo["failTime"] = self.taskData["failTime"]        # 失败次数
        taskInfo["isNextLimitTime"] = self.taskSystem.isNextLimitTime(self.getTaskId())
        taskInfo["model"] = TaskModel.Red if util.isNewbieRoom(self.player.table.typeName) and self.taskSystem.taskModel == TaskModel.Main else self.taskSystem.taskModel
        taskInfo["type"] = self.taskConfig["type"]
        if self.taskSystem.taskModel in [TaskModel.Red, TaskModel.Main]:
            taskInfo["index"] = self.taskSystem.allMainTaskIds.index(self.taskId)
        return taskInfo

    def getTaskData(self):
        """
        获取存储的任务数据
        """
        saveData = {}
        saveData["type"] = self.taskConfig["type"]
        saveData["taskId"] = self.taskId
        saveData["progress"] = self.taskData["progress"]
        saveData["helpProgress"] = self.helpProgress
        saveData["state"] = self.taskData["state"]
        saveData["target"] = self.taskConfig["target"]
        saveData["targetNum"] = self.taskData["targetNum"]
        saveData["failTime"] = self.taskData["failTime"]
        saveData["waitTime"] = int(self.taskActivateTimer.getTimeOut()) if self.taskActivateTimer else 0
        if self.catchBetNum:
            saveData["catchBetNum"] = self.catchBetNum
        return saveData

    def taskEnd(self):
        """
        任务结束
        """
        if ftlog.is_debug():
            ftlog.debug("taskBase_______taskEnd", self.taskId, self.userId, self.taskData["state"])
        beforeState = self.taskData["state"]
        self.clear()
        if beforeState == TaskState.Update:
            isComplete = self._isComplete()
            if isComplete:
                _, rewards = self._receiveTaskReward()
                self.receiveRewards = rewards
                self.taskSystem.saveRedState()  # 保存红包
            else:
                self.taskSystem.taskExpedite = 1
                self.taskData["state"] = TaskState.Fail
                if self.isLimitTime():
                    self.taskData["failTime"] += 1
            from newfish.game import TGFish
            from newfish.entity.event import TableTaskEndEvent
            event = TableTaskEndEvent(self.userId, FISH_GAMEID, self.taskSystem.table.tableId, self.getTaskId(),
                                      isComplete,  self.isLimitTime(), self.receiveRewards)
            TGFish.getEventBus().publishEvent(event)
            # 上传当前完成任务进度
            if self.taskSystem.taskModel == TaskModel.Main and self.taskSystem.isRedRoom():
                ftlog.debug("BI_NFISH_THOUSAND_RED_TASK_PROGRESS--->000", self.getTaskId())
                bireport.reportGameEvent("BI_NFISH_GE_THOUSAND_RED_TASK", self.userId,FISH_GAMEID,
                                self.taskSystem.table.roomId, self.taskSystem.table.tableId,
                                self.getTaskId(), int(isComplete), 0,  0, [], config.CLIENTID_ROBOT)
                # 新手引导步骤完成
                if self.taskConfig["type"] == TaskType.UpgradeLevel:
                    util.addGuideStep(self.player.userId, config.NEWBIE_GUIDE_GUN_UP, self.player.clientId)
        self.sendUserTaskInfo()

    def sendTimerUpdate(self):
        """
        任务进度刷新
        """
        if self.taskConfig["type"] == TaskType.HoldCoin:
            self.taskSystem.refreshHoldCoin(self.player.holdCoin)
        elif self.taskConfig["type"] == TaskType.UpgradeLevel:
            gunLevel = self.player.gunLevel - 2100
            self.taskSystem.refreshLevel(gunLevel)
        if self.isSendMsg:
            self.sendUserTaskInfo()

    def delaySendUserTaskInfo(self, interval=0):
        """
        延时发送任务信息
        """
        if self.sendTaskInfoTimer:
            self.sendTaskInfoTimer.cancel()
        self.sendTaskInfoTimer = FTLoopTimer(interval, 0, self.sendUserTaskInfo)
        self.sendTaskInfoTimer.start()

    def sendUserTaskInfo(self):
        """
        发送任务信息
        """
        self.isSendMsg = False
        message = MsgPack()
        message.setCmd("table_task_info")
        message.setResult("gameId", FISH_GAMEID)
        message.setResult("userId", self.userId)
        taskInfo = self.getTaskInfo()
        message.setResult("taskInfo", taskInfo)
        router.sendToUser(message, self.userId)

    def _isComplete(self):
        """
        任务是否完成
        """
        assert (self.taskData)
        targetCount = self.taskData["targetNum"]
        return self.taskData["progress"] >= targetCount

    def isTaskSuccess(self):
        """
        任务成功
        """
        return self.taskData["state"] == TaskState.Success

    def getTaskConf(self):
        assert (self.taskConfig)
        return self.taskConfig

    def isTaskOver(self):
        """任务结束"""
        return self.taskData["state"] in [TaskState.Success, TaskState.Fail]

    def getTaskState(self):
        return self.taskData["state"]

    def getTaskTargets(self):
        if self.taskData["state"] != TaskState.Update:
            return []
        if self.taskConfig["type"] in [TaskType.CatchFishNum, TaskType.CatchFishCoin,
                                       TaskType.UseSkillCatchFishNum, TaskType.UseSkillCatchFishCoin]:
            if self.taskConfig["target"] != 0:
                return [self.taskConfig["target"]]
        return []

    def isLimitTime(self):
        """是否限制了时间"""
        if not self.taskConfig:
            return 0
        return 1 if self.taskConfig.get("timeLong", 0) != 0 else 0
示例#26
0
class CmpttTask(TableMatchTask):
    """
    竞争性任务(夺宝赛)
    """
    def __init__(self, table, taskName, taskInterval):
        super(CmpttTask, self).__init__(table, taskName, taskInterval)
        self._reload()

    def _reload(self):
        self.currentTask = {}
        self.userIds = []
        self.usersData = {}
        self.state = 0
        self.catchId = 100000000
        self.rewardType = 0
        self.recordStartTime = 0
        self.sendInfoTime = 60
        self.chestRewardId = 0
        # self.readyTimer = FishTableTimer(self.table)
        self.startTimer = FishTableTimer(self.table)
        self.endTimer = FishTableTimer(self.table)
        self.sendInfoTimer = None
        # self.readyTimer.setup(self.taskInterval, "task_ready", {"task": self.taskName})
        self.recordReloadTime = time.time()
        self.taskId = "%d-%d" % (self.table.tableId, 0)

    def clear(self):
        """
        清除所有公共数据
        """
        self.currentTask = {}
        self.userIds = []
        self.usersData = {}
        self.state = 0
        self.recordStartTime = 0
        self.recordReloadTime = 0
        # if self.readyTimer:
        #     self.readyTimer.cancel()
        if self.startTimer:
            self.startTimer.cancel()
        if self.endTimer:
            self.endTimer.cancel()
        if self.sendInfoTimer:
            self.sendInfoTimer.cancel()

    def taskReady(self, *args):
        """
        任务准备
        """
        self.state = 1
        if self.sendInfoTimer:
            self.sendInfoTimer.cancel()
        tasks = config.getCmpttTaskConf(self.table.runConfig.fishPool)
        if len(tasks) == 0 or len(self.table.getBroadcastUids()) == 0:
            endTimer = FishTableTimer(self.table)
            endTimer.setup(0, "task_end", {"uid": 0, "task": self.taskName})
            return
        self.taskId = "%d-%d" % (self.table.tableId, int(time.time()))
        randTask = random.choice(tasks)
        self.currentTask = copy.deepcopy(randTask)
        for uid in self.table.getBroadcastUids():
            if util.isFinishAllNewbieTask(uid):
                self.userIds.append(uid)
        if len(self.userIds) <= 2:
            self.chestRewardId = self.currentTask["chestReward"][0]
        elif len(self.userIds) == 3:
            self.chestRewardId = self.currentTask["chestReward"][1]
        elif len(self.userIds) >= 4:
            self.chestRewardId = self.currentTask["chestReward"][2]
        for uid in self.userIds:
            self.usersData[uid] = {
                "uid": uid,
                "task": self.currentTask,
                "score": 0,
                "results": {},
                "lastCatchId": 0
            }
        readySeconds = self.currentTask["readySeconds"]
        msg = MsgPack()
        msg.setCmd("cmptt_task")
        msg.setResult("gameId", FISH_GAMEID)
        msg.setResult("action", "ready")
        msg.setResult("taskId", self.currentTask["taskId"])
        msg.setResult("taskType", self.currentTask["taskType"])
        msg.setResult("targets", self.currentTask["targets"])
        msg.setResult("reward", {"name": self.chestRewardId, "count": 1})
        GameMsg.sendMsg(msg, self.userIds)
        self.startTimer.setup(readySeconds, "task_start",
                              {"task": self.taskName})

    def taskStart(self, *args):
        """
        任务开始
        """
        if not self.currentTask:
            return 0
        self.state = 2
        self.rewardType = 1
        # if len(self.userIds) in [1, 2]:
        #     self.rewardType = 4  # 宝箱+珍珠
        # elif len(self.userIds) == 3:
        #     self.rewardType = 3  # 宝箱+金币
        # elif len(self.userIds) == 4:
        #     self.rewardType = random.choice([3, 5])  # 宝箱+金币or宝箱+奖券
        for userId in self.userIds:
            player = self.table.getPlayer(userId)
            if player:
                self.sendCmpttTaskStartInfo(userId,
                                            self.currentTask["timeLong"])
                task = copy.deepcopy(self.currentTask)
                player.currentTask = [
                    self.taskName, task["taskId"], task["taskType"],
                    task["targets"]
                ]
        self.recordStartTime = int(time.time())
        self.endTimer.setup(self.currentTask["timeLong"], "task_end",
                            {"task": self.taskName})
        return self.currentTask["taskId"]

    def taskEnd(self, *args, **kwargs):
        """
        任务结束
        """
        if self.state == 0:
            self.clear()
            return
        self.state = 0
        _taskId = 0
        if self.currentTask:
            _taskId = self.currentTask["taskId"]
            ranks = kwargs.get("ranks")
            if not ranks:
                ranks = self._getRanks()
            reward = False
            dropItems = None
            player = None
            rewardDropId = 0
            rewardItem = 0
            if ranks:
                usersData = self.usersData.get(ranks[1]["uid"])
                if self._checkFinished(usersData):
                    reward = True
                    player = self.table.getPlayer(ranks[1]["uid"])
                    dropItems = self._sendTaskReward(player,
                                                     self.chestRewardId,
                                                     self.userIds)
                    # 夺宝赛获奖
                    from newfish.game import TGFish
                    from newfish.entity.event import WinCmpttTaskEvent
                    event = WinCmpttTaskEvent(player.userId, FISH_GAMEID,
                                              self.table.roomId,
                                              self.table.tableId)
                    TGFish.getEventBus().publishEvent(event)

            msg = MsgPack()
            msg.setCmd("cmptt_task")
            msg.setResult("gameId", FISH_GAMEID)
            msg.setResult("action", "finish")
            msg.setResult("taskId", self.currentTask["taskId"])
            msg.setResult("taskType", self.currentTask["taskType"])
            msg.setResult("ranks", ranks)
            if reward and player:
                msg.setResult("reward", dropItems)
            GameMsg.sendMsg(msg, self.userIds)
        self.clearTaskData()
        if _taskId and self.table.ttAutofillFishGroup:
            self.table.ttAutofillFishGroup.endAutofill(0, _taskId)

    def clearTaskData(self, uid=None):
        """
        清除用户任务数据
        """
        if uid:
            player = self.table.getPlayer(uid)
            if player:
                player.currentTask = None
            if uid in self.userIds:
                self.userIds.remove(uid)
            if uid in self.usersData:
                del self.usersData[uid]
        if self.state == 0 or len(self.userIds) == 0:
            for userId in self.userIds:
                player = self.table.getPlayer(userId)
                if player:
                    player.currentTask = None
            self.clear()

    def sendCmpttTaskInfo(self):
        """
        发送夺宝赛任务倒计时信息
        """
        userIds = []
        for uid in self.table.getBroadcastUids():
            if util.isFinishAllNewbieTask(uid):
                userIds.append(uid)
        if self.sendInfoTimer:
            self.sendInfoTimer.cancel()
        if not userIds:
            return
        if self.state == 0:
            self.sendInfoTimer = FTLoopTimer(self.sendInfoTime, 0,
                                             self.sendCmpttTaskInfo)
            self.sendInfoTimer.start()
        else:
            return
        timeLeft = int(
            self.taskInterval) - int(time.time() - self.recordReloadTime)
        if timeLeft <= 0:
            return
        msg = MsgPack()
        msg.setCmd("cmptt_task")
        msg.setResult("gameId", FISH_GAMEID)
        msg.setResult("action", "info")
        msg.setResult("timeLeft", timeLeft)
        GameMsg.sendMsg(msg, userIds)

    def sendCmpttTaskStartInfo(self, userId, timeLeft):
        """
        发送夺宝赛开始消息
        """
        msg = MsgPack()
        msg.setCmd("cmptt_task")
        msg.setResult("gameId", FISH_GAMEID)
        msg.setResult("action", "start")
        msg.setResult("taskId", self.currentTask["taskId"])
        desc = config.getMultiLangTextConf(str(self.currentTask["desc"]),
                                           lang=util.getLanguage(userId))
        if desc.find("%d") >= 0:
            desc = desc % self.currentTask["targets"].get("number1", 0)
        msg.setResult("desc", desc)
        msg.setResult("timeLeft", timeLeft)
        msg.setResult("timeLong", self.currentTask["timeLong"])
        msg.setResult("taskType", self.currentTask["taskType"])
        msg.setResult("rewardType", self.rewardType)
        msg.setResult("targets", self.currentTask["targets"])
        msg.setResult("reward", {"name": self.chestRewardId, "count": 1})
        GameMsg.sendMsg(msg, userId)

    def newJoinTask(self, userId):
        """
        新加入任务
        """
        if self.state == 0:
            return
        self.userIds.append(userId)
        self.usersData[userId] = {
            "uid": userId,
            "task": copy.deepcopy(self.currentTask),
            "score": 0,
            "results": {},
            "lastCatchId": 0
        }

    def newJoinTaskForAfterTheStart(self, userId):
        """
        任务开始后结束前新加入任务
        """
        if self.state != 2:
            return
        if userId is None or len(self.userIds) == 0:
            return
        timeLeft = int(
            self.currentTask["timeLong"]) - int(time.time() -
                                                self.recordStartTime)
        if timeLeft <= 10:
            return
        self.newJoinTask(userId)
        # 发送开始消息,给出任务剩余时间
        self.sendCmpttTaskStartInfo(userId, timeLeft)
        # 发送排名信息
        self._sendRanksInfo()
        # 设置用户当前任务信息
        player = self.table.getPlayer(userId)
        if player:
            task = copy.deepcopy(self.currentTask)
            player.currentTask = [
                self.taskName, task["taskId"], task["taskType"],
                task["targets"]
            ]

    def sendTaskInfoForReconnect(self, userId):
        """
        用户断线重连发送任务相关信息
        """
        if self.state != 2:
            return
        timeLeft = int(
            self.currentTask["timeLong"]) - int(time.time() -
                                                self.recordStartTime)
        if timeLeft <= 5:
            return
        self.sendCmpttTaskStartInfo(userId, timeLeft)
        self._sendRanksInfo()

    def _sendTaskReward(self, player, chestId, broadcastUserIds):
        """
        发送任务奖励
        """
        chestRewards = chest_system.getChestRewards(player.userId, chestId)
        util.addRewards(player.userId,
                        chestRewards,
                        "BI_NFISH_CMPTT_TASK_REWARDS",
                        roomId=self.table.roomId,
                        tableId=self.table.tableId)
        from newfish.game import TGFish
        from newfish.entity.event import GainChestEvent
        from newfish.entity.chest.chest_system import ChestFromType
        event = GainChestEvent(player.userId, FISH_GAMEID, chestId,
                               ChestFromType.Cmptt_Ncmptt_Bonus_Task)
        TGFish.getEventBus().publishEvent(event)
        dropItems = {"chest": chestId, "chestRewards": chestRewards, "type": 0}
        return dropItems

    def _sendRanksInfo(self):
        """
        发送排名信息
        """
        if self.currentTask:
            msg = MsgPack()
            msg.setCmd("cmptt_task")
            msg.setResult("gameId", FISH_GAMEID)
            msg.setResult("action", "rank")
            msg.setResult("taskId", self.currentTask["taskId"])
            msg.setResult("taskType", self.currentTask["taskType"])
            msg.setResult("ranks", self._getRanks())
            GameMsg.sendMsg(msg, self.userIds)

    def dealLeaveTable(self, event):
        """
        处理离开事件
        """
        if self.state == 0:
            return
        uid = event.userId
        self.clearTaskData(uid)
        self._sendRanksInfo()

    def dealCatchEvent(self, event):
        """
        处理捕获事件
        """
        if self.state != 2:
            return
        uid = event.userId
        fishTypes = event.fishTypes
        if uid not in self.userIds:
            return

        fpMultiple = self.getEventFpMultiple(event)
        score = 0
        player = self.table.getPlayer(uid)
        usersData = self.usersData.get(uid)
        taskType = usersData["task"]["taskType"]
        targets = usersData["task"]["targets"]
        target1 = targets.get("target1", 0)
        target2 = targets.get("target2", 0)
        multipleTarget1 = 14000 + target1 % 11000
        multipleTarget2 = 14000 + target2 % 11000
        number1 = targets.get("number1", 999)
        number2 = targets.get("number2", 999)

        if taskType != 1 and "progress" not in usersData["results"]:
            usersData["results"]["progress"] = 0
        if taskType == 1:  # 指定数量特定鱼
            if target1 not in fishTypes and target2 not in fishTypes and multipleTarget1 not in fishTypes and multipleTarget2 not in fishTypes:
                return
            if (target1 in fishTypes or multipleTarget1
                    in fishTypes) and target1 not in usersData["results"]:
                usersData["results"][target1] = 0
            if (target2 in fishTypes or multipleTarget2
                    in fishTypes) and target2 not in usersData["results"]:
                usersData["results"][target2] = 0
            if self._checkFinished(usersData):
                return
            if player and player.currentTask:
                if target1 in fishTypes or multipleTarget1 in fishTypes:
                    target1Score = fishTypes.count(target1) + fishTypes.count(
                        multipleTarget1)
                    if usersData["results"][target1] + target1Score >= number1:
                        score += (number1 - usersData["results"][target1])
                        usersData["results"][target1] = number1
                        if player.currentTask[3].has_key("target1"):
                            player.currentTask[3].pop("target1")
                    else:
                        score += target1Score
                        usersData["results"][target1] += target1Score
                if target2 in fishTypes or multipleTarget2 in fishTypes:
                    target2Score = fishTypes.count(target2) + fishTypes.count(
                        multipleTarget2)
                    if usersData["results"][target2] + target2Score >= number2:
                        score += (number2 - usersData["results"][target2])
                        usersData["results"][target2] = number2
                        if player.currentTask[3].has_key("target2"):
                            player.currentTask[3].pop("target2")
                    else:
                        score += target2Score
                        usersData["results"][target2] += target2Score
        elif taskType == 2:  # 指定分数
            for fishType in fishTypes:
                fishConf = config.getFishConf(fishType, self.table.typeName,
                                              fpMultiple)
                if fishConf.get("itemId", 0) in config.BULLET_KINDIDS:
                    score += (
                        fishConf.get("score", 0) *
                        config.BULLET_KINDIDS[fishConf.get("itemId", 0)] /
                        fpMultiple)
                else:
                    score += fishConf.get("score", 0)
            usersData["results"]["progress"] += score

        usersData["score"] += score
        if score == 0:
            return
        usersData["lastCatchId"] = self.catchId
        self.catchId -= 1
        self._sendRanksInfo()
        if self._checkFinished(usersData):
            self.endTimer.cancel()
            self.taskEnd(ranks=self._getRanks())
            return

    def _getRanks(self):
        """
        获得排名信息
        """
        udatas = self.usersData.values()
        if udatas:
            udatas.sort(key=lambda x: (x["score"], x["lastCatchId"]),
                        reverse=True)
        ranks = {}
        for m in xrange(len(udatas)):
            if udatas[m]["score"] == 0:
                continue
            ranks[m + 1] = {
                "uid": udatas[m]["uid"],
                "results": udatas[m]["results"]
            }
        return ranks

    def _checkFinished(self, usersData):
        """
        检查是否完成任务
        """
        results = usersData["results"]
        taskType = usersData["task"]["taskType"]
        targets = usersData["task"]["targets"]
        target1 = targets.get("target1", 0)
        target2 = targets.get("target2", 0)
        number1 = targets.get("number1", 999)
        number2 = targets.get("number2", 999)
        finished = False
        if taskType == 1:
            if len(targets.keys()) == 3:  # 一个target会对应有3个字段
                if target1 in results.keys() and results[target1] >= number1:
                    finished = True
            else:
                if target1 in results.keys() and results[target1] >= number1 and \
                   target2 in results.keys() and results[target2] >= number2:
                    finished = True
        else:
            if usersData["results"].get("progress", 0) >= number1:
                finished = True
        return finished
示例#27
0
class FishFightTable(FishTable):
    def __init__(self, room, tableId):
        super(FishFightTable, self).__init__(room, tableId)
        self.clearTableData()
        # 用户离线等待时间
        self._offlineWaitSeconds = 1200
        # 用户空闲超时时间
        self._idleTimeOutSeconds = 1200
        # 用户无子弹时超时时间
        self._inactiveTimeOutSeconds = 1200
        # 桌子过期时间
        self._tableExpiresTime = 600
        # 准备倒计时
        self._readySeconds = 4
        # 初始化定时器
        self._expiresTimer = None
        self._readyTimer = None
        self._beginTimer = None
        # 最大人数
        self.tableSeatCount = self.runConfig.matchConf["table.seat.count"]
        # table_call可用action
        self.actionMap = {
            "robot_leave": self._robotLeave,
            "catch": self._verifyCatch,
            "skill_use": self._skill_use,
            "skill_install": self._skill_install,
            "skill_replace": self._skill_replace,
            "smile": self.doTableSmilies,
            "honor_push": self._honor_push,
            "honor_replace": self._honor_replace,
            "guns_list": self._guns_list,
            "guns_pool": self._guns_pool,
            "ft_start": self.doFTStart,
            "ft_leave": self.doUserLeave,
            "treasure_rewards": self._getTreasureRewards
        }
        self._logger = Logger()
        self._logger.add("gameId", self.gameId)
        self._logger.add("roomId", room.roomId)
        self._logger.add("tableId", tableId)

    @property
    def ftId(self):
        return self.ftTable.ftId if self.ftTable else 0

    @property
    def ftTable(self):
        return self._ftTable

    def clearTableData(self):
        """
        清理桌子数据和状态
        """
        if ftlog.is_debug():
            ftlog.debug("friendTable.clear-->begin", "tableId=", self.tableId)
        self._tableState = TableState.DEFAULT  # 桌子状态
        # 桌子详情(房号、房主、服务费)
        self._ftTable = None
        self._beginTime = None
        self._usersData = {}
        self.targets = {}
        self.ftRanks = []
        self.winnerId = None
        self.otherId = None
        self._overState = None
        if ftlog.is_debug():
            ftlog.debug("friendTable.clear-->end", "tableId=", self.tableId)

    def clearAllTimer(self):
        """
        清理所有的计时器
        """
        if self._readyTimer:
            self._readyTimer.cancel()
            self._readyTimer = None
        if self._beginTimer:
            self._beginTimer.cancel()
            self._beginTimer = None
        if self._expiresTimer:
            self._expiresTimer.cancel()
            self._expiresTimer = None

    def createPlayer(self, table, seatIndex, clientId):
        """
        新创建Player对象
        """
        return FishFightPlayer(table, seatIndex, clientId)

    @locked
    def doFTEnter(self, ftId, userId, seatId):
        ftlog.info("FishFriendTable.doFTEnter", "tableId=", self.tableId,
                   "ftId=", ftId, "seatId=", seatId)
        lang = util.getLanguage(userId)
        if ftId != self.ftId:
            raise TYBizException(
                1,
                config.getMultiLangTextConf("ID_INPUT_ROOMID_ERROR_INFO",
                                            lang=lang))

        player = self.getPlayer(userId)
        if player and player.userId:
            self.sendFriendDetails(userId)
        else:
            if self._expiresTimer:  # 重置桌子超时计时器
                self._expiresTimer.cancel()
                self._expiresTimer = None
            self._expiresTimer = FTLoopTimer(self._tableExpiresTime, 0,
                                             self._tableExpires)
            self._expiresTimer.start()
            self._doTableQuickStart(userId, seatId)  # 用户进入
            self.sendFriendDetails(userId)  # 发送对战详情信息
            if userId != self.ftTable.userId:  # 记录参与者Id
                self.otherId = userId
                fight_history.addOneHistory(userId, self.ftTable.userId,
                                            fight_history.HistoryType.Enter,
                                            self.ftId,
                                            self.ftTable.fee)  # 进入房间记录
        return 0

    def sendFriendDetails(self, userId):
        """发送好友竞技的详情"""
        self._updateFriendInfo(userId)
        self._updateFriendTask()
        if self._tableState >= TableState.READY:
            self._ftStart(userId)

    def _updateFriendInfo(self, userId):
        """更新好友消息"""
        ftPlayer = self.getPlayer(self.ftTable.userId)
        ftName = ""
        if ftPlayer:
            ftName = ftPlayer.name
        player = self.getPlayer(userId)
        if player and player.userId:
            msg = MsgPack()
            msg.setCmd("ft_info")
            msg.setResult("gameId", FISH_GAMEID)
            msg.setResult("roomId", self.roomId)
            msg.setResult("tableId", self.tableId)
            msg.setResult("seatId", player.seatId)
            msg.setResult("userId", player.userId)
            msg.setResult("tableState", self._tableState)
            msg.setResult("reward", self.ftTable.fee)
            msg.setResult("ftId", self.ftTable.ftId)
            msg.setResult("ftUserName", ftName)
            msg.setResult("ftUserId", self.ftTable.userId)
            msg.setResult("timeLong", self.runConfig.playingTime)
            msg.setResult(
                "expirseTime",
                int(self._expiresTimer.getTimeOut())
                if self._expiresTimer else self._tableExpiresTime)
            msg.setResult("targets", self.targets)
            GameMsg.sendMsg(msg, player.userId)

    def _tableExpires(self):
        """桌子过期了"""
        if self._tableState < TableState.START:
            self._sendExpriseHistory()
            self._sendLeaveMsg(reason=1)
            self._clearTable()
示例#28
0
class Heartbeat(object):

    ST_IDLE = 0
    ST_START = 1
    ST_STOP = 2

    def __init__(self, target, interval):
        self._target = target
        self._state = Heartbeat.ST_IDLE
        self._count = 0
        self._postTaskList = []
        self._timer = None
        self._interval = interval
        self._logger = Logger()
        self._init = False

    def start(self):
        assert (self._state == Heartbeat.ST_IDLE)
        self._state = Heartbeat.ST_START
        self._timer = FTLoopTimer(0, 0, self._onInit)
        self._timer.start()

    def stop(self):
        if self._state != Heartbeat.ST_STOP:
            self._state = Heartbeat.ST_STOP
            if self._timer:
                self._timer.cancel()
            self._timer = None

    @property
    def count(self):
        return self._count

    def postCall(self, func, *args, **kwargs):
        self.postTask(functools.partial(func, *args, **kwargs))

    def postTask(self, task):
        if self._state != Heartbeat.ST_STOP:
            self._postTaskList.append(task)
            if self._init and self._timer:
                self._timer.cancel()
                self._timer = FTLoopTimer(0, 0, self._onTimeout)
                self._timer.start()

    def _onInit(self):
        try:
            self._timer = None
            interval = self._target.onInit()
            if interval:
                self._interval = interval
            self._scheduleTimer()
        except:
            self._logger.error("Heartbeat._onInit")

    def _onTimeout(self):
        try:
            self._timer = None
            self._count += 1
            self._processPostTaskList()
            interval = self._target.onHeartbeat()
            if interval is not None:
                self._interval = interval
        except:
            self._interval = 1
            self._logger.error("Heartbeat._onTimeout")
        self._scheduleTimer()

    def _scheduleTimer(self):
        if self._state == Heartbeat.ST_START:
            interval = 0 if self._postTaskList else self._interval
            self._timer = FTLoopTimer(interval, 0, self._onTimeout)
            self._timer.start()

    def _processPostTaskList(self):
        taskList = self._postTaskList
        self._postTaskList = []
        for task in taskList:
            try:
                task()
            except:
                self._logger.error("task=", task)
示例#29
0
class ShortUrlx3me(object):
    def __init__(self, apiKey, secretKey):
        self.apiKey = apiKey
        self.secretKey = secretKey
        self.token = None
        self.expires = None
        self.refreshTimer = None

    def translate(self, longUrl):
        '''
        转换长url为短url
        @return: shortUrl
        '''
        try:
            if self.isExpires():
                self.token, self.expires = self.loadToken()
            return self._getShorUrl(longUrl)
        except:
            ftlog.error('ShortUrlx3me.translate',
                        'longUrl=', longUrl)
            return longUrl
    
    def initialize(self, serverType):
        if serverType == gdata.SRV_TYPE_CENTER:
            # 只在CT中执行刷新token的操作
            self.refreshTimer = FTLoopTimer(300, -1, self._refreshTokenIfNeed)
            self.refreshTimer.start()
            FTLoopTimer(0, 0, self._refreshTokenIfNeed).start()
        else:
            self.refreshTimer = FTLoopTimer(300, -1, self._reloadToken)
            self.refreshTimer.start()
            self._reloadToken()

    def loadToken(self):
        jstr = None
        try:
            jstr = daobase.executeMixCmd('get', 'shortUrl.x3me:token')
            if jstr:
                d = strutil.loads(jstr)
                return d['token'], d['expires']
        except:
            ftlog.error('ShortUrlx3me.getToken',
                        'jstr=', jstr)
        return None, None

    def saveToken(self, token, expires):
        d = {'token':token, 'expires':expires}
        jstr = strutil.dumps(d)
        daobase.executeMixCmd('set', 'shortUrl.x3me:token', jstr)
    
    def isExpires(self, timestamp=None):
        # 离过期时间1小时算过期
        timestamp = timestamp or pktimestamp.getCurrentTimestamp()
        return not self.token or not self.expires or (timestamp + 3600) >= self.expires
    
    def _reloadToken(self):
        self.token, self.expires = self.loadToken()
        ftlog.info('ShortUrlx3me._reloadToken',
                   'token=', self.token,
                   'expires=', self.expires)
        
    def _refreshTokenIfNeed(self, timestamp=None):
        timestamp = timestamp or pktimestamp.getCurrentTimestamp()
        # 重新从数据库读取,可能数据库里面改变了(人工操作)
        self._reloadToken()
        # 提前一天刷新
        if not self.token or (timestamp + 86400) >= self.expires:
            try:
                token, expires = self._requestToken()
                self.saveToken(token, expires)
                ftlog.info('ShortUrlx3me._refreshTokenIfNeed',
                           'old=', (self.token, self.expires),
                           'new=', (token, expires))
                self.token, self.expires = token, expires
            except:
                ftlog.error('Failed to refresh token',
                            'old=', (self.token, self.expires))
        
    def _requestToken(self):
        code = self._requestCode()
        return self._requestTokenWithCode(code)
    
    def _validResponse(self, response):
        datas = strutil.loads(response)
        return datas['status'], datas['info'], datas['data']
    
    def _requestCode(self):
        response, _ = webpage.webget('https://0x3.me/apis/authorize/getCode', method_='GET')
        status, info, data = self._validResponse(response)
        if ftlog.is_debug():
            ftlog.debug('ShortUrlx3me._requestCode',
                        'response=', response)
        if status != 1:
            ftlog.warn('ShortUrlx3me._requestCode',
                       'response=', response)
            raise TYBizException(-1, '%s:%s' % (status, info))
        return data
    
    def _calcSign(self, params):
        kvs = []
        for key in sorted(params.keys()):
            kvs.append('%s=%s' % (key, params[key]))
        kvs.append(self.secretKey)
        signstr = ''.join(kvs)
        return strutil.md5digest(signstr)

    def _requestTokenWithCode(self, code):
        timestr = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        params = {'api_key':self.apiKey, 'code':code, 'request_time':timestr}
        params['sign'] = self._calcSign(params)
        response, _ = webpage.webget('https://0x3.me/apis/authorize/getAccessToken', postdata_=params, method_='POST')
        status, info, data = self._validResponse(response)
        if status != 1:
            ftlog.warn('ShortUrlx3me._requestTokenWithCode',
                       'code=', code,
                       'response=', response)
            raise TYBizException(-1, '%s:%s' % (status, info))
        return data['access_token'], int(data['expire_timestamp'])
    
    def _getShorUrl(self, longUrl):
        if not self.token:
            ftlog.warn('ShortUrlx3me._getShorUrl',
                       'err=', 'NoToken')
            return longUrl
        
        response, _ = webpage.webget('https://0x3.me/apis/urls/add', postdata_={'access_token':self.token, 'longurl':longUrl}, method_='POST')
        status, info, data = self._validResponse(response)
        if status != 1:
            raise TYBizException(-1, '%s:%s' % (status, info))

        return data['short_url']
示例#30
0
class DizhuCtrlRoomFriend(DizhuRoom, MsgHandler):
    def __init__(self, roomDefine):
        super(DizhuCtrlRoomFriend, self).__init__(roomDefine)
        self._ftMap = OrderedDict()
        self._tableCtrl = TableController()
        self._tableManager = self._buildTableManager()
        self._idleFTTimer = FTLoopTimer(60, -1, self._releaseIdleFT)
        self._idleFTTimer.start()
        ftlog.info('DizhuCtrlRoomFriend.DizhuCtrlRoomFriend Succ', 'roomId=',
                   self.roomId, 'tableCount=',
                   self._tableManager.allTableCount)

    def findFT(self, ftId):
        return self._ftMap.get(ftId)

    def createFT(self, userId, ftConf):
        from dizhu.friendtable import ft_service
        ftId = self._genFTId()
        if not ftId:
            raise TYBizException(-1, '资源不足')

        collectedFee = False
        # 收费
        try:
            self._collectFee(userId, ftId, ftConf)
            collectedFee = True
            ft_service.ftBindRoomId(ftId, self.roomId)
            ftTable = FTTable(
                userId, ftId, ftConf, pktimestamp.getCurrentTimestamp(),
                pktimestamp.getCurrentTimestamp() +
                ft_service.getCreatorConf(userId).tableExpires)
            self._ftMap[ftId] = ftTable
            ftlog.info('DizhuCtrlRoomFriend.createFT Succ', 'roomId=',
                       self.roomId, 'userId=', userId, 'ftId=', ftId,
                       'nRound=', ftConf.nRound, 'canDouble=',
                       ftConf.canDouble, 'playMode=', ftConf.playMode,
                       'expires=', ftTable.expires, 'goodCard=',
                       ftConf.goodCard, 'fee=',
                       ftConf.fee.toDict() if ftConf.fee else None)
            return ftTable
        except:
            if collectedFee:
                self._returnFee(userId, ftId, ftConf)
            ft_service.releaseFTId(ftId)
            raise

    def continueFT(self, userId, ftId):
        # 收费
        ftTable = self.findFT(ftId)
        if not ftTable:
            raise TYBizException(-2, '没有找到该牌桌')
        if ftTable.userId != userId:
            raise TYBizException(-3, '只有桌子主人才能继续')
        self._collectFee(userId, ftTable.ftId, ftTable.ftConf)
        from dizhu.friendtable import ft_service
        ftTable.expires = pktimestamp.getCurrentTimestamp(
        ) + ft_service.getCreatorConf(userId).tableExpires
        return ftTable

    def disbindFT(self, ftId, returnFee):
        from dizhu.friendtable import ft_service
        ftTable = self.findFT(ftId)
        if not ftTable:
            raise TYBizException(-1, '没有找到该牌桌')

        # 没有开始则退费
        if not ftTable.table or returnFee:
            self._returnFee(ftTable.userId, ftId, ftTable.ftConf)

        del self._ftMap[ftId]
        if ftTable.table:
            self._tableManager.returnTable(ftTable.table)
        ft_service.releaseFTId(ftId)

        ftlog.info('DizhuCtrlRoomFriend.disbindFT Succ', 'roomId=',
                   self.roomId, 'userId=', ftTable.userId, 'ftId=',
                   ftTable.ftId, 'nRound=', ftTable.ftConf.nRound,
                   'canDouble=', ftTable.ftConf.canDouble, 'playMode=',
                   ftTable.ftConf.playMode, 'fee=',
                   ftTable.ftConf.fee.toDict() if ftTable.ftConf.fee else None)

    def enterFT(self, userId, ftId):
        ftTable = self.findFT(ftId)
        if not ftTable:
            raise TYBizException(-1, '没有找到该牌桌')

        # 绑定桌子
        if not ftTable.table:
            if self._tableManager.idleTableCount < 1:
                raise TYBizException(-1, '桌子资源不足')
            table = self._tableManager.borrowTable()
            ftTable.table = table
            table._ftTable = ftTable
            ftlog.info('DizhuCtrlRoomFriend.enterFT BindTable', 'roomId=',
                       self.roomId, 'userId=', userId, 'ftId=', ftTable.ftId,
                       'tableId=', ftTable.table.tableId)
            # 通知桌子绑定了朋友桌
            self._tableCtrl.bindTable(ftTable.table)

        ec, info = self._tableCtrl.sitdown(ftTable.table, userId)
        if ec != 0:
            raise TYBizException(ec, info)

        ftlog.info('DizhuCtrlRoomFriend.enterFT Succ', 'roomId=', self.roomId,
                   'userId=', userId, 'ftId=', ftTable.ftId, 'tableId=',
                   ftTable.table.tableId)
        return ftTable

    def _releaseIdleFT(self):
        if ftlog.is_debug():
            ftlog.debug('DizhuCtrlRoomFriend._releaseIdleFT', 'roomId=',
                        self.roomId)
        try:
            ftIds = []
            timestamp = pktimestamp.getCurrentTimestamp()
            for ftId, ftTable in self._ftMap.iteritems():
                if (timestamp - ftTable.createTime) >= 60:
                    if not ftTable.table:
                        ftIds.append(ftId)
                else:
                    break
            for ftId in ftIds:
                try:
                    self._ftMap.pop(ftId)
                    ftlog.info('DizhuCtrlRoomFriend._releaseIdleFT', 'roomId=',
                               self.roomId, 'ftId=', ftId, 'reason=',
                               'idleExpires')
                except:
                    pass
        except:
            ftlog.error('DizhuCtrlRoomFriend._releaseIdleFT', 'roomId=',
                        self.roomId)

        ftlog.info('DizhuCtrlRoomFriend._releaseIdleFT', 'roomId=',
                   self.roomId, 'ftCount=', len(self._ftMap))

    def _buildTableManager(self):
        shadowRoomIds = self.roomDefine.shadowRoomIds
        seatCount = self.tableConf.get('maxSeatN')
        ftlog.info('DizhuCtrlRoomFriend._buildTableManager', 'roomId=',
                   self.roomId, 'shadowRoomIds=', list(shadowRoomIds),
                   'seatCount=', seatCount)

        tableManager = TableManager(self)
        for roomId in self.roomDefine.shadowRoomIds:
            count = self.roomDefine.configure['gameTableCount']
            baseId = roomId * 10000 + 1
            ftlog.info('DizhuCtrlRoomFriend._buildTableManager addTables',
                       'roomId=', self.roomId, 'shadowRoomId=', roomId,
                       'baseId=', baseId, 'tableCount=', count)
            for i in xrange(count):
                table = Table(DIZHU_GAMEID, roomId, baseId + i)
                tableManager.addTable(table)
        ftlog.info('FTRoom._buildTableManager Succ', 'roomId=', self.roomId,
                   'shadowRoomIds=', list(shadowRoomIds), 'seatCount=',
                   seatCount, 'tableCount=', tableManager.allTableCount)
        return tableManager

    def _returnFee(self, userId, ftId, ftConf):
        if not ftConf.fee:
            return
        try:
            addCount, final = user_remote.addAsset(DIZHU_GAMEID, userId,
                                                   ftConf.fee.assetKindId,
                                                   ftConf.fee.count, 'FT_FEE',
                                                   int(ftId))
            ftlog.info('DizhuCtrlRoomFriend._returnFee', 'roomId=',
                       self.roomId, 'userId=', userId, 'ftId=', ftId,
                       'nRound=', ftConf.nRound, 'playMode=', ftConf.playMode,
                       'canDouble=', ftConf.canDouble, 'fee=',
                       ftConf.fee.toDict(), 'addCount=', addCount, 'final=',
                       final)
        except:
            ftlog.error('DizhuCtrlRoomFriend._returnFee', 'roomId=',
                        self.roomId, 'userId=', userId, 'ftId=', ftId,
                        'nRound=', ftConf.nRound, 'playMode=', ftConf.playMode,
                        'canDouble=', ftConf.canDouble, 'fee=',
                        ftConf.fee.toDict())

    def _collectFee(self, userId, ftId, ftConf):
        if ftConf.fee:
            consumeCount, final = user_remote.consumeAsset(
                DIZHU_GAMEID, userId, ftConf.fee.assetKindId, ftConf.fee.count,
                'FT_FEE', int(ftId))
            if consumeCount != ftConf.fee.count:
                raise TYBizException(-1, '房卡不足')

            ftlog.info('DizhuCtrlRoomFriend._collectFee', 'roomId=',
                       self.roomId, 'userId=', userId, 'nRound=',
                       ftConf.nRound, 'playMode=', ftConf.playMode,
                       'canDouble=', ftConf.canDouble, 'fee=',
                       ftConf.fee.toDict(), 'cousumeCount=', ftConf.fee.count,
                       'final=', final)

    def _genFTId(self):
        from dizhu.friendtable import ft_service
        for _ in xrange(10):
            ftId = ft_service.genFTId()
            if not self.findFT(ftId):
                return ftId
        return None

    def _do_room__leave(self, msg):
        ftlog.info('DizhuCtrlRoomFriend._do_room__leave', 'roomId=',
                   self.roomId, 'msg=', msg)
        userId = msg.getParam('userId')
        reason = msg.getParam('reason')
        clientRoomId = msg.getParam('clientRoomId')
        ft_table_remote.leaveRoom(self.gameId, userId, clientRoomId, reason)
示例#31
0
文件: rpccore.py 项目: zhaozw/hall37
def _invokeRpcMethod(markParams, argl, argd):
    '''
    进程内其它方法调用RPC方法的代理方法
    '''
    rpc = markParams['rpc']
    rpcSrvType = markParams['rpcSrvType']
    groupIndex = markParams['groupIndex']
    future = markParams['future']
    groupVal = 0
    dstSid = None
    if rpcSrvType == RPC_FIRST_SERVERID:
        dstSid = argl[0]
    else:
        if groupIndex >= 0:
            groupVal = argl[groupIndex]
        if rpcSrvType == gdata.SRV_TYPE_UTIL:
            dstSid = _getRpcDstServerId(router._utilServer, groupVal)
        elif rpcSrvType == gdata.SRV_TYPE_ROOM:
            dstSid = getRpcDstRoomServerId(groupVal, 1)
        elif rpcSrvType == gdata.SRV_TYPE_TABLE:
            dstSid = getRpcDstRoomServerId(groupVal, 0)
        elif rpcSrvType == gdata.SRV_TYPE_CONN:
            dstSid = _getRpcDstServerId(router._connServer, groupVal)
        elif rpcSrvType == gdata.SRV_TYPE_HTTP:
            dstSid = _getRpcDstServerId(router._httpServer, groupVal)
        elif rpcSrvType == gdata.SRV_TYPE_ROBOT:
            dstSid = _getRpcDstServerId(router._robotServer, groupVal)
        elif rpcSrvType == gdata.SRV_TYPE_AGENT:
            dstSid = _getRpcDstServerId(router._agentServer, groupVal)
        elif rpcSrvType == gdata.SRV_TYPE_SDK_HTTP:
            dstSid = _getRpcDstServerId(router._sdkHttpServer, groupVal)
        elif rpcSrvType == gdata.SRV_TYPE_SDK_GATEWAY:
            dstSid = _getRpcDstServerId(router._gatewayHttpServer, groupVal)
        elif rpcSrvType == gdata.SRV_TYPE_CENTER:
            for dst, logics in gdata.centerServerLogics().items():
                if groupVal in logics:
                    dstSid = dst
                    break
            if not dstSid:
                dstSid = router._centerServer.sids[0]

    if not dstSid:
        raise RpcException('RpcException ' + rpc + '! can not location the target server, rpcSrvType=' + str(
            rpcSrvType) + ' groupVal=' + str(groupVal))

    rpcid = _getRpcId()
    if dstSid == gdata.serverId():
        if markParams['syncCall']:
            if future:
                # TODO: Future RPC CALL 1
                return _FutureResultLocal(markParams, argl, argd)
            else:
                ret = _invokeMethodLocked(markParams, argl, argd)
                return strutil.cloneData(ret)
        else:
            ftt = FTLoopTimer(0.01, 0, _invokeMethodLocked, markParams, argl, argd)
            ftt.start()
            return None

    mi = strutil.dumps({'cmd': _runenv._CMD_RPC_,
                        'rpc': rpc,
                        'argl': argl,
                        'argd': argd
                        })

    if markParams['syncCall']:
        if future:
            # TODO: Future RPC CALL 1
            return _FutureResultRemote(rpc, dstSid, mi, rpcid, str(groupVal), _runenv._RPC_TIME_OUT)
        else:
            try:
                jstr = wrapper.query(dstSid, mi, rpcid, str(groupVal), _runenv._RPC_TIME_OUT)
            except FTMsgPackException, e:
                raise e
            except Exception, e:
                ftlog.warn('RpcException msg=', mi)
                raise RpcException('RpcException ' + rpc + ' ! query remote false, ' + str(e))
            return _parseRpcResult(mi, jstr, rpc)
示例#32
0
class HttpGetNdayAfterMatchs(object):
    '''N日后的比赛列表'''
    def __init__(self, interval, ndays, callback):
        self.httpContents = []
        self.callback = callback

        self.now = datetime.datetime.now()
        self._afterday = (self.now +
                          datetime.timedelta(days=ndays)).strftime('%Y-%m-%d')

        self.timer = FTLoopTimer(interval, -1, self._checkResult)
        self.timer.start()

    def __str__(self):
        return '%s:%s' % (self.now, self._afterday)

    def __repr__(self):
        return self.__str__()

    @property
    def key(self):
        return self.__str__()

    def _checkDate(self):
        return self.now.date() == datetime.datetime.now().date()

    def _checkResult(self):
        if ftlog.is_debug():
            ftlog.debug('HttpGetNdayAfterMatchs', 'now=', self.now,
                        '_afterday=', self._afterday)

        if not self._checkDate():
            ftlog.info('hallsportlottery.HttpNdayAfterMatchList',
                       '_checkDate=', self.now.date(), 'nowDate=',
                       datetime.datetime.now().date())
            if self.timer:
                self.timer.cancel()

            if self.callback:
                self.callback(self)

            return

        contents = http7Mgetschedulebydate(self._afterday)
        if contents and len(contents) > 0:
            if self.timer:
                self.timer.cancel()

            self.doContents(contents)

            if self.callback:
                self.callback(self)

    def doContents(self, contents):
        leagues = SportlotteryConf.leaguekeys()
        teams = SportlotteryConf.teamskeys()
        focusTeams = SportlotteryConf.focusTeamskeys()

        schedule = contents.get('Schedule')
        if schedule and len(schedule) > 0:
            for matchDict in schedule:
                match = matchDict['Id']
                if match and len(match) >= 4:
                    if match[1] not in leagues:
                        continue
                    if match[2] not in teams or match[3] not in teams:
                        continue
                    if match[2] not in focusTeams and match[
                            3] not in focusTeams:
                        continue

                    d = {
                        'matchId': match[0],
                        'leagueId': match[1],
                        'homeTeamId': match[2],
                        'awayTeamId': match[3],
                        'timestamp': matchDict['Date'] / 1000
                    }

                    self.httpContents.append(d)