summaryrefslogtreecommitdiff
path: root/yaksh
diff options
context:
space:
mode:
Diffstat (limited to 'yaksh')
-rw-r--r--yaksh/models.py19
-rw-r--r--yaksh/templates/yaksh/add_question.html45
-rw-r--r--yaksh/test_models.py4
-rw-r--r--yaksh/urls.py2
-rw-r--r--yaksh/views.py127
5 files changed, 89 insertions, 108 deletions
diff --git a/yaksh/models.py b/yaksh/models.py
index dc12707..7fae305 100644
--- a/yaksh/models.py
+++ b/yaksh/models.py
@@ -53,6 +53,7 @@ test_case_types = (
("standardtestcase", "Standard Testcase"),
("stdiobasedtestcase", "StdIO Based Testcase"),
("mcqtestcase", "MCQ Testcase"),
+ ("hooktestcase", "Hook Testcase"),
)
attempts = [(i, i) for i in range(1, 6)]
@@ -1129,10 +1130,11 @@ class AssignmentUpload(models.Model):
################################################################################
class TestCase(models.Model):
question = models.ForeignKey(Question, blank=True, null = True)
+ type = models.CharField(max_length=24, choices=test_case_types, null=True)
class StandardTestCase(TestCase):
- test_case = models.TextField(blank=True)
- weight = models.FloatField(default=0.0)
+ test_case = models.TextField()
+ weight = models.FloatField(default=1.0)
def get_field_value(self):
return {"test_case": self.test_case,
@@ -1145,9 +1147,9 @@ class StandardTestCase(TestCase):
class StdioBasedTestCase(TestCase):
- expected_input = models.TextField(blank=True)
- expected_output = models.TextField()
- weight = models.IntegerField(default=0.0)
+ expected_input = models.CharField(max_length=100, blank=True)
+ expected_output = models.CharField(max_length=100)
+ weight = models.IntegerField(default=1.0)
def get_field_value(self):
return {"expected_output": self.expected_output,
@@ -1161,7 +1163,7 @@ class StdioBasedTestCase(TestCase):
class McqTestCase(TestCase):
- options = models.TextField()
+ options = models.CharField(max_length=100)
correct = models.BooleanField(default=False)
def get_field_value(self):
@@ -1171,3 +1173,8 @@ class McqTestCase(TestCase):
return u'Question: {0} | Correct: {1}'.format(self.question,
self.correct
)
+
+
+class HookTestCase(TestCase):
+ code = models.TextField()
+ weight = models.FloatField(default=1.0)
diff --git a/yaksh/templates/yaksh/add_question.html b/yaksh/templates/yaksh/add_question.html
index e1b05fe..57e5e78 100644
--- a/yaksh/templates/yaksh/add_question.html
+++ b/yaksh/templates/yaksh/add_question.html
@@ -13,20 +13,20 @@
{% block onload %} onload='javascript:textareaformat();' {% endblock %}
{% block content %}
-<form action="" method="post" name=frm onSubmit="return autosubmit();" enctype="multipart/form-data">
+<form action="{{ URL_ROOT }}/exam/manage/addquestion/{{ question.id }}/" method="post" name=frm onSubmit="return autosubmit();" enctype="multipart/form-data">
{% csrf_token %}
<center><table class="table">
- <tr><td>Summary: <td>{{ form.summary }}{{ form.summary.errors }}
- <tr><td> Language: <td> {{form.language}}{{form.language.errors}}
- <tr><td> Type: <td> {{ form.type }}{{form.type.errors}}
- <tr><td>Points:<td><button class="btn-mini" type="button" onClick="increase(frm);">+</button>{{form.points }}<button class="btn-mini" type="button" onClick="decrease(frm);">-</button>{{ form.points.errors }}
+ <tr><td>Summary: <td>{{ qform.summary }}{{ qform.summary.errors }}
+ <tr><td> Language: <td> {{qform.language}}{{qform.language.errors}}
+ <tr><td> Type: <td> {{ qform.type }}{{qform.type.errors}}
+ <tr><td>Points:<td><button class="btn-mini" type="button" onClick="increase(frm);">+</button>{{qform.points }}<button class="btn-mini" type="button" onClick="decrease(frm);">-</button>{{ qform.points.errors }}
<tr><td><strong>Rendered: </strong><td><p id='my'></p>
- <tr><td>Description: <td>{{ form.description}} {{form.description.errors}}
- <tr><td>Tags: <td>{{ form.tags }}
- <tr><td>Snippet: <td>{{ form.snippet }}
- <tr><td>Partial Grading: <td>{{ form.partial_grading }}
- <tr><td> Test Case Type: <td> {{ form.test_case_type }}{{ form.test_case_type.errors }}
- <tr><td> File: <td> {{ upload_form.file_field }}{{ upload_form.file_field.errors }}
+ <tr><td>Description: <td>{{ qform.description}} {{qform.description.errors}}
+ <tr><td>Tags: <td>{{ qform.tags }}
+ <tr><td>Snippet: <td>{{ qform.snippet }}
+ <tr><td>Partial Grading: <td>{{ qform.partial_grading }}
+ <tr><td> Test Case Type: <td> {{ qform.test_case_type }}{{ qform.test_case_type.errors }}
+ <tr><td> File: <td> {{ fileform.file_field }}{{ fileform.file_field.errors }}
{% if uploaded_files %}<br><b>Uploaded files:</b><br>Check on delete to delete files,
extract to extract files and hide to hide files from student(if required)<br>
{% for file in uploaded_files %}
@@ -36,22 +36,29 @@
<input type="checkbox" name="hide" value="{{file.id}}" >{% if file.hide %} show{% else %}
hide{% endif %}</input><br>
<a href="{{file.file.url}}">{{ file.file.name }}</a>
- <br>
{% endfor %}{% endif %}
+ </table></center>
+ {% for formset in formsets %}
<div class="form-group">
- {{ test_case_formset.management_form }}
+ {{ formset.management_form }}
- {% for form in test_case_formset %}
- <div class="link-formset">
- {{ form }}
+ {% for form in formset %}
+ <div class="link-formset well">
+ {{ form.as_p }}
</div>
{% endfor %}
</div>
-
- </table></center>
+ {% endfor %}
+ <p><label for="case_type">Add Test Case:</label> <select id="case_type" name="case_type" onchange="frm.submit()">
+ <option value="" selected="selected">---------</option>
+ <option value="standardtestcase">Standard </option>
+ <option value="stdiobasedtestcase">StdIO </option>
+ <option value="mcqtestcase">MCQ/MCC </option>
+ <option value="hooktestcase">Hook </option>
+ </select></p>
<center>
- <button class="btn" type="submit" name="save_question">Save & Add Testcase</button>
+ <button class="btn" type="submit" name="save_question">Save</button>
<button class="btn" type="button" name="button" onClick='location.replace("{{URL_ROOT}}/exam/manage/questions/");'>Back to Questions</button>
<button class="btn" type="submit" name="delete_files">Delete Selected Files</button>
</center>
diff --git a/yaksh/test_models.py b/yaksh/test_models.py
index 1aeffb6..522da89 100644
--- a/yaksh/test_models.py
+++ b/yaksh/test_models.py
@@ -142,7 +142,7 @@ class QuestionTestCases(unittest.TestCase):
self.upload_test_case.save()
self.user_answer = "demo_answer"
self.test_case_upload_data = [{"test_case": "assert fact(3)==6",
- "weight": 0.0
+ "weight": 1.0
}]
questions_data = [{"snippet": "def fact()", "active": True,
"points": 1.0,
@@ -881,7 +881,7 @@ class TestCaseTestCases(unittest.TestCase):
answer_data = {"user_answer": "demo_answer",
"test_case_data": [
{"test_case": "assert myfunc(12, 13) == 15",
- "weight": 0.0
+ "weight": 1.0
}
]
}
diff --git a/yaksh/urls.py b/yaksh/urls.py
index bb8cf2e..036c6a3 100644
--- a/yaksh/urls.py
+++ b/yaksh/urls.py
@@ -52,7 +52,7 @@ urlpatterns += [
url(r'^view_answerpaper/(?P<questionpaper_id>\d+)/$', views.view_answerpaper, name='view_answerpaper'),
url(r'^manage/$', views.prof_manage, name='manage'),
url(r'^manage/addquestion/$', views.add_question),
- url(r'^manage/addquestion/(?P<question_id>\d+)/$', views.edit_question),
+ url(r'^manage/addquestion/(?P<question_id>\d+)/$', views.add_question),
url(r'^manage/addquiz/(?P<course_id>\d+)/$', views.add_quiz, name='add_quiz'),
url(r'^manage/addquiz/(?P<course_id>\d+)/(?P<quiz_id>\d+)/$', views.add_quiz, name='edit_quiz'),
url(r'^manage/gradeuser/$', views.grade_user),
diff --git a/yaksh/views.py b/yaksh/views.py
index b6cf578..0d77426 100644
--- a/yaksh/views.py
+++ b/yaksh/views.py
@@ -25,7 +25,7 @@ import six
# Local imports.
from yaksh.models import get_model_class, Quiz, Question, QuestionPaper, QuestionSet, Course
from yaksh.models import Profile, Answer, AnswerPaper, User, TestCase, FileUpload,\
- has_profile
+ has_profile, StandardTestCase, McqTestCase, StdioBasedTestCase, HookTestCase
from yaksh.forms import UserRegisterForm, UserLoginForm, QuizForm,\
QuestionForm, RandomQuestionForm,\
QuestionFilterForm, CourseForm, ProfileForm, UploadFileForm,\
@@ -130,62 +130,33 @@ def results_user(request):
@login_required
-def add_question(request):
- """To add a new question in the database.
- Create a new question and store it."""
+def add_question(request, question_id=None):
user = request.user
ci = RequestContext(request)
+ test_case_type = None
- if request.method == "POST" and 'save_question' in request.POST:
- question_form = QuestionForm(request.POST)
- form = FileForm(request.POST, request.FILES)
- if question_form.is_valid():
- new_question = question_form.save(commit=False)
- new_question.user = user
- new_question.save()
- files = request.FILES.getlist('file_field')
- if files:
- for file in files:
- FileUpload.objects.get_or_create(question=new_question, file=file)
- return my_redirect("/exam/manage/addquestion/{0}".format(new_question.id))
- else:
- return my_render_to_response('yaksh/add_question.html',
- {'form': question_form,
- 'upload_form': form},
- context_instance=ci)
+ if question_id is None:
+ question = Question(user=user)
+ question.save()
else:
- question_form = QuestionForm()
- form = FileForm()
- return my_render_to_response('yaksh/add_question.html',
- {'form': question_form,
- 'upload_form': form},
- context_instance=ci)
-
-@login_required
-def edit_question(request, question_id=None):
- """To add a new question in the database.
- Create a new question and store it."""
- user = request.user
- ci = RequestContext(request)
- if not question_id:
- raise Http404('No Question Found')
+ question = Question.objects.get(id=question_id)
- question_instance = Question.objects.get(id=question_id)
if request.method == "POST" and 'delete_files' in request.POST:
remove_files_id = request.POST.getlist('clear')
if remove_files_id:
files = FileUpload.objects.filter(id__in=remove_files_id)
for file in files:
file.remove()
- if request.method == "POST" and 'save_question' in request.POST:
- question_form = QuestionForm(request.POST, instance=question_instance)
- form = FileForm(request.POST, request.FILES)
+
+ if request.method == 'POST':
+ qform = QuestionForm(request.POST, instance=question)
+ fileform = FileForm(request.POST, request.FILES)
files = request.FILES.getlist('file_field')
extract_files_id = request.POST.getlist('extract')
hide_files_id = request.POST.getlist('hide')
if files:
for file in files:
- FileUpload.objects.get_or_create(question=question_instance, file=file)
+ FileUpload.objects.get_or_create(question=question, file=file)
if extract_files_id:
files = FileUpload.objects.filter(id__in=extract_files_id)
for file in files:
@@ -194,47 +165,43 @@ def edit_question(request, question_id=None):
files = FileUpload.objects.filter(id__in=hide_files_id)
for file in files:
file.toggle_hide_status()
- if question_form.is_valid():
- new_question = question_form.save(commit=False)
- test_case_type = question_form.cleaned_data.get('test_case_type')
- test_case_form_class = get_object_form(model=test_case_type, exclude_fields=['question'])
- test_case_model_class = get_model_class(test_case_type)
- TestCaseInlineFormSet = inlineformset_factory(Question, test_case_model_class, form=test_case_form_class, extra=1)
- test_case_formset = TestCaseInlineFormSet(request.POST, request.FILES, instance=new_question)
- if test_case_formset.is_valid():
- new_question.save()
- test_case_formset.save()
- return my_redirect("/exam/manage/addquestion/{0}".format(new_question.id))
+ formsets = []
+ for testcase in TestCase.__subclasses__():
+ formset = inlineformset_factory(Question, testcase, extra=0,
+ fields='__all__')
+ formsets.append(formset(request.POST, request.FILES, instance=question))
+ files = request.FILES.getlist('file_field')
+ uploaded_files = FileUpload.objects.filter(question_id=question.id)
+ if qform.is_valid():
+ question = qform.save(commit=False)
+ question.user = user
+ question.save()
+ for formset in formsets:
+ if formset.is_valid():
+ formset.save()
+ test_case_type = request.POST.get('case_type', None)
else:
- test_case_type = question_form.cleaned_data.get('test_case_type')
- test_case_form_class = get_object_form(model=test_case_type, exclude_fields=['question'])
- test_case_model_class = get_model_class(test_case_type)
- TestCaseInlineFormSet = inlineformset_factory(Question, test_case_model_class, form=test_case_form_class, extra=1)
- test_case_formset = TestCaseInlineFormSet(request.POST, request.FILES, instance=question_instance)
- uploaded_files = FileUpload.objects.filter(question_id=question_instance.id)
- return my_render_to_response('yaksh/add_question.html',
- {'form': question_form,
- 'test_case_formset': test_case_formset,
- 'question_id': question_id,
- 'upload_form': form,
- 'uploaded_files': uploaded_files},
+ context = {'qform': qform, 'fileform': fileform, 'question': question,
+ 'formsets': formsets, 'uploaded_files': uploaded_files}
+ return my_render_to_response("yaksh/add_question.html", context,
context_instance=ci)
- else:
- question_form = QuestionForm(instance=question_instance)
- form = FileForm()
- test_case_type = question_instance.test_case_type
- test_case_form_class = get_object_form(model=test_case_type, exclude_fields=['question'])
- test_case_model_class = get_model_class(test_case_type)
- TestCaseInlineFormSet = inlineformset_factory(Question, test_case_model_class, form=test_case_form_class, extra=1)
- test_case_formset = TestCaseInlineFormSet(instance=question_instance)
- uploaded_files = FileUpload.objects.filter(question_id=question_instance.id)
- return my_render_to_response('yaksh/add_question.html',
- {'form': question_form,
- 'test_case_formset': test_case_formset,
- 'question_id': question_id,
- 'upload_form': form,
- 'uploaded_files': uploaded_files},
- context_instance=ci)
+
+ qform = QuestionForm(instance=question)
+ fileform = FileForm()
+ uploaded_files = FileUpload.objects.filter(question_id=question.id)
+ formsets = []
+ for testcase in TestCase.__subclasses__():
+ if test_case_type == testcase.__name__.lower():
+ formset = inlineformset_factory(Question, testcase, extra=1,
+ fields='__all__')
+ else:
+ formset = inlineformset_factory(Question, testcase, extra=0,
+ fields='__all__')
+ formsets.append(formset(instance=question))
+ context = {'qform': qform, 'fileform': fileform, 'question': question,
+ 'formsets': formsets, 'uploaded_files': uploaded_files}
+ return my_render_to_response("yaksh/add_question.html", context, context_instance=ci)
+
@login_required
def add_quiz(request, course_id, quiz_id=None):