public
Created

Fake Recommender class for CoffeeScript/tame discussion

  • Download Gist
recommender.coffee
CoffeeScript
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
```coffeescript
 
class Recommender
 
getRecommendations: (search_params, cb) ->
 
# Do 2 things at once:
# - check if we have a logged in user, get their info
# - fire off distributed requests for search queries
# ------------------------------------------------------------------------
 
await
interest_meta = {}
@isLoggedIn defer logged_in, user_info
for interest in search_params.interests
@getMetaInfo interest.text, defer interest_meta[interest.text]
 
#
# Do more things at once:
# - get a taste profile for the user (only if logged in)
# - get taste profiles for each legit search interest
# ------------------------------------------------------------------------
 
await
taste_profiles = {}
@getUserTasteProfile user_info.id, defer user_taste_profile if logged_in
for interest, meta of interest_meta
@getTasteProfile meta.id, defer taste_profiles[meta.id] if meta
 
#
# Get the recommendations, combining all the taste profiles
# ------------------------------------------------------------------------
 
await @getRecsFromTasteProfiles taste_profiles, user_taste_profile, defer recommendations
 
#
# We have recs, but just [id, score] pairs. Let's:
# - look up info on each interest
# - save that this user got these recs (if logged in)
# ------------------------------------------------------------------------
 
full_recommendations = []
await
for v,i in recommendations
@getInfo v[0], defer full_recommendations[i]
@rememberRecommendations user_info.id, recommendations, defer() if logged_in
cb full_recommendations
 
# --------------------------------------------------------------------------
 
 
# --------------------------------------------------------------------------
# Fake functions, for those who want to test getRecommendations()
# I added some management of what's concurrent
# --------------------------------------------------------------------------
 
isLoggedIn: (cb) ->
@_fakeRpc "logged_in", =>
if Math.random() < 0.5
cb true,
id: "user_id_#{Math.random()}"
age: Math.floor(18 + 30 * Math.random())
else
cb false, null
 
getRecsFromTasteProfiles: (tp, utp, cb) ->
@_fakeRpc "get_recs", =>
res = []
for i in [0..10]
res.push ["interest_id_#{Math.random()}", Math.random()]
cb res
 
getMetaInfo: (search_str, cb) ->
@_fakeRpc "get_meta", ->
cb id: "interest_id_#{Math.random()}"
 
getUserTasteProfile: (uid, cb) ->
@_fakeRpc "get_user_taste", ->
cb Math.random()
 
getTasteProfile: (uid, cb) ->
@_fakeRpc "get_taste", ->
cb Math.random()
 
getInfo: (rec_id, cb) ->
@_fakeRpc "get_info", ->
cb
title: "Bangin'"
avg_age: Math.floor(18 + 30 * Math.random())
id: rec_id
 
rememberRecommendations: (id, recommendations, cb) ->
@_fakeRpc "rememberRecommendations", cb
 
# --------------------------------------------------------------------------
 
_fakeRpc: (name, cb) ->
@_openRpcCount = {} if not @_openRpcCount
@_openRpcCount[name] = 0 if not @_openRpcCount[name]
@_openRpcCount[name]++
@_printFakeRpcData()
setTimeout((()=>
@_openRpcCount[name]--
@_printFakeRpcData()
cb()),Math.random()*1000)
 
_printFakeRpcData: ->
console.log "open remote calls: " + ("#{k} (#{v})" for k,v of @_openRpcCount).join(" ")
 
 
R = new Recommender()
 
search_params =
interests: [ { text: "football", opinion: 1.23 }, { text: "basketball", opinion: 13.23 } ]
 
start_time = Date.now()
 
R.getRecommendations search_params, (res) ->
console.log "-------------"
console.log "Done. Got #{res.length} results in #{Date.now() - start_time}ms"
 
```

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.