def get_honor_reward(self, honor_id): config = ConfigArenaHonorReward.get(honor_id) if not config: raise GameException(ConfigErrorMessage.get_error_id("BAD_MESSAGE")) if honor_id > self.get_honor_points(): raise GameException(ConfigErrorMessage.get_error_id("ARENA_HONOR_REWARD_POINT_NOT_ENOUGH")) reward_info = self.get_today_honor_reward_info() if honor_id in reward_info: raise GameException(ConfigErrorMessage.get_error_id("ARENA_HONOR_REWARD_ALREADY_GOT")) resource_classified = ResourceClassification.classify(config.reward) resource_classified.add(self.server_id, self.char_id, message="Arena.get_honor_reward:{0}".format(honor_id)) today_key = str(get_start_time_of_today().timestamp) MongoArena.db(self.server_id).update_one( {'_id': str(self.char_id)}, { '$push': { 'honor_rewards.{0}'.format(today_key): honor_id } } ) reward_info.append(honor_id) self.send_honor_notify(reward_info=reward_info) return resource_classified
def remove_point(self, point): new_point = self.check_point(point) MongoArena.db(self.server_id).update_one( {'_id': str(self.char_id)}, {'$set': {'point': new_point}} ) self.send_notify()
def try_create_arena_npc(cls, server_id): if MongoArena.db(server_id).count(): return with ArenaLock(server_id, None).lock(hold_seconds=20): # 这里要进行double-check # 考虑这种情况: # 有两个并发的 try_create_arena_npc 调用 # A先进入,B稍晚进入 # B 首先判断到 MongoArena 没有记录 # 然后等待锁, 此时A已经获取了锁,并且最终填充完数据后,B获得锁 # 此时B必须再进行一次检查,否则B就会生成多余数据 # double-check 在 多线程的 单例模式 中,也是必备 if MongoArena.db(server_id).count(): return npcs = [] for _K, v in ConfigArenaNPC.INSTANCES.iteritems(): for _ in range(v.amount): npc_id = random.choice(v.npcs) _id = "npc:{0}:{1}".format(npc_id, make_string_id()) doc = MongoArena.document() doc['_id'] = _id doc['search_index'] = ConfigArenaSearchRange.START_INDEX npcs.append(doc) score = random.randint(v.score_low, v.score_high) ArenaScore(server_id, _id).set_score(score) MongoArena.db(server_id).insert_many(npcs)
def remove_point(self, point): new_point = self.check_point(point) MongoArena.db(self.server_id).update_one( {'_id': str(self.char_id)}, {'$set': { 'point': new_point }}) self.send_notify()
def add_point(self, point): assert point > 0 MongoArena.db(self.server_id).update_one({'_id': str(self.char_id)}, {'$inc': { 'point': point }}) self.send_notify()
def refresh(self): cd = self.get_refresh_cd() if cd: # 就是要花钱了 ti = TimesInfo(self.server_id, self.char_id) if not ti.remained_reset_times: raise GameException( ConfigErrorMessage.get_error_id( "ARENA_NO_SEARCH_RESET_TIMES")) cost = [ (money_text_to_item_id('diamond'), ti.reset_cost), ] rc = ResourceClassification.classify(cost) rc.check_exist(self.server_id, self.char_id) rc.remove(self.server_id, self.char_id, message="Arena.refresh") ValueLogArenaSearchResetTimes(self.server_id, self.char_id).record() else: ArenaRefreshCD(self.server_id, self.char_id).set(ARENA_REFRESH_CD_SECONDS) rival = self.search_rival() MongoArena.db(self.server_id).update_one({'_id': str(self.char_id)}, {'$set': { 'rival': rival }}) self.send_notify()
def get_honor_reward(self, honor_id): config = ConfigArenaHonorReward.get(honor_id) if not config: raise GameException(ConfigErrorMessage.get_error_id("BAD_MESSAGE")) if honor_id > self.get_honor_points(): raise GameException( ConfigErrorMessage.get_error_id( "ARENA_HONOR_REWARD_POINT_NOT_ENOUGH")) reward_info = self.get_today_honor_reward_info() if honor_id in reward_info: raise GameException( ConfigErrorMessage.get_error_id( "ARENA_HONOR_REWARD_ALREADY_GOT")) resource_classified = ResourceClassification.classify(config.reward) resource_classified.add( self.server_id, self.char_id, message="Arena.get_honor_reward:{0}".format(honor_id)) today_key = str(get_start_time_of_today().timestamp) MongoArena.db(self.server_id).update_one( {'_id': str(self.char_id)}, {'$push': { 'honor_rewards.{0}'.format(today_key): honor_id }}) reward_info.append(honor_id) self.send_honor_notify(reward_info=reward_info) return resource_classified
def refresh(self): cd = self.get_refresh_cd() if cd: # 就是要花钱了 ti = TimesInfo(self.server_id, self.char_id) if not ti.remained_reset_times: raise GameException(ConfigErrorMessage.get_error_id("ARENA_NO_SEARCH_RESET_TIMES")) cost = [(money_text_to_item_id('diamond'), ti.reset_cost), ] rc = ResourceClassification.classify(cost) rc.check_exist(self.server_id, self.char_id) rc.remove(self.server_id, self.char_id, message="Arena.refresh") ValueLogArenaSearchResetTimes(self.server_id, self.char_id).record() else: ArenaRefreshCD(self.server_id, self.char_id).set(ARENA_REFRESH_CD_SECONDS) rival = self.search_rival() MongoArena.db(self.server_id).update_one( {'_id': str(self.char_id)}, {'$set': { 'rival': rival }} ) self.send_notify()
def add_point(self, point): assert point > 0 MongoArena.db(self.server_id).update_one( {'_id': str(self.char_id)}, {'$inc': { 'point': point }} ) self.send_notify()
def send_notify(self): doc = MongoArena.db(self.server_id).find_one( {'_id': str(self.char_id)} ) ti = TimesInfo(self.server_id, self.char_id) notify = ArenaNotify() notify.my_rank = self.get_current_rank() notify.remained_match_times = ti.remained_match_times notify.refresh_cd = self.get_refresh_cd() notify.remained_refresh_times = ti.remained_reset_times notify.refresh_cost = ti.reset_cost notify.remained_buy_times = ti.remained_buy_times notify.buy_cost = ti.buy_cost notify.point = doc['point'] notify.max_rank = self.get_max_rank() notify.my_score = ArenaScore(self.server_id, self.char_id).score if doc['rival']: rival_club = ArenaClub(self.server_id, doc['rival']) notify.rival.id = str(rival_club.id) notify.rival.name = rival_club.name notify.rival.club_flag = rival_club.flag notify.rival.level = rival_club.level notify.rival.power = rival_club.power notify.rival.rank = Arena(self.server_id, doc['rival']).get_current_rank() notify.rival.score = ArenaScore(self.server_id, doc['rival']).score MessagePipe(self.char_id).put(msg=notify)
def send_notify(self): doc = MongoArena.db(self.server_id).find_one( {'_id': str(self.char_id)}) ti = TimesInfo(self.server_id, self.char_id) notify = ArenaNotify() notify.my_rank = self.get_current_rank() notify.remained_match_times = ti.remained_match_times notify.refresh_cd = self.get_refresh_cd() notify.remained_refresh_times = ti.remained_reset_times notify.refresh_cost = ti.reset_cost notify.remained_buy_times = ti.remained_buy_times notify.buy_cost = ti.buy_cost notify.point = doc['point'] notify.max_rank = self.get_max_rank() notify.my_score = ArenaScore(self.server_id, self.char_id).score if doc['rival']: rival_club = ArenaClub(self.server_id, doc['rival']) notify.rival.id = str(rival_club.id) notify.rival.name = rival_club.name notify.rival.club_flag = rival_club.flag notify.rival.level = rival_club.level notify.rival.power = rival_club.power notify.rival.rank = Arena(self.server_id, doc['rival']).get_current_rank() notify.rival.score = ArenaScore(self.server_id, doc['rival']).score MessagePipe(self.char_id).put(msg=notify)
def get_today_honor_reward_info(self): today_key = str(get_start_time_of_today().timestamp) doc = MongoArena.db(self.server_id).find_one( {'_id': str(self.char_id)}, {'honor_rewards.{0}'.format(today_key): 1}) return doc.get('honor_rewards', {}).get(today_key, [])
def send_rank_reward(*args): logger = Logger("arena_send_rank_reward") logger.write("Start") try: for sid in Server.duty_server_ids(): MongoArena.db(sid).update_many({}, {'$set': {'continue_win': 0}}) Arena.send_rank_reward(sid) logger.write("Server {0} Finish".format(sid)) except: logger.error(traceback.format_exc()) else: logger.write("Done") finally: logger.close()
def get_today_honor_reward_info(self): today_key = str(get_start_time_of_today().timestamp) doc = MongoArena.db(self.server_id).find_one( {'_id': str(self.char_id)}, {'honor_rewards.{0}'.format(today_key): 1} ) return doc.get('honor_rewards', {}).get(today_key, [])
def get_max_rank(self): doc = MongoArena.db(self.server_id).find_one( {'_id': str(self.char_id)}, {'max_rank': 1}) max_rank = doc['max_rank'] if max_rank: return max_rank return self.get_current_rank()
def get_max_rank(self): doc = MongoArena.db(self.server_id).find_one( {'_id': str(self.char_id)}, {'max_rank': 1} ) max_rank = doc['max_rank'] if max_rank: return max_rank return self.get_current_rank()
def check_point(self, point): doc = MongoArena.db(self.server_id).find_one( {'_id': str(self.char_id)}, {'point': 1}) current_point = doc.get('point', 0) new_point = current_point - point if new_point < 0: raise GameException( ConfigErrorMessage.get_error_id("ARENA_POINT_NOT_ENOUGH")) return new_point
def send_rank_reward(*args): logger = Logger("arena_send_rank_reward") logger.write("Start") try: for sid in Server.duty_server_ids(): MongoArena.db(sid).update_many( {}, {'$set': { 'continue_win': 0 }} ) Arena.send_rank_reward(sid) logger.write("Server {0} Finish".format(sid)) except: logger.error(traceback.format_exc()) else: logger.write("Done") finally: logger.close()
def check_point(self, point): doc = MongoArena.db(self.server_id).find_one( {'_id': str(self.char_id)}, {'point': 1} ) current_point = doc.get('point', 0) new_point = current_point - point if new_point < 0: raise GameException(ConfigErrorMessage.get_error_id("ARENA_POINT_NOT_ENOUGH")) return new_point
def try_add_self_in_arena(self): doc = MongoArena.db(self.server_id).find_one( {'_id': str(self.char_id)}, {'honor_rewards': 1} ) if doc: # 清理过期的 honor_rewards 记录 honor_rewards = doc.get('honor_rewards', {}) if not honor_rewards: return today_key = str(get_start_time_of_today().timestamp) unset = {} for k in honor_rewards.keys(): if k != today_key: unset['honor_rewards.{0}'.format(k)] = 1 if unset: MongoArena.db(self.server_id).update_one( {'_id': str(self.char_id)}, {'$unset': unset} ) return doc = MongoArena.document() doc['_id'] = str(self.char_id) doc['search_index'] = ConfigArenaSearchRange.START_INDEX MongoArena.db(self.server_id).insert_one(doc) ArenaScore(self.server_id, self.char_id).set_score(ARENA_DEFAULT_SCORE)
def try_add_self_in_arena(self): doc = MongoArena.db(self.server_id).find_one( {'_id': str(self.char_id)}, {'honor_rewards': 1}) if doc: # 清理过期的 honor_rewards 记录 honor_rewards = doc.get('honor_rewards', {}) if not honor_rewards: return today_key = str(get_start_time_of_today().timestamp) unset = {} for k in honor_rewards.keys(): if k != today_key: unset['honor_rewards.{0}'.format(k)] = 1 if unset: MongoArena.db(self.server_id).update_one( {'_id': str(self.char_id)}, {'$unset': unset}) return doc = MongoArena.document() doc['_id'] = str(self.char_id) doc['search_index'] = ConfigArenaSearchRange.START_INDEX MongoArena.db(self.server_id).insert_one(doc) ArenaScore(self.server_id, self.char_id).set_score(ARENA_DEFAULT_SCORE)
def send_rank_reward(cls, server_id): char_ids = Club.get_recent_login_char_ids(server_id) # 加上一分钟,确保已经到了第二天 # 定时任务要是 23:59:59 启动,那天数判断就错了 weekday = arrow.utcnow().to(settings.TIME_ZONE).replace(minutes=1).weekday() for cid in char_ids: arena = Arena(server_id, cid) rank = arena.get_current_rank() # 每日奖励 config = ConfigArenaRankReward.get(rank) rc = ResourceClassification.classify(config.reward) m = MailManager(server_id, cid) m.add( config.mail_title, config.mail_content, attachment=rc.to_json(), ) if weekday == 0: # 周一发周奖励 config_weekly = ConfigArenaRankRewardWeekly.get(rank) rc = ResourceClassification.classify(config_weekly.reward) m = MailManager(server_id, cid) m.add( config_weekly.mail_title, config_weekly.mail_content, attachment=rc.to_json() ) if weekday == 0: docs = MongoArena.db(server_id).find( {'_id': {'$regex': '^\d+$'}}, {'_id': 1} ) default_score_doc = MongoArenaScore.db(server_id).find_one({'_id': ARENA_DEFAULT_SCORE}) for doc in docs: if doc['_id'] in default_score_doc['char_ids']: continue ArenaScore(server_id, int(doc['_id'])).set_score(ARENA_DEFAULT_SCORE)
def send_rank_reward(cls, server_id): char_ids = Club.get_recent_login_char_ids(server_id) # 加上一分钟,确保已经到了第二天 # 定时任务要是 23:59:59 启动,那天数判断就错了 weekday = arrow.utcnow().to( settings.TIME_ZONE).replace(minutes=1).weekday() for cid in char_ids: arena = Arena(server_id, cid) rank = arena.get_current_rank() # 每日奖励 config = ConfigArenaRankReward.get(rank) rc = ResourceClassification.classify(config.reward) m = MailManager(server_id, cid) m.add( config.mail_title, config.mail_content, attachment=rc.to_json(), ) if weekday == 0: # 周一发周奖励 config_weekly = ConfigArenaRankRewardWeekly.get(rank) rc = ResourceClassification.classify(config_weekly.reward) m = MailManager(server_id, cid) m.add(config_weekly.mail_title, config_weekly.mail_content, attachment=rc.to_json()) if weekday == 0: docs = MongoArena.db(server_id).find({'_id': { '$regex': '^\d+$' }}, {'_id': 1}) default_score_doc = MongoArenaScore.db(server_id).find_one( {'_id': ARENA_DEFAULT_SCORE}) for doc in docs: if doc['_id'] in default_score_doc['char_ids']: continue ArenaScore(server_id, int(doc['_id'])).set_score(ARENA_DEFAULT_SCORE)
def match(self, formation_slots=None): doc = MongoArena.db(self.server_id).find_one( {'_id': str(self.char_id)}, {'rival': 1} ) rival_id = doc['rival'] if not rival_id: raise GameException(ConfigErrorMessage.get_error_id("ARENA_MATCH_NO_RIVAL")) f = Formation(self.server_id, self.char_id) if formation_slots: f.sync_slots(formation_slots) self.check_and_buy_times() club_one = Club(self.server_id, self.char_id) club_two = ArenaClub(self.server_id, rival_id) club_match = ClubMatch(club_one, club_two, 6, f.get_skill_sequence(), {}) msg = club_match.start() msg.key = rival_id msg.map_name = GlobalConfig.value_string("MATCH_MAP_ARENA") return msg
def match(self, formation_slots=None): doc = MongoArena.db(self.server_id).find_one( {'_id': str(self.char_id)}, {'rival': 1}) rival_id = doc['rival'] if not rival_id: raise GameException( ConfigErrorMessage.get_error_id("ARENA_MATCH_NO_RIVAL")) f = Formation(self.server_id, self.char_id) if formation_slots: f.sync_slots(formation_slots) self.check_and_buy_times() club_one = Club(self.server_id, self.char_id) club_two = ArenaClub(self.server_id, rival_id) club_match = ClubMatch(club_one, club_two, 6, f.get_skill_sequence(), {}) msg = club_match.start() msg.key = rival_id msg.map_name = GlobalConfig.value_string("MATCH_MAP_ARENA") return msg
def _query(low, high): condition = [ { '_id': { '$gte': low } }, { '_id': { '$lte': high } }, ] _docs = MongoArenaScore.db(self.server_id).find( {'$and': condition}) _char_ids = [] for _doc in _docs: _char_ids.extend(_doc['char_ids']) random.shuffle(_char_ids) amount = len(_char_ids) # 上面已经按照积分范围选除了 角色id # 下面用各种条件过滤 npc = [] real = [] loop_times = 0 for cid in _char_ids: if cid == str(self.char_id): continue # 有cd的肯定的就不要了 if ArenaMatchCD(self.server_id, self.char_id, cid).get_cd_seconds(): continue if is_npc_club(cid): npc.append(cid) else: # 选出来的真实玩家,需要一次都没打过 _rival_doc = MongoArena.db(self.server_id).find_one( {'_id': cid}, {'match_times': 1}) if _rival_doc.get('match_times', 0): real.append(cid) # 第一次,优先给NPC if match_times == 0: if npc: return npc[0] else: if loop_times >= amount / 2: # 已经跑了一半了,还没玩家, 就返回NPC吧 if npc: return npc[0] else: if real: return real[0] loop_times += 1 # 走到这儿,已经循环完了,原因 # 1 如果是第一次, 那就没有Npc # 2 如果不是第一次,那就没有 符合条件的 real # 这时候有什么就给什么吧 if real: return real[0] if npc: return npc[0] return None
def _query(low, high): condition = [ {'_id': {'$gte': low}}, {'_id': {'$lte': high}}, ] _docs = MongoArenaScore.db(self.server_id).find({'$and': condition}) _char_ids = [] for _doc in _docs: _char_ids.extend(_doc['char_ids']) random.shuffle(_char_ids) amount = len(_char_ids) # 上面已经按照积分范围选除了 角色id # 下面用各种条件过滤 npc = [] real = [] loop_times = 0 for cid in _char_ids: if cid == str(self.char_id): continue # 有cd的肯定的就不要了 if ArenaMatchCD(self.server_id, self.char_id, cid).get_cd_seconds(): continue if is_npc_club(cid): npc.append(cid) else: # 选出来的真实玩家,需要一次都没打过 _rival_doc = MongoArena.db(self.server_id).find_one({'_id': cid}, {'match_times': 1}) if _rival_doc.get('match_times', 0): real.append(cid) # 第一次,优先给NPC if match_times == 0: if npc: return npc[0] else: if loop_times >= amount / 2: # 已经跑了一半了,还没玩家, 就返回NPC吧 if npc: return npc[0] else: if real: return real[0] loop_times += 1 # 走到这儿,已经循环完了,原因 # 1 如果是第一次, 那就没有Npc # 2 如果不是第一次,那就没有 符合条件的 real # 这时候有什么就给什么吧 if real: return real[0] if npc: return npc[0] return None
def search_rival(self): # 获取对手 def _query(low, high): condition = [ { '_id': { '$gte': low } }, { '_id': { '$lte': high } }, ] _docs = MongoArenaScore.db(self.server_id).find( {'$and': condition}) _char_ids = [] for _doc in _docs: _char_ids.extend(_doc['char_ids']) random.shuffle(_char_ids) amount = len(_char_ids) # 上面已经按照积分范围选除了 角色id # 下面用各种条件过滤 npc = [] real = [] loop_times = 0 for cid in _char_ids: if cid == str(self.char_id): continue # 有cd的肯定的就不要了 if ArenaMatchCD(self.server_id, self.char_id, cid).get_cd_seconds(): continue if is_npc_club(cid): npc.append(cid) else: # 选出来的真实玩家,需要一次都没打过 _rival_doc = MongoArena.db(self.server_id).find_one( {'_id': cid}, {'match_times': 1}) if _rival_doc.get('match_times', 0): real.append(cid) # 第一次,优先给NPC if match_times == 0: if npc: return npc[0] else: if loop_times >= amount / 2: # 已经跑了一半了,还没玩家, 就返回NPC吧 if npc: return npc[0] else: if real: return real[0] loop_times += 1 # 走到这儿,已经循环完了,原因 # 1 如果是第一次, 那就没有Npc # 2 如果不是第一次,那就没有 符合条件的 real # 这时候有什么就给什么吧 if real: return real[0] if npc: return npc[0] return None doc = MongoArena.db(self.server_id).find_one( {'_id': str(self.char_id)}, { 'search_index': 1, 'match_times': 1 }) search_index = doc['search_index'] match_times = doc.get('match_times', 0) my_score = ArenaScore(self.server_id, self.char_id).score rival_id = 0 _search_times = 0 while True: if _search_times > len(ConfigArenaSearchRange.LIST) * 2: break # 这里循环 search_index if search_index > ConfigArenaSearchRange.MAX_INDEX: search_index = ConfigArenaSearchRange.START_INDEX - 1 elif search_index < 0: search_index = ConfigArenaSearchRange.START_INDEX search_config = ConfigArenaSearchRange.get(search_index) rival_id = _query(my_score * search_config.range_1, my_score * search_config.range_2) if rival_id: break # 这里改变 search_index if search_index >= ConfigArenaSearchRange.START_INDEX: search_index += 1 else: search_index -= 1 _search_times += 1 if not rival_id: # 找不到人的情况就是 第一名的, 积分太高, 实在找不到. 就随机选一个 docs = MongoArena.db(self.server_id).find( { '_id': { '$ne': str(self.char_id) } }, { '_id': 1 }).limit(200) char_ids = [] for doc in docs: char_ids.append(doc['_id']) rival_id = random.choice(char_ids) return rival_id
def report(self, key, win): rival_id = key my_rank = self.get_current_rank() my_max_rank = self.get_max_rank() doc = MongoArena.db(self.server_id).find_one( {'_id': str(self.char_id)}, { 'search_index': 1, 'continue_win': 1, }) ArenaRefreshCD(self.server_id, self.char_id).clean() ArenaMatchCD(self.server_id, self.char_id, rival_id).set(GlobalConfig.value("ARENA_MATCH_CD")) config_search = ConfigArenaSearchRange.get(doc['search_index']) if win: score_changed = config_search.score_win new_search_index = doc['search_index'] + 1 continue_win = doc.get('continue_win', 0) + 1 else: score_changed = -config_search.score_lose new_search_index = doc['search_index'] - 1 continue_win = 0 if new_search_index > ConfigArenaSearchRange.MAX_INDEX: new_search_index = ConfigArenaSearchRange.MAX_INDEX if new_search_index < 0: new_search_index = 0 MongoArena.db(self.server_id).update_one({'_id': str(self.char_id)}, { '$set': { 'search_index': new_search_index, 'rival': 0, 'continue_win': continue_win, }, '$inc': { 'match_times': 1, } }) ass = ArenaScore(self.server_id, self.char_id) score_changed = ass.add_score(score_changed) new_rank = ass.rank max_rank_changed = False if new_rank > my_max_rank: my_max_rank = new_rank MongoArena.db(self.server_id).update_one( {'_id': str(self.char_id)}, {'$set': { 'max_rank': new_rank }}) max_rank_changed = True rank_changed = new_rank - my_rank rival_rank = Arena(self.server_id, rival_id).get_current_rank() if win: ValueLogArenaWinTimes(self.server_id, self.char_id).record() config_reward = ConfigArenaMatchReward.get(1) else: config_reward = ConfigArenaMatchReward.get(2) ValueLogArenaHonorPoints( self.server_id, self.char_id).record(value=config_reward.honor) ValueLogArenaMatchTimes(self.server_id, self.char_id).record() drop = config_reward.get_drop() resource_classified = ResourceClassification.classify(drop) resource_classified.add(self.server_id, self.char_id, message="Arena.report:{0}".format(win)) self.send_honor_notify() self.send_notify() arena_match_signal.send( sender=None, server_id=self.server_id, char_id=self.char_id, target_id=rival_id, target_name=ArenaClub(self.server_id, rival_id).name, my_rank=new_rank, target_rank=rival_rank, win=win, continue_win=continue_win, ) if max_rank_changed: task_condition_trig_signal.send(sender=None, server_id=self.server_id, char_id=self.char_id, condition_name='core.arena.Arena') WinningArena(self.server_id, self.char_id).set(win) return resource_classified, score_changed, -rank_changed, my_max_rank, new_rank, ass.score
def report(self, key, win): rival_id = key my_rank = self.get_current_rank() my_max_rank = self.get_max_rank() doc = MongoArena.db(self.server_id).find_one( {'_id': str(self.char_id)}, { 'search_index': 1, 'continue_win': 1, } ) ArenaRefreshCD(self.server_id, self.char_id).clean() ArenaMatchCD(self.server_id, self.char_id, rival_id).set(GlobalConfig.value("ARENA_MATCH_CD")) config_search = ConfigArenaSearchRange.get(doc['search_index']) if win: score_changed = config_search.score_win new_search_index = doc['search_index'] + 1 continue_win = doc.get('continue_win', 0) + 1 else: score_changed = -config_search.score_lose new_search_index = doc['search_index'] - 1 continue_win = 0 if new_search_index > ConfigArenaSearchRange.MAX_INDEX: new_search_index = ConfigArenaSearchRange.MAX_INDEX if new_search_index < 0: new_search_index = 0 MongoArena.db(self.server_id).update_one( {'_id': str(self.char_id)}, { '$set': { 'search_index': new_search_index, 'rival': 0, 'continue_win': continue_win, }, '$inc': { 'match_times': 1, } } ) ass = ArenaScore(self.server_id, self.char_id) score_changed = ass.add_score(score_changed) new_rank = ass.rank max_rank_changed = False if new_rank > my_max_rank: my_max_rank = new_rank MongoArena.db(self.server_id).update_one( {'_id': str(self.char_id)}, {'$set': {'max_rank': new_rank}} ) max_rank_changed = True rank_changed = new_rank - my_rank rival_rank = Arena(self.server_id, rival_id).get_current_rank() if win: ValueLogArenaWinTimes(self.server_id, self.char_id).record() config_reward = ConfigArenaMatchReward.get(1) else: config_reward = ConfigArenaMatchReward.get(2) ValueLogArenaHonorPoints(self.server_id, self.char_id).record(value=config_reward.honor) ValueLogArenaMatchTimes(self.server_id, self.char_id).record() drop = config_reward.get_drop() resource_classified = ResourceClassification.classify(drop) resource_classified.add(self.server_id, self.char_id, message="Arena.report:{0}".format(win)) self.send_honor_notify() self.send_notify() arena_match_signal.send( sender=None, server_id=self.server_id, char_id=self.char_id, target_id=rival_id, target_name=ArenaClub(self.server_id, rival_id).name, my_rank=new_rank, target_rank=rival_rank, win=win, continue_win=continue_win, ) if max_rank_changed: task_condition_trig_signal.send( sender=None, server_id=self.server_id, char_id=self.char_id, condition_name='core.arena.Arena' ) WinningArena(self.server_id, self.char_id).set(win) return resource_classified, score_changed, -rank_changed, my_max_rank, new_rank, ass.score
def search_rival(self): # 获取对手 def _query(low, high): condition = [ {'_id': {'$gte': low}}, {'_id': {'$lte': high}}, ] _docs = MongoArenaScore.db(self.server_id).find({'$and': condition}) _char_ids = [] for _doc in _docs: _char_ids.extend(_doc['char_ids']) random.shuffle(_char_ids) amount = len(_char_ids) # 上面已经按照积分范围选除了 角色id # 下面用各种条件过滤 npc = [] real = [] loop_times = 0 for cid in _char_ids: if cid == str(self.char_id): continue # 有cd的肯定的就不要了 if ArenaMatchCD(self.server_id, self.char_id, cid).get_cd_seconds(): continue if is_npc_club(cid): npc.append(cid) else: # 选出来的真实玩家,需要一次都没打过 _rival_doc = MongoArena.db(self.server_id).find_one({'_id': cid}, {'match_times': 1}) if _rival_doc.get('match_times', 0): real.append(cid) # 第一次,优先给NPC if match_times == 0: if npc: return npc[0] else: if loop_times >= amount / 2: # 已经跑了一半了,还没玩家, 就返回NPC吧 if npc: return npc[0] else: if real: return real[0] loop_times += 1 # 走到这儿,已经循环完了,原因 # 1 如果是第一次, 那就没有Npc # 2 如果不是第一次,那就没有 符合条件的 real # 这时候有什么就给什么吧 if real: return real[0] if npc: return npc[0] return None doc = MongoArena.db(self.server_id).find_one( {'_id': str(self.char_id)}, {'search_index': 1, 'match_times': 1} ) search_index = doc['search_index'] match_times = doc.get('match_times', 0) my_score = ArenaScore(self.server_id, self.char_id).score rival_id = 0 _search_times = 0 while True: if _search_times > len(ConfigArenaSearchRange.LIST) * 2: break # 这里循环 search_index if search_index > ConfigArenaSearchRange.MAX_INDEX: search_index = ConfigArenaSearchRange.START_INDEX - 1 elif search_index < 0: search_index = ConfigArenaSearchRange.START_INDEX search_config = ConfigArenaSearchRange.get(search_index) rival_id = _query(my_score * search_config.range_1, my_score * search_config.range_2) if rival_id: break # 这里改变 search_index if search_index >= ConfigArenaSearchRange.START_INDEX: search_index += 1 else: search_index -= 1 _search_times += 1 if not rival_id: # 找不到人的情况就是 第一名的, 积分太高, 实在找不到. 就随机选一个 docs = MongoArena.db(self.server_id).find( {'_id': {'$ne': str(self.char_id)}}, {'_id': 1} ).limit(200) char_ids = [] for doc in docs: char_ids.append(doc['_id']) rival_id = random.choice(char_ids) return rival_id