-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.js
134 lines (104 loc) · 3.33 KB
/
main.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
const api = "https://api.douban.com/v2/book/search";
const apikey = "0df993c66c0c636e29ecbb5344252a4a";
const MAX_BOOKS = 1024;
let books = [];
let searchURL;
let minRaters = 1;
let booksRead = 0;
let end = true;
function removeElementsByClass(className)
{
var elements = document.getElementsByClassName(className);
while(elements.length > 0){
elements[0].parentNode.removeChild(elements[0]);
}
}
function sortBooks(keywords)
{
if (!end) return;
var progress = document.getElementById("searching-progress");
progress.hidden = false;
progress.value = `0`;
var ul = document.getElementById("search-result-list");
while (ul.firstChild) {
ul.removeChild(ul.firstChild);
}
var minRatersInput = document.getElementById("minimum-raters-input");
var value = parseInt(minRatersInput.value);
if (!isNaN(value)) {
minRaters = value;
}
books = [];
removeElementsByClass("jsonp");
searchURL = `${api}?apikey=${apikey}&q=${encodeURI(keywords)}`;
jsonp(searchURL, "jsonpCallback");
end = false;
}
function jsonp(url, callback)
{
const script = document.createElement("script");
script.type = "text/javascript";
script.src = url + `&callback=${callback}`;
script.async = true;
script.className = "jsonp";
document.body.append(script);
}
function jsonpCallback(page)
{
const count = page['count'];
const start = page['start'];
const total = page['total'] > MAX_BOOKS ? MAX_BOOKS : page['total'];
if (start == 0) {
booksRead = 0;
for (let s = start + count; s < total; s += count) {
jsonp(searchURL + `&start=${s}`, "jsonpCallback");
}
}
page['books'].forEach(book => {
if (book['rating']['numRaters'] >= minRaters) {
books.push(book);
}
});
booksRead += count;
var progress = document.getElementById("searching-progress");
progress.value = `${Math.ceil(booksRead / total * 100)}`;
if (booksRead >= total || total < 0) {
calculateBayesian(books);
books.sort((a, b) => {
return b['rating']['bayesian'] - a['rating']['bayesian'];
});
showBooks();
end = true;
}
}
function calculateBayesian(books) {
let allRaters = 0;
let allScore = 0;
for (let book of books) {
const n = book['rating']['numRaters'];
allRaters += n;
allScore += n * parseFloat(book['rating']['average']);
}
for (let book of books) {
const n = book['rating']['numRaters'];
const s = parseFloat(book['rating']['average']);
book['rating']['bayesian'] = (allScore + books.length * n * s) / (allRaters + books.length * n);
}
}
function showBooks() {
const progress = document.getElementById("searching-progress");
progress.hidden = true;
const ol = document.getElementById("search-result-list");
for (let book of books) {
const li = document.createElement("li");
ol.appendChild(li);
const a = document.createElement("a");
a.href = book['alt'];
li.appendChild(a);
let title = book['title'];
if (book['subtitle'].length > 0)
title += ": " + book['subtitle'];
const text = document.createTextNode(`${book['rating']['bayesian'].toFixed(2)} - ${title}`);
a.appendChild(text);
}
}