예제 #1
0
파일: rating.py 프로젝트: CSC480-20S/Master
def ratingsys(id, user, name, rate, comment):
    """Creates a review for a study and updates that study's rating.
    If the user is submitting a duplicate review (same study), the previous review will be overwritten.

    Args:
         id (Integer): The identifier for the study being reviewed.
         user (String): The identifier for the user making the review.
         name (String): The name of the user, as it should be displayed on the review.
         rate (Integer): The rating the user is applying to the study.
         comment (String): The comment the user has about the study.

    Returns:
        Nothing.
    """
    connect = DbConnection.connector()
    review = connect["Reviews"]
    # post the review, overwriting any existing review
    review.update_one({
        "Study_id": id,
        "User_id": user
    }, {
        "$set": {
            "Study_id": id,
            "User_id": user,
            "Name": name,
            "Rating": rate,
            "Comment": comment
        }
    },
                      upsert=True)
    update_study_rating(id)
예제 #2
0
파일: rating.py 프로젝트: CSC480-20S/Master
def update_study_rating(id):
    """Updates a study's rating based on the reviews in the database.

    Intended for use after a review has been made or removed.

    Args:
        id (Integer): The identifier of the study to update.

    Returns:
        Integer: The new value of teh rating.
    """
    # find the new overall rating
    connect = DbConnection.connector()
    review = connect["Reviews"]
    query = review.find({"Study_id": id})
    ratelist = []
    for rates in query:
        ratelist.append(rates["Rating"])
    if (len(ratelist) == 0):
        average = 0
    else:
        average = sum(ratelist) / len(
            ratelist)  # Gets the average rating of this study
        average = round(
            average)  # this average is then converted to a whole number

    # update the rating for the study itself
    rater = connect["Studies"]
    rater.update_one({"Study_id": id}, {"$set": {"Rating": average}})
    return average
예제 #3
0
파일: rating.py 프로젝트: CSC480-20S/Master
def getReviews(study_id):
    """Returns all the reviews for a given study.

    Each review is limited to the name, occupation, rating, and comment.

    Args:
        study_id (Integer): The identifier of the study for which to return reviews.

    Returns:
        List<Dict>: A list of dictionaries containing the name, occupation, rating, and comment for each review.
    """
    # query the database
    connect = DbConnection.connector()["Reviews"]
    queryresults = connect.find({
        "Study_id": study_id,
        "Name": {
            "$exists": True
        },
        "Rating": {
            "$exists": True
        },
        "Comment": {
            "$exists": True
        }
    })
    # convert tot he output format
    reviewlist = []
    for review in queryresults[:]:
        outdoc = dict()
        outdoc["name"] = review["Name"]
        outdoc["rating"] = review["Rating"]
        outdoc["comment"] = review["Comment"]
        reviewlist += [outdoc]
    return reviewlist
예제 #4
0
파일: rating.py 프로젝트: CSC480-20S/Master
def remove_rating(study_id, user_id):
    """Removes a review for a study and updates that study's rating.

    Args:
        study_id (Integer): The study that was reviewed.
        user_id (String): The user whose review should be removed.

    Returns:
        Boolean: True if a study was deleted."""
    connect = DbConnection.connector()
    review = connect["Reviews"]
    # delete the review
    result = review.delete_one({"Study_id": study_id, "User_id": user_id})
    update_study_rating(study_id)
    return result.deleted_count > 0
예제 #5
0
def getTemplate(study_id):
    """Grabs a study's template given the study's ID.

    Pulls from the database and returns a String object representing the JSON template.

    Args:
        study_id (int): The ID assigned to a study at upload.

    Returns:
        String: The associated study's template field from the database.
    """

    connect = DbConnection.connector()["Studies"]
    study = {"Study_id": study_id}
    seek = connect.find_one(study, ["Template"])
    return seek["Template"]
예제 #6
0
def updateUser(user):
    """"Updates a user in the database.	
    Pushes a new version of the user data into the database. Assumes the current ID already exists.	
    Args:	
        user (FindingFiveStudyStoreUser): The new data to write to the database.	
    Returns:	
        Nothing.	
    """

    connect = DbConnection.connector()["Users"]
    userJ = {"User_id": user.get_userId()}
    changes = {"$set": {"Num Credits": user.get_numCredits(),
                        "Owned Studies": user.get_ownedStudies(),
                        "Viewed Studies": user.get_viewedStudies(),
                        "Wish List": user.get_wishList(),
                        "Author List": user.get_authorList()}}
    connect.update_one(userJ, changes)
예제 #7
0
def removeWishlist(user_id, study_id):
    """Removes a study from a user's wish list of studies.

    Removes all occurences in the list.

    Args:
        user_id (String): The ID of the user removing the study from the wish list.
        study_id (int): The ID of the study being removed from the wish list.

    Returns:
        Nothing.
    """

    connect = DbConnection.connector()["Users"]
    user = {"User_id": user_id}
    lister = {"$pull": {"Wish List": study_id}}
    connect.update_one(user, lister)
예제 #8
0
def addWishlist(user_id, study_id):
    """"Adds a study to a user's wish list of studies.

    Adds the study to the end of the list, unless already in the wish list.

    Args:
        user_id (String): The ID of the user wish listing the study.
        study_id (int): The ID of the study being saved to the wish list.

    Returns:
        Nothing.
    """

    connect = DbConnection.connector()["Users"]
    user = {"User_id": user_id}
    lister = {"$addToSet": {"Wish List": study_id}}
    connect.update_one(user, lister)
예제 #9
0
def addViewed(user_id, study_id):
    """"Adds a study to a user's list of viewed studies.

    Adds the study to the end of the list, even if viewed before.

    Args:
        user_id (String): The ID of the user viewing the study.
        study_id (int): The ID of the study being viewed.

    Returns:
        Nothing.
    """

    connect = DbConnection.connector()["Users"]
    user = {"User_id": user_id}
    lister = {"$push": {"Viewed Studies": study_id}}
    connect.update_one(user, lister)
예제 #10
0
def createUser(user):
    """Creates a new user in the database.

    If the user already exists, do nothing.
    A user object can be created with just a user ID.

    Args:
        user (FindingFiveStudyStoreUser): The user object to store.

    Returns:
        Boolean: True if the user was created, False if they user was already present."""

    connect = DbConnection.connector()["Users"]
    filter = {"User_id": user.get_userId()}
    update = {"$setOnInsert": user.build_database_doc()}
    # this should be returning the "pre-update" doc, which will be None if nothing matches the filter.
    result = connect.find_one_and_update(filter, update, upsert=True)
    return result is None
예제 #11
0
def addAuthored(user_id, study_id):
    """Marks a user as being the author of a study.

    Also marks the user as being an owner of that study.
    Does not change the study itself.
    Intended for use with /upload.

    Args:
        user_id (String): The ID of the user authoring the study.
        study_id (Integer): The ID of the study being uploaded.

    Returns:
        Nothing."""

    connect = DbConnection.connector()["Users"]
    user = {"User_id": user_id}
    changes = {"$addToSet": {"Owned Studies": study_id, "Author List": study_id}}
    connect.update_one(user, changes)
예제 #12
0
def getTitle(study_id):
    """Grabs a study's title given the study's ID.

    Returns None if the study does not exist, allowing this method to be used to check existence.

    Args:
        study_id (int): The ID assigned to a study at upload.

    Returns:
        String: The associated study's title field from the database, or None when no such study exists.
    """
    connect = DbConnection.connector()["Studies"]
    study = {"Study_id": study_id}
    seek = connect.find_one(study, ["Title"])
    if seek is None:
        return None
    else:
        return seek["Title"]
예제 #13
0
def getStudies(params, maxStudies=-1):
    """Grabs a list of studies given some parameters they need to meet.

    Pulls from the database and returns a list of FindingFiveStudyStoreStudy objects.
    Each object will have the fields given in params equal to the values paired with them in params.

    Args:
        params (dict): Pairs field names with the values they must have.
        maxStudies (int): If greater than or equal to zero, no more than max studies will be in the output list.

    Returns:
        list<FindingFiveStudyStoreStudy>: The first "max" studies that have the given params.
    """

    # if asked for zero studies, just return
    if (maxStudies == 0):
        return []
    # change to the number the Mongo code likes uses for no limit
    elif (maxStudies < 0):
        maxStudies = 0

    # acquire studies
    connect = DbConnection.connector()["Studies"]
    seek = connect.find(filter=params, projection={"Template": False, "Images": False}, limit=maxStudies, collation={'locale':'en_US', 'strength':1})

    # get the number of studies returned - params maintains the filter
    numStudies = seek.collection.count_documents(params, collation={'locale':'en_US', 'strength':1})

    # make sure we don't return more studies than expected
    numWanted = min(numStudies, maxStudies)
    if maxStudies == 0:
        numWanted = numStudies

    studyList = []
    # not sure if this actually returns a list
    for study in seek[0:numWanted]:
        studyList.append(
            f5study(study["Study_id"], study["Title"], study["Author"], study["CostinCredits"], study["Purpose"],
                    study["References"],
                    study["Categories"], study["Sub_Categories"], study["Keywords"], study["Num_Stimuli"],
                    study["Num_Responses"], study["Randomize"], study["Duration"], study["Num_trials"], study["Rating"],
                    study["Institution"], "Template redacted", [], study["Abstract"], study["Author_id"],
                    study["Upload Date"]))
    return studyList
예제 #14
0
def getUser(user_id):
    """Grabs a user given its ID.

    Pulls from the database and returns a FindingFiveStudyStoreUser object.

    Args:
        user_id (String): The ID associated with a user at authentication.

    Returns:
        FindingFiveStudyStoreUser: The associated user in the database.
    """

    connect = DbConnection.connector()["Users"]
    user = {"User_id": user_id}
    seek = connect.find_one(user)
    if seek is not None:
        return f5user(user_id, seek["Num Credits"], seek["Owned Studies"], seek["Viewed Studies"], seek["Wish List"], seek["Author List"])
    else:
        return f5user(user_id)
예제 #15
0
def isWishlisted(user_id, study_id):
    """"Returns the wish list status of the study.

    Returns true only if the indicated user wishes for the indicated study,
    otherwise returns false.

    Args:
        user_id (String): The identifier for the user who may wish for the study.
        study_id (int): The identifier for the study the user may wish for.

    Returns:
        boolean: True if the user wishes for the study, else false.
    """

    connect = DbConnection.connector()["Users"]
    user = {"User_id": user_id,
            "Wish List": {"$in": [study_id]}}
    # if such a user exists, we get the user, else we get None
    return connect.find_one(user) != None
예제 #16
0
def timestampAndGetAuthor(study_id, field_name):
    """"Adds a timestamp to a study and returns the author ID of that study.

    Timestamps a study, using  field_name as the name of the timestamp.
    Returns the author ID of the study.
    These two actions are combined for optimization of the administrative review endpoint ReviewPending.

    Args:
        study_id (Integer): The identifier of the study to timestamp.
        field_name (String): The name to attach to the timestamp.


    Returns:
        String: The author ID of the specified study.
    """
    connect = DbConnection.connector()["Studies"]
    study = connect.find_one_and_update({"Study_id": study_id},
                                        {"$currentDate": {field_name: {"$type": "timestamp"}}},
                                        ["Author_id"])
    return study["Author_id"]
예제 #17
0
def addNotification(user_id, title, body, type):
    """"Posts a notification to the database.

    Posts the notification, along with an additional timestamp, to the database.

    Args:
        user_id (String): The user who should receive the notification.
        title (String): The header of the notification.
        body (String): The main portion of the notification for when the user clicks on it.
        type (String): The type of notifaction, such as approval, denial, or welcome.

    Returns:
        Nothing.
    """
    connect = DbConnection.connector()["Notifications"]
    notification = {"User_id": user_id, "Title": title, "Body": body, "Type": type}
    connect.insert(notification)
    timeUpdate = {"$currentDate": {"Timestamp": True}}
    notificationFinder = notification
    notificationFinder["Timestamp"] = {"$exists": False}
    connect.update_one(notificationFinder, timeUpdate, upsert=True)
예제 #18
0
def addOwned(user_id, study_id, cost):
    """Decreases a user's credits to purchase a study.

    Atomically decreases a user's credits and adds the study to the user's list of owned studies.
    Does not verify that the referenced study actually exists.
    If the study is already in the list, a duplicate will not be created.

    Args:
        user_id (String): The ID of the user purchasing the study.
        study_id (Integer): The ID of the study being purchased.
        cost (Integer): The positive number of credits to deduct from the user for the study.

    Returns:
        Nothing.
    """

    connect = DbConnection.connector()["Users"]
    user = {"User_id": user_id}
    changes = {"$inc": {"Num Credits": 0 - cost},
               "$addToSet": {"Owned Studies": study_id}}
    connect.update_one(user, changes)
예제 #19
0
def getStudy(study_id):
    """Grabs a study given its ID.

    Pulls from the database and returns a FindingFiveStudyStoreStudy object.

    Args:
        study_id (int): The ID assigned to a study at upload.

    Returns:
        FindingFiveStudyStoreStudy: The associated study in the database.
    """
    connect = DbConnection.connector()["Studies"]
    study = {"Study_id": study_id}
    seek = connect.find_one(study)

    return f5study(study_id, seek["Title"], seek["Author"], seek["CostinCredits"], seek["Purpose"],
                   seek["References"],
                   seek["Categories"], seek["Sub_Categories"], seek["Keywords"], seek["Num_Stimuli"],
                   seek["Num_Responses"], seek["Randomize"], seek["Duration"], seek["Num_trials"], seek["Rating"],
                   seek["Institution"], seek["Template"], seek["Images"], seek["Abstract"], seek["Author_id"],
                   seek["Upload Date"])
예제 #20
0
    def get(self, **kwargs):
        """"Removes the specified.study from search results.

        This operation will fail if the user making the request is not the author of the study.
        An unpublished study can still be accessed via other user's historical lists,
        and the template can still be accessed via /deliver.

        Args:
            user_id (String): The identifier for the user trying to unpublish the study.
            study_id (Integer): The identifier of the study the user is trying to unpublish.

        Returns:
            JSON: {"Success": True} if unpublished, {"Success": False} if no such study authored by user.
        """
        # obtain parameters
        parser = reqparse.RequestParser(bundle_errors=True)
        parser.add_argument(
            "study_id",
            type=int,
            required=True,
            help="The study ID to be unpublished is an integer.")
        returned_args = parser.parse_args()
        user_id = kwargs["user_id"]
        study_id = returned_args.get("study_id", None)

        connect = DbConnection.connector()["Studies"]
        study = connect.find_one_and_update(
            {
                "Study_id": study_id,
                "Author_id": user_id
            }, {"$currentDate": {
                "Denied": {
                    "$type": "timestamp"
                }
            }})
        result = study is not None
        # return converted output
        return jsonify({"Success": result})
예제 #21
0
def getMessages(user_id):
    """"Returns the list of .notifications sent to a user.

    Returns all notifications sent to a user, starting with the newest.

    Args:
        user_id (String): The identifier for the user for whom the notifications are to be returned.

    Returns:
        JSON: The list of notifications.
    """
    # acquire notifications
    connect = DbConnection.connector()["Notifications"]
    seek = connect.find(filter={"User_id": user_id}, sort=[('Timestamp', -1)])
    # build list
    out = []
    for notif in seek:
        out.append({
            "title": notif["Title"],
            "body": notif["Body"],
            "type": notif["Type"],
            "timestamp": notif["Timestamp"]
        })
    return out
예제 #22
0
    def post(self,**kwargs):
        """Uploads a new study to the database.

        Uploaded studies are not visible in the store's search results until they are approved by an administrator.
        Adds the new study to the author's author list and owned list.
        Note the difference between author and author_id:
        author is intended to be displayed to other users,
        while author_id is used for internal referencing.
        They can be the same, but security may be improved by not displaying other user's IDs.

        Args:
            title (String): The title of the study.
            author (String): The author of the study, as it should be displayed.
            costInCredits (Integer): The cost of the study in credits. Negative values are possible, but will not be
                                     returned when filtering by price.
            purpose (String): The purpose of the study.
            references (String): The reference that others should use when referencing this study.
            categories (List of Strings): The main categories that the study belongs to.
            subcategories (List of Strings): The subcategories that the study belongs to.
            keywords (List of Strings): The keywords associated with a study.
            num_stimuli (Integer): The number of stimuli that the study uses.
            num_responses (Integer): The number of responses that the study uses.
            num_trials (Integer): The number of trials that the study uses.
            randomize (Boolean): Whether the study uses randomization.
            duration (Integer): The expected duration, in minutes, of the study.
            institution (String): The institution associated with the author or study.
            template (String): The JSON study template from FindingFive.
            images (List of Strings): The images for display when previewing the study.
                                      May be references to external images, or may be base64 encoded images.
            abstract (String): The abstract of the study. Acts as a description.
            author_id (String): The user ID of the author.


        Returns:
            JSON: {"study_id": id}, where id is the generated study ID for this study.
        """
        # obtain parameters
        parser = reqparse.RequestParser(bundle_errors=True)
        parser.add_argument("title", type=str, required=True,
                            help="Title should be a String.", nullable=False)
        parser.add_argument("author", type=str, required=True,
                            help="Author should be a String.", nullable=False)
        parser.add_argument("costInCredits", type=int, required=True,
                            help="Cost should be an integer.", nullable=False)
        parser.add_argument("purpose", type=str, required=True,
                            help="Purpose should be a String.", nullable=False)
        parser.add_argument("references", type=str, required=True,
                            help="References should be a String.", nullable=False)
        parser.add_argument("categories", type=str, action='append', required=True,
                            help="Category should be a list of Strings.", nullable=False)
        parser.add_argument("subcategories", type=str, action='append', required=True,
                            help="Subcategories should be a list of Strings.", nullable=False)
        parser.add_argument("keywords", type=str, action='append', required=True,
                            help="Keywords should be a list of Strings.", nullable=False)
        parser.add_argument("num_stimuli", type=int, required=True,
                            help="The number of stimuli should be an integer.", nullable=False)
        parser.add_argument("num_responses", type=int, required=True,
                            help="The number of responses should be an integer.", nullable=False)
        parser.add_argument("num_trials", type=int, required=True,
                            help="The number of trials should be an integer.", nullable=False)
        parser.add_argument("randomize", type=inputs.boolean, required=True,
                            help="Randomization of trials should be a boolean.", nullable=False)
        parser.add_argument("duration", type=int, required=True,
                            help="Duration should be an integer.", nullable=False)
        parser.add_argument("institution", type=str, required=True,
                            help="Institution should be a String.", nullable=False)
        parser.add_argument("template", type=str, required=True,
                            help="Template should be a JSON in String form.", nullable=False)
        parser.add_argument("images", type=str, action="append",
                            required=True, help="Images should be a list of base64-encoded Strings.", nullable=False)
        parser.add_argument("abstract", type=str, required=True,
                            help="Abstract should be a String.", nullable=False)
        #parser.add_argument("author_id", type=str, required=True, help="The author_id is the user_id of the uploading user.")

        returned_args = parser.parse_args()

        constants = DbConnection.connector()["Constants"]
        counter = constants.find_one_and_update({"Next_ID": {"$exists": True}}, {"$inc": {"Next_ID": 1}})
        study_id = counter["Next_ID"]
        title = returned_args.get("title", None)
        author = returned_args.get("author", None)
        costInCredits = returned_args.get("costInCredits", None)
        purpose = returned_args.get("purpose", None)

        # todo: check to ensure that the lists are coming back with proper values
        references = returned_args.get("references", None)
        categories = returned_args.get("categories", None)
        subcategories = returned_args.get("subcategories", None)
        keywords = returned_args.get("keywords", None)
        num_stimuli = returned_args.get("num_stimuli", None)
        num_responses = returned_args.get("num_responses", None)
        num_trials = returned_args.get("num_trials", None)
        randomize = returned_args.get("randomize", None)
        duration = returned_args.get("duration", None)
        institution = returned_args.get("institution", None)
        template = returned_args.get("template", None)
        images = returned_args.get("images", None)
        abstract = returned_args.get("abstract", None)
        author_id = kwargs["user_id"]  #returned_args.get("author_id", None)
        # the miscelaneous-looking 0 is the initial rating.
        study = FindingFiveStudyStoreStudy(study_id, title, author, costInCredits, purpose, references, categories,
                                           subcategories, keywords, num_stimuli, num_responses, randomize,
                                           duration, num_trials, 0, institution, template, images, abstract, author_id)
        # connect = DbConnection.connector()["Studies"]
        study_dict = study.build_database_doc()

        # using update_one so that we can use update operations to establish the upload date.
        DbConnection.connector()["Studies"].update_one({"Study_id": study_id}, study_dict, upsert=True)

        # update the author and ownenship information of the uploading user
        Auxiliary.addAuthored(author_id, study_id)
        # tq=task_queue.TaskQueue()
        # tq.add_function(prefix_cache.SearchCache.add_new_word,full=title)

        return jsonify({"study_id": study_id})