Subversion Repositories wimsdev

Rev

Rev 13043 | Go to most recent revision | 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.     var alfabet="abcdefghijklmonpqrstuvwxyz";
  192.     var Alfabet="ABCDEFGHIJKLMONPQRSTUVWXYZ";
  193.     t=t.replace(/log\[/g,'#');
  194.     t=t.replace(/sqrt\[/g,'#');
  195.     var ft;var ismatch;var fun;var F;var t2;var c0;var t1;
  196.     var functies=['log','ln','abs','sqrt','sin','cos','tan','atan','acos','sinh','cosh','tanh'];
  197.     ft=functies.length;var trouble=0;
  198.     for(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(ismatch-1,ismatch);t2=t.substring(c,c+1);
  202.             if(t2=='(' || alfabet.indexOf(t1)!=-1 || Alfabet.indexOf(t1)!=-1 || alfabet.indexOf(t2)!=-1 || Alfabet.indexOf(t2)!=-1){t=t.replace(fun,F);ismatch=t.indexOf(fun);}else{setAlarm(r9);return 0;}
  203.             trouble++;if(trouble>200){setAlarm(r20);return 0;}
  204.         };
  205.     };
  206.     return 1;
  207. };
  208.  
  209. function check_x(t){
  210.     var dingen=['1','2','3','4','5','6','7','8','9','0'];
  211.     var t2;var t3;var d;var chk;var trouble=0;
  212.     t1=t.indexOf('x');
  213.     /// tollerate: x1= x2= etc ---> t1>0
  214.     while(t1>0){
  215.         chk=0;
  216.         t2=t.charAt(t1-1);
  217.         t3=t.charAt(t1+1);
  218.         for(s=0;s<10;s++){
  219.             d=dingen[s];
  220.             if(t2==d){chk=chk+1;}if(t3==d){chk=chk+1;};
  221.         };
  222.         if(chk==2){setAlarm(r7);return 0;};
  223.         t=t.replace('x','*');t1=t.indexOf('x');
  224.         trouble++;if(trouble>100){setAlarm(r20);return 0;};
  225.     };
  226.     return 1;
  227. };
  228.  
  229. function specialroot(t){
  230.     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;
  231.     t2=t.indexOf("](");if(t2==-1){setAlarm(r11);t="error";return t;}
  232.     org=t;t=t.replace(/sqrt\(/g,"SQRT(");
  233.     t=t.replace(/log\[/g,"LOG~");t=t.replace(/sqrt\[/g,"@[");test=t.replace(/[a-z]\[/g,"#");
  234.     if(test.indexOf("#")!=-1){setAlarm(r11);t="error"; return t;};
  235.     t2=t.indexOf("[");var trouble=0;
  236.     while(t2 != -1){
  237.         begin=t.indexOf("@");t2=t.indexOf("[");t3=t.indexOf("]");
  238.         if(t2==begin+1 && t3>t2){
  239.             power=t.substring(t2+1,t3);
  240.             if(power.length==0){setAlarm(r16);t="error";return t;};
  241.             if(power<2){setAlarm(r16);t="error";return t;}
  242.             t4="["+power+"]";t=t.replace(t4,'');
  243.             tot=t.length;wait=0;got=0;end=0;
  244.             for(s=begin;s<tot;s++){
  245.                 if(end==0){
  246.                     chr=t.charAt(s);
  247.                     if(chr=="("){wait=wait+1;};
  248.                     if(chr==")"){got=got+1;};
  249.                     if(got!=0){if(wait==got){end=s;};};
  250.                 };
  251.             };
  252.             begin=begin+2;
  253.             sqrt=t.substring(begin,end);
  254.             mod=(power % 2);
  255.             if(sqrt<0 && mod!=1){setAlarm(r16);t="error";return t;};
  256.             t=t.replace("@("+sqrt+")","("+sqrt+")^(1/("+power+"))");
  257.         }
  258.         else
  259.         {
  260.          t=t.replace("]","?");
  261.         };
  262.         trouble++;if(trouble>100){setAlarm(r20);t="error";return t;};
  263.     };
  264.     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");
  265.     return t;
  266. };
  267.    
  268. function speciallog(t){
  269.     var noemer;var teller;var begin;var end;var tot;var wait;var got;var chr;var t1;var t2;var t3;var t4;
  270.     t2=t.indexOf("](");if(t2==-1){setAlarm(r11);t="error";return t;}
  271.     t=t.replace(/log\(/g,'LOG(');
  272.     t=t.replace(/log/g,"@");
  273.     t2=t.indexOf("[");var trouble=0;
  274.     while(t2 != -1){
  275.         begin=t.indexOf("@");t3=t.indexOf("]");
  276.         if(t2==begin+1 && t3>t2){
  277.             grondtal=t.substring(t2+1,t3);
  278.             if(grondtal=="10"){setAlarm(r14);t="error";return t;}
  279.             if(grondtal=="e" || grondtal=='E'){setAlarm(r15);t="error";return t;}
  280.             t4="["+grondtal+"]";t=t.replace(t4,'');
  281.             tot=t.length;wait=0;got=0;end=0;
  282.             for(s=begin;s<tot;s++){
  283.                 if(end==0){
  284.                     chr=t.charAt(s);
  285.                     if(chr=="("){wait=wait+1;}
  286.                     if(chr==")"){got=got+1;}
  287.                     if(got!=0){if(wait==got){end=s;}}
  288.                 }
  289.             }
  290.             begin=begin+2;teller=t.substring(begin,end);
  291.             if(grondtal==teller){setAlarm(r17);}
  292.             t=t.replace("@("+teller+")","(~("+teller+")/~("+grondtal+"))");
  293.         }else{t=t.replace("[","%");}
  294.         t2=t.indexOf("[");
  295.         trouble++;if(trouble>100){setAlarm(r20);t="error";return t;}
  296.     }
  297.     t=t.replace(/\%/g,"[");t=t.replace(/~/g,"log");t=t.replace(/LOG\(/g,"log(");t=t.replace(/@/g,"log");
  298.     return t;
  299. }
  300.  
  301. function check_log_NaN(t){
  302.     t=t.replace(/log\(/g,'@(');if(t.indexOf('@')==-1){return 1;}
  303.     if(t.indexOf('--')!=-1 || t.indexOf('++')!=-1 ){setAlarm(r18);return 0;}
  304.     /* 3/2017 added ^ to dingen ; eval return 0 for eval(4^6) */
  305.     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'];
  306.     begin=t.indexOf('@');var exp;var variable;var trouble=0;var sa;
  307.     while(begin != -1){
  308.         t1=t.indexOf('(');
  309.         t2=t.indexOf(')');
  310.         if(t1=begin+1 && t2>t1){
  311.             tot=t.length;wait=0;got=0;end=0;
  312.             for(s=begin;s<tot;s++){
  313.                 if(end==0){
  314.                     chr=t.charAt(s);
  315.                     if(chr=="("){wait=wait+1;}
  316.                     if(chr==")"){got=got+1;}
  317.                     if(got!=0){if(wait==got){end=s;}}
  318.                 }
  319.             }
  320.             begin=begin+2;exp=t.substring(begin,end);sa=0;variable=0;
  321.             while(sa<28){v=dingen[sa];w=exp.indexOf(v);if(w!=-1){sa=28;variable=1;}sa++;}
  322.             if(variable==0){test=eval(exp);if(test<=0){setAlarm(r16);return 0;}}
  323.             t=t.replace('@(','log(');begin=t.indexOf('@');
  324.         }else{return 1;}
  325.         trouble++;
  326.         if(trouble>100){setAlarm(r20);return 0;}
  327.     }
  328.     return 1;
  329. }
  330.  
  331. function check_sqrt_NaN(t){
  332.     t=t.replace(/sqrt\(/g,'@(');if(t.indexOf('@')==-1){return 1;}
  333.     if(t.indexOf('--')!=-1 || t.indexOf('++')!=-1 ){setAlarm(r18);return 0;}
  334.     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'];
  335.     begin=t.indexOf('@');var exp;var variable;var trouble=0;var s;var sa;
  336.     while(begin != -1){
  337.         t1=t.indexOf('(');
  338.         t2=t.indexOf(')');
  339.         if(t1=begin+1 && t2>t1){
  340.             tot=t.length;wait=0;got=0;end=0;
  341.             for(s=begin;s<tot;s++){
  342.                 if(end==0){
  343.                     chr=t.charAt(s);
  344.                     if(chr=="("){wait=wait+1;}
  345.                     if(chr==")"){got=got+1;}
  346.                     if(got!=0){if(wait==got){end=s;}}
  347.                 }
  348.             }
  349.             begin=begin+2;exp=t.substring(begin,end);exp=exp.replace(/\ /g,'');sa=0;variable=0;
  350.             while(sa<27){v=dingen[sa];w=exp.indexOf(v);if(w!=-1){sa=27;variable=1;}sa++;}
  351.             if(variable==0){test=eval(exp);if(test<0){setAlarm(r16);return 0;}}
  352.             t=t.replace('@(','sqrt(');begin=t.indexOf('@');
  353.         }else{return 1;}
  354.         trouble++;
  355.         if(trouble>100){setAlarm(r20);return 0;}
  356.     }
  357.     return 1;
  358. }
  359.  
  360. function nthroot(t){
  361.     var test=t.replace(/root/g,'@');
  362.     if(test.indexOf('@')==-1){return t;}
  363.     var t1;var t2;var t3;var exp;var variable;
  364.     var under;var wait;var end;var got;var s;var trouble=0;
  365.     t=t.replace(/root/g,'@');var begin=t.indexOf('@');
  366.     var tot=t.length;
  367.     while(begin != -1){
  368.         t1=t.indexOf('(');
  369.         t2=t.indexOf(')');
  370.         if(t1=begin+1 && t2>t1){
  371.             wait=0;got=0;end=0;
  372.             for(s=begin;s<tot;s++){
  373.                 if(end==0){
  374.                     chr=t.charAt(s);
  375.                     if(chr=="("){wait=wait+1;}
  376.                     if(chr==")"){got=got+1;}
  377.                     if(got!=0){if(wait==got){end=s;}}
  378.                 }
  379.             }
  380.             under=t.substring(begin+2,end);
  381.             t3=under.indexOf(',');
  382.             if(t3==-1){t=t.replace("@("+under+")","sqrt%"+under+"#");}
  383.             else{
  384.                 variable=under.substring(0,t3);
  385.                 exp=under.substring(t3+1,end)
  386.                 if(exp.indexOf(',')!=-1 || variable.indexOf(',')!=-1 ){setAlarm(r20);t="error";return t;}
  387.                 t=t.replace("@("+under+")","%"+variable+"#^%1/%"+exp+"##");
  388.             }
  389.         }
  390.         else
  391.         {
  392.             t=t.replace('(','%');
  393.             t=t.replace(')','#');
  394.         }
  395.         tot=t.length;
  396.         begin=t.indexOf('@');
  397.         trouble++;if(trouble>100){setAlarm(r20);t="error";return t;}
  398.     }
  399.     t=t.replace(/\%/g,'(');
  400.     t=t.replace(/#/g,')');
  401.     return t;
  402. }
  403.  
  404. function normalize(t){
  405.     // we can't use lower.case() because of F(x)= x^123 + C :(
  406.     var accent_H = ['Æ','Ã','À','Ä','Â','É','È','Ë','Ê','Ã','ÃŒ','Ã','ÃŽ','Ó','Ã’','Ö','Ô','Ú','Ù','Ü','Û','Ç','²','³','¼','½','¾','ß'];
  407.     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'];
  408.     var accent_L = ['ò','ó','ô','õ','ö','ø','ù','ú','û','ü','à','á','â','ã','ä','Ã¥','ç','è','é','ê','ë','ì','í','î','ï','ñ','æ'];
  409.     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'];
  410.     var char_t;var s;var str_a;var str_n;var trouble=0;
  411.     for(s=0;s<accent_H.length;s++){
  412.         str_a=accent_H[s];
  413.         str_n=normal_H[s];
  414.         while(t.indexOf(str_a)!=-1){
  415.             t=t.replace(str_a,str_n);
  416.             trouble++;if(trouble>200){setAlarm(r20);t="error";return t;}
  417.         }
  418.     }
  419.     trouble=0;
  420.     for(s=0;s<accent_L.length;s++){
  421.         str_a=accent_L[s];
  422.         str_n=normal_L[s];
  423.         while(t.indexOf(str_a)!=-1){
  424.             t=t.replace(str_a,str_n);
  425.             trouble++;if(trouble>200){setAlarm(r20);t="error";return t;}
  426.         }
  427.     }
  428.     return t;
  429. }
  430.  
  431. function prefix(t){
  432.     // replace SI prefixes
  433.     // still no good: case sensitive !!! can not / will not do a lowercase on the student reply ...
  434.     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'];
  435.     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'];
  436.     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'];
  437.     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;
  438.     for (s=0;s<l;s++){
  439.         number=SI[s];prefix1=VA1[s];prefix2=VA2[s];prefix3=prefix1.toUpperCase();x1=t.indexOf(prefix1);x2=t.indexOf(prefix2);x3=t.indexOf(prefix3)
  440.         while(x1 != -1 || x2 !=-1 || x3 !=-1){
  441.             rep=0;s1=t.indexOf('*'+prefix1);s2=t.indexOf('*'+prefix2);s3=t.indexOf('*'+prefix3);
  442.             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;}
  443.             if(rep==0){t=t.replace(prefix1,number);t=t.replace(prefix2,number);t=t.replace(prefix3,number);}
  444.             x1=t.indexOf(prefix1);x2=t.indexOf(prefix2);x3=t.indexOf(prefix3);
  445.             trouble++;if(trouble>200){setAlarm(r20);t="error";return t;}
  446.         }
  447.     }
  448.     if(t.charAt(0)=='*'){x4=t.length;t=t.substring(1,x4);}
  449.     return t;  
  450. }
  451.  
  452.  
  453. function check_s2(t){
  454.     // scientific notation...broken exponents or 10^03 or 10^+3 10^0.4 10^.5 10^12.3 ...
  455.     var x=t.indexOf('^');
  456.     if(x != -1){
  457.         var x1=t.charAt(x+1);var x2=t.charAt(x+2);var x3=t.charAt(x+3);
  458.         if(x1 == '.' || x2 == '.' || x3 == '.'){setAlarm(r10);t="error";return t;}
  459.         if(x1 == '0' && x2 == ''  && x3 == '' ){t=t.replace(/\*10\^0/,'*1');}
  460.         if(x1 == '0' && x2 != '' ){x=x.replace(/10\^0/,'10^');}
  461.         if(x1 == '+' && x2 == ''  && x3 == '' ){setAlarm(r16);t="error";return t;}
  462.         if(x1 == '+' && x2 != '' ){t=t.replace(/\^\+/g,'^');}
  463.     }
  464.     return t;
  465. }
  466.  
  467. function keywords(t){
  468.     var kwords=[' en ',' et ',' of ',' or ',' ou ',' plus ',' and ','and/or',' & '];
  469.     var a1;t=t.replace(/\~/g,' ');var trouble=0;t=t.toLowerCase();
  470.     for (var s=0 ; s<kwords.length ; s++){
  471.         a1=kwords[s];
  472.         while(t.indexOf(a1) != -1){
  473.             t=t.replace(a1,'~');
  474.             trouble++;if(trouble>100){setAlarm(r20);t="error";return t;}
  475.         }
  476.     }
  477.     t=t.replace(/\~/g,' and ');
  478.     return t;
  479. }
  480.  
  481. function upper_f(t){
  482.     var functies=['log','ln','abs','sqrt','sin','cos','tan','atan','acos','sinh','cosh','tanh','pi',' and ',' or '];
  483.     var trouble=0;var fun;var FUN;
  484.     for(s=0;s<functies.length;s++){
  485.         fun=functies[s];FUN=fun.toUpperCase();
  486.         while( t.indexOf(fun) != -1 ){
  487.             t=t.replace(fun,FUN);
  488.             trouble++;if(trouble>100){setAlarm(r20);t="error";return t;}
  489.         }
  490.     }
  491.     return t;
  492. }
  493.  
  494. function upper_varlist(varlist,t){
  495.     return t;
  496. }
  497.  
  498. function arrows(t,arg1,arg2,arg3){
  499.     // modify t in order to have a uniform arrow.
  500.     var ascii_arrows=['volgt','alors','thus','dus','therefor','ergo','<===>','===>','<==>','==>','<=>','=>','<--->','--->','<-->','-->','<->','->'];
  501.     var a1;t=t.replace(/@/g,' ');var trouble=0;var s;total_arrows=0;
  502.     for( s=0 ; s<ascii_arrows.length ; s++){
  503.         a1=ascii_arrows[s];
  504.         while(t.indexOf(a1) != -1){
  505.             t=t.replace(a1,'@');total_arrows++;
  506.             trouble++;if(trouble>100){setAlarm(t+"<br />"+r20);t="error";return t;}
  507.         }
  508.     }
  509.    
  510.     // arg3>0 there should be arrows
  511.     if(arg3){
  512.         if(arg3==1){if(total_arrows == 0){setAlarm(r30+"  "+arg3);t="error";return t;}}
  513.         if(arg3>1){if(total_arrows < arg3){setAlarm(r31+"  "+arg3);t="error";return t;}}
  514.     }
  515.  
  516.     // arg2 is the variable: we replace x1=,y_1=,z_9= by x=,y=,z= : just 1 variable at a time
  517.     if(arg2){
  518.         // preserve keywords...convert to ' and '
  519.         t=keywords(t);if(t=="error"){return t;}
  520.         t=t.replace(/[\s\r\n\ ]/g,'');
  521.         for(var m=1;m<10;m++){
  522.             a1=arg2+"_"+m+"=";t=t.replace(a1,arg2+"=");
  523.             a1=arg2+m+"=";t=t.replace(a1,arg2+"=");
  524.         }
  525.         t=t.replace(/and/g,' and ');
  526.     }
  527.    
  528.     var arrow_array=t.split('@');
  529.  
  530.     // there could ? be an sqrt[3](5) or log[7](12) in the sub_answers...
  531.     if(t.indexOf('[')!= -1){
  532.         var new_arrow_array=new Array();
  533.         t="";
  534.         for(s=0;s<total_arrows+1;s++){
  535.             a1=arrow_array[s];
  536.             if(a1.indexOf('sqrt[') != -1){a1=specialroot(a1);if(a1=="error"){t="error";return;}}
  537.             if(a1.indexOf('log[') != -1){a1=speciallog(a1);if(a1=="error"){t="error";return;}}
  538.             // rebuild the answer...
  539.             t=t+"@"+a1;
  540.             new_arrow_array[s]=a1;
  541.         }
  542.         arrow_array=new_arrow_array;
  543.     }
  544.  
  545.     if(arg1==0){
  546.         // returns standardized arrow " -> "
  547.         t=t.replace(/@/g,' -> ');return t;
  548.     }
  549.     if(arg1==1){
  550.         // returns unicode arrow symbol
  551.         t=t.replace(/@/g,' \u2192 ');return t;
  552.     }
  553.  
  554.     if(arg1==2){
  555.         // returns only the text after the last arrow
  556.         t=arrow_array[total_arrows];
  557.         // but should the answer be in the form arg2=1234 ?
  558.         if(arg2){
  559.             a1=t.replace(/[\s\r\n\ ]/g,'');
  560.             var x1=a1.indexOf(arg2);var is=a1.indexOf('=');
  561.             if(x1==-1 || is==-1){setAlarm(r22+"  "+a1);t="error";return t;}
  562.             if(x1>is){setAlarm(r29+"  "+a1);t="error";return t;}
  563.         }
  564.         // if there are more arrows, skip these and alert the student about this
  565.         if(total_arrows>0){
  566.             var rem="";
  567.             for(m=0;m<total_arrows;m++){
  568.                 a1=arrow_array[m];
  569.                 rem=rem+" \u2192 "+a1;
  570.             }
  571.             setAlarm("\""+rem+"\""+r32);
  572.         }
  573.         return t;
  574.     }
  575.    
  576.     if(arg1==3){
  577.         // returns the answer as an array split by the arrow symbol: no arrows present in this answer
  578.         // will not be used...
  579.         t=arrow_array;return t;
  580.     }
  581.    
  582.     if(arg1==4){
  583.         // returns the complete "stream of deduction"...and checks...
  584.         // every step [between arrows] if there is an arg2 (variable) and an "="
  585.         for(s=0;s<total_arrows-1;s++){
  586.             a1=arrow_array[s];a1=a1.replace(/[\s\r\n\ ]/g,'');
  587.             a2=arrow_array[s+1];a2=a2.replace(/[\s\r\n\ ]/g,'');
  588.             if(a1 == a2){setAlarm(r33+"<br />"+a1+" \u2192 "+a2);t="error";return t;}
  589.             if(a1.indexOf(arg2) == -1 && a1.indexOf('=') == -1){setAlarm(r30+" : "+a1);t="error";return t;}
  590.         }
  591.         if(arg2){
  592.             // and sees if the last argument is a conclusion  : arg2=12345 and arg2=54321
  593.             a1=arrow_array[total_arrows];
  594.             var x1=a1.indexOf(arg2);
  595.             var is=a1.indexOf('=');
  596.             if(x1==-1 || is==-1){setAlarm(r22+"  "+a1);t="error";return t;}
  597.             if(x1 > is ){setAlarm(r29+" : "+a1);t="error";return t;}
  598.         }
  599.         t=t.replace(/@/g,' -> ');return t;
  600.     }
  601.     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...");
  602. }
  603.  
  604. function is_text(t){
  605.     if(t.length == 0 || t == " "){setAlarm(r44);return 0;}
  606.     var tt=t.toLowerCase();
  607.     tt = nospace(tt);
  608.     tt = tt.replace(/[a-z]/g,'');
  609.     if(tt.length != 0 ){setAlarm("<b>"+t+"</b>...?<br />"+r47);return 0;}
  610. }
  611.  
  612. function is_number(t){
  613.     if(t.length == 0 || t == " "){setAlarm(r44);return 0;}
  614.     t=science(t);
  615.     var s=t.toLowerCase();
  616.     var functies=['log','ln','abs','sqrt','sin','cos','tan','atan','acos','sinh','cosh','tanh','pi'];
  617.     var f;var F;
  618.     for(var p=0;p<functies.length;p++){
  619.         f=functies[p];
  620.         F=f.toUpperCase();
  621.         s=s.replace(f,F);
  622.     }
  623.     s=s.replace(/[a-z\~\!\@\#\$\&\_\=\:\;]/g,'');
  624.     if(s.length != t.length){setAlarm(r37+"<br /><b>"+t+"</b>..."); return 0;}else{return 1;}
  625. }
  626.  
  627. function is_real_number(t){
  628.     if(t.length == 0 || t == " "){setAlarm(r44);return 0;}
  629.     t=science(t);
  630.     var s=t.toLowerCase();
  631.     s=s.replace(/[a-z\~\!\@\#\$\&\_\=\:\;]/g,'');
  632.     if(s.length != t.length){setAlarm(r37+"<br /><b>"+t+"</b>...") ; return 0;}else{return 1;}
  633. }
  634.  
  635. function make_description(list,cnt){
  636.     if( cnt == null ){ cnt = 30; }
  637.     if( list == null ){
  638.         list = new Array(cnt);
  639.     }
  640.     else
  641.     {
  642.         list = list.split(',');
  643.     }
  644.     for(var p = 0 ; p < cnt ; p++ ){
  645.         if( list[p] == null ){
  646.             list[p] = list[0];
  647.         }
  648.     }
  649.     return list;
  650. }
  651.  
  652. function singlespace(list){
  653.     var c = 0;
  654.     while(list.indexOf('  ')!=-1){
  655.         list = list.replace('  ',' ');
  656.         c++;
  657.         if(c > 100){return list;}
  658.     }
  659.     if( list.charAt(list.length - 1) == ' ' ){
  660.         list = list.substring(0,list.length-1);
  661.     }
  662.     if( list.charAt(0) == ' ' ){
  663.         list = list.substring(1,list.length);
  664.     }
  665.     return list;
  666. }
  667.  
  668. function nospace(list){
  669.     var c = 0;
  670.     while(list.indexOf(' ')!=-1){
  671.         list = list.replace(' ','');
  672.         c++;
  673.         if(c > 100){return list;}
  674.     }
  675.     return list;
  676. }
  677.  
  678. function words2items(words){
  679.     return words2string(words,',');
  680. }
  681.  
  682. function words2string(words,separator){
  683.   if( words.constructor.name == "Array" ){
  684.      var newwords = words[0];
  685.      var t = words.length;
  686.      for(var p = 1 ; p < t ; p++){newwords = newwords+separator+words[t];};
  687.      return newwords;
  688.    }
  689.    words = singlespace(words);
  690.      var c = 0;
  691.      while(words.indexOf(' ')!=-1){
  692.         words = words.replace(' ',separator);
  693.         c++;
  694.         if(c > 100){return words;}
  695.      };
  696.     return words;
  697. }
  698.  
  699. function wordcnt(string){
  700.     return wordcount(string);
  701. }
  702.  
  703. function wordcount(string){
  704.     if(string.length == 0 ){return 0;}
  705.     var tmp = singlespace(string);
  706.     if(tmp.length  === 0 ){ return 0;}// === checks on value and type
  707.     tmp = tmp.split(' ');
  708.     return tmp.length;
  709. }
  710.  
  711. // not invented here ...
  712. Array.prototype.listuniq = function() {
  713.         var o = {}, i, l = this.length, r = [];
  714.         for(i=0; i<l;i+=1) o[this[i]] = this[i];
  715.         for(i in o) r.push(o[i]);
  716.         return r;
  717. }
  718.  
  719. function rawmath(i){
  720.     i=i.toLowerCase();
  721.     i=i.replace(/\ /g,"");
  722.     i=i.replace(/\*\*/g,"^");
  723.     i=i.replace(/\u03c0/g,"pi");i=i.replace(/\u212e/g,"e");
  724.     if(i.indexOf("e+")!=-1){i=i.replace("e+","*10^");}
  725.     if(i.indexOf("e-")!=-1){i=i.replace("e-","*10^-");}
  726.     i=i.replace(/\*\*/g,"*");if(i.charAt(0)=="*"){i=i.substring(1,i.length);}
  727.     var fun=["asin","acos","atan","sin","cos","tan","log","ln","pi","e","x","y"];
  728.     var cons=["pi","e","0","1","2","3","4","5","6","7","8","9"];
  729.     var P;var D;var p;var d;
  730.     var l=cons.length;var cntl=0;var cntr=0;
  731.     for(p=0;p<i.length;p++){
  732.         if(i.charAt(p) == '('){cntl++;}
  733.         if(i.charAt(p) == ')'){cntr++;}
  734.     }
  735.     if(cntl != cntr){i = i+')';}
  736.     for(p=0;p<fun.length;p++){
  737.         for(d=0;d<l;d++){
  738.             while(i.indexOf(cons[d]+""+fun[p])!=-1){
  739.                 i=i.replace(cons[d]+""+fun[p],cons[d]+"*"+fun[p]);
  740.             }
  741.             while(i.indexOf(fun[p]+""+cons[d])!=-1){
  742.                 i=i.replace(fun[p]+""+cons[d],fun[p]+"*"+cons[d]);
  743.             }
  744.         }
  745.     }
  746.     if(i.indexOf("(")!=-1){
  747.         for(p=0;p<l;p++){
  748.             if(i.indexOf(cons[p]+"(")!=-1){
  749.                 i=i.replace(cons[p]+"(",cons[p]+"*(");
  750.             }
  751.             if(i.indexOf(")"+cons[p])!=-1){
  752.                 i=i.replace(")"+cons[p],")*"+cons[p]);
  753.             }
  754.         }
  755.         i=i.replace(/\)\(/g,")*(");
  756.     }
  757.     return i;
  758. }
  759.    
  760.  
  761. function plusminus(t){
  762.  if( t.indexOf('pm') < 0 ){ return t;};
  763.  t = keywords(t);if( t == "error" ){return "error";};
  764.  /* x = pm 5 and x = pm 6 */
  765.  var temp = t.split('and');
  766.  var len = temp.length;
  767.  var rp = "";
  768.  for( var p = 0 ; p < len ; p++ ){
  769.   var t1=temp[p].replace('pm','-');
  770.   var t2=temp[p].replace('pm',' ');
  771.   rp = rp + t1 + " or " + t2;
  772.   if(len > 1 && p < len - 1){
  773.    rp = rp + " or ";
  774.   };
  775.  };
  776.  return rp;
  777. };
  778.  
  779.