def before_request(): uri = os.environ.get("MONGOLAB_URI", "mongodb://localhost/wtflunch") flask.g.dbc = pymongo.Connection(host=uri) dbname = pymongo.uri_parser.parse_uri(uri).get("database", "wtflunch") flask.g.db = flask.g.dbc[dbname] # Indexing. c = User.c() c.ensure_index("token") c.ensure_index("open_id") c = Proposal.c() c.ensure_index("accepted") c.ensure_index("date") c.ensure_index("user_id") c.ensure_index("short_url") # Redis database. flask.g.redis = redis.StrictRedis.from_url( os.environ.get("REDISTOGO_URL", "redis://localhost:6379"))
def main(rejectid=None, blackid=None): # Get the currently logged in user. user = current_user() # Get the acceptance model. # try: # model = AcceptanceModel(*(user["model"])) # except (TypeError, KeyError): model = AcceptanceModel(0.3, 2.0, 1.0, 3.0) # Blacklist the proposal forever. if blackid is not None: if user is not None: proposal = Proposal.from_id(blackid) if proposal is not None: user.blacklist(proposal["id"]) proposal.update_response(-2) # model.update(proposal.distance, proposal.rating, # proposal.price, False, eta=0.02) # user.update_model(model.pars) else: rejectid = blackid # Reject the proposal for today. rediskey = "blacklist:" if user is None: h = flask.request.headers rediskey += h.get("X-Forwarded-For", unicode(flask.request.remote_addr)) else: rediskey += unicode(user._id) if rejectid is not None: proposal = Proposal.from_id(rejectid) if proposal is not None: # Update the model. # if user is not None: # model.update(proposal.distance, proposal.rating, # proposal.price, False, eta=0.01) # user.update_model(model.pars) # Cache the rejection. pipe = flask.g.redis.pipeline() pipe.sadd(rediskey, proposal["id"]) pipe.expire(rediskey, 12 * 60 * 60) pipe.execute() if user is None: proposal.remove() else: proposal.update_response(0) print("model", model.pars) # Parse the location coordinates. a = flask.request.args if "longitude" in a and "latitude" in a: loc = np.array((a.get("longitude"), a.get("latitude")), dtype=float) else: return json.dumps({"code": 1, "message": "You need to provide coordinates."}), 400 # Find some yelp restaurant. data = get_listings(loc, model._sd2) if len(data) == 0: # We really couldn't find any results at all. return (json.dumps({"message": "We couldn't find any results. Maybe you should just stay home."}), 404) # Loop over the list of suggestions and accept or reject stochastically. inds = np.arange(len(data)) np.random.shuffle(inds) best = (0, None, None) for ind in inds: choice = data[ind] # Check the user blacklist. if user is not None: bl = user._doc.get("blacklist", []) if choice.id in bl: continue # Check the cached temporary blacklist. if flask.g.redis.sismember(rediskey, choice.id) != 0: continue # Get the aggregate user rating. n0, r0 = 5, choice.rating if r0 is not None: nratings = choice.likes rating = nratings * r0 / (n0 + nratings) else: rating = None # Compute the distance. cloc = choice.location x1 = lnglat2xyz(cloc["longitude"], cloc["latitude"]) x2 = lnglat2xyz(*loc) dist = np.sqrt(2 * (rearth * rearth - np.dot(x1, x2))) # Compute the predictive acceptance probability. prob = model.predict(dist, rating, choice.price) # Check if you've already been there. v = None if user is not None: v = Proposal.c().find_one({"user_id": user._id, "accepted": {"$in": [2, -1]}}) # Down weight the probability if you have been there. if v is not None: # HACKISH MAGIC. prob = 0.1 * prob print(dist, rating, choice.price, prob, choice.likes) if prob > best[0]: best = (prob, ind, dist) # Accept stochastically. if np.random.rand() <= prob: best = (prob, ind, dist) break if best[1] is None: # None of the restaurants had non-zero acceptance probability. return (json.dumps({"message": "We couldn't find any results. Maybe you should just stay home."}), 404) choice = data[best[1]] # Try and get the directions. # l = choice.location # params = { # "mode": "walking", # "sensor": "false", # "origin": "{1},{0}".format(*loc), # "destination": "{latitude},{longitude}".format(**l) # } # r = requests.get(google_directions_url, params=params) # resp = r.json() # Build the static map URL. map_params = { "size": "640x200", "zoom": 15, "scale": 2, "sensor": "false", "markers": "label:B|{latitude},{longitude}" .format(**choice.location) } map_url = "http://maps.googleapis.com/maps/api/staticmap?" + \ urllib.urlencode(map_params) result = { "id": choice.id, "name": choice.name, "address": choice.address, "url": choice.url, "rating": choice.rating, "price": choice.price, "categories": choice.categories, "checkins": choice.checkins, "users": choice.users, "likes": choice.likes, "probability": best[0], "distance": best[2], "map_url": map_url, "map_link": "http://maps.google.com/?q=" + urllib.quote(choice.address.encode("utf-8")) } # Save the proposal. if user is None: prop = Proposal.new(None, **result) else: prop = Proposal.new(user._id, **result) result["accept_url"] = flask.url_for(".accept", acceptid=prop._id) result["reject_url"] = flask.url_for(".main", rejectid=prop._id) result["blacklist_url"] = flask.url_for(".main", blackid=prop._id) return json.dumps(result)
def share_view(short_url): prop = Proposal.c().find_one({"short_url": short_url}) if prop is not None: return flask.render_template("share.html", proposal=Proposal(prop)) return flask.redirect(flask.url_for("index"))