-
Notifications
You must be signed in to change notification settings - Fork 0
/
get_hits_X_min_ago.js
109 lines (79 loc) · 3.38 KB
/
get_hits_X_min_ago.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/*
LOG HIT COUNT (in constant O(1) time)
Premise
We have a web app that users are visiting. We need a function logHit()
that increments a count of total visits every time a user visits the app.
Assume logHit() is called automatically when a hit on our app is detected.
Now we need a function getHits() that returns the total number of visits
from a given number of minutes ago.
*/
//**********************************************************************
class HitsTracker {
// new HitsTracker obj can take an integer for calculating visits X min ago
// (assigned 5 mins by default)
// for example, to track website in the past 2 minutes => `let tracker = new HitsTracker(2)`;
constructor(minAgo = 5) {
// startPointer will keep track of the time of the least recent hits
this.startPointer = null;
// hitsCount will keep track of total number of count
// as well as a list of number of hits at a given time
this.hitsCount = {"totalCount": 0};
this.minsAgo = minAgo;
this.minsAgoInMilli = this.minsAgo * 60 * 1000;
let ctx = this;
this.cleanHitsInterval = setInterval(function() { if (ctx._cleanHits) { ctx._cleanHits()}}, 1)
}
logHit() {
let now = Date.now();
if (this.startPointer === null || this.hitsCount["totalCount"] === 0) {
this.startPointer = now;
}
// log_hit will keep track of number of visits at the time a visit is logged
if (this.hitsCount[now]) {
this.hitsCount[now] += 1;
} else {
this.hitsCount[now] = 1;
}
// every visit will be added to "totalCount"
this.hitsCount["totalCount"] += 1;
}
/**
_cleanhits will be called every millisecond to constantly update our
hitsCount["totalCount"]. It will delete website hits older than 5 min ago.
Startpoint gets set only ONCE by log_hit, at our first hit.
Every time _cleanHits() is invoked, it will check if our Startpointer
is at a longer time than 5 minutes ago.
If yes, it means we have old logged hit entries that we don't want
to include in our total hits count.
StartPointer will be incremented every millisecond up until it
reaches the 5 minutes ago mark.
1) _cleanHits will delete those logged hits from hitsCount.
2) It will also subtract those out of date logged hits from total hits.
**/
_cleanHits() {
let now = Date.now();
let xMilliSecondsAgo = now - this.minsAgoInMilli;
console.log("Time now: ", this._toHHMMSS(now));
console.log(`Time ${this.minsAgo} minute ago: `, this._toHHMMSS(xMilliSecondsAgo));
console.log("total hits: ", this.hitsCount["totalCount"]);
for (; this.startPointer < xMilliSecondsAgo; this.startPointer++) {
if (this.hitsCount[this.startPointer]) {
// we need to delete the oldest visit entries from the total count
// for example, if we logged 10 visits 5 min and 1 milliseconds ago
// 1) we need to delete that key-value pair from the hash AND
// 2) we need to subtract 10 visits from "totalCount"
this.hitsCount["totalCount"] -= this.hitsCount[this.startPointer];
delete this.hitsCount[this.startPointer];
}
}
}
getHits() {
this._cleanHits();
return hitsCount["totalCount"];
}
//formats milliseconds into HH:MM:SS:MS format for readability
_toHHMMSS(ms) {
return new Date(ms).toISOString().slice(11, -1);
// console.log( time(1234567890) ); // "06:56:07.890"
}
}