Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0b101c4

Browse files
author
Sashko Stubailo
authored
Merge pull request #68 from apollostack/hot
Implement Hot ranking
2 parents 3168cbd + 36b4bc8 commit 0b101c4

File tree

5 files changed

+87
-3
lines changed

5 files changed

+87
-3
lines changed

api/sql/models.js

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import RedditScore from 'reddit-score';
2+
13
import knex from './connector';
24

35
// A utility function that makes sure we always query the same columns
@@ -66,6 +68,8 @@ export class Entries {
6668
query.orderBy('created_at', 'desc');
6769
} else if (type === 'TOP') {
6870
query.orderBy('score', 'desc');
71+
} else if (type === 'HOT') {
72+
query.orderBy('hot_score', 'desc');
6973
} else {
7074
throw new Error(`Feed type ${type} not implemented.`);
7175
}
@@ -96,7 +100,7 @@ export class Entries {
96100

97101
return Promise.resolve()
98102

99-
// First, get the entry_id from repoFullName
103+
// First, get the entry_id from repoFullName
100104
.then(() => (
101105
knex('entries')
102106
.where({
@@ -125,6 +129,57 @@ export class Entries {
125129
username,
126130
vote_value: voteValue,
127131
})
132+
))
133+
// Update hot score
134+
.then(() => this.updateHotScore(repoFullName));
135+
}
136+
137+
updateHotScore(repoFullName) {
138+
let entryId;
139+
let createdAt;
140+
141+
return Promise.resolve()
142+
.then(() => (
143+
knex('entries')
144+
.where({
145+
repository_name: repoFullName,
146+
})
147+
.select(['id', 'created_at'])
148+
.first()
149+
.then(({ id, created_at }) => {
150+
entryId = id;
151+
createdAt = created_at;
152+
})
153+
))
154+
.then(() => {
155+
return knex('votes')
156+
.select(['vote_value'])
157+
.where({
158+
entry_id: entryId,
159+
});
160+
})
161+
.then((results) => {
162+
function countVotes(vote) {
163+
return (count, value) => count + (value === vote ? 1 : 0);
164+
}
165+
166+
if (results && results.map) {
167+
const votes = results.map(vote => vote.vote_value);
168+
const ups = votes.reduce(countVotes(1), 0);
169+
const downs = votes.reduce(countVotes(-1), 0);
170+
const date = createdAt instanceof Date ? createdAt : new Date(createdAt);
171+
172+
return (new RedditScore()).hot(ups, downs, date);
173+
}
174+
175+
return 0;
176+
})
177+
.then(hotScore => (
178+
knex('entries')
179+
.where('id', entryId)
180+
.update({
181+
hot_score: hotScore,
182+
})
128183
));
129184
}
130185

@@ -183,6 +238,7 @@ export class Entries {
183238
posted_by: username,
184239
});
185240
}
186-
}));
241+
}))
242+
.then(() => this.updateHotScore(repoFullName));
187243
}
188244
}

api/sql/schema.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ type Entry {
3939
# The score of this repository, upvotes - downvotes
4040
score: Int!
4141
42+
# The hot score of this repository
43+
hotScore: Int!
44+
4245
# Comments posted about this repository
4346
comments: [Comment]! # Should this be paginated?
4447
@@ -66,6 +69,7 @@ export const resolvers = {
6669
return context.Comments.getCommentsByRepoName(repository_name);
6770
},
6871
createdAt: property('created_at'),
72+
hotScore: property('hot_score'),
6973
commentCount({ repository_name }, _, context) {
7074
return context.Comments.getCommentCount(repository_name) || constant(0);
7175
},

migrations/20160518201950_create_comments_entries_votes.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export function up(knex, Promise) {
1313
table.timestamps();
1414
table.string('repository_name').unique();
1515
table.string('posted_by');
16+
table.float('hot_score');
1617
}),
1718

1819
knex.schema.createTable('votes', (table) => {

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
"lodash": "4.16.4",
5555
"passport": "0.3.2",
5656
"passport-github": "1.1.0",
57+
"reddit-score": "0.0.1",
5758
"request-promise": "4.1.1",
5859
"sqlite3": "3.1.7",
5960
"subscriptions-transport-ws": "0.2.6"

seeds/seed.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,21 @@
11
import _ from 'lodash';
2+
import RedditScore from 'reddit-score';
3+
4+
function countScore(score) {
5+
return (count, value) => count + (value === score ? 1 : 0);
6+
}
7+
8+
function hot(repoVotes, date) {
9+
const redditScore = new RedditScore();
10+
11+
const createdAt = date instanceof Date ? date : new Date(date);
12+
13+
const scores = _.values(repoVotes || {});
14+
const ups = scores.reduce(countScore(1), 0);
15+
const downs = scores.reduce(countScore(-1), 0);
16+
17+
return redditScore.hot(ups, downs, createdAt);
18+
}
219

320
const repos = [
421
{
@@ -83,11 +100,16 @@ export function seed(knex, Promise) {
83100
// Insert some entries for the repositories
84101
.then(() => {
85102
return Promise.all(repos.map(({ repository_name, posted_by }, i) => {
103+
const createdAt = Date.now() - (i * 10000);
104+
const repoVotes = votes[repository_name];
105+
const hotScore = hot(repoVotes, createdAt);
106+
86107
return knex('entries').insert({
87-
created_at: Date.now() - (i * 10000),
108+
created_at: createdAt,
88109
updated_at: Date.now() - (i * 10000),
89110
repository_name,
90111
posted_by,
112+
hot_score: hotScore,
91113
}).then(([id]) => {
92114
repoIds[repository_name] = id;
93115
});

0 commit comments

Comments
 (0)