def show_worldtop(bot, update, args):
    battle_id = None
    if args:
        try:
            battle_id = int(args[0])
            if battle_id < 0:
                battle_id = count_battle_id() + battle_id
        except ValueError:
            pass
    worldtop = load_worldtop(battle_id=battle_id)
    if worldtop is None and battle_id is None:
        battle_id = count_battle_id()
        for i in range(6):
            worldtop = load_worldtop(battle_id - i)
            if worldtop is not None:
                break
    response = "Worldtop: {}\n".format("битва {}\n({}):".format(
        battle_id,
        count_battle_time(battle_id).strftime("%d/%m/%y %H:%M:%S")
    ) if battle_id is not None else "")
    i = 1
    for k, v in list(worldtop.items()):
        response += "# {} {}: <code>{:>5}</code> 🏆 очков\n".format(i, k, v)
        i += 1
    bot.send_message(chat_id=update.message.chat_id,
                     text=response,
                     parse_mode='HTML')
示例#2
0
def battle_equip(bot, update):
    mes = update.message
    if mes.from_user.id != SUPER_ADMIN_ID:
        return
    battle_id = re.search("\\d+", mes.text)
    if battle_id is None:
        battle_id = count_battle_id(mes)
    else:
        battle_id = int(battle_id.group(0))
    full = 'full' in mes.text
    request = "select player_id, equip from reports where battle_id = %s and equip is not null " \
              "order by equip ->> 'status'"
    cursor.execute(request, (battle_id, ))
    rows = cursor.fetchall()
    response = "Дроп с битвы {} - {} :\n".format(
        battle_id,
        count_battle_time(battle_id).strftime("%d/%m/%y %H:%M:%S"))
    for row in rows:
        name, found_from = row[1].get("name"), row[1].get("from")
        player = Player.get_player(row[0])
        response += "{}<b>{}</b> {}\n".format(
            "{} ".format((player.castle + player.nickname) if full else ""),
            name,
            "(От {})".format(found_from) if found_from is not None else "")
    bot.send_message(chat_id=mes.chat_id, text=response, parse_mode='HTML')
 def get_reports_count(self):
     if count_battle_id(None) != self.__reports_counted_battle_id or \
             not (self.__total_reports_count >= 0 and self.__current_reports_count >= 0 and
                  self.__previous_reports_count >= 0):
         self.count_reports()
     return [
         self.__current_reports_count, self.__previous_reports_count,
         self.__total_reports_count
     ]
def save_worldtop(worldtop: dict, battle_id: int = None):
    try:
        if battle_id is None:
            battle_id = count_battle_id()
        request = "insert into worldtop(battle_id, "
        args = [battle_id]
        for k, v in list(worldtop.items()):
            request += "{}, ".format(emodji_to_castle_names.get(k))
            args.append(v)
        request = request[:-2] + ')' + 'values(%s, %s, %s, %s, %s, %s, %s, %s)'
        cursor.execute(request, args)
    except Exception:
        logging.error(traceback.format_exc())
def load_worldtop(battle_id: int = None) -> dict:
    """
    Загружает /worldtop после битвы с battle_id
    :return: { str: int }
    """
    if battle_id is None:
        battle_id = count_battle_id()
    request = "select ferma, amber, oplot, rassvet, tortuga, night, skala from worldtop where battle_id = %s"
    cursor.execute(request, (battle_id, ))
    row = cursor.fetchone()
    if not row:
        return {}
    worldtop = {k: v for k, v in zip(castles, row)}
    sort_worldtop(worldtop)
    return worldtop
示例#6
0
def parse_worldtop_strings_results(worldtop_strings):
    worldtop = load_worldtop(battle_id=count_battle_id() - 1)
    for string in worldtop_strings:
        parse = re.search("(.).* \\+(\\d+) 🏆 очков", string)
        if parse is None:
            continue
        castle = parse.group(1)
        count = int(parse.group(2))
        score = worldtop.get(castle, 0)
        score += count
        worldtop.update({castle: score})
        sort_worldtop(worldtop)
        logging.info("Worldtop updated: {}: {}".format(castle, count))
    save_worldtop(worldtop)
    return worldtop
示例#7
0
 def count_reports(self):
     self.__current_reports_count, self.__previous_reports_count, self.__total_reports_count = 0, 0, 0
     request = "select battle_id from reports where player_id = %s and exp != 0"
     cursor.execute(request, (self.id,))
     row = cursor.fetchone()
     self.__reports_counted_battle_id = count_battle_id(None)
     current_week = count_week_by_battle_id(self.__reports_counted_battle_id)
     while row is not None:
         week = count_week_by_battle_id(row[0])
         if week == current_week:
             self.__current_reports_count += 1
         elif week == current_week - 1:
             self.__previous_reports_count += 1
         self.__total_reports_count += 1
         row = cursor.fetchone()
示例#8
0
    def count_battle_stats(self, battle_id: int = None):
        if battle_id is None:
            battle_id = count_battle_id() - 1
        cursor = conn.cursor()
        request = "select r.attack, r.defense, r.exp, r.gold, r.stock " \
                  "from reports r join players p on r.player_id = p.id where p.guild = %s and r.battle_id = %s"
        cursor.execute(request, (self.id, battle_id))
        row = cursor.fetchone()
        total_attack, total_defense, total_exp, total_gold, total_stock = 0, 0, 0, 0, 0
        while row:
            attack, defense, exp, gold, stock = row
            total_attack += attack
            total_defense += defense
            total_exp += exp
            total_gold += gold
            total_stock += stock

            row = cursor.fetchone()

        return total_attack, total_defense, total_exp, total_gold, total_stock
示例#9
0
def save_worldtop(worldtop: dict, battle_id: int = None):
    cursor = conn.cursor()
    try:
        if battle_id is None:
            battle_id = count_battle_id()
        request = "insert into worldtop(battle_id, "
        args = [battle_id]
        for k, v in list(worldtop.items()):
            request += "{}, ".format(emodji_to_castle_names.get(k))
            args.append(v)
        request = request[:-2] + ')' + 'values(%s, %s, %s, %s, %s, %s, %s, %s)'
        cursor.execute(request, args)
    except psycopg2.IntegrityError:
        request = "update worldtop set "
        for k, v in list(worldtop.items()):
            request += "{} = {}, ".format(emodji_to_castle_names.get(k), v)
        request = request[:-2] + " where battle_id = {}".format(battle_id)
        cursor.execute(request)
    except Exception:
        logging.error(traceback.format_exc())
    cursor.close()
示例#10
0
def remember_exp(bot, job):
    cursor = conn.cursor()
    request = "select id, exp, exp_info from players"
    cursor.execute(request)
    rows = cursor.fetchall()
    battle_id = count_battle_id(None)
    for row in rows:
        player_id, exp, exp_info = row
        player = Player.get_player(player_id)
        if exp_info is None:
            exp_info = {}
        exp_info.update({str(battle_id): exp})
        exp_info = {
            k: v
            for k, v in sorted(list(exp_info.items()), key=lambda x: int(x[0]))
        }
        player.exp_info = exp_info
        player.update()
        # request = "update players set exp_info = %s where id = %s"
        # cursor.execute(request, (json.dumps(exp_info, ensure_ascii=False), player_id))
    plan_remember_exp()
def parse_stats():
    data = castles_stats_queue.get()
    while data is not None:
        debug = data.get("debug", False)
        data = data.get("data")
        # logging.error("Got data in parse: {}".format(data))
        if 'Результаты сражений:' in data:
            # Результаты битвы замков
            if not debug:
                response_all = "Игроки, попавшие в топ:\n"
                for guild_id in Guild.guild_ids:
                    response = ""
                    guild = Guild.get_guild(guild_id=guild_id)
                    tag = guild.tag
                    for castle_results_string in data.split("\n\n"):
                        if tag in castle_results_string:
                            try:
                                attacked_castle = re.search(
                                    '[🍁☘🖤🐢🦇🌹🍆]',
                                    castle_results_string).group(0)
                            except TypeError:
                                attacked_castle = "???"
                            nicknames_list = re.findall(
                                ".\\[{}\\][^🍁☘🖤🐢🦇🌹🍆🎖\n]+".format(tag),
                                castle_results_string)
                            print(nicknames_list)
                            for nickname in nicknames_list:
                                if response == "":
                                    response = "Игроки, попавшие в топ:\n"
                                response += "{}{} <b>{}</b>\n".format(
                                    "🛡️" if nickname[0] == attacked_castle else
                                    "⚔️", attacked_castle, nickname[:-1])

                                response_all += "{}{} <b>{}</b>\n".format(
                                    "🛡️" if nickname[0] == attacked_castle else
                                    "⚔️", attacked_castle, nickname[:-1])

                    if response != "":
                        if guild.chat_id is None:
                            continue
                        dispatcher.bot.send_message(chat_id=guild.chat_id,
                                                    text=response,
                                                    parse_mode='HTML')
                if response_all != "Игроки, попавшие в топ:\n":
                    dispatcher.bot.send_message(chat_id=CENTRAL_SQUARE_CHAT_ID,
                                                text=response_all,
                                                parse_mode='HTML')
            worldtop_strings = data.split("\n\n")[-1].splitlines()
            worldtop = load_worldtop(battle_id=count_battle_id() - 1)
            old_worldtop = copy.deepcopy(worldtop)
            for string in worldtop_strings:
                parse = re.search("(.).* \\+(\\d+) 🏆 очков", string)
                if parse is None:
                    continue
                castle = parse.group(1)
                count = int(parse.group(2))
                score = worldtop.get(castle)
                score += count
                worldtop.update({castle: score})
                sort_worldtop(worldtop)
                logging.info("Worldtop updated: {}: {}".format(castle, count))
            save_worldtop(worldtop)
            if not debug:
                send_worldtop_update(old_worldtop, worldtop)
            logging.info("Worldtop at the end: {}".format(worldtop))
        elif data.startswith("🤝Headquarters news:") or data.startswith(
                "🗺State of map:"):
            # Итоги штабов альянсов
            logging.info("Got alliance news")
            parse_alliance_battle_results(data, debug)
        else:
            #  Сообщение о пиратстве
            response_by_tags = {}
            data = data.replace("Attackers:", "   🗡Атакующие:")
            data = data.replace("Defenders:", "   🛡Обороняющиеся:")
            guild_list = re.split("[⚔🛡] ..?Гильдия", data)
            for guild_str in guild_list:
                new_str = guild_str
                new_str = "{}".format('⚔️' if 'атакована' in
                                      new_str else '🛡') + new_str
                tags = re.findall("[🍁☘🖤🐢🦇🌹🍆](\\w+)", guild_str)
                tags = list(set(tags))
                for tag in tags:
                    new_str = new_str.replace(tag, "<b>{}</b>".format(tag))
                for tag in tags:
                    lst = response_by_tags.get(tag)
                    if lst is None:
                        lst = "Итоги гильдейских битв с вашим участием:\n\n"
                        response_by_tags.update({tag: lst})
                    lst += new_str + "\n"
                    response_by_tags.update({tag: lst})
                # dispatcher.bot.send_message(chat_id=SUPER_ADMIN_ID, text=guild_str, parse_mode='HTML')
            import json
            # logging.error("Guild list for parse_stats: {}".format(json.dumps(guild_list, indent=4, ensure_ascii=False)))
            logging.error("Response by tags: {}".format(
                json.dumps(response_by_tags, indent=4, ensure_ascii=False)))
            print(guild_list)
            print(json.dumps(response_by_tags, indent=4, ensure_ascii=False))
            for tag, string in list(response_by_tags.items()):
                guild = Guild.get_guild(guild_tag=tag)
                if guild is None:
                    continue
                dispatcher.bot.send_message(chat_id=guild.chat_id,
                                            text=string,
                                            parse_mode='HTML')
        data = castles_stats_queue.get()
def get_top_text(guild,
                 battles_for_count,
                 max_players=None,
                 curr_cursor=None) -> [str]:
    if max_players is None:
        max_players = 10000
    if curr_cursor is None:
        curr_cursor = cursor
    total_battles = count_battles_in_this_week()
    players = []
    for player_id in guild.members:
        player = Player.get_player(player_id, notify_on_error=False)
        if player is None:
            continue
        request = "select exp, gold, stock from reports where player_id = %s and battle_id >= %s"
        curr_cursor.execute(request,
                            (player_id, count_battle_id(message=None) -
                             battles_for_count + 1))  # За последние 3 битвы
        row = curr_cursor.fetchone()
        exp, gold, stock = 0, 0, 0
        while row is not None:
            exp += row[0]
            gold += row[1]
            stock += row[2]
            row = curr_cursor.fetchone()
        reports = player.get_reports_count()[0]
        players.append([
            player, exp, gold, stock,
            "{}/{} ({}%)".format(reports, total_battles,
                                 reports * 100 // total_battles)
        ])
    ret = []
    response = "📈Топ <b>{}</b> за {} по битвам:\n".format(
        guild.tag, "день" if battles_for_count == 3 else "неделю")

    tops = [
        "🔥По опыту:", "💰По золоту:", "📦По стоку:",
        "⚔️Участие в битвах на этой неделе:"
    ]
    for i, top in enumerate(tops):
        response += "\n<b>{}</b>\n".format(top)
        players.sort(
            key=lambda x: x[i + 1]
            if isinstance(x[i + 1], int) else int(x[i + 1].partition("/")[0]),
            reverse=True)
        for j, elem in enumerate(players):
            if (j < max_players
                    or j == len(players) - 1) or (i == (len(tops) - 1)
                                                  and battles_for_count == 21):
                response += "{}){}{} — {}<code>{}</code>" \
                            "\n".format(j + 1, elem[0].castle,
                                        "{}{}".format(elem[0].nickname.partition("]")[2] if "]" in elem[0].nickname else
                                                      elem[0].nickname, '🎗' if elem[0].id == guild.commander_id else
                                                                        ""), top[0], elem[i + 1])
            elif j == max_players:
                response += "...\n"
            if len(response) > MAX_MESSAGE_LENGTH:
                ret.append(response)
                response = ""
    if response != "":
        ret.append(response)
    return ret
示例#13
0
def add_report(bot, update, user_data):
    """
    Функция сохранения репорта от игрока
    """
    mes = update.message
    s = mes.text
    player = Player.get_player(mes.from_user.id)
    if player is None:
        return

    try:
        forward_message_date = utc.localize(
            mes.forward_date).astimezone(tz=moscow_tz).replace(tzinfo=None)
    except ValueError:
        try:
            forward_message_date = mes.forward_date
        except AttributeError:
            forward_message_date = local_tz.localize(
                mes.date).astimezone(tz=moscow_tz).replace(tzinfo=None)

    line = re.search(
        "[🍆🍁☘️🌹🐢🦇🖤️]*(.*)\\s⚔:(\\d+)\\(?(.?\\d*)\\)?.*🛡:(\\d+)\\(?(.?\\d*)\\)?.*Lvl: (\\d+)\\s",
        s)
    """ 
    . - замок, (.*)\\s - никнейм в игре - от замка до эмодзи атаки. ⚔:(\\d+) - Парсинг атаки в конкретной битве
    \\(? - Возможно атака подверглась модификациям, тогда сразу после числа атаки будет открывающая скобка. 
    \\(?(.?\\d*)\\)? - Парсинг дополнительной атаки целиком. Группа будет равна ' ', то есть одному пробельному символу,
    если дополнительной атаки нет.
    .*🛡: - всё лишнее до дефа. Далее абсолютно аналогично атаке 🛡:(\\d+)\\(?(.?\\d*)\\)?
    .*Lvl: (\\d+)\\s - лишнее до уровня и парсинг уровня, в комментариях не нуждается
    """
    nickname = line.group(1)
    if nickname != player.nickname:
        bot.send_message(
            chat_id=mes.chat_id,
            text="Это не ваш репорт. В случае ошибок обновите профиль.",
            reply_to_message_id=mes.message_id)
        return
    attack = int(line.group(2))
    additional_attack = int(line.group(3)) if line.group(3) != " " else 0
    defense = int(line.group(4))
    additional_defense = int(line.group(5)) if line.group(5) != " " else 0
    lvl = int(line.group(6))
    exp = re.search("🔥Exp:\\s(-?\\d+)", s)
    exp = int(exp.group(1)) if exp is not None else 0
    gold = re.search("💰Gold:\\s+(-?\\d+)", s)
    gold = int(gold.group(1)) if gold is not None else 0
    stock = re.search("📦Stock:\\s+(-?\\d+)", s)
    stock = int(stock.group(1)) if stock is not None else 0
    battle_id = count_battle_id(mes)
    hp = re.search("❤️Hp: (-?\\d+)", s)
    hp = int(hp.group(1)) if hp is not None else 0
    outplay = re.search("You outplayed (.+) by ⚔️(\\d+)", s)
    outplay_dict = {}
    if outplay is not None:
        outplay_nickname = outplay.group(1)
        outplay_attack = int(outplay.group(2))
        outplay_dict.update({
            "nickname": outplay_nickname,
            "attack": outplay_attack
        })

    if 'Встреча:' in s or ('Твои удары' in s.lower()
                           and 'Атаки врагов' in s.lower()
                           and 'Ластхит' in s.lower()):
        # Репорт с мобов
        earned = re.search("Получено: (.+) \\((\\d+)\\)", s)
        if earned is not None:
            name = earned.group(1)
            count = earned.group(2)
            code = get_item_code_by_name(name)
            if code is None:
                code = name
            drop = player.mobs_info.get("drop")
            if drop is None:
                drop = {}
                player.mobs_info.update({"drop": drop})
            drop.update(
                {forward_message_date.timestamp(): {
                     "code": code,
                     "count": 1
                 }})
            player.update()
        names, lvls, buffs = [], [], []
        for string in mes.text.splitlines():
            parse = re.search("(.+) lvl\\.(\\d+)", string)
            if parse is not None:
                name = parse.group(1)
                lvl = int(parse.group(2))
                names.append(name)
                lvls.append(lvl)
                buffs.append("")
            else:
                parse = re.search("  ╰ (.+)", string)
                if parse is not None:
                    buff = parse.group(1)
                    buffs.pop()
                    buffs.append(buff)
        hit = re.search("Твои удары: (\\d+)", s)
        hit = int(hit.group(1)) if hit is not None else 0
        miss = re.search("Атаки врагов: (\\d+)", s)
        miss = int(miss.group(1)) if miss is not None else 0
        last_hit = re.search("Ластхит: (\\d+)", s)
        last_hit = int(last_hit.group(1)) if last_hit is not None else 0
        request = "select report_id from mob_reports where date_created = %s and player_id = %s"
        cursor.execute(request, (forward_message_date, player.id))
        row = cursor.fetchone()
        if row is not None:
            return
        request = "insert into mob_reports(player_id, date_created, attack, additional_attack, defense, " \
                  "additional_defense, lvl, exp, gold, stock, mob_names, mob_lvls, buffs, hp, hit, miss, last_hit) " \
                  "values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
        cursor.execute(
            request,
            (player.id, forward_message_date, attack, additional_attack,
             defense, additional_defense, lvl, exp, gold, stock, names, lvls,
             buffs, hp, hit, miss, last_hit))
        return

    equip = re.search("Found: (.+) \\(from (.+)\\)", s)
    equip_change = None
    if equip is not None:
        name = equip.group(1)
        found_from = equip.group(2)
        equip_change = {"status": "Found", "name": name, "from": found_from}
    else:
        equip = re.search("Lost: (.+)", s)
        if equip is not None:
            name = equip.group(1)
            equip_change = {"status": "Lost", "name": name}

    request = "select report_id from reports where battle_id = %s and player_id = %s"
    cursor.execute(request, (battle_id, player.id))
    row = cursor.fetchone()
    if row is not None:
        bot.send_message(chat_id=mes.from_user.id,
                         text="Репорт за эту битву уже учтён!")
        return
    request = "insert into reports(player_id, battle_id, attack, additional_attack, defense, additional_defense, lvl, "\
              "exp, gold, stock, equip, outplay) values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
    cursor.execute(
        request,
        (player.id, battle_id, attack, additional_attack, defense,
         additional_defense, lvl, exp, gold, stock,
         json.dumps(equip_change, ensure_ascii=False) if equip_change
         is not None else None, json.dumps(outplay_dict, ensure_ascii=False)
         if outplay_dict is not None else None))

    player.count_reports()
    reputation = REPORT_REPUTATION_COUNT

    if forward_message_date < datetime.datetime(
            year=2019, month=5, day=29, hour=12):
        reputation = 0

    player.reputation += reputation
    player.update()
    response = "Репорт учтён. Спасибо!\n" \
               "{}".format("Получено {}🔘!".format(reputation) if not user_data.get("rp_off") else "")
    bot.send_message(chat_id=mes.from_user.id,
                     text=response,
                     parse_mode='HTML')
    if exp != 0:
        on_add_report(player, forward_message_date)
    """
示例#14
0
def battle_stats(bot, update):
    mes = update.message
    cursor1 = conn.cursor()
    battle_id = re.search("_(\\d+)", mes.text)
    battle_id = int(
        battle_id.group(1)) if battle_id is not None else count_battle_id(mes)

    guilds = []
    for guild_id in Guild.guild_ids:
        guild = Guild.get_guild(guild_id=guild_id)
        if guild is None or guild.division in SKIPPED_DIVISIONS:
            continue
        guild.clear_counted_reports()
        guilds.append(guild)
    guilds.sort(key=lambda x: x.division or "")
    guilds.append(
        Guild(-1, "Без гильдии", None, None, None, None, None, None, None,
              None, None, None, None, None))
    request = "select player_id, attack, defense, gold from reports where battle_id = %s"
    cursor1.execute(request, (battle_id, ))
    row = cursor1.fetchone()
    response = "Статистика по битве {} - {}:\n".format(
        battle_id,
        count_battle_time(battle_id).strftime("%d/%m/%y %H:%M:%S"))
    while row is not None:
        player = Player.get_player(row[0])
        if player.castle != '🖤':
            row = cursor1.fetchone()
            continue
        if player.guild is None:
            guild = guilds[-1]
        else:
            guild = Guild.get_guild(player.guild)
        guild.add_count_report(row[1], row[2], row[3])
        row = cursor1.fetchone()
    total_reports = 0
    total_attack = 0
    total_defense = 0
    total_gold = 0
    guilds.sort(key=lambda x:
                (x.division or "", x.get_counted_report_values()[1]),
                reverse=True)
    current_division = guilds[0].division
    division_reports, division_attack, division_defense, division_gold = 0, 0, 0, 0
    for guild in guilds:
        if guild.division != current_division:
            response += "Дивизион {}:\nВсего: {} репортов, ⚔️: <b>{}</b>, 🛡: <b>{}</b>, 💰: <b>{}</b>\n\n" \
                        "".format(current_division, division_reports, division_attack, division_defense, division_gold)
            total_attack += division_attack
            total_defense += division_defense
            total_gold += division_gold
            total_reports += division_reports
            division_reports, division_attack, division_defense, division_gold = 0, 0, 0, 0

            current_division = guild.division

        values = guild.get_counted_report_values()
        division_reports += values[0]
        division_attack += values[1]
        division_defense += values[2]
        division_gold += values[3]
        response += "<code>{:<3}</code>-👣{} ⚔️{} 🛡{} 💰{}" \
                    "\n".format(guild.tag, values[0], values[1], values[2], values[3])


    response += "\nВсего: {} репортов, ⚔️: <b>{}</b>, 🛡: <b>{}</b>, " \
                    "💰: <b>{}</b>\n".format(total_reports, total_attack, total_defense, total_gold)
    bot.send_message(chat_id=mes.chat_id, text=response, parse_mode='HTML')