# -*- coding: utf-8 -*- from django import forms from django.db.models import Q from django.http import Http404 from django.utils.translation import ugettext_lazy as _ from django.utils.encoding import force_unicode import settings as settings from conf.tools import switch_language_code from models import * #from game import * #from rus_drill.game import relax import datetime import socket import sys, os import itertools from random import choice # TODO: These should be accessible in the admin interface, not hardcoded. PRONOUNS_LIST = {'Sg1':u'я', 'Sg2':u'ты', 'Sg3':u'он', 'Pl1':u'мы', 'Pl2':u'вы', 'Pl3':u'они'} # DEMONSTRATIVE_PRESENTATION plus Sg3/Pl3 PASSIVE_PRONOUNS_LIST = {'Sg1':'меня́', 'Sg2':'тебя́', 'Sg3':'его́', 'Pl1':'нас', 'Pl2':'вас', 'Pl3':'их'} NEGATIVE_VERB_PRES = {'Sg1':'in', 'Sg2':'it', 'Sg3':'ii', 'Pl1':'eat', 'Pl2':'ehpet', 'Pl3':'eai', 'Du1':'ean', 'Du2':'eahppi', 'Du3':'eaba'} TENSE_PRESENTATION = { 'Prs': u'сегодня', 'Pst': u'вчера', } RECIPROCATIVE_PRESENTATION = { 'Du': u'guhtet', 'Pl': u'goabbat', } DEMONSTRATIVE_PRESENTATION = { 'Sg': u'okta', 'Sg3': u'okta', 'Pl': u'máŋga', 'Pl3': u'máŋga', } POS_CHOICES = ( ('N', _('noun')), ('V', _('verb')), ('A', _('adjective')), ('Num', _('numeral')), ('Pron', _('pronoun')), ) CASE_CHOICES = ( ('N-NOM-PL', _('Nominative plural')), ('N-ACC', _('Accusative')), ('N-GEN', _('Genitive')), ('N-DAT', _('Dative')), ('N-INS', _('Instrumental')), ('N-LOC', _('Locative')), ('N-GEN2', _('Genitive 2')), ('N-LOC2', _('Locative 2')), ) # For now this is just a part of a test, used in game.Game.get_db_info_new # I wanted a very general way to specify question/answers. NOUN_QUESTION_ANSWER = { # gametype question answer 'NOMPL': [('N+Sg+Nom', 'N+Pl+Nom')], 'N-ACC': [('N+NumberN+Nom', 'N+NumberN+Acc')], 'N-ILL': [('N+NumberN+Nom', 'N+NumberN+Ill')], 'N-LOC': [('N+NumberN+Nom', 'N+NumberN+Loc')], 'N-COM': [('N+NumberN+Nom', 'N+NumberN+Com')], 'N-GEN': [('N+NumberN+Nom', 'N+NumberN+Gen')], 'N-ESS': [('N+NumberN+Nom', 'N+Ess')], } NOUN_FILTER_DEFINITION = ['animacy', 'declension', 'gender', 'source'] # Pers - akk, gen, ill, lok, kom # Dem - akk, gen, ill, lok, kom CASE_CHOICES_PRONOUN = ( ('NOMPL', _('plural')), ('N-ACC', _('accusative')), ('N-DAT', _('dative')), ('N-LOC', _('locative')), ('N-INS', _('instrumental')), ('N-GEN', _('genitive')), ) # ('N-ACC', _('accusative')), # ('N-ILL', _('illative')), # ('N-LOC', _('locative')), # ('N-COM', _('comitative')), # ('N-GEN', _('genitive')), # # ('N-ESS', _('essive')), # ) PRONOUN_QUESTION_ANSWER = { # gametype question answer 'N-ACC': [('Pron+Subclass+NumberN+Nom', 'Pron+Subclass+NumberN+Acc')], # 'N-ILL': [('Pron+Subclass+NumberN+Nom', 'Pron+Subclass+NumberN+Ill')], 'N-LOC': [('Pron+Subclass+NumberN+Nom', 'Pron+Subclass+NumberN+Loc')], # 'N-COM': [('Pron+Subclass+NumberN+Nom', 'Pron+Subclass+NumberN+Com')], 'N-GEN': [('Pron+Subclass+NumberN+Nom', 'Pron+Subclass+NumberN+Gen')], } PRONOUN_FILTER_DEFINITION = ['pron_type',] # Refl - ill, lok, kom # Recipr - ill, lok, kom RECIP_REFL_CHOICES = ( ('N-ILL', _('illative')), ('N-LOC', _('locative')), ('N-COM', _('comitative')), ) PRONOUN_SUBCLASSES = ( ('Pers', _('personal')), ('Dem', _('demonstrative')), ('Recipr', _('reciprocative')), ('Refl', _('reflexive')), ('Rel', _('relative')), ) CASE_CONTEXT_CHOICES = ( # ('N-NOM-PL', _('plural')), ('N-ACC', _('accusative')), ('N-GEN', _('genitive')), # ('N-ILL', _('illative')), ('N-LOC', _('locative')), ('N-DAT', _('dative')), # ('N-ESS', _('essive')), # ('N-MIX', _('mix')), ) NOUN_TYPE_CHOICES =( ('N-FEM-other', _(u'feminine in -a/-я')), ('N-FEM-8', _(u'feminine in -ь')), ('N-MASC-INANIM', _('masculine inanimate')), ('N-MASC-ANIM', _('masculine animate')), ('N-NEUT', _('neuter')), ('all', _('All')), ) # # No inessive or essive, and no choice between nom sg. and pl, but nom sg and pl come together. # PRON_CONTEXT_CHOICES = ( #('P-NOM', _('nominative')), Morfa C pronomen nominativ skal fjernes fra menyen dersom oppgavene har ingen hensikt. ('P-PERS', _('personal')), ('P-DEM', _('demonstrative')), ('P-RECIPR', _('reciprocative')), ('P-REFL', _('reflexive')), ('P-REL', _('relative')), ) WORDFORM_TYPE_CHOICES = ( ('goabbat', _('goabbat/guhtet')), ('nubbi', _('nubbi/nuppit')), ) ADJCASE_CHOICES = ( ('N-NOM-PL', _('plural')), ('N-ACC', _('Accusative')), ('N-GEN', _('Genitive')), ('N-DAT', _('Dative')), ('N-INS', _('Instrumental')), ('N-LOC', _('Locative')), ) ADJECTIVE_QUESTION_ANSWER = { # gametype question answer 'NOMPL': [('A+Sg+Nom', 'A+Pl+Nom')], 'ATTR': [('A+Sg+Nom', 'A+Attr')], 'N-ACC': [('A+NumberA+Nom', 'A+NumberN+Acc')], # 'N-ILL': [('A+NumberA+Nom', 'A+NumberN+Ill')], 'N-LOC': [('A+NumberA+Nom', 'A+NumberN+Loc')], # 'N-COM': [('A+NumberA+Nom', 'A+NumberN+Com')], 'N-GEN': [('A+NumberA+Nom', 'A+NumberN+Gen')], # 'N-ESS': [('A+NumberA+Nom', 'A+Ess')], } ADJECTIVE_FILTER_DEFINITION = ['grade', 'stem', 'source'] ADJEX_CHOICES = ( ('A-ATTR', _('attributive')), # A+Nom+Sg -> A+Attr ('A-COMP', _('comparative')), # A+Nom+Sg -> Comp ('A-SUPERL', _('superlative')), # A+Nom+Sg -> Superl ) ADJ_CONTEXT_CHOICES = ( ('ATTRPOS', _('attributive positive')), ('ATTRCOMP', _('attributive comparative')), ('ATTRSUP', _('attributive superlative')), ('PREDPOS', _('predicative positive')), ('PREDCOMP', _('predicative comparative')), ('PREDSUP', _('predicative superlative')), ) GRADE_CHOICES = ( ('POS', _('positive')), ('COMP', _('comparative')), ('SUPERL', _('superlative')), ) NUM_CONTEXT_CHOICES = ( ('NUM-ATTR', _('attributive')), ('NUM-NOM-PL', _('plural')), ('NUM-ACC', _('accusative')), # ('NUM-ILL', _('illative')), ('NUM-LOC', _('locative')), # ('NUM-COM', _('comitative')), ('COLL-NUM', _('collective')), ('ORD-NUM', _('ordinals')), ) NUM_BARE_CHOICES = ( ('NOMPL', _('plural')), ('N-ACC', _('accusative')), # ('N-ILL', _('illative')), ('N-LOC', _('locative')), # ('N-COM', _('comitative')), ) NUMERAL_QUESTION_ANSWER = { # gametype question answer # 'N-ESS': [('Num+NumberN+Nom', 'Num+Ess')], 'N-LOC': [('Num+NumberN+Nom', 'Num+NumberN+Loc')], # 'N-ILL': [('Num+NumberN+Nom', 'Num+NumberN+Ill')], } NUMERAL_FILTER_DEFINITION = ['stem', 'source'] NUM_LEVEL_CHOICES = ( ('1', _('First level')), ('2', _('Second level')), ) NUM_TYPE_CHOICES = ( ('CARD', _('cardinal')), ('ORD', _('ordinal')), ('COLL', _('collective')), ) VTYPE_CHOICES = ( ('PRS', _('present')), ('PRT', _('past')), #('PRF', _('perfect')), #('GER', _('gerund')), #('COND', _('conditional')), ('IMPRT', _('imperative')), #('POT', _('potential')), ) VERB_QUESTION_ANSWER = { 'PRS': [('V+Inf', 'V+Ind+Prs+Person-Number')], 'PRT': [('V+Inf', 'V+Ind+Pst+Person-Number')], 'PRF': [('V+Inf', 'V+PrfPrc')], 'GER': [('V+Inf', 'V+Ger')], 'COND': [('V+Inf', 'V+Cond+Prs+Person-Number')], 'IMPRT': [('V+Inf', 'V+Imprt+Person-Number')], 'POT': [('V+Inf', 'V+Pot+Prs+Person-Number')], } VERB_FILTER_DEFINITION = ['stem', 'source'] VTYPE_CONTEXT_CHOICES = ( ('V-PRS', _('present')), ('V-PST', _('past')), # ('V-PRF', _('perfect')), # ('V-GER', _('gerund')), # ('V-COND', _('conditional')), # ('V-IMPRT', _('imperative')), # ('V-POT', _('potential')), # ('V-MIX', _('mix')), # ('TEST', _('test questions')), ) LEVEL_CHOICES = ( ('l1', _('Level 1')), ('l2', _('Level 1-2')), ('l3', _('Level 1-3')), ('all', _('All')), ) DERIVATION_CHOICES = ( ('V-DER-PASS', _('passive derivation')), ('A-DER-V', _('adjective->verb derivation')), ) DERIVATION_QUESTION_ANSWER = { 'A-DER-V': [('A+Sg+Nom', 'A+Der/AV+V+Ind+Prs+Person-Number')], } DERIVATION_FILTER_DEFINITION = False DERIVATION_CHOICES_CONTEXT = ( ('A-DER-V', _('adjective->verb derivation')), ('DER-PASSV', _('passive derivation')), ) BOOK_CHOICES = ( ('all', _(u'Møde i Petersborg')), ('l1', _('MiP 1-5')), ('l2', _('MiP 1-12')), ('l3', _('MiP 1-17')), ) FREQUENCY_CHOICES = ( ('rare', _('rare')), ('common', _('common')), ) GEOGRAPHY_CHOICES = ( ('world', _('world')), ('sapmi', _('sapmi')), # was: sápmi, maybe characters with diacritics not allowed in drop-down menus ('suopma', _('suopma')), ) VASTA_LEVELS = ( ('1', _('First level')), ('2', _('Second level')), ('3', _('Third level')), ) VASTAS_NR_OF_TASKWORDS = ( ('2', _('2')), ('3', _('3')), ('4', _('4')), ) TRANS_CHOICES = ( ('rusnob', _('Russian to Norwegian')), ('nobrus', _('Norwegian to Russian')), ('rusdan', _('Russian to Danish')), ('danrus', _('Danish to Russian')), ('ruseng', _('Russian to English')), ('engrus', _('English to Russian')), ) NUMLANGUAGE_CHOICES = ( ('rus', _('Russian')), ) SEMTYPE_CHOICES = ( ('CLASS1', _('class1')), ('CLASS2', _('class2')), ('all', _('all')), ) """ ('KIN', _('family')), ('HUMAN', _('human')), ('ANIMAL_FISH', _('animal/fish')), ('BODY', _('body')), ('FOOD_DRINK', _('food/drink')), ('TIME', _('time')), ('CLOTHING', _('clothes')), ('HEALTH', _('health')), ('PLACE', _('place')), ('PLACE_DOMESTIC', _('domestic place')), ('TRAVELING', _('travel')), ('WEATHER', _('weather')), ('NATURE_PHENOMENA', _('nature')), ('PLANT', _('plant')), ('HANDICRAFT', _('handicraft')), ('GRAMMAR_TERMINOLOGY', _('grammar terminology')), ('EDUCATION', _('school/education')), ('EXPRESSIONS', _('expressions')), ('CHURCH', _('church')), ('ABSTRACT_CONCEPTS', _('abstract')), ('VERB1', _('easy verbs')), ('VERB2', _('intermediate verbs')), ('VERB3', _('difficult verbs')), ('PRONOUN', _('pronoun')), ('NAME', _('name')), ('DIMINUTIVE', _('diminutive')), ('all', _('all')), ) """ NUM_CHOICES = ( ('10', _('0-10')), ('20', _('0-20')), ('100', _('0-100')), ('1000', _('0-1000')), # ('ALL', _('all')), ) NUMGAME_CHOICES = ( ('string', _('String to numeral')), ('numeral', _('Numeral to string')), ) NUMGAME_CHOICES_PL = ( ('string', _('Strings to numerals')), ('numeral', _('Numerals to strings')), ) # These are not actually used in Forms, but used as a way to sneak these # into the locale files so that the trans tag may be applied to # form.wordclass without altering code here VERB_CLASSES = ( ('I', _('I')), ('II', _('II')), ('III', _('III')), ('IV', _('IV')), ('V', _('V')), ('VI', _('VI')), ('Odd', _('Odd')), ) KLOKKA_CHOICES = ( ('kl1', _('easy')), ('kl2', _('medium')), ('kl3', _('hard')), ) DIALOGUE_CHOICES = ( ('firstmeeting', _('Firstmeeting')), ('firstmeeting_boy', _('Firstmeeting boy')), ('firstmeeting_girl', _('Firstmeeting girl')), ('firstmeeting_man', _('Firstmeeting man')), ('visit', _('Visit')), ('grocery', _('Grocery')), ('shopadj', _('Shopadj')), ) #BOOK_CHOICES = tuple( # [(source.name, source.name) for source in Source.objects.all()] + # [('all', _('ALL'))] #) # Syllables are manually coded in the templates, but it's useful to get the # translation strings here, also for the courses module logging. SYLLABLE_VALUES = ( ('2syll', _('bisyllabic')), ('3syll', _('trisyllabic')), ('Csyll', _('contracted')), ) ALL_CHOICES = [ ADJCASE_CHOICES, ADJEX_CHOICES, ADJ_CONTEXT_CHOICES, BOOK_CHOICES, CASE_CHOICES, CASE_CHOICES_PRONOUN, CASE_CONTEXT_CHOICES, DIALOGUE_CHOICES, FREQUENCY_CHOICES, GEOGRAPHY_CHOICES, GRADE_CHOICES, KLOKKA_CHOICES, LEVEL_CHOICES, NUMGAME_CHOICES, NUMGAME_CHOICES_PL, NUMLANGUAGE_CHOICES, NUM_BARE_CHOICES, NUM_CHOICES, NUM_CONTEXT_CHOICES, NUM_LEVEL_CHOICES, NUM_TYPE_CHOICES, POS_CHOICES, PRONOUN_SUBCLASSES, PRON_CONTEXT_CHOICES, RECIP_REFL_CHOICES, SEMTYPE_CHOICES, SYLLABLE_VALUES, TRANS_CHOICES, VASTA_LEVELS, VASTAS_NR_OF_TASKWORDS, VERB_CLASSES, VTYPE_CHOICES, VTYPE_CONTEXT_CHOICES] GAME_TYPE_DEFINITIONS = { 'A': ADJECTIVE_QUESTION_ANSWER, 'Der': DERIVATION_QUESTION_ANSWER, 'N': NOUN_QUESTION_ANSWER, 'Num': NUMERAL_QUESTION_ANSWER, 'Pron': PRONOUN_QUESTION_ANSWER, 'V': VERB_QUESTION_ANSWER, } GAME_FILTER_DEFINITIONS = { 'A': ADJECTIVE_FILTER_DEFINITION, 'Der': DERIVATION_FILTER_DEFINITION, 'N': NOUN_FILTER_DEFINITION, 'Num': NUMERAL_FILTER_DEFINITION, 'Pron': PRONOUN_FILTER_DEFINITION, 'V': VERB_FILTER_DEFINITION, } # # # # Form validation # # # import re from settings import INFINITIVE_SUBTRACT as infinitives_sub from settings import INFINITIVE_ADD as infinitives_add def relax(strict): """Returns a list of relaxed possibilities, making changes by relax_pairs. Many possibilities are generated in the event that users are inconsistent in terms of substituting one letter but not substituting another, however, *all* possibilities are not generated. E.g., *ryøjnesjäjja is accepted for ryöjnesjæjja (user types ø instead of ö consistently) ... but ... *töølledh is not accepted for töölledh (user mixes the two in one word) Similarly, directionality is included. is accepted for <ï>, but not vice versa. E.g.: *ååjmedïdh is not accepted for ååjmedidh, ... but ... *miele is accepted for mïele. """ # Not needed in NumQuestion and KlokkaQuestion anymore as this is done by new text2digit trascriptors # Still used in OahpaQuestion and ContextMorfaQuestion until other oahpa transducers incorporate the feature from django.utils.encoding import force_unicode relaxed = strict sub_str = lambda _string, _target, _sub: _string.replace(_target, _sub) relax_pairs = { # key: value # value is accepted for key - have changed the order in the pairs because the key must be unique # For Russian: spellrelax for je vs jo, vowels with and without stress marks u'а́': u'а', u'е́': u'е', u'и́': u'и', u'о́': u'о', u'у́': u'у', u'ы́': u'ы', u'э́': u'э', u'ю́': u'ю', u'я́': u'я', u'ё': u'е', } # Create an iterator. We want to generate as many possibilities as # possible (very fast), so more relaxed options are available. searches = relax_pairs.items() # HU: Commented out the following complex code because it was causing an infinite loop or similar. And the generation of relaxed forms works fine without it. :) #print "searches composed", searches #permutations = itertools.chain(itertools.permutations(searches)) #print "permutations composed" #perms_flat = sum([list(a) for a in permutations], []) #print "list of permutations ",perms_flat # Individual possibilities relaxed_perms = [sub_str(relaxed, R, S) for R, S in searches] #print relaxed_perms # Possibilities applied one by one #for S, R in perms_flat: # relaxed = sub_str(relaxed, R, S) # relaxed_perms.append(relaxed) # Return list of unique possibilities relaxed_perms = list(set(relaxed_perms)) relaxed_perms = [force_unicode(item) for item in relaxed_perms] return relaxed_perms def relax_stress(strict): """Returns a string without stress marks (all). It is difefrent from the previous relax() as for stress relaxing there is no need for the list of input string with different pair substitutions. The original relax() was written for different purpose, where each substitution has its own meaning. This is not applicable for stress marks as its meaning for different letters is identical. And it is not sufficient to have string with only one substitution, if there are multiple stress marks missing or incorrect in the answer string. For written text it is necessary and sufficient if the student answer without stress marks matches the correct answer without stress marks. """ from django.utils.encoding import force_unicode relaxed = strict sub_str = lambda _string, _target, _sub: _string.replace(_target, _sub) relax_pairs = { # key: value # value is accepted for key - have changed the order in the pairs because the key must be unique # For Russian: spellrelax for je vs jo, vowels with and without stress marks u'а́': u'а', u'е́': u'е', u'и́': u'и', u'о́': u'о', u'у́': u'у', u'ы́': u'ы', u'э́': u'э', u'ю́': u'ю', u'я́': u'я', u'ё': u'е', u'ё́': u'е', } searches = relax_pairs.items() for R, S in searches: relaxed = sub_str(relaxed, R, S) return relaxed def is_correct(self, game, example=None): """ Determines if the given answer is correct (for a bound form). """ self.game = game self.example = example if not self.is_valid(): return False self.userans = self.cleaned_data['answer'] self.answer = self.userans.strip() if not game == "numra": self.answer = self.answer.rstrip('.!?,') self.error = "error" self.iscorrect = False if self.answer in set(self.correct_anslist) or \ self.answer.lower() in set(self.correct_anslist) or \ self.answer.upper() in set(self.correct_anslist): self.error = "correct" self.iscorrect = True # Log information about user answers. correctlist = u",".join([a for a in self.correct_anslist]) self.correctlist = correctlist self.log_response() def set_correct(self): """ Adds correct wordforms to the question form. """ if self.correct_ans: self.correct_answers = self.correct_ans[:] if type(self.correct_answers) == list: self.correct_answers = ', '.join(self.correct_answers) def set_settings(self): # self.levels = { # 'l1': ['l1'], # 'l2': ['l2', 'l1'], # 'l3': ['l3', 'l2', 'l1'], # 'all': ['l3', 'l2', 'l1', 'all'], # } # Construct arrays for level choices. # Commenting this out because I don't see yet why this needs to be constructed this way. # If it's done automatically so that more levels can be added, the code here will still need # to be altered... So it seems easiest to just hard-code this for now. # self.levels = {} # self.levels['all'] = [] # for b in LEVEL_CHOICES: # if b[0] != 'all': # self.levels[b[0]] = [] # self.levels['all'].append(b[0]) # # self.levels[b[0]].append(b[0]) # # self.levels['l2'].append('l1') # for b in ['l1', 'l2']: # self.levels['l3'].append(b) # Turning these into dictionary type means there's no need to iterate to # get the first tuple item. Also makes it easier to read. And, there are # no many-to-many relationships in these tuples of tuples self.allsem = dict(SEMTYPE_CHOICES).keys() self.allcase = dict(CASE_CHOICES).keys() self.allcase_context = dict(CASE_CONTEXT_CHOICES).keys() self.proncase_context = dict(PRON_CONTEXT_CHOICES).keys() self.allvtype_context = dict(VTYPE_CONTEXT_CHOICES).keys() self.alladjcase = dict(ADJCASE_CHOICES).keys() # added by Heli self.allgrade = dict(GRADE_CHOICES).keys() # added by Heli self.alladj_context = dict(ADJ_CONTEXT_CHOICES).keys() self.allnum_context = dict(NUM_CONTEXT_CHOICES).keys() self.allnum_bare = dict(NUM_BARE_CHOICES).keys() self.allnum_type = dict(NUM_TYPE_CHOICES).keys() # added by Heli self.sources = dict(BOOK_CHOICES).keys() self.geography = dict(GEOGRAPHY_CHOICES).keys() self.frequency = dict(FREQUENCY_CHOICES).keys() # added by Heli self.allnoun_type = dict(NOUN_TYPE_CHOICES).keys() # added by Pavel # comment # DEBUG = open('/dev/ttys001', 'w') # DEBUG = open('/dev/null', 'w') def get_feedback(self, wordform, language): language = switch_language_code(language) feedbacks = wordform.feedback.filter(feedbacktext__language=language).order_by('feedbacktext__order') feedback_messages = [] for feedback in feedbacks: texts = feedback.feedbacktext_set.filter(language=language).order_by('order') feedback_messages.extend([a.message for a in texts]) message_list = [] if feedback_messages: for text in feedback_messages: text = text.replace('WORDFORM', '"%s"' % wordform.word.lemma) message_list.append(text) self.feedback = ' \n '.join(list(message_list)) ### print wordform.fullform ### print wordform.tag.string ### print 'stem:' + wordform.word.stem ### print 'gradation:' + wordform.word.gradation ### print 'diphthong:' + wordform.word.diphthong ### print 'rime:' + wordform.word.rime ### print 'soggi:' + wordform.word.soggi ### print 'attrsuffix:' + wordform.word.attrsuffix ### print 'compsuffix:' + wordform.word.compsuffix ### print self.feedback ### print '--' ### # NOTE: debug ### # print wordform.id ### # print wordform.feedback.all() ### # print feedbacks ### # print self.feedback ### # print '\n' def select_words(self, qwords, awords): """ Fetch words and tags from the database. """ from random import choice selected_awords = {} for syntax in awords.keys(): word = None tag = None selected_awords[syntax] = {} # Select answer words and fullforms for interface if awords.has_key(syntax) and len(awords[syntax]) > 0: aword = choice(awords[syntax]) if aword.has_key('tag'): selected_awords[syntax]['tag'] = aword['tag'] if aword.has_key('task'): selected_awords[syntax]['task'] = aword['task'] if aword.has_key('taskword'): selected_awords[syntax]['taskword'] = aword['taskword'] if aword.has_key('qelement'): qelem = aword['qelement'] if type(qelem) is not long: # to exclude MorfaC if qelem.task: # words in VastaS answer frame where task="yes". selected_awords[syntax]['taskword'] = qelem.task if aword.has_key('word') and aword['word']: selected_awords[syntax]['word'] = aword['word'] else: if aword.has_key('qelement') and selected_awords[syntax].has_key('tag'): # get form_list for a given qelement wqelems = WordQElement.objects.filter(qelement__id=aword['qelement']) # Some WordQElements are associated with words that have no # Forms, as such we have to randomly select one until we # find an element with forms. This is faster than filtering # by annotating and Count() if wqelems.count() > 0: form_list = None i, max = 0, 50 while not form_list and i < max: i += 1 wqel = wqelems.order_by('?')[0] selected_awords[syntax]['word'] = wqel.word.id form_list = wqel.word.form_set.filter( tag__id = selected_awords[syntax]['tag'] ) if form_list: fullf = [f.fullform for f in form_list] selected_awords[syntax]['fullform'] = fullf[:] if not selected_awords[syntax].has_key('fullform'): if aword.has_key('fullform') and len(aword['fullform']) > 0: selected_awords[syntax]['fullform'] = aword['fullform'][:] if not selected_awords[syntax].has_key('fullform'): if selected_awords[syntax].has_key('word')\ and selected_awords[syntax].has_key('tag'): form_list = Form.objects.filter( word__id=selected_awords[syntax]['word'], tag__id=selected_awords[syntax]['tag'], ) excl = form_list.exclude(dialects__dialect='NG') if excl.count() > 0: form_list = excl form_list_dialects = form_list.filter(dialects__dialect=self.dialect) if form_list_dialects.count() > 0: form_list = form_list_dialects if form_list.count() > 0: fullf = [] for f in form_list: fullf.append(f.fullform) selected_awords[syntax]['fullform'] = fullf[:] # make sure that there is something to print if not selected_awords[syntax].has_key('fullform'): selected_awords[syntax]['fullform'] = [] selected_awords[syntax]['fullform'].append(syntax) print "selected awords: " print selected_awords return selected_awords # # # # Oahpa form meta-classes # # # class OahpaSettings(forms.Form): """ The metaform for game settings. Various games subclass from this form. """ set_settings = set_settings def clean(self): x = self.cleaned_data['bisyllabic'] print 'clean: ', x return self.cleaned_data def set_default_data(self): self.default_data = { 'language' : 'rus', # sme in univ_oahpa 'syll' : ['2syll'], # syllabicity not relevant, change this 'bisyllabic': 'on', 'trisyllabic': False, 'contracted': False, 'level' : 'all', 'lemmacount' : '2', 'case': 'N-ACC', 'pos' : 'N', 'vtype' : 'PRS', # was IMPRT 'adjcase' : 'N-GEN', 'number' : '', 'pron_type': 'Pers', 'proncase' : 'N-NOM', # Need a new default case here 'grade' : '', # was: '' 'Pos' is not a good idea beacuse it is implicit in the database. 'case_context' : 'N-ACC', # was: N-NOM 'vtype_context' : 'V-PRS', 'pron_context' : 'P-PERS', 'num_context' : 'NUM-ATTR', 'num_level' : '1', 'num_type' : 'CARD', # added by Heli 'derivation_type' : 'V-DER-PASS', 'derivation_type_context' : 'DER-PASSV', # was V-DER 'geography': 'world', 'frequency' : [], 'num_bare' : 'N-NOM', # Need a new default case here 'adj_context' : 'ATTRPOS', 'book' : 'all', 'noun_type': 'N-MASC-INANIM', 'singular_only' : False} class OahpaQuestion(forms.Form): """ Meta form for question/answer section. """ is_correct = is_correct set_correct = set_correct get_feedback = get_feedback # Set answer widget. Can this JS actually be moved to templates? KEYDOWN = 'javascript:return process(this, event, document.gameform);' answer_attrs = {'size': 45} # , 'onkeydown': KEYDOWN} answer = forms.CharField(max_length=45, widget=forms.TextInput(attrs=answer_attrs)) def log_response(self): import datetime today = datetime.date.today() # print ','.join(self.correct_anslist) is_correct_answer = self.iscorrect if self.error == "error": # here: correct answer string except wrong stress mark(s) is_correct_answer = False log, c = Log.objects.get_or_create(userinput=self.answer, correct=','.join(self.correct_anslist), iscorrect=is_correct_answer, example=self.example, game=self.game, date=today) def __init__(self, *args, **kwargs): correct_val = False if 'correct_val' in kwargs: correct_val = kwargs.get('correct_val') kwargs.pop('correct_val') super(OahpaQuestion, self).__init__(*args, **kwargs) # set correct and error values if correct_val == "correct": self.error = "correct" def init_variables(self, possible, userans_val, accepted_answers, preferred=False): # Get lemma and feedback self.feedback = "" self.messages = [] if preferred: self.correct_ans = preferred else: self.correct_ans = accepted_answers self.correct_answers = "" self.case = "" self.userans = userans_val self.correct_anslist = [] self.error = "empty" self.problems = "error" self.pron = "" self.pron_imp = "" self.PronPNBase = PRONOUNS_LIST self.is_relaxed = "" self.is_tcomm = "" forms = [] relaxings = [] if hasattr(self, 'translang'): # commented out these two lines, because otherwise relax was not working in Morfa if self.translang == 'rus': # Relax spellings. accepted_answers = [force_unicode(item) for item in accepted_answers] forms = sum([relax(force_unicode(item)) for item in accepted_answers], []) #print "relaxed forms: ", forms # need to subtract legal answers and make an only relaxed list. relaxings = [item for item in forms if force_unicode(item) not in accepted_answers] elif self.gametype == 'leksa': # this applies only to Leksa # PI: commented out at this stage # # add infinitives as possible answers if self.word.pos == 'V': if self.translang in infinitives_sub and infinitives_add: infin_s = infinitives_sub[self.translang] infin_a = infinitives_add[self.translang] lemma = re.compile(infin_s) infins = [lemma.sub(infin_a, force_unicode(ax)) for ax in accepted_answers] accepted_answers = infins + accepted_answers #forms = accepted_answers # This is wrong: the relaxed pairs are overwritten! self.correct_anslist = [force_unicode(item) for item in accepted_answers] + [force_unicode(f) for f in forms] print "correct_anslist:",self.correct_anslist self.relaxings = relaxings #def generate_fields(self,answer_size, maxlength): # self.fields['answer'] = forms.CharField(max_length = maxlength, \ # widget=forms.TextInput(\ # attrs={'size': answer_size, 'onkeydown':'javascript:return process(this, event,document.gameform);',})) # copied from old-oahpa # # # # Leksa Forms # # # class LeksaSettings(OahpaSettings): semtype = forms.ChoiceField(initial='all', choices=SEMTYPE_CHOICES) # was: HUMAN transtype = forms.ChoiceField(choices=TRANS_CHOICES, widget=forms.Select) # For placename quizz #geography = forms.ChoiceField(initial='world', choices=GEOGRAPHY_CHOICES) #frequency = forms.MultipleChoiceField(required=False, widget=CheckboxSelectMultiple, choices=FREQUENCY_CHOICES) # added #common = forms.BooleanField(required=False, initial='1') #rare = forms.BooleanField(required=False,initial=0) # sapmi = forms.BooleanField(required=False, initial='1') # world = forms.BooleanField(required=False,initial=0) # suopma = forms.BooleanField(required=False,initial=0) source = forms.ChoiceField(initial='all', choices=BOOK_CHOICES) # level = forms.ChoiceField(initial='all', choices=LEVEL_CHOICES, widget=forms.Select(attrs={'onchange':'javascript:return SetIndex(document.gameform.semtype,this.value);',})) default_data = {'gametype' : 'leksa', 'language' : 'rus', 'dialogue' : 'GG', #'syll' : [], #'bisyllabic': False, #'trisyllabic': False, #'bisyllabic': False, #'contracted': False, 'source': 'all', 'semtype' : 'all', # was: 'HUMAN', #'geography' : 'world', #'frequency' : ['common'] # added } # set default language pair from session language setting. def __init__(self, *args, **kwargs): if 'initial_transtype' in kwargs: initial_transtype = kwargs.pop('initial_transtype') else: initial_transtype = False self.set_settings() super(LeksaSettings, self).__init__(*args, **kwargs) if initial_transtype: self.fields['transtype'].initial = initial_transtype self.default_data['transtype'] = initial_transtype class LeksaQuestion(OahpaQuestion): """ Questions for word quizz """ def __init__(self, tcomms, stat_pref, preferred, possible, transtype, word, correct, translations, question, userans_val, correct_val, *args, **kwargs): lemma_widget = forms.HiddenInput(attrs={'value' : word.id}) self.translang = transtype[-3::] self.sourcelang = transtype[0:3] self.word = word self.gametype = 'leksa' kwargs['correct_val'] = correct_val super(LeksaQuestion, self).__init__(*args, **kwargs) self.tcomm = None if tcomms: if userans_val in tcomms: self.tcomm = True else: self.tcomm = None self.fields['word_id'] = forms.CharField(widget=lemma_widget, required=False) # If we want stress marks in Leksa then we have to use lemma_stressed instead of lemma. if type(word) == Word: if self.sourcelang == 'rus': self.lemma = word.lemma_stressed # for Russian the words will be presented with stress marks else: self.lemma = word.lemma # for other languages 'lemma_stressed' does not exist else: self.lemma = word.definition if word.pos.upper() == 'V': if word.language in infinitives_sub and infinitives_add: infin_s = infinitives_sub[word.language] infin_a = infinitives_add[word.language] lemma = re.compile(infin_s) lemmax = lemma.sub(infin_a, force_unicode(self.lemma)) self.lemma = force_unicode(lemmax) self.init_variables(possible=translations, userans_val=userans_val, accepted_answers=possible, preferred=preferred) self.is_correct("leksa", self.lemma) # set correct and error values if correct_val: if correct_val == "correct": self.error = "correct" # always accept relaxed spelling #if userans_val in self.relaxings: self.is_relaxed = "relaxed" self.strict = 'Strict form' #else: # self.is_relaxed = "" if stat_pref: self.correct_ans = stat_pref # Displayed answer also needs infinitive marking # Needs to happen last because of stat_pref if word.pos.upper() == 'V': if self.translang in infinitives_sub and infinitives_add: infin_s = infinitives_sub[self.translang] infin_a = infinitives_add[self.translang] lemma = re.compile(infin_s) self.correct_ans = [lemma.sub(infin_a, force_unicode(ax)) for ax in self.correct_ans] self.correct_ans = [force_unicode(ax) for ax in self.correct_ans] # # # # Morfa Forms # # # class MorfaSettings(OahpaSettings): """ A form for the settings part of the game form, e.g., the form used to set case, stem and source books for quiz questions. This is a separate form from the one which validates questions and answers. PI: this is quite hardcoded (and it wasn't exactly easy finding where the N-ILL default value in $home/morfa/ came from, because instead of an exception there was a relatively unhelpful 404 error. """ case = forms.ChoiceField(initial='N-ACC', choices=CASE_CHOICES, widget=forms.Select) pron_type = forms.ChoiceField(initial='PERS', choices=PRONOUN_SUBCLASSES, widget=forms.Select) proncase = forms.ChoiceField(initial='N-NOM-PL', choices=CASE_CHOICES_PRONOUN, widget=forms.Select) adjcase = forms.ChoiceField(initial='N-GEN', choices=ADJCASE_CHOICES, widget=forms.Select) # was ADJEX_CHOICES vtype = forms.ChoiceField(initial='PRS', choices=VTYPE_CHOICES, widget=forms.Select) num_bare = forms.ChoiceField(initial='N-GEN', choices=NUM_BARE_CHOICES, widget=forms.Select) num_level = forms.ChoiceField(initial='1', choices=NUM_LEVEL_CHOICES, widget=forms.Select) num_type = forms.ChoiceField(initial='CARD',choices=NUM_TYPE_CHOICES, widget=forms.Select) derivation_type = forms.ChoiceField(initial='V-DER-PASS', choices=DERIVATION_CHOICES, widget=forms.Select) derivation_type_context = forms.ChoiceField(initial='DER-PASSV', choices=DERIVATION_CHOICES_CONTEXT, widget=forms.Select) num_context = forms.ChoiceField(initial='NUM-ATTR', choices=NUM_CONTEXT_CHOICES, widget=forms.Select) case_context = forms.ChoiceField(initial='N-ACC', choices=CASE_CONTEXT_CHOICES, widget=forms.Select) adj_context = forms.ChoiceField(initial='ATTR', choices=ADJ_CONTEXT_CHOICES, widget=forms.Select) vtype_context = forms.ChoiceField(initial='V-PRS', choices=VTYPE_CONTEXT_CHOICES, widget=forms.Select) pron_context = forms.ChoiceField(initial='P-PERS', choices=PRON_CONTEXT_CHOICES, widget=forms.Select) wordform_type = forms.ChoiceField(initial='', choices=WORDFORM_TYPE_CHOICES, widget=forms.Select) book = forms.ChoiceField(initial='all', choices=BOOK_CHOICES, widget=forms.Select) bisyllabic = forms.BooleanField(required=False, initial=True) trisyllabic = forms.BooleanField(required=False, initial=False) contracted = forms.BooleanField(required=False, initial=False) grade = forms.ChoiceField(initial='POS', choices=GRADE_CHOICES, widget=forms.Select) # PI added noun_type = forms.ChoiceField(initial='all', choices=NOUN_TYPE_CHOICES, widget=forms.Select) # HU added singular_only = forms.BooleanField(required=False, initial=False) def __init__(self, *args, **kwargs): self.set_settings() self.set_default_data() super(MorfaSettings, self).__init__(*args, **kwargs) # If this is set, then the form has been posted by the user otherwise # it hasn't try: post_data = args[0] except: post_data = False if post_data: # Gen2 and Loc2 mostly exist for masculine nouns: #if 'case' in post_data: # if post_data['case'] in ['Par', 'Loc']: # self.settings['noun_type'] = "N-MASC-INANIM" # self.fields['noun_type'] = 'N-MASC-INANIM' # Use a restricted choice set for pronoun case for Refl and Recipr if 'pron_type' in post_data: if post_data['pron_type'].lower() in ['refl', 'recipr']: self.fields['proncase'].choices = RECIP_REFL_CHOICES class MorfaQuestion(OahpaQuestion): """ Questions for morphology game. """ def __init__(self, word, tag, baseform, correct, accepted_answers, answer_presentation, translations, question, dialect, language, userans_val, correct_val, conneg, *args, **kwargs): lemma_widget = forms.HiddenInput(attrs={'value': word.id}) tag_widget = forms.HiddenInput(attrs={'value': tag.id}) self.translang = 'rus' self.gametype = 'morfa' kwargs['correct_val'] = correct_val super(MorfaQuestion, self).__init__(*args, **kwargs) # initialize variables self.init_variables(possible=[], userans_val=userans_val, accepted_answers=accepted_answers) if tag.string.lower().find('conneg') > -1: if conneg: conneg_agr = conneg else: conneg_agr = choice(self.PronPNBase.keys()) else: conneg_agr = False conneg_widget = forms.HiddenInput(attrs={'value': conneg_agr}) self.fields['word_id'] = forms.CharField(widget=lemma_widget, required=False) self.fields['tag_id'] = forms.CharField(widget=tag_widget, required=False) self.fields['conneg'] = forms.CharField(widget=conneg_widget, required=False) try: self.lemma = baseform.fullform except AttributeError: self.lemma = baseform # self.wordclass = word.wordclass # PI: seems to be only used for verbs at this point, so just commenting out if not self.pron: self.pron = False #print self.lemma, correct #print baseform.tag, correct.tag # Retrieve feedback information self.get_feedback(correct, language) # Take only the first translation for the tooltip if len(translations) > 0: self.translations = translations[0] if tag.pos in ["N", "A"]: self.case = tag.case if tag.pos == 'Pron': self.case = tag.case self.tag = tag.string if tag.pos == "V": if not self.pron: if tag.string.find("ConNeg") > -1: # TODO: New choice for every refresh, fix! pers = conneg_agr pronoun = self.PronPNBase[pers] neg_verb = NEGATIVE_VERB_PRES[pers] self.pron = '%s %s' % (pronoun, neg_verb) elif tag.personnumber: pronbase = self.PronPNBase[tag.personnumber] pronoun = pronbase self.pron = pronoun if self.pron and tag.mood == "Imprt": self.pron_imp = "(" + self.pron + ")" self.pron = "" # TODO: conneg only in Prs # Odne 'today', ikte 'yesterday' if (tag.tense in ['Prs','Pst']) and (tag.mood == 'Ind'): if tag.tense == 'Pst': if Word.objects.filter(id=word.id, semtype__semtype="PERSON3"): pronoun = self.PronPNBase[tag.number+'3'] else: pronoun = self.PronPNBase[tag.number+choice(['1', '2', '3'])] time = TENSE_PRESENTATION.get(tag.tense, False) self.pron = ' '.join([time, pronoun]) if ("+Der/Pass" in tag.string) and ("+V" in tag.string): # Odne mun ___ # Ikte mun ___ # Ikte dat (okta) ___ # Choose one if not set, if set then game is in progress, and # do not choose another pers = tag.personnumber if not pers: pers = conneg_agr time = TENSE_PRESENTATION.get(tag.tense, False) pronoun = PASSIVE_PRONOUNS_LIST[pers] number = '' if pers in ['Sg3', 'Pl3']: number = '(%s)' % DEMONSTRATIVE_PRESENTATION.get(tag.personnumber, False) self.pron = ' '.join([time, pronoun, number]) # All pres? if tag.string.find("Der/AV") > -1: self.pron = TENSE_PRESENTATION.get(tag.tense, False) + " " + self.pron if tag.pos == "Pron": # Various display alternations for pronouns. # Reciprocative: # guhtet guoibmámet # goabbat guoibmámet if tag.subclass == 'Recipr': if tag.possessive.find('PxDu'): px_no = 'Du' elif tag.possessive.find('PxPl'): px_no = 'Pl' pronoun = RECIPROCATIVE_PRESENTATION.get(px_no, False) if pronoun: self.pron = pronoun # Demonstrative: # dát okta # dát máŋga if tag.subclass == 'Dem': noun_pres = DEMONSTRATIVE_PRESENTATION.get(tag.number, False) if noun_pres: self.lemma += ' (%s)' % force_unicode(noun_pres).encode('utf-8') log_name = "morfa_%s" % tag.pos try: self.is_correct(log_name, self.lemma + "+" + self.tag) except TypeError: self.is_correct(log_name, self.lemma.lemma + "+" + self.tag) # set correct and error values if correct_val: if correct_val == "correct": self.error="correct" # relax #if userans_val in self.relaxings: let's make the spelling always relaxed self.is_relaxed = "relaxed" self.strict = 'Strict form' #else: # self.is_relaxed = "" self.correct_ans = answer_presentation # # # # Numra Forms # # # class NumSettings(OahpaSettings): maxnum = forms.ChoiceField(initial='10', choices=NUM_CHOICES, widget=forms.RadioSelect) numgame = forms.ChoiceField(initial='numeral', choices=NUMGAME_CHOICES, widget=forms.RadioSelect) #numlanguage = forms.ChoiceField(initial='sjd', choices=NUMLANGUAGE_CHOICES, widget=forms.RadioSelect) # TODO: remove mandatory need to set default data, should be done through 'initial' field setting. default_data = {'language' : 'rus', 'numlanguage' : 'rus', 'dialogue' : 'GG', 'maxnum' : '10', 'numgame': 'numeral'} def __init__(self, *args, **kwargs): self.set_settings() super(NumSettings, self).__init__(*args, **kwargs) class NumQuestion(OahpaQuestion): """ Questions for numeral quizz """ game_log_name = 'numra' def answer_relax(self, answer): """ Method for relaxing answers. Override if needed. """ return answer def is_correct(self, game, example=None): self.game = game self.example = example if not self.is_valid(): return False self.userans = self.cleaned_data['answer'] self.answer = self.userans.strip() self.error = "error" self.iscorrect = False correct_test = self.game_obj.check_answer(self.question_str, self.userans, self.correct_anslist) if correct_test: self.error = "correct" self.iscorrect = True elif relax_stress(self.userans) in [relax_stress(corans) for corans in self.correct_anslist]: # which one should be logged? self.iscorrect = True self.correctlist = u",".join(list(set(self.correct_anslist))) self.log_response() def __init__(self, numeral, num_string, num_list, gametype, userans_val, correct_val, game, *args, **kwargs): numeral_widget = forms.HiddenInput(attrs={'value' : numeral}) kwargs['correct_val'] = correct_val self.userans_val = self.userans = userans_val self.game_obj = game if 'no_eval_correct' in kwargs: no_eval_correct = kwargs.pop('no_eval_correct') else: no_eval_correct = False super(NumQuestion, self).__init__(*args, **kwargs) wforms = [] self.relaxings = [] # Initialize variables if gametype == "string": self.init_variables(force_unicode(numeral), userans_val, [ numeral ]) example = num_string self.question_str = num_string else: self.init_variables(force_unicode(num_list[0]), userans_val, num_list) #wforms = sum([relax(force_unicode(item)) for item in num_list], []) # need to subtract legal answers and make an only relaxed list. self.relaxings = [item for item in wforms if item not in num_list] example = numeral self.question_str = numeral self.correct_anslist = self.correct_anslist + [force_unicode(f) for f in wforms] self.fields['numeral_id'] = forms.CharField(widget=numeral_widget, required=False) if gametype == "string": self.numstring = num_string self.numeral = numeral # Correctness not evaluated here but in child class. Short fix if not no_eval_correct: self.is_correct(self.game_log_name, example) if correct_val: if correct_val == "correct": self.error = "correct" # always accept relaxed spelling # if userans_val in self.relaxings: self.is_relaxed = "relaxed" self.strict = 'Strict form' else: self.is_relaxed = "" # # # # Klokka Forms # # # class KlokkaSettings(NumSettings): numgame = forms.ChoiceField(initial='string', choices=NUMGAME_CHOICES_PL, widget=forms.RadioSelect) gametype = forms.ChoiceField(initial='kl1', choices=KLOKKA_CHOICES, widget=forms.RadioSelect) default_data = {'language' : 'rus', 'numlanguage' : 'rus', 'dialogue' : 'GG', 'gametype' : 'kl1', 'numgame': 'string'} def __init__(self, *args, **kwargs): self.set_settings() super(KlokkaSettings, self).__init__(*args, **kwargs) class KlokkaQuestion(NumQuestion): """ Questions for numeral quizz """ game_log_name = "klokka" def relax_military(self, number): """ Change the presentation of numerals above 13 to their lower equivalents. """ military = [ ('13', '01'), ('14', '02'), ('15', '03'), ('16', '04'), ('17', '05'), ('18', '06'), ('19', '07'), ('20', '08'), ('21', '09'), ('22', '10'), ('23', '11'), ('00', '12'), ] military_dict = dict(military) options = [number] hh, _, mm = number.partition(':') try: switched = '%s:%s' % (military_dict[hh], mm) return switched except KeyError: return number def __init__(self, *args, **kwargs): present_list = kwargs.get('present_list') accept_list = kwargs.get('accept_list') kwargs.pop('present_list') kwargs.pop('accept_list') numeral = kwargs.get('numeral') num_string = kwargs.get('num_string') correct_val = kwargs.get('correct_val') userans_val = kwargs.get('userans_val') self.gametype = gametype = kwargs.get('gametype') prefix = kwargs.get('prefix') data = kwargs.get('data') numeral_widget = forms.HiddenInput(attrs={'value' : numeral}) kwargs['correct_val'] = correct_val self.userans_val = self.userans = userans_val kwargs['num_list'] = present_list # Prevent double evaluation of correctness kwargs['no_eval_correct'] = True super(KlokkaQuestion, self).__init__(*args, **kwargs) wforms = [] self.relaxings = [] # Initialize variables if gametype == "string": self.init_variables(force_unicode(numeral), userans_val, [ numeral ]) example = num_string else: self.init_variables(force_unicode(accept_list), userans_val, present_list) #wforms = sum([relax(force_unicode(item)) for item in accept_list], []) # need to subtract legal answers and make an only relaxed list. self.relaxings = [item for item in wforms if item not in accept_list] example = numeral self.correct_anslist = self.correct_anslist + [force_unicode(f) for f in wforms] self.fields['numeral_id'] = forms.CharField(widget=numeral_widget, required=False) self.numstring = num_string # Need to change presentation of certain numerals to avoid if gametype == "string": relaxed_presentation = [self.relax_military(a) for a in self.correct_anslist[:]] self.correct_ans = relaxed_presentation + self.correct_anslist self.correct_ans = self.correct_ans[0] else: # Clear numstring to switch presentation self.numstring = None self.numeral = numeral self.is_correct(self.game_log_name, example) if correct_val: if correct_val == "correct": self.error = "correct" # always accept relaxed spelling # if userans_val in self.relaxings: self.is_relaxed = "relaxed" self.strict = 'Strict form' elif userans_val in accept_list and userans_val not in present_list: self.is_relaxed = "relaxed" self.strict = 'Strict form' else: self.is_relaxed = "" def is_correct(self, game, example=None): self.game = game self.example = example if not self.is_valid(): return False self.userans = self.cleaned_data['answer'] self.answer = self.userans.strip() self.error = "error" self.iscorrect = False correct_test = self.game_obj.check_answer(self.question_str, self.userans, self.correct_anslist) if correct_test: self.error = "correct" self.iscorrect = True elif relax_stress(self.userans) in [relax_stress(corans) for corans in self.correct_anslist]: # which one should be logged? self.iscorrect = True self.correctlist = u",".join(list(set(self.correct_anslist))) self.log_response() # # # # Dato Forms # # # class DatoSettings(KlokkaSettings): gametype = None # Disable gametype (easy, medium, hard) default_data = {'language' : 'rus', 'numlanguage' : 'rus', 'numgame': 'string'} class DatoQuestion(KlokkaQuestion): game_log_name = "dato" def answer_relax(self, answer): """ No need to relax. """ return answer # # # # MorfaC Forms # # # class ContextMorfaQuestion(OahpaQuestion): """ Questions for contextual morfa """ select_words = select_words qtype_verbs = set(['V-PRS', 'V-PST', 'V-COND','V-IMPRT', 'TEST']) def generate_fields(self,answer_size, maxlength): self.fields['answer'] = forms.CharField(max_length = maxlength, \ widget=forms.TextInput(\ attrs={'size': answer_size,})) # 'onkeydown':'javascript:return process(this, event,document.gameform);' def __init__(self, question, qanswer, \ qwords, awords, dialect, language, userans_val, correct_val, *args, **kwargs): self.init_variables("", userans_val, []) self.lemma = "" self.dialect = dialect qtype=question.qtype #if qtype in self.qtype_verbs: # qtype = 'PRS' question_widget = forms.HiddenInput(attrs={'value' : question.id}) answer_widget = forms.HiddenInput(attrs={'value' : qanswer.id}) atext = force_unicode(qanswer.string) task = qanswer.task if not task: error_msg = u"not task: %s %s (%s)" % (atext, question.qid, question.qatype) raise Http404(error_msg) super(ContextMorfaQuestion, self).__init__(*args, **kwargs) answer_size = 20 maxlength = 30 self.generate_fields(20,30) self.fields['question_id'] = forms.CharField(widget=question_widget, required=False) self.fields['answer_id'] = forms.CharField(widget=answer_widget, required=False) # Select words for the the answer selected_awords = self.select_words(qwords, awords) relaxed = [] form_list=[] if not selected_awords.has_key(task): raise Http404(task + " " + atext + " " + str(qanswer.id)) if len(selected_awords[task]['fullform'])>0: for f in selected_awords[task]['fullform']: self.correct_anslist.append(force_unicode(f)) accepted = sum([relax(force_unicode(item)) for item in self.correct_anslist], []) self.relaxings = [item for item in accepted if item not in self.correct_anslist] self.correct_anslist.extend(self.relaxings) log_w = Word.objects.get(id=selected_awords[task]['word']) w_str = log_w.lemma w_pos = log_w.pos t_str = Tag.objects.get(id=selected_awords[task]['tag']).string log_name = "contextual_morfa_" + w_pos log_value = '%s+%s' % (w_str, t_str) self.is_correct(log_name, log_value) self.correct_ans = self.correct_anslist[0] self.correct_anslist = [force_unicode(item) for item in accepted] self.qattrs = {} self.aattrs = {} for syntax in qwords.keys(): qword = qwords[syntax] if qword.has_key('word'): self.qattrs['question_word_' + syntax] = qword['word'] if qword.has_key('tag') and qword['tag']: self.qattrs['question_tag_' + syntax] = qword['tag'] if qword.has_key('fullform') and qword['fullform']: self.qattrs['question_fullform_' + syntax] = qword['fullform'][0] for syntax in selected_awords.keys(): if selected_awords[syntax].has_key('word'): self.aattrs['answer_word_' + syntax] = selected_awords[syntax]['word'] if selected_awords[syntax].has_key('tag'): self.aattrs['answer_tag_' + syntax] = selected_awords[syntax]['tag'] if selected_awords[syntax].has_key('fullform') and len(selected_awords[syntax]['fullform']) == 1: self.aattrs['answer_fullform_' + syntax] = selected_awords[syntax]['fullform'][0] # Forms question string and answer string out of grammatical elements and other strings. qstring = "" astring= "" # Format question string qtext = question.string for w in qtext.split(): if not qwords.has_key(w): qstring = qstring + " " + force_unicode(w) else: if qwords[w].has_key('fullform'): qstring = qstring + " " + force_unicode(qwords[w]['fullform'][0]) else: qstring = qstring + " " + force_unicode(w) qstring=qstring.replace(" -","-") qstring=qstring.replace(" .",".") try: answer_word = selected_awords[task]['word'] except KeyError: answer_word = False # print 'fail: ', question.qid # print ' task: ', task self.error = 'error' self.lemma = 'error in answer words: ' + question.qid return # self.lemma = question.qid answer_tag = selected_awords[task]['tag'] selected_awords[task]['fullform'][0] = 'Q' # Get lemma for contextual morfa # lemma is displayed as the 'task' word in parentheses after the question answer_word_el = Word.objects.get(id=answer_word) answer_tag_el = Tag.objects.get(id=answer_tag) self.lemma = answer_word_el.lemma self.tooltip_question_id = question.qid # Set tooltip translations transl = answer_word_el.translations2(language) # if len(transl) == 0: # transl = answer_word_el.translations2('nob') # Norwegian as default if len(transl) > 0: xl = transl[0] self.translations = xl.definition # if answer_word_el.pos == 'V': # self.wordclass = answer_word_el.wordclass # If the asked word is in Pl, generate nominal form if answer_tag_el.pos == "N": if qtype == "COLL-NUM": self.lemma = answer_word_el.lemma else: if answer_tag_el.number=="Sg" or answer_tag_el.case=="Ess" or answer_tag_el.case=="Nom": #was: qtype="N-NOM-PL" self.lemma = answer_word_el.lemma else: nplforms = Form.objects.filter(word__pk=answer_word, tag__string='N+Pl+Nom') if nplforms.count() > 0: self.lemma = nplforms[0].fullform else: self.lemma = answer_word_el.lemma + " (plural) fix this" if qtype == "ORD-NUM": self.lemma = answer_word_el.lemma if answer_tag_el.pos == "Pron": # Hide task word for Recipr and Refl if qtype in ["P-REFL", "P-RECIPR", "P-REL"]: self.lemma = False # Retrieve feedback information try: answer_word_form = Form.objects.exclude(dialects__dialect='NG')\ .filter(word__pk=answer_word, tag=answer_tag_el, dialects__dialect=self.dialect) answer_word_form = answer_word_form[0] except: answer_word_form = False if answer_word_form: self.get_feedback(answer_word_form, language) # Format answer string for w in atext.split(): if w.count("(") > 0: continue if not selected_awords.has_key(w) or not selected_awords[w].has_key('fullform'): astring = astring + " " + force_unicode(w) else: astring = astring + " " + force_unicode(selected_awords[w]['fullform'][0]) # Remove leading whitespace and capitalize. astring = astring.lstrip() qstring = qstring.lstrip() astring = astring[0].capitalize() + astring[1:] qstring = qstring[0].capitalize() + qstring[1:] qstring = qstring + "?" # Add dot if the last word is not the open question. if astring.count("!")==0 and not astring[-1]=="Q": astring = astring + "." self.question=qstring # Format answer strings for context q_count = astring.count('Q') if q_count > 0: astrings = astring.split('Q') if astrings[0]: self.answertext1 = astrings[0] if astrings[1]: self.answertext2 = astrings[1] # set correct and error values if correct_val: if correct_val == "correct": self.error="correct" # relax if userans_val in self.relaxings: self.is_relaxed = "relaxed" self.strict = 'Strict form' else: self.is_relaxed = "" if answer_word == False: self.lemma = '%s - error: %s' % (answer_word_el.lemma, question.qid) def vasta_is_correct(self,question,qwords,language,utterance_name=None): """ Analyzes the answer and returns a message. """ if not self.is_valid(): return None, None, None noanalysis=False fstdir = "/opt/smi/sme/bin" #fstdir = settings.FST_DIRECTORY fst = fstdir + "/ped-sme.fst" lo = "/opt/sami/xerox/c-fsm/ix86-linux2.6-gcc3.4/bin/lookup" # on victorio #lo="/Users/mslm/bin/lookup" # on Heli's machine lookup = " | " + lo + " -flags mbTT -utf8 -d " + fst # on Heli's machine #lookup2cg = " | /Users/pyry/gtsvn/gt/script/lookup2cg" # on Ryan's machine lookup2cg = " | /usr/local/bin/lookup2cg " # on victorio cg3 = "/usr/local/bin/vislcg3" preprocess = " | /opt/sami/cg/bin/preprocess " # on victorio #preprocess = " | /Users/mslm/main/gt/script/preprocess " dis_bin = "/opt/smi/sme/bin/sme-ped.cg3" # on victorio #dis_bin = "../sme/src/sme-ped.cg3" # on Heli's machine TODO: add to settings.py vislcg3 = " | " + cg3 + " --grammar " + dis_bin + " -C UTF-8" self.userans = self.cleaned_data['answer'] answer = self.userans.rstrip() answer = answer.lstrip() answer = answer.rstrip('.!?,') self.error = "error" qtext = question qtext = qtext.rstrip('.!?,') #logfile = open('/home/rusoahpa/rus_oahpa/rus_drill/vastaF_log.txt','w') host = 'localhost' port = 9000 # was: 9000, TODO - add to settings.py size = 1024 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.connect((host,port)) # on victorio sys.stdout.write('%') analysis = "" question_lookup = "echo \"" + qtext + "\"" + preprocess words = os.popen(question_lookup).readlines() for qword in words: # or qwords ? cohort="" w = qword.lstrip().rstrip() s.send(w) # on victorio cohort = s.recv(size) if not cohort or cohort == w: cohort = w + "\n" if cohort=="error": raise Http500 analysis = analysis + cohort if self.gametype=="sahka": analysis = analysis + "\"<^qdl_id>\"\n\t\"^sahka\" QDL " + utterance_name +"\n" else: analysis = analysis + "\"<^qst>\"\n\t\"^qst\" QDL\n" #logfile.write(analysis+"\n") data_lookup = "echo \"" + answer.encode('utf-8') + "\"" + preprocess words = os.popen(data_lookup).readlines() analyzed="" for w in words: w=w.strip() s.send(w) # on vic analyzed = analyzed + s.recv(size) s.send("q") # on vic s.close() except socket.error: # port 9000 not available => morph. analysis will be done by ped-sme.fst # analyse words in the question analysis = "" question_lookup = "echo \"" + qtext + "\"" + preprocess words = os.popen(question_lookup).readlines() for qword in words: # or qwords ? cohort="" w = qword.lstrip().rstrip() word_lookup = "echo \"" + force_unicode(w).encode('utf-8') + "\"" + lookup + lookup2cg # on Heli's machine morfanal = os.popen(word_lookup).readlines() for row in morfanal: row = row.strip() cohort = cohort + row + "\n" + "\t" if not cohort or cohort == w: cohort = w + "\n" if cohort=="error": raise Http500 analysis = analysis + cohort if self.gametype=="sahka": analysis = analysis + "\"<^qdl_id>\"\n\t\"^sahka\" QDL " + utterance_name +"\n" else: analysis = analysis + "\"<^qst>\"\n\t\"^qst\" QDL\n" #logfile.write(analysis+"\n") # analyse words in the answer data_lookup = "echo \"" + answer.encode('utf-8') + "\"" + preprocess words = os.popen(data_lookup).readlines() analyzed="" for w in words: w=w.strip() word_lookup = "echo \"" + force_unicode(w).encode('utf-8') + "\"" + lookup + lookup2cg # on Heli's machine morfanal = os.popen(word_lookup).readlines() ans_cohort="" for row in morfanal: row = row.strip() ans_cohort = ans_cohort + row + "\n" + "\t" analyzed = analyzed + ans_cohort # except socket.timeout: # raise Http404("Technical error, please try again later.") #logfile.write(analyzed+"\n") analysis = analysis + analyzed analysis = analysis + "\"<.>\"\n\t\".\" CLB" analysis = analysis.rstrip() analysis = analysis.replace("\"","\\\"") ped_cg3 = "echo \"" + analysis + "\"" + vislcg3 checked = os.popen(ped_cg3).readlines() wordformObj=re.compile(r'^\"<(?P.*)>\".*$', re.U) messageObj=re.compile(r'^.*(?P&(grm|err|sem)[\w-]*)\s*$', re.U) targetObj=re.compile(r'^.*\"(?P[\wáÁæÆåÅáÁšŠŧŦŋŊøØđĐžZčČ-]*)\".*dia-.*$', re.U) # Extract the lemma constantObj=re.compile(r'^.*\"\<(?P[\wáÁæÆåÅáÁšŠŧŦŋŊøØđĐžZčČ-]*)\>\".*$', re.U) diaObj=re.compile(r'^.*(?P&dia-[\w]*)\s*$', re.U) # Each wordform may have a set of tags. spelling = False msgstrings = {} diastring = "jee" lemma="" for line in checked: line = line.strip() #logfile.write(line+"\n") #Find the lemma first matchObj=constantObj.search(line) if matchObj: lemma = matchObj.expand(r'\g') #The wordform matchObj=wordformObj.search(line) if matchObj: wordform = matchObj.expand(r'\g') msgstrings[wordform] = {} #grammatical/semantic/other error matchObj=messageObj.search(line) if matchObj: msgstring = matchObj.expand(r'\g') if msgstring.count("spellingerror") > 0: spelling = True msgstrings[wordform][msgstring] = 1 #Store the baseform if tehre is dia-whatever matchObj=targetObj.search(line) if matchObj: msgstring = matchObj.expand(r'\g') msgstrings[wordform]['dia-target'] = msgstring msgstrings[wordform]['dia-lemma'] = lemma # What is the dia-tag? matchObj=diaObj.search(line) if matchObj: msgstring = matchObj.expand(r'\g') msgstrings[wordform][msgstring] = 1 diastring=msgstring msg=[] dia_msg = [] target = "" variable="" constant="" found=False #Interface language if not language: language = "nob" language = switch_language_code(language) #if language == "no" : language = "nob" #if language == "fi" : language = "fin" #if language == "en" : language = "eng" if not language in ["nob","sme","fin","eng","swe"]: language="nob" for w in msgstrings.keys(): if found: break for m in msgstrings[w].keys(): if spelling and m.count("spelling") == 0: continue m = m.replace("&","") if Feedbackmsg.objects.filter(msgid=m).count() > 0: msg_el = Feedbackmsg.objects.filter(msgid=m)[0] message = Feedbacktext.objects.filter(feedbackmsg=msg_el,language=language)[0].message message = message.replace("WORDFORM","\"" + w + "\"") msg.append(message) if not spelling: found=True break else: if m.count("dia-") == 0: msg.append(m) if not spelling: found=True break if m.count("dia-") > 0: dia_msg.append(m) if msgstrings[w].has_key('dia-target'): constant = msgstrings[w]['dia-lemma'] variable = msgstrings[w]['dia-target'] if msgstrings[w].has_key('dia-unknown'): constant = msgstrings[w]['dia-lemma'] variable = msgstrings[w]['dia-unknown'] #iscorrect is used only in logging iscorrect=False if not msg: self.error = "correct" iscorrect=True feedbackmsg=' '.join(msg) today=datetime.date.today() log = Log.objects.create(userinput=self.userans,feedback=feedbackmsg,iscorrect=iscorrect,\ example=question,game=self.gametype,date=today) log.save() variables = [] variables.append(variable) variables.append(constant) return msg, dia_msg, variables class VastaSettings(OahpaSettings): book = forms.ChoiceField(initial='all', choices=BOOK_CHOICES, widget=forms.Select) level = forms.ChoiceField(initial='1', choices=VASTA_LEVELS, widget=forms.Select) def __init__(self, *args, **kwargs): self.set_settings() self.set_default_data() self.default_data['gametype'] = 'qa' super(VastaSettings, self).__init__(*args, **kwargs) class VastaQuestion(OahpaQuestion): """ Questions for vasta """ select_words = select_words vasta_is_correct = vasta_is_correct def __init__(self, question, qwords, language, userans_val, correct_val, *args, **kwargs): self.init_variables("", userans_val, []) question_widget = forms.HiddenInput(attrs={'value' : question.id}) super(VastaQuestion, self).__init__(*args, **kwargs) maxlength=50 answer_size=50 self.fields['answer'] = forms.CharField(max_length = maxlength, \ widget=forms.TextInput(\ attrs={'size': answer_size, 'onkeydown':'javascript:return process(this, event, document.gameform);',})) self.fields['question_id'] = forms.CharField(widget=question_widget, required=False) self.qattrs= {} for syntax in qwords.keys(): qword = qwords[syntax] if qword.has_key('word'): self.qattrs['question_word_' + syntax] = qword['word'] if qword.has_key('tag') and qword['tag']: self.qattrs['question_tag_' + syntax] = qword['tag'] if qword.has_key('fullform') and qword['fullform']: self.qattrs['question_fullform_' + syntax] = qword['fullform'][0] # Forms question string and answer string out of grammatical elements and other strings. qstring = "" # Format question string qtext = question.string for w in qtext.split(): if not qwords.has_key(w): qstring = qstring + " " + force_unicode(w) else: if qwords[w].has_key('fullform'): qstring = qstring + " " + force_unicode(qwords[w]['fullform'][0]) else: qstring = qstring + " " + w # this is for -guovttos qstring=qstring.replace(" -","-"); qstring=qstring.replace("- ","-"); # Remove leading whitespace and capitalize. qstring = qstring.lstrip() qstring = qstring[0].capitalize() + qstring[1:] qstring = qstring + "?" self.question=qstring # In qagame, all words are considered as answers. self.gametype="vasta" self.messages, jee, joo = self.vasta_is_correct(qstring.encode('utf-8'), qwords, language) # set correct and error values if correct_val == "correct": self.error="correct" def sahka_is_correct(self,utterance,targets,language): """ Analyzes the answer and returns a message. """ if not self.is_valid(): return False if not self.cleaned_data.has_key('answer'): return qwords = {} # Split the question to words for analaysis. self.messages, self.dia_messages, self.variables = self.vasta_is_correct(utterance.utterance, None, language, utterance.name) #self.variables = [ "Kárášjohka" ] #self.dia_messages = [ "dia-unknown" ] if not self.messages: self.error = "correct" for answer in self.dia_messages: answer = answer.lstrip("dia-") if answer == "target": self.target = answer class SahkaSettings(OahpaSettings): #dialogue = forms.ChoiceField(initial='firstmeeting', choices=DIALOGUE_CHOICES, widget=forms.Select) def __init__(self, *args, **kwargs): self.set_settings() self.set_default_data() self.default_data['gametype'] = 'sahka' self.default_data['dialogue_id'] = '1' self.default_data['dialogue'] = 'firstmeeting' self.default_data['topicnumber'] = '0' self.default_data['image'] = 'sahka.png' self.default_data['wordlist'] = '' self.default_data['num_fields'] = '2' super(SahkaSettings, self).__init__(*args, **kwargs) # Link to grammatical explanation for each page self.grammarlinkssme = Grammarlinks.objects.filter(language="sme") self.grammarlinksno = Grammarlinks.objects.filter(language="no") def init_hidden(self, topicnumber, num_fields, dialogue, image, wordlist): # Store topicnumber as hidden input to keep track of topics. #print "topicnumber", topicnumber #print "num_fields", num_fields topicnumber = topicnumber num_fields = num_fields dialogue = dialogue image = image wordlist = wordlist class SahkaQuestion(OahpaQuestion): """ Sahka: Dialogue game """ select_words = select_words sahka_is_correct = sahka_is_correct vasta_is_correct = vasta_is_correct def __init__(self, utterance, qwords, targets, global_targets, language, userans_val, correct_val, *args, **kwargs): self.init_variables("", userans_val, []) utterance_widget = forms.HiddenInput(attrs={'value' : utterance.id}) super(SahkaQuestion, self).__init__(*args, **kwargs) if utterance.utttype == "question": maxlength=50 answer_size=50 self.fields['answer'] = forms.CharField(max_length = maxlength, \ widget=forms.TextInput(\ attrs={'size': answer_size, 'onkeydown':'javascript:return process(this, event, document.gameform);',})) self.fields['utterance_id'] = forms.CharField(widget=utterance_widget, required=False) self.global_targets = global_targets #print self.global_targets self.utterance ="" self.qattrs={} if utterance: self.utterance_id=utterance.id #self.utterance=utterance.utterance # Forms question string and answer string out of grammatical elements and other strings. qstring = "" # Format question string qtext = utterance.utterance for w in qtext.split(): if not qwords.has_key(w): qstring = qstring + " " + force_unicode(w) self.qattrs['question_fullform_' + w] = force_unicode(w) else: if qwords[w].has_key('fullform'): qstring = qstring + " " + force_unicode(qwords[w]['fullform'][0]) self.qattrs['question_fullform_' + w] = qwords[w]['fullform'][0] else: qstring = qstring + " " + w self.qattrs['question_fullform_' + w] = w # this is for -guovttos qstring=qstring.replace(" -","-"); qstring=qstring.replace("- ","-"); # Remove leading whitespace and capitalize. qstring=qstring.replace(" .","."); qstring=qstring.replace(" ?","?"); qstring=qstring.replace(" !","!"); qstring = qstring.lstrip() if len(qstring)>0: qstring = qstring[0].capitalize() + qstring[1:] self.utterance=qstring self.target="" self.constant="" self.dia_messages = "" self.gametype="sahka" self.variables = [] self.variables.append("") self.variables.append("") self.sahka_is_correct(utterance,targets,language) if self.target: variable="" constant="" if utterance.links.filter(target=self.target).count()>0: variable = utterance.links.filter(target=self.target)[0].variable if variable: self.qattrs['target_' + variable] = self.variables[0] self.global_targets[variable] = { 'target' : self.variables[0] } constant = utterance.links.filter(target=self.target)[0].constant if constant: self.qattrs['target_' + constant] = self.variables[1] self.global_targets[constant] = { 'target' : self.variables[1] } for t in self.global_targets.keys(): if not self.qattrs.has_key(t): self.qattrs['target_' + t] = self.global_targets[t]['target'] #self.error="correct" self.errormsg = "" if correct_val == "correct": self.error="correct" ########### ## Vasta-S (Cealkka) ########### def cealkka_is_correct(self,question,qwords,awords,language,question_id=None): #was: question_id=None """ Analyzes the answer and returns a message. """ if not self.is_valid(): return None, None, None noanalysis=False fstdir = "/opt/smi/sme/bin" #fstdir = settings.FST_DIRECTORY fst = fstdir + "/ped-sme.fst" lo = "/opt/sami/xerox/c-fsm/ix86-linux2.6-gcc3.4/bin/lookup"# on victorio #lo="/Users/mslm/bin/lookup" # on Heli's machine lookup = " | " + lo + " -flags mbTT -utf8 -d " + fst # on Heli's machine lookup2cg = " | /usr/local/bin/lookup2cg " # on victorio cg3 = "/usr/local/bin/vislcg3" preprocess = " | /opt/sami/cg/bin/preprocess " # on victorio #preprocess = " | /Users/mslm/main/gt/script/preprocess " # on Heli's machine dis_bin = "/opt/smi/sme/bin/sme-ped.cg3" # on victorio #dis_bin = "/Users/mslm/main/ped/sme/src/sme-ped.cg3" # on Heli's machine TODO: add to settings.py vislcg3 = " | " + cg3 + " --grammar " + dis_bin + " -C UTF-8" self.userans = self.cleaned_data['answer'] answer = self.userans.rstrip() answer = answer.lstrip() answer = answer.rstrip('.!?,') #print answer self.error = "error" qtext = question qtext = qtext.rstrip('.!?,') #logfile = open('/home/rusoahpa/rus_oahpa/rus_drill/vastas_log.txt', 'w') host = 'localhost' port = 9000 # was: 9000, TODO - add to settings.py size = 1024 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.connect((host,port)) # on vic sys.stdout.write('%') analysis = "" data_lookup = "echo \"" + qtext + "\"" + preprocess words = os.popen(data_lookup).readlines() print question_id #print words #print qwords for word in words: w="" cohort="" print word # All the words will go through morph.analyser, even if they have a tag-attribute already. We do it to avoid problems with compound words. w = force_unicode(word).encode('utf-8') w=w.lstrip().rstrip() s.send(w) # on victorio cohort = s.recv(size) analysis = analysis + cohort #logfile.write(analysis+"\n") print analysis ### Lemmas and POS tags of task words are gathered into the variables ### tasklemmas and taskpos respectively. Tasklemmas and taskpos will be ### sent to CG together with the morph. analysed question and answer. tasklemmas = "" for aword in awords: print aword #logfile.write(aword) if aword.has_key('taskword') and aword['taskword']: tlemma = aword['fullform'] tlemma = force_unicode(tlemma).encode('utf-8') tlemma = tlemma.strip() print tlemma #logfile.write(tlemma+" ") tasktag = Tag.objects.filter(id=aword['tag']) tasktagstring = tasktag[0].string taskpos = tasktag[0].pos ttag = tasktagstring.replace("+"," ") print ttag #logfile.write(ttag+"\n") s.send(tlemma) # on vic word_lookup = s.recv(size) # on vic #logfile.write(word_lookup) ans_cohort="" #print rows rows = word_lookup.split("\n") # on vic morfanal = "" for row in rows: ans_cohort = ans_cohort + row #logfile.write(row + "\n") malemmas = row.split("\"") if row: malemma = malemmas[1] malemma_without_hash = malemma.replace('#','') taglist = ttag.split() tag_match = 1 for entag in taglist: if entag not in row: tag_match = 0 if tag_match and tlemma == malemma_without_hash: # 'Sg Nom' or 'V Inf' is not enough - exact tag sequence needed, and also need to compare the primary form to the analysed word, to resolve ambiguities print malemmas #logfile.write(malemma+"\n") print malemma print malemma_without_hash tasklemmas = tasklemmas + "\n\t\"" + malemma + "\" "+taskpos morfanal = morfanal + ans_cohort # END analysis = analysis + "\"<^vastas>\"\n\t\"^vastas\" QDL " + question_id + " " + tasklemmas + "\n" ##### print analysis #logfile.write(analysis) data_lookup = "echo \"" + force_unicode(answer).encode('utf-8') + "\"" + preprocess word = os.popen(data_lookup).readlines() #print word analyzed="" for c in word: c=c.strip() print c s.send(c) # on vic analyzed = analyzed + s.recv(size) s.send("q") # on vic s.close() # on vic except socket.error: analysis = "" data_lookup = "echo \"" + qtext + "\"" + preprocess words = os.popen(data_lookup).readlines() print question_id #print words #print qwords for word in words: w="" cohort="" print word # All the words will go through morph.analyser, even if they have a tag-attribute already. We do it to avoid problems with compound words. w = force_unicode(word).encode('utf-8') w=w.lstrip().rstrip() word_lookup = "echo \"" + force_unicode(w).encode('utf-8') + "\"" + lookup + lookup2cg # on Heli's machine morfanal = os.popen(word_lookup).readlines() for row in morfanal: cohort = cohort + row #print cohort analysis = analysis + cohort tasklemmas = "" for aword in awords: print aword #logfile.write(aword) if aword.has_key('taskword') and aword['taskword']: tlemma = aword['fullform'] tlemma = force_unicode(tlemma).encode('utf-8') tlemma = tlemma.strip() print tlemma #logfile.write(tlemma+" ") tasktag = Tag.objects.filter(id=aword['tag']) tasktagstring = tasktag[0].string taskpos = tasktag[0].pos ttag = tasktagstring.replace("+"," ") print ttag #logfile.write(ttag+"\n") ans_cohort = "" word_lookup = "echo \"" + tlemma + "\"" + lookup + lookup2cg # on Heli's machine rows = os.popen(word_lookup).readlines() morfanal = "" for row in rows: ans_cohort = ans_cohort + row #logfile.write(row + "\n") malemmas = row.split("\"") if row: malemma = malemmas[1] malemma_without_hash = malemma.replace('#','') taglist = ttag.split() tag_match = 1 for entag in taglist: if entag not in row: tag_match = 0 if tag_match and tlemma == malemma_without_hash: # 'Sg Nom' or 'V Inf' is not enough - exact tag sequence needed, and also need to compare the primary form to the analysed word, to resolve ambiguities print malemmas #logfile.write(malemma+"\n") print malemma print malemma_without_hash tasklemmas = tasklemmas + "\n\t\"" + malemma + "\" "+taskpos morfanal = morfanal + ans_cohort # END analysis = analysis + "\"<^vastas>\"\n\t\"^vastas\" QDL " + question_id + " " + tasklemmas + "\n" # analyse the user's answer data_lookup = "echo \"" + force_unicode(answer).encode('utf-8') + "\"" + preprocess word = os.popen(data_lookup).readlines() #print word analyzed="" for c in word: c=c.strip() word_lookup = "echo \"" + force_unicode(c).encode('utf-8') + "\"" + lookup + lookup2cg # on Heli's machine morfanal = os.popen(word_lookup).readlines() ans_cohort="" for row in morfanal: ans_cohort = ans_cohort + row analyzed = analyzed + ans_cohort #except socket.timeout: #raise Http404("Technical error, please try again later.") analysis = analysis + analyzed analysis = analysis + "\"<.>\"\n\t\".\" CLB" analysis = analysis.rstrip() analysis = analysis.replace("\"","\\\"") print analysis #logfile.write(analysis) ped_cg3 = "echo \"" + analysis + "\"" + vislcg3 checked = os.popen(ped_cg3).readlines() #print checked wordformObj=re.compile(r'^\"<(?P.*)>\".*$', re.U) messageObj=re.compile(r'^.*(?P&(grm|err|sem)[\w-]*)\s*$', re.U) targetObj=re.compile(r'^.*\"(?P[\wáÁæÆåÅáÁšŠŧŦŋŊøØđĐžZčČ-]*)\".*dia-.*$', re.U) # Extract the lemma constantObj=re.compile(r'^.*\"\<(?P[\wáÁæÆåÅáÁšŠŧŦŋŊøØđĐžZčČ-]*)\>\".*$', re.U) diaObj=re.compile(r'^.*(?P&dia-[\w]*)\s*$', re.U) # Each wordform may have a set of tags. spelling = False msgstrings = {} diastring = "jee" lemma="" for line in checked: line = line.strip() #Find the lemma first matchObj=constantObj.search(line) if matchObj: lemma = matchObj.expand(r'\g') #The wordform matchObj=wordformObj.search(line) if matchObj: wordform = matchObj.expand(r'\g') msgstrings[wordform] = {} #grammatical/semantic/other error matchObj=messageObj.search(line) if matchObj: msgstring = matchObj.expand(r'\g') if msgstring.count("spellingerror") > 0: spelling = True msgstrings[wordform][msgstring] = 1 #Store the baseform if there is dia-whatever matchObj=targetObj.search(line) if matchObj: msgstring = matchObj.expand(r'\g') msgstrings[wordform]['dia-target'] = msgstring msgstrings[wordform]['dia-lemma'] = lemma # What is the dia-tag? matchObj=diaObj.search(line) if matchObj: msgstring = matchObj.expand(r'\g') msgstrings[wordform][msgstring] = 1 diastring=msgstring msg=[] dia_msg = [] target = "" variable="" constant="" found=False #Interface language if not language: language = "nob" language = switch_language_code(language) #if language == "no" : language = "nob" #if language == "fi" : language = "fin" #if language == "en" : language = "eng" if not language in ["nob","sme","fin","eng","swe"]: language="nob" for w in msgstrings.keys(): if found: break for m in msgstrings[w].keys(): if spelling and m.count("spelling") == 0: continue m = m.replace("&","") if Feedbackmsg.objects.filter(msgid=m).count() > 0: msg_el = Feedbackmsg.objects.filter(msgid=m)[0] message = Feedbacktext.objects.filter(feedbackmsg=msg_el,language=language)[0].message message = message.replace("WORDFORM","\"" + w + "\"") msg.append(message) if not spelling: found=True break else: if m.count("dia-") == 0: msg.append(m) if not spelling: found=True break if m.count("dia-") > 0: dia_msg.append(m) if msgstrings[w].has_key('dia-target'): constant = msgstrings[w]['dia-lemma'] variable = msgstrings[w]['dia-target'] if msgstrings[w].has_key('dia-unknown'): constant = msgstrings[w]['dia-lemma'] variable = msgstrings[w]['dia-unknown'] #iscorrect is used only in logging iscorrect=False if not msg: self.error = "correct" iscorrect=True feedbackmsg=' '.join(msg) today=datetime.date.today() log = Log.objects.create(userinput=self.userans,feedback=feedbackmsg,iscorrect=iscorrect,\ example=question,game=self.gametype,date=today) log.save() variables = [] variables.append(variable) variables.append(constant) return msg, dia_msg, variables class CealkkaSettings(OahpaSettings): book = forms.ChoiceField(initial='all', choices=BOOK_CHOICES, widget=forms.Select) level = forms.ChoiceField(initial='1', choices=VASTA_LEVELS, widget=forms.Select) lemmacount = forms.ChoiceField(initial='2', choices=VASTAS_NR_OF_TASKWORDS, widget=forms.Select) def __init__(self, *args, **kwargs): self.set_settings() self.set_default_data() self.default_data['gametype'] = 'cealkka', super(CealkkaSettings, self).__init__(*args, **kwargs) class CealkkaQuestion(OahpaQuestion): """ Questions for cealkka """ select_words = select_words cealkka_is_correct = cealkka_is_correct def __init__(self, question, qanswer, qwords, awords, dialect, language, userans_val, correct_val, *args, **kwargs): self.init_variables("", userans_val, []) self.dialect = dialect self.gametype = "cealkka" qtype=question.qtype atext = qanswer.string # print atext question_widget = forms.HiddenInput(attrs={'value' : question.id}) answer_widget = forms.HiddenInput(attrs={'value' : qanswer.id}) #was: qanswer.id super(CealkkaQuestion, self).__init__(*args, **kwargs) maxlength=50 answer_size=50 self.fields['question_id'] = forms.CharField(widget=question_widget, required=False) self.fields['answer_id'] = forms.CharField(widget=answer_widget, required=False) self.fields['answer'] = forms.CharField(max_length = maxlength, \ widget=forms.TextInput(\ attrs={'size': answer_size, 'onkeydown':'javascript:return process(this, event, document.gameform);',})) # Select words for the answer astring = "" print "awords that come in CealkkaQuestion as parameter: " print awords selected_awords = self.select_words(qwords, awords) awords = [] for token in atext.split(): # det här har jag (Heli) hittat på if token.isupper(): # added because of keyerror word = selected_awords[token] if word.has_key('fullform') and word['fullform']: word['fullform'] = force_unicode(word['fullform'][0]) else: word = {} word['fullform'] = token word['taskword'] = "" awords.append(word) astring=astring+" "+force_unicode(word['fullform']) astring = astring.lstrip() #print astring self.awords=awords relaxed = [] form_list=[] self.qattrs= {} self.aattrs = {} for syntax in qwords.keys(): qword = qwords[syntax] if qword.has_key('word'): self.qattrs['question_word_' + syntax] = qword['word'] if qword.has_key('tag') and qword['tag']: self.qattrs['question_tag_' + syntax] = qword['tag'] if qword.has_key('fullform') and qword['fullform']: self.qattrs['question_fullform_' + syntax] = qword['fullform'][0] for syntax in selected_awords.keys(): if selected_awords[syntax].has_key('word'): self.aattrs['answer_word_' + syntax] = selected_awords[syntax]['word'] if selected_awords[syntax].has_key('tag'): self.aattrs['answer_tag_' + syntax] = selected_awords[syntax]['tag'] if selected_awords[syntax].has_key('fullform') and len(selected_awords[syntax]['fullform']) == 1: self.aattrs['answer_fullform_' + syntax] = selected_awords[syntax]['fullform'][0] if selected_awords[syntax].has_key('taskword'): self.aattrs['answer_taskword_' + syntax] = selected_awords[syntax]['taskword'] # to track the taskword attribute print question.qid print self.awords # Forms question string and answer string out of grammatical elements and other strings. qstring = "" # Format question string qtext = question.string for w in qtext.split(): if not qwords.has_key(w): qstring = qstring + " " + force_unicode(w) else: if qwords[w].has_key('fullform'): qstring = qstring + " " + force_unicode(qwords[w]['fullform'][0]) else: qstring = qstring + " " + w # this is for -guovttos qstring=qstring.replace(" -","-"); qstring=qstring.replace("- ","-"); # Remove leading whitespace and capitalize. qstring = qstring.lstrip() qstring = qstring[0].capitalize() + qstring[1:] qstring = qstring + "?" self.question=qstring self.gametype="cealkka" self.messages, jee, joo = self.cealkka_is_correct(qstring.encode('utf-8'), qwords, awords, language, question.qid) # was astring, awords for VastaS before # set correct and error values if correct_val == "correct": self.error="correct"