Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
cerealbox
committed
Aug 8, 2015
1 parent
04a249f
commit 1c357ce
Showing
5 changed files
with
286 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
var Promise = require('promise'); | ||
|
||
//fun = [1,2,3] -> Promise({1: {}, 2: {}, 3: {}}) | ||
module.exports = function batch(fun) { | ||
var batches = {}; | ||
var result = null; | ||
|
||
return function(ids) { | ||
|
||
if (!Object.keys(batches).length) { | ||
result = | ||
Promise. | ||
resolve(). | ||
then(function() { | ||
var keys = Object.keys(batches); | ||
batches = {}; | ||
return fun(keys); | ||
}); | ||
} | ||
ids.forEach(function(id) { | ||
batches[id] = true; | ||
}); | ||
|
||
return result.then(function(results) { | ||
var prunedResults = {}; | ||
ids.forEach(function(id) { | ||
prunedResults[id] = results[id]; | ||
}); | ||
return prunedResults; | ||
}); | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
var Promise = require('promise'); | ||
|
||
//fun = [1,2,3] -> Promise({1: {}, 2: {}, 3: {}}) | ||
module.exports = function cache(fun) { | ||
var cache = {}; | ||
|
||
return function(ids) { | ||
|
||
var assemble = function(results) { | ||
//put new results in cache: | ||
Object.keys(results).forEach(function(id) { | ||
cache[id] = results[id]; | ||
}); | ||
//grab cached results: | ||
ids.forEach(function(id) { | ||
results[id] = cache[id]; | ||
}); | ||
|
||
return results; | ||
}; | ||
|
||
var culledIds = ids.filter(function(id) { | ||
return !cache[id]; | ||
}); | ||
|
||
if (culledIds.length) { | ||
return fun(culledIds).then(assemble); | ||
} else { | ||
return Promise.resolve(assemble({})); | ||
} | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
var Promise = require('promise') | ||
var PouchDB = require('pouchdb') | ||
var ratingsDB = new PouchDB('ratings_db') | ||
var batch = require('./batch') | ||
var cache = require('./cache') | ||
|
||
var jlog = function(x) { console.log(JSON.stringify(x, null, 3)) } | ||
|
||
// ratings service | ||
function RatingService() {} | ||
RatingService.prototype = { | ||
|
||
getRatings: function(userId, titleIds) { | ||
jlog("getRatings(" + userId + ", [" + titleIds + "])") | ||
|
||
return ratingsDB.allDocs({ | ||
keys: titleIds.map(function(id) { | ||
return userId + "," + id; | ||
}), | ||
include_docs: true | ||
}).then(function(dbResponse) { | ||
var ratings = {} | ||
dbResponse.rows.forEach(function(row) { | ||
ratings[row.key.substr((userId + ",").length)] = row | ||
}) | ||
return ratings | ||
}); | ||
}, | ||
|
||
setRatings: function(userId, titlesIdsAndRating) { | ||
jlog("setRatings(" + userId + ", {" + JSON.stringify(titlesIdsAndRating) + "})") | ||
|
||
function coerce(rating) { | ||
if (rating > 5) | ||
return 5 | ||
else if (rating < 1) | ||
return 1 | ||
else | ||
return rating | ||
} | ||
|
||
var ids = Object.keys(titlesIdsAndRating) | ||
|
||
//test: | ||
// return Promise.resolve({ | ||
// 9: { | ||
// doc: {rating: 69} | ||
|
||
// }, | ||
// 10: { | ||
// doc: {rating: 69} | ||
// } | ||
// }) | ||
|
||
return ratingsDB.allDocs({ | ||
keys: ids.map(function(id) { | ||
return userId + "," + id; | ||
}), | ||
include_docs: true | ||
}).then(function(getResponse) { | ||
//jlog(getResponse) | ||
return ratingsDB.bulkDocs(ids.map(function(id, index) { | ||
// jlog("=============") | ||
// jlog(titlesIdsAndRating[id].userRating) | ||
return { | ||
_id: userId + "," + id, | ||
_rev: (!getResponse.rows[index].error ? getResponse.rows[index].value.rev : undefined), | ||
rating: coerce(titlesIdsAndRating[id].userRating) | ||
}; | ||
})).then(function(setResponse) { | ||
var results = {} | ||
getResponse.rows.forEach(function(response, index) { | ||
if (setResponse[index].ok) { | ||
if (getResponse.rows[index].error) { | ||
results[response.key.substr((userId + ",").length)] = { | ||
id: setResponse[index].id, | ||
key: setResponse[index].id, | ||
value: { | ||
rev: setResponse[index].rev | ||
}, | ||
doc: { | ||
rating: coerce(titlesIdsAndRating[response.key.substr((userId + ",").length)].userRating), | ||
_id: setResponse[index].id, | ||
_rev: setResponse[index].rev | ||
} | ||
} | ||
} else { | ||
results[response.key.substr((userId + ",").length)] = response | ||
} | ||
} else { | ||
results[response.key.substr((userId + ",").length)] = setResponse[index] | ||
} | ||
}) | ||
return results | ||
}) | ||
}); | ||
} | ||
} | ||
|
||
module.exports = new RatingService() | ||
|
||
// module.exports.getRatings(1, [3,4,5]).then(jlog, jlog) | ||
// module.exports.getRatings(1, [1,2,3]).then(jlog, jlog) | ||
|
||
// //example: | ||
// module.exports.getRatings(1, [11]).then(jlog) | ||
// module.exports.getRatings(1, [11]).then(function(x) { | ||
// jlog(x) | ||
// module.exports.getRatings(1, [11]).then(jlog) | ||
// module.exports.getRatings(1, [11]).then(jlog) | ||
// }) | ||
// jlog("-----------------------------------") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
var Promise = require('promise') | ||
|
||
var PouchDB = require('pouchdb') | ||
var recommendationsDB = new PouchDB('recommendations_db') | ||
|
||
var log = console.log.bind(console) | ||
var jlog = function(x) { console.log(JSON.stringify(x, null, 3)) } | ||
|
||
// genrelist service | ||
function RecommendationsService() {} | ||
RecommendationsService.prototype = { | ||
getGenreList: function(userId) { | ||
var self = this | ||
if (self.cache) { | ||
return Promise.resolve(self.cache) | ||
} else { | ||
return recommendationsDB.get((userId || 'all').toString()) | ||
.then(function(response) { | ||
self.cache = response.recommendations | ||
return response.recommendations | ||
}) | ||
} | ||
}, | ||
addTitleToGenreList: function(userId, genreIndex, titles) { | ||
|
||
return recommendationsDB.get(userId) | ||
.then(function(response) { | ||
var titlesLength = response.recommendations[genreIndex].titles.push(titles); | ||
return recommendationsDB.put({ | ||
_id: userId, | ||
_rev: response._rev, | ||
recommendations: response.recommendations | ||
}).then(function(a) { | ||
return [ | ||
{ | ||
path: ['genrelist', genreIndex, 'titles', titlesLength - 1], | ||
value: titles | ||
}, | ||
{ | ||
path: ['genrelist', genreIndex, 'titles', 'length'], | ||
value: titlesLength | ||
} | ||
]; | ||
}); | ||
}); | ||
}, | ||
|
||
//@TODO: untested. | ||
//[].splice(index, howMany, replce, replce, replce) takes unlimited number of the final argument | ||
spliceTitleFromGenreList: function(userId, a, b, c) { | ||
return recommendationsDB.get(userId) | ||
.then(function(response) { | ||
var titlesLength = response.recommendations[genreIndex].titles.splice(a, b, c); | ||
return recommendationsDB.put({ | ||
_id: userId, | ||
_rev: response._rev, | ||
recommendations: response.recommendations | ||
}).then(function() { | ||
return [ | ||
{ | ||
path: ['genrelist', genreIndex, 'titles', titlesLength - 1], | ||
value: titles | ||
}, | ||
{ | ||
path: ['genrelist', genreIndex, 'titles', 'length'], | ||
value: titlesLength | ||
} | ||
]; | ||
}); | ||
}); | ||
} | ||
} | ||
|
||
module.exports = new RecommendationsService() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
var PouchDB = require('pouchdb') | ||
var titlesDB = new PouchDB('titles_db') | ||
var batch = require('./batch') | ||
var cache = require('./cache') | ||
|
||
var jlog = function(x) { console.log(JSON.stringify(x, null, 3)) } | ||
|
||
// titles service | ||
function TitleService() {} | ||
TitleService.prototype = { | ||
getTitles: function(titleIds) { | ||
jlog("getTitles([" + titleIds + "])") | ||
|
||
return titlesDB.allDocs({ | ||
keys: titleIds, | ||
include_docs: true | ||
}).then(function(dbResponse) { | ||
var titles = {} | ||
dbResponse.rows.forEach(function (row) { | ||
titles[row.key] = row | ||
}) | ||
return titles | ||
}) | ||
} | ||
} | ||
|
||
module.exports = new TitleService() | ||
|
||
//example: | ||
// module.exports.getTitles([12]).then(jlog) | ||
// module.exports.getTitles([12]).then(function(x) { | ||
// jlog(x) | ||
// module.exports.getTitles([13]).then(jlog) | ||
// module.exports.getTitles([12,13]).then(jlog) | ||
// }) | ||
// jlog("-----------------------------------") |