Пример #1
0
    def end_users(self, stat: Dict[str, Any]) -> None:
        assert self.stat

        for step in self._ratings:
            with open(os.path.join(self.stat.destination,
                                   'users_ratings_{}.csv'.format(step)),
                      'w',
                      encoding='utf-8') as fp:
                fp.write(utils.csvline('Рейтинг', 'Число пользователей'))

                step_vote = min(self._ratings[step])
                vmax = max(self._ratings[step])

                while step_vote <= vmax:
                    count = self._ratings[step].get(step_vote, 0)

                    x1 = '{:.2f}'.format(step_vote)
                    x2 = '{:.2f}'.format(round(step_vote + (step - 0.01), 2))
                    fp.write(utils.csvline(x1 + ' – ' + x2, count))

                    step_vote += step

        with open(os.path.join(self.stat.destination,
                               'users_ratings_zero.txt'),
                  'w',
                  encoding='utf-8') as fp:
            fp.write('{}\n'.format(self._zero))
Пример #2
0
    def stop(self) -> None:
        assert self.stat

        min_rating = 0
        max_rating = 0
        for votes_dict in self._stat.values():
            min_rating = min(min(votes_dict), min_rating)
            max_rating = max(max(votes_dict), max_rating)

        header = ['Рейтинг', 'За всё время']
        for year in sorted(self._stat):
            header.append('{} год'.format(year))

        with open(os.path.join(self.stat.destination, 'posts_ratings.csv'),
                  'w',
                  encoding='utf-8') as fp:
            fp.write(utils.csvline(*header))
            for vote in range(min_rating, max_rating + 1):
                line = [vote, 0]
                for year in sorted(self._stat):
                    line.append(self._stat[year].get(vote, 0))
                    line[1] += line[-1]
                fp.write(utils.csvline(*line))

        super().stop()
Пример #3
0
    def end_users(self, stat: Dict[str, Any]) -> None:
        assert self.stat

        with open(os.path.join(self.stat.destination, 'birthdays.csv'), 'w', encoding='utf-8') as fp:
            fp.write(utils.csvline('День рождения', 'Число пользователей'))
            for day, user_ids in sorted(self._birthdays.items(), key=lambda x: len(x[1]), reverse=True):
                fp.write(utils.csvline('{:02d}.{:02d}'.format(*day), len(user_ids)))
Пример #4
0
    def stop(self) -> None:
        assert self.stat

        # Считаем статистику за всё время...
        counts_all = [0] * 24
        days_all = 0

        # ...и по годам...
        counts_year = {}  # type: Dict[int, List[int]]
        days_year = {}  # type: Dict[int, int]

        # ...в одном цикле
        for (year, monn), stat in self._counts.items():
            days = self._days[(year, monn)]

            if year not in counts_year:
                counts_year[year] = [0] * 24
                days_year[year] = 0

            days_all += days
            days_year[year] += days

            for hour, cnt in enumerate(stat):
                counts_all[hour] += cnt
                counts_year[year][hour] += cnt

        last_months = sorted(self._counts)[-2:]

        # Собираем CSV-заголовок
        header = ['Час ({})'.format(str(self.stat.timezone)), 'За всё время']
        for year in sorted(counts_year):
            header.append('{} год'.format(year))
        for mon in last_months:
            header.append('{:04d}-{:02d}'.format(*mon))

        with open(os.path.join(self.stat.destination, 'posts_counts_avg.csv'),
                  'w',
                  encoding='utf-8') as fp:
            fp.write(utils.csvline(*header))

            for hour in range(24):
                line = [hour]  # type: List[Any]

                # За всё время
                line.append('{:.2f}'.format(counts_all[hour] /
                                            (days_all or 1)))

                # И по годам
                for year in sorted(counts_year):
                    line.append('{:.2f}'.format(counts_year[year][hour] /
                                                (days_year.get(year) or 1)))

                # И за два последних месяца
                for mon in last_months:
                    line.append('{:.2f}'.format(self._counts[mon][hour] /
                                                (self._days.get(mon) or 1)))

                fp.write(utils.csvline(*line))

        super().stop()
Пример #5
0
    def start(self,
              stat: TabunStat,
              min_date: Optional[datetime] = None,
              max_date: Optional[datetime] = None) -> None:
        super().start(stat, min_date, max_date)
        assert self.stat

        self._fp = open(os.path.join(self.stat.destination,
                                     'posts_counts.csv'),
                        'w',
                        encoding='utf-8')
        self._fp_sum = open(os.path.join(self.stat.destination,
                                         'posts_counts_sum.csv'),
                            'w',
                            encoding='utf-8')
        self._fp_perc = open(os.path.join(self.stat.destination,
                                          'posts_counts_perc.csv'),
                             'w',
                             encoding='utf-8')

        # Применяем часовой пояс к периоду
        self.period_end = self._append_days(self.period_begin)

        header = ['Первый день недели'] + self._labels
        header_csv = utils.csvline(*header)

        self._fp.write(header_csv)
        self._fp_sum.write(header_csv)
        self._fp_perc.write(utils.csvline(
            *header[:-1]))  # В процентах комменты из лички не учитываем
Пример #6
0
    def save_stat(self, filename: str, stat_posts: Dict[int, int],
                  stat_comments: Dict[int, int]) -> None:
        assert self.stat

        stat = {}  # type: Dict[int, List[int]]

        for user_id, count in stat_posts.items():
            if user_id not in stat:
                stat[user_id] = [0, 0]
            stat[user_id][0] = count

        for user_id, count in stat_comments.items():
            if user_id not in stat:
                stat[user_id] = [0, 0]
            stat[user_id][1] = count

        items = sorted(stat.items(),
                       key=lambda x: x[1][0] + x[1][1],
                       reverse=True)

        with open(os.path.join(self.stat.destination, filename),
                  'w',
                  encoding='utf-8') as fp:
            fp.write(
                utils.csvline('ID юзера', 'Пользователь', 'Сколько постов',
                              'Сколько комментов'))

            for user_id, (posts_count, comments_count) in items:
                fp.write(
                    utils.csvline(
                        user_id,
                        self.stat.source.get_username_by_user_id(user_id),
                        posts_count, comments_count))
Пример #7
0
    def stop(self) -> None:
        assert self.stat

        with open(os.path.join(self.stat.destination, 'nicknames.csv'), 'w', encoding='utf-8') as fp:
            fp.write(utils.csvline('Первая буква ника', 'Число пользователей'))
            for c, user_ids in sorted(self._letters.items(), key=lambda x: len(x[1]), reverse=True):
                fp.write(utils.csvline(c, len(user_ids)))

        super().stop()
Пример #8
0
    def stop(self) -> None:
        assert self.stat

        with open(os.path.join(self.stat.destination, 'dices.csv'),
                  'w',
                  encoding='utf-8') as fp:
            fp.write(
                utils.csvline('ID юзера', 'Пользователь',
                              'Сколько публикаций с дайсами',
                              'Сколько раз брошены дайсы'))
            for user_id, (msgs_count,
                          dices_count) in sorted(self._dices.items(),
                                                 key=lambda x: x[1][0],
                                                 reverse=True):
                fp.write(
                    utils.csvline(
                        user_id,
                        self.stat.source.get_username_by_user_id(user_id),
                        msgs_count, dices_count))

        super().stop()
Пример #9
0
    def _flush_stat(self) -> None:
        assert self.stat
        period_begin_local = utils.apply_tzinfo(self.period_begin,
                                                self.stat.timezone)

        # Собираем три разные строки для трёх файлов
        line = [period_begin_local.strftime('%Y-%m-%d')]  # type: List[Any]
        line_sum = line[:]  # type: List[Any]
        line_perc = line[:]  # type: List[Any]

        # Высчитываем, что такое 100%
        all_exist_count = sum(self._stat)

        # И собираем в строки данные по каждой категории
        cnt_sum = 0
        for cnt in self._stat:
            # В простой файл просто пишем число как есть
            line.append(cnt)
            # В файле с суммами используем складывание слева направо для более простого рисования графиков
            cnt_sum += cnt
            line_sum.append(cnt_sum)
            # Проценты тоже суммируем для удобства рисования графиков
            percent = 0.0 if all_exist_count <= 0 else (cnt_sum * 100.0 /
                                                        all_exist_count)
            line_perc.append('{:.2f}'.format(percent))

        # Пишем в файлы
        assert self._fp
        self._fp.write(utils.csvline(*line))
        assert self._fp_sum
        self._fp_sum.write(utils.csvline(*line_sum))
        assert self._fp_perc
        self._fp_perc.write(utils.csvline(*line_perc))

        # Обнуляем статистику для начала следующего периода
        self._stat = [0] * len(self._labels)

        # Высчитываем следующий период
        self.period_begin = self.period_end
        self.period_end = self._append_days(self.period_begin)
Пример #10
0
    def stop(self) -> None:
        assert self.stat
        with open(os.path.join(self.stat.destination, 'chars.csv'),
                  'w',
                  encoding='utf-8') as fp:
            fp.write(utils.csvline('Символ', 'Сколько раз встретился'))

            for c, x in sorted(self._chars.items(),
                               key=lambda x: [-x[1][0], x[1][1]]):
                cnt, created_at_unix = x

                # created_at = utils.apply_tzinfo(
                #     datetime.utcfromtimestamp(created_at_unix),
                #     self.stat.timezone
                # )

                if c == '"':
                    c = 'Кавычка'
                elif c == ',':
                    c = 'Запятая'
                elif c == ' ':
                    c = 'Пробел'
                elif c == '\u00a0':
                    c = 'Неразр. пробел'
                elif c == '\t':
                    c = 'Табуляция'
                elif c == '\n':
                    c = 'Перенос строки'
                elif c == '\r':
                    c = 'Возврат каретки'
                elif c.lower() in ('a', 'o', 'e', 'c', 'k', 'p', 'x',
                                   'm') or c in ('B', 'T', 'H', 'y'):
                    c = c + ' (англ.)'
                elif not c.strip():
                    c = repr(c)
                fp.write(utils.csvline(c, cnt))

        super().stop()
Пример #11
0
    def end_users(self, stat: Dict[str, Any]) -> None:
        assert self.stat

        if not self._stat:
            return

        day = min(self._stat)
        max_day = max(self._stat)

        with open(os.path.join(self.stat.destination, 'registrations.csv'),
                  'w',
                  encoding='utf-8') as fp:
            fp.write(
                utils.csvline('Дата', 'Новые пользователи',
                              'Всего пользователей',
                              'Всего с рейтингом больше -20',
                              'Всего с рейтингом больше +20'))

            all_users = 0
            all_users_gte_minus20 = 0
            all_users_gte_plus20 = 0

            while day <= max_day:
                # Слава костылям
                if day not in self._stat and (
                        day.year < 2011 or day.year == 2011 and day.month < 8):
                    day += timedelta(days=1)
                    continue

                all_users += self._stat.get(day, 0)
                all_users_gte_minus20 += self._stat_gte_minus20.get(day, 0)
                all_users_gte_plus20 += self._stat_gte_plus20.get(day, 0)

                fp.write(
                    utils.csvline(day, self._stat.get(day, 0), all_users,
                                  all_users_gte_minus20, all_users_gte_plus20))

                day += timedelta(days=1)
Пример #12
0
    def _flush_activity(self, item: Dict[str, Any]) -> None:
        stat = [str(self._last_day)]  # type: List[Any]

        for period in self.periods:
            # Собираем все id за последние period дней
            all_users = set()  # type: Set[int]

            for a, b in item['activity'][-period:]:
                all_users = all_users | a | b
                item['users_with_posts'] = item['users_with_posts'] | a
                item['users_with_comments'] = item['users_with_comments'] | b

            stat.append(len(all_users))

        # И пишем собранные числа в статистику
        assert item['fp']
        item['fp'].write(utils.csvline(*stat))
Пример #13
0
    def stop(self) -> None:
        assert self.stat

        with open(os.path.join(self.stat.destination, 'images.csv'),
                  'w',
                  encoding='utf-8') as fp:
            fp.write(
                utils.csvline('Картинка', 'Первое исп-е',
                              'Первое исп-е на внешке', 'Последнее исп-е',
                              'Последнее исп-е на внешке', 'Сколько раз',
                              'Сколько раз на внешке'))

            for img in self._images_list:
                data = self._stat[img]
                fp.write(
                    utils.csvline(img, data['first_date'],
                                  data['first_public_date'] or '',
                                  data['last_date'], data['last_public_date']
                                  or '', data['count'], data['public_count']))

        with open(os.path.join(self.stat.destination, 'images_hosts.csv'),
                  'w',
                  encoding='utf-8') as fp:
            fp.write(
                utils.csvline('Хост', 'Число ссылок', 'Число использований'))

            items = sorted(self._hosts.items(),
                           key=lambda x: x[1][1],
                           reverse=True)
            for h, c in items:
                assert c[1] >= c[0]
                fp.write(utils.csvline(h, c[0], c[1]))

        with open(os.path.join(self.stat.destination, 'images_hosts2.csv'),
                  'w',
                  encoding='utf-8') as fp:
            fp.write(
                utils.csvline('Хост', 'Число ссылок', 'Число использований'))

            items = sorted(self._hosts2.items(),
                           key=lambda x: x[1][1],
                           reverse=True)
            for h, c in items:
                assert c[1] >= c[0]
                fp.write(utils.csvline(h, c[0], c[1]))

        super().stop()
Пример #14
0
    def start(self,
              stat: TabunStat,
              min_date: Optional[datetime] = None,
              max_date: Optional[datetime] = None) -> None:
        super().start(stat, min_date, max_date)
        assert self.stat

        header = ['Дата']
        for period in self.periods:
            if period == 1:
                header.append('Активны в этот день')
            else:
                header.append('Активны в последние {} дней'.format(period))

        for rating, item in self._ratings.items():
            filename = 'activity.csv'
            if rating is not None:
                filename = 'activity_{:.2f}.csv'.format(rating)
            item['fp'] = open(os.path.join(self.stat.destination, filename),
                              'w',
                              encoding='utf-8')
            item['fp'].write(utils.csvline(*header))
Пример #15
0
    def stop(self) -> None:
        assert self.stat

        with open(os.path.join(self.stat.destination, 'words.csv'),
                  'w',
                  encoding='utf-8') as fp:
            fp.write(
                utils.csvline('Слово', 'Первое исп-е',
                              'Первое исп-е на внешке', 'Последнее исп-е',
                              'Последнее исп-е на внешке', 'Сколько раз',
                              'Сколько раз на внешке',
                              'Сколько раз (без ботов)',
                              'Сколько раз на внешке (без ботов)',
                              'Сколько юзеров юзали', 'Кто юзал',
                              'Сколько юзеров юзали на внешке',
                              'Кто юзал на внешке'))
            for word in self._words_list:
                data = self._stat[word[:2]][word]
                fp.write(
                    utils.csvline(
                        word,
                        data['first_date'],
                        data['first_public_date'] or '',
                        data['last_date'],
                        data['last_public_date'] or '',
                        data['count'],
                        data['public_count'],
                        data['nobots_count'],
                        data['public_nobots_count'],
                        len(data['users']),
                        '; '.join(sorted(data['users']))
                        if len(data['users']) < 20 else '',
                        len(data['public_users']),
                        '; '.join(sorted(data['public_users']))
                        if len(data['public_users']) < 20 else '',
                    ))

        with open(os.path.join(self.stat.destination, 'avgstats.txt'),
                  'w',
                  encoding='utf-8') as fp:
            fp.write(
                'Средняя длина поста: {} слов, {} символов, {} байт\n'.format(
                    int(self._post_len_words[0] / self._post_len_words[1])
                    if self._post_len_words[1] != 0 else 0,
                    int(self._post_len_chars[0] / self._post_len_chars[1])
                    if self._post_len_chars[1] != 0 else 0,
                    int(self._post_len_bytes[0] / self._post_len_bytes[1])
                    if self._post_len_bytes[1] != 0 else 0,
                ))
            fp.write('Средняя длина коммента: {} слов, {} символов, {} байт\n'.
                     format(
                         int(self._comment_len_words[0] /
                             self._comment_len_words[1])
                         if self._comment_len_words[1] != 0 else 0,
                         int(self._comment_len_chars[0] /
                             self._comment_len_chars[1])
                         if self._comment_len_chars[1] != 0 else 0,
                         int(self._comment_len_bytes[0] /
                             self._comment_len_bytes[1])
                         if self._comment_len_bytes[1] != 0 else 0,
                     ))
            fp.write('Комментов без текста: {}\n'.format(
                self._comments_without_text))

        super().stop()