//Karl Rupp, e0325941@stud3.tuwien.ac.at
//Dies ist ein Programmbeispiel in Java in Ergänzung zum Einführungsvortrag von DI Kramer
//im Rahmen des Computer-Mathematik-Praktikum an der TU Wien.
//Die Richtigkeit des Quellcodes kann von mir nicht garantiert werden
//Ich verzichte des weiteren auf jegliches Copyright. Sofern also jemand mit meinem bisschen
//Quellcode hier ein Geschäft machen möchte/kann, dann nur zu! ;-)

//Des weiteren sind Rechtschreibfehler in den Kommentaren auf den geistigen Zustand des Autors zurückzuführen...

///////////////////////Dann los:////////////////////////////////////////

//Programmbeschreibung:
//Hier soll nochmal das Fahrrad-Demo aufgegriffen werden.
//Eine Klasse Fahrrad wird lebensnotwendige Informationen, Daten und Schnittstellen bereitstellen.
//Danach wird eine Klasse TUBike von Fahrrad abgeleitet, die alle Eigenschaften von Fahrrad erbt.
//Zusätzlich ist TU-Bike in der Lage, 2x2-Matrizen zu multiplizieren (ein TU-Bike sollte ja schon "more sophisticated" sein ;-)). 
//Die Matrizen werden ebenfalls über eine eigene Klasse zur Verfügung gestellt.


//Zuerst kommen eventuelle "Imports". Im Prinzip 1:1 mit '#include ...' von C vergleichbar.
//import java.math.*;								//Wird hier nicht benötigt!


public class JavaDemo1{ 		//die Hauptklasse. Muss gleich heißen wie die Java-Datei! Dies ist der Ausgangspunkt des Programms.
	
	public static void main (String args[]){		//"Startfunktion" des gesamten Programms.
		
		Fahrrad drahtesel = new Fahrrad("Drahtesel");		//Deklarieren wir hier unsere Variable/unser Objekt 'Fahrrad'
		TUBike flottelotte = new TUBike("Flotte Lotte", 24);					//Hier unser TU-Bike mit 24 Gängen!!
		
		//Dann lassen wir drahtesel mal laufen:´
		drahtesel.gibGas(10);
		drahtesel.printInformation();
		
		//Auch die Flotte Lotte möchte fahren:
		flottelotte.gibGas(10);
		flottelotte.raufschalten();		//haha, Gangschaltung!!
		flottelotte.gibGas(5);
		flottelotte.printInformation();
		
		//So, jetzt soll Flotte Lotte mal zwei Matrizen multiplizieren:
		Matrix m1 = new Matrix(2,3,4,1);
		Matrix m2 = new Matrix(4,2,3,2);
		Matrix ergebnis = new Matrix();

		System.out.println("Matrix 1:");		
		m1.printMatrix();
		System.out.println("Matrix 2:");		
		m2.printMatrix();
		ergebnis = flottelotte.MatrixMultiplizierer(m1, m2);
		System.out.println("Matrix 1 * Matrix 2:");		
		ergebnis.printMatrix();
		
		//Zur Belohnung darf Flotte Lotte schneller fahren:
		flottelotte.raufschalten();
		flottelotte.gibGas(30);				//Jetzt wird sie stürzen!!!
		flottelotte.printInformation();
				
		//Genug geblödelt, aufhören:
		System.out.println("CU @ Uni! Bye!");
			
	} //main()
	
	
}  //class




//Unser Objekt Fahrrad. Was kann das alles: beschleunigen, bremsen, stürzen, Geschwindigkeit anzeigen.
class Fahrrad{					
	
	private int speed;					//Geschwindigkeit,		'private' sagt, dass kein direkter Zugriff von außen auf die Variable möglich ist
	private int damage;					//Zustand
	private String name;				//Name
	
	Fahrrad(String newname){	//Der "Konstruktor". Diese Funktion wird automatisch aufgerufen, wenn ein neues Objekt dieses Typs initialisiert wird.
								//wird meist dazu verwendet, die internen Variablen zu initialisieren. Ist aber nicht unbedingt notwendig.
								//Dem Konstruktor können auch wie hier Variablen übergeben werden, wie bei einer normalen Funktion. 
		
		//Initialisieren des Fahrrades:
		speed = 0;						//zuerst soll es mal ruhig stehen. Ist äquivalent mit 'this.speed = 0;'
		damage = 0;						//Zumindest am Anfang sollte das Fahrrad noch OK sein...
		name = newname;					//Bei Strings ist Java flexibler/angenehmer als C.
		
	} //Fahrrad()
	
	
	public void gibGas(int delta){						//Beschleunigen um den Wert delta
		
		if (delta > 0 && damage < 100)					//ist delta gültig und das Rad fahrtüchtig?
			speed = delta + speed;						//hier erkennt man die "Sicherheit" von Objekten. Der Benutzer kann von außen keine ungültigen Werte mehr setzen
		
		if (speed > 40)									//zu schnell sollen wir nicht fahren, sonst haut es uns auf...
			stürzen();									
		
	} //gibGas()
	
	public void bremsen(int delta){						//Um den Wert delta bremsen
		
		if (delta > 0)									//Gültigen Wert überprüfen
			speed = speed - delta;
		
		if (speed < 0)									//Rückwärts fahren gibt es nicht!
			speed = 0;
		
	} //bremsen()
	
	public void stürzen(){								//Oje, zu schnell unterwegs.
		
		System.out.println("Zu schnell unterwegs! Ein Sturz war leider unvermeidbar.");		//Den User über sein Mißgeschick informieren

		if (damage < 90)								//Durch übermäßigen Bodenkontakt nimmt das Fahrrad Schaden
			damage = damage + 10;
		else{
			damage = 100;	
			System.out.println("Leider ist " + name + " jetzt hin!");
		}	
		speed = 0;										//und Geschwindigkeit ist dann auch Geschichte...
		
	} //stürzen()
	
	public void printInformation(){						//Ausgabe der Information über das Fahrrad
		
		System.out.println("------------");
		System.out.println(">>Information über " + name + "<<");		//Anmerkung: System.out.println ist im Praktikum eventuell durch etwas anderes zu ersetzen! Auf die Ausgabe kommt wohl insgesamt nicht an
		System.out.println("Geschwindigkeit: " + speed);
		System.out.println("Schaden: " + damage);
		
	} //printInformation()
	
	
} //class




//TUBike ist von Fahrrad abgeleitet, erbt also alle Funktionen von der Klasse Fahrrad
//Daher ist TUBike eine Subklasse von Fahrrad und Fahrrad die Superklasse von TUBike

class TUBike extends Fahrrad{						
	
	
	private int gear_num;								//Anzahl der Gänge
	private int gear;									//zusätzlich hat TUBike noch Gänge.

	TUBike(String name, int gaenge){					//zusätzlich zum Fahrrad-Konstruktor müssen wir noch die Gänge initialisieren

		super(name);									//ruft den Konstruktor von Fahrrad auf						
		gear_num = gaenge;								//setzt die Ganganzahl
		gear = 1;										//aktueller Gang

	} //TUBike()

	public int whichGear(){								//gibt den eingelegten Gang zurück

		return gear; 

	} //whichGear()
	
	public void raufschalten(){

		if (gear < gear_num)
			gear++;

	} //raufschalten()
	
	public void runterschalten(){

		if (gear > 1)
			gear--;

	} //runterschalten()


	//Es ist auch möglich, Funktionen der Superklasse zu überschreiben. Hier wollen wir nun auch unsere Gänge ausgeben:	
	public void printInformation(){							

		super.printInformation();							//Zuerst lassen wir "printInformation()" der Superklasse Fahrrad aufrufen
		System.out.println("Gang: " + gear + " von " + gear_num);		//zusätzlich soll eben der Gang ausgegeben werden.

	} //printInformation();
	
	//Schließlich unsere tolle TUBike-Matrix-Multiplikationsfähigkeit!!!	
	public Matrix MatrixMultiplizierer(Matrix m1, Matrix m2){	

		Matrix result = new Matrix();						//Einheitsmatrix 
	
		result.setValue(0, 0, m1.getValue(0,0)*m2.getValue(0,0) + m1.getValue(0,1)*m2.getValue(1,0));
		result.setValue(1, 0, m1.getValue(1,0)*m2.getValue(0,0) + m1.getValue(1,1)*m2.getValue(1,0));
		result.setValue(0, 1, m1.getValue(0,0)*m2.getValue(0,1) + m1.getValue(0,1)*m2.getValue(1,1));
		result.setValue(1, 1, m1.getValue(1,0)*m2.getValue(0,1) + m1.getValue(1,1)*m2.getValue(1,1));
	
		return result;	

	} //MatrixMultiplizierer()
	
} //class




//Die Klasse Matrix (nicht "Die klasse Matrix" ;-)). Sehr minimalistisch und an den Haaren herbeigezogen. Kann immerhin die Determinante berechnen und transponieren!
class Matrix{										
	
	private int[][] eintraege = new int[2][2];				//Die Matrixeinträge. Erster Index: Zeile, zweiter Index: Spalte

	Matrix(){
		
		this(1, 0, 0, 1);								//Dies ruft Matrix(1,0,0,1) auf. Es entspricht also einer "Weiterleitung" an einen anderen, besseren/flexibleren Konstruktor.
		
	} //Matrix()
	
	Matrix(int lo, int lu, int ro, int ru){				//Die Matrix
		
		eintraege[0][0] = lo;							//links oben
		eintraege[0][1] = ro;							//rechts oben
		eintraege[1][0] = lu;							//links unten
		eintraege[1][1] = ru;							//rechts unten

	}	//Matrix(lo,lu,ro,ru)

	public int getValue(int row, int col){				//Eintrag an Zeile row und Spalte col zurückgeben

		return eintraege[row][col];

	} //getValue()


	public void setValue(int row, int col, int value){					//Wert value in Zeile row und Spalte col setzen

		eintraege[row][col] = value;

	} //setValue()


	public int getDeterminante(){						//Gibt die Determinante zurück
		
		return eintraege[0][0] * eintraege[1][1] - eintraege[1][0] * eintraege[0][1];
	
	} //getDeterminante()
	
	public void printMatrix(){							//Matrix ausgeben
	
		System.out.println("-------");
		System.out.println(eintraege[0][0] + " " + eintraege[0][1]);
		System.out.println(eintraege[1][0] + " " + eintraege[1][1]);
		System.out.println("-------");
	
	} //printMatrix()
	
	public void transponieren(){						//Bei 2x2-Matrizen soll ja transponieren nicht so schwer sein...
	
		int temp;
		temp = eintraege[0][1];
		eintraege[0][1] = eintraege[1][0];
		eintraege[1][0] = temp;
	
	} //transponieren
	

} //class


//Abschließende Worte:
//Sofern Bedarf besteht, kann ich dieses Programm auch erweitern. Beispielsweise wäre eine interaktive Steuerung
//über die Kommandozeile vorstellbar... ;-)

