summaryrefslogtreecommitdiff
path: root/yaksh/models.py
diff options
context:
space:
mode:
authorPalaparthy Adityachandra2021-02-08 09:37:18 +0530
committerGitHub2021-02-08 09:37:18 +0530
commit1206e886588b3d7e8dfe5fb88a6891e85c5b73ee (patch)
treeda2620ee519b68cfad42b2169b2a79cbccd3734d /yaksh/models.py
parent7448e1fa32f4e5af14a3af6b9196d6e1983edf55 (diff)
parentfca319fefcd2a0e476415968b18873b0c791a5fe (diff)
downloadonline_test-1206e886588b3d7e8dfe5fb88a6891e85c5b73ee.tar.gz
online_test-1206e886588b3d7e8dfe5fb88a6891e85c5b73ee.tar.bz2
online_test-1206e886588b3d7e8dfe5fb88a6891e85c5b73ee.zip
Merge pull request #814 from adityacp/code_refactors
Code Refactor
Diffstat (limited to 'yaksh/models.py')
-rw-r--r--yaksh/models.py213
1 files changed, 115 insertions, 98 deletions
diff --git a/yaksh/models.py b/yaksh/models.py
index a475493..0f62948 100644
--- a/yaksh/models.py
+++ b/yaksh/models.py
@@ -991,13 +991,13 @@ class Course(models.Model):
return self.rejected.all()
def is_enrolled(self, user):
- return user in self.students.all()
+ return self.students.filter(id=user.id).exists()
def is_creator(self, user):
return self.creator == user
def is_teacher(self, user):
- return True if user in self.teachers.all() else False
+ return self.teachers.filter(id=user.id).exists()
def is_self_enroll(self):
return True if self.enrollment == enrollment_methods[1][0] else False
@@ -1061,7 +1061,7 @@ class Course(models.Model):
return success
def get_only_students(self):
- teachers = list(self.teachers.all().values_list("id", flat=True))
+ teachers = list(self.teachers.values_list("id", flat=True))
teachers.append(self.creator.id)
students = self.students.exclude(id__in=teachers)
return students
@@ -1159,7 +1159,7 @@ class Course(models.Model):
return grade
def get_current_unit(self, user):
- course_status = CourseStatus.objects.filter(course=self, user=user)
+ course_status = CourseStatus.objects.filter(course=self, user_id=user)
if course_status.exists():
return course_status.first().current_unit
@@ -1180,7 +1180,7 @@ class Course(models.Model):
return percentage
def is_student(self, user):
- return user in self.students.all()
+ return self.students.filter(id=user.id).exists()
def create_zip(self, path, static_files):
zip_file_name = string_io()
@@ -1953,6 +1953,12 @@ class QuestionPaper(models.Model):
list(self.random_questions.all())
return len(questions) > 0
+ def get_questions_count(self):
+ que_count = self.fixed_questions.count()
+ for r_set in self.random_questions.all():
+ que_count += r_set.num_questions
+ return que_count
+
def __str__(self):
return "Question Paper for " + self.quiz.description
@@ -1979,58 +1985,6 @@ class QuestionSet(models.Model):
###############################################################################
class AnswerPaperManager(models.Manager):
- def get_all_questions(self, questionpaper_id, attempt_number, course_id,
- status='completed'):
- ''' Return a dict of question id as key and count as value'''
- papers = self.filter(question_paper_id=questionpaper_id,
- course_id=course_id,
- attempt_number=attempt_number, status=status)
- all_questions = list()
- questions = list()
- for paper in papers:
- all_questions += paper.get_questions()
- for question in all_questions:
- questions.append(question.id)
- return Counter(questions)
-
- def get_per_answer_stats(self, questionpaper_id, attempt_number,
- course_id, status='completed'):
- papers = self.filter(question_paper_id=questionpaper_id,
- course_id=course_id,
- attempt_number=attempt_number, status=status)
- questions = Question.objects.filter(
- questions__id__in=papers,
- ).distinct()
-
- stats = {}
- for question in questions:
- answers = Answer.objects.filter(
- answerpaper__id__in=papers, question=question.id
- ).values('answer', 'question__id', 'answerpaper__id')
- question_ans_count = {}
- answerpaper_count = []
- for ans in answers:
- if ans.get('answerpaper__id'):
- if ans.get('answer') not in question_ans_count:
- question_ans_count[ans.get('answer')] = 1
- else:
- question_ans_count[ans.get('answer')] += 1
- answerpaper_count.append(ans.get('answerpaper__id'))
- stats[question] = question_ans_count
- return stats
-
- def get_all_questions_answered(self, questionpaper_id, attempt_number,
- course_id, status='completed'):
- ''' Return a dict of answered question id as key and count as value'''
- papers = self.filter(question_paper_id=questionpaper_id,
- course_id=course_id,
- attempt_number=attempt_number, status=status)
- questions_answered = list()
- for paper in papers:
- for question in filter(None, paper.get_questions_answered()):
- if paper.is_answer_correct(question):
- questions_answered.append(question.id)
- return Counter(questions_answered)
def get_attempt_numbers(self, questionpaper_id, course_id,
status='completed'):
@@ -2063,36 +2017,45 @@ class AnswerPaperManager(models.Manager):
def get_question_statistics(self, questionpaper_id, attempt_number,
course_id, status='completed'):
''' Return dict with question object as key and list as value
- The list contains two value, first the number of times a question
- was answered correctly, and second the number of times a question
- appeared in a quiz'''
+ The list contains four values, first total attempts, second correct
+ attempts, third correct percentage, fourth per test case answers
+ a question
+ '''
question_stats = {}
- questions_answered = self.get_all_questions_answered(questionpaper_id,
- attempt_number,
- course_id)
- questions = self.get_all_questions(questionpaper_id, attempt_number,
- course_id)
- per_answer_stats = self.get_per_answer_stats(
- questionpaper_id, attempt_number, course_id
+ qp = QuestionPaper.objects.get(id=questionpaper_id)
+ all_questions = qp.get_question_bank()
+ que_ids = [que.id for que in all_questions]
+ papers = self.filter(
+ question_paper_id=questionpaper_id, course_id=course_id,
+ attempt_number=attempt_number
+ ).values_list("id", flat=True)
+ answers = Answer.objects.filter(
+ answerpaper__id__in=papers, question_id__in=que_ids
+ ).order_by("id").values(
+ "answerpaper__id", "question_id", "correct", "answer"
)
- all_questions = Question.objects.filter(
- id__in=set(questions),
- active=True
- ).order_by('type')
- for question in all_questions:
- if question.id in questions_answered:
- question_stats[question] = {
- 'answered': [questions_answered[question.id],
- questions[question.id]],
- 'per_answer': per_answer_stats[question],
- }
-
- else:
- question_stats[question] = {
- 'answered': [0, questions[question.id]],
- 'per_answer': per_answer_stats[question],
- }
-
+ def _get_per_tc_data(answers, q_type):
+ tc = []
+ for answer in answers["answer"]:
+ ans = literal_eval(answer) if answer else None
+ tc.extend(ans) if q_type == "mcc" else tc.append(str(ans))
+ return dict(Counter(tc))
+ df = pd.DataFrame(answers)
+ if not df.empty:
+ for question in all_questions:
+ que = df[df["question_id"]==question.id].groupby(
+ "answerpaper__id").tail(1)
+ if not que.empty:
+ total_attempts = que.shape[0]
+ correct_attempts = que[que["correct"]==True].shape[0]
+ per_tc_ans = {}
+ if question.type in ["mcq", "mcc"]:
+ per_tc_ans = _get_per_tc_data(que, question.type)
+ question_stats[question] = (
+ total_attempts, correct_attempts,
+ round((correct_attempts/total_attempts)*100),
+ per_tc_ans
+ )
return question_stats
def _get_answerpapers_for_quiz(self, questionpaper_id, course_id,
@@ -2171,11 +2134,51 @@ class AnswerPaperManager(models.Manager):
best_attempt = 0.0
papers = self.filter(question_paper__quiz_id=quiz.id,
course_id=course_id,
- user=user_id).values("marks_obtained")
- if papers:
- best_attempt = max([marks["marks_obtained"] for marks in papers])
+ user=user_id).order_by("-marks_obtained").values(
+ "marks_obtained")
+ if papers.exists():
+ best_attempt = papers[0]["marks_obtained"]
return best_attempt
+ def get_user_scores(self, question_papers, user, course_id):
+ if not question_papers:
+ return None
+ qp_ids = list(zip(*question_papers))[0]
+ papers = self.filter(
+ course_id=course_id, user_id=user.get("id"),
+ question_paper__id__in=qp_ids
+ ).values("question_paper_id", "marks_obtained")
+ df = pd.DataFrame(papers)
+ user_marks = 0
+ ap_data = None
+ if not df.empty:
+ ap_data = df.groupby("question_paper_id").tail(1)
+ for qp_id, quiz, quiz_marks in question_papers:
+ if ap_data is not None:
+ qp = ap_data['question_paper_id'].to_list()
+ marks = ap_data['marks_obtained'].to_list()
+ if qp_id in qp:
+ idx = qp.index(qp_id)
+ user_marks += marks[idx]
+ user[f"{quiz}-{quiz_marks}-Marks"] = marks[idx]
+ else:
+ user[f"{quiz}-{quiz_marks}-Marks"] = 0
+ else:
+ user[f"{quiz}-{quiz_marks}-Marks"] = 0
+ user.pop("id")
+ user["total_marks"] = user_marks
+
+ def get_questions_attempted(self, answerpaper_ids):
+ answers = Answer.objects.filter(
+ answerpaper__id__in=answerpaper_ids
+ ).values("question_id", "answerpaper__id")
+ df = pd.DataFrame(answers)
+ answerpapers = df.groupby("answerpaper__id")
+ question_attempted = {}
+ for ap in answerpapers:
+ question_attempted[ap[0]] = len(ap[1]["question_id"].unique())
+ return question_attempted
+
###############################################################################
class AnswerPaper(models.Model):
@@ -2249,15 +2252,29 @@ class AnswerPaper(models.Model):
'attempt_number', "course"
)
- def get_per_question_score(self, question_id):
- questions = self.get_questions().values_list('id', flat=True)
- if question_id not in questions:
- return 'NA'
- answer = self.get_latest_answer(question_id)
- if answer:
- return answer.marks
- else:
- return 0
+ def get_per_question_score(self, question_ids):
+ if not question_ids:
+ return None
+ que_ids = list(zip(*question_ids))[1]
+ answers = self.answers.filter(
+ question_id__in=que_ids).values("question_id", "marks")
+ que_data = {}
+ df = pd.DataFrame(answers)
+ ans_data = None
+ if not df.empty:
+ ans_data = df.groupby("question_id").tail(1)
+ for que_summary, que_id in question_ids:
+ if ans_data is not None:
+ ans = ans_data['question_id'].to_list()
+ marks = ans_data['marks'].to_list()
+ if que_id in ans:
+ idx = ans.index(que_id)
+ que_data[que_summary] = marks[idx]
+ else:
+ que_data[que_summary] = 0
+ else:
+ que_data[que_summary] = 0
+ return que_data
def current_question(self):
"""Returns the current active question to display."""
@@ -2420,7 +2437,7 @@ class AnswerPaper(models.Model):
"""
q_a = {}
for question in self.questions.all():
- answers = question.answer_set.filter(answerpaper=self)
+ answers = question.answer_set.filter(answerpaper=self).distinct()
if not answers.exists():
q_a[question] = [None, 0.0]
continue