예제 #1
0
async def _chat_top(update: Update, context: ContextTypes.DEFAULT_TYPE,
                    short: bool) -> None:
    if 'contest_slug' not in context.chat_data:
        await update.effective_message.reply_markdown(
            "Для чата не установлено текущее с🔥ревнование. "
            f"Команда `!{cmd.CONTEST[0]} %CONTEST_SLUG%`")
        return

    if 'task_id' not in context.chat_data:
        await update.effective_message.reply_markdown(
            "Для чата не в🔥брана задача. "
            f"Команда `!{cmd.TASK[0]}`")
        return

    cups_logins = context.chat_data.get('cups_logins', set())
    if not cups_logins:
        await update.effective_message.reply_markdown(
            "Для чата не добавлены CUPS л🔥гины. "
            f"Команда `!{cmd.CHAT_ADD[0]}`")
        return

    await context.bot.send_chat_action(chat_id=update.effective_chat.id,
                                       action=ChatAction.TYPING)
    task = allcups.task(context.chat_data['task_id'])
    scores = allcups.task_leaderboard(context.chat_data['task_id'])
    scores = [s for s in scores if s['user']['login'] in cups_logins]

    name = f"{task['contest']['name']}: {task['name']}"
    if short:
        text = msg_formatter.format_top(name, scores)
    else:
        text = msg_formatter.format_toop(name, scores)
    if len(text) > 4000:
        text = text[:-3][:4000] + ".🔥..🔥🔥```"
    await update.effective_message.reply_markdown(text)
예제 #2
0
async def _games(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    if 'contest_slug' not in context.chat_data:
        await update.effective_message.reply_markdown(
            "Для чата не установлено текущее с🔥ревнование. "
            f"Команда `!{cmd.CONTEST[0]} %CONTEST_SLUG%`")
        return

    if 'task_id' not in context.chat_data:
        await update.effective_message.reply_markdown(
            "Для чата не в🔥брана задача. "
            f"Команда `!{cmd.TASK[0]}`")
        return

    if not context.args:
        await update.effective_message.reply_text("Ст🔥ит  указ🔥ть  ник")
        return
    cups_login = context.args[0]

    await context.bot.send_chat_action(chat_id=update.effective_chat.id,
                                       action=ChatAction.TYPING)
    task = allcups.task(context.chat_data['task_id'])
    battles = allcups.battles(context.chat_data['task_id'],
                              max_count=10,
                              search=cups_login.lower())[:10]

    if not battles:
        await update.effective_message.reply_text(
            "Не  н🔥шел  таких  участник🔥в")
        return

    name = f"{task['contest']['name']}: {task['name']}"
    text = msg_formatter.format_battles(name, cups_login, battles)
    await update.effective_message.reply_markdown(text)
예제 #3
0
async def _info(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    contest = None
    task = None
    if 'contest_slug' in context.chat_data:
        contest = allcups.contest(context.chat_data['contest_slug'])
        if 'task_id' in context.chat_data:
            task = allcups.task(context.chat_data['task_id'])
    info_txt = msg_formatter.format_chat_info(contest, task)
    battle_login = context.chat_data.get('battle_login', None)
    if battle_login:
        info_txt += f"\nCUPS Battle Login: `{battle_login}`"

    await update.effective_message.reply_markdown(info_txt)
예제 #4
0
async def _task_button(update: Update,
                       context: ContextTypes.DEFAULT_TYPE) -> None:
    """Parses the CallbackQuery and updates the message text."""
    query = update.callback_query

    # CallbackQueries need to be answered, even if no notification to the user is needed
    # Some clients may have trouble otherwise. See https://core.telegram.org/bots/api#callbackquery
    await query.answer()
    task_id = query.data.split()[1]
    task = allcups.task(task_id)
    contest = allcups.contest(task['contest']['slug'])
    context.chat_data['contest_slug'] = task['contest']['slug']
    context.chat_data['task_id'] = task_id

    info_txt = msg_formatter.format_chat_info(contest, task)
    await query.edit_message_text(info_txt, parse_mode='markdown')
예제 #5
0
async def _pos(update: Update, context: ContextTypes.DEFAULT_TYPE,
               short: bool) -> None:
    if 'contest_slug' not in context.chat_data:
        await update.effective_message.reply_markdown(
            "Для чата не установлено текущее с🔥ревнование. "
            f"Команда `!{cmd.CONTEST[0]} %CONTEST_SLUG%`")
        return

    if 'task_id' not in context.chat_data:
        await update.effective_message.reply_markdown(
            "Для чата не в🔥брана задача. "
            f"Команда `!{cmd.TASK[0]}`")
        return

    cups_logins = set(login.lower() for login in context.args)
    if not cups_logins:
        await update.effective_message.reply_text("Ст🔥ит  указ🔥ть  ник")
        return

    await context.bot.send_chat_action(chat_id=update.effective_chat.id,
                                       action=ChatAction.TYPING)
    task = allcups.task(context.chat_data['task_id'])
    scores = allcups.task_leaderboard(context.chat_data['task_id'])

    f_scores = []
    for s in scores:
        s_l = s['user']['login'].lower()
        for login in cups_logins:
            if login in s_l:
                f_scores.append(s)
    scores = f_scores

    if not scores:
        await update.effective_message.reply_text(
            "Не  н🔥шел  таких  участник🔥в")
        return

    name = f"{task['contest']['name']}: {task['name']}"
    if short:
        text = msg_formatter.format_top(name, scores, header=False)
    else:
        text = msg_formatter.format_toop(name, scores, header=False)
    if len(text) > 4000:
        text = text[:-3][:4000] + ".🔥..🔥🔥```"
    await update.effective_message.reply_markdown(text)
예제 #6
0
async def _top(update: Update, context: ContextTypes.DEFAULT_TYPE,
               short: bool) -> None:
    if 'contest_slug' not in context.chat_data:
        await update.effective_message.reply_markdown(
            "Для чата не установлено текущее соревнование. "
            f"Команда `!{cmd.CONTEST[0]} %CONTEST_SLUG%`")
        return

    if 'task_id' not in context.chat_data:
        await update.effective_message.reply_markdown(
            "Для чата не выбрана задача. "
            f"Команда `!{cmd.TASK[0]}`")
        return

    await context.bot.send_chat_action(chat_id=update.effective_chat.id,
                                       action=ChatAction.TYPING)
    n = 10
    if context.args:
        try:
            n = int(context.args[0])
        except ValueError:
            logger.warning(
                f"Couldn't parse N for ai top callback: {context.args[0]}")
            await update.effective_message.reply_text("Ты меня ог🔥рчаешь")
            return
        if n == 0:
            await update.effective_message.reply_text("C🔥mmandos")
            return
        if n < 0:
            await update.effective_message.reply_text("Не н🔥до так")
            return

    task = allcups.task(context.chat_data['task_id'])
    scores = allcups.task_leaderboard(context.chat_data['task_id'])[:n]
    name = f"{task['contest']['name']}: {task['name']}"

    horse_logins = context.chat_data.get('cups_logins', set())
    if short:
        text = msg_formatter.format_top(name, scores, horse_logins)
    else:
        text = msg_formatter.format_toop(name, scores)
    if len(text) > 4000:
        text = text[:-3][:4000] + ".🔥..🔥🔥```"
    await update.effective_message.reply_markdown(text)
예제 #7
0
async def _plot_logins(cups_logins,
                       update: Update,
                       context: ContextTypes.DEFAULT_TYPE,
                       relative_login=None,
                       relative_rank=None,
                       display_rank=False,
                       plot_type='step') -> None:
    task = allcups.task(context.chat_data['task_id'])
    display_field = 'rank' if display_rank else 'score'

    # context.bot_data.pop('history', None)
    history = context.bot_data.get('history', {})
    context.bot_data['history'] = history
    task_history = history.get(context.chat_data['task_id'], [])
    history[context.chat_data['task_id']] = task_history

    ts = datetime.fromisoformat(task['start_date'])
    finish_date = datetime.fromisoformat(task['finish_date'])
    time_step = timedelta(minutes=15)
    now = datetime.now(timezone.utc)
    end = min(finish_date, now)
    if task_history:
        ts = datetime.fromtimestamp(task_history[-1]['ts'], timezone.utc)

    # TODO: Remove in future.
    while ts > finish_date:
        task_history.pop()
        ts = datetime.fromtimestamp(task_history[-1]['ts'], timezone.utc)

    time_limit = timedelta(days=2)
    # ts = max(now - time_limit, ts)
    ts += time_step
    while ts <= end:
        scores = allcups.task_leaderboard(context.chat_data['task_id'], ts)
        lb = [{
            'rank': s['rank'],
            'login': s['user']['login'],
            'score': s['score']
        } for s in scores]
        task_history.append({'ts': ts.timestamp(), 'leaderboard': lb})
        ts += time_step

    plt.clf()
    fig, ax = plt.subplots(1, 1, figsize=(15, 7))

    # ax.tick_params(axis='x', rotation=0, labelsize=12)
    ax.tick_params(axis='y', rotation=0, labelsize=12, labelcolor='tab:red')
    myFmt = mdates.DateFormatter('%b %d %H:%M')
    ax.xaxis.set_major_formatter(myFmt)
    ax.grid(alpha=.9)

    task_history = [
        h for h in task_history
        if now - datetime.fromtimestamp(h['ts'], timezone.utc) < time_limit
    ]
    dates = [
        datetime.fromtimestamp(h['ts'], timezone.utc) for h in task_history
    ]

    plot_data = {}
    ls = set(cups_logins)
    if relative_login is not None:
        ls.add(relative_login)

    for login in ls:
        pd = []
        plot_data[login] = pd
        for h in task_history:
            point = None
            for s in h['leaderboard']:
                if s['login'].lower() == login.lower():
                    point = s[display_field]
                    break
            pd.append(point)

    if relative_login is not None and relative_login in plot_data:
        relative_data = list(plot_data[relative_login])
        for login in cups_logins:
            login_data = plot_data[login]
            for i, rel_d in enumerate(relative_data):
                if login_data[i] is None or rel_d is None:
                    login_data[i] = None
                else:
                    login_data[i] -= rel_d

        plt.axhline(y=0.0,
                    color='darkviolet',
                    linestyle='--',
                    label=relative_login)

    if relative_rank is not None:
        relative_data = [
            h['leaderboard'][relative_rank - 1][display_field]
            if relative_rank <= len(h['leaderboard']) else None
            for h in task_history
        ]
        for login in cups_logins:
            login_data = plot_data[login]
            for i, rel_d in enumerate(relative_data):
                if login_data[i] is None or rel_d is None:
                    login_data[i] = None
                else:
                    login_data[i] -= rel_d

        plt.axhline(y=0.0,
                    color='darkviolet',
                    linestyle='--',
                    label=f'rank={relative_rank}')

    for login in cups_logins:
        if relative_login is not None and login.lower(
        ) == relative_login.lower():
            continue
        if plot_type == 'lines':
            plt.plot(dates, plot_data[login], label=login)
        else:
            plt.step(dates, plot_data[login], where='mid', label=login)

    plt.grid(color='0.95')
    plt.legend(fontsize=16, bbox_to_anchor=(1, 1), loc="upper left")

    if display_field == 'rank':
        plt.gca().invert_yaxis()

    plot_file = BytesIO()
    fig.tight_layout()
    fig.savefig(plot_file, format='png')
    plt.clf()
    plt.close(fig)
    plot_file.seek(0)

    await update.effective_message.reply_photo(plot_file, caption="🔥")