Completed
Pull Request — master (#242)
by Alejandro
18:08
created

src/visits/services/VisitsParser.js   A

Complexity

Total Complexity 11
Complexity/F 1.22

Size

Lines of Code 68
Function Count 9

Duplication

Duplicated Lines 0
Ratio 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 11
eloc 42
mnd 2
bc 2
fnc 9
dl 0
loc 68
ccs 33
cts 33
cp 1
rs 10
bpm 0.2222
cpm 1.2222
noi 0
c 0
b 0
f 0
1
import { isEmpty, isNil, memoizeWith, prop } from 'ramda';
2
import { browserFromUserAgent, extractDomain, osFromUserAgent } from '../../utils/helpers/visits';
3
4 1
const visitLocationHasProperty = (visitLocation, propertyName) =>
5 15
  !isNil(visitLocation)
6
  && !isNil(visitLocation[propertyName])
7
  && !isEmpty(visitLocation[propertyName]);
8
9 1
const updateOsStatsForVisit = (osStats, { userAgent }) => {
10 5
  const os = osFromUserAgent(userAgent);
11
12 5
  osStats[os] = (osStats[os] || 0) + 1;
13
};
14
15 1
const updateBrowsersStatsForVisit = (browsersStats, { userAgent }) => {
16 5
  const browser = browserFromUserAgent(userAgent);
17
18 5
  browsersStats[browser] = (browsersStats[browser] || 0) + 1;
19
};
20
21 1
const updateReferrersStatsForVisit = (referrersStats, { referer }) => {
22 5
  const domain = extractDomain(referer);
23
24 5
  referrersStats[domain] = (referrersStats[domain] || 0) + 1;
25
};
26
27 2
const updateLocationsStatsForVisit = (propertyName) => (stats, { visitLocation }) => {
28 10
  const hasLocationProperty = visitLocationHasProperty(visitLocation, propertyName);
29 10
  const value = hasLocationProperty ? visitLocation[propertyName] : 'Unknown';
30
31 10
  stats[value] = (stats[value] || 0) + 1;
32
};
33
34 1
const updateCountriesStatsForVisit = updateLocationsStatsForVisit('countryName');
35 1
const updateCitiesStatsForVisit = updateLocationsStatsForVisit('cityName');
36
37 1
const updateCitiesForMapForVisit = (citiesForMapStats, { visitLocation }) => {
38 5
  if (!visitLocationHasProperty(visitLocation, 'cityName')) {
39 2
    return;
40
  }
41
42 3
  const { cityName, latitude, longitude } = visitLocation;
43 3
  const currentCity = citiesForMapStats[cityName] || {
44
    cityName,
45
    count: 0,
46
    latLong: [ parseFloat(latitude), parseFloat(longitude) ],
47
  };
48
49 3
  currentCity.count++;
50
51 3
  citiesForMapStats[cityName] = currentCity;
52
};
53
54 1
export const processStatsFromVisits = memoizeWith(prop('id'), ({ visits }) =>
55 1
  visits.reduce(
56
    (stats, visit) => {
57
      // We mutate the original object because it has a big side effect when large data sets are processed
58 5
      updateOsStatsForVisit(stats.os, visit);
59 5
      updateBrowsersStatsForVisit(stats.browsers, visit);
60 5
      updateReferrersStatsForVisit(stats.referrers, visit);
61 5
      updateCountriesStatsForVisit(stats.countries, visit);
62 5
      updateCitiesStatsForVisit(stats.cities, visit);
63 5
      updateCitiesForMapForVisit(stats.citiesForMap, visit);
64
65 5
      return stats;
66
    },
67
    { os: {}, browsers: {}, referrers: {}, countries: {}, cities: {}, citiesForMap: {} }
68
  ));
69