Example #1
0
    def get(self):
        lat = self.get_argument("lat")
        lon = self.get_argument("lon")

        user_tastes = self.redis.smembers("tastes::like::%s" % self.email)
        user_dislikes = self.redis.smembers("tastes::dislike::%s" % self.email)

        user_history = self.redis.lrange("places::history::%s" % self.email,
                                         0, 5)

        place_reasons_key = "places::reasons::%s::%%s" % self.email
        place_scores = "places::score::%s" % str(uuid.uuid4())

        self.redis.delete(place_scores)

        self.reason_keys = set()

        def process_businesses(businesses):
            for business in businesses:
                key = business["factual_id"]
                reason_key = place_reasons_key % key
                self.reason_keys.add(reason_key)

                score = 0

                if business["$distance"] < 500:
                    self.redis.sadd(reason_key, "distance")
                    score += 1
                else:
                    distance = business["$distance"]
                    if distance > 1000:
                        distance -= 1000
                        score -= math.floor(distance / 500)

                # TODO: Add some sort of alternate lookup for the rating if it
                # isn't present.
                if "rating" in business:
                    place_rating = business["rating"]
                    if place_rating > 4:
                        self.redis.sadd(reason_key, "great_rating")
                        score += 2
                    elif place_rating > 3:
                        self.redis.sadd(reason_key, "good_rating")
                        score += 1

                for category in business["cuisine"].split(", "):
                    if category in user_dislikes:
                        score -= 4
                    elif category in user_tastes:
                        score += 3
                        self.redis.sadd(reason_key, "like:%s" % category)

                if key in user_history:
                    score -= 3
                else:
                    self.redis.sadd(reason_key, "notrecent")

                # Add the data to redis for this session
                print place_scores, score, key
                self.redis.zadd(place_scores, key, score)

        def place_callback(data):
            # Generate a score for each venue.
            process_businesses(data)

            # Get the place with the best score.
            pick = self.redis.zrevrange(place_scores, 0, 1)[0]

            # Get the reasons for picking
            pick_reasons = self.redis.smembers(place_reasons_key % pick)

            # Delete all the used keys from Redis.
            map(self.redis.delete, self.reason_keys)
            self.redis.delete(place_scores)

            def pick_output(data):
                self.write({"result": "okay",
                            "business": data,
                            "reasons": list(pick_reasons),
                            "stars": data["rating"] if "rating" in data else 3})
                self.finish()
                print "Finished"

            print "Picked %s" % pick
            business_data(pick_output, pick, redis=self.redis)
            self.redis.lpush("places::history::%s" % self.email, pick)

        print "Searching Factual"
        fact_search(place_callback, latitude=lat, longitude=lon,
                    categories=user_tastes, redis=self.redis)
Example #2
0
    def _render_choices(self, group_id, lat, lon):
        members = self.redis.smembers("group::%s" % group_id)

        user_tastes = self.redis.sunion(map(lambda i: "tastes::like::%s" % i, members))
        user_dislikes = self.redis.sunion(map(lambda i: "tastes::dislike::%s" % i, members))

        print "Tastes: ", user_tastes
        print "Dislikes: ", user_dislikes

        histories = set()
        for member in members:
            for h in self.redis.lrange("places::history::%s" % member, 0, 3):
                histories.add(h)

        place_scores = "places::group_score::%s" % group_id
        self.redis.delete(place_scores)

        def process_businesses(businesses):
            for business in businesses:
                key = business["factual_id"]
                score = 0

                if business["$distance"] < 750:
                    score += 1
                else:
                    distance = business["$distance"]
                    if distance > 1000:
                        distance -= 1000
                        score -= math.floor(distance / 500)

                if "rating" in business:
                    place_rating = business["rating"]
                    if place_rating > 4:
                        score += 2
                    elif place_rating > 3:
                        score += 1

                for category in business["cuisine"].split(", "):
                    if category in user_tastes and category in user_dislikes:
                        continue

                    if category in user_dislikes:
                        score -= 2
                    elif category in user_tastes:
                        score += 1

                if key in histories:
                    score -= 1

                # Add the data to redis for this session
                print place_scores, score, key
                self.redis.zadd(place_scores, key, score)

        def place_callback(data):
            # Generate a score for each venue.
            process_businesses(data)

            # Get the places with the best scores.
            def get_tiny_business(choice):
                id_, score = choice
                return business_data(None, id_, self.redis)["name"], score, id_

            picks = self.redis.zrevrange(place_scores, 0, 3, withscores=True)
            picks = map(get_tiny_business, picks)

            self.write({"result": "okay",
                        "registered": "yes",
                        "members": list(members),
                        "choices": picks,
                        "latitude": lat,
                        "longitude": lon})
            self.finish()

        fact_search(place_callback, latitude=lat, longitude=lon,
                    categories=user_tastes, redis=self.redis)