Skip to content
Permalink
Browse files

feat: 🎸 add first implementation

  • Loading branch information
streamich committed Apr 15, 2019
1 parent 08425d4 commit 8f3351ffcbf4df429b938aa6a8ece56115fb56a7
Showing with 135 additions and 2 deletions.
  1. +85 −1 src/__tests__/index.spec.ts
  2. +50 −1 src/index.ts
@@ -1 +1,85 @@
xit('Jest working', () => {});
import {hotReddit, bestReddit, hotYCombinator} from '..';

describe('hotReddit', () => {
it('gives higher rating to never content', async () => {
const ts = Date.now();
const score1 = hotReddit(10, 2, ts - 10000);
const score2 = hotReddit(10, 2, ts);

expect(score2).toBeGreaterThan(score1);
});

it('gives higher rating to content with more up votes', async () => {
const ts = Date.now();
const score1 = hotReddit(12, 2, ts);
const score2 = hotReddit(10, 2, ts);

expect(score1).toBeGreaterThan(score2);
});

it('gives higher rating to content with less down votes', async () => {
const ts = Date.now();
const score1 = hotReddit(12, 2, ts);
const score2 = hotReddit(12, 1, ts);

expect(score2).toBeGreaterThan(score1);
});

it('gives higher rating to content with more up votes - 2', async () => {
const ts = Date.now();
const score1 = hotReddit(1, 0, ts);
const score2 = hotReddit(2, 0, ts);

expect(score2).toBeGreaterThan(score1);
});
});

describe('bestReddit', () => {
it('gives higher score to content with more up votes', async () => {
const score1 = bestReddit(11, 2);
const score2 = bestReddit(10, 2);

expect(score1).toBeGreaterThan(score2);
});

it('gives higher score to content with less down votes', async () => {
const score1 = bestReddit(1000, 10);
const score2 = bestReddit(1000, 11);

expect(score1).toBeGreaterThan(score2);
});
});

describe('hotYCombinator', () => {
it('gives higher score to more recent content', async () => {
const ts = Date.now();
const score1 = hotYCombinator(10, ts);
const score2 = hotYCombinator(10, ts - 10000);

expect(score1).toBeGreaterThan(score2);
});

it('gives higher score to content with more up votes', async () => {
const ts = Date.now();
const score1 = hotYCombinator(110, ts);
const score2 = hotYCombinator(111, ts);

expect(score2).toBeGreaterThan(score1);
});

it('gives higher score to content with more up votes - 2', async () => {
const ts = Date.now();
const score1 = hotYCombinator(0, ts);
const score2 = hotYCombinator(111, ts);

expect(score2).toBeGreaterThan(score1);
});

it('gives higher score to content with more up votes - 3', async () => {
const ts = Date.now();
const score1 = hotYCombinator(1, ts);
const score2 = hotYCombinator(111, ts);

expect(score2).toBeGreaterThan(score1);
});
});
@@ -1 +1,50 @@
console.log('Hello world!'); // tslint:disable-line no-console
/**
* Reddit's hot content scoring function. Used for raking higher most recent and
* highest voted content. More recent content items get higher score automatically.
*
* - See: https://medium.com/hacking-and-gonzo/how-reddit-ranking-algorithms-work-ef111e33d0d9
*
* @param ups Number of up votes.
* @param downs Number of down votes.
* @param ts Timestamp in milliseconds when content was created.
*/
export function hotReddit (ups: number, downs: number, ts = Date.now()) {
const s = ups - downs;
const order = Math.log(Math.max(Math.abs(s), 1)) / Math.LN10;
const sign = s > 0 ? 1 : (s < 0 ? -1 : 0);
const seconds = (ts / 1e3) - 1134028003;
return sign * order + seconds / 45000;
}

/**
* YCombinator's hot content scoring formula. Does not require down votes.
*
* - See: https://moz.com/blog/reddit-stumbleupon-delicious-and-hacker-news-algorithms-exposed
*
* @param ups Number of up votes.
* @param ts Timestamp when content was created in milliseconds.
*/
export function hotYCombinator (ups: number, ts: number = Date.now()) {
const hoursSinceCreated = (Date.now() - ts) / (1000 * 60 * 60);
return ups / Math.pow(hoursSinceCreated + 2, 1.5);
}

/**
* Reddit's content scoring function for finding best replies regardless of time
* when content was created. This function does not penalize old content.
*
* - See: https://medium.com/hacking-and-gonzo/how-reddit-ranking-algorithms-work-ef111e33d0d9
*
* @param ups Number of up votes.
* @param downs Number of down votes.
*/
export function bestReddit (ups: number, downs: number) {
const n = ups + downs;
if (!n) return 0;
const z = 1.281551565545;
const p = ups / n;
const left = p + 1 / (2 * n) * z * z;
const right = z * Math.sqrt(p * (1 - p) / n + z * z / (4 * n * n));
const under = 1 + 1 / n * z * z;
return (left - right) / under;
}

0 comments on commit 8f3351f

Please sign in to comment.
You can’t perform that action at this time.