diff --git a/uebung07/src/oop/ch02/cards/Card.java b/uebung07/src/oop/ch02/cards/Card.java new file mode 100644 index 0000000..c903159 --- /dev/null +++ b/uebung07/src/oop/ch02/cards/Card.java @@ -0,0 +1,79 @@ +package oop.ch02.cards; + +/** + * Represents any card with a name and a unique serial number. + * + * @author Mark Minas + */ +public class Card { + /** + * The name of this card. + */ + private final String name; + + /** + * Counts the number of instantiations of this class. + */ + private static int counter = 0; + + /** + * The unique serial number of this card. + */ + private final int number; + + /** + * Creates a new card with the specified name. + * + * @param name the name of this card + */ + public Card(String name) { + if (name == null) + throw new NullPointerException("name is null"); + this.name = name; + this.number = ++counter; + } + + /** + * Creates a new card for a student with the specified number. + * + * @param num the student's number + */ + public Card(int num) { + this("MatrNr. " + num); + } + + /** + * Returns the name of this card. + * + * @return the name + */ + public String getName() { + return name; + } + + /** + * Returns the serial number of this card. + * + * @return the serial number + */ + public int getNumber() { + return number; + } + + /** + * Returns the number of instantiations of this class. + * + * @return the number of instantiations. + */ + public static int getCounter() { + return counter; + } + + /** + * Returns a string representation of this card. + */ + @Override + public String toString() { + return "Card " + name + " (no " + number + ")"; + } +} diff --git a/uebung07/src/oop/ch05/mensa/AccountCard.java b/uebung07/src/oop/ch05/mensa/AccountCard.java new file mode 100644 index 0000000..b74f3a4 --- /dev/null +++ b/uebung07/src/oop/ch05/mensa/AccountCard.java @@ -0,0 +1,34 @@ +package oop.ch05.mensa; + +import oop.ch05.secured.AuthorizationException; +import oop.ch05.secured.SecuredContent; +import oop.ch05.secured.SecurityClient; + +public class AccountCard extends MensaCard { + private final SecuredContent account; + + public AccountCard(String key, String account, int password) { + super(key, Color.white); + this.account = new SecuredContent(password, account); + } + + public String getAccount() { + return (String) account.getContent(); + } + + public void setAccount(SecurityClient client, String account) throws AuthorizationException { + if (account == null || account.trim().length() == 0) + throw new IllegalArgumentException("Invalid account " + account); + this.account.setContent(client, account); + } + + @Override + public String toString() { + return super.toString() + " for account " + account.getContent(); + } + + @Override + public void pass(CashPoint cashPoint) { + cashPoint.charge(this); + } +} diff --git a/uebung07/src/oop/ch05/mensa/CashCard.java b/uebung07/src/oop/ch05/mensa/CashCard.java new file mode 100644 index 0000000..810f6d0 --- /dev/null +++ b/uebung07/src/oop/ch05/mensa/CashCard.java @@ -0,0 +1,43 @@ +package oop.ch05.mensa; + +import oop.ch05.secured.AuthorizationException; +import oop.ch05.secured.SecuredContent; + +public class CashCard extends MensaCard { + private final SecuredContent balance; + + public CashCard(String key, Color color, int password) { + super(key, color); + balance = new SecuredContent(password, 0); + if (color != Color.blue && color != Color.green) + throw new IllegalArgumentException("Invalid CashCard color " + color); + } + + public int getBalance() { + return (Integer) balance.getContent(); + } + + void deposit(VendingMachine client, int cents) + throws AuthorizationException { + if (cents <= 0) + throw new IllegalArgumentException("Non-positive deposit"); + final int newBalance = getBalance() + cents; + balance.setContent(client, newBalance); + } + + void charge(CashPoint client, int cents) throws AuthorizationException { + if (cents < 0) + throw new IllegalArgumentException("Negative charge"); + balance.setContent(client, getBalance() - cents); + } + + @Override + public String toString() { + return super.toString() + " with " + balance.getContent() + " cents"; + } + + @Override + public void pass(CashPoint cashPoint) throws AuthorizationException, RejectedException { + cashPoint.charge(this); + } +} diff --git a/uebung07/src/oop/ch05/mensa/CashPoint.java b/uebung07/src/oop/ch05/mensa/CashPoint.java new file mode 100644 index 0000000..832899b --- /dev/null +++ b/uebung07/src/oop/ch05/mensa/CashPoint.java @@ -0,0 +1,64 @@ +package oop.ch05.mensa; + +import oop.ch05.secured.AuthorizationException; +import oop.ch05.secured.SecurityClient; + +public class CashPoint implements SecurityClient { + private final int password; + public final String name; + private int counter; + private int cents; + + public CashPoint(String name, int password) { + this.name = name; + this.password = password; + this.counter = 0; + this.cents = 0; + } + + @Override + public int challengeResponse(int challenge) { + return challenge ^ password; + } + + @Override + public String toString() { + return "Cash point " + name + " (" + getCounter() + " meals, " + getCents() + " cents charged)"; + } + + public int getCounter() { + return counter; + } + + public int getCents() { + return cents; + } + + private int getPrice(Color color) { + return switch (color) { + case green -> 267; + case blue -> 357; + case white -> 495; + default -> 0; + }; + } + + void count(MensaCard card) { + counter++; + } + + void charge(CashCard cashCard) throws AuthorizationException, RejectedException { + final int price = getPrice(cashCard.color); + if (cashCard.getBalance() < price) + throw new RejectedException("insufficient payment"); + cashCard.charge(this, price); + count(cashCard); + cents += price; + } + + void charge(AccountCard accountCard) { + final int price = getPrice(accountCard.color); + System.out.println("Charging " + price + " cents on account " + accountCard.getAccount()); + cents += price; + } +} diff --git a/uebung07/src/oop/ch05/mensa/Color.java b/uebung07/src/oop/ch05/mensa/Color.java new file mode 100644 index 0000000..13945c7 --- /dev/null +++ b/uebung07/src/oop/ch05/mensa/Color.java @@ -0,0 +1,5 @@ +package oop.ch05.mensa; + +public enum Color { + green, red, blue, white, gray +} diff --git a/uebung07/src/oop/ch05/mensa/CountCard.java b/uebung07/src/oop/ch05/mensa/CountCard.java new file mode 100644 index 0000000..f0c32d3 --- /dev/null +++ b/uebung07/src/oop/ch05/mensa/CountCard.java @@ -0,0 +1,15 @@ +package oop.ch05.mensa; + +public class CountCard extends MensaCard { + + public CountCard(String key, Color color) { + super(key, color); + if (color != Color.red && color != Color.gray) + throw new IllegalArgumentException("Invalid CountCard color " + color); + } + + @Override + public void pass(CashPoint cashPoint) { + cashPoint.count(this); + } +} diff --git a/uebung07/src/oop/ch05/mensa/MensaCard.java b/uebung07/src/oop/ch05/mensa/MensaCard.java new file mode 100644 index 0000000..cf0be76 --- /dev/null +++ b/uebung07/src/oop/ch05/mensa/MensaCard.java @@ -0,0 +1,20 @@ +package oop.ch05.mensa; + +import oop.ch02.cards.Card; +import oop.ch05.secured.AuthorizationException; + +public abstract class MensaCard extends Card { + public final Color color; + + protected MensaCard(String name, Color color) { + super(name); + this.color = color; + } + + @Override + public String toString() { + return color + " card " + getNumber() + " (" + getName() + ")"; + } + + public abstract void pass(CashPoint cashPoint) throws RejectedException, AuthorizationException; +} \ No newline at end of file diff --git a/uebung07/src/oop/ch05/mensa/MensaExample.java b/uebung07/src/oop/ch05/mensa/MensaExample.java new file mode 100644 index 0000000..478c549 --- /dev/null +++ b/uebung07/src/oop/ch05/mensa/MensaExample.java @@ -0,0 +1,68 @@ +package oop.ch05.mensa; + +import oop.ch05.secured.AuthorizationException; + +public class MensaExample { + public static void main(String[] args) { + VendingMachine vm1 = new VendingMachine("left", 4711); + VendingMachine vm2 = new VendingMachine("right", 4711); + VendingMachine tumVM = new VendingMachine("TUM Mensa", 3141); + CashPoint unibwMensa = new CashPoint("UniBw Mensa", 4711); + + AccountCard conf = new AccountCard("conference", "33-1298", 42); + MensaCard frankSmith = new CountCard("Frank Smith", Color.gray); + CashCard hansMueller = new CashCard("Hans Müller", Color.green, 4711); + CashCard peterSchmidt = new CashCard("Peter Schmidt", Color.green, 4711); + CashCard thomasMayer = new CashCard("Thomas Mayer", Color.blue, 4711); + + deposit(vm1, hansMueller, 10); + deposit(vm1, peterSchmidt, 5); + deposit(vm2, thomasMayer, 2); + deposit(tumVM, hansMueller, 10); + + System.out.println(vm1); + System.out.println(vm2); + System.out.println(tumVM); + System.out.println(hansMueller); + System.out.println(peterSchmidt); + System.out.println(thomasMayer); + System.out.println(); + + pass(hansMueller, unibwMensa); + System.out.println(hansMueller); + System.out.println(unibwMensa); + + pass(frankSmith, unibwMensa); + pass(conf, unibwMensa); + pass(thomasMayer, unibwMensa); + pass(hansMueller, unibwMensa); + pass(hansMueller, unibwMensa); + pass(hansMueller, unibwMensa); + + System.out.println(unibwMensa); + System.out.println(hansMueller); + System.out.println(peterSchmidt); + System.out.println(thomasMayer); + } + + private static void pass(MensaCard mensaCard, CashPoint cashPoint) { + try { + mensaCard.pass(cashPoint); + } + catch (RejectedException e) { + System.out.println("rejected: " + e.getMessage()); + } + catch (AuthorizationException e) { + System.out.println("authrozation failed: " + e.getMessage()); + } + } + + private static void deposit(VendingMachine vm, CashCard cashCard, int euros) { + try { + vm.deposit(cashCard, euros); + } + catch (AuthorizationException e) { + System.out.println("authorization failed: " + e.getMessage()); + } + } +} diff --git a/uebung07/src/oop/ch05/mensa/RejectedException.java b/uebung07/src/oop/ch05/mensa/RejectedException.java new file mode 100644 index 0000000..c51c48b --- /dev/null +++ b/uebung07/src/oop/ch05/mensa/RejectedException.java @@ -0,0 +1,7 @@ +package oop.ch05.mensa; + +public class RejectedException extends Exception { + public RejectedException(String message) { + super(message); + } +} diff --git a/uebung07/src/oop/ch05/mensa/VendingMachine.java b/uebung07/src/oop/ch05/mensa/VendingMachine.java new file mode 100644 index 0000000..b2e80ec --- /dev/null +++ b/uebung07/src/oop/ch05/mensa/VendingMachine.java @@ -0,0 +1,37 @@ +package oop.ch05.mensa; + +import oop.ch05.secured.AuthorizationException; +import oop.ch05.secured.SecurityClient; + +public class VendingMachine implements SecurityClient { + private final int password; + public final String name; + private int euros; + + public VendingMachine(String name, int password) { + this.name = name; + this.password = password; + this.euros = 0; + } + + @Override + public int challengeResponse(int challenge) { + return challenge ^ password; + } + + @Override + public String toString() { + return "Vending machine " + name + " (contains EUR " + euros + ")"; + } + + public int getEuros() { + return euros; + } + + public void deposit(CashCard card, int euros) throws AuthorizationException { + if (euros <= 0) + throw new IllegalArgumentException("Non-positive deposit"); + card.deposit(this, euros * 100); + this.euros += euros; + } +} diff --git a/uebung07/src/oop/ch05/secured/AuthorizationException.java b/uebung07/src/oop/ch05/secured/AuthorizationException.java new file mode 100644 index 0000000..325c201 --- /dev/null +++ b/uebung07/src/oop/ch05/secured/AuthorizationException.java @@ -0,0 +1,20 @@ +package oop.ch05.secured; + +/** + * This class represents exceptions that are thrown whenever an authorization + * fails. + * + * @author Mark Minas + */ +public class AuthorizationException extends Exception { + /** + * Constructs a new authorization exception with the specified detail message + * and cause. + * + * @param message the detail message (which is saved for later retrieval by the + * {@link #getMessage()} method). + */ + public AuthorizationException(String message) { + super(message); + } +} diff --git a/uebung07/src/oop/ch05/secured/SecuredContent.java b/uebung07/src/oop/ch05/secured/SecuredContent.java new file mode 100644 index 0000000..1426aaf --- /dev/null +++ b/uebung07/src/oop/ch05/secured/SecuredContent.java @@ -0,0 +1,79 @@ +package oop.ch05.secured; + +import java.util.Random; + +/** + * Represents containers for some content that is secured against modifications + * by a challenge-response approach. The content may be read at any time, but + * only authorized clients are allowed to modify the contents. + * + * @author Mark Minas + */ +public class SecuredContent { + /** + * The actual, secured content + */ + private Object content; + /** + * A random number generator used for generating challenges. + */ + private final Random random = new Random(); + /** + * The password used for encryption. + */ + private final int password; + + /** + * Creates a new container containing the specified contents. + * + * @param password this password is used for computing the expected response for a + * challenge. + * @param content the contained content + */ + public SecuredContent(int password, Object content) { + this.password = password; + this.content = content; + } + + /** + * Returns the contained contents. There is no authorization necessary for + * reading the contents. + */ + public Object getContent() { + return content; + } + + /** + * Sets the new contained contents. Only authorized clients are allowed to do + * so. + * + * @param client The accessing client. Authorization is checked prior to really + * modifying he contained content. + * @param content The new contained contents + * @throws AuthorizationException if the specified client cannot authorize himself + */ + public void setContent(SecurityClient client, Object content) + throws AuthorizationException { + final int challenge = nextChallenge(); + if (client.challengeResponse(challenge) != requiredResponse(challenge)) + throw new AuthorizationException(client + + " is not authorized to access contents."); + this.content = content; + } + + /** + * Computes the next random challenge. + */ + private int nextChallenge() { + return random.nextInt(); + } + + /** + * Returns the expected response for the specified challenge. + * + * @param challenge an arbitrary integer used as a challenge + */ + private int requiredResponse(int challenge) { + return challenge ^ password; + } +} diff --git a/uebung07/src/oop/ch05/secured/SecurityClient.java b/uebung07/src/oop/ch05/secured/SecurityClient.java new file mode 100644 index 0000000..760bfd9 --- /dev/null +++ b/uebung07/src/oop/ch05/secured/SecurityClient.java @@ -0,0 +1,18 @@ +package oop.ch05.secured; + +/** + * This interface must be implemented by any client that is going to be + * authorized by a challenge-response approach. + * + * @author Mark Minas + */ +public interface SecurityClient { + /** + * Returns the response for the specified challenge. Authorization succeeds + * if this response is the same as the one expected by the server. + * + * @param challenge the integer number for which the correct response has to be + * computed. + */ + int challengeResponse(int challenge); +} diff --git a/uebung07/src/quantities/plain/Length.java b/uebung07/src/quantities/plain/Length.java new file mode 100644 index 0000000..b8a2b23 --- /dev/null +++ b/uebung07/src/quantities/plain/Length.java @@ -0,0 +1,46 @@ +package quantities.plain; + +import static quantities.plain.LengthUnit.METER; +import static quantities.plain.TimeUnit.SECOND; +import static quantities.plain.VelocityUnit.METER_PER_SECOND; + +public class Length extends Quantity { + private final LengthUnit unit; + + public Length(double value, LengthUnit unit) { + super(value, unit); + this.unit = unit; + } + + public Length plus(Length other) { + return new Length(value + other.getBaseValue() / unit.baseFactor, unit); + } + + public Length minus(Length other) { + return new Length(value - other.getBaseValue() / unit.baseFactor, unit); + } + + public Length mult(double f) { + return new Length(value * f, unit); + } + + public Length div(double f) { + return new Length(value / f, unit); + } + + public Length to(LengthUnit unit) { + return new Length(getBaseValue() / unit.baseFactor, unit); + } + + public double div(Length other) { + return getBaseValue() / other.getBaseValue(); + } + + public Velocity div(Time t) { + return new Velocity(this.value(METER) / t.value(SECOND), METER_PER_SECOND); + } + + public Time div(Velocity v) { + return new Time(this.value(METER) / v.value(METER_PER_SECOND), SECOND); + } +} diff --git a/uebung07/src/quantities/plain/LengthUnit.java b/uebung07/src/quantities/plain/LengthUnit.java new file mode 100644 index 0000000..c5a8e04 --- /dev/null +++ b/uebung07/src/quantities/plain/LengthUnit.java @@ -0,0 +1,14 @@ +package quantities.plain; + +public class LengthUnit extends Unit { + public LengthUnit(String name, double baseFactor) { + super(name, baseFactor); + } + + public static final LengthUnit METER = new LengthUnit("m", 1); + public static final LengthUnit MILLIMETER = new LengthUnit("mm", 0.001); + public static final LengthUnit KILOMETER = new LengthUnit("km", 1000); + public static final LengthUnit MILE = new LengthUnit("mi", 1609.344); + public static final LengthUnit LIGHTYEAR = new LengthUnit("ly", 9460730472580800.0); + public static final LengthUnit PARSEC = new LengthUnit("pc", 3.0856776e16); +} diff --git a/uebung07/src/quantities/plain/PlainQuantitiesDemo.java b/uebung07/src/quantities/plain/PlainQuantitiesDemo.java new file mode 100644 index 0000000..dff87ad --- /dev/null +++ b/uebung07/src/quantities/plain/PlainQuantitiesDemo.java @@ -0,0 +1,60 @@ +package quantities.plain; + +import static quantities.plain.LengthUnit.KILOMETER; +import static quantities.plain.LengthUnit.MILE; +import static quantities.plain.LengthUnit.MILLIMETER; +import static quantities.plain.LengthUnit.PARSEC; +import static quantities.plain.TimeUnit.HOUR; +import static quantities.plain.TimeUnit.MINUTE; +import static quantities.plain.TimeUnit.SECOND; +import static quantities.plain.VelocityUnit.KMH; +import static quantities.plain.VelocityUnit.METER_PER_SECOND; +import static quantities.plain.VelocityUnit.MPH; + +public class PlainQuantitiesDemo { + public static void main(String[] args) { + final Length l1 = new Length(1, KILOMETER); + final Length l2 = new Length(1200, MILLIMETER); + final Length l3 = new Length(1, MILE); + + System.out.println(l1); + System.out.println(l2); + System.out.println(l1 + " + " + l2 + " = " + l1.plus(l2)); + System.out.println(l1 + " + " + l2 + " (in mm) = " + l1.plus(l2).to(MILLIMETER)); + + System.out.println(l3 + " / " + l1 + " = " + l3.div(l1)); + + final Time t1 = new Time(100, SECOND); + final Time t2 = new Time(5, HOUR); + + System.out.println(t1); + System.out.println(t2); + System.out.println(t1.plus(t2)); + System.out.println(t1.plus(t2).to(MINUTE)); + + final Velocity v1 = new Velocity(12, KMH); + final Velocity v2 = new Velocity(100, METER_PER_SECOND); + + System.out.println(v1); + System.out.println(v2); + System.out.println(v2.to(KMH)); + System.out.println(v1.plus(v2)); + + final Length l4 = new Length(300, KILOMETER).to(PARSEC); + final Time t3 = new Time(2, HOUR); + final Velocity v3 = l4.div(t3); + System.out.println(l4 + " / " + l3 + " = " + v3); + + System.out.println(v1 + " * " + t1 + " = " + v1.mult(t1).to(KILOMETER)); + + final Length l5 = v3.mult(t1.to(HOUR)); + System.out.println(v3 + " * " + t1 + " = " + l5); + + final Time t5 = l4.div(v2); + System.out.println(l4 + " / " + v2 + " = " + t5.to(MINUTE)); + + Velocity v5 = new Velocity(55, MPH); + System.out.println(v5 + " = " + v5.format("%4.1f %s", KMH)); + System.out.println((v5.mult(new Time(30, MINUTE)).to(MILE))); + } +} diff --git a/uebung07/src/quantities/plain/Quantity.java b/uebung07/src/quantities/plain/Quantity.java new file mode 100644 index 0000000..cfd6a67 --- /dev/null +++ b/uebung07/src/quantities/plain/Quantity.java @@ -0,0 +1,28 @@ +package quantities.plain; + +public abstract class Quantity { + public final double value; + public final Unit unit; + + protected Quantity(double value, Unit unit) { + this.value = value; + this.unit = unit; + } + + public double getBaseValue() { + return value * unit.baseFactor; + } + + public double value(Unit unit) { + return getBaseValue() / unit.baseFactor; + } + + @Override + public String toString() { + return value + " " + unit; + } + + public String format(String fmt, Unit unit) { + return String.format(fmt, value(unit), unit); + } +} diff --git a/uebung07/src/quantities/plain/Unit.java b/uebung07/src/quantities/plain/Unit.java new file mode 100644 index 0000000..1ad6d51 --- /dev/null +++ b/uebung07/src/quantities/plain/Unit.java @@ -0,0 +1,16 @@ +package quantities.plain; + +public abstract class Unit { + public final String name; + public final double baseFactor; + + public Unit(String name, double baseFactor) { + this.name = name; + this.baseFactor = baseFactor; + } + + @Override + public String toString() { + return name; + } +} diff --git a/uebung07/test/oop/ch05/generic/mensa/MensaTest.java b/uebung07/test/oop/ch05/generic/mensa/MensaTest.java new file mode 100644 index 0000000..b3a3e06 --- /dev/null +++ b/uebung07/test/oop/ch05/generic/mensa/MensaTest.java @@ -0,0 +1,80 @@ +package oop.ch05.generic.mensa; + +import oop.ch05.generic.secured.AuthorizationException; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; + +public class MensaTest { + private static final String CONF_ACCOUNT = "33-1298"; + private static final String OTHER_ACCOUNT = "33-1299"; + private AccountManagement accountMgt; + private VendingMachine vm1; + private VendingMachine vm2; + private VendingMachine tumVM; + private CashPoint unibwMensa; + + private AccountCard conf; + private MensaCard frankSmith; + private CashCard hansMueller; + private CashCard peterSchmidt; + private CashCard thomasMayer; + + @Before + public void setup() { + accountMgt = new AccountManagement(4711, "UniBw admin"); + + vm1 = new VendingMachine("left", 4711); + vm2 = new VendingMachine("right", 4711); + tumVM = new VendingMachine("TUM Mensa", 3141); + unibwMensa = new CashPoint("UniBw Mensa", 4711, accountMgt); + + conf = new AccountCard("conference", CONF_ACCOUNT, 42); + frankSmith = new CountCard("Frank Smith", Color.gray); + hansMueller = new CashCard("Hans Müller", Color.green, 4711); + peterSchmidt = new CashCard("Peter Schmidt", Color.green, 4711); + thomasMayer = new CashCard("Thomas Mayer", Color.blue, 4711); + } + + @Test + public void testPayment() throws AuthorizationException, RejectedException { + vm1.deposit(hansMueller, 10); + vm1.deposit(peterSchmidt, 5); + vm2.deposit(thomasMayer, 2); + assertThrows(AuthorizationException.class, () -> tumVM.deposit(hansMueller, 10)); + + assertEquals(15, vm1.getEuros()); + assertEquals(2, vm2.getEuros()); + assertEquals(0, tumVM.getEuros()); + assertEquals(1000, hansMueller.getBalance()); + assertEquals(500, peterSchmidt.getBalance()); + assertEquals(200, thomasMayer.getBalance()); + + hansMueller.pass(unibwMensa); + assertEquals(733, hansMueller.getBalance()); + assertEquals(1, unibwMensa.getCounter()); + assertEquals(267, unibwMensa.getCents()); + + frankSmith.pass(unibwMensa); + assertEquals(0, accountMgt.getAmount(CONF_ACCOUNT)); + assertThrows(RejectedException.class, () -> conf.pass(unibwMensa)); + assertThrows(RejectedException.class, () -> thomasMayer.pass(unibwMensa)); + hansMueller.pass(unibwMensa); + hansMueller.pass(unibwMensa); + assertEquals(199, hansMueller.getBalance()); + + assertThrows(RejectedException.class, () -> hansMueller.pass(unibwMensa)); + + accountMgt.deposit(CONF_ACCOUNT, 1000); + accountMgt.deposit(OTHER_ACCOUNT, 2000); + assertEquals(100000, accountMgt.getAmount(CONF_ACCOUNT)); + assertEquals(200000, accountMgt.getAmount(OTHER_ACCOUNT)); + + conf.pass(unibwMensa); + assertEquals(99505, accountMgt.getAmount(CONF_ACCOUNT)); + assertEquals(200000, accountMgt.getAmount(OTHER_ACCOUNT)); + assertEquals(5, unibwMensa.getCounter()); + } +}