def get_user_position(cls, user_id, cid, date):
        position = -1
        msg_count = 0
        last_monday = get_current_monday(
        ) if date is None else get_date_monday(date)

        try:
            with session_scope() as db:
                # noinspection PyUnresolvedReferences
                q = db.query(UserStatDB, UserDB) \
                    .filter(UserStatDB.stats_monday == last_monday) \
                    .filter(UserStatDB.uid == UserDB.uid) \
                    .filter(UserStatDB.cid == cid) \
                    .filter(UserStatDB.all_messages_count > 0) \
                    .order_by(UserStatDB.all_messages_count.desc()) \
                    .all()
                q = [(UserStat.copy(userstat), User.copy(user))
                     for userstat, user in q]
            if q:
                position = 0
                for userstat, user in q:
                    position += 1
                    if userstat.uid == user_id:
                        msg_count = userstat.all_messages_count
                        break
        except Exception as e:
            logger.error(e)
        return {'position': position, 'msg_count': msg_count}
 def get_chat_stats(cls, cid, date=None):
     last_monday = get_current_monday(
     ) if date is None else get_date_monday(date)
     try:
         with session_scope() as db:
             # noinspection PyUnresolvedReferences
             q = db.query(UserStatDB, UserDB) \
                 .filter(UserStatDB.stats_monday == last_monday) \
                 .filter(UserStatDB.uid == UserDB.uid) \
                 .filter(UserStatDB.cid == cid) \
                 .filter(UserStatDB.all_messages_count > 0) \
                 .order_by(UserStatDB.all_messages_count.desc()) \
                 .all()
         return [(UserStat.copy(userstat), User.copy(user))
                 for userstat, user in q]
     except Exception:
         return []
    def get_top_kroshka(cls, cid, date=None):
        """
        :rtype: User
        """
        last_monday = get_current_monday(
        ) if date is None else get_date_monday(date)
        try:
            with session_scope() as db:
                # noinspection PyUnresolvedReferences
                q = db.query(UserStatDB, UserDB) \
                    .filter(UserStatDB.stats_monday == last_monday) \
                    .filter(UserStatDB.uid == UserDB.uid) \
                    .filter(UserStatDB.cid == cid) \
                    .filter(or_(
                        UserStatDB.emoji_count > 0,
                        UserStatDB.stickers_count > 0,
                        UserStatDB.gifs_count > 0
                    )) \
                    .order_by(UserStatDB.emoji_count.desc()) \
                    .all()
                q = [(UserStat.copy(userstat), User.copy(user))
                     for userstat, user in q]
            if not q:
                return None
        except Exception as e:
            logger.error(e)
            return None

        # получаем соотношение количества эмодзи к сообщениям
        users_by_emoji = {}
        for user_stat, user in q:
            count = user_stat.all_messages_count
            # учитываем только тек, кто написал от 30 сообщений
            if count < 30 or user_stat.words_count < 500:
                continue
            users_by_emoji[user.uid] = user_stat.emoji_count / count

        if len(users_by_emoji) > 0:
            uid, _ = random.choice(sort_dict(users_by_emoji)[:10])
        else:
            _, user = random.choice(q)
            uid = user.uid
        user = User.get(uid)
        return user
    def get_chat(cls,
                 cid,
                 date=None,
                 fullstat=False,
                 salo=False,
                 tag_salo=False,
                 mat=False):
        if cid > 0:
            return {
                'users_count': 0,
                'top_chart': '',
                'msg_count': 0,
                'percent': 0
            }
        msg_count_percent = 100
        top_chart = ''
        uids = []
        last_monday = get_current_monday(
        ) if date is None else get_date_monday(date)
        all_msg_count = cls.__get_all_msg_count(last_monday, cid)

        q = []
        try:
            with session_scope() as db:
                # noinspection PyUnresolvedReferences
                q = db.query(UserStatDB, UserDB) \
                    .filter(UserStatDB.stats_monday == last_monday) \
                    .filter(UserStatDB.uid == UserDB.uid) \
                    .filter(UserStatDB.cid == cid) \
                    .filter(UserStatDB.all_messages_count > 0) \
                    .order_by(UserStatDB.all_messages_count.desc()) \
                    .all()
                q = [(UserStat.copy(userstat), User.copy(user))
                     for userstat, user in q]
        except Exception as e:
            logger.error(e)
        if len(q) == 0:
            return {
                'users_count': 0,
                'top_chart': '',
                'msg_count': 0,
                'percent': 0,
                'uids': []
            }

        user_position = 0
        asc_msg_count = 0
        if salo:
            q = q[::-1]

        magic_percent = 100
        q_all_length = len(q)  # if type(q) is list else len(q.all())
        if not salo and q_all_length > 25:
            magic_percent = 146

        for user_stat, user in q:
            count = user_stat.all_messages_count
            user_position += 1
            asc_msg_count += count
            raw_percent = count * magic_percent / all_msg_count
            percent = cls.number_format(raw_percent, 2)
            user_mat = '' if not mat else cls.__get_user_mat(user_stat)
            top_chart += f"<b>{user_position}. {user.fullname}</b> — <b>{count}</b> ({percent}%){user_mat}\n"
            uids.append(user.uid)
            if not fullstat and user_position >= CONFIG['top_users_num']:
                break
            if salo and count > 15:
                break

        if not salo:
            users_count = q_all_length
        else:
            users_count = user_position
            all_users: typing.List[ChatUser] = []
            try:
                all_users = ChatUserDB.get_all(cid)
            except Exception as e:
                logger.error(e)
            active_user_ids = [x.uid for _, x in q]
            silent_lines = []
            for chat_user in all_users:
                if chat_user.uid not in active_user_ids:
                    user = User.get(chat_user.uid)
                    if user is not None:
                        username_if_salo = ' @{}'.format(
                            user.username) if tag_salo else ''
                        silent_lines.append("<b>{}</b>{}\n".format(
                            user.fullname, username_if_salo))
            if len(silent_lines) > 0:
                top_chart += "\nСовсем молчуны:\n"
                top_chart += ''.join(silent_lines)
            else:
                top_chart += "\nСовсем молчунов нет 🙊\n"

        if not fullstat or salo:
            msg_count_percent = cls.number_format(
                asc_msg_count * 100 / all_msg_count, 2)
            all_msg_count = asc_msg_count

        return {
            'users_count': users_count,
            'top_chart': top_chart,
            'msg_count': all_msg_count,
            'percent': msg_count_percent,
            'uids': uids
        }