Ejemplo n.º 1
0
    def get(self, course_id, question_id, user_id):
        course = Courses.query.get_or_404(course_id)
        require(READ, course)

        question = PostsForQuestions.query.get_or_404(question_id)
        # ineligible authors - eg. instructors, TAs, dropped student, current user
        student = UserTypesForCourse.query.filter_by(
            name=UserTypesForCourse.TYPE_STUDENT).first_or_404()
        ineligible_users = CoursesAndUsers.query.filter_by(courses_id=course_id) \
            .filter(CoursesAndUsers.usertypesforcourse_id != student.id) \
            .values(CoursesAndUsers.users_id)
        ineligible_user_ids_base = [u[0] for u in ineligible_users]
        ineligible_user_ids_base.append(user_id)

        # ineligible authors (potentially) - eg. authors for answers that the user has seen
        judged = Judgements.query.filter_by(users_id=current_user.id).join(AnswerPairings) \
            .filter_by(questions_id=question.id).all()
        judged_authors1 = [
            j.answerpairing.answer1.post.users_id for j in judged
        ]
        judged_authors2 = [
            j.answerpairing.answer2.post.users_id for j in judged
        ]
        ineligible_user_ids = ineligible_user_ids_base + judged_authors1 + judged_authors2

        eligible_answers = PostsForAnswers.query.filter_by(questions_id=question.id) \
            .join(Posts).filter(Posts.users_id.notin_(ineligible_user_ids)).count()
        avail_pairs = eligible_answers / 2 >= 1  # min 1 pair required

        return {'availPairsLogic': avail_pairs}
Ejemplo n.º 2
0
    def get(self, course_id, question_id, user_id):
        course = Courses.query.get_or_404(course_id)
        require(READ, course)

        question = PostsForQuestions.query.get_or_404(question_id)
        # ineligible authors - eg. instructors, TAs, dropped student, current user
        student = UserTypesForCourse.query.filter_by(name=UserTypesForCourse.TYPE_STUDENT).first_or_404()
        ineligible_users = CoursesAndUsers.query.filter_by(courses_id=course_id) \
            .filter(CoursesAndUsers.usertypesforcourse_id != student.id) \
            .values(CoursesAndUsers.users_id)
        ineligible_user_ids_base = [u[0] for u in ineligible_users]
        ineligible_user_ids_base.append(user_id)

        # ineligible authors (potentially) - eg. authors for answers that the user has seen
        judged = Judgements.query.filter_by(users_id=current_user.id).join(AnswerPairings) \
            .filter_by(questions_id=question.id).all()
        judged_authors1 = [j.answerpairing.answer1.post.users_id for j in judged]
        judged_authors2 = [j.answerpairing.answer2.post.users_id for j in judged]
        ineligible_user_ids = ineligible_user_ids_base + judged_authors1 + judged_authors2

        eligible_answers = PostsForAnswers.query.filter_by(questions_id=question.id) \
            .join(Posts).filter(Posts.users_id.notin_(ineligible_user_ids)).count()
        avail_pairs = eligible_answers / 2 >= 1  # min 1 pair required

        return {'availPairsLogic': avail_pairs}
Ejemplo n.º 3
0
    def get(self, course_id, question_id):
        """
        Get an answer pair for judgement.
        """
        course = Courses.query.get_or_404(course_id)
        question = PostsForQuestions.query.get_or_404(question_id)
        require(READ, question)
        if not question.judging_period:
            return {'error': 'Evaluation period is not active.'}, 403

        pair_generator = AnswerPairGenerator(course.id, question,
                                             current_user.id)

        try:
            answerpairing = pair_generator.get_pair()

            on_answer_pair_get.send(self,
                                    event_name=on_answer_pair_get.name,
                                    user=current_user,
                                    course_id=course_id,
                                    data={
                                        'id':
                                        answerpairing.id,
                                        'answer_pair':
                                        ','.join([
                                            str(answerpairing.answers_id1),
                                            str(answerpairing.answers_id2)
                                        ]),
                                    })

            return marshal(
                {
                    'id': answerpairing.id,
                    'answers': [answerpairing.answer1, answerpairing.answer2]
                }, dataformat.get_answer_pairings_new())
        except InsufficientAnswersException:
            return {
                "error": "Not enough answers are available for an evaluation."
            }, 400
        except UserHasJudgedAllAnswers:
            return {
                "error": "You have judged all the currently available answers."
            }, 400
        except AnswerMissingScoreCalculation:
            return {"error": "An answer is missing a calculated score."}, 400
        except MissingScoreFromAnswer:
            return {"error": "A score is missing from an answer."}, 400
        except UnknownAnswerPairError:
            return {
                "error":
                "Generating scored pairs failed, this really shouldn't happen."
            }, 500
Ejemplo n.º 4
0
    def get(self, course_id):
        course = Courses.query.get_or_404(course_id)
        require(READ, course)

        questions = PostsForQuestions.query. \
            with_entities(PostsForQuestions.id). \
            join(Posts).filter_by(courses_id=course.id). \
            all()

        # ineligible authors - eg. instructors, TAs, dropped student, current user
        ineligible_users = CoursesAndUsers.query. \
            filter_by(courses_id=course_id). \
            join(UserTypesForCourse).filter(UserTypesForCourse.name.notlike(UserTypesForCourse.TYPE_STUDENT)). \
            values(CoursesAndUsers.users_id)
        ineligible_user_ids_base = [u[0] for u in ineligible_users]
        ineligible_user_ids_base.append(current_user.id)

        # It is a little bit hard to write query to include authors for each answers in the loop below
        # stmt = PostsForAnswers.query.\
        # 	with_entities(PostsForAnswers.questions_id, func.count(PostsForAnswers.id).label('answer_count')). \
        # 	join(Posts).join(AnswerPairings).join(Judgements). \
        # 	filter(Posts.users_id.notin_(ineligible_userIds_base)).subquery()
        #
        # questions = PostsForQuestions.query.\
        # 	with_entities(PostsForQuestions.id, stmt.c.answer_count). \
        # 	join(Posts).filter_by(courses_id=course.id). \
        # 	outerjoin(stmt, PostsForQuestions.id == stmt.c.questions_id). \
        # 	all()

        avail_pairs = {}
        for ques in questions:
            question_id = ques[0]
            # ineligible authors (potentially) - eg. authors for answers that the user has seen
            judged = Judgements.query.filter_by(users_id=current_user.id).join(AnswerPairings) \
                .filter_by(questions_id=question_id).all()
            judged_authors1 = [
                j.answerpairing.answer1.post.users_id for j in judged
            ]
            judged_authors2 = [
                j.answerpairing.answer2.post.users_id for j in judged
            ]
            ineligible_user_ids = ineligible_user_ids_base + judged_authors1 + judged_authors2

            eligible_answers = PostsForAnswers.query.filter_by(questions_id=question_id) \
                .join(Posts).filter(Posts.users_id.notin_(ineligible_user_ids)).count()
            avail_pairs[
                question_id] = eligible_answers / 2 >= 1  # min 1 pair required

        return {'availPairsLogic': avail_pairs}
Ejemplo n.º 5
0
    def get(self, course_id):
        course = Courses.query.get_or_404(course_id)
        require(READ, course)
        questions = PostsForQuestions.query.join(Posts).filter_by(courses_id=course.id).all()
        judgements = {ques.id: judgement_count(ques, current_user.id) for ques in questions}

        on_judgement_course_count.send(
            self,
            event_name=on_judgement_course_count.name,
            user=current_user,
            course_id=course_id,
            data={'user_id': current_user.id, 'counts': judgements}
        )

        return {'judgements': judgements}
Ejemplo n.º 6
0
    def get(self, course_id, question_id, user_id):
        course = Courses.query.get_or_404(course_id)
        require(READ, course)
        question = PostsForQuestions.query. \
            options(load_only('id', 'criteria_count', 'posts_id')). \
            get_or_404(question_id)
        require(READ, question)
        count = judgement_count(question, user_id)

        on_judgement_question_count.send(
            self,
            event_name=on_judgement_question_count.name,
            user=current_user,
            course_id=course_id,
            data={'question_id': question_id, 'user_id': user_id, 'count': count}
        )

        return {"count": count}
Ejemplo n.º 7
0
    def get(self, course_id):
        course = Courses.query.get_or_404(course_id)
        require(READ, course)

        questions = PostsForQuestions.query. \
            with_entities(PostsForQuestions.id). \
            join(Posts).filter_by(courses_id=course.id). \
            all()

        # ineligible authors - eg. instructors, TAs, dropped student, current user
        ineligible_users = CoursesAndUsers.query. \
            filter_by(courses_id=course_id). \
            join(UserTypesForCourse).filter(UserTypesForCourse.name.notlike(UserTypesForCourse.TYPE_STUDENT)). \
            values(CoursesAndUsers.users_id)
        ineligible_user_ids_base = [u[0] for u in ineligible_users]
        ineligible_user_ids_base.append(current_user.id)

        # It is a little bit hard to write query to include authors for each answers in the loop below
        # stmt = PostsForAnswers.query.\
        # 	with_entities(PostsForAnswers.questions_id, func.count(PostsForAnswers.id).label('answer_count')). \
        # 	join(Posts).join(AnswerPairings).join(Judgements). \
        # 	filter(Posts.users_id.notin_(ineligible_userIds_base)).subquery()
        #
        # questions = PostsForQuestions.query.\
        # 	with_entities(PostsForQuestions.id, stmt.c.answer_count). \
        # 	join(Posts).filter_by(courses_id=course.id). \
        # 	outerjoin(stmt, PostsForQuestions.id == stmt.c.questions_id). \
        # 	all()

        avail_pairs = {}
        for ques in questions:
            question_id = ques[0]
            # ineligible authors (potentially) - eg. authors for answers that the user has seen
            judged = Judgements.query.filter_by(users_id=current_user.id).join(AnswerPairings) \
                .filter_by(questions_id=question_id).all()
            judged_authors1 = [j.answerpairing.answer1.post.users_id for j in judged]
            judged_authors2 = [j.answerpairing.answer2.post.users_id for j in judged]
            ineligible_user_ids = ineligible_user_ids_base + judged_authors1 + judged_authors2

            eligible_answers = PostsForAnswers.query.filter_by(questions_id=question_id) \
                .join(Posts).filter(Posts.users_id.notin_(ineligible_user_ids)).count()
            avail_pairs[question_id] = eligible_answers / 2 >= 1  # min 1 pair required

        return {'availPairsLogic': avail_pairs}
Ejemplo n.º 8
0
    def get(self, course_id):
        course = Courses.query.get_or_404(course_id)
        require(READ, course)
        questions = PostsForQuestions.query.join(Posts).filter_by(
            courses_id=course.id).all()
        judgements = {
            ques.id: judgement_count(ques, current_user.id)
            for ques in questions
        }

        on_judgement_course_count.send(
            self,
            event_name=on_judgement_course_count.name,
            user=current_user,
            course_id=course_id,
            data={
                'user_id': current_user.id,
                'counts': judgements
            })

        return {'judgements': judgements}
Ejemplo n.º 9
0
    def get(self, course_id, question_id, user_id):
        course = Courses.query.get_or_404(course_id)
        require(READ, course)
        question = PostsForQuestions.query. \
            options(load_only('id', 'criteria_count', 'posts_id')). \
            get_or_404(question_id)
        require(READ, question)
        count = judgement_count(question, user_id)

        on_judgement_question_count.send(
            self,
            event_name=on_judgement_question_count.name,
            user=current_user,
            course_id=course_id,
            data={
                'question_id': question_id,
                'user_id': user_id,
                'count': count
            })

        return {"count": count}
Ejemplo n.º 10
0
    def get(self, course_id, question_id):
        """
        Get an answer pair for judgement.
        """
        course = Courses.query.get_or_404(course_id)
        question = PostsForQuestions.query.get_or_404(question_id)
        require(READ, question)
        if not question.judging_period:
            return {'error': 'Evaluation period is not active.'}, 403

        pair_generator = AnswerPairGenerator(course.id, question, current_user.id)

        try:
            answerpairing = pair_generator.get_pair()

            on_answer_pair_get.send(
                self,
                event_name=on_answer_pair_get.name,
                user=current_user,
                course_id=course_id,
                data={
                    'id': answerpairing.id,
                    'answer_pair': ','.join([str(answerpairing.answers_id1), str(answerpairing.answers_id2)]),
                })

            return marshal(
                {'id': answerpairing.id, 'answers': [answerpairing.answer1, answerpairing.answer2]},
                dataformat.get_answer_pairings_new())
        except InsufficientAnswersException:
            return {"error": "Not enough answers are available for an evaluation."}, 400
        except UserHasJudgedAllAnswers:
            return {"error": "You have judged all the currently available answers."}, 400
        except AnswerMissingScoreCalculation:
            return {"error": "An answer is missing a calculated score."}, 400
        except MissingScoreFromAnswer:
            return {"error": "A score is missing from an answer."}, 400
        except UnknownAnswerPairError:
            return {"error": "Generating scored pairs failed, this really shouldn't happen."}, 500
Ejemplo n.º 11
0
    def post(self, course_id, question_id):
        """
        Stores a judgement into the database.
        """
        Courses.query.get_or_404(course_id)
        question = PostsForQuestions.query.get_or_404(question_id)
        if not question.judging_period:
            return {'error': 'Evaluation period is not active.'}, 403
        require(READ, question)
        require(CREATE, Judgements)
        question_criteria = CriteriaAndPostsForQuestions.query. \
            filter_by(question=question, active=True).all()
        params = new_judgement_parser.parse_args()
        answer_pair = AnswerPairings.query.get(params['answerpair_id'])
        if not answer_pair:
            return {"error": "Invalid Answer Pair ID"}, 404
        # check if number of judgements matches number of criteria
        if len(question_criteria) != len(params['judgements']):
            return {"error": "Not all criteria were evaluated."}, 400
        # check if each judgement has an questionCriteria Id and a winner id
        for judgement in params['judgements']:
            if 'question_criterion_id' not in judgement:
                return {"error": "Missing question_criterion_id in evaluation."}, 400
            if 'answer_id_winner' not in judgement:
                return {"error": "Missing selected answer for one of the criteria."}, 400
            # check that we're using criteria that were assigned to the course and that we didn't
            # get duplicate criteria in judgements
            known_criterion = False
            for question_criterion_entry in question_criteria[:]:
                if judgement['question_criterion_id'] == question_criterion_entry.id:
                    known_criterion = True
                    question_criteria.remove(question_criterion_entry)
            if not known_criterion:
                return {"error": "Unknown criterion submitted in judgement!"}, 400
            # check that the winner id matches one of the answer pairs
            winner_id = judgement['answer_id_winner']
            if winner_id != answer_pair.answer1.id and winner_id != answer_pair.answer2.id:
                return {"error": "Selected answer ID does not match the available pair of answers."}, 400
        # check if pair has already been judged by this user
        if Judgements.query.filter_by(users_id=current_user.id).join(AnswerPairings). \
            filter(or_(
                and_(
                    AnswerPairings.answers_id1 == answer_pair.answers_id1,
                    AnswerPairings.answers_id2 == answer_pair.answers_id2),
                and_(
                    AnswerPairings.answers_id1 == answer_pair.answers_id2,
                    AnswerPairings.answers_id2 == answer_pair.answers_id1)
            )
        ).first():
            return {"error": "You've already evaluated this pair of answers."}, 400

        # now the real deal, creating the judgement
        judgements = Judgements.create_judgement(params, answer_pair, current_user.id)

        # update answer scores
        current_app.logger.debug("Doing scoring")
        Judgements.calculate_scores(question_id)

        on_judgement_create.send(
            self,
            event_name=on_judgement_create.name,
            user=current_user,
            course_id=course_id,
            data=marshal(judgements, dataformat.get_judgements()))

        return {'objects': marshal(judgements, dataformat.get_judgements())}
Ejemplo n.º 12
0
    def post(self, course_id, question_id):
        """
        Stores a judgement into the database.
        """
        Courses.query.get_or_404(course_id)
        question = PostsForQuestions.query.get_or_404(question_id)
        if not question.judging_period:
            return {'error': 'Evaluation period is not active.'}, 403
        require(READ, question)
        require(CREATE, Judgements)
        question_criteria = CriteriaAndPostsForQuestions.query. \
            filter_by(question=question, active=True).all()
        params = new_judgement_parser.parse_args()
        answer_pair = AnswerPairings.query.get(params['answerpair_id'])
        if not answer_pair:
            return {"error": "Invalid Answer Pair ID"}, 404
        # check if number of judgements matches number of criteria
        if len(question_criteria) != len(params['judgements']):
            return {"error": "Not all criteria were evaluated."}, 400
        # check if each judgement has an questionCriteria Id and a winner id
        for judgement in params['judgements']:
            if 'question_criterion_id' not in judgement:
                return {
                    "error": "Missing question_criterion_id in evaluation."
                }, 400
            if 'answer_id_winner' not in judgement:
                return {
                    "error": "Missing selected answer for one of the criteria."
                }, 400
            # check that we're using criteria that were assigned to the course and that we didn't
            # get duplicate criteria in judgements
            known_criterion = False
            for question_criterion_entry in question_criteria[:]:
                if judgement[
                        'question_criterion_id'] == question_criterion_entry.id:
                    known_criterion = True
                    question_criteria.remove(question_criterion_entry)
            if not known_criterion:
                return {
                    "error": "Unknown criterion submitted in judgement!"
                }, 400
            # check that the winner id matches one of the answer pairs
            winner_id = judgement['answer_id_winner']
            if winner_id != answer_pair.answer1.id and winner_id != answer_pair.answer2.id:
                return {
                    "error":
                    "Selected answer ID does not match the available pair of answers."
                }, 400
        # check if pair has already been judged by this user
        if Judgements.query.filter_by(users_id=current_user.id).join(AnswerPairings). \
            filter(or_(
                and_(
                    AnswerPairings.answers_id1 == answer_pair.answers_id1,
                    AnswerPairings.answers_id2 == answer_pair.answers_id2),
                and_(
                    AnswerPairings.answers_id1 == answer_pair.answers_id2,
                    AnswerPairings.answers_id2 == answer_pair.answers_id1)
            )
        ).first():
            return {
                "error": "You've already evaluated this pair of answers."
            }, 400

        # now the real deal, creating the judgement
        judgements = Judgements.create_judgement(params, answer_pair,
                                                 current_user.id)

        # update answer scores
        current_app.logger.debug("Doing scoring")
        Judgements.calculate_scores(question_id)

        on_judgement_create.send(self,
                                 event_name=on_judgement_create.name,
                                 user=current_user,
                                 course_id=course_id,
                                 data=marshal(judgements,
                                              dataformat.get_judgements()))

        return {'objects': marshal(judgements, dataformat.get_judgements())}