From 81e119899ebc04b53ac9c15c66286c8dbc08726b Mon Sep 17 00:00:00 2001 From: ankitjavalkar Date: Thu, 9 Jul 2015 16:19:24 +0530 Subject: Add Date-Time limits for exams --- testapp/yaksh_app/forms.py | 13 +- testapp/yaksh_app/models.py | 11 +- testapp/yaksh_app/templates/yaksh_app/intro.html | 27 +++- testapp/yaksh_app/views.py | 198 ++++++++++++++++------- 4 files changed, 183 insertions(+), 66 deletions(-) (limited to 'testapp') diff --git a/testapp/yaksh_app/forms.py b/testapp/yaksh_app/forms.py index c0b5cdc..8a909f2 100644 --- a/testapp/yaksh_app/forms.py +++ b/testapp/yaksh_app/forms.py @@ -139,7 +139,10 @@ class QuizForm(forms.Form): self.fields['prerequisite'] = forms.CharField(required=False, widget=forms.Select(choices=quizzes)) - start_date = forms.DateField(initial=datetime.date.today) + start_date = forms.DateField(initial=datetime.date.today(), required=False) + start_time = forms.TimeField(initial=datetime.datetime.now().time(), required=False) + end_date = forms.DateField(initial=datetime.date(2199, 1, 1), required=False) + end_time = forms.TimeField(initial=datetime.time(0, 0, 0, 0), required=False) duration = forms.IntegerField(help_text='Will be taken in minutes') active = forms.BooleanField(required=False) description = forms.CharField(max_length=256, widget=forms.Textarea\ @@ -154,6 +157,9 @@ class QuizForm(forms.Form): def save(self): start_date = self.cleaned_data["start_date"] + start_time = self.cleaned_data["start_time"] + end_date = self.cleaned_data["end_date"] + end_time = self.cleaned_data["end_time"] duration = self.cleaned_data["duration"] active = self.cleaned_data['active'] description = self.cleaned_data["description"] @@ -163,7 +169,10 @@ class QuizForm(forms.Form): attempts_allowed = self.cleaned_data["attempts_allowed"] time_between_attempts = self.cleaned_data["time_between_attempts"] new_quiz = Quiz() - new_quiz.start_date = start_date + new_quiz.start_date_time = datetime.datetime.combine(start_date, + start_time) + new_quiz.end_date_time = datetime.datetime.combine(end_date, + end_time) new_quiz.duration = duration new_quiz.active = active new_quiz.description = description diff --git a/testapp/yaksh_app/models.py b/testapp/yaksh_app/models.py index 9e37ef5..62ac9bc 100644 --- a/testapp/yaksh_app/models.py +++ b/testapp/yaksh_app/models.py @@ -160,7 +160,14 @@ class Quiz(models.Model): """ # The start date of the quiz. - start_date = models.DateField("Date of the quiz") + start_date_time = models.DateTimeField("Start Date and Time of the quiz", + default=datetime.datetime.now(), + null=True) + + # The end date and time of the quiz + end_date_time = models.DateTimeField("End Date and Time of the quiz", + default=datetime.datetime(2199, 1, 1, 0, 0, 0, 0), + null=True) # This is always in minutes. duration = models.IntegerField("Duration of quiz in minutes", default=20) @@ -192,7 +199,7 @@ class Quiz(models.Model): def __unicode__(self): desc = self.description or 'Quiz' - return '%s: on %s for %d minutes' % (desc, self.start_date, + return '%s: on %s for %d minutes' % (desc, self.start_date_time, self.duration) diff --git a/testapp/yaksh_app/templates/yaksh_app/intro.html b/testapp/yaksh_app/templates/yaksh_app/intro.html index 592937a..9c5c14d 100644 --- a/testapp/yaksh_app/templates/yaksh_app/intro.html +++ b/testapp/yaksh_app/templates/yaksh_app/intro.html @@ -5,8 +5,21 @@ {% block formtitle %}Important instructions & rules {% endblock %} {% block content %} - - + {% if enable_quiz_time or disable_quiz_time %} + {% if quiz_expired %} +
Welcome {{user.first_name.title}} {{user.last_name.title}}, to the programming quiz!
This examination system has been developed with the intention of making you @@ -27,8 +40,14 @@
We hope you enjoy taking this exam !!!
- + {% if not quiz_expired %} + + {% endif %} {% endblock content %} diff --git a/testapp/yaksh_app/views.py b/testapp/yaksh_app/views.py index f6666e6..e72919f 100644 --- a/testapp/yaksh_app/views.py +++ b/testapp/yaksh_app/views.py @@ -141,23 +141,20 @@ def quizlist_user(request): user = request.user avail_quizzes = list(QuestionPaper.objects.filter(quiz__active=True)) user_answerpapers = AnswerPaper.objects.filter(user=user) - quizzes_taken = user_answerpapers pre_requisites = [] - context = {} + enabled_quizzes = [] + disabled_quizzes = [] - if 'cannot_attempt' in request.GET: - context['cannot_attempt'] = True + cannot_attempt = True if 'cannot_attempt' in request.GET else False + quizzes_taken = None if user_answerpapers.count() == 0 else user_answerpapers - if user_answerpapers.count() == 0: - context['quizzes'] = avail_quizzes - context['user'] = user - context['quizzes_taken'] = None - return my_render_to_response("yaksh_app/quizzes_user.html", context) + context = {'cannot_attempt': cannot_attempt, + 'quizzes': avail_quizzes, + 'user': user, + 'quizzes_taken': quizzes_taken + } - context['quizzes'] = avail_quizzes - context['user'] = user - context['quizzes_taken'] = quizzes_taken - return my_render_to_response("yaksh_app/quizzes_user.html", context) + return my_render_to_response("exam/quizzes_user.html", context) def intro(request, questionpaper_id): @@ -167,6 +164,12 @@ def intro(request, questionpaper_id): quest_paper = QuestionPaper.objects.get(id=questionpaper_id) attempt_number = quest_paper.quiz.attempts_allowed time_lag = quest_paper.quiz.time_between_attempts + quiz_enable_time = quest_paper.quiz.start_date_time + quiz_disable_time = quest_paper.quiz.end_date_time + + quiz_expired = False if quiz_enable_time <= datetime.datetime.now() \ + <= quiz_disable_time else True + if quest_paper.quiz.prerequisite: try: pre_quest = QuestionPaper.objects.get( @@ -185,27 +188,11 @@ def intro(request, questionpaper_id): attempted_papers = AnswerPaper.objects.filter(question_paper=quest_paper, user=user) already_attempted = attempted_papers.count() - if already_attempted == 0: - context = {'user': user, 'paper_id': questionpaper_id,\ - 'attempt_num': already_attempted + 1} - return my_render_to_response('yaksh_app/intro.html', context, - context_instance=ci) - - if already_attempted == attempt_number: - inprogress, previous_attempt = _check_previous_attempt(attempted_papers, - already_attempted) - if inprogress: - return show_question(request, - previous_attempt.current_question(), - previous_attempt.attempt_number, - previous_attempt.question_paper.id) - else: - return my_redirect("/exam/quizzes") + inprogress, previous_attempt, next_attempt = _check_previous_attempt(attempted_papers, + already_attempted, + attempt_number) - - if already_attempted < attempt_number or attempt_number < 0: - inprogress, previous_attempt = _check_previous_attempt(attempted_papers, - already_attempted) + if previous_attempt: if inprogress: return show_question(request, previous_attempt.current_question(), @@ -213,30 +200,51 @@ def intro(request, questionpaper_id): previous_attempt.question_paper.id) days_after_attempt = (datetime.datetime.today() - \ previous_attempt.start_time).days - if days_after_attempt >= time_lag: - context = {'user': user, 'paper_id': questionpaper_id,\ - 'attempt_num': already_attempted + 1} - return my_render_to_response('yaksh_app/intro.html', context, - context_instance=ci) + + if next_attempt: + if days_after_attempt >= time_lag: + context = {'user': user, + 'paper_id': questionpaper_id, + 'attempt_num': already_attempted + 1, + 'enable_quiz_time': quiz_enable_time, + 'disable_quiz_time': quiz_disable_time, + 'quiz_expired': quiz_expired + } + return my_render_to_response('exam/intro.html', context, + context_instance=ci) else: return my_redirect("/exam/quizzes/") + else: - return my_redirect("/exam/quizzes/") - - -def _check_previous_attempt(attempted_papers, already_attempted): - previous_attempt = attempted_papers[already_attempted-1] - previous_attempt_day = previous_attempt.start_time - today = datetime.datetime.today() - if previous_attempt.status == 'inprogress': - end_time = previous_attempt.end_time - quiz_time = previous_attempt.question_paper.quiz.duration*60 - if quiz_time > (today-previous_attempt_day).seconds: - return True, previous_attempt - else: - return False, previous_attempt + context = {'user': user, + 'paper_id': questionpaper_id, + 'attempt_num': already_attempted + 1, + 'enable_quiz_time': quiz_enable_time, + 'disable_quiz_time': quiz_disable_time, + 'quiz_expired': quiz_expired + } + return my_render_to_response('exam/intro.html', context, + context_instance=ci) + + +def _check_previous_attempt(attempted_papers, already_attempted, attempt_number): + next_attempt = False if already_attempted == attempt_number else True + if already_attempted == 0: + return False, None, next_attempt else: - return False, previous_attempt + previous_attempt = attempted_papers[already_attempted-1] + previous_attempt_day = previous_attempt.start_time + today = datetime.datetime.today() + if previous_attempt.status == 'inprogress': + end_time = previous_attempt.end_time + quiz_time = previous_attempt.question_paper.quiz.duration*60 + if quiz_time > (today-previous_attempt_day).seconds: + return True, previous_attempt, next_attempt + else: + return False, previous_attempt, next_attempt + else: + return False, previous_attempt, next_attempt + def results_user(request): """Show list of Results of Quizzes that is taken by logged-in user.""" @@ -262,6 +270,9 @@ def edit_quiz(request): raise Http404('You are not allowed to view this page!') quiz_list = request.POST.getlist('quizzes') start_date = request.POST.getlist('start_date') + start_time = request.POST.getlist('start_time') + end_date = request.POST.getlist('end_date') + end_time = request.POST.getlist('end_time') duration = request.POST.getlist('duration') active = request.POST.getlist('active') description = request.POST.getlist('description') @@ -271,7 +282,10 @@ def edit_quiz(request): for j, quiz_id in enumerate(quiz_list): quiz = Quiz.objects.get(id=quiz_id) - quiz.start_date = start_date[j] + quiz.start_date_time = datetime.datetime.combine(start_date[j], + start_time[j]) + quiz.end_date_time = datetime.datetime.combine(end_date[j], + end_time[j]) quiz.duration = duration[j] quiz.active = active[j] quiz.description = description[j] @@ -471,7 +485,11 @@ def add_quiz(request, quiz_id=None): return my_redirect("/exam/manage/designquestionpaper") else: d = Quiz.objects.get(id=quiz_id) - d.start_date = form['start_date'].data + d.start_date_time = datetime.datetime.combine(form['start_date'].data, + form['start_time'].data) + d.end_date_time = datetime.datetime.combine(form['end_date'].data, + form['end_time'].data) + d.duration = form['duration'].data d.active = form['active'].data d.description = form['description'].data @@ -496,7 +514,10 @@ def add_quiz(request, quiz_id=None): else: d = Quiz.objects.get(id=quiz_id) form = QuizForm() - form.initial['start_date'] = d.start_date + form.initial['start_date'] = d.start_date_time.date() + form.initial['start_time'] = d.start_date_time.time() + form.initial['end_date'] = d.end_date_time.date() + form.initial['end_time'] = d.end_date_time.time() form.initial['duration'] = d.duration form.initial['description'] = d.description form.initial['active'] = d.active @@ -759,6 +780,65 @@ def user_login(request): def start(request, attempt_num=None, questionpaper_id=None): + # """Check the user cedentials and if any quiz is available, + # start the exam.""" + # user = request.user + # if questionpaper_id is None: + # return my_redirect('/exam/quizzes/') + # try: + # """Right now the app is designed so there is only one active quiz + # at a particular time.""" + # questionpaper = QuestionPaper.objects.get(id=questionpaper_id) + # except QuestionPaper.DoesNotExist: + # msg = 'Quiz not found, please contact your '\ + # 'instructor/administrator. Please login again thereafter.' + # return complete(request, msg, attempt_num, questionpaper_id) + + # # if questionpaper.quiz.start_date_time: + # # quiz_enable_time = questionpaper.quiz.start_date_time + # # else: + # # quiz_enable_time = datetime.datetime.now() + # # if questionpaper.quiz.end_date_time: + # # quiz_disable_time = questionpaper.quiz.end_date_time + # # else: + # # quiz_disable_time = datetime.datetime.now() + # # quiz_enable_time = questionpaper.quiz.start_date_time + # # quiz_disable_time = questionpaper.quiz.end_date_time + + # if not questionpaper.quiz.active: + # reason = 'The quiz has been deactivated!' + # return complete(request, reason, attempt_num, questionpaper_id) + + # if quiz_enable_time <= datetime.datetime.now() <= quiz_disable_time: + # try: + # old_paper = AnswerPaper.objects.get( + # question_paper=questionpaper, user=user, attempt_number=attempt_num) + # q = old_paper.current_question() + # return show_question(request, q, attempt_num, questionpaper_id) + # except AnswerPaper.DoesNotExist: + # ip = request.META['REMOTE_ADDR'] + # key = gen_key(10) + # try: + # profile = user.get_profile() + # except Profile.DoesNotExist: + # msg = 'You do not have a profile and cannot take the quiz!' + # raise Http404(msg) + + # new_paper = questionpaper.make_answerpaper(user, ip, attempt_num) + # # Make user directory. + # user_dir = get_user_dir(user) + # return start(request, attempt_num, questionpaper_id) + # else: + # ci = RequestContext(request) + # quiz_expired = datetime.datetime.now() >= quiz_disable_time + # context = {'user': user, 'paper_id': questionpaper_id,\ + # 'attempt_num': attempt_num, + # 'enable_quiz_time': quiz_enable_time, + # 'disable_quiz_time': quiz_disable_time, + # 'quiz_expired': quiz_expired} + # return my_render_to_response('exam/intro.html', context, + # context_instance=ci) + """Check the user cedentials and if any quiz is available, start the exam.""" user = request.user @@ -792,7 +872,6 @@ def start(request, attempt_num=None, questionpaper_id=None): user_dir = get_user_dir(user) return start(request, attempt_num, questionpaper_id) - def get_questions(paper): ''' Takes answerpaper as an argument. Returns the total questions as @@ -1230,7 +1309,10 @@ def show_all_quiz(request): for j in data: d = Quiz.objects.get(id=j) form = QuizForm() - form.initial['start_date'] = d.start_date + form.initial['start_date'] = d.start_date_time.date() + form.initial['start_time'] = d.start_date_time.time() + form.initial['end_date'] = d.end_date_time.date() + form.initial['end_time'] = d.end_date_time.time() form.initial['duration'] = d.duration form.initial['active'] = d.active form.initial['description'] = d.description -- cgit From ba1f02c1129859fe32577e3da67bee6374ed5190 Mon Sep 17 00:00:00 2001 From: ankitjavalkar Date: Tue, 25 Aug 2015 15:49:30 +0530 Subject: Add Date-Time expiry notification on front page --- .../templates/yaksh_app/quizzes_user.html | 12 +++- testapp/yaksh_app/views.py | 80 ++++------------------ 2 files changed, 24 insertions(+), 68 deletions(-) (limited to 'testapp') diff --git a/testapp/yaksh_app/templates/yaksh_app/quizzes_user.html b/testapp/yaksh_app/templates/yaksh_app/quizzes_user.html index 19618ec..94f9d0f 100644 --- a/testapp/yaksh_app/templates/yaksh_app/quizzes_user.html +++ b/testapp/yaksh_app/templates/yaksh_app/quizzes_user.html @@ -26,9 +26,15 @@=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, -CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, -g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, -text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, -setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= -h[3];l=0;for(m=h.length;l =0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== -"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, -h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l ";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& -q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; -if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); -(function(){var g=s.createElement("div");g.innerHTML="";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: -function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q =0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f
0)for(var j=d;j 0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= -{},i;if(f&&a.length){e=0;for(var o=a.length;e -1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== -"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", -d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? -a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== -1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"+d+">"},F={option:[1,""],legend:[1,""],thead:[1," ","
"],tr:[2,"","
"],td:[3,""],col:[2,"
"," "],area:[1,""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
"," ",""];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= -c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, -wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, -prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, -this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); -return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, -""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); -return this}else{e=0;for(var j=d.length;e 0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", -""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===" "&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= -c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? -c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= -function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= -Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, -"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= -a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= -a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/ + diff --git a/testapp/yaksh_app/templates/yaksh_app/manual_questionpaper.html b/testapp/yaksh_app/templates/yaksh_app/manual_questionpaper.html index 66c83ed..9e2a082 100644 --- a/testapp/yaksh_app/templates/yaksh_app/manual_questionpaper.html +++ b/testapp/yaksh_app/templates/yaksh_app/manual_questionpaper.html @@ -14,8 +14,7 @@ select {% endblock %} {% block script %} - - + {% endblock %} diff --git a/testapp/yaksh_app/templates/yaksh_app/question.html b/testapp/yaksh_app/templates/yaksh_app/question.html index 8b43fff..594693c 100644 --- a/testapp/yaksh_app/templates/yaksh_app/question.html +++ b/testapp/yaksh_app/templates/yaksh_app/question.html @@ -10,7 +10,7 @@ {% endblock %} {% block script %} - + diff --git a/testapp/yaksh_app/views.py b/testapp/yaksh_app/views.py index c7b97d1..e6aabc4 100644 --- a/testapp/yaksh_app/views.py +++ b/testapp/yaksh_app/views.py @@ -162,7 +162,7 @@ def quizlist_user(request): 'unexpired_quizzes': unexpired_quizzes } - return my_render_to_response("exam/quizzes_user.html", context) + return my_render_to_response("yaksh_app/quizzes_user.html", context) def intro(request, questionpaper_id): @@ -218,7 +218,7 @@ def intro(request, questionpaper_id): 'disable_quiz_time': quiz_disable_time, 'quiz_expired': quiz_expired } - return my_render_to_response('exam/intro.html', context, + return my_render_to_response('yaksh_app/intro.html', context, context_instance=ci) else: return my_redirect("/exam/quizzes/") @@ -231,7 +231,7 @@ def intro(request, questionpaper_id): 'disable_quiz_time': quiz_disable_time, 'quiz_expired': quiz_expired } - return my_render_to_response('exam/intro.html', context, + return my_render_to_response('yaksh_app/intro.html', context, context_instance=ci) @@ -1302,7 +1302,7 @@ def ajax_questions_filter(request): questions = list(Question.objects.filter(**filter_dict)) - return my_render_to_response('exam/ajax_question_filter.html', + return my_render_to_response('yaksh_app/ajax_question_filter.html', {'questions': questions}) @@ -1324,7 +1324,7 @@ def show_all_questions(request): 'questions': questions, 'form': form } - return my_render_to_response('exam/showquestions.html', context, + return my_render_to_response('yaksh_app/showquestions.html', context, context_instance=ci) else: for i in data: @@ -1336,7 +1336,7 @@ def show_all_questions(request): 'questions': questions, 'form': form } - return my_render_to_response('exam/showquestions.html', context, + return my_render_to_response('yaksh_app/showquestions.html', context, context_instance=ci) elif request.method == 'POST' and request.POST.get('edit') == 'edit': data = request.POST.getlist('question') @@ -1381,7 +1381,7 @@ def show_all_questions(request): 'questions': questions, 'form': form } - return my_render_to_response('exam/showquestions.html', context, + return my_render_to_response('yaksh_app/showquestions.html', context, context_instance=ci) -- cgit From 32cde26f9807a29eb1fae0833e353212d43d7802 Mon Sep 17 00:00:00 2001 From: ankitjavalkar Date: Fri, 11 Sep 2015 12:35:09 +0530 Subject: Change app name to 'yaksh' --- testapp/templates/demo_urls.py | 2 +- testapp/tests/test_bash_evaluation.py | 4 +- testapp/tests/test_c_cpp_evaluation.py | 4 +- testapp/tests/test_code_evaluation.py | 8 +- testapp/tests/test_java_evaluation.py | 4 +- testapp/tests/test_python_evaluation.py | 4 +- testapp/tests/test_scilab_evaluation.py | 4 +- testapp/urls.py | 2 +- testapp/yaksh/__init__.py | 0 testapp/yaksh/admin.py | 6 + testapp/yaksh/bash_code_evaluator.py | 122 + testapp/yaksh/bash_files/sample.args | 2 + testapp/yaksh/bash_files/sample.sh | 2 + testapp/yaksh/c_cpp_files/main.cpp | 32 + testapp/yaksh/c_cpp_files/main2.c | 30 + testapp/yaksh/c_cpp_files/main_array_check.cpp | 34 + testapp/yaksh/c_cpp_files/main_array_check_all.cpp | 34 + testapp/yaksh/c_cpp_files/main_array_sum.cpp | 34 + testapp/yaksh/c_cpp_files/main_blackJack.cpp | 41 + testapp/yaksh/c_cpp_files/main_check_digit.cpp | 32 + testapp/yaksh/c_cpp_files/main_count667.cpp | 42 + testapp/yaksh/c_cpp_files/main_count7.cpp | 42 + testapp/yaksh/c_cpp_files/main_fact.cpp | 32 + testapp/yaksh/c_cpp_files/main_greatest.cpp | 44 + testapp/yaksh/c_cpp_files/main_hello_name.c | 29 + testapp/yaksh/c_cpp_files/main_lessThan9.cpp | 38 + testapp/yaksh/c_cpp_files/main_mean.cpp | 38 + testapp/yaksh/c_cpp_files/main_palindrome.cpp | 32 + testapp/yaksh/c_cpp_files/main_roundTo10.cpp | 41 + testapp/yaksh/c_cpp_files/main_specialSum.cpp | 41 + testapp/yaksh/c_cpp_files/main_within.cpp | 38 + testapp/yaksh/code_evaluator.py | 206 ++ testapp/yaksh/code_server.py | 162 ++ testapp/yaksh/cpp_code_evaluator.py | 125 ++ testapp/yaksh/docs/sample.args | 2 + testapp/yaksh/docs/sample.sh | 2 + testapp/yaksh/docs/sample_questions.py | 84 + testapp/yaksh/docs/sample_questions.xml | 43 + testapp/yaksh/forms.py | 267 +++ testapp/yaksh/java_code_evaluator.py | 128 ++ testapp/yaksh/java_files/main_array_sum.java | 36 + testapp/yaksh/java_files/main_fact.java | 29 + testapp/yaksh/java_files/main_great.java | 39 + testapp/yaksh/java_files/main_hello_name.java | 29 + testapp/yaksh/java_files/main_lastDigit.java | 36 + testapp/yaksh/java_files/main_moreThan30.java | 36 + testapp/yaksh/java_files/main_palindrome.java | 29 + testapp/yaksh/java_files/main_square.java | 32 + testapp/yaksh/language_registry.py | 36 + testapp/yaksh/management/__init__.py | 0 testapp/yaksh/management/commands/__init__.py | 0 testapp/yaksh/management/commands/add_group.py | 33 + .../yaksh/management/commands/dump_user_data.py | 98 + testapp/yaksh/management/commands/load_exam.py | 57 + .../management/commands/load_questions_xml.py | 73 + testapp/yaksh/management/commands/results2csv.py | 69 + testapp/yaksh/models.py | 471 ++++ testapp/yaksh/output/README.txt | 4 + testapp/yaksh/python_code_evaluator.py | 61 + testapp/yaksh/scilab_code_evaluator.py | 105 + testapp/yaksh/scilab_files/test_add.sce | 29 + testapp/yaksh/settings.py | 29 + testapp/yaksh/static/yaksh_app/css/autotaggit.css | 48 + testapp/yaksh/static/yaksh_app/css/base.css | 2327 ++++++++++++++++++++ testapp/yaksh/static/yaksh_app/css/gradeuser.css | 52 + testapp/yaksh/static/yaksh_app/css/login.css | 10 + testapp/yaksh/static/yaksh_app/css/monitor.css | 11 + testapp/yaksh/static/yaksh_app/css/question.css | 42 + .../yaksh_app/css/question_paper_creation.css | 119 + .../yaksh/static/yaksh_app/css/question_quiz.css | 24 + testapp/yaksh/static/yaksh_app/css/showusers.css | 5 + testapp/yaksh/static/yaksh_app/js/add_question.js | 205 ++ .../yaksh/static/yaksh_app/js/add_questionpaper.js | 25 + testapp/yaksh/static/yaksh_app/js/add_quiz.js | 11 + .../yaksh/static/yaksh_app/js/bootstrap-modal.js | 260 +++ .../yaksh/static/yaksh_app/js/bootstrap-tabs.js | 80 + testapp/yaksh/static/yaksh_app/js/edit_question.js | 278 +++ testapp/yaksh/static/yaksh_app/js/edit_quiz.js | 9 + .../yaksh/static/yaksh_app/js/jquery-1.4.2.min.js | 154 ++ testapp/yaksh/static/yaksh_app/js/min.js | 19 + testapp/yaksh/static/yaksh_app/js/question.js | 152 ++ .../yaksh/static/yaksh_app/js/question_filter.js | 47 + .../static/yaksh_app/js/question_paper_creation.js | 237 ++ testapp/yaksh/static/yaksh_app/js/show_question.js | 39 + testapp/yaksh/static/yaksh_app/js/show_quiz.js | 41 + testapp/yaksh/templates/404.html | 5 + testapp/yaksh/templates/500.html | 7 + testapp/yaksh/templates/base.html | 46 + testapp/yaksh/templates/manage.html | 88 + testapp/yaksh/templates/user.html | 58 + testapp/yaksh/templates/yaksh/add_question.html | 50 + .../yaksh/templates/yaksh/add_questionpaper.html | 27 + testapp/yaksh/templates/yaksh/add_quiz.html | 25 + testapp/yaksh/templates/yaksh/ajax_marks.html | 4 + .../templates/yaksh/ajax_question_filter.html | 15 + testapp/yaksh/templates/yaksh/ajax_questions.html | 31 + .../templates/yaksh/automatic_questionpaper.html | 87 + testapp/yaksh/templates/yaksh/complete.html | 33 + .../templates/yaksh/design_questionpaper.html | 182 ++ testapp/yaksh/templates/yaksh/edit_question.html | 61 + testapp/yaksh/templates/yaksh/edit_quiz.html | 39 + .../yaksh/templates/yaksh/editquestionpaper.html | 21 + testapp/yaksh/templates/yaksh/grade_user.html | 94 + testapp/yaksh/templates/yaksh/intro.html | 53 + testapp/yaksh/templates/yaksh/login.html | 22 + .../templates/yaksh/manual_questionpaper.html | 79 + testapp/yaksh/templates/yaksh/monitor.html | 69 + testapp/yaksh/templates/yaksh/question.html | 203 ++ testapp/yaksh/templates/yaksh/quit.html | 35 + testapp/yaksh/templates/yaksh/quizlist.html | 24 + testapp/yaksh/templates/yaksh/quizzes_user.html | 87 + testapp/yaksh/templates/yaksh/register.html | 20 + testapp/yaksh/templates/yaksh/results_user.html | 28 + testapp/yaksh/templates/yaksh/show_quiz.html | 33 + .../yaksh/templates/yaksh/showquestionpapers.html | 23 + testapp/yaksh/templates/yaksh/showquestions.html | 44 + testapp/yaksh/templates/yaksh/showusers.html | 26 + testapp/yaksh/templates/yaksh/user_data.html | 80 + testapp/yaksh/tests.py | 345 +++ testapp/yaksh/urls.py | 52 + testapp/yaksh/views.py | 1502 +++++++++++++ testapp/yaksh/xmlrpc_clients.py | 80 + testapp/yaksh_app/__init__.py | 0 testapp/yaksh_app/admin.py | 6 - testapp/yaksh_app/bash_code_evaluator.py | 122 - testapp/yaksh_app/bash_files/sample.args | 2 - testapp/yaksh_app/bash_files/sample.sh | 2 - testapp/yaksh_app/c_cpp_files/main.cpp | 32 - testapp/yaksh_app/c_cpp_files/main2.c | 30 - testapp/yaksh_app/c_cpp_files/main_array_check.cpp | 34 - .../yaksh_app/c_cpp_files/main_array_check_all.cpp | 34 - testapp/yaksh_app/c_cpp_files/main_array_sum.cpp | 34 - testapp/yaksh_app/c_cpp_files/main_blackJack.cpp | 41 - testapp/yaksh_app/c_cpp_files/main_check_digit.cpp | 32 - testapp/yaksh_app/c_cpp_files/main_count667.cpp | 42 - testapp/yaksh_app/c_cpp_files/main_count7.cpp | 42 - testapp/yaksh_app/c_cpp_files/main_fact.cpp | 32 - testapp/yaksh_app/c_cpp_files/main_greatest.cpp | 44 - testapp/yaksh_app/c_cpp_files/main_hello_name.c | 29 - testapp/yaksh_app/c_cpp_files/main_lessThan9.cpp | 38 - testapp/yaksh_app/c_cpp_files/main_mean.cpp | 38 - testapp/yaksh_app/c_cpp_files/main_palindrome.cpp | 32 - testapp/yaksh_app/c_cpp_files/main_roundTo10.cpp | 41 - testapp/yaksh_app/c_cpp_files/main_specialSum.cpp | 41 - testapp/yaksh_app/c_cpp_files/main_within.cpp | 38 - testapp/yaksh_app/code_evaluator.py | 206 -- testapp/yaksh_app/code_server.py | 162 -- testapp/yaksh_app/cpp_code_evaluator.py | 125 -- testapp/yaksh_app/docs/sample.args | 2 - testapp/yaksh_app/docs/sample.sh | 2 - testapp/yaksh_app/docs/sample_questions.py | 84 - testapp/yaksh_app/docs/sample_questions.xml | 43 - testapp/yaksh_app/forms.py | 267 --- testapp/yaksh_app/java_code_evaluator.py | 128 -- testapp/yaksh_app/java_files/main_array_sum.java | 36 - testapp/yaksh_app/java_files/main_fact.java | 29 - testapp/yaksh_app/java_files/main_great.java | 39 - testapp/yaksh_app/java_files/main_hello_name.java | 29 - testapp/yaksh_app/java_files/main_lastDigit.java | 36 - testapp/yaksh_app/java_files/main_moreThan30.java | 36 - testapp/yaksh_app/java_files/main_palindrome.java | 29 - testapp/yaksh_app/java_files/main_square.java | 32 - testapp/yaksh_app/language_registry.py | 36 - testapp/yaksh_app/management/__init__.py | 0 testapp/yaksh_app/management/commands/__init__.py | 0 testapp/yaksh_app/management/commands/add_group.py | 33 - .../management/commands/dump_user_data.py | 98 - testapp/yaksh_app/management/commands/load_exam.py | 57 - .../management/commands/load_questions_xml.py | 73 - .../yaksh_app/management/commands/results2csv.py | 69 - testapp/yaksh_app/models.py | 471 ---- testapp/yaksh_app/output/README.txt | 4 - testapp/yaksh_app/python_code_evaluator.py | 61 - testapp/yaksh_app/scilab_code_evaluator.py | 105 - testapp/yaksh_app/scilab_files/test_add.sce | 29 - testapp/yaksh_app/settings.py | 29 - .../yaksh_app/static/yaksh_app/css/autotaggit.css | 48 - testapp/yaksh_app/static/yaksh_app/css/base.css | 2327 -------------------- .../yaksh_app/static/yaksh_app/css/gradeuser.css | 52 - testapp/yaksh_app/static/yaksh_app/css/login.css | 10 - testapp/yaksh_app/static/yaksh_app/css/monitor.css | 11 - .../yaksh_app/static/yaksh_app/css/question.css | 42 - .../yaksh_app/css/question_paper_creation.css | 119 - .../static/yaksh_app/css/question_quiz.css | 24 - .../yaksh_app/static/yaksh_app/css/showusers.css | 5 - .../yaksh_app/static/yaksh_app/js/add_question.js | 205 -- .../static/yaksh_app/js/add_questionpaper.js | 25 - testapp/yaksh_app/static/yaksh_app/js/add_quiz.js | 11 - .../static/yaksh_app/js/bootstrap-modal.js | 260 --- .../static/yaksh_app/js/bootstrap-tabs.js | 80 - .../yaksh_app/static/yaksh_app/js/edit_question.js | 278 --- testapp/yaksh_app/static/yaksh_app/js/edit_quiz.js | 9 - .../static/yaksh_app/js/jquery-1.4.2.min.js | 154 -- testapp/yaksh_app/static/yaksh_app/js/min.js | 19 - testapp/yaksh_app/static/yaksh_app/js/question.js | 152 -- .../static/yaksh_app/js/question_filter.js | 47 - .../static/yaksh_app/js/question_paper_creation.js | 237 -- .../yaksh_app/static/yaksh_app/js/show_question.js | 39 - testapp/yaksh_app/static/yaksh_app/js/show_quiz.js | 41 - testapp/yaksh_app/templates/404.html | 5 - testapp/yaksh_app/templates/500.html | 7 - testapp/yaksh_app/templates/base.html | 46 - testapp/yaksh_app/templates/manage.html | 88 - testapp/yaksh_app/templates/user.html | 58 - .../templates/yaksh_app/add_question.html | 50 - .../templates/yaksh_app/add_questionpaper.html | 27 - .../yaksh_app/templates/yaksh_app/add_quiz.html | 25 - .../yaksh_app/templates/yaksh_app/ajax_marks.html | 4 - .../templates/yaksh_app/ajax_question_filter.html | 15 - .../templates/yaksh_app/ajax_questions.html | 31 - .../yaksh_app/automatic_questionpaper.html | 87 - .../yaksh_app/templates/yaksh_app/complete.html | 33 - .../templates/yaksh_app/design_questionpaper.html | 182 -- .../templates/yaksh_app/edit_question.html | 61 - .../yaksh_app/templates/yaksh_app/edit_quiz.html | 39 - .../templates/yaksh_app/editquestionpaper.html | 21 - .../yaksh_app/templates/yaksh_app/grade_user.html | 94 - testapp/yaksh_app/templates/yaksh_app/intro.html | 53 - testapp/yaksh_app/templates/yaksh_app/login.html | 22 - .../templates/yaksh_app/manual_questionpaper.html | 79 - testapp/yaksh_app/templates/yaksh_app/monitor.html | 69 - .../yaksh_app/templates/yaksh_app/question.html | 203 -- testapp/yaksh_app/templates/yaksh_app/quit.html | 35 - .../yaksh_app/templates/yaksh_app/quizlist.html | 24 - .../templates/yaksh_app/quizzes_user.html | 87 - .../yaksh_app/templates/yaksh_app/register.html | 20 - .../templates/yaksh_app/results_user.html | 28 - .../yaksh_app/templates/yaksh_app/show_quiz.html | 33 - .../templates/yaksh_app/showquestionpapers.html | 23 - .../templates/yaksh_app/showquestions.html | 44 - .../yaksh_app/templates/yaksh_app/showusers.html | 26 - .../yaksh_app/templates/yaksh_app/user_data.html | 80 - testapp/yaksh_app/tests.py | 345 --- testapp/yaksh_app/urls.py | 52 - testapp/yaksh_app/views.py | 1502 ------------- testapp/yaksh_app/xmlrpc_clients.py | 80 - 236 files changed, 11025 insertions(+), 11025 deletions(-) create mode 100644 testapp/yaksh/__init__.py create mode 100644 testapp/yaksh/admin.py create mode 100644 testapp/yaksh/bash_code_evaluator.py create mode 100644 testapp/yaksh/bash_files/sample.args create mode 100755 testapp/yaksh/bash_files/sample.sh create mode 100755 testapp/yaksh/c_cpp_files/main.cpp create mode 100755 testapp/yaksh/c_cpp_files/main2.c create mode 100755 testapp/yaksh/c_cpp_files/main_array_check.cpp create mode 100755 testapp/yaksh/c_cpp_files/main_array_check_all.cpp create mode 100755 testapp/yaksh/c_cpp_files/main_array_sum.cpp create mode 100755 testapp/yaksh/c_cpp_files/main_blackJack.cpp create mode 100755 testapp/yaksh/c_cpp_files/main_check_digit.cpp create mode 100755 testapp/yaksh/c_cpp_files/main_count667.cpp create mode 100755 testapp/yaksh/c_cpp_files/main_count7.cpp create mode 100755 testapp/yaksh/c_cpp_files/main_fact.cpp create mode 100755 testapp/yaksh/c_cpp_files/main_greatest.cpp create mode 100755 testapp/yaksh/c_cpp_files/main_hello_name.c create mode 100755 testapp/yaksh/c_cpp_files/main_lessThan9.cpp create mode 100755 testapp/yaksh/c_cpp_files/main_mean.cpp create mode 100755 testapp/yaksh/c_cpp_files/main_palindrome.cpp create mode 100755 testapp/yaksh/c_cpp_files/main_roundTo10.cpp create mode 100755 testapp/yaksh/c_cpp_files/main_specialSum.cpp create mode 100755 testapp/yaksh/c_cpp_files/main_within.cpp create mode 100644 testapp/yaksh/code_evaluator.py create mode 100755 testapp/yaksh/code_server.py create mode 100644 testapp/yaksh/cpp_code_evaluator.py create mode 100644 testapp/yaksh/docs/sample.args create mode 100755 testapp/yaksh/docs/sample.sh create mode 100644 testapp/yaksh/docs/sample_questions.py create mode 100644 testapp/yaksh/docs/sample_questions.xml create mode 100644 testapp/yaksh/forms.py create mode 100644 testapp/yaksh/java_code_evaluator.py create mode 100644 testapp/yaksh/java_files/main_array_sum.java create mode 100644 testapp/yaksh/java_files/main_fact.java create mode 100644 testapp/yaksh/java_files/main_great.java create mode 100644 testapp/yaksh/java_files/main_hello_name.java create mode 100644 testapp/yaksh/java_files/main_lastDigit.java create mode 100644 testapp/yaksh/java_files/main_moreThan30.java create mode 100644 testapp/yaksh/java_files/main_palindrome.java create mode 100644 testapp/yaksh/java_files/main_square.java create mode 100644 testapp/yaksh/language_registry.py create mode 100644 testapp/yaksh/management/__init__.py create mode 100644 testapp/yaksh/management/commands/__init__.py create mode 100644 testapp/yaksh/management/commands/add_group.py create mode 100644 testapp/yaksh/management/commands/dump_user_data.py create mode 100644 testapp/yaksh/management/commands/load_exam.py create mode 100644 testapp/yaksh/management/commands/load_questions_xml.py create mode 100644 testapp/yaksh/management/commands/results2csv.py create mode 100644 testapp/yaksh/models.py create mode 100644 testapp/yaksh/output/README.txt create mode 100644 testapp/yaksh/python_code_evaluator.py create mode 100644 testapp/yaksh/scilab_code_evaluator.py create mode 100644 testapp/yaksh/scilab_files/test_add.sce create mode 100644 testapp/yaksh/settings.py create mode 100644 testapp/yaksh/static/yaksh_app/css/autotaggit.css create mode 100644 testapp/yaksh/static/yaksh_app/css/base.css create mode 100644 testapp/yaksh/static/yaksh_app/css/gradeuser.css create mode 100644 testapp/yaksh/static/yaksh_app/css/login.css create mode 100644 testapp/yaksh/static/yaksh_app/css/monitor.css create mode 100644 testapp/yaksh/static/yaksh_app/css/question.css create mode 100644 testapp/yaksh/static/yaksh_app/css/question_paper_creation.css create mode 100644 testapp/yaksh/static/yaksh_app/css/question_quiz.css create mode 100644 testapp/yaksh/static/yaksh_app/css/showusers.css create mode 100644 testapp/yaksh/static/yaksh_app/js/add_question.js create mode 100644 testapp/yaksh/static/yaksh_app/js/add_questionpaper.js create mode 100644 testapp/yaksh/static/yaksh_app/js/add_quiz.js create mode 100644 testapp/yaksh/static/yaksh_app/js/bootstrap-modal.js create mode 100644 testapp/yaksh/static/yaksh_app/js/bootstrap-tabs.js create mode 100644 testapp/yaksh/static/yaksh_app/js/edit_question.js create mode 100644 testapp/yaksh/static/yaksh_app/js/edit_quiz.js create mode 100644 testapp/yaksh/static/yaksh_app/js/jquery-1.4.2.min.js create mode 100644 testapp/yaksh/static/yaksh_app/js/min.js create mode 100644 testapp/yaksh/static/yaksh_app/js/question.js create mode 100644 testapp/yaksh/static/yaksh_app/js/question_filter.js create mode 100644 testapp/yaksh/static/yaksh_app/js/question_paper_creation.js create mode 100644 testapp/yaksh/static/yaksh_app/js/show_question.js create mode 100644 testapp/yaksh/static/yaksh_app/js/show_quiz.js create mode 100644 testapp/yaksh/templates/404.html create mode 100644 testapp/yaksh/templates/500.html create mode 100644 testapp/yaksh/templates/base.html create mode 100644 testapp/yaksh/templates/manage.html create mode 100644 testapp/yaksh/templates/user.html create mode 100644 testapp/yaksh/templates/yaksh/add_question.html create mode 100644 testapp/yaksh/templates/yaksh/add_questionpaper.html create mode 100644 testapp/yaksh/templates/yaksh/add_quiz.html create mode 100644 testapp/yaksh/templates/yaksh/ajax_marks.html create mode 100644 testapp/yaksh/templates/yaksh/ajax_question_filter.html create mode 100644 testapp/yaksh/templates/yaksh/ajax_questions.html create mode 100644 testapp/yaksh/templates/yaksh/automatic_questionpaper.html create mode 100644 testapp/yaksh/templates/yaksh/complete.html create mode 100644 testapp/yaksh/templates/yaksh/design_questionpaper.html create mode 100644 testapp/yaksh/templates/yaksh/edit_question.html create mode 100644 testapp/yaksh/templates/yaksh/edit_quiz.html create mode 100644 testapp/yaksh/templates/yaksh/editquestionpaper.html create mode 100644 testapp/yaksh/templates/yaksh/grade_user.html create mode 100644 testapp/yaksh/templates/yaksh/intro.html create mode 100644 testapp/yaksh/templates/yaksh/login.html create mode 100644 testapp/yaksh/templates/yaksh/manual_questionpaper.html create mode 100644 testapp/yaksh/templates/yaksh/monitor.html create mode 100644 testapp/yaksh/templates/yaksh/question.html create mode 100644 testapp/yaksh/templates/yaksh/quit.html create mode 100644 testapp/yaksh/templates/yaksh/quizlist.html create mode 100644 testapp/yaksh/templates/yaksh/quizzes_user.html create mode 100644 testapp/yaksh/templates/yaksh/register.html create mode 100644 testapp/yaksh/templates/yaksh/results_user.html create mode 100644 testapp/yaksh/templates/yaksh/show_quiz.html create mode 100644 testapp/yaksh/templates/yaksh/showquestionpapers.html create mode 100644 testapp/yaksh/templates/yaksh/showquestions.html create mode 100644 testapp/yaksh/templates/yaksh/showusers.html create mode 100644 testapp/yaksh/templates/yaksh/user_data.html create mode 100644 testapp/yaksh/tests.py create mode 100644 testapp/yaksh/urls.py create mode 100644 testapp/yaksh/views.py create mode 100644 testapp/yaksh/xmlrpc_clients.py delete mode 100644 testapp/yaksh_app/__init__.py delete mode 100644 testapp/yaksh_app/admin.py delete mode 100644 testapp/yaksh_app/bash_code_evaluator.py delete mode 100644 testapp/yaksh_app/bash_files/sample.args delete mode 100755 testapp/yaksh_app/bash_files/sample.sh delete mode 100755 testapp/yaksh_app/c_cpp_files/main.cpp delete mode 100755 testapp/yaksh_app/c_cpp_files/main2.c delete mode 100755 testapp/yaksh_app/c_cpp_files/main_array_check.cpp delete mode 100755 testapp/yaksh_app/c_cpp_files/main_array_check_all.cpp delete mode 100755 testapp/yaksh_app/c_cpp_files/main_array_sum.cpp delete mode 100755 testapp/yaksh_app/c_cpp_files/main_blackJack.cpp delete mode 100755 testapp/yaksh_app/c_cpp_files/main_check_digit.cpp delete mode 100755 testapp/yaksh_app/c_cpp_files/main_count667.cpp delete mode 100755 testapp/yaksh_app/c_cpp_files/main_count7.cpp delete mode 100755 testapp/yaksh_app/c_cpp_files/main_fact.cpp delete mode 100755 testapp/yaksh_app/c_cpp_files/main_greatest.cpp delete mode 100755 testapp/yaksh_app/c_cpp_files/main_hello_name.c delete mode 100755 testapp/yaksh_app/c_cpp_files/main_lessThan9.cpp delete mode 100755 testapp/yaksh_app/c_cpp_files/main_mean.cpp delete mode 100755 testapp/yaksh_app/c_cpp_files/main_palindrome.cpp delete mode 100755 testapp/yaksh_app/c_cpp_files/main_roundTo10.cpp delete mode 100755 testapp/yaksh_app/c_cpp_files/main_specialSum.cpp delete mode 100755 testapp/yaksh_app/c_cpp_files/main_within.cpp delete mode 100644 testapp/yaksh_app/code_evaluator.py delete mode 100755 testapp/yaksh_app/code_server.py delete mode 100644 testapp/yaksh_app/cpp_code_evaluator.py delete mode 100644 testapp/yaksh_app/docs/sample.args delete mode 100755 testapp/yaksh_app/docs/sample.sh delete mode 100644 testapp/yaksh_app/docs/sample_questions.py delete mode 100644 testapp/yaksh_app/docs/sample_questions.xml delete mode 100644 testapp/yaksh_app/forms.py delete mode 100644 testapp/yaksh_app/java_code_evaluator.py delete mode 100644 testapp/yaksh_app/java_files/main_array_sum.java delete mode 100644 testapp/yaksh_app/java_files/main_fact.java delete mode 100644 testapp/yaksh_app/java_files/main_great.java delete mode 100644 testapp/yaksh_app/java_files/main_hello_name.java delete mode 100644 testapp/yaksh_app/java_files/main_lastDigit.java delete mode 100644 testapp/yaksh_app/java_files/main_moreThan30.java delete mode 100644 testapp/yaksh_app/java_files/main_palindrome.java delete mode 100644 testapp/yaksh_app/java_files/main_square.java delete mode 100644 testapp/yaksh_app/language_registry.py delete mode 100644 testapp/yaksh_app/management/__init__.py delete mode 100644 testapp/yaksh_app/management/commands/__init__.py delete mode 100644 testapp/yaksh_app/management/commands/add_group.py delete mode 100644 testapp/yaksh_app/management/commands/dump_user_data.py delete mode 100644 testapp/yaksh_app/management/commands/load_exam.py delete mode 100644 testapp/yaksh_app/management/commands/load_questions_xml.py delete mode 100644 testapp/yaksh_app/management/commands/results2csv.py delete mode 100644 testapp/yaksh_app/models.py delete mode 100644 testapp/yaksh_app/output/README.txt delete mode 100644 testapp/yaksh_app/python_code_evaluator.py delete mode 100644 testapp/yaksh_app/scilab_code_evaluator.py delete mode 100644 testapp/yaksh_app/scilab_files/test_add.sce delete mode 100644 testapp/yaksh_app/settings.py delete mode 100644 testapp/yaksh_app/static/yaksh_app/css/autotaggit.css delete mode 100644 testapp/yaksh_app/static/yaksh_app/css/base.css delete mode 100644 testapp/yaksh_app/static/yaksh_app/css/gradeuser.css delete mode 100644 testapp/yaksh_app/static/yaksh_app/css/login.css delete mode 100644 testapp/yaksh_app/static/yaksh_app/css/monitor.css delete mode 100644 testapp/yaksh_app/static/yaksh_app/css/question.css delete mode 100644 testapp/yaksh_app/static/yaksh_app/css/question_paper_creation.css delete mode 100644 testapp/yaksh_app/static/yaksh_app/css/question_quiz.css delete mode 100644 testapp/yaksh_app/static/yaksh_app/css/showusers.css delete mode 100644 testapp/yaksh_app/static/yaksh_app/js/add_question.js delete mode 100644 testapp/yaksh_app/static/yaksh_app/js/add_questionpaper.js delete mode 100644 testapp/yaksh_app/static/yaksh_app/js/add_quiz.js delete mode 100644 testapp/yaksh_app/static/yaksh_app/js/bootstrap-modal.js delete mode 100644 testapp/yaksh_app/static/yaksh_app/js/bootstrap-tabs.js delete mode 100644 testapp/yaksh_app/static/yaksh_app/js/edit_question.js delete mode 100644 testapp/yaksh_app/static/yaksh_app/js/edit_quiz.js delete mode 100644 testapp/yaksh_app/static/yaksh_app/js/jquery-1.4.2.min.js delete mode 100644 testapp/yaksh_app/static/yaksh_app/js/min.js delete mode 100644 testapp/yaksh_app/static/yaksh_app/js/question.js delete mode 100644 testapp/yaksh_app/static/yaksh_app/js/question_filter.js delete mode 100644 testapp/yaksh_app/static/yaksh_app/js/question_paper_creation.js delete mode 100644 testapp/yaksh_app/static/yaksh_app/js/show_question.js delete mode 100644 testapp/yaksh_app/static/yaksh_app/js/show_quiz.js delete mode 100644 testapp/yaksh_app/templates/404.html delete mode 100644 testapp/yaksh_app/templates/500.html delete mode 100644 testapp/yaksh_app/templates/base.html delete mode 100644 testapp/yaksh_app/templates/manage.html delete mode 100644 testapp/yaksh_app/templates/user.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/add_question.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/add_questionpaper.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/add_quiz.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/ajax_marks.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/ajax_question_filter.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/ajax_questions.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/automatic_questionpaper.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/complete.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/design_questionpaper.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/edit_question.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/edit_quiz.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/editquestionpaper.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/grade_user.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/intro.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/login.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/manual_questionpaper.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/monitor.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/question.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/quit.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/quizlist.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/quizzes_user.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/register.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/results_user.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/show_quiz.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/showquestionpapers.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/showquestions.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/showusers.html delete mode 100644 testapp/yaksh_app/templates/yaksh_app/user_data.html delete mode 100644 testapp/yaksh_app/tests.py delete mode 100644 testapp/yaksh_app/urls.py delete mode 100644 testapp/yaksh_app/views.py delete mode 100644 testapp/yaksh_app/xmlrpc_clients.py (limited to 'testapp') diff --git a/testapp/templates/demo_urls.py b/testapp/templates/demo_urls.py index 4308eba..da8bc2b 100644 --- a/testapp/templates/demo_urls.py +++ b/testapp/templates/demo_urls.py @@ -9,5 +9,5 @@ urlpatterns = patterns('', # url(r'^blog/', include('blog.urls')), url(r'^admin/', include(admin.site.urls)), - url(r'^exam/', include('testapp.yaksh_app.urls')), + url(r'^exam/', include('testapp.yaksh.urls')), ) diff --git a/testapp/tests/test_bash_evaluation.py b/testapp/tests/test_bash_evaluation.py index 924c560..4f7e4b6 100644 --- a/testapp/tests/test_bash_evaluation.py +++ b/testapp/tests/test_bash_evaluation.py @@ -1,7 +1,7 @@ import unittest import os -from testapp.yaksh_app.bash_code_evaluator import BashCodeEvaluator -from testapp.yaksh_app.settings import SERVER_TIMEOUT +from testapp.yaksh.bash_code_evaluator import BashCodeEvaluator +from testapp.yaksh.settings import SERVER_TIMEOUT class BashEvaluationTestCases(unittest.TestCase): def setUp(self): diff --git a/testapp/tests/test_c_cpp_evaluation.py b/testapp/tests/test_c_cpp_evaluation.py index 3d7f09d..9cbc013 100644 --- a/testapp/tests/test_c_cpp_evaluation.py +++ b/testapp/tests/test_c_cpp_evaluation.py @@ -1,7 +1,7 @@ import unittest import os -from testapp.yaksh_app.cpp_code_evaluator import CppCodeEvaluator -from testapp.yaksh_app.settings import SERVER_TIMEOUT +from testapp.yaksh.cpp_code_evaluator import CppCodeEvaluator +from testapp.yaksh.settings import SERVER_TIMEOUT class CEvaluationTestCases(unittest.TestCase): def setUp(self): diff --git a/testapp/tests/test_code_evaluation.py b/testapp/tests/test_code_evaluation.py index 9f0885f..10b88b5 100644 --- a/testapp/tests/test_code_evaluation.py +++ b/testapp/tests/test_code_evaluation.py @@ -1,8 +1,8 @@ import unittest import os -from testapp.yaksh_app import python_code_evaluator -from testapp.yaksh_app.language_registry import _LanguageRegistry, set_registry, get_registry -from testapp.yaksh_app.settings import SERVER_TIMEOUT +from testapp.yaksh import python_code_evaluator +from testapp.yaksh.language_registry import _LanguageRegistry, set_registry, get_registry +from testapp.yaksh.settings import SERVER_TIMEOUT class RegistryTestCase(unittest.TestCase): @@ -13,7 +13,7 @@ class RegistryTestCase(unittest.TestCase): def test_set_register(self): class_name = getattr(python_code_evaluator, 'PythonCodeEvaluator') - self.registry_object.register("python", "testapp.yaksh_app.python_code_evaluator.PythonCodeEvaluator") + self.registry_object.register("python", "testapp.yaksh.python_code_evaluator.PythonCodeEvaluator") self.assertEquals(self.registry_object.get_class("python"), class_name) def tearDown(self): diff --git a/testapp/tests/test_java_evaluation.py b/testapp/tests/test_java_evaluation.py index 8e1fdeb..92339e4 100644 --- a/testapp/tests/test_java_evaluation.py +++ b/testapp/tests/test_java_evaluation.py @@ -1,7 +1,7 @@ import unittest import os -from testapp.yaksh_app import code_evaluator as evaluator -from testapp.yaksh_app.java_code_evaluator import JavaCodeEvaluator +from testapp.yaksh import code_evaluator as evaluator +from testapp.yaksh.java_code_evaluator import JavaCodeEvaluator class JavaEvaluationTestCases(unittest.TestCase): diff --git a/testapp/tests/test_python_evaluation.py b/testapp/tests/test_python_evaluation.py index 7039b75..ea01fa8 100644 --- a/testapp/tests/test_python_evaluation.py +++ b/testapp/tests/test_python_evaluation.py @@ -1,7 +1,7 @@ import unittest import os -from testapp.yaksh_app.python_code_evaluator import PythonCodeEvaluator -from testapp.yaksh_app.settings import SERVER_TIMEOUT +from testapp.yaksh.python_code_evaluator import PythonCodeEvaluator +from testapp.yaksh.settings import SERVER_TIMEOUT class PythonEvaluationTestCases(unittest.TestCase): def setUp(self): diff --git a/testapp/tests/test_scilab_evaluation.py b/testapp/tests/test_scilab_evaluation.py index 346060a..4d05426 100644 --- a/testapp/tests/test_scilab_evaluation.py +++ b/testapp/tests/test_scilab_evaluation.py @@ -1,7 +1,7 @@ import unittest import os -from testapp.yaksh_app.scilab_code_evaluator import ScilabCodeEvaluator -from testapp.yaksh_app.settings import SERVER_TIMEOUT +from testapp.yaksh.scilab_code_evaluator import ScilabCodeEvaluator +from testapp.yaksh.settings import SERVER_TIMEOUT class ScilabEvaluationTestCases(unittest.TestCase): def setUp(self): diff --git a/testapp/urls.py b/testapp/urls.py index 4547232..7022b0d 100644 --- a/testapp/urls.py +++ b/testapp/urls.py @@ -14,7 +14,7 @@ else: ADMIN_BASE = r'^admin/' urlpatterns = patterns('', - url(URL_BASE, include('yaksh_app.urls')), + url(URL_BASE, include('yaksh.urls')), #url(r'^admin/', include(admin.site.urls)), # Uncomment the admin/doc line below to enable admin documentation: # url(r'^admin/doc/', include('django.contrib.admindocs.urls')), diff --git a/testapp/yaksh/__init__.py b/testapp/yaksh/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/testapp/yaksh/admin.py b/testapp/yaksh/admin.py new file mode 100644 index 0000000..ed0afde --- /dev/null +++ b/testapp/yaksh/admin.py @@ -0,0 +1,6 @@ +from testapp.yaksh.models import Question, Quiz, TestCase +from django.contrib import admin + +admin.site.register(Question) +admin.site.register(TestCase) +admin.site.register(Quiz) diff --git a/testapp/yaksh/bash_code_evaluator.py b/testapp/yaksh/bash_code_evaluator.py new file mode 100644 index 0000000..a468fd7 --- /dev/null +++ b/testapp/yaksh/bash_code_evaluator.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python +import traceback +import pwd +import os +from os.path import join, isfile +import subprocess +import importlib + +# local imports +from code_evaluator import CodeEvaluator + + +class BashCodeEvaluator(CodeEvaluator): + """Tests the Bash code obtained from Code Server""" + def __init__(self, test_case_data, test, language, user_answer, + ref_code_path=None, in_dir=None): + super(BashCodeEvaluator, self).__init__(test_case_data, test, language, user_answer, + ref_code_path, in_dir) + self.test_case_args = self._setup() + + # Private Protocol ########## + def _setup(self): + super(BashCodeEvaluator, self)._setup() + + self.submit_path = self.create_submit_code_file('submit.sh') + self._set_file_as_executable(self.submit_path) + get_ref_path, get_test_case_path = self.ref_code_path.strip().split(',') + get_ref_path = get_ref_path.strip() + get_test_case_path = get_test_case_path.strip() + ref_path, test_case_path = self._set_test_code_file_path(get_ref_path, + get_test_case_path) + + return ref_path, self.submit_path, test_case_path + + def _teardown(self): + # Delete the created file. + super(BashCodeEvaluator, self)._teardown() + os.remove(self.submit_path) + + def _check_code(self, ref_path, submit_path, + test_case_path=None): + """ Function validates student script using instructor script as + reference. Test cases can optionally be provided. The first argument + ref_path, is the path to instructor script, it is assumed to + have executable permission. The second argument submit_path, is + the path to the student script, it is assumed to have executable + permission. The Third optional argument is the path to test the + scripts. Each line in this file is a test case and each test case is + passed to the script as standard arguments. + + Returns + -------- + + returns (True, "Correct answer") : If the student script passes all + test cases/have same output, when compared to the instructor script + + returns (False, error_msg): If the student script fails a single + test/have dissimilar output, when compared to the instructor script. + + Returns (False, error_msg): If mandatory arguments are not files or if + the required permissions are not given to the file(s). + + """ + if not isfile(ref_path): + return False, "No file at %s or Incorrect path" % ref_path + if not isfile(submit_path): + return False, "No file at %s or Incorrect path" % submit_path + if not os.access(ref_path, os.X_OK): + return False, "Script %s is not executable" % ref_path + if not os.access(submit_path, os.X_OK): + return False, "Script %s is not executable" % submit_path + + success = False + + if test_case_path is None or "": + ret = self._run_command(ref_path, stdin=None, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + proc, inst_stdout, inst_stderr = ret + ret = self._run_command(submit_path, stdin=None, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + proc, stdnt_stdout, stdnt_stderr = ret + if inst_stdout == stdnt_stdout: + return True, "Correct answer" + else: + err = "Error: expected %s, got %s" % (inst_stderr, + stdnt_stderr) + return False, err + else: + if not isfile(test_case_path): + return False, "No test case at %s" % test_case_path + if not os.access(ref_path, os.R_OK): + return False, "Test script %s, not readable" % test_case_path + # valid_answer is True, so that we can stop once a test case fails + valid_answer = True + # loop_count has to be greater than or equal to one. + # Useful for caching things like empty test files,etc. + loop_count = 0 + test_cases = open(test_case_path).readlines() + num_lines = len(test_cases) + for test_case in test_cases: + loop_count += 1 + if valid_answer: + args = [ref_path] + [x for x in test_case.split()] + ret = self._run_command(args, stdin=None, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + proc, inst_stdout, inst_stderr = ret + args = [submit_path]+[x for x in test_case.split()] + ret = self._run_command(args, stdin=None, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + proc, stdnt_stdout, stdnt_stderr = ret + valid_answer = inst_stdout == stdnt_stdout + if valid_answer and (num_lines == loop_count): + return True, "Correct answer" + else: + err = "Error:expected %s, got %s" % (inst_stdout+inst_stderr, + stdnt_stdout+stdnt_stderr) + return False, err + diff --git a/testapp/yaksh/bash_files/sample.args b/testapp/yaksh/bash_files/sample.args new file mode 100644 index 0000000..4d9f00d --- /dev/null +++ b/testapp/yaksh/bash_files/sample.args @@ -0,0 +1,2 @@ +1 2 +2 1 diff --git a/testapp/yaksh/bash_files/sample.sh b/testapp/yaksh/bash_files/sample.sh new file mode 100755 index 0000000..e935cb3 --- /dev/null +++ b/testapp/yaksh/bash_files/sample.sh @@ -0,0 +1,2 @@ +#!/bin/bash +[[ $# -eq 2 ]] && echo $(( $1 + $2 )) && exit $(( $1 + $2 )) diff --git a/testapp/yaksh/c_cpp_files/main.cpp b/testapp/yaksh/c_cpp_files/main.cpp new file mode 100755 index 0000000..ebe1f08 --- /dev/null +++ b/testapp/yaksh/c_cpp_files/main.cpp @@ -0,0 +1,32 @@ +#include
+#include + +extern int add(int, int); + +template + +void check(T expect, T result) +{ + if (expect == result) + { + printf("\nCorrect:\n Expected %d got %d \n",expect,result); + } + else + { + printf("\nIncorrect:\n Expected %d got %d \n",expect,result); + exit (1); + } +} + +int main(void) +{ + int result; + result = add(0,0); + printf("Input submitted to the function: 0, 0"); + check(0, result); + result = add(2,3); + printf("Input submitted to the function: 2 3"); + check(5,result); + printf("All Correct\n"); + return 0; +} diff --git a/testapp/yaksh/c_cpp_files/main2.c b/testapp/yaksh/c_cpp_files/main2.c new file mode 100755 index 0000000..ccd1768 --- /dev/null +++ b/testapp/yaksh/c_cpp_files/main2.c @@ -0,0 +1,30 @@ +#include +#include + +extern int add(int, int, int); + +template +void check(T expect,T result) +{ + if (expect == result) + { + printf("\nCorrect:\n Expected %d got %d \n",expect,result); + } + else + { + printf("\nIncorrect:\n Expected %d got %d \n",expect,result); + exit (0); + } +} + +int main(void) +{ + int result; + result = add(0,0,0); + printf("Input submitted to the function: 0, 0, 0"); + check(0, result); + result = add(2,3,3); + printf("Input submitted to the function: 2, 3, 3"); + check(8,result); + printf("All Correct\n"); +} diff --git a/testapp/yaksh/c_cpp_files/main_array_check.cpp b/testapp/yaksh/c_cpp_files/main_array_check.cpp new file mode 100755 index 0000000..ea34fdd --- /dev/null +++ b/testapp/yaksh/c_cpp_files/main_array_check.cpp @@ -0,0 +1,34 @@ +#include +#include + +extern bool array_check(int [], int); + +template + +void check(T expect,T result) +{ + if (expect == result) + { + printf("\nCorrect:\n Expected %d got %d \n",expect,result); + } + else + { + printf("\nIncorrect:\n Expected %d got %d \n",expect,result); + exit (1); + } +} + +int main(void) +{ + bool result; + int a[] = {1,2,3,0,0}; + result = array_check(a, 2); + printf("Input submitted to the function: {1, 2, 3, 0, 0} and index 2"); + check(false, result); + int b[] = {1,2,3,4,5}; + result = array_check(b, 3); + printf("Input submitted to the function: {1, 2, 3, 4, 5} and index 3"); + check(true, result); + printf("All Correct\n"); + return 0; +} diff --git a/testapp/yaksh/c_cpp_files/main_array_check_all.cpp b/testapp/yaksh/c_cpp_files/main_array_check_all.cpp new file mode 100755 index 0000000..140578e --- /dev/null +++ b/testapp/yaksh/c_cpp_files/main_array_check_all.cpp @@ -0,0 +1,34 @@ +#include +#include + +extern bool array_check_all(int []); + +template + +void check(T expect,T result) +{ + if (expect == result) + { + printf("\nCorrect:\n Expected %d got %d \n",expect,result); + } + else + { + printf("\nIncorrect:\n Expected %d got %d \n",expect,result); + exit (1); + } +} + +int main(void) +{ + bool result; + int a[] = {1,2,3,2,8}; + result = array_check_all(a); + printf("Input submitted to the function: {1, 2, 3, 2, 8}"); + check(false, result); + int b[] = {4,2,32,4,56}; + result = array_check_all(b); + printf("Input submitted to the function: {4, 2, 32, 4, 56}"); + check(true, result); + printf("All Correct\n"); + return 0; +} diff --git a/testapp/yaksh/c_cpp_files/main_array_sum.cpp b/testapp/yaksh/c_cpp_files/main_array_sum.cpp new file mode 100755 index 0000000..55b2ebf --- /dev/null +++ b/testapp/yaksh/c_cpp_files/main_array_sum.cpp @@ -0,0 +1,34 @@ +#include +#include + +extern int array_sum(int []); + +template + +void check(T expect,T result) +{ + if (expect == result) + { + printf("\nCorrect:\n Expected %d got %d \n",expect,result); + } + else + { + printf("\nIncorrect:\n Expected %d got %d \n",expect,result); + exit (1); + } +} + +int main(void) +{ + int result; + int a[] = {1,2,3,0,0}; + result = array_sum(a); + printf("Input submitted to the function: {1, 2, 3, 0, 0}"); + check(6, result); + int b[] = {1,2,3,4,5}; + result = array_sum(b); + printf("Input submitted to the function: {1, 2, 3, 4, 5}"); + check(15,result); + printf("All Correct\n"); + return 0; +} diff --git a/testapp/yaksh/c_cpp_files/main_blackJack.cpp b/testapp/yaksh/c_cpp_files/main_blackJack.cpp new file mode 100755 index 0000000..cc54e78 --- /dev/null +++ b/testapp/yaksh/c_cpp_files/main_blackJack.cpp @@ -0,0 +1,41 @@ +#include +#include + +extern int blackJack(int, int); + +template + +void check(T expect, T result) +{ + if (expect == result) + { + printf("\nCorrect:\n Expected %d got %d \n",expect,result); + } + else + { + printf("\nIncorrect:\n Expected %d got %d \n",expect,result); + exit (1); + } +} + +int main(void) +{ + int result; + result = blackJack(11, 12); + printf("Input submitted to the function: 11, 12"); + check(12, result); + result = blackJack(15, 19); + printf("Input submitted to the function: 15, 19"); + check(19, result); + result = blackJack(10, 21); + printf("Input submitted to the function: 10, 21"); + check(21, result); + result = blackJack(31, 22); + printf("Input submitted to the function: 31, 22"); + check(0, result); + result = blackJack(91, 61); + printf("Input submitted to the function: 91, 61"); + check(0, result); + printf("All Correct\n"); + return 0; +} diff --git a/testapp/yaksh/c_cpp_files/main_check_digit.cpp b/testapp/yaksh/c_cpp_files/main_check_digit.cpp new file mode 100755 index 0000000..d3bf3d6 --- /dev/null +++ b/testapp/yaksh/c_cpp_files/main_check_digit.cpp @@ -0,0 +1,32 @@ +#include +#include + +extern bool check_digit(int, int); + +template + +void check(T expect, T result) +{ + if (expect == result) + { + printf("\nCorrect:\n Expected %d got %d \n",expect,result); + } + else + { + printf("\nIncorrect:\n Expected %d got %d \n",expect,result); + exit (1); + } +} + +int main(void) +{ + bool result; + result = check_digit(12, 23); + printf("Input submitted to the function: 12, 23"); + check(true, result); + result = check_digit(22, 11); + printf("Input submitted to the function: 121"); + check(false, result); + printf("All Correct\n"); + return 0; +} diff --git a/testapp/yaksh/c_cpp_files/main_count667.cpp b/testapp/yaksh/c_cpp_files/main_count667.cpp new file mode 100755 index 0000000..f146e8c --- /dev/null +++ b/testapp/yaksh/c_cpp_files/main_count667.cpp @@ -0,0 +1,42 @@ +#include +#include + +extern int count667(int[]); + +template + +void check(T expect, T result) +{ + if (expect == result) + { + printf("\nCorrect:\n Expected %d got %d \n",expect,result); + } + else + { + printf("\nIncorrect:\n Expected %d got %d \n",expect,result); + exit (1); + } +} + +int main(void) +{ + int result; + int arr[5] = {2,6,4,5,6}; + result = count667(arr); + printf("Input submitted to the function: [2, 6, 4, 5,6]"); + check(0, result); + int arr2[5] = {6,6,2,17,9}; + result = count667(arr2); + printf("Input submitted to the function: [6, 6, 2, 17, 9]"); + check(1, result); + int arr3[5] = {6,6,6,7,1}; + result = count667(arr3); + printf("Input submitted to the function: [6, 6, 7, 2, 1]"); + check(3, result); + int arr4[5] = {6,7,7,6,6}; + result = count667(arr4); + printf("Input submitted to the function: [6, 7, 7, 6, 6]"); + check(2, result); + printf("All Correct\n"); + return 0; +} diff --git a/testapp/yaksh/c_cpp_files/main_count7.cpp b/testapp/yaksh/c_cpp_files/main_count7.cpp new file mode 100755 index 0000000..982e930 --- /dev/null +++ b/testapp/yaksh/c_cpp_files/main_count7.cpp @@ -0,0 +1,42 @@ +#include +#include + +extern int count7(int[]); + +template + +void check(T expect, T result) +{ + if (expect == result) + { + printf("\nCorrect:\n Expected %d got %d \n",expect,result); + } + else + { + printf("\nIncorrect:\n Expected %d got %d \n",expect,result); + exit (1); + } +} + +int main(void) +{ + int result; + int arr[4] = {2,3,4,5}; + result = count7(arr); + printf("Input submitted to the function: [2, 3, 4, 5]"); + check(0, result); + int arr2[4] = {1,2,17,9}; + result = count7(arr2); + printf("Input submitted to the function: [1, 2, 17, 9]"); + check(0, result); + int arr3[4] = {7,9,2,1}; + result = count7(arr3); + printf("Input submitted to the function: [7, 9, 2, 1]"); + check(1, result); + int arr4[4] = {1,7,7,7}; + result = count7(arr4); + printf("Input submitted to the function: [1, 7, 7, 7]"); + check(3, result); + printf("All Correct\n"); + return 0; +} diff --git a/testapp/yaksh/c_cpp_files/main_fact.cpp b/testapp/yaksh/c_cpp_files/main_fact.cpp new file mode 100755 index 0000000..a4ff230 --- /dev/null +++ b/testapp/yaksh/c_cpp_files/main_fact.cpp @@ -0,0 +1,32 @@ +#include +#include + +extern int factorial(int); + +template + +void check(T expect, T result) +{ + if (expect == result) + { + printf("\nCorrect:\n Expected %d got %d \n",expect,result); + } + else + { + printf("\nIncorrect:\n Expected %d got %d \n",expect,result); + exit (1); + } +} + +int main(void) +{ + int result; + result = factorial(0); + printf("Input submitted to the function: 0"); + check(1, result); + result = factorial(3); + printf("Input submitted to the function: 3"); + check(6, result); + printf("All Correct\n"); + return 0; +} diff --git a/testapp/yaksh/c_cpp_files/main_greatest.cpp b/testapp/yaksh/c_cpp_files/main_greatest.cpp new file mode 100755 index 0000000..6d0a7c2 --- /dev/null +++ b/testapp/yaksh/c_cpp_files/main_greatest.cpp @@ -0,0 +1,44 @@ +#include +#include + +extern int greatest(int, int, int); + +template + +void check(T expect, T result) +{ + if (expect == result) + { + printf("\nCorrect:\n Expected %d got %d \n",expect,result); + } + else + { + printf("\nIncorrect:\n Expected %d got %d \n",expect,result); + exit (1); + } +} + +int main(void) +{ + int result; + result = greatest(1, 2, 3); + printf("Input submitted to the function: 1, 2, 3"); + check(3, result); + result = greatest(5, 9, 2); + printf("Input submitted to the function: 5, 9, 2"); + check(9, result); + result = greatest(7, 2, 4); + printf("Input submitted to the function: 7, 2, 4"); + check(7, result); + result = greatest(11, 2, 45); + printf("Input submitted to the function: 11, 2, 45"); + check(45, result); + result = greatest(2, 7, 0); + printf("Input submitted to the function: 2, 7, 0"); + check(7, result); + result = greatest(9, 6, 5); + printf("Input submitted to the function: 9, 6, 5"); + check(9, result); + printf("All Correct\n"); + return 0; +} diff --git a/testapp/yaksh/c_cpp_files/main_hello_name.c b/testapp/yaksh/c_cpp_files/main_hello_name.c new file mode 100755 index 0000000..71b83a2 --- /dev/null +++ b/testapp/yaksh/c_cpp_files/main_hello_name.c @@ -0,0 +1,29 @@ +#include +#include + + +void check(char expect[], char result[]) +{ + if (expect == result) + { + printf("Correct:expected %s got %s \n",expect,result); + } + else + { + printf("ERROR:expected %s got %s \n",expect,result); + exit (0); + } +} + +int main(void) +{ + char result[20]; + char A[20]=" pratham"; + char B[20]=" sir"; + result[20] = message(A); + printf("%s",result); + check("hello pratham", result); + result[20] = message(B); + check("hello sir",result); + printf("All Correct\n"); +} diff --git a/testapp/yaksh/c_cpp_files/main_lessThan9.cpp b/testapp/yaksh/c_cpp_files/main_lessThan9.cpp new file mode 100755 index 0000000..722b4bb --- /dev/null +++ b/testapp/yaksh/c_cpp_files/main_lessThan9.cpp @@ -0,0 +1,38 @@ +#include +#include + +extern bool lessThan9(int); + +template + +void check(T expect, T result) +{ + if (expect == result) + { + printf("\nCorrect:\n Expected %d got %d \n",expect,result); + } + else + { + printf("\nIncorrect:\n Expected %d got %d \n",expect,result); + exit (1); + } +} + +int main(void) +{ + bool result; + result = lessThan9(10); + printf("Input submitted to the function: 10"); + check(false, result); + result = lessThan9(17); + printf("Input submitted to the function: 17"); + check(true, result); + result = lessThan9(16); + printf("Input submitted to the function: 16"); + check(true, result); + result = lessThan9(15); + printf("Input submitted to the function: 15"); + check(false, result); + printf("All Correct\n"); + return 0; +} diff --git a/testapp/yaksh/c_cpp_files/main_mean.cpp b/testapp/yaksh/c_cpp_files/main_mean.cpp new file mode 100755 index 0000000..21a4b1a --- /dev/null +++ b/testapp/yaksh/c_cpp_files/main_mean.cpp @@ -0,0 +1,38 @@ +#include +#include + +extern bool mean(int, int , int); + +template + +void check(T expect, T result) +{ + if (expect == result) + { + printf("\nCorrect:\n Expected %d got %d \n",expect,result); + } + else + { + printf("\nIncorrect:\n Expected %d got %d \n",expect,result); + exit (1); + } +} + +int main(void) +{ + bool result; + result = mean(11, 11, 11); + printf("Input submitted to the function: 11, 121, 11"); + check(true, result); + result = mean(16, 12, 9); + printf("Input submitted to the function: 16, 144, 9"); + check(true, result); + result = mean(19, 221, 9); + printf("Input submitted to the function: 19, 221, 9"); + check(false, result); + result = mean(34, 12, 3); + printf("Input submitted to the function: 11, 121, 11"); + check(false, result); + printf("All Correct\n"); + return 0; +} diff --git a/testapp/yaksh/c_cpp_files/main_palindrome.cpp b/testapp/yaksh/c_cpp_files/main_palindrome.cpp new file mode 100755 index 0000000..0e66928 --- /dev/null +++ b/testapp/yaksh/c_cpp_files/main_palindrome.cpp @@ -0,0 +1,32 @@ +#include +#include + +extern bool palindrome(int); + +template + +void check(T expect, T result) +{ + if (expect == result) + { + printf("\nCorrect:\n Expected %d got %d \n",expect,result); + } + else + { + printf("\nIncorrect:\n Expected %d got %d \n",expect,result); + exit (1); + } +} + +int main(void) +{ + bool result; + result = palindrome(123); + printf("Input submitted to the function: 123"); + check(false, result); + result = palindrome(121); + printf("Input submitted to the function: 121"); + check(true, result); + printf("All Correct\n"); + return 0; +} diff --git a/testapp/yaksh/c_cpp_files/main_roundTo10.cpp b/testapp/yaksh/c_cpp_files/main_roundTo10.cpp new file mode 100755 index 0000000..12c961d --- /dev/null +++ b/testapp/yaksh/c_cpp_files/main_roundTo10.cpp @@ -0,0 +1,41 @@ +#include +#include + +extern int roundTo10(int,int,int); + +template + +void check(T expect, T result) +{ + if (expect == result) + { + printf("\nCorrect:\n Expected %d got %d \n",expect,result); + } + else + { + printf("\nIncorrect:\n Expected %d got %d \n",expect,result); + exit (1); + } +} + +int main(void) +{ + int result; + result = roundTo10(10, 22, 39); + printf("Input submitted to the function: 10, 22, 39"); + check(70, result); + result = roundTo10(45, 42, 39); + printf("Input submitted to the function: 45, 42, 39"); + check(130, result); + result = roundTo10(7, 3, 9); + printf("Input submitted to the function: 7, 3, 9"); + check(20, result); + result = roundTo10(1, 2, 3); + printf("Input submitted to the function: 1, 2, 3"); + check(0, result); + result = roundTo10(30, 40, 50); + printf("Input submitted to the function: 30, 40, 50"); + check(120, result); + printf("All Correct\n"); + return 0; +} diff --git a/testapp/yaksh/c_cpp_files/main_specialSum.cpp b/testapp/yaksh/c_cpp_files/main_specialSum.cpp new file mode 100755 index 0000000..d614536 --- /dev/null +++ b/testapp/yaksh/c_cpp_files/main_specialSum.cpp @@ -0,0 +1,41 @@ +#include +#include + +extern int specialSum(int,int,int); + +template + +void check(T expect, T result) +{ + if (expect == result) + { + printf("\nCorrect:\n Expected %d got %d \n",expect,result); + } + else + { + printf("\nIncorrect:\n Expected %d got %d \n",expect,result); + exit (1); + } +} + +int main(void) +{ + int result; + result = specialSum(10, 2, 9); + printf("Input submitted to the function: 10, 2, 9"); + check(21, result); + result = specialSum(1, 21, 9); + printf("Input submitted to the function: 1, 21, 9"); + check(1, result); + result = specialSum(21, 2, 3); + printf("Input submitted to the function: 21, 2, 3"); + check(0, result); + result = specialSum(10, 2, 21); + printf("Input submitted to the function: 10, 2, 21"); + check(12, result); + result = specialSum(10, 2, 6); + printf("Input submitted to the function: 10, 2, 6"); + check(18, result); + printf("All Correct\n"); + return 0; +} diff --git a/testapp/yaksh/c_cpp_files/main_within.cpp b/testapp/yaksh/c_cpp_files/main_within.cpp new file mode 100755 index 0000000..50f9ad0 --- /dev/null +++ b/testapp/yaksh/c_cpp_files/main_within.cpp @@ -0,0 +1,38 @@ +#include +#include + +extern bool within(int, int, int); + +template + +void check(T expect, T result) +{ + if (expect == result) + { + printf("\nCorrect:\n Expected %d got %d \n",expect,result); + } + else + { + printf("\nIncorrect:\n Expected %d got %d \n",expect,result); + exit (1); + } +} + +int main(void) +{ + bool result; + result = within(12, 3, 20); + printf("Input submitted to the function: 12, 3, 20"); + check(true, result); + result = within(12, 13, 20); + printf("Input submitted to the function: 12, 13, 20"); + check(false, result); + result = within(29, 13, 120); + printf("Input submitted to the function: 29, 13, 120"); + check(true, result); + result = within(12, 12, 20); + printf("Input submitted to the function: 12, 3, 20"); + check(false, result); + printf("All Correct\n"); + return 0; +} diff --git a/testapp/yaksh/code_evaluator.py b/testapp/yaksh/code_evaluator.py new file mode 100644 index 0000000..381b2e8 --- /dev/null +++ b/testapp/yaksh/code_evaluator.py @@ -0,0 +1,206 @@ +import sys +from SimpleXMLRPCServer import SimpleXMLRPCServer +import pwd +import os +import stat +from os.path import isdir, dirname, abspath, join, isfile +import signal +from multiprocessing import Process, Queue +import subprocess +import re +import json +# Local imports. +from settings import SERVER_TIMEOUT + + +MY_DIR = abspath(dirname(__file__)) + + +# Raised when the code times-out. +# c.f. http://pguides.net/python/timeout-a-function +class TimeoutException(Exception): + pass + + +def timeout_handler(signum, frame): + """A handler for the ALARM signal.""" + raise TimeoutException('Code took too long to run.') + + +def create_signal_handler(): + """Add a new signal handler for the execution of this code.""" + prev_handler = signal.signal(signal.SIGALRM, timeout_handler) + signal.alarm(SERVER_TIMEOUT) + return prev_handler + + +def set_original_signal_handler(old_handler=None): + """Set back any original signal handler.""" + if old_handler is not None: + signal.signal(signal.SIGALRM, old_handler) + return + else: + raise Exception("Signal Handler: object cannot be NoneType") + + +def delete_signal_handler(): + signal.alarm(0) + return + + +class CodeEvaluator(object): + """Tests the code obtained from Code Server""" + def __init__(self, test_case_data, test, language, user_answer, + ref_code_path=None, in_dir=None): + msg = 'Code took more than %s seconds to run. You probably '\ + 'have an infinite loop in your code.' % SERVER_TIMEOUT + self.timeout_msg = msg + self.test_case_data = test_case_data + self.language = language.lower() + self.user_answer = user_answer + self.ref_code_path = ref_code_path + self.test = test + self.in_dir = in_dir + self.test_case_args = None + + # Public Protocol ########## + @classmethod + def from_json(cls, language, json_data, in_dir): + json_data = json.loads(json_data) + test_case_data = json_data.get("test_case_data") + user_answer = json_data.get("user_answer") + ref_code_path = json_data.get("ref_code_path") + test = json_data.get("test") + + instance = cls(test_case_data, test, language, user_answer, ref_code_path, + in_dir) + return instance + + def evaluate(self): + """Evaluates given code with the test cases based on + given arguments in test_case_data. + + The ref_code_path is a path to the reference code. + The reference code will call the function submitted by the student. + The reference code will check for the expected output. + + If the path's start with a "/" then we assume they are absolute paths. + If not, we assume they are relative paths w.r.t. the location of this + code_server script. + + If the optional `in_dir` keyword argument is supplied it changes the + directory to that directory (it does not change it back to the original + when done). + + Returns + ------- + + A tuple: (success, error message). + """ + + self._setup() + success, err = self._evaluate(self.test_case_args) + self._teardown() + + result = {'success': success, 'error': err} + return result + + # Private Protocol ########## + def _setup(self): + self._change_dir(self.in_dir) + + def _evaluate(self, args): + # Add a new signal handler for the execution of this code. + prev_handler = create_signal_handler() + success = False + args = args or [] + + # Do whatever testing needed. + try: + success, err = self._check_code(*args) + + except TimeoutException: + err = self.timeout_msg + except: + _type, value = sys.exc_info()[:2] + err = "Error: {0}".format(repr(value)) + finally: + # Set back any original signal handler. + set_original_signal_handler(prev_handler) + + return success, err + + def _teardown(self): + # Cancel the signal + delete_signal_handler() + + def _check_code(self): + raise NotImplementedError("check_code method not implemented") + + def create_submit_code_file(self, file_name): + """ Write the code (`answer`) to a file and set the file path""" + submit_f = open(file_name, 'w') + submit_f.write(self.user_answer.lstrip()) + submit_f.close() + submit_path = abspath(submit_f.name) + + return submit_path + + def _set_file_as_executable(self, fname): + os.chmod(fname, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR + | stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP + | stat.S_IROTH | stat.S_IWOTH | stat.S_IXOTH) + + def _set_test_code_file_path(self, ref_path=None, test_case_path=None): + if ref_path and not ref_path.startswith('/'): + ref_path = join(MY_DIR, ref_path) + + if test_case_path and not test_case_path.startswith('/'): + test_case_path = join(MY_DIR, test_case_path) + + return ref_path, test_case_path + + def _run_command(self, cmd_args, *args, **kw): + """Run a command in a subprocess while blocking, the process is killed + if it takes more than 2 seconds to run. Return the Popen object, the + stdout and stderr. + """ + try: + proc = subprocess.Popen(cmd_args, *args, **kw) + stdout, stderr = proc.communicate() + except TimeoutException: + # Runaway code, so kill it. + proc.kill() + # Re-raise exception. + raise + return proc, stdout, stderr + + def _compile_command(self, cmd, *args, **kw): + """Compiles C/C++/java code and returns errors if any. + Run a command in a subprocess while blocking, the process is killed + if it takes more than 2 seconds to run. Return the Popen object, the + stderr. + """ + try: + proc_compile = subprocess.Popen(cmd, shell=True, stdin=None, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + out, err = proc_compile.communicate() + except TimeoutException: + # Runaway code, so kill it. + proc_compile.kill() + # Re-raise exception. + raise + return proc_compile, err + + def _change_dir(self, in_dir): + if in_dir is not None and isdir(in_dir): + os.chdir(in_dir) + + def _remove_null_substitute_char(self, string): + """Returns a string without any null and substitute characters""" + stripped = "" + for c in string: + if ord(c) is not 26 and ord(c) is not 0: + stripped = stripped + c + return ''.join(stripped) diff --git a/testapp/yaksh/code_server.py b/testapp/yaksh/code_server.py new file mode 100755 index 0000000..2593752 --- /dev/null +++ b/testapp/yaksh/code_server.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python +"""This server runs an XMLRPC server that can be submitted code and tests +and returns the output. It *should* be run as root and will run as the user +'nobody' so as to minimize any damange by errant code. This can be configured +by editing settings.py to run as many servers as desired. One can also +specify the ports on the command line. Here are examples:: + + $ sudo ./code_server.py + # Runs servers based on settings.py:SERVER_PORTS one server per port given. + +or:: + + $ sudo ./code_server.py 8001 8002 8003 8004 8005 + # Runs 5 servers on ports specified. + +All these servers should be running as nobody. This will also start a server +pool that defaults to port 50000 and is configurable in +settings.py:SERVER_POOL_PORT. This port exposes a `get_server_port` function +that returns an available server. +""" +import sys +from SimpleXMLRPCServer import SimpleXMLRPCServer +import pwd +import os +import stat +from os.path import isdir, dirname, abspath, join, isfile +import signal +from multiprocessing import Process, Queue +import subprocess +import re +import json +# Local imports. +from settings import SERVER_PORTS, SERVER_POOL_PORT +from language_registry import set_registry, get_registry + + +MY_DIR = abspath(dirname(__file__)) + + +# Private Protocol ########## +def run_as_nobody(): + """Runs the current process as nobody.""" + # Set the effective uid and to that of nobody. + nobody = pwd.getpwnam('nobody') + os.setegid(nobody.pw_gid) + os.seteuid(nobody.pw_uid) + + +############################################################################### +# `CodeServer` class. +############################################################################### +class CodeServer(object): + """A code server that executes user submitted test code, tests it and + reports if the code was correct or not. + """ + def __init__(self, port, queue): + self.port = port + self.queue = queue + + # Public Protocol ########## + def check_code(self, language, json_data, in_dir=None): + """Calls relevant EvaluateCode class based on language to check the + answer code + """ + code_evaluator = self._create_evaluator_instance(language, json_data, + in_dir) + result = code_evaluator.evaluate() + + # Put us back into the server pool queue since we are free now. + self.queue.put(self.port) + + return json.dumps(result) + + def run(self): + """Run XMLRPC server, serving our methods.""" + server = SimpleXMLRPCServer(("localhost", self.port)) + self.server = server + server.register_instance(self) + self.queue.put(self.port) + server.serve_forever() + + # Private Protocol ########## + def _create_evaluator_instance(self, language, json_data, in_dir): + """Create instance of relevant EvaluateCode class based on language""" + set_registry() + registry = get_registry() + cls = registry.get_class(language) + instance = cls.from_json(language, json_data, in_dir) + return instance + + +############################################################################### +# `ServerPool` class. +############################################################################### +class ServerPool(object): + """Manages a pool of CodeServer objects.""" + def __init__(self, ports, pool_port=50000): + """Create a pool of servers. Uses a shared Queue to get available + servers. + + Parameters + ---------- + + ports : list(int) + List of ports at which the CodeServer's should run. + + pool_port : int + Port at which the server pool should serve. + """ + self.my_port = pool_port + self.ports = ports + queue = Queue(maxsize=len(ports)) + self.queue = queue + servers = [] + for port in ports: + server = CodeServer(port, queue) + servers.append(server) + p = Process(target=server.run) + p.start() + self.servers = servers + + # Public Protocol ########## + + def get_server_port(self): + """Get available server port from ones in the pool. This will block + till it gets an available server. + """ + q = self.queue + was_waiting = True if q.empty() else False + port = q.get() + if was_waiting: + print '*'*80 + print "No available servers, was waiting but got server \ + later at %d." % port + print '*'*80 + sys.stdout.flush() + return port + + def run(self): + """Run server which returns an available server port where code + can be executed. + """ + server = SimpleXMLRPCServer(("localhost", self.my_port)) + self.server = server + server.register_instance(self) + server.serve_forever() + + +############################################################################### +def main(args=None): + run_as_nobody() + if args: + ports = [int(x) for x in args[1:]] + else: + ports = SERVER_PORTS + + server_pool = ServerPool(ports=ports, pool_port=SERVER_POOL_PORT) + server_pool.run() + +if __name__ == '__main__': + args = sys.argv[1:] + main(args) diff --git a/testapp/yaksh/cpp_code_evaluator.py b/testapp/yaksh/cpp_code_evaluator.py new file mode 100644 index 0000000..7242884 --- /dev/null +++ b/testapp/yaksh/cpp_code_evaluator.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python +import traceback +import pwd +import os +from os.path import join, isfile +import subprocess +import importlib + +# local imports +from code_evaluator import CodeEvaluator + + +class CppCodeEvaluator(CodeEvaluator): + """Tests the C code obtained from Code Server""" + def __init__(self, test_case_data, test, language, user_answer, + ref_code_path=None, in_dir=None): + super(CppCodeEvaluator, self).__init__(test_case_data, test, language, + user_answer, ref_code_path, + in_dir) + self.test_case_args = self._setup() + + # Private Protocol ########## + def _setup(self): + super(CppCodeEvaluator, self)._setup() + + get_ref_path = self.ref_code_path + ref_path, test_case_path = self._set_test_code_file_path(get_ref_path) + self.submit_path = self.create_submit_code_file('submit.c') + + # Set file paths + c_user_output_path = os.getcwd() + '/output' + c_ref_output_path = os.getcwd() + '/executable' + + # Set command variables + compile_command = 'g++ {0} -c -o {1}'.format(self.submit_path, + c_user_output_path) + compile_main = 'g++ {0} {1} -o {2}'.format(ref_path, + c_user_output_path, + c_ref_output_path) + run_command_args = [c_ref_output_path] + remove_user_output = c_user_output_path + remove_ref_output = c_ref_output_path + + return (ref_path, self.submit_path, compile_command, compile_main, + run_command_args, remove_user_output, remove_ref_output) + + def _teardown(self): + # Delete the created file. + super(CppCodeEvaluator, self)._teardown() + os.remove(self.submit_path) + + def _check_code(self, ref_code_path, submit_code_path, compile_command, + compile_main, run_command_args, remove_user_output, + remove_ref_output): + """ Function validates student code using instructor code as + reference.The first argument ref_code_path, is the path to + instructor code, it is assumed to have executable permission. + The second argument submit_code_path, is the path to the student + code, it is assumed to have executable permission. + + Returns + -------- + + returns (True, "Correct answer") : If the student function returns + expected output when called by reference code. + + returns (False, error_msg): If the student function fails to return + expected output when called by reference code. + + Returns (False, error_msg): If mandatory arguments are not files or + if the required permissions are not given to the file(s). + + """ + if not isfile(ref_code_path): + return False, "No file at %s or Incorrect path" % ref_code_path + if not isfile(submit_code_path): + return False, 'No file at %s or Incorrect path' % submit_code_path + + success = False + ret = self._compile_command(compile_command) + proc, stdnt_stderr = ret + stdnt_stderr = self._remove_null_substitute_char(stdnt_stderr) + + # Only if compilation is successful, the program is executed + # And tested with testcases + if stdnt_stderr == '': + ret = self._compile_command(compile_main) + proc, main_err = ret + main_err = self._remove_null_substitute_char(main_err) + + if main_err == '': + ret = self._run_command(run_command_args, stdin=None, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + proc, stdout, stderr = ret + if proc.returncode == 0: + success, err = True, "Correct answer" + else: + err = stdout + "\n" + stderr + os.remove(remove_ref_output) + else: + err = "Error:" + try: + error_lines = main_err.splitlines() + for e in error_lines: + if ':' in e: + err = err + "\n" + e.split(":", 1)[1] + else: + err = err + "\n" + e + except: + err = err + "\n" + main_err + os.remove(remove_user_output) + else: + err = "Compilation Error:" + try: + error_lines = stdnt_stderr.splitlines() + for e in error_lines: + if ':' in e: + err = err + "\n" + e.split(":", 1)[1] + else: + err = err + "\n" + e + except: + err = err + "\n" + stdnt_stderr + + return success, err diff --git a/testapp/yaksh/docs/sample.args b/testapp/yaksh/docs/sample.args new file mode 100644 index 0000000..4d9f00d --- /dev/null +++ b/testapp/yaksh/docs/sample.args @@ -0,0 +1,2 @@ +1 2 +2 1 diff --git a/testapp/yaksh/docs/sample.sh b/testapp/yaksh/docs/sample.sh new file mode 100755 index 0000000..e935cb3 --- /dev/null +++ b/testapp/yaksh/docs/sample.sh @@ -0,0 +1,2 @@ +#!/bin/bash +[[ $# -eq 2 ]] && echo $(( $1 + $2 )) && exit $(( $1 + $2 )) diff --git a/testapp/yaksh/docs/sample_questions.py b/testapp/yaksh/docs/sample_questions.py new file mode 100644 index 0000000..60f32cb --- /dev/null +++ b/testapp/yaksh/docs/sample_questions.py @@ -0,0 +1,84 @@ +from datetime import date + +questions = [ +[Question( + summary='Factorial', + points=2, + language='python', + type='code', + description=''' +Write a function called fact
which takes a single integer argument +(sayn
) and returns the factorial of the number. +For example:
+fact(3) -> 6
+''', + test=''' +assert fact(0) == 1 +assert fact(5) == 120 +''', + snippet="def fact(num):" + ), +#Add tags here as a list of string. +['Python','function','factorial'], +], + +[Question( + summary='Simple function', + points=1, + language='python', + type='code', + description='''Create a simple function calledsqr
which takes a single +argument and returns the square of the argument. For example:
+sqr(3) -> 9
.''', + test=''' +import math +assert sqr(3) == 9 +assert abs(sqr(math.sqrt(2)) - 2.0) < 1e-14 + ''', + snippet="def sqr(num):" + ), +#Add tags here as a list of string. +['Python','function'], +], + +[Question( + summary='Bash addition', + points=2, + language='bash', + type='code', + description='''Write a shell script which takes two arguments on the + command line and prints the sum of the two on the output.''', + test='''\ +docs/sample.sh +docs/sample.args +''', + snippet="#!/bin/bash" + ), +#Add tags here as a list of string. +[''], +], + +[Question( + summary='Size of integer in Python', + points=0.5, + language='python', + type='mcq', + description='''What is the largest integer value that can be represented +in Python?''', + options='''No Limit +2**32 +2**32 - 1 +None of the above +''', + test = "No Limit" + ), +#Add tags here as a list of string. +['mcq'], +], + +] #list of questions ends here + +quiz = Quiz(start_date=date.today(), + duration=10, + description='Basic Python Quiz 1' + ) diff --git a/testapp/yaksh/docs/sample_questions.xml b/testapp/yaksh/docs/sample_questions.xml new file mode 100644 index 0000000..53c76f8 --- /dev/null +++ b/testapp/yaksh/docs/sample_questions.xml @@ -0,0 +1,43 @@ ++ + diff --git a/testapp/yaksh/forms.py b/testapp/yaksh/forms.py new file mode 100644 index 0000000..8878114 --- /dev/null +++ b/testapp/yaksh/forms.py @@ -0,0 +1,267 @@ +from django import forms +from testapp.yaksh.models import Profile, Quiz, Question, TestCase + +from django.contrib.auth import authenticate +from django.contrib.auth.models import User +from taggit.managers import TaggableManager +from taggit.forms import TagField +from django.forms.models import inlineformset_factory + +from string import letters, punctuation, digits +import datetime + +languages = ( + ("select", "Select Language"), + ("python", "Python"), + ("bash", "Bash"), + ("c", "C Language"), + ("cpp", "C++ Language"), + ("java", "Java Language"), + ("scilab", "Scilab"), + ) + +question_types = ( + ("select", "Select Question Type"), + ("mcq", "Multiple Choice"), + ("mcc", "Multiple Correct Choices"), + ("code", "Code"), + ("upload", "Assignment Upload"), + ) + +UNAME_CHARS = letters + "._" + digits +PWD_CHARS = letters + punctuation + digits + +attempts = [(i, i) for i in range(1, 6)] +attempts.append((-1, 'Infinite')) +days_between_attempts = ((j, j) for j in range(401)) + + +class UserRegisterForm(forms.Form): + """A Class to create new form for User's Registration. + It has the various fields and functions required to register + a new user to the system""" + + username = forms.CharField(max_length=30, help_text='Letters, digits,\ + period and underscores only.') + email = forms.EmailField() + password = forms.CharField(max_length=30, widget=forms.PasswordInput()) + confirm_password = forms.CharField\ + (max_length=30, widget=forms.PasswordInput()) + first_name = forms.CharField(max_length=30) + last_name = forms.CharField(max_length=30) + roll_number = forms.CharField\ + (max_length=30, help_text="Use a dummy if you don't have one.") + institute = forms.CharField\ + (max_length=128, help_text='Institute/Organization') + department = forms.CharField\ + (max_length=64, help_text='Department you work/study at') + position = forms.CharField\ + (max_length=64, help_text='Student/Faculty/Researcher/Industry/etc.') + + def clean_username(self): + u_name = self.cleaned_data["username"] + if u_name.strip(UNAME_CHARS): + msg = "Only letters, digits, period and underscore characters are"\ + " allowed in username" + raise forms.ValidationError(msg) + try: + User.objects.get(username__exact=u_name) + raise forms.ValidationError("Username already exists.") + except User.DoesNotExist: + return u_name + + def clean_password(self): + pwd = self.cleaned_data['password'] + if pwd.strip(PWD_CHARS): + raise forms.ValidationError("Only letters, digits and punctuation\ + are allowed in password") + return pwd + + def clean_confirm_password(self): + c_pwd = self.cleaned_data['confirm_password'] + pwd = self.data['password'] + if c_pwd != pwd: + raise forms.ValidationError("Passwords do not match") + + return c_pwd + + def save(self): + u_name = self.cleaned_data["username"] + u_name = u_name.lower() + pwd = self.cleaned_data["password"] + email = self.cleaned_data['email'] + new_user = User.objects.create_user(u_name, email, pwd) + + new_user.first_name = self.cleaned_data["first_name"] + new_user.last_name = self.cleaned_data["last_name"] + new_user.save() + + cleaned_data = self.cleaned_data + new_profile = Profile(user=new_user) + new_profile.roll_number = cleaned_data["roll_number"] + new_profile.institute = cleaned_data["institute"] + new_profile.department = cleaned_data["department"] + new_profile.position = cleaned_data["position"] + new_profile.save() + + return u_name, pwd + + +class UserLoginForm(forms.Form): + """Creates a form which will allow the user to log into the system.""" + + username = forms.CharField(max_length=30) + password = forms.CharField(max_length=30, widget=forms.PasswordInput()) + + def clean(self): + super(UserLoginForm, self).clean() + try: + u_name, pwd = self.cleaned_data["username"],\ + self.cleaned_data["password"] + user = authenticate(username=u_name, password=pwd) + except Exception: + raise forms.ValidationError\ + ("Username and/or Password is not entered") + if not user: + raise forms.ValidationError("Invalid username/password") + return user + + +class QuizForm(forms.Form): + """Creates a form to add or edit a Quiz. + It has the related fields and functions required.""" + + def __init__(self, *args, **kwargs): + super(QuizForm, self).__init__(*args, **kwargs) + quizzes = [('', 'Select a prerequisite quiz')] + quizzes = quizzes + \ + list(Quiz.objects.values_list('id', 'description')) + self.fields['prerequisite'] = forms.CharField(required=False, + widget=forms.Select(choices=quizzes)) + + start_date = forms.DateField(initial=datetime.date.today(), required=False) + start_time = forms.TimeField(initial=datetime.datetime.now().time(), required=False) + end_date = forms.DateField(initial=datetime.date(2199, 1, 1), required=False) + end_time = forms.TimeField(initial=datetime.time(0, 0, 0, 0), required=False) + duration = forms.IntegerField(help_text='Will be taken in minutes') + active = forms.BooleanField(required=False) + description = forms.CharField(max_length=256, widget=forms.Textarea\ + (attrs={'cols': 20, 'rows': 1})) + pass_criteria = forms.FloatField(initial=40, + help_text='Will be taken as percentage') + language = forms.CharField(widget=forms.Select(choices=languages)) + attempts_allowed = forms.IntegerField(widget=forms.Select(choices=attempts)) + time_between_attempts = forms.IntegerField\ + (widget=forms.Select(choices=days_between_attempts), + help_text='Will be in days') + + def save(self): + start_date = self.cleaned_data["start_date"] + start_time = self.cleaned_data["start_time"] + end_date = self.cleaned_data["end_date"] + end_time = self.cleaned_data["end_time"] + duration = self.cleaned_data["duration"] + active = self.cleaned_data['active'] + description = self.cleaned_data["description"] + pass_criteria = self.cleaned_data["pass_criteria"] + language = self.cleaned_data["language"] + prerequisite = self.cleaned_data["prerequisite"] + attempts_allowed = self.cleaned_data["attempts_allowed"] + time_between_attempts = self.cleaned_data["time_between_attempts"] + new_quiz = Quiz() + new_quiz.start_date_time = datetime.datetime.combine(start_date, + start_time) + new_quiz.end_date_time = datetime.datetime.combine(end_date, + end_time) + new_quiz.duration = duration + new_quiz.active = active + new_quiz.description = description + new_quiz.pass_criteria = pass_criteria + new_quiz.language = language + new_quiz.prerequisite_id = prerequisite + new_quiz.attempts_allowed = attempts_allowed + new_quiz.time_between_attempts = time_between_attempts + new_quiz.save() + + +class QuestionForm(forms.ModelForm): + """Creates a form to add or edit a Question. + It has the related fields and functions required.""" + + summary = forms.CharField(widget=forms.Textarea\ + (attrs={'cols': 40, 'rows': 1})) + description = forms.CharField(widget=forms.Textarea\ + (attrs={'cols': 40, 'rows': 1})) + points = forms.FloatField() + test = forms.CharField(widget=forms.Textarea\ + (attrs={'cols': 40, 'rows': 1}), required=False) + options = forms.CharField(widget=forms.Textarea\ + (attrs={'cols': 40, 'rows': 1}), required=False) + language = forms.CharField(max_length=20, widget=forms.Select\ + (choices=languages)) + type = forms.CharField(max_length=8, widget=forms.Select\ + (choices=question_types)) + active = forms.BooleanField(required=False) + tags = TagField(required=False) + snippet = forms.CharField(widget=forms.Textarea\ + (attrs={'cols': 40, 'rows': 1}), required=False) + ref_code_path = forms.CharField(widget=forms.Textarea\ + (attrs={'cols': 40, 'rows': 1}), required=False) + + def save(self, commit=True): + summary = self.cleaned_data.get("summary") + description = self.cleaned_data.get("description") + points = self.cleaned_data.get("points") + test = self.cleaned_data.get("test") + options = self.cleaned_data.get("options") + language = self.cleaned_data.get("language") + type = self.cleaned_data.get("type") + active = self.cleaned_data.get("active") + snippet = self.cleaned_data.get("snippet") + + new_question = Question() + new_question.summary = summary + new_question.description = description + new_question.points = points + new_question.test = test + new_question.options = options + new_question.language = language + new_question.type = type + new_question.active = active + new_question.snippet = snippet + new_question = super(QuestionForm, self).save(commit=False) + if commit: + new_question.save() + + return new_question + + class Meta: + model = Question + + +class RandomQuestionForm(forms.Form): + question_type = forms.CharField(max_length=8, widget=forms.Select\ + (choices=question_types)) + marks = forms.CharField(max_length=8, widget=forms.Select\ + (choices=(('select', 'Select Marks'),))) + shuffle_questions = forms.BooleanField(required=False) + + +class QuestionFilterForm(forms.Form): + def __init__(self, *args, **kwargs): + super(QuestionFilterForm, self).__init__(*args, **kwargs) + questions = Question.objects.all() + points_list = questions.values_list('points', flat=True).distinct() + points_options = [('select', 'Select Marks')] + points_options.extend([(point, point) for point in points_list]) + self.fields['marks'] = forms.FloatField(widget=forms.Select\ + (choices=points_options)) + + language = forms.CharField(max_length=8, widget=forms.Select\ + (choices=languages)) + question_type = forms.CharField(max_length=8, widget=forms.Select\ + (choices=question_types)) + + +TestCaseFormSet = inlineformset_factory(Question, TestCase,\ + can_order=False, can_delete=False, extra=1) diff --git a/testapp/yaksh/java_code_evaluator.py b/testapp/yaksh/java_code_evaluator.py new file mode 100644 index 0000000..4367259 --- /dev/null +++ b/testapp/yaksh/java_code_evaluator.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +import traceback +import pwd +import os +from os.path import join, isfile +import subprocess +import importlib + +# local imports +from code_evaluator import CodeEvaluator + + +class JavaCodeEvaluator(CodeEvaluator): + """Tests the Java code obtained from Code Server""" + def __init__(self, test_case_data, test, language, user_answer, + ref_code_path=None, in_dir=None): + super(JavaCodeEvaluator, self).__init__(test_case_data, test, + language, user_answer, + ref_code_path, in_dir) + self.test_case_args = self._setup() + + # Private Protocol ########## + def _setup(self): + super(JavaCodeEvaluator, self)._setup() + + ref_path, test_case_path = self._set_test_code_file_path(self.ref_code_path) + self.submit_path = self.create_submit_code_file('Test.java') + + # Set file paths + java_student_directory = os.getcwd() + '/' + java_ref_file_name = (ref_path.split('/')[-1]).split('.')[0] + + # Set command variables + compile_command = 'javac {0}'.format(self.submit_path), + compile_main = ('javac {0} -classpath ' + '{1} -d {2}').format(ref_path, + java_student_directory, + java_student_directory) + run_command_args = "java -cp {0} {1}".format(java_student_directory, + java_ref_file_name) + remove_user_output = "{0}{1}.class".format(java_student_directory, + 'Test') + remove_ref_output = "{0}{1}.class".format(java_student_directory, + java_ref_file_name) + + return (ref_path, self.submit_path, compile_command, compile_main, + run_command_args, remove_user_output, remove_ref_output) + + def _teardown(self): + # Delete the created file. + super(JavaCodeEvaluator, self)._teardown() + os.remove(self.submit_path) + + def _check_code(self, ref_code_path, submit_code_path, compile_command, + compile_main, run_command_args, remove_user_output, + remove_ref_output): + """ Function validates student code using instructor code as + reference.The first argument ref_code_path, is the path to + instructor code, it is assumed to have executable permission. + The second argument submit_code_path, is the path to the student + code, it is assumed to have executable permission. + + Returns + -------- + + returns (True, "Correct answer") : If the student function returns + expected output when called by reference code. + + returns (False, error_msg): If the student function fails to return + expected output when called by reference code. + + Returns (False, error_msg): If mandatory arguments are not files or + if the required permissions are not given to the file(s). + + """ + if not isfile(ref_code_path): + return False, "No file at %s or Incorrect path" % ref_code_path + if not isfile(submit_code_path): + return False, 'No file at %s or Incorrect path' % submit_code_path + + success = False + ret = self._compile_command(compile_command) + proc, stdnt_stderr = ret + stdnt_stderr = self._remove_null_substitute_char(stdnt_stderr) + + # Only if compilation is successful, the program is executed + # And tested with testcases + if stdnt_stderr == '': + ret = self._compile_command(compile_main) + proc, main_err = ret + main_err = self._remove_null_substitute_char(main_err) + + if main_err == '': + ret = self._run_command(run_command_args, shell=True, + stdin=None, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + proc, stdout, stderr = ret + if proc.returncode == 0: + success, err = True, "Correct answer" + else: + err = stdout + "\n" + stderr + os.remove(remove_ref_output) + else: + err = "Error:" + try: + error_lines = main_err.splitlines() + for e in error_lines: + if ':' in e: + err = err + "\n" + e.split(":", 1)[1] + else: + err = err + "\n" + e + except: + err = err + "\n" + main_err + os.remove(remove_user_output) + else: + err = "Compilation Error:" + try: + error_lines = stdnt_stderr.splitlines() + for e in error_lines: + if ':' in e: + err = err + "\n" + e.split(":", 1)[1] + else: + err = err + "\n" + e + except: + err = err + "\n" + stdnt_stderr + + return success, err diff --git a/testapp/yaksh/java_files/main_array_sum.java b/testapp/yaksh/java_files/main_array_sum.java new file mode 100644 index 0000000..5eae299 --- /dev/null +++ b/testapp/yaksh/java_files/main_array_sum.java @@ -0,0 +1,36 @@ +class main_array_sum +{ + public static+ + ++Factorial + ++Write a function called "fact" which takes a single integer argument (say "n") +and returns the factorial of the number. +For example fact(3) -> 6 + +2 +python ++assert fact(0) == 1 +assert fact(5) == 120 + ++ ++ + + ++Simple function + ++Create a simple function called "sqr" which takes a single argument and +returns the square of the argument +For example sqr(3) -> 9. + +1 +python ++import math +assert sqr(3) == 9 +assert abs(sqr(math.sqrt(2)) - 2.0) < 1e-14 + ++ +void check(E expect, E result) + { + if(result.equals(expect)) + { + System.out.println("Correct:\nOutput expected "+expect+" and got "+result); + } + else + { + System.out.println("Incorrect:\nOutput expected "+expect+" but got "+result); + System.exit(1); + } + } + public static void main(String arg[]) + { + int result; + Test t = new Test(); + int x[] = {0,0,0,0,0}; + result = t.array_sum(x); + System.out.println("Input submitted to the function: {0,0,0,0,0}"); + check(0, result); + int a[] = {1,2,3,4,5}; + result = t.array_sum(a); + System.out.println("Input submitted to the function: {1,2,3,4,5}"); + check(15, result); + int b[] = {1,2,3,0,0}; + result = t.array_sum(b); + System.out.println("Input submitted to the function: {1,2,3,0,0}"); + check(6, result); + int c[] = {1,1,1,1,1}; + result = t.array_sum(c); + System.out.println("Input submitted to the function: {1,1,1,1,1}"); + check(5, result); + } +} diff --git a/testapp/yaksh/java_files/main_fact.java b/testapp/yaksh/java_files/main_fact.java new file mode 100644 index 0000000..325dab6 --- /dev/null +++ b/testapp/yaksh/java_files/main_fact.java @@ -0,0 +1,29 @@ +class main_fact +{ + public static void check(E expect, E result) + { + if(result.equals(expect)) + { + System.out.println("Correct:\nOutput expected "+expect+" and got "+result); + } + else + { + System.out.println("Incorrect:\nOutput expected "+expect+" but got "+result); + System.exit(1); + } + } + public static void main(String arg[]) + { + Test t = new Test(); + int result; + result = t.factorial(0); + System.out.println("Input submitted to the function: 0"); + check(1, result); + result = t.factorial(3); + System.out.println("Input submitted to the function: 3"); + check(6, result); + result = t.factorial(4); + System.out.println("Input submitted to the function: 4"); + check(24, result); + } +} diff --git a/testapp/yaksh/java_files/main_great.java b/testapp/yaksh/java_files/main_great.java new file mode 100644 index 0000000..4bfcb1f --- /dev/null +++ b/testapp/yaksh/java_files/main_great.java @@ -0,0 +1,39 @@ +class main_great +{ + public static void check(E expect, E result) + { + if(result.equals(expect)) + { + System.out.println("Correct:\nOutput expected "+expect+" and got "+result); + } + else + { + System.out.println("Incorrect:\nOutput expected "+expect+" but got "+result); + System.exit(1); + } + } + public static void main(String arg[]) + { + Test t = new Test(); + int result; + result = t.greatest(1, 3, 4); + System.out.println("Input submitted to the function: 1, 3, 4"); + check(4, result); + result = t.greatest(5, 10, 3); + System.out.println("Input submitted to the function: 5, 10, 3"); + check(10, result); + result = t.greatest(6, 1, 4); + System.out.println("Input submitted to the function: 6, 1, 4"); + check(6, result); + result = t.greatest(6, 11, 14); + System.out.println("Input submitted to the function: 6, 11, 14"); + check(14, result); + result = t.greatest(3, 31, 4); + System.out.println("Input submitted to the function: 3, 31, 4"); + check(31, result); + result = t.greatest(26, 13, 3); + System.out.println("Input submitted to the function: 26, 13, 3"); + check(26, result); + + } +} diff --git a/testapp/yaksh/java_files/main_hello_name.java b/testapp/yaksh/java_files/main_hello_name.java new file mode 100644 index 0000000..84bb282 --- /dev/null +++ b/testapp/yaksh/java_files/main_hello_name.java @@ -0,0 +1,29 @@ +class main_hello_name +{ + public static void check(E expect, E result) + { + if(result.equals(expect)) + { + System.out.println("Correct:\nOutput expected "+expect+" and got "+result); + } + else + { + System.out.println("Incorrect:\nOutput expected "+expect+" but got "+result); + System.exit(1); + } + } + public static void main(String arg[]) + { + Test t = new Test(); + String result; + result = t.hello_name("Raj"); + System.out.println("Input submitted to the function: 'Raj'"); + check("hello Raj", result); + result = t.hello_name("Pratham"); + System.out.println("Input submitted to the function: 'Pratham'"); + check("hello Pratham", result); + result = t.hello_name("Ram"); + System.out.println("Input submitted to the function: 'Ram'"); + check("hello Ram", result); + } +} diff --git a/testapp/yaksh/java_files/main_lastDigit.java b/testapp/yaksh/java_files/main_lastDigit.java new file mode 100644 index 0000000..05439e2 --- /dev/null +++ b/testapp/yaksh/java_files/main_lastDigit.java @@ -0,0 +1,36 @@ +class main_lastDigit +{ + public static void check(E expect, E result) + { + if(result.equals(expect)) + { + System.out.println("Correct:\nOutput expected "+expect+" and got "+result+"\n"); + } + else + { + System.out.println("Incorrect:\nOutput expected "+expect+" but got "+result+"\n"); + System.exit(1); + } + } + public static void main(String arg[]) + { + Test t = new Test(); + boolean result; + result= t.lastDigit(12, 2, 13); + System.out.println("Input submitted to the function: 12, 2, 13"); + check(true, result); + result = t.lastDigit(11, 52, 32); + System.out.println("Input submitted to the function: 11, 52, 32"); + check(true, result); + result = t.lastDigit(6, 34, 22); + System.out.println("Input submitted to the function: 6, 34, 22"); + check(false, result); + result = t.lastDigit(6, 46, 26); + System.out.println("Input submitted to the function: 63"); + check(true, result); + result = t.lastDigit(91, 90, 92); + System.out.println("Input submitted to the function: 91"); + check(false, result); + + } +} diff --git a/testapp/yaksh/java_files/main_moreThan30.java b/testapp/yaksh/java_files/main_moreThan30.java new file mode 100644 index 0000000..7da31cb --- /dev/null +++ b/testapp/yaksh/java_files/main_moreThan30.java @@ -0,0 +1,36 @@ +class main_moreThan30 +{ + public static void check(E expect, E result) + { + if(result.equals(expect)) + { + System.out.println("Correct:\nOutput expected "+expect+" and got "+result+"\n"); + } + else + { + System.out.println("Incorrect:\nOutput expected "+expect+" but got "+result+"\n"); + System.exit(1); + } + } + public static void main(String arg[]) + { + Test t = new Test(); + boolean result; + result= t.moreThan30(30); + System.out.println("Input submitted to the function: 30"); + check(false, result); + result = t.moreThan30(151); + System.out.println("Input submitted to the function: 151"); + check(true, result); + result = t.moreThan30(66); + System.out.println("Input submitted to the function: 66"); + check(false, result); + result = t.moreThan30(63); + System.out.println("Input submitted to the function: 63"); + check(true, result); + result = t.moreThan30(91); + System.out.println("Input submitted to the function: 91"); + check(true, result); + + } +} diff --git a/testapp/yaksh/java_files/main_palindrome.java b/testapp/yaksh/java_files/main_palindrome.java new file mode 100644 index 0000000..c0745f9 --- /dev/null +++ b/testapp/yaksh/java_files/main_palindrome.java @@ -0,0 +1,29 @@ +class main_palindrome +{ + public static void check(E expect, E result) + { + if(result.equals(expect)) + { + System.out.println("Correct:\nOutput expected "+expect+" and got "+result+"\n"); + } + else + { + System.out.println("Incorrect:\nOutput expected "+expect+" but got "+result+"\n"); + System.exit(1); + } + } + public static void main(String arg[]) + { + Test t = new Test(); + boolean result; + result= t.palindrome(123); + System.out.println("Input submitted to the function: 123"); + check(false, result); + result = t.palindrome(151); + System.out.println("Input submitted to the function: 151"); + check(true, result); + result = t.palindrome(23432); + System.out.println("Input submitted to the function: 23432"); + check(true, result); + } +} diff --git a/testapp/yaksh/java_files/main_square.java b/testapp/yaksh/java_files/main_square.java new file mode 100644 index 0000000..5cb8c35 --- /dev/null +++ b/testapp/yaksh/java_files/main_square.java @@ -0,0 +1,32 @@ +class main_square +{ + public static void check(E expect, E result) + { + if(result.equals(expect)) + { + System.out.println("Correct:\nOutput expected "+expect+" and got "+result); + } + else + { + System.out.println("Incorrect:\nOutput expected "+expect+" but got "+result); + System.exit(1); + } + } + public static void main(String arg[]) + { + Test t = new Test(); + int result, input, output; + input = 0; output = 0; + result = t.square_num(input); + System.out.println("Input submitted to the function: "+input); + check(output, result); + input = 5; output = 25; + result = t.square_num(input); + System.out.println("Input submitted to the function: "+input); + check(output, result); + input = 6; output = 36; + result = t.square_num(input); + System.out.println("Input submitted to the function: "+input); + check(output, result); + } +} diff --git a/testapp/yaksh/language_registry.py b/testapp/yaksh/language_registry.py new file mode 100644 index 0000000..76a23d7 --- /dev/null +++ b/testapp/yaksh/language_registry.py @@ -0,0 +1,36 @@ +from settings import code_evaluators +import importlib + +registry = None + +def set_registry(): + global registry + registry = _LanguageRegistry() + +def get_registry(): + return registry + +class _LanguageRegistry(object): + def __init__(self): + self._register = {} + for language, module in code_evaluators.iteritems(): + self._register[language] = None + + # Public Protocol ########## + def get_class(self, language): + """ Get the code evaluator class for the given language """ + if not self._register.get(language): + self._register[language] = code_evaluators.get(language) + + cls = self._register[language] + module_name, class_name = cls.rsplit(".", 1) + # load the module, will raise ImportError if module cannot be loaded + get_module = importlib.import_module(module_name) + # get the class, will raise AttributeError if class cannot be found + get_class = getattr(get_module, class_name) + return get_class + + def register(self, language, class_name): + """ Register a new code evaluator class for language""" + self._register[language] = class_name + diff --git a/testapp/yaksh/management/__init__.py b/testapp/yaksh/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/testapp/yaksh/management/commands/__init__.py b/testapp/yaksh/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/testapp/yaksh/management/commands/add_group.py b/testapp/yaksh/management/commands/add_group.py new file mode 100644 index 0000000..03ef103 --- /dev/null +++ b/testapp/yaksh/management/commands/add_group.py @@ -0,0 +1,33 @@ +''' + This command adds moderator group with permissions to add, change and delete + the objects in the exam app. + We can modify this command to add more groups by providing arguments. + Arguments like group-name, app-name can be passed. +''' + +# django imports +from django.core.management.base import BaseCommand, CommandError +from django.contrib.auth.models import Group, Permission +from django.contrib.contenttypes.models import ContentType +from django.db.utils import IntegrityError + +class Command(BaseCommand): + help = 'Adds the moderator group' + + def handle(self, *args, **options): + app = 'yaksh' + group = Group(name='moderator') + try: + group.save() + except IntegrityError: + raise CommandError("The group already exits") + else: + # Get the models for the given app + content_types = ContentType.objects.filter(app_label=app) + # Get list of permissions for the models + permission_list = Permission.objects.filter(content_type=content_types) + for permission in permission_list: + group.permissions.add(permission) + group.save() + + self.stdout.write('Moderator group added successfully') diff --git a/testapp/yaksh/management/commands/dump_user_data.py b/testapp/yaksh/management/commands/dump_user_data.py new file mode 100644 index 0000000..302728e --- /dev/null +++ b/testapp/yaksh/management/commands/dump_user_data.py @@ -0,0 +1,98 @@ +import sys + +# Django imports. +from django.core.management.base import BaseCommand +from django.template import Template, Context + +# Local imports. +from testapp.yaksh.views import get_user_data +from testapp.yaksh.models import User + +data_template = Template('''\ +=============================================================================== +Data for {{ data.user.get_full_name.title }} ({{ data.user.username }}) + +Name: {{ data.user.get_full_name.title }} +Username: {{ data.user.username }} +{% if data.profile %}\ +Roll number: {{ data.profile.roll_number }} +Position: {{ data.profile.position }} +Department: {{ data.profile.department }} +Institute: {{ data.profile.institute }} +{% endif %}\ +Email: {{ data.user.email }} +Date joined: {{ data.user.date_joined }} +Last login: {{ data.user.last_login }} +{% for paper in data.papers %} +Paper: {{ paper.quiz.description }} +--------------------------------------- +Marks obtained: {{ paper.get_total_marks }} +Questions correctly answered: {{ paper.get_answered_str }} +Total attempts at questions: {{ paper.answers.count }} +Start time: {{ paper.start_time }} +User IP address: {{ paper.user_ip }} +{% if paper.answers.count %} +Answers +------- +{% for question, answers in paper.get_question_answers.items %} +Question: {{ question.id }}. {{ question.summary }} (Points: {{ question.points }}) +{% if question.type == "mcq" %}\ +############################################################################### +Choices: {% for option in question.options.strip.splitlines %} {{option}}, {% endfor %} +Student answer: {{ answers.0|safe }} +{% else %}{# non-mcq questions #}\ +{% for answer in answers %}\ +############################################################################### +{{ answer.answer.strip|safe }} +# Autocheck: {{ answer.error|safe }} +{% endfor %}{# for answer in answers #}\ +{% endif %}\ +{% with answers|last as answer %}\ +Marks: {{answer.marks}} +{% endwith %}\ +{% endfor %}{# for question, answers ... #}\ + +Teacher comments +----------------- +{{ paper.comments|default:"None" }} +{% endif %}{# if paper.answers.count #}\ +{% endfor %}{# for paper in data.papers #} +''') + + +def dump_user_data(unames, stdout): + '''Dump user data given usernames (a sequence) if none is given dump all + their data. The data is dumped to stdout. + ''' + if not unames: + try: + users = User.objects.all() + except User.DoesNotExist: + pass + else: + users = [] + for uname in unames: + try: + user = User.objects.get(username__exact = uname) + except User.DoesNotExist: + stdout.write('User %s does not exist'%uname) + else: + users.append(user) + + for user in users: + data = get_user_data(user.username) + context = Context({'data': data}) + result = data_template.render(context) + stdout.write(result.encode('ascii', 'xmlcharrefreplace')) + +class Command(BaseCommand): + args = ' ... ' + help = '''Dumps all user data to stdout, optional usernames can be + specified. If none is specified all user data is dumped. + ''' + + def handle(self, *args, **options): + """Handle the command.""" + # Dump data. + dump_user_data(args, self.stdout) + diff --git a/testapp/yaksh/management/commands/load_exam.py b/testapp/yaksh/management/commands/load_exam.py new file mode 100644 index 0000000..84bf762 --- /dev/null +++ b/testapp/yaksh/management/commands/load_exam.py @@ -0,0 +1,57 @@ +# System library imports. +from os.path import basename + +# Django imports. +from django.core.management.base import BaseCommand + +# Local imports. +from testapp.yaksh.models import Question, Quiz + +def clear_exam(): + """Deactivate all questions from the database.""" + for question in Question.objects.all(): + question.active = False + question.save() + + # Deactivate old quizzes. + for quiz in Quiz.objects.all(): + quiz.active = False + quiz.save() + +def load_exam(filename): + """Load questions and quiz from the given Python file. The Python file + should declare a list of name "questions" which define all the questions + in pure Python. It can optionally load a Quiz from an optional 'quiz' + object. + """ + # Simply exec the given file and we are done. + exec(open(filename).read()) + + if 'questions' not in locals(): + msg = 'No variable named "questions" with the Questions in file.' + raise NameError(msg) + + for question in questions: + question[0].save() + for tag in question[1]: + question[0].tags.add(tag) + + if 'quiz' in locals(): + quiz.save() + +class Command(BaseCommand): + args = ' ' + help = '''loads the questions from given Python files which declare the + questions in a list called "questions".''' + + def handle(self, *args, **options): + """Handle the command.""" + # Delete existing stuff. + clear_exam() + + # Load from files. + for fname in args: + self.stdout.write('Importing from {0} ... '.format(basename(fname))) + load_exam(fname) + self.stdout.write('Done\n') + diff --git a/testapp/yaksh/management/commands/load_questions_xml.py b/testapp/yaksh/management/commands/load_questions_xml.py new file mode 100644 index 0000000..0109e40 --- /dev/null +++ b/testapp/yaksh/management/commands/load_questions_xml.py @@ -0,0 +1,73 @@ +# System library imports. +from os.path import basename +from xml.dom.minidom import parse +from htmlentitydefs import name2codepoint +import re + +# Django imports. +from django.core.management.base import BaseCommand + +# Local imports. +from testapp.yaksh.models import Question + +def decode_html(html_str): + """Un-escape or decode HTML strings to more usable Python strings. + From here: http://wiki.python.org/moin/EscapingHtml + """ + return re.sub('&(%s);' % '|'.join(name2codepoint), + lambda m: unichr(name2codepoint[m.group(1)]), html_str) + +def clear_questions(): + """Deactivate all questions from the database.""" + for question in Question.objects.all(): + question.active = False + question.save() + +def load_questions_xml(filename): + """Load questions from the given XML file.""" + q_bank = parse(filename).getElementsByTagName("question") + + for question in q_bank: + + summary_node = question.getElementsByTagName("summary")[0] + summary = (summary_node.childNodes[0].data).strip() + + desc_node = question.getElementsByTagName("description")[0] + description = (desc_node.childNodes[0].data).strip() + + type_node = question.getElementsByTagName("type")[0] + type = (type_node.childNodes[0].data).strip() + + points_node = question.getElementsByTagName("points")[0] + points = float((points_node.childNodes[0].data).strip()) \ + if points_node else 1.0 + + test_node = question.getElementsByTagName("test")[0] + test = decode_html((test_node.childNodes[0].data).strip()) + + opt_node = question.getElementsByTagName("options")[0] + opt = decode_html((opt_node.childNodes[0].data).strip()) + + new_question = Question(summary=summary, + description=description, + points=points, + options=opt, + type=type, + test=test) + new_question.save() + +class Command(BaseCommand): + args = ' ' + help = 'loads the questions from given XML files' + + def handle(self, *args, **options): + """Handle the command.""" + # Delete existing stuff. + clear_questions() + + # Load from files. + for fname in args: + self.stdout.write('Importing from {0} ... '.format(basename(fname))) + load_questions_xml(fname) + self.stdout.write('Done\n') + diff --git a/testapp/yaksh/management/commands/results2csv.py b/testapp/yaksh/management/commands/results2csv.py new file mode 100644 index 0000000..daf6eb9 --- /dev/null +++ b/testapp/yaksh/management/commands/results2csv.py @@ -0,0 +1,69 @@ +# System library imports. +import sys +from os.path import basename + +# Django imports. +from django.core.management.base import BaseCommand +from django.template import Template, Context + +# Local imports. +from testapp.yaksh.models import Quiz, QuestionPaper + +result_template = Template('''\ +"name","username","rollno","email","answered","total","attempts","position",\ +"department","institute" +{% for paper in papers %}\ +"{{ paper.user.get_full_name.title }}",\ +"{{ paper.user.username }}",\ +"{{ paper.profile.roll_number }}",\ +"{{ paper.user.email }}",\ +"{{ paper.get_answered_str }}",\ +{{ paper.get_total_marks }},\ +{{ paper.answers.count }},\ +"{{ paper.profile.position }}",\ +"{{ paper.profile.department }}",\ +"{{ paper.profile.institute }}" +{% endfor %}\ +''') + +def results2csv(filename, stdout): + """Write exam data to a CSV file. It prompts the user to choose the + appropriate quiz. + """ + qs = Quiz.objects.all() + + if len(qs) > 1: + print "Select quiz to save:" + for q in qs: + stdout.write('%d. %s\n'%(q.id, q.description)) + quiz_id = int(raw_input("Please select quiz: ")) + try: + quiz = Quiz.objects.get(id=quiz_id) + except Quiz.DoesNotExist: + stdout.write("Sorry, quiz %d does not exist!\n"%quiz_id) + sys.exit(1) + else: + quiz = qs[0] + + papers = QuestionPaper.objects.filter(quiz=quiz, + user__profile__isnull=False) + stdout.write("Saving results of %s to %s ... "%(quiz.description, + basename(filename))) + # Render the data and write it out. + f = open(filename, 'w') + context = Context({'papers': papers}) + f.write(result_template.render(context)) + f.close() + + stdout.write('Done\n') + +class Command(BaseCommand): + args = ' ' + help = '''Writes out the results of a quiz to a CSV file. Prompt user + to select appropriate quiz if there are multiple. + ''' + + def handle(self, *args, **options): + """Handle the command.""" + # Save to file. + results2csv(args[0], self.stdout) diff --git a/testapp/yaksh/models.py b/testapp/yaksh/models.py new file mode 100644 index 0000000..62ac9bc --- /dev/null +++ b/testapp/yaksh/models.py @@ -0,0 +1,471 @@ +import datetime +import json +from random import sample, shuffle +from itertools import islice, cycle +from django.db import models +from django.contrib.auth.models import User +from taggit.managers import TaggableManager + + +############################################################################### +class Profile(models.Model): + """Profile for a user to store roll number and other details.""" + user = models.OneToOneField(User) + roll_number = models.CharField(max_length=20) + institute = models.CharField(max_length=128) + department = models.CharField(max_length=64) + position = models.CharField(max_length=64) + + +languages = ( + ("python", "Python"), + ("bash", "Bash"), + ("c", "C Language"), + ("cpp", "C++ Language"), + ("java", "Java Language"), + ("scilab", "Scilab"), + ) + + +question_types = ( + ("mcq", "Multiple Choice"), + ("mcc", "Multiple Correct Choices"), + ("code", "Code"), + ("upload", "Assignment Upload"), + ) +attempts = [(i, i) for i in range(1, 6)] +attempts.append((-1, 'Infinite')) +days_between_attempts = ((j, j) for j in range(401)) + +test_status = ( + ('inprogress', 'Inprogress'), + ('completed', 'Completed'), + ) + + +def get_assignment_dir(instance, filename): + return '%s/%s' % (instance.user.roll_number, instance.assignmentQuestion.id) + + +############################################################################### +class Question(models.Model): + """Question for a quiz.""" + + # A one-line summary of the question. + summary = models.CharField(max_length=256) + + # The question text, should be valid HTML. + description = models.TextField() + + # Number of points for the question. + points = models.FloatField(default=1.0) + + # Answer for MCQs. + test = models.TextField(blank=True) + + # Test cases file paths (comma seperated for reference code path and test case code path) + # Applicable for CPP, C, Java and Scilab + ref_code_path = models.TextField(blank=True) + + # Any multiple choice options. Place one option per line. + options = models.TextField(blank=True) + + # The language for question. + language = models.CharField(max_length=24, + choices=languages) + + # The type of question. + type = models.CharField(max_length=24, choices=question_types) + + # Is this question active or not. If it is inactive it will not be used + # when creating a QuestionPaper. + active = models.BooleanField(default=True) + + # Snippet of code provided to the user. + snippet = models.CharField(max_length=256) + + # Tags for the Question. + tags = TaggableManager() + + def consolidate_answer_data(self, test_cases, user_answer): + test_case_data_dict = [] + question_info_dict = {} + + for test_case in test_cases: + kw_args_dict = {} + pos_args_list = [] + + test_case_data = {} + test_case_data['test_id'] = test_case.id + test_case_data['func_name'] = test_case.func_name + test_case_data['expected_answer'] = test_case.expected_answer + + if test_case.kw_args: + for args in test_case.kw_args.split(","): + arg_name, arg_value = args.split("=") + kw_args_dict[arg_name.strip()] = arg_value.strip() + + if test_case.pos_args: + for args in test_case.pos_args.split(","): + pos_args_list.append(args.strip()) + + test_case_data['kw_args'] = kw_args_dict + test_case_data['pos_args'] = pos_args_list + test_case_data_dict.append(test_case_data) + + # question_info_dict['language'] = self.language + question_info_dict['id'] = self.id + question_info_dict['user_answer'] = user_answer + question_info_dict['test_parameter'] = test_case_data_dict + question_info_dict['ref_code_path'] = self.ref_code_path + question_info_dict['test'] = self.test + + return json.dumps(question_info_dict) + + def __unicode__(self): + return self.summary + + +############################################################################### +class Answer(models.Model): + """Answers submitted by the users.""" + + # The question for which user answers. + question = models.ForeignKey(Question) + + # The answer submitted by the user. + answer = models.TextField(null=True, blank=True) + + # Error message when auto-checking the answer. + error = models.TextField() + + # Marks obtained for the answer. This can be changed by the teacher if the + # grading is manual. + marks = models.FloatField(default=0.0) + + # Is the answer correct. + correct = models.BooleanField(default=False) + + # Whether skipped or not. + skipped = models.BooleanField(default=False) + + def __unicode__(self): + return self.answer + + +############################################################################### +class Quiz(models.Model): + """A quiz that students will participate in. One can think of this + as the "examination" event. + """ + + # The start date of the quiz. + start_date_time = models.DateTimeField("Start Date and Time of the quiz", + default=datetime.datetime.now(), + null=True) + + # The end date and time of the quiz + end_date_time = models.DateTimeField("End Date and Time of the quiz", + default=datetime.datetime(2199, 1, 1, 0, 0, 0, 0), + null=True) + + # This is always in minutes. + duration = models.IntegerField("Duration of quiz in minutes", default=20) + + # Is the quiz active. The admin should deactivate the quiz once it is + # complete. + active = models.BooleanField(default=True) + + # Description of quiz. + description = models.CharField(max_length=256) + + # Mininum passing percentage condition. + pass_criteria = models.FloatField("Passing percentage", default=40) + + # List of prerequisite quizzes to be passed to take this quiz + prerequisite = models.ForeignKey("Quiz", null=True) + + # Programming language for a quiz + language = models.CharField(max_length=20, choices=languages) + + # Number of attempts for the quiz + attempts_allowed = models.IntegerField(default=1, choices=attempts) + + time_between_attempts = models.IntegerField("Number of Days",\ + choices=days_between_attempts) + + class Meta: + verbose_name_plural = "Quizzes" + + def __unicode__(self): + desc = self.description or 'Quiz' + return '%s: on %s for %d minutes' % (desc, self.start_date_time, + self.duration) + + +############################################################################### +class QuestionPaper(models.Model): + """Question paper stores the detail of the questions.""" + + # Question paper belongs to a particular quiz. + quiz = models.ForeignKey(Quiz) + + # Questions that will be mandatory in the quiz. + fixed_questions = models.ManyToManyField(Question) + + # Questions that will be fetched randomly from the Question Set. + random_questions = models.ManyToManyField("QuestionSet") + + # Option to shuffle questions, each time a new question paper is created. + shuffle_questions = models.BooleanField(default=False) + + # Total marks for the question paper. + total_marks = models.FloatField() + + def update_total_marks(self): + """ Updates the total marks for the Question Paper""" + marks = 0.0 + questions = self.fixed_questions.all() + for question in questions: + marks += question.points + for question_set in self.random_questions.all(): + marks += question_set.marks * question_set.num_questions + self.total_marks = marks + + def _get_questions_for_answerpaper(self): + """ Returns fixed and random questions for the answer paper""" + questions = [] + questions = list(self.fixed_questions.all()) + for question_set in self.random_questions.all(): + questions += question_set.get_random_questions() + return questions + + def make_answerpaper(self, user, ip, attempt_num): + """Creates an answer paper for the user to attempt the quiz""" + ans_paper = AnswerPaper(user=user, user_ip=ip, attempt_number=attempt_num) + ans_paper.start_time = datetime.datetime.now() + ans_paper.end_time = ans_paper.start_time \ + + datetime.timedelta(minutes=self.quiz.duration) + ans_paper.question_paper = self + questions = self._get_questions_for_answerpaper() + question_ids = [str(x.id) for x in questions] + if self.shuffle_questions: + shuffle(question_ids) + ans_paper.questions = "|".join(question_ids) + ans_paper.save() + return ans_paper + + +############################################################################### +class QuestionSet(models.Model): + """Question set contains a set of questions from which random questions + will be selected for the quiz. + """ + + # Marks of each question of a particular Question Set + marks = models.FloatField() + + # Number of questions to be fetched for the quiz. + num_questions = models.IntegerField() + + # Set of questions for sampling randomly. + questions = models.ManyToManyField(Question) + + def get_random_questions(self): + """ Returns random questions from set of questions""" + return sample(self.questions.all(), self.num_questions) + + +############################################################################### +class AnswerPaper(models.Model): + """A answer paper for a student -- one per student typically. + """ + # The user taking this question paper. + user = models.ForeignKey(User) + + # All questions that remain to be attempted for a particular Student + # (a list of ids separated by '|') + questions = models.CharField(max_length=128) + + # The Quiz to which this question paper is attached to. + question_paper = models.ForeignKey(QuestionPaper) + + # The attempt number for the question paper. + attempt_number = models.IntegerField() + + # The time when this paper was started by the user. + start_time = models.DateTimeField() + + # The time when this paper was ended by the user. + end_time = models.DateTimeField() + + # User's IP which is logged. + user_ip = models.CharField(max_length=15) + + # The questions successfully answered (a list of ids separated by '|') + questions_answered = models.CharField(max_length=128) + + # All the submitted answers. + answers = models.ManyToManyField(Answer) + + # Teacher comments on the question paper. + comments = models.TextField() + + # Total marks earned by the student in this paper. + marks_obtained = models.FloatField(null=True, default=None) + + # Marks percent scored by the user + percent = models.FloatField(null=True, default=None) + + # Result of the quiz, True if student passes the exam. + passed = models.NullBooleanField() + + # Status of the quiz attempt + status = models.CharField(max_length=20, choices=test_status,\ + default='inprogress') + + def current_question(self): + """Returns the current active question to display.""" + qu = self.get_unanswered_questions() + if len(qu) > 0: + return qu[0] + else: + return '' + + def questions_left(self): + """Returns the number of questions left.""" + qu = self.get_unanswered_questions() + return len(qu) + + def get_unanswered_questions(self): + """Returns the list of unanswered questions.""" + qa = self.questions_answered.split('|') + qs = self.questions.split('|') + qu = [q for q in qs if q not in qa] + return qu + + def completed_question(self, question_id): + """ + Adds the completed question to the list of answered + questions and returns the next question. + """ + qa = self.questions_answered + if len(qa) > 0: + self.questions_answered = '|'.join([qa, str(question_id)]) + else: + self.questions_answered = str(question_id) + self.save() + + return self.skip(question_id) + + def skip(self, question_id): + """ + Skips the current question and returns the next sequentially + available question. + """ + qu = self.get_unanswered_questions() + qs = self.questions.split('|') + + if len(qu) == 0: + return '' + + try: + q_index = qs.index(unicode(question_id)) + except ValueError: + return qs[0] + + start = q_index + 1 + stop = q_index + 1 + len(qs) + q_list = islice(cycle(qs), start, stop) + for next_q in q_list: + if next_q in qu: + return next_q + + return qs[0] + + def time_left(self): + """Return the time remaining for the user in seconds.""" + dt = datetime.datetime.now() - self.start_time.replace(tzinfo=None) + try: + secs = dt.total_seconds() + except AttributeError: + # total_seconds is new in Python 2.7. :( + secs = dt.seconds + dt.days*24*3600 + total = self.question_paper.quiz.duration*60.0 + remain = max(total - secs, 0) + return int(remain) + + def get_answered_str(self): + """Returns the answered questions, sorted and as a nice string.""" + qa = self.questions_answered.split('|') + answered = ', '.join(sorted(qa)) + return answered if answered else 'None' + + def update_marks_obtained(self): + """Updates the total marks earned by student for this paper.""" + marks = sum([x.marks for x in self.answers.filter(marks__gt=0.0)]) + self.marks_obtained = marks + + def update_percent(self): + """Updates the percent gained by the student for this paper.""" + total_marks = self.question_paper.total_marks + if self.marks_obtained is not None: + percent = self.marks_obtained/self.question_paper.total_marks*100 + self.percent = round(percent, 2) + + def update_passed(self): + """ + Checks whether student passed or failed, as per the quiz + passing criteria. + """ + if self.percent is not None: + if self.percent >= self.question_paper.quiz.pass_criteria: + self.passed = True + else: + self.passed = False + + def update_status(self): + """ Sets status to completed """ + self.status = 'completed' + + def get_question_answers(self): + """ + Return a dictionary with keys as questions and a list of the + corresponding answers. + """ + q_a = {} + for answer in self.answers.all(): + question = answer.question + if question in q_a: + q_a[question].append(answer) + else: + q_a[question] = [answer] + return q_a + + def __unicode__(self): + u = self.user + return u'Question paper for {0} {1}'.format(u.first_name, u.last_name) + + +############################################################################### +class AssignmentUpload(models.Model): + user = models.ForeignKey(Profile) + assignmentQuestion = models.ForeignKey(Question) + assignmentFile = models.FileField(upload_to=get_assignment_dir) + + +################################################################################ +class TestCase(models.Model): + question = models.ForeignKey(Question, blank=True, null = True) + + # Test case function name + func_name = models.CharField(blank=True, null = True, max_length=200) + + # Test case Keyword arguments in dict form + kw_args = models.TextField(blank=True, null = True) + + # Test case Positional arguments in list form + pos_args = models.TextField(blank=True, null = True) + + # Test case Expected answer in list form + expected_answer = models.TextField(blank=True, null = True) diff --git a/testapp/yaksh/output/README.txt b/testapp/yaksh/output/README.txt new file mode 100644 index 0000000..3163ed4 --- /dev/null +++ b/testapp/yaksh/output/README.txt @@ -0,0 +1,4 @@ +This directory contains files generated/saved by users as per their +username. The test executor will chdir into this user directory for each +user when they run the test. Do not delete this directory and ensure that +it is writeable by all. \ No newline at end of file diff --git a/testapp/yaksh/python_code_evaluator.py b/testapp/yaksh/python_code_evaluator.py new file mode 100644 index 0000000..0c473cf --- /dev/null +++ b/testapp/yaksh/python_code_evaluator.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +import sys +import traceback +import os +from os.path import join +import importlib + +# local imports +from code_evaluator import CodeEvaluator + + +class PythonCodeEvaluator(CodeEvaluator): + """Tests the Python code obtained from Code Server""" + # Private Protocol ########## + def _check_code(self): + success = False + + try: + tb = None + test_code = self._create_test_case() + submitted = compile(self.user_answer, ' ', mode='exec') + g = {} + exec submitted in g + _tests = compile(test_code, ' ', mode='exec') + exec _tests in g + except AssertionError: + type, value, tb = sys.exc_info() + info = traceback.extract_tb(tb) + fname, lineno, func, text = info[-1] + text = str(test_code).splitlines()[lineno-1] + err = "{0} {1} in: {2}".format(type.__name__, str(value), text) + else: + success = True + err = 'Correct answer' + + del tb + return success, err + + def _create_test_case(self): + """ + Create assert based test cases in python + """ + test_code = "" + if self.test: + return self.test + elif self.test_case_data: + for test_case in self.test_case_data: + pos_args = ", ".join(str(i) for i in test_case.get('pos_args')) \ + if test_case.get('pos_args') else "" + kw_args = ", ".join(str(k+"="+a) for k, a + in test_case.get('kw_args').iteritems()) \ + if test_case.get('kw_args') else "" + args = pos_args + ", " + kw_args if pos_args and kw_args \ + else pos_args or kw_args + function_name = test_case.get('func_name') + expected_answer = test_case.get('expected_answer') + + tcode = "assert {0}({1}) == {2}".format(function_name, args, + expected_answer) + test_code += tcode + "\n" + return test_code diff --git a/testapp/yaksh/scilab_code_evaluator.py b/testapp/yaksh/scilab_code_evaluator.py new file mode 100644 index 0000000..392cd45 --- /dev/null +++ b/testapp/yaksh/scilab_code_evaluator.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python +import traceback +import os +from os.path import join, isfile +import subprocess +import re +import importlib + +# local imports +from code_evaluator import CodeEvaluator + + +class ScilabCodeEvaluator(CodeEvaluator): + """Tests the Scilab code obtained from Code Server""" + def __init__(self, test_case_data, test, language, user_answer, + ref_code_path=None, in_dir=None): + super(ScilabCodeEvaluator, self).__init__(test_case_data, test, + language, user_answer, + ref_code_path, in_dir) + + # Removes all the commands that terminates scilab + self.user_answer, self.terminate_commands = self._remove_scilab_exit(user_answer.lstrip()) + self.test_case_args = self._setup() + + # Private Protocol ########## + def _setup(self): + super(ScilabCodeEvaluator, self)._setup() + + ref_path, test_case_path = self._set_test_code_file_path(self.ref_code_path) + self.submit_path = self.create_submit_code_file('function.sci') + + return ref_path, # Return as a tuple + + def _teardown(self): + # Delete the created file. + super(ScilabCodeEvaluator, self)._teardown() + os.remove(self.submit_path) + + def _check_code(self, ref_path): + success = False + + # Throw message if there are commmands that terminates scilab + add_err="" + if self.terminate_commands: + add_err = "Please do not use exit, quit and abort commands in your\ + code.\n Otherwise your code will not be evaluated\ + correctly.\n" + + cmd = 'printf "lines(0)\nexec(\'{0}\',2);\nquit();"'.format(ref_path) + cmd += ' | timeout 8 scilab-cli -nb' + ret = self._run_command(cmd, + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + proc, stdout, stderr = ret + + # Get only the error. + stderr = self._get_error(stdout) + if stderr is None: + # Clean output + stdout = self._strip_output(stdout) + if proc.returncode == 5: + success, err = True, "Correct answer" + else: + err = add_err + stdout + else: + err = add_err + stderr + + return success, err + + def _remove_scilab_exit(self, string): + """ + Removes exit, quit and abort from the scilab code + """ + new_string = "" + terminate_commands = False + for line in string.splitlines(): + new_line = re.sub(r"exit.*$", "", line) + new_line = re.sub(r"quit.*$", "", new_line) + new_line = re.sub(r"abort.*$", "", new_line) + if line != new_line: + terminate_commands = True + new_string = new_string + '\n' + new_line + return new_string, terminate_commands + + def _get_error(self, string): + """ + Fetches only the error from the string. + Returns None if no error. + """ + obj = re.search("!.+\n.+", string) + if obj: + return obj.group() + return None + + def _strip_output(self, out): + """ + Cleans whitespace from the output + """ + strip_out = "Message" + for l in out.split('\n'): + if l.strip(): + strip_out = strip_out+"\n"+l.strip() + return strip_out + diff --git a/testapp/yaksh/scilab_files/test_add.sce b/testapp/yaksh/scilab_files/test_add.sce new file mode 100644 index 0000000..a317cdb --- /dev/null +++ b/testapp/yaksh/scilab_files/test_add.sce @@ -0,0 +1,29 @@ +mode(-1) +exec("function.sci",-1); +i = 0 +p = add(3,5); +correct = (p == 8); +if correct then + i=i+1 +end +disp("Input submitted 3 and 5") +disp("Expected output 8 got " + string(p)) +p = add(22,-20); +correct = (p==2); +if correct then + i=i+1 +end +disp("Input submitted 22 and -20") +disp("Expected output 2 got " + string(p)) +p =add(91,0); +correct = (p==91); +if correct then + i=i+1 +end +disp("Input submitted 91 and 0") +disp("Expected output 91 got " + string(p)) +if i==3 then + exit(5); +else + exit(3); +end diff --git a/testapp/yaksh/settings.py b/testapp/yaksh/settings.py new file mode 100644 index 0000000..4b1828e --- /dev/null +++ b/testapp/yaksh/settings.py @@ -0,0 +1,29 @@ +""" +settings for yaksh app. +""" +# The ports the code server should run on. This will run one separate +# server for each port listed in the following list. +SERVER_PORTS = [8001] # range(8001, 8026) + +# The server pool port. This is the server which returns available server +# ports so as to minimize load. This is some random number where no other +# service is running. It should be > 1024 and less < 65535 though. +SERVER_POOL_PORT = 53579 + +# Timeout for the code to run in seconds. This is an integer! +SERVER_TIMEOUT = 2 + +# The root of the URL, for example you might be in the situation where you +# are not hosted as host.org/exam/ but as host.org/foo/exam/ for whatever +# reason set this to the root you have to serve at. In the above example +# host.org/foo/exam set URL_ROOT='/foo' +URL_ROOT = '' + +code_evaluators = { + "python": "python_code_evaluator.PythonCodeEvaluator", + "c": "c_cpp_code_evaluator.CCPPCodeEvaluator", + "cpp": "c_cpp_code_evaluator.CCPPCodeEvaluator", + "java": "java_code_evaluator.JavaCodeEvaluator", + "bash": "bash_code_evaluator.BashCodeEvaluator", + "scilab": "scilab_code_evaluator.ScilabCodeEvaluator", + } diff --git a/testapp/yaksh/static/yaksh_app/css/autotaggit.css b/testapp/yaksh/static/yaksh_app/css/autotaggit.css new file mode 100644 index 0000000..ed856ce --- /dev/null +++ b/testapp/yaksh/static/yaksh_app/css/autotaggit.css @@ -0,0 +1,48 @@ +.ac_results { + padding: 0px; + border: 1px solid #efefef; + background-color: white; + overflow: hidden; + z-index: 99999; +} + +.ac_results ul { + width: 100%; + list-style-position: outside; + list-style: none; + padding: 0; + margin: 0; +} + +.ac_results li { + margin: 0px; + padding: 2px 5px; + cursor: default; + display: block; + /* + if width will be 100% horizontal scrollbar will apear + when scroll mode will be used + */ + /*width: 100%;*/ + font: menu; + font-size: 12px; + /* + it is very important, if line-height not setted or setted + in relative units scroll will be broken in firefox + */ + line-height: 16px; + overflow: hidden; +} + +.ac_loading { + background: white url('indicator.gif') right center no-repeat; +} + +.ac_odd { + background-color: #CACACA; +} + +.ac_over { + background-color: #f5f5f5; + color: black; +} diff --git a/testapp/yaksh/static/yaksh_app/css/base.css b/testapp/yaksh/static/yaksh_app/css/base.css new file mode 100644 index 0000000..3570098 --- /dev/null +++ b/testapp/yaksh/static/yaksh_app/css/base.css @@ -0,0 +1,2327 @@ +/*! +Copyright 2012 Twitter, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with the License. You may obtain a copy of the License in the LICENSE file, or at: + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + + * Bootstrap v1.4.0 + * + * Copyright 2011 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + * Date: Sun Dec 25 20:18:31 PST 2011 + */ +/* Reset.less + * Props to Eric Meyer (meyerweb.com) for his CSS reset file. We're using an adapted version here that cuts out some of the reset HTML elements we will never need here (i.e., dfn, samp, etc). + * For Online Test Application, this CSS was changed as per the requirements wherever required. ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */ + +html, body { + background-color: #eee; + margin: 0; + padding: 0; + +} +h1, +h2, +h3, +h4, +h5, +h6, +p, +blockquote, +pre, +a, +abbr, +acronym, +address, +cite, +code, +del, +dfn, +em, +img, +q, +s, +samp, +small, +strike, +strong, +sub, +sup, +tt, +var, +dd, +dl, +dt, +li, +ol, +ul, +fieldset, +form, +label, +legend, +button, +table, +caption, +tbody, +tfoot, +thead, +tr, +th, +td { + margin: 0; + padding: 0; + border: 0; + font-weight: normal; + font-style: normal; + font-size: 100%; + line-height: 1; + font-family: serif; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +ol, ul { + list-style: none; +} +q:before, +q:after, +blockquote:before, +blockquote:after { + content: ""; +} +html { + overflow-y: scroll; + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} +a:focus { + outline: thin dotted; +} +a:hover, a:active { + outline: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section { + display: block; +} +audio, canvas, video { + display: inline-block; + *display: inline; + *zoom: 1; +} +audio:not([controls]) { + display: none; +} +sub, sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + border: 0; + -ms-interpolation-mode: bicubic; +} +button, +input, +select, +textarea { + font-size: 100%; + margin: 0; + vertical-align: baseline; + *vertical-align: middle; +} +button, input { + line-height: normal; + *overflow: visible; +} +button::-moz-focus-inner, input::-moz-focus-inner { + border: 0; + padding: 0; +} +button, +input[type="button"], +input[type="reset"], +input[type="submit"] { + cursor: pointer; + -webkit-appearance: button; +} +input[type="search"] { + -webkit-appearance: textfield; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +textarea { + overflow: visible; + vertical-align: top; +} +/* Variables.less +* Variables to customize the look and feel of Bootstrap +* ----------------------------------------------------- */ +/* Mixins.less +* Snippets of reusable CSS to develop faster and keep code readable +* ----------------------------------------------------------------- */ +/* +* Scaffolding +* Basic and global styles for generating a grid system, structural layout, and page templates +* ------------------------------------------------------------------------------------------- */ +body { + padding-top : 10px; + background-color: #eee; + margin: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + font-weight: normal; + line-height: 18px; + color: #404040; + +} +.container { + width: 820px; + margin-left: auto; + margin-right: auto; + zoom: 1; +} +.container > footer p { + text-align: center; +} +.container > .content { + background-color: #fff; + padding: 20px; + margin: 0 -20px; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.15); + -moz-box-shadow: 0 1px 2px rgba(0,0,0,.15); + box-shadow: 0 1px 2px rgba(0,0,0,.15); +} +.content .span10, +.content .span14 { + min-height: 475px; +} +.content .span4 { + margin-left: 0; + padding-left: 19px; + border-left: 1px solid #eee; +} +.topbar .btn { + border: 0; +} +.page-header { + background-color: #f5f5f5; + padding: 20px 20px 10px; + margin: -20px -20px 20px; +} +.container:before, .container:after { + display: table; + content: ""; + zoom: 1; +} +.container:after { + clear: both; +} +.container-fluid { + position: relative; + min-width: 940px; + padding-left: 20px; + padding-right: 20px; + zoom: 1; +} +.container-fluid:before, .container-fluid:after { + display: table; + content: ""; + zoom: 1; +} +.container-fluid:after { + clear: both; +} +.container-fluid > .sidebar { + position: absolute; + top: 0; + left: 20px; + width: 220px; +} +.container-fluid > .content { + margin-left: 240px; +} +a { + color: #0069d6; + text-decoration: none; + line-height: inherit; + font-weight: inherit; +} +a:hover { + color: #00438a; + text-decoration: underline; +} +.pull-right { + float: right; +} +.pull-left { + float: left; +} +.hide { + display: none; +} +.show { + display: block; +} +.row { + zoom: 1; + margin-left: -20px; +} +.row:before, .row:after { + display: table; + content: ""; + zoom: 1; +} +.row:after { + clear: both; +} +.row > [class*="span"] { + display: inline; + float: left; + margin-left: 20px; +} +.span1 { + width: 40px; +} +.span2 { + width: 100px; +} +.span3 { + width: 160px; +} +.span4 { + width: 220px; +} +.span5 { + width: 280px; +} +.span6 { + width: 340px; +} +.span7 { + width: 400px; +} +.span8 { + width: 460px; +} +.span9 { + width: 520px; +} +.span10 { + width: 560px; +} +.span11 { + width: 640px; +} +.span12 { + width: 700px; +} +.span13 { + width: 760px; +} +.span14 { + width: 820px; +} +.span15 { + width: 880px; +} +.span16 { + width: 940px; +} +.span17 { + width: 1000px; +} +.span18 { + width: 1060px; +} +.span19 { + width: 1120px; +} +.span20 { + width: 1180px; +} +.span21 { + width: 1240px; +} +.span22 { + width: 1300px; +} +.span23 { + width: 1360px; +} +.span24 { + width: 1420px; +} +.row > .offset1 { + margin-left: 80px; +} +.row > .offset2 { + margin-left: 140px; +} +.row > .offset3 { + margin-left: 200px; +} +.row > .offset4 { + margin-left: 260px; +} +.row > .offset5 { + margin-left: 320px; +} +.row > .offset6 { + margin-left: 380px; +} +.row > .offset7 { + margin-left: 440px; +} +.row > .offset8 { + margin-left: 500px; +} +.row > .offset9 { + margin-left: 560px; +} +.row > .offset10 { + margin-left: 620px; +} +.row > .offset11 { + margin-left: 680px; +} +.row > .offset12 { + margin-left: 740px; +} +.span-one-third { + width: 300px; +} +.span-two-thirds { + width: 620px; +} +.row > .offset-one-third { + margin-left: 340px; +} +.row > .offset-two-thirds { + margin-left: 660px; +} +/* Typography.less +* Headings, body text, lists, code, and more for a versatile and durable typography system +* ---------------------------------------------------------------------------------------- */ +p { + font-size: 13px; + font-weight: normal; + line-height: 18px; + margin-bottom: 9px; +} +p small { + font-size: 11px; + color: #bfbfbf; +} +h1, +h2, +h3, +h4, +h5, +h6 { + font-weight: bold; + color: #404040; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small { + color: #bfbfbf; +} +h1 { + margin-bottom: 18px; + font-size: 30px; + line-height: 36px; +} +h1 small { + font-size: 18px; +} +h2 { + font-size: 24px; + line-height: 36px; +} +h2 small { + font-size: 14px; +} +h3, +h4, +h5, +h6 { + line-height: 36px; +} +h3 { + font-size: 18px; +} +h3 small { + font-size: 14px; +} +h4 { + font-size: 16px; +} +h4 small { + font-size: 12px; +} +h5 { + font-size: 14px; +} +h6 { + font-size: 13px; + color: #bfbfbf; + text-transform: uppercase; +} +ul, ol { + margin: 0 0 18px 25px; +} +ul ul, +ul ol, +ol ol, +ol ul { + margin-bottom: 0; +} +ul { + list-style: disc; +} +ol { + list-style: decimal; +} +li { + line-height: 18px; + color: #808080; +} +ul.unstyled { + list-style: none; + margin-left: 0; +} +dl { + margin-bottom: 18px; +} +dl dt, dl dd { + line-height: 18px; +} +dl dt { + font-weight: bold; +} +dl dd { + margin-left: 9px; +} +hr { + margin: 20px 0 19px; + border: 0; + border-bottom: 1px solid; +} +strong { + font-style: inherit; + font-weight: bold; +} +em { + font-style: italic; + font-weight: inherit; + line-height: inherit; +} +.muted { + color: #bfbfbf; +} +blockquote { + margin-bottom: 18px; + border-left: 5px solid #eee; + padding-left: 15px; +} +blockquote p { + font-size: 14px; + font-weight: 300; + line-height: 18px; + margin-bottom: 0; +} +blockquote small { + display: block; + font-size: 12px; + font-weight: 300; + line-height: 18px; + color: #bfbfbf; +} +blockquote small:before { + content: '\2014 \00A0'; +} +address { + display: block; + line-height: 18px; + margin-bottom: 18px; +} +code, pre { + padding: 0 3px 2px; + font-family: Monaco, Andale Mono, Courier New, monospace; + font-size: 12px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} +code { + background-color: #FDE8E8; + color: rgba(0, 0, 0, 0.75); + padding: 1px 3px; +} +pre { + background-color: #EAB9B9; + color:red; + display: block; + padding: 8.5px; + margin: 0 0 18px; + line-height: 18px; + font-size: 12px; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.15); + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + white-space: pre; + white-space: pre-wrap; + word-wrap: break-word; +} +/* Forms.less +* Base styles for various input types, form layouts, and states +* ------------------------------------------------------------- */ +form { + margin-bottom: 18px; +} +fieldset { + margin-bottom: 18px; + padding-top: 18px; +} +fieldset legend { + display: block; + padding-left: 150px; + font-size: 19.5px; + line-height: 1; + color: #404040; + *padding: 0 0 5px 145px; + /* IE6-7 */ + + *line-height: 1.5; + /* IE6-7 */ + +} +form .clearfix { + margin-bottom: 18px; + zoom: 1; +} +form .clearfix:before, form .clearfix:after { + display: table; + content: ""; + zoom: 1; +} +form .clearfix:after { + clear: both; +} +label, +input, +select, +textarea { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + font-weight: normal; + line-height: normal; +} +select +{ + width : auto; +} +label { + padding-top: 6px; + font-size: 13px; + line-height: 18px; + float: left; + width: 130px; + text-align: left; + color: #404040; +} +form .input { + margin-left: 150px; +} +input[type=checkbox], input[type=radio] { + cursor: pointer; +} +input, +textarea, +select, +.uneditable-input { + display: inline-block; + width: 210px; + height: 18px; + padding: 4px; + font-size: 13px; + line-height: 18px; + color: #808080; + border: 1px solid #ccc; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} +select { + padding: initial; +} +input[type=checkbox], input[type=radio] { + width: auto; + height: auto; + padding: 0; + margin: 3px 0; + *margin-top: 0; + /* IE6-7 */ + + line-height: normal; + border: none; +} +input[type=file] { + background-color: #ffffff; + padding: initial; + border: initial; + line-height: initial; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +input[type=button], input[type=reset], input[type=submit] { + width: auto; + height: auto; +} +select, input[type=file] { + height: 27px; + *height: auto; + line-height: 27px; + *margin-top: 4px; + /* For IE7, add top margin to align select with labels */ + +} +select[multiple] { + height: inherit; + background-color: #ffffff; +} +textarea { + height: auto; +} +.uneditable-input { + background-color: #ffffff; + display: block; + border-color: #eee; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + cursor: not-allowed; +} +:-moz-placeholder { + color: #bfbfbf; +} +::-webkit-input-placeholder { + color: #bfbfbf; +} +input, textarea { + -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; + -moz-transition: border linear 0.2s, box-shadow linear 0.2s; + -ms-transition: border linear 0.2s, box-shadow linear 0.2s; + -o-transition: border linear 0.2s, box-shadow linear 0.2s; + transition: border linear 0.2s, box-shadow linear 0.2s; + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); + -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); +} +input:focus, textarea:focus { + outline: 0; + border-color: rgba(82, 168, 236, 0.8); + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); + -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); +} +input[type=file]:focus, input[type=checkbox]:focus, select:focus { + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + outline: 1px dotted #666; +} +form .clearfix.error > label, form .clearfix.error .help-block, form .clearfix.error .help-inline { + color: #b94a48; +} +form .clearfix.error input, form .clearfix.error textarea { + color: #b94a48; + border-color: #ee5f5b; +} +form .clearfix.error input:focus, form .clearfix.error textarea:focus { + border-color: #e9322d; + -webkit-box-shadow: 0 0 6px #f8b9b7; + -moz-box-shadow: 0 0 6px #f8b9b7; + box-shadow: 0 0 6px #f8b9b7; +} +form .clearfix.error .input-prepend .add-on, form .clearfix.error .input-append .add-on { + color: #b94a48; + background-color: #fce6e6; + border-color: #b94a48; +} +form .clearfix.warning > label, form .clearfix.warning .help-block, form .clearfix.warning .help-inline { + color: #c09853; +} +form .clearfix.warning input, form .clearfix.warning textarea { + color: #c09853; + border-color: #ccae64; +} +form .clearfix.warning input:focus, form .clearfix.warning textarea:focus { + border-color: #be9a3f; + -webkit-box-shadow: 0 0 6px #e5d6b1; + -moz-box-shadow: 0 0 6px #e5d6b1; + box-shadow: 0 0 6px #e5d6b1; +} +form .clearfix.warning .input-prepend .add-on, form .clearfix.warning .input-append .add-on { + color: #c09853; + background-color: #d2b877; + border-color: #c09853; +} +form .clearfix.success > label, form .clearfix.success .help-block, form .clearfix.success .help-inline { + color: #468847; +} +form .clearfix.success input, form .clearfix.success textarea { + color: #468847; + border-color: #57a957; +} +form .clearfix.success input:focus, form .clearfix.success textarea:focus { + border-color: #458845; + -webkit-box-shadow: 0 0 6px #9acc9a; + -moz-box-shadow: 0 0 6px #9acc9a; + box-shadow: 0 0 6px #9acc9a; +} +form .clearfix.success .input-prepend .add-on, form .clearfix.success .input-append .add-on { + color: #468847; + background-color: #bcddbc; + border-color: #468847; +} +textarea +{ + width : 290px; +} +.input-mini, +input.mini, +textarea.mini, +select.mini { + width: 60px; +} +.input-small, +input.small, +textarea.small, +select.small { + width: 90px; +} +.input-medium, +input.medium, +textarea.medium, +select.medium { + width: 150px; +} +.input-large, +input.large, +textarea.large, +select.large { + width: 210px; +} +.input-xlarge, +input.xlarge, +textarea.xlarge, +select.xlarge { + width: 270px; +} +.input-xxlarge, +input.xxlarge, +textarea.xxlarge, +select.xxlarge { + width: 530px; +} +textarea.xxlarge { + overflow-y: auto; +} +input.span1, textarea.span1 { + display: inline-block; + float: none; + width: 30px; + margin-left: 0; +} +input.span2, textarea.span2 { + display: inline-block; + float: none; + width: 90px; + margin-left: 0; +} +input.span3, textarea.span3 { + display: inline-block; + float: none; + width: 150px; + margin-left: 0; +} +input.span4, textarea.span4 { + display: inline-block; + float: none; + width: 210px; + margin-left: 0; +} +input.span5, textarea.span5 { + display: inline-block; + float: none; + width: 270px; + margin-left: 0; +} +input.span6, textarea.span6 { + display: inline-block; + float: none; + width: 330px; + margin-left: 0; +} +input.span7, textarea.span7 { + display: inline-block; + float: none; + width: 390px; + margin-left: 0; +} +input.span8, textarea.span8 { + display: inline-block; + float: none; + width: 450px; + margin-left: 0; +} +input.span9, textarea.span9 { + display: inline-block; + float: none; + width: 510px; + margin-left: 0; +} +input.span10, textarea.span10 { + display: inline-block; + float: none; + width: 570px; + margin-left: 0; +} +input.span11, textarea.span11 { + display: inline-block; + float: none; + width: 630px; + margin-left: 0; +} +input.span12, textarea.span12 { + display: inline-block; + float: none; + width: 690px; + margin-left: 0; +} +input.span13, textarea.span13 { + display: inline-block; + float: none; + width: 750px; + margin-left: 0; +} +input.span14, textarea.span14 { + display: inline-block; + float: none; + width: 810px; + margin-left: 0; +} +input.span15, textarea.span15 { + display: inline-block; + float: none; + width: 870px; + margin-left: 0; +} +input.span16, textarea.span16 { + display: inline-block; + float: none; + width: 930px; + margin-left: 0; +} +input[disabled], +select[disabled], +textarea[disabled], +input[readonly], +select[readonly], +textarea[readonly] { + background-color: #f5f5f5; + border-color: #ddd; + cursor: not-allowed; +} +.actions { + background: #f5f5f5; + margin-top: 18px; + margin-bottom: 18px; + padding: 17px 20px 18px 150px; + border-top: 1px solid #ddd; + -webkit-border-radius: 0 0 3px 3px; + -moz-border-radius: 0 0 3px 3px; + border-radius: 0 0 3px 3px; +} +.actions .secondary-action { + float: right; +} +.actions .secondary-action a { + line-height: 30px; +} +.actions .secondary-action a:hover { + text-decoration: underline; +} +.help-inline, .help-block { + font-size: 13px; + line-height: 18px; + color: #bfbfbf; +} +.help-inline { + padding-left: 5px; + *position: relative; + /* IE6-7 */ + + *top: -5px; + /* IE6-7 */ + +} +.help-block { + display: block; + max-width: 600px; +} +.inline-inputs { + color: #808080; +} +.inline-inputs span { + padding: 0 2px 0 1px; +} +.input-prepend input, .input-append input { + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; +} +.input-prepend .add-on, .input-append .add-on { + position: relative; + background: #f5f5f5; + border: 1px solid #ccc; + z-index: 2; + float: left; + display: block; + width: auto; + min-width: 16px; + height: 18px; + padding: 4px 4px 4px 5px; + margin-right: -1px; + font-weight: normal; + line-height: 18px; + color: #bfbfbf; + text-align: center; + text-shadow: 0 1px 0 #ffffff; + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} +.input-prepend .active, .input-append .active { + background: #a9dba9; + border-color: #46a546; +} +.input-prepend .add-on { + *margin-top: 1px; + /* IE6-7 */ + +} +.input-append input { + float: left; + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} +.input-append .add-on { + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; + margin-right: 0; + margin-left: -1px; +} +.inputs-list { + margin: 0 0 5px; + width: 100%; +} +.inputs-list li { + display: block; + padding: 0; + width: 100%; +} +.inputs-list label { + display: block; + float: none; + width: auto; + padding: 0; + margin-left: 20px; + line-height: 18px; + text-align: left; + white-space: normal; +} +.inputs-list label strong { + color: #808080; +} +.inputs-list label small { + font-size: 11px; + font-weight: normal; +} +.inputs-list .inputs-list { + margin-left: 25px; + margin-bottom: 10px; + padding-top: 0; +} +.inputs-list:first-child { + padding-top: 6px; +} +.inputs-list li + li { + padding-top: 2px; +} +.inputs-list input[type=radio], .inputs-list input[type=checkbox] { + margin-bottom: 0; + margin-left: -20px; + float: left; +} +.form-stacked { + padding-left: 20px; +} +.form-stacked fieldset { + padding-top: 9px; +} +.form-stacked legend { + padding-left: 0; +} +.form-stacked label { + display: block; + float: none; + width: auto; + font-weight: bold; + text-align: left; + line-height: 20px; + padding-top: 0; +} +.form-stacked .clearfix { + margin-bottom: 9px; +} +.form-stacked .clearfix div.input { + margin-left: 0; +} +.form-stacked .inputs-list { + margin-bottom: 0; +} +.form-stacked .inputs-list li { + padding-top: 0; +} +.form-stacked .inputs-list li label { + font-weight: normal; + padding-top: 0; +} +.form-stacked div.clearfix.error { + padding-top: 10px; + padding-bottom: 10px; + padding-left: 10px; + margin-top: 0; + margin-left: -10px; +} +.form-stacked .actions { + margin-left: -20px; + padding-left: 20px; +} +/* +* Tables.less +* Tables for, you guessed it, tabular data +* ---------------------------------------- */ +table { + width: 100%; + margin-bottom: 18px; + padding: 0; + font-size: 13px; + border-collapse: collapse; +} +table th, table td { + padding: 10px 10px 9px; + line-height: 18px; + text-align: center; +} +table th { + padding-top: 9px; + font-weight: bold; + vertical-align: middle; +} +table td { + vertical-align: top; + /*border-top: 1px solid #ddd;*/ +} +table tbody th { +/* border-top: 1px solid #ddd;*/ + vertical-align: top; +} +.condensed-table th, .condensed-table td { + padding: 5px 5px 4px; +} +.bordered-table { + border: 1px solid #ddd; + border-collapse: separate; + *border-collapse: collapse; + /* IE7, collapse table to remove spacing */ + + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.bordered-table th + th, .bordered-table td + td, .bordered-table th + td { + border-left: 1px solid #ddd; +} +.bordered-table thead tr:first-child th:first-child, .bordered-table tbody tr:first-child td:first-child { + -webkit-border-radius: 4px 0 0 0; + -moz-border-radius: 4px 0 0 0; + border-radius: 4px 0 0 0; +} +.bordered-table thead tr:first-child th:last-child, .bordered-table tbody tr:first-child td:last-child { + -webkit-border-radius: 0 4px 0 0; + -moz-border-radius: 0 4px 0 0; + border-radius: 0 4px 0 0; +} +.bordered-table tbody tr:last-child td:first-child { + -webkit-border-radius: 0 0 0 4px; + -moz-border-radius: 0 0 0 4px; + border-radius: 0 0 0 4px; +} +.bordered-table tbody tr:last-child td:last-child { + -webkit-border-radius: 0 0 4px 0; + -moz-border-radius: 0 0 4px 0; + border-radius: 0 0 4px 0; +} +table .span1 { + width: 20px; +} +table .span2 { + width: 60px; +} +table .span3 { + width: 100px; +} +table .span4 { + width: 140px; +} +table .span5 { + width: 180px; +} +table .span6 { + width: 220px; +} +table .span7 { + width: 260px; +} +table .span8 { + width: 300px; +} +table .span9 { + width: 340px; +} +table .span10 { + width: 380px; +} +table .span11 { + width: 420px; +} +table .span12 { + width: 460px; +} +table .span13 { + width: 500px; +} +table .span14 { + width: 540px; +} +table .span15 { + width: 580px; +} +table .span16 { + width: 620px; +} +.zebra-striped tbody tr:nth-child(odd) td, .zebra-striped tbody tr:nth-child(odd) th { + background-color: #f9f9f9; +} +.zebra-striped tbody tr:hover td, .zebra-striped tbody tr:hover th { + background-color: #f5f5f5; +} +table .header { + cursor: pointer; +} +table .header:after { + content: ""; + float: right; + margin-top: 7px; + border-width: 0 4px 4px; + border-style: solid; + border-color: #000 transparent; + visibility: hidden; +} +table .headerSortUp, table .headerSortDown { + background-color: rgba(141, 192, 219, 0.25); + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); +} +table .header:hover:after { + visibility: visible; +} +table .headerSortDown:after, table .headerSortDown:hover:after { + visibility: visible; + filter: alpha(opacity=60); + -khtml-opacity: 0.6; + -moz-opacity: 0.6; + opacity: 0.6; +} +table .headerSortUp:after { + border-bottom: none; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #000; + visibility: visible; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + filter: alpha(opacity=60); + -khtml-opacity: 0.6; + -moz-opacity: 0.6; + opacity: 0.6; +} +table .blue { + color: #049cdb; + border-bottom-color: #049cdb; +} +table .headerSortUp.blue, table .headerSortDown.blue { + background-color: #ade6fe; +} +table .green { + color: #46a546; + border-bottom-color: #46a546; +} +table .headerSortUp.green, table .headerSortDown.green { + background-color: #cdeacd; +} +table .red { + color: #9d261d; + border-bottom-color: #9d261d; +} +table .headerSortUp.red, table .headerSortDown.red { + background-color: #f4c8c5; +} +table .yellow { + color: #ffc40d; + border-bottom-color: #ffc40d; +} +table .headerSortUp.yellow, table .headerSortDown.yellow { + background-color: #fff6d9; +} +table .orange { + color: #f89406; + border-bottom-color: #f89406; +} +.center1 +{ +margin-left: auto; +margin-right: auto; +} +table .headerSortUp.orange, table .headerSortDown.orange { + background-color: #fee9cc; +} +table .purple { + color: #7a43b6; + border-bottom-color: #7a43b6; +} +table .headerSortUp.purple, table .headerSortDown.purple { + background-color: #e2d5f0; +} +/* Patterns.less +* Repeatable UI elements outside the base styles provided from the scaffolding +* ---------------------------------------------------------------------------- */ +.topbar { + height: 40px; + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 10000; + overflow: visible; +} +.topbar a { + color: #bfbfbf; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.topbar h3 a:hover, .topbar .brand:hover, .topbar ul .active > a { + background-color: #333; + background-color: rgba(255, 255, 255, 0.05); + color: #ffffff; + text-decoration: none; +} +.topbar h3 { + position: relative; +} +.topbar h3 a, .topbar .brand { + float: left; + display: block; + padding: 8px 20px 12px; + margin-left: -20px; + color: #ffffff; + font-size: 20px; + font-weight: 200; + line-height: 1; +} +.topbar p { + margin: 0; + line-height: 40px; +} +.topbar p a:hover { + background-color: transparent; + color: #ffffff; +} +.topbar form { + float: left; + margin: 5px 0 0 0; + position: relative; + filter: alpha(opacity=100); + -khtml-opacity: 1; + -moz-opacity: 1; + opacity: 1; +} +.topbar form.pull-right { + float: right; +} +.topbar input { + background-color: #444; + background-color: rgba(255, 255, 255, 0.3); + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: normal; + font-weight: 13px; + line-height: 1; + padding: 4px 9px; + color: #ffffff; + color: rgba(255, 255, 255, 0.75); + border: 1px solid #111; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25); + -webkit-transition: none; + -moz-transition: none; + -ms-transition: none; + -o-transition: none; + transition: none; +} +.topbar input:-moz-placeholder { + color: #e6e6e6; +} +.topbar input::-webkit-input-placeholder { + color: #e6e6e6; +} +.topbar input:hover { + background-color: #bfbfbf; + background-color: rgba(255, 255, 255, 0.5); + color: #ffffff; +} +.topbar input:focus, .topbar input.focused { + outline: 0; + background-color: #ffffff; + color: #404040; + text-shadow: 0 1px 0 #ffffff; + border: 0; + padding: 5px 10px; + -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); +} +.topbar-inner, .topbar .fill { + background-color: #222; + background-color: #222222; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#333333), to(#222222)); + background-image: -moz-linear-gradient(top, #333333, #222222); + background-image: -ms-linear-gradient(top, #333333, #222222); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #333333), color-stop(100%, #222222)); + background-image: -webkit-linear-gradient(top, #333333, #222222); + background-image: -o-linear-gradient(top, #333333, #222222); + background-image: linear-gradient(top, #333333, #222222); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); +} +.topbar div > ul, .nav { + display: block; + float: left; + margin: 0 10px 0 0; + position: relative; + left: 0; +} +.topbar div > ul > li, .nav > li { + display: block; + float: left; +} +.topbar div > ul a, .nav a { + display: block; + float: none; + padding: 10px 10px 11px; + line-height: 19px; + text-decoration: none; +} +.topbar div > ul a:hover, .nav a:hover { + color: #ffffff; + text-decoration: none; +} +.topbar div > ul .active > a, .nav .active > a { + background-color: #222; + background-color: rgba(0, 0, 0, 0.5); +} +.topbar div > ul.secondary-nav, .nav.secondary-nav { + float: right; + margin-left: 10px; + margin-right: 0; +} +.topbar div > ul.secondary-nav .menu-dropdown, +.nav.secondary-nav .menu-dropdown, +.topbar div > ul.secondary-nav .dropdown-menu, +.nav.secondary-nav .dropdown-menu { + right: 0; + border: 0; +} +.topbar div > ul a.menu:hover, +.nav a.menu:hover, +.topbar div > ul li.open .menu, +.nav li.open .menu, +.topbar div > ul .dropdown-toggle:hover, +.nav .dropdown-toggle:hover, +.topbar div > ul .dropdown.open .dropdown-toggle, +.nav .dropdown.open .dropdown-toggle { + background: #444; + background: rgba(255, 255, 255, 0.05); +} +.topbar div > ul .menu-dropdown, +.nav .menu-dropdown, +.topbar div > ul .dropdown-menu, +.nav .dropdown-menu { + background-color: #333; +} +.topbar div > ul .menu-dropdown a.menu, +.nav .menu-dropdown a.menu, +.topbar div > ul .dropdown-menu a.menu, +.nav .dropdown-menu a.menu, +.topbar div > ul .menu-dropdown .dropdown-toggle, +.nav .menu-dropdown .dropdown-toggle, +.topbar div > ul .dropdown-menu .dropdown-toggle, +.nav .dropdown-menu .dropdown-toggle { + color: #ffffff; +} +.topbar div > ul .menu-dropdown a.menu.open, +.nav .menu-dropdown a.menu.open, +.topbar div > ul .dropdown-menu a.menu.open, +.nav .dropdown-menu a.menu.open, +.topbar div > ul .menu-dropdown .dropdown-toggle.open, +.nav .menu-dropdown .dropdown-toggle.open, +.topbar div > ul .dropdown-menu .dropdown-toggle.open, +.nav .dropdown-menu .dropdown-toggle.open { + background: #444; + background: rgba(255, 255, 255, 0.05); +} +.topbar div > ul .menu-dropdown li a, +.nav .menu-dropdown li a, +.topbar div > ul .dropdown-menu li a, +.nav .dropdown-menu li a { + color: #999; + text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5); +} +.topbar div > ul .menu-dropdown li a:hover, +.nav .menu-dropdown li a:hover, +.topbar div > ul .dropdown-menu li a:hover, +.nav .dropdown-menu li a:hover { + background-color: #191919; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#292929), to(#191919)); + background-image: -moz-linear-gradient(top, #292929, #191919); + background-image: -ms-linear-gradient(top, #292929, #191919); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #292929), color-stop(100%, #191919)); + background-image: -webkit-linear-gradient(top, #292929, #191919); + background-image: -o-linear-gradient(top, #292929, #191919); + background-image: linear-gradient(top, #292929, #191919); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#292929', endColorstr='#191919', GradientType=0); + color: #ffffff; +} +.topbar div > ul .menu-dropdown .active a, +.nav .menu-dropdown .active a, +.topbar div > ul .dropdown-menu .active a, +.nav .dropdown-menu .active a { + color: #ffffff; +} +.topbar div > ul .menu-dropdown .divider, +.nav .menu-dropdown .divider, +.topbar div > ul .dropdown-menu .divider, +.nav .dropdown-menu .divider { + background-color: #222; + border-color: #444; +} +.topbar ul .menu-dropdown li a, .topbar ul .dropdown-menu li a { + padding: 4px 15px; +} +li.menu, .dropdown { + position: relative; +} +a.menu:after, .dropdown-toggle:after { + width: 0; + height: 0; + display: inline-block; + content: "↓"; + text-indent: -99999px; + vertical-align: top; + margin-top: 8px; + margin-left: 4px; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #ffffff; + filter: alpha(opacity=50); + -khtml-opacity: 0.5; + -moz-opacity: 0.5; + opacity: 0.5; +} +.menu-dropdown, .dropdown-menu { + background-color: #ffffff; + float: left; + display: none; + position: absolute; + top: 40px; + z-index: 900; + min-width: 160px; + max-width: 220px; + _width: 160px; + margin-left: 0; + margin-right: 0; + padding: 6px 0; + zoom: 1; + border-color: #999; + border-color: rgba(0, 0, 0, 0.2); + border-style: solid; + border-width: 0 1px 1px; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + -webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} +.menu-dropdown li, .dropdown-menu li { + float: none; + display: block; + background-color: none; +} +.menu-dropdown .divider, .dropdown-menu .divider { + height: 1px; + margin: 5px 0; + overflow: hidden; + background-color: #eee; + border-bottom: 1px solid #ffffff; +} +.topbar .dropdown-menu a, .dropdown-menu a { + display: block; + padding: 4px 15px; + clear: both; + font-weight: normal; + line-height: 18px; + color: #808080; + text-shadow: 0 1px 0 #ffffff; +} +.topbar .dropdown-menu a:hover, +.dropdown-menu a:hover, +.topbar .dropdown-menu a.hover, +.dropdown-menu a.hover { + background-color: #dddddd; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#eeeeee), to(#dddddd)); + background-image: -moz-linear-gradient(top, #eeeeee, #dddddd); + background-image: -ms-linear-gradient(top, #eeeeee, #dddddd); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #eeeeee), color-stop(100%, #dddddd)); + background-image: -webkit-linear-gradient(top, #eeeeee, #dddddd); + background-image: -o-linear-gradient(top, #eeeeee, #dddddd); + background-image: linear-gradient(top, #eeeeee, #dddddd); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#dddddd', GradientType=0); + color: #404040; + text-decoration: none; + -webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.025), inset 0 -1px rgba(0, 0, 0, 0.025); + -moz-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.025), inset 0 -1px rgba(0, 0, 0, 0.025); + box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.025), inset 0 -1px rgba(0, 0, 0, 0.025); +} +footer { + margin-top: 17px; + padding-top: 17px; +} +.page-header { + margin-bottom: 17px; + border-bottom: 1px solid #ddd; + -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + -moz-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); +} +.page-header h3 { + margin-top: 20px; + margin-bottom : -17px; +} +.btn.danger, +.alert-message.danger, +.btn.danger:hover, +.alert-message.danger:hover, +.btn.error, +.alert-message.error, +.btn.error:hover, +.alert-message.error:hover, +.btn.success, +.alert-message.success, +.btn.success:hover, +.alert-message.success:hover, +.btn.info, +.alert-message.info, +.btn.info:hover, +.alert-message.info:hover { + color: #ffffff; +} +.btn .close, .alert-message .close { + font-family: Arial, sans-serif; + line-height: 18px; +} +.btn-mini { + padding: 2px 6px; + font-size: 15px; + line-height: 16px; +} +.btn.danger, +.alert-message.danger, +.btn.error, +.alert-message.error { + background-color: #c43c35; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35)); + background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); + background-image: linear-gradient(top, #ee5f5b, #c43c35); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #c43c35 #c43c35 #882a25; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} +.btn.success, .alert-message.success { + background-color: #57a957; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957)); + background-image: -moz-linear-gradient(top, #62c462, #57a957); + background-image: -ms-linear-gradient(top, #62c462, #57a957); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957)); + background-image: -webkit-linear-gradient(top, #62c462, #57a957); + background-image: -o-linear-gradient(top, #62c462, #57a957); + background-image: linear-gradient(top, #62c462, #57a957); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #57a957 #57a957 #3d773d; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} +.btn.info, .alert-message.info { + background-color: #339bb9; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#5bc0de), to(#339bb9)); + background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); + background-image: -ms-linear-gradient(top, #5bc0de, #339bb9); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9)); + background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); + background-image: -o-linear-gradient(top, #5bc0de, #339bb9); + background-image: linear-gradient(top, #5bc0de, #339bb9); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #339bb9 #339bb9 #22697d; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} +.btn { + cursor: pointer; + display: inline-block; + background-color: #e6e6e6; + background-repeat: no-repeat; + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + background-image: -moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6); + background-image: -ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + background-image: -o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + background-image: linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); + padding: 5px 14px 6px; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + color: #333; + font-size: 13px; + line-height: normal; + border: 1px solid #ccc; + border-bottom-color: #bbb; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -webkit-transition: 0.1s linear all; + -moz-transition: 0.1s linear all; + -ms-transition: 0.1s linear all; + -o-transition: 0.1s linear all; + transition: 0.1s linear all; +} +.btn:hover { + background-position: 0 -15px; + color: #333; + text-decoration: none; +} +.btn:focus { + outline: 1px dotted #666; +} +.btn.primary { + color: #ffffff; + background-color: #0064cd; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd)); + background-image: -moz-linear-gradient(top, #049cdb, #0064cd); + background-image: -ms-linear-gradient(top, #049cdb, #0064cd); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd)); + background-image: -webkit-linear-gradient(top, #049cdb, #0064cd); + background-image: -o-linear-gradient(top, #049cdb, #0064cd); + background-image: linear-gradient(top, #049cdb, #0064cd); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #0064cd #0064cd #003f81; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} +.btn.active, .btn:active { + -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); +} +.btn.disabled { + cursor: default; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: alpha(opacity=65); + -khtml-opacity: 0.65; + -moz-opacity: 0.65; + opacity: 0.65; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +.btn[disabled] { + cursor: default; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: alpha(opacity=65); + -khtml-opacity: 0.65; + -moz-opacity: 0.65; + opacity: 0.65; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +.btn.large { + font-size: 15px; + line-height: normal; + padding: 9px 14px 9px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} +.btn.small { + padding: 7px 9px 7px; + font-size: 11px; +} +:root .alert-message, :root .btn { + border-radius: 0 \0; +} +.alert { + padding: 8px 35px 8px 14px; + margin-bottom: 18px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + background-color: #fcf8e3; + border: 1px solid #fbeed5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.alert, .alert-heading { + color: #c09853; +} +.alert .close { + position: relative; + top: -2px; + right: -21px; + line-height: 18px; +} +.alert-success { + background-color: #dff0d8; + border-color: #d6e9c6; +} +.alert-success, .alert-success .alert-heading { + color: #468847; +} +.alert-danger, .alert-error { + background-color: #f2dede; + border-color: #eed3d7; +} +.alert-danger, +.alert-error, +.alert-danger .alert-heading, +.alert-error .alert-heading { + color: #b94a48; +} +.alert-info { + background-color: #d9edf7; + border-color: #bce8f1; +} +.alert-info, .alert-info .alert-heading { + color: #3a87ad; +} +.alert-block { + padding-top: 14px; + padding-bottom: 14px; +} +.alert-block > p, .alert-block > ul { + margin-bottom: 0; +} +.alert-block p + p { + margin-top: 5px; +} + +button.btn::-moz-focus-inner, input[type=submit].btn::-moz-focus-inner { + padding: 0; + border: 0; +} +.alert-message { + position: relative; + padding: 7px 15px; + margin-bottom: 18px; + color: #404040; + background-color: #eedc94; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#fceec1), to(#eedc94)); + background-image: -moz-linear-gradient(top, #fceec1, #eedc94); + background-image: -ms-linear-gradient(top, #fceec1, #eedc94); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fceec1), color-stop(100%, #eedc94)); + background-image: -webkit-linear-gradient(top, #fceec1, #eedc94); + background-image: -o-linear-gradient(top, #fceec1, #eedc94); + background-image: linear-gradient(top, #fceec1, #eedc94); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fceec1', endColorstr='#eedc94', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #eedc94 #eedc94 #e4c652; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + border-width: 1px; + border-style: solid; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); +} +.alert-message .close { + margin-top: 1px; + *margin-top: 0; +} +.alert-message a { + font-weight: bold; + color: #404040; +} +.alert-message.danger p a, +.alert-message.error p a, +.alert-message.success p a, +.alert-message.info p a { + color: #ffffff; +} +.alert-message h5 { + line-height: 18px; +} +.alert-message p { + margin-bottom: 0; +} +.alert-message div { + margin-top: 5px; + margin-bottom: 2px; + line-height: 28px; +} +.alert-message .btn { + -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); + -moz-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); + box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); +} +.alert-message.block-message { + background-image: none; + background-color: #fdf5d9; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + padding: 14px; + border-color: #fceec1; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +.alert-message.block-message ul, .alert-message.block-message p { + margin-right: 30px; +} +.alert-message.block-message ul { + margin-bottom: 0; +} +.alert-message.block-message li { + color: #404040; +} +.alert-message.block-message .alert-actions { + margin-top: 5px; +} +.alert-message.block-message.error, .alert-message.block-message.success, .alert-message.block-message.info { + color: #404040; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); +} +.alert-message.block-message.error { + background-color: #fddfde; + border-color: #fbc7c6; +} +.alert-message.block-message.success { + background-color: #d1eed1; + border-color: #bfe7bf; +} +.alert-message.block-message.info { + background-color: #ddf4fb; + border-color: #c6edf9; +} +.alert-message.block-message.danger p a, +.alert-message.block-message.error p a, +.alert-message.block-message.success p a, +.alert-message.block-message.info p a { + color: #404040; +} +.label { + padding: 1px 3px 2px; + font-size: 9.75px; + font-weight: bold; + color: #ffffff; + text-transform: uppercase; + white-space: nowrap; + background-color: #bfbfbf; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + text-shadow: none; +} +.label.important { + background-color: #c43c35; +} +.label.warning { + background-color: #f89406; +} +.label.success { + background-color: #46a546; +} +.label.notice { + background-color: #62cffc; +} +.well { + background-color: #f5f5f5; + margin-bottom: 20px; + padding: 19px; + min-height: 20px; + border: 1px solid #eee; + border: 1px solid rgba(0, 0, 0, 0.05); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} +.modal-backdrop { + background-color: #000000; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 10000; +} +.modal-backdrop.fade { + opacity: 0; +} +.modal-backdrop, .modal-backdrop.fade.in { + filter: alpha(opacity=80); + -khtml-opacity: 0.8; + -moz-opacity: 0.8; + opacity: 0.8; +} +.modal { + position: fixed; + top: 10%; + left: 50%; + z-index: 1050; + width: 560px; + margin-left: -280px; + background-color: #ffffff; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.3); + *border: 1px solid #999; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + outline: none; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} +.modal.fade { + top: -25%; + -webkit-transition: opacity 0.3s linear, top 0.3s ease-out; + -moz-transition: opacity 0.3s linear, top 0.3s ease-out; + -o-transition: opacity 0.3s linear, top 0.3s ease-out; + transition: opacity 0.3s linear, top 0.3s ease-out; +} + +.modal.fade.in { + top: 10%; +} + +.modal-header { + padding: 9px 15px; + border-bottom: 1px solid #eee; +} + +.modal-header .close { + margin-top: 2px; +} + +.modal-header h3 { + margin: 0; + line-height: 30px; +} + +.modal-body { + position: relative; + max-height: 400px; + padding: 15px; + overflow-y: auto; +} + +.modal-form { + margin-bottom: 0; +} + +.modal-footer { + padding: 14px 15px 15px; + margin-bottom: 0; + text-align: right; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + *zoom: 1; + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; +} + +.modal-footer:before, +.modal-footer:after { + display: table; + line-height: 0; + content: ""; +} + +.modal-footer:after { + clear: both; +} + +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px; +} + +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} + +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.tabs, .pills { + margin: 0 0 18px; + padding: 0; + list-style: none; + zoom: 1; +} +.tabs:before, +.pills:before, +.tabs:after, +.pills:after { + display: table; + content: ""; + zoom: 1; +} +.tabs:after, .pills:after { + clear: both; +} +.tabs > li, .pills > li { + float: left; +} +.tabs > li > a, .pills > li > a { + display: block; +} +.tabs { + border-color: #ddd; + border-style: solid; + border-width: 0 0 1px; +} +.tabs > li { + position: relative; + margin-bottom: -1px; +} +.tabs > li > a { + padding: 0 15px; + margin-right: 2px; + line-height: 23px; + border: 1px solid transparent; + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} +.tabs > li > a:hover { + text-decoration: none; + background-color: #eee; + border-color: #eee #eee #ddd; +} +.tabs .active > a, .tabs .active > a:hover { + color: #808080; + background-color: #ffffff; + border: 1px solid #ddd; + border-bottom-color: transparent; + cursor: default; +} +.tabs .menu-dropdown, .tabs .dropdown-menu { + top: 35px; + border-width: 1px; + -webkit-border-radius: 0 6px 6px 6px; + -moz-border-radius: 0 6px 6px 6px; + border-radius: 0 6px 6px 6px; +} +.tabs a.menu:after, .tabs .dropdown-toggle:after { + border-top-color: #999; + margin-top: 15px; + margin-left: 5px; +} +.tabs li.open.menu .menu, .tabs .open.dropdown .dropdown-toggle { + border-color: #999; +} +.tabs li.open a.menu:after, .tabs .dropdown.open .dropdown-toggle:after { + border-top-color: #555; +} +.pills a { + margin: 5px 3px 5px 0; + padding: 0 15px; + line-height: 30px; + text-shadow: 0 1px 1px #ffffff; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} +.pills a:hover { + color: #ffffff; + text-decoration: none; + text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25); + background-color: #00438a; +} +.pills .active a { + color: #ffffff; + text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25); + background-color: #0069d6; +} +.pills-vertical > li { + float: none; +} +.tab-content > .tab-pane, .pill-content > .pill-pane { + display: none; +} +.tab-content > .active, .pill-content > .active { + display: block; +} +.pagination { + height: 36px; + margin: 18px 0; +} +.pagination ul { + float: left; + margin: 0; + border: 1px solid #ddd; + border: 1px solid rgba(0, 0, 0, 0.15); + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); +} +.pagination li { + display: inline; +} +.pagination a { + float: left; + padding: 0 14px; + line-height: 34px; + border-right: 1px solid; + border-right-color: #ddd; + border-right-color: rgba(0, 0, 0, 0.15); + *border-right-color: #ddd; + /* IE6-7 */ + + text-decoration: none; +} +.pagination a:hover, .pagination .active a { + background-color: #c7eefe; +} +/*custom classes*/ +.pagination .done a { + background-color: #00CC66; +} +.pagination .disabled a, .pagination .disabled a:hover { + background-color: transparent; + color: #bfbfbf; +} +.pagination .next a { + border: 0; +} diff --git a/testapp/yaksh/static/yaksh_app/css/gradeuser.css b/testapp/yaksh/static/yaksh_app/css/gradeuser.css new file mode 100644 index 0000000..07b1079 --- /dev/null +++ b/testapp/yaksh/static/yaksh_app/css/gradeuser.css @@ -0,0 +1,52 @@ +textarea +{ +width : 550px; +height : 200px; + +} + +.for-question{ + background: none repeat scroll 0 0 #F1F1F1; + border-radius: 6px 6px 6px 6px; + margin-bottom: 10px; + padding: 5px; +} + +#headerDiv, #contentDiv { +float: left; +} +#titleText { +float: left; +font-size: 1.1em; +font-weight: bold; +margin: 5px; +} +#myHeader { +font-size: 1.1em; +font-weight: bold; +margin: 5px; +} +#headerDiv { +background-color: #0037DB; +color: #9EB6FF; +} + +#contentDiv { + background-color:#F0F8FF; + border: 1px solid #C9C9C9; + border-radius: 5px 5px 5px 5px; + margin-bottom: 10px; + min-width: 805px; + +} + +#myContent { +margin: 5px 10px; + +} +#headerDiv a { +float: right; +margin: 10px 10px 5px 5px; +} +#headerDiv a:hover { +color: #FFFFFF; diff --git a/testapp/yaksh/static/yaksh_app/css/login.css b/testapp/yaksh/static/yaksh_app/css/login.css new file mode 100644 index 0000000..a10cbaa --- /dev/null +++ b/testapp/yaksh/static/yaksh_app/css/login.css @@ -0,0 +1,10 @@ +label +{ + padding-top: 6px; + font-size: 15px; + line-height: 18px; + float: left; + width: 80px; + text-align: center; + color: #404040; + } diff --git a/testapp/yaksh/static/yaksh_app/css/monitor.css b/testapp/yaksh/static/yaksh_app/css/monitor.css new file mode 100644 index 0000000..b16c8b3 --- /dev/null +++ b/testapp/yaksh/static/yaksh_app/css/monitor.css @@ -0,0 +1,11 @@ + table td + { + vertical-align: top; + border-top: 1px solid #ddd; + } + table tbody th + { + border-top: 1px solid #ddd; + vertical-align: top; + } + diff --git a/testapp/yaksh/static/yaksh_app/css/question.css b/testapp/yaksh/static/yaksh_app/css/question.css new file mode 100644 index 0000000..4bf5913 --- /dev/null +++ b/testapp/yaksh/static/yaksh_app/css/question.css @@ -0,0 +1,42 @@ +.time-div +{ + background-color:black; + padding: 8px; + color: #5DFC0A; + vertical-align:middle; + width:150px; + float:right; + border-radius: 6px 6px 6px 6px; +} +.td1-class +{ + width:175px; +} +.td2-class +{ + width:50px; +} +.page-header { + height:50px; + text-align: center; + background-color: #f5f5f5; + padding: 35px 20px 10px; + margin: -20px -20px 20px; +} +#codeTextarea{ + + } + .textAreaWithLines{ + font-family:courier; + border:1px solid #eee; + + } + .textAreaWithLines textarea,.textAreaWithLines div{ + border:0px; + line-height:120%; + font-size:12px; + } + .lineObj{ + color: grey; + } + diff --git a/testapp/yaksh/static/yaksh_app/css/question_paper_creation.css b/testapp/yaksh/static/yaksh_app/css/question_paper_creation.css new file mode 100644 index 0000000..c915320 --- /dev/null +++ b/testapp/yaksh/static/yaksh_app/css/question_paper_creation.css @@ -0,0 +1,119 @@ +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + font-weight: normal; + line-height: 18px; + color: #404040; +} +.clearfix { + clear: both; +} +.tabs li { + text-align: center; + width: 33%; +} +.tabs li:last-child { + width: 34%; +} +.tabs > .active > a { + border: 0; + background: lightgreen; +} +.tabs > .active > a:hover { + border: 0; + background: green; + color: #ffffff; +} +.tabs li a { + border-radius: 0; + margin-right: 0; +} +.tabs { + border: 1px solid #ddd; +} +#progress { + background: red; +} +#content-left{ + text-align: center; + background: grey; +} +#content-right{ + text-align: center; + background: grey; +} +#selectors { + margin-left: 0; + background: #fafafa; + padding: 7px 0; + border: 2px solid #f5f5f5; +} +#selectors .span4 { + margin-left: 0; +} +#id_question_type { + width: 100%; +} +#id_marks { + width: 100%; +} +#fixed-questions .span7 > div, +#random-questions .span7 > div{ + background: #f5f5f5; + height: 200px; + border: 1px solid #333333; + padding: 5px; +} +#fixed-available, +#random-available { + height: 125px; + min-height: 125px; + overflow-y: scroll; + margin-bottom: 15px; +} +#fixed-added, +#random-added { + height: 160px; + overflow-y: scroll; +} +#fixed-added hr, +#random-added hr { + margin: 5px 0 4px; +} +.qcard { + position: relative; + background: #ffffff; + padding: 5px; + margin: 5px 5px; + box-shadow: 1px 1px 5px #cccccc; + -webkit-box-shadow: 1px 1px 5px #cccccc; + -moz-box-shadow: 1px 1px 5px #cccccc; + -o-box-shadow: 1px 1px 5px #cccccc; +} +.qcard ul { + margin-bottom: 5px; +} +.qcard .remove { + position: absolute; + + top: 3px; + right: 3px; + padding: 1px 3px; + text-decoration: none; + color: #ffffff; + background: #ff4136; + border-radius: 3px; + font-weight: bold; +} +.qcard .remove:hover { + background: #333333; +} +.red-alert { + border: 2px solid red; +} +#myModal .qcard .remove{ + display: none; +} +.well{ + padding: 5px; +} diff --git a/testapp/yaksh/static/yaksh_app/css/question_quiz.css b/testapp/yaksh/static/yaksh_app/css/question_quiz.css new file mode 100644 index 0000000..ee249d4 --- /dev/null +++ b/testapp/yaksh/static/yaksh_app/css/question_quiz.css @@ -0,0 +1,24 @@ +table th, table td + { + text-align: left; + } + +.mini-text +{ + height : 25px; + width : 70px; +} +.select-type +{ + width : 225px; +} +.tag-text +{ + height : 30px; + width : 290px; +} +.date-text +{ + height : 30px; + width : 100px; +} diff --git a/testapp/yaksh/static/yaksh_app/css/showusers.css b/testapp/yaksh/static/yaksh_app/css/showusers.css new file mode 100644 index 0000000..66a3746 --- /dev/null +++ b/testapp/yaksh/static/yaksh_app/css/showusers.css @@ -0,0 +1,5 @@ +.table-class +{ + text-align:left; + width:60%; +} diff --git a/testapp/yaksh/static/yaksh_app/js/add_question.js b/testapp/yaksh/static/yaksh_app/js/add_question.js new file mode 100644 index 0000000..946c139 --- /dev/null +++ b/testapp/yaksh/static/yaksh_app/js/add_question.js @@ -0,0 +1,205 @@ +function increase(frm) +{ + if(frm.points.value == "") + { + frm.points.value = "0.5"; + return; + } + frm.points.value = parseFloat(frm.points.value) + 0.5; +} + +function decrease(frm) +{ + if(frm.points.value > 0) + { + frm.points.value = parseFloat(frm.points.value) - 0.5; + } + else + { + frm.points.value=0; + } + + +} + +function setSelectionRange(input, selectionStart, selectionEnd) +{ + if (input.setSelectionRange) + { + input.focus(); + input.setSelectionRange(selectionStart, selectionEnd); + } + else if (input.createTextRange) + { + var range = input.createTextRange(); + range.collapse(true); + range.moveEnd('character', selectionEnd); + range.moveStart('character', selectionStart); + range.select(); + } +} + +function replaceSelection (input, replaceString) +{ + if (input.setSelectionRange) + { + var selectionStart = input.selectionStart; + var selectionEnd = input.selectionEnd; + input.value = input.value.substring(0, selectionStart)+ replaceString + input.value.substring(selectionEnd); + if (selectionStart != selectionEnd) + { + setSelectionRange(input, selectionStart, selectionStart + replaceString.length); + } + else + { + setSelectionRange(input, selectionStart + replaceString.length, selectionStart + replaceString.length); + } + } + else if (document.selection) + { + var range = document.selection.createRange(); + if (range.parentElement() == input) + { + var isCollapsed = range.text == ''; + range.text = replaceString; + if (!isCollapsed) + { + range.moveStart('character', -replaceString.length); + range.select(); + } + } + } +} + +function textareaformat() +{ + document.getElementById('id_type').setAttribute('class','select-type'); + document.getElementById('id_points').setAttribute('class','mini-text'); + document.getElementById('id_tags').setAttribute('class','tag-text'); + + + $('#id_snippet').bind('keydown', function( event ){ + if(navigator.userAgent.match("Gecko")) + { + c=event.which; + } + else + { + c=event.keyCode; + } + if(c==9) + { + replaceSelection(document.getElementById('id_snippet'),String.fromCharCode(9)); + setTimeout(document.getElementById('id_snippet'),0); + return false; + } + }); + + $('#id_description').bind('focus', function( event ){ + document.getElementById("id_description").rows=5; + document.getElementById("id_description").cols=40; + }); + + $('#id_description').bind('blur', function( event ){ + document.getElementById("id_description").rows=1; + document.getElementById("id_description").cols=40; + }); + + $('#id_description').bind('keypress', function (event){ + document.getElementById('my').innerHTML = document.getElementById('id_description').value ; + }); + + $('#id_test').bind('focus', function( event ){ + document.getElementById("id_test").rows=5; + document.getElementById("id_test").cols=40; + }); + + $('#id_test').bind('blur', function( event ){ + document.getElementById("id_test").rows=1; + document.getElementById("id_test").cols=40; + }); + + $('#id_options').bind('focus', function( event ){ + document.getElementById("id_options").rows=5; + document.getElementById("id_options").cols=40; + }); + $('#id_options').bind('blur', function( event ){ + document.getElementById("id_options").rows=1; + document.getElementById("id_options").cols=40; + }); + + $('#id_snippet').bind('focus', function( event ){ + document.getElementById("id_snippet").rows=5; + document.getElementById("id_snippet").cols=40; + }); + $('#id_snippet').bind('blur', function( event ){ + document.getElementById("id_snippet").rows=1; + document.getElementById("id_snippet").cols=40; + }); + + + $('#id_type').bind('focus', function(event){ + var type = document.getElementById('id_type'); + type.style.border = '1px solid #ccc'; + }); + + $('#id_language').bind('focus', function(event){ + var language = document.getElementById('id_language'); + language.style.border = '1px solid #ccc'; + }); + + $('#id_type').bind('change',function(event){ + var value = document.getElementById('id_type').value; + if(value == 'mcq' || value == 'mcc') + { + document.getElementById('id_options').style.visibility='visible'; + document.getElementById('label_option').innerHTML="Options :"; + } + else + { + document.getElementById('id_options').style.visibility='hidden'; + document.getElementById('label_option').innerHTML = ""; + } + }); + document.getElementById('my').innerHTML = document.getElementById('id_description').value ; + var value = document.getElementById('id_type').value; + if(value == 'mcq' || value == 'mcc') + { + document.getElementById('id_options').style.visibility='visible'; + document.getElementById('label_option').innerHTML="Options :" + } + else + { + document.getElementById('id_options').style.visibility='hidden'; + document.getElementById('label_option').innerHTML = ""; + } +} + +function autosubmit() +{ + var language = document.getElementById('id_language'); + if(language.value == 'select') + { + language.style.border="solid red"; + return false; + } + var type = document.getElementById('id_type'); + if(type.value == 'select') + { + type.style.border = 'solid red'; + return false; + } + + + if (type.value == 'mcq' || type.value == 'mcc') + { + var value = document.getElementById('id_options').value; + if(value.split('\n').length < 4) + { + alert("Please Enter 4 options. One option per line."); + return false; + } + return true; + } + +} diff --git a/testapp/yaksh/static/yaksh_app/js/add_questionpaper.js b/testapp/yaksh/static/yaksh_app/js/add_questionpaper.js new file mode 100644 index 0000000..6185dd5 --- /dev/null +++ b/testapp/yaksh/static/yaksh_app/js/add_questionpaper.js @@ -0,0 +1,25 @@ +function load_data() +{ + var url_root = document.getElementById('url_root').value; + var value = document.getElementById('mode').value; + var pathArray = window.location.pathname.split( '/' ); + length = pathArray.length; + var digit = parseInt(pathArray[length-2]); + + if (! isNaN(digit) && value == 'Automatic') + { + window.location = url_root + "/exam/manage/designquestionpaper/automatic/" + digit; + } + else if(!isNaN(digit) && value == 'Manual') + { + window.location = url_root + "/exam/manage/designquestionpaper/manual/" + digit; + } + else if(value == 'Automatic') + { + window.location = window.location.pathname + "automatic"; + } + else if( value == 'Manual') + { + window.location = window.location.pathname + "manual"; + } +} diff --git a/testapp/yaksh/static/yaksh_app/js/add_quiz.js b/testapp/yaksh/static/yaksh_app/js/add_quiz.js new file mode 100644 index 0000000..184881c --- /dev/null +++ b/testapp/yaksh/static/yaksh_app/js/add_quiz.js @@ -0,0 +1,11 @@ +function test() +{ + + document.getElementById('id_duration').setAttribute('class','mini-text'); + document.getElementById('id_pass_criteria').setAttribute('class','mini-text'); + document.getElementById('id_start_date').setAttribute('class','date-text'); + if (document.getElementById("id_description").value != "") + { + document.getElementById("submit").innerHTML = "Save"; + } +} diff --git a/testapp/yaksh/static/yaksh_app/js/bootstrap-modal.js b/testapp/yaksh/static/yaksh_app/js/bootstrap-modal.js new file mode 100644 index 0000000..b328217 --- /dev/null +++ b/testapp/yaksh/static/yaksh_app/js/bootstrap-modal.js @@ -0,0 +1,260 @@ +/* ========================================================= + * bootstrap-modal.js v1.4.0 + * http://twitter.github.com/bootstrap/javascript.html#modal + * ========================================================= + * Copyright 2011 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================= */ + + +!function( $ ){ + + "use strict" + + /* CSS TRANSITION SUPPORT (https://gist.github.com/373874) + * ======================================================= */ + + var transitionEnd + + $(document).ready(function () { + + $.support.transition = (function () { + var thisBody = document.body || document.documentElement + , thisStyle = thisBody.style + , support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined + return support + })() + + // set CSS transition event type + if ( $.support.transition ) { + transitionEnd = "TransitionEnd" + if ( $.browser.webkit ) { + transitionEnd = "webkitTransitionEnd" + } else if ( $.browser.mozilla ) { + transitionEnd = "transitionend" + } else if ( $.browser.opera ) { + transitionEnd = "oTransitionEnd" + } + } + + }) + + + /* MODAL PUBLIC CLASS DEFINITION + * ============================= */ + + var Modal = function ( content, options ) { + this.settings = $.extend({}, $.fn.modal.defaults, options) + this.$element = $(content) + .delegate('.close', 'click.modal', $.proxy(this.hide, this)) + + if ( this.settings.show ) { + this.show() + } + + return this + } + + Modal.prototype = { + + toggle: function () { + return this[!this.isShown ? 'show' : 'hide']() + } + + , show: function () { + var that = this + this.isShown = true + this.$element.trigger('show') + + escape.call(this) + backdrop.call(this, function () { + var transition = $.support.transition && that.$element.hasClass('fade') + + that.$element + .appendTo(document.body) + .show() + + if (transition) { + that.$element[0].offsetWidth // force reflow + } + + that.$element.addClass('in') + + transition ? + that.$element.one(transitionEnd, function () { that.$element.trigger('shown') }) : + that.$element.trigger('shown') + + }) + + return this + } + + , hide: function (e) { + e && e.preventDefault() + + if ( !this.isShown ) { + return this + } + + var that = this + this.isShown = false + + escape.call(this) + + this.$element + .trigger('hide') + .removeClass('in') + + $.support.transition && this.$element.hasClass('fade') ? + hideWithTransition.call(this) : + hideModal.call(this) + + return this + } + + } + + + /* MODAL PRIVATE METHODS + * ===================== */ + + function hideWithTransition() { + // firefox drops transitionEnd events :{o + var that = this + , timeout = setTimeout(function () { + that.$element.unbind(transitionEnd) + hideModal.call(that) + }, 500) + + this.$element.one(transitionEnd, function () { + clearTimeout(timeout) + hideModal.call(that) + }) + } + + function hideModal (that) { + this.$element + .hide() + .trigger('hidden') + + backdrop.call(this) + } + + function backdrop ( callback ) { + var that = this + , animate = this.$element.hasClass('fade') ? 'fade' : '' + if ( this.isShown && this.settings.backdrop ) { + var doAnimate = $.support.transition && animate + + this.$backdrop = $('') + .appendTo(document.body) + + if ( this.settings.backdrop != 'static' ) { + this.$backdrop.click($.proxy(this.hide, this)) + } + + if ( doAnimate ) { + this.$backdrop[0].offsetWidth // force reflow + } + + this.$backdrop.addClass('in') + + doAnimate ? + this.$backdrop.one(transitionEnd, callback) : + callback() + + } else if ( !this.isShown && this.$backdrop ) { + this.$backdrop.removeClass('in') + + $.support.transition && this.$element.hasClass('fade')? + this.$backdrop.one(transitionEnd, $.proxy(removeBackdrop, this)) : + removeBackdrop.call(this) + + } else if ( callback ) { + callback() + } + } + + function removeBackdrop() { + this.$backdrop.remove() + this.$backdrop = null + } + + function escape() { + var that = this + if ( this.isShown && this.settings.keyboard ) { + $(document).bind('keyup.modal', function ( e ) { + if ( e.which == 27 ) { + that.hide() + } + }) + } else if ( !this.isShown ) { + $(document).unbind('keyup.modal') + } + } + + + /* MODAL PLUGIN DEFINITION + * ======================= */ + + $.fn.modal = function ( options ) { + var modal = this.data('modal') + + if (!modal) { + + if (typeof options == 'string') { + options = { + show: /show|toggle/.test(options) + } + } + + return this.each(function () { + $(this).data('modal', new Modal(this, options)) + }) + } + + if ( options === true ) { + return modal + } + + if ( typeof options == 'string' ) { + modal[options]() + } else if ( modal ) { + modal.toggle() + } + + return this + } + + $.fn.modal.Modal = Modal + + $.fn.modal.defaults = { + backdrop: false + , keyboard: false + , show: false + } + + + /* MODAL DATA- IMPLEMENTATION + * ========================== */ + + $(document).ready(function () { + $('body').delegate('[data-controls-modal]', 'click', function (e) { + e.preventDefault() + var $this = $(this).data('show', true) + $('#' + $this.attr('data-controls-modal')).modal( $this.data() ) + }) + }) + +}( window.jQuery || window.ender ); diff --git a/testapp/yaksh/static/yaksh_app/js/bootstrap-tabs.js b/testapp/yaksh/static/yaksh_app/js/bootstrap-tabs.js new file mode 100644 index 0000000..a3c7ee1 --- /dev/null +++ b/testapp/yaksh/static/yaksh_app/js/bootstrap-tabs.js @@ -0,0 +1,80 @@ +/* ======================================================== + * bootstrap-tabs.js v1.4.0 + * http://twitter.github.com/bootstrap/javascript.html#tabs + * ======================================================== + * Copyright 2011 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================== */ + + +!function( $ ){ + + "use strict" + + function activate ( element, container ) { + container + .find('> .active') + .removeClass('active') + .find('> .dropdown-menu > .active') + .removeClass('active') + + element.addClass('active') + + if ( element.parent('.dropdown-menu') ) { + element.closest('li.dropdown').addClass('active') + } + } + + function tab( e ) { + var $this = $(this) + , $ul = $this.closest('ul:not(.dropdown-menu)') + , href = $this.attr('href') + , previous + , $href + + if ( /^#\w+/.test(href) ) { + e.preventDefault() + + if ( $this.parent('li').hasClass('active') ) { + return + } + + previous = $ul.find('.active a').last()[0] + $href = $(href) + + activate($this.parent('li'), $ul) + activate($href, $href.parent()) + + $this.trigger({ + type: 'change' + , relatedTarget: previous + }) + } + } + + + /* TABS/PILLS PLUGIN DEFINITION + * ============================ */ + + $.fn.tabs = $.fn.pills = function ( selector ) { + return this.each(function () { + $(this).delegate(selector || '.tabs li > a, .pills > li > a', 'click', tab) + }) + } + + $(document).ready(function () { + $('body').tabs('ul[data-tabs] li > a, ul[data-pills] > li > a') + }) + +}( window.jQuery || window.ender ); diff --git a/testapp/yaksh/static/yaksh_app/js/edit_question.js b/testapp/yaksh/static/yaksh_app/js/edit_question.js new file mode 100644 index 0000000..7a0f56d --- /dev/null +++ b/testapp/yaksh/static/yaksh_app/js/edit_question.js @@ -0,0 +1,278 @@ +function render_question(frm) +{ + for(var i=1;i<=frm.description.length;i++) + { + document.getElementById('my'+i).innerHTML = frm.description[i-1].value; + } + +} + +function increase(frm,n) +{ + var newValue = document.getElementById('id_points'+ (n-1)).value ; + + if( newValue == "") + { + document.getElementById('id_points'+(n-1)).value = "0.5"; + return; + } + document.getElementById('id_points' + (n-1)).value = parseFloat(newValue) + 0.5; +} + +function decrease(frm,n) +{ + var newValue = document.getElementById('id_points'+ (n-1)).value ; + + if( newValue > 0) + { + document.getElementById('id_points' + (n-1)).value = parseFloat(newValue) - 0.5; + } + else + { + document.getElementById('id_points' + (n-1)).value = 0; + } +} + +function grade_data(showHideDiv) +{ + var ele=document.getElementById(showHideDiv); + if (ele.style.display=="block") + { + ele.style.display = "none"; + } + else + { + ele.style.display = "block"; + } +} + +function setSelectionRange(input, selectionStart, selectionEnd) +{ + if (input.setSelectionRange) + { + input.focus(); + input.setSelectionRange(selectionStart, selectionEnd); + } + else if (input.createTextRange) + { + var range = input.createTextRange(); + range.collapse(true); + range.moveEnd('character', selectionEnd); + range.moveStart('character', selectionStart); + range.select(); + } +} + +function replaceSelection (input, replaceString) +{ + if (input.setSelectionRange) + { + var selectionStart = input.selectionStart; + var selectionEnd = input.selectionEnd; + input.value = input.value.substring(0, selectionStart)+ replaceString + input.value.substring(selectionEnd); + if (selectionStart != selectionEnd) + { + setSelectionRange(input, selectionStart, selectionStart + replaceString.length); + } + else + { + setSelectionRange(input, selectionStart + replaceString.length, selectionStart + replaceString.length); + } + } + else if (document.selection) + { + var range = document.selection.createRange(); + if (range.parentElement() == input) + { + var isCollapsed = range.text == ''; + range.text = replaceString; + if (!isCollapsed) + { + range.moveStart('character', -replaceString.length); + range.select(); + } + } + } +} + +function data(showContent,showHideDiv,a,summary) +{ + var con = document.getElementById(showContent); + var ele=document.getElementById(showHideDiv); + var atag=document.getElementById(a); + if (ele.style.display=="block") + { + con.style.display = "none" + ele.style.display = "none"; + atag.text = summary; + } + else + { + con.style.display = "block"; + ele.style.display = "block"; + } +} + +function textareaformat() +{ + var point = document.getElementsByName('points'); + var test = document.getElementsByName('test'); + var option = document.getElementsByName('options'); + var descriptions = document.getElementsByName('description'); + var snippets = document.getElementsByName('snippet'); + var language = document.getElementsByName('language') + var type = document.getElementsByName('type'); + var tags = document.getElementsByName('tags'); + for (var i=0;i 0) + { + alert('Enter 4 options. One option per line.'); + return false; + } + return true; +} diff --git a/testapp/yaksh/static/yaksh_app/js/edit_quiz.js b/testapp/yaksh/static/yaksh_app/js/edit_quiz.js new file mode 100644 index 0000000..ce6dac7 --- /dev/null +++ b/testapp/yaksh/static/yaksh_app/js/edit_quiz.js @@ -0,0 +1,9 @@ +function form_load() +{ + var tags = document.getElementsByName('tags'); + + for (var i=0;i )[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, +Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& +(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, +a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== +"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, +function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b a"; +var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, +parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= +false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= +s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, +applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; +else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, +a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== +w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, +cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d
-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j =0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= +c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); +a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, +function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); +k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), +C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B =0){a.type= +e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& +f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; +if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e -1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", +e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, +"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, +d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j 0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, +e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); +t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| +g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h ":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m =0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, +CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, +g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, +text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, +setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= +h[3];l=0;for(m=h.length;l =0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== +"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, +h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l ";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& +q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; +if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); +(function(){var g=s.createElement("div");g.innerHTML="";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: +function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q =0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f
0)for(var j=d;j 0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= +{},i;if(f&&a.length){e=0;for(var o=a.length;e -1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== +"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", +d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? +a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== +1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"+d+">"},F={option:[1,""],legend:[1,""],thead:[1," ","
"],tr:[2,"","
"],td:[3,""],col:[2,"
"," "],area:[1,""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
"," ",""];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= +c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, +wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, +prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, +this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); +return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, +""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); +return this}else{e=0;for(var j=d.length;e 0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", +""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===" "&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= +c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? +c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= +function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= +Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, +"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= +a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= +a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/ + +{% endblock %} + +{% block onload %} onload='javascript:textareaformat();' {% endblock %} + +{% block manage %} + +{% endblock %} + diff --git a/testapp/yaksh/templates/yaksh/add_questionpaper.html b/testapp/yaksh/templates/yaksh/add_questionpaper.html new file mode 100644 index 0000000..eaa96bc --- /dev/null +++ b/testapp/yaksh/templates/yaksh/add_questionpaper.html @@ -0,0 +1,27 @@ +{% extends "manage.html" %} + + +{% block subtitle %}Design Question Paper{% endblock %} + +{% block css %} + + +{% endblock %} +{% block script %} + + +{% endblock %} + +{% block manage %} + +
+{% csrf_token %} +Select mode to design Question Paper: + + + +{% endblock %} diff --git a/testapp/yaksh/templates/yaksh/add_quiz.html b/testapp/yaksh/templates/yaksh/add_quiz.html new file mode 100644 index 0000000..e78023d --- /dev/null +++ b/testapp/yaksh/templates/yaksh/add_quiz.html @@ -0,0 +1,25 @@ +{% extends "manage.html" %} + + +{% block subtitle %}Add Quiz{% endblock %} + +{% block css %} + +{% endblock %} +{% block script %} + +{% endblock %} +{% block onload %} onload="javascript:test();" {% endblock %} +{% block manage %} ++ {% csrf_token %} + +{% endblock %} diff --git a/testapp/yaksh/templates/yaksh/ajax_marks.html b/testapp/yaksh/templates/yaksh/ajax_marks.html new file mode 100644 index 0000000..716bb88 --- /dev/null +++ b/testapp/yaksh/templates/yaksh/ajax_marks.html @@ -0,0 +1,4 @@ + +{% for mark in marks %} + +{% endfor %} diff --git a/testapp/yaksh/templates/yaksh/ajax_question_filter.html b/testapp/yaksh/templates/yaksh/ajax_question_filter.html new file mode 100644 index 0000000..11bf660 --- /dev/null +++ b/testapp/yaksh/templates/yaksh/ajax_question_filter.html @@ -0,0 +1,15 @@ ++ + ++ {{ form.as_table }} +
++ ++ {% if questions %} +diff --git a/testapp/yaksh/templates/yaksh/ajax_questions.html b/testapp/yaksh/templates/yaksh/ajax_questions.html new file mode 100644 index 0000000..e343f9b --- /dev/null +++ b/testapp/yaksh/templates/yaksh/ajax_questions.html @@ -0,0 +1,31 @@ +Select All
+ {% endif %} ++ + {% for question in questions %} +
+- + +
+ {% endfor %} ++ {% if questions %} + + Select All + {% endif %} ++ ++ + {% for question in questions %} +
+- + +
+ {% endfor %} ++ +diff --git a/testapp/yaksh/templates/yaksh/automatic_questionpaper.html b/testapp/yaksh/templates/yaksh/automatic_questionpaper.html new file mode 100644 index 0000000..b9a4ae0 --- /dev/null +++ b/testapp/yaksh/templates/yaksh/automatic_questionpaper.html @@ -0,0 +1,87 @@ +{% extends "manage.html" %} + + +{% block subtitle %}Design Question Paper{% endblock %} + +{% block css %} + + + +{% endblock %} +{% block script %} + + +{% endblock %} + +{% block manage %} + +Automatic mode to design the Question Paper
++ {% csrf_token %} + + +{% endblock %} diff --git a/testapp/yaksh/templates/yaksh/complete.html b/testapp/yaksh/templates/yaksh/complete.html new file mode 100644 index 0000000..08abe76 --- /dev/null +++ b/testapp/yaksh/templates/yaksh/complete.html @@ -0,0 +1,33 @@ +{% extends "base.html" %} + +{% block title %}Good bye!{% endblock %} + +{% block pagetitle %}Online Test{% endblock %} +{% block content %} +{% csrf_token %} + {% if submitted or unattempted %} ++ Tag Conditions: + + + + + + + + + + + +
+ +Number of question: + +
+
+Below is the list of Questions fetched according to the given tag conditions
+
++
+ {% if data.msg %}Summary + Type + Points + Tags + {% for question in data.questions %} + + + {{ question.summary }} {{ question.type }} {{ question.points }} + {% for tag in question.tags.all %} + {{ tag }} + {% endfor %} +
+ {% endfor %} +{{ data.msg }}{% endif %} ++ + {% endif %} + +
+ Submitted Questions ++ {% if submitted %} + {{ submitted|join:", " }} + {% else %} + No Questions have been Submitted
+ {% endif %} ++ Unattempted Questions ++ {% if unattempted %} + {{ unattempted|join:", " }} + {% else %} + All Questions have been Submitted
+ {% endif %} ++ Good bye!
+ {{message}}
You may now close the browser.
+Login Again +{% endblock content %} diff --git a/testapp/yaksh/templates/yaksh/design_questionpaper.html b/testapp/yaksh/templates/yaksh/design_questionpaper.html new file mode 100644 index 0000000..2aa169b --- /dev/null +++ b/testapp/yaksh/templates/yaksh/design_questionpaper.html @@ -0,0 +1,182 @@ +{% extends "manage.html" %} + +{% block subtitle %}Design Question Paper{% endblock %} + +{% block css %} + + + + + +{% endblock %} +{% block script %} + + + + + + +{% endblock %} + +{% block manage %} + +Manual mode to design the {{lang}} Question Paper
++
+ +- + + STEP 1
+
+ Add Fixed Questions + +- + + STEP 2
+
+ Add Random Questions + +- + + STEP 3
+
+ Finish +{% csrf_token %} + +++Total Marks: 0
++ ++ +++Please select Question type and Marks
++ {{ form.question_type }} +++ {{ form.marks }} +++ ++
+ + + + + + + ++++ +Almost finished creating your question paper
+
+ + +
++ < Previous ++
+ + + +++ +++ +++ + + +{% endblock %} diff --git a/testapp/yaksh/templates/yaksh/edit_question.html b/testapp/yaksh/templates/yaksh/edit_question.html new file mode 100644 index 0000000..9a66250 --- /dev/null +++ b/testapp/yaksh/templates/yaksh/edit_question.html @@ -0,0 +1,61 @@ +{% extends "manage.html" %} + +{% block subtitle %}Edit Question{% endblock %} + +{% block css %} + + +{% endblock %} +{% block script %} + + +{% endblock %} + +{% block onload %} onload = 'javascript:textareaformat();' {% endblock %} + +{% block manage %} +++ ++ {% csrf_token %} + +{% endblock %} diff --git a/testapp/yaksh/templates/yaksh/edit_quiz.html b/testapp/yaksh/templates/yaksh/edit_quiz.html new file mode 100644 index 0000000..fb7df93 --- /dev/null +++ b/testapp/yaksh/templates/yaksh/edit_quiz.html @@ -0,0 +1,39 @@ +{% extends "manage.html" %} + + +{% block subtitle %}Edit Quiz(zes){% endblock %} + +{% block css %} + +{% endblock %} + +{% block script %} + +{% endblock %} + +{% block onload %} onload = 'javascript:form_load();' {% endblock %} + +{% block manage %} ++ + Click on the Question links to edit the question.
+ + {% for question, test in data_list %} + +
+ + +{% for i in data %} + +{% endfor %} + +{{question.summary.value}} + + + {% endfor %} + + ++ {% csrf_token %} + +{% endblock %} diff --git a/testapp/yaksh/templates/yaksh/editquestionpaper.html b/testapp/yaksh/templates/yaksh/editquestionpaper.html new file mode 100644 index 0000000..2b7b835 --- /dev/null +++ b/testapp/yaksh/templates/yaksh/editquestionpaper.html @@ -0,0 +1,21 @@ +{% extends "manage.html" %} + + +{% block subtitle %}Questions in "{{ papers.quiz.description }}"{% endblock %} + +{% block script %} + +{% endblock %} + +{% block manage %} ++ +{% for i in data %} + +{% endfor %} ++ {% for form in forms %} +
+Start Date: {{ form.start_date}} + Duration: {{ form.duration }}
{{form.duration.help_text}} +Active: {{ form.active }} + Description: {{ form.description }} + Passing Criteria: {{ form.pass_criteria }}
{{form.pass_criteria.help_text}} +Language: {{ form.language }} + Prerequisite: {{ form.prerequisite }} +
+ {% endfor %} ++ ++{% csrf_token %} + +{% for i in papers.questions %} + {{ i.summary}} +{% endblock %} diff --git a/testapp/yaksh/templates/yaksh/grade_user.html b/testapp/yaksh/templates/yaksh/grade_user.html new file mode 100644 index 0000000..8c094a7 --- /dev/null +++ b/testapp/yaksh/templates/yaksh/grade_user.html @@ -0,0 +1,94 @@ +{% extends "manage.html" %} + +{% block title %} Grading papers for {{ data.user.get_full_name.title }} {% endblock title %} + +{% block subtitle %}Grading papers for {{ data.user.get_full_name.title }}{% endblock %} + +{% block css %} + +{% endblock %} + +{% block script %} + +{% endblock %} +{% block manage %} + +
+{% endfor %} +
+ + ++Name: {{ data.user.get_full_name.title }} +{% if data.profile %} +(roll number: {{ data.profile.roll_number }})
+ +{% if data.papers %} + +{% for paper in data.papers %} + +
+{{ data.profile.position }}, +{{ data.profile.department }}, +{{ data.profile.institute }} +{% endif %} +Quiz: {{ paper.quiz.description }}
+ ++Questions correctly answered: {{ paper.get_answered_str }}
+ +{% if paper.answers.count %} +
+Total attempts at questions: {{ paper.answers.count }}
+Marks obtained: {{ paper.get_total_marks }}
+Start time: {{ paper.start_time }}
+Answers
++{% csrf_token %} +{% for question, answers in paper.get_question_answers.items %} + +{% endif %} {# if paper.answers.count #} + +{% endfor %} {# for paper in data.papers #} + +{% endif %} {# if data.papers #} + +{% endblock%} diff --git a/testapp/yaksh/templates/yaksh/intro.html b/testapp/yaksh/templates/yaksh/intro.html new file mode 100644 index 0000000..9c5c14d --- /dev/null +++ b/testapp/yaksh/templates/yaksh/intro.html @@ -0,0 +1,53 @@ +{% extends "base.html" %} + +{% block title %}Instructions and Rules {% endblock %} +{% block pagetitle %}Online Test {% endblock %} +{% block formtitle %}Important instructions & rules {% endblock %} +{% block content %} + + {% if enable_quiz_time or disable_quiz_time %} + {% if quiz_expired %} +++{% endfor %} {# for question, answers ... #} + + ++ Question: {{ question.id }}. {{ question.summary }} (Points: {{ question.points }}) + +Details
+++ ++ +{% if question.type == "mcq" %} ++
+Choices: +{% for option in question.options.strip.splitlines %} {{option}}, {% endfor %} +
+Student answer: {{ answers.0 }}
+{% else %}{# non-mcq questions #} ++{% for answer in answers %}################################################################################ +{{ answer.answer.strip }} +# Autocheck: {{ answer.error }} +{% endfor %}+{% endif %} {# if question.type #} +{% with answers|last as answer %} +Marks:
+{% endwith %} +Teacher comments:
+ +
+
+ ++ This Quiz has expired. You can no longer attempt this Quiz. ++ {% else %} +
++ You can attempt this Quiz at any time between {{ enable_quiz_time }} and {{ disable_quiz_time }} ++ {% endif %} + {% endif %} +
+ You are not allowed to attempt the Quiz before or after this duration +
+Welcome {{user.first_name.title}} {{user.last_name.title}}, to the programming quiz!
++ This examination system has been developed with the intention of making you + learn programming and be assessed in an interactive and fun manner. + You will be presented with a series of programming questions and problems that + you will answer online and get immediate feedback for. +
+Here are some important instructions and rules that you should understand carefully.
++
+- For any programming questions, you can submit solutions as many times as you want without a penalty. You may skip questions and solve them later. +
+- You may use your computer's Python/IPython shell or an editor to solve the problem and cut/paste the solution to the web interface. +
+- You are not allowed to use any internet resources, i.e. no google etc.
+- Do not copy or share the questions or answers with anyone until the exam is complete for everyone.
+- All your attempts at the questions are logged. Do not try to outsmart and break the testing system. If you do, we know who you are and we will expell you from the course. You have been warned. +
+We hope you enjoy taking this exam !!!
+ ++ {% csrf_token %} + + {% if not quiz_expired %} ++ + {% csrf_token %} + + {% endif %} +{% endblock content %} diff --git a/testapp/yaksh/templates/yaksh/login.html b/testapp/yaksh/templates/yaksh/login.html new file mode 100644 index 0000000..dfeac1e --- /dev/null +++ b/testapp/yaksh/templates/yaksh/login.html @@ -0,0 +1,22 @@ +{% extends "base.html" %} + +{% block title %}Login{% endblock title %} +{% block pagetitle %} Online Test {% endblock %} +{% block formtitle %}Login{% endblock %} +{% block css %} + +{% endblock %} +{% block content %} + ++ + {% csrf_token %} + + + +{% endblock content %} diff --git a/testapp/yaksh/templates/yaksh/manual_questionpaper.html b/testapp/yaksh/templates/yaksh/manual_questionpaper.html new file mode 100644 index 0000000..86bfd67 --- /dev/null +++ b/testapp/yaksh/templates/yaksh/manual_questionpaper.html @@ -0,0 +1,79 @@ +{% extends "manage.html" %} + + +{% block subtitle %}Design Question Paper{% endblock %} + +{% block css %} + + + +{% endblock %} +{% block script %} + + +{% endblock %} + +{% block manage %} + ++ + {{ form.as_table }} +
+ Forgot Password?
+New User? Sign-Up +Manual mode to design the Question Paper
+ ++ {% csrf_token %} + + +{% endblock %} diff --git a/testapp/yaksh/templates/yaksh/monitor.html b/testapp/yaksh/templates/yaksh/monitor.html new file mode 100644 index 0000000..52695cb --- /dev/null +++ b/testapp/yaksh/templates/yaksh/monitor.html @@ -0,0 +1,69 @@ +{% extends "manage.html" %} + +{% block title %} Quiz results {% endblock title %} + +{% block meta %} {% endblock meta %} + +{% block css %} + +{% endblock %} +{% block subtitle %} + {% if not quizzes and not quiz %} + Quiz Results + {% endif %} + {% if quizzes %} + Available Quizzes + {% endif %} + {% if quiz %} + {{ quiz.description }} Results + {% endif %} +{% endblock %} +{% block manage %} + {% if not quizzes and not quiz %} ++ Tag Conditions: + + + + + + +
++ +
Below is the list of Questions fetched according to the given tag conditions
++
+ {% if data.msg %}+ Summary + Type + Points + Tags + {% for question in data.questions %} + + {{ question.summary }} {{ question.type }} {{ question.points }} + {% for tag in question.tags.all %} + {{ tag }} + {% endfor %} +
+ {% endfor %} +{{ data.msg }}{% endif %} ++ + {% endif %} + +{# ############################################################### #} +{# This is rendered when we are just viewing exam/monitor #} +{% if quizzes %} + No quizzes available.
+{% for q in quizzes %} +
+{% endif %} + +{# ############################################################### #} +{# This is rendered when we are just viewing exam/monitor/quiz_num #} +{% if quiz %} + +{% if papers %} +{#- {{ q.quiz.description }}
+{% endfor %} +Quiz: {{ quiz_name }}
#} +Number of papers: {{ papers|length }}
++
+{% else %} ++ + {% for paper in papers %} +Name +Username +Roll number +Institute +Questions answered +Marks obtained +Attempts ++ + {% endfor %} +{{ paper.user.get_full_name.title }} +{{ paper.user.username }} +{{ paper.profile.roll_number }} +{{ paper.profile.institute }} +{{ paper.get_answered_str }} +{{ paper.marks_obtained }} +{{ paper.answers.count }} +No answer papers so far.
+{% endif %} {# if papers #} +{% endif %} +{% endblock %} diff --git a/testapp/yaksh/templates/yaksh/question.html b/testapp/yaksh/templates/yaksh/question.html new file mode 100644 index 0000000..e532513 --- /dev/null +++ b/testapp/yaksh/templates/yaksh/question.html @@ -0,0 +1,203 @@ +{% extends "base.html" %} + + + +{% block title %} Answer question {% endblock %} + +{% block css %} + + +{% endblock %} + +{% block script %} + + + + + +{% endblock script %} + + + +{% block onload %} onload="update_time();setSnippetHeight()" {% endblock %} + +{% block pagetitle %} + ++ +{% endblock %} + +{% block content %} + +
+You have {{ paper.questions_left }} question(s) left in {{ quiz_name }}
+ ++++ + +{{ question.summary }} (Marks : {{ question.points }})
+ {{ question.description|safe }} + {% if error_message %} ++ {% for e in error_message.splitlines %} + {{ e|join:"" }} +{% endif %} + + + +
+ {% endfor%} ++ {% csrf_token %} + + + {% if question.type == "mcq" %} + {% for option in question.options.strip.splitlines %} + {{option}} + + + +
+ {% endfor %} + {% endif %} + {% if question.type == "upload" %} +Upload assignment file for the said question
+ +
+ {% endif %} + {% if question.type == "mcc" %} + {% for option in question.options.strip.splitlines %} + {{ option }} +
+ {% endfor %} + {% endif %} + {% if question.type == "code" %} + + + + +
+ + + + {% endif %} + + {% if question.type == "mcq" or question.type == "mcc "%} +
+ {% elif question.type == "upload" %} +
+ {% else %} + + {% endif %} + {% if to_attempt|length != 1 %} + + {% endif %} +++ +{% endblock content %} diff --git a/testapp/yaksh/templates/yaksh/quit.html b/testapp/yaksh/templates/yaksh/quit.html new file mode 100644 index 0000000..91bce64 --- /dev/null +++ b/testapp/yaksh/templates/yaksh/quit.html @@ -0,0 +1,35 @@ +{% extends "base.html" %} + +{% block title %}Quit exam {% endblock %} +{% block pagetitle %}Online Test {% endblock %} +{% block content %} + {% if submitted or unattempted %} +++ ++ {% endif %} + + +
+ Submitted Questions ++ {% if submitted %} + {{ submitted|join:", " }} + {% else %} + No Questions have been Submitted
+ {% endif %} ++ Unattempted Questions ++ {% if unattempted %} + {{ unattempted|join:", " }} + {% else %} + All Questions have been Submitted
+ {% endif %} ++ Your current answers are saved.
+ Are you sure you wish to quit the exam?
+ Be sure, as you won't be able to restart this exam.
+ {% csrf_token %} + +{% endblock content %} diff --git a/testapp/yaksh/templates/yaksh/quizlist.html b/testapp/yaksh/templates/yaksh/quizlist.html new file mode 100644 index 0000000..9b1fd73 --- /dev/null +++ b/testapp/yaksh/templates/yaksh/quizlist.html @@ -0,0 +1,24 @@ +{% extends "base.html" %} + +{% block title %} Quiz List {% endblock title %} + +{% block formtitle %} Quiz List {% endblock %} + +{% block pagetitle %} Online Test {% endblock %} + +{% block content %} +{% if not quizzes and not quiz %} ++ +{% endif %} + +{% if quizzes %} + No quizzes available.
+{% csrf_token %} + +{% for quiz in quizzes %} +{{ quiz.description }} +{% endif %} + +{% endblock %} diff --git a/testapp/yaksh/templates/yaksh/quizzes_user.html b/testapp/yaksh/templates/yaksh/quizzes_user.html new file mode 100644 index 0000000..fbd50ce --- /dev/null +++ b/testapp/yaksh/templates/yaksh/quizzes_user.html @@ -0,0 +1,87 @@ +{% extends "user.html" %} + + +{% block subtitle %}Hello {{ user.first_name }}, welcome to your dashboard !{% endblock %} + +{% block css %} + +{% endblock %} + +{% block script %} + + +{% endblock %} + + +{% block manage %} + {% if cannot_attempt %} +
+{% endfor %} +You have not passed the prerequisite & hence you cannot take the quiz.
+ {% endif %} +List of quizzes availbale for you
+ {% if not quizzes %} +No active quizzes for you
+ {% endif %} ++
+Quiz +Pre requisite quiz + {% for paper in quizzes %} ++ {% if paper in unexpired_quizzes %} + + {% endfor %} ++ {{ paper.quiz.description }} + {% else %} +
++ {{ paper.quiz.description }} Expired + {% endif %} +
++ {% if paper.quiz.prerequisite %} + You have to pass {{ paper.quiz.prerequisite.description }} for taking {{ paper.quiz.description }} + {% else %} + No pre requisites for {{ paper.quiz.description }} + {% endif %} + +
+List of quizzes taken by you so far
+ {% if quizzes_taken %} ++
+ {% else %} +Quiz +Result +Mraks Obtained +Total Marks +Percentage + {% for paper in quizzes_taken %} ++ + {% endfor %} ++ {{ paper.question_paper.quiz.description }} + ++ {% if paper.passed %} + +Pass
+ {% else %} +Fail
+ {% endif %} ++ {{ paper.marks_obtained }} + ++ {{ paper.question_paper.total_marks }} + ++ {{ paper.percent }} + +You have not taken any quiz yet !!
+ {% endif %} + + +{% endblock %} + diff --git a/testapp/yaksh/templates/yaksh/register.html b/testapp/yaksh/templates/yaksh/register.html new file mode 100644 index 0000000..5ff79cc --- /dev/null +++ b/testapp/yaksh/templates/yaksh/register.html @@ -0,0 +1,20 @@ +{% extends "base.html" %} + +{% block title %}Registration form {% endblock %} + +{% block pagetitle %}Online Test {% endblock %} +{% block formtitle %}Please fill in the following details {% endblock %} + +{% block content %} + + + ++ {% csrf_token %} + + +{% endblock content %} diff --git a/testapp/yaksh/templates/yaksh/results_user.html b/testapp/yaksh/templates/yaksh/results_user.html new file mode 100644 index 0000000..0f35c0d --- /dev/null +++ b/testapp/yaksh/templates/yaksh/results_user.html @@ -0,0 +1,28 @@ +{% extends "user.html" %} + + +{% block subtitle %}Results{% endblock %} + +{% block css %} + +{% endblock %} + +{% block manage %} ++ + {{ form.as_table }} +
+ + {% csrf_token %} + +{% endblock %} + diff --git a/testapp/yaksh/templates/yaksh/show_quiz.html b/testapp/yaksh/templates/yaksh/show_quiz.html new file mode 100644 index 0000000..2cd4e11 --- /dev/null +++ b/testapp/yaksh/templates/yaksh/show_quiz.html @@ -0,0 +1,33 @@ +{% extends "manage.html" %} + +{% block title %} Quiz List {% endblock title %} + +{% block script %} + +{% endblock %} + +{% block subtitle %} Quiz List {% endblock %} +{% block manage %} +{% if not quizzes and not quiz %} ++ +
Quiz Description + Obtained Marks + Maximum Marks + Percentage + {% for paper in papers %} + + {% for i in paper %} + {{ i }} + {% endfor %} +
+ {% endfor %} ++ +{% endif %} + +{# ############################################################### #} +{# This is rendered when we are just viewing exam/monitor #} +{% if quizzes %} + No quizzes available.
+{% csrf_token %} + +{% for quiz in quizzes %} + {{ quiz.description }} +{% endif %} + +{% endblock %} diff --git a/testapp/yaksh/templates/yaksh/showquestionpapers.html b/testapp/yaksh/templates/yaksh/showquestionpapers.html new file mode 100644 index 0000000..e705ce7 --- /dev/null +++ b/testapp/yaksh/templates/yaksh/showquestionpapers.html @@ -0,0 +1,23 @@ +{% extends "manage.html" %} + + +{% block subtitle %}List of Question Papers {% endblock %} + +{% block script %} + +{% endblock %} + +{% block manage %} +{% if papers %} +
+{% endfor %} + +
+ + + ++{% csrf_token %} +{% for i in papers %} + {{ i.quiz.description }} +{% else %} +
+{% endfor %} +
+ ++{% endif %} +{% endblock %} diff --git a/testapp/yaksh/templates/yaksh/showquestions.html b/testapp/yaksh/templates/yaksh/showquestions.html new file mode 100644 index 0000000..6222d6d --- /dev/null +++ b/testapp/yaksh/templates/yaksh/showquestions.html @@ -0,0 +1,44 @@ +{% extends "manage.html" %} + + +{% block subtitle %}List of Questions {% endblock %} + +{% block script %} + + + +{% endblock %} + +{% block manage %} + No Question Papers available
+{% csrf_token %} + +{% endblock %} diff --git a/testapp/yaksh/templates/yaksh/showusers.html b/testapp/yaksh/templates/yaksh/showusers.html new file mode 100644 index 0000000..ae91076 --- /dev/null +++ b/testapp/yaksh/templates/yaksh/showusers.html @@ -0,0 +1,26 @@ +{% extends "manage.html" %} + + +{% block subtitle %} +List of Users +{% endblock %} + +{% block css %} + +{% endblock css %} + + +{% block manage %} +++Filters
++ {{ form.question_type }} +++ {{ form.language }} +++ {{ form.marks }} ++
++++ ++
++{% for i in questions %} + {{ i }}+
+{% endfor %} +
+ + + ++{% endblock %} diff --git a/testapp/yaksh/templates/yaksh/user_data.html b/testapp/yaksh/templates/yaksh/user_data.html new file mode 100644 index 0000000..61a3a97 --- /dev/null +++ b/testapp/yaksh/templates/yaksh/user_data.html @@ -0,0 +1,80 @@ +{% extends "manage.html" %} + +{% block title %} Data for user {{ data.user.get_full_name.title }} {% endblock title %} + +{% block manage %} + +{% block subtitle %}Data for user {{ data.user.get_full_name.title }}{% endblock %} + +
Username + First Name + Last Name + Quiz Description +{% for papers in question %} + {{ papers.user.username }}
+{{ papers.user.first_name.title }} + {{ papers.user.last_name.title }} + {{ papers.question_paper.quiz.description }} +{% endfor %} + + +Name: {{ data.user.get_full_name.title }}
+ +{% if data.papers %} + + +{% for paper in data.papers %} + +
+Username: {{ data.user.username }}
+{% if data.profile %} +Roll number: {{ data.profile.roll_number }}
+Position: {{ data.profile.position }}
+Department: {{ data.profile.department }}
+Institute: {{ data.profile.institute }}
+{% endif %} +Email: {{ data.user.email }}
+Date joined: {{ data.user.date_joined }}
+Last login: {{ data.user.last_login }} +Quiz: {{ paper.quiz.description }}
+ ++Questions correctly answered: {{ paper.get_answered_str }}
+ +{% if paper.answers.count %} +
+Total attempts at questions: {{ paper.answers.count }}
+Marks obtained: {{ paper.get_total_marks }}
+Start time: {{ paper.start_time }}
+User IP address: {{ paper.user_ip }} +Answers
+{% for question, answers in paper.get_question_answers.items %} +Question: {{ question.id }}. {{ question.summary }} (Points: {{ question.points }})
+{% if question.type == "mcq" %} +Choices: +{% for option in question.options.strip.splitlines %} {{option}}, {% endfor %} +
+Student answer: {{ answers.0 }}
+{% else %}{# non-mcq questions #} ++{% for answer in answers %}################################################################################ +{{ answer.answer.strip }} +# Autocheck: {{ answer.error }} +{% endfor %}+{% endif %} +{% with answers|last as answer %} +Marks: {{answer.marks}}
+{% endwith %} +{% endfor %} {# for question, answers ... #} +Teacher comments:
+{{ paper.comments|default:"None" }} +{% endif %} {# if paper.answers.count #} + +{% endfor %} {# for paper in data.papers #} + +{% endif %} {# if data.papers #} +
+
+ + Grade/correct paper +
+{% if data.papers.count > 1 %} +Monitor quiz +{% else %} +{% with data.papers.0 as paper %} +Monitor quiz +{% endwith %} +{% endif %} + +{% endblock %} diff --git a/testapp/yaksh/tests.py b/testapp/yaksh/tests.py new file mode 100644 index 0000000..f1587b7 --- /dev/null +++ b/testapp/yaksh/tests.py @@ -0,0 +1,345 @@ +from django.utils import unittest +from testapp.yaksh.models import User, Profile, Question, Quiz, QuestionPaper,\ + QuestionSet, AnswerPaper, Answer, TestCase +import datetime, json + +def setUpModule(): + # create user profile + user = User.objects.create_user(username='demo_user', + password='demo', + email='demo@test.com') + User.objects.create_user(username='demo_user2', + password='demo', + email='demo@test.com') + Profile.objects.create(user=user, roll_number=1, institute='IIT', + department='Chemical', position='Student') + + # create 20 questions + for i in range(1, 21): + Question.objects.create(summary='Q%d' % (i), points=1) + + # create a quiz + Quiz.objects.create(start_date='2014-06-16', duration=30, active=False, + attempts_allowed=-1, time_between_attempts=0, + description='demo quiz', pass_criteria=40, + language='Python', prerequisite=None) + + +def tearDownModule(): + User.objects.all().delete() + Question.objects.all().delete() + Quiz.objects.all().delete() + + +############################################################################### +class ProfileTestCases(unittest.TestCase): + def setUp(self): + self.user = User.objects.get(pk=1) + self.profile = Profile.objects.get(pk=1) + + def test_user_profile(self): + """ Test user profile""" + self.assertEqual(self.user.username, 'demo_user') + self.assertEqual(self.profile.user.username, 'demo_user') + self.assertEqual(int(self.profile.roll_number), 1) + self.assertEqual(self.profile.institute, 'IIT') + self.assertEqual(self.profile.department, 'Chemical') + self.assertEqual(self.profile.position, 'Student') + + +############################################################################### +class QuestionTestCases(unittest.TestCase): + def setUp(self): + # Single question details + # self.question = Question(summary='Demo question', language='Python', + # type='Code', active=True, + # description='Write a function', points=1.0, + # test='Test Cases', snippet='def myfunc()') + self.question = Question(summary='Demo question', language='Python', + type='Code', active=True, + description='Write a function', points=1.0, + snippet='def myfunc()') + self.question.save() + self.question.tags.add('python', 'function') + self.testcase = TestCase(question=self.question, + func_name='def myfunc', kw_args='a=10,b=11', + pos_args='12,13', expected_answer='15') + answer_data = { "test": "", + "user_answer": "demo_answer", + "test_parameter": [{"func_name": "def myfunc", + "expected_answer": "15", + "test_id": self.testcase.id, + "pos_args": ["12", "13"], + "kw_args": {"a": "10", + "b": "11"} + }], + "id": self.question.id, + "ref_code_path": "", + } + self.answer_data_json = json.dumps(answer_data) + self.user_answer = "demo_answer" + + def test_question(self): + """ Test question """ + self.assertEqual(self.question.summary, 'Demo question') + self.assertEqual(self.question.language, 'Python') + self.assertEqual(self.question.type, 'Code') + self.assertFalse(self.question.options) + self.assertEqual(self.question.description, 'Write a function') + self.assertEqual(self.question.points, 1.0) + self.assertTrue(self.question.active) + self.assertEqual(self.question.snippet, 'def myfunc()') + tag_list = [] + for tag in self.question.tags.all(): + tag_list.append(tag.name) + self.assertEqual(tag_list, ['python', 'function']) + + def test_consolidate_answer_data(self): + """ Test consolidate_answer_data function """ + result = self.question.consolidate_answer_data([self.testcase], + self.user_answer) + self.assertEqual(result, self.answer_data_json) + + + +############################################################################### +class TestCaseTestCases(unittest.TestCase): + def setUp(self): + self.question = Question(summary='Demo question', language='Python', + type='Code', active=True, + description='Write a function', points=1.0, + snippet='def myfunc()') + self.question.save() + self.testcase = TestCase(question=self.question, + func_name='def myfunc', kw_args='a=10,b=11', + pos_args='12,13', expected_answer='15') + + def test_testcase(self): + """ Test question """ + self.assertEqual(self.testcase.question, self.question) + self.assertEqual(self.testcase.func_name, 'def myfunc') + self.assertEqual(self.testcase.kw_args, 'a=10,b=11') + self.assertEqual(self.testcase.pos_args, '12,13') + self.assertEqual(self.testcase.expected_answer, '15') + + +############################################################################### +class QuizTestCases(unittest.TestCase): + def setUp(self): + self.quiz = Quiz.objects.get(pk=1) + + def test_quiz(self): + """ Test Quiz""" + self.assertEqual((self.quiz.start_date).strftime('%Y-%m-%d'), + '2014-06-16') + self.assertEqual(self.quiz.duration, 30) + self.assertTrue(self.quiz.active is False) + self.assertEqual(self.quiz.description, 'demo quiz') + self.assertEqual(self.quiz.language, 'Python') + self.assertEqual(self.quiz.pass_criteria, 40) + self.assertEqual(self.quiz.prerequisite, None) + + +############################################################################### +class QuestionPaperTestCases(unittest.TestCase): + @classmethod + def setUpClass(self): + # All active questions + self.questions = Question.objects.filter(active=True) + self.quiz = Quiz.objects.get(id=1) + + # create question paper + self.question_paper = QuestionPaper.objects.create(quiz=self.quiz, + total_marks=0.0, shuffle_questions=True) + + # add fixed set of questions to the question paper + self.question_paper.fixed_questions.add(self.questions[3], + self.questions[5]) + # create two QuestionSet for random questions + # QuestionSet 1 + self.question_set_1 = QuestionSet.objects.create(marks=2, + num_questions=2) + + # add pool of questions for random sampling + self.question_set_1.questions.add(self.questions[6], self.questions[7], + self.questions[8], self.questions[9]) + # add question set 1 to random questions in Question Paper + self.question_paper.random_questions.add(self.question_set_1) + + # QuestionSet 2 + self.question_set_2 = QuestionSet.objects.create(marks=3, + num_questions=3) + + # add pool of questions + self.question_set_2.questions.add(self.questions[11], + self.questions[12], + self.questions[13], + self.questions[14]) + # add question set 2 + self.question_paper.random_questions.add(self.question_set_2) + + # ip address for AnswerPaper + self.ip = '127.0.0.1' + + self.user = User.objects.get(pk=1) + + self.attempted_papers = AnswerPaper.objects.filter(question_paper=self.question_paper, + user=self.user) + + def test_questionpaper(self): + """ Test question paper""" + self.assertEqual(self.question_paper.quiz.description, 'demo quiz') + self.assertEqual(list(self.question_paper.fixed_questions.all()), + [self.questions[3], self.questions[5]]) + self.assertTrue(self.question_paper.shuffle_questions) + + def test_update_total_marks(self): + """ Test update_total_marks() method of Question Paper""" + self.assertEqual(self.question_paper.total_marks, 0) + self.question_paper.update_total_marks() + self.assertEqual(self.question_paper.total_marks, 15) + + def test_get_random_questions(self): + """ Test get_random_questions() method of Question Paper""" + random_questions_set_1 = self.question_set_1.get_random_questions() + random_questions_set_2 = self.question_set_2.get_random_questions() + + # To check whether random questions are from random_question_set + questions_set_1 = set(self.question_set_1.questions.all()) + random_set_1 = set(random_questions_set_1) + random_set_2 = set(random_questions_set_2) + boolean = questions_set_1.intersection(random_set_1) == random_set_1 + self.assertTrue(boolean) + self.assertEqual(len(random_set_1), 2) + # To check that the questions are random. + # If incase not random then check that the order is diferent + try: + self.assertFalse(random_set_1 == random_set_2) + except AssertionError: + self.assertTrue(random_questions_set_1 != random_questions_set_2) + + def test_get_questions_for_answerpaper(self): + """ Test get_questions_for_answerpaper() method of Question Paper""" + questions = self.question_paper._get_questions_for_answerpaper() + fixed = list(self.question_paper.fixed_questions.all()) + question_set = self.question_paper.random_questions.all() + total_random_questions = 0 + available_questions = [] + for qs in question_set: + total_random_questions += qs.num_questions + available_questions += qs.questions.all() + self.assertEqual(total_random_questions, 5) + self.assertEqual(len(available_questions), 8) + self.assertEqual(len(questions), 7) + + def test_make_answerpaper(self): + """ Test make_answerpaper() method of Question Paper""" + already_attempted = self.attempted_papers.count() + attempt_num = already_attempted + 1 + answerpaper = self.question_paper.make_answerpaper(self.user, self.ip, + attempt_num) + self.assertIsInstance(answerpaper, AnswerPaper) + paper_questions = set((answerpaper.questions).split('|')) + self.assertEqual(len(paper_questions), 7) + fixed = {'4', '6'} + boolean = fixed.intersection(paper_questions) == fixed + self.assertTrue(boolean) + + +############################################################################### +class AnswerPaperTestCases(unittest.TestCase): + @classmethod + def setUpClass(self): + self.ip = '101.0.0.1' + self.user = User.objects.get(id=1) + self.profile = self.user.profile + self.quiz = Quiz.objects.get(pk=1) + self.question_paper = QuestionPaper(quiz=self.quiz, total_marks=3) + self.question_paper.save() + + # create answerpaper + self.answerpaper = AnswerPaper(user=self.user, + questions='1|2|3', + question_paper=self.question_paper, + start_time='2014-06-13 12:20:19.791297', + end_time='2014-06-13 12:50:19.791297', + user_ip=self.ip) + self.answerpaper.questions_answered = '1' + self.attempted_papers = AnswerPaper.objects.filter(question_paper=self.question_paper, + user=self.user) + already_attempted = self.attempted_papers.count() + self.answerpaper.attempt_number = already_attempted + 1 + self.answerpaper.save() + + # answers for the Answer Paper + self.answer_right = Answer(question=Question.objects.get(id=1), + answer="Demo answer", correct=True, marks=1) + self.answer_wrong = Answer(question=Question.objects.get(id=2), + answer="My answer", correct=False, marks=0) + self.answer_right.save() + self.answer_wrong.save() + self.answerpaper.answers.add(self.answer_right) + self.answerpaper.answers.add(self.answer_wrong) + + def test_answerpaper(self): + """ Test Answer Paper""" + self.assertEqual(self.answerpaper.user.username, 'demo_user') + self.assertEqual(self.answerpaper.user_ip, self.ip) + questions = self.answerpaper.questions + num_questions = len(questions.split('|')) + self.assertEqual(questions, '1|2|3') + self.assertEqual(num_questions, 3) + self.assertEqual(self.answerpaper.question_paper, self.question_paper) + self.assertEqual(self.answerpaper.start_time, + '2014-06-13 12:20:19.791297') + self.assertEqual(self.answerpaper.end_time, + '2014-06-13 12:50:19.791297') + + def test_current_question(self): + """ Test current_question() method of Answer Paper""" + current_question = self.answerpaper.current_question() + self.assertEqual(current_question, '2') + + def test_completed_question(self): + """ Test completed_question() method of Answer Paper""" + question = self.answerpaper.completed_question(1) + self.assertEqual(self.answerpaper.questions_left(), 2) + + def test_questions_left(self): + """ Test questions_left() method of Answer Paper""" + self.assertEqual(self.answerpaper.questions_left(), 2) + + def test_skip(self): + """ Test skip() method of Answer Paper""" + current_question = self.answerpaper.current_question() + next_question_id = self.answerpaper.skip(current_question) + self.assertTrue(next_question_id is not None) + self.assertEqual(next_question_id, '3') + + def test_answered_str(self): + """ Test answered_str() method of Answer Paper""" + answered_question = self.answerpaper.get_answered_str() + self.assertEqual(answered_question, '1') + + def test_update_marks_obtained(self): + """ Test get_marks_obtained() method of Answer Paper""" + self.answerpaper.update_marks_obtained() + self.assertEqual(self.answerpaper.marks_obtained, 1.0) + + def test_update_percent(self): + """ Test update_percent() method of Answerpaper""" + self.answerpaper.update_percent() + self.assertEqual(self.answerpaper.percent, 33.33) + + def test_update_passed(self): + """ Test update_passed method of AnswerPaper""" + self.answerpaper.update_passed() + self.assertFalse(self.answerpaper.passed) + + def test_get_question_answer(self): + """ Test get_question_answer() method of Answer Paper""" + answered = self.answerpaper.get_question_answers() + first_answer = answered.values()[0][0] + self.assertEqual(first_answer.answer, 'Demo answer') + self.assertTrue(first_answer.correct) + self.assertEqual(len(answered), 2) diff --git a/testapp/yaksh/urls.py b/testapp/yaksh/urls.py new file mode 100644 index 0000000..11e5965 --- /dev/null +++ b/testapp/yaksh/urls.py @@ -0,0 +1,52 @@ +from django.conf.urls import patterns, url + +urlpatterns = patterns('testapp.yaksh.views', + url(r'^$', 'index'), + url(r'^login/$', 'user_login'), + url(r'^quizzes/$', 'quizlist_user'), + url(r'^results/$', 'results_user'), + url(r'^start/$', 'start'), + url(r'^start/(?P\d+)/(?P \d+)/$', 'start'), + url(r'^quit/(?P \d+)/(?P \d+)/$', 'quit'), + url(r'^intro/(?P \d+)/$', 'intro'), + url(r'^complete/$', 'complete'), + url(r'^complete/(?P \d+)/(?P \d+)/$',\ + 'complete'), + url(r'^register/$', 'user_register'), + url(r'^(?P \d+)/$', 'question'), + url(r'^(?P \d+)/check/$', 'check'), + url(r'^(?P \d+)/check/(?P \d+)/(?P \d+)/$',\ + 'check'), + url(r'^intro/$', 'start'), + url(r'^(?P \d+)/(?P \d+)/(?P \d+)/$', 'show_question'), + + url(r'^manage/$', 'prof_manage'), + url(r'^manage/addquestion/$', 'add_question'), + url(r'^manage/addquestion/(?P \d+)/$', 'add_question'), + url(r'^manage/addquiz/$', 'add_quiz'), + url(r'^manage/editquiz/$', 'edit_quiz'), + url(r'^manage/editquestion/$', 'edit_question'), + url(r'^manage/addquiz/(?P \d+)/$', 'add_quiz'), + url(r'^manage/gradeuser/$', 'show_all_users'), + url(r'^manage/gradeuser/(?P .*)/$', 'grade_user'), + url(r'^manage/questions/$', 'show_all_questions'), + url(r'^manage/showquiz/$', 'show_all_quiz'), + url(r'^manage/monitor/$', 'monitor'), + url(r'^manage/showquestionpapers/$', 'show_all_questionpapers'), + url(r'^manage/showquestionpapers/(?P \d+)/$',\ + 'show_all_questionpapers'), + url(r'^manage/monitor/(?P \d+)/$', 'monitor'), + url(r'^manage/user_data/(?P .*)/$', 'user_data'), + url(r'^manage/designquestionpaper/$', 'design_questionpaper'), + url(r'^manage/designquestionpaper/(?P \d+)/$',\ + 'design_questionpaper'), + url(r'^manage/designquestionpaper/automatic/(?P \d+)/$',\ + 'automatic_questionpaper'), + url(r'^manage/designquestionpaper/automatic$', 'automatic_questionpaper'), + url(r'^manage/designquestionpaper/manual$', 'manual_questionpaper'), + url(r'^manage/designquestionpaper/manual/(?P \d+)/$',\ + 'manual_questionpaper'), + url(r'^ajax/questionpaper/(?P .+)/$', 'ajax_questionpaper'), + url(r'^ajax/questions/filter/$', 'ajax_questions_filter'), ##@@ + +) diff --git a/testapp/yaksh/views.py b/testapp/yaksh/views.py new file mode 100644 index 0000000..d4476b7 --- /dev/null +++ b/testapp/yaksh/views.py @@ -0,0 +1,1502 @@ +import random +import string +import os +import stat +from os.path import dirname, pardir, abspath, join, exists +import datetime +import collections +from django.http import HttpResponse +from django.contrib.auth import login, logout, authenticate +from django.shortcuts import render_to_response, get_object_or_404, redirect +from django.template import RequestContext +from django.http import Http404 +from django.db.models import Sum +from django.views.decorators.csrf import csrf_exempt +from taggit.models import Tag +from itertools import chain +import json +# Local imports. +from testapp.yaksh.models import Quiz, Question, QuestionPaper, QuestionSet +from testapp.yaksh.models import Profile, Answer, AnswerPaper, User, TestCase +from testapp.yaksh.forms import UserRegisterForm, UserLoginForm, QuizForm,\ + QuestionForm, RandomQuestionForm, TestCaseFormSet,\ + QuestionFilterForm +from testapp.yaksh.xmlrpc_clients import code_server +from settings import URL_ROOT +from testapp.yaksh.models import AssignmentUpload + +# The directory where user data can be saved. +OUTPUT_DIR = abspath(join(dirname(__file__), 'output')) + + +def my_redirect(url): + """An overridden redirect to deal with URL_ROOT-ing. See settings.py + for details.""" + return redirect(URL_ROOT + url) + + +def my_render_to_response(template, context=None, **kwargs): + """Overridden render_to_response. + """ + if context is None: + context = {'URL_ROOT': URL_ROOT} + else: + context['URL_ROOT'] = URL_ROOT + return render_to_response(template, context, **kwargs) + + +def gen_key(no_of_chars): + """Generate a random key of the number of characters.""" + allowed_chars = string.digits+string.uppercase + return ''.join([random.choice(allowed_chars) for i in range(no_of_chars)]) + + +def get_user_dir(user): + """Return the output directory for the user.""" + + user_dir = join(OUTPUT_DIR, str(user.username)) + if not exists(user_dir): + os.mkdir(user_dir) + # Make it rwx by others. + os.chmod(user_dir, stat.S_IROTH | stat.S_IWOTH | stat.S_IXOTH + | stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR + | stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP) + return user_dir + + +def is_moderator(user): + """Check if the user is having moderator rights""" + if user.groups.filter(name='moderator').count() == 1: + return True + + +def fetch_questions(request): + """Fetch questions from database based on the given search conditions & + tags""" + set1 = set() + set2 = set() + first_tag = request.POST.get('first_tag') + first_condition = request.POST.get('first_condition') + second_tag = request.POST.get('second_tag') + second_condition = request.POST.get('second_condition') + third_tag = request.POST.get('third_tag') + question1 = set(Question.objects.filter(tags__name__in=[first_tag])) + question2 = set(Question.objects.filter(tags__name__in=[second_tag])) + question3 = set(Question.objects.filter(tags__name__in=[third_tag])) + if first_condition == 'and': + set1 = question1.intersection(question2) + if second_condition == 'and': + set2 = set1.intersection(question3) + else: + set2 = set1.union(question3) + else: + set1 = question1.union(question2) + if second_condition == 'and': + set2 = set1.intersection(question3) + else: + set2 = set1.union(question3) + return set2 + + +def index(request): + """The start page. + """ + user = request.user + if user.is_authenticated(): + if user.groups.filter(name='moderator').count() > 0: + return my_redirect('/exam/manage/') + return my_redirect("/exam/start/") + + return my_redirect("/exam/login/") + + +def user_register(request): + """ Register a new user. + Create a user and corresponding profile and store roll_number also.""" + + user = request.user + ci = RequestContext(request) + if user.is_authenticated(): + return my_redirect("/exam/start/") + + if request.method == "POST": + form = UserRegisterForm(request.POST) + if form.is_valid(): + data = form.cleaned_data + u_name, pwd = form.save() + new_user = authenticate(username=u_name, password=pwd) + login(request, new_user) + return my_redirect("/exam/start/") + else: + return my_render_to_response('yaksh/register.html', {'form': form}, + context_instance=ci) + else: + form = UserRegisterForm() + return my_render_to_response('yaksh/register.html', {'form': form}, + context_instance=ci) + + +def quizlist_user(request): + """Show All Quizzes that is available to logged-in user.""" + user = request.user + avail_quizzes = list(QuestionPaper.objects.filter(quiz__active=True)) + user_answerpapers = AnswerPaper.objects.filter(user=user) + pre_requisites = [] + enabled_quizzes = [] + disabled_quizzes = [] + unexpired_quizzes = [] + + for paper in avail_quizzes: + quiz_enable_time = paper.quiz.start_date_time + quiz_disable_time = paper.quiz.end_date_time + if quiz_enable_time <= datetime.datetime.now() <= quiz_disable_time: + unexpired_quizzes.append(paper) + + cannot_attempt = True if 'cannot_attempt' in request.GET else False + quizzes_taken = None if user_answerpapers.count() == 0 else user_answerpapers + + context = {'cannot_attempt': cannot_attempt, + 'quizzes': avail_quizzes, + 'user': user, + 'quizzes_taken': quizzes_taken, + 'unexpired_quizzes': unexpired_quizzes + } + + return my_render_to_response("yaksh/quizzes_user.html", context) + + +def intro(request, questionpaper_id): + """Show introduction page before quiz starts""" + user = request.user + ci = RequestContext(request) + quest_paper = QuestionPaper.objects.get(id=questionpaper_id) + attempt_number = quest_paper.quiz.attempts_allowed + time_lag = quest_paper.quiz.time_between_attempts + quiz_enable_time = quest_paper.quiz.start_date_time + quiz_disable_time = quest_paper.quiz.end_date_time + + quiz_expired = False if quiz_enable_time <= datetime.datetime.now() \ + <= quiz_disable_time else True + + if quest_paper.quiz.prerequisite: + try: + pre_quest = QuestionPaper.objects.get( + quiz=quest_paper.quiz.prerequisite) + answer_papers = AnswerPaper.objects.filter( + question_paper=pre_quest, user=user) + answer_papers_failed = AnswerPaper.objects.filter( + question_paper=pre_quest, user=user, passed=False) + if answer_papers.count() == answer_papers_failed.count(): + context = {'user': user, 'cannot_attempt': True} + return my_redirect("/exam/quizzes/?cannot_attempt=True") + except: + context = {'user': user, 'cannot_attempt': True} + return my_redirect("/exam/quizzes/?cannot_attempt=True") + + attempted_papers = AnswerPaper.objects.filter(question_paper=quest_paper, + user=user) + already_attempted = attempted_papers.count() + inprogress, previous_attempt, next_attempt = _check_previous_attempt(attempted_papers, + already_attempted, + attempt_number) + + if previous_attempt: + if inprogress: + return show_question(request, + previous_attempt.current_question(), + previous_attempt.attempt_number, + previous_attempt.question_paper.id) + days_after_attempt = (datetime.datetime.today() - \ + previous_attempt.start_time).days + + if next_attempt: + if days_after_attempt >= time_lag: + context = {'user': user, + 'paper_id': questionpaper_id, + 'attempt_num': already_attempted + 1, + 'enable_quiz_time': quiz_enable_time, + 'disable_quiz_time': quiz_disable_time, + 'quiz_expired': quiz_expired + } + return my_render_to_response('yaksh/intro.html', context, + context_instance=ci) + else: + return my_redirect("/exam/quizzes/") + + else: + context = {'user': user, + 'paper_id': questionpaper_id, + 'attempt_num': already_attempted + 1, + 'enable_quiz_time': quiz_enable_time, + 'disable_quiz_time': quiz_disable_time, + 'quiz_expired': quiz_expired + } + return my_render_to_response('yaksh/intro.html', context, + context_instance=ci) + + +def _check_previous_attempt(attempted_papers, already_attempted, attempt_number): + next_attempt = False if already_attempted == attempt_number else True + if already_attempted == 0: + return False, None, next_attempt + else: + previous_attempt = attempted_papers[already_attempted-1] + previous_attempt_day = previous_attempt.start_time + today = datetime.datetime.today() + if previous_attempt.status == 'inprogress': + end_time = previous_attempt.end_time + quiz_time = previous_attempt.question_paper.quiz.duration*60 + if quiz_time > (today-previous_attempt_day).seconds: + return True, previous_attempt, next_attempt + else: + return False, previous_attempt, next_attempt + else: + return False, previous_attempt, next_attempt + + +def results_user(request): + """Show list of Results of Quizzes that is taken by logged-in user.""" + user = request.user + papers = AnswerPaper.objects.filter(user=user) + quiz_marks = [] + for paper in papers: + marks_obtained = paper.marks_obtained + max_marks = paper.question_paper.total_marks + percentage = round((marks_obtained/max_marks)*100, 2) + temp = paper.question_paper.quiz.description, marks_obtained,\ + max_marks, percentage + quiz_marks.append(temp) + context = {'papers': quiz_marks} + return my_render_to_response("yaksh/results_user.html", context) + + +def edit_quiz(request): + """Edit the list of quizzes seleted by the user for editing.""" + + user = request.user + if not user.is_authenticated() or not is_moderator(user): + raise Http404('You are not allowed to view this page!') + quiz_list = request.POST.getlist('quizzes') + start_date = request.POST.getlist('start_date') + start_time = request.POST.getlist('start_time') + end_date = request.POST.getlist('end_date') + end_time = request.POST.getlist('end_time') + duration = request.POST.getlist('duration') + active = request.POST.getlist('active') + description = request.POST.getlist('description') + pass_criteria = request.POST.getlist('pass_criteria') + language = request.POST.getlist('language') + prerequisite = request.POST.getlist('prerequisite') + + for j, quiz_id in enumerate(quiz_list): + quiz = Quiz.objects.get(id=quiz_id) + quiz.start_date_time = datetime.datetime.combine(start_date[j], + start_time[j]) + quiz.end_date_time = datetime.datetime.combine(end_date[j], + end_time[j]) + quiz.duration = duration[j] + quiz.active = active[j] + quiz.description = description[j] + quiz.pass_criteria = pass_criteria[j] + quiz.language = language[j] + quiz.prerequisite_id = prerequisite[j] + quiz.save() + return my_redirect("/exam/manage/showquiz/") + + +def edit_question(request): + """Edit the list of questions selected by the user for editing.""" + user = request.user + if not user.is_authenticated() or not is_moderator(user): + raise Http404('You are not allowed to view this page!') + question_list = request.POST.getlist('questions') + summary = request.POST.getlist('summary') + description = request.POST.getlist('description') + points = request.POST.getlist('points') + options = request.POST.getlist('options') + test = request.POST.getlist('test') + type = request.POST.getlist('type') + active = request.POST.getlist('active') + language = request.POST.getlist('language') + snippet = request.POST.getlist('snippet') + for j, question_id in enumerate(question_list): + question = Question.objects.get(id=question_id) + test_case_formset = TestCaseFormSet(request.POST, prefix='test', instance=question) + if test_case_formset.is_valid(): + test_case_instance = test_case_formset.save(commit=False) + for i in test_case_instance: + i.save() + + question.summary = summary[j] + question.description = description[j] + question.points = points[j] + question.options = options[j] + question.active = active[j] + question.language = language[j] + question.snippet = snippet[j] + question.ref_code_path = ref_code_path[j] + question.test = test[j] + question.type = type[j] + question.save() + return my_redirect("/exam/manage/questions") + + +def add_question(request, question_id=None): + """To add a new question in the database. + Create a new question and store it.""" + + def add_or_delete_test_form(post_request, instance): + request_copy = post_request.copy() + if 'add_test' in post_request: + request_copy['test-TOTAL_FORMS'] = int(request_copy['test-TOTAL_FORMS']) + 1 + elif 'delete_test' in post_request: + request_copy['test-TOTAL_FORMS'] = int(request_copy['test-TOTAL_FORMS']) - 1 + test_case_formset = TestCaseFormSet(request_copy, prefix='test', instance=instance) + return test_case_formset + + user = request.user + ci = RequestContext(request) + if not user.is_authenticated() or not is_moderator(user): + raise Http404('You are not allowed to view this page!') + if request.method == "POST": + form = QuestionForm(request.POST) + if form.is_valid(): + if question_id is None: + test_case_formset = add_or_delete_test_form(request.POST, form.save(commit=False)) + if 'save_question' in request.POST: + qtn = form.save(commit=False) + test_case_formset = TestCaseFormSet(request.POST, prefix='test', instance=qtn) + form.save() + question = Question.objects.order_by("-id")[0] + tags = form['tags'].data.split(',') + for i in range(0, len(tags)-1): + tag = tags[i].strip() + question.tags.add(tag) + if test_case_formset.is_valid(): + test_case_formset.save() + else: + return my_render_to_response('yaksh/add_question.html', + {'form': form, + 'formset': test_case_formset}, + context_instance=ci) + + return my_redirect("/exam/manage/questions") + + return my_render_to_response('yaksh/add_question.html', + {'form': form, + 'formset': test_case_formset}, + context_instance=ci) + + else: + d = Question.objects.get(id=question_id) + test_case_formset = add_or_delete_test_form(request.POST, d) + if 'save_question' in request.POST: + d.summary = form['summary'].data + d.description = form['description'].data + d.points = form['points'].data + d.options = form['options'].data + d.type = form['type'].data + d.active = form['active'].data + d.language = form['language'].data + d.snippet = form['snippet'].data + d.ref_code_path = form['ref_code_path'].data + d.test = form['test'].data + d.save() + question = Question.objects.get(id=question_id) + for tag in question.tags.all(): + question.tags.remove(tag) + tags = form['tags'].data.split(',') + for i in range(0, len(tags)-1): + tag = tags[i].strip() + question.tags.add(tag) + + test_case_formset = TestCaseFormSet(request.POST, prefix='test', instance=question) + if test_case_formset.is_valid(): + test_case_instance = test_case_formset.save(commit=False) + for i in test_case_instance: + i.save() + else: + return my_render_to_response('yaksh/add_question.html', + {'form': form, + 'formset': test_case_formset}, + context_instance=ci) + + + return my_redirect("/exam/manage/questions") + return my_render_to_response('yaksh/add_question.html', + {'form': form, + 'formset': test_case_formset}, + context_instance=ci) + + else: + test_case_formset = add_or_delete_test_form(request.POST, form.save(commit=False)) + return my_render_to_response('yaksh/add_question.html', + {'form': form, + 'formset': test_case_formset}, + context_instance=ci) + else: + form = QuestionForm() + test_case_formset = TestCaseFormSet(prefix='test', instance=Question()) + if question_id is None: + form = QuestionForm() + test_case_formset = TestCaseFormSet(prefix='test', instance=Question()) + return my_render_to_response('yaksh/add_question.html', + {'form': form, + 'formset': test_case_formset}, + context_instance=ci) + else: + d = Question.objects.get(id=question_id) + form = QuestionForm() + form.initial['summary'] = d.summary + form.initial['description'] = d.description + form.initial['points'] = d.points + form.initial['options'] = d.options + form.initial['type'] = d.type + form.initial['active'] = d.active + form.initial['language'] = d.language + form.initial['snippet'] = d.snippet + form.initial['ref_code_path'] = d.ref_code_path + form.initial['test'] = d.test + form_tags = d.tags.all() + form_tags_split = form_tags.values('name') + initial_tags = "" + for tag in form_tags_split: + initial_tags = initial_tags + str(tag['name']).strip() + "," + if (initial_tags == ","): + initial_tags = "" + form.initial['tags'] = initial_tags + + test_case_formset = TestCaseFormSet(prefix='test', + instance=d) + + return my_render_to_response('yaksh/add_question.html', + {'form': form, + 'formset': test_case_formset}, + context_instance=ci) + + +def add_quiz(request, quiz_id=None): + """To add a new quiz in the database. + Create a new quiz and store it.""" + + user = request.user + ci = RequestContext(request) + if not user.is_authenticated() or not is_moderator(user): + raise Http404('You are not allowed to view this page!') + if request.method == "POST": + form = QuizForm(request.POST) + if form.is_valid(): + data = form.cleaned_data + if quiz_id is None: + form.save() + quiz = Quiz.objects.order_by("-id")[0] + return my_redirect("/exam/manage/designquestionpaper") + else: + d = Quiz.objects.get(id=quiz_id) + sd = datetime.datetime.strptime(form['start_date'].data, '%Y-%m-%d').date() + st = datetime.datetime.strptime(form['start_time'].data, "%H:%M:%S").time() + ed = datetime.datetime.strptime(form['end_date'].data, '%Y-%m-%d').date() + et = datetime.datetime.strptime(form['end_time'].data, "%H:%M:%S").time() + d.start_date_time = datetime.datetime.combine(sd, st) + d.end_date_time = datetime.datetime.combine(ed, et) + d.duration = form['duration'].data + d.active = form['active'].data + d.description = form['description'].data + d.pass_criteria = form['pass_criteria'].data + d.language = form['language'].data + d.prerequisite_id = form['prerequisite'].data + d.attempts_allowed = form['attempts_allowed'].data + d.time_between_attempts = form['time_between_attempts'].data + d.save() + quiz = Quiz.objects.get(id=quiz_id) + return my_redirect("/exam/manage/showquiz") + else: + return my_render_to_response('yaksh/add_quiz.html', + {'form': form}, + context_instance=ci) + else: + if quiz_id is None: + form = QuizForm() + return my_render_to_response('yaksh/add_quiz.html', + {'form': form}, + context_instance=ci) + else: + d = Quiz.objects.get(id=quiz_id) + form = QuizForm() + form.initial['start_date'] = d.start_date_time.date() + form.initial['start_time'] = d.start_date_time.time() + form.initial['end_date'] = d.end_date_time.date() + form.initial['end_time'] = d.end_date_time.time() + form.initial['duration'] = d.duration + form.initial['description'] = d.description + form.initial['active'] = d.active + form.initial['pass_criteria'] = d.pass_criteria + form.initial['language'] = d.language + form.initial['prerequisite'] = d.prerequisite_id + form.initial['attempts_allowed'] = d.attempts_allowed + form.initial['time_between_attempts'] = d.time_between_attempts + return my_render_to_response('yaksh/add_quiz.html', + {'form': form}, + context_instance=ci) + + +def show_all_questionpapers(request, questionpaper_id=None): + user = request.user + ci = RequestContext(request) + if not user.is_authenticated() or not is_moderator(user): + raise Http404('You are not allowed to view this page!') + + if request.method == "POST" and request.POST.get('add') == "add": + return my_redirect("/exam/manage/designquestionpaper/" + + questionpaper_id) + + if request.method == "POST" and request.POST.get('delete') == "delete": + data = request.POST.getlist('papers') + q_paper = QuestionPaper.objects.get(id=questionpaper_id) + for i in data: + q_paper.questions.remove(Question.objects.get(id=i)) + question_paper = QuestionPaper.objects.all() + context = {'papers': question_paper} + return my_render_to_response('yaksh/showquestionpapers.html', context, + context_instance=ci) + if questionpaper_id is None: + qu_papers = QuestionPaper.objects.all() + context = {'papers': qu_papers} + return my_render_to_response('yaksh/showquestionpapers.html', context, + context_instance=ci) + else: + qu_papers = QuestionPaper.objects.get(id=questionpaper_id) + quiz = qu_papers.quiz + questions = qu_papers.questions.all() + context = {'papers': {'quiz': quiz, 'questions': questions}} + return my_render_to_response('yaksh/editquestionpaper.html', context, + context_instance=ci) + + +def automatic_questionpaper(request, questionpaper_id=None): + """Generate automatic question paper for a particular quiz""" + + user = request.user + ci = RequestContext(request) + if not user.is_authenticated() or not is_moderator(user): + raise Http404('You are not allowed to view this page!') + + if questionpaper_id is None: + if request.method == "POST": + if request.POST.get('save') == 'save': + quiz = Quiz.objects.order_by("-id")[0] + quest_paper = QuestionPaper() + questions = request.POST.getlist('questions') + tot_marks = 0 + for quest in questions: + q = Question.objects.get(id=quest) + tot_marks += q.points + quest_paper.quiz = quiz + quest_paper.total_marks = tot_marks + quest_paper.save() + for quest in questions: + q = Question.objects.get(id=quest) + quest_paper.fixed_questions.add(q) + return my_redirect('/exam/manage/showquiz') + else: + no_questions = int(request.POST.get('num_questions')) + fetched_questions = fetch_questions(request) + n = len(fetched_questions) + msg = '' + if (no_questions < n): + i = n - no_questions + for i in range(0, i): + fetched_questions.pop() + elif (no_questions > n): + msg = 'The given Criteria does not satisfy the number\ + of Questions...' + tags = Tag.objects.all() + context = {'data': {'questions': fetched_questions, + 'tags': tags, + 'msg': msg}} + return my_render_to_response( + 'yaksh/automatic_questionpaper.html', context, + context_instance=ci) + else: + tags = Tag.objects.all() + context = {'data': {'tags': tags}} + return my_render_to_response('yaksh/automatic_questionpaper.html', + context, context_instance=ci) + + else: + if request.method == "POST": + if request.POST.get('save') == 'save': + quest_paper = QuestionPaper.objects.get(id=questionpaper_id) + questions = request.POST.getlist('questions') + tot_marks = quest_paper.total_marks + for quest in questions: + q = Question.objects.get(id=quest) + tot_marks += q.points + quest_paper.total_marks = tot_marks + quest_paper.save() + for quest in questions: + q = Question.objects.get(id=quest) + quest_paper.questions.add(q) + return my_redirect('/yaksh/manage/showquiz') + else: + no_questions = int(request.POST.get('num_questions')) + fetched_questions = fetch_questions(request) + n = len(fetched_questions) + msg = '' + if(no_questions < n): + i = n - no_questions + for i in range(0, i): + fetched_questions.pop() + elif(no_questions > n): + msg = 'The given Criteria does not satisfy the number of \ + Questions...' + tags = Tag.objects.all() + context = {'data': {'questions': fetched_questions, + 'tags': tags, + 'msg': msg}} + return my_render_to_response( + 'yaksh/automatic_questionpaper.html', context, + context_instance=ci) + else: + tags = Tag.objects.all() + context = {'data': {'tags': tags}} + return my_render_to_response('yaksh/automatic_questionpaper.html', + context, context_instance=ci) + + +def manual_questionpaper(request, questionpaper_id=None): + user = request.user + ci = RequestContext(request) + if not user.is_authenticated() or not is_moderator(user): + raise Http404('You are not allowed to view this page!') + + if questionpaper_id is None: + if request.method == "POST": + if request.POST.get('save') == 'save': + questions = request.POST.getlist('questions') + quest_paper = QuestionPaper() + quiz = Quiz.objects.order_by("-id")[0] + tot_marks = 0 + for quest in questions: + q = Question.objects.get(id=quest) + tot_marks += q.points + quest_paper.quiz = quiz + quest_paper.total_marks = tot_marks + quest_paper.save() + for i in questions: + q = Question.objects.get(id=i) + quest_paper.questions.add(q) + return my_redirect('/exam/manage/showquiz') + else: + fetched_questions = fetch_questions(request) + n = len(fetched_questions) + msg = '' + if (n == 0): + msg = 'No matching Question found...' + tags = Tag.objects.all() + context = {'data': {'questions': fetched_questions, + 'tags': tags, 'msg': msg}} + return my_render_to_response('yaksh/manual_questionpaper.html', + context, + context_instance=ci) + else: + tags = Tag.objects.all() + context = {'data': {'tags': tags}} + return my_render_to_response('yaksh/manual_questionpaper.html', + context, context_instance=ci) + + else: + if request.method == "POST": + if request.POST.get('save') == 'save': + quest_paper = QuestionPaper.objects.get(id=questionpaper_id) + questions = request.POST.getlist('questions') + tot_marks = quest_paper.total_marks + for quest in questions: + q = Question.objects.get(id=quest) + tot_marks += q.points + quest_paper.total_marks = tot_marks + quest_paper.save() + for i in questions: + q = Question.objects.get(id=i) + quest_paper.questions.add(q) + return my_redirect('/exam/manage/showquiz') + else: + fetched_questions = fetch_questions(request) + n = len(fetched_questions) + msg = '' + if (n == 0): + msg = 'No matching Question found...' + tags = Tag.objects.all() + context = {'data': {'questions': fetched_questions, + 'tags': tags, 'msg': msg}} + return my_render_to_response('yaksh/manual_questionpaper.html', + context, + context_instance=ci) + else: + tags = Tag.objects.all() + context = {'data': {'tags': tags}} + return my_render_to_response('yaksh/manual_questionpaper.html', + context, context_instance=ci) + + +def prof_manage(request): + """Take credentials of the user with professor/moderator +rights/permissions and log in.""" + user = request.user + if user.is_authenticated() and is_moderator(user): + question_papers = QuestionPaper.objects.all() + users_per_paper = [] + for paper in question_papers: + answer_papers = AnswerPaper.objects.filter(question_paper=paper) + users_passed = AnswerPaper.objects.filter(question_paper=paper, + passed=True).count() + users_failed = AnswerPaper.objects.filter(question_paper=paper, + passed=False).count() + temp = paper, answer_papers, users_passed, users_failed + users_per_paper.append(temp) + context = {'user': user, 'users_per_paper': users_per_paper} + return my_render_to_response('manage.html', context) + return my_redirect('/exam/login/') + + +def user_login(request): + """Take the credentials of the user and log the user in.""" + + user = request.user + ci = RequestContext(request) + if user.is_authenticated(): + if user.groups.filter(name='moderator').count() > 0: + return my_redirect('/exam/manage/') + return my_redirect("/exam/intro/") + + if request.method == "POST": + form = UserLoginForm(request.POST) + if form.is_valid(): + user = form.cleaned_data + login(request, user) + if user.groups.filter(name='moderator').count() > 0: + return my_redirect('/exam/manage/') + return my_redirect('/exam/login/') + else: + context = {"form": form} + return my_render_to_response('yaksh/login.html', context, + context_instance=ci) + else: + form = UserLoginForm() + context = {"form": form} + return my_render_to_response('yaksh/login.html', context, + context_instance=ci) + + +def start(request, attempt_num=None, questionpaper_id=None): + """Check the user cedentials and if any quiz is available, + start the exam.""" + user = request.user + if questionpaper_id is None: + return my_redirect('/exam/quizzes/') + try: + """Right now the app is designed so there is only one active quiz + at a particular time.""" + questionpaper = QuestionPaper.objects.get(id=questionpaper_id) + except QuestionPaper.DoesNotExist: + msg = 'Quiz not found, please contact your '\ + 'instructor/administrator. Please login again thereafter.' + return complete(request, msg, attempt_num, questionpaper_id) + + try: + old_paper = AnswerPaper.objects.get( + question_paper=questionpaper, user=user, attempt_number=attempt_num) + q = old_paper.current_question() + return show_question(request, q, attempt_num, questionpaper_id) + except AnswerPaper.DoesNotExist: + ip = request.META['REMOTE_ADDR'] + key = gen_key(10) + try: + profile = user.get_profile() + except Profile.DoesNotExist: + msg = 'You do not have a profile and cannot take the quiz!' + raise Http404(msg) + + new_paper = questionpaper.make_answerpaper(user, ip, attempt_num) + # Make user directory. + user_dir = get_user_dir(user) + return start(request, attempt_num, questionpaper_id) + +def get_questions(paper): + ''' + Takes answerpaper as an argument. Returns the total questions as + ordered dictionary, the questions yet to attempt and the questions + attempted + ''' + to_attempt = [] + submitted = [] + all_questions = [] + questions = {} + if paper.questions: + all_questions = (paper.questions).split('|') + if paper.questions_answered: + q_answered = (paper.questions_answered).split('|') + q_answered.sort() + submitted = q_answered + if paper.get_unanswered_questions(): + q_unanswered = paper.get_unanswered_questions() + q_unanswered.sort() + to_attempt = q_unanswered + for index, value in enumerate(all_questions, 1): + questions[value] = index + questions = collections.OrderedDict(sorted(questions.items(), key=lambda x:x[1])) + return questions, to_attempt, submitted + + +def question(request, q_id, attempt_num, questionpaper_id, success_msg=None): + """Check the credentials of the user and start the exam.""" + + user = request.user + if not user.is_authenticated(): + return my_redirect('/exam/login/') + q = get_object_or_404(Question, pk=q_id) + try: + q_paper = QuestionPaper.objects.get(id=questionpaper_id) + paper = AnswerPaper.objects.get( + user=request.user, attempt_number=attempt_num, question_paper=q_paper) + except AnswerPaper.DoesNotExist: + return my_redirect('/exam/start/') + if not paper.question_paper.quiz.active: + reason = 'The quiz has been deactivated!' + return complete(request, reason, questionpaper_id) + elif paper.end_time < datetime.datetime.now(): + reason = 'You have already attempted the quiz' + return complete(request, reason, questionpaper_id) + time_left = paper.time_left() + if time_left == 0: + return complete(request, reason='Your time is up!') + quiz_name = paper.question_paper.quiz.description + questions, to_attempt, submitted = get_questions(paper) + if success_msg is None: + context = {'question': q, 'questions': questions, 'paper': paper, + 'user': user, 'quiz_name': quiz_name, 'time_left': time_left, + 'to_attempt': to_attempt, 'submitted': submitted} + else: + context = {'question': q, 'questions': questions, 'paper': paper, + 'user': user, 'quiz_name': quiz_name, 'time_left': time_left, + 'success_msg': success_msg, 'to_attempt': to_attempt, + 'submitted': submitted} + if q.type == 'code': + skipped_answer = paper.answers.filter(question=q, skipped=True) + if skipped_answer: + context['last_attempt'] = skipped_answer[0].answer + ci = RequestContext(request) + return my_render_to_response('yaksh/question.html', context, + context_instance=ci) + + +def show_question(request, q_id, attempt_num, questionpaper_id, success_msg=None): + """Show a question if possible.""" + user = request.user + q_paper = QuestionPaper.objects.get(id=questionpaper_id) + paper = AnswerPaper.objects.get(user=request.user, attempt_number=attempt_num, + question_paper=q_paper) + if not user.is_authenticated() or paper.end_time < datetime.datetime.now(): + return my_redirect('/exam/login/') + old_qid = request.POST.get('question_id') + if old_qid is not None: + quest = Question.objects.get(pk=old_qid) + user_code = request.POST.get('answer') + if quest.type == 'code': + old_skipped = paper.answers.filter(question=quest, skipped=True) + _save_skipped_answer(old_skipped, user_code, paper, quest) + if len(q_id) == 0: + msg = 'Congratulations! You have successfully completed the quiz.' + return complete(request, msg, attempt_num, questionpaper_id) + else: + return question(request, q_id, attempt_num, questionpaper_id, success_msg) + + +def _save_skipped_answer(old_skipped, user_answer, paper, question): + """ + Saves the answer on skip. Only the code questions are saved. + Snippet is not saved with the answer. + """ + if old_skipped: + skipped_answer = old_skipped[0] + skipped_answer.answer=user_answer + skipped_answer.save() + else: + skipped_answer = Answer(question=question, answer=user_answer, + correct=False, skipped=True) + skipped_answer.save() + paper.answers.add(skipped_answer) + +def check(request, q_id, attempt_num=None, questionpaper_id=None): + """Checks the answers of the user for particular question""" + + user = request.user + q_paper = QuestionPaper.objects.get(id=questionpaper_id) + paper = AnswerPaper.objects.get(user=request.user, attempt_number=attempt_num, + question_paper=q_paper) + if q_id in paper.questions_answered: + next_q = paper.skip(q_id) + return show_question(request, next_q, attempt_num, questionpaper_id) + + if not user.is_authenticated() or paper.end_time < datetime.datetime.now(): + return my_redirect('/exam/login/') + + question = get_object_or_404(Question, pk=q_id) + test_cases = TestCase.objects.filter(question=question) + + snippet_code = request.POST.get('snippet') + user_code = request.POST.get('answer') + skip = request.POST.get('skip', None) + success_msg = False + success = True + if skip is not None: + if question.type == 'code': + old_skipped = paper.answers.filter(question=question, skipped=True) + _save_skipped_answer(old_skipped, user_code, paper, question) + next_q = paper.skip(q_id) + return show_question(request, next_q, attempt_num, questionpaper_id) + + # Add the answer submitted, regardless of it being correct or not. + if question.type == 'mcq': + user_answer = request.POST.get('answer') + elif question.type == 'mcc': + user_answer = request.POST.getlist('answer') + elif question.type == 'upload': + assign = AssignmentUpload() + assign.user = user.profile + assign.assignmentQuestion = question + # if time-up at upload question then the form is submitted without + # validation + if 'assignment' in request.FILES: + assign.assignmentFile = request.FILES['assignment'] + assign.save() + user_answer = 'ASSIGNMENT UPLOADED' + else: + user_code = request.POST.get('answer') + user_answer = snippet_code + "\n" + user_code if snippet_code else user_code + + new_answer = Answer(question=question, answer=user_answer, + correct=False) + new_answer.save() + paper.answers.add(new_answer) + + # If we were not skipped, we were asked to check. For any non-mcq + # questions, we obtain the results via XML-RPC with the code executed + # safely in a separate process (the code_server.py) running as nobody. + if not question.type == 'upload': + json_data = question.consolidate_answer_data(test_cases, user_answer) \ + if question.type == 'code' else None + correct, result = validate_answer(user, user_answer, question, json_data) + if correct: + new_answer.correct = correct + new_answer.marks = question.points + new_answer.error = result.get('error') + success_msg = True + else: + new_answer.error = result.get('error') + new_answer.save() + + time_left = paper.time_left() + if not result.get('success'): # Should only happen for non-mcq questions. + if time_left == 0: + reason = 'Your time is up!' + return complete(request, reason, attempt_num, questionpaper_id) + if not paper.question_paper.quiz.active: + reason = 'The quiz has been deactivated!' + return complete(request, reason, attempt_num, questionpaper_id) + if not paper.question_paper.quiz.active: + reason = 'The quiz has been deactivated!' + return complete(request, reason, attempt_num, questionpaper_id) + questions, to_attempt, submitted = get_questions(paper) + old_answer = paper.answers.filter(question=question, skipped=True) + if old_answer: + old_answer[0].answer = user_code + old_answer[0].save() + context = {'question': question, 'error_message': result.get('error'), + 'paper': paper, 'last_attempt': user_code, + 'quiz_name': paper.question_paper.quiz.description, + 'time_left': time_left, 'questions': questions, + 'to_attempt': to_attempt, 'submitted': submitted} + ci = RequestContext(request) + + return my_render_to_response('yaksh/question.html', context, + context_instance=ci) + else: + if time_left <= 0: + reason = 'Your time is up!' + return complete(request, reason, attempt_num, questionpaper_id) + + # Display the same question if user_answer is None + elif not user_answer: + msg = "Please submit a valid option or code" + time_left = paper.time_left() + questions, to_attempt, submitted = get_questions(paper) + context = {'question': question, 'error_message': msg, + 'paper': paper, 'quiz_name': paper.question_paper.quiz.description, + 'time_left': time_left, 'questions': questions, + 'to_attempt': to_attempt, 'submitted': submitted} + ci = RequestContext(request) + + return my_render_to_response('yaksh/question.html', context, + context_instance=ci) + else: + next_q = paper.completed_question(question.id) + return show_question(request, next_q, attempt_num, + questionpaper_id, success_msg) + + +def validate_answer(user, user_answer, question, json_data=None): + """ + Checks whether the answer submitted by the user is right or wrong. + If right then returns correct = True, success and + message = Correct answer. + success is True for MCQ's and multiple correct choices because + only one attempt are allowed for them. + For code questions success is True only if the answer is correct. + """ + + result = {'success': True, 'error': 'Incorrect answer'} + correct = False + + if user_answer is not None: + if question.type == 'mcq': + if user_answer.strip() == question.test.strip(): + correct = True + message = 'Correct answer' + elif question.type == 'mcc': + answers = set(question.test.splitlines()) + if set(user_answer) == answers: + correct = True + message = 'Correct answer' + elif question.type == 'code': + user_dir = get_user_dir(user) + json_result = code_server.run_code(question.language, json_data, user_dir) + result = json.loads(json_result) + if result.get('success'): + correct = True + + return correct, result + +def get_question_labels(request, attempt_num=None, questionpaper_id=None): + """Get the question number show in template for corresponding + question id.""" + unattempted_questions = [] + submitted_questions = [] + try: + q_paper = QuestionPaper.objects.get(id=questionpaper_id) + paper = AnswerPaper.objects.get( + user=request.user, attempt_number=attempt_num, question_paper=q_paper) + except AnswerPaper.DoesNotExist: + return my_redirect('/exam/start/') + questions, to_attempt, submitted = get_questions(paper) + for q_id, question_label in questions.items(): + if q_id in to_attempt: + unattempted_questions.append(question_label) + else: + submitted_questions.append(question_label) + unattempted_questions.sort() + submitted_questions.sort() + return unattempted_questions, submitted_questions + +def quit(request, attempt_num=None, questionpaper_id=None): + """Show the quit page when the user logs out.""" + unattempted_questions, submitted_questions = get_question_labels(request, + attempt_num, questionpaper_id) + context = {'id': questionpaper_id, 'attempt_num': attempt_num, + 'unattempted': unattempted_questions, + 'submitted': submitted_questions} + return my_render_to_response('yaksh/quit.html', context, + context_instance=RequestContext(request)) + + +def complete(request, reason=None, attempt_num=None, questionpaper_id=None): + """Show a page to inform user that the quiz has been compeleted.""" + + user = request.user + if questionpaper_id is None: + logout(request) + message = reason or "You are successfully logged out." + context = {'message': message} + return my_render_to_response('yaksh/complete.html', context) + else: + unattempted_questions, submitted_questions = get_question_labels(request, + attempt_num, questionpaper_id) + q_paper = QuestionPaper.objects.get(id=questionpaper_id) + paper = AnswerPaper.objects.get(user=user, question_paper=q_paper, + attempt_number=attempt_num) + paper.update_marks_obtained() + paper.update_percent() + paper.update_passed() + paper.end_time = datetime.datetime.now() + paper.update_status() + paper.save() + obt_marks = paper.marks_obtained + tot_marks = paper.question_paper.total_marks + if obt_marks == paper.question_paper.total_marks: + context = {'message': "Hurray ! You did an excellent job.\ + you answered all the questions correctly.\ + You have been logged out successfully,\ + Thank You !", + 'unattempted': unattempted_questions, + 'submitted': submitted_questions} + return my_render_to_response('yaksh/complete.html', context) + else: + message = reason or "You are successfully logged out" + context = {'message': message, + 'unattempted': unattempted_questions, + 'submitted': submitted_questions} + return my_render_to_response('yaksh/complete.html', context) + no = False + message = reason or 'The quiz has been completed. Thank you.' + if user.groups.filter(name='moderator').count() > 0: + message = 'You are successfully Logged out.' + if request.method == 'POST' and 'no' in request.POST: + no = True + if not no: + # Logout the user and quit with the message given. + answer_paper = AnswerPaper.objects.get(id=answerpaper_id) + answer_paper.end_time = datetime.datetime.now() + answer_paper.save() + return my_redirect('/exam/quizzes/') + else: + return my_redirect('/exam/') + + +def monitor(request, questionpaper_id=None): + """Monitor the progress of the papers taken so far.""" + + user = request.user + ci = RequestContext(request) + if not user.is_authenticated() or not is_moderator(user): + raise Http404('You are not allowed to view this page!') + + if questionpaper_id is None: + q_paper = QuestionPaper.objects.all() + context = {'papers': [], + 'quiz': None, + 'quizzes': q_paper} + return my_render_to_response('yaksh/monitor.html', context, + context_instance=ci) + # quiz_id is not None. + try: + q_paper = QuestionPaper.objects.get(id=questionpaper_id) + except QuestionPaper.DoesNotExist: + papers = [] + q_paper = None + else: + papers = AnswerPaper.objects.filter(question_paper=q_paper).annotate( + total=Sum('answers__marks')).order_by('-total') + + context = {'papers': papers, 'quiz': q_paper, 'quizzes': None} + return my_render_to_response('yaksh/monitor.html', context, + context_instance=ci) + + +def get_user_data(username): + """For a given username, this returns a dictionary of important data + related to the user including all the user's answers submitted. + """ + user = User.objects.get(username=username) + papers = AnswerPaper.objects.filter(user=user) + + data = {} + try: + profile = user.get_profile() + except Profile.DoesNotExist: + # Admin user may have a paper by accident but no profile. + profile = None + data['user'] = user + data['profile'] = profile + data['papers'] = papers + return data + + +def show_all_users(request): + """Shows all the users who have taken various exams/quiz.""" + + user = request.user + if not user.is_authenticated() or not is_moderator(user): + raise Http404('You are not allowed to view this page !') + user = User.objects.filter(username__contains="") + questionpaper = AnswerPaper.objects.all() + context = {'question': questionpaper} + return my_render_to_response('yaksh/showusers.html', context, + context_instance=RequestContext(request)) + + +def show_all_quiz(request): + """Generates a list of all the quizzes + that are currently in the database.""" + + user = request.user + ci = RequestContext(request) + if not user.is_authenticated() or not is_moderator(user): + raise Http404('You are not allowed to view this page !') + + if request.method == 'POST' and request.POST.get('delete') == 'delete': + data = request.POST.getlist('quiz') + + if data is None: + quizzes = Quiz.objects.all() + context = {'papers': [], + 'quiz': None, + 'quizzes': quizzes} + return my_render_to_response('yaksh/show_quiz.html', context, + context_instance=ci) + else: + for i in data: + quiz = Quiz.objects.get(id=i).delete() + quizzes = Quiz.objects.all() + context = {'papers': [], + 'quiz': None, + 'quizzes': quizzes} + return my_render_to_response('yaksh/show_quiz.html', context, + context_instance=ci) + + elif request.method == 'POST' and request.POST.get('edit') == 'edit': + data = request.POST.getlist('quiz') + forms = [] + for j in data: + d = Quiz.objects.get(id=j) + form = QuizForm() + form.initial['start_date'] = d.start_date_time.date() + form.initial['start_time'] = d.start_date_time.time() + form.initial['end_date'] = d.end_date_time.date() + form.initial['end_time'] = d.end_date_time.time() + form.initial['duration'] = d.duration + form.initial['active'] = d.active + form.initial['description'] = d.description + form.initial['pass_criteria'] = d.pass_criteria + form.initial['language'] = d.language + form.initial['prerequisite'] = d.prerequisite_id + forms.append(form) + return my_render_to_response('yaksh/edit_quiz.html', + {'forms': forms, 'data': data}, + context_instance=ci) + else: + quizzes = Quiz.objects.all() + context = {'papers': [], + 'quiz': None, + 'quizzes': quizzes} + return my_render_to_response('yaksh/show_quiz.html', context, + context_instance=ci) + + +@csrf_exempt +def ajax_questions_filter(request): + """Ajax call made when filtering displayed questions.""" + + filter_dict = {} + question_type = request.POST.get('question_type') + marks = request.POST.get('marks') + language = request.POST.get('language') + + if question_type != "select": + filter_dict['type'] = str(question_type) + + if marks != "select": + filter_dict['points'] = marks + + if language != "select": + filter_dict['language'] = str(language) + + questions = list(Question.objects.filter(**filter_dict)) + + return my_render_to_response('yaksh/ajax_question_filter.html', + {'questions': questions}) + + +def show_all_questions(request): + """Show a list of all the questions currently in the databse.""" + + user = request.user + ci = RequestContext(request) + if not user.is_authenticated() or not is_moderator(user): + raise Http404("You are not allowed to view this page !") + + if request.method == 'POST' and request.POST.get('delete') == 'delete': + data = request.POST.getlist('question') + if data is None: + questions = Question.objects.all() + form = QuestionFilterForm() + context = {'papers': [], + 'question': None, + 'questions': questions, + 'form': form + } + return my_render_to_response('yaksh/showquestions.html', context, + context_instance=ci) + else: + for i in data: + question = Question.objects.get(id=i).delete() + questions = Question.objects.all() + form = QuestionFilterForm() + context = {'papers': [], + 'question': None, + 'questions': questions, + 'form': form + } + return my_render_to_response('yaksh/showquestions.html', context, + context_instance=ci) + elif request.method == 'POST' and request.POST.get('edit') == 'edit': + data = request.POST.getlist('question') + + forms = [] + formsets = [] + for j in data: + d = Question.objects.get(id=j) + form = QuestionForm() + form.initial['summary'] = d.summary + form.initial['description'] = d.description + form.initial['points'] = d.points + form.initial['options'] = d.options + form.initial['type'] = d.type + form.initial['active'] = d.active + form.initial['language'] = d.language + form.initial['snippet'] = d.snippet + form.initial['ref_code_path'] = d.ref_code_path + form.initial['test'] = d.test + form_tags = d.tags.all() + form_tags_split = form_tags.values('name') + initial_tags = "" + for tag in form_tags_split: + initial_tags = initial_tags + str(tag['name']).strip() + "," + if (initial_tags == ","): + initial_tags = "" + form.initial['tags'] = initial_tags + forms.append(form) + test_case_formset = TestCaseFormSet(prefix='test', instance=d) + formsets.append(test_case_formset) + data_list = zip(forms, formsets) + + return my_render_to_response('yaksh/edit_question.html', + {'data': data, + 'data_list': data_list}, + context_instance=ci) + else: + questions = Question.objects.all() + form = QuestionFilterForm() + context = {'papers': [], + 'question': None, + 'questions': questions, + 'form': form + } + return my_render_to_response('yaksh/showquestions.html', context, + context_instance=ci) + + +def user_data(request, username): + """Render user data.""" + + current_user = request.user + if not current_user.is_authenticated() or not is_moderator(current_user): + raise Http404('You are not allowed to view this page!') + + data = get_user_data(username) + + context = {'data': data} + return my_render_to_response('yaksh/user_data.html', context, + context_instance=RequestContext(request)) + + +def grade_user(request, username): + """Present an interface with which we can easily grade a user's papers + and update all their marks and also give comments for each paper. + """ + current_user = request.user + ci = RequestContext(request) + if not current_user.is_authenticated() or not is_moderator(current_user): + raise Http404('You are not allowed to view this page!') + + data = get_user_data(username) + if request.method == 'POST': + papers = data['papers'] + for paper in papers: + for question, answers in paper.get_question_answers().iteritems(): + marks = float(request.POST.get('q%d_marks' % question.id)) + last_ans = answers[-1] + last_ans.marks = marks + last_ans.save() + paper.comments = request.POST.get( + 'comments_%d' % paper.question_paper.id) + paper.save() + + context = {'data': data} + return my_render_to_response('yaksh/user_data.html', context, + context_instance=ci) + else: + context = {'data': data} + return my_render_to_response('yaksh/grade_user.html', context, + context_instance=ci) + + +@csrf_exempt +def ajax_questionpaper(request, query): + """ + During question paper creation, ajax call made to get question details. + """ + if query == 'marks': + question_type = request.POST.get('question_type') + questions = Question.objects.filter(type=question_type) + marks = questions.values_list('points').distinct() + return my_render_to_response('yaksh/ajax_marks.html', {'marks': marks}) + elif query == 'questions': + question_type = request.POST['question_type'] + marks_selected = request.POST['marks'] + fixed_questions = request.POST.getlist('fixed_list[]') + fixed_question_list = ",".join(fixed_questions).split(',') + random_questions = request.POST.getlist('random_list[]') + random_question_list = ",".join(random_questions).split(',') + question_list = fixed_question_list + random_question_list + questions = list(Question.objects.filter(type=question_type, + points=marks_selected)) + questions = [question for question in questions \ + if not str(question.id) in question_list] + return my_render_to_response('yaksh/ajax_questions.html', + {'questions': questions}) + + +def design_questionpaper(request): + user = request.user + ci = RequestContext(request) + + if not user.is_authenticated() or not is_moderator(user): + raise Http404('You are not allowed to view this page!') + + if request.method == 'POST': + fixed_questions = request.POST.getlist('fixed') + random_questions = request.POST.getlist('random') + random_number = request.POST.getlist('number') + is_shuffle = request.POST.get('shuffle_questions', False) + if is_shuffle == 'on': + is_shuffle = True + + question_paper = QuestionPaper(shuffle_questions=is_shuffle) + quiz = Quiz.objects.order_by("-id")[0] + tot_marks = 0 + question_paper.quiz = quiz + question_paper.total_marks = tot_marks + question_paper.save() + if fixed_questions: + fixed_questions_ids = ",".join(fixed_questions) + fixed_questions_ids_list = fixed_questions_ids.split(',') + for question_id in fixed_questions_ids_list: + question_paper.fixed_questions.add(question_id) + if random_questions: + for random_question, num in zip(random_questions, random_number): + qid = random_question.split(',')[0] + question = Question.objects.get(id=int(qid)) + marks = question.points + question_set = QuestionSet(marks=marks, num_questions=num) + question_set.save() + for question_id in random_question.split(','): + question_set.questions.add(question_id) + question_paper.random_questions.add(question_set) + question_paper.update_total_marks() + question_paper.save() + return my_redirect('/exam/manage/showquiz') + else: + form = RandomQuestionForm() + context = {'form': form} + return my_render_to_response('yaksh/design_questionpaper.html', + context, context_instance=ci) diff --git a/testapp/yaksh/xmlrpc_clients.py b/testapp/yaksh/xmlrpc_clients.py new file mode 100644 index 0000000..3a3c0c6 --- /dev/null +++ b/testapp/yaksh/xmlrpc_clients.py @@ -0,0 +1,80 @@ +from xmlrpclib import ServerProxy +import time +import random +import socket +import json + +from settings import SERVER_PORTS, SERVER_POOL_PORT + + +class ConnectionError(Exception): + pass + +############################################################################### +# `CodeServerProxy` class. +############################################################################### + + +class CodeServerProxy(object): + """A class that manages accesing the farm of Python servers and making + calls to them such that no one XMLRPC server is overloaded. + """ + def __init__(self): + pool_url = 'http://localhost:%d' % (SERVER_POOL_PORT) + self.pool_server = ServerProxy(pool_url) + + def run_code(self, language, json_data, user_dir): + """Tests given code (`answer`) with the `test_code` supplied. If the + optional `in_dir` keyword argument is supplied it changes the directory + to that directory (it does not change it back to the original when + done). The parameter language specifies which language to use for the + tests. + + Parameters + ---------- + json_data contains; + user_answer : str + The user's answer for the question. + test_code : str + The test code to check the user code with. + language : str + The programming language to use. + + user_dir : str (directory) + The directory to run the tests inside. + + + Returns + ------- + A json string of a dict: {success: success, err: error message}. + """ + + try: + server = self._get_server() + result = server.check_code(language, json_data, user_dir) + except ConnectionError: + result = json.dumps({'success': False, 'error': 'Unable to connect to any code servers!'}) + return result + + def _get_server(self): + # Get a suitable server from our pool of servers. This may block. We + # try about 60 times, essentially waiting at most for about 30 seconds. + done, count = False, 60 + + while not done and count > 0: + try: + port = self.pool_server.get_server_port() + except socket.error: + # Wait a while try again. + time.sleep(random.random()) + count -= 1 + else: + done = True + if not done: + raise ConnectionError("Couldn't connect to a server!") + proxy = ServerProxy('http://localhost:%d' % port) + return proxy + +# views.py calls this Python server which forwards the request to one +# of the running servers. +code_server = CodeServerProxy() diff --git a/testapp/yaksh_app/__init__.py b/testapp/yaksh_app/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/testapp/yaksh_app/admin.py b/testapp/yaksh_app/admin.py deleted file mode 100644 index e0a7741..0000000 --- a/testapp/yaksh_app/admin.py +++ /dev/null @@ -1,6 +0,0 @@ -from testapp.yaksh_app.models import Question, Quiz, TestCase -from django.contrib import admin - -admin.site.register(Question) -admin.site.register(TestCase) -admin.site.register(Quiz) diff --git a/testapp/yaksh_app/bash_code_evaluator.py b/testapp/yaksh_app/bash_code_evaluator.py deleted file mode 100644 index a468fd7..0000000 --- a/testapp/yaksh_app/bash_code_evaluator.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env python -import traceback -import pwd -import os -from os.path import join, isfile -import subprocess -import importlib - -# local imports -from code_evaluator import CodeEvaluator - - -class BashCodeEvaluator(CodeEvaluator): - """Tests the Bash code obtained from Code Server""" - def __init__(self, test_case_data, test, language, user_answer, - ref_code_path=None, in_dir=None): - super(BashCodeEvaluator, self).__init__(test_case_data, test, language, user_answer, - ref_code_path, in_dir) - self.test_case_args = self._setup() - - # Private Protocol ########## - def _setup(self): - super(BashCodeEvaluator, self)._setup() - - self.submit_path = self.create_submit_code_file('submit.sh') - self._set_file_as_executable(self.submit_path) - get_ref_path, get_test_case_path = self.ref_code_path.strip().split(',') - get_ref_path = get_ref_path.strip() - get_test_case_path = get_test_case_path.strip() - ref_path, test_case_path = self._set_test_code_file_path(get_ref_path, - get_test_case_path) - - return ref_path, self.submit_path, test_case_path - - def _teardown(self): - # Delete the created file. - super(BashCodeEvaluator, self)._teardown() - os.remove(self.submit_path) - - def _check_code(self, ref_path, submit_path, - test_case_path=None): - """ Function validates student script using instructor script as - reference. Test cases can optionally be provided. The first argument - ref_path, is the path to instructor script, it is assumed to - have executable permission. The second argument submit_path, is - the path to the student script, it is assumed to have executable - permission. The Third optional argument is the path to test the - scripts. Each line in this file is a test case and each test case is - passed to the script as standard arguments. - - Returns - -------- - - returns (True, "Correct answer") : If the student script passes all - test cases/have same output, when compared to the instructor script - - returns (False, error_msg): If the student script fails a single - test/have dissimilar output, when compared to the instructor script. - - Returns (False, error_msg): If mandatory arguments are not files or if - the required permissions are not given to the file(s). - - """ - if not isfile(ref_path): - return False, "No file at %s or Incorrect path" % ref_path - if not isfile(submit_path): - return False, "No file at %s or Incorrect path" % submit_path - if not os.access(ref_path, os.X_OK): - return False, "Script %s is not executable" % ref_path - if not os.access(submit_path, os.X_OK): - return False, "Script %s is not executable" % submit_path - - success = False - - if test_case_path is None or "": - ret = self._run_command(ref_path, stdin=None, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - proc, inst_stdout, inst_stderr = ret - ret = self._run_command(submit_path, stdin=None, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - proc, stdnt_stdout, stdnt_stderr = ret - if inst_stdout == stdnt_stdout: - return True, "Correct answer" - else: - err = "Error: expected %s, got %s" % (inst_stderr, - stdnt_stderr) - return False, err - else: - if not isfile(test_case_path): - return False, "No test case at %s" % test_case_path - if not os.access(ref_path, os.R_OK): - return False, "Test script %s, not readable" % test_case_path - # valid_answer is True, so that we can stop once a test case fails - valid_answer = True - # loop_count has to be greater than or equal to one. - # Useful for caching things like empty test files,etc. - loop_count = 0 - test_cases = open(test_case_path).readlines() - num_lines = len(test_cases) - for test_case in test_cases: - loop_count += 1 - if valid_answer: - args = [ref_path] + [x for x in test_case.split()] - ret = self._run_command(args, stdin=None, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - proc, inst_stdout, inst_stderr = ret - args = [submit_path]+[x for x in test_case.split()] - ret = self._run_command(args, stdin=None, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - proc, stdnt_stdout, stdnt_stderr = ret - valid_answer = inst_stdout == stdnt_stdout - if valid_answer and (num_lines == loop_count): - return True, "Correct answer" - else: - err = "Error:expected %s, got %s" % (inst_stdout+inst_stderr, - stdnt_stdout+stdnt_stderr) - return False, err - diff --git a/testapp/yaksh_app/bash_files/sample.args b/testapp/yaksh_app/bash_files/sample.args deleted file mode 100644 index 4d9f00d..0000000 --- a/testapp/yaksh_app/bash_files/sample.args +++ /dev/null @@ -1,2 +0,0 @@ -1 2 -2 1 diff --git a/testapp/yaksh_app/bash_files/sample.sh b/testapp/yaksh_app/bash_files/sample.sh deleted file mode 100755 index e935cb3..0000000 --- a/testapp/yaksh_app/bash_files/sample.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -[[ $# -eq 2 ]] && echo $(( $1 + $2 )) && exit $(( $1 + $2 )) diff --git a/testapp/yaksh_app/c_cpp_files/main.cpp b/testapp/yaksh_app/c_cpp_files/main.cpp deleted file mode 100755 index ebe1f08..0000000 --- a/testapp/yaksh_app/c_cpp_files/main.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include - -extern int add(int, int); - -template - -void check(T expect, T result) -{ - if (expect == result) - { - printf("\nCorrect:\n Expected %d got %d \n",expect,result); - } - else - { - printf("\nIncorrect:\n Expected %d got %d \n",expect,result); - exit (1); - } -} - -int main(void) -{ - int result; - result = add(0,0); - printf("Input submitted to the function: 0, 0"); - check(0, result); - result = add(2,3); - printf("Input submitted to the function: 2 3"); - check(5,result); - printf("All Correct\n"); - return 0; -} diff --git a/testapp/yaksh_app/c_cpp_files/main2.c b/testapp/yaksh_app/c_cpp_files/main2.c deleted file mode 100755 index ccd1768..0000000 --- a/testapp/yaksh_app/c_cpp_files/main2.c +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include - -extern int add(int, int, int); - -template -void check(T expect,T result) -{ - if (expect == result) - { - printf("\nCorrect:\n Expected %d got %d \n",expect,result); - } - else - { - printf("\nIncorrect:\n Expected %d got %d \n",expect,result); - exit (0); - } -} - -int main(void) -{ - int result; - result = add(0,0,0); - printf("Input submitted to the function: 0, 0, 0"); - check(0, result); - result = add(2,3,3); - printf("Input submitted to the function: 2, 3, 3"); - check(8,result); - printf("All Correct\n"); -} diff --git a/testapp/yaksh_app/c_cpp_files/main_array_check.cpp b/testapp/yaksh_app/c_cpp_files/main_array_check.cpp deleted file mode 100755 index ea34fdd..0000000 --- a/testapp/yaksh_app/c_cpp_files/main_array_check.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include - -extern bool array_check(int [], int); - -template - -void check(T expect,T result) -{ - if (expect == result) - { - printf("\nCorrect:\n Expected %d got %d \n",expect,result); - } - else - { - printf("\nIncorrect:\n Expected %d got %d \n",expect,result); - exit (1); - } -} - -int main(void) -{ - bool result; - int a[] = {1,2,3,0,0}; - result = array_check(a, 2); - printf("Input submitted to the function: {1, 2, 3, 0, 0} and index 2"); - check(false, result); - int b[] = {1,2,3,4,5}; - result = array_check(b, 3); - printf("Input submitted to the function: {1, 2, 3, 4, 5} and index 3"); - check(true, result); - printf("All Correct\n"); - return 0; -} diff --git a/testapp/yaksh_app/c_cpp_files/main_array_check_all.cpp b/testapp/yaksh_app/c_cpp_files/main_array_check_all.cpp deleted file mode 100755 index 140578e..0000000 --- a/testapp/yaksh_app/c_cpp_files/main_array_check_all.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include - -extern bool array_check_all(int []); - -template - -void check(T expect,T result) -{ - if (expect == result) - { - printf("\nCorrect:\n Expected %d got %d \n",expect,result); - } - else - { - printf("\nIncorrect:\n Expected %d got %d \n",expect,result); - exit (1); - } -} - -int main(void) -{ - bool result; - int a[] = {1,2,3,2,8}; - result = array_check_all(a); - printf("Input submitted to the function: {1, 2, 3, 2, 8}"); - check(false, result); - int b[] = {4,2,32,4,56}; - result = array_check_all(b); - printf("Input submitted to the function: {4, 2, 32, 4, 56}"); - check(true, result); - printf("All Correct\n"); - return 0; -} diff --git a/testapp/yaksh_app/c_cpp_files/main_array_sum.cpp b/testapp/yaksh_app/c_cpp_files/main_array_sum.cpp deleted file mode 100755 index 55b2ebf..0000000 --- a/testapp/yaksh_app/c_cpp_files/main_array_sum.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include - -extern int array_sum(int []); - -template - -void check(T expect,T result) -{ - if (expect == result) - { - printf("\nCorrect:\n Expected %d got %d \n",expect,result); - } - else - { - printf("\nIncorrect:\n Expected %d got %d \n",expect,result); - exit (1); - } -} - -int main(void) -{ - int result; - int a[] = {1,2,3,0,0}; - result = array_sum(a); - printf("Input submitted to the function: {1, 2, 3, 0, 0}"); - check(6, result); - int b[] = {1,2,3,4,5}; - result = array_sum(b); - printf("Input submitted to the function: {1, 2, 3, 4, 5}"); - check(15,result); - printf("All Correct\n"); - return 0; -} diff --git a/testapp/yaksh_app/c_cpp_files/main_blackJack.cpp b/testapp/yaksh_app/c_cpp_files/main_blackJack.cpp deleted file mode 100755 index cc54e78..0000000 --- a/testapp/yaksh_app/c_cpp_files/main_blackJack.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include - -extern int blackJack(int, int); - -template - -void check(T expect, T result) -{ - if (expect == result) - { - printf("\nCorrect:\n Expected %d got %d \n",expect,result); - } - else - { - printf("\nIncorrect:\n Expected %d got %d \n",expect,result); - exit (1); - } -} - -int main(void) -{ - int result; - result = blackJack(11, 12); - printf("Input submitted to the function: 11, 12"); - check(12, result); - result = blackJack(15, 19); - printf("Input submitted to the function: 15, 19"); - check(19, result); - result = blackJack(10, 21); - printf("Input submitted to the function: 10, 21"); - check(21, result); - result = blackJack(31, 22); - printf("Input submitted to the function: 31, 22"); - check(0, result); - result = blackJack(91, 61); - printf("Input submitted to the function: 91, 61"); - check(0, result); - printf("All Correct\n"); - return 0; -} diff --git a/testapp/yaksh_app/c_cpp_files/main_check_digit.cpp b/testapp/yaksh_app/c_cpp_files/main_check_digit.cpp deleted file mode 100755 index d3bf3d6..0000000 --- a/testapp/yaksh_app/c_cpp_files/main_check_digit.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include - -extern bool check_digit(int, int); - -template - -void check(T expect, T result) -{ - if (expect == result) - { - printf("\nCorrect:\n Expected %d got %d \n",expect,result); - } - else - { - printf("\nIncorrect:\n Expected %d got %d \n",expect,result); - exit (1); - } -} - -int main(void) -{ - bool result; - result = check_digit(12, 23); - printf("Input submitted to the function: 12, 23"); - check(true, result); - result = check_digit(22, 11); - printf("Input submitted to the function: 121"); - check(false, result); - printf("All Correct\n"); - return 0; -} diff --git a/testapp/yaksh_app/c_cpp_files/main_count667.cpp b/testapp/yaksh_app/c_cpp_files/main_count667.cpp deleted file mode 100755 index f146e8c..0000000 --- a/testapp/yaksh_app/c_cpp_files/main_count667.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include - -extern int count667(int[]); - -template - -void check(T expect, T result) -{ - if (expect == result) - { - printf("\nCorrect:\n Expected %d got %d \n",expect,result); - } - else - { - printf("\nIncorrect:\n Expected %d got %d \n",expect,result); - exit (1); - } -} - -int main(void) -{ - int result; - int arr[5] = {2,6,4,5,6}; - result = count667(arr); - printf("Input submitted to the function: [2, 6, 4, 5,6]"); - check(0, result); - int arr2[5] = {6,6,2,17,9}; - result = count667(arr2); - printf("Input submitted to the function: [6, 6, 2, 17, 9]"); - check(1, result); - int arr3[5] = {6,6,6,7,1}; - result = count667(arr3); - printf("Input submitted to the function: [6, 6, 7, 2, 1]"); - check(3, result); - int arr4[5] = {6,7,7,6,6}; - result = count667(arr4); - printf("Input submitted to the function: [6, 7, 7, 6, 6]"); - check(2, result); - printf("All Correct\n"); - return 0; -} diff --git a/testapp/yaksh_app/c_cpp_files/main_count7.cpp b/testapp/yaksh_app/c_cpp_files/main_count7.cpp deleted file mode 100755 index 982e930..0000000 --- a/testapp/yaksh_app/c_cpp_files/main_count7.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include - -extern int count7(int[]); - -template - -void check(T expect, T result) -{ - if (expect == result) - { - printf("\nCorrect:\n Expected %d got %d \n",expect,result); - } - else - { - printf("\nIncorrect:\n Expected %d got %d \n",expect,result); - exit (1); - } -} - -int main(void) -{ - int result; - int arr[4] = {2,3,4,5}; - result = count7(arr); - printf("Input submitted to the function: [2, 3, 4, 5]"); - check(0, result); - int arr2[4] = {1,2,17,9}; - result = count7(arr2); - printf("Input submitted to the function: [1, 2, 17, 9]"); - check(0, result); - int arr3[4] = {7,9,2,1}; - result = count7(arr3); - printf("Input submitted to the function: [7, 9, 2, 1]"); - check(1, result); - int arr4[4] = {1,7,7,7}; - result = count7(arr4); - printf("Input submitted to the function: [1, 7, 7, 7]"); - check(3, result); - printf("All Correct\n"); - return 0; -} diff --git a/testapp/yaksh_app/c_cpp_files/main_fact.cpp b/testapp/yaksh_app/c_cpp_files/main_fact.cpp deleted file mode 100755 index a4ff230..0000000 --- a/testapp/yaksh_app/c_cpp_files/main_fact.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include - -extern int factorial(int); - -template - -void check(T expect, T result) -{ - if (expect == result) - { - printf("\nCorrect:\n Expected %d got %d \n",expect,result); - } - else - { - printf("\nIncorrect:\n Expected %d got %d \n",expect,result); - exit (1); - } -} - -int main(void) -{ - int result; - result = factorial(0); - printf("Input submitted to the function: 0"); - check(1, result); - result = factorial(3); - printf("Input submitted to the function: 3"); - check(6, result); - printf("All Correct\n"); - return 0; -} diff --git a/testapp/yaksh_app/c_cpp_files/main_greatest.cpp b/testapp/yaksh_app/c_cpp_files/main_greatest.cpp deleted file mode 100755 index 6d0a7c2..0000000 --- a/testapp/yaksh_app/c_cpp_files/main_greatest.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include -#include - -extern int greatest(int, int, int); - -template - -void check(T expect, T result) -{ - if (expect == result) - { - printf("\nCorrect:\n Expected %d got %d \n",expect,result); - } - else - { - printf("\nIncorrect:\n Expected %d got %d \n",expect,result); - exit (1); - } -} - -int main(void) -{ - int result; - result = greatest(1, 2, 3); - printf("Input submitted to the function: 1, 2, 3"); - check(3, result); - result = greatest(5, 9, 2); - printf("Input submitted to the function: 5, 9, 2"); - check(9, result); - result = greatest(7, 2, 4); - printf("Input submitted to the function: 7, 2, 4"); - check(7, result); - result = greatest(11, 2, 45); - printf("Input submitted to the function: 11, 2, 45"); - check(45, result); - result = greatest(2, 7, 0); - printf("Input submitted to the function: 2, 7, 0"); - check(7, result); - result = greatest(9, 6, 5); - printf("Input submitted to the function: 9, 6, 5"); - check(9, result); - printf("All Correct\n"); - return 0; -} diff --git a/testapp/yaksh_app/c_cpp_files/main_hello_name.c b/testapp/yaksh_app/c_cpp_files/main_hello_name.c deleted file mode 100755 index 71b83a2..0000000 --- a/testapp/yaksh_app/c_cpp_files/main_hello_name.c +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include - - -void check(char expect[], char result[]) -{ - if (expect == result) - { - printf("Correct:expected %s got %s \n",expect,result); - } - else - { - printf("ERROR:expected %s got %s \n",expect,result); - exit (0); - } -} - -int main(void) -{ - char result[20]; - char A[20]=" pratham"; - char B[20]=" sir"; - result[20] = message(A); - printf("%s",result); - check("hello pratham", result); - result[20] = message(B); - check("hello sir",result); - printf("All Correct\n"); -} diff --git a/testapp/yaksh_app/c_cpp_files/main_lessThan9.cpp b/testapp/yaksh_app/c_cpp_files/main_lessThan9.cpp deleted file mode 100755 index 722b4bb..0000000 --- a/testapp/yaksh_app/c_cpp_files/main_lessThan9.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include - -extern bool lessThan9(int); - -template - -void check(T expect, T result) -{ - if (expect == result) - { - printf("\nCorrect:\n Expected %d got %d \n",expect,result); - } - else - { - printf("\nIncorrect:\n Expected %d got %d \n",expect,result); - exit (1); - } -} - -int main(void) -{ - bool result; - result = lessThan9(10); - printf("Input submitted to the function: 10"); - check(false, result); - result = lessThan9(17); - printf("Input submitted to the function: 17"); - check(true, result); - result = lessThan9(16); - printf("Input submitted to the function: 16"); - check(true, result); - result = lessThan9(15); - printf("Input submitted to the function: 15"); - check(false, result); - printf("All Correct\n"); - return 0; -} diff --git a/testapp/yaksh_app/c_cpp_files/main_mean.cpp b/testapp/yaksh_app/c_cpp_files/main_mean.cpp deleted file mode 100755 index 21a4b1a..0000000 --- a/testapp/yaksh_app/c_cpp_files/main_mean.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include - -extern bool mean(int, int , int); - -template - -void check(T expect, T result) -{ - if (expect == result) - { - printf("\nCorrect:\n Expected %d got %d \n",expect,result); - } - else - { - printf("\nIncorrect:\n Expected %d got %d \n",expect,result); - exit (1); - } -} - -int main(void) -{ - bool result; - result = mean(11, 11, 11); - printf("Input submitted to the function: 11, 121, 11"); - check(true, result); - result = mean(16, 12, 9); - printf("Input submitted to the function: 16, 144, 9"); - check(true, result); - result = mean(19, 221, 9); - printf("Input submitted to the function: 19, 221, 9"); - check(false, result); - result = mean(34, 12, 3); - printf("Input submitted to the function: 11, 121, 11"); - check(false, result); - printf("All Correct\n"); - return 0; -} diff --git a/testapp/yaksh_app/c_cpp_files/main_palindrome.cpp b/testapp/yaksh_app/c_cpp_files/main_palindrome.cpp deleted file mode 100755 index 0e66928..0000000 --- a/testapp/yaksh_app/c_cpp_files/main_palindrome.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include - -extern bool palindrome(int); - -template - -void check(T expect, T result) -{ - if (expect == result) - { - printf("\nCorrect:\n Expected %d got %d \n",expect,result); - } - else - { - printf("\nIncorrect:\n Expected %d got %d \n",expect,result); - exit (1); - } -} - -int main(void) -{ - bool result; - result = palindrome(123); - printf("Input submitted to the function: 123"); - check(false, result); - result = palindrome(121); - printf("Input submitted to the function: 121"); - check(true, result); - printf("All Correct\n"); - return 0; -} diff --git a/testapp/yaksh_app/c_cpp_files/main_roundTo10.cpp b/testapp/yaksh_app/c_cpp_files/main_roundTo10.cpp deleted file mode 100755 index 12c961d..0000000 --- a/testapp/yaksh_app/c_cpp_files/main_roundTo10.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include - -extern int roundTo10(int,int,int); - -template - -void check(T expect, T result) -{ - if (expect == result) - { - printf("\nCorrect:\n Expected %d got %d \n",expect,result); - } - else - { - printf("\nIncorrect:\n Expected %d got %d \n",expect,result); - exit (1); - } -} - -int main(void) -{ - int result; - result = roundTo10(10, 22, 39); - printf("Input submitted to the function: 10, 22, 39"); - check(70, result); - result = roundTo10(45, 42, 39); - printf("Input submitted to the function: 45, 42, 39"); - check(130, result); - result = roundTo10(7, 3, 9); - printf("Input submitted to the function: 7, 3, 9"); - check(20, result); - result = roundTo10(1, 2, 3); - printf("Input submitted to the function: 1, 2, 3"); - check(0, result); - result = roundTo10(30, 40, 50); - printf("Input submitted to the function: 30, 40, 50"); - check(120, result); - printf("All Correct\n"); - return 0; -} diff --git a/testapp/yaksh_app/c_cpp_files/main_specialSum.cpp b/testapp/yaksh_app/c_cpp_files/main_specialSum.cpp deleted file mode 100755 index d614536..0000000 --- a/testapp/yaksh_app/c_cpp_files/main_specialSum.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include - -extern int specialSum(int,int,int); - -template - -void check(T expect, T result) -{ - if (expect == result) - { - printf("\nCorrect:\n Expected %d got %d \n",expect,result); - } - else - { - printf("\nIncorrect:\n Expected %d got %d \n",expect,result); - exit (1); - } -} - -int main(void) -{ - int result; - result = specialSum(10, 2, 9); - printf("Input submitted to the function: 10, 2, 9"); - check(21, result); - result = specialSum(1, 21, 9); - printf("Input submitted to the function: 1, 21, 9"); - check(1, result); - result = specialSum(21, 2, 3); - printf("Input submitted to the function: 21, 2, 3"); - check(0, result); - result = specialSum(10, 2, 21); - printf("Input submitted to the function: 10, 2, 21"); - check(12, result); - result = specialSum(10, 2, 6); - printf("Input submitted to the function: 10, 2, 6"); - check(18, result); - printf("All Correct\n"); - return 0; -} diff --git a/testapp/yaksh_app/c_cpp_files/main_within.cpp b/testapp/yaksh_app/c_cpp_files/main_within.cpp deleted file mode 100755 index 50f9ad0..0000000 --- a/testapp/yaksh_app/c_cpp_files/main_within.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include - -extern bool within(int, int, int); - -template - -void check(T expect, T result) -{ - if (expect == result) - { - printf("\nCorrect:\n Expected %d got %d \n",expect,result); - } - else - { - printf("\nIncorrect:\n Expected %d got %d \n",expect,result); - exit (1); - } -} - -int main(void) -{ - bool result; - result = within(12, 3, 20); - printf("Input submitted to the function: 12, 3, 20"); - check(true, result); - result = within(12, 13, 20); - printf("Input submitted to the function: 12, 13, 20"); - check(false, result); - result = within(29, 13, 120); - printf("Input submitted to the function: 29, 13, 120"); - check(true, result); - result = within(12, 12, 20); - printf("Input submitted to the function: 12, 3, 20"); - check(false, result); - printf("All Correct\n"); - return 0; -} diff --git a/testapp/yaksh_app/code_evaluator.py b/testapp/yaksh_app/code_evaluator.py deleted file mode 100644 index 381b2e8..0000000 --- a/testapp/yaksh_app/code_evaluator.py +++ /dev/null @@ -1,206 +0,0 @@ -import sys -from SimpleXMLRPCServer import SimpleXMLRPCServer -import pwd -import os -import stat -from os.path import isdir, dirname, abspath, join, isfile -import signal -from multiprocessing import Process, Queue -import subprocess -import re -import json -# Local imports. -from settings import SERVER_TIMEOUT - - -MY_DIR = abspath(dirname(__file__)) - - -# Raised when the code times-out. -# c.f. http://pguides.net/python/timeout-a-function -class TimeoutException(Exception): - pass - - -def timeout_handler(signum, frame): - """A handler for the ALARM signal.""" - raise TimeoutException('Code took too long to run.') - - -def create_signal_handler(): - """Add a new signal handler for the execution of this code.""" - prev_handler = signal.signal(signal.SIGALRM, timeout_handler) - signal.alarm(SERVER_TIMEOUT) - return prev_handler - - -def set_original_signal_handler(old_handler=None): - """Set back any original signal handler.""" - if old_handler is not None: - signal.signal(signal.SIGALRM, old_handler) - return - else: - raise Exception("Signal Handler: object cannot be NoneType") - - -def delete_signal_handler(): - signal.alarm(0) - return - - -class CodeEvaluator(object): - """Tests the code obtained from Code Server""" - def __init__(self, test_case_data, test, language, user_answer, - ref_code_path=None, in_dir=None): - msg = 'Code took more than %s seconds to run. You probably '\ - 'have an infinite loop in your code.' % SERVER_TIMEOUT - self.timeout_msg = msg - self.test_case_data = test_case_data - self.language = language.lower() - self.user_answer = user_answer - self.ref_code_path = ref_code_path - self.test = test - self.in_dir = in_dir - self.test_case_args = None - - # Public Protocol ########## - @classmethod - def from_json(cls, language, json_data, in_dir): - json_data = json.loads(json_data) - test_case_data = json_data.get("test_case_data") - user_answer = json_data.get("user_answer") - ref_code_path = json_data.get("ref_code_path") - test = json_data.get("test") - - instance = cls(test_case_data, test, language, user_answer, ref_code_path, - in_dir) - return instance - - def evaluate(self): - """Evaluates given code with the test cases based on - given arguments in test_case_data. - - The ref_code_path is a path to the reference code. - The reference code will call the function submitted by the student. - The reference code will check for the expected output. - - If the path's start with a "/" then we assume they are absolute paths. - If not, we assume they are relative paths w.r.t. the location of this - code_server script. - - If the optional `in_dir` keyword argument is supplied it changes the - directory to that directory (it does not change it back to the original - when done). - - Returns - ------- - - A tuple: (success, error message). - """ - - self._setup() - success, err = self._evaluate(self.test_case_args) - self._teardown() - - result = {'success': success, 'error': err} - return result - - # Private Protocol ########## - def _setup(self): - self._change_dir(self.in_dir) - - def _evaluate(self, args): - # Add a new signal handler for the execution of this code. - prev_handler = create_signal_handler() - success = False - args = args or [] - - # Do whatever testing needed. - try: - success, err = self._check_code(*args) - - except TimeoutException: - err = self.timeout_msg - except: - _type, value = sys.exc_info()[:2] - err = "Error: {0}".format(repr(value)) - finally: - # Set back any original signal handler. - set_original_signal_handler(prev_handler) - - return success, err - - def _teardown(self): - # Cancel the signal - delete_signal_handler() - - def _check_code(self): - raise NotImplementedError("check_code method not implemented") - - def create_submit_code_file(self, file_name): - """ Write the code (`answer`) to a file and set the file path""" - submit_f = open(file_name, 'w') - submit_f.write(self.user_answer.lstrip()) - submit_f.close() - submit_path = abspath(submit_f.name) - - return submit_path - - def _set_file_as_executable(self, fname): - os.chmod(fname, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR - | stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP - | stat.S_IROTH | stat.S_IWOTH | stat.S_IXOTH) - - def _set_test_code_file_path(self, ref_path=None, test_case_path=None): - if ref_path and not ref_path.startswith('/'): - ref_path = join(MY_DIR, ref_path) - - if test_case_path and not test_case_path.startswith('/'): - test_case_path = join(MY_DIR, test_case_path) - - return ref_path, test_case_path - - def _run_command(self, cmd_args, *args, **kw): - """Run a command in a subprocess while blocking, the process is killed - if it takes more than 2 seconds to run. Return the Popen object, the - stdout and stderr. - """ - try: - proc = subprocess.Popen(cmd_args, *args, **kw) - stdout, stderr = proc.communicate() - except TimeoutException: - # Runaway code, so kill it. - proc.kill() - # Re-raise exception. - raise - return proc, stdout, stderr - - def _compile_command(self, cmd, *args, **kw): - """Compiles C/C++/java code and returns errors if any. - Run a command in a subprocess while blocking, the process is killed - if it takes more than 2 seconds to run. Return the Popen object, the - stderr. - """ - try: - proc_compile = subprocess.Popen(cmd, shell=True, stdin=None, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - out, err = proc_compile.communicate() - except TimeoutException: - # Runaway code, so kill it. - proc_compile.kill() - # Re-raise exception. - raise - return proc_compile, err - - def _change_dir(self, in_dir): - if in_dir is not None and isdir(in_dir): - os.chdir(in_dir) - - def _remove_null_substitute_char(self, string): - """Returns a string without any null and substitute characters""" - stripped = "" - for c in string: - if ord(c) is not 26 and ord(c) is not 0: - stripped = stripped + c - return ''.join(stripped) diff --git a/testapp/yaksh_app/code_server.py b/testapp/yaksh_app/code_server.py deleted file mode 100755 index 2593752..0000000 --- a/testapp/yaksh_app/code_server.py +++ /dev/null @@ -1,162 +0,0 @@ -#!/usr/bin/env python -"""This server runs an XMLRPC server that can be submitted code and tests -and returns the output. It *should* be run as root and will run as the user -'nobody' so as to minimize any damange by errant code. This can be configured -by editing settings.py to run as many servers as desired. One can also -specify the ports on the command line. Here are examples:: - - $ sudo ./code_server.py - # Runs servers based on settings.py:SERVER_PORTS one server per port given. - -or:: - - $ sudo ./code_server.py 8001 8002 8003 8004 8005 - # Runs 5 servers on ports specified. - -All these servers should be running as nobody. This will also start a server -pool that defaults to port 50000 and is configurable in -settings.py:SERVER_POOL_PORT. This port exposes a `get_server_port` function -that returns an available server. -""" -import sys -from SimpleXMLRPCServer import SimpleXMLRPCServer -import pwd -import os -import stat -from os.path import isdir, dirname, abspath, join, isfile -import signal -from multiprocessing import Process, Queue -import subprocess -import re -import json -# Local imports. -from settings import SERVER_PORTS, SERVER_POOL_PORT -from language_registry import set_registry, get_registry - - -MY_DIR = abspath(dirname(__file__)) - - -# Private Protocol ########## -def run_as_nobody(): - """Runs the current process as nobody.""" - # Set the effective uid and to that of nobody. - nobody = pwd.getpwnam('nobody') - os.setegid(nobody.pw_gid) - os.seteuid(nobody.pw_uid) - - -############################################################################### -# `CodeServer` class. -############################################################################### -class CodeServer(object): - """A code server that executes user submitted test code, tests it and - reports if the code was correct or not. - """ - def __init__(self, port, queue): - self.port = port - self.queue = queue - - # Public Protocol ########## - def check_code(self, language, json_data, in_dir=None): - """Calls relevant EvaluateCode class based on language to check the - answer code - """ - code_evaluator = self._create_evaluator_instance(language, json_data, - in_dir) - result = code_evaluator.evaluate() - - # Put us back into the server pool queue since we are free now. - self.queue.put(self.port) - - return json.dumps(result) - - def run(self): - """Run XMLRPC server, serving our methods.""" - server = SimpleXMLRPCServer(("localhost", self.port)) - self.server = server - server.register_instance(self) - self.queue.put(self.port) - server.serve_forever() - - # Private Protocol ########## - def _create_evaluator_instance(self, language, json_data, in_dir): - """Create instance of relevant EvaluateCode class based on language""" - set_registry() - registry = get_registry() - cls = registry.get_class(language) - instance = cls.from_json(language, json_data, in_dir) - return instance - - -############################################################################### -# `ServerPool` class. -############################################################################### -class ServerPool(object): - """Manages a pool of CodeServer objects.""" - def __init__(self, ports, pool_port=50000): - """Create a pool of servers. Uses a shared Queue to get available - servers. - - Parameters - ---------- - - ports : list(int) - List of ports at which the CodeServer's should run. - - pool_port : int - Port at which the server pool should serve. - """ - self.my_port = pool_port - self.ports = ports - queue = Queue(maxsize=len(ports)) - self.queue = queue - servers = [] - for port in ports: - server = CodeServer(port, queue) - servers.append(server) - p = Process(target=server.run) - p.start() - self.servers = servers - - # Public Protocol ########## - - def get_server_port(self): - """Get available server port from ones in the pool. This will block - till it gets an available server. - """ - q = self.queue - was_waiting = True if q.empty() else False - port = q.get() - if was_waiting: - print '*'*80 - print "No available servers, was waiting but got server \ - later at %d." % port - print '*'*80 - sys.stdout.flush() - return port - - def run(self): - """Run server which returns an available server port where code - can be executed. - """ - server = SimpleXMLRPCServer(("localhost", self.my_port)) - self.server = server - server.register_instance(self) - server.serve_forever() - - -############################################################################### -def main(args=None): - run_as_nobody() - if args: - ports = [int(x) for x in args[1:]] - else: - ports = SERVER_PORTS - - server_pool = ServerPool(ports=ports, pool_port=SERVER_POOL_PORT) - server_pool.run() - -if __name__ == '__main__': - args = sys.argv[1:] - main(args) diff --git a/testapp/yaksh_app/cpp_code_evaluator.py b/testapp/yaksh_app/cpp_code_evaluator.py deleted file mode 100644 index 7242884..0000000 --- a/testapp/yaksh_app/cpp_code_evaluator.py +++ /dev/null @@ -1,125 +0,0 @@ -#!/usr/bin/env python -import traceback -import pwd -import os -from os.path import join, isfile -import subprocess -import importlib - -# local imports -from code_evaluator import CodeEvaluator - - -class CppCodeEvaluator(CodeEvaluator): - """Tests the C code obtained from Code Server""" - def __init__(self, test_case_data, test, language, user_answer, - ref_code_path=None, in_dir=None): - super(CppCodeEvaluator, self).__init__(test_case_data, test, language, - user_answer, ref_code_path, - in_dir) - self.test_case_args = self._setup() - - # Private Protocol ########## - def _setup(self): - super(CppCodeEvaluator, self)._setup() - - get_ref_path = self.ref_code_path - ref_path, test_case_path = self._set_test_code_file_path(get_ref_path) - self.submit_path = self.create_submit_code_file('submit.c') - - # Set file paths - c_user_output_path = os.getcwd() + '/output' - c_ref_output_path = os.getcwd() + '/executable' - - # Set command variables - compile_command = 'g++ {0} -c -o {1}'.format(self.submit_path, - c_user_output_path) - compile_main = 'g++ {0} {1} -o {2}'.format(ref_path, - c_user_output_path, - c_ref_output_path) - run_command_args = [c_ref_output_path] - remove_user_output = c_user_output_path - remove_ref_output = c_ref_output_path - - return (ref_path, self.submit_path, compile_command, compile_main, - run_command_args, remove_user_output, remove_ref_output) - - def _teardown(self): - # Delete the created file. - super(CppCodeEvaluator, self)._teardown() - os.remove(self.submit_path) - - def _check_code(self, ref_code_path, submit_code_path, compile_command, - compile_main, run_command_args, remove_user_output, - remove_ref_output): - """ Function validates student code using instructor code as - reference.The first argument ref_code_path, is the path to - instructor code, it is assumed to have executable permission. - The second argument submit_code_path, is the path to the student - code, it is assumed to have executable permission. - - Returns - -------- - - returns (True, "Correct answer") : If the student function returns - expected output when called by reference code. - - returns (False, error_msg): If the student function fails to return - expected output when called by reference code. - - Returns (False, error_msg): If mandatory arguments are not files or - if the required permissions are not given to the file(s). - - """ - if not isfile(ref_code_path): - return False, "No file at %s or Incorrect path" % ref_code_path - if not isfile(submit_code_path): - return False, 'No file at %s or Incorrect path' % submit_code_path - - success = False - ret = self._compile_command(compile_command) - proc, stdnt_stderr = ret - stdnt_stderr = self._remove_null_substitute_char(stdnt_stderr) - - # Only if compilation is successful, the program is executed - # And tested with testcases - if stdnt_stderr == '': - ret = self._compile_command(compile_main) - proc, main_err = ret - main_err = self._remove_null_substitute_char(main_err) - - if main_err == '': - ret = self._run_command(run_command_args, stdin=None, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - proc, stdout, stderr = ret - if proc.returncode == 0: - success, err = True, "Correct answer" - else: - err = stdout + "\n" + stderr - os.remove(remove_ref_output) - else: - err = "Error:" - try: - error_lines = main_err.splitlines() - for e in error_lines: - if ':' in e: - err = err + "\n" + e.split(":", 1)[1] - else: - err = err + "\n" + e - except: - err = err + "\n" + main_err - os.remove(remove_user_output) - else: - err = "Compilation Error:" - try: - error_lines = stdnt_stderr.splitlines() - for e in error_lines: - if ':' in e: - err = err + "\n" + e.split(":", 1)[1] - else: - err = err + "\n" + e - except: - err = err + "\n" + stdnt_stderr - - return success, err diff --git a/testapp/yaksh_app/docs/sample.args b/testapp/yaksh_app/docs/sample.args deleted file mode 100644 index 4d9f00d..0000000 --- a/testapp/yaksh_app/docs/sample.args +++ /dev/null @@ -1,2 +0,0 @@ -1 2 -2 1 diff --git a/testapp/yaksh_app/docs/sample.sh b/testapp/yaksh_app/docs/sample.sh deleted file mode 100755 index e935cb3..0000000 --- a/testapp/yaksh_app/docs/sample.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -[[ $# -eq 2 ]] && echo $(( $1 + $2 )) && exit $(( $1 + $2 )) diff --git a/testapp/yaksh_app/docs/sample_questions.py b/testapp/yaksh_app/docs/sample_questions.py deleted file mode 100644 index 60f32cb..0000000 --- a/testapp/yaksh_app/docs/sample_questions.py +++ /dev/null @@ -1,84 +0,0 @@ -from datetime import date - -questions = [ -[Question( - summary='Factorial', - points=2, - language='python', - type='code', - description=''' -Write a function called fact
which takes a single integer argument -(sayn
) and returns the factorial of the number. -For example:
-fact(3) -> 6
-''', - test=''' -assert fact(0) == 1 -assert fact(5) == 120 -''', - snippet="def fact(num):" - ), -#Add tags here as a list of string. -['Python','function','factorial'], -], - -[Question( - summary='Simple function', - points=1, - language='python', - type='code', - description='''Create a simple function calledsqr
which takes a single -argument and returns the square of the argument. For example:
-sqr(3) -> 9
.''', - test=''' -import math -assert sqr(3) == 9 -assert abs(sqr(math.sqrt(2)) - 2.0) < 1e-14 - ''', - snippet="def sqr(num):" - ), -#Add tags here as a list of string. -['Python','function'], -], - -[Question( - summary='Bash addition', - points=2, - language='bash', - type='code', - description='''Write a shell script which takes two arguments on the - command line and prints the sum of the two on the output.''', - test='''\ -docs/sample.sh -docs/sample.args -''', - snippet="#!/bin/bash" - ), -#Add tags here as a list of string. -[''], -], - -[Question( - summary='Size of integer in Python', - points=0.5, - language='python', - type='mcq', - description='''What is the largest integer value that can be represented -in Python?''', - options='''No Limit -2**32 -2**32 - 1 -None of the above -''', - test = "No Limit" - ), -#Add tags here as a list of string. -['mcq'], -], - -] #list of questions ends here - -quiz = Quiz(start_date=date.today(), - duration=10, - description='Basic Python Quiz 1' - ) diff --git a/testapp/yaksh_app/docs/sample_questions.xml b/testapp/yaksh_app/docs/sample_questions.xml deleted file mode 100644 index 53c76f8..0000000 --- a/testapp/yaksh_app/docs/sample_questions.xml +++ /dev/null @@ -1,43 +0,0 @@ -- - diff --git a/testapp/yaksh_app/forms.py b/testapp/yaksh_app/forms.py deleted file mode 100644 index 8a909f2..0000000 --- a/testapp/yaksh_app/forms.py +++ /dev/null @@ -1,267 +0,0 @@ -from django import forms -from testapp.yaksh_app.models import Profile, Quiz, Question, TestCase - -from django.contrib.auth import authenticate -from django.contrib.auth.models import User -from taggit.managers import TaggableManager -from taggit.forms import TagField -from django.forms.models import inlineformset_factory - -from string import letters, punctuation, digits -import datetime - -languages = ( - ("select", "Select Language"), - ("python", "Python"), - ("bash", "Bash"), - ("c", "C Language"), - ("cpp", "C++ Language"), - ("java", "Java Language"), - ("scilab", "Scilab"), - ) - -question_types = ( - ("select", "Select Question Type"), - ("mcq", "Multiple Choice"), - ("mcc", "Multiple Correct Choices"), - ("code", "Code"), - ("upload", "Assignment Upload"), - ) - -UNAME_CHARS = letters + "._" + digits -PWD_CHARS = letters + punctuation + digits - -attempts = [(i, i) for i in range(1, 6)] -attempts.append((-1, 'Infinite')) -days_between_attempts = ((j, j) for j in range(401)) - - -class UserRegisterForm(forms.Form): - """A Class to create new form for User's Registration. - It has the various fields and functions required to register - a new user to the system""" - - username = forms.CharField(max_length=30, help_text='Letters, digits,\ - period and underscores only.') - email = forms.EmailField() - password = forms.CharField(max_length=30, widget=forms.PasswordInput()) - confirm_password = forms.CharField\ - (max_length=30, widget=forms.PasswordInput()) - first_name = forms.CharField(max_length=30) - last_name = forms.CharField(max_length=30) - roll_number = forms.CharField\ - (max_length=30, help_text="Use a dummy if you don't have one.") - institute = forms.CharField\ - (max_length=128, help_text='Institute/Organization') - department = forms.CharField\ - (max_length=64, help_text='Department you work/study at') - position = forms.CharField\ - (max_length=64, help_text='Student/Faculty/Researcher/Industry/etc.') - - def clean_username(self): - u_name = self.cleaned_data["username"] - if u_name.strip(UNAME_CHARS): - msg = "Only letters, digits, period and underscore characters are"\ - " allowed in username" - raise forms.ValidationError(msg) - try: - User.objects.get(username__exact=u_name) - raise forms.ValidationError("Username already exists.") - except User.DoesNotExist: - return u_name - - def clean_password(self): - pwd = self.cleaned_data['password'] - if pwd.strip(PWD_CHARS): - raise forms.ValidationError("Only letters, digits and punctuation\ - are allowed in password") - return pwd - - def clean_confirm_password(self): - c_pwd = self.cleaned_data['confirm_password'] - pwd = self.data['password'] - if c_pwd != pwd: - raise forms.ValidationError("Passwords do not match") - - return c_pwd - - def save(self): - u_name = self.cleaned_data["username"] - u_name = u_name.lower() - pwd = self.cleaned_data["password"] - email = self.cleaned_data['email'] - new_user = User.objects.create_user(u_name, email, pwd) - - new_user.first_name = self.cleaned_data["first_name"] - new_user.last_name = self.cleaned_data["last_name"] - new_user.save() - - cleaned_data = self.cleaned_data - new_profile = Profile(user=new_user) - new_profile.roll_number = cleaned_data["roll_number"] - new_profile.institute = cleaned_data["institute"] - new_profile.department = cleaned_data["department"] - new_profile.position = cleaned_data["position"] - new_profile.save() - - return u_name, pwd - - -class UserLoginForm(forms.Form): - """Creates a form which will allow the user to log into the system.""" - - username = forms.CharField(max_length=30) - password = forms.CharField(max_length=30, widget=forms.PasswordInput()) - - def clean(self): - super(UserLoginForm, self).clean() - try: - u_name, pwd = self.cleaned_data["username"],\ - self.cleaned_data["password"] - user = authenticate(username=u_name, password=pwd) - except Exception: - raise forms.ValidationError\ - ("Username and/or Password is not entered") - if not user: - raise forms.ValidationError("Invalid username/password") - return user - - -class QuizForm(forms.Form): - """Creates a form to add or edit a Quiz. - It has the related fields and functions required.""" - - def __init__(self, *args, **kwargs): - super(QuizForm, self).__init__(*args, **kwargs) - quizzes = [('', 'Select a prerequisite quiz')] - quizzes = quizzes + \ - list(Quiz.objects.values_list('id', 'description')) - self.fields['prerequisite'] = forms.CharField(required=False, - widget=forms.Select(choices=quizzes)) - - start_date = forms.DateField(initial=datetime.date.today(), required=False) - start_time = forms.TimeField(initial=datetime.datetime.now().time(), required=False) - end_date = forms.DateField(initial=datetime.date(2199, 1, 1), required=False) - end_time = forms.TimeField(initial=datetime.time(0, 0, 0, 0), required=False) - duration = forms.IntegerField(help_text='Will be taken in minutes') - active = forms.BooleanField(required=False) - description = forms.CharField(max_length=256, widget=forms.Textarea\ - (attrs={'cols': 20, 'rows': 1})) - pass_criteria = forms.FloatField(initial=40, - help_text='Will be taken as percentage') - language = forms.CharField(widget=forms.Select(choices=languages)) - attempts_allowed = forms.IntegerField(widget=forms.Select(choices=attempts)) - time_between_attempts = forms.IntegerField\ - (widget=forms.Select(choices=days_between_attempts), - help_text='Will be in days') - - def save(self): - start_date = self.cleaned_data["start_date"] - start_time = self.cleaned_data["start_time"] - end_date = self.cleaned_data["end_date"] - end_time = self.cleaned_data["end_time"] - duration = self.cleaned_data["duration"] - active = self.cleaned_data['active'] - description = self.cleaned_data["description"] - pass_criteria = self.cleaned_data["pass_criteria"] - language = self.cleaned_data["language"] - prerequisite = self.cleaned_data["prerequisite"] - attempts_allowed = self.cleaned_data["attempts_allowed"] - time_between_attempts = self.cleaned_data["time_between_attempts"] - new_quiz = Quiz() - new_quiz.start_date_time = datetime.datetime.combine(start_date, - start_time) - new_quiz.end_date_time = datetime.datetime.combine(end_date, - end_time) - new_quiz.duration = duration - new_quiz.active = active - new_quiz.description = description - new_quiz.pass_criteria = pass_criteria - new_quiz.language = language - new_quiz.prerequisite_id = prerequisite - new_quiz.attempts_allowed = attempts_allowed - new_quiz.time_between_attempts = time_between_attempts - new_quiz.save() - - -class QuestionForm(forms.ModelForm): - """Creates a form to add or edit a Question. - It has the related fields and functions required.""" - - summary = forms.CharField(widget=forms.Textarea\ - (attrs={'cols': 40, 'rows': 1})) - description = forms.CharField(widget=forms.Textarea\ - (attrs={'cols': 40, 'rows': 1})) - points = forms.FloatField() - test = forms.CharField(widget=forms.Textarea\ - (attrs={'cols': 40, 'rows': 1}), required=False) - options = forms.CharField(widget=forms.Textarea\ - (attrs={'cols': 40, 'rows': 1}), required=False) - language = forms.CharField(max_length=20, widget=forms.Select\ - (choices=languages)) - type = forms.CharField(max_length=8, widget=forms.Select\ - (choices=question_types)) - active = forms.BooleanField(required=False) - tags = TagField(required=False) - snippet = forms.CharField(widget=forms.Textarea\ - (attrs={'cols': 40, 'rows': 1}), required=False) - ref_code_path = forms.CharField(widget=forms.Textarea\ - (attrs={'cols': 40, 'rows': 1}), required=False) - - def save(self, commit=True): - summary = self.cleaned_data.get("summary") - description = self.cleaned_data.get("description") - points = self.cleaned_data.get("points") - test = self.cleaned_data.get("test") - options = self.cleaned_data.get("options") - language = self.cleaned_data.get("language") - type = self.cleaned_data.get("type") - active = self.cleaned_data.get("active") - snippet = self.cleaned_data.get("snippet") - - new_question = Question() - new_question.summary = summary - new_question.description = description - new_question.points = points - new_question.test = test - new_question.options = options - new_question.language = language - new_question.type = type - new_question.active = active - new_question.snippet = snippet - new_question = super(QuestionForm, self).save(commit=False) - if commit: - new_question.save() - - return new_question - - class Meta: - model = Question - - -class RandomQuestionForm(forms.Form): - question_type = forms.CharField(max_length=8, widget=forms.Select\ - (choices=question_types)) - marks = forms.CharField(max_length=8, widget=forms.Select\ - (choices=(('select', 'Select Marks'),))) - shuffle_questions = forms.BooleanField(required=False) - - -class QuestionFilterForm(forms.Form): - def __init__(self, *args, **kwargs): - super(QuestionFilterForm, self).__init__(*args, **kwargs) - questions = Question.objects.all() - points_list = questions.values_list('points', flat=True).distinct() - points_options = [('select', 'Select Marks')] - points_options.extend([(point, point) for point in points_list]) - self.fields['marks'] = forms.FloatField(widget=forms.Select\ - (choices=points_options)) - - language = forms.CharField(max_length=8, widget=forms.Select\ - (choices=languages)) - question_type = forms.CharField(max_length=8, widget=forms.Select\ - (choices=question_types)) - - -TestCaseFormSet = inlineformset_factory(Question, TestCase,\ - can_order=False, can_delete=False, extra=1) diff --git a/testapp/yaksh_app/java_code_evaluator.py b/testapp/yaksh_app/java_code_evaluator.py deleted file mode 100644 index 4367259..0000000 --- a/testapp/yaksh_app/java_code_evaluator.py +++ /dev/null @@ -1,128 +0,0 @@ -#!/usr/bin/env python -import traceback -import pwd -import os -from os.path import join, isfile -import subprocess -import importlib - -# local imports -from code_evaluator import CodeEvaluator - - -class JavaCodeEvaluator(CodeEvaluator): - """Tests the Java code obtained from Code Server""" - def __init__(self, test_case_data, test, language, user_answer, - ref_code_path=None, in_dir=None): - super(JavaCodeEvaluator, self).__init__(test_case_data, test, - language, user_answer, - ref_code_path, in_dir) - self.test_case_args = self._setup() - - # Private Protocol ########## - def _setup(self): - super(JavaCodeEvaluator, self)._setup() - - ref_path, test_case_path = self._set_test_code_file_path(self.ref_code_path) - self.submit_path = self.create_submit_code_file('Test.java') - - # Set file paths - java_student_directory = os.getcwd() + '/' - java_ref_file_name = (ref_path.split('/')[-1]).split('.')[0] - - # Set command variables - compile_command = 'javac {0}'.format(self.submit_path), - compile_main = ('javac {0} -classpath ' - '{1} -d {2}').format(ref_path, - java_student_directory, - java_student_directory) - run_command_args = "java -cp {0} {1}".format(java_student_directory, - java_ref_file_name) - remove_user_output = "{0}{1}.class".format(java_student_directory, - 'Test') - remove_ref_output = "{0}{1}.class".format(java_student_directory, - java_ref_file_name) - - return (ref_path, self.submit_path, compile_command, compile_main, - run_command_args, remove_user_output, remove_ref_output) - - def _teardown(self): - # Delete the created file. - super(JavaCodeEvaluator, self)._teardown() - os.remove(self.submit_path) - - def _check_code(self, ref_code_path, submit_code_path, compile_command, - compile_main, run_command_args, remove_user_output, - remove_ref_output): - """ Function validates student code using instructor code as - reference.The first argument ref_code_path, is the path to - instructor code, it is assumed to have executable permission. - The second argument submit_code_path, is the path to the student - code, it is assumed to have executable permission. - - Returns - -------- - - returns (True, "Correct answer") : If the student function returns - expected output when called by reference code. - - returns (False, error_msg): If the student function fails to return - expected output when called by reference code. - - Returns (False, error_msg): If mandatory arguments are not files or - if the required permissions are not given to the file(s). - - """ - if not isfile(ref_code_path): - return False, "No file at %s or Incorrect path" % ref_code_path - if not isfile(submit_code_path): - return False, 'No file at %s or Incorrect path' % submit_code_path - - success = False - ret = self._compile_command(compile_command) - proc, stdnt_stderr = ret - stdnt_stderr = self._remove_null_substitute_char(stdnt_stderr) - - # Only if compilation is successful, the program is executed - # And tested with testcases - if stdnt_stderr == '': - ret = self._compile_command(compile_main) - proc, main_err = ret - main_err = self._remove_null_substitute_char(main_err) - - if main_err == '': - ret = self._run_command(run_command_args, shell=True, - stdin=None, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - proc, stdout, stderr = ret - if proc.returncode == 0: - success, err = True, "Correct answer" - else: - err = stdout + "\n" + stderr - os.remove(remove_ref_output) - else: - err = "Error:" - try: - error_lines = main_err.splitlines() - for e in error_lines: - if ':' in e: - err = err + "\n" + e.split(":", 1)[1] - else: - err = err + "\n" + e - except: - err = err + "\n" + main_err - os.remove(remove_user_output) - else: - err = "Compilation Error:" - try: - error_lines = stdnt_stderr.splitlines() - for e in error_lines: - if ':' in e: - err = err + "\n" + e.split(":", 1)[1] - else: - err = err + "\n" + e - except: - err = err + "\n" + stdnt_stderr - - return success, err diff --git a/testapp/yaksh_app/java_files/main_array_sum.java b/testapp/yaksh_app/java_files/main_array_sum.java deleted file mode 100644 index 5eae299..0000000 --- a/testapp/yaksh_app/java_files/main_array_sum.java +++ /dev/null @@ -1,36 +0,0 @@ -class main_array_sum -{ - public static- - --Factorial - --Write a function called "fact" which takes a single integer argument (say "n") -and returns the factorial of the number. -For example fact(3) -> 6 - -2 -python --assert fact(0) == 1 -assert fact(5) == 120 - -- -- - - --Simple function - --Create a simple function called "sqr" which takes a single argument and -returns the square of the argument -For example sqr(3) -> 9. - -1 -python --import math -assert sqr(3) == 9 -assert abs(sqr(math.sqrt(2)) - 2.0) < 1e-14 - -- -void check(E expect, E result) - { - if(result.equals(expect)) - { - System.out.println("Correct:\nOutput expected "+expect+" and got "+result); - } - else - { - System.out.println("Incorrect:\nOutput expected "+expect+" but got "+result); - System.exit(1); - } - } - public static void main(String arg[]) - { - int result; - Test t = new Test(); - int x[] = {0,0,0,0,0}; - result = t.array_sum(x); - System.out.println("Input submitted to the function: {0,0,0,0,0}"); - check(0, result); - int a[] = {1,2,3,4,5}; - result = t.array_sum(a); - System.out.println("Input submitted to the function: {1,2,3,4,5}"); - check(15, result); - int b[] = {1,2,3,0,0}; - result = t.array_sum(b); - System.out.println("Input submitted to the function: {1,2,3,0,0}"); - check(6, result); - int c[] = {1,1,1,1,1}; - result = t.array_sum(c); - System.out.println("Input submitted to the function: {1,1,1,1,1}"); - check(5, result); - } -} diff --git a/testapp/yaksh_app/java_files/main_fact.java b/testapp/yaksh_app/java_files/main_fact.java deleted file mode 100644 index 325dab6..0000000 --- a/testapp/yaksh_app/java_files/main_fact.java +++ /dev/null @@ -1,29 +0,0 @@ -class main_fact -{ - public static void check(E expect, E result) - { - if(result.equals(expect)) - { - System.out.println("Correct:\nOutput expected "+expect+" and got "+result); - } - else - { - System.out.println("Incorrect:\nOutput expected "+expect+" but got "+result); - System.exit(1); - } - } - public static void main(String arg[]) - { - Test t = new Test(); - int result; - result = t.factorial(0); - System.out.println("Input submitted to the function: 0"); - check(1, result); - result = t.factorial(3); - System.out.println("Input submitted to the function: 3"); - check(6, result); - result = t.factorial(4); - System.out.println("Input submitted to the function: 4"); - check(24, result); - } -} diff --git a/testapp/yaksh_app/java_files/main_great.java b/testapp/yaksh_app/java_files/main_great.java deleted file mode 100644 index 4bfcb1f..0000000 --- a/testapp/yaksh_app/java_files/main_great.java +++ /dev/null @@ -1,39 +0,0 @@ -class main_great -{ - public static void check(E expect, E result) - { - if(result.equals(expect)) - { - System.out.println("Correct:\nOutput expected "+expect+" and got "+result); - } - else - { - System.out.println("Incorrect:\nOutput expected "+expect+" but got "+result); - System.exit(1); - } - } - public static void main(String arg[]) - { - Test t = new Test(); - int result; - result = t.greatest(1, 3, 4); - System.out.println("Input submitted to the function: 1, 3, 4"); - check(4, result); - result = t.greatest(5, 10, 3); - System.out.println("Input submitted to the function: 5, 10, 3"); - check(10, result); - result = t.greatest(6, 1, 4); - System.out.println("Input submitted to the function: 6, 1, 4"); - check(6, result); - result = t.greatest(6, 11, 14); - System.out.println("Input submitted to the function: 6, 11, 14"); - check(14, result); - result = t.greatest(3, 31, 4); - System.out.println("Input submitted to the function: 3, 31, 4"); - check(31, result); - result = t.greatest(26, 13, 3); - System.out.println("Input submitted to the function: 26, 13, 3"); - check(26, result); - - } -} diff --git a/testapp/yaksh_app/java_files/main_hello_name.java b/testapp/yaksh_app/java_files/main_hello_name.java deleted file mode 100644 index 84bb282..0000000 --- a/testapp/yaksh_app/java_files/main_hello_name.java +++ /dev/null @@ -1,29 +0,0 @@ -class main_hello_name -{ - public static void check(E expect, E result) - { - if(result.equals(expect)) - { - System.out.println("Correct:\nOutput expected "+expect+" and got "+result); - } - else - { - System.out.println("Incorrect:\nOutput expected "+expect+" but got "+result); - System.exit(1); - } - } - public static void main(String arg[]) - { - Test t = new Test(); - String result; - result = t.hello_name("Raj"); - System.out.println("Input submitted to the function: 'Raj'"); - check("hello Raj", result); - result = t.hello_name("Pratham"); - System.out.println("Input submitted to the function: 'Pratham'"); - check("hello Pratham", result); - result = t.hello_name("Ram"); - System.out.println("Input submitted to the function: 'Ram'"); - check("hello Ram", result); - } -} diff --git a/testapp/yaksh_app/java_files/main_lastDigit.java b/testapp/yaksh_app/java_files/main_lastDigit.java deleted file mode 100644 index 05439e2..0000000 --- a/testapp/yaksh_app/java_files/main_lastDigit.java +++ /dev/null @@ -1,36 +0,0 @@ -class main_lastDigit -{ - public static void check(E expect, E result) - { - if(result.equals(expect)) - { - System.out.println("Correct:\nOutput expected "+expect+" and got "+result+"\n"); - } - else - { - System.out.println("Incorrect:\nOutput expected "+expect+" but got "+result+"\n"); - System.exit(1); - } - } - public static void main(String arg[]) - { - Test t = new Test(); - boolean result; - result= t.lastDigit(12, 2, 13); - System.out.println("Input submitted to the function: 12, 2, 13"); - check(true, result); - result = t.lastDigit(11, 52, 32); - System.out.println("Input submitted to the function: 11, 52, 32"); - check(true, result); - result = t.lastDigit(6, 34, 22); - System.out.println("Input submitted to the function: 6, 34, 22"); - check(false, result); - result = t.lastDigit(6, 46, 26); - System.out.println("Input submitted to the function: 63"); - check(true, result); - result = t.lastDigit(91, 90, 92); - System.out.println("Input submitted to the function: 91"); - check(false, result); - - } -} diff --git a/testapp/yaksh_app/java_files/main_moreThan30.java b/testapp/yaksh_app/java_files/main_moreThan30.java deleted file mode 100644 index 7da31cb..0000000 --- a/testapp/yaksh_app/java_files/main_moreThan30.java +++ /dev/null @@ -1,36 +0,0 @@ -class main_moreThan30 -{ - public static void check(E expect, E result) - { - if(result.equals(expect)) - { - System.out.println("Correct:\nOutput expected "+expect+" and got "+result+"\n"); - } - else - { - System.out.println("Incorrect:\nOutput expected "+expect+" but got "+result+"\n"); - System.exit(1); - } - } - public static void main(String arg[]) - { - Test t = new Test(); - boolean result; - result= t.moreThan30(30); - System.out.println("Input submitted to the function: 30"); - check(false, result); - result = t.moreThan30(151); - System.out.println("Input submitted to the function: 151"); - check(true, result); - result = t.moreThan30(66); - System.out.println("Input submitted to the function: 66"); - check(false, result); - result = t.moreThan30(63); - System.out.println("Input submitted to the function: 63"); - check(true, result); - result = t.moreThan30(91); - System.out.println("Input submitted to the function: 91"); - check(true, result); - - } -} diff --git a/testapp/yaksh_app/java_files/main_palindrome.java b/testapp/yaksh_app/java_files/main_palindrome.java deleted file mode 100644 index c0745f9..0000000 --- a/testapp/yaksh_app/java_files/main_palindrome.java +++ /dev/null @@ -1,29 +0,0 @@ -class main_palindrome -{ - public static void check(E expect, E result) - { - if(result.equals(expect)) - { - System.out.println("Correct:\nOutput expected "+expect+" and got "+result+"\n"); - } - else - { - System.out.println("Incorrect:\nOutput expected "+expect+" but got "+result+"\n"); - System.exit(1); - } - } - public static void main(String arg[]) - { - Test t = new Test(); - boolean result; - result= t.palindrome(123); - System.out.println("Input submitted to the function: 123"); - check(false, result); - result = t.palindrome(151); - System.out.println("Input submitted to the function: 151"); - check(true, result); - result = t.palindrome(23432); - System.out.println("Input submitted to the function: 23432"); - check(true, result); - } -} diff --git a/testapp/yaksh_app/java_files/main_square.java b/testapp/yaksh_app/java_files/main_square.java deleted file mode 100644 index 5cb8c35..0000000 --- a/testapp/yaksh_app/java_files/main_square.java +++ /dev/null @@ -1,32 +0,0 @@ -class main_square -{ - public static void check(E expect, E result) - { - if(result.equals(expect)) - { - System.out.println("Correct:\nOutput expected "+expect+" and got "+result); - } - else - { - System.out.println("Incorrect:\nOutput expected "+expect+" but got "+result); - System.exit(1); - } - } - public static void main(String arg[]) - { - Test t = new Test(); - int result, input, output; - input = 0; output = 0; - result = t.square_num(input); - System.out.println("Input submitted to the function: "+input); - check(output, result); - input = 5; output = 25; - result = t.square_num(input); - System.out.println("Input submitted to the function: "+input); - check(output, result); - input = 6; output = 36; - result = t.square_num(input); - System.out.println("Input submitted to the function: "+input); - check(output, result); - } -} diff --git a/testapp/yaksh_app/language_registry.py b/testapp/yaksh_app/language_registry.py deleted file mode 100644 index 76a23d7..0000000 --- a/testapp/yaksh_app/language_registry.py +++ /dev/null @@ -1,36 +0,0 @@ -from settings import code_evaluators -import importlib - -registry = None - -def set_registry(): - global registry - registry = _LanguageRegistry() - -def get_registry(): - return registry - -class _LanguageRegistry(object): - def __init__(self): - self._register = {} - for language, module in code_evaluators.iteritems(): - self._register[language] = None - - # Public Protocol ########## - def get_class(self, language): - """ Get the code evaluator class for the given language """ - if not self._register.get(language): - self._register[language] = code_evaluators.get(language) - - cls = self._register[language] - module_name, class_name = cls.rsplit(".", 1) - # load the module, will raise ImportError if module cannot be loaded - get_module = importlib.import_module(module_name) - # get the class, will raise AttributeError if class cannot be found - get_class = getattr(get_module, class_name) - return get_class - - def register(self, language, class_name): - """ Register a new code evaluator class for language""" - self._register[language] = class_name - diff --git a/testapp/yaksh_app/management/__init__.py b/testapp/yaksh_app/management/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/testapp/yaksh_app/management/commands/__init__.py b/testapp/yaksh_app/management/commands/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/testapp/yaksh_app/management/commands/add_group.py b/testapp/yaksh_app/management/commands/add_group.py deleted file mode 100644 index db0ebb6..0000000 --- a/testapp/yaksh_app/management/commands/add_group.py +++ /dev/null @@ -1,33 +0,0 @@ -''' - This command adds moderator group with permissions to add, change and delete - the objects in the exam app. - We can modify this command to add more groups by providing arguments. - Arguments like group-name, app-name can be passed. -''' - -# django imports -from django.core.management.base import BaseCommand, CommandError -from django.contrib.auth.models import Group, Permission -from django.contrib.contenttypes.models import ContentType -from django.db.utils import IntegrityError - -class Command(BaseCommand): - help = 'Adds the moderator group' - - def handle(self, *args, **options): - app = 'yaksh_app' - group = Group(name='moderator') - try: - group.save() - except IntegrityError: - raise CommandError("The group already exits") - else: - # Get the models for the given app - content_types = ContentType.objects.filter(app_label=app) - # Get list of permissions for the models - permission_list = Permission.objects.filter(content_type=content_types) - for permission in permission_list: - group.permissions.add(permission) - group.save() - - self.stdout.write('Moderator group added successfully') diff --git a/testapp/yaksh_app/management/commands/dump_user_data.py b/testapp/yaksh_app/management/commands/dump_user_data.py deleted file mode 100644 index 2c1a108..0000000 --- a/testapp/yaksh_app/management/commands/dump_user_data.py +++ /dev/null @@ -1,98 +0,0 @@ -import sys - -# Django imports. -from django.core.management.base import BaseCommand -from django.template import Template, Context - -# Local imports. -from testapp.yaksh_app.views import get_user_data -from testapp.yaksh_app.models import User - -data_template = Template('''\ -=============================================================================== -Data for {{ data.user.get_full_name.title }} ({{ data.user.username }}) - -Name: {{ data.user.get_full_name.title }} -Username: {{ data.user.username }} -{% if data.profile %}\ -Roll number: {{ data.profile.roll_number }} -Position: {{ data.profile.position }} -Department: {{ data.profile.department }} -Institute: {{ data.profile.institute }} -{% endif %}\ -Email: {{ data.user.email }} -Date joined: {{ data.user.date_joined }} -Last login: {{ data.user.last_login }} -{% for paper in data.papers %} -Paper: {{ paper.quiz.description }} ---------------------------------------- -Marks obtained: {{ paper.get_total_marks }} -Questions correctly answered: {{ paper.get_answered_str }} -Total attempts at questions: {{ paper.answers.count }} -Start time: {{ paper.start_time }} -User IP address: {{ paper.user_ip }} -{% if paper.answers.count %} -Answers -------- -{% for question, answers in paper.get_question_answers.items %} -Question: {{ question.id }}. {{ question.summary }} (Points: {{ question.points }}) -{% if question.type == "mcq" %}\ -############################################################################### -Choices: {% for option in question.options.strip.splitlines %} {{option}}, {% endfor %} -Student answer: {{ answers.0|safe }} -{% else %}{# non-mcq questions #}\ -{% for answer in answers %}\ -############################################################################### -{{ answer.answer.strip|safe }} -# Autocheck: {{ answer.error|safe }} -{% endfor %}{# for answer in answers #}\ -{% endif %}\ -{% with answers|last as answer %}\ -Marks: {{answer.marks}} -{% endwith %}\ -{% endfor %}{# for question, answers ... #}\ - -Teacher comments ------------------ -{{ paper.comments|default:"None" }} -{% endif %}{# if paper.answers.count #}\ -{% endfor %}{# for paper in data.papers #} -''') - - -def dump_user_data(unames, stdout): - '''Dump user data given usernames (a sequence) if none is given dump all - their data. The data is dumped to stdout. - ''' - if not unames: - try: - users = User.objects.all() - except User.DoesNotExist: - pass - else: - users = [] - for uname in unames: - try: - user = User.objects.get(username__exact = uname) - except User.DoesNotExist: - stdout.write('User %s does not exist'%uname) - else: - users.append(user) - - for user in users: - data = get_user_data(user.username) - context = Context({'data': data}) - result = data_template.render(context) - stdout.write(result.encode('ascii', 'xmlcharrefreplace')) - -class Command(BaseCommand): - args = ' ... ' - help = '''Dumps all user data to stdout, optional usernames can be - specified. If none is specified all user data is dumped. - ''' - - def handle(self, *args, **options): - """Handle the command.""" - # Dump data. - dump_user_data(args, self.stdout) - diff --git a/testapp/yaksh_app/management/commands/load_exam.py b/testapp/yaksh_app/management/commands/load_exam.py deleted file mode 100644 index 9163fdc..0000000 --- a/testapp/yaksh_app/management/commands/load_exam.py +++ /dev/null @@ -1,57 +0,0 @@ -# System library imports. -from os.path import basename - -# Django imports. -from django.core.management.base import BaseCommand - -# Local imports. -from testapp.yaksh_app.models import Question, Quiz - -def clear_exam(): - """Deactivate all questions from the database.""" - for question in Question.objects.all(): - question.active = False - question.save() - - # Deactivate old quizzes. - for quiz in Quiz.objects.all(): - quiz.active = False - quiz.save() - -def load_exam(filename): - """Load questions and quiz from the given Python file. The Python file - should declare a list of name "questions" which define all the questions - in pure Python. It can optionally load a Quiz from an optional 'quiz' - object. - """ - # Simply exec the given file and we are done. - exec(open(filename).read()) - - if 'questions' not in locals(): - msg = 'No variable named "questions" with the Questions in file.' - raise NameError(msg) - - for question in questions: - question[0].save() - for tag in question[1]: - question[0].tags.add(tag) - - if 'quiz' in locals(): - quiz.save() - -class Command(BaseCommand): - args = ' ' - help = '''loads the questions from given Python files which declare the - questions in a list called "questions".''' - - def handle(self, *args, **options): - """Handle the command.""" - # Delete existing stuff. - clear_exam() - - # Load from files. - for fname in args: - self.stdout.write('Importing from {0} ... '.format(basename(fname))) - load_exam(fname) - self.stdout.write('Done\n') - diff --git a/testapp/yaksh_app/management/commands/load_questions_xml.py b/testapp/yaksh_app/management/commands/load_questions_xml.py deleted file mode 100644 index 7bde9e9..0000000 --- a/testapp/yaksh_app/management/commands/load_questions_xml.py +++ /dev/null @@ -1,73 +0,0 @@ -# System library imports. -from os.path import basename -from xml.dom.minidom import parse -from htmlentitydefs import name2codepoint -import re - -# Django imports. -from django.core.management.base import BaseCommand - -# Local imports. -from testapp.yaksh_app.models import Question - -def decode_html(html_str): - """Un-escape or decode HTML strings to more usable Python strings. - From here: http://wiki.python.org/moin/EscapingHtml - """ - return re.sub('&(%s);' % '|'.join(name2codepoint), - lambda m: unichr(name2codepoint[m.group(1)]), html_str) - -def clear_questions(): - """Deactivate all questions from the database.""" - for question in Question.objects.all(): - question.active = False - question.save() - -def load_questions_xml(filename): - """Load questions from the given XML file.""" - q_bank = parse(filename).getElementsByTagName("question") - - for question in q_bank: - - summary_node = question.getElementsByTagName("summary")[0] - summary = (summary_node.childNodes[0].data).strip() - - desc_node = question.getElementsByTagName("description")[0] - description = (desc_node.childNodes[0].data).strip() - - type_node = question.getElementsByTagName("type")[0] - type = (type_node.childNodes[0].data).strip() - - points_node = question.getElementsByTagName("points")[0] - points = float((points_node.childNodes[0].data).strip()) \ - if points_node else 1.0 - - test_node = question.getElementsByTagName("test")[0] - test = decode_html((test_node.childNodes[0].data).strip()) - - opt_node = question.getElementsByTagName("options")[0] - opt = decode_html((opt_node.childNodes[0].data).strip()) - - new_question = Question(summary=summary, - description=description, - points=points, - options=opt, - type=type, - test=test) - new_question.save() - -class Command(BaseCommand): - args = ' ' - help = 'loads the questions from given XML files' - - def handle(self, *args, **options): - """Handle the command.""" - # Delete existing stuff. - clear_questions() - - # Load from files. - for fname in args: - self.stdout.write('Importing from {0} ... '.format(basename(fname))) - load_questions_xml(fname) - self.stdout.write('Done\n') - diff --git a/testapp/yaksh_app/management/commands/results2csv.py b/testapp/yaksh_app/management/commands/results2csv.py deleted file mode 100644 index c9b05ce..0000000 --- a/testapp/yaksh_app/management/commands/results2csv.py +++ /dev/null @@ -1,69 +0,0 @@ -# System library imports. -import sys -from os.path import basename - -# Django imports. -from django.core.management.base import BaseCommand -from django.template import Template, Context - -# Local imports. -from testapp.yaksh_app.models import Quiz, QuestionPaper - -result_template = Template('''\ -"name","username","rollno","email","answered","total","attempts","position",\ -"department","institute" -{% for paper in papers %}\ -"{{ paper.user.get_full_name.title }}",\ -"{{ paper.user.username }}",\ -"{{ paper.profile.roll_number }}",\ -"{{ paper.user.email }}",\ -"{{ paper.get_answered_str }}",\ -{{ paper.get_total_marks }},\ -{{ paper.answers.count }},\ -"{{ paper.profile.position }}",\ -"{{ paper.profile.department }}",\ -"{{ paper.profile.institute }}" -{% endfor %}\ -''') - -def results2csv(filename, stdout): - """Write exam data to a CSV file. It prompts the user to choose the - appropriate quiz. - """ - qs = Quiz.objects.all() - - if len(qs) > 1: - print "Select quiz to save:" - for q in qs: - stdout.write('%d. %s\n'%(q.id, q.description)) - quiz_id = int(raw_input("Please select quiz: ")) - try: - quiz = Quiz.objects.get(id=quiz_id) - except Quiz.DoesNotExist: - stdout.write("Sorry, quiz %d does not exist!\n"%quiz_id) - sys.exit(1) - else: - quiz = qs[0] - - papers = QuestionPaper.objects.filter(quiz=quiz, - user__profile__isnull=False) - stdout.write("Saving results of %s to %s ... "%(quiz.description, - basename(filename))) - # Render the data and write it out. - f = open(filename, 'w') - context = Context({'papers': papers}) - f.write(result_template.render(context)) - f.close() - - stdout.write('Done\n') - -class Command(BaseCommand): - args = ' ' - help = '''Writes out the results of a quiz to a CSV file. Prompt user - to select appropriate quiz if there are multiple. - ''' - - def handle(self, *args, **options): - """Handle the command.""" - # Save to file. - results2csv(args[0], self.stdout) diff --git a/testapp/yaksh_app/models.py b/testapp/yaksh_app/models.py deleted file mode 100644 index 62ac9bc..0000000 --- a/testapp/yaksh_app/models.py +++ /dev/null @@ -1,471 +0,0 @@ -import datetime -import json -from random import sample, shuffle -from itertools import islice, cycle -from django.db import models -from django.contrib.auth.models import User -from taggit.managers import TaggableManager - - -############################################################################### -class Profile(models.Model): - """Profile for a user to store roll number and other details.""" - user = models.OneToOneField(User) - roll_number = models.CharField(max_length=20) - institute = models.CharField(max_length=128) - department = models.CharField(max_length=64) - position = models.CharField(max_length=64) - - -languages = ( - ("python", "Python"), - ("bash", "Bash"), - ("c", "C Language"), - ("cpp", "C++ Language"), - ("java", "Java Language"), - ("scilab", "Scilab"), - ) - - -question_types = ( - ("mcq", "Multiple Choice"), - ("mcc", "Multiple Correct Choices"), - ("code", "Code"), - ("upload", "Assignment Upload"), - ) -attempts = [(i, i) for i in range(1, 6)] -attempts.append((-1, 'Infinite')) -days_between_attempts = ((j, j) for j in range(401)) - -test_status = ( - ('inprogress', 'Inprogress'), - ('completed', 'Completed'), - ) - - -def get_assignment_dir(instance, filename): - return '%s/%s' % (instance.user.roll_number, instance.assignmentQuestion.id) - - -############################################################################### -class Question(models.Model): - """Question for a quiz.""" - - # A one-line summary of the question. - summary = models.CharField(max_length=256) - - # The question text, should be valid HTML. - description = models.TextField() - - # Number of points for the question. - points = models.FloatField(default=1.0) - - # Answer for MCQs. - test = models.TextField(blank=True) - - # Test cases file paths (comma seperated for reference code path and test case code path) - # Applicable for CPP, C, Java and Scilab - ref_code_path = models.TextField(blank=True) - - # Any multiple choice options. Place one option per line. - options = models.TextField(blank=True) - - # The language for question. - language = models.CharField(max_length=24, - choices=languages) - - # The type of question. - type = models.CharField(max_length=24, choices=question_types) - - # Is this question active or not. If it is inactive it will not be used - # when creating a QuestionPaper. - active = models.BooleanField(default=True) - - # Snippet of code provided to the user. - snippet = models.CharField(max_length=256) - - # Tags for the Question. - tags = TaggableManager() - - def consolidate_answer_data(self, test_cases, user_answer): - test_case_data_dict = [] - question_info_dict = {} - - for test_case in test_cases: - kw_args_dict = {} - pos_args_list = [] - - test_case_data = {} - test_case_data['test_id'] = test_case.id - test_case_data['func_name'] = test_case.func_name - test_case_data['expected_answer'] = test_case.expected_answer - - if test_case.kw_args: - for args in test_case.kw_args.split(","): - arg_name, arg_value = args.split("=") - kw_args_dict[arg_name.strip()] = arg_value.strip() - - if test_case.pos_args: - for args in test_case.pos_args.split(","): - pos_args_list.append(args.strip()) - - test_case_data['kw_args'] = kw_args_dict - test_case_data['pos_args'] = pos_args_list - test_case_data_dict.append(test_case_data) - - # question_info_dict['language'] = self.language - question_info_dict['id'] = self.id - question_info_dict['user_answer'] = user_answer - question_info_dict['test_parameter'] = test_case_data_dict - question_info_dict['ref_code_path'] = self.ref_code_path - question_info_dict['test'] = self.test - - return json.dumps(question_info_dict) - - def __unicode__(self): - return self.summary - - -############################################################################### -class Answer(models.Model): - """Answers submitted by the users.""" - - # The question for which user answers. - question = models.ForeignKey(Question) - - # The answer submitted by the user. - answer = models.TextField(null=True, blank=True) - - # Error message when auto-checking the answer. - error = models.TextField() - - # Marks obtained for the answer. This can be changed by the teacher if the - # grading is manual. - marks = models.FloatField(default=0.0) - - # Is the answer correct. - correct = models.BooleanField(default=False) - - # Whether skipped or not. - skipped = models.BooleanField(default=False) - - def __unicode__(self): - return self.answer - - -############################################################################### -class Quiz(models.Model): - """A quiz that students will participate in. One can think of this - as the "examination" event. - """ - - # The start date of the quiz. - start_date_time = models.DateTimeField("Start Date and Time of the quiz", - default=datetime.datetime.now(), - null=True) - - # The end date and time of the quiz - end_date_time = models.DateTimeField("End Date and Time of the quiz", - default=datetime.datetime(2199, 1, 1, 0, 0, 0, 0), - null=True) - - # This is always in minutes. - duration = models.IntegerField("Duration of quiz in minutes", default=20) - - # Is the quiz active. The admin should deactivate the quiz once it is - # complete. - active = models.BooleanField(default=True) - - # Description of quiz. - description = models.CharField(max_length=256) - - # Mininum passing percentage condition. - pass_criteria = models.FloatField("Passing percentage", default=40) - - # List of prerequisite quizzes to be passed to take this quiz - prerequisite = models.ForeignKey("Quiz", null=True) - - # Programming language for a quiz - language = models.CharField(max_length=20, choices=languages) - - # Number of attempts for the quiz - attempts_allowed = models.IntegerField(default=1, choices=attempts) - - time_between_attempts = models.IntegerField("Number of Days",\ - choices=days_between_attempts) - - class Meta: - verbose_name_plural = "Quizzes" - - def __unicode__(self): - desc = self.description or 'Quiz' - return '%s: on %s for %d minutes' % (desc, self.start_date_time, - self.duration) - - -############################################################################### -class QuestionPaper(models.Model): - """Question paper stores the detail of the questions.""" - - # Question paper belongs to a particular quiz. - quiz = models.ForeignKey(Quiz) - - # Questions that will be mandatory in the quiz. - fixed_questions = models.ManyToManyField(Question) - - # Questions that will be fetched randomly from the Question Set. - random_questions = models.ManyToManyField("QuestionSet") - - # Option to shuffle questions, each time a new question paper is created. - shuffle_questions = models.BooleanField(default=False) - - # Total marks for the question paper. - total_marks = models.FloatField() - - def update_total_marks(self): - """ Updates the total marks for the Question Paper""" - marks = 0.0 - questions = self.fixed_questions.all() - for question in questions: - marks += question.points - for question_set in self.random_questions.all(): - marks += question_set.marks * question_set.num_questions - self.total_marks = marks - - def _get_questions_for_answerpaper(self): - """ Returns fixed and random questions for the answer paper""" - questions = [] - questions = list(self.fixed_questions.all()) - for question_set in self.random_questions.all(): - questions += question_set.get_random_questions() - return questions - - def make_answerpaper(self, user, ip, attempt_num): - """Creates an answer paper for the user to attempt the quiz""" - ans_paper = AnswerPaper(user=user, user_ip=ip, attempt_number=attempt_num) - ans_paper.start_time = datetime.datetime.now() - ans_paper.end_time = ans_paper.start_time \ - + datetime.timedelta(minutes=self.quiz.duration) - ans_paper.question_paper = self - questions = self._get_questions_for_answerpaper() - question_ids = [str(x.id) for x in questions] - if self.shuffle_questions: - shuffle(question_ids) - ans_paper.questions = "|".join(question_ids) - ans_paper.save() - return ans_paper - - -############################################################################### -class QuestionSet(models.Model): - """Question set contains a set of questions from which random questions - will be selected for the quiz. - """ - - # Marks of each question of a particular Question Set - marks = models.FloatField() - - # Number of questions to be fetched for the quiz. - num_questions = models.IntegerField() - - # Set of questions for sampling randomly. - questions = models.ManyToManyField(Question) - - def get_random_questions(self): - """ Returns random questions from set of questions""" - return sample(self.questions.all(), self.num_questions) - - -############################################################################### -class AnswerPaper(models.Model): - """A answer paper for a student -- one per student typically. - """ - # The user taking this question paper. - user = models.ForeignKey(User) - - # All questions that remain to be attempted for a particular Student - # (a list of ids separated by '|') - questions = models.CharField(max_length=128) - - # The Quiz to which this question paper is attached to. - question_paper = models.ForeignKey(QuestionPaper) - - # The attempt number for the question paper. - attempt_number = models.IntegerField() - - # The time when this paper was started by the user. - start_time = models.DateTimeField() - - # The time when this paper was ended by the user. - end_time = models.DateTimeField() - - # User's IP which is logged. - user_ip = models.CharField(max_length=15) - - # The questions successfully answered (a list of ids separated by '|') - questions_answered = models.CharField(max_length=128) - - # All the submitted answers. - answers = models.ManyToManyField(Answer) - - # Teacher comments on the question paper. - comments = models.TextField() - - # Total marks earned by the student in this paper. - marks_obtained = models.FloatField(null=True, default=None) - - # Marks percent scored by the user - percent = models.FloatField(null=True, default=None) - - # Result of the quiz, True if student passes the exam. - passed = models.NullBooleanField() - - # Status of the quiz attempt - status = models.CharField(max_length=20, choices=test_status,\ - default='inprogress') - - def current_question(self): - """Returns the current active question to display.""" - qu = self.get_unanswered_questions() - if len(qu) > 0: - return qu[0] - else: - return '' - - def questions_left(self): - """Returns the number of questions left.""" - qu = self.get_unanswered_questions() - return len(qu) - - def get_unanswered_questions(self): - """Returns the list of unanswered questions.""" - qa = self.questions_answered.split('|') - qs = self.questions.split('|') - qu = [q for q in qs if q not in qa] - return qu - - def completed_question(self, question_id): - """ - Adds the completed question to the list of answered - questions and returns the next question. - """ - qa = self.questions_answered - if len(qa) > 0: - self.questions_answered = '|'.join([qa, str(question_id)]) - else: - self.questions_answered = str(question_id) - self.save() - - return self.skip(question_id) - - def skip(self, question_id): - """ - Skips the current question and returns the next sequentially - available question. - """ - qu = self.get_unanswered_questions() - qs = self.questions.split('|') - - if len(qu) == 0: - return '' - - try: - q_index = qs.index(unicode(question_id)) - except ValueError: - return qs[0] - - start = q_index + 1 - stop = q_index + 1 + len(qs) - q_list = islice(cycle(qs), start, stop) - for next_q in q_list: - if next_q in qu: - return next_q - - return qs[0] - - def time_left(self): - """Return the time remaining for the user in seconds.""" - dt = datetime.datetime.now() - self.start_time.replace(tzinfo=None) - try: - secs = dt.total_seconds() - except AttributeError: - # total_seconds is new in Python 2.7. :( - secs = dt.seconds + dt.days*24*3600 - total = self.question_paper.quiz.duration*60.0 - remain = max(total - secs, 0) - return int(remain) - - def get_answered_str(self): - """Returns the answered questions, sorted and as a nice string.""" - qa = self.questions_answered.split('|') - answered = ', '.join(sorted(qa)) - return answered if answered else 'None' - - def update_marks_obtained(self): - """Updates the total marks earned by student for this paper.""" - marks = sum([x.marks for x in self.answers.filter(marks__gt=0.0)]) - self.marks_obtained = marks - - def update_percent(self): - """Updates the percent gained by the student for this paper.""" - total_marks = self.question_paper.total_marks - if self.marks_obtained is not None: - percent = self.marks_obtained/self.question_paper.total_marks*100 - self.percent = round(percent, 2) - - def update_passed(self): - """ - Checks whether student passed or failed, as per the quiz - passing criteria. - """ - if self.percent is not None: - if self.percent >= self.question_paper.quiz.pass_criteria: - self.passed = True - else: - self.passed = False - - def update_status(self): - """ Sets status to completed """ - self.status = 'completed' - - def get_question_answers(self): - """ - Return a dictionary with keys as questions and a list of the - corresponding answers. - """ - q_a = {} - for answer in self.answers.all(): - question = answer.question - if question in q_a: - q_a[question].append(answer) - else: - q_a[question] = [answer] - return q_a - - def __unicode__(self): - u = self.user - return u'Question paper for {0} {1}'.format(u.first_name, u.last_name) - - -############################################################################### -class AssignmentUpload(models.Model): - user = models.ForeignKey(Profile) - assignmentQuestion = models.ForeignKey(Question) - assignmentFile = models.FileField(upload_to=get_assignment_dir) - - -################################################################################ -class TestCase(models.Model): - question = models.ForeignKey(Question, blank=True, null = True) - - # Test case function name - func_name = models.CharField(blank=True, null = True, max_length=200) - - # Test case Keyword arguments in dict form - kw_args = models.TextField(blank=True, null = True) - - # Test case Positional arguments in list form - pos_args = models.TextField(blank=True, null = True) - - # Test case Expected answer in list form - expected_answer = models.TextField(blank=True, null = True) diff --git a/testapp/yaksh_app/output/README.txt b/testapp/yaksh_app/output/README.txt deleted file mode 100644 index 3163ed4..0000000 --- a/testapp/yaksh_app/output/README.txt +++ /dev/null @@ -1,4 +0,0 @@ -This directory contains files generated/saved by users as per their -username. The test executor will chdir into this user directory for each -user when they run the test. Do not delete this directory and ensure that -it is writeable by all. \ No newline at end of file diff --git a/testapp/yaksh_app/python_code_evaluator.py b/testapp/yaksh_app/python_code_evaluator.py deleted file mode 100644 index 0c473cf..0000000 --- a/testapp/yaksh_app/python_code_evaluator.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env python -import sys -import traceback -import os -from os.path import join -import importlib - -# local imports -from code_evaluator import CodeEvaluator - - -class PythonCodeEvaluator(CodeEvaluator): - """Tests the Python code obtained from Code Server""" - # Private Protocol ########## - def _check_code(self): - success = False - - try: - tb = None - test_code = self._create_test_case() - submitted = compile(self.user_answer, ' ', mode='exec') - g = {} - exec submitted in g - _tests = compile(test_code, ' ', mode='exec') - exec _tests in g - except AssertionError: - type, value, tb = sys.exc_info() - info = traceback.extract_tb(tb) - fname, lineno, func, text = info[-1] - text = str(test_code).splitlines()[lineno-1] - err = "{0} {1} in: {2}".format(type.__name__, str(value), text) - else: - success = True - err = 'Correct answer' - - del tb - return success, err - - def _create_test_case(self): - """ - Create assert based test cases in python - """ - test_code = "" - if self.test: - return self.test - elif self.test_case_data: - for test_case in self.test_case_data: - pos_args = ", ".join(str(i) for i in test_case.get('pos_args')) \ - if test_case.get('pos_args') else "" - kw_args = ", ".join(str(k+"="+a) for k, a - in test_case.get('kw_args').iteritems()) \ - if test_case.get('kw_args') else "" - args = pos_args + ", " + kw_args if pos_args and kw_args \ - else pos_args or kw_args - function_name = test_case.get('func_name') - expected_answer = test_case.get('expected_answer') - - tcode = "assert {0}({1}) == {2}".format(function_name, args, - expected_answer) - test_code += tcode + "\n" - return test_code diff --git a/testapp/yaksh_app/scilab_code_evaluator.py b/testapp/yaksh_app/scilab_code_evaluator.py deleted file mode 100644 index 392cd45..0000000 --- a/testapp/yaksh_app/scilab_code_evaluator.py +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env python -import traceback -import os -from os.path import join, isfile -import subprocess -import re -import importlib - -# local imports -from code_evaluator import CodeEvaluator - - -class ScilabCodeEvaluator(CodeEvaluator): - """Tests the Scilab code obtained from Code Server""" - def __init__(self, test_case_data, test, language, user_answer, - ref_code_path=None, in_dir=None): - super(ScilabCodeEvaluator, self).__init__(test_case_data, test, - language, user_answer, - ref_code_path, in_dir) - - # Removes all the commands that terminates scilab - self.user_answer, self.terminate_commands = self._remove_scilab_exit(user_answer.lstrip()) - self.test_case_args = self._setup() - - # Private Protocol ########## - def _setup(self): - super(ScilabCodeEvaluator, self)._setup() - - ref_path, test_case_path = self._set_test_code_file_path(self.ref_code_path) - self.submit_path = self.create_submit_code_file('function.sci') - - return ref_path, # Return as a tuple - - def _teardown(self): - # Delete the created file. - super(ScilabCodeEvaluator, self)._teardown() - os.remove(self.submit_path) - - def _check_code(self, ref_path): - success = False - - # Throw message if there are commmands that terminates scilab - add_err="" - if self.terminate_commands: - add_err = "Please do not use exit, quit and abort commands in your\ - code.\n Otherwise your code will not be evaluated\ - correctly.\n" - - cmd = 'printf "lines(0)\nexec(\'{0}\',2);\nquit();"'.format(ref_path) - cmd += ' | timeout 8 scilab-cli -nb' - ret = self._run_command(cmd, - shell=True, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - proc, stdout, stderr = ret - - # Get only the error. - stderr = self._get_error(stdout) - if stderr is None: - # Clean output - stdout = self._strip_output(stdout) - if proc.returncode == 5: - success, err = True, "Correct answer" - else: - err = add_err + stdout - else: - err = add_err + stderr - - return success, err - - def _remove_scilab_exit(self, string): - """ - Removes exit, quit and abort from the scilab code - """ - new_string = "" - terminate_commands = False - for line in string.splitlines(): - new_line = re.sub(r"exit.*$", "", line) - new_line = re.sub(r"quit.*$", "", new_line) - new_line = re.sub(r"abort.*$", "", new_line) - if line != new_line: - terminate_commands = True - new_string = new_string + '\n' + new_line - return new_string, terminate_commands - - def _get_error(self, string): - """ - Fetches only the error from the string. - Returns None if no error. - """ - obj = re.search("!.+\n.+", string) - if obj: - return obj.group() - return None - - def _strip_output(self, out): - """ - Cleans whitespace from the output - """ - strip_out = "Message" - for l in out.split('\n'): - if l.strip(): - strip_out = strip_out+"\n"+l.strip() - return strip_out - diff --git a/testapp/yaksh_app/scilab_files/test_add.sce b/testapp/yaksh_app/scilab_files/test_add.sce deleted file mode 100644 index a317cdb..0000000 --- a/testapp/yaksh_app/scilab_files/test_add.sce +++ /dev/null @@ -1,29 +0,0 @@ -mode(-1) -exec("function.sci",-1); -i = 0 -p = add(3,5); -correct = (p == 8); -if correct then - i=i+1 -end -disp("Input submitted 3 and 5") -disp("Expected output 8 got " + string(p)) -p = add(22,-20); -correct = (p==2); -if correct then - i=i+1 -end -disp("Input submitted 22 and -20") -disp("Expected output 2 got " + string(p)) -p =add(91,0); -correct = (p==91); -if correct then - i=i+1 -end -disp("Input submitted 91 and 0") -disp("Expected output 91 got " + string(p)) -if i==3 then - exit(5); -else - exit(3); -end diff --git a/testapp/yaksh_app/settings.py b/testapp/yaksh_app/settings.py deleted file mode 100644 index 9039250..0000000 --- a/testapp/yaksh_app/settings.py +++ /dev/null @@ -1,29 +0,0 @@ -""" -settings for yaksh_app app. -""" -# The ports the code server should run on. This will run one separate -# server for each port listed in the following list. -SERVER_PORTS = [8001] # range(8001, 8026) - -# The server pool port. This is the server which returns available server -# ports so as to minimize load. This is some random number where no other -# service is running. It should be > 1024 and less < 65535 though. -SERVER_POOL_PORT = 53579 - -# Timeout for the code to run in seconds. This is an integer! -SERVER_TIMEOUT = 2 - -# The root of the URL, for example you might be in the situation where you -# are not hosted as host.org/exam/ but as host.org/foo/exam/ for whatever -# reason set this to the root you have to serve at. In the above example -# host.org/foo/exam set URL_ROOT='/foo' -URL_ROOT = '' - -code_evaluators = { - "python": "python_code_evaluator.PythonCodeEvaluator", - "c": "c_cpp_code_evaluator.CCPPCodeEvaluator", - "cpp": "c_cpp_code_evaluator.CCPPCodeEvaluator", - "java": "java_code_evaluator.JavaCodeEvaluator", - "bash": "bash_code_evaluator.BashCodeEvaluator", - "scilab": "scilab_code_evaluator.ScilabCodeEvaluator", - } diff --git a/testapp/yaksh_app/static/yaksh_app/css/autotaggit.css b/testapp/yaksh_app/static/yaksh_app/css/autotaggit.css deleted file mode 100644 index ed856ce..0000000 --- a/testapp/yaksh_app/static/yaksh_app/css/autotaggit.css +++ /dev/null @@ -1,48 +0,0 @@ -.ac_results { - padding: 0px; - border: 1px solid #efefef; - background-color: white; - overflow: hidden; - z-index: 99999; -} - -.ac_results ul { - width: 100%; - list-style-position: outside; - list-style: none; - padding: 0; - margin: 0; -} - -.ac_results li { - margin: 0px; - padding: 2px 5px; - cursor: default; - display: block; - /* - if width will be 100% horizontal scrollbar will apear - when scroll mode will be used - */ - /*width: 100%;*/ - font: menu; - font-size: 12px; - /* - it is very important, if line-height not setted or setted - in relative units scroll will be broken in firefox - */ - line-height: 16px; - overflow: hidden; -} - -.ac_loading { - background: white url('indicator.gif') right center no-repeat; -} - -.ac_odd { - background-color: #CACACA; -} - -.ac_over { - background-color: #f5f5f5; - color: black; -} diff --git a/testapp/yaksh_app/static/yaksh_app/css/base.css b/testapp/yaksh_app/static/yaksh_app/css/base.css deleted file mode 100644 index 3570098..0000000 --- a/testapp/yaksh_app/static/yaksh_app/css/base.css +++ /dev/null @@ -1,2327 +0,0 @@ -/*! -Copyright 2012 Twitter, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with the License. You may obtain a copy of the License in the LICENSE file, or at: - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - - * Bootstrap v1.4.0 - * - * Copyright 2011 Twitter, Inc - * Licensed under the Apache License v2.0 - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Designed and built with all the love in the world @twitter by @mdo and @fat. - * Date: Sun Dec 25 20:18:31 PST 2011 - */ -/* Reset.less - * Props to Eric Meyer (meyerweb.com) for his CSS reset file. We're using an adapted version here that cuts out some of the reset HTML elements we will never need here (i.e., dfn, samp, etc). - * For Online Test Application, this CSS was changed as per the requirements wherever required. ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */ - -html, body { - background-color: #eee; - margin: 0; - padding: 0; - -} -h1, -h2, -h3, -h4, -h5, -h6, -p, -blockquote, -pre, -a, -abbr, -acronym, -address, -cite, -code, -del, -dfn, -em, -img, -q, -s, -samp, -small, -strike, -strong, -sub, -sup, -tt, -var, -dd, -dl, -dt, -li, -ol, -ul, -fieldset, -form, -label, -legend, -button, -table, -caption, -tbody, -tfoot, -thead, -tr, -th, -td { - margin: 0; - padding: 0; - border: 0; - font-weight: normal; - font-style: normal; - font-size: 100%; - line-height: 1; - font-family: serif; -} -table { - border-collapse: collapse; - border-spacing: 0; -} -ol, ul { - list-style: none; -} -q:before, -q:after, -blockquote:before, -blockquote:after { - content: ""; -} -html { - overflow-y: scroll; - font-size: 100%; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} -a:focus { - outline: thin dotted; -} -a:hover, a:active { - outline: 0; -} -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -nav, -section { - display: block; -} -audio, canvas, video { - display: inline-block; - *display: inline; - *zoom: 1; -} -audio:not([controls]) { - display: none; -} -sub, sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} -sup { - top: -0.5em; -} -sub { - bottom: -0.25em; -} -img { - border: 0; - -ms-interpolation-mode: bicubic; -} -button, -input, -select, -textarea { - font-size: 100%; - margin: 0; - vertical-align: baseline; - *vertical-align: middle; -} -button, input { - line-height: normal; - *overflow: visible; -} -button::-moz-focus-inner, input::-moz-focus-inner { - border: 0; - padding: 0; -} -button, -input[type="button"], -input[type="reset"], -input[type="submit"] { - cursor: pointer; - -webkit-appearance: button; -} -input[type="search"] { - -webkit-appearance: textfield; - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; -} -input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} -textarea { - overflow: visible; - vertical-align: top; -} -/* Variables.less -* Variables to customize the look and feel of Bootstrap -* ----------------------------------------------------- */ -/* Mixins.less -* Snippets of reusable CSS to develop faster and keep code readable -* ----------------------------------------------------------------- */ -/* -* Scaffolding -* Basic and global styles for generating a grid system, structural layout, and page templates -* ------------------------------------------------------------------------------------------- */ -body { - padding-top : 10px; - background-color: #eee; - margin: 0; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 13px; - font-weight: normal; - line-height: 18px; - color: #404040; - -} -.container { - width: 820px; - margin-left: auto; - margin-right: auto; - zoom: 1; -} -.container > footer p { - text-align: center; -} -.container > .content { - background-color: #fff; - padding: 20px; - margin: 0 -20px; - -webkit-border-radius: 0 0 6px 6px; - -moz-border-radius: 0 0 6px 6px; - border-radius: 0 0 6px 6px; - -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.15); - -moz-box-shadow: 0 1px 2px rgba(0,0,0,.15); - box-shadow: 0 1px 2px rgba(0,0,0,.15); -} -.content .span10, -.content .span14 { - min-height: 475px; -} -.content .span4 { - margin-left: 0; - padding-left: 19px; - border-left: 1px solid #eee; -} -.topbar .btn { - border: 0; -} -.page-header { - background-color: #f5f5f5; - padding: 20px 20px 10px; - margin: -20px -20px 20px; -} -.container:before, .container:after { - display: table; - content: ""; - zoom: 1; -} -.container:after { - clear: both; -} -.container-fluid { - position: relative; - min-width: 940px; - padding-left: 20px; - padding-right: 20px; - zoom: 1; -} -.container-fluid:before, .container-fluid:after { - display: table; - content: ""; - zoom: 1; -} -.container-fluid:after { - clear: both; -} -.container-fluid > .sidebar { - position: absolute; - top: 0; - left: 20px; - width: 220px; -} -.container-fluid > .content { - margin-left: 240px; -} -a { - color: #0069d6; - text-decoration: none; - line-height: inherit; - font-weight: inherit; -} -a:hover { - color: #00438a; - text-decoration: underline; -} -.pull-right { - float: right; -} -.pull-left { - float: left; -} -.hide { - display: none; -} -.show { - display: block; -} -.row { - zoom: 1; - margin-left: -20px; -} -.row:before, .row:after { - display: table; - content: ""; - zoom: 1; -} -.row:after { - clear: both; -} -.row > [class*="span"] { - display: inline; - float: left; - margin-left: 20px; -} -.span1 { - width: 40px; -} -.span2 { - width: 100px; -} -.span3 { - width: 160px; -} -.span4 { - width: 220px; -} -.span5 { - width: 280px; -} -.span6 { - width: 340px; -} -.span7 { - width: 400px; -} -.span8 { - width: 460px; -} -.span9 { - width: 520px; -} -.span10 { - width: 560px; -} -.span11 { - width: 640px; -} -.span12 { - width: 700px; -} -.span13 { - width: 760px; -} -.span14 { - width: 820px; -} -.span15 { - width: 880px; -} -.span16 { - width: 940px; -} -.span17 { - width: 1000px; -} -.span18 { - width: 1060px; -} -.span19 { - width: 1120px; -} -.span20 { - width: 1180px; -} -.span21 { - width: 1240px; -} -.span22 { - width: 1300px; -} -.span23 { - width: 1360px; -} -.span24 { - width: 1420px; -} -.row > .offset1 { - margin-left: 80px; -} -.row > .offset2 { - margin-left: 140px; -} -.row > .offset3 { - margin-left: 200px; -} -.row > .offset4 { - margin-left: 260px; -} -.row > .offset5 { - margin-left: 320px; -} -.row > .offset6 { - margin-left: 380px; -} -.row > .offset7 { - margin-left: 440px; -} -.row > .offset8 { - margin-left: 500px; -} -.row > .offset9 { - margin-left: 560px; -} -.row > .offset10 { - margin-left: 620px; -} -.row > .offset11 { - margin-left: 680px; -} -.row > .offset12 { - margin-left: 740px; -} -.span-one-third { - width: 300px; -} -.span-two-thirds { - width: 620px; -} -.row > .offset-one-third { - margin-left: 340px; -} -.row > .offset-two-thirds { - margin-left: 660px; -} -/* Typography.less -* Headings, body text, lists, code, and more for a versatile and durable typography system -* ---------------------------------------------------------------------------------------- */ -p { - font-size: 13px; - font-weight: normal; - line-height: 18px; - margin-bottom: 9px; -} -p small { - font-size: 11px; - color: #bfbfbf; -} -h1, -h2, -h3, -h4, -h5, -h6 { - font-weight: bold; - color: #404040; -} -h1 small, -h2 small, -h3 small, -h4 small, -h5 small, -h6 small { - color: #bfbfbf; -} -h1 { - margin-bottom: 18px; - font-size: 30px; - line-height: 36px; -} -h1 small { - font-size: 18px; -} -h2 { - font-size: 24px; - line-height: 36px; -} -h2 small { - font-size: 14px; -} -h3, -h4, -h5, -h6 { - line-height: 36px; -} -h3 { - font-size: 18px; -} -h3 small { - font-size: 14px; -} -h4 { - font-size: 16px; -} -h4 small { - font-size: 12px; -} -h5 { - font-size: 14px; -} -h6 { - font-size: 13px; - color: #bfbfbf; - text-transform: uppercase; -} -ul, ol { - margin: 0 0 18px 25px; -} -ul ul, -ul ol, -ol ol, -ol ul { - margin-bottom: 0; -} -ul { - list-style: disc; -} -ol { - list-style: decimal; -} -li { - line-height: 18px; - color: #808080; -} -ul.unstyled { - list-style: none; - margin-left: 0; -} -dl { - margin-bottom: 18px; -} -dl dt, dl dd { - line-height: 18px; -} -dl dt { - font-weight: bold; -} -dl dd { - margin-left: 9px; -} -hr { - margin: 20px 0 19px; - border: 0; - border-bottom: 1px solid; -} -strong { - font-style: inherit; - font-weight: bold; -} -em { - font-style: italic; - font-weight: inherit; - line-height: inherit; -} -.muted { - color: #bfbfbf; -} -blockquote { - margin-bottom: 18px; - border-left: 5px solid #eee; - padding-left: 15px; -} -blockquote p { - font-size: 14px; - font-weight: 300; - line-height: 18px; - margin-bottom: 0; -} -blockquote small { - display: block; - font-size: 12px; - font-weight: 300; - line-height: 18px; - color: #bfbfbf; -} -blockquote small:before { - content: '\2014 \00A0'; -} -address { - display: block; - line-height: 18px; - margin-bottom: 18px; -} -code, pre { - padding: 0 3px 2px; - font-family: Monaco, Andale Mono, Courier New, monospace; - font-size: 12px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} -code { - background-color: #FDE8E8; - color: rgba(0, 0, 0, 0.75); - padding: 1px 3px; -} -pre { - background-color: #EAB9B9; - color:red; - display: block; - padding: 8.5px; - margin: 0 0 18px; - line-height: 18px; - font-size: 12px; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.15); - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - white-space: pre; - white-space: pre-wrap; - word-wrap: break-word; -} -/* Forms.less -* Base styles for various input types, form layouts, and states -* ------------------------------------------------------------- */ -form { - margin-bottom: 18px; -} -fieldset { - margin-bottom: 18px; - padding-top: 18px; -} -fieldset legend { - display: block; - padding-left: 150px; - font-size: 19.5px; - line-height: 1; - color: #404040; - *padding: 0 0 5px 145px; - /* IE6-7 */ - - *line-height: 1.5; - /* IE6-7 */ - -} -form .clearfix { - margin-bottom: 18px; - zoom: 1; -} -form .clearfix:before, form .clearfix:after { - display: table; - content: ""; - zoom: 1; -} -form .clearfix:after { - clear: both; -} -label, -input, -select, -textarea { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 13px; - font-weight: normal; - line-height: normal; -} -select -{ - width : auto; -} -label { - padding-top: 6px; - font-size: 13px; - line-height: 18px; - float: left; - width: 130px; - text-align: left; - color: #404040; -} -form .input { - margin-left: 150px; -} -input[type=checkbox], input[type=radio] { - cursor: pointer; -} -input, -textarea, -select, -.uneditable-input { - display: inline-block; - width: 210px; - height: 18px; - padding: 4px; - font-size: 13px; - line-height: 18px; - color: #808080; - border: 1px solid #ccc; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} -select { - padding: initial; -} -input[type=checkbox], input[type=radio] { - width: auto; - height: auto; - padding: 0; - margin: 3px 0; - *margin-top: 0; - /* IE6-7 */ - - line-height: normal; - border: none; -} -input[type=file] { - background-color: #ffffff; - padding: initial; - border: initial; - line-height: initial; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} -input[type=button], input[type=reset], input[type=submit] { - width: auto; - height: auto; -} -select, input[type=file] { - height: 27px; - *height: auto; - line-height: 27px; - *margin-top: 4px; - /* For IE7, add top margin to align select with labels */ - -} -select[multiple] { - height: inherit; - background-color: #ffffff; -} -textarea { - height: auto; -} -.uneditable-input { - background-color: #ffffff; - display: block; - border-color: #eee; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); - cursor: not-allowed; -} -:-moz-placeholder { - color: #bfbfbf; -} -::-webkit-input-placeholder { - color: #bfbfbf; -} -input, textarea { - -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; - -moz-transition: border linear 0.2s, box-shadow linear 0.2s; - -ms-transition: border linear 0.2s, box-shadow linear 0.2s; - -o-transition: border linear 0.2s, box-shadow linear 0.2s; - transition: border linear 0.2s, box-shadow linear 0.2s; - -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); - -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); -} -input:focus, textarea:focus { - outline: 0; - border-color: rgba(82, 168, 236, 0.8); - -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); - -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); - box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); -} -input[type=file]:focus, input[type=checkbox]:focus, select:focus { - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; - outline: 1px dotted #666; -} -form .clearfix.error > label, form .clearfix.error .help-block, form .clearfix.error .help-inline { - color: #b94a48; -} -form .clearfix.error input, form .clearfix.error textarea { - color: #b94a48; - border-color: #ee5f5b; -} -form .clearfix.error input:focus, form .clearfix.error textarea:focus { - border-color: #e9322d; - -webkit-box-shadow: 0 0 6px #f8b9b7; - -moz-box-shadow: 0 0 6px #f8b9b7; - box-shadow: 0 0 6px #f8b9b7; -} -form .clearfix.error .input-prepend .add-on, form .clearfix.error .input-append .add-on { - color: #b94a48; - background-color: #fce6e6; - border-color: #b94a48; -} -form .clearfix.warning > label, form .clearfix.warning .help-block, form .clearfix.warning .help-inline { - color: #c09853; -} -form .clearfix.warning input, form .clearfix.warning textarea { - color: #c09853; - border-color: #ccae64; -} -form .clearfix.warning input:focus, form .clearfix.warning textarea:focus { - border-color: #be9a3f; - -webkit-box-shadow: 0 0 6px #e5d6b1; - -moz-box-shadow: 0 0 6px #e5d6b1; - box-shadow: 0 0 6px #e5d6b1; -} -form .clearfix.warning .input-prepend .add-on, form .clearfix.warning .input-append .add-on { - color: #c09853; - background-color: #d2b877; - border-color: #c09853; -} -form .clearfix.success > label, form .clearfix.success .help-block, form .clearfix.success .help-inline { - color: #468847; -} -form .clearfix.success input, form .clearfix.success textarea { - color: #468847; - border-color: #57a957; -} -form .clearfix.success input:focus, form .clearfix.success textarea:focus { - border-color: #458845; - -webkit-box-shadow: 0 0 6px #9acc9a; - -moz-box-shadow: 0 0 6px #9acc9a; - box-shadow: 0 0 6px #9acc9a; -} -form .clearfix.success .input-prepend .add-on, form .clearfix.success .input-append .add-on { - color: #468847; - background-color: #bcddbc; - border-color: #468847; -} -textarea -{ - width : 290px; -} -.input-mini, -input.mini, -textarea.mini, -select.mini { - width: 60px; -} -.input-small, -input.small, -textarea.small, -select.small { - width: 90px; -} -.input-medium, -input.medium, -textarea.medium, -select.medium { - width: 150px; -} -.input-large, -input.large, -textarea.large, -select.large { - width: 210px; -} -.input-xlarge, -input.xlarge, -textarea.xlarge, -select.xlarge { - width: 270px; -} -.input-xxlarge, -input.xxlarge, -textarea.xxlarge, -select.xxlarge { - width: 530px; -} -textarea.xxlarge { - overflow-y: auto; -} -input.span1, textarea.span1 { - display: inline-block; - float: none; - width: 30px; - margin-left: 0; -} -input.span2, textarea.span2 { - display: inline-block; - float: none; - width: 90px; - margin-left: 0; -} -input.span3, textarea.span3 { - display: inline-block; - float: none; - width: 150px; - margin-left: 0; -} -input.span4, textarea.span4 { - display: inline-block; - float: none; - width: 210px; - margin-left: 0; -} -input.span5, textarea.span5 { - display: inline-block; - float: none; - width: 270px; - margin-left: 0; -} -input.span6, textarea.span6 { - display: inline-block; - float: none; - width: 330px; - margin-left: 0; -} -input.span7, textarea.span7 { - display: inline-block; - float: none; - width: 390px; - margin-left: 0; -} -input.span8, textarea.span8 { - display: inline-block; - float: none; - width: 450px; - margin-left: 0; -} -input.span9, textarea.span9 { - display: inline-block; - float: none; - width: 510px; - margin-left: 0; -} -input.span10, textarea.span10 { - display: inline-block; - float: none; - width: 570px; - margin-left: 0; -} -input.span11, textarea.span11 { - display: inline-block; - float: none; - width: 630px; - margin-left: 0; -} -input.span12, textarea.span12 { - display: inline-block; - float: none; - width: 690px; - margin-left: 0; -} -input.span13, textarea.span13 { - display: inline-block; - float: none; - width: 750px; - margin-left: 0; -} -input.span14, textarea.span14 { - display: inline-block; - float: none; - width: 810px; - margin-left: 0; -} -input.span15, textarea.span15 { - display: inline-block; - float: none; - width: 870px; - margin-left: 0; -} -input.span16, textarea.span16 { - display: inline-block; - float: none; - width: 930px; - margin-left: 0; -} -input[disabled], -select[disabled], -textarea[disabled], -input[readonly], -select[readonly], -textarea[readonly] { - background-color: #f5f5f5; - border-color: #ddd; - cursor: not-allowed; -} -.actions { - background: #f5f5f5; - margin-top: 18px; - margin-bottom: 18px; - padding: 17px 20px 18px 150px; - border-top: 1px solid #ddd; - -webkit-border-radius: 0 0 3px 3px; - -moz-border-radius: 0 0 3px 3px; - border-radius: 0 0 3px 3px; -} -.actions .secondary-action { - float: right; -} -.actions .secondary-action a { - line-height: 30px; -} -.actions .secondary-action a:hover { - text-decoration: underline; -} -.help-inline, .help-block { - font-size: 13px; - line-height: 18px; - color: #bfbfbf; -} -.help-inline { - padding-left: 5px; - *position: relative; - /* IE6-7 */ - - *top: -5px; - /* IE6-7 */ - -} -.help-block { - display: block; - max-width: 600px; -} -.inline-inputs { - color: #808080; -} -.inline-inputs span { - padding: 0 2px 0 1px; -} -.input-prepend input, .input-append input { - -webkit-border-radius: 0 3px 3px 0; - -moz-border-radius: 0 3px 3px 0; - border-radius: 0 3px 3px 0; -} -.input-prepend .add-on, .input-append .add-on { - position: relative; - background: #f5f5f5; - border: 1px solid #ccc; - z-index: 2; - float: left; - display: block; - width: auto; - min-width: 16px; - height: 18px; - padding: 4px 4px 4px 5px; - margin-right: -1px; - font-weight: normal; - line-height: 18px; - color: #bfbfbf; - text-align: center; - text-shadow: 0 1px 0 #ffffff; - -webkit-border-radius: 3px 0 0 3px; - -moz-border-radius: 3px 0 0 3px; - border-radius: 3px 0 0 3px; -} -.input-prepend .active, .input-append .active { - background: #a9dba9; - border-color: #46a546; -} -.input-prepend .add-on { - *margin-top: 1px; - /* IE6-7 */ - -} -.input-append input { - float: left; - -webkit-border-radius: 3px 0 0 3px; - -moz-border-radius: 3px 0 0 3px; - border-radius: 3px 0 0 3px; -} -.input-append .add-on { - -webkit-border-radius: 0 3px 3px 0; - -moz-border-radius: 0 3px 3px 0; - border-radius: 0 3px 3px 0; - margin-right: 0; - margin-left: -1px; -} -.inputs-list { - margin: 0 0 5px; - width: 100%; -} -.inputs-list li { - display: block; - padding: 0; - width: 100%; -} -.inputs-list label { - display: block; - float: none; - width: auto; - padding: 0; - margin-left: 20px; - line-height: 18px; - text-align: left; - white-space: normal; -} -.inputs-list label strong { - color: #808080; -} -.inputs-list label small { - font-size: 11px; - font-weight: normal; -} -.inputs-list .inputs-list { - margin-left: 25px; - margin-bottom: 10px; - padding-top: 0; -} -.inputs-list:first-child { - padding-top: 6px; -} -.inputs-list li + li { - padding-top: 2px; -} -.inputs-list input[type=radio], .inputs-list input[type=checkbox] { - margin-bottom: 0; - margin-left: -20px; - float: left; -} -.form-stacked { - padding-left: 20px; -} -.form-stacked fieldset { - padding-top: 9px; -} -.form-stacked legend { - padding-left: 0; -} -.form-stacked label { - display: block; - float: none; - width: auto; - font-weight: bold; - text-align: left; - line-height: 20px; - padding-top: 0; -} -.form-stacked .clearfix { - margin-bottom: 9px; -} -.form-stacked .clearfix div.input { - margin-left: 0; -} -.form-stacked .inputs-list { - margin-bottom: 0; -} -.form-stacked .inputs-list li { - padding-top: 0; -} -.form-stacked .inputs-list li label { - font-weight: normal; - padding-top: 0; -} -.form-stacked div.clearfix.error { - padding-top: 10px; - padding-bottom: 10px; - padding-left: 10px; - margin-top: 0; - margin-left: -10px; -} -.form-stacked .actions { - margin-left: -20px; - padding-left: 20px; -} -/* -* Tables.less -* Tables for, you guessed it, tabular data -* ---------------------------------------- */ -table { - width: 100%; - margin-bottom: 18px; - padding: 0; - font-size: 13px; - border-collapse: collapse; -} -table th, table td { - padding: 10px 10px 9px; - line-height: 18px; - text-align: center; -} -table th { - padding-top: 9px; - font-weight: bold; - vertical-align: middle; -} -table td { - vertical-align: top; - /*border-top: 1px solid #ddd;*/ -} -table tbody th { -/* border-top: 1px solid #ddd;*/ - vertical-align: top; -} -.condensed-table th, .condensed-table td { - padding: 5px 5px 4px; -} -.bordered-table { - border: 1px solid #ddd; - border-collapse: separate; - *border-collapse: collapse; - /* IE7, collapse table to remove spacing */ - - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} -.bordered-table th + th, .bordered-table td + td, .bordered-table th + td { - border-left: 1px solid #ddd; -} -.bordered-table thead tr:first-child th:first-child, .bordered-table tbody tr:first-child td:first-child { - -webkit-border-radius: 4px 0 0 0; - -moz-border-radius: 4px 0 0 0; - border-radius: 4px 0 0 0; -} -.bordered-table thead tr:first-child th:last-child, .bordered-table tbody tr:first-child td:last-child { - -webkit-border-radius: 0 4px 0 0; - -moz-border-radius: 0 4px 0 0; - border-radius: 0 4px 0 0; -} -.bordered-table tbody tr:last-child td:first-child { - -webkit-border-radius: 0 0 0 4px; - -moz-border-radius: 0 0 0 4px; - border-radius: 0 0 0 4px; -} -.bordered-table tbody tr:last-child td:last-child { - -webkit-border-radius: 0 0 4px 0; - -moz-border-radius: 0 0 4px 0; - border-radius: 0 0 4px 0; -} -table .span1 { - width: 20px; -} -table .span2 { - width: 60px; -} -table .span3 { - width: 100px; -} -table .span4 { - width: 140px; -} -table .span5 { - width: 180px; -} -table .span6 { - width: 220px; -} -table .span7 { - width: 260px; -} -table .span8 { - width: 300px; -} -table .span9 { - width: 340px; -} -table .span10 { - width: 380px; -} -table .span11 { - width: 420px; -} -table .span12 { - width: 460px; -} -table .span13 { - width: 500px; -} -table .span14 { - width: 540px; -} -table .span15 { - width: 580px; -} -table .span16 { - width: 620px; -} -.zebra-striped tbody tr:nth-child(odd) td, .zebra-striped tbody tr:nth-child(odd) th { - background-color: #f9f9f9; -} -.zebra-striped tbody tr:hover td, .zebra-striped tbody tr:hover th { - background-color: #f5f5f5; -} -table .header { - cursor: pointer; -} -table .header:after { - content: ""; - float: right; - margin-top: 7px; - border-width: 0 4px 4px; - border-style: solid; - border-color: #000 transparent; - visibility: hidden; -} -table .headerSortUp, table .headerSortDown { - background-color: rgba(141, 192, 219, 0.25); - text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); -} -table .header:hover:after { - visibility: visible; -} -table .headerSortDown:after, table .headerSortDown:hover:after { - visibility: visible; - filter: alpha(opacity=60); - -khtml-opacity: 0.6; - -moz-opacity: 0.6; - opacity: 0.6; -} -table .headerSortUp:after { - border-bottom: none; - border-left: 4px solid transparent; - border-right: 4px solid transparent; - border-top: 4px solid #000; - visibility: visible; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; - filter: alpha(opacity=60); - -khtml-opacity: 0.6; - -moz-opacity: 0.6; - opacity: 0.6; -} -table .blue { - color: #049cdb; - border-bottom-color: #049cdb; -} -table .headerSortUp.blue, table .headerSortDown.blue { - background-color: #ade6fe; -} -table .green { - color: #46a546; - border-bottom-color: #46a546; -} -table .headerSortUp.green, table .headerSortDown.green { - background-color: #cdeacd; -} -table .red { - color: #9d261d; - border-bottom-color: #9d261d; -} -table .headerSortUp.red, table .headerSortDown.red { - background-color: #f4c8c5; -} -table .yellow { - color: #ffc40d; - border-bottom-color: #ffc40d; -} -table .headerSortUp.yellow, table .headerSortDown.yellow { - background-color: #fff6d9; -} -table .orange { - color: #f89406; - border-bottom-color: #f89406; -} -.center1 -{ -margin-left: auto; -margin-right: auto; -} -table .headerSortUp.orange, table .headerSortDown.orange { - background-color: #fee9cc; -} -table .purple { - color: #7a43b6; - border-bottom-color: #7a43b6; -} -table .headerSortUp.purple, table .headerSortDown.purple { - background-color: #e2d5f0; -} -/* Patterns.less -* Repeatable UI elements outside the base styles provided from the scaffolding -* ---------------------------------------------------------------------------- */ -.topbar { - height: 40px; - position: fixed; - top: 0; - left: 0; - right: 0; - z-index: 10000; - overflow: visible; -} -.topbar a { - color: #bfbfbf; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); -} -.topbar h3 a:hover, .topbar .brand:hover, .topbar ul .active > a { - background-color: #333; - background-color: rgba(255, 255, 255, 0.05); - color: #ffffff; - text-decoration: none; -} -.topbar h3 { - position: relative; -} -.topbar h3 a, .topbar .brand { - float: left; - display: block; - padding: 8px 20px 12px; - margin-left: -20px; - color: #ffffff; - font-size: 20px; - font-weight: 200; - line-height: 1; -} -.topbar p { - margin: 0; - line-height: 40px; -} -.topbar p a:hover { - background-color: transparent; - color: #ffffff; -} -.topbar form { - float: left; - margin: 5px 0 0 0; - position: relative; - filter: alpha(opacity=100); - -khtml-opacity: 1; - -moz-opacity: 1; - opacity: 1; -} -.topbar form.pull-right { - float: right; -} -.topbar input { - background-color: #444; - background-color: rgba(255, 255, 255, 0.3); - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: normal; - font-weight: 13px; - line-height: 1; - padding: 4px 9px; - color: #ffffff; - color: rgba(255, 255, 255, 0.75); - border: 1px solid #111; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25); - -webkit-transition: none; - -moz-transition: none; - -ms-transition: none; - -o-transition: none; - transition: none; -} -.topbar input:-moz-placeholder { - color: #e6e6e6; -} -.topbar input::-webkit-input-placeholder { - color: #e6e6e6; -} -.topbar input:hover { - background-color: #bfbfbf; - background-color: rgba(255, 255, 255, 0.5); - color: #ffffff; -} -.topbar input:focus, .topbar input.focused { - outline: 0; - background-color: #ffffff; - color: #404040; - text-shadow: 0 1px 0 #ffffff; - border: 0; - padding: 5px 10px; - -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); - -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); - box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); -} -.topbar-inner, .topbar .fill { - background-color: #222; - background-color: #222222; - background-repeat: repeat-x; - background-image: -khtml-gradient(linear, left top, left bottom, from(#333333), to(#222222)); - background-image: -moz-linear-gradient(top, #333333, #222222); - background-image: -ms-linear-gradient(top, #333333, #222222); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #333333), color-stop(100%, #222222)); - background-image: -webkit-linear-gradient(top, #333333, #222222); - background-image: -o-linear-gradient(top, #333333, #222222); - background-image: linear-gradient(top, #333333, #222222); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); - -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); -} -.topbar div > ul, .nav { - display: block; - float: left; - margin: 0 10px 0 0; - position: relative; - left: 0; -} -.topbar div > ul > li, .nav > li { - display: block; - float: left; -} -.topbar div > ul a, .nav a { - display: block; - float: none; - padding: 10px 10px 11px; - line-height: 19px; - text-decoration: none; -} -.topbar div > ul a:hover, .nav a:hover { - color: #ffffff; - text-decoration: none; -} -.topbar div > ul .active > a, .nav .active > a { - background-color: #222; - background-color: rgba(0, 0, 0, 0.5); -} -.topbar div > ul.secondary-nav, .nav.secondary-nav { - float: right; - margin-left: 10px; - margin-right: 0; -} -.topbar div > ul.secondary-nav .menu-dropdown, -.nav.secondary-nav .menu-dropdown, -.topbar div > ul.secondary-nav .dropdown-menu, -.nav.secondary-nav .dropdown-menu { - right: 0; - border: 0; -} -.topbar div > ul a.menu:hover, -.nav a.menu:hover, -.topbar div > ul li.open .menu, -.nav li.open .menu, -.topbar div > ul .dropdown-toggle:hover, -.nav .dropdown-toggle:hover, -.topbar div > ul .dropdown.open .dropdown-toggle, -.nav .dropdown.open .dropdown-toggle { - background: #444; - background: rgba(255, 255, 255, 0.05); -} -.topbar div > ul .menu-dropdown, -.nav .menu-dropdown, -.topbar div > ul .dropdown-menu, -.nav .dropdown-menu { - background-color: #333; -} -.topbar div > ul .menu-dropdown a.menu, -.nav .menu-dropdown a.menu, -.topbar div > ul .dropdown-menu a.menu, -.nav .dropdown-menu a.menu, -.topbar div > ul .menu-dropdown .dropdown-toggle, -.nav .menu-dropdown .dropdown-toggle, -.topbar div > ul .dropdown-menu .dropdown-toggle, -.nav .dropdown-menu .dropdown-toggle { - color: #ffffff; -} -.topbar div > ul .menu-dropdown a.menu.open, -.nav .menu-dropdown a.menu.open, -.topbar div > ul .dropdown-menu a.menu.open, -.nav .dropdown-menu a.menu.open, -.topbar div > ul .menu-dropdown .dropdown-toggle.open, -.nav .menu-dropdown .dropdown-toggle.open, -.topbar div > ul .dropdown-menu .dropdown-toggle.open, -.nav .dropdown-menu .dropdown-toggle.open { - background: #444; - background: rgba(255, 255, 255, 0.05); -} -.topbar div > ul .menu-dropdown li a, -.nav .menu-dropdown li a, -.topbar div > ul .dropdown-menu li a, -.nav .dropdown-menu li a { - color: #999; - text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5); -} -.topbar div > ul .menu-dropdown li a:hover, -.nav .menu-dropdown li a:hover, -.topbar div > ul .dropdown-menu li a:hover, -.nav .dropdown-menu li a:hover { - background-color: #191919; - background-repeat: repeat-x; - background-image: -khtml-gradient(linear, left top, left bottom, from(#292929), to(#191919)); - background-image: -moz-linear-gradient(top, #292929, #191919); - background-image: -ms-linear-gradient(top, #292929, #191919); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #292929), color-stop(100%, #191919)); - background-image: -webkit-linear-gradient(top, #292929, #191919); - background-image: -o-linear-gradient(top, #292929, #191919); - background-image: linear-gradient(top, #292929, #191919); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#292929', endColorstr='#191919', GradientType=0); - color: #ffffff; -} -.topbar div > ul .menu-dropdown .active a, -.nav .menu-dropdown .active a, -.topbar div > ul .dropdown-menu .active a, -.nav .dropdown-menu .active a { - color: #ffffff; -} -.topbar div > ul .menu-dropdown .divider, -.nav .menu-dropdown .divider, -.topbar div > ul .dropdown-menu .divider, -.nav .dropdown-menu .divider { - background-color: #222; - border-color: #444; -} -.topbar ul .menu-dropdown li a, .topbar ul .dropdown-menu li a { - padding: 4px 15px; -} -li.menu, .dropdown { - position: relative; -} -a.menu:after, .dropdown-toggle:after { - width: 0; - height: 0; - display: inline-block; - content: "↓"; - text-indent: -99999px; - vertical-align: top; - margin-top: 8px; - margin-left: 4px; - border-left: 4px solid transparent; - border-right: 4px solid transparent; - border-top: 4px solid #ffffff; - filter: alpha(opacity=50); - -khtml-opacity: 0.5; - -moz-opacity: 0.5; - opacity: 0.5; -} -.menu-dropdown, .dropdown-menu { - background-color: #ffffff; - float: left; - display: none; - position: absolute; - top: 40px; - z-index: 900; - min-width: 160px; - max-width: 220px; - _width: 160px; - margin-left: 0; - margin-right: 0; - padding: 6px 0; - zoom: 1; - border-color: #999; - border-color: rgba(0, 0, 0, 0.2); - border-style: solid; - border-width: 0 1px 1px; - -webkit-border-radius: 0 0 6px 6px; - -moz-border-radius: 0 0 6px 6px; - border-radius: 0 0 6px 6px; - -webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); - -moz-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); - -webkit-background-clip: padding-box; - -moz-background-clip: padding-box; - background-clip: padding-box; -} -.menu-dropdown li, .dropdown-menu li { - float: none; - display: block; - background-color: none; -} -.menu-dropdown .divider, .dropdown-menu .divider { - height: 1px; - margin: 5px 0; - overflow: hidden; - background-color: #eee; - border-bottom: 1px solid #ffffff; -} -.topbar .dropdown-menu a, .dropdown-menu a { - display: block; - padding: 4px 15px; - clear: both; - font-weight: normal; - line-height: 18px; - color: #808080; - text-shadow: 0 1px 0 #ffffff; -} -.topbar .dropdown-menu a:hover, -.dropdown-menu a:hover, -.topbar .dropdown-menu a.hover, -.dropdown-menu a.hover { - background-color: #dddddd; - background-repeat: repeat-x; - background-image: -khtml-gradient(linear, left top, left bottom, from(#eeeeee), to(#dddddd)); - background-image: -moz-linear-gradient(top, #eeeeee, #dddddd); - background-image: -ms-linear-gradient(top, #eeeeee, #dddddd); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #eeeeee), color-stop(100%, #dddddd)); - background-image: -webkit-linear-gradient(top, #eeeeee, #dddddd); - background-image: -o-linear-gradient(top, #eeeeee, #dddddd); - background-image: linear-gradient(top, #eeeeee, #dddddd); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#dddddd', GradientType=0); - color: #404040; - text-decoration: none; - -webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.025), inset 0 -1px rgba(0, 0, 0, 0.025); - -moz-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.025), inset 0 -1px rgba(0, 0, 0, 0.025); - box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.025), inset 0 -1px rgba(0, 0, 0, 0.025); -} -footer { - margin-top: 17px; - padding-top: 17px; -} -.page-header { - margin-bottom: 17px; - border-bottom: 1px solid #ddd; - -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); - -moz-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); - box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); -} -.page-header h3 { - margin-top: 20px; - margin-bottom : -17px; -} -.btn.danger, -.alert-message.danger, -.btn.danger:hover, -.alert-message.danger:hover, -.btn.error, -.alert-message.error, -.btn.error:hover, -.alert-message.error:hover, -.btn.success, -.alert-message.success, -.btn.success:hover, -.alert-message.success:hover, -.btn.info, -.alert-message.info, -.btn.info:hover, -.alert-message.info:hover { - color: #ffffff; -} -.btn .close, .alert-message .close { - font-family: Arial, sans-serif; - line-height: 18px; -} -.btn-mini { - padding: 2px 6px; - font-size: 15px; - line-height: 16px; -} -.btn.danger, -.alert-message.danger, -.btn.error, -.alert-message.error { - background-color: #c43c35; - background-repeat: repeat-x; - background-image: -khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35)); - background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); - background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35)); - background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); - background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); - background-image: linear-gradient(top, #ee5f5b, #c43c35); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0); - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - border-color: #c43c35 #c43c35 #882a25; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); -} -.btn.success, .alert-message.success { - background-color: #57a957; - background-repeat: repeat-x; - background-image: -khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957)); - background-image: -moz-linear-gradient(top, #62c462, #57a957); - background-image: -ms-linear-gradient(top, #62c462, #57a957); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957)); - background-image: -webkit-linear-gradient(top, #62c462, #57a957); - background-image: -o-linear-gradient(top, #62c462, #57a957); - background-image: linear-gradient(top, #62c462, #57a957); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0); - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - border-color: #57a957 #57a957 #3d773d; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); -} -.btn.info, .alert-message.info { - background-color: #339bb9; - background-repeat: repeat-x; - background-image: -khtml-gradient(linear, left top, left bottom, from(#5bc0de), to(#339bb9)); - background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); - background-image: -ms-linear-gradient(top, #5bc0de, #339bb9); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9)); - background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); - background-image: -o-linear-gradient(top, #5bc0de, #339bb9); - background-image: linear-gradient(top, #5bc0de, #339bb9); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0); - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - border-color: #339bb9 #339bb9 #22697d; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); -} -.btn { - cursor: pointer; - display: inline-block; - background-color: #e6e6e6; - background-repeat: no-repeat; - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6)); - background-image: -webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); - background-image: -moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6); - background-image: -ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); - background-image: -o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); - background-image: linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); - padding: 5px 14px 6px; - text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); - color: #333; - font-size: 13px; - line-height: normal; - border: 1px solid #ccc; - border-bottom-color: #bbb; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - -webkit-transition: 0.1s linear all; - -moz-transition: 0.1s linear all; - -ms-transition: 0.1s linear all; - -o-transition: 0.1s linear all; - transition: 0.1s linear all; -} -.btn:hover { - background-position: 0 -15px; - color: #333; - text-decoration: none; -} -.btn:focus { - outline: 1px dotted #666; -} -.btn.primary { - color: #ffffff; - background-color: #0064cd; - background-repeat: repeat-x; - background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd)); - background-image: -moz-linear-gradient(top, #049cdb, #0064cd); - background-image: -ms-linear-gradient(top, #049cdb, #0064cd); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd)); - background-image: -webkit-linear-gradient(top, #049cdb, #0064cd); - background-image: -o-linear-gradient(top, #049cdb, #0064cd); - background-image: linear-gradient(top, #049cdb, #0064cd); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0); - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - border-color: #0064cd #0064cd #003f81; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); -} -.btn.active, .btn:active { - -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); -} -.btn.disabled { - cursor: default; - background-image: none; - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - filter: alpha(opacity=65); - -khtml-opacity: 0.65; - -moz-opacity: 0.65; - opacity: 0.65; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} -.btn[disabled] { - cursor: default; - background-image: none; - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - filter: alpha(opacity=65); - -khtml-opacity: 0.65; - -moz-opacity: 0.65; - opacity: 0.65; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} -.btn.large { - font-size: 15px; - line-height: normal; - padding: 9px 14px 9px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} -.btn.small { - padding: 7px 9px 7px; - font-size: 11px; -} -:root .alert-message, :root .btn { - border-radius: 0 \0; -} -.alert { - padding: 8px 35px 8px 14px; - margin-bottom: 18px; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); - background-color: #fcf8e3; - border: 1px solid #fbeed5; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} -.alert, .alert-heading { - color: #c09853; -} -.alert .close { - position: relative; - top: -2px; - right: -21px; - line-height: 18px; -} -.alert-success { - background-color: #dff0d8; - border-color: #d6e9c6; -} -.alert-success, .alert-success .alert-heading { - color: #468847; -} -.alert-danger, .alert-error { - background-color: #f2dede; - border-color: #eed3d7; -} -.alert-danger, -.alert-error, -.alert-danger .alert-heading, -.alert-error .alert-heading { - color: #b94a48; -} -.alert-info { - background-color: #d9edf7; - border-color: #bce8f1; -} -.alert-info, .alert-info .alert-heading { - color: #3a87ad; -} -.alert-block { - padding-top: 14px; - padding-bottom: 14px; -} -.alert-block > p, .alert-block > ul { - margin-bottom: 0; -} -.alert-block p + p { - margin-top: 5px; -} - -button.btn::-moz-focus-inner, input[type=submit].btn::-moz-focus-inner { - padding: 0; - border: 0; -} -.alert-message { - position: relative; - padding: 7px 15px; - margin-bottom: 18px; - color: #404040; - background-color: #eedc94; - background-repeat: repeat-x; - background-image: -khtml-gradient(linear, left top, left bottom, from(#fceec1), to(#eedc94)); - background-image: -moz-linear-gradient(top, #fceec1, #eedc94); - background-image: -ms-linear-gradient(top, #fceec1, #eedc94); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fceec1), color-stop(100%, #eedc94)); - background-image: -webkit-linear-gradient(top, #fceec1, #eedc94); - background-image: -o-linear-gradient(top, #fceec1, #eedc94); - background-image: linear-gradient(top, #fceec1, #eedc94); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fceec1', endColorstr='#eedc94', GradientType=0); - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - border-color: #eedc94 #eedc94 #e4c652; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); - border-width: 1px; - border-style: solid; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); -} -.alert-message .close { - margin-top: 1px; - *margin-top: 0; -} -.alert-message a { - font-weight: bold; - color: #404040; -} -.alert-message.danger p a, -.alert-message.error p a, -.alert-message.success p a, -.alert-message.info p a { - color: #ffffff; -} -.alert-message h5 { - line-height: 18px; -} -.alert-message p { - margin-bottom: 0; -} -.alert-message div { - margin-top: 5px; - margin-bottom: 2px; - line-height: 28px; -} -.alert-message .btn { - -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); - -moz-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); - box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); -} -.alert-message.block-message { - background-image: none; - background-color: #fdf5d9; - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - padding: 14px; - border-color: #fceec1; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} -.alert-message.block-message ul, .alert-message.block-message p { - margin-right: 30px; -} -.alert-message.block-message ul { - margin-bottom: 0; -} -.alert-message.block-message li { - color: #404040; -} -.alert-message.block-message .alert-actions { - margin-top: 5px; -} -.alert-message.block-message.error, .alert-message.block-message.success, .alert-message.block-message.info { - color: #404040; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); -} -.alert-message.block-message.error { - background-color: #fddfde; - border-color: #fbc7c6; -} -.alert-message.block-message.success { - background-color: #d1eed1; - border-color: #bfe7bf; -} -.alert-message.block-message.info { - background-color: #ddf4fb; - border-color: #c6edf9; -} -.alert-message.block-message.danger p a, -.alert-message.block-message.error p a, -.alert-message.block-message.success p a, -.alert-message.block-message.info p a { - color: #404040; -} -.label { - padding: 1px 3px 2px; - font-size: 9.75px; - font-weight: bold; - color: #ffffff; - text-transform: uppercase; - white-space: nowrap; - background-color: #bfbfbf; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - text-shadow: none; -} -.label.important { - background-color: #c43c35; -} -.label.warning { - background-color: #f89406; -} -.label.success { - background-color: #46a546; -} -.label.notice { - background-color: #62cffc; -} -.well { - background-color: #f5f5f5; - margin-bottom: 20px; - padding: 19px; - min-height: 20px; - border: 1px solid #eee; - border: 1px solid rgba(0, 0, 0, 0.05); - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); -} -.well blockquote { - border-color: #ddd; - border-color: rgba(0, 0, 0, 0.15); -} -.modal-backdrop { - background-color: #000000; - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - z-index: 10000; -} -.modal-backdrop.fade { - opacity: 0; -} -.modal-backdrop, .modal-backdrop.fade.in { - filter: alpha(opacity=80); - -khtml-opacity: 0.8; - -moz-opacity: 0.8; - opacity: 0.8; -} -.modal { - position: fixed; - top: 10%; - left: 50%; - z-index: 1050; - width: 560px; - margin-left: -280px; - background-color: #ffffff; - border: 1px solid #999; - border: 1px solid rgba(0, 0, 0, 0.3); - *border: 1px solid #999; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - outline: none; - -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - -webkit-background-clip: padding-box; - -moz-background-clip: padding-box; - background-clip: padding-box; -} -.modal.fade { - top: -25%; - -webkit-transition: opacity 0.3s linear, top 0.3s ease-out; - -moz-transition: opacity 0.3s linear, top 0.3s ease-out; - -o-transition: opacity 0.3s linear, top 0.3s ease-out; - transition: opacity 0.3s linear, top 0.3s ease-out; -} - -.modal.fade.in { - top: 10%; -} - -.modal-header { - padding: 9px 15px; - border-bottom: 1px solid #eee; -} - -.modal-header .close { - margin-top: 2px; -} - -.modal-header h3 { - margin: 0; - line-height: 30px; -} - -.modal-body { - position: relative; - max-height: 400px; - padding: 15px; - overflow-y: auto; -} - -.modal-form { - margin-bottom: 0; -} - -.modal-footer { - padding: 14px 15px 15px; - margin-bottom: 0; - text-align: right; - background-color: #f5f5f5; - border-top: 1px solid #ddd; - -webkit-border-radius: 0 0 6px 6px; - -moz-border-radius: 0 0 6px 6px; - border-radius: 0 0 6px 6px; - *zoom: 1; - -webkit-box-shadow: inset 0 1px 0 #ffffff; - -moz-box-shadow: inset 0 1px 0 #ffffff; - box-shadow: inset 0 1px 0 #ffffff; -} - -.modal-footer:before, -.modal-footer:after { - display: table; - line-height: 0; - content: ""; -} - -.modal-footer:after { - clear: both; -} - -.modal-footer .btn + .btn { - margin-bottom: 0; - margin-left: 5px; -} - -.modal-footer .btn-group .btn + .btn { - margin-left: -1px; -} - -.modal-footer .btn-block + .btn-block { - margin-left: 0; -} -.tabs, .pills { - margin: 0 0 18px; - padding: 0; - list-style: none; - zoom: 1; -} -.tabs:before, -.pills:before, -.tabs:after, -.pills:after { - display: table; - content: ""; - zoom: 1; -} -.tabs:after, .pills:after { - clear: both; -} -.tabs > li, .pills > li { - float: left; -} -.tabs > li > a, .pills > li > a { - display: block; -} -.tabs { - border-color: #ddd; - border-style: solid; - border-width: 0 0 1px; -} -.tabs > li { - position: relative; - margin-bottom: -1px; -} -.tabs > li > a { - padding: 0 15px; - margin-right: 2px; - line-height: 23px; - border: 1px solid transparent; - -webkit-border-radius: 4px 4px 0 0; - -moz-border-radius: 4px 4px 0 0; - border-radius: 4px 4px 0 0; -} -.tabs > li > a:hover { - text-decoration: none; - background-color: #eee; - border-color: #eee #eee #ddd; -} -.tabs .active > a, .tabs .active > a:hover { - color: #808080; - background-color: #ffffff; - border: 1px solid #ddd; - border-bottom-color: transparent; - cursor: default; -} -.tabs .menu-dropdown, .tabs .dropdown-menu { - top: 35px; - border-width: 1px; - -webkit-border-radius: 0 6px 6px 6px; - -moz-border-radius: 0 6px 6px 6px; - border-radius: 0 6px 6px 6px; -} -.tabs a.menu:after, .tabs .dropdown-toggle:after { - border-top-color: #999; - margin-top: 15px; - margin-left: 5px; -} -.tabs li.open.menu .menu, .tabs .open.dropdown .dropdown-toggle { - border-color: #999; -} -.tabs li.open a.menu:after, .tabs .dropdown.open .dropdown-toggle:after { - border-top-color: #555; -} -.pills a { - margin: 5px 3px 5px 0; - padding: 0 15px; - line-height: 30px; - text-shadow: 0 1px 1px #ffffff; - -webkit-border-radius: 15px; - -moz-border-radius: 15px; - border-radius: 15px; -} -.pills a:hover { - color: #ffffff; - text-decoration: none; - text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25); - background-color: #00438a; -} -.pills .active a { - color: #ffffff; - text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25); - background-color: #0069d6; -} -.pills-vertical > li { - float: none; -} -.tab-content > .tab-pane, .pill-content > .pill-pane { - display: none; -} -.tab-content > .active, .pill-content > .active { - display: block; -} -.pagination { - height: 36px; - margin: 18px 0; -} -.pagination ul { - float: left; - margin: 0; - border: 1px solid #ddd; - border: 1px solid rgba(0, 0, 0, 0.15); - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); -} -.pagination li { - display: inline; -} -.pagination a { - float: left; - padding: 0 14px; - line-height: 34px; - border-right: 1px solid; - border-right-color: #ddd; - border-right-color: rgba(0, 0, 0, 0.15); - *border-right-color: #ddd; - /* IE6-7 */ - - text-decoration: none; -} -.pagination a:hover, .pagination .active a { - background-color: #c7eefe; -} -/*custom classes*/ -.pagination .done a { - background-color: #00CC66; -} -.pagination .disabled a, .pagination .disabled a:hover { - background-color: transparent; - color: #bfbfbf; -} -.pagination .next a { - border: 0; -} diff --git a/testapp/yaksh_app/static/yaksh_app/css/gradeuser.css b/testapp/yaksh_app/static/yaksh_app/css/gradeuser.css deleted file mode 100644 index 07b1079..0000000 --- a/testapp/yaksh_app/static/yaksh_app/css/gradeuser.css +++ /dev/null @@ -1,52 +0,0 @@ -textarea -{ -width : 550px; -height : 200px; - -} - -.for-question{ - background: none repeat scroll 0 0 #F1F1F1; - border-radius: 6px 6px 6px 6px; - margin-bottom: 10px; - padding: 5px; -} - -#headerDiv, #contentDiv { -float: left; -} -#titleText { -float: left; -font-size: 1.1em; -font-weight: bold; -margin: 5px; -} -#myHeader { -font-size: 1.1em; -font-weight: bold; -margin: 5px; -} -#headerDiv { -background-color: #0037DB; -color: #9EB6FF; -} - -#contentDiv { - background-color:#F0F8FF; - border: 1px solid #C9C9C9; - border-radius: 5px 5px 5px 5px; - margin-bottom: 10px; - min-width: 805px; - -} - -#myContent { -margin: 5px 10px; - -} -#headerDiv a { -float: right; -margin: 10px 10px 5px 5px; -} -#headerDiv a:hover { -color: #FFFFFF; diff --git a/testapp/yaksh_app/static/yaksh_app/css/login.css b/testapp/yaksh_app/static/yaksh_app/css/login.css deleted file mode 100644 index a10cbaa..0000000 --- a/testapp/yaksh_app/static/yaksh_app/css/login.css +++ /dev/null @@ -1,10 +0,0 @@ -label -{ - padding-top: 6px; - font-size: 15px; - line-height: 18px; - float: left; - width: 80px; - text-align: center; - color: #404040; - } diff --git a/testapp/yaksh_app/static/yaksh_app/css/monitor.css b/testapp/yaksh_app/static/yaksh_app/css/monitor.css deleted file mode 100644 index b16c8b3..0000000 --- a/testapp/yaksh_app/static/yaksh_app/css/monitor.css +++ /dev/null @@ -1,11 +0,0 @@ - table td - { - vertical-align: top; - border-top: 1px solid #ddd; - } - table tbody th - { - border-top: 1px solid #ddd; - vertical-align: top; - } - diff --git a/testapp/yaksh_app/static/yaksh_app/css/question.css b/testapp/yaksh_app/static/yaksh_app/css/question.css deleted file mode 100644 index 4bf5913..0000000 --- a/testapp/yaksh_app/static/yaksh_app/css/question.css +++ /dev/null @@ -1,42 +0,0 @@ -.time-div -{ - background-color:black; - padding: 8px; - color: #5DFC0A; - vertical-align:middle; - width:150px; - float:right; - border-radius: 6px 6px 6px 6px; -} -.td1-class -{ - width:175px; -} -.td2-class -{ - width:50px; -} -.page-header { - height:50px; - text-align: center; - background-color: #f5f5f5; - padding: 35px 20px 10px; - margin: -20px -20px 20px; -} -#codeTextarea{ - - } - .textAreaWithLines{ - font-family:courier; - border:1px solid #eee; - - } - .textAreaWithLines textarea,.textAreaWithLines div{ - border:0px; - line-height:120%; - font-size:12px; - } - .lineObj{ - color: grey; - } - diff --git a/testapp/yaksh_app/static/yaksh_app/css/question_paper_creation.css b/testapp/yaksh_app/static/yaksh_app/css/question_paper_creation.css deleted file mode 100644 index c915320..0000000 --- a/testapp/yaksh_app/static/yaksh_app/css/question_paper_creation.css +++ /dev/null @@ -1,119 +0,0 @@ -body { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 13px; - font-weight: normal; - line-height: 18px; - color: #404040; -} -.clearfix { - clear: both; -} -.tabs li { - text-align: center; - width: 33%; -} -.tabs li:last-child { - width: 34%; -} -.tabs > .active > a { - border: 0; - background: lightgreen; -} -.tabs > .active > a:hover { - border: 0; - background: green; - color: #ffffff; -} -.tabs li a { - border-radius: 0; - margin-right: 0; -} -.tabs { - border: 1px solid #ddd; -} -#progress { - background: red; -} -#content-left{ - text-align: center; - background: grey; -} -#content-right{ - text-align: center; - background: grey; -} -#selectors { - margin-left: 0; - background: #fafafa; - padding: 7px 0; - border: 2px solid #f5f5f5; -} -#selectors .span4 { - margin-left: 0; -} -#id_question_type { - width: 100%; -} -#id_marks { - width: 100%; -} -#fixed-questions .span7 > div, -#random-questions .span7 > div{ - background: #f5f5f5; - height: 200px; - border: 1px solid #333333; - padding: 5px; -} -#fixed-available, -#random-available { - height: 125px; - min-height: 125px; - overflow-y: scroll; - margin-bottom: 15px; -} -#fixed-added, -#random-added { - height: 160px; - overflow-y: scroll; -} -#fixed-added hr, -#random-added hr { - margin: 5px 0 4px; -} -.qcard { - position: relative; - background: #ffffff; - padding: 5px; - margin: 5px 5px; - box-shadow: 1px 1px 5px #cccccc; - -webkit-box-shadow: 1px 1px 5px #cccccc; - -moz-box-shadow: 1px 1px 5px #cccccc; - -o-box-shadow: 1px 1px 5px #cccccc; -} -.qcard ul { - margin-bottom: 5px; -} -.qcard .remove { - position: absolute; - - top: 3px; - right: 3px; - padding: 1px 3px; - text-decoration: none; - color: #ffffff; - background: #ff4136; - border-radius: 3px; - font-weight: bold; -} -.qcard .remove:hover { - background: #333333; -} -.red-alert { - border: 2px solid red; -} -#myModal .qcard .remove{ - display: none; -} -.well{ - padding: 5px; -} diff --git a/testapp/yaksh_app/static/yaksh_app/css/question_quiz.css b/testapp/yaksh_app/static/yaksh_app/css/question_quiz.css deleted file mode 100644 index ee249d4..0000000 --- a/testapp/yaksh_app/static/yaksh_app/css/question_quiz.css +++ /dev/null @@ -1,24 +0,0 @@ -table th, table td - { - text-align: left; - } - -.mini-text -{ - height : 25px; - width : 70px; -} -.select-type -{ - width : 225px; -} -.tag-text -{ - height : 30px; - width : 290px; -} -.date-text -{ - height : 30px; - width : 100px; -} diff --git a/testapp/yaksh_app/static/yaksh_app/css/showusers.css b/testapp/yaksh_app/static/yaksh_app/css/showusers.css deleted file mode 100644 index 66a3746..0000000 --- a/testapp/yaksh_app/static/yaksh_app/css/showusers.css +++ /dev/null @@ -1,5 +0,0 @@ -.table-class -{ - text-align:left; - width:60%; -} diff --git a/testapp/yaksh_app/static/yaksh_app/js/add_question.js b/testapp/yaksh_app/static/yaksh_app/js/add_question.js deleted file mode 100644 index 946c139..0000000 --- a/testapp/yaksh_app/static/yaksh_app/js/add_question.js +++ /dev/null @@ -1,205 +0,0 @@ -function increase(frm) -{ - if(frm.points.value == "") - { - frm.points.value = "0.5"; - return; - } - frm.points.value = parseFloat(frm.points.value) + 0.5; -} - -function decrease(frm) -{ - if(frm.points.value > 0) - { - frm.points.value = parseFloat(frm.points.value) - 0.5; - } - else - { - frm.points.value=0; - } - - -} - -function setSelectionRange(input, selectionStart, selectionEnd) -{ - if (input.setSelectionRange) - { - input.focus(); - input.setSelectionRange(selectionStart, selectionEnd); - } - else if (input.createTextRange) - { - var range = input.createTextRange(); - range.collapse(true); - range.moveEnd('character', selectionEnd); - range.moveStart('character', selectionStart); - range.select(); - } -} - -function replaceSelection (input, replaceString) -{ - if (input.setSelectionRange) - { - var selectionStart = input.selectionStart; - var selectionEnd = input.selectionEnd; - input.value = input.value.substring(0, selectionStart)+ replaceString + input.value.substring(selectionEnd); - if (selectionStart != selectionEnd) - { - setSelectionRange(input, selectionStart, selectionStart + replaceString.length); - } - else - { - setSelectionRange(input, selectionStart + replaceString.length, selectionStart + replaceString.length); - } - } - else if (document.selection) - { - var range = document.selection.createRange(); - if (range.parentElement() == input) - { - var isCollapsed = range.text == ''; - range.text = replaceString; - if (!isCollapsed) - { - range.moveStart('character', -replaceString.length); - range.select(); - } - } - } -} - -function textareaformat() -{ - document.getElementById('id_type').setAttribute('class','select-type'); - document.getElementById('id_points').setAttribute('class','mini-text'); - document.getElementById('id_tags').setAttribute('class','tag-text'); - - - $('#id_snippet').bind('keydown', function( event ){ - if(navigator.userAgent.match("Gecko")) - { - c=event.which; - } - else - { - c=event.keyCode; - } - if(c==9) - { - replaceSelection(document.getElementById('id_snippet'),String.fromCharCode(9)); - setTimeout(document.getElementById('id_snippet'),0); - return false; - } - }); - - $('#id_description').bind('focus', function( event ){ - document.getElementById("id_description").rows=5; - document.getElementById("id_description").cols=40; - }); - - $('#id_description').bind('blur', function( event ){ - document.getElementById("id_description").rows=1; - document.getElementById("id_description").cols=40; - }); - - $('#id_description').bind('keypress', function (event){ - document.getElementById('my').innerHTML = document.getElementById('id_description').value ; - }); - - $('#id_test').bind('focus', function( event ){ - document.getElementById("id_test").rows=5; - document.getElementById("id_test").cols=40; - }); - - $('#id_test').bind('blur', function( event ){ - document.getElementById("id_test").rows=1; - document.getElementById("id_test").cols=40; - }); - - $('#id_options').bind('focus', function( event ){ - document.getElementById("id_options").rows=5; - document.getElementById("id_options").cols=40; - }); - $('#id_options').bind('blur', function( event ){ - document.getElementById("id_options").rows=1; - document.getElementById("id_options").cols=40; - }); - - $('#id_snippet').bind('focus', function( event ){ - document.getElementById("id_snippet").rows=5; - document.getElementById("id_snippet").cols=40; - }); - $('#id_snippet').bind('blur', function( event ){ - document.getElementById("id_snippet").rows=1; - document.getElementById("id_snippet").cols=40; - }); - - - $('#id_type').bind('focus', function(event){ - var type = document.getElementById('id_type'); - type.style.border = '1px solid #ccc'; - }); - - $('#id_language').bind('focus', function(event){ - var language = document.getElementById('id_language'); - language.style.border = '1px solid #ccc'; - }); - - $('#id_type').bind('change',function(event){ - var value = document.getElementById('id_type').value; - if(value == 'mcq' || value == 'mcc') - { - document.getElementById('id_options').style.visibility='visible'; - document.getElementById('label_option').innerHTML="Options :"; - } - else - { - document.getElementById('id_options').style.visibility='hidden'; - document.getElementById('label_option').innerHTML = ""; - } - }); - document.getElementById('my').innerHTML = document.getElementById('id_description').value ; - var value = document.getElementById('id_type').value; - if(value == 'mcq' || value == 'mcc') - { - document.getElementById('id_options').style.visibility='visible'; - document.getElementById('label_option').innerHTML="Options :" - } - else - { - document.getElementById('id_options').style.visibility='hidden'; - document.getElementById('label_option').innerHTML = ""; - } -} - -function autosubmit() -{ - var language = document.getElementById('id_language'); - if(language.value == 'select') - { - language.style.border="solid red"; - return false; - } - var type = document.getElementById('id_type'); - if(type.value == 'select') - { - type.style.border = 'solid red'; - return false; - } - - - if (type.value == 'mcq' || type.value == 'mcc') - { - var value = document.getElementById('id_options').value; - if(value.split('\n').length < 4) - { - alert("Please Enter 4 options. One option per line."); - return false; - } - return true; - } - -} diff --git a/testapp/yaksh_app/static/yaksh_app/js/add_questionpaper.js b/testapp/yaksh_app/static/yaksh_app/js/add_questionpaper.js deleted file mode 100644 index 6185dd5..0000000 --- a/testapp/yaksh_app/static/yaksh_app/js/add_questionpaper.js +++ /dev/null @@ -1,25 +0,0 @@ -function load_data() -{ - var url_root = document.getElementById('url_root').value; - var value = document.getElementById('mode').value; - var pathArray = window.location.pathname.split( '/' ); - length = pathArray.length; - var digit = parseInt(pathArray[length-2]); - - if (! isNaN(digit) && value == 'Automatic') - { - window.location = url_root + "/exam/manage/designquestionpaper/automatic/" + digit; - } - else if(!isNaN(digit) && value == 'Manual') - { - window.location = url_root + "/exam/manage/designquestionpaper/manual/" + digit; - } - else if(value == 'Automatic') - { - window.location = window.location.pathname + "automatic"; - } - else if( value == 'Manual') - { - window.location = window.location.pathname + "manual"; - } -} diff --git a/testapp/yaksh_app/static/yaksh_app/js/add_quiz.js b/testapp/yaksh_app/static/yaksh_app/js/add_quiz.js deleted file mode 100644 index 184881c..0000000 --- a/testapp/yaksh_app/static/yaksh_app/js/add_quiz.js +++ /dev/null @@ -1,11 +0,0 @@ -function test() -{ - - document.getElementById('id_duration').setAttribute('class','mini-text'); - document.getElementById('id_pass_criteria').setAttribute('class','mini-text'); - document.getElementById('id_start_date').setAttribute('class','date-text'); - if (document.getElementById("id_description").value != "") - { - document.getElementById("submit").innerHTML = "Save"; - } -} diff --git a/testapp/yaksh_app/static/yaksh_app/js/bootstrap-modal.js b/testapp/yaksh_app/static/yaksh_app/js/bootstrap-modal.js deleted file mode 100644 index b328217..0000000 --- a/testapp/yaksh_app/static/yaksh_app/js/bootstrap-modal.js +++ /dev/null @@ -1,260 +0,0 @@ -/* ========================================================= - * bootstrap-modal.js v1.4.0 - * http://twitter.github.com/bootstrap/javascript.html#modal - * ========================================================= - * Copyright 2011 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================================================= */ - - -!function( $ ){ - - "use strict" - - /* CSS TRANSITION SUPPORT (https://gist.github.com/373874) - * ======================================================= */ - - var transitionEnd - - $(document).ready(function () { - - $.support.transition = (function () { - var thisBody = document.body || document.documentElement - , thisStyle = thisBody.style - , support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined - return support - })() - - // set CSS transition event type - if ( $.support.transition ) { - transitionEnd = "TransitionEnd" - if ( $.browser.webkit ) { - transitionEnd = "webkitTransitionEnd" - } else if ( $.browser.mozilla ) { - transitionEnd = "transitionend" - } else if ( $.browser.opera ) { - transitionEnd = "oTransitionEnd" - } - } - - }) - - - /* MODAL PUBLIC CLASS DEFINITION - * ============================= */ - - var Modal = function ( content, options ) { - this.settings = $.extend({}, $.fn.modal.defaults, options) - this.$element = $(content) - .delegate('.close', 'click.modal', $.proxy(this.hide, this)) - - if ( this.settings.show ) { - this.show() - } - - return this - } - - Modal.prototype = { - - toggle: function () { - return this[!this.isShown ? 'show' : 'hide']() - } - - , show: function () { - var that = this - this.isShown = true - this.$element.trigger('show') - - escape.call(this) - backdrop.call(this, function () { - var transition = $.support.transition && that.$element.hasClass('fade') - - that.$element - .appendTo(document.body) - .show() - - if (transition) { - that.$element[0].offsetWidth // force reflow - } - - that.$element.addClass('in') - - transition ? - that.$element.one(transitionEnd, function () { that.$element.trigger('shown') }) : - that.$element.trigger('shown') - - }) - - return this - } - - , hide: function (e) { - e && e.preventDefault() - - if ( !this.isShown ) { - return this - } - - var that = this - this.isShown = false - - escape.call(this) - - this.$element - .trigger('hide') - .removeClass('in') - - $.support.transition && this.$element.hasClass('fade') ? - hideWithTransition.call(this) : - hideModal.call(this) - - return this - } - - } - - - /* MODAL PRIVATE METHODS - * ===================== */ - - function hideWithTransition() { - // firefox drops transitionEnd events :{o - var that = this - , timeout = setTimeout(function () { - that.$element.unbind(transitionEnd) - hideModal.call(that) - }, 500) - - this.$element.one(transitionEnd, function () { - clearTimeout(timeout) - hideModal.call(that) - }) - } - - function hideModal (that) { - this.$element - .hide() - .trigger('hidden') - - backdrop.call(this) - } - - function backdrop ( callback ) { - var that = this - , animate = this.$element.hasClass('fade') ? 'fade' : '' - if ( this.isShown && this.settings.backdrop ) { - var doAnimate = $.support.transition && animate - - this.$backdrop = $('') - .appendTo(document.body) - - if ( this.settings.backdrop != 'static' ) { - this.$backdrop.click($.proxy(this.hide, this)) - } - - if ( doAnimate ) { - this.$backdrop[0].offsetWidth // force reflow - } - - this.$backdrop.addClass('in') - - doAnimate ? - this.$backdrop.one(transitionEnd, callback) : - callback() - - } else if ( !this.isShown && this.$backdrop ) { - this.$backdrop.removeClass('in') - - $.support.transition && this.$element.hasClass('fade')? - this.$backdrop.one(transitionEnd, $.proxy(removeBackdrop, this)) : - removeBackdrop.call(this) - - } else if ( callback ) { - callback() - } - } - - function removeBackdrop() { - this.$backdrop.remove() - this.$backdrop = null - } - - function escape() { - var that = this - if ( this.isShown && this.settings.keyboard ) { - $(document).bind('keyup.modal', function ( e ) { - if ( e.which == 27 ) { - that.hide() - } - }) - } else if ( !this.isShown ) { - $(document).unbind('keyup.modal') - } - } - - - /* MODAL PLUGIN DEFINITION - * ======================= */ - - $.fn.modal = function ( options ) { - var modal = this.data('modal') - - if (!modal) { - - if (typeof options == 'string') { - options = { - show: /show|toggle/.test(options) - } - } - - return this.each(function () { - $(this).data('modal', new Modal(this, options)) - }) - } - - if ( options === true ) { - return modal - } - - if ( typeof options == 'string' ) { - modal[options]() - } else if ( modal ) { - modal.toggle() - } - - return this - } - - $.fn.modal.Modal = Modal - - $.fn.modal.defaults = { - backdrop: false - , keyboard: false - , show: false - } - - - /* MODAL DATA- IMPLEMENTATION - * ========================== */ - - $(document).ready(function () { - $('body').delegate('[data-controls-modal]', 'click', function (e) { - e.preventDefault() - var $this = $(this).data('show', true) - $('#' + $this.attr('data-controls-modal')).modal( $this.data() ) - }) - }) - -}( window.jQuery || window.ender ); diff --git a/testapp/yaksh_app/static/yaksh_app/js/bootstrap-tabs.js b/testapp/yaksh_app/static/yaksh_app/js/bootstrap-tabs.js deleted file mode 100644 index a3c7ee1..0000000 --- a/testapp/yaksh_app/static/yaksh_app/js/bootstrap-tabs.js +++ /dev/null @@ -1,80 +0,0 @@ -/* ======================================================== - * bootstrap-tabs.js v1.4.0 - * http://twitter.github.com/bootstrap/javascript.html#tabs - * ======================================================== - * Copyright 2011 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ======================================================== */ - - -!function( $ ){ - - "use strict" - - function activate ( element, container ) { - container - .find('> .active') - .removeClass('active') - .find('> .dropdown-menu > .active') - .removeClass('active') - - element.addClass('active') - - if ( element.parent('.dropdown-menu') ) { - element.closest('li.dropdown').addClass('active') - } - } - - function tab( e ) { - var $this = $(this) - , $ul = $this.closest('ul:not(.dropdown-menu)') - , href = $this.attr('href') - , previous - , $href - - if ( /^#\w+/.test(href) ) { - e.preventDefault() - - if ( $this.parent('li').hasClass('active') ) { - return - } - - previous = $ul.find('.active a').last()[0] - $href = $(href) - - activate($this.parent('li'), $ul) - activate($href, $href.parent()) - - $this.trigger({ - type: 'change' - , relatedTarget: previous - }) - } - } - - - /* TABS/PILLS PLUGIN DEFINITION - * ============================ */ - - $.fn.tabs = $.fn.pills = function ( selector ) { - return this.each(function () { - $(this).delegate(selector || '.tabs li > a, .pills > li > a', 'click', tab) - }) - } - - $(document).ready(function () { - $('body').tabs('ul[data-tabs] li > a, ul[data-pills] > li > a') - }) - -}( window.jQuery || window.ender ); diff --git a/testapp/yaksh_app/static/yaksh_app/js/edit_question.js b/testapp/yaksh_app/static/yaksh_app/js/edit_question.js deleted file mode 100644 index 7a0f56d..0000000 --- a/testapp/yaksh_app/static/yaksh_app/js/edit_question.js +++ /dev/null @@ -1,278 +0,0 @@ -function render_question(frm) -{ - for(var i=1;i<=frm.description.length;i++) - { - document.getElementById('my'+i).innerHTML = frm.description[i-1].value; - } - -} - -function increase(frm,n) -{ - var newValue = document.getElementById('id_points'+ (n-1)).value ; - - if( newValue == "") - { - document.getElementById('id_points'+(n-1)).value = "0.5"; - return; - } - document.getElementById('id_points' + (n-1)).value = parseFloat(newValue) + 0.5; -} - -function decrease(frm,n) -{ - var newValue = document.getElementById('id_points'+ (n-1)).value ; - - if( newValue > 0) - { - document.getElementById('id_points' + (n-1)).value = parseFloat(newValue) - 0.5; - } - else - { - document.getElementById('id_points' + (n-1)).value = 0; - } -} - -function grade_data(showHideDiv) -{ - var ele=document.getElementById(showHideDiv); - if (ele.style.display=="block") - { - ele.style.display = "none"; - } - else - { - ele.style.display = "block"; - } -} - -function setSelectionRange(input, selectionStart, selectionEnd) -{ - if (input.setSelectionRange) - { - input.focus(); - input.setSelectionRange(selectionStart, selectionEnd); - } - else if (input.createTextRange) - { - var range = input.createTextRange(); - range.collapse(true); - range.moveEnd('character', selectionEnd); - range.moveStart('character', selectionStart); - range.select(); - } -} - -function replaceSelection (input, replaceString) -{ - if (input.setSelectionRange) - { - var selectionStart = input.selectionStart; - var selectionEnd = input.selectionEnd; - input.value = input.value.substring(0, selectionStart)+ replaceString + input.value.substring(selectionEnd); - if (selectionStart != selectionEnd) - { - setSelectionRange(input, selectionStart, selectionStart + replaceString.length); - } - else - { - setSelectionRange(input, selectionStart + replaceString.length, selectionStart + replaceString.length); - } - } - else if (document.selection) - { - var range = document.selection.createRange(); - if (range.parentElement() == input) - { - var isCollapsed = range.text == ''; - range.text = replaceString; - if (!isCollapsed) - { - range.moveStart('character', -replaceString.length); - range.select(); - } - } - } -} - -function data(showContent,showHideDiv,a,summary) -{ - var con = document.getElementById(showContent); - var ele=document.getElementById(showHideDiv); - var atag=document.getElementById(a); - if (ele.style.display=="block") - { - con.style.display = "none" - ele.style.display = "none"; - atag.text = summary; - } - else - { - con.style.display = "block"; - ele.style.display = "block"; - } -} - -function textareaformat() -{ - var point = document.getElementsByName('points'); - var test = document.getElementsByName('test'); - var option = document.getElementsByName('options'); - var descriptions = document.getElementsByName('description'); - var snippets = document.getElementsByName('snippet'); - var language = document.getElementsByName('language') - var type = document.getElementsByName('type'); - var tags = document.getElementsByName('tags'); - for (var i=0;i 0) - { - alert('Enter 4 options. One option per line.'); - return false; - } - return true; -} diff --git a/testapp/yaksh_app/static/yaksh_app/js/edit_quiz.js b/testapp/yaksh_app/static/yaksh_app/js/edit_quiz.js deleted file mode 100644 index ce6dac7..0000000 --- a/testapp/yaksh_app/static/yaksh_app/js/edit_quiz.js +++ /dev/null @@ -1,9 +0,0 @@ -function form_load() -{ - var tags = document.getElementsByName('tags'); - - for (var i=0;i )[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, -Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& -(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, -a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== -"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, -function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b a"; -var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, -parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= -false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= -s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, -applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; -else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, -a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== -w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, -cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d
-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j =0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= -c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); -a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, -function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); -k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), -C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B =0){a.type= -e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& -f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; -if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e -1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", -e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, -"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, -d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j 0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, -e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); -t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| -g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h ":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m =0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, -CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, -g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, -text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, -setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= -h[3];l=0;for(m=h.length;l =0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== -"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, -h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l ";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& -q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; -if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); -(function(){var g=s.createElement("div");g.innerHTML="";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: -function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q =0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f
0)for(var j=d;j 0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= -{},i;if(f&&a.length){e=0;for(var o=a.length;e -1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== -"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", -d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? -a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== -1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"+d+">"},F={option:[1,""],legend:[1,""],thead:[1," ","
"],tr:[2,"","
"],td:[3,""],col:[2,"
"," "],area:[1,""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
"," ",""];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= -c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, -wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, -prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, -this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); -return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, -""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); -return this}else{e=0;for(var j=d.length;e 0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", -""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===" "&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= -c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? -c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= -function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= -Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, -"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= -a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= -a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/ - -{% endblock %} - -{% block onload %} onload='javascript:textareaformat();' {% endblock %} - -{% block manage %} -
- {% csrf_token %} - -{% endblock %} - diff --git a/testapp/yaksh_app/templates/yaksh_app/add_questionpaper.html b/testapp/yaksh_app/templates/yaksh_app/add_questionpaper.html deleted file mode 100644 index 049abbe..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/add_questionpaper.html +++ /dev/null @@ -1,27 +0,0 @@ -{% extends "manage.html" %} - - -{% block subtitle %}Design Question Paper{% endblock %} - -{% block css %} - - -{% endblock %} -{% block script %} - - -{% endblock %} - -{% block manage %} - -- -
Summary: {{ form.summary }}{{ form.summary.errors }} - Language: {{form.language}}{{form.language.errors}} - Active: {{ form.active }}{{form.active.errors}} Type: {{ form.type }}{{form.type.errors}} - Points: {{ form.points }}{{ form.points.errors }} - Rendered: - Description: {{ form.description}} {{form.description.errors}} - - Snippet: {{ form.snippet }}{{ form.snippet.errors }} Tags: {{ form.tags }} - Options: {{ form.options }} {{form.options.errors}} - Test: {{ form.test }} {{form.test.errors}} - Reference Code Path: {{ form.ref_code_path }} {{form.ref_code_path.errors}} - - - {% if formset%} - {{ formset.management_form }} - {% for form in formset %} - {{ form }} - {% endfor %} - {% endif %} - -- -
-- --{% csrf_token %} -Select mode to design Question Paper: - - - -{% endblock %} diff --git a/testapp/yaksh_app/templates/yaksh_app/add_quiz.html b/testapp/yaksh_app/templates/yaksh_app/add_quiz.html deleted file mode 100644 index ded8e9b..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/add_quiz.html +++ /dev/null @@ -1,25 +0,0 @@ -{% extends "manage.html" %} - - -{% block subtitle %}Add Quiz{% endblock %} - -{% block css %} - -{% endblock %} -{% block script %} - -{% endblock %} -{% block onload %} onload="javascript:test();" {% endblock %} -{% block manage %} -- {% csrf_token %} - -{% endblock %} diff --git a/testapp/yaksh_app/templates/yaksh_app/ajax_marks.html b/testapp/yaksh_app/templates/yaksh_app/ajax_marks.html deleted file mode 100644 index 716bb88..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/ajax_marks.html +++ /dev/null @@ -1,4 +0,0 @@ - -{% for mark in marks %} - -{% endfor %} diff --git a/testapp/yaksh_app/templates/yaksh_app/ajax_question_filter.html b/testapp/yaksh_app/templates/yaksh_app/ajax_question_filter.html deleted file mode 100644 index 11bf660..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/ajax_question_filter.html +++ /dev/null @@ -1,15 +0,0 @@ -- - -- {{ form.as_table }} -
-- -- {% if questions %} -diff --git a/testapp/yaksh_app/templates/yaksh_app/ajax_questions.html b/testapp/yaksh_app/templates/yaksh_app/ajax_questions.html deleted file mode 100644 index e343f9b..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/ajax_questions.html +++ /dev/null @@ -1,31 +0,0 @@ -Select All
- {% endif %} -- - {% for question in questions %} -
-- - -
- {% endfor %} -- {% if questions %} - - Select All - {% endif %} -- -- - {% for question in questions %} -
-- - -
- {% endfor %} -- -diff --git a/testapp/yaksh_app/templates/yaksh_app/automatic_questionpaper.html b/testapp/yaksh_app/templates/yaksh_app/automatic_questionpaper.html deleted file mode 100644 index f9c222a..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/automatic_questionpaper.html +++ /dev/null @@ -1,87 +0,0 @@ -{% extends "manage.html" %} - - -{% block subtitle %}Design Question Paper{% endblock %} - -{% block css %} - - - -{% endblock %} -{% block script %} - - -{% endblock %} - -{% block manage %} - -Automatic mode to design the Question Paper
-- {% csrf_token %} - - -{% endblock %} diff --git a/testapp/yaksh_app/templates/yaksh_app/complete.html b/testapp/yaksh_app/templates/yaksh_app/complete.html deleted file mode 100644 index 08abe76..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/complete.html +++ /dev/null @@ -1,33 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Good bye!{% endblock %} - -{% block pagetitle %}Online Test{% endblock %} -{% block content %} -{% csrf_token %} - {% if submitted or unattempted %} -- Tag Conditions: - - - - - - - - - - - -
- -Number of question: - -
-
-Below is the list of Questions fetched according to the given tag conditions
-
--
- {% if data.msg %}Summary - Type - Points - Tags - {% for question in data.questions %} - - - {{ question.summary }} {{ question.type }} {{ question.points }} - {% for tag in question.tags.all %} - {{ tag }} - {% endfor %} -
- {% endfor %} -{{ data.msg }}{% endif %} -- - {% endif %} - -
- Submitted Questions -- {% if submitted %} - {{ submitted|join:", " }} - {% else %} - No Questions have been Submitted
- {% endif %} -- Unattempted Questions -- {% if unattempted %} - {{ unattempted|join:", " }} - {% else %} - All Questions have been Submitted
- {% endif %} -- Good bye!
- {{message}}
You may now close the browser.
-Login Again -{% endblock content %} diff --git a/testapp/yaksh_app/templates/yaksh_app/design_questionpaper.html b/testapp/yaksh_app/templates/yaksh_app/design_questionpaper.html deleted file mode 100644 index f999cb1..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/design_questionpaper.html +++ /dev/null @@ -1,182 +0,0 @@ -{% extends "manage.html" %} - -{% block subtitle %}Design Question Paper{% endblock %} - -{% block css %} - - - - - -{% endblock %} -{% block script %} - - - - - - -{% endblock %} - -{% block manage %} - -Manual mode to design the {{lang}} Question Paper
--
- -- - - STEP 1
-
- Add Fixed Questions - -- - - STEP 2
-
- Add Random Questions - -- - - STEP 3
-
- Finish -{% csrf_token %} - ---Total Marks: 0
-- -- ---Please select Question type and Marks
-- {{ form.question_type }} --- {{ form.marks }} --- --
- - - - - - - ---- -Almost finished creating your question paper
-
- - -
-- < Previous --
- - - --- --- --- - - -{% endblock %} diff --git a/testapp/yaksh_app/templates/yaksh_app/edit_question.html b/testapp/yaksh_app/templates/yaksh_app/edit_question.html deleted file mode 100644 index 7aad7de..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/edit_question.html +++ /dev/null @@ -1,61 +0,0 @@ -{% extends "manage.html" %} - -{% block subtitle %}Edit Question{% endblock %} - -{% block css %} - - -{% endblock %} -{% block script %} - - -{% endblock %} - -{% block onload %} onload = 'javascript:textareaformat();' {% endblock %} - -{% block manage %} --- -- {% csrf_token %} - -{% endblock %} diff --git a/testapp/yaksh_app/templates/yaksh_app/edit_quiz.html b/testapp/yaksh_app/templates/yaksh_app/edit_quiz.html deleted file mode 100644 index c8a36e7..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/edit_quiz.html +++ /dev/null @@ -1,39 +0,0 @@ -{% extends "manage.html" %} - - -{% block subtitle %}Edit Quiz(zes){% endblock %} - -{% block css %} - -{% endblock %} - -{% block script %} - -{% endblock %} - -{% block onload %} onload = 'javascript:form_load();' {% endblock %} - -{% block manage %} -- - Click on the Question links to edit the question.
- - {% for question, test in data_list %} - -
- - -{% for i in data %} - -{% endfor %} - -{{question.summary.value}} - - - {% endfor %} - - -- {% csrf_token %} - -{% endblock %} diff --git a/testapp/yaksh_app/templates/yaksh_app/editquestionpaper.html b/testapp/yaksh_app/templates/yaksh_app/editquestionpaper.html deleted file mode 100644 index 90038b4..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/editquestionpaper.html +++ /dev/null @@ -1,21 +0,0 @@ -{% extends "manage.html" %} - - -{% block subtitle %}Questions in "{{ papers.quiz.description }}"{% endblock %} - -{% block script %} - -{% endblock %} - -{% block manage %} -- -{% for i in data %} - -{% endfor %} -- {% for form in forms %} -
-Start Date: {{ form.start_date}} - Duration: {{ form.duration }}
{{form.duration.help_text}} -Active: {{ form.active }} - Description: {{ form.description }} - Passing Criteria: {{ form.pass_criteria }}
{{form.pass_criteria.help_text}} -Language: {{ form.language }} - Prerequisite: {{ form.prerequisite }} -
- {% endfor %} -- --{% csrf_token %} - -{% for i in papers.questions %} - {{ i.summary}} -{% endblock %} diff --git a/testapp/yaksh_app/templates/yaksh_app/grade_user.html b/testapp/yaksh_app/templates/yaksh_app/grade_user.html deleted file mode 100644 index 1447337..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/grade_user.html +++ /dev/null @@ -1,94 +0,0 @@ -{% extends "manage.html" %} - -{% block title %} Grading papers for {{ data.user.get_full_name.title }} {% endblock title %} - -{% block subtitle %}Grading papers for {{ data.user.get_full_name.title }}{% endblock %} - -{% block css %} - -{% endblock %} - -{% block script %} - -{% endblock %} -{% block manage %} - -
-{% endfor %} -
- - --Name: {{ data.user.get_full_name.title }} -{% if data.profile %} -(roll number: {{ data.profile.roll_number }})
- -{% if data.papers %} - -{% for paper in data.papers %} - -
-{{ data.profile.position }}, -{{ data.profile.department }}, -{{ data.profile.institute }} -{% endif %} -Quiz: {{ paper.quiz.description }}
- --Questions correctly answered: {{ paper.get_answered_str }}
- -{% if paper.answers.count %} -
-Total attempts at questions: {{ paper.answers.count }}
-Marks obtained: {{ paper.get_total_marks }}
-Start time: {{ paper.start_time }}
-Answers
--{% csrf_token %} -{% for question, answers in paper.get_question_answers.items %} - -{% endif %} {# if paper.answers.count #} - -{% endfor %} {# for paper in data.papers #} - -{% endif %} {# if data.papers #} - -{% endblock%} diff --git a/testapp/yaksh_app/templates/yaksh_app/intro.html b/testapp/yaksh_app/templates/yaksh_app/intro.html deleted file mode 100644 index 9c5c14d..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/intro.html +++ /dev/null @@ -1,53 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Instructions and Rules {% endblock %} -{% block pagetitle %}Online Test {% endblock %} -{% block formtitle %}Important instructions & rules {% endblock %} -{% block content %} - - {% if enable_quiz_time or disable_quiz_time %} - {% if quiz_expired %} ---{% endfor %} {# for question, answers ... #} - - -- Question: {{ question.id }}. {{ question.summary }} (Points: {{ question.points }}) - -Details
--- -- -{% if question.type == "mcq" %} --
-Choices: -{% for option in question.options.strip.splitlines %} {{option}}, {% endfor %} -
-Student answer: {{ answers.0 }}
-{% else %}{# non-mcq questions #} --{% for answer in answers %}################################################################################ -{{ answer.answer.strip }} -# Autocheck: {{ answer.error }} -{% endfor %}-{% endif %} {# if question.type #} -{% with answers|last as answer %} -Marks:
-{% endwith %} -Teacher comments:
- -
-
- -- This Quiz has expired. You can no longer attempt this Quiz. -- {% else %} -
-- You can attempt this Quiz at any time between {{ enable_quiz_time }} and {{ disable_quiz_time }} -- {% endif %} - {% endif %} -
- You are not allowed to attempt the Quiz before or after this duration -
-Welcome {{user.first_name.title}} {{user.last_name.title}}, to the programming quiz!
-- This examination system has been developed with the intention of making you - learn programming and be assessed in an interactive and fun manner. - You will be presented with a series of programming questions and problems that - you will answer online and get immediate feedback for. -
-Here are some important instructions and rules that you should understand carefully.
--
-- For any programming questions, you can submit solutions as many times as you want without a penalty. You may skip questions and solve them later. -
-- You may use your computer's Python/IPython shell or an editor to solve the problem and cut/paste the solution to the web interface. -
-- You are not allowed to use any internet resources, i.e. no google etc.
-- Do not copy or share the questions or answers with anyone until the exam is complete for everyone.
-- All your attempts at the questions are logged. Do not try to outsmart and break the testing system. If you do, we know who you are and we will expell you from the course. You have been warned. -
-We hope you enjoy taking this exam !!!
- -- {% csrf_token %} - - {% if not quiz_expired %} -- - {% csrf_token %} - - {% endif %} -{% endblock content %} diff --git a/testapp/yaksh_app/templates/yaksh_app/login.html b/testapp/yaksh_app/templates/yaksh_app/login.html deleted file mode 100644 index 341d7a7..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/login.html +++ /dev/null @@ -1,22 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Login{% endblock title %} -{% block pagetitle %} Online Test {% endblock %} -{% block formtitle %}Login{% endblock %} -{% block css %} - -{% endblock %} -{% block content %} - -- - {% csrf_token %} - - - -{% endblock content %} diff --git a/testapp/yaksh_app/templates/yaksh_app/manual_questionpaper.html b/testapp/yaksh_app/templates/yaksh_app/manual_questionpaper.html deleted file mode 100644 index 9e2a082..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/manual_questionpaper.html +++ /dev/null @@ -1,79 +0,0 @@ -{% extends "manage.html" %} - - -{% block subtitle %}Design Question Paper{% endblock %} - -{% block css %} - - - -{% endblock %} -{% block script %} - - -{% endblock %} - -{% block manage %} - -- - {{ form.as_table }} -
- Forgot Password?
-New User? Sign-Up -Manual mode to design the Question Paper
- -- {% csrf_token %} - - -{% endblock %} diff --git a/testapp/yaksh_app/templates/yaksh_app/monitor.html b/testapp/yaksh_app/templates/yaksh_app/monitor.html deleted file mode 100644 index 261dffd..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/monitor.html +++ /dev/null @@ -1,69 +0,0 @@ -{% extends "manage.html" %} - -{% block title %} Quiz results {% endblock title %} - -{% block meta %} {% endblock meta %} - -{% block css %} - -{% endblock %} -{% block subtitle %} - {% if not quizzes and not quiz %} - Quiz Results - {% endif %} - {% if quizzes %} - Available Quizzes - {% endif %} - {% if quiz %} - {{ quiz.description }} Results - {% endif %} -{% endblock %} -{% block manage %} - {% if not quizzes and not quiz %} -- Tag Conditions: - - - - - - -
-- -
Below is the list of Questions fetched according to the given tag conditions
--
- {% if data.msg %}- Summary - Type - Points - Tags - {% for question in data.questions %} - - {{ question.summary }} {{ question.type }} {{ question.points }} - {% for tag in question.tags.all %} - {{ tag }} - {% endfor %} -
- {% endfor %} -{{ data.msg }}{% endif %} -- - {% endif %} - -{# ############################################################### #} -{# This is rendered when we are just viewing exam/monitor #} -{% if quizzes %} - No quizzes available.
-{% for q in quizzes %} -
-{% endif %} - -{# ############################################################### #} -{# This is rendered when we are just viewing exam/monitor/quiz_num #} -{% if quiz %} - -{% if papers %} -{#- {{ q.quiz.description }}
-{% endfor %} -Quiz: {{ quiz_name }}
#} -Number of papers: {{ papers|length }}
--
-{% else %} -- - {% for paper in papers %} -Name -Username -Roll number -Institute -Questions answered -Marks obtained -Attempts -- - {% endfor %} -{{ paper.user.get_full_name.title }} -{{ paper.user.username }} -{{ paper.profile.roll_number }} -{{ paper.profile.institute }} -{{ paper.get_answered_str }} -{{ paper.marks_obtained }} -{{ paper.answers.count }} -No answer papers so far.
-{% endif %} {# if papers #} -{% endif %} -{% endblock %} diff --git a/testapp/yaksh_app/templates/yaksh_app/question.html b/testapp/yaksh_app/templates/yaksh_app/question.html deleted file mode 100644 index 594693c..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/question.html +++ /dev/null @@ -1,203 +0,0 @@ -{% extends "base.html" %} - - - -{% block title %} Answer question {% endblock %} - -{% block css %} - - -{% endblock %} - -{% block script %} - - - - - -{% endblock script %} - - - -{% block onload %} onload="update_time();setSnippetHeight()" {% endblock %} - -{% block pagetitle %} - -- -{% endblock %} - -{% block content %} - -
-You have {{ paper.questions_left }} question(s) left in {{ quiz_name }}
- ---- - -{{ question.summary }} (Marks : {{ question.points }})
- {{ question.description|safe }} - {% if error_message %} -- {% for e in error_message.splitlines %} - {{ e|join:"" }} -{% endif %} - - - -
- {% endfor%} -- {% csrf_token %} - - - {% if question.type == "mcq" %} - {% for option in question.options.strip.splitlines %} - {{option}} - - - -
- {% endfor %} - {% endif %} - {% if question.type == "upload" %} -Upload assignment file for the said question
- -
- {% endif %} - {% if question.type == "mcc" %} - {% for option in question.options.strip.splitlines %} - {{ option }} -
- {% endfor %} - {% endif %} - {% if question.type == "code" %} - - - - -
- - - - {% endif %} - - {% if question.type == "mcq" or question.type == "mcc "%} -
- {% elif question.type == "upload" %} -
- {% else %} - - {% endif %} - {% if to_attempt|length != 1 %} - - {% endif %} --- -{% endblock content %} diff --git a/testapp/yaksh_app/templates/yaksh_app/quit.html b/testapp/yaksh_app/templates/yaksh_app/quit.html deleted file mode 100644 index 91bce64..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/quit.html +++ /dev/null @@ -1,35 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Quit exam {% endblock %} -{% block pagetitle %}Online Test {% endblock %} -{% block content %} - {% if submitted or unattempted %} --- -- {% endif %} - - -
- Submitted Questions -- {% if submitted %} - {{ submitted|join:", " }} - {% else %} - No Questions have been Submitted
- {% endif %} -- Unattempted Questions -- {% if unattempted %} - {{ unattempted|join:", " }} - {% else %} - All Questions have been Submitted
- {% endif %} -- Your current answers are saved.
- Are you sure you wish to quit the exam?
- Be sure, as you won't be able to restart this exam.
- {% csrf_token %} - -{% endblock content %} diff --git a/testapp/yaksh_app/templates/yaksh_app/quizlist.html b/testapp/yaksh_app/templates/yaksh_app/quizlist.html deleted file mode 100644 index 9b1fd73..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/quizlist.html +++ /dev/null @@ -1,24 +0,0 @@ -{% extends "base.html" %} - -{% block title %} Quiz List {% endblock title %} - -{% block formtitle %} Quiz List {% endblock %} - -{% block pagetitle %} Online Test {% endblock %} - -{% block content %} -{% if not quizzes and not quiz %} -- -{% endif %} - -{% if quizzes %} - No quizzes available.
-{% csrf_token %} - -{% for quiz in quizzes %} -{{ quiz.description }} -{% endif %} - -{% endblock %} diff --git a/testapp/yaksh_app/templates/yaksh_app/quizzes_user.html b/testapp/yaksh_app/templates/yaksh_app/quizzes_user.html deleted file mode 100644 index 94f9d0f..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/quizzes_user.html +++ /dev/null @@ -1,87 +0,0 @@ -{% extends "user.html" %} - - -{% block subtitle %}Hello {{ user.first_name }}, welcome to your dashboard !{% endblock %} - -{% block css %} - -{% endblock %} - -{% block script %} - - -{% endblock %} - - -{% block manage %} - {% if cannot_attempt %} -
-{% endfor %} -You have not passed the prerequisite & hence you cannot take the quiz.
- {% endif %} -List of quizzes availbale for you
- {% if not quizzes %} -No active quizzes for you
- {% endif %} --
-Quiz -Pre requisite quiz - {% for paper in quizzes %} -- {% if paper in unexpired_quizzes %} - - {% endfor %} -- {{ paper.quiz.description }} - {% else %} -
-- {{ paper.quiz.description }} Expired - {% endif %} -
-- {% if paper.quiz.prerequisite %} - You have to pass {{ paper.quiz.prerequisite.description }} for taking {{ paper.quiz.description }} - {% else %} - No pre requisites for {{ paper.quiz.description }} - {% endif %} - -
-List of quizzes taken by you so far
- {% if quizzes_taken %} --
- {% else %} -Quiz -Result -Mraks Obtained -Total Marks -Percentage - {% for paper in quizzes_taken %} -- - {% endfor %} -- {{ paper.question_paper.quiz.description }} - -- {% if paper.passed %} - -Pass
- {% else %} -Fail
- {% endif %} -- {{ paper.marks_obtained }} - -- {{ paper.question_paper.total_marks }} - -- {{ paper.percent }} - -You have not taken any quiz yet !!
- {% endif %} - - -{% endblock %} - diff --git a/testapp/yaksh_app/templates/yaksh_app/register.html b/testapp/yaksh_app/templates/yaksh_app/register.html deleted file mode 100644 index 5ff79cc..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/register.html +++ /dev/null @@ -1,20 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Registration form {% endblock %} - -{% block pagetitle %}Online Test {% endblock %} -{% block formtitle %}Please fill in the following details {% endblock %} - -{% block content %} - - - -- {% csrf_token %} - - -{% endblock content %} diff --git a/testapp/yaksh_app/templates/yaksh_app/results_user.html b/testapp/yaksh_app/templates/yaksh_app/results_user.html deleted file mode 100644 index fa8284e..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/results_user.html +++ /dev/null @@ -1,28 +0,0 @@ -{% extends "user.html" %} - - -{% block subtitle %}Results{% endblock %} - -{% block css %} - -{% endblock %} - -{% block manage %} -- - {{ form.as_table }} -
- - {% csrf_token %} - -{% endblock %} - diff --git a/testapp/yaksh_app/templates/yaksh_app/show_quiz.html b/testapp/yaksh_app/templates/yaksh_app/show_quiz.html deleted file mode 100644 index a3c1c44..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/show_quiz.html +++ /dev/null @@ -1,33 +0,0 @@ -{% extends "manage.html" %} - -{% block title %} Quiz List {% endblock title %} - -{% block script %} - -{% endblock %} - -{% block subtitle %} Quiz List {% endblock %} -{% block manage %} -{% if not quizzes and not quiz %} -- -
Quiz Description - Obtained Marks - Maximum Marks - Percentage - {% for paper in papers %} - - {% for i in paper %} - {{ i }} - {% endfor %} -
- {% endfor %} -- -{% endif %} - -{# ############################################################### #} -{# This is rendered when we are just viewing exam/monitor #} -{% if quizzes %} - No quizzes available.
-{% csrf_token %} - -{% for quiz in quizzes %} - {{ quiz.description }} -{% endif %} - -{% endblock %} diff --git a/testapp/yaksh_app/templates/yaksh_app/showquestionpapers.html b/testapp/yaksh_app/templates/yaksh_app/showquestionpapers.html deleted file mode 100644 index 2a04717..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/showquestionpapers.html +++ /dev/null @@ -1,23 +0,0 @@ -{% extends "manage.html" %} - - -{% block subtitle %}List of Question Papers {% endblock %} - -{% block script %} - -{% endblock %} - -{% block manage %} -{% if papers %} -
-{% endfor %} - -
- - - --{% csrf_token %} -{% for i in papers %} - {{ i.quiz.description }} -{% else %} -
-{% endfor %} -
- --{% endif %} -{% endblock %} diff --git a/testapp/yaksh_app/templates/yaksh_app/showquestions.html b/testapp/yaksh_app/templates/yaksh_app/showquestions.html deleted file mode 100644 index 0c8f9a4..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/showquestions.html +++ /dev/null @@ -1,44 +0,0 @@ -{% extends "manage.html" %} - - -{% block subtitle %}List of Questions {% endblock %} - -{% block script %} - - - -{% endblock %} - -{% block manage %} - No Question Papers available
-{% csrf_token %} - -{% endblock %} diff --git a/testapp/yaksh_app/templates/yaksh_app/showusers.html b/testapp/yaksh_app/templates/yaksh_app/showusers.html deleted file mode 100644 index 7b2bb6d..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/showusers.html +++ /dev/null @@ -1,26 +0,0 @@ -{% extends "manage.html" %} - - -{% block subtitle %} -List of Users -{% endblock %} - -{% block css %} - -{% endblock css %} - - -{% block manage %} ---Filters
-- {{ form.question_type }} --- {{ form.language }} --- {{ form.marks }} --
---- --
--{% for i in questions %} - {{ i }}-
-{% endfor %} -
- - - --{% endblock %} diff --git a/testapp/yaksh_app/templates/yaksh_app/user_data.html b/testapp/yaksh_app/templates/yaksh_app/user_data.html deleted file mode 100644 index 61a3a97..0000000 --- a/testapp/yaksh_app/templates/yaksh_app/user_data.html +++ /dev/null @@ -1,80 +0,0 @@ -{% extends "manage.html" %} - -{% block title %} Data for user {{ data.user.get_full_name.title }} {% endblock title %} - -{% block manage %} - -{% block subtitle %}Data for user {{ data.user.get_full_name.title }}{% endblock %} - -
Username - First Name - Last Name - Quiz Description -{% for papers in question %} - {{ papers.user.username }}
-{{ papers.user.first_name.title }} - {{ papers.user.last_name.title }} - {{ papers.question_paper.quiz.description }} -{% endfor %} - - -Name: {{ data.user.get_full_name.title }}
- -{% if data.papers %} - - -{% for paper in data.papers %} - -
-Username: {{ data.user.username }}
-{% if data.profile %} -Roll number: {{ data.profile.roll_number }}
-Position: {{ data.profile.position }}
-Department: {{ data.profile.department }}
-Institute: {{ data.profile.institute }}
-{% endif %} -Email: {{ data.user.email }}
-Date joined: {{ data.user.date_joined }}
-Last login: {{ data.user.last_login }} -Quiz: {{ paper.quiz.description }}
- --Questions correctly answered: {{ paper.get_answered_str }}
- -{% if paper.answers.count %} -
-Total attempts at questions: {{ paper.answers.count }}
-Marks obtained: {{ paper.get_total_marks }}
-Start time: {{ paper.start_time }}
-User IP address: {{ paper.user_ip }} -Answers
-{% for question, answers in paper.get_question_answers.items %} -Question: {{ question.id }}. {{ question.summary }} (Points: {{ question.points }})
-{% if question.type == "mcq" %} -Choices: -{% for option in question.options.strip.splitlines %} {{option}}, {% endfor %} -
-Student answer: {{ answers.0 }}
-{% else %}{# non-mcq questions #} --{% for answer in answers %}################################################################################ -{{ answer.answer.strip }} -# Autocheck: {{ answer.error }} -{% endfor %}-{% endif %} -{% with answers|last as answer %} -Marks: {{answer.marks}}
-{% endwith %} -{% endfor %} {# for question, answers ... #} -Teacher comments:
-{{ paper.comments|default:"None" }} -{% endif %} {# if paper.answers.count #} - -{% endfor %} {# for paper in data.papers #} - -{% endif %} {# if data.papers #} -
-
- - Grade/correct paper -
-{% if data.papers.count > 1 %} -Monitor quiz -{% else %} -{% with data.papers.0 as paper %} -Monitor quiz -{% endwith %} -{% endif %} - -{% endblock %} diff --git a/testapp/yaksh_app/tests.py b/testapp/yaksh_app/tests.py deleted file mode 100644 index fd6f6a9..0000000 --- a/testapp/yaksh_app/tests.py +++ /dev/null @@ -1,345 +0,0 @@ -from django.utils import unittest -from testapp.yaksh_app.models import User, Profile, Question, Quiz, QuestionPaper,\ - QuestionSet, AnswerPaper, Answer, TestCase -import datetime, json - -def setUpModule(): - # create user profile - user = User.objects.create_user(username='demo_user', - password='demo', - email='demo@test.com') - User.objects.create_user(username='demo_user2', - password='demo', - email='demo@test.com') - Profile.objects.create(user=user, roll_number=1, institute='IIT', - department='Chemical', position='Student') - - # create 20 questions - for i in range(1, 21): - Question.objects.create(summary='Q%d' % (i), points=1) - - # create a quiz - Quiz.objects.create(start_date='2014-06-16', duration=30, active=False, - attempts_allowed=-1, time_between_attempts=0, - description='demo quiz', pass_criteria=40, - language='Python', prerequisite=None) - - -def tearDownModule(): - User.objects.all().delete() - Question.objects.all().delete() - Quiz.objects.all().delete() - - -############################################################################### -class ProfileTestCases(unittest.TestCase): - def setUp(self): - self.user = User.objects.get(pk=1) - self.profile = Profile.objects.get(pk=1) - - def test_user_profile(self): - """ Test user profile""" - self.assertEqual(self.user.username, 'demo_user') - self.assertEqual(self.profile.user.username, 'demo_user') - self.assertEqual(int(self.profile.roll_number), 1) - self.assertEqual(self.profile.institute, 'IIT') - self.assertEqual(self.profile.department, 'Chemical') - self.assertEqual(self.profile.position, 'Student') - - -############################################################################### -class QuestionTestCases(unittest.TestCase): - def setUp(self): - # Single question details - # self.question = Question(summary='Demo question', language='Python', - # type='Code', active=True, - # description='Write a function', points=1.0, - # test='Test Cases', snippet='def myfunc()') - self.question = Question(summary='Demo question', language='Python', - type='Code', active=True, - description='Write a function', points=1.0, - snippet='def myfunc()') - self.question.save() - self.question.tags.add('python', 'function') - self.testcase = TestCase(question=self.question, - func_name='def myfunc', kw_args='a=10,b=11', - pos_args='12,13', expected_answer='15') - answer_data = { "test": "", - "user_answer": "demo_answer", - "test_parameter": [{"func_name": "def myfunc", - "expected_answer": "15", - "test_id": self.testcase.id, - "pos_args": ["12", "13"], - "kw_args": {"a": "10", - "b": "11"} - }], - "id": self.question.id, - "ref_code_path": "", - } - self.answer_data_json = json.dumps(answer_data) - self.user_answer = "demo_answer" - - def test_question(self): - """ Test question """ - self.assertEqual(self.question.summary, 'Demo question') - self.assertEqual(self.question.language, 'Python') - self.assertEqual(self.question.type, 'Code') - self.assertFalse(self.question.options) - self.assertEqual(self.question.description, 'Write a function') - self.assertEqual(self.question.points, 1.0) - self.assertTrue(self.question.active) - self.assertEqual(self.question.snippet, 'def myfunc()') - tag_list = [] - for tag in self.question.tags.all(): - tag_list.append(tag.name) - self.assertEqual(tag_list, ['python', 'function']) - - def test_consolidate_answer_data(self): - """ Test consolidate_answer_data function """ - result = self.question.consolidate_answer_data([self.testcase], - self.user_answer) - self.assertEqual(result, self.answer_data_json) - - - -############################################################################### -class TestCaseTestCases(unittest.TestCase): - def setUp(self): - self.question = Question(summary='Demo question', language='Python', - type='Code', active=True, - description='Write a function', points=1.0, - snippet='def myfunc()') - self.question.save() - self.testcase = TestCase(question=self.question, - func_name='def myfunc', kw_args='a=10,b=11', - pos_args='12,13', expected_answer='15') - - def test_testcase(self): - """ Test question """ - self.assertEqual(self.testcase.question, self.question) - self.assertEqual(self.testcase.func_name, 'def myfunc') - self.assertEqual(self.testcase.kw_args, 'a=10,b=11') - self.assertEqual(self.testcase.pos_args, '12,13') - self.assertEqual(self.testcase.expected_answer, '15') - - -############################################################################### -class QuizTestCases(unittest.TestCase): - def setUp(self): - self.quiz = Quiz.objects.get(pk=1) - - def test_quiz(self): - """ Test Quiz""" - self.assertEqual((self.quiz.start_date).strftime('%Y-%m-%d'), - '2014-06-16') - self.assertEqual(self.quiz.duration, 30) - self.assertTrue(self.quiz.active is False) - self.assertEqual(self.quiz.description, 'demo quiz') - self.assertEqual(self.quiz.language, 'Python') - self.assertEqual(self.quiz.pass_criteria, 40) - self.assertEqual(self.quiz.prerequisite, None) - - -############################################################################### -class QuestionPaperTestCases(unittest.TestCase): - @classmethod - def setUpClass(self): - # All active questions - self.questions = Question.objects.filter(active=True) - self.quiz = Quiz.objects.get(id=1) - - # create question paper - self.question_paper = QuestionPaper.objects.create(quiz=self.quiz, - total_marks=0.0, shuffle_questions=True) - - # add fixed set of questions to the question paper - self.question_paper.fixed_questions.add(self.questions[3], - self.questions[5]) - # create two QuestionSet for random questions - # QuestionSet 1 - self.question_set_1 = QuestionSet.objects.create(marks=2, - num_questions=2) - - # add pool of questions for random sampling - self.question_set_1.questions.add(self.questions[6], self.questions[7], - self.questions[8], self.questions[9]) - # add question set 1 to random questions in Question Paper - self.question_paper.random_questions.add(self.question_set_1) - - # QuestionSet 2 - self.question_set_2 = QuestionSet.objects.create(marks=3, - num_questions=3) - - # add pool of questions - self.question_set_2.questions.add(self.questions[11], - self.questions[12], - self.questions[13], - self.questions[14]) - # add question set 2 - self.question_paper.random_questions.add(self.question_set_2) - - # ip address for AnswerPaper - self.ip = '127.0.0.1' - - self.user = User.objects.get(pk=1) - - self.attempted_papers = AnswerPaper.objects.filter(question_paper=self.question_paper, - user=self.user) - - def test_questionpaper(self): - """ Test question paper""" - self.assertEqual(self.question_paper.quiz.description, 'demo quiz') - self.assertEqual(list(self.question_paper.fixed_questions.all()), - [self.questions[3], self.questions[5]]) - self.assertTrue(self.question_paper.shuffle_questions) - - def test_update_total_marks(self): - """ Test update_total_marks() method of Question Paper""" - self.assertEqual(self.question_paper.total_marks, 0) - self.question_paper.update_total_marks() - self.assertEqual(self.question_paper.total_marks, 15) - - def test_get_random_questions(self): - """ Test get_random_questions() method of Question Paper""" - random_questions_set_1 = self.question_set_1.get_random_questions() - random_questions_set_2 = self.question_set_2.get_random_questions() - - # To check whether random questions are from random_question_set - questions_set_1 = set(self.question_set_1.questions.all()) - random_set_1 = set(random_questions_set_1) - random_set_2 = set(random_questions_set_2) - boolean = questions_set_1.intersection(random_set_1) == random_set_1 - self.assertTrue(boolean) - self.assertEqual(len(random_set_1), 2) - # To check that the questions are random. - # If incase not random then check that the order is diferent - try: - self.assertFalse(random_set_1 == random_set_2) - except AssertionError: - self.assertTrue(random_questions_set_1 != random_questions_set_2) - - def test_get_questions_for_answerpaper(self): - """ Test get_questions_for_answerpaper() method of Question Paper""" - questions = self.question_paper._get_questions_for_answerpaper() - fixed = list(self.question_paper.fixed_questions.all()) - question_set = self.question_paper.random_questions.all() - total_random_questions = 0 - available_questions = [] - for qs in question_set: - total_random_questions += qs.num_questions - available_questions += qs.questions.all() - self.assertEqual(total_random_questions, 5) - self.assertEqual(len(available_questions), 8) - self.assertEqual(len(questions), 7) - - def test_make_answerpaper(self): - """ Test make_answerpaper() method of Question Paper""" - already_attempted = self.attempted_papers.count() - attempt_num = already_attempted + 1 - answerpaper = self.question_paper.make_answerpaper(self.user, self.ip, - attempt_num) - self.assertIsInstance(answerpaper, AnswerPaper) - paper_questions = set((answerpaper.questions).split('|')) - self.assertEqual(len(paper_questions), 7) - fixed = {'4', '6'} - boolean = fixed.intersection(paper_questions) == fixed - self.assertTrue(boolean) - - -############################################################################### -class AnswerPaperTestCases(unittest.TestCase): - @classmethod - def setUpClass(self): - self.ip = '101.0.0.1' - self.user = User.objects.get(id=1) - self.profile = self.user.profile - self.quiz = Quiz.objects.get(pk=1) - self.question_paper = QuestionPaper(quiz=self.quiz, total_marks=3) - self.question_paper.save() - - # create answerpaper - self.answerpaper = AnswerPaper(user=self.user, - questions='1|2|3', - question_paper=self.question_paper, - start_time='2014-06-13 12:20:19.791297', - end_time='2014-06-13 12:50:19.791297', - user_ip=self.ip) - self.answerpaper.questions_answered = '1' - self.attempted_papers = AnswerPaper.objects.filter(question_paper=self.question_paper, - user=self.user) - already_attempted = self.attempted_papers.count() - self.answerpaper.attempt_number = already_attempted + 1 - self.answerpaper.save() - - # answers for the Answer Paper - self.answer_right = Answer(question=Question.objects.get(id=1), - answer="Demo answer", correct=True, marks=1) - self.answer_wrong = Answer(question=Question.objects.get(id=2), - answer="My answer", correct=False, marks=0) - self.answer_right.save() - self.answer_wrong.save() - self.answerpaper.answers.add(self.answer_right) - self.answerpaper.answers.add(self.answer_wrong) - - def test_answerpaper(self): - """ Test Answer Paper""" - self.assertEqual(self.answerpaper.user.username, 'demo_user') - self.assertEqual(self.answerpaper.user_ip, self.ip) - questions = self.answerpaper.questions - num_questions = len(questions.split('|')) - self.assertEqual(questions, '1|2|3') - self.assertEqual(num_questions, 3) - self.assertEqual(self.answerpaper.question_paper, self.question_paper) - self.assertEqual(self.answerpaper.start_time, - '2014-06-13 12:20:19.791297') - self.assertEqual(self.answerpaper.end_time, - '2014-06-13 12:50:19.791297') - - def test_current_question(self): - """ Test current_question() method of Answer Paper""" - current_question = self.answerpaper.current_question() - self.assertEqual(current_question, '2') - - def test_completed_question(self): - """ Test completed_question() method of Answer Paper""" - question = self.answerpaper.completed_question(1) - self.assertEqual(self.answerpaper.questions_left(), 2) - - def test_questions_left(self): - """ Test questions_left() method of Answer Paper""" - self.assertEqual(self.answerpaper.questions_left(), 2) - - def test_skip(self): - """ Test skip() method of Answer Paper""" - current_question = self.answerpaper.current_question() - next_question_id = self.answerpaper.skip(current_question) - self.assertTrue(next_question_id is not None) - self.assertEqual(next_question_id, '3') - - def test_answered_str(self): - """ Test answered_str() method of Answer Paper""" - answered_question = self.answerpaper.get_answered_str() - self.assertEqual(answered_question, '1') - - def test_update_marks_obtained(self): - """ Test get_marks_obtained() method of Answer Paper""" - self.answerpaper.update_marks_obtained() - self.assertEqual(self.answerpaper.marks_obtained, 1.0) - - def test_update_percent(self): - """ Test update_percent() method of Answerpaper""" - self.answerpaper.update_percent() - self.assertEqual(self.answerpaper.percent, 33.33) - - def test_update_passed(self): - """ Test update_passed method of AnswerPaper""" - self.answerpaper.update_passed() - self.assertFalse(self.answerpaper.passed) - - def test_get_question_answer(self): - """ Test get_question_answer() method of Answer Paper""" - answered = self.answerpaper.get_question_answers() - first_answer = answered.values()[0][0] - self.assertEqual(first_answer.answer, 'Demo answer') - self.assertTrue(first_answer.correct) - self.assertEqual(len(answered), 2) diff --git a/testapp/yaksh_app/urls.py b/testapp/yaksh_app/urls.py deleted file mode 100644 index d096a61..0000000 --- a/testapp/yaksh_app/urls.py +++ /dev/null @@ -1,52 +0,0 @@ -from django.conf.urls import patterns, url - -urlpatterns = patterns('testapp.yaksh_app.views', - url(r'^$', 'index'), - url(r'^login/$', 'user_login'), - url(r'^quizzes/$', 'quizlist_user'), - url(r'^results/$', 'results_user'), - url(r'^start/$', 'start'), - url(r'^start/(?P\d+)/(?P \d+)/$', 'start'), - url(r'^quit/(?P \d+)/(?P \d+)/$', 'quit'), - url(r'^intro/(?P \d+)/$', 'intro'), - url(r'^complete/$', 'complete'), - url(r'^complete/(?P \d+)/(?P \d+)/$',\ - 'complete'), - url(r'^register/$', 'user_register'), - url(r'^(?P \d+)/$', 'question'), - url(r'^(?P \d+)/check/$', 'check'), - url(r'^(?P \d+)/check/(?P \d+)/(?P \d+)/$',\ - 'check'), - url(r'^intro/$', 'start'), - url(r'^(?P \d+)/(?P \d+)/(?P \d+)/$', 'show_question'), - - url(r'^manage/$', 'prof_manage'), - url(r'^manage/addquestion/$', 'add_question'), - url(r'^manage/addquestion/(?P \d+)/$', 'add_question'), - url(r'^manage/addquiz/$', 'add_quiz'), - url(r'^manage/editquiz/$', 'edit_quiz'), - url(r'^manage/editquestion/$', 'edit_question'), - url(r'^manage/addquiz/(?P \d+)/$', 'add_quiz'), - url(r'^manage/gradeuser/$', 'show_all_users'), - url(r'^manage/gradeuser/(?P .*)/$', 'grade_user'), - url(r'^manage/questions/$', 'show_all_questions'), - url(r'^manage/showquiz/$', 'show_all_quiz'), - url(r'^manage/monitor/$', 'monitor'), - url(r'^manage/showquestionpapers/$', 'show_all_questionpapers'), - url(r'^manage/showquestionpapers/(?P \d+)/$',\ - 'show_all_questionpapers'), - url(r'^manage/monitor/(?P \d+)/$', 'monitor'), - url(r'^manage/user_data/(?P .*)/$', 'user_data'), - url(r'^manage/designquestionpaper/$', 'design_questionpaper'), - url(r'^manage/designquestionpaper/(?P \d+)/$',\ - 'design_questionpaper'), - url(r'^manage/designquestionpaper/automatic/(?P \d+)/$',\ - 'automatic_questionpaper'), - url(r'^manage/designquestionpaper/automatic$', 'automatic_questionpaper'), - url(r'^manage/designquestionpaper/manual$', 'manual_questionpaper'), - url(r'^manage/designquestionpaper/manual/(?P \d+)/$',\ - 'manual_questionpaper'), - url(r'^ajax/questionpaper/(?P .+)/$', 'ajax_questionpaper'), - url(r'^ajax/questions/filter/$', 'ajax_questions_filter'), ##@@ - -) diff --git a/testapp/yaksh_app/views.py b/testapp/yaksh_app/views.py deleted file mode 100644 index e6aabc4..0000000 --- a/testapp/yaksh_app/views.py +++ /dev/null @@ -1,1502 +0,0 @@ -import random -import string -import os -import stat -from os.path import dirname, pardir, abspath, join, exists -import datetime -import collections -from django.http import HttpResponse -from django.contrib.auth import login, logout, authenticate -from django.shortcuts import render_to_response, get_object_or_404, redirect -from django.template import RequestContext -from django.http import Http404 -from django.db.models import Sum -from django.views.decorators.csrf import csrf_exempt -from taggit.models import Tag -from itertools import chain -import json -# Local imports. -from testapp.yaksh_app.models import Quiz, Question, QuestionPaper, QuestionSet -from testapp.yaksh_app.models import Profile, Answer, AnswerPaper, User, TestCase -from testapp.yaksh_app.forms import UserRegisterForm, UserLoginForm, QuizForm,\ - QuestionForm, RandomQuestionForm, TestCaseFormSet,\ - QuestionFilterForm -from testapp.yaksh_app.xmlrpc_clients import code_server -from settings import URL_ROOT -from testapp.yaksh_app.models import AssignmentUpload - -# The directory where user data can be saved. -OUTPUT_DIR = abspath(join(dirname(__file__), 'output')) - - -def my_redirect(url): - """An overridden redirect to deal with URL_ROOT-ing. See settings.py - for details.""" - return redirect(URL_ROOT + url) - - -def my_render_to_response(template, context=None, **kwargs): - """Overridden render_to_response. - """ - if context is None: - context = {'URL_ROOT': URL_ROOT} - else: - context['URL_ROOT'] = URL_ROOT - return render_to_response(template, context, **kwargs) - - -def gen_key(no_of_chars): - """Generate a random key of the number of characters.""" - allowed_chars = string.digits+string.uppercase - return ''.join([random.choice(allowed_chars) for i in range(no_of_chars)]) - - -def get_user_dir(user): - """Return the output directory for the user.""" - - user_dir = join(OUTPUT_DIR, str(user.username)) - if not exists(user_dir): - os.mkdir(user_dir) - # Make it rwx by others. - os.chmod(user_dir, stat.S_IROTH | stat.S_IWOTH | stat.S_IXOTH - | stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR - | stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP) - return user_dir - - -def is_moderator(user): - """Check if the user is having moderator rights""" - if user.groups.filter(name='moderator').count() == 1: - return True - - -def fetch_questions(request): - """Fetch questions from database based on the given search conditions & - tags""" - set1 = set() - set2 = set() - first_tag = request.POST.get('first_tag') - first_condition = request.POST.get('first_condition') - second_tag = request.POST.get('second_tag') - second_condition = request.POST.get('second_condition') - third_tag = request.POST.get('third_tag') - question1 = set(Question.objects.filter(tags__name__in=[first_tag])) - question2 = set(Question.objects.filter(tags__name__in=[second_tag])) - question3 = set(Question.objects.filter(tags__name__in=[third_tag])) - if first_condition == 'and': - set1 = question1.intersection(question2) - if second_condition == 'and': - set2 = set1.intersection(question3) - else: - set2 = set1.union(question3) - else: - set1 = question1.union(question2) - if second_condition == 'and': - set2 = set1.intersection(question3) - else: - set2 = set1.union(question3) - return set2 - - -def index(request): - """The start page. - """ - user = request.user - if user.is_authenticated(): - if user.groups.filter(name='moderator').count() > 0: - return my_redirect('/exam/manage/') - return my_redirect("/exam/start/") - - return my_redirect("/exam/login/") - - -def user_register(request): - """ Register a new user. - Create a user and corresponding profile and store roll_number also.""" - - user = request.user - ci = RequestContext(request) - if user.is_authenticated(): - return my_redirect("/exam/start/") - - if request.method == "POST": - form = UserRegisterForm(request.POST) - if form.is_valid(): - data = form.cleaned_data - u_name, pwd = form.save() - new_user = authenticate(username=u_name, password=pwd) - login(request, new_user) - return my_redirect("/exam/start/") - else: - return my_render_to_response('yaksh_app/register.html', {'form': form}, - context_instance=ci) - else: - form = UserRegisterForm() - return my_render_to_response('yaksh_app/register.html', {'form': form}, - context_instance=ci) - - -def quizlist_user(request): - """Show All Quizzes that is available to logged-in user.""" - user = request.user - avail_quizzes = list(QuestionPaper.objects.filter(quiz__active=True)) - user_answerpapers = AnswerPaper.objects.filter(user=user) - pre_requisites = [] - enabled_quizzes = [] - disabled_quizzes = [] - unexpired_quizzes = [] - - for paper in avail_quizzes: - quiz_enable_time = paper.quiz.start_date_time - quiz_disable_time = paper.quiz.end_date_time - if quiz_enable_time <= datetime.datetime.now() <= quiz_disable_time: - unexpired_quizzes.append(paper) - - cannot_attempt = True if 'cannot_attempt' in request.GET else False - quizzes_taken = None if user_answerpapers.count() == 0 else user_answerpapers - - context = {'cannot_attempt': cannot_attempt, - 'quizzes': avail_quizzes, - 'user': user, - 'quizzes_taken': quizzes_taken, - 'unexpired_quizzes': unexpired_quizzes - } - - return my_render_to_response("yaksh_app/quizzes_user.html", context) - - -def intro(request, questionpaper_id): - """Show introduction page before quiz starts""" - user = request.user - ci = RequestContext(request) - quest_paper = QuestionPaper.objects.get(id=questionpaper_id) - attempt_number = quest_paper.quiz.attempts_allowed - time_lag = quest_paper.quiz.time_between_attempts - quiz_enable_time = quest_paper.quiz.start_date_time - quiz_disable_time = quest_paper.quiz.end_date_time - - quiz_expired = False if quiz_enable_time <= datetime.datetime.now() \ - <= quiz_disable_time else True - - if quest_paper.quiz.prerequisite: - try: - pre_quest = QuestionPaper.objects.get( - quiz=quest_paper.quiz.prerequisite) - answer_papers = AnswerPaper.objects.filter( - question_paper=pre_quest, user=user) - answer_papers_failed = AnswerPaper.objects.filter( - question_paper=pre_quest, user=user, passed=False) - if answer_papers.count() == answer_papers_failed.count(): - context = {'user': user, 'cannot_attempt': True} - return my_redirect("/exam/quizzes/?cannot_attempt=True") - except: - context = {'user': user, 'cannot_attempt': True} - return my_redirect("/exam/quizzes/?cannot_attempt=True") - - attempted_papers = AnswerPaper.objects.filter(question_paper=quest_paper, - user=user) - already_attempted = attempted_papers.count() - inprogress, previous_attempt, next_attempt = _check_previous_attempt(attempted_papers, - already_attempted, - attempt_number) - - if previous_attempt: - if inprogress: - return show_question(request, - previous_attempt.current_question(), - previous_attempt.attempt_number, - previous_attempt.question_paper.id) - days_after_attempt = (datetime.datetime.today() - \ - previous_attempt.start_time).days - - if next_attempt: - if days_after_attempt >= time_lag: - context = {'user': user, - 'paper_id': questionpaper_id, - 'attempt_num': already_attempted + 1, - 'enable_quiz_time': quiz_enable_time, - 'disable_quiz_time': quiz_disable_time, - 'quiz_expired': quiz_expired - } - return my_render_to_response('yaksh_app/intro.html', context, - context_instance=ci) - else: - return my_redirect("/exam/quizzes/") - - else: - context = {'user': user, - 'paper_id': questionpaper_id, - 'attempt_num': already_attempted + 1, - 'enable_quiz_time': quiz_enable_time, - 'disable_quiz_time': quiz_disable_time, - 'quiz_expired': quiz_expired - } - return my_render_to_response('yaksh_app/intro.html', context, - context_instance=ci) - - -def _check_previous_attempt(attempted_papers, already_attempted, attempt_number): - next_attempt = False if already_attempted == attempt_number else True - if already_attempted == 0: - return False, None, next_attempt - else: - previous_attempt = attempted_papers[already_attempted-1] - previous_attempt_day = previous_attempt.start_time - today = datetime.datetime.today() - if previous_attempt.status == 'inprogress': - end_time = previous_attempt.end_time - quiz_time = previous_attempt.question_paper.quiz.duration*60 - if quiz_time > (today-previous_attempt_day).seconds: - return True, previous_attempt, next_attempt - else: - return False, previous_attempt, next_attempt - else: - return False, previous_attempt, next_attempt - - -def results_user(request): - """Show list of Results of Quizzes that is taken by logged-in user.""" - user = request.user - papers = AnswerPaper.objects.filter(user=user) - quiz_marks = [] - for paper in papers: - marks_obtained = paper.marks_obtained - max_marks = paper.question_paper.total_marks - percentage = round((marks_obtained/max_marks)*100, 2) - temp = paper.question_paper.quiz.description, marks_obtained,\ - max_marks, percentage - quiz_marks.append(temp) - context = {'papers': quiz_marks} - return my_render_to_response("yaksh_app/results_user.html", context) - - -def edit_quiz(request): - """Edit the list of quizzes seleted by the user for editing.""" - - user = request.user - if not user.is_authenticated() or not is_moderator(user): - raise Http404('You are not allowed to view this page!') - quiz_list = request.POST.getlist('quizzes') - start_date = request.POST.getlist('start_date') - start_time = request.POST.getlist('start_time') - end_date = request.POST.getlist('end_date') - end_time = request.POST.getlist('end_time') - duration = request.POST.getlist('duration') - active = request.POST.getlist('active') - description = request.POST.getlist('description') - pass_criteria = request.POST.getlist('pass_criteria') - language = request.POST.getlist('language') - prerequisite = request.POST.getlist('prerequisite') - - for j, quiz_id in enumerate(quiz_list): - quiz = Quiz.objects.get(id=quiz_id) - quiz.start_date_time = datetime.datetime.combine(start_date[j], - start_time[j]) - quiz.end_date_time = datetime.datetime.combine(end_date[j], - end_time[j]) - quiz.duration = duration[j] - quiz.active = active[j] - quiz.description = description[j] - quiz.pass_criteria = pass_criteria[j] - quiz.language = language[j] - quiz.prerequisite_id = prerequisite[j] - quiz.save() - return my_redirect("/exam/manage/showquiz/") - - -def edit_question(request): - """Edit the list of questions selected by the user for editing.""" - user = request.user - if not user.is_authenticated() or not is_moderator(user): - raise Http404('You are not allowed to view this page!') - question_list = request.POST.getlist('questions') - summary = request.POST.getlist('summary') - description = request.POST.getlist('description') - points = request.POST.getlist('points') - options = request.POST.getlist('options') - test = request.POST.getlist('test') - type = request.POST.getlist('type') - active = request.POST.getlist('active') - language = request.POST.getlist('language') - snippet = request.POST.getlist('snippet') - for j, question_id in enumerate(question_list): - question = Question.objects.get(id=question_id) - test_case_formset = TestCaseFormSet(request.POST, prefix='test', instance=question) - if test_case_formset.is_valid(): - test_case_instance = test_case_formset.save(commit=False) - for i in test_case_instance: - i.save() - - question.summary = summary[j] - question.description = description[j] - question.points = points[j] - question.options = options[j] - question.active = active[j] - question.language = language[j] - question.snippet = snippet[j] - question.ref_code_path = ref_code_path[j] - question.test = test[j] - question.type = type[j] - question.save() - return my_redirect("/exam/manage/questions") - - -def add_question(request, question_id=None): - """To add a new question in the database. - Create a new question and store it.""" - - def add_or_delete_test_form(post_request, instance): - request_copy = post_request.copy() - if 'add_test' in post_request: - request_copy['test-TOTAL_FORMS'] = int(request_copy['test-TOTAL_FORMS']) + 1 - elif 'delete_test' in post_request: - request_copy['test-TOTAL_FORMS'] = int(request_copy['test-TOTAL_FORMS']) - 1 - test_case_formset = TestCaseFormSet(request_copy, prefix='test', instance=instance) - return test_case_formset - - user = request.user - ci = RequestContext(request) - if not user.is_authenticated() or not is_moderator(user): - raise Http404('You are not allowed to view this page!') - if request.method == "POST": - form = QuestionForm(request.POST) - if form.is_valid(): - if question_id is None: - test_case_formset = add_or_delete_test_form(request.POST, form.save(commit=False)) - if 'save_question' in request.POST: - qtn = form.save(commit=False) - test_case_formset = TestCaseFormSet(request.POST, prefix='test', instance=qtn) - form.save() - question = Question.objects.order_by("-id")[0] - tags = form['tags'].data.split(',') - for i in range(0, len(tags)-1): - tag = tags[i].strip() - question.tags.add(tag) - if test_case_formset.is_valid(): - test_case_formset.save() - else: - return my_render_to_response('yaksh_app/add_question.html', - {'form': form, - 'formset': test_case_formset}, - context_instance=ci) - - return my_redirect("/exam/manage/questions") - - return my_render_to_response('yaksh_app/add_question.html', - {'form': form, - 'formset': test_case_formset}, - context_instance=ci) - - else: - d = Question.objects.get(id=question_id) - test_case_formset = add_or_delete_test_form(request.POST, d) - if 'save_question' in request.POST: - d.summary = form['summary'].data - d.description = form['description'].data - d.points = form['points'].data - d.options = form['options'].data - d.type = form['type'].data - d.active = form['active'].data - d.language = form['language'].data - d.snippet = form['snippet'].data - d.ref_code_path = form['ref_code_path'].data - d.test = form['test'].data - d.save() - question = Question.objects.get(id=question_id) - for tag in question.tags.all(): - question.tags.remove(tag) - tags = form['tags'].data.split(',') - for i in range(0, len(tags)-1): - tag = tags[i].strip() - question.tags.add(tag) - - test_case_formset = TestCaseFormSet(request.POST, prefix='test', instance=question) - if test_case_formset.is_valid(): - test_case_instance = test_case_formset.save(commit=False) - for i in test_case_instance: - i.save() - else: - return my_render_to_response('yaksh_app/add_question.html', - {'form': form, - 'formset': test_case_formset}, - context_instance=ci) - - - return my_redirect("/exam/manage/questions") - return my_render_to_response('yaksh_app/add_question.html', - {'form': form, - 'formset': test_case_formset}, - context_instance=ci) - - else: - test_case_formset = add_or_delete_test_form(request.POST, form.save(commit=False)) - return my_render_to_response('yaksh_app/add_question.html', - {'form': form, - 'formset': test_case_formset}, - context_instance=ci) - else: - form = QuestionForm() - test_case_formset = TestCaseFormSet(prefix='test', instance=Question()) - if question_id is None: - form = QuestionForm() - test_case_formset = TestCaseFormSet(prefix='test', instance=Question()) - return my_render_to_response('yaksh_app/add_question.html', - {'form': form, - 'formset': test_case_formset}, - context_instance=ci) - else: - d = Question.objects.get(id=question_id) - form = QuestionForm() - form.initial['summary'] = d.summary - form.initial['description'] = d.description - form.initial['points'] = d.points - form.initial['options'] = d.options - form.initial['type'] = d.type - form.initial['active'] = d.active - form.initial['language'] = d.language - form.initial['snippet'] = d.snippet - form.initial['ref_code_path'] = d.ref_code_path - form.initial['test'] = d.test - form_tags = d.tags.all() - form_tags_split = form_tags.values('name') - initial_tags = "" - for tag in form_tags_split: - initial_tags = initial_tags + str(tag['name']).strip() + "," - if (initial_tags == ","): - initial_tags = "" - form.initial['tags'] = initial_tags - - test_case_formset = TestCaseFormSet(prefix='test', - instance=d) - - return my_render_to_response('yaksh_app/add_question.html', - {'form': form, - 'formset': test_case_formset}, - context_instance=ci) - - -def add_quiz(request, quiz_id=None): - """To add a new quiz in the database. - Create a new quiz and store it.""" - - user = request.user - ci = RequestContext(request) - if not user.is_authenticated() or not is_moderator(user): - raise Http404('You are not allowed to view this page!') - if request.method == "POST": - form = QuizForm(request.POST) - if form.is_valid(): - data = form.cleaned_data - if quiz_id is None: - form.save() - quiz = Quiz.objects.order_by("-id")[0] - return my_redirect("/exam/manage/designquestionpaper") - else: - d = Quiz.objects.get(id=quiz_id) - sd = datetime.datetime.strptime(form['start_date'].data, '%Y-%m-%d').date() - st = datetime.datetime.strptime(form['start_time'].data, "%H:%M:%S").time() - ed = datetime.datetime.strptime(form['end_date'].data, '%Y-%m-%d').date() - et = datetime.datetime.strptime(form['end_time'].data, "%H:%M:%S").time() - d.start_date_time = datetime.datetime.combine(sd, st) - d.end_date_time = datetime.datetime.combine(ed, et) - d.duration = form['duration'].data - d.active = form['active'].data - d.description = form['description'].data - d.pass_criteria = form['pass_criteria'].data - d.language = form['language'].data - d.prerequisite_id = form['prerequisite'].data - d.attempts_allowed = form['attempts_allowed'].data - d.time_between_attempts = form['time_between_attempts'].data - d.save() - quiz = Quiz.objects.get(id=quiz_id) - return my_redirect("/exam/manage/showquiz") - else: - return my_render_to_response('yaksh_app/add_quiz.html', - {'form': form}, - context_instance=ci) - else: - if quiz_id is None: - form = QuizForm() - return my_render_to_response('yaksh_app/add_quiz.html', - {'form': form}, - context_instance=ci) - else: - d = Quiz.objects.get(id=quiz_id) - form = QuizForm() - form.initial['start_date'] = d.start_date_time.date() - form.initial['start_time'] = d.start_date_time.time() - form.initial['end_date'] = d.end_date_time.date() - form.initial['end_time'] = d.end_date_time.time() - form.initial['duration'] = d.duration - form.initial['description'] = d.description - form.initial['active'] = d.active - form.initial['pass_criteria'] = d.pass_criteria - form.initial['language'] = d.language - form.initial['prerequisite'] = d.prerequisite_id - form.initial['attempts_allowed'] = d.attempts_allowed - form.initial['time_between_attempts'] = d.time_between_attempts - return my_render_to_response('yaksh_app/add_quiz.html', - {'form': form}, - context_instance=ci) - - -def show_all_questionpapers(request, questionpaper_id=None): - user = request.user - ci = RequestContext(request) - if not user.is_authenticated() or not is_moderator(user): - raise Http404('You are not allowed to view this page!') - - if request.method == "POST" and request.POST.get('add') == "add": - return my_redirect("/exam/manage/designquestionpaper/" + - questionpaper_id) - - if request.method == "POST" and request.POST.get('delete') == "delete": - data = request.POST.getlist('papers') - q_paper = QuestionPaper.objects.get(id=questionpaper_id) - for i in data: - q_paper.questions.remove(Question.objects.get(id=i)) - question_paper = QuestionPaper.objects.all() - context = {'papers': question_paper} - return my_render_to_response('yaksh_app/showquestionpapers.html', context, - context_instance=ci) - if questionpaper_id is None: - qu_papers = QuestionPaper.objects.all() - context = {'papers': qu_papers} - return my_render_to_response('yaksh_app/showquestionpapers.html', context, - context_instance=ci) - else: - qu_papers = QuestionPaper.objects.get(id=questionpaper_id) - quiz = qu_papers.quiz - questions = qu_papers.questions.all() - context = {'papers': {'quiz': quiz, 'questions': questions}} - return my_render_to_response('yaksh_app/editquestionpaper.html', context, - context_instance=ci) - - -def automatic_questionpaper(request, questionpaper_id=None): - """Generate automatic question paper for a particular quiz""" - - user = request.user - ci = RequestContext(request) - if not user.is_authenticated() or not is_moderator(user): - raise Http404('You are not allowed to view this page!') - - if questionpaper_id is None: - if request.method == "POST": - if request.POST.get('save') == 'save': - quiz = Quiz.objects.order_by("-id")[0] - quest_paper = QuestionPaper() - questions = request.POST.getlist('questions') - tot_marks = 0 - for quest in questions: - q = Question.objects.get(id=quest) - tot_marks += q.points - quest_paper.quiz = quiz - quest_paper.total_marks = tot_marks - quest_paper.save() - for quest in questions: - q = Question.objects.get(id=quest) - quest_paper.fixed_questions.add(q) - return my_redirect('/exam/manage/showquiz') - else: - no_questions = int(request.POST.get('num_questions')) - fetched_questions = fetch_questions(request) - n = len(fetched_questions) - msg = '' - if (no_questions < n): - i = n - no_questions - for i in range(0, i): - fetched_questions.pop() - elif (no_questions > n): - msg = 'The given Criteria does not satisfy the number\ - of Questions...' - tags = Tag.objects.all() - context = {'data': {'questions': fetched_questions, - 'tags': tags, - 'msg': msg}} - return my_render_to_response( - 'yaksh_app/automatic_questionpaper.html', context, - context_instance=ci) - else: - tags = Tag.objects.all() - context = {'data': {'tags': tags}} - return my_render_to_response('yaksh_app/automatic_questionpaper.html', - context, context_instance=ci) - - else: - if request.method == "POST": - if request.POST.get('save') == 'save': - quest_paper = QuestionPaper.objects.get(id=questionpaper_id) - questions = request.POST.getlist('questions') - tot_marks = quest_paper.total_marks - for quest in questions: - q = Question.objects.get(id=quest) - tot_marks += q.points - quest_paper.total_marks = tot_marks - quest_paper.save() - for quest in questions: - q = Question.objects.get(id=quest) - quest_paper.questions.add(q) - return my_redirect('/yaksh_app/manage/showquiz') - else: - no_questions = int(request.POST.get('num_questions')) - fetched_questions = fetch_questions(request) - n = len(fetched_questions) - msg = '' - if(no_questions < n): - i = n - no_questions - for i in range(0, i): - fetched_questions.pop() - elif(no_questions > n): - msg = 'The given Criteria does not satisfy the number of \ - Questions...' - tags = Tag.objects.all() - context = {'data': {'questions': fetched_questions, - 'tags': tags, - 'msg': msg}} - return my_render_to_response( - 'yaksh_app/automatic_questionpaper.html', context, - context_instance=ci) - else: - tags = Tag.objects.all() - context = {'data': {'tags': tags}} - return my_render_to_response('yaksh_app/automatic_questionpaper.html', - context, context_instance=ci) - - -def manual_questionpaper(request, questionpaper_id=None): - user = request.user - ci = RequestContext(request) - if not user.is_authenticated() or not is_moderator(user): - raise Http404('You are not allowed to view this page!') - - if questionpaper_id is None: - if request.method == "POST": - if request.POST.get('save') == 'save': - questions = request.POST.getlist('questions') - quest_paper = QuestionPaper() - quiz = Quiz.objects.order_by("-id")[0] - tot_marks = 0 - for quest in questions: - q = Question.objects.get(id=quest) - tot_marks += q.points - quest_paper.quiz = quiz - quest_paper.total_marks = tot_marks - quest_paper.save() - for i in questions: - q = Question.objects.get(id=i) - quest_paper.questions.add(q) - return my_redirect('/exam/manage/showquiz') - else: - fetched_questions = fetch_questions(request) - n = len(fetched_questions) - msg = '' - if (n == 0): - msg = 'No matching Question found...' - tags = Tag.objects.all() - context = {'data': {'questions': fetched_questions, - 'tags': tags, 'msg': msg}} - return my_render_to_response('yaksh_app/manual_questionpaper.html', - context, - context_instance=ci) - else: - tags = Tag.objects.all() - context = {'data': {'tags': tags}} - return my_render_to_response('yaksh_app/manual_questionpaper.html', - context, context_instance=ci) - - else: - if request.method == "POST": - if request.POST.get('save') == 'save': - quest_paper = QuestionPaper.objects.get(id=questionpaper_id) - questions = request.POST.getlist('questions') - tot_marks = quest_paper.total_marks - for quest in questions: - q = Question.objects.get(id=quest) - tot_marks += q.points - quest_paper.total_marks = tot_marks - quest_paper.save() - for i in questions: - q = Question.objects.get(id=i) - quest_paper.questions.add(q) - return my_redirect('/exam/manage/showquiz') - else: - fetched_questions = fetch_questions(request) - n = len(fetched_questions) - msg = '' - if (n == 0): - msg = 'No matching Question found...' - tags = Tag.objects.all() - context = {'data': {'questions': fetched_questions, - 'tags': tags, 'msg': msg}} - return my_render_to_response('yaksh_app/manual_questionpaper.html', - context, - context_instance=ci) - else: - tags = Tag.objects.all() - context = {'data': {'tags': tags}} - return my_render_to_response('yaksh_app/manual_questionpaper.html', - context, context_instance=ci) - - -def prof_manage(request): - """Take credentials of the user with professor/moderator -rights/permissions and log in.""" - user = request.user - if user.is_authenticated() and is_moderator(user): - question_papers = QuestionPaper.objects.all() - users_per_paper = [] - for paper in question_papers: - answer_papers = AnswerPaper.objects.filter(question_paper=paper) - users_passed = AnswerPaper.objects.filter(question_paper=paper, - passed=True).count() - users_failed = AnswerPaper.objects.filter(question_paper=paper, - passed=False).count() - temp = paper, answer_papers, users_passed, users_failed - users_per_paper.append(temp) - context = {'user': user, 'users_per_paper': users_per_paper} - return my_render_to_response('manage.html', context) - return my_redirect('/exam/login/') - - -def user_login(request): - """Take the credentials of the user and log the user in.""" - - user = request.user - ci = RequestContext(request) - if user.is_authenticated(): - if user.groups.filter(name='moderator').count() > 0: - return my_redirect('/exam/manage/') - return my_redirect("/exam/intro/") - - if request.method == "POST": - form = UserLoginForm(request.POST) - if form.is_valid(): - user = form.cleaned_data - login(request, user) - if user.groups.filter(name='moderator').count() > 0: - return my_redirect('/exam/manage/') - return my_redirect('/exam/login/') - else: - context = {"form": form} - return my_render_to_response('yaksh_app/login.html', context, - context_instance=ci) - else: - form = UserLoginForm() - context = {"form": form} - return my_render_to_response('yaksh_app/login.html', context, - context_instance=ci) - - -def start(request, attempt_num=None, questionpaper_id=None): - """Check the user cedentials and if any quiz is available, - start the exam.""" - user = request.user - if questionpaper_id is None: - return my_redirect('/exam/quizzes/') - try: - """Right now the app is designed so there is only one active quiz - at a particular time.""" - questionpaper = QuestionPaper.objects.get(id=questionpaper_id) - except QuestionPaper.DoesNotExist: - msg = 'Quiz not found, please contact your '\ - 'instructor/administrator. Please login again thereafter.' - return complete(request, msg, attempt_num, questionpaper_id) - - try: - old_paper = AnswerPaper.objects.get( - question_paper=questionpaper, user=user, attempt_number=attempt_num) - q = old_paper.current_question() - return show_question(request, q, attempt_num, questionpaper_id) - except AnswerPaper.DoesNotExist: - ip = request.META['REMOTE_ADDR'] - key = gen_key(10) - try: - profile = user.get_profile() - except Profile.DoesNotExist: - msg = 'You do not have a profile and cannot take the quiz!' - raise Http404(msg) - - new_paper = questionpaper.make_answerpaper(user, ip, attempt_num) - # Make user directory. - user_dir = get_user_dir(user) - return start(request, attempt_num, questionpaper_id) - -def get_questions(paper): - ''' - Takes answerpaper as an argument. Returns the total questions as - ordered dictionary, the questions yet to attempt and the questions - attempted - ''' - to_attempt = [] - submitted = [] - all_questions = [] - questions = {} - if paper.questions: - all_questions = (paper.questions).split('|') - if paper.questions_answered: - q_answered = (paper.questions_answered).split('|') - q_answered.sort() - submitted = q_answered - if paper.get_unanswered_questions(): - q_unanswered = paper.get_unanswered_questions() - q_unanswered.sort() - to_attempt = q_unanswered - for index, value in enumerate(all_questions, 1): - questions[value] = index - questions = collections.OrderedDict(sorted(questions.items(), key=lambda x:x[1])) - return questions, to_attempt, submitted - - -def question(request, q_id, attempt_num, questionpaper_id, success_msg=None): - """Check the credentials of the user and start the exam.""" - - user = request.user - if not user.is_authenticated(): - return my_redirect('/exam/login/') - q = get_object_or_404(Question, pk=q_id) - try: - q_paper = QuestionPaper.objects.get(id=questionpaper_id) - paper = AnswerPaper.objects.get( - user=request.user, attempt_number=attempt_num, question_paper=q_paper) - except AnswerPaper.DoesNotExist: - return my_redirect('/exam/start/') - if not paper.question_paper.quiz.active: - reason = 'The quiz has been deactivated!' - return complete(request, reason, questionpaper_id) - elif paper.end_time < datetime.datetime.now(): - reason = 'You have already attempted the quiz' - return complete(request, reason, questionpaper_id) - time_left = paper.time_left() - if time_left == 0: - return complete(request, reason='Your time is up!') - quiz_name = paper.question_paper.quiz.description - questions, to_attempt, submitted = get_questions(paper) - if success_msg is None: - context = {'question': q, 'questions': questions, 'paper': paper, - 'user': user, 'quiz_name': quiz_name, 'time_left': time_left, - 'to_attempt': to_attempt, 'submitted': submitted} - else: - context = {'question': q, 'questions': questions, 'paper': paper, - 'user': user, 'quiz_name': quiz_name, 'time_left': time_left, - 'success_msg': success_msg, 'to_attempt': to_attempt, - 'submitted': submitted} - if q.type == 'code': - skipped_answer = paper.answers.filter(question=q, skipped=True) - if skipped_answer: - context['last_attempt'] = skipped_answer[0].answer - ci = RequestContext(request) - return my_render_to_response('yaksh_app/question.html', context, - context_instance=ci) - - -def show_question(request, q_id, attempt_num, questionpaper_id, success_msg=None): - """Show a question if possible.""" - user = request.user - q_paper = QuestionPaper.objects.get(id=questionpaper_id) - paper = AnswerPaper.objects.get(user=request.user, attempt_number=attempt_num, - question_paper=q_paper) - if not user.is_authenticated() or paper.end_time < datetime.datetime.now(): - return my_redirect('/exam/login/') - old_qid = request.POST.get('question_id') - if old_qid is not None: - quest = Question.objects.get(pk=old_qid) - user_code = request.POST.get('answer') - if quest.type == 'code': - old_skipped = paper.answers.filter(question=quest, skipped=True) - _save_skipped_answer(old_skipped, user_code, paper, quest) - if len(q_id) == 0: - msg = 'Congratulations! You have successfully completed the quiz.' - return complete(request, msg, attempt_num, questionpaper_id) - else: - return question(request, q_id, attempt_num, questionpaper_id, success_msg) - - -def _save_skipped_answer(old_skipped, user_answer, paper, question): - """ - Saves the answer on skip. Only the code questions are saved. - Snippet is not saved with the answer. - """ - if old_skipped: - skipped_answer = old_skipped[0] - skipped_answer.answer=user_answer - skipped_answer.save() - else: - skipped_answer = Answer(question=question, answer=user_answer, - correct=False, skipped=True) - skipped_answer.save() - paper.answers.add(skipped_answer) - -def check(request, q_id, attempt_num=None, questionpaper_id=None): - """Checks the answers of the user for particular question""" - - user = request.user - q_paper = QuestionPaper.objects.get(id=questionpaper_id) - paper = AnswerPaper.objects.get(user=request.user, attempt_number=attempt_num, - question_paper=q_paper) - if q_id in paper.questions_answered: - next_q = paper.skip(q_id) - return show_question(request, next_q, attempt_num, questionpaper_id) - - if not user.is_authenticated() or paper.end_time < datetime.datetime.now(): - return my_redirect('/exam/login/') - - question = get_object_or_404(Question, pk=q_id) - test_cases = TestCase.objects.filter(question=question) - - snippet_code = request.POST.get('snippet') - user_code = request.POST.get('answer') - skip = request.POST.get('skip', None) - success_msg = False - success = True - if skip is not None: - if question.type == 'code': - old_skipped = paper.answers.filter(question=question, skipped=True) - _save_skipped_answer(old_skipped, user_code, paper, question) - next_q = paper.skip(q_id) - return show_question(request, next_q, attempt_num, questionpaper_id) - - # Add the answer submitted, regardless of it being correct or not. - if question.type == 'mcq': - user_answer = request.POST.get('answer') - elif question.type == 'mcc': - user_answer = request.POST.getlist('answer') - elif question.type == 'upload': - assign = AssignmentUpload() - assign.user = user.profile - assign.assignmentQuestion = question - # if time-up at upload question then the form is submitted without - # validation - if 'assignment' in request.FILES: - assign.assignmentFile = request.FILES['assignment'] - assign.save() - user_answer = 'ASSIGNMENT UPLOADED' - else: - user_code = request.POST.get('answer') - user_answer = snippet_code + "\n" + user_code if snippet_code else user_code - - new_answer = Answer(question=question, answer=user_answer, - correct=False) - new_answer.save() - paper.answers.add(new_answer) - - # If we were not skipped, we were asked to check. For any non-mcq - # questions, we obtain the results via XML-RPC with the code executed - # safely in a separate process (the code_server.py) running as nobody. - if not question.type == 'upload': - json_data = question.consolidate_answer_data(test_cases, user_answer) \ - if question.type == 'code' else None - correct, result = validate_answer(user, user_answer, question, json_data) - if correct: - new_answer.correct = correct - new_answer.marks = question.points - new_answer.error = result.get('error') - success_msg = True - else: - new_answer.error = result.get('error') - new_answer.save() - - time_left = paper.time_left() - if not result.get('success'): # Should only happen for non-mcq questions. - if time_left == 0: - reason = 'Your time is up!' - return complete(request, reason, attempt_num, questionpaper_id) - if not paper.question_paper.quiz.active: - reason = 'The quiz has been deactivated!' - return complete(request, reason, attempt_num, questionpaper_id) - if not paper.question_paper.quiz.active: - reason = 'The quiz has been deactivated!' - return complete(request, reason, attempt_num, questionpaper_id) - questions, to_attempt, submitted = get_questions(paper) - old_answer = paper.answers.filter(question=question, skipped=True) - if old_answer: - old_answer[0].answer = user_code - old_answer[0].save() - context = {'question': question, 'error_message': result.get('error'), - 'paper': paper, 'last_attempt': user_code, - 'quiz_name': paper.question_paper.quiz.description, - 'time_left': time_left, 'questions': questions, - 'to_attempt': to_attempt, 'submitted': submitted} - ci = RequestContext(request) - - return my_render_to_response('yaksh_app/question.html', context, - context_instance=ci) - else: - if time_left <= 0: - reason = 'Your time is up!' - return complete(request, reason, attempt_num, questionpaper_id) - - # Display the same question if user_answer is None - elif not user_answer: - msg = "Please submit a valid option or code" - time_left = paper.time_left() - questions, to_attempt, submitted = get_questions(paper) - context = {'question': question, 'error_message': msg, - 'paper': paper, 'quiz_name': paper.question_paper.quiz.description, - 'time_left': time_left, 'questions': questions, - 'to_attempt': to_attempt, 'submitted': submitted} - ci = RequestContext(request) - - return my_render_to_response('yaksh_app/question.html', context, - context_instance=ci) - else: - next_q = paper.completed_question(question.id) - return show_question(request, next_q, attempt_num, - questionpaper_id, success_msg) - - -def validate_answer(user, user_answer, question, json_data=None): - """ - Checks whether the answer submitted by the user is right or wrong. - If right then returns correct = True, success and - message = Correct answer. - success is True for MCQ's and multiple correct choices because - only one attempt are allowed for them. - For code questions success is True only if the answer is correct. - """ - - result = {'success': True, 'error': 'Incorrect answer'} - correct = False - - if user_answer is not None: - if question.type == 'mcq': - if user_answer.strip() == question.test.strip(): - correct = True - message = 'Correct answer' - elif question.type == 'mcc': - answers = set(question.test.splitlines()) - if set(user_answer) == answers: - correct = True - message = 'Correct answer' - elif question.type == 'code': - user_dir = get_user_dir(user) - json_result = code_server.run_code(question.language, json_data, user_dir) - result = json.loads(json_result) - if result.get('success'): - correct = True - - return correct, result - -def get_question_labels(request, attempt_num=None, questionpaper_id=None): - """Get the question number show in template for corresponding - question id.""" - unattempted_questions = [] - submitted_questions = [] - try: - q_paper = QuestionPaper.objects.get(id=questionpaper_id) - paper = AnswerPaper.objects.get( - user=request.user, attempt_number=attempt_num, question_paper=q_paper) - except AnswerPaper.DoesNotExist: - return my_redirect('/exam/start/') - questions, to_attempt, submitted = get_questions(paper) - for q_id, question_label in questions.items(): - if q_id in to_attempt: - unattempted_questions.append(question_label) - else: - submitted_questions.append(question_label) - unattempted_questions.sort() - submitted_questions.sort() - return unattempted_questions, submitted_questions - -def quit(request, attempt_num=None, questionpaper_id=None): - """Show the quit page when the user logs out.""" - unattempted_questions, submitted_questions = get_question_labels(request, - attempt_num, questionpaper_id) - context = {'id': questionpaper_id, 'attempt_num': attempt_num, - 'unattempted': unattempted_questions, - 'submitted': submitted_questions} - return my_render_to_response('yaksh_app/quit.html', context, - context_instance=RequestContext(request)) - - -def complete(request, reason=None, attempt_num=None, questionpaper_id=None): - """Show a page to inform user that the quiz has been compeleted.""" - - user = request.user - if questionpaper_id is None: - logout(request) - message = reason or "You are successfully logged out." - context = {'message': message} - return my_render_to_response('yaksh_app/complete.html', context) - else: - unattempted_questions, submitted_questions = get_question_labels(request, - attempt_num, questionpaper_id) - q_paper = QuestionPaper.objects.get(id=questionpaper_id) - paper = AnswerPaper.objects.get(user=user, question_paper=q_paper, - attempt_number=attempt_num) - paper.update_marks_obtained() - paper.update_percent() - paper.update_passed() - paper.end_time = datetime.datetime.now() - paper.update_status() - paper.save() - obt_marks = paper.marks_obtained - tot_marks = paper.question_paper.total_marks - if obt_marks == paper.question_paper.total_marks: - context = {'message': "Hurray ! You did an excellent job.\ - you answered all the questions correctly.\ - You have been logged out successfully,\ - Thank You !", - 'unattempted': unattempted_questions, - 'submitted': submitted_questions} - return my_render_to_response('yaksh_app/complete.html', context) - else: - message = reason or "You are successfully logged out" - context = {'message': message, - 'unattempted': unattempted_questions, - 'submitted': submitted_questions} - return my_render_to_response('yaksh_app/complete.html', context) - no = False - message = reason or 'The quiz has been completed. Thank you.' - if user.groups.filter(name='moderator').count() > 0: - message = 'You are successfully Logged out.' - if request.method == 'POST' and 'no' in request.POST: - no = True - if not no: - # Logout the user and quit with the message given. - answer_paper = AnswerPaper.objects.get(id=answerpaper_id) - answer_paper.end_time = datetime.datetime.now() - answer_paper.save() - return my_redirect('/exam/quizzes/') - else: - return my_redirect('/exam/') - - -def monitor(request, questionpaper_id=None): - """Monitor the progress of the papers taken so far.""" - - user = request.user - ci = RequestContext(request) - if not user.is_authenticated() or not is_moderator(user): - raise Http404('You are not allowed to view this page!') - - if questionpaper_id is None: - q_paper = QuestionPaper.objects.all() - context = {'papers': [], - 'quiz': None, - 'quizzes': q_paper} - return my_render_to_response('yaksh_app/monitor.html', context, - context_instance=ci) - # quiz_id is not None. - try: - q_paper = QuestionPaper.objects.get(id=questionpaper_id) - except QuestionPaper.DoesNotExist: - papers = [] - q_paper = None - else: - papers = AnswerPaper.objects.filter(question_paper=q_paper).annotate( - total=Sum('answers__marks')).order_by('-total') - - context = {'papers': papers, 'quiz': q_paper, 'quizzes': None} - return my_render_to_response('yaksh_app/monitor.html', context, - context_instance=ci) - - -def get_user_data(username): - """For a given username, this returns a dictionary of important data - related to the user including all the user's answers submitted. - """ - user = User.objects.get(username=username) - papers = AnswerPaper.objects.filter(user=user) - - data = {} - try: - profile = user.get_profile() - except Profile.DoesNotExist: - # Admin user may have a paper by accident but no profile. - profile = None - data['user'] = user - data['profile'] = profile - data['papers'] = papers - return data - - -def show_all_users(request): - """Shows all the users who have taken various exams/quiz.""" - - user = request.user - if not user.is_authenticated() or not is_moderator(user): - raise Http404('You are not allowed to view this page !') - user = User.objects.filter(username__contains="") - questionpaper = AnswerPaper.objects.all() - context = {'question': questionpaper} - return my_render_to_response('yaksh_app/showusers.html', context, - context_instance=RequestContext(request)) - - -def show_all_quiz(request): - """Generates a list of all the quizzes - that are currently in the database.""" - - user = request.user - ci = RequestContext(request) - if not user.is_authenticated() or not is_moderator(user): - raise Http404('You are not allowed to view this page !') - - if request.method == 'POST' and request.POST.get('delete') == 'delete': - data = request.POST.getlist('quiz') - - if data is None: - quizzes = Quiz.objects.all() - context = {'papers': [], - 'quiz': None, - 'quizzes': quizzes} - return my_render_to_response('yaksh_app/show_quiz.html', context, - context_instance=ci) - else: - for i in data: - quiz = Quiz.objects.get(id=i).delete() - quizzes = Quiz.objects.all() - context = {'papers': [], - 'quiz': None, - 'quizzes': quizzes} - return my_render_to_response('yaksh_app/show_quiz.html', context, - context_instance=ci) - - elif request.method == 'POST' and request.POST.get('edit') == 'edit': - data = request.POST.getlist('quiz') - forms = [] - for j in data: - d = Quiz.objects.get(id=j) - form = QuizForm() - form.initial['start_date'] = d.start_date_time.date() - form.initial['start_time'] = d.start_date_time.time() - form.initial['end_date'] = d.end_date_time.date() - form.initial['end_time'] = d.end_date_time.time() - form.initial['duration'] = d.duration - form.initial['active'] = d.active - form.initial['description'] = d.description - form.initial['pass_criteria'] = d.pass_criteria - form.initial['language'] = d.language - form.initial['prerequisite'] = d.prerequisite_id - forms.append(form) - return my_render_to_response('yaksh_app/edit_quiz.html', - {'forms': forms, 'data': data}, - context_instance=ci) - else: - quizzes = Quiz.objects.all() - context = {'papers': [], - 'quiz': None, - 'quizzes': quizzes} - return my_render_to_response('yaksh_app/show_quiz.html', context, - context_instance=ci) - - -@csrf_exempt -def ajax_questions_filter(request): - """Ajax call made when filtering displayed questions.""" - - filter_dict = {} - question_type = request.POST.get('question_type') - marks = request.POST.get('marks') - language = request.POST.get('language') - - if question_type != "select": - filter_dict['type'] = str(question_type) - - if marks != "select": - filter_dict['points'] = marks - - if language != "select": - filter_dict['language'] = str(language) - - questions = list(Question.objects.filter(**filter_dict)) - - return my_render_to_response('yaksh_app/ajax_question_filter.html', - {'questions': questions}) - - -def show_all_questions(request): - """Show a list of all the questions currently in the databse.""" - - user = request.user - ci = RequestContext(request) - if not user.is_authenticated() or not is_moderator(user): - raise Http404("You are not allowed to view this page !") - - if request.method == 'POST' and request.POST.get('delete') == 'delete': - data = request.POST.getlist('question') - if data is None: - questions = Question.objects.all() - form = QuestionFilterForm() - context = {'papers': [], - 'question': None, - 'questions': questions, - 'form': form - } - return my_render_to_response('yaksh_app/showquestions.html', context, - context_instance=ci) - else: - for i in data: - question = Question.objects.get(id=i).delete() - questions = Question.objects.all() - form = QuestionFilterForm() - context = {'papers': [], - 'question': None, - 'questions': questions, - 'form': form - } - return my_render_to_response('yaksh_app/showquestions.html', context, - context_instance=ci) - elif request.method == 'POST' and request.POST.get('edit') == 'edit': - data = request.POST.getlist('question') - - forms = [] - formsets = [] - for j in data: - d = Question.objects.get(id=j) - form = QuestionForm() - form.initial['summary'] = d.summary - form.initial['description'] = d.description - form.initial['points'] = d.points - form.initial['options'] = d.options - form.initial['type'] = d.type - form.initial['active'] = d.active - form.initial['language'] = d.language - form.initial['snippet'] = d.snippet - form.initial['ref_code_path'] = d.ref_code_path - form.initial['test'] = d.test - form_tags = d.tags.all() - form_tags_split = form_tags.values('name') - initial_tags = "" - for tag in form_tags_split: - initial_tags = initial_tags + str(tag['name']).strip() + "," - if (initial_tags == ","): - initial_tags = "" - form.initial['tags'] = initial_tags - forms.append(form) - test_case_formset = TestCaseFormSet(prefix='test', instance=d) - formsets.append(test_case_formset) - data_list = zip(forms, formsets) - - return my_render_to_response('yaksh_app/edit_question.html', - {'data': data, - 'data_list': data_list}, - context_instance=ci) - else: - questions = Question.objects.all() - form = QuestionFilterForm() - context = {'papers': [], - 'question': None, - 'questions': questions, - 'form': form - } - return my_render_to_response('yaksh_app/showquestions.html', context, - context_instance=ci) - - -def user_data(request, username): - """Render user data.""" - - current_user = request.user - if not current_user.is_authenticated() or not is_moderator(current_user): - raise Http404('You are not allowed to view this page!') - - data = get_user_data(username) - - context = {'data': data} - return my_render_to_response('yaksh_app/user_data.html', context, - context_instance=RequestContext(request)) - - -def grade_user(request, username): - """Present an interface with which we can easily grade a user's papers - and update all their marks and also give comments for each paper. - """ - current_user = request.user - ci = RequestContext(request) - if not current_user.is_authenticated() or not is_moderator(current_user): - raise Http404('You are not allowed to view this page!') - - data = get_user_data(username) - if request.method == 'POST': - papers = data['papers'] - for paper in papers: - for question, answers in paper.get_question_answers().iteritems(): - marks = float(request.POST.get('q%d_marks' % question.id)) - last_ans = answers[-1] - last_ans.marks = marks - last_ans.save() - paper.comments = request.POST.get( - 'comments_%d' % paper.question_paper.id) - paper.save() - - context = {'data': data} - return my_render_to_response('yaksh_app/user_data.html', context, - context_instance=ci) - else: - context = {'data': data} - return my_render_to_response('yaksh_app/grade_user.html', context, - context_instance=ci) - - -@csrf_exempt -def ajax_questionpaper(request, query): - """ - During question paper creation, ajax call made to get question details. - """ - if query == 'marks': - question_type = request.POST.get('question_type') - questions = Question.objects.filter(type=question_type) - marks = questions.values_list('points').distinct() - return my_render_to_response('yaksh_app/ajax_marks.html', {'marks': marks}) - elif query == 'questions': - question_type = request.POST['question_type'] - marks_selected = request.POST['marks'] - fixed_questions = request.POST.getlist('fixed_list[]') - fixed_question_list = ",".join(fixed_questions).split(',') - random_questions = request.POST.getlist('random_list[]') - random_question_list = ",".join(random_questions).split(',') - question_list = fixed_question_list + random_question_list - questions = list(Question.objects.filter(type=question_type, - points=marks_selected)) - questions = [question for question in questions \ - if not str(question.id) in question_list] - return my_render_to_response('yaksh_app/ajax_questions.html', - {'questions': questions}) - - -def design_questionpaper(request): - user = request.user - ci = RequestContext(request) - - if not user.is_authenticated() or not is_moderator(user): - raise Http404('You are not allowed to view this page!') - - if request.method == 'POST': - fixed_questions = request.POST.getlist('fixed') - random_questions = request.POST.getlist('random') - random_number = request.POST.getlist('number') - is_shuffle = request.POST.get('shuffle_questions', False) - if is_shuffle == 'on': - is_shuffle = True - - question_paper = QuestionPaper(shuffle_questions=is_shuffle) - quiz = Quiz.objects.order_by("-id")[0] - tot_marks = 0 - question_paper.quiz = quiz - question_paper.total_marks = tot_marks - question_paper.save() - if fixed_questions: - fixed_questions_ids = ",".join(fixed_questions) - fixed_questions_ids_list = fixed_questions_ids.split(',') - for question_id in fixed_questions_ids_list: - question_paper.fixed_questions.add(question_id) - if random_questions: - for random_question, num in zip(random_questions, random_number): - qid = random_question.split(',')[0] - question = Question.objects.get(id=int(qid)) - marks = question.points - question_set = QuestionSet(marks=marks, num_questions=num) - question_set.save() - for question_id in random_question.split(','): - question_set.questions.add(question_id) - question_paper.random_questions.add(question_set) - question_paper.update_total_marks() - question_paper.save() - return my_redirect('/exam/manage/showquiz') - else: - form = RandomQuestionForm() - context = {'form': form} - return my_render_to_response('yaksh_app/design_questionpaper.html', - context, context_instance=ci) diff --git a/testapp/yaksh_app/xmlrpc_clients.py b/testapp/yaksh_app/xmlrpc_clients.py deleted file mode 100644 index 3a3c0c6..0000000 --- a/testapp/yaksh_app/xmlrpc_clients.py +++ /dev/null @@ -1,80 +0,0 @@ -from xmlrpclib import ServerProxy -import time -import random -import socket -import json - -from settings import SERVER_PORTS, SERVER_POOL_PORT - - -class ConnectionError(Exception): - pass - -############################################################################### -# `CodeServerProxy` class. -############################################################################### - - -class CodeServerProxy(object): - """A class that manages accesing the farm of Python servers and making - calls to them such that no one XMLRPC server is overloaded. - """ - def __init__(self): - pool_url = 'http://localhost:%d' % (SERVER_POOL_PORT) - self.pool_server = ServerProxy(pool_url) - - def run_code(self, language, json_data, user_dir): - """Tests given code (`answer`) with the `test_code` supplied. If the - optional `in_dir` keyword argument is supplied it changes the directory - to that directory (it does not change it back to the original when - done). The parameter language specifies which language to use for the - tests. - - Parameters - ---------- - json_data contains; - user_answer : str - The user's answer for the question. - test_code : str - The test code to check the user code with. - language : str - The programming language to use. - - user_dir : str (directory) - The directory to run the tests inside. - - - Returns - ------- - A json string of a dict: {success: success, err: error message}. - """ - - try: - server = self._get_server() - result = server.check_code(language, json_data, user_dir) - except ConnectionError: - result = json.dumps({'success': False, 'error': 'Unable to connect to any code servers!'}) - return result - - def _get_server(self): - # Get a suitable server from our pool of servers. This may block. We - # try about 60 times, essentially waiting at most for about 30 seconds. - done, count = False, 60 - - while not done and count > 0: - try: - port = self.pool_server.get_server_port() - except socket.error: - # Wait a while try again. - time.sleep(random.random()) - count -= 1 - else: - done = True - if not done: - raise ConnectionError("Couldn't connect to a server!") - proxy = ServerProxy('http://localhost:%d' % port) - return proxy - -# views.py calls this Python server which forwards the request to one -# of the running servers. -code_server = CodeServerProxy() -- cgit From 7a60f782995eed0352f3172f445bb35ae8ee6aa9 Mon Sep 17 00:00:00 2001 From: ankitjavalkar Date: Mon, 14 Sep 2015 12:28:41 +0530 Subject: Remove testapp dir, remove reference to testapp in paths, files --- testapp/__init__.py | 0 testapp/fixtures/initial_fixtures.json | 1 - testapp/myauthentication/README | 12 - testapp/myauthentication/__init__.py | 0 testapp/myauthentication/backend.py | 43 - testapp/myauthentication/models_spoken_tutorial.py | 26 - testapp/myauthentication/router.py | 12 - testapp/myauthentication/tests.py | 5 - testapp/myauthentication/urls.py | 0 testapp/myauthentication/views.py | 1 - testapp/scripts/__init__.py | 0 testapp/scripts/project_detail.py | 2 - testapp/scripts/yaksh.py | 147 -- testapp/templates/demo_settings.py | 88 - testapp/templates/demo_urls.py | 13 - testapp/tests/__init__.py | 0 testapp/tests/test_bash_evaluation.py | 41 - testapp/tests/test_c_cpp_evaluation.py | 77 - testapp/tests/test_code_evaluation.py | 24 - testapp/tests/test_java_evaluation.py | 53 - testapp/tests/test_python_evaluation.py | 53 - testapp/tests/test_scilab_evaluation.py | 47 - testapp/urls.py | 29 - testapp/yaksh/__init__.py | 0 testapp/yaksh/admin.py | 6 - testapp/yaksh/bash_code_evaluator.py | 122 - testapp/yaksh/bash_files/sample.args | 2 - testapp/yaksh/bash_files/sample.sh | 2 - testapp/yaksh/c_cpp_files/main.cpp | 32 - testapp/yaksh/c_cpp_files/main2.c | 30 - testapp/yaksh/c_cpp_files/main_array_check.cpp | 34 - testapp/yaksh/c_cpp_files/main_array_check_all.cpp | 34 - testapp/yaksh/c_cpp_files/main_array_sum.cpp | 34 - testapp/yaksh/c_cpp_files/main_blackJack.cpp | 41 - testapp/yaksh/c_cpp_files/main_check_digit.cpp | 32 - testapp/yaksh/c_cpp_files/main_count667.cpp | 42 - testapp/yaksh/c_cpp_files/main_count7.cpp | 42 - testapp/yaksh/c_cpp_files/main_fact.cpp | 32 - testapp/yaksh/c_cpp_files/main_greatest.cpp | 44 - testapp/yaksh/c_cpp_files/main_hello_name.c | 29 - testapp/yaksh/c_cpp_files/main_lessThan9.cpp | 38 - testapp/yaksh/c_cpp_files/main_mean.cpp | 38 - testapp/yaksh/c_cpp_files/main_palindrome.cpp | 32 - testapp/yaksh/c_cpp_files/main_roundTo10.cpp | 41 - testapp/yaksh/c_cpp_files/main_specialSum.cpp | 41 - testapp/yaksh/c_cpp_files/main_within.cpp | 38 - testapp/yaksh/code_evaluator.py | 206 -- testapp/yaksh/code_server.py | 162 -- testapp/yaksh/cpp_code_evaluator.py | 125 -- testapp/yaksh/docs/sample.args | 2 - testapp/yaksh/docs/sample.sh | 2 - testapp/yaksh/docs/sample_questions.py | 84 - testapp/yaksh/docs/sample_questions.xml | 43 - testapp/yaksh/forms.py | 267 --- testapp/yaksh/java_code_evaluator.py | 128 -- testapp/yaksh/java_files/main_array_sum.java | 36 - testapp/yaksh/java_files/main_fact.java | 29 - testapp/yaksh/java_files/main_great.java | 39 - testapp/yaksh/java_files/main_hello_name.java | 29 - testapp/yaksh/java_files/main_lastDigit.java | 36 - testapp/yaksh/java_files/main_moreThan30.java | 36 - testapp/yaksh/java_files/main_palindrome.java | 29 - testapp/yaksh/java_files/main_square.java | 32 - testapp/yaksh/language_registry.py | 36 - testapp/yaksh/management/__init__.py | 0 testapp/yaksh/management/commands/__init__.py | 0 testapp/yaksh/management/commands/add_group.py | 33 - .../yaksh/management/commands/dump_user_data.py | 98 - testapp/yaksh/management/commands/load_exam.py | 57 - .../management/commands/load_questions_xml.py | 73 - testapp/yaksh/management/commands/results2csv.py | 69 - testapp/yaksh/models.py | 471 ---- testapp/yaksh/output/README.txt | 4 - testapp/yaksh/python_code_evaluator.py | 61 - testapp/yaksh/scilab_code_evaluator.py | 105 - testapp/yaksh/scilab_files/test_add.sce | 29 - testapp/yaksh/settings.py | 29 - testapp/yaksh/static/yaksh_app/css/autotaggit.css | 48 - testapp/yaksh/static/yaksh_app/css/base.css | 2327 -------------------- testapp/yaksh/static/yaksh_app/css/gradeuser.css | 52 - testapp/yaksh/static/yaksh_app/css/login.css | 10 - testapp/yaksh/static/yaksh_app/css/monitor.css | 11 - testapp/yaksh/static/yaksh_app/css/question.css | 42 - .../yaksh_app/css/question_paper_creation.css | 119 - .../yaksh/static/yaksh_app/css/question_quiz.css | 24 - testapp/yaksh/static/yaksh_app/css/showusers.css | 5 - testapp/yaksh/static/yaksh_app/js/add_question.js | 205 -- .../yaksh/static/yaksh_app/js/add_questionpaper.js | 25 - testapp/yaksh/static/yaksh_app/js/add_quiz.js | 11 - .../yaksh/static/yaksh_app/js/bootstrap-modal.js | 260 --- .../yaksh/static/yaksh_app/js/bootstrap-tabs.js | 80 - testapp/yaksh/static/yaksh_app/js/edit_question.js | 278 --- testapp/yaksh/static/yaksh_app/js/edit_quiz.js | 9 - .../yaksh/static/yaksh_app/js/jquery-1.4.2.min.js | 154 -- testapp/yaksh/static/yaksh_app/js/min.js | 19 - testapp/yaksh/static/yaksh_app/js/question.js | 152 -- .../yaksh/static/yaksh_app/js/question_filter.js | 47 - .../static/yaksh_app/js/question_paper_creation.js | 237 -- testapp/yaksh/static/yaksh_app/js/show_question.js | 39 - testapp/yaksh/static/yaksh_app/js/show_quiz.js | 41 - testapp/yaksh/templates/404.html | 5 - testapp/yaksh/templates/500.html | 7 - testapp/yaksh/templates/base.html | 46 - testapp/yaksh/templates/manage.html | 88 - testapp/yaksh/templates/user.html | 58 - testapp/yaksh/templates/yaksh/add_question.html | 50 - .../yaksh/templates/yaksh/add_questionpaper.html | 27 - testapp/yaksh/templates/yaksh/add_quiz.html | 25 - testapp/yaksh/templates/yaksh/ajax_marks.html | 4 - .../templates/yaksh/ajax_question_filter.html | 15 - testapp/yaksh/templates/yaksh/ajax_questions.html | 31 - .../templates/yaksh/automatic_questionpaper.html | 87 - testapp/yaksh/templates/yaksh/complete.html | 33 - .../templates/yaksh/design_questionpaper.html | 182 -- testapp/yaksh/templates/yaksh/edit_question.html | 61 - testapp/yaksh/templates/yaksh/edit_quiz.html | 39 - .../yaksh/templates/yaksh/editquestionpaper.html | 21 - testapp/yaksh/templates/yaksh/grade_user.html | 94 - testapp/yaksh/templates/yaksh/intro.html | 53 - testapp/yaksh/templates/yaksh/login.html | 22 - .../templates/yaksh/manual_questionpaper.html | 79 - testapp/yaksh/templates/yaksh/monitor.html | 69 - testapp/yaksh/templates/yaksh/question.html | 203 -- testapp/yaksh/templates/yaksh/quit.html | 35 - testapp/yaksh/templates/yaksh/quizlist.html | 24 - testapp/yaksh/templates/yaksh/quizzes_user.html | 87 - testapp/yaksh/templates/yaksh/register.html | 20 - testapp/yaksh/templates/yaksh/results_user.html | 28 - testapp/yaksh/templates/yaksh/show_quiz.html | 33 - .../yaksh/templates/yaksh/showquestionpapers.html | 23 - testapp/yaksh/templates/yaksh/showquestions.html | 44 - testapp/yaksh/templates/yaksh/showusers.html | 26 - testapp/yaksh/templates/yaksh/user_data.html | 80 - testapp/yaksh/tests.py | 345 --- testapp/yaksh/urls.py | 52 - testapp/yaksh/views.py | 1502 ------------- testapp/yaksh/xmlrpc_clients.py | 80 - 137 files changed, 11683 deletions(-) delete mode 100644 testapp/__init__.py delete mode 100644 testapp/fixtures/initial_fixtures.json delete mode 100644 testapp/myauthentication/README delete mode 100644 testapp/myauthentication/__init__.py delete mode 100644 testapp/myauthentication/backend.py delete mode 100644 testapp/myauthentication/models_spoken_tutorial.py delete mode 100644 testapp/myauthentication/router.py delete mode 100644 testapp/myauthentication/tests.py delete mode 100644 testapp/myauthentication/urls.py delete mode 100644 testapp/myauthentication/views.py delete mode 100644 testapp/scripts/__init__.py delete mode 100644 testapp/scripts/project_detail.py delete mode 100644 testapp/scripts/yaksh.py delete mode 100644 testapp/templates/demo_settings.py delete mode 100644 testapp/templates/demo_urls.py delete mode 100644 testapp/tests/__init__.py delete mode 100644 testapp/tests/test_bash_evaluation.py delete mode 100644 testapp/tests/test_c_cpp_evaluation.py delete mode 100644 testapp/tests/test_code_evaluation.py delete mode 100644 testapp/tests/test_java_evaluation.py delete mode 100644 testapp/tests/test_python_evaluation.py delete mode 100644 testapp/tests/test_scilab_evaluation.py delete mode 100644 testapp/urls.py delete mode 100644 testapp/yaksh/__init__.py delete mode 100644 testapp/yaksh/admin.py delete mode 100644 testapp/yaksh/bash_code_evaluator.py delete mode 100644 testapp/yaksh/bash_files/sample.args delete mode 100755 testapp/yaksh/bash_files/sample.sh delete mode 100755 testapp/yaksh/c_cpp_files/main.cpp delete mode 100755 testapp/yaksh/c_cpp_files/main2.c delete mode 100755 testapp/yaksh/c_cpp_files/main_array_check.cpp delete mode 100755 testapp/yaksh/c_cpp_files/main_array_check_all.cpp delete mode 100755 testapp/yaksh/c_cpp_files/main_array_sum.cpp delete mode 100755 testapp/yaksh/c_cpp_files/main_blackJack.cpp delete mode 100755 testapp/yaksh/c_cpp_files/main_check_digit.cpp delete mode 100755 testapp/yaksh/c_cpp_files/main_count667.cpp delete mode 100755 testapp/yaksh/c_cpp_files/main_count7.cpp delete mode 100755 testapp/yaksh/c_cpp_files/main_fact.cpp delete mode 100755 testapp/yaksh/c_cpp_files/main_greatest.cpp delete mode 100755 testapp/yaksh/c_cpp_files/main_hello_name.c delete mode 100755 testapp/yaksh/c_cpp_files/main_lessThan9.cpp delete mode 100755 testapp/yaksh/c_cpp_files/main_mean.cpp delete mode 100755 testapp/yaksh/c_cpp_files/main_palindrome.cpp delete mode 100755 testapp/yaksh/c_cpp_files/main_roundTo10.cpp delete mode 100755 testapp/yaksh/c_cpp_files/main_specialSum.cpp delete mode 100755 testapp/yaksh/c_cpp_files/main_within.cpp delete mode 100644 testapp/yaksh/code_evaluator.py delete mode 100755 testapp/yaksh/code_server.py delete mode 100644 testapp/yaksh/cpp_code_evaluator.py delete mode 100644 testapp/yaksh/docs/sample.args delete mode 100755 testapp/yaksh/docs/sample.sh delete mode 100644 testapp/yaksh/docs/sample_questions.py delete mode 100644 testapp/yaksh/docs/sample_questions.xml delete mode 100644 testapp/yaksh/forms.py delete mode 100644 testapp/yaksh/java_code_evaluator.py delete mode 100644 testapp/yaksh/java_files/main_array_sum.java delete mode 100644 testapp/yaksh/java_files/main_fact.java delete mode 100644 testapp/yaksh/java_files/main_great.java delete mode 100644 testapp/yaksh/java_files/main_hello_name.java delete mode 100644 testapp/yaksh/java_files/main_lastDigit.java delete mode 100644 testapp/yaksh/java_files/main_moreThan30.java delete mode 100644 testapp/yaksh/java_files/main_palindrome.java delete mode 100644 testapp/yaksh/java_files/main_square.java delete mode 100644 testapp/yaksh/language_registry.py delete mode 100644 testapp/yaksh/management/__init__.py delete mode 100644 testapp/yaksh/management/commands/__init__.py delete mode 100644 testapp/yaksh/management/commands/add_group.py delete mode 100644 testapp/yaksh/management/commands/dump_user_data.py delete mode 100644 testapp/yaksh/management/commands/load_exam.py delete mode 100644 testapp/yaksh/management/commands/load_questions_xml.py delete mode 100644 testapp/yaksh/management/commands/results2csv.py delete mode 100644 testapp/yaksh/models.py delete mode 100644 testapp/yaksh/output/README.txt delete mode 100644 testapp/yaksh/python_code_evaluator.py delete mode 100644 testapp/yaksh/scilab_code_evaluator.py delete mode 100644 testapp/yaksh/scilab_files/test_add.sce delete mode 100644 testapp/yaksh/settings.py delete mode 100644 testapp/yaksh/static/yaksh_app/css/autotaggit.css delete mode 100644 testapp/yaksh/static/yaksh_app/css/base.css delete mode 100644 testapp/yaksh/static/yaksh_app/css/gradeuser.css delete mode 100644 testapp/yaksh/static/yaksh_app/css/login.css delete mode 100644 testapp/yaksh/static/yaksh_app/css/monitor.css delete mode 100644 testapp/yaksh/static/yaksh_app/css/question.css delete mode 100644 testapp/yaksh/static/yaksh_app/css/question_paper_creation.css delete mode 100644 testapp/yaksh/static/yaksh_app/css/question_quiz.css delete mode 100644 testapp/yaksh/static/yaksh_app/css/showusers.css delete mode 100644 testapp/yaksh/static/yaksh_app/js/add_question.js delete mode 100644 testapp/yaksh/static/yaksh_app/js/add_questionpaper.js delete mode 100644 testapp/yaksh/static/yaksh_app/js/add_quiz.js delete mode 100644 testapp/yaksh/static/yaksh_app/js/bootstrap-modal.js delete mode 100644 testapp/yaksh/static/yaksh_app/js/bootstrap-tabs.js delete mode 100644 testapp/yaksh/static/yaksh_app/js/edit_question.js delete mode 100644 testapp/yaksh/static/yaksh_app/js/edit_quiz.js delete mode 100644 testapp/yaksh/static/yaksh_app/js/jquery-1.4.2.min.js delete mode 100644 testapp/yaksh/static/yaksh_app/js/min.js delete mode 100644 testapp/yaksh/static/yaksh_app/js/question.js delete mode 100644 testapp/yaksh/static/yaksh_app/js/question_filter.js delete mode 100644 testapp/yaksh/static/yaksh_app/js/question_paper_creation.js delete mode 100644 testapp/yaksh/static/yaksh_app/js/show_question.js delete mode 100644 testapp/yaksh/static/yaksh_app/js/show_quiz.js delete mode 100644 testapp/yaksh/templates/404.html delete mode 100644 testapp/yaksh/templates/500.html delete mode 100644 testapp/yaksh/templates/base.html delete mode 100644 testapp/yaksh/templates/manage.html delete mode 100644 testapp/yaksh/templates/user.html delete mode 100644 testapp/yaksh/templates/yaksh/add_question.html delete mode 100644 testapp/yaksh/templates/yaksh/add_questionpaper.html delete mode 100644 testapp/yaksh/templates/yaksh/add_quiz.html delete mode 100644 testapp/yaksh/templates/yaksh/ajax_marks.html delete mode 100644 testapp/yaksh/templates/yaksh/ajax_question_filter.html delete mode 100644 testapp/yaksh/templates/yaksh/ajax_questions.html delete mode 100644 testapp/yaksh/templates/yaksh/automatic_questionpaper.html delete mode 100644 testapp/yaksh/templates/yaksh/complete.html delete mode 100644 testapp/yaksh/templates/yaksh/design_questionpaper.html delete mode 100644 testapp/yaksh/templates/yaksh/edit_question.html delete mode 100644 testapp/yaksh/templates/yaksh/edit_quiz.html delete mode 100644 testapp/yaksh/templates/yaksh/editquestionpaper.html delete mode 100644 testapp/yaksh/templates/yaksh/grade_user.html delete mode 100644 testapp/yaksh/templates/yaksh/intro.html delete mode 100644 testapp/yaksh/templates/yaksh/login.html delete mode 100644 testapp/yaksh/templates/yaksh/manual_questionpaper.html delete mode 100644 testapp/yaksh/templates/yaksh/monitor.html delete mode 100644 testapp/yaksh/templates/yaksh/question.html delete mode 100644 testapp/yaksh/templates/yaksh/quit.html delete mode 100644 testapp/yaksh/templates/yaksh/quizlist.html delete mode 100644 testapp/yaksh/templates/yaksh/quizzes_user.html delete mode 100644 testapp/yaksh/templates/yaksh/register.html delete mode 100644 testapp/yaksh/templates/yaksh/results_user.html delete mode 100644 testapp/yaksh/templates/yaksh/show_quiz.html delete mode 100644 testapp/yaksh/templates/yaksh/showquestionpapers.html delete mode 100644 testapp/yaksh/templates/yaksh/showquestions.html delete mode 100644 testapp/yaksh/templates/yaksh/showusers.html delete mode 100644 testapp/yaksh/templates/yaksh/user_data.html delete mode 100644 testapp/yaksh/tests.py delete mode 100644 testapp/yaksh/urls.py delete mode 100644 testapp/yaksh/views.py delete mode 100644 testapp/yaksh/xmlrpc_clients.py (limited to 'testapp') diff --git a/testapp/__init__.py b/testapp/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/testapp/fixtures/initial_fixtures.json b/testapp/fixtures/initial_fixtures.json deleted file mode 100644 index e16b09f..0000000 --- a/testapp/fixtures/initial_fixtures.json +++ /dev/null @@ -1 +0,0 @@ -[{"pk": 1, "model": "contenttypes.contenttype", "fields": {"model": "logentry", "name": "log entry", "app_label": "admin"}}, {"pk": 2, "model": "contenttypes.contenttype", "fields": {"model": "permission", "name": "permission", "app_label": "auth"}}, {"pk": 3, "model": "contenttypes.contenttype", "fields": {"model": "group", "name": "group", "app_label": "auth"}}, {"pk": 4, "model": "contenttypes.contenttype", "fields": {"model": "user", "name": "user", "app_label": "auth"}}, {"pk": 5, "model": "contenttypes.contenttype", "fields": {"model": "contenttype", "name": "content type", "app_label": "contenttypes"}}, {"pk": 6, "model": "contenttypes.contenttype", "fields": {"model": "session", "name": "session", "app_label": "sessions"}}, {"pk": 7, "model": "contenttypes.contenttype", "fields": {"model": "profile", "name": "profile", "app_label": "exam"}}, {"pk": 8, "model": "contenttypes.contenttype", "fields": {"model": "question", "name": "question", "app_label": "exam"}}, {"pk": 9, "model": "contenttypes.contenttype", "fields": {"model": "answer", "name": "answer", "app_label": "exam"}}, {"pk": 10, "model": "contenttypes.contenttype", "fields": {"model": "quiz", "name": "quiz", "app_label": "exam"}}, {"pk": 11, "model": "contenttypes.contenttype", "fields": {"model": "questionpaper", "name": "question paper", "app_label": "exam"}}, {"pk": 12, "model": "contenttypes.contenttype", "fields": {"model": "questionset", "name": "question set", "app_label": "exam"}}, {"pk": 13, "model": "contenttypes.contenttype", "fields": {"model": "answerpaper", "name": "answer paper", "app_label": "exam"}}, {"pk": 14, "model": "contenttypes.contenttype", "fields": {"model": "assignmentupload", "name": "assignment upload", "app_label": "exam"}}, {"pk": 15, "model": "contenttypes.contenttype", "fields": {"model": "testcase", "name": "test case", "app_label": "exam"}}, {"pk": 16, "model": "contenttypes.contenttype", "fields": {"model": "tag", "name": "Tag", "app_label": "taggit"}}, {"pk": 17, "model": "contenttypes.contenttype", "fields": {"model": "taggeditem", "name": "Tagged Item", "app_label": "taggit"}}, {"pk": "3tcbtzy1umsaf1zesqbsprjm2bw7w1gi", "model": "sessions.session", "fields": {"expire_date": "2015-07-08T12:52:42.395", "session_data": "ZjM0OGNlZmQxYzgzM2U4ZGJlNGZkYzE3MDdmYzY5NDMzMmVlMzdmYjp7Il9hdXRoX3VzZXJfYmFja2VuZCI6ImRqYW5nby5jb250cmliLmF1dGguYmFja2VuZHMuTW9kZWxCYWNrZW5kIiwiX2F1dGhfdXNlcl9pZCI6MX0="}}, {"pk": 1, "model": "exam.question", "fields": {"ref_code_path": "", "description": "\r\nWrite a function called fact
which takes a single integer argument\r\n(sayn
) and returns the factorial of the number. \r\nFor example:
\r\nfact(3) -> 6
\r\n", "language": "python", "summary": "Factorial", "snippet": "def fact(num):", "active": true, "points": 2.0, "test": "assert fact(0) == 1\r\nassert fact(5) == 120", "type": "code", "options": ""}}, {"pk": 2, "model": "exam.question", "fields": {"ref_code_path": "", "description": "Create a simple function calledsqr
which takes a single \r\nargument and returns the square of the argument. For example:
\r\nsqr(3) -> 9
.", "language": "python", "summary": "Simple function", "snippet": "def sqr(num):", "active": true, "points": 1.0, "test": "import math\r\nassert sqr(3) == 9\r\nassert abs(sqr(math.sqrt(2)) - 2.0) < 1e-14", "type": "code", "options": ""}}, {"pk": 3, "model": "exam.question", "fields": {"ref_code_path": "docs/sample.sh, docs/sample.args", "description": "Write a shell script which takes two arguments on the\r\n command line and prints the sum of the two on the output.", "language": "bash", "summary": "Bash addition", "snippet": "#!/bin/bash", "active": true, "points": 2.0, "test": "", "type": "code", "options": ""}}, {"pk": 4, "model": "exam.question", "fields": {"ref_code_path": "", "description": "What is the largest integer value that can be represented\r\nin Python?", "language": "python", "summary": "Size of integer in Python", "snippet": "", "active": true, "points": 0.5, "test": "No Limit", "type": "mcq", "options": "No Limit\r\n2**32\r\n2**32 - 1\r\nNone of the above\r\n"}}, {"pk": 1, "model": "exam.quiz", "fields": {"description": "Demo Quiz", "language": "C", "time_between_attempts": 0, "pass_criteria": 2.0, "active": true, "attempts_allowed": -1, "duration": 30, "start_date": "2015-06-24", "prerequisite": null}}, {"pk": 1, "model": "exam.questionpaper", "fields": {"shuffle_questions": true, "total_marks": 5.5, "fixed_questions": [1, 2, 3, 4], "random_questions": [], "quiz": 1}}, {"pk": 1, "model": "taggit.tag", "fields": {"name": "Python", "slug": "python"}}, {"pk": 2, "model": "taggit.tag", "fields": {"name": "function", "slug": "function"}}, {"pk": 3, "model": "taggit.tag", "fields": {"name": "factorial", "slug": "factorial"}}, {"pk": 4, "model": "taggit.tag", "fields": {"name": "", "slug": ""}}, {"pk": 5, "model": "taggit.tag", "fields": {"name": "mcq", "slug": "mcq"}}, {"pk": 8, "model": "taggit.taggeditem", "fields": {"tag": 1, "content_type": 8, "object_id": 1}}, {"pk": 9, "model": "taggit.taggeditem", "fields": {"tag": 2, "content_type": 8, "object_id": 1}}, {"pk": 10, "model": "taggit.taggeditem", "fields": {"tag": 3, "content_type": 8, "object_id": 1}}, {"pk": 11, "model": "taggit.taggeditem", "fields": {"tag": 1, "content_type": 8, "object_id": 2}}, {"pk": 12, "model": "taggit.taggeditem", "fields": {"tag": 2, "content_type": 8, "object_id": 2}}, {"pk": 13, "model": "taggit.taggeditem", "fields": {"tag": 5, "content_type": 8, "object_id": 4}}, {"pk": 1, "model": "auth.permission", "fields": {"codename": "add_logentry", "name": "Can add log entry", "content_type": 1}}, {"pk": 2, "model": "auth.permission", "fields": {"codename": "change_logentry", "name": "Can change log entry", "content_type": 1}}, {"pk": 3, "model": "auth.permission", "fields": {"codename": "delete_logentry", "name": "Can delete log entry", "content_type": 1}}, {"pk": 4, "model": "auth.permission", "fields": {"codename": "add_permission", "name": "Can add permission", "content_type": 2}}, {"pk": 5, "model": "auth.permission", "fields": {"codename": "change_permission", "name": "Can change permission", "content_type": 2}}, {"pk": 6, "model": "auth.permission", "fields": {"codename": "delete_permission", "name": "Can delete permission", "content_type": 2}}, {"pk": 7, "model": "auth.permission", "fields": {"codename": "add_group", "name": "Can add group", "content_type": 3}}, {"pk": 8, "model": "auth.permission", "fields": {"codename": "change_group", "name": "Can change group", "content_type": 3}}, {"pk": 9, "model": "auth.permission", "fields": {"codename": "delete_group", "name": "Can delete group", "content_type": 3}}, {"pk": 10, "model": "auth.permission", "fields": {"codename": "add_user", "name": "Can add user", "content_type": 4}}, {"pk": 11, "model": "auth.permission", "fields": {"codename": "change_user", "name": "Can change user", "content_type": 4}}, {"pk": 12, "model": "auth.permission", "fields": {"codename": "delete_user", "name": "Can delete user", "content_type": 4}}, {"pk": 13, "model": "auth.permission", "fields": {"codename": "add_contenttype", "name": "Can add content type", "content_type": 5}}, {"pk": 14, "model": "auth.permission", "fields": {"codename": "change_contenttype", "name": "Can change content type", "content_type": 5}}, {"pk": 15, "model": "auth.permission", "fields": {"codename": "delete_contenttype", "name": "Can delete content type", "content_type": 5}}, {"pk": 16, "model": "auth.permission", "fields": {"codename": "add_session", "name": "Can add session", "content_type": 6}}, {"pk": 17, "model": "auth.permission", "fields": {"codename": "change_session", "name": "Can change session", "content_type": 6}}, {"pk": 18, "model": "auth.permission", "fields": {"codename": "delete_session", "name": "Can delete session", "content_type": 6}}, {"pk": 19, "model": "auth.permission", "fields": {"codename": "add_profile", "name": "Can add profile", "content_type": 7}}, {"pk": 20, "model": "auth.permission", "fields": {"codename": "change_profile", "name": "Can change profile", "content_type": 7}}, {"pk": 21, "model": "auth.permission", "fields": {"codename": "delete_profile", "name": "Can delete profile", "content_type": 7}}, {"pk": 22, "model": "auth.permission", "fields": {"codename": "add_question", "name": "Can add question", "content_type": 8}}, {"pk": 23, "model": "auth.permission", "fields": {"codename": "change_question", "name": "Can change question", "content_type": 8}}, {"pk": 24, "model": "auth.permission", "fields": {"codename": "delete_question", "name": "Can delete question", "content_type": 8}}, {"pk": 25, "model": "auth.permission", "fields": {"codename": "add_answer", "name": "Can add answer", "content_type": 9}}, {"pk": 26, "model": "auth.permission", "fields": {"codename": "change_answer", "name": "Can change answer", "content_type": 9}}, {"pk": 27, "model": "auth.permission", "fields": {"codename": "delete_answer", "name": "Can delete answer", "content_type": 9}}, {"pk": 28, "model": "auth.permission", "fields": {"codename": "add_quiz", "name": "Can add quiz", "content_type": 10}}, {"pk": 29, "model": "auth.permission", "fields": {"codename": "change_quiz", "name": "Can change quiz", "content_type": 10}}, {"pk": 30, "model": "auth.permission", "fields": {"codename": "delete_quiz", "name": "Can delete quiz", "content_type": 10}}, {"pk": 31, "model": "auth.permission", "fields": {"codename": "add_questionpaper", "name": "Can add question paper", "content_type": 11}}, {"pk": 32, "model": "auth.permission", "fields": {"codename": "change_questionpaper", "name": "Can change question paper", "content_type": 11}}, {"pk": 33, "model": "auth.permission", "fields": {"codename": "delete_questionpaper", "name": "Can delete question paper", "content_type": 11}}, {"pk": 34, "model": "auth.permission", "fields": {"codename": "add_questionset", "name": "Can add question set", "content_type": 12}}, {"pk": 35, "model": "auth.permission", "fields": {"codename": "change_questionset", "name": "Can change question set", "content_type": 12}}, {"pk": 36, "model": "auth.permission", "fields": {"codename": "delete_questionset", "name": "Can delete question set", "content_type": 12}}, {"pk": 37, "model": "auth.permission", "fields": {"codename": "add_answerpaper", "name": "Can add answer paper", "content_type": 13}}, {"pk": 38, "model": "auth.permission", "fields": {"codename": "change_answerpaper", "name": "Can change answer paper", "content_type": 13}}, {"pk": 39, "model": "auth.permission", "fields": {"codename": "delete_answerpaper", "name": "Can delete answer paper", "content_type": 13}}, {"pk": 40, "model": "auth.permission", "fields": {"codename": "add_assignmentupload", "name": "Can add assignment upload", "content_type": 14}}, {"pk": 41, "model": "auth.permission", "fields": {"codename": "change_assignmentupload", "name": "Can change assignment upload", "content_type": 14}}, {"pk": 42, "model": "auth.permission", "fields": {"codename": "delete_assignmentupload", "name": "Can delete assignment upload", "content_type": 14}}, {"pk": 43, "model": "auth.permission", "fields": {"codename": "add_testcase", "name": "Can add test case", "content_type": 15}}, {"pk": 44, "model": "auth.permission", "fields": {"codename": "change_testcase", "name": "Can change test case", "content_type": 15}}, {"pk": 45, "model": "auth.permission", "fields": {"codename": "delete_testcase", "name": "Can delete test case", "content_type": 15}}, {"pk": 46, "model": "auth.permission", "fields": {"codename": "add_tag", "name": "Can add Tag", "content_type": 16}}, {"pk": 47, "model": "auth.permission", "fields": {"codename": "change_tag", "name": "Can change Tag", "content_type": 16}}, {"pk": 48, "model": "auth.permission", "fields": {"codename": "delete_tag", "name": "Can delete Tag", "content_type": 16}}, {"pk": 49, "model": "auth.permission", "fields": {"codename": "add_taggeditem", "name": "Can add Tagged Item", "content_type": 17}}, {"pk": 50, "model": "auth.permission", "fields": {"codename": "change_taggeditem", "name": "Can change Tagged Item", "content_type": 17}}, {"pk": 51, "model": "auth.permission", "fields": {"codename": "delete_taggeditem", "name": "Can delete Tagged Item", "content_type": 17}}, {"pk": 1, "model": "auth.group", "fields": {"name": "moderator", "permissions": [25, 26, 27, 37, 38, 39, 40, 41, 42, 19, 20, 21, 22, 23, 24, 31, 32, 33, 34, 35, 36, 28, 29, 30, 43, 44, 45]}}, {"pk": 1, "model": "auth.user", "fields": {"username": "admin", "first_name": "", "last_name": "", "is_active": true, "is_superuser": true, "is_staff": true, "last_login": "2015-06-24T12:52:42.246", "groups": [1], "user_permissions": [], "password": "pbkdf2_sha256$12000$cm9G5GLAN5TA$hmAKSYEUGjgicK/JJPYlB3BiROfv6FLJqhw/slAQIqU=", "email": "admin@admin.com", "date_joined": "2015-06-24T12:47:31"}}, {"pk": 2, "model": "auth.user", "fields": {"username": "teacher", "first_name": "Teacher", "last_name": "Demo", "is_active": true, "is_superuser": false, "is_staff": false, "last_login": "2015-06-24T12:50:42", "groups": [1], "user_permissions": [], "password": "pbkdf2_sha256$12000$RVSJsXu5jmkK$TfcRzV2LPFpEpv/shnlPG1CxWK6D6HovprqE+1neuqk=", "email": "teacher@teacher.com", "date_joined": "2015-06-24T12:50:40"}}, {"pk": 3, "model": "auth.user", "fields": {"username": "student", "first_name": "Student", "last_name": "Demo", "is_active": true, "is_superuser": false, "is_staff": false, "last_login": "2015-06-24T12:51:41.470", "groups": [], "user_permissions": [], "password": "pbkdf2_sha256$12000$jdwsvOoiB4UH$G+iAJR0nse50jxyNd+V/IATLrTra/FtaL+R1Uat0ewE=", "email": "student@student.com", "date_joined": "2015-06-24T12:51:40.477"}}, {"pk": 1, "model": "exam.profile", "fields": {"institute": "Teacher Institute", "department": "Teacher Department", "roll_number": "12345", "user": 2, "position": "Teacher"}}, {"pk": 2, "model": "exam.profile", "fields": {"institute": "Student Institute", "department": "Student Department", "roll_number": "54321", "user": 3, "position": "Student"}}, {"pk": 1, "model": "admin.logentry", "fields": {"action_flag": 1, "action_time": "2015-06-24T12:49:40.282", "object_repr": "moderator", "object_id": "1", "change_message": "", "user": 1, "content_type": 3}}, {"pk": 2, "model": "admin.logentry", "fields": {"action_flag": 2, "action_time": "2015-06-24T12:52:08.691", "object_repr": "admin", "object_id": "1", "change_message": "Changed groups.", "user": 1, "content_type": 4}}, {"pk": 3, "model": "admin.logentry", "fields": {"action_flag": 2, "action_time": "2015-06-24T12:52:17.144", "object_repr": "teacher", "object_id": "2", "change_message": "Changed groups.", "user": 1, "content_type": 4}}] \ No newline at end of file diff --git a/testapp/myauthentication/README b/testapp/myauthentication/README deleted file mode 100644 index 4aef3c5..0000000 --- a/testapp/myauthentication/README +++ /dev/null @@ -1,12 +0,0 @@ -To use authentication from external source, follow the instructions given below: - -1. In settings.py, - Uncomment AUTHENTICATION_BACKENDS = ('myauthentication.backend.MyBackend',) - Uncomment AUTHENTICATION_BACKENDS = ('myauthentication.backend.MyBackend',) - Enter database name, username and password for the spoken tutorial database. - -2. From login.html template comment 'New User? Sign-Up' link. - This is to be done so that user will register only from external - application and their details will be stored in the external database. - -3. In urls.py comment 'register' url pattern. diff --git a/testapp/myauthentication/__init__.py b/testapp/myauthentication/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/testapp/myauthentication/backend.py b/testapp/myauthentication/backend.py deleted file mode 100644 index 721fe54..0000000 --- a/testapp/myauthentication/backend.py +++ /dev/null @@ -1,43 +0,0 @@ -import hashlib -from django.contrib.auth.models import User, check_password -from models_spoken_tutorial import MoodleUser - - -class MyBackend: - supports_object_permissions = False - supports_anonymous_user = False - supports_inactive_user = False - - def authenticate(self, username=None, password=None): - ''' - Checks username and password with external User table. - If valid then adds the user details in django User table - and authenticates the user. - ''' - try: - user = MoodleUser.objects.get(username=username) - pwd = user.password - uid = user.id - firstname = user.firstname - lastname = user.lastname - email_id = user.email - p = hashlib.md5(password) - pwd_valid = (pwd == p.hexdigest()) - if user and pwd_valid: - try: - user = User.objects.get(username=username) - return user - except Exception, e: - user = User(id=uid, username=username, password=pwd, - first_name=firstname, last_name=lastname, - email=email_id) - user.save() - return user - except Exception, e: - return None - - def get_user(self, user_id): - try: - return User.objects.get(pk=user_id) - except Exception, e: - return None diff --git a/testapp/myauthentication/models_spoken_tutorial.py b/testapp/myauthentication/models_spoken_tutorial.py deleted file mode 100644 index d333400..0000000 --- a/testapp/myauthentication/models_spoken_tutorial.py +++ /dev/null @@ -1,26 +0,0 @@ -# This is an auto-generated Django model module. -# You'll have to do the following manually to clean this up: -# * Rearrange models' order -# * Make sure each model has one field with primary_key=True -# Feel free to rename the models, but don't rename db_table values or field names. -# -# Also note: You'll have to insert the output of 'django-admin.py sqlcustom [appname]' -# into your database. - -from django.db import models - -class MoodleUser(models.Model): - id = models.BigIntegerField(primary_key=True) - username = models.CharField(unique=True, max_length=300) - password = models.CharField(max_length=96) - idnumber = models.CharField(max_length=765) - firstname = models.CharField(max_length=300) - lastname = models.CharField(max_length=300) - email = models.CharField(max_length=300) - institution = models.CharField(max_length=120) - department = models.CharField(max_length=90) - address = models.CharField(max_length=210) - city = models.CharField(max_length=360) - country = models.CharField(max_length=6) - class Meta: - db_table = u'mdl_user' diff --git a/testapp/myauthentication/router.py b/testapp/myauthentication/router.py deleted file mode 100644 index 3d9c330..0000000 --- a/testapp/myauthentication/router.py +++ /dev/null @@ -1,12 +0,0 @@ -class MyDatabaseRouter(object): - """ - A router to manage database operations in the myauthentication app. - """ - def db_for_read(self, model, **hints): - """ - Point all read operations on myauthentication app to spoken - database. - """ - if model._meta.app_label == 'myauthentication': - return 'spoken_tutorial' - return None diff --git a/testapp/myauthentication/tests.py b/testapp/myauthentication/tests.py deleted file mode 100644 index 4103038..0000000 --- a/testapp/myauthentication/tests.py +++ /dev/null @@ -1,5 +0,0 @@ -#This file demonstrates writing tests using the unittest module. These will pass -#when you run "manage.py test". - -#Write appropriate tests for the application. - diff --git a/testapp/myauthentication/urls.py b/testapp/myauthentication/urls.py deleted file mode 100644 index e69de29..0000000 diff --git a/testapp/myauthentication/views.py b/testapp/myauthentication/views.py deleted file mode 100644 index 60f00ef..0000000 --- a/testapp/myauthentication/views.py +++ /dev/null @@ -1 +0,0 @@ -# Create your views here. diff --git a/testapp/scripts/__init__.py b/testapp/scripts/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/testapp/scripts/project_detail.py b/testapp/scripts/project_detail.py deleted file mode 100644 index 583e9f4..0000000 --- a/testapp/scripts/project_detail.py +++ /dev/null @@ -1,2 +0,0 @@ -NAME = None -PATH = None diff --git a/testapp/scripts/yaksh.py b/testapp/scripts/yaksh.py deleted file mode 100644 index 8b3e8b7..0000000 --- a/testapp/scripts/yaksh.py +++ /dev/null @@ -1,147 +0,0 @@ -from __future__ import print_function - -import subprocess -import contextlib -import os -from os import path -import argparse -from importlib import import_module -from django.conf import settings -from django.core import management -from django.template import Template, Context, loader - -from project_detail import NAME, PATH - -CUR_DIR = os.getcwd() -SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__)) -PARENT_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, os.pardir)) -TEMPLATE_DIR = path.join(PARENT_DIR, 'templates') - -def main(): - #Parse command-line to obtain the arguments and/or options - # create top-level parser object - parser = argparse.ArgumentParser(prog="vimarsh") - subparser = parser.add_subparsers(dest="subcommand") - - # create parser for the "create_demo" subcommand - create_demo_parser = subparser.add_parser("create_demo", - help="Create a new demo Django project") - create_demo_parser.add_argument("project_name", type=str, - help="name of demo Django project") - create_demo_parser.add_argument("-p", "--path", type=str, - help="path of demo Django project") - - # create parser for the "run_demo" subcommand - run_demo_parser = subparser.add_parser("run_demo", - help="Initialise django server and run the demo project") - - # create parser for the "run_code_server" subcommand - code_server_parser = subparser.add_parser("run_code_server", - help="Initialise Vimarsh code server") - code_server_parser.add_argument("-P", "--ports", type=int, nargs='+', - help="code server ports") - - args = parser.parse_args() - - if args.subcommand == "create_demo": - if args.path: - create_demo(args.project_name, args.path) - else: - create_demo(args.project_name) - - elif args.subcommand == "run_demo": - try: - run_demo(NAME, PATH) - except Exception as e: - if not NAME or not PATH: - print("Error: Unable to find Project Name or Path variables\n") - else: - print("Error: {0}\n".format(e)) - subparser.print_help() - - elif args.subcommand == "run_code_server": - if args.ports: - run_server(args.ports) - else: - run_server() - -def create_demo(project_name='vimarsh_demo', project_dir=CUR_DIR): - try: - management.call_command('startproject', project_name, project_dir) - print("Demo Django project '{0}' created at '{1}'".format(project_name, - project_dir)) - except Exception, e: - print("Error: {0}\nExiting Vimarsh Installer".format(e)) - - if project_dir is None: - top_dir = path.join(os.getcwd(), project_name) - else: - top_dir = project_dir - - project_path = path.join(top_dir, project_name) - fixture_dir = path.join(PARENT_DIR, 'fixtures') - # Store project details - _set_project_details(project_name, top_dir) - - with _chdir(project_path): - root_urlconf = "{0}.{1}".format(project_name, 'demo_urls') - settings_template_path = path.join(TEMPLATE_DIR, 'demo_settings.py') - settings_target_path = path.join(project_path, 'demo_settings.py') - settings_context = Context({'project_name': project_name, - 'root_urlconf': root_urlconf, - 'fixture_dir': fixture_dir}) - urls_template_path = path.join(TEMPLATE_DIR, 'demo_urls.py') - urls_target_path = path.join(project_path, 'demo_urls.py') - command = ("python ../manage.py syncdb " - "--noinput --settings={0}.demo_settings").format(project_name) - - # Create demo_settings file - _render_demo_files(settings_template_path, settings_target_path, settings_context) - # Create demo_urls file - _render_demo_files(urls_template_path, urls_target_path) - # Run syncdb - subprocess.call(command, shell=True) - -def run_demo(project_name, top_dir): - with _chdir(top_dir): - project_path = path.join(top_dir, 'manage.py') - command = ("python manage.py runserver " - "--settings={0}.demo_settings").format(project_name) - subprocess.call(command, shell=True) - -def run_server(): - try: - from testapp.exam import code_server - code_server.main() - except Exception as e: - print("Error: {0}\nExiting Vimarsh code server".format(e)) - -def _set_project_details(project_name, top_dir): - file_path = path.join(SCRIPT_DIR, 'project_detail.py') - detail = "NAME ='{0}'\nPATH ='{1}'".format(project_name, top_dir) - with open(file_path, 'w') as data_store: - data_store.write(detail) - -def _render_demo_files(template_path, output_path, context=None): - with open(template_path, 'r') as template_file: - content = template_file.read() - if context: - content = content.decode('utf-8') - template = Template(content) - content = template.render(context) - content = content.encode('utf-8') - - with open(output_path, 'w') as new_file: - new_file.write(content) - -@contextlib.contextmanager -def _chdir(path): - starting_directory = os.getcwd() - try: - os.chdir(path) - yield - finally: - os.chdir(starting_directory) - -if __name__ == '__main__': - main() diff --git a/testapp/templates/demo_settings.py b/testapp/templates/demo_settings.py deleted file mode 100644 index ecc1fe3..0000000 --- a/testapp/templates/demo_settings.py +++ /dev/null @@ -1,88 +0,0 @@ -""" -Django settings for my_demo project. - -For more information on this file, see -https://docs.djangoproject.com/en/1.6/topics/settings/ - -For the full list of settings and their values, see -https://docs.djangoproject.com/en/1.6/ref/settings/ -""" - -# Build paths inside the project like this: os.path.join(BASE_DIR, ...) -import os -BASE_DIR = os.path.dirname(os.path.dirname(__file__)) - - -# Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/1.6/howto/deployment/checklist/ - -# SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = 'TH!S_!S_@_DUMMY_K3Y' - -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True - -TEMPLATE_DEBUG = True - -ALLOWED_HOSTS = [] - - -# Application definition - -FIXTURE_DIRS = ('{{ fixture_dir }}') - -INSTALLED_APPS = ( - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'testapp.exam', - 'taggit', -) - -MIDDLEWARE_CLASSES = ( - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', -) - -ROOT_URLCONF = '{{ root_urlconf }}' - -WSGI_APPLICATION = '{{ project_name }}.wsgi.application' - - -# Database -# https://docs.djangoproject.com/en/1.6/ref/settings/#databases - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), - } -} - -# Internationalization -# https://docs.djangoproject.com/en/1.6/topics/i18n/ - -LANGUAGE_CODE = 'en-us' - -TIME_ZONE = 'UTC' - -USE_I18N = True - -USE_L10N = True - -USE_TZ = False - - -# Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/1.6/howto/static-files/ - -STATIC_URL = '/static/' - -AUTH_PROFILE_MODULE = 'exam.Profile' diff --git a/testapp/templates/demo_urls.py b/testapp/templates/demo_urls.py deleted file mode 100644 index da8bc2b..0000000 --- a/testapp/templates/demo_urls.py +++ /dev/null @@ -1,13 +0,0 @@ -from django.conf.urls import patterns, include, url - -from django.contrib import admin -admin.autodiscover() - -urlpatterns = patterns('', - # Examples: - # url(r'^$', 'my_demo.views.home', name='home'), - # url(r'^blog/', include('blog.urls')), - - url(r'^admin/', include(admin.site.urls)), - url(r'^exam/', include('testapp.yaksh.urls')), -) diff --git a/testapp/tests/__init__.py b/testapp/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/testapp/tests/test_bash_evaluation.py b/testapp/tests/test_bash_evaluation.py deleted file mode 100644 index 4f7e4b6..0000000 --- a/testapp/tests/test_bash_evaluation.py +++ /dev/null @@ -1,41 +0,0 @@ -import unittest -import os -from testapp.yaksh.bash_code_evaluator import BashCodeEvaluator -from testapp.yaksh.settings import SERVER_TIMEOUT - -class BashEvaluationTestCases(unittest.TestCase): - def setUp(self): - self.language = "bash" - self.ref_code_path = "bash_files/sample.sh,bash_files/sample.args" - self.in_dir = "/tmp" - self.test_case_data = [] - self.timeout_msg = ("Code took more than {0} seconds to run. " - "You probably have an infinite loop in your code.").format(SERVER_TIMEOUT) - self.test = None - - def test_correct_answer(self): - user_answer = "#!/bin/bash\n[[ $# -eq 2 ]] && echo $(( $1 + $2 )) && exit $(( $1 + $2 ))" - get_class = BashCodeEvaluator(self.test_case_data, self.test, self.language, user_answer, self.ref_code_path, self.in_dir) - result = get_class.evaluate() - - self.assertTrue(result.get("success")) - self.assertEqual(result.get("error"), "Correct answer") - - def test_error(self): - user_answer = "#!/bin/bash\n[[ $# -eq 2 ]] && echo $(( $1 - $2 )) && exit $(( $1 - $2 ))" - get_class = BashCodeEvaluator(self.test_case_data, self.test, self.language, user_answer, self.ref_code_path, self.in_dir) - result = get_class.evaluate() - - self.assertFalse(result.get("success")) - self.assertTrue("Error" in result.get("error")) - - def test_infinite_loop(self): - user_answer = "#!/bin/bash\nwhile [ 1 ] ; do echo "" > /dev/null ; done" - get_class = BashCodeEvaluator(self.test_case_data, self.test, self.language, user_answer, self.ref_code_path, self.in_dir) - result = get_class.evaluate() - - self.assertFalse(result.get("success")) - self.assertEquals(result.get("error"), self.timeout_msg) - -if __name__ == '__main__': - unittest.main() diff --git a/testapp/tests/test_c_cpp_evaluation.py b/testapp/tests/test_c_cpp_evaluation.py deleted file mode 100644 index 9cbc013..0000000 --- a/testapp/tests/test_c_cpp_evaluation.py +++ /dev/null @@ -1,77 +0,0 @@ -import unittest -import os -from testapp.yaksh.cpp_code_evaluator import CppCodeEvaluator -from testapp.yaksh.settings import SERVER_TIMEOUT - -class CEvaluationTestCases(unittest.TestCase): - def setUp(self): - self.language = "C" - self.ref_code_path = "c_cpp_files/main.cpp" - self.in_dir = "/tmp" - self.test_case_data = [] - self.timeout_msg = ("Code took more than {0} seconds to run. " - "You probably have an infinite loop in your code.").format(SERVER_TIMEOUT) - self.test = None - - def test_correct_answer(self): - user_answer = "int add(int a, int b)\n{return a+b;}" - get_class = CppCodeEvaluator(self.test_case_data, self.test, self.language, user_answer, self.ref_code_path, self.in_dir) - result = get_class.evaluate() - - self.assertTrue(result.get("success")) - self.assertEqual(result.get("error"), "Correct answer") - - def test_compilation_error(self): - user_answer = "int add(int a, int b)\n{return a+b}" - get_class = CppCodeEvaluator(self.test_case_data, self.test, self.language, user_answer, self.ref_code_path, self.in_dir) - result = get_class.evaluate() - - self.assertFalse(result.get("success")) - self.assertTrue("Compilation Error" in result.get("error")) - - def test_infinite_loop(self): - user_answer = "int add(int a, int b)\n{while(1>0){}}" - get_class = CppCodeEvaluator(self.test_case_data, self.test, self.language, user_answer, self.ref_code_path, self.in_dir) - result = get_class.evaluate() - - self.assertFalse(result.get("success")) - self.assertEquals(result.get("error"), self.timeout_msg) - - -############################################################################### -class CppEvaluationTestCases(unittest.TestCase): - def setUp(self): - self.language = "CPP" - self.ref_code_path = "c_cpp_files/main.cpp" - self.in_dir = "/tmp" - self.test_case_data = [] - self.timeout_msg = ("Code took more than {0} seconds to run. " - "You probably have an infinite loop in your code.").format(SERVER_TIMEOUT) - self.test = None - - def test_correct_answer(self): - user_answer = "int add(int a, int b)\n{return a+b;}" - get_class = CppCodeEvaluator(self.test_case_data, self.test, self.language, user_answer, self.ref_code_path, self.in_dir) - result = get_class.evaluate() - - self.assertTrue(result.get("success")) - self.assertEqual(result.get("error"), "Correct answer") - - def test_compilation_error(self): - user_answer = "int add(int a, int b)\n{return a+b}" - get_class = CppCodeEvaluator(self.test_case_data, self.test, self.language, user_answer, self.ref_code_path, self.in_dir) - result = get_class.evaluate() - - self.assertFalse(result.get("success")) - self.assertTrue("Compilation Error" in result.get("error")) - - def test_infinite_loop(self): - user_answer = "int add(int a, int b)\n{while(1>0){}}" - get_class = CppCodeEvaluator(self.test_case_data, self.test, self.language, user_answer, self.ref_code_path, self.in_dir) - result = get_class.evaluate() - - self.assertFalse(result.get("success")) - self.assertEquals(result.get("error"), self.timeout_msg) - -if __name__ == '__main__': - unittest.main() diff --git a/testapp/tests/test_code_evaluation.py b/testapp/tests/test_code_evaluation.py deleted file mode 100644 index 10b88b5..0000000 --- a/testapp/tests/test_code_evaluation.py +++ /dev/null @@ -1,24 +0,0 @@ -import unittest -import os -from testapp.yaksh import python_code_evaluator -from testapp.yaksh.language_registry import _LanguageRegistry, set_registry, get_registry -from testapp.yaksh.settings import SERVER_TIMEOUT - - -class RegistryTestCase(unittest.TestCase): - def setUp(self): - set_registry() - self.registry_object = get_registry() - self.language_registry = _LanguageRegistry() - - def test_set_register(self): - class_name = getattr(python_code_evaluator, 'PythonCodeEvaluator') - self.registry_object.register("python", "testapp.yaksh.python_code_evaluator.PythonCodeEvaluator") - self.assertEquals(self.registry_object.get_class("python"), class_name) - - def tearDown(self): - self.registry_object = None - - -if __name__ == '__main__': - unittest.main() diff --git a/testapp/tests/test_java_evaluation.py b/testapp/tests/test_java_evaluation.py deleted file mode 100644 index 92339e4..0000000 --- a/testapp/tests/test_java_evaluation.py +++ /dev/null @@ -1,53 +0,0 @@ -import unittest -import os -from testapp.yaksh import code_evaluator as evaluator -from testapp.yaksh.java_code_evaluator import JavaCodeEvaluator - - -class JavaEvaluationTestCases(unittest.TestCase): - def setUp(self): - self.language = "java" - self.ref_code_path = "java_files/main_square.java" - self.in_dir = "/tmp" - self.test_case_data = [] - evaluator.SERVER_TIMEOUT = 9 - self.timeout_msg = ("Code took more than {0} seconds to run. " - "You probably have an infinite loop in " - "your code.").format(evaluator.SERVER_TIMEOUT) - self.test = None - - def tearDown(self): - evaluator.SERVER_TIMEOUT = 2 - - def test_correct_answer(self): - user_answer = "class Test {\n\tint square_num(int a) {\n\treturn a*a;\n\t}\n}" - get_class = JavaCodeEvaluator(self.test_case_data, self.test, - self.language, user_answer, - self.ref_code_path, self.in_dir) - result = get_class.evaluate() - - self.assertTrue(result.get("success")) - self.assertEqual(result.get("error"), "Correct answer") - - def test_error(self): - user_answer = "class Test {\n\tint square_num(int a) {\n\treturn a*a" - get_class = JavaCodeEvaluator(self.test_case_data, self.test, - self.language, user_answer, - self.ref_code_path, self.in_dir) - result = get_class.evaluate() - - self.assertFalse(result.get("success")) - self.assertTrue("Error" in result.get("error")) - - def test_infinite_loop(self): - user_answer = "class Test {\n\tint square_num(int a) {\n\t\twhile(0==0){\n\t\t}\n\t}\n}" - get_class = JavaCodeEvaluator(self.test_case_data, self.test, - self.language, user_answer, - self.ref_code_path, self.in_dir) - result = get_class.evaluate() - - self.assertFalse(result.get("success")) - self.assertEquals(result.get("error"), self.timeout_msg) - -if __name__ == '__main__': - unittest.main() diff --git a/testapp/tests/test_python_evaluation.py b/testapp/tests/test_python_evaluation.py deleted file mode 100644 index ea01fa8..0000000 --- a/testapp/tests/test_python_evaluation.py +++ /dev/null @@ -1,53 +0,0 @@ -import unittest -import os -from testapp.yaksh.python_code_evaluator import PythonCodeEvaluator -from testapp.yaksh.settings import SERVER_TIMEOUT - -class PythonEvaluationTestCases(unittest.TestCase): - def setUp(self): - self.language = "Python" - self.test = None - self.test_case_data = [{"func_name": "add", - "expected_answer": "5", - "test_id": u'null', - "pos_args": ["3", "2"], - "kw_args": {} - }] - self.timeout_msg = ("Code took more than {0} seconds to run. " - "You probably have an infinite loop in your code.").format(SERVER_TIMEOUT) - - def test_correct_answer(self): - user_answer = "def add(a, b):\n\treturn a + b""" - get_class = PythonCodeEvaluator(self.test_case_data, self.test, self.language, user_answer, ref_code_path=None, in_dir=None) - result = get_class.evaluate() - self.assertTrue(result.get("success")) - self.assertEqual(result.get("error"), "Correct answer") - - def test_incorrect_answer(self): - user_answer = "def add(a, b):\n\treturn a - b" - test_case_data = [{"func_name": "add", - "expected_answer": "5", - "test_id": u'null', - "pos_args": ["3", "2"], - "kw_args": {} - }] - get_class = PythonCodeEvaluator(self.test_case_data, self.test, self.language, user_answer, ref_code_path=None, in_dir=None) - result = get_class.evaluate() - self.assertFalse(result.get("success")) - self.assertEqual(result.get("error"), "AssertionError in: assert add(3, 2) == 5") - - def test_infinite_loop(self): - user_answer = "def add(a, b):\n\twhile True:\n\t\tpass""" - test_case_data = [{"func_name": "add", - "expected_answer": "5", - "test_id": u'null', - "pos_args": ["3", "2"], - "kw_args": {} - }] - get_class = PythonCodeEvaluator(self.test_case_data, self.test, self.language, user_answer, ref_code_path=None, in_dir=None) - result = get_class.evaluate() - self.assertFalse(result.get("success")) - self.assertEquals(result.get("error"), self.timeout_msg) - -if __name__ == '__main__': - unittest.main() diff --git a/testapp/tests/test_scilab_evaluation.py b/testapp/tests/test_scilab_evaluation.py deleted file mode 100644 index 4d05426..0000000 --- a/testapp/tests/test_scilab_evaluation.py +++ /dev/null @@ -1,47 +0,0 @@ -import unittest -import os -from testapp.yaksh.scilab_code_evaluator import ScilabCodeEvaluator -from testapp.yaksh.settings import SERVER_TIMEOUT - -class ScilabEvaluationTestCases(unittest.TestCase): - def setUp(self): - self.language = "scilab" - self.ref_code_path = "scilab_files/test_add.sce" - self.in_dir = "/tmp" - self.test_case_data = [] - self.timeout_msg = ("Code took more than {0} seconds to run. " - "You probably have an infinite loop in your code.").format(SERVER_TIMEOUT) - self.test = None - - def test_correct_answer(self): - user_answer = "funcprot(0)\nfunction[c]=add(a,b)\n\tc=a+b;\nendfunction" - get_class = ScilabCodeEvaluator(self.test_case_data, self.test, - self.language, user_answer, - self.ref_code_path, self.in_dir) - result = get_class.evaluate() - - self.assertTrue(result.get("success")) - self.assertEqual(result.get("error"), "Correct answer") - - def test_error(self): - user_answer = "funcprot(0)\nfunction[c]=add(a,b)\n\tc=a+b;\ndis(\tendfunction" - get_class = ScilabCodeEvaluator(self.test_case_data, self.test, - self.language, user_answer, - self.ref_code_path, self.in_dir) - result = get_class.evaluate() - - self.assertFalse(result.get("success")) - self.assertTrue("error" in result.get("error")) - - def test_infinite_loop(self): - user_answer = "funcprot(0)\nfunction[c]=add(a,b)\n\tc=a;\nwhile(1==1)\nend\nendfunction" - get_class = ScilabCodeEvaluator(self.test_case_data, self.test, - self.language, user_answer, - self.ref_code_path, self.in_dir) - result = get_class.evaluate() - - self.assertFalse(result.get("success")) - self.assertEquals(result.get("error"), self.timeout_msg) - -if __name__ == '__main__': - unittest.main() diff --git a/testapp/urls.py b/testapp/urls.py deleted file mode 100644 index 7022b0d..0000000 --- a/testapp/urls.py +++ /dev/null @@ -1,29 +0,0 @@ -from django.conf.urls import patterns, include, url - -# Uncomment the next two lines to enable the admin: -from django.contrib import admin -admin.autodiscover() - -from settings import URL_ROOT - -if URL_ROOT.startswith('/'): - URL_BASE = r'^%s/exam/'%URL_ROOT[1:] - ADMIN_BASE = r'^%s/admin/'%URL_ROOT[1:] -else: - URL_BASE = r'^exam/' - ADMIN_BASE = r'^admin/' - -urlpatterns = patterns('', - url(URL_BASE, include('yaksh.urls')), - #url(r'^admin/', include(admin.site.urls)), - # Uncomment the admin/doc line below to enable admin documentation: - # url(r'^admin/doc/', include('django.contrib.admindocs.urls')), - # Uncomment the next line to enable the admin: - url(ADMIN_BASE, include(admin.site.urls)), - -) - -urlpatterns += patterns('', - url(r'^taggit_autocomplete_modified/', include\ - ('taggit_autocomplete_modified.urls')), -) diff --git a/testapp/yaksh/__init__.py b/testapp/yaksh/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/testapp/yaksh/admin.py b/testapp/yaksh/admin.py deleted file mode 100644 index ed0afde..0000000 --- a/testapp/yaksh/admin.py +++ /dev/null @@ -1,6 +0,0 @@ -from testapp.yaksh.models import Question, Quiz, TestCase -from django.contrib import admin - -admin.site.register(Question) -admin.site.register(TestCase) -admin.site.register(Quiz) diff --git a/testapp/yaksh/bash_code_evaluator.py b/testapp/yaksh/bash_code_evaluator.py deleted file mode 100644 index a468fd7..0000000 --- a/testapp/yaksh/bash_code_evaluator.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env python -import traceback -import pwd -import os -from os.path import join, isfile -import subprocess -import importlib - -# local imports -from code_evaluator import CodeEvaluator - - -class BashCodeEvaluator(CodeEvaluator): - """Tests the Bash code obtained from Code Server""" - def __init__(self, test_case_data, test, language, user_answer, - ref_code_path=None, in_dir=None): - super(BashCodeEvaluator, self).__init__(test_case_data, test, language, user_answer, - ref_code_path, in_dir) - self.test_case_args = self._setup() - - # Private Protocol ########## - def _setup(self): - super(BashCodeEvaluator, self)._setup() - - self.submit_path = self.create_submit_code_file('submit.sh') - self._set_file_as_executable(self.submit_path) - get_ref_path, get_test_case_path = self.ref_code_path.strip().split(',') - get_ref_path = get_ref_path.strip() - get_test_case_path = get_test_case_path.strip() - ref_path, test_case_path = self._set_test_code_file_path(get_ref_path, - get_test_case_path) - - return ref_path, self.submit_path, test_case_path - - def _teardown(self): - # Delete the created file. - super(BashCodeEvaluator, self)._teardown() - os.remove(self.submit_path) - - def _check_code(self, ref_path, submit_path, - test_case_path=None): - """ Function validates student script using instructor script as - reference. Test cases can optionally be provided. The first argument - ref_path, is the path to instructor script, it is assumed to - have executable permission. The second argument submit_path, is - the path to the student script, it is assumed to have executable - permission. The Third optional argument is the path to test the - scripts. Each line in this file is a test case and each test case is - passed to the script as standard arguments. - - Returns - -------- - - returns (True, "Correct answer") : If the student script passes all - test cases/have same output, when compared to the instructor script - - returns (False, error_msg): If the student script fails a single - test/have dissimilar output, when compared to the instructor script. - - Returns (False, error_msg): If mandatory arguments are not files or if - the required permissions are not given to the file(s). - - """ - if not isfile(ref_path): - return False, "No file at %s or Incorrect path" % ref_path - if not isfile(submit_path): - return False, "No file at %s or Incorrect path" % submit_path - if not os.access(ref_path, os.X_OK): - return False, "Script %s is not executable" % ref_path - if not os.access(submit_path, os.X_OK): - return False, "Script %s is not executable" % submit_path - - success = False - - if test_case_path is None or "": - ret = self._run_command(ref_path, stdin=None, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - proc, inst_stdout, inst_stderr = ret - ret = self._run_command(submit_path, stdin=None, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - proc, stdnt_stdout, stdnt_stderr = ret - if inst_stdout == stdnt_stdout: - return True, "Correct answer" - else: - err = "Error: expected %s, got %s" % (inst_stderr, - stdnt_stderr) - return False, err - else: - if not isfile(test_case_path): - return False, "No test case at %s" % test_case_path - if not os.access(ref_path, os.R_OK): - return False, "Test script %s, not readable" % test_case_path - # valid_answer is True, so that we can stop once a test case fails - valid_answer = True - # loop_count has to be greater than or equal to one. - # Useful for caching things like empty test files,etc. - loop_count = 0 - test_cases = open(test_case_path).readlines() - num_lines = len(test_cases) - for test_case in test_cases: - loop_count += 1 - if valid_answer: - args = [ref_path] + [x for x in test_case.split()] - ret = self._run_command(args, stdin=None, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - proc, inst_stdout, inst_stderr = ret - args = [submit_path]+[x for x in test_case.split()] - ret = self._run_command(args, stdin=None, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - proc, stdnt_stdout, stdnt_stderr = ret - valid_answer = inst_stdout == stdnt_stdout - if valid_answer and (num_lines == loop_count): - return True, "Correct answer" - else: - err = "Error:expected %s, got %s" % (inst_stdout+inst_stderr, - stdnt_stdout+stdnt_stderr) - return False, err - diff --git a/testapp/yaksh/bash_files/sample.args b/testapp/yaksh/bash_files/sample.args deleted file mode 100644 index 4d9f00d..0000000 --- a/testapp/yaksh/bash_files/sample.args +++ /dev/null @@ -1,2 +0,0 @@ -1 2 -2 1 diff --git a/testapp/yaksh/bash_files/sample.sh b/testapp/yaksh/bash_files/sample.sh deleted file mode 100755 index e935cb3..0000000 --- a/testapp/yaksh/bash_files/sample.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -[[ $# -eq 2 ]] && echo $(( $1 + $2 )) && exit $(( $1 + $2 )) diff --git a/testapp/yaksh/c_cpp_files/main.cpp b/testapp/yaksh/c_cpp_files/main.cpp deleted file mode 100755 index ebe1f08..0000000 --- a/testapp/yaksh/c_cpp_files/main.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include-#include - -extern int add(int, int); - -template - -void check(T expect, T result) -{ - if (expect == result) - { - printf("\nCorrect:\n Expected %d got %d \n",expect,result); - } - else - { - printf("\nIncorrect:\n Expected %d got %d \n",expect,result); - exit (1); - } -} - -int main(void) -{ - int result; - result = add(0,0); - printf("Input submitted to the function: 0, 0"); - check(0, result); - result = add(2,3); - printf("Input submitted to the function: 2 3"); - check(5,result); - printf("All Correct\n"); - return 0; -} diff --git a/testapp/yaksh/c_cpp_files/main2.c b/testapp/yaksh/c_cpp_files/main2.c deleted file mode 100755 index ccd1768..0000000 --- a/testapp/yaksh/c_cpp_files/main2.c +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include - -extern int add(int, int, int); - -template -void check(T expect,T result) -{ - if (expect == result) - { - printf("\nCorrect:\n Expected %d got %d \n",expect,result); - } - else - { - printf("\nIncorrect:\n Expected %d got %d \n",expect,result); - exit (0); - } -} - -int main(void) -{ - int result; - result = add(0,0,0); - printf("Input submitted to the function: 0, 0, 0"); - check(0, result); - result = add(2,3,3); - printf("Input submitted to the function: 2, 3, 3"); - check(8,result); - printf("All Correct\n"); -} diff --git a/testapp/yaksh/c_cpp_files/main_array_check.cpp b/testapp/yaksh/c_cpp_files/main_array_check.cpp deleted file mode 100755 index ea34fdd..0000000 --- a/testapp/yaksh/c_cpp_files/main_array_check.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include - -extern bool array_check(int [], int); - -template - -void check(T expect,T result) -{ - if (expect == result) - { - printf("\nCorrect:\n Expected %d got %d \n",expect,result); - } - else - { - printf("\nIncorrect:\n Expected %d got %d \n",expect,result); - exit (1); - } -} - -int main(void) -{ - bool result; - int a[] = {1,2,3,0,0}; - result = array_check(a, 2); - printf("Input submitted to the function: {1, 2, 3, 0, 0} and index 2"); - check(false, result); - int b[] = {1,2,3,4,5}; - result = array_check(b, 3); - printf("Input submitted to the function: {1, 2, 3, 4, 5} and index 3"); - check(true, result); - printf("All Correct\n"); - return 0; -} diff --git a/testapp/yaksh/c_cpp_files/main_array_check_all.cpp b/testapp/yaksh/c_cpp_files/main_array_check_all.cpp deleted file mode 100755 index 140578e..0000000 --- a/testapp/yaksh/c_cpp_files/main_array_check_all.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include