Beispiel #1
0
    def test_answer_many_incorrect_questions_many_topics(self):
        """ check that answering many incorrect questions affects competency children"""
        author_course = self._bootstrap_courses(1)
        author_user = self._bootstrap_user(1)
        author = CourseUser.objects.create(user=author_user,
                                           course=author_course)
        self._bootstrap_topics(author_course)
        topic_selected = Topic.objects.all().filter(id__in=[1, 2])
        self._bootstrap_questions_same_topics(author, topic_selected, 20)
        self._bootstrap_question_choices(correct_id=2)

        QuestionService.respond_to_question(3, author)

        for i in range(1, 20):
            offset = 4 * i
            first_old_competency = Competency.objects.all()[0].competency
            second_old_competency = Competency.objects.all()[1].competency
            third_old_competency = Competency.objects.all()[2].competency
            QuestionService.respond_to_question(3 + offset, author)
            first_new_competency = Competency.objects.all()[0].competency
            second_new_competency = Competency.objects.all()[1].competency
            third_new_competency = Competency.objects.all()[2].competency
            self.assertTrue(first_old_competency >= first_new_competency)
            self.assertTrue(second_old_competency >= second_new_competency)
            self.assertTrue(third_old_competency >= third_new_competency)

        self.assertEqual(QuestionResponse.objects.count(), 20)

        num_topics = combinations(
            QuestionScore.objects.all().first().question.topics.all())
        self.assertEqual(Competency.objects.count(), len(num_topics))
Beispiel #2
0
    def test_decay_function(self):
        """ Test decay function influences question competency over time """
        author_course = self._bootstrap_courses(1)
        author_user = self._bootstrap_user(1)
        responder_user = self._bootstrap_user(2)
        responder = CourseUser.objects.create(user=responder_user,
                                              course=author_course)
        author = CourseUser.objects.create(user=author_user,
                                           course=author_course)
        self._bootstrap_topics(author_course)
        topic_selected = Topic.objects.all().filter(id__in=[1])
        self._bootstrap_questions_same_topics(author, topic_selected, 20)
        self._bootstrap_question_choices(correct_id=2)

        for question in Question.objects.all():
            question.difficulty = 10
            question.save()

        for i in range(0, 10):
            offset = 4 * i
            QuestionService.respond_to_question(2 + offset, author)
            QuestionService.respond_to_question(3 + offset, responder)
        for i in range(10, 20):
            offset = 4 * i
            QuestionService.respond_to_question(3 + offset, author)
            QuestionService.respond_to_question(2 + offset, responder)

        author_competency = Competency.objects.get(user=author).competency
        responder_competency = Competency.objects.get(
            user=responder).competency
        self.assertEqual(QuestionResponse.objects.count(), 40)
        self.assertEqual(QuestionScore.objects.count(), 40)
        self.assertTrue(author_competency <= responder_competency)
Beispiel #3
0
def next_recommended_question(request):
    logged_in_user = UserService.logged_in_user(request)
    question = QuestionService.next_recommended_question(logged_in_user)
    if question is None:
        return JsonResponse({"error": "You are not enrolled in the course for this question"}, status=403)

    return JsonResponse({"data": question.id})
Beispiel #4
0
def rate(request):
    if request.method != 'POST':
        return JsonResponse({
            "error": "Must use POST to this endpoint"
        }, status=405)

    post_request = loads(request.body.decode("utf-8"))
    distractor_id = post_request.get("distractorID", None)

    difficulty = post_request.get("difficulty", None)
    quality = post_request.get("quality", None)

    if difficulty is None and quality is None:
        return JsonResponse({"error": "At least response.rating or response.quality must be specified"}, status=422)

    if difficulty is not None:
        if is_number(difficulty) is False or not 0 <= int(difficulty) <= 5:
            return JsonResponse({"error": "response.difficulty must be between 0 and 5 inclusive"}, status=422)
        difficulty = int(difficulty)

    if quality is not None:
        if is_number(quality) is False or not 0 <= int(quality) <= 5:
            return JsonResponse({"error": "response.quality must be between 0 and 5 inclusive"}, status=422)
        quality = int(quality)

    if distractor_id is None:
        return JsonResponse({"error": "Missing integer distractorID in request"}, status=422)

    user_ratings = {"difficulty": difficulty, "quality": quality}
    if QuestionService.rate_question(distractor_id, user_ratings, UserService.logged_in_user(request)) is False:
        return JsonResponse({"error": "Invalid distractorID"}, status=422)
    else:
        return HttpResponse(status=204)
    def test_leaderboard_fetch_multiple(self):
        """ Tests fetching leaderboard results with multiple courses"""
        courses = [self._bootstrap_courses(1), self._bootstrap_courses(2)]
        course_user = self._bootstrap_course_user(-1, courses[0], True)
        course_user_2 = self._bootstrap_course_user(-2, courses[1], True)
        for count, course in enumerate(courses):
            self._bootstrap_topics(course)
            for i in range((count+1) * 5):
                id = i + count*5
                self._boostrap_leaderboard_users(course, id, id == count)

        leaderboard = QuestionService.get_course_leaders(course_user, False, "questionsAuthored", "")
        self.assertEqual(len(leaderboard), 5)

        leaderboard = QuestionService.get_course_leaders(course_user_2, False, "questionsAuthored", "")
        self.assertEqual(len(leaderboard), 10)
def id(request, id):
    question = QuestionService.getQuestion(id)

    if question is None:
        return JsonResponse({}, status=404)

    return JsonResponse(question.toJSON())
Beispiel #7
0
def all_reports(request):
    user = UserService.logged_in_user(request)

    result = QuestionService.all_reports(user)
    if type(result) != list and result.get("error", None) is not None:
        return JsonResponse(result)
    else:
        return JsonResponse({"data": result})
Beispiel #8
0
def id(request, id):
    logged_in_user = UserService.logged_in_user(request)
    question = QuestionService.get_question_by_id(logged_in_user, id)

    if question is None:
        return JsonResponse({"error": "You are not enrolled in the course for this question"}, status=403)

    return JsonResponse({"data": question})
Beispiel #9
0
def get_reasons(request):
    if request.method != 'POST':
        return JsonResponse({
            "error": "Must use POST to this endpoint"
        }, status=405)

    user = UserService.logged_in_user(request)
    return JsonResponse({"data": QuestionService.get_reason_list(user)})
    def test_leaderboard_sort_direction(self):
        course = self._bootstrap_courses(1)
        course_user = self._bootstrap_course_user(-1, course, True)
        self._bootstrap_topics(course)
        for i in [1,2,3,4,5]:
            self._boostrap_leaderboard_users(course, i, i == 1)

        leaderboard = QuestionService.get_course_leaders(course_user, False, "questionsAuthored", "DESC")
        self.assertEqual(len(leaderboard), 5)
        self.assertEqual(leaderboard[0]["questionsAuthored"], 5)
        self.assertEqual(leaderboard[1]["questionsAuthored"], 0)

        # Sort in other direction
        leaderboard = QuestionService.get_course_leaders(course_user, False, "questionsAuthored", "ASC")
        self.assertEqual(len(leaderboard), 5)
        self.assertEqual(leaderboard[0]["questionsAuthored"], 0)
        self.assertEqual(leaderboard[-1]["questionsAuthored"], 5)
 def test_leaderboard_fetch_many_instructor(self):
     """ Tests limiting of leaderboard fetching results for instructor"""
     course = self._bootstrap_courses(1)
     course_user = self._bootstrap_course_user(-1, course, True)
     self._bootstrap_topics(course)
     for i in range(0, 100):
         self._boostrap_leaderboard_users(course, i, i == 1)
     leaderboard = QuestionService.get_course_leaders(course_user, False, "questionsAuthored", "DESC", limit=-1)
     self.assertEqual(len(leaderboard), 100)
Beispiel #12
0
def report(request):
    if request.method != 'POST':
        return JsonResponse({
            "error": "Must use POST to this endpoint"
        }, status=405)

    post_request = loads(request.body.decode("utf-8"))
    user = UserService.logged_in_user(request)
    return JsonResponse({"data": QuestionService.report_question(user, post_request)})
def get_all_stats(user):
    if not util.is_administrator(user):
        return {"error": "User is not authorized"}

    leaderboard = QuestionService.create_leaderboard(user, False,
                                                     ["lastName", "firstName"],
                                                     "ASC")
    for person in leaderboard:
        person.pop("rank", None)
    return {"data": leaderboard}
    def test_leaderboard_fetch(self):
        """ Tests fetching leaderboard results"""
        course = self._bootstrap_courses(1)
        course_user = self._bootstrap_course_user(-1, course, True)
        self._bootstrap_topics(course)
        for i in [1,2,3,4,5]:
            self._boostrap_leaderboard_users(course, i, i == 1)

        leaderboard = QuestionService.get_course_leaders(course_user, False, "questionsAuthored", "")
        self.assertEqual(len(leaderboard), 5)
Beispiel #15
0
    def test_course_topics_multiple(self):
        """ Tests fetching topics for a course when there are multiple courses"""
        courses = [self._bootstrap_courses(1), self._bootstrap_courses(2)]
        for _c, course in enumerate(courses):
            self._bootstrap_topics(course)
            user = self._bootstrap_user(_c + 1)
            author = CourseUser.objects.create(user=user, course=course)
            self._bootstrap_questions(author)

        def _e(s):
            return [x for x in s]

        course_topics = QuestionService.get_course_topics(courses[0])
        self.assertEqual(_e(course_topics),
                         _e(Topic.objects.filter(course=courses[0])))

        course_topics = QuestionService.get_course_topics(courses[1])
        self.assertEqual(_e(course_topics),
                         _e(Topic.objects.filter(course=courses[1])))
Beispiel #16
0
def make_question_responses(user, correct, incorrect, ability):
    if chance(2):
        user_choice = choose_answer(correct, incorrect, ability)
        response = QuestionService.respond_to_question(user_choice.id, user)

        if chance(2):
            rating = QuestionRating(quality=randrange(0, 10),
                                    difficulty=randrange(0, 10),
                                    response=user_choice,
                                    user=user)
            rating.save()
Beispiel #17
0
def leaderboard(request, sort_field, sort_order):
    logged_in_user = UserService.logged_in_user(request)
    user_roles = (str(x) for x in logged_in_user.roles.all())
    limit = -1 if is_administrator(logged_in_user) else 20

    if sort_order != "DESC" and sort_order != "ASC":
        sort_order = "DESC"

    leaderboard_scores = QuestionService.get_course_leaders(logged_in_user,
        False, sort_field, sort_order, limit)
    return JsonResponse({"data": leaderboard_scores})
Beispiel #18
0
    def test_course_topics(self):
        """ Tests fetching topics for a course"""
        course = self._bootstrap_courses(1)
        self._bootstrap_topics(course)

        user = self._bootstrap_user(1)
        author = CourseUser.objects.create(user=user, course=course)
        self._bootstrap_questions(author)

        course_topics = QuestionService.get_course_topics(course)
        self.assertEqual(len(course_topics), 6)
Beispiel #19
0
def update(request, qid):
    val = validate_request(request)
    if not val[0]:
        return val[1]

    root_path, post_request = val

    response = QuestionService.update_question(
        post_request, root_path, UserService.logged_in_user(request), qid)

    return validate_response(response)
Beispiel #20
0
    def test_add_filter_answered(self):
        """test that questions can be filtered if they have been answered before, QuestionResponse exists"""
        course = self._bootstrap_courses(1)
        user = self._bootstrap_user(1)
        author = CourseUser.objects.create(user=user, course=course)
        self._bootstrap_topics(course)
        self._bootstrap_questions(author)
        self._bootstrap_question_choices(correct_id=2)

        #answer the first two questions
        QuestionService.respond_to_question(2, author)
        QuestionService.respond_to_question(6, author)

        test_search = SearchService.SearchService(course)
        test_search.add_filter("answered", author)
        answered_questions = test_search.execute()

        # Check searched questions should be the first 2 answered ones
        for i in answered_questions:
            self.assertTrue(i in Question.objects.all()[0:2])
        self.assertEqual(test_search.execute().count(), 2)
Beispiel #21
0
    def test_add_filter_unanswered(self):
        """Test that questions are filtered when they have not been answered before, no QuestionResponse"""
        course = self._bootstrap_courses(1)
        user = self._bootstrap_user(1)
        author = CourseUser.objects.create(user=user, course=course)
        self._bootstrap_topics(course)
        self._bootstrap_questions(author)
        self._bootstrap_question_choices(correct_id=2)

        #answer the first two questions
        QuestionService.respond_to_question(2, author)
        QuestionService.respond_to_question(6, author)

        test_search = SearchService.SearchService(course)
        test_search.add_filter("unanswered", author)
        unanswered_questions = test_search.execute()

        # Check searched questions should be the last 3 unanaswered ones
        for i in unanswered_questions:
            self.assertTrue(i in Question.objects.all()[2:5])
        self.assertEqual(test_search.execute().count(), 3)
Beispiel #22
0
    def test_answer_many_correct_questions_single_topic(self):
        """ checks that answering many correct questions bring competency upwards"""
        author_course = self._bootstrap_courses(1)
        author_user = self._bootstrap_user(1)
        author = CourseUser.objects.create(user=author_user,
                                           course=author_course)
        self._bootstrap_topics(author_course)

        topic_selected = Topic.objects.all().filter(id__in=[1])
        self._bootstrap_questions_same_topics(author, topic_selected, 20)
        self._bootstrap_question_choices(correct_id=2)

        QuestionService.respond_to_question(2, author)

        for i in range(1, 20):
            offset = 4 * i
            old_competency = Competency.objects.all().first().competency
            QuestionService.respond_to_question(2 + offset, author)
            new_competency = Competency.objects.all().first().competency
            self.assertTrue(old_competency <= new_competency)
        self.assertEqual(QuestionResponse.objects.count(), 20)
        self.assertEqual(Competency.objects.count(), 1)
 def test_rate_nonexistent(self):
     """ Tests rating a question which does not exists """
     course = self._bootstrap_courses(1)
     user = self._bootstrap_user(1)
     author = CourseUser.objects.create(user=user, course=course)
     self._bootstrap_topics(course)
     self._bootstrap_questions(author)
     self._bootstrap_question_choices(correct_id=2)
     self.assertFalse(
         QuestionService.rate_question(-1, {
             "difficulty": 2,
             "quality": 4
         }, author))
Beispiel #24
0
    def test_add_filter_improve(self):
        """
            Test that questions can be filtered by questions answered where user did not get maximun score.
            QuestionResponse exists but Question Score < 1
        """
        course = self._bootstrap_courses(1)
        user = self._bootstrap_user(1)
        author = CourseUser.objects.create(user=user, course=course)
        self._bootstrap_topics(course)
        self._bootstrap_questions(author)
        self._bootstrap_question_choices(correct_id=2)

        #answer the first question correctly after two tries
        QuestionService.respond_to_question(3, author)
        QuestionService.respond_to_question(2, author)

        test_search = SearchService.SearchService(course)
        test_search.add_filter("improve", author)
        improve_questions = test_search.execute()

        self.assertEqual(Question.objects.all().first(),
                         improve_questions.first())
        self.assertEqual(test_search.execute().count(), 1)
    def test_rate_update(self):
        """ Tests rating a question which the user has rated before"""
        course = self._bootstrap_courses(1)
        user = self._bootstrap_user(1)
        author = CourseUser.objects.create(user=user, course=course)
        self._bootstrap_topics(course)
        self._bootstrap_questions(author)
        self._bootstrap_question_choices(correct_id=2)
        QuestionService.rate_question(2, {
            "difficulty": 2,
            "quality": 4
        }, author)
        self.assertTrue(
            QuestionService.rate_question(2, {"difficulty": 4}, author))

        user_rating = QuestionRating.objects.all()
        self.assertEqual(len(user_rating), 1)
        self.assertEqual(user_rating.first().quality, 4.0)
        self.assertEqual(user_rating.first().difficulty, 4.0)

        answered_question = Question.objects.get(pk=1).toJSON()
        self.assertEqual(answered_question["difficultyCount"], 1)
        self.assertEqual(answered_question["difficulty"], 4.0)
Beispiel #26
0
def search(request):
    if request.method != 'POST':
        return JsonResponse({
            "error": "Must use POST to this endpoint"
        }, status=405)

    search = SearchService.SearchService()
    post_request = loads(request.body)
    sort_field = post_request.get("sortField", None)
    filter_field = post_request.get("filterField", None)
    filter_topics = post_request.get("filterTopics", None)
    query = post_request.get("query", None)
    sort_order = post_request.get("sortOrder", None)
    page = post_request.get("page", None)

    if sort_field is None and filter_field is None and query is None:
        found_questions = QuestionService.allQuestions()
        return page_response(found_questions, page)

    if sort_field is not None:
        search.addSort(sort_field, sort_order)

    if filter_field is not None:
        search.addFilter(filter_field)

    if filter_topics is not None:
        search.addTopicFilter(filter_topics)

    if query is not None:
        search.textSearch(query)

    try:
        search_result = search.execute()
        return page_response(search_result, page)
    except TypeError:
        all_questions = QuestionService.allQuestions()
        return page_response(all_questions, page)
Beispiel #27
0
    def test_answer_question_different_difficulties(self):
        """ Test for checking that difficulty influences competency scores """
        author_course = self._bootstrap_courses(1)
        author_user = self._bootstrap_user(1)
        responder_user = self._bootstrap_user(2)
        responder = CourseUser.objects.create(user=responder_user,
                                              course=author_course)
        author = CourseUser.objects.create(user=author_user,
                                           course=author_course)
        self._bootstrap_topics(author_course)
        topic_selected = Topic.objects.all().filter(id__in=[1])
        self._bootstrap_questions_same_topics(author, topic_selected, 20)

        for question in Question.objects.all():
            question.difficulty = 10
            question.save()

        topic_selected = Topic.objects.all().filter(id__in=[2])
        self._bootstrap_questions_same_topics(author, topic_selected, 20)
        self._bootstrap_question_choices(correct_id=2)

        starting_point = 20 * 4

        QuestionService.respond_to_question(2, author)
        QuestionService.respond_to_question(2 + starting_point, responder)

        for i in range(1, 20):
            offset = 4 * i
            author_old_competency = Competency.objects.get(
                user=author).competency
            responder_old_competency = Competency.objects.get(
                user=responder).competency

            QuestionService.respond_to_question(2 + offset, author)
            QuestionService.respond_to_question((2 + starting_point) + offset,
                                                responder)

            author_new_competency = Competency.objects.get(
                user=author).competency
            responder_new_competency = Competency.objects.get(
                user=responder).competency

            self.assertTrue(author_old_competency <= author_new_competency)
            self.assertTrue(
                responder_old_competency <= responder_new_competency)
            self.assertTrue(author_new_competency >= responder_new_competency)
Beispiel #28
0
def respond(request):
    if request.method != 'POST':
        return JsonResponse({
            "error": "Must use POST to this endpoint"
        }, status=405)

    post_request = loads(request.body)
    distractor_id = post_request.get("distractorID", None)

    if distractor_id is None:
        return JsonResponse({"error": "Missing integer distractorID in request"}, status=422)
    if QuestionService.respond_to_question(distractor_id, UserService.logged_in_user(request)) is None:
        return JsonResponse({"error": "Invalid distractorID"}, status=422)
    else:
        return HttpResponse(status=204)
Beispiel #29
0
def respond(request):
    if request.method != 'POST':
        return JsonResponse({
            "error": "Must use POST to this endpoint"
        }, status=405)

    post_request = loads(request.body.decode("utf-8"))
    distractor_id = post_request.get("distractorID", None)

    try:
        if distractor_id is None:
            return JsonResponse({"error": "Missing integer distractorID in request"}, status=422)
        if QuestionService.respond_to_question(distractor_id, UserService.logged_in_user(request)) is False:
            return JsonResponse({"error": "Invalid distractorID"}, status=422)
        else:
            return JsonResponse({})
    except ValueError:
        return JsonResponse({"error": "You are not enrolled in the course for this course"}, status=403)
Beispiel #30
0
    def test_answer_alternating_questions_many_topics(self):
        """ answer alternating questions to ensure competency scores bounce accordingly """
        author_course = self._bootstrap_courses(1)
        author_user = self._bootstrap_user(1)
        author = CourseUser.objects.create(user=author_user,
                                           course=author_course)
        self._bootstrap_topics(author_course)
        topic_selected = Topic.objects.all().filter(id__in=[1, 2])
        self._bootstrap_questions_same_topics(author, topic_selected, 20)
        self._bootstrap_question_choices(correct_id=2)

        # Get question wrong
        QuestionService.respond_to_question(2, author)
        for i in range(1, 10):
            offset = (4 * i) + (4 * (i - 1))
            first_old_competency = Competency.objects.all()[0].competency
            second_old_competency = Competency.objects.all()[1].competency
            third_old_competency = Competency.objects.all()[2].competency

            # Get question wrong
            QuestionService.respond_to_question(3 + offset, author)

            first_new_competency = Competency.objects.all()[0].competency
            second_new_competency = Competency.objects.all()[1].competency
            third_new_competency = Competency.objects.all()[2].competency
            self.assertTrue(first_old_competency >= first_new_competency)
            self.assertTrue(second_old_competency >= second_new_competency)
            self.assertTrue(third_old_competency >= third_new_competency)

            QuestionService.respond_to_question(2 + offset, author)

            self.assertTrue(
                first_new_competency <= Competency.objects.all()[0].competency)
            self.assertTrue(
                second_new_competency <= Competency.objects.all()[1].competency
            )
            self.assertTrue(
                third_new_competency <= Competency.objects.all()[2].competency)

        self.assertEqual(QuestionResponse.objects.count(), 19)

        num_topics = combinations(
            QuestionScore.objects.all().first().question.topics.all())
        self.assertEqual(Competency.objects.count(), len(num_topics))