// Javascript (linfunktueb.js) für linearefunktionenueben.htm
// (c) Arndt Brünner, 18. 8. 2002

var na1=0,na2=0,            // Anzahl Aufgaben
    nf1=0,nf2=0,            // Anzahl Fehler
    nrmax1=0,nrmax2=0,      // Längste Erfolgsreihe
    nar1=0,nar2=0,          // Aktuelle Anzahl ohne Fehler
    nv1,nv2;                // Anzahl Versuche in aktueller Aufgabe
var m=0,b=0;                // Parameter der aktuellen Funktion 
var err1=new Array(),
    err2=new Array(),       // Fehlerspeicher
    nerr1=0,nerr2=0;        // Anzahl
var nf=new Array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);       // Fehleranalyse
var nff=new Array(0,0,0);
var terme=new Array(10),     // Speicher der letzten 10 Terme
    iterme=0;               // aktueller Index
var nsc =(navigator.appName.indexOf("Netscape")>-1);// new Boolean();    // Netscape?

function init()
{
	aufgabe(1);
	aufgabe(2);
	if(nsc) 
	{
		document.f.term1.onkeydown=testenter1;
		document.f.term2.onkeydown=testenter2;
	}
}

function testenter1(blubber)
{var tc=(nsc==true)? blubber.which : window.event.keyCode;if(tc==13)test1();return blubber;}

function testenter2(blubber)
{var tc=(nsc==true)? blubber.which : window.event.keyCode;if(tc==13)test2();return blubber;}


function aufgabe(typ)
{
	if(typ==1)nv1=0;else nv2=0;
	var t="",mm,bb,wdh=new Boolean(),ok=new Boolean();
	wdh=false;bb=b; mm=m;
	do
	{
		if((Math.random()>0.6)&&(((typ==1)?nerr1:nerr2)>0))
			{
				t=(typ==1)?err1[Math.floor(Math.random()*nerr1)]:err2[Math.floor(Math.random()*nerr2)];
				wdh=true; b=parseB(t); m=parseM(t);
			}
		else
		{
			var na=(typ==1)?na1:na2;
			if(na<10){m=Math.floor(Math.random()*6-3);if(m==0)m=1;b=Math.floor(Math.random()*10-5);}
			if(na>=10){m=Math.floor(Math.random()*10-5)/2;b=Math.floor(Math.random()*10-5)/2;}
			if((typ==1)&&(Math.random()>.5))
			{
				if(na>=15){m=Math.floor(Math.random()*20-10)/4;b=Math.floor(Math.random()*20-10)/2;}
				if(na>=25){m=Math.floor(Math.random()*20-10)/Math.floor(Math.random()*9+1);b=Math.floor(Math.random()*10-5)/2;}
				if(na>=35){m=Math.floor(Math.random()*20-10)/Math.floor(Math.random()*9+1);b=Math.floor(Math.random()*20-10)/Math.floor(Math.random()*9+1);}
			}
			if((typ==2)&&(Math.random()>.5))
			{
				if(na>=15){m=1/Math.floor(Math.random()*12-6);b=Math.floor(Math.random()*20-10)/2;}
				if(na>=25){m=Math.floor(Math.random()*10-5)/Math.floor(Math.random()*4+1);b=Math.floor(Math.random()*20-10)/2;}
				if(na>=35){m=Math.floor(Math.random()*20-10)/Math.floor(Math.random()*5+1);b=Math.floor(Math.random()*40-20)/4;}
				if(na>=45){m=Math.floor(Math.random()*20-10)/Math.floor(Math.random()*10+1);b=Math.floor(Math.random()*40-20)/2;}
			}
			t=TermStr(m,b);wdh=false;
		}
		ok=true;
		if(t.indexOf("Inf")>-1)ok=false;
		if(t.indexOf("NaN")>-1)ok=false;
		if(t==terme[iterme]){ok=false;}
		else if(((mm-m)*(bb-b)==0)&&(wdh==false)){ok=false;}
		else if(wdh==false)
		{
			for(i=0;i<10;i++)
				{if(terme[i]==t){ok=false;break;}}
		}
	}while(!ok);
	iterme=(iterme+1)%10
	terme[iterme]=t;
	
	if(typ==1){document.f.term1.value=t;if(document.f.term3!=null)document.f.term3.value=t;}
	if(typ==2)
	{
		document.plotter2.parse(m+"*x+("+b+")");
		document.plotter2.plot();
	}
}


function test1()
{
	var mm=document.plotter1.getKoeff(1);
	var bb=document.plotter1.getKoeff(0);
	var mmm=parseM(document.f.term1.value);
	var bbb=parseB(document.f.term1.value);
	var tt=TermStr(mm,bb);
	nv1++;
	if(tt==document.f.term1.value)
	{
		if(!document.f.nomsg1.checked)alert("Richtig!");
		if(nv1==1){loescheFehler1(document.f.term1.value); statistik(1,true);}
		aufgabe(1);
	}
	else 
	{
		fehleranalyse(mmm,bbb,mm,bb,1)
		speicherFehler1(document.f.term1.value);
		if(nv1>=7)if(!confirm("Leider noch immer falsch. Willst du weitermachen oder die Aufgabe abbrechen?","")){aufgeben(1);return;}
		if(nv1==1)
			{statistik(1,false);alert("Falsch!");}
		else if(nv1<4)
			{alert("Falsch!\n\nDiese Gerade hat die Gleichung\nf(x) ="+TermStr(mm,bb));}
		else if(bbb!=bb)
			alert("Leider noch immer falsch.\n\nDu mußt einen Punkt auf (0|"+bbb+") setzen und den zweiten so, daß die Steigung "+mmm+" beträgt.");
		else if(bbb==bb)
			{var fehlerm="Leider noch immer falsch.\n\nDer Schnittpunkt mit der y-Achse stimmt jedoch.\nDu mußt einen Punkt auf (0|"+bbb+") setzen und den zweiten so, daß die Steigung "+mmm;
			fehlerm+=" beträgt, das heißt: ein Schritt nach rechts entspricht "+Math.abs(mmm)+" nach "+((mmm>0)?"oben.":"unten.");
			alert(fehlerm);
			}
	}
	statistikzeigen();
}

var lasttest2="";

function test2()
{
	var t=document.f.term2.value;
	if((t=="")||(t==lasttest2))return;
	lasttest2=t;
	nv2++;
	var bb=parseB(t),bbb=document.plotter2.calcY(0);
	var mm=parseM(t),mmm=document.plotter2.calcY(1)-bbb;
	if((Math.abs(bb-bbb)<1.0e-10)&&(Math.abs(mm-mmm)<1.0e-10))
	{
		if((mm==1)&&(t.indexOf("1x")>-1))
			alert("Richtig! - Jedoch solltest du statt '1x' einfach 'x' schreiben!");
		else if((mm==-1)&&(t.indexOf("-1x")>-1))
			alert("Richtig! - Jedoch solltest du statt '-1x' einfach '-x' schreiben!");
		else	if(!document.f.nomsg2.checked)alert("Richtig!");
		if(nv2==1){loescheFehler2(TermStr(mm,bb)); statistik(2,true);}
		document.f.term2.value="";
		document.f.term2.focus();
		aufgabe(2);
	}
	else 
	{
		fehleranalyse(bbb,mmm,bb,mm,2);
		speicherFehler2(TermStr(mmm,bbb));
		if(nv2==1)
			{statistik(2,false);alert("Falsch!");document.f.term2.focus();
}
		else
			{
				var meld="Falsch!\n\n"
				if(mm==mmm)meld+="Die Steigung m ist aber schon richtig!\n";
				else if(bb==bbb)meld+="Der Parameter b ist aber schon richtig!\n";
				if((mm==-mmm)&&(mm!=0))meld+="Die Steigung m hat das falsche Vorzeichen.\n";
				if((bb==-bbb)&&(bb!=0))meld+="Der Parameter b hat das falsche Vorzeichen.\n";
				if((nv2>2)&&(mm!=mmm)&&(bbb!=bb))meld+="Den Parameter b (Summand ohne x) liest man am Schnittpunkt mit der y-Achse ab!\n";
				if((nv2>3)&&(mm!=mmm)&&(bbb!=bb))meld+="Der Parameter m (Faktor vor dem x) ist die Steigung der Geraden: Wieviel steigt die Gerade bei jedem Schritt um 1 nach rechts?";
				if(nv2>5){if(!confirm(meld+"\n\nWeitermachen oder Aufgabe abbrechen?","")){aufgeben(2);return;}}
				else alert(meld);
				document.f.term2.focus();
			}
	}
	statistikzeigen();
}

var na3=0;

function test3()
{
	var mm=document.f.term3m.value.replace(/,/g,".").replace(/ /g,""),bb=document.f.term3b.value.replace(/,/g,".").replace(/ /g,"");
	if((mm.charAt(0)=="+")||(bb.charAt(0)=="+"))alert("Die Eingabe des positiven Vorzeichens '+' ist überflüssig!");
	if(mm.indexOf("x")>-1){alert("Die Variable x gehört NICHT zur Steigung.\nDie Steigung m ist der Zahlen-Faktor vor dem x!\n\nFalls in der Gleichung nur x steht, ist m=1, bei -x ist m=-1.");return;}
	if(mm.indexOf("x")>-1){alert("Die Variable x gehört zu KEINEM der Parameter. Die Steigung m ist der Zahlen-Faktor vor dem x, der Parameter b ist der Summand oder Subtrahend ohne x.");return;}
	if((mm=="")||(bb==""))return;
	var mmm=eval(mm),bbb=eval(bb),b=parseB(document.f.term3.value),m=parseM(document.f.term3.value);
	if((Math.abs(mmm-m)<1e-12)&&(Math.abs(bbb-b)<1e-12))
	{
		alert("Richtig");
		na3++;
		if(na3<10){m=Math.floor(Math.random()*6-3);if(m==0)m=1;b=Math.floor(Math.random()*10-5);}
		if(na3>=10){m=Math.floor(Math.random()*10-5)/2;b=Math.floor(Math.random()*10-5)/2;}
		if(na3>=15){m=Math.floor(Math.random()*20-10)/4;b=Math.floor(Math.random()*20-10)/2;}
		if(na3>=25){m=Math.floor(Math.random()*20-10)/Math.floor(Math.random()*9+1);b=Math.floor(Math.random()*10-5)/2;}
		if(na3>=35){m=Math.floor(Math.random()*20-10)/Math.floor(Math.random()*9+1);b=Math.floor(Math.random()*20-10)/Math.floor(Math.random()*9+1);}
		document.f.term3.value=TermStr(m,b);
		document.f.term3b.value="";
		document.f.term3m.value="";
		document.f.term3m.focus();
		return;		
	}
	else if(mmm==m)alert("m ist richtig, b ist falsch");
	else if(bbb==b)alert("b ist richtig, m ist falsch");
}

function aufgeben(typ)
{
	if(typ==1){speicherFehler1(document.f.term1.value);}
	else 
	{
		
		var bbb=document.plotter2.calcY(0);
		var mmm=document.plotter2.calcY(1)-bbb;
		speicherFehler2(TermStr(mmm,bbb));
	}
	fehleranalyse("nix","ixn","xni","xin",typ);
	statistik(typ,false);
	statistikzeigen();
	aufgabe(typ);
}

function speicherFehler1(t)
{
	for(i=0;i<nerr1;i++)if(t==err1[i])return;
	err1[nerr1++]=t;
}
function speicherFehler2(t)
{
	for(i=0;i<nerr2;i++)if(t==err2[i])return;
	err2[nerr2++]=t;
}
function loescheFehler1(t)
{
	for(i=0;i<nerr1;i++)
	if(t==err1[i])
	{
		nerr1--;
		for(j=i;j<nerr1;err1[j++]=err1[j]);
		return;
	}
}

function loescheFehler2(t)
{
	for(i=0;i<nerr2;i++)
	if(t==err2[i])
	{
		for(j=i;j<nerr2-1;j++)err2[j]=err2[j+1];
		nerr2--;
		return;
	}
}

function statistik(typ,richtig)
{
	switch(typ)
	{
	case 1:
		na1++;
		if(!richtig){nf1++;nar1=0;}
		else nar1++;
		if(nar1>nrmax1)nrmax1=nar1;
		break;
	case 2:
		na2++;
		if(!richtig){nf2++;nar2=0;}
		else nar2++;
		if(nar2>nrmax2)nrmax2=nar2;
		break;
	}
	var FQ=(nf1+nf2)/(na1+na2);
	var QC="#"+Hex(255*FQ)+Hex(255-255*FQ)+"00";
	//if(nsc);//document.ampel.style.bgColor=QC;
	//else document.all.ampel.style.backgroundColor=QC;
}

function statistikzeigen()
{
	var t="";
	t+="Anzahl der bearbeiteten Aufgaben:\n   Gerade zeichnen: "+(na1)+"\n   Gleichung finden: "+(na2);
	t+=("\n\nauf Anhieb gelöste Aufgaben:\n   Gerade finden: "+(na1-nf1)+" von "+(na1)+" ("+Runden(100-100*nf1/(na1),1)+"%"+((document.f.Noten.checked)?  " - Note: "+getNote(1-nf1/na1):"")+")\n").replace(/\./g,",");
	t+=("   Gleichung finden: "+(na2-nf2)+" von "+(na2)+" ("+Runden(100-100*nf2/(na2),1)+"%"+((document.f.Noten.checked)?  " - Note: "+getNote(1-nf2/na2):"")+")\n").replace(/\./g,",");
	t+=("   gesamt: "+(na1+na2-nf1-nf2)+" von "+(na1+na2)+" ("+Runden(100-100*(nf1+nf2)/(na1+na2),1)+"%"+((document.f.Noten.checked)?  " - Note: "+getNote(1-(nf1+nf2)/(na1+na2)):"")+")").replace(/\./g,",");
	t+="\n\nlängste Serie ohne Fehler: "+((nrmax1>nrmax2)? nrmax1+ " (Gerade zeichnen)":nrmax2+" (Gleichung finden)");
	var max=0,sf1=0,sf2=0;for(i=0;i<20;i++){if(max<nf[i])max=nf[i];if(i<10)sf1+=nf[i];else sf2+=nf[i];}
	if(sf1+sf2>0)
	{
	t+="\n\nhäufige Fehlertypen:";
	//t+="\n\n"+nf.join(", ");
	var fq="";
	for(i=max;i>max*0.25;i--)
	for(j=0;j<20;j++)
	if(nf[j]==i)
	{
		fq=(": "+Runden(100*nf[j]/nff[(j>9)?2:1],1)+"%").replace(/\./,",")+" aller Fehler";
		switch(j)
		{
		case 0:break;
		case 1:t+="\n• Vorzeichen bei b verwechselt (beim Gerade zeichnen)"+fq;break;
		case 2:t+="\n• Vorzeichen bei m verwechselt (beim Gerade zeichnen)"+fq;break;
		case 3:t+="\n• Statt m den Kehrwehrt 1/m verwendet (beim Gerade zeichnen)"+fq;break;
		case 4:t+="\n• Achsenabschnitt und Steigung vertauscht (beim Gerade zeichnen)"+fq;break;
		case 5:t+="\n• b richtig, m falsch (beim Gerade zeichnen)"+fq;break;
		case 6:t+="\n• m richtig, b falsch (beim Gerade zeichnen)"+fq;break;
		case 7:t+="\n• Steigung als b aufgefaßt (beim Gerade zeichnen)"+fq;break;
		case 8:t+="\n• Achsenabschnitt als Steigung aufgefaßt (beim Gerade zeichnen)"+fq;break;
		case 9:t+="\n• Aufgabe abgebrochen (Gerade zeichnen)"+fq;break;
		case 10:break;
		case 11:t+="\n• Vorzeichen bei b verwechselt (beim Gleichung finden)"+fq;break;
		case 12:t+="\n• Vorzeichen bei m verwechselt (beim Gleichung finden)"+fq;break;
		case 13:t+="\n• Statt m den Kehrwehrt 1/m verwendet (beim Gleichung finden)"+fq;break;
		case 14:t+="\n• Achsenabschnitt und Steigung vertauscht (beim Gleichung finden)"+fq;break;
		case 15:t+="\n• b richtig, aber m falsch (beim Gleichung finden)"+fq;break;
		case 16:t+="\n• m richtig, aber b falsch (beim Gleichung finden)"+fq;break;
		case 17:t+="\n• Steigung als b aufgefaßt (beim Gleichung finden)"+fq;break;
		case 18:t+="\n• Achsenabschnitt als Steigung aufgefaßt (beim Gleichung finden)"+fq;break;
		case 19:t+="\n• Aufgabe abgebrochen (Gleichung finden)"+fq;break;
		default: break;
		}
	}
	if(t.indexOf("typen")==t.length-6)t=t.replace(/\nhäufige Fehlertypen:/,"");
	}	
	t=t.replace(/NaN%/g,"").replace(/Infinity%/g,"").replace(/-Infinity%/g,"");
	if(nerr1+nerr2>0)
	{
		t+="\n\nNicht fehlerlos gelöste Aufgaben:\n1.) Finden der Geraden:\n";
		for(i=0;i<nerr1;i++)t+="    f(x) ="+ err1[i]+"\n";
		if(nerr1==0)t+="    kein Eintrag\n";
		t+="2.) Finden der Funktionsgleichung:\n";
		for(i=0;i<nerr2;i++)t+="    f(x) ="+ err2[i]+"\n";
		if(nerr2==0)t+="    kein Eintrag\n";
	}
	else t+="\n\nAlle gestellten Aufgaben wurden "+((nff[1]+nff[2]==0)?"":"letztlich ")+ "auf Anhieb gelöst."
	document.f.Statistik.value=t;
}


var alsbruch=false;

function TermStr(m,b)
{
	m=Runden(m,12);
	var M=String(m).replace(/\./,",");
	if((M.length-M.indexOf(".")>8)||alsbruch)M=GetBruch(m,0.00000001,1000);
	b=Runden(b,12);
	var B=String(b).replace(/\./,",");
	if((B.length-B.indexOf(".")>8)||alsbruch)B=GetBruch(b,0.00000001,1000);
	var t=" "+M+"·x" + " + "+B+" ";
	t=t.replace(/\+ \-/g,"- ").replace(/ ,/g," 0,").replace(/ 0·x/g," ");
	t=t.replace(/ \+ 0 /g," ").replace(/ 1·x/g," x").replace(/ -1·x/g," -x").replace(/-,/g,"-0,"); 
	if(t.substr(0,4)=="  + ")t=t.substr(3,t.length);
	if(t.substr(0,4)=="  - ")t=" -"+t.substr(4,t.length);
	if(t=="  ")t=" 0";
	return t;
}


function Runden(t,i)
{
	var d=Math.pow(10,i);
	return Math.round(t*d)/d;
}


function GetBruch(x,d,max)
{

	var y;
	for(var i=1;i<=max;i++)
	{
		y=x*i;
		if(Math.abs(y-Math.floor(y+0.5))<=d) {Nenner=i;Zaehler=y; if (i>1.5){return Math.floor(y+0.5)+"/"+i;} else return Math.floor(y+0.5);}
	}
	for(i=1;i<=100;i++)
	{
		y=Math.sqrt(i)*x;
		if(Math.abs(y-Math.floor(y+0.5))<=d) {Nenner=i;Zaehler=y; if (i>1.5){return Math.floor(y+0.5)+"/sqr("+i+")";} else return Math.floor(y+0.5);}
	}
	return String(x).replace(/\./,",");
}

function parseM(t)
{
	t=t.replace(/·/g,"").replace(/,/g,".").replace(/ /g,"").replace(/\*/g,"").replace(/x/g,"*x").replace(/\*+/g,"*").replace(/\-\*/g,"-").replace(/\+\*/g,"+");
	if(t=="")return 0;
	var b=parseB(t);
	t=t.replace(/x/g,"1");
	if(t.charAt(0)=="*")t="1"+t;
//	alert("("+t+")-("+b+")");
	return eval("("+t+")-("+b+")");
}

function parseB(t)
{
	if(t=="")return 0;
	t=t.replace(/x/g,"*x").replace(/·/g,"*").replace(/,/g,".").replace(/\*+/g,"*").replace(/ /g,"");
	t=t.replace(/x/g,"0").replace(/\-\*/g,"-").replace(/\+\*/g,"+");
	if(t.charAt(0)=="*")t="1"+t;
	return eval(t);
}

function Hex(x)
{
	var H=new Array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
	return H[Math.floor(x/16)]+H[x%16];
}

function getNote(p)
{
	var n=(p<.5)?6.5-p*2:4.499-(p-0.5)*8,
	N=Math.round(n);if(N>6)return "6";if(N<1)return "1";
	return N+((n-N>.2)?"-":((N-n>.2)?"+":""));
}

function fehleranalyse(m,b,mv,bv,typ)
{
	nff[typ]++;
	typ=typ*10-10;
	if((m!=mv)&&(b!=bv))nf[typ]++;
	if((b==-bv)&&(b!=0))nf[typ+1]++;
	if((m==-mv)&&(m!=0))nf[typ+2]++;
	if(m==1/mv)nf[typ+3]++;
	if((m!=mv)&&(b==bv))nf[typ+5]++;
	if((m==mv)&&(b!=bv))nf[typ+6]++;
	if(m==bv)nf[typ+7]++;
	if(b==mv)nf[typ+8]++;
	if((m==bv)&&(b==mv))nf[typ+4]++;
	if(isNaN(mv))nf[typ+9]++;
}

