# =========================================================================== # eXe # Copyright 2004-2006, University of Auckland # Copyright 2004-2008 eXe Project, http://eXeLearning.org/ # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # =========================================================================== """ Cloze Idevice. Shows a paragraph where the student must fill in the blanks """ import logging from exe.engine.idevice import Idevice from exe.engine.path import Path from exe.engine.field import ClozeField, TextAreaField from exe.engine.persist import Persistable import Image import re log = logging.getLogger(__name__) # =========================================================================== class ClozeIdevice(Idevice): """ Holds a paragraph with words missing that the student must fill in """ persistenceVersion = 4 def __init__(self, parentNode=None): """ Sets up the idevice title and instructions etc """ Idevice.__init__(self, x_(u"Cloze Activity"), x_(u"University of Auckland"), x_(u"

Cloze exercises are texts or " "sentences where students must fill in " "missing words. They are often used for the " "following purposes:

" "
    " "
  1. To check knowledge of core course " "concepts (this could be a pre-check, " "formative exercise, or summative check).
  2. " "
  3. To check reading comprehension.
  4. " "
  5. To check vocabulary knowledge.
  6. " "
  7. To check word formation and/or grammatical " "competence.
"), x_(u"
" "
If your goal is to test understanding " "of core concepts or reading comprehension" "
" "
" "

" " Write a summary of the concept or reading long " " enough to adequately test the target's " "knowledge, but short enough not to " "induce fatigue. Less than one typed page is " "probably adequate, but probably " "considerably less for young students or " "beginners." "

" "

" "Select words in the text that" "are key to understanding the concepts. These" "will probably be verbs, nouns, and key adverbs." "Choose alternatives with one clear answer." "

" "
" "
" "If your goal is to test vocabulary knowledge" "
" "
" "

Write a text using the target vocabulary. This " "text should be coherent and cohesive, and be of " "an appropriate length. Highlight the target " "words in the text. Choose alternatives with one " "clear answer.

" "
" "
" "If your goal is to test word " "formation/grammar:" "
" "
" "

" "Write a text using the " "target forms. This text should be coherent and " "cohesive, and be of an appropriate length. " "Remember that the goal is not vocabulary " "knowledge, so the core meanings of the stem " "words should be well known to the students." "

" "

" "Highlight the target words in the text. Provide " "alternatives with the same word stem, but " "different affixes. It is a good idea to get a " "colleague to test the test/exercise to make " "sure there are no surprises!" "

" "
" "
"), u"question", parentNode) self.instructionsForLearners = TextAreaField( x_(u'Instructions'), x_(u"""Provide instruction on how the cloze activity should be completed. Default text will be entered if there are no changes to this field. """), x_(u'Read the paragraph below and ' 'fill in the missing words.')) self.instructionsForLearners.idevice = self self._content = ClozeField(x_(u'Cloze'), x_(u"""

Enter the text for the cloze activity in to the cloze field by either pasting text from another source or by typing text directly into the field.

To select words to hide, double click on the word to select it and click on the Hide/Show Word button below.

""")) self._content.idevice = self self.feedback = TextAreaField(x_(u'Feedback'), x_(u'Enter any feedback you wish to provide the learner ' 'with-in the feedback field. This field can be left blank.')) self.feedback.idevice = self self.emphasis = Idevice.SomeEmphasis self.systemResources += ["common.js"] self.isCloze = True # Properties content = property(lambda self: self._content, doc="Read only, use 'self.content.encodedContent = x' " "instead") def getResourcesField(self, this_resource): """ implement the specific resource finding mechanism for this iDevice: """ # be warned that before upgrading, this iDevice field could not exist: if hasattr(self, '_content') and hasattr(self._content, 'images'): for this_image in self._content.images: if hasattr(this_image, '_imageResource') \ and this_resource == this_image._imageResource: return self._content # be warned that before upgrading, this iDevice field could not exist: if hasattr(self, 'instructionsForLearners')\ and hasattr(self.instructionsForLearners, 'images'): for this_image in self.instructionsForLearners.images: if hasattr(this_image, '_imageResource') \ and this_resource == this_image._imageResource: return self.instructionsForLearners # be warned that before upgrading, this iDevice field could not exist: if hasattr(self, 'feedback') and hasattr(self.feedback, 'images'): for this_image in self.feedback.images: if hasattr(this_image, '_imageResource') \ and this_resource == this_image._imageResource: return self.feedback return None def getRichTextFields(self): """ Like getResourcesField(), a general helper to allow nodes to search through all of their fields without having to know the specifics of each iDevice type. """ fields_list = [] if hasattr(self, '_content'): fields_list.append(self._content) if hasattr(self, 'instructionsForLearners'): fields_list.append(self.instructionsForLearners) if hasattr(self, 'feedback'): fields_list.append(self.feedback) return fields_list def burstHTML(self, i): """ takes a BeautifulSoup fragment (i) and bursts its contents to import this idevice from a CommonCartridge export """ # Cloze Idevice: title = i.find(name='span', attrs={'class' : 'iDeviceTitle' }) self.title = title.renderContents().decode('utf-8') inner = i.find(name='div', attrs={'class' : 'iDevice_inner' }) instruct = inner.find(name='div', attrs={'class' : 'block' , 'style' : 'display:block' }) self.instructionsForLearners.content_wo_resourcePaths = \ instruct.renderContents().decode('utf-8') # and add the LOCAL resource paths back in: self.instructionsForLearners.content_w_resourcePaths = \ self.instructionsForLearners.MassageResourceDirsIntoContent( \ self.instructionsForLearners.content_wo_resourcePaths) self.instructionsForLearners.content = \ self.instructionsForLearners.content_w_resourcePaths content = inner.find(name='div', attrs={'id' : re.compile('^cloze') }) rebuilt_contents = "" for this_content in content.contents: if not this_content.__str__().startswith('" elif not this_content.__str__().startswith('