-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathposts-storage.js
119 lines (93 loc) · 3.21 KB
/
posts-storage.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
110
111
112
113
114
115
116
117
118
119
class PriorityQueue {
constructor(maxSize) {
this.maxSize = maxSize;
this.elements = new Map(); // Store elements by ID
this.priorityList = []; // Array to maintain order based on priority
this.onElementRemovedListeners = [];
}
add(id, element, priority) {
// Check if the element is already present
if (this.elements.has(id))
return false;
// Check and maintain the max size
if (this.priorityList.length >= this.maxSize) {
// Remove the element with the lowest priority (first in the array)
const lowest = this.priorityList.shift();
this.elements.delete(lowest.id);
for (const listener of this.onElementRemovedListeners)
listener(lowest.id);
}
// Add the new element
const newElement = { id, element, priority };
this.elements.set(id, newElement);
const index = this.priorityList.findIndex(el => el.priority > priority);
if (index === -1)
this.priorityList.push(newElement);
else
this.priorityList.splice(index, 0, newElement);
return true;
}
getTop() {
return this.priorityList[this.priorityList.length - 1];
}
getAll() {
return this.priorityList.slice(); // Return a shallow copy of the sorted list
}
getAllAfter(priority) {
return this.priorityList.filter(el => el.priority > priority);
}
exists(id) {
return this.elements.has(id);
}
getById(id) {
return this.elements.get(id).element;
}
onElementRemoved(listener) {
this.onElementRemovedListeners.push(listener);
}
get size() {
return this.priorityList.length;
}
}
export class PostsStorage {
static maxPosts = 200;
static maxPostLength = 10000;
constructor() {
this.posts = new PriorityQueue(PostsStorage.maxPosts);
this.onPostAddedListeners = [];
}
addPost(post) {
if(post.text.length > PostsStorage.maxPostLength)
return;
// check that the post has required fields and only those fields
if(!post.text || !post.timestamp || Object.keys(post).length !== 2) {
return;
}
// check that the timestamp is a number and is not more than 30s in the future
if(isNaN(Number(post.timestamp)) || Number(post.timestamp) > Date.now() + 30000) {
return;
}
post.id = nkn.hash.sha256Hex(post.text + "|" + post.timestamp);
if(this.posts.add(post.id, post, Number(post.timestamp)))
for(const listener of this.onPostAddedListeners)
listener(post);
}
getPostsAfter(timestamp) {
return this.posts.getAllAfter(Number(timestamp)).map(el => el.element);
}
onPostAdded(listener) {
this.onPostAddedListeners.push(listener);
}
onPostRemoved(listener) {
this.posts.onElementRemoved(listener);
}
getLatestPost() {
return this.posts.size === 0 ? null : this.posts.getTop().element;
}
getAllIds() {
return this.posts.getAll().map(el => el.id);
}
getById(id) {
return this.posts.getById(id);
}
}