def __init__(self, parentNode=None): """ Sets up the idevice title and instructions etc """ Idevice.__init__( self, x_(u"FPD - Actividad de Espacios en Blanco (Modificada)"), x_(u"University of Auckland"), x_(u"<p>Cloze exercises are texts or " "sentences where students must fill in " "missing words. They are often used for the " "following purposes:</p>" "<ol>" "<li>To check knowledge of core course " "concepts (this could be a pre-check, " "formative exercise, or summative check).</li>" "<li>To check reading comprehension.</li>" "<li>To check vocabulary knowledge.</li>" "<li>To check word formation and/or grammatical " "competence. </li></ol>"), x_(u"<dl>" " <dt>If your goal is to test understanding " "of core concepts or reading comprehension" " </dt>" " <dd>" " <p>" " 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." " </p>" " <p>" "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." " </p>" " </dd>" " <dt>" "If your goal is to test vocabulary knowledge" " </dt>" " <dd>" "<p>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.</p>" " </dd>" " <dt>" "If your goal is to test word " "formation/grammar:" " </dt>" " <dd>" " <p>" "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." " </p>" " <p>" "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!" " </p>" " </dd>" "</dl>"), u"autoevaluacionfpd", 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 = ClozelangField( x_(u'Clozelang'), x_(u"""<p>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.</p><p> To select words to hide, double click on the word to select it and click on the Hide/Show Word button below.</p>""")) 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.emphasis = "_autoevaluacionfpd" self.systemResources += ["common.js"] self.isCloze = True
class ClozelangfpdIdevice(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"FPD - Actividad de Espacios en Blanco (Modificada)"), x_(u"University of Auckland"), x_(u"<p>Cloze exercises are texts or " "sentences where students must fill in " "missing words. They are often used for the " "following purposes:</p>" "<ol>" "<li>To check knowledge of core course " "concepts (this could be a pre-check, " "formative exercise, or summative check).</li>" "<li>To check reading comprehension.</li>" "<li>To check vocabulary knowledge.</li>" "<li>To check word formation and/or grammatical " "competence. </li></ol>"), x_(u"<dl>" " <dt>If your goal is to test understanding " "of core concepts or reading comprehension" " </dt>" " <dd>" " <p>" " 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." " </p>" " <p>" "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." " </p>" " </dd>" " <dt>" "If your goal is to test vocabulary knowledge" " </dt>" " <dd>" "<p>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.</p>" " </dd>" " <dt>" "If your goal is to test word " "formation/grammar:" " </dt>" " <dd>" " <p>" "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." " </p>" " <p>" "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!" " </p>" " </dd>" "</dl>"), u"autoevaluacionfpd", 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 = ClozelangField( x_(u'Clozelang'), x_(u"""<p>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.</p><p> To select words to hide, double click on the word to select it and click on the Hide/Show Word button below.</p>""")) 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.emphasis = "_autoevaluacionfpd" 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('^clozelang')}) rebuilt_contents = "" for this_content in content.contents: if not this_content.__str__().startswith('<input'): if this_content.__str__().startswith('<span'): # Now, decode the answer # with code reverse-engineered from: # a) Cloze's getClozeAnswer() in common.js # b) ClozeElement's renderView() + encrypt() answer = "" code_key = 'X' code = this_content.renderContents() code = code.decode('base64') # now in the form %uABCD%uEFGH%uIJKL.... char_pos = 0 while char_pos < len(code): # first 2 chars = %u, replace with 0x to get int # next 4 = the encoded unichr this_code_char = "0x" + code[char_pos + 2:char_pos + 6] this_code_ord = int(this_code_char, 16) letter = chr(ord(code_key) ^ this_code_ord) answer += letter # key SHOULD be ^'d by letter, but seems to be: code_key = letter char_pos += 6 rebuilt_contents += "<U>" + answer + "</U>" elif not this_content.__str__().startswith('<div'): # this should be the un-clozed text: rebuilt_contents += this_content.__str__() self._content.content_wo_resourcePaths = rebuilt_contents # and add the LOCAL resource paths back in: self._content.content_w_resourcePaths = \ self._content.MassageResourceDirsIntoContent( \ self._content.content_wo_resourcePaths) self._content.content = self._content.content_w_resourcePaths feedback = inner.find(name='div', attrs={'class': 'feedback'}) self.feedback.content_wo_resourcePaths = \ feedback.renderContents().decode('utf-8') # and add the LOCAL resource paths back in: self.feedback.content_w_resourcePaths = \ self.feedback.MassageResourceDirsIntoContent( \ self.feedback.content_wo_resourcePaths) self.feedback.content = self.feedback.content_w_resourcePaths # and each cloze flag field (strict, case, instant): flag_strict = inner.find( name='input', attrs={'id': re.compile('^clozelangFlag.*strictMarking$')}) if flag_strict.attrMap['value'] == "true": self._content.strictMarking = True flag_caps = inner.find( name='input', attrs={'id': re.compile('^clozelangFlag.*checkCaps$')}) if flag_caps.attrMap['value'] == "true": self._content.checkCaps = True flag_instant = inner.find( name='input', attrs={'id': re.compile('^clozelangFlag.*instantMarking$')}) if flag_instant.attrMap['value'] == "true": self._content.instantMarking = True flag_score = inner.find( name='input', attrs={'id': re.compile('^clozelangFlag.*showScore$')}) if flag_score.attrMap['value'] == "true": self._content.showScore = True def upgradeToVersion1(self): """ Upgrades exe to v0.10 """ self._upgradeIdeviceToVersion1() self.instructionsForLearners = TextAreaField( x_(u'Instructions For Learners'), x_(u'Put instructions for learners here'), x_(u'Read the paragraph below and ' 'fill in the missing words')) self.instructionsForLearners.idevice = self self.feedback = TextAreaField(x_(u'Feedback')) self.feedback.idevice = self def upgradeToVersion2(self): """ Upgrades exe to v0.11 """ self.content.autoCompletion = True self.content.autoCompletionInstruc = _(u"Allow auto completion when " u"user filling the gaps.") def upgradeToVersion3(self): """ Upgrades to v0.12 """ self._upgradeIdeviceToVersion2() self.systemResources += ["common.js"] def upgradeToVersion4(self): """ Upgrades to v0.20.3 """ self.isCloze = True