def get_greatest(_achievements):
     assert(_achievements is not None)
     _greatest = Achievement.get_by_id(int(_achievements[0]["id"]))
     for _achievement in _achievements[1:]:
         _candidate = Achievement.get_by_id(int(_achievement["id"]))
         if _candidate.points >= _greatest.points:
             _greatest = _candidate
     return _greatest
def get_nearby_achievements(location, radius=None):
    """ @param location a dictionary containing "lng" and "lat" entries
        @param radius radius of google places search
        @return list of Achievement objects as json
        Does a google Places nearby_search lookup,
        Retrieves all Datastore Places entries s.t. place_id is in search results
        Retrieves all Datastore Achievements s.t. achievement_id is in a Places achievements list
        return set of Achievements as a json objects
    """
    google_places = GooglePlaces(API_KEY)
    location = {"lng": location['lon'], "lat": location['lat']}
    query_results = google_places.nearby_search(lat_lng=location, rankby=ranking.DISTANCE, keyword='[Achievement]')

    result = {}
    achievements = []
    for place in query_results.places:
        query = Place.gql("WHERE id = '" + str(place.id) + "'")
        place_object = query.get()
        if place_object != None:
            for achievement_id in place_object.achievements:
                achievement_obj = Achievement.get_by_id(int(achievement_id))
                achievements.append(achievement_obj.to_dict())
            result["status_code"] = 200
        else:
            result["status_code"] = 404
    result["achievements"] = achievements
    return json.dumps(result)
def get_achievement_photo(achievement_id):
    try:
        from Tools import rescale
        from Models import Achievement
        import cloudstorage as gcs
        from search import nearby_search
        if achievement_id == 'nearby':
            print 'nearby'
            lon = request.query['lon']
            lat = request.query['lat']
            place_documents = nearby_search(lon, lat, 500000)
            print place_documents
            if place_documents is None:
                return json.dumps({'status_code': 204})
            achievement_id = place_documents[0]['achievement_id']
            print achievement_id
        achievement = Achievement.get_by_id(int(achievement_id))
        pictures = list(achievement.pictures)
        picture_id = pictures[0]
        size = [int(request.query['x']), int(request.query['y'])]
        gcs_filename = '/thebucket/picture/' + picture_id + '/photo'
        gcs_file = gcs.open(gcs_filename)
        data = gcs_file.read()
        return rescale.rescale(data, *size)
    except BaseException, ex:
        logging.exception("Exception: %s" % ex)
        print(str(ex))
        return json.dumps({"status_code": 400})
def get_achievement(achievement_id):
    result = {'achievement_id': achievement_id}
    achievement = Achievement.get_by_id(int(achievement_id))
    if achievement is None:
        result['status_code'] = 404
    else:
        result['status_code'] = 200
        result['achievement'] = json.dumps(achievement.to_dict())
    return result
def user_achievements_latest_and_greatest():
    from Models import UserDetails, Achievement
    user_id = request.json['user_id']
    print "user_id" + str(user_id)
    user_details = UserDetails.get_by_id(int(user_id))
    print user_details
    achievements = [json.loads(a) for a in user_details.achievements]
    if achievements is not None:
        latest = achievements[0]
        greatest = Achievement.get_by_id(int(achievements[0]['id']))
        for achievement in achievements[1:]:
            candidate = Achievement.get_by_id(int(achievement['id']))
            if candidate.points > greatest.points:
                greatest = candidate
            if int(achievement['time']) > int(latest['time']):
                latest = achievement
        latest_id = latest['id']
        greatest_id = greatest.key.id()
        print latest_id
        print greatest_id
        return json.dumps(dict(status_code=200, latest_id=int(latest_id), greatest_id=greatest_id))
    else:
        return json.dumps(dict(status_code=204))
def add_achievement(achievement_id, user_id):
    from Models import UserDetails, Achievement
    user_details = UserDetails.get_by_id(int(user_id))
    achievement = Achievement.get_by_id(int(achievement_id))
    if achievement is None or user_details is None:
        print achievement_id
        print user_id
        return None
    print achievement.to_dict()
    print user_details.to_dict()
    if not user_details.achievements:
        achievements = []
    else:
        achievements = [json.loads(a) for a in user_details.achievements]
    print achievements
    if not any(d.get('id', None) == int(achievement_id) for d in achievements):
        # user does not have achievement
        def get_greatest(_achievements):
            assert(_achievements is not None)
            _greatest = Achievement.get_by_id(int(_achievements[0]["id"]))
            for _achievement in _achievements[1:]:
                _candidate = Achievement.get_by_id(int(_achievement["id"]))
                if _candidate.points >= _greatest.points:
                    _greatest = _candidate
            return _greatest

        achievement_entry = {"id": int(achievement_id),
                             "time": time.time()}
        achievements.append(achievement_entry)
        if user_details.score is None:
            user_details.score = 0
        user_details.score += achievement.points
        greatest = get_greatest(achievements)
        user_details.greatest = greatest.key
        user_details.greatest_thumbnail = greatest.thumbnail
        user_details.latest = achievement.key
        user_details.latest_thumbnail = achievement.thumbnail
        print achievements
        user_details.achievements = list(json.dumps(a) for a in achievements)
        print user_details.achievements
        user_details.put()
        print user_details.to_dict()
        return achievement_id
    else:
        print "User already has achievement"
def achievement_info(achievement_id):
    try:
        from Models import Achievement
        from Tools import decode
        print request.json
        d = dict(decode.decode_dict(request.json))
        print d
        num_pictures = d['num_pictures']
        print num_pictures
        achievement = Achievement.get_by_id(int(achievement_id))
        print achievement
        pictures = achievement.pictures
        return json.dumps(
            {
                "picture_ids": pictures[1:int(num_pictures)],
                "achievement_name": achievement.name,
                "achievement_description": achievement.description,
                "points": achievement.points
            })
    except BaseException, ex:
        logging.exception("Exception: %s" % ex)
        print(str(ex))
        return json.dumps({"status_code": 400})
def add_place():
    try:
        # Create a new achievement to associate with the new place
        new_achievement = Achievement(name=ach_name,
                                      description=ach_description,
                                      points=ach_points,
                                      requirements=ach_requirements)
        achievement_key = new_achievement.put()
        achievement = achievement_key.get()
        achievement_pictures = []

        if add_photos:
            try:
                # Do a place search to get photos
                google_places = GooglePlaces(TEST_KEY)
                query_result = google_places.text_search(place_name)
                for place in query_result.places:
                    print "Google place: " + str(place.name)
                    thumbnail_size = (128, 128)
                    first = True
                    place.get_details()
                    print "Google place, photos: " + str(len(place.photos))
                    for photo in place.photos:
                        photo.get(maxheight=2000, maxwidth=2000)
                        photo_data = photo.data
                        mime_type = photo.mimetype

                        thumbnail_data = rescale.rescale(photo_data, *thumbnail_size)
                        thumbnail = images.Image(thumbnail_data)
                        thumbnail.im_feeling_lucky()

                        # TODO Generate BlobStore entity for get_serving_url(Blobstore

                        # Create Picture Entity to get a unique ID
                        picture = Picture(votes=0, mime_type=mime_type)
                        picture_key = picture.put()
                        picture = picture_key.get()
                        picture_id = str(picture_key.id())
                        picture.created = datetime.now()
                        # Go ahead and add a link from the Achievement Entity to the Picture Entity

                        picture.put()

                        # Write to GCS and create blob_key
                        gcs_filename = '/thebucket/picture/' + picture_id + '/photo'
                        try:
                            with gcs.open(gcs_filename, 'w', content_type=mime_type) as f:
                                f.write(photo.data)
                            blob_key_picture = blobstore.create_gs_key('/gs' + gcs_filename)
                            picture.picture_url = images.get_serving_url(blob_key_picture)

                            gcs_filename = '/thebucket/picture/' + picture_id + '/thumbnail'
                            with gcs.open(gcs_filename, 'w', content_type=mime_type) as f:
                                f.write(thumbnail.execute_transforms())
                            blob_key_thumbnail = blobstore.create_gs_key('/gs' + gcs_filename)
                            picture.thumbnail_url = images.get_serving_url(blob_key_thumbnail)
                        except BaseException, TransformationError:
                            print str(TransformationError)
                            continue
                        picture.put()
                        # Save the first photo as the achievements thumbnail
                        if first:
                            achievement.thumbnail = picture.thumbnail_url
                            first = False
                        achievement_pictures.append(picture_id)
                        achievement.pictures = achievement_pictures
                    #end for, break because we only want the first place returned
                    break
                    #end for
            except GooglePlacesError as error_detail:
                # You've passed in parameter values that the Places API doesn't like..
                print error_detail
        # end if add_photos
        achievement.put()
        # create place document and add it to index
        place_document = search.Document(
            doc_id=str(achievement_key.id()),
            fields=[
                search.TextField(name='name', value=place_name),
                search.TextField(name='country', value=place_country),
                search.TextField(name='state', value=place_state),
                search.TextField(name='city', value=place_city),
                search.GeoField(name='location', value=search.GeoPoint(place_lat, place_lon)),
                search.NumberField(name='radius', value=place_accuracy),
                search.NumberField(name='altitude', value=place_altitude),
                search.TextField(name='achievement_id', value=str(achievement_key.id())),
                search.DateField(name='created', value=datetime.now()),
            ])
        index = search.Index(name="places-index")
        index.put(place_document)
        return "Achievement:\n" + str(achievement.to_dict()) + "\nPlace:\n" + str(place_document)
    except BaseException, ex:
        logging.exception("Add place exception: %s " % ex)
        return str(ex)