/*
* Datei: CompLeaf.java
* Autor(en): Lukas K�nig
* Java-Version: 6.0
* Erstellt (vor): 31.10.2008
*
* (c) Lukas K�nig, die Datei unterliegt der LGPL
* -> http://www.gnu.de/lgpl-ger.html
*/
package fmg.fmg8.endlAutomat.conditions;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import fmg.fmg8.endlAutomat.Konstanten;
import fmg.fmg8.endlAutomat.translator.Translator;
import fmg.fmg8.sonstiges.SonstMeth;
import fmg.fmg8.umgebung2D.Roboter;
/**
* @author lko
*
*/
public class CompLeaf implements Condition, Serializable {
/**
* ID vom 25.09.2008.
*/
private static final long serialVersionUID = -5491830944979761296L;
/**
* Der erste Operand.
*/
private int operand1;
/**
* Ob der erste Operand ein Sensor ist.
*/
private boolean sensor1;
/**
* Der zweite Operand.
*/
private int operand2;
/**
* Ob der zweite Operand ein Sensor ist.
*/
private boolean sensor2;
/**
* Der Operator.
*/
private char operator;
/**
* Konstruktor eines nicht-konstanten Bedingungsblattes.
*
* @param op1 Der erste Operand.
* @param op2 Der zweite Operand.
* @param sens1 Ob der erste Operand eine Sensorvariable ist.
* @param sens2 Ob der zweite Operand eine Sensorvariable ist.
* @param op Der Operator.
*/
public CompLeaf(final int op1,
final int op2,
final boolean sens1,
final boolean sens2,
final char op) {
this.operand1 = op1;
this.operand2 = op2;
this.sensor1 = sens1;
this.sensor2 = sens2;
this.operator = op;
}
/**
* Evaluiert die gegebene Bedingung.
*
* @param sens Sensoren.
* @return Ob die Bedingung zu "true" evaluiert.
*/
@Override
public boolean evaluiereSens(final int[] sens) {
int zahl1;
int zahl2;
if (this.sensor1) {
zahl1 = sens[this.operand1 - 1];
} else {
zahl1 = this.operand1;
}
if (this.sensor2) {
zahl2 = sens[this.operand2 - 1];
} else {
zahl2 = this.operand2;
}
if (this.operator == Konstanten.GL) {
return zahl1 == zahl2;
} else if (this.operator == Konstanten.GR) {
return zahl1 > zahl2;
} else if (this.operator == Konstanten.KL) {
return zahl1 < zahl2;
} else if (this.operator == Konstanten.GRGL) {
return zahl1 >= zahl2;
} else if (this.operator == Konstanten.KLGL) {
return zahl1 <= zahl2;
} else if (this.operator == Konstanten.UGL) {
return zahl1 != zahl2;
} else if (this.operator == Konstanten.UNGF) {
return SonstMeth.ungefGleich(zahl1,
zahl2,
fmg.fmg8.umgebung2D.Konstanten.UNGEF_KONST);
} else if (this.operator == Konstanten.NUNGF) {
return !SonstMeth.ungefGleich(zahl1,
zahl2,
fmg.fmg8.umgebung2D.Konstanten.UNGEF_KONST);
}
throw new RuntimeException("Kein G�ltiges Bedingungsblatt.");
}
/**
* Evaluiert die gegebene Bedingung.
*
* @param aut Roboter mit zugrundeliegenden Sensoren.
* @return Ob die Bedingung zu "true" evaluiert.
*/
public boolean evaluiere(final Object aut) {
int zahl1;
int zahl2;
Roboter rob;
Translator trans;
if (aut == null) {
zahl1 = this.operand1;
zahl2 = this.operand2;
} else if (aut.getClass().equals(Roboter.class)) {
rob = (Roboter) aut;
if (this.sensor1) {
zahl1 = rob.getSensorWert(this.operand1 - 1);
} else {
zahl1 = this.operand1;
}
if (this.sensor2) {
zahl2 = rob.getSensorWert(this.operand2 - 1);
} else {
zahl2 = this.operand2;
}
} else if (aut.getClass().equals(Translator.class)) {
trans = (Translator) aut;
if (this.sensor1) {
zahl1 = trans.getH(this.operand1);
} else {
zahl1 = this.operand1;
}
if (this.sensor2) {
zahl2 = trans.getH(this.operand2);
} else {
zahl2 = this.operand2;
}
} else {
throw new RuntimeException(
"Falscher Klassentyp an Evaluierung uebergeben.");
}
if (this.operator == Konstanten.GL) {
return zahl1 == zahl2;
} else if (this.operator == Konstanten.GR) {
return zahl1 > zahl2;
} else if (this.operator == Konstanten.KL) {
return zahl1 < zahl2;
} else if (this.operator == Konstanten.GRGL) {
return zahl1 >= zahl2;
} else if (this.operator == Konstanten.KLGL) {
return zahl1 <= zahl2;
} else if (this.operator == Konstanten.UGL) {
return zahl1 != zahl2;
} else if (this.operator == Konstanten.UNGF) {
return SonstMeth.ungefGleich(zahl1,
zahl2,
fmg.fmg8.umgebung2D.Konstanten.UNGEF_KONST);
} else if (this.operator == Konstanten.NUNGF) {
return !SonstMeth.ungefGleich(zahl1,
zahl2,
fmg.fmg8.umgebung2D.Konstanten.UNGEF_KONST);
}
throw new RuntimeException("Kein G�ltiges Bedingungsblatt.");
}
/**
* Vereinfacht die Bedingung. Dabei wird folgende Normalform N erzeugt (die
* die semantische Ausdruckskraft der Bedingung nicht einschr�nkt): <BR>
* <BR>
* N ::= true | false | C <BR>
* C ::= H comp B | H comp H | (C op C) <BR>
* H ::= h1 | h2 | ... <BR>
* B ::= 1 | 2 | ... | 255 <BR>
* comp ::= < | > | = | ! | [ | ] | ~ | # <BR>
* op ::= UND | ODER <BR>
* <BR>
* N.b. Insbesondere kommen true und false nicht in zusammengesetzten
* Bedingungen vor.
*
* @return Die vereinfachte Bedingung.
*/
public Condition simplify() {
if (this.sensor1 || this.sensor2) {
if (this.sensor1 && this.sensor2) {
if (this.operand1 == this.operand2) {
if (this.operator == Konstanten.GL
|| this.operator == Konstanten.GRGL
|| this.operator == Konstanten.KLGL
|| this.operator == Konstanten.UNGF) {
return new ConstLeaf(true);
} else {
return new ConstLeaf(false);
}
}
}
if (this.sensor1) {
return this;
} else {
char umOp = this.umOp();
CompLeaf c = new CompLeaf(this.operand2,
this.operand1,
this.sensor2,
this.sensor1,
umOp);
return c;
}
} else {
if (this.evaluiere(null)) {
return new ConstLeaf(true);
} else {
return new ConstLeaf(false);
}
}
}
/**
* Gibt den gedrehten Operator von this zur�ck.
*
* @return Gedrehter Operator von this.
*/
public char umOp() {
char umOp = this.operator;
if (this.operator == Konstanten.GRGL) {
umOp = Konstanten.KLGL;
} else if (this.operator == Konstanten.GR) {
umOp = Konstanten.KL;
} else if (this.operator == Konstanten.KLGL) {
umOp = Konstanten.GRGL;
} else if (this.operator == Konstanten.KL) {
umOp = Konstanten.GR;
}
return umOp;
}
/**
* @return Die Bedingung als Textausgabe.
*/
public String toString() {
String op1;
String op2;
String comp = "" + this.operator;
if (this.sensor1) {
op1 = "h" + this.operand1;
} else {
op1 = "" + this.operand1;
}
if (this.sensor2) {
op2 = "h" + this.operand2;
} else {
op2 = "" + this.operand2;
}
if (this.operator == Konstanten.GRGL) {
comp = ">=";
} else if (this.operator == Konstanten.KLGL) {
comp = "<=";
} else if (this.operator == Konstanten.NUNGF) {
comp = "!~";
} else if (this.operator == Konstanten.UGL) {
comp = "!=";
}
return op1 + " " + comp + " " + op2;
}
/**
* @return Returns the operand1.
*/
public int getOperand1() {
return this.operand1;
}
/**
* @return Returns the sensor1.
*/
public boolean isSensor1() {
return this.sensor1;
}
/**
* @return Returns the operand2.
*/
public int getOperand2() {
return this.operand2;
}
/**
* @return Returns the sensor2.
*/
public boolean isSensor2() {
return this.sensor2;
}
/**
* @return Returns the operator.
*/
public char getOp() {
return this.operator;
}
/**
* Gibt die in <code>this</code> vorkommenden Variablen zur�ck.
*
* @return Die Variablenliste.
*/
public Set<Integer> variablenListe() {
Set<Integer> liste = new HashSet<Integer>();
if (this.sensor1) {
liste.add(new Integer(this.operand1));
}
if (this.sensor2) {
liste.add(new Integer(this.operand2));
}
return liste;
}
/**
* Gibt die Bedingung formatiert (nach der in EndlicherAutomat benutzten
* Konvention zur�ck. Das bedeutet im Wesentlichen, dass drei Buchstaben
* ein Zeichen darstellen.
*
* @return Die formatierte Bedingung.
*/
public String formatted() {
String op1;
String op2;
if (this.sensor1) {
op1 = " h " + SonstMeth.normZahl(this.operand1);
} else {
op1 = "" + SonstMeth.normZahl(this.operand1);
}
if (this.sensor2) {
op2 = " h " + SonstMeth.normZahl(this.operand2);
} else {
op2 = "" + SonstMeth.normZahl(this.operand2);
}
return op1 + " " + this.operator + " " + op2;
}
/**
* Gibt <code>true</code>.
*
* @return Ob die Bedingung ein Blatt ist.
*/
public boolean isLeaf() {
return true;
}
/**
* Negiert das Komparationsblatt.
*/
@Override
public void negiere() {
if (this.operator == Konstanten.GL) {
this.operator = Konstanten.UGL;
} else if (this.operator == Konstanten.UGL) {
this.operator = Konstanten.GL;
} else if (this.operator == Konstanten.UNGF) {
this.operator = Konstanten.NUNGF;
} else if (this.operator == Konstanten.NUNGF) {
this.operator = Konstanten.UNGF;
} else if (this.operator == Konstanten.KL) {
this.operator = Konstanten.GRGL;
} else if (this.operator == Konstanten.GRGL) {
this.operator = Konstanten.KL;
} else if (this.operator == Konstanten.GR) {
this.operator = Konstanten.KLGL;
} else if (this.operator == Konstanten.KLGL) {
this.operator = Konstanten.GR;
}
}
/**
* Gibt die Nummern der aktiven Sensoren zur�ck.
*
* @return Die Nummern der aktiven Sensoren.
*/
@Override
public HashSet<Integer> aktSens() {
HashSet<Integer> l = new HashSet<Integer>();
if (this.sensor1) {
l.add(this.operand1);
}
if (this.sensor2) {
l.add(this.operand2);
}
return l;
}
/**
* Die Hashcode-Methode.
*
* @return Der Hashcode.
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + this.operand1;
result = prime * result + this.operand2;
result = prime * result + this.operator;
result = prime * result + (this.sensor1 ? 1231 : 1237);
result = prime * result + (this.sensor2 ? 1231 : 1237);
return result;
}
/**
* Die equals-Methode.
*
* @param obj Das zu vergleichende Objekt.
*
* @return Ob die Objekte gleich sind.
*/
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final CompLeaf other = (CompLeaf) obj;
if (this.operand1 != other.operand1) {
return false;
}
if (this.operand2 != other.operand2) {
return false;
}
if (this.operator != other.operator) {
return false;
}
if (this.sensor1 != other.sensor1) {
return false;
}
if (this.sensor2 != other.sensor2) {
return false;
}
return true;
}
}