/
ratings.py
118 lines (100 loc) · 4.38 KB
/
ratings.py
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
from openlibrary.utils.dateutil import DATE_ONE_MONTH_AGO, DATE_ONE_WEEK_AGO
from . import db
class Ratings(object):
VALID_STAR_RATINGS = range(6) # inclusive: [0 - 5] (0-5 star)
@classmethod
def summary(cls):
return {
'total_books_starred': {
'total': Ratings.total_num_books_rated(),
'month': Ratings.total_num_books_rated(since=DATE_ONE_MONTH_AGO),
'week': Ratings.total_num_books_rated(since=DATE_ONE_WEEK_AGO),
'unique': Ratings.total_num_unique_raters()
}
}
@classmethod
def total_num_books_rated(cls, since=None, distinct=False):
oldb = db.get_db()
query = "SELECT count(%s work_id) from ratings" % ('DISTINCT' if distinct else '')
if since:
query += " WHERE created >= $since"
results = oldb.query(query, vars={'since': since})
return results[0] if results else None
@classmethod
def total_num_unique_raters(cls, since=None):
oldb = db.get_db()
query = "select count(DISTINCT username) from ratings"
if since:
query += " WHERE created >= $since"
results = oldb.query(query, vars={'since': since})
return results[0] if results else None
@classmethod
def most_rated_books(cls, limit=10, since=False):
oldb = db.get_db()
query = 'select work_id, count(*) as cnt from ratings '
if since:
query += " WHERE created >= $since"
query += ' group by work_id order by cnt desc limit $limit'
return list(oldb.query(query, vars={'limit': limit, 'since': since}))
@classmethod
def get_users_ratings(cls, username):
oldb = db.get_db()
query = 'select * from ratings where username=$username'
return list(oldb.query(query, vars={'username': username}))
@classmethod
def get_rating_stats(cls, work_id):
oldb = db.get_db()
query = ("SELECT AVG(rating) as avg_rating, COUNT(DISTINCT username) as num_ratings"
" FROM ratings"
" WHERE work_id = $work_id")
result = oldb.query(query, vars={'work_id': int(work_id)})
return result[0] if result else {}
@classmethod
def get_all_works_ratings(cls, work_id):
oldb = db.get_db()
query = 'select * from ratings where work_id=$work_id'
return list(oldb.query(query, vars={'work_id': work_id}))
@classmethod
def get_users_rating_for_work(cls, username, work_id):
oldb = db.get_db()
data = {
'username': username,
'work_id': int(work_id)
}
query = 'SELECT * from ratings where username=$username AND work_id=$work_id'
results = list(oldb.query(query, vars=data))
rating = results[0].rating if results else None
return rating
@classmethod
def remove(cls, username, work_id):
oldb = db.get_db()
where = {
'username': username,
'work_id': int(work_id)
}
try:
return oldb.delete('ratings', where=(
'work_id=$work_id AND username=$username'), vars=where)
except: # we want to catch no entry exists
return None
@classmethod
def add(cls, username, work_id, rating, edition_id=None):
from openlibrary.core.bookshelves import Bookshelves
oldb = db.get_db()
work_id = int(work_id)
data = {'work_id': work_id, 'username': username}
if rating not in cls.VALID_STAR_RATINGS:
return None
# Vote implies user read book; Update reading log status as "Already Read"
users_read_status_for_work = Bookshelves.get_users_read_status_of_work(username, work_id)
if users_read_status_for_work != Bookshelves.PRESET_BOOKSHELVES['Already Read']:
Bookshelves.add(username, Bookshelves.PRESET_BOOKSHELVES['Already Read'],
work_id, edition_id=edition_id)
users_rating_for_work = cls.get_users_rating_for_work(username, work_id)
if not users_rating_for_work:
return oldb.insert('ratings', username=username,
work_id=work_id, rating=rating, edition_id=edition_id)
else:
where = "work_id=$work_id AND username=$username"
return oldb.update('ratings', where=where,
rating=rating, vars=data)