hellowin/kanca

View on GitHub
src/domain/metric/service/postsMetric.js

Summary

Maintainability
D
2 days
Test Coverage
// @flow
import postMetric from './postMetric';
import _ from 'lodash';
import moment from 'moment-timezone';
import type { PostMetric } from './postMetric';
import { wordCounter } from 'infra/service/util';

export type PostsMetric = {
  postMetrics: PostMetric[],
  dateStart(): Date,
  dateEnd(): Date,
  totalPosts(): number,
  totalUsers(): number,
  totalComments(): number,
  totalShares(): number,
  sortBySharesCount(): PostMetric[],
  totalLikes(): number,
  sortByLikesCount(): PostMetric[],
  postsByDays(): { day: string, postMetrics: PostMetric[], postsMetric: PostsMetric }[],
  postsByHours(): { hour: string, trihourly: string, postMetrics: PostMetric[], postsMetric: PostsMetric }[],
  wordCount(): Promise<{ word: string, count: number }[]>,
}

const postsMetric = (posts: Post[]): PostsMetric => {
  const postMetrics = postMetric(posts);
  const postsByDays = () => {
    const days = {};
    postMetrics.forEach(met => {
      const day = moment(met.createdTime).format('dddd');
      if (!days[day]) days[day] = { day, postMetrics: [] };
      days[day].postMetrics.push(met);
    });
    return _.values(days).map(day => ({
      ...day,
      postsMetric: postsMetric(day.postMetrics.map(me => me.post)),
    }));
  };
  const postsByHours = () => {
    const hours = {};
    postMetrics.forEach(met => {
      const hour = moment(met.createdTime).format('HH');
      let trihourly = Math.ceil(parseInt(hour, 10)/3) + '';
      // handle 00:00 AM
      if (trihourly === '0') trihourly = '1';

      if (!hours[hour]) hours[hour] = { hour, trihourly, postMetrics: [] };
      hours[hour].postMetrics.push(met);
    });
    return _.values(hours).map(hour => ({
      ...hour,
      postsMetric: postsMetric(hour.postMetrics.map(me => me.post)),
    }));
  };
  const wordCount = () => wordCounter(postMetrics.map(pos => pos.text).join(' '));

  return {
    postMetrics,
    dateStart: () => _.sortBy(postMetrics, 'createdTime')[0].createdTime,
    dateEnd: () => _.sortBy(postMetrics, 'createdTime').reverse()[0].createdTime,
    totalPosts: () => postMetrics.length,
    totalUsers: () => new Set(postMetrics.map(post => (post.from || {}).id).filter(x => x)).size,
    totalComments: () => postMetrics.map(post => (post || {}).commentsCount).reduce((pre, cur) => pre + cur, 0),
    totalShares: () => postMetrics.map(post => (post || {}).sharesCount).reduce((pre, cur) => pre + cur, 0),
    sortBySharesCount: () => _.sortBy(postMetrics, 'sharesCount').reverse(),
    totalLikes: () => postMetrics.map(post => (post || {}).likesCount).reduce((pre, cur) => pre + cur, 0),
    sortByLikesCount: () => _.sortBy(postMetrics, 'likesCount').reverse(),
    postsByDays,
    postsByHours,
    wordCount,
  };
}

export default postsMetric;