Subversion Repositories wimsdev

Rev

Rev 13047 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.  3/5/2008 version 0.02 [added item 10]
  3.  18/5/2008 version 0.03 [added item 11]
  4.  19/5/2008 version 0.04 [added item 12,13,14,15]
  5.  12/2012 version 0.05 [added item 16...26]
  6.  5/2014 version 0.06 [ added item 27,28]
  7.  6/2016 version 0.07 [added item 29]
  8.  3/2018 version 0.08 [added item 30]
  9.  6/2017 version 0.09 [added item 32] modified item 24
  10.  this is all very premature !!! The naming needs to be adapted to f1,f2...f20
  11.  
  12.   1 science(t)  checks scientific notation 4e+4 --> 4*10^4              : returns modified t or "error"
  13.   2 check_o(t)  checks letter o instead of number 0                     : returns 0 or 1 (0=error,1=success)           
  14.   3 check_f(t)  checks parenthesis usage in functions sin()             : returns 0 or 1       
  15.   4 check_x(t)  checks usage of x as multiplication *                   : returns 0 or 1
  16.   5 specialroot(t)      converts sqrt[a](b) to b^(1/a)                          : returns modified t or "error"
  17.   6 speciallog(t)       converts log[a](b) to log(b)/(log(a))                   : returns modified t or "error"
  18.   7 nthroot(t)  converts root(b,a) to b^(1/a)                           : returns modified t or "error"
  19.   8 check_log_NaN(t)    checks negative numbers in log                          : returns 0 or 1
  20.   9 check_sqrt_NaN(t)   checks negative numbers in sqrt                         : returns 0 or 1
  21.  10 normalize(t)        converts accents to letters without...                  : returns modified t or "error"
  22.  11 prefix(t)           converts SI prefixes to powers of 10                    : returns modified t or "error"
  23.  12 check_s2(t) checks and corrects powers 10^01,10^0.1                 : returns modified t or "error"
  24.  13 arrows(t,arg1,arg2,arg3)
  25.         t is answer ; if needed "t" will be corrected for special sqrt[] and log[] syntax
  26.         arg1=switch:
  27.                 arg1=0  : converts ascii arrows to unified "->"
  28.                 arg1=1  : converts ascii arrows to unified "\u2192"
  29.                 arg1=2  : returns no arrows ,just the text after the last arrow
  30.                 arg1=3  : returns no arrows...the answer is an array
  31.                 arg1=4  : returns the answer ,checks on all steps if arg2 and "=" are present
  32.         arg2=x  : variable name in needed ($varlist?)
  33.         arg3=3  : amount -if any- of arrows...
  34.  
  35.  14 keywords(t) convert all keywords to  ' and '                        : returns modified t or "error"
  36.  15 upper_f(t)  converts all 'known' functions and 'and' to uppercase   : returns modified t or "error"
  37.  16 is_number(t)        checks if no text is present                            : returns 0 or 1  (0=error,1=success)
  38.  17 is_real_number(t)   checks if real number: no sqrt or e+ allowed                    : returns 0 or 1  (0=error,1=success)
  39.  18 make_description(list,cnt) converts wims item list into javascript array size "cnt" : returns array(cnt)
  40.  19 myConfirm(txt,reply,server,session,module,counter,color) will send answer to server...or not
  41.  20 nospace(string) returns string without spaces
  42.  21 singlespace(string) returns  string with multiple spaces collapsed (including trailing spaces; eg trim)
  43.  22 word2items(string) returns itemlist (not a js-array ) 1 2 3 -> 1,2,3
  44.  23 rawmath(string) returns modified string 4x -> 4*x  ; 4sin(3pi) -> 4*sin(3*pi)
  45.  24 words2string(words,separator) returs modified string 1 2 3 --> 1:2:3 or 1@2@3
  46.  25 wordcnt(string) || wordcount(string) returns amount of words " A   B  ABC     " = 3  [a space is not a word]
  47.  26 is_text(string) returns 0 if number are present in text
  48.  27 shuffle(array) : returns randomized array
  49.  28 randint(x1,x2) : returns random integer between x1 and x2
  50.  29 plusminus(t) : reforms the answer t : x= pm 5 or x= pm 6 (etc) into x=5 or x=-5 or x=6 or x=-6  : returns modified t or "error"  [pm -> \u00B1 can be used with mathmlinput app.]
  51.  30 disable_mathml_input(): called only in answer.phtml to disable some mathml formula$n with inputfields.
  52.  31 check_js_injection(reply) : checks for substring 'script>' in a reply (case / space insensitive, array or string-based reply)
  53. */
  54.  
  55. function disable_mathml_input(){
  56.     /* change to 'input' when wims_mathml changes... */
  57.     if( document.getElementsByTagName('textarea') != null ){
  58.         var len = document.getElementsByTagName('textarea').length;
  59.         for(var p= 0 ; p<len ;p++){
  60.             document.getElementsByTagName('textarea')[p].setAttribute('readonly','readonly');
  61.         };
  62.     };
  63. };
  64.  
  65. function shuffle(array) {
  66.     for (var i = array.length - 1; i > 0; i--) {
  67.         var j = Math.floor(Math.random() * (i + 1));
  68.         var temp = array[i];
  69.         array[i] = array[j];
  70.         array[j] = temp;
  71.     };
  72.     return array;
  73. };
  74.  
  75. function randint(min,max){return Math.floor(Math.random()*(max-min+1)+min);};
  76.  
  77.  
  78. function SetTexAppSize(){
  79.     if( document.getElementById('TexApp1') ){ // starts with 1 !!!!
  80.         var p = 1;var xsize,ysize;
  81.         while ( document.getElementById('TexApp'+p) ){
  82.             try{
  83.                 xsize = document.getElementById('TexApp'+p).getPrefferedWidth();
  84.                 ysize = document.getElementById('TexApp'+p).getPrefferedHeight();
  85.                 document.getElementById('TexApp'+p).width = xsize;
  86.                 document.getElementById('TexApp'+p).height = ysize;
  87.                 p++;
  88.             }catch(e){setAlarm("The resizing of the applet went wrong...<br />May be your java \"virtual machine\" is very slow in starting up...<br />Try a reload on the page ...<br />or try a different -more recent- browswer<br />Use the Oracle / SUN java plugin...the \"OpenJDK plugin (icedtea)\" is known to have some serious problems");return;}// problems on opera (bug)
  89.         };
  90.         if(document.getElementById('wait_for_applet')){
  91.             document.getElementById('wait_for_applet').style.display = "none";
  92.         };
  93.     };
  94. };
  95.  
  96. function setAlarm(txt){
  97.     var h = parseInt( (document.documentElement.clientHeight)/2);
  98.     var w = parseInt( (document.documentElement.clientWidth)/2 - 200);
  99.     var alarmbox = document.getElementById('alarmtext');
  100.     alarmbox.style.top = h+'px';
  101.     alarmbox.style.left = w+'px';
  102.     alarmbox.style.display = "block"
  103.     alarmbox.innerHTML=txt;
  104.     window.scrollTo(w,h-120);
  105.     setTimeout('resetAlarm()',4000);
  106. };
  107.  
  108. function check_js_injection(r){
  109.   r = r.toString().toLowerCase(); r = nospace(r);
  110.   return r.indexOf('script>');
  111. };
  112.  
  113. function myConfirm(txt,reply,server,session,module,counter,color){
  114.     if( check_js_injection(reply) > 0 ){setAlarm('@#! JAVASCRIPT !#@');return;}
  115.     reply=encodeURIComponent(reply);
  116. //    reply = reply.replace(/'/g,'%22'); // need to replace '  
  117.     reply = reply.replace(/'/g,"\\'"); // need to escape "
  118.     var h = parseInt( (document.documentElement.clientHeight)/2);
  119.     var w = parseInt( (document.documentElement.clientWidth)/2 - 200);
  120.     var alarmbox = document.getElementById('alarmtext');
  121.     alarmbox.style.top = h+'px';
  122.     alarmbox.style.left = w+'px';
  123.     alarmbox.style.display = "block";
  124.     window.scrollTo(w,h-120);
  125.     alarmbox.innerHTML=r0+'<br /><span style=\"color:red\"><tt>'+txt+'</tt></span><br />'+"<input type=\"button\" id=\"schaersvoorde_confirm_ok_button\" value="+r45+" onclick=\"javascript:document.getElementById(\'schaersvoorde_exercise\').setAttribute(\'style\',\'background-color:"+color+"\');if(xcalc_window != null ){ xcalc_window.close();};if( typeof popup !== 'undefined'){popup.close();};document.location.href = \'"+server+"?session="+session+"&module="+module+"&cmd=reply&reply"+counter+"="+reply+"\';\" />&nbsp;&nbsp;<input type=\"button\" id=\"schaersvoorde_confirm_nok_button\" value="+r46+" onclick=\"javascript:resetAlarm()\" \>"
  126. };
  127.  
  128. function resetAlarm(){
  129.     document.getElementById('alarmtext').style.display = "none";
  130. };
  131.  
  132. function science(t){// corrected: startvalue+3 != startvalu*10^3 :)
  133.     t=t.replace(/\*\*/g,'^');
  134.     t=t.replace(/x10/g,'*10')
  135.     e=t.indexOf('e');
  136.     if(e != -1){
  137.         cc=['0','1','2','3','4','5','6','7','8','9'];
  138.         var c0;var c1;var t0;var t1;var c;var a;var trouble=0;var s;
  139.         while(e!=-1){
  140.             t0=t.charAt(e-1);
  141.             t1=t.charAt(e+1);
  142.             t2=t.charAt(e+2);
  143.             c0=0;c1=0;
  144.             for(s=0;s<10;s++){a=cc[s];if(t0==a){c0=1;}}
  145.             for(s=0;s<10;s++){a=cc[s];if(t1==a){c1=1;}}
  146.             if(c0==1 && c1==1){t=t.replace('e','*10^');}
  147.             if(c0==1 && c1==0 && t1=="+"){t=t.replace('e+','*10^');}
  148.             if(c0==1 && c1==0 && t1=="-"){t=t.replace('e-','*10^-');}
  149.             if(c0==1 && c1==0 && t1==""){t=t.replace('e','E');}
  150.             t=t.replace('e','E');
  151.             e=t.indexOf('e');
  152.             trouble++;if(trouble>100){setAlarm(r20);t="error";return t;}
  153.         };
  154.         t=t.replace(/E/g,"e");
  155.         t=t.replace(/10\^0/g,"10^");
  156.     };
  157.     return t;
  158. };
  159.  
  160. function check_o(t){
  161.     var alfabet="abcdefghijklmonpqrstuvwxyz";
  162.     var Alfabet="ABCDEFGHIJKLMONPQRSTUVWXYZ";
  163.    
  164.     var dingen=['1','2','3','4','5','6','7','8','9','0','.','+','-','*','/','^','=',' '];
  165.     var ld=dingen.length;var t2;var d;var sa;
  166.     var os=['o','O'];var o;var trouble=0;
  167.     for(s=0;s<2;s++){
  168.         o=os[s];t1=t.indexOf(o)
  169.         while(t1!=-1){
  170.             if(t1<1){t2='a';}else{t2=t.charAt(t1-1);}
  171.             t3=t.charAt(t1+1);
  172.             if(t3!=" " && t2!=" "){
  173.                 if(alfabet.indexOf(t2)==-1 && Alfabet.indexOf(t2)==-1 && alfabet.indexOf(t3)==-1 && Alfabet.indexOf(t3)==-1){
  174.                     for(sa=0;sa<ld;sa++){
  175.                         d=dingen[sa];
  176.                         if(t3==d || t2==d){
  177.                             setAlarm(r5);return 0;
  178.                         };
  179.                     };
  180.                 };
  181.             };
  182.             t=t.replace(o,'0');t1=t.indexOf(o);
  183.             trouble++;if(trouble>200){setAlarm(r20);return 0;};
  184.         };
  185.     };
  186.     return 1;
  187. };
  188.  
  189. function check_f(t){
  190.     if(t.indexOf('^^') > 0 ){setAlarm(r48);return 0;};
  191.     t=t.replace(/log\[/g,'#');
  192.     t=t.replace(/sqrt\[/g,'#');
  193.     var ft;var ismatch;var fun;var F;var c0;var t1;
  194.     var functies=['log','ln','abs','sqrt','sin','cos','tan','atan','acos','sinh','cosh','tanh'];
  195.     ft=functies.length;var trouble=0;
  196.     var len = t.length;var fnd = 0;
  197.     var numbers="0123456789";
  198.     for(var s=0;s<ft;s++){
  199.         fun=functies[s];ismatch=t.indexOf(fun);F=fun.toUpperCase();c0=fun.length;
  200.         while(ismatch != -1 ){
  201.             c=c0+ismatch;t1=t.substring(c,c+1);
  202.             fnd = 0;
  203.             if( t1 == '^'){
  204.                 for(var r=c;r<len-1;r++){
  205.                     var c1 = t.charAt(r);
  206.                     var isnumber = numbers.indexOf(c1);
  207.                     var c2 = t.charAt(r+1);
  208.                     if( c2 == '(' && isnumber != -1){
  209.                         fnd = 1;
  210.                         break;
  211.                     }
  212.                 }
  213.             };
  214.             if(t1=='(' || (t1=='^' && fnd == 1) ){
  215.                 t=t.replace(fun,F);ismatch=t.indexOf(fun);
  216.             }
  217.             else
  218.             {
  219.                 setAlarm(r9);return 0;
  220.             }
  221.             trouble++;if(trouble>200){setAlarm(r20);return 0;}
  222.         };
  223.     };
  224.     return 1;
  225. };
  226.  
  227. function check_x(t){
  228.     var dingen=['1','2','3','4','5','6','7','8','9','0'];
  229.     var t2;var t3;var d;var chk;var trouble=0;
  230.     t1=t.indexOf('x');
  231.     /// tollerate: x1= x2= etc ---> t1>0
  232.     while(t1>0){
  233.         chk=0;
  234.         t2=t.charAt(t1-1);
  235.         t3=t.charAt(t1+1);
  236.         for(s=0;s<10;s++){
  237.             d=dingen[s];
  238.             if(t2==d){chk=chk+1;}if(t3==d){chk=chk+1;};
  239.         };
  240.         if(chk==2){setAlarm(r7);return 0;};
  241.         t=t.replace('x','*');t1=t.indexOf('x');
  242.         trouble++;if(trouble>100){setAlarm(r20);return 0;};
  243.     };
  244.     return 1;
  245. };
  246.  
  247. function specialroot(t){
  248.     var power;var sqrt;var begin;var end;var mod;var tot;var wait;var got;var chr;var t1;var t2;var t3;var t4;var test;var org;
  249.     t2=t.indexOf("](");if(t2==-1){setAlarm(r11);t="error";return t;}
  250.     org=t;t=t.replace(/sqrt\(/g,"SQRT(");
  251.     t=t.replace(/log\[/g,"LOG~");t=t.replace(/sqrt\[/g,"@[");test=t.replace(/[a-z]\[/g,"#");
  252.     if(test.indexOf("#")!=-1){setAlarm(r11);t="error"; return t;};
  253.     t2=t.indexOf("[");var trouble=0;
  254.     while(t2 != -1){
  255.         begin=t.indexOf("@");t2=t.indexOf("[");t3=t.indexOf("]");
  256.         if(t2==begin+1 && t3>t2){
  257.             power=t.substring(t2+1,t3);
  258.             if(power.length==0){setAlarm(r16);t="error";return t;};
  259.             if(power<2){setAlarm(r16);t="error";return t;}
  260.             t4="["+power+"]";t=t.replace(t4,'');
  261.             tot=t.length;wait=0;got=0;end=0;
  262.             for(s=begin;s<tot;s++){
  263.                 if(end==0){
  264.                     chr=t.charAt(s);
  265.                     if(chr=="("){wait=wait+1;};
  266.                     if(chr==")"){got=got+1;};
  267.                     if(got!=0){if(wait==got){end=s;};};
  268.                 };
  269.             };
  270.             begin=begin+2;
  271.             sqrt=t.substring(begin,end);
  272.             mod=(power % 2);
  273.             if(sqrt<0 && mod!=1){setAlarm(r16);t="error";return t;};
  274.             t=t.replace("@("+sqrt+")","("+sqrt+")^(1/("+power+"))");
  275.         }
  276.         else
  277.         {
  278.          t=t.replace("]","?");
  279.         };
  280.         trouble++;if(trouble>100){setAlarm(r20);t="error";return t;};
  281.     };
  282.     t=t.replace(/SQRT\(/g,"sqrt(");t=t.replace(/LOG~/g,"log[");t=t.replace(/~/g,"[");t=t.replace(/\?/g,"]");t=t.replace(/@/g,"sqrt");
  283.     return t;
  284. };
  285.    
  286. function speciallog(t){
  287.     var noemer;var teller;var begin;var end;var tot;var wait;var got;var chr;var t1;var t2;var t3;var t4;
  288.     t2=t.indexOf("](");if(t2==-1){setAlarm(r11);t="error";return t;}
  289.     t=t.replace(/log\(/g,'LOG(');
  290.     t=t.replace(/log/g,"@");
  291.     t2=t.indexOf("[");var trouble=0;
  292.     while(t2 != -1){
  293.         begin=t.indexOf("@");t3=t.indexOf("]");
  294.         if(t2==begin+1 && t3>t2){
  295.             grondtal=t.substring(t2+1,t3);
  296.             if(grondtal=="10"){setAlarm(r14);t="error";return t;}
  297.             if(grondtal=="e" || grondtal=='E'){setAlarm(r15);t="error";return t;}
  298.             t4="["+grondtal+"]";t=t.replace(t4,'');
  299.             tot=t.length;wait=0;got=0;end=0;
  300.             for(s=begin;s<tot;s++){
  301.                 if(end==0){
  302.                     chr=t.charAt(s);
  303.                     if(chr=="("){wait=wait+1;}
  304.                     if(chr==")"){got=got+1;}
  305.                     if(got!=0){if(wait==got){end=s;}}
  306.                 }
  307.             }
  308.             begin=begin+2;teller=t.substring(begin,end);
  309.             if(grondtal==teller){setAlarm(r17);}
  310.             t=t.replace("@("+teller+")","(~("+teller+")/~("+grondtal+"))");
  311.         }else{t=t.replace("[","%");}
  312.         t2=t.indexOf("[");
  313.         trouble++;if(trouble>100){setAlarm(r20);t="error";return t;}
  314.     }
  315.     t=t.replace(/\%/g,"[");t=t.replace(/~/g,"log");t=t.replace(/LOG\(/g,"log(");t=t.replace(/@/g,"log");
  316.     return t;
  317. }
  318.  
  319. function check_log_NaN(t){
  320.     t=t.replace(/log\(/g,'@(');if(t.indexOf('@')==-1){return 1;}
  321.     if(t.indexOf('--')!=-1 || t.indexOf('++')!=-1 ){setAlarm(r18);return 0;}
  322.     /* 3/2017 added ^ to dingen ; eval return 0 for eval(4^6) */
  323.     dingen=['^','@','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
  324.     begin=t.indexOf('@');var exp;var variable;var trouble=0;var sa;
  325.     while(begin != -1){
  326.         t1=t.indexOf('(');
  327.         t2=t.indexOf(')');
  328.         if(t1=begin+1 && t2>t1){
  329.             tot=t.length;wait=0;got=0;end=0;
  330.             for(s=begin;s<tot;s++){
  331.                 if(end==0){
  332.                     chr=t.charAt(s);
  333.                     if(chr=="("){wait=wait+1;}
  334.                     if(chr==")"){got=got+1;}
  335.                     if(got!=0){if(wait==got){end=s;}}
  336.                 }
  337.             }
  338.             begin=begin+2;exp=t.substring(begin,end);sa=0;variable=0;
  339.             while(sa<28){v=dingen[sa];w=exp.indexOf(v);if(w!=-1){sa=28;variable=1;}sa++;}
  340.             if(variable==0){test=eval(exp);if(test<=0){setAlarm(r16);return 0;}}
  341.             t=t.replace('@(','log(');begin=t.indexOf('@');
  342.         }else{return 1;}
  343.         trouble++;
  344.         if(trouble>100){setAlarm(r20);return 0;}
  345.     }
  346.     return 1;
  347. }
  348.  
  349. function check_sqrt_NaN(t){
  350.     t=t.replace(/sqrt\(/g,'@(');if(t.indexOf('@')==-1){return 1;}
  351.     if(t.indexOf('--')!=-1 || t.indexOf('++')!=-1 ){setAlarm(r18);return 0;}
  352.     dingen=['@','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
  353.     begin=t.indexOf('@');var exp;var variable;var trouble=0;var s;var sa;
  354.     while(begin != -1){
  355.         t1=t.indexOf('(');
  356.         t2=t.indexOf(')');
  357.         if(t1=begin+1 && t2>t1){
  358.             tot=t.length;wait=0;got=0;end=0;
  359.             for(s=begin;s<tot;s++){
  360.                 if(end==0){
  361.                     chr=t.charAt(s);
  362.                     if(chr=="("){wait=wait+1;}
  363.                     if(chr==")"){got=got+1;}
  364.                     if(got!=0){if(wait==got){end=s;}}
  365.                 }
  366.             }
  367.             begin=begin+2;exp=t.substring(begin,end);exp=exp.replace(/\ /g,'');sa=0;variable=0;
  368.             while(sa<27){v=dingen[sa];w=exp.indexOf(v);if(w!=-1){sa=27;variable=1;}sa++;}
  369.             if(variable==0){test=eval(exp);if(test<0){setAlarm(r16);return 0;}}
  370.             t=t.replace('@(','sqrt(');begin=t.indexOf('@');
  371.         }else{return 1;}
  372.         trouble++;
  373.         if(trouble>100){setAlarm(r20);return 0;}
  374.     }
  375.     return 1;
  376. }
  377.  
  378. function nthroot(t){
  379.     var test=t.replace(/root/g,'@');
  380.     if(test.indexOf('@')==-1){return t;}
  381.     var t1;var t2;var t3;var exp;var variable;
  382.     var under;var wait;var end;var got;var s;var trouble=0;
  383.     t=t.replace(/root/g,'@');var begin=t.indexOf('@');
  384.     var tot=t.length;
  385.     while(begin != -1){
  386.         t1=t.indexOf('(');
  387.         t2=t.indexOf(')');
  388.         if(t1=begin+1 && t2>t1){
  389.             wait=0;got=0;end=0;
  390.             for(s=begin;s<tot;s++){
  391.                 if(end==0){
  392.                     chr=t.charAt(s);
  393.                     if(chr=="("){wait=wait+1;}
  394.                     if(chr==")"){got=got+1;}
  395.                     if(got!=0){if(wait==got){end=s;}}
  396.                 }
  397.             }
  398.             under=t.substring(begin+2,end);
  399.             t3=under.indexOf(',');
  400.             if(t3==-1){t=t.replace("@("+under+")","sqrt%"+under+"#");}
  401.             else{
  402.                 variable=under.substring(0,t3);
  403.                 exp=under.substring(t3+1,end)
  404.                 if(exp.indexOf(',')!=-1 || variable.indexOf(',')!=-1 ){setAlarm(r20);t="error";return t;}
  405.                 t=t.replace("@("+under+")","%"+variable+"#^%1/%"+exp+"##");
  406.             }
  407.         }
  408.         else
  409.         {
  410.             t=t.replace('(','%');
  411.             t=t.replace(')','#');
  412.         }
  413.         tot=t.length;
  414.         begin=t.indexOf('@');
  415.         trouble++;if(trouble>100){setAlarm(r20);t="error";return t;}
  416.     }
  417.     t=t.replace(/\%/g,'(');
  418.     t=t.replace(/#/g,')');
  419.     return t;
  420. }
  421.  
  422. function normalize(t){
  423.     // we can't use lower.case() because of F(x)= x^123 + C :(
  424.     var accent_H = ['Æ','Ã','À','Ä','Â','É','È','Ë','Ê','Ã','ÃŒ','Ã','ÃŽ','Ó','Ã’','Ö','Ô','Ú','Ù','Ü','Û','Ç','²','³','¼','½','¾','ß'];
  425.     var normal_H = ['AE','A','A','A','A','E','E','E','E','A','I','I','I','O','O','O','O','U','U','U','U','C','^2','^3','0.25','0.5','0.75','S'];
  426.     var accent_L = ['ò','ó','ô','õ','ö','ø','ù','ú','û','ü','à','á','â','ã','ä','Ã¥','ç','è','é','ê','ë','ì','í','î','ï','ñ','æ'];
  427.     var normal_L = ['o','o','o','o','o','o','u','u','u','u','a','a','a','a','a','a','c','e','e','e','e','i','i','i','i','n','ae'];
  428.     var char_t;var s;var str_a;var str_n;var trouble=0;
  429.     for(s=0;s<accent_H.length;s++){
  430.         str_a=accent_H[s];
  431.         str_n=normal_H[s];
  432.         while(t.indexOf(str_a)!=-1){
  433.             t=t.replace(str_a,str_n);
  434.             trouble++;if(trouble>200){setAlarm(r20);t="error";return t;}
  435.         }
  436.     }
  437.     trouble=0;
  438.     for(s=0;s<accent_L.length;s++){
  439.         str_a=accent_L[s];
  440.         str_n=normal_L[s];
  441.         while(t.indexOf(str_a)!=-1){
  442.             t=t.replace(str_a,str_n);
  443.             trouble++;if(trouble>200){setAlarm(r20);t="error";return t;}
  444.         }
  445.     }
  446.     return t;
  447. }
  448.  
  449. function prefix(t){
  450.     // replace SI prefixes
  451.     // still no good: case sensitive !!! can not / will not do a lowercase on the student reply ...
  452.     var SI=['*10^-1','*10^1','*10^6','*10^12','*10^15','*10^18','*10^15','*10^12','*10^9','*10^6','*10^3','*10^2','*10^1','*10^-1','*10^-2','*10^-3','*10^-6','*10^-9','*10^-12','*10^-15','*10^-18'];
  453.     var VA1=['déci','déca','méga','téra','péta','exa','peta','tera','giga','mega','kilo','hecto','deca','deci','centi','milli','micro','nano','pico','femto','atto'];
  454.     var VA2=['Déci','Déca','Méga','Téra','Péta','Exa','Peta','Tera','Giga','Mega','Kilo','Hecto','Deca','Deci','Centi','Milli','Micro','Nano','Pico','Femto','Atto'];
  455.     var trouble=0;var l=VA1.length;var prefix1;var prefix2;var prefix3;var x1;var x2;var x3;var s;var number;var s1;var s2;var s3;var rep=0;var t;var x4;
  456.     for (s=0;s<l;s++){
  457.         number=SI[s];prefix1=VA1[s];prefix2=VA2[s];prefix3=prefix1.toUpperCase();x1=t.indexOf(prefix1);x2=t.indexOf(prefix2);x3=t.indexOf(prefix3)
  458.         while(x1 != -1 || x2 !=-1 || x3 !=-1){
  459.             rep=0;s1=t.indexOf('*'+prefix1);s2=t.indexOf('*'+prefix2);s3=t.indexOf('*'+prefix3);
  460.             if(s1 != -1){t=t.replace('*'+prefix1,number);rep=1;}if(s2 != -1){t=t.replace('*'+prefix2,number);rep=1;}if(s3 != -1){t=t.replace('*'+prefix3,number);rep=1;}
  461.             if(rep==0){t=t.replace(prefix1,number);t=t.replace(prefix2,number);t=t.replace(prefix3,number);}
  462.             x1=t.indexOf(prefix1);x2=t.indexOf(prefix2);x3=t.indexOf(prefix3);
  463.             trouble++;if(trouble>200){setAlarm(r20);t="error";return t;}
  464.         }
  465.     }
  466.     if(t.charAt(0)=='*'){x4=t.length;t=t.substring(1,x4);}
  467.     return t;  
  468. }
  469.  
  470.  
  471. function check_s2(t){
  472.     // scientific notation...broken exponents or 10^03 or 10^+3 10^0.4 10^.5 10^12.3 ...
  473.     var x=t.indexOf('^');
  474.     if(x != -1){
  475.         var x1=t.charAt(x+1);var x2=t.charAt(x+2);var x3=t.charAt(x+3);
  476.         if(x1 == '.' || x2 == '.' || x3 == '.'){setAlarm(r10);t="error";return t;}
  477.         if(x1 == '0' && x2 == ''  && x3 == '' ){t=t.replace(/\*10\^0/,'*1');}
  478.         if(x1 == '0' && x2 != '' ){x=x.replace(/10\^0/,'10^');}
  479.         if(x1 == '+' && x2 == ''  && x3 == '' ){setAlarm(r16);t="error";return t;}
  480.         if(x1 == '+' && x2 != '' ){t=t.replace(/\^\+/g,'^');}
  481.     }
  482.     return t;
  483. }
  484.  
  485. function keywords(t){
  486.     var kwords=[' en ',' et ',' of ',' or ',' ou ',' plus ',' and ','and/or',' & '];
  487.     var a1;t=t.replace(/\~/g,' ');var trouble=0;t=t.toLowerCase();
  488.     for (var s=0 ; s<kwords.length ; s++){
  489.         a1=kwords[s];
  490.         while(t.indexOf(a1) != -1){
  491.             t=t.replace(a1,'~');
  492.             trouble++;if(trouble>100){setAlarm(r20);t="error";return t;}
  493.         }
  494.     }
  495.     t=t.replace(/\~/g,' and ');
  496.     return t;
  497. }
  498.  
  499. function upper_f(t){
  500.     var functies=['log','ln','abs','sqrt','sin','cos','tan','atan','acos','sinh','cosh','tanh','pi',' and ',' or '];
  501.     var trouble=0;var fun;var FUN;
  502.     for(s=0;s<functies.length;s++){
  503.         fun=functies[s];FUN=fun.toUpperCase();
  504.         while( t.indexOf(fun) != -1 ){
  505.             t=t.replace(fun,FUN);
  506.             trouble++;if(trouble>100){setAlarm(r20);t="error";return t;}
  507.         }
  508.     }
  509.     return t;
  510. }
  511.  
  512. function upper_varlist(varlist,t){
  513.     return t;
  514. }
  515.  
  516. function arrows(t,arg1,arg2,arg3){
  517.     // modify t in order to have a uniform arrow.
  518.     var ascii_arrows=['volgt','alors','thus','dus','therefor','ergo','<===>','===>','<==>','==>','<=>','=>','<--->','--->','<-->','-->','<->','->'];
  519.     var a1;t=t.replace(/@/g,' ');var trouble=0;var s;total_arrows=0;
  520.     for( s=0 ; s<ascii_arrows.length ; s++){
  521.         a1=ascii_arrows[s];
  522.         while(t.indexOf(a1) != -1){
  523.             t=t.replace(a1,'@');total_arrows++;
  524.             trouble++;if(trouble>100){setAlarm(t+"<br />"+r20);t="error";return t;}
  525.         }
  526.     }
  527.    
  528.     // arg3>0 there should be arrows
  529.     if(arg3){
  530.         if(arg3==1){if(total_arrows == 0){setAlarm(r30+"  "+arg3);t="error";return t;}}
  531.         if(arg3>1){if(total_arrows < arg3){setAlarm(r31+"  "+arg3);t="error";return t;}}
  532.     }
  533.  
  534.     // arg2 is the variable: we replace x1=,y_1=,z_9= by x=,y=,z= : just 1 variable at a time
  535.     if(arg2){
  536.         // preserve keywords...convert to ' and '
  537.         t=keywords(t);if(t=="error"){return t;}
  538.         t=t.replace(/[\s\r\n\ ]/g,'');
  539.         for(var m=1;m<10;m++){
  540.             a1=arg2+"_"+m+"=";t=t.replace(a1,arg2+"=");
  541.             a1=arg2+m+"=";t=t.replace(a1,arg2+"=");
  542.         }
  543.         t=t.replace(/and/g,' and ');
  544.     }
  545.    
  546.     var arrow_array=t.split('@');
  547.  
  548.     // there could ? be an sqrt[3](5) or log[7](12) in the sub_answers...
  549.     if(t.indexOf('[')!= -1){
  550.         var new_arrow_array=new Array();
  551.         t="";
  552.         for(s=0;s<total_arrows+1;s++){
  553.             a1=arrow_array[s];
  554.             if(a1.indexOf('sqrt[') != -1){a1=specialroot(a1);if(a1=="error"){t="error";return;}}
  555.             if(a1.indexOf('log[') != -1){a1=speciallog(a1);if(a1=="error"){t="error";return;}}
  556.             // rebuild the answer...
  557.             t=t+"@"+a1;
  558.             new_arrow_array[s]=a1;
  559.         }
  560.         arrow_array=new_arrow_array;
  561.     }
  562.  
  563.     if(arg1==0){
  564.         // returns standardized arrow " -> "
  565.         t=t.replace(/@/g,' -> ');return t;
  566.     }
  567.     if(arg1==1){
  568.         // returns unicode arrow symbol
  569.         t=t.replace(/@/g,' \u2192 ');return t;
  570.     }
  571.  
  572.     if(arg1==2){
  573.         // returns only the text after the last arrow
  574.         t=arrow_array[total_arrows];
  575.         // but should the answer be in the form arg2=1234 ?
  576.         if(arg2){
  577.             a1=t.replace(/[\s\r\n\ ]/g,'');
  578.             var x1=a1.indexOf(arg2);var is=a1.indexOf('=');
  579.             if(x1==-1 || is==-1){setAlarm(r22+"  "+a1);t="error";return t;}
  580.             if(x1>is){setAlarm(r29+"  "+a1);t="error";return t;}
  581.         }
  582.         // if there are more arrows, skip these and alert the student about this
  583.         if(total_arrows>0){
  584.             var rem="";
  585.             for(m=0;m<total_arrows;m++){
  586.                 a1=arrow_array[m];
  587.                 rem=rem+" \u2192 "+a1;
  588.             }
  589.             setAlarm("\""+rem+"\""+r32);
  590.         }
  591.         return t;
  592.     }
  593.    
  594.     if(arg1==3){
  595.         // returns the answer as an array split by the arrow symbol: no arrows present in this answer
  596.         // will not be used...
  597.         t=arrow_array;return t;
  598.     }
  599.    
  600.     if(arg1==4){
  601.         // returns the complete "stream of deduction"...and checks...
  602.         // every step [between arrows] if there is an arg2 (variable) and an "="
  603.         for(s=0;s<total_arrows-1;s++){
  604.             a1=arrow_array[s];a1=a1.replace(/[\s\r\n\ ]/g,'');
  605.             a2=arrow_array[s+1];a2=a2.replace(/[\s\r\n\ ]/g,'');
  606.             if(a1 == a2){setAlarm(r33+"<br />"+a1+" \u2192 "+a2);t="error";return t;}
  607.             if(a1.indexOf(arg2) == -1 && a1.indexOf('=') == -1){setAlarm(r30+" : "+a1);t="error";return t;}
  608.         }
  609.         if(arg2){
  610.             // and sees if the last argument is a conclusion  : arg2=12345 and arg2=54321
  611.             a1=arrow_array[total_arrows];
  612.             var x1=a1.indexOf(arg2);
  613.             var is=a1.indexOf('=');
  614.             if(x1==-1 || is==-1){setAlarm(r22+"  "+a1);t="error";return t;}
  615.             if(x1 > is ){setAlarm(r29+" : "+a1);t="error";return t;}
  616.         }
  617.         t=t.replace(/@/g,' -> ');return t;
  618.     }
  619.     setAlarm("syntax error in function <br /> arrows(t,arg1,arg2,arg3)<br /> t is answer <br /> arg1=switch, arg1=0: converts ascii arrows to unified \"->\" <br /> arg1=1 : converts ascii arrows to unified \"\u2192\" <br /> arg1=2 : returns no arrows ,just the text after the last arrow<br /> arg1=3 : returns no arrows...the answer is an array <br /> arg1=4 : returns the answer ,checks on all steps<br /> arg2=variable name<br />arg3=amount if any of arrows...");
  620. }
  621.  
  622. function is_text(t){
  623.     if(t.length == 0 || t == " "){setAlarm(r44);return 0;}
  624.     var tt=t.toLowerCase();
  625.     tt = nospace(tt);
  626.     tt = tt.replace(/[a-z]/g,'');
  627.     if(tt.length != 0 ){setAlarm("<b>"+t+"</b>...?<br />"+r47);return 0;}
  628. }
  629.  
  630. function is_number(t){
  631.     if(t.length == 0 || t == " "){setAlarm(r44);return 0;}
  632.     t=science(t);
  633.     var s=t.toLowerCase();
  634.     var functies=['log','ln','abs','sqrt','sin','cos','tan','atan','acos','sinh','cosh','tanh','pi'];
  635.     var f;var F;
  636.     for(var p=0;p<functies.length;p++){
  637.         f=functies[p];
  638.         F=f.toUpperCase();
  639.         s=s.replace(f,F);
  640.     }
  641.     s=s.replace(/[a-z\~\!\@\#\$\&\_\=\:\;]/g,'');
  642.     if(s.length != t.length){setAlarm(r37+"<br /><b>"+t+"</b>..."); return 0;}else{return 1;}
  643. }
  644.  
  645. function is_real_number(t){
  646.     if(t.length == 0 || t == " "){setAlarm(r44);return 0;}
  647.     t=science(t);
  648.     var s=t.toLowerCase();
  649.     s=s.replace(/[a-z\~\!\@\#\$\&\_\=\:\;]/g,'');
  650.     if(s.length != t.length){setAlarm(r37+"<br /><b>"+t+"</b>...") ; return 0;}else{return 1;}
  651. }
  652.  
  653. function make_description(list,cnt){
  654.     if( cnt == null ){ cnt = 30; }
  655.     if( list == null ){
  656.         list = new Array(cnt);
  657.     }
  658.     else
  659.     {
  660.         list = list.split(',');
  661.     }
  662.     for(var p = 0 ; p < cnt ; p++ ){
  663.         if( list[p] == null ){
  664.             list[p] = list[0];
  665.         }
  666.     }
  667.     return list;
  668. }
  669.  
  670. function singlespace(list){
  671.     var c = 0;
  672.     while(list.indexOf('  ')!=-1){
  673.         list = list.replace('  ',' ');
  674.         c++;
  675.         if(c > 100){return list;}
  676.     }
  677.     if( list.charAt(list.length - 1) == ' ' ){
  678.         list = list.substring(0,list.length-1);
  679.     }
  680.     if( list.charAt(0) == ' ' ){
  681.         list = list.substring(1,list.length);
  682.     }
  683.     return list;
  684. }
  685.  
  686. function nospace(list){
  687.     var c = 0;
  688.     while(list.indexOf(' ')!=-1){
  689.         list = list.replace(' ','');
  690.         c++;
  691.         if(c > 100){return list;}
  692.     }
  693.     return list;
  694. }
  695.  
  696. function words2items(words){
  697.     return words2string(words,',');
  698. }
  699.  
  700. function words2string(words,separator){
  701.   if( words.constructor.name == "Array" ){
  702.      var newwords = words[0];
  703.      var t = words.length;
  704.      for(var p = 1 ; p < t ; p++){newwords = newwords+separator+words[t];};
  705.      return newwords;
  706.    }
  707.    words = singlespace(words);
  708.      var c = 0;
  709.      while(words.indexOf(' ')!=-1){
  710.         words = words.replace(' ',separator);
  711.         c++;
  712.         if(c > 100){return words;}
  713.      };
  714.     return words;
  715. }
  716.  
  717. function wordcnt(string){
  718.     return wordcount(string);
  719. }
  720.  
  721. function wordcount(string){
  722.     if(string.length == 0 ){return 0;}
  723.     var tmp = singlespace(string);
  724.     if(tmp.length  === 0 ){ return 0;}// === checks on value and type
  725.     tmp = tmp.split(' ');
  726.     return tmp.length;
  727. }
  728.  
  729. // not invented here ...
  730. Array.prototype.listuniq = function() {
  731.         var o = {}, i, l = this.length, r = [];
  732.         for(i=0; i<l;i+=1) o[this[i]] = this[i];
  733.         for(i in o) r.push(o[i]);
  734.         return r;
  735. }
  736.  
  737. function rawmath(i){
  738.     i=i.toLowerCase();
  739.     i=i.replace(/\ /g,"");
  740.     i=i.replace(/\*\*/g,"^");
  741.     i=i.replace(/\u03c0/g,"pi");i=i.replace(/\u212e/g,"e");
  742.     if(i.indexOf("e+")!=-1){i=i.replace("e+","*10^");}
  743.     if(i.indexOf("e-")!=-1){i=i.replace("e-","*10^-");}
  744.     i=i.replace(/\*\*/g,"*");if(i.charAt(0)=="*"){i=i.substring(1,i.length);}
  745.     var fun=["asin","acos","atan","sin","cos","tan","log","ln","pi","e","x","y"];
  746.     var cons=["pi","e","0","1","2","3","4","5","6","7","8","9"];
  747.     var P;var D;var p;var d;
  748.     var l=cons.length;var cntl=0;var cntr=0;
  749.     for(p=0;p<i.length;p++){
  750.         if(i.charAt(p) == '('){cntl++;}
  751.         if(i.charAt(p) == ')'){cntr++;}
  752.     }
  753.     if(cntl != cntr){i = i+')';}
  754.     for(p=0;p<fun.length;p++){
  755.         for(d=0;d<l;d++){
  756.             while(i.indexOf(cons[d]+""+fun[p])!=-1){
  757.                 i=i.replace(cons[d]+""+fun[p],cons[d]+"*"+fun[p]);
  758.             }
  759.             while(i.indexOf(fun[p]+""+cons[d])!=-1){
  760.                 i=i.replace(fun[p]+""+cons[d],fun[p]+"*"+cons[d]);
  761.             }
  762.         }
  763.     }
  764.     if(i.indexOf("(")!=-1){
  765.         for(p=0;p<l;p++){
  766.             if(i.indexOf(cons[p]+"(")!=-1){
  767.                 i=i.replace(cons[p]+"(",cons[p]+"*(");
  768.             }
  769.             if(i.indexOf(")"+cons[p])!=-1){
  770.                 i=i.replace(")"+cons[p],")*"+cons[p]);
  771.             }
  772.         }
  773.         i=i.replace(/\)\(/g,")*(");
  774.     }
  775.     return i;
  776. }
  777.    
  778.  
  779. function plusminus(t){
  780.  if( t.indexOf('pm') < 0 ){ return t;};
  781.  t = keywords(t);if( t == "error" ){return "error";};
  782.  /* x = pm 5 and x = pm 6 */
  783.  var temp = t.split('and');
  784.  var len = temp.length;
  785.  var rp = "";
  786.  for( var p = 0 ; p < len ; p++ ){
  787.   var t1=temp[p].replace('pm','-');
  788.   var t2=temp[p].replace('pm',' ');
  789.   rp = rp + t1 + " or " + t2;
  790.   if(len > 1 && p < len - 1){
  791.    rp = rp + " or ";
  792.   };
  793.  };
  794.  return rp;
  795. };
  796.  
  797.