Пример #1
0
class TestElement(BaseTopicElement):
    """"
    Integration with the automatic tutor. The test is embedded via an iframe,
    which makes it very easy to just use the tutor app standalone.
    """

    test = models.CharField(max_length=256, choices=test_choices())
    #test = "dette er selveste test name"
    difficulty = models.CharField(max_length=256,
                                  choices=(('Easy', 'Easy'), ('Medium',
                                                              'Medium'),
                                           ('Hard', 'Hard'), ('Adaptive',
                                                              'Adaptive')))
    effect_files = MultiSelectField(
        default='NULL.inc',
        max_length=10000,
        choices=tuple([(fx, fx) for fx in find_inc_files() +
                       ['ALL FX', 'Effects the student has seen so far']]))

    feedback_bad = models.TextField(help_text=_(
        'Feedback for a badly performing student. He/she should be practicing more, perhaps?'
    ),
                                    default='Keep on working!')
    feecback_ok = models.TextField(
        help_text=_('Feedback for a student that is doing OK.'),
        default='Well done!')
    feecback_good = models.TextField(help_text=_(
        'Feedback for a student that is doing very good, maybe he/she should be encouraged to move on to the next lesson?'
    ),
                                     default='Brilliant. You can move on!')

    def save(self, *args, **kwargs):
        if not self.pk:
            self.element_type = BaseTopicElement.TEST
        super(TestElement, self).save(*args, **kwargs)

    def to_html(self):
        current_site = Site.objects.get_current()
        current_test = self.test
        if "Interactive" in self.test:
            current_test = "test_interactive/" + current_test
        print current_test

        #return u'<h2>{description}</h2><iframe src="http://127.0.0.1:8000/tutor/{test}/{difficulty}/{FX}" frameborder="0" scrolling="no" width="100%" height=300"></iframe>'.format( description=self.description, test="Guess the effect", difficulty = self.difficulty, FX=str(' '.join(self.effect_files)))
        #return u'<h2>{description}</h2><iframe src="http://{domain}/tutor/{test}/{difficulty}/{FX}" frameborder="0" scrolling="no" width="100%" height=300"></iframe>'.format(domain=current_site.domain, description=self.description, test=self.test, difficulty = self.difficulty, FX=str(' '.join(self.effect_files)))
        #return u'<h2>{description}</h2><iframe src="http://gdsp.hf.ntnu.no/tutor/{test}/{difficulty}/{FX}" frameborder="0" scrolling="no" width="100%" height=300"></iframe>'.format(domain=current_site.domain, description=self.description, test=self.test, difficulty = self.difficulty, FX=str(' '.join(self.effect_files)))

        return u'<h2>{description}</h2><iframe class="testElement" src="http://{domain}/tutor/{test}/{level}/{FX}" frameborder="0" scrolling="yes" width="100%" height=750;"></iframe>'.format(
            domain=current_site.domain,
            description=self.description,
            test=current_test,
            level=self.difficulty,
            FX=str(' '.join(self.effect_files)))

        #return u'<h2>{description}</h2><iframe src="http://folk.ntnu.no/mortengk/csound" frameborder="0" scrolling="yes" width="100%" height=600"></iframe>'

    class Meta:
        verbose_name = _('test element')
        verbose_name_plural = _('test elements')
Пример #2
0
class Tag(taggit.models.TagBase):
    name = models.CharField(blank=False, max_length=100)
    field_name = models.CharField(blank=False, max_length=100, default=raise_error_on_empty)

    @property
    def is_predefined(self) -> bool:
        return False

    class Meta:
        verbose_name = 'Tag'
        verbose_name_plural = 'Tags'
        unique_together = (("name", "field_name"),)
        app_label = 'tagging'
Пример #3
0
class BaseTopicElement(models.Model):
    """
    A base class for the elements that go into a topic, such as text,
    images etc. The description attribute should describe to an
    administrator putting together a topic what the subject matter of
    the element is.

    Inheriting classes must implement a to_html() instance method
    which renders an HTML representation of the element suitable to be
    included as part of a web page.
    """

    AUDIO, CODE, IMAGE, MATH, TEXT, TEST, RESULTS = 'audio', 'code', 'image', 'math', 'text', 'test', 'results'
    ELEMENT_TYPES = (
        (AUDIO, _('Audio')),
        (CODE, _('Code')),
        (IMAGE, _('Imagery')),
        (MATH, _('Mathematics')),
        (TEXT, _('Text')),
        (TEST, _('Test')),
        (RESULTS, _('Results')),
    )

    description = models.CharField(
        max_length=255,
        help_text=_('What does this element contain?'),
    )
    topic = models.ForeignKey('Topic', related_name='elements')
    # The element_type is set in the save() method of the subclass, and will
    # be the same for all elements of a given type; its value should be one
    # of the ELEMENT_TYPES defined above, e.g. AUDIO ('audio'). This reduces
    # the number of database queries needed to determine a BaseTopicElement's
    # actual type when compared to iterating over the possible subclasses
    # and looking for an attribute of that name. It is, of course, data
    # duplication, but the speed-up is worth it.
    element_type = models.CharField(max_length=16, blank=False, editable=False)

    # model_utils.managers.InheritanceManager allows us to fetch subclass
    # objects as instances of those subclasses rather than as instances of
    # BaseTopicElement. This means that the correct to_html() method will be
    # called in our views.
    objects = model_utils.managers.InheritanceManager()

    def to_html(self):
        raise NotImplementedError

    def __unicode__(self):
        return self.description

    class Meta:
        order_with_respect_to = 'topic'
Пример #4
0
class MathElement(BaseTopicElement):
    """
    A topic element containing equations, formulae or other mathematical
    writing expressed in the LaTeX markup language and rendered to HTML+CSS
    client-side by the MathJax JavaScript library.
    """

    latex = models.TextField(help_text=_(
        'LaTeX-formatted mathematics. Remember to enclose '
        'your markup in delimiters, like so: '
        '<code>\[ 2^3 = 8 \]</code>.'), )
    caption = models.CharField(max_length=255, blank=True)

    def save(self, *args, **kwargs):
        if not self.pk:
            self.element_type = BaseTopicElement.MATH
        super(MathElement, self).save(*args, **kwargs)

    def to_html(self):
        html = u'<figure class="math-element">'
        html += u'<p>{}</p>'.format(self.latex)
        if self.caption:
            html += u'<figcaption>{}</figcaption>'.format(self.caption)
        html += u'</figure>'
        return html

    class Meta:
        verbose_name = _('math element')
        verbose_name_plural = _('math elements')
Пример #5
0
class ResultsElement(BaseTopicElement):
    """"
    Displays the results for the student. Can be both aggregated and lesson-based.
    """
    def save(self, *args, **kwargs):
        if not self.pk:
            self.element_type = BaseTopicElement.RESULTS
        super(ResultsElement, self).save(*args, **kwargs)

    scope = models.CharField(max_length=256,
                             choices=(('Lesson', 'Lesson'), ('Aggregated',
                                                             'Aggregated')),
                             default='Lesson')

    def to_html(self):
        if self.scope == 'Lesson':
            return u'<h2>{description}</h2><iframe src="http://{domain}/tutor/lesson_results" frameborder="0" scrolling="yes" width="100%" height=500;"></iframe>'.format(
                domain=current_site.domain, description=self.description)
        if self.scope == 'Aggregated':
            return u'<h2>{description}</h2><iframe src="http://{domain}/tutor/results" frameborder="0" scrolling="yes" width="100%" height=500;"></iframe>'.format(
                domain=current_site.domain, description=self.description)

    class Meta:
        verbose_name = _('results element')
        verbose_name_plural = _('results elements')
Пример #6
0
class ImageElement(BaseTopicElement):
    """
    A topic element containing an image and, optionally, a caption.
    Its  HTML representation wraps the image and caption (if present)
    in a figure element.
    """

    caption = models.CharField(max_length=255, blank=True)
    image = models.ImageField(upload_to='images')
    max_width = models.IntegerField(default=100)

    def save(self, *args, **kwargs):
        if not self.pk:
            self.element_type = BaseTopicElement.IMAGE
        super(ImageElement, self).save(*args, **kwargs)

    def to_html(self):
        if self.description == 'Lesson top':
            html = u'<img class="lesson-intro-img" src="{}">'.format(
                self.image.url)
        else:
            html = u'<figure class="image-element">'
            html += u'<img style="max-width: {width}%" src="{url}">'.format(
                width=self.max_width,
                url=self.image.url,
            )
        if self.caption:
            html += u'<figcaption>{}</figcaption>'.format(self.caption)
        html += u'</figure>'
        return html

    class Meta:
        verbose_name = _('image element')
        verbose_name_plural = _('image elements')
Пример #7
0
class Topic(models.Model):
    """
    A topic is an ordered collection of topic elements relished with a title
    and a collection of tags. It constitutes one web page of content and part
    of a lesson.
    """

    title = models.CharField(max_length=255)
    caption = models.CharField(
        max_length=255,
        blank=True,
        default='',
        help_text=_('The title that will be displayed '
                    '(use if different from title)'),
    )
    tags = LowerCaseTaggableManager(
        through=LowerCaseTaggedItem,
        help_text=_('A comma-separated list of keywords that describe '
                    'this topic.'),
        blank=True,
    )

    def get_absolute_url(self):
        return reverse('core:topic', kwargs={'pk': self.id})

    def __unicode__(self):
        return self.title

    def display_title(self):
        return self.caption if self.caption else self.title

    class Meta:
        # NOTE: Because lesson-topic relations which are unique may
        #       well include topics which are not, this ordering causes
        #       Topic.objects.all() to return the same topic once for
        #       every relation it is part of. If you need actually
        #       distinct topics, specify a different ordering, e.g.
        #       Topic.objects.order_by('id').
        ordering = [
            'lessontopicrelation__lesson',
            'lessontopicrelation__topic_ordinal',
        ]
        verbose_name = _('topic')
        verbose_name_plural = _('topics')
Пример #8
0
class AudioElement(BaseTopicElement):
    """
    A topic element containing an audio file and a title. Its HTML
    representation is a link which, if all goes well, plays / stops
    the audio when clicked; if a problem occurs, it falls back to
    being a regular link allowing the student to download the file.
    """

    title = models.CharField(
        max_length=128,
        blank=True,
        help_text=_('The title of the track as displayed to the student.'),
    )
    hover = models.CharField(
        max_length=128,
        blank=True,
        help_text=_('A text that appears only when hovering over the field.'),
    )
    file = models.FileField(upload_to='audio')

    def save(self, *args, **kwargs):
        if not self.pk:
            self.element_type = BaseTopicElement.AUDIO
        super(AudioElement, self).save(*args, **kwargs)

    def to_html(self):
        html = u''
        if self.title:
            html += u'<br>{}<br>'.format(self.title, )
        if self.hover:
            html += u'<span class="answer-hover">{}</span>'.format(
                self.hover, )
        html += u'<audio controls><source src="{}" type="audio/wav">Your browser does not support the audio element.</audio>'.format(
            self.file.url, )
        return html

    class Meta:
        verbose_name = _('audio element')
        verbose_name_plural = _('audio elements')
Пример #9
0
class Course(models.Model):
    """
    A course is an ordered collection of lessons.
    """

    title = models.CharField(max_length=255)

    def get_absolute_url(self):
        return reverse('core:course', kwargs={'pk': self.id})

    def __unicode__(self):
        return self.title

    class Meta:
        verbose_name = _('course')
        verbose_name_plural = _('courses')
Пример #10
0
class Lesson(models.Model):
    """
    A lesson is an ordered collection of topics.
    """

    title = models.CharField(max_length=255)
    image = models.ImageField(upload_to='images', default='no-img.jpg')
    course = models.ForeignKey('Course', related_name='lessons')
    topics = models.ManyToManyField(Topic, through='LessonTopicRelation')
    objects = LessonManager()

    def get_absolute_url(self):
        return reverse('core:lesson', kwargs={'pk': self.id})

    def __unicode__(self):
        return self.title

    class Meta:
        verbose_name = _('lesson')
        verbose_name_plural = _('lessons')
        order_with_respect_to = 'course'
Пример #11
0
class LessonTopicRelation(models.Model):
    topic = models.ForeignKey(Topic)
    lesson = models.ForeignKey(Lesson)
    visible = models.BooleanField(default=True)
    topic_ordinal = models.PositiveIntegerField()
    # excluded_content is a comma-separated list of topic element types
    # which should not be displayed in this lesson, e.g. 'code, audio':
    excluded_content = models.CharField(max_length=255, blank=True)
    objects = LessonTopicManager()

    @property
    def excludes(self):
        return (e.strip() for e in self.excluded_content.split(','))

    @property
    def topic_elements(self):
        return self.topic.elements.select_subclasses().exclude(
            element_type__in=self.excludes, )

    @property
    def next(self):
        return LessonTopicRelation.objects.after(self)

    @property
    def previous(self):
        return LessonTopicRelation.objects.before(self)

    def __unicode__(self):
        return u'Topic: "{}", Lesson: "{}"'.format(self.topic, self.lesson)

    class Meta:
        ordering = ['lesson', 'topic_ordinal']
        index_together = [
            ['lesson', 'topic_ordinal'],
        ]
        verbose_name = _('lesson topic')
        verbose_name_plural = _('lesson topics')