# -*- coding: utf-8 -*-

from oahpa.drills.models import *
from oahpa.drills.forms import *
from django.db.models import Q, Count
from django.http import HttpResponse, Http404
from django.shortcuts import get_list_or_404, render_to_response
from django.core.exceptions import ObjectDoesNotExist
from random import randint
#from django.contrib.admin.views.decorators import _encode_post_data, _decode_post_data
import os
import re
import itertools

import settings

# DEBUG = open('/dev/ttys001', 'w')

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. <i> is accepted for <ï>, but
		not vice versa.
		
		E.g.:  *ååjmedïdh is not accepted for ååjmedidh, 
				... but ...
				*miele is accepted for mïele.
	"""
	relaxed = strict
	sub_str = lambda _string, _target, _sub: _string.replace(_target, _sub)
	
	relax_pairs = {
		# key: value
		# key is accepted for value
	    u'ø': u'ö',
	    u'ä': u'æ',
	    u'i': 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()
	permutations = itertools.chain(itertools.permutations(searches))
	perms_flat = sum([list(a) for a in permutations], [])
	
	# Individual possibilities
	relaxed_perms = [sub_str(relaxed, R, S) for S, R in perms_flat]
	
	# 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))
	return relaxed_perms

class Info:
	pass

class Game:
	def __init__(self, settings):
		self.form_list = []
		self.count = ""
		self.score = ""
		self.comment = ""
		self.settings = settings
		self.all_correct = ""
		self.show_correct = 0
		self.num_fields = 6
		self.global_targets = {}
		# .has_key deprecated, is there a way to use in with this?
		if not self.settings.has_key('gametype'):
			self.settings['gametype'] = "bare"
		
		if self.settings.has_key('semtype'):
			if self.settings['semtype'] == 'all':
				self.settings['semtype'] = self.settings['allsem']
			else:
				semtype = self.settings['semtype'][:]
				self.settings['semtype'] = []
				self.settings['semtype'].append(semtype)

	def new_game(self):
		self.form_list = []
		word_ids = []
		i = 1
		num = 0
		# if self.settings['pos'] == 'Pron':
			# print 'omg'
			# for i in range(self.num_fields):
				# db_info = {}
				# db_info['userans'] = ""
				# db_info['correct'] = ""
				
				# errormsg = self.get_db_info(db_info)

				# form, word_id = self.create_form(db_info, i, 0)
				# print form
		# else:

		# Use this to make sure that pronouns don't have repeated
		# pronouns
		existing_tags = []
		
		# Can this be changed? Self.create_form should go without fail.
		tries = 0
		maxtries = 40
		
		while i < self.num_fields and len(self.form_list) < 5 and tries < maxtries:
			tries += 1
			db_info = {}
			db_info['userans'] = ""
			db_info['correct'] = ""
			
			errormsg = self.get_db_info(db_info)
			
			if errormsg and errormsg == "error":
				# i = i+1
				continue
				# raise Http404(errormsg)
			
			form = None
			# TODO: find indexerror, is it here? need to find a way
			# to pass indexerror into http404 with useful meaning; qid
			# or whatever
			try:
				form, word_id = self.create_form(db_info, i, 0)
			except Http404, e:
				raise e
			except ObjectDoesNotExist:
				continue
						
			# Do not generate same question twice
			if word_id:
				num = num + 1
				if word_id in set(word_ids): continue
				else: word_ids.append(word_id)
		
			self.form_list.append(form)
			i = i+1
		
		# print len(self.form_list)
		if tries == maxtries:
			raise Http404('No questions were able to be generated.')
		if not self.form_list:
			# No questions found, so the quiz_id must have been bad.
			raise Http404('Invalid quiz id.')
		
	def search_info(self, reObj, string, value, words, t_type):
		matchObj = reObj.search(string)
		if matchObj:
			syntax = matchObj.expand(r'\g<syntaxString>')
			if not words.has_key(syntax):
				words[syntax] = {}
			
			words[syntax][t_type] = value
		return words
	
				
	def check_game(self, data=None):
		db_info = {}
		
		question_tagObj = re.compile(r'^question_tag_(?P<syntaxString>[\w\-]*)$', re.U)
		question_wordObj = re.compile(r'^question_word_(?P<syntaxString>[\w\-]*)$', re.U)
		question_fullformObj = re.compile(r'^question_fullform_(?P<syntaxString>[\w\-]*)$', re.U)
		answer_tagObj = re.compile(r'^answer_tag_(?P<syntaxString>[\w\-]*)$', re.U)
		answer_wordObj = re.compile(r'^answer_word_(?P<syntaxString>[\w\-]*)$', re.U)
		answer_fullformObj = re.compile(r'^answer_fullform_(?P<syntaxString>[\w\-]*)$', re.U)
		targetObj = re.compile(r'^target_(?P<syntaxString>[\w\-]*)$', re.U)
		
		# Collect all the game targets as global variables
		self.global_targets = {}
		
		# If POST data was data check, regenerate the form using ids.
		# This iterates through forms in list of forms
		for n in range (1, self.num_fields):
			db_info = {}
			qwords = {}
			awords = {}
			tmpawords = {}
			
			# This compiles a dictionary from all of the form fields
				# {u'answer': u'', 
				# u'userans': u'empty', 
				# u'correct': u'empty', 
				# u'tag_id': u'66', 
				# u'word_id': u'628'}
			
			for fieldname, value in data.items():
				# print >> DEBUG, d, value
				if fieldname.count(str(n) + '-') > 0:
					fieldname = fieldname.lstrip(str(n) + '-')
					qwords = self.search_info(question_tagObj, fieldname, value, qwords, 'tag')
					qwords = self.search_info(question_wordObj, fieldname, value, qwords, 'word')
					qwords = self.search_info(question_fullformObj, fieldname, value, qwords, 'fullform')
					
					tmpawords = self.search_info(answer_tagObj, fieldname, value, tmpawords, 'tag')
					tmpawords = self.search_info(answer_wordObj, fieldname, value, tmpawords, 'word')
					tmpawords = self.search_info(answer_fullformObj, fieldname, value, tmpawords, 'fullform')
					
					self.global_targets = self.search_info(targetObj, fieldname, value, self.global_targets, 'target')
					
					db_info[fieldname] = value
					
			
			
			# This appears to not be used for leksa and morfa
			# Or if it is to be used with morfa, last stanza has problem.
			# Furthermore, qwords has no keys, and thus doesn't iterate.
			for syntax in qwords.keys():
				if qwords[syntax].has_key('fullform'):
					qwords[syntax]['fullform'] = [qwords[syntax]['fullform']]
			
			# This also appears to not be used for leksa and morfa
			# Or else there's a problem in the initial forloop.
			# Dictionary here comes out empty.
			# tmpawords doesn't iterate here; no keys
			for syntax in tmpawords.keys():
				awords[syntax] = []
				info = {}
				if tmpawords[syntax].has_key('word'):
					info['word'] = tmpawords[syntax]['word']
					if tmpawords[syntax].has_key('tag'):
						info['tag'] = tmpawords[syntax]['tag']
					if tmpawords[syntax].has_key('fullform'):
						info['fullform'] = [ tmpawords[syntax]['fullform']]
					
					awords[syntax].append(info)
				# print info
			
			
			db_info['awords'] = awords
			db_info['qwords'] = qwords
			db_info['global_targets'] = self.global_targets
			
			new_db_info = {}
			
			# Generate possible answers for contextual Morfa.
			if self.settings.has_key('gametype') and self.settings['gametype'] == 'context':
				new_db_info = self.get_db_info(db_info)
			if not new_db_info:
				new_db_info = db_info
			form, word_id = self.create_form(new_db_info, n, data)
			if form:
				self.form_list.append(form)
	
	def get_score(self, data):
		
		# Add correct forms for words to the page
		if "show_correct" in data:
			self.show_correct = 1
			
			for form in self.form_list:
				form.set_correct()
				
				self.count = 2
		
		# Count correct answers:
		self.all_correct = 0
		self.score = ""
		self.comment = ""
		i = 0
		
		points = sum([1 for form in self.form_list if form.error == "correct"])
		
		if points == len(self.form_list):
			self.all_correct = 1
		
		if self.show_correct or self.all_correct:
			self.score = self.score.join([repr(i), "/", repr(len(self.form_list))])
		
		if (self.show_correct or self.all_correct) and not self.settings['gametype'] == 'qa' :
			if i == 2: i = 3
			if i == 1: i = 2
			if self.settings.has_key('language'):
				language = switch_language_code(self.settings['language'])
				
				com_count = Comment.objects.filter(Q(level=i) & Q(lang=language)).count()
				if com_count > 0:
					self.comment = Comment.objects.filter(Q(level=i) & Q(lang=language))[randint(0,com_count-1)].comment
		
		self.score = '%d/%d' % (points, len(self.form_list))


class BareGame(Game):
	
	casetable = {
		'NOMPL' : 'Nom', 
		'ATTR':'Attr', 
		'N-ILL':'Ill', 
		'N-ESS':'Ess', 
		'N-GEN':'Gen',
		'N-INE':'Ine', 
		'N-ELA':'Ela',
		'N-ACC':'Acc', 
		'N-COM':'Com',
		'': ''
	}
	
	def get_baseform(self, word_id, tag):
		
		basetag = None
		
		if tag.pos in ["N", "A", "Num", "Pron"]:
			if tag.number and tag.case != "Nom":
				tagstring = tag.pos + "+" + tag.number + "+Nom"
			else:
				tagstring = tag.pos + "+Sg" + "+Nom"
			if Form.objects.filter(word__pk=word_id, tag__string=tagstring).count() > 0:
				basetag = Tag.objects.filter(string=tagstring)[0]
		
		if tag.pos=="V":
			tagstring = "V+Inf"
			if Form.objects.filter(word__pk=word_id,tag__string=tagstring).count() > 0:
				basetag = Tag.objects.filter(string=tagstring)[0]
		
		return basetag
	
	def get_db_info(self, db_info):
		
		if self.settings.has_key('pos'):
			pos = self.settings['pos']

		
		syll = True and	self.settings.get('syll')	or   "All"
		case = True and	self.settings.get('case')	or   ""
		levels = True and  self.settings.get('level')   or   []
		adjcase = True and self.settings.get('adjcase') or   ""
		grade = True and   self.settings.get('grade')   or   ""
		source = ""
		
		mood, tense, attributive = "", "", ""
		num_bare = ""
		# if self.settings.has_key('syll'):
		# 	syll = self.settings['syll']
		# if self.settings.has_key('case'):
		# 	case = self.settings['case']
		# if self.settings.has_key('level'):
		# 	levels = self.settings['level']
		# if self.settings.has_key('adjcase'):
		# 	adjcase = self.settings['adjcase']
		if self.settings.has_key('book'):
			source = self.settings['book']
		if self.settings.has_key('num_bare'):
			num_bare = self.settings['num_bare']
		if self.settings.has_key('num_level'):
			num_level = self.settings['num_level']
		# if self.settings.has_key('grade'):
		# 	grade = self.settings['grade']
		pos_tables = {
			"N":	case,
			"A":	adjcase,
			"Num":  num_bare,
			"V":	""
		}
		
		sylls = []
		bisyl = ['2syll', 'bisyllabic']
		trisyl = ['3syll', 'trisyllabic']
		
		for item in syll:
			if item in bisyl:
				sylls.extend(bisyl)
			if item in trisyl:
				sylls.extend(trisyl)

		if pos == 'Pron':
			syll = ['']
		
		case = self.casetable[pos_tables[pos]]
		
		pos_mood_tense = {
			"PRS":	("Ind", "Prs"),
			"PRT":	("Ind", "Prt"),
			"COND":   ("Cond", "Prs"),
			"IMPRT":  ("Imprt", "Prs"),
			"POT":	("Pot", "Prs")
		}
		
		if pos == "V" and self.settings.has_key('vtype'):
			mood, tense = pos_mood_tense[self.settings['vtype']]
		
		
		number = ["Sg","Pl",""]
		if case == "Nom" and pos != "Pron": number = ["Pl"]
		
		# A+Sg+Nom
		# A+Comp+Sg+Nom
		# A+Superl+Sg+Nom
		# A+Attr
		if pos == "A":
			if case == "Attr":
				attributive = "Attr"
				grade = ""
				case = ""
				number = ""
			elif case in ["Comp", "Superl"]:
				grade = case
				case = "Nom" ; number = "Sg"
				attributive = ""				
		
		maxnum, i = 20, 0
		
		TAG_QUERY = Q(pos=pos)
		
		TAG_EXCLUDES = Q(personnumber="ConNeg") & Q(subclass="Prop")
		
		FORM_FILTER = False

		# Query filtering on words 
		# SUB_QUERY = Q(word__stem__in=sylls)
		SUB_QUERY = False

		if pos in ['Pron', 'N']:
			TAG_QUERY = TAG_QUERY & \
						Q(possessive="") & \
						Q(case=case)
		
		if pos == 'Pron':
			sylls = False

		if pos == 'V':
			TAG_QUERY =  TAG_QUERY & \
							Q(tense=tense) & \
							Q(mood=mood)
			sylls = False 
			
		if pos == 'A':
			base_set = Form.objects.filter(tag__string='A+Sg+Nom')
			TAG_QUERY = Q(attributive=attributive) & \
						Q(grade=grade) & \
						Q(case=case) & \
						Q(number=number)
			
			SUB_QUERY = Q(word__form__tag__attributive=attributive) & \
						Q(word__form__tag__grade=grade) & \
						Q(word__form__tag__case=case) & \
						Q(word__form__tag__number=number)
		
		# filter can include several queries, exclude must have only one
		# to work successfully
		tags = Tag.objects.filter(TAG_QUERY).exclude(personnumber='ConNeg').exclude(subclass='Prop')
		
		# TODO: fix this Http404 so it gives back clearer feedback
		
		if tags.count() == 0:
			error = "Morfa.get_db_info: Database is improperly loaded.\
					 No tags for the query were found.\n\n"
			error += repr((pos, case, tense, mood, attributive, grade, number))
			raise Http404(error)
		
		# print self.settings.get('pos'), self.settings.get('num_level'), str(self.settings.get('num_level'))
		
		if self.settings['pos'] == "Num":
			if self.settings.has_key('num_level') and str(self.settings['num_level']) == "1":
				smallnum = ["1","2","3","4","5","6","7","8","9","10"]
				QUERY = Q(pos__iexact=pos) & Q(presentationform__in=smallnum)
			else:
				QUERY = Q(pos__iexact=pos)
		else:
			# levels is not what we're looking for
			QUERY = Q(pos__iexact=pos) & Q(stem__in=syll)
			if source and source not in ['all', 'All']:
				QUERY = QUERY & Q(source__name=source)
				
		error = "Morfa.get_db_info: Database is improperly loaded.\
				 There are no Words, Tags or Forms, or the query\
				 is not returning any."
		NoWordsFound = Http404(error)
		
		try:
			# Previously the same Tag was being grabbed by the same query, twice
			# This should be easier.
			
			tag = tags.order_by('?')[0]
			
			if SUB_QUERY:
				no_form = True
				count = 0
				while no_form and count < 10:
					random_word = tag.form_set.filter(word__language=L1)\
										.filter(word__stem__in=sylls)\
										.order_by('?')[0].word
					random_form = random_word.form_set.filter(SUB_QUERY)\
										.filter(tag=tag)

					if random_form.count() > 0:
						random_form = random_form[0]
						no_form = False
						break
					else:
						count += 1
						continue
			else:
				no_form = True
				count = 0
				while no_form and count < 10:
					random_word = tag.form_set.filter(word__language='sma')
					if sylls:
						random_word = random_word.filter(word__stem__in=sylls)
					if random_word.count() > 0:
						random_form = random_word.order_by('?')[0]
						random_word = random_form.word
						no_form = False
						break
					else:
						count += 1
						continue
			db_info['word_id'] = random_word.id
			db_info['tag_id'] = tag.id
		except IndexError:
			wc = Word.objects.count()
			tc = Tag.objects.count()
			fc = Form.objects.count()
			wfc = Word.objects.filter(QUERY).count()
			tfc = Tag.objects.filter(TAG_QUERY).count()
			if 0 in [tc, wc, fc, wfc, tfc]:
				# print error
				error += "Word count (%d), Tag count (%d), Form count (%d), Words matching query (%d), Tags matching query (%d)." % (wc, tc, fc, wfc, tfc)
				error += "\n  Query: %s" % repr(QUERY)
				error += "\n  Tag Query: %s" % repr(TAG_QUERY)
				raise Http404(error)
		return		
	
	
	def create_form(self, db_info, n, data=None):
		language = self.settings['language']
		pos = self.settings['pos']
		
		if not db_info.has_key('word_id'):
			return None, None
		
		word_id = db_info['word_id']
		
		tag_id = db_info['tag_id']
		
		tag = Tag.objects.get(id=tag_id)
		
		if pos == 'Pron':
			form_list = Form.objects.filter(tag=tag)
		else:
			form_list = Form.objects.filter(word__id=word_id, tag=tag)
		
		if not form_list:
			raise Form.DoesNotExist
		
		correct = form_list[0]
		
		if pos in ['N', 'V', 'A']:
			word = Word.objects.get(Q(id=word_id))
			# Preserve number in nouns: Sg-Sg, Pl-Pl
		elif pos == 'Pron':
			word = correct.word
		
		# Get baseform, matching number; except for in essive where
		# there is no number, and with Nominative, where the test is
		# about turning nominative singular into nominative plural, 
		# thus all baseforms should be singular.

		if tag.case in ['Ess', 'Nom']:
			match_number = False
		else:
			match_number = True
		
		# Here we use Form.getBaseForm, because Word.baseform doesn't
		# pay attention to number. 
		# base_forms = [form.getBaseform(match_num=match_number) for form in form_list]
		base_forms = []
		for form in form_list:
			try:
				bf = form.getBaseform(match_num=match_number)
			except Form.DoesNotExist:
				raise ObjectDoesNotExist
			base_forms.append(bf)

		# Just in case multiple forms are returned; make them unique and
		# get the first. I feel like this may lead to problems
		# TODO: allomorphy in baseforms? What to do?
		
		baseform = list(set(base_forms))[0]
		
		target_key = switch_language_code(self.settings['language'][-3::])
		# if target_key == "sma":
		# 	translations = sum([w.word_answers for w in word.translations.all()],[])
		# else:
		translations = sum([w.word_answers for w in word.translations2(target_key).all()],[])
		
		fullforms = form_list.values_list('fullform',flat=True)
		morph = (MorfaQuestion(
					word=word,
					tag=tag,
					baseform=baseform, 
					correct=correct,
					fullforms=fullforms,
					translations=translations,
					question="",
					dialect="",
					language=language,
					userans_val=db_info['userans'],  # TODO: userans not in use?
					correct_val=db_info['correct'],
					data=data,
					prefix=n)
				)
		return morph, word_id
		
	


class NumGame(Game):
	
	def get_db_info(self, db_info):
		""" Options supplied by views
			ord, card - obvious
			kl1 - easy clock (half hours only)
			kl2 - medium clock (quarter hours)
			TODO: kl3 - difficult clock (all numbers??)
		"""
		numeral=""
		num_list = []
		
		from random import choice
		
		if self.settings['gametype'] in ["ord", "card"]:
			random_num = randint(1, int(self.settings['maxnum']))
		elif self.settings['gametype'] in ["kl1", "kl2", "kl3"]:
			hour = str(randint(0, 23))
			if len(hour) == 1:
				hour = '0' + hour
			else:
				hour = str(hour)
			if self.settings['gametype'] == "kl1":
				min_options = ['00', '30']
				minutes = choice(min_options)
			elif self.settings['gametype'] == "kl2":
				min_options = ['00', '15', '30', '45']
				minutes = choice(min_options)
			elif self.settings['gametype'] == "kl3":
				mins = str(randint(0, 59))
				if len(mins) == 1:
					mins = '0' + mins
				minutes = mins
			random_num = '%s:%s' % (hour, minutes)
				
		if self.settings['gametype'] == "ord":
			db_info['numeral_id'] = str(random_num) + "."
		else:
			db_info['numeral_id'] = str(random_num)
		return db_info
		
	
	def create_form(self, db_info, n, data=None):
		
		if self.settings['gametype'] in ["ord", "kl1", "kl2", "kl3"]:
			language = L1
		else:
			#language=self.settings['numlanguage']
			language = L1
		numstring = ""
		
		# TODO: use settings.py for these. Perhaps abstract lookup calls
		# to some additional app outside of smadrill
		
		# Add generator call here
		# fstdir="/Users/pyry/gtsvn/gt/" + language + "/bin"
		# lookup = '/Users/pyry/bin/lookup'
		#lookup ="/Users/cipriangerstenberger/bin/lookup"

		if self.settings['gametype'] in ["ord", "card"]:
			fstfile = "sma-num.fst"
			q, a = 0, 1
		elif self.settings['gametype'] in ["kl1", "kl2", "kl3"]:
			fstfile = "iclock-sma.fst"

		# production paths
		fstdir="/opt/smi/" + language + "/bin"
		lookup = "/opt/sami/xerox/c-fsm/ix86-linux2.6-gcc3.4/bin/lookup"
		gen_norm_fst = fstdir + "/" + fstfile

		# TODO: uncomment dev stuff 
		# lookup = "/Users/pyry/bin/lookup"
		# gen_norm_fst = "/Users/pyry/gtsvn/gt/sma/bin/" + fstfile
		
		# os.popen stuff
		# gen_norm_lookup = "echo " + db_info['numeral_id'] + " | " + lookup + " -flags mbTT -utf8 -d " + gen_norm_fst
		# num_tmp = os.popen(gen_norm_lookup).readlines()
		
		import subprocess
		
		# Need to use subprocess.Popen, because there's a good chance
		# that a failed command results in victorio eating up memory

		gen_norm_command = [lookup, "-flags", "mbTT", "-utf8",  "-d", gen_norm_fst]
		

		num_proc = subprocess.Popen(gen_norm_command, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
		output, err = num_proc.communicate(input=db_info['numeral_id'] + '\n')
		num_tmp = output.splitlines()
		num_list = []
		for num in num_tmp:
			line = num.strip()
			line = line.replace(' ','')
			if line:
				nums = line.split('\t')
				num_list.append(nums[a].decode('utf-8'))
		try:
			numstring = num_list[0]
		except IndexError:
			error = "Morfa.NumGame.create_form: Database is improperly loaded, \
					 or Numra is unable to look up words."
			raise Http404(error)
		# form = (NumQuestion(db_info['numeral_id'],
		# 		numstring,
		# 		num_list,
		# 		self.settings['numgame'],
		# 		db_info['userans'],
		# 		db_info['correct'],
		# 		data,
		# 		prefix=n))
		form = (NumQuestion(
					numeral=db_info['numeral_id'],
					num_string=numstring,
					num_list=num_list,
					gametype=self.settings['numgame'],
					userans_val=db_info['userans'],
					correct_val=db_info['correct'],
					data=data,
					prefix=n)
				)
		
		return form, numstring


class QuizzGame(Game):
	
	def get_db_info(self, db_info):
		
		# levels = self.settings['level']
		semtypes = self.settings['semtype']
		geography = self.settings['geography']
		source = self.settings['source']
		maxnum, i = 20, 0
		
		while i < maxnum:
			i = i + 1
			
			source_language = self.settings['transtype'][0:3]
			target_language = self.settings['transtype'][-3::]
			QueryModel = Word
			QUERY = Q(semtype__semtype__in=semtypes) & Q(language=source_language)
			
			if geography:
				QUERY = QUERY & Q(geography=geography)
			
			# Excludes
			excl = 'exclude_' + self.settings['transtype']
			
			if source and source not in ['all', 'All']:
			#	s = Source.objects.get(name=source)
				source = [source]
				QUERY = QUERY & Q(source__name__in=source)
			
			# Annotating with count to filter out Word2nob with no Word
			# normally would use Wordnob.translations but appears not to
			# be in use in db. word_set__count won't work either.
			
			error = "QuizzGame.get_db_info: Database may be improperly loaded. \
			Query for semantic type %s and book %s returned zero results." % ((semtypes, source))
			
			# if QueryModel == Word:
			try:
				word_set = QueryModel.objects\
								.filter(wordtranslation__language=target_language)\
								.annotate(num_xlations=Count('wordtranslation'))\
								.filter(num_xlations__gt=0)\
								.filter(QUERY)\
								.exclude(semtype__semtype=excl)
				if not geography:
					word_set = word_set.exclude(semtype__semtype=['PLACES'])

				random_word = word_set.order_by('?')[0]
			except IndexError:
				if QueryModel.objects.filter(QUERY).count() == 0:
					raise Http404(error)
			
			db_info['word_id'] = random_word.id
			db_info['question_id'] = ""
			return db_info
			
	
	
	def create_form(self, db_info, n, data=None):
		tr_lemmas = []
		# This is producing an unnecessary query, but it takes a lot of work to switch this
		# to just passing a word model instead of the ID.
		# Ideally should pass the model, so there's no need to query it again.
		word_id = db_info['word_id']
		
		target_language = self.settings['transtype'][-3::]
		source_language = self.settings['transtype'][0:3]
				
		word = Word.objects.get(Q(id=word_id))
		
		# Database change means this is no longer needed 
		
		# synwords = WordTranslation.objects\
		# 			.filter(language=target_language)\
		# 			.filter(wordid=word.lemma)
		# print synwords
		# print 'synwords: ', `synwords`
		# print repr(word)
		# fail, check word to see what translations or words it has
		# at this point we shouldn't be getting word_ids that have fails
		# find synonymous words and pick them to the translations
		
		translations = word.wordtranslation_set.filter(language=target_language)
		tr_lemmas.extend([w.definition for w in translations])
		
		# tr_lemmas.extend([w.definition for w in WordTranslation])
		# for s in synwords:
		# 	target_key = self.settings['transtype'][-3::]
		# 	print s
		# 	if type(s) == Word:
		# 		translations = s.translations2(target_key).all()
		# 		trs = [w.definition for w in translations]
		# 	elif type(s) == WordTranslation:
		# 		translations = s.word
		# 		trs = [translations.lemma]
		# 		# trs = [w.lemma for w in translations]
		# 	for t in trs:
		# 		tr_lemmas.append(t)

		# Get correct answers; pick the first (oho!)
		# Need to not pick the first one.
		correct = ""
		preferred = False
		possible = False
		stat_pref = False
		tcomms = False
		if type(word) == Word:
			trans_obj = word.translations2(self.settings['transtype']).all()
			possible = [t.definition for t in trans_obj.filter(tcomm=False)]
			trans = [t.definition for t in trans_obj]
			
			tcomms = [t.definition for t in trans_obj.filter(tcomm=True)]
			stat_pref = [t.definition for t in trans_obj.filter(tcomm_pref=True)]
			
			if len(tcomms) > 0:
				preferred = [t.definition for t in trans_obj.filter(tcomm=False)]
			if not correct:
				if len(stat_pref) > 0:
					correct = stat_pref[:]
			# 	if not correct:
			# 		correct = preferred[:]
			# else:
			# 	if not correct:
			# 		correct = trans
		elif type(word) == WordTranslation:
			# Pick one
			# trans_obj = word.word_set.all()[0]
			# trans = trans_obj.lemma
			
			# Use all
			trans_obj = word.word
			trans = [trans_obj.lemma]
			if not correct:
				correct = trans
		
		question_list = []
		
		# cheat mode for us poor people who don't speak sørsamisk yet
		# but have to program. ;) 
		# if type(correct) == list:
		# 	print repr(word), ', '.join([c.encode('utf-8') for c in correct])
		# elif type(correct) in [unicode, str]:
		# 	print repr(word), correct.encode('utf-8')

		userans_val = ''
		try:
			userans_val = db_info['answer'].strip()
		except KeyError:
			userans_val = db_info['userans']
		
		form = (LeksaQuestion(
					tcomms,
					stat_pref,
					preferred,
					possible, 
					self.settings['transtype'],
					word,
					correct,
					tr_lemmas,
					question_list,
					userans_val,
					db_info['correct'],
					data,
					prefix=n,))
		return form, word.id
