<s> from __future__ import unicode_literals <EOL> import re <EOL> import json <EOL> from django . db import models <EOL> from django . core . exceptions import ValidationError , ImproperlyConfigured <EOL> from django . core . validators import MaxValueValidator <EOL> from django . utils . translation import ugettext as _ <EOL> from django . utils . timezone import now <EOL> from django . utils . encoding import python_2_unicode_compatible <EOL> from django . conf import settings <EOL> from model_utils . managers import InheritanceManager <EOL> class CategoryManager ( models . Manager ) : <EOL> def new_category ( self , category ) : <EOL> new_category = self . create ( category = re . sub ( '<STR_LIT>' , '<STR_LIT:->' , category ) <EOL> . lower ( ) ) <EOL> new_category . save ( ) <EOL> return new_category <EOL> @ python_2_unicode_compatible <EOL> class Category ( models . Model ) : <EOL> category = models . CharField ( <EOL> verbose_name = _ ( "<STR_LIT>" ) , <EOL> max_length = <NUM_LIT> , blank = True , <EOL> unique = True , null = True ) <EOL> objects = CategoryManager ( ) <EOL> class Meta : <EOL> verbose_name = _ ( "<STR_LIT>" ) <EOL> verbose_name_plural = _ ( "<STR_LIT>" ) <EOL> def __str__ ( self ) : <EOL> return self . category <EOL> @ python_2_unicode_compatible <EOL> class SubCategory ( models . Model ) : <EOL> sub_category = models . CharField ( <EOL> verbose_name = _ ( "<STR_LIT>" ) , <EOL> max_length = <NUM_LIT> , blank = True , null = True ) <EOL> category = models . ForeignKey ( <EOL> Category , null = True , blank = True , <EOL> verbose_name = _ ( "<STR_LIT>" ) ) <EOL> objects = CategoryManager ( ) <EOL> class Meta : <EOL> verbose_name = _ ( "<STR_LIT>" ) <EOL> verbose_name_plural = _ ( "<STR_LIT>" ) <EOL> def __str__ ( self ) : <EOL> return self . sub_category + "<STR_LIT>" + self . category . category + "<STR_LIT:)>" <EOL> @ python_2_unicode_compatible <EOL> class Quiz ( models . Model ) : <EOL> title = models . CharField ( <EOL> verbose_name = _ ( "<STR_LIT>" ) , <EOL> max_length = <NUM_LIT> , blank = False ) <EOL> description = models . TextField ( <EOL> verbose_name = _ ( "<STR_LIT>" ) , <EOL> blank = True , help_text = _ ( "<STR_LIT>" ) ) <EOL> url = models . SlugField ( <EOL> max_length = <NUM_LIT> , blank = False , <EOL> help_text = _ ( "<STR_LIT>" ) , <EOL> verbose_name = _ ( "<STR_LIT>" ) ) <EOL> category = models . ForeignKey ( <EOL> Category , null = True , blank = True , <EOL> verbose_name = _ ( "<STR_LIT>" ) ) <EOL> random_order = models . BooleanField ( <EOL> blank = False , default = False , <EOL> verbose_name = _ ( "<STR_LIT>" ) , <EOL> help_text = _ ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" ) ) <EOL> max_questions = models . PositiveIntegerField ( <EOL> blank = True , null = True , verbose_name = _ ( "<STR_LIT>" ) , <EOL> help_text = _ ( "<STR_LIT>" ) ) <EOL> answers_at_end = models . BooleanField ( <EOL> blank = False , default = False , <EOL> help_text = _ ( "<STR_LIT>" <EOL> "<STR_LIT>" ) , <EOL> verbose_name = _ ( "<STR_LIT>" ) ) <EOL> exam_paper = models . BooleanField ( <EOL> blank = False , default = False , <EOL> help_text = _ ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" ) , <EOL> verbose_name = _ ( "<STR_LIT>" ) ) <EOL> single_attempt = models . BooleanField ( <EOL> blank = False , default = False , <EOL> help_text = _ ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" ) , <EOL> verbose_name = _ ( "<STR_LIT>" ) ) <EOL> pass_mark = models . SmallIntegerField ( <EOL> blank = True , default = <NUM_LIT:0> , <EOL> verbose_name = _ ( "<STR_LIT>" ) , <EOL> help_text = _ ( "<STR_LIT>" ) , <EOL> validators = [ MaxValueValidator ( <NUM_LIT:100> ) ] ) <EOL> success_text = models . TextField ( <EOL> blank = True , help_text = _ ( "<STR_LIT>" ) , <EOL> verbose_name = _ ( "<STR_LIT>" ) ) <EOL> fail_text = models . TextField ( <EOL> verbose_name = _ ( "<STR_LIT>" ) , <EOL> blank = True , help_text = _ ( "<STR_LIT>" ) ) <EOL> draft = models . BooleanField ( <EOL> blank = True , default = False , <EOL> verbose_name = _ ( "<STR_LIT>" ) , <EOL> help_text = _ ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" ) ) <EOL> def save ( self , force_insert = False , force_update = False , * args , ** kwargs ) : <EOL> self . url = re . sub ( '<STR_LIT>' , '<STR_LIT:->' , self . url ) . lower ( ) <EOL> self . url = '<STR_LIT>' . join ( letter for letter in self . url if <EOL> letter . isalnum ( ) or letter == '<STR_LIT:->' ) <EOL> if self . single_attempt is True : <EOL> self . exam_paper = True <EOL> if self . pass_mark > <NUM_LIT:100> : <EOL> raise ValidationError ( '<STR_LIT>' % self . pass_mark ) <EOL> super ( Quiz , self ) . save ( force_insert , force_update , * args , ** kwargs ) <EOL> class Meta : <EOL> verbose_name = _ ( "<STR_LIT>" ) <EOL> verbose_name_plural = _ ( "<STR_LIT>" ) <EOL> def __str__ ( self ) : <EOL> return self . title <EOL> def get_questions ( self ) : <EOL> return self . question_set . all ( ) . select_subclasses ( ) <EOL> @ property <EOL> def get_max_score ( self ) : <EOL> return self . get_questions ( ) . count ( ) <EOL> def anon_score_id ( self ) : <EOL> return str ( self . id ) + "<STR_LIT>" <EOL> def anon_q_list ( self ) : <EOL> return str ( self . id ) + "<STR_LIT>" <EOL> def anon_q_data ( self ) : <EOL> return str ( self . id ) + "<STR_LIT>" <EOL> class ProgressManager ( models . Manager ) : <EOL> def new_progress ( self , user ) : <EOL> new_progress = self . create ( user = user , <EOL> score = "<STR_LIT>" ) <EOL> new_progress . save ( ) <EOL> return new_progress <EOL> class Progress ( models . Model ) : <EOL> """<STR_LIT>""" <EOL> user = models . OneToOneField ( settings . AUTH_USER_MODEL , verbose_name = _ ( "<STR_LIT>" ) ) <EOL> score = models . CommaSeparatedIntegerField ( max_length = <NUM_LIT> , <EOL> verbose_name = _ ( "<STR_LIT>" ) ) <EOL> objects = ProgressManager ( ) <EOL> class Meta : <EOL> verbose_name = _ ( "<STR_LIT>" ) <EOL> verbose_name_plural = _ ( "<STR_LIT>" ) <EOL> @ property <EOL> def list_all_cat_scores ( self ) : <EOL> """<STR_LIT>""" <EOL> score_before = self . score <EOL> output = { } <EOL> for cat in Category . objects . all ( ) : <EOL> to_find = re . escape ( cat . category ) + r"<STR_LIT>" <EOL> match = re . search ( to_find , self . score , re . IGNORECASE ) <EOL> if match : <EOL> score = int ( match . group ( <NUM_LIT:1> ) ) <EOL> possible = int ( match . group ( <NUM_LIT:2> ) ) <EOL> try : <EOL> percent = int ( round ( ( float ( score ) / float ( possible ) ) <EOL> * <NUM_LIT:100> ) ) <EOL> except : <EOL> percent = <NUM_LIT:0> <EOL> output [ cat . category ] = [ score , possible , percent ] <EOL> else : <EOL> self . score += cat . category + "<STR_LIT>" <EOL> output [ cat . category ] = [ <NUM_LIT:0> , <NUM_LIT:0> ] <EOL> if len ( self . score ) > len ( score_before ) : <EOL> self . save ( ) <EOL> return output <EOL> def update_score ( self , question , score_to_add = <NUM_LIT:0> , possible_to_add = <NUM_LIT:0> ) : <EOL> """<STR_LIT>""" <EOL> category_test = Category . objects . filter ( category = question . category ) . exists ( ) <EOL> if any ( [ item is False for item in [ category_test , <EOL> score_to_add , <EOL> possible_to_add , <EOL> isinstance ( score_to_add , int ) , <EOL> isinstance ( possible_to_add , int ) ] ] ) : <EOL> return _ ( "<STR_LIT:error>" ) , _ ( "<STR_LIT>" ) <EOL> to_find = re . escape ( str ( question . category ) ) + r"<STR_LIT>" <EOL> match = re . search ( to_find , self . score , re . IGNORECASE ) <EOL> if match : <EOL> updated_score = int ( match . group ( '<STR_LIT>' ) ) + abs ( score_to_add ) <EOL> updated_possible = int ( match . group ( '<STR_LIT>' ) ) + abs ( possible_to_add ) <EOL> new_score = "<STR_LIT:U+002C>" . join ( <EOL> [ <EOL> str ( question . category ) , <EOL> str ( updated_score ) , <EOL> str ( updated_possible ) , "<STR_LIT>" <EOL> ] ) <EOL> self . score = self . score . replace ( match . group ( ) , new_score ) <EOL> self . save ( ) <EOL> else : <EOL> self . score += "<STR_LIT:U+002C>" . join ( <EOL> [ <EOL> str ( question . category ) , <EOL> str ( score_to_add ) , <EOL> str ( possible_to_add ) , <EOL> "<STR_LIT>" <EOL> ] ) <EOL> self . save ( ) <EOL> def show_exams ( self ) : <EOL> """<STR_LIT>""" <EOL> return Sitting . objects . filter ( user = self . user , complete = True ) <EOL> class SittingManager ( models . Manager ) : <EOL> def new_sitting ( self , user , quiz ) : <EOL> if quiz . random_order is True : <EOL> question_set = quiz . question_set . all ( ) . select_subclasses ( ) . order_by ( '<STR_LIT:?>' ) <EOL> else : <EOL> question_set = quiz . question_set . all ( ) . select_subclasses ( ) <EOL> question_set = question_set . values_list ( '<STR_LIT:id>' , flat = True ) <EOL> if len ( question_set ) == <NUM_LIT:0> : <EOL> raise ImproperlyConfigured ( '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> if quiz . max_questions and quiz . max_questions < len ( question_set ) : <EOL> question_set = question_set [ : quiz . max_questions ] <EOL> questions = "<STR_LIT:U+002C>" . join ( map ( str , question_set ) ) + "<STR_LIT:U+002C>" <EOL> new_sitting = self . create ( user = user , <EOL> quiz = quiz , <EOL> question_order = questions , <EOL> question_list = questions , <EOL> incorrect_questions = "<STR_LIT>" , <EOL> current_score = <NUM_LIT:0> , <EOL> complete = False , <EOL> user_answers = '<STR_LIT:{}>' ) <EOL> return new_sitting <EOL> def user_sitting ( self , user , quiz ) : <EOL> if quiz . single_attempt is True and self . filter ( user = user , <EOL> quiz = quiz , <EOL> complete = True ) . exists ( ) : <EOL> return False <EOL> try : <EOL> sitting = self . get ( user = user , quiz = quiz , complete = False ) <EOL> except Sitting . DoesNotExist : <EOL> sitting = self . new_sitting ( user , quiz ) <EOL> except Sitting . MultipleObjectsReturned : <EOL> sitting = self . filter ( user = user , quiz = quiz , complete = False ) [ <NUM_LIT:0> ] <EOL> return sitting <EOL> class Sitting ( models . Model ) : <EOL> """<STR_LIT>""" <EOL> user = models . ForeignKey ( settings . AUTH_USER_MODEL , verbose_name = _ ( "<STR_LIT>" ) ) <EOL> quiz = models . ForeignKey ( Quiz , verbose_name = _ ( "<STR_LIT>" ) ) <EOL> question_order = models . CommaSeparatedIntegerField ( <EOL> max_length = <NUM_LIT> , verbose_name = _ ( "<STR_LIT>" ) ) <EOL> question_list = models . CommaSeparatedIntegerField ( <EOL> max_length = <NUM_LIT> , verbose_name = _ ( "<STR_LIT>" ) ) <EOL> incorrect_questions = models . CommaSeparatedIntegerField ( <EOL> max_length = <NUM_LIT> , blank = True , verbose_name = _ ( "<STR_LIT>" ) ) <EOL> current_score = models . IntegerField ( verbose_name = _ ( "<STR_LIT>" ) ) <EOL> complete = models . BooleanField ( default = False , blank = False , <EOL> verbose_name = _ ( "<STR_LIT>" ) ) <EOL> user_answers = models . TextField ( blank = True , default = '<STR_LIT:{}>' , <EOL> verbose_name = _ ( "<STR_LIT>" ) ) <EOL> start = models . DateTimeField ( auto_now_add = True , <EOL> verbose_name = _ ( "<STR_LIT>" ) ) <EOL> end = models . DateTimeField ( null = True , blank = True , verbose_name = _ ( "<STR_LIT>" ) ) <EOL> objects = SittingManager ( ) <EOL> class Meta : <EOL> permissions = ( ( "<STR_LIT>" , _ ( "<STR_LIT>" ) ) , ) <EOL> def get_first_question ( self ) : <EOL> """<STR_LIT>""" <EOL> if not self . question_list : <EOL> return False <EOL> first , _ = self . question_list . split ( '<STR_LIT:U+002C>' , <NUM_LIT:1> ) <EOL> question_id = int ( first ) <EOL> return Question . objects . get_subclass ( id = question_id ) <EOL> def remove_first_question ( self ) : <EOL> if not self . question_list : <EOL> return <EOL> _ , others = self . question_list . split ( '<STR_LIT:U+002C>' , <NUM_LIT:1> ) <EOL> self . question_list = others <EOL> self . save ( ) <EOL> def add_to_score ( self , points ) : <EOL> self . current_score += int ( points ) <EOL> self . save ( ) <EOL> @ property <EOL> def get_current_score ( self ) : <EOL> return self . current_score <EOL> def _question_ids ( self ) : <EOL> return [ int ( n ) for n in self . question_order . split ( '<STR_LIT:U+002C>' ) if n ] <EOL> @ property <EOL> def get_percent_correct ( self ) : <EOL> dividend = float ( self . current_score ) <EOL> divisor = len ( self . _question_ids ( ) ) <EOL> if divisor < <NUM_LIT:1> : <EOL> return <NUM_LIT:0> <EOL> if dividend > divisor : <EOL> return <NUM_LIT:100> <EOL> correct = int ( round ( ( dividend / divisor ) * <NUM_LIT:100> ) ) <EOL> if correct >= <NUM_LIT:1> : <EOL> return correct <EOL> else : <EOL> return <NUM_LIT:0> <EOL> def mark_quiz_complete ( self ) : <EOL> self . complete = True <EOL> self . end = now ( ) <EOL> self . save ( ) <EOL> def add_incorrect_question ( self , question ) : <EOL> """<STR_LIT>""" <EOL> if len ( self . incorrect_questions ) > <NUM_LIT:0> : <EOL> self . incorrect_questions += '<STR_LIT:U+002C>' <EOL> self . incorrect_questions += str ( question . id ) + "<STR_LIT:U+002C>" <EOL> if self . complete : <EOL> self . add_to_score ( - <NUM_LIT:1> ) <EOL> self . save ( ) <EOL> @ property <EOL> def get_incorrect_questions ( self ) : <EOL> """<STR_LIT>""" <EOL> return [ int ( q ) for q in self . incorrect_questions . split ( '<STR_LIT:U+002C>' ) if q ] <EOL> def remove_incorrect_question ( self , question ) : <EOL> current = self . get_incorrect_questions <EOL> current . remove ( question . id ) <EOL> self . incorrect_questions = '<STR_LIT:U+002C>' . join ( map ( str , current ) ) <EOL> self . add_to_score ( <NUM_LIT:1> ) <EOL> self . save ( ) <EOL> @ property <EOL> def check_if_passed ( self ) : <EOL> return self . get_percent_correct >= self . quiz . pass_mark <EOL> @ property <EOL> def result_message ( self ) : <EOL> if self . check_if_passed : <EOL> return self . quiz . success_text <EOL> else : <EOL> return self . quiz . fail_text <EOL> def add_user_answer ( self , question , guess ) : <EOL> current = json . loads ( self . user_answers ) <EOL> current [ question . id ] = guess <EOL> self . user_answers = json . dumps ( current ) <EOL> self . save ( ) <EOL> def get_questions ( self , with_answers = False ) : <EOL> question_ids = self . _question_ids ( ) <EOL> questions = sorted ( <EOL> self . quiz . question_set . filter ( id__in = question_ids ) <EOL> . select_subclasses ( ) , <EOL> key = lambda q : question_ids . index ( q . id ) ) <EOL> if with_answers : <EOL> user_answers = json . loads ( self . user_answers ) <EOL> for question in questions : <EOL> question . user_answer = user_answers [ str ( question . id ) ] <EOL> return questions <EOL> @ property <EOL> def questions_with_user_answers ( self ) : <EOL> return { <EOL> q : q . user_answer for q in self . get_questions ( with_answers = True ) <EOL> } <EOL> @ property <EOL> def get_max_score ( self ) : <EOL> return len ( self . _question_ids ( ) ) <EOL> def progress ( self ) : <EOL> """<STR_LIT>""" <EOL> answered = len ( json . loads ( self . user_answers ) ) <EOL> total = self . get_max_score <EOL> return answered , total <EOL> @ python_2_unicode_compatible <EOL> class Question ( models . Model ) : <EOL> """<STR_LIT>""" <EOL> quiz = models . ManyToManyField ( Quiz , <EOL> verbose_name = _ ( "<STR_LIT>" ) , <EOL> blank = True ) <EOL> category = models . ForeignKey ( Category , <EOL> verbose_name = _ ( "<STR_LIT>" ) , <EOL> blank = True , <EOL> null = True ) <EOL> sub_category = models . ForeignKey ( SubCategory , <EOL> verbose_name = _ ( "<STR_LIT>" ) , <EOL> blank = True , <EOL> null = True ) <EOL> figure = models . ImageField ( upload_to = '<STR_LIT>' , <EOL> blank = True , <EOL> null = True , <EOL> verbose_name = _ ( "<STR_LIT>" ) ) <EOL> content = models . CharField ( max_length = <NUM_LIT:1000> , <EOL> blank = False , <EOL> help_text = _ ( "<STR_LIT>" <EOL> "<STR_LIT>" ) , <EOL> verbose_name = _ ( '<STR_LIT>' ) ) <EOL> explanation = models . TextField ( max_length = <NUM_LIT> , <EOL> blank = True , <EOL> help_text = _ ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" ) , <EOL> verbose_name = _ ( '<STR_LIT>' ) ) <EOL> objects = InheritanceManager ( ) <EOL> class Meta : <EOL> verbose_name = _ ( "<STR_LIT>" ) <EOL> verbose_name_plural = _ ( "<STR_LIT>" ) <EOL> ordering = [ '<STR_LIT>' ] <EOL> def __str__ ( self ) : <EOL> return self . content </s>
