//////////////////////////////
//This file is part of the projectLK
//////////////////////////////
//name: query.js
//last modified/version: 14.06.2009
//core
//description: Engine and global functions for queries.
//Author: David Glenck
//Licence: GNU General Public Licence (see licence.txt in Mainfolder)
//////////////////////////////

//////////
//content:
//  Engine
//  Check Result
//  Other
//////////

//////////
//ENGINE
//////////

var q_el=new Object();
var qe={
  ////Execute
  //Start a query
  start: function() {
    this.gone=new Object;
    this.that=new Object;
    this.come=new Object;
    req('get_query',{queryid:here.queryid},'qe.refreshqinfo(info)');
  },
  refreshqinfo: function(info) {
    try{
      this.mode=info.mode;
      this.total=parseFloat(info.total);
      this.done=parseFloat(info.done);
      this.correct=parseFloat(info.correct);
      this.wrong=info.wrong;
      if(info.wrong.id==null) { this.wrong={id: new Object, answer: new Object}; }
      this.querylastid=this.that.id;
      this.that=new Object;
      this.come=new Object;
      if(info.word) {
        this.that.word=info.word.question[0];
        this.that.answer=info.word.answer[0];
        this.that.id=info.word.id[0];
        this.that.id=info.word.id[0];
        this.come.word=info.word.question[1];
        this.come.answer=info.word.answer[1];
        this.come.id=info.word.id[1];
      }
      this.inidisp();
      this.display(); 
    } catch(err) { errg('[query-01]'+err); }
  },
  //send an answer
  send: function() {
    try{
      this.hisanswer=clean($('q_answer').value);
      this.result=wordcheck(this.hisanswer, this.that.answer);
      this.done+=1;
      this.correct+=parseFloat(this.result);
      req('update_active',{queryid:here.queryid, result: this.result, wordid: this.that.id, nextid: this.come.id, answer: this.hisanswer, uncorr: 0},'qe.setnext(info,1)');
    } catch(err) { errg('[query-02]'+err); }
    return false;
  },
  //update last answer
  updatelast: function() {
    try{
      req('get_query',{queryid:here.queryid, wordid:this.gone.id},'qe.updategone(info)');
    } catch(err) { errg('[query-021]'+err); }
  },
  updategone: function(info) {
    this.gone.word=info.word.question?info.word.question[0]:null;
    this.gone.answer=info.word.answer?info.word.answer[0]:null;
  },
  //skip a question
  skip: function() {
    try{
      req('update_active',{queryid:here.queryid, wordid: this.that.id, nextid: this.come.id, uncorr: 1},'qe.setnext(info,0)');
    } catch(err) { errg('[query-03]'+err); }
    return false;
  },
  //load next question
  setnext: function(info,disp) {
    try{
      this.gone.word=this.that.word;
      this.gone.answer=this.that.answer;
      this.gone.id=this.that.id;
      this.that.word=this.come.word;
      this.that.answer=this.come.answer;
      this.that.id=this.come.id;
      if(info.word!=null) {
        this.gone.group=info.oldgroup;
        this.come.word=info.word.question?info.word.question[0]:null;
        this.come.answer=info.word.answer?info.word.answer[0]:null;
        this.come.id=info.word.id?info.word.id[0]:null;
      }
      if(this.result==0) { 
        this.wrong.id[this.wrong.id.length]=this.gone.id; 
        this.wrong.answer[this.gone.id]=this.hisanswer; 
      }
      this.display(disp);
    } catch(err) { errg('[query-04]'+err); }
  },
  showres: function() {
    this.inidisp();
    this.display();
  },
  //Change mode
  chmod: function(what) {
    req('change_mode',{chwhat: what, queryid:here.queryid},'qe.start()')
  },
  //Get direction of query
  getquerydir: function(link) {
    if(link==null) {link=' &gt; ';}
    var mode=this.mode;
    if(mode==0 || mode==2) {
      return la.lang+link+la.fore;
    } else if(mode==1 || mode==3) {
      return la.fore+link+la.lang;
    } else if(mode==4) {
      return '';
    }
  },
  //Correct an answer
  correction: function() {
    qe.updatelast(); //Update last word (if edited)
    req('correction',{corrid:this.gone.id, queryid:here.queryid, ngroup:this.gone.group},'qe.correctit()');
  },
  correctit: function() {
    this.correct+=1;
    this.result=1;
    this.display(1);
  },
  ////Display
  display: function(showres)  {
    try{
      this.hidem();
      write('done',this.done);
      write('correct',this.correct);
      write('correct',this.correct);
      write('thisword',this.that.word);
      write('lastword',this.gone.word);
      write('lastresult',this.gone.answer);
      write('lastanswer',this.hisanswer);
      var qans=$('q_answer');
      if(qans) {
        qans.value='';
        if(!Prototype.Browser.IE) { qans.focus(); }
      }
    } catch(err) { errg('[query-05.0]'+err); }
    try {
      if(this.total>this.done) { write('thisword',this.that.word); }
      //resultdiv
      if (showres==1) {
        if(this.result) { write('result',la.corr); } else { write('result',la.wrong); }
        $('resultdiv').style.display="block";
      } else { $('resultdiv').style.display="none"; }
    } catch(err) { errg('[query-05.1]'+err); }
  },
  inidisp: function() {
    try{
      if(this.total<=this.done) { withall('run',0); withall('fin',1); }
      else { withall('run',1); withall('fin',0); }
      write('total',this.total);
      var percent=Math.round(this.correct/this.total*1000000)/10000;
      write('percent',percent.toString());
      write('qquestion',la.qquestion[this.mode]);
      write('qanswer',la.qanswer[this.mode]); 
      write('wrong',la.wrongansws+': <a href="javascript: void(0)" onclick="javascript: qe.showwrong()">'+la.show+'</a>')
      //Show Links to change mode
      write('modeinfo',la.querymode+': '+la.modeinfo[this.mode]+' <a href="javascript: void(0)" id="chquerymodebutton" class="s -m0 -m1" onclick="javascript: qe.chmod(0)">'+la.change+'</a>');
      write('modeinfodir',this.getquerydir()+' <a href="javascript: void(0)" id="chquerydirbutton" class="s" onclick="javascript: qe.chmod(1)">'+la.change+'</a>');
      this.hidem();
    } catch(err) { errg('[query-06]'+err); }
  },
  //shows wrong answers
  showwrong: function() {
    if(this.mode==4) { this.getnames(); }
    else { req('get_words',{'wordid[]': this.wrong.id, nolimit:1},'qe.dispwrong(info);'); }
  },
  dispwrong: function(info) {
    try{
      
      var out='<table id="wordlist">';
      if(this.mode==4) {
        out+='<tr class="tabhead"><td>'+la['person']+'</td><td>'+la['form']+'</td><td>'+la['verb']+'</td><td>'+la['wrongansw']+'</td></tr>';
        for(i=0;i<info.count;i++) {
          out+='<tr>';
            out+='<td>'+this.personnames[info.personid[i]]+'</td>';
            out+='<td>'+this.formnames[info.formid[i]]+'</td>';
            out+='<td>'+info.kword[i]+'</td>';
            out+='<td>'+this.wrong.answer[info.id[i]]+'</td>';
          out+='</tr>';
        }        
      } else {
        out+='<tr class="tabhead"><td>'+la['lang']+'</td><td>'+la['fore']+'</td><td>'+la['wrongansw']+'</td></tr>';
        for(i=0;i<info.count;i++) {
          out+='<tr>';
            out+='<td>'+info.wordfirst[i]+'</td>';
            out+='<td>'+info.wordfore[i]+'</td>';
            out+='<td>'+this.wrong.answer[info.id[i]]+'</td>';
          out+='</tr>';
        }
      }
      out+='</table>';
      if(typeof(gui_wrong)=='function') { gui_wrong(out); }
    } catch(err) { errg('[query-08]'+err); }
  },
  //gets names of forms and persons if not already loaded
  getnames: function() {
    if(this.formnames==null) { req('get_form',{'registerid':here.registerid},'qe.save(\'form\',info); qe.getnames()'); }
    else if(this.personnames==null) { req('get_person',{'registerid':here.registerid},'qe.save(\'person\',info); qe.getnames()'); }
    else { req('get_verbs',{'id[]': this.wrong.id, struc:1},'qe.dispwrong(info);'); }
  },
  save: function(what, info) {
    this[what+'names']=new Object;
    for(i=0;i<info.count;i++) {
      this[what+'names'][info[what+'id'][i]]=info[what+'name'][i];
    }
  },  
  //hides elements depending on keywords
  hidem: function() {
    try{
      //hide if every answer was correct
      var w=get_el('.-w');
      for(i=0;i<w.length;i++) { this.correct==this.done?w[i].hide():w[i].show(); }
      //show if answer was correct
      var r=get_el('.r');
      for(i=0;i<r.length;i++) { this.result==0?r[i].hide():r[i].show(); }
      //show if answer was incorrect
      var rr=get_el('.-r');
      for(i=0;i<rr.length;i++) { this.result?rr[i].hide():rr[i].show(); }
      //show if every question has been answerd
      var f=get_el('.f');
      for(i=0;i<f.length;i++) { this.total>this.done?f[i].hide():f[i].show(); }
      //hide if every question has been answerd
      var ff=get_el('.-f');      
      for(i=0;i<ff.length;i++) { this.total<=this.done?ff[i].hide():ff[i].show(); }
      //show only if no question has been answerd yet
      var s=get_el('.s');  
      for(i=0;i<s.length;i++) { this.done==0?s[i].show():s[i].hide(); }
      //Hide if mode is x
      var m=get_el('.-m'+this.mode,1);  
      for(i=0;i<m.length;i++) { m[i].hide(); }
    } catch(err) { errg('[query-09]'+err); }
  }
}

//////////
//CHECK RESULT
//////////

//function to match a stringa with a stringb (recursive)
//version 9.05.10.2
var last; //var to save the las char which matched
var laststringb;
function stringcheck(stringa, stringb) {
  res=1; i=0;
  maxlen=Math.max(stringa.length, stringb.length); 
  if(laststringb==stringb) { return 0; }  //prevent useless recursion
  else {
    laststringb=stringb;
    while(stringa.charAt(i)==stringb.charAt(i)) {    //try until mismatch
     last=stringa.charAt(i);
     if(stringb.charAt(i)=='*') { i=maxlen; break; }
     i++;
     if(i>=maxlen) { break; }
    }
    if(i<maxlen) {                     //find problem of mismatch
      stringa=stringa.substr(i);       //shorten strings to relevant parts
      stringb=stringb.substr(i);
      if(last==' ' && stringb.charAt(0)==' ') {    //if problem is whitespace
        res=stringcheck(stringa, stringb.substr(1));
      } else if(stringb.charAt(0)=='(' || stringb.charAt(0)=='[') {          //if problem is a bracket (bracket function)
        res=stringcheck(stringa, stringb.substr(1));  //try the same with no bracket
        if (res==0 && stringb.charAt(0)=='(') { 
          res=stringcheck(stringa, stringb.replace(/\([^\)]+\)/,''));   //try the same without bracket and content
        }                                                               //(bracket function only)
        part=stringb.substr(1);
        while (res==0) {               //try every part of the content seperatet by a slash (slash function)
          npart=part.replace(/^[^\)\/\]]+\//,'');
          if(part==npart) { break; }
          res=stringcheck(stringa, npart);
          part=npart;
        }
      } else if(stringb.charAt(0)=='-' && stringb.charAt(1)==')') {     //if problem is a hyphen before a closing bracket (hyphen function)
        part=stringb.charAt(2).toLowerCase()+stringb.substr(3);
        res=stringcheck(stringa, part);  //try with changed case of the first character
      } else if(stringb.charAt(0)==')' || stringb.charAt(0)==')') {     // if problem is a closing bracket just remove it
        res=stringcheck(stringa, stringb.substr(1));
      } else if(stringb.charAt(0)=='/') {     //if problem is a slash remove the rest of the brackets content (slash function)
        res=stringcheck(stringa, stringb.replace(/\/[^\)\]]+[\)|\]]/,''));
      } else if(stringb.charAt(0)=='*' || (stringb.charAt(0)==' ' && stringb.charAt(1)=='*')) { //if problem is a asterik (asterik function)
        if(stringa.charAt(0)!=null) { res=0; }  //if the other string is over here, the match is valid
      } else { res=0; }                //otherwise no luck
    }
    return res;
  }
}

//Matches worda with wordb - not communicative
function wordcheck(worda,wordb) {
  wordar=worda.split(',');
  wordbr=wordb.split(',');
  lenk=wordar.length;
  lenj=wordbr.length;
  var res;
  for(k=0;k<lenk;k++) {
    res=0;
    for(j=0;j<lenj;j++) {
      laststringb=null;
      if(stringcheck(trim(wordar[k]),trim(wordbr[j]))) { res=1; break; }
    }
    if(res==0) { break; }
  }
  return res;
}

//////////
//OTHER
//////////

//saves elements to array and loads them
function get_el(element, force) {
  if(!q_el[element] || force==1) { q_el[element]=$$(element); }
  return q_el[element];
}

//shows or hides elements
function withall(elements,bool) {
  var el=get_el('.q_'+elements);
  for(i=0;i<el.length;i++)  { (bool==1)?el[i].show():el[i].hide(); }
}

//write in all elements
function write(elements,text) {
  var el=get_el('.q_'+elements);
  for (i in el) { el[i].innerHTML=text; }
}

//changes from uppercase to lowercase and vise versa
function changeCase(strch) {
  res=strch.toUpperCase();
  if(res==strch) { res=strch.toLowerCase(); }
  return res;
}

//Cleans an input: removes whitespace
function clean(word) {
  word=word.replace(/\s+/g,' ');
  word=word.replace(/^ +/,'');
  word=word.replace(/ +$/,'');
  return word;
}

