diff --git a/bank/.idea/.gitignore b/bank/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/bank/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/bank/.idea/compiler.xml b/bank/.idea/compiler.xml new file mode 100644 index 0000000..9cc5561 --- /dev/null +++ b/bank/.idea/compiler.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/bank/.idea/encodings.xml b/bank/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/bank/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/bank/.idea/jarRepositories.xml b/bank/.idea/jarRepositories.xml new file mode 100644 index 0000000..712ab9d --- /dev/null +++ b/bank/.idea/jarRepositories.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/bank/.idea/misc.xml b/bank/.idea/misc.xml new file mode 100644 index 0000000..b3cf2e0 --- /dev/null +++ b/bank/.idea/misc.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/bank/.idea/uiDesigner.xml b/bank/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/bank/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bank/.idea/vcs.xml b/bank/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/bank/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/bank/.mvn/jvm.config b/bank/.mvn/jvm.config new file mode 100644 index 0000000..e69de29 diff --git a/bank/.mvn/maven.config b/bank/.mvn/maven.config new file mode 100644 index 0000000..e69de29 diff --git a/bank/example.txt b/bank/example.txt new file mode 100644 index 0000000..a8e2bb9 --- /dev/null +++ b/bank/example.txt @@ -0,0 +1,41 @@ +$> create Paul +Created account with id: '0' and name 'Paul' + +$> create Peter +Created account with id: '1' and name 'Peter' + +$> create Mic +Created account with id: '2' and name 'Mic' + +$> info 1 +Info for account '1': [Name: 'Peter', Balance: 0$] + +$> add 1 100 +Added 100$ to account '1' + +$> info 1 +Info for account '1': [Name: 'Paul', Balance: 0$] + +$> transfer 1 0 40 +Transferred 40$ from account '1' to account '0' + +$> info 0 +Info for account '0': [Name: 'Paul', Balance: 40$] + +$> info 1 +Info for account '1': [Name: 'Peter', Balance: 60$] + +$> transfer 1 2 30 +Transferred 30$ from account '1' to account '2' + +$> transfer 2 1 10 +Transferred 10$ from account '2' to account '1' + +$> transactions 1 +Transactions for account '1': +Send 40$ to account '0' +Send 30$ to account '2' +Received 10$ from account '2' + +$> remove 0 120 +Removed 120$ from account '0' \ No newline at end of file diff --git a/bank/pom.xml b/bank/pom.xml new file mode 100644 index 0000000..7197bdf --- /dev/null +++ b/bank/pom.xml @@ -0,0 +1,81 @@ + + + + 4.0.0 + + de.vivi + bank + 1.0-SNAPSHOT + + bank + A simple bank. + + http://www.example.com + + + UTF-8 + 8 + 8 + + + + + junit + junit + 3.8.1 + + + + + + + + maven-clean-plugin + 3.4.0 + + + maven-site-plugin + 3.12.1 + + + maven-project-info-reports-plugin + 3.6.1 + + + + maven-resources-plugin + 3.3.1 + + + maven-compiler-plugin + 3.13.0 + + + maven-surefire-plugin + 3.3.0 + + + maven-jar-plugin + 3.4.2 + + + maven-install-plugin + 3.1.2 + + + maven-deploy-plugin + 3.1.2 + + + + + + + + + maven-project-info-reports-plugin + + + + diff --git a/bank/src/main/java/de/vivi/App.java b/bank/src/main/java/de/vivi/App.java new file mode 100644 index 0000000..2101eff --- /dev/null +++ b/bank/src/main/java/de/vivi/App.java @@ -0,0 +1,27 @@ +package de.vivi; + +import de.vivi.bank.Bank; + +import java.util.Scanner; + +/** + * Hello world! + * + */ +public class App { + + public static void main(String[] args) { + Bank bank = null; + Scanner scanner = new Scanner(System.in); + + while (true) { + String[] values = scanner.nextLine().split(" "); + + if (values.length > 0 && values[0].equals("exit")) { + return; + } + + Command.exec(bank, values); + } + } +} diff --git a/bank/src/main/java/de/vivi/Command.java b/bank/src/main/java/de/vivi/Command.java new file mode 100644 index 0000000..0b701b4 --- /dev/null +++ b/bank/src/main/java/de/vivi/Command.java @@ -0,0 +1,50 @@ +package de.vivi; + +import de.vivi.bank.Bank; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.BiConsumer; + +public class Command { + + private static final Map COMMANDS = new HashMap() {{ + put("create", new Command(1, (bank, args) -> bank.create(args[1]))); + put("info", new Command(1, (bank, args) -> bank.info(Integer.parseInt(args[1])))); + put("add", new Command(1, (bank, args) -> bank.add(Integer.parseInt(args[1]), Integer.parseInt(args[2])))); + put("remove", new Command(1, (bank, args) -> bank.remove(Integer.parseInt(args[1]), Integer.parseInt(args[2])))); + put("transfer", new Command(1, (bank, args) -> bank.transfer(Integer.parseInt(args[1]), Integer.parseInt(args[2]), Integer.parseInt(args[3])))); + put("transactions", new Command(1, (bank, args) -> bank.transactions(Integer.parseInt(args[1])))); + }}; + + private final int args; + + private final BiConsumer consumer; + + private Command(int args, BiConsumer consumer) { + this.args = args; + this.consumer = consumer; + } + + public static void exec(Bank bank, String[] args) { + if (args.length > 0) { + Command command = COMMANDS.get(args[0]); + + if (command == null) { + System.out.println("Command not found"); + return; + } + + if (command.args != args.length) { + System.out.println("Invalid argument count"); + return; + } + + try { + command.consumer.accept(bank, args); + } catch (NumberFormatException e) { + System.out.println("Invalid argument"); + } + } + } +} diff --git a/bank/src/main/java/de/vivi/bank/Bank.java b/bank/src/main/java/de/vivi/bank/Bank.java new file mode 100644 index 0000000..8e226c5 --- /dev/null +++ b/bank/src/main/java/de/vivi/bank/Bank.java @@ -0,0 +1,50 @@ +package de.vivi.bank; + +public interface Bank { + + /** + * Creates an account with the given name and generates the id. + * Prints: + * Created account with id '#id' and name '#name' + */ + void create(String name); + + /** + * Prints the info of the account with the given id. + * Prints: + * Account info: [Name: '#name', Balance: '#balance'] + */ + void info(int id); + + /** + * Adds the given amount to the account with the given id. + * Prints: + * Added #amount$ to account '#id' + */ + void add(int id, int amount); + + /** + * Removes the given amount from the account with the given id. + * Prints: + * Removed #amount$ from account '#id' + */ + void remove(int id, int amount); + + /** + * Transfers the given amount from the account with the given + * fromId to the account with the given toId. + * Prints: + * Transferred #amount$ from account '#fromId' to account '#toId' + */ + void transfer(int fromId, int toId, int amount); + + /** + * Lists all transactions of the account with the given id. + * Prints: + * Transactions for account with id '#id': + * Send #amount$ to account '#id' + * Received #amount$ from account '#id' + * ... + */ + void transactions(int id); +} diff --git a/bank/src/site/site.xml b/bank/src/site/site.xml new file mode 100644 index 0000000..20c5490 --- /dev/null +++ b/bank/src/site/site.xml @@ -0,0 +1,26 @@ + + + + + bank + https://maven.apache.org/images/apache-maven-project.png + https://www.apache.org/ + + + + https://maven.apache.org/images/maven-logo-black-on-white.png + https://maven.apache.org/ + + + + org.apache.maven.skins + maven-fluido-skin + 1.7 + + + + + + + \ No newline at end of file diff --git a/bank/src/test/java/de/vivi/AppTest.java b/bank/src/test/java/de/vivi/AppTest.java new file mode 100644 index 0000000..a52d24b --- /dev/null +++ b/bank/src/test/java/de/vivi/AppTest.java @@ -0,0 +1,38 @@ +package de.vivi; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Unit test for simple App. + */ +public class AppTest + extends TestCase +{ + /** + * Create the test case + * + * @param testName name of the test case + */ + public AppTest( String testName ) + { + super( testName ); + } + + /** + * @return the suite of tests being tested + */ + public static Test suite() + { + return new TestSuite( AppTest.class ); + } + + /** + * Rigourous Test :-) + */ + public void testApp() + { + assertTrue( true ); + } +} diff --git a/jmarket-09-10 b/jmarket-09-10 deleted file mode 160000 index 24e7f12..0000000 --- a/jmarket-09-10 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 24e7f12667ab03948f09c71612c893fdc52993cf diff --git a/jmarket/.gitignore b/jmarket/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/jmarket/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/jmarket/.idea/.gitignore b/jmarket/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/jmarket/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/jmarket/.idea/encodings.xml b/jmarket/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/jmarket/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/jmarket/.idea/misc.xml b/jmarket/.idea/misc.xml new file mode 100644 index 0000000..a12cfda --- /dev/null +++ b/jmarket/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/jmarket/.idea/uiDesigner.xml b/jmarket/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/jmarket/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/jmarket/.idea/vcs.xml b/jmarket/.idea/vcs.xml new file mode 100644 index 0000000..288b36b --- /dev/null +++ b/jmarket/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/jmarket/pom.xml b/jmarket/pom.xml new file mode 100644 index 0000000..f5c6a9b --- /dev/null +++ b/jmarket/pom.xml @@ -0,0 +1,16 @@ + + + 4.0.0 + + org.example + jmarket-09-10 + 1.0-SNAPSHOT + + + 17 + 17 + UTF-8 + + \ No newline at end of file diff --git a/jmarket/src/main/java/de/vimo/jmarket/Main.java b/jmarket/src/main/java/de/vimo/jmarket/Main.java new file mode 100644 index 0000000..7d5bc9d --- /dev/null +++ b/jmarket/src/main/java/de/vimo/jmarket/Main.java @@ -0,0 +1,28 @@ +package de.vimo.jmarket; + +import de.vimo.jmarket.api.ProductDatabase; + +import java.time.LocalDate; + +public class Main { + + public static void main(String[] args) { + + } + + /* + private static void usage() { + ProductDatabase db = null; + + db.addProduct(new PaulMarketProduct("banana", LocalDate.of(2025, 8, 1), 10.4, 4.5)); + db.addProduct(new PaulMarketProduct("banana", LocalDate.of(2025, 4, 3), 6.4, 2.5)); + db.addProduct(new PaulMarketProduct("banana", LocalDate.of(2026, 8, 1), 12.7, 6.5)); + db.addProduct(new PaulMarketProduct("orange", LocalDate.of(2024, 1, 14), 2.4, 1.5)); + db.addProduct(new PaulMarketProduct("orange", LocalDate.of(2023, 3, 20), 3.3, 2.5)); + db.addProduct(new PaulMarketProduct("candy", LocalDate.of(2028, 8, 1), 30.4, 10.4)); + db.addProduct(new PaulMarketProduct("candy", LocalDate.of(2026, 8, 23), 24.5, 12.6)); + db.addProduct(new PaulMarketProduct("beans", LocalDate.of(2025, 6, 12), 2.3, 120.5)); + db.addProduct(new PaulMarketProduct("doughnut", LocalDate.of(2020, 3, 1), 1.4, 6.5)); + } + */ +} diff --git a/jmarket/src/main/java/de/vimo/jmarket/api/Product.java b/jmarket/src/main/java/de/vimo/jmarket/api/Product.java new file mode 100644 index 0000000..aa7d97f --- /dev/null +++ b/jmarket/src/main/java/de/vimo/jmarket/api/Product.java @@ -0,0 +1,17 @@ +package de.vimo.jmarket.api; + +import java.time.LocalDate; + +/** + * TODO: implement all methods + */ +public interface Product { + + String getName(); + + LocalDate getExpirationDate(); + + double getWeight(); + + double getPrice(); +} diff --git a/jmarket/src/main/java/de/vimo/jmarket/api/ProductDatabase.java b/jmarket/src/main/java/de/vimo/jmarket/api/ProductDatabase.java new file mode 100644 index 0000000..0abf0f4 --- /dev/null +++ b/jmarket/src/main/java/de/vimo/jmarket/api/ProductDatabase.java @@ -0,0 +1,93 @@ +package de.vimo.jmarket.api; + +import java.time.LocalDate; +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; +import java.util.stream.Stream; + +/** + * TODO: implement all methods + */ +public interface ProductDatabase { + + /** + * Adds a product to the database and generates a random id for it. + * + * @param product The product to add + * @return The randomly generated id + */ + int addProduct(Product product); + + /** + * Returns the product with the specified id. If there is no + * such product, it returns null. + * + * @param id The id of the product + * @return The product with the specified id + */ + Product getProduct(int id); + + /** + * Returns all products with the specified name. + * + * @param name The name to search for + * @return The products that have the specified name + */ + List getProductsByName(String name); + + /** + * Gets all products that match the given predicate. + * + * @param predicate The condition the products have to fulfill + * @return The filtered products + */ + List getProducts(Predicate predicate); + + /** + * Returns all products that are expired at or after the specified + * date. + * + * @param date The date to check for + * @return The products that are expired at or after the date + */ + List getExpiredProducts(LocalDate date); + + /** + * Returns a list of all distinct product names inside the database. + * + * @return The product names. + */ + List getDistinctProductNames(); + + /** + * Returns a map where the key is the product name and the + * value is the total weight of all products with that name. + * + * @return The map with product names and weights + */ + Map getTotalProductWeights(); + + /** + * Returns the count of products with the specified name. + * + * @param name The name of the product to count + * @return The count of products + */ + int getProductCount(String name); + + /** + * Returns the total price of all products with the specified name. + * + * @param name The name of the product + * @return The total price + */ + double getTotalProductPrice(String name); + + /** + * Adds all values from the specified databases to this database. + * + * @param databases The databases to add + */ + void addAll(Stream> databases); +} diff --git a/jmarket/src/main/java/de/vimo/jmarket/api/TreeList.java b/jmarket/src/main/java/de/vimo/jmarket/api/TreeList.java new file mode 100644 index 0000000..7472b42 --- /dev/null +++ b/jmarket/src/main/java/de/vimo/jmarket/api/TreeList.java @@ -0,0 +1,34 @@ +package de.vimo.jmarket.api; + +import java.util.function.BiConsumer; + +/** + * TODO: implement all methods + */ +public interface TreeList { + + /** + * Adds the product with the id into the list. + * + * @param id The unique identifier + * @param product The product + */ + void add(int id, Product product); + + /** + * Returns the product with the specified id or null if + * the id can't be found. + * + * @param id The unique identifier + * @return The product + */ + Product get(int id); + + /** + * Calls the accept method for each entry inside the tree + * for the provided consumer. + * + * @param consumer The consumer to consume all entries in the list + */ + void forEach(BiConsumer consumer); +} diff --git a/list/src/main/java/de/vivi/list/Main.java b/list/src/main/java/de/vivi/list/Main.java index 34d7b46..ccac39c 100644 --- a/list/src/main/java/de/vivi/list/Main.java +++ b/list/src/main/java/de/vivi/list/Main.java @@ -2,19 +2,20 @@ package de.vivi.list; import de.vivi.list.list.ArrayByteList; import de.vivi.list.list.ByteList; +import de.vivi.list.list.LinkedByteList; public class Main { public static void main(String[] args) { ByteList array = new ArrayByteList(); - // ByteList linked = new LinkedByteList(); + ByteList linked = new LinkedByteList(); // ByteList combined = new CombinedByteList(16); testList(array); - // testList(linked); + testList(linked); // testList(combined); - testSort(array); + // testSort(array); // testSort(linked); // testSort(combined); } @@ -54,35 +55,35 @@ public class Main { list.size(); // returns: 4 // does the list contain the specified element? - list.contains(43); // returns: true - list.contains(4); // returns: false - - // return a string of the form: [1, 84, 53] - list.toString(); // returns: "[8, 43, -86, 3]" - - // return a copy of the list - list.copy(); // returns: [8, 43, -86, 3] - - - // remove all elements inside the list - list.clear(); - - // list: [] - - // allow to use for each loop on list - for (byte value : list) { - // do some stuff with value... - } +// list.contains(43); // returns: true +// list.contains(4); // returns: false +// +// // return a string of the form: [1, 84, 53] +// list.toString(); // returns: "[8, 43, -86, 3]" +// +// // return a copy of the list +// list.copy(); // returns: [8, 43, -86, 3] +// +// +// // remove all elements inside the list +// list.clear(); +// +// // list: [] +// +// // allow to use for each loop on list +// for (byte value : list) { +// // do some stuff with value... +// } } - private static void testSort(ByteList list) { - ByteSort bubble = new BubbleSort(); - ByteSort merge = new MergeSort(); - ByteSort bogo = new BogoSort(); - - // sort the lists with the sorting algorithm - bubble.sort(list.copy()); - merge.sort(list.copy()); - bogo.sort(list.copy()); - } +// private static void testSort(ByteList list) { +// ByteSort bubble = new BubbleSort(); +// ByteSort merge = new MergeSort(); +// ByteSort bogo = new BogoSort(); +// +// // sort the lists with the sorting algorithm +// bubble.sort(list.copy()); +// merge.sort(list.copy()); +// bogo.sort(list.copy()); +// } } diff --git a/list/src/main/java/de/vivi/list/list/ArrayByteList.java b/list/src/main/java/de/vivi/list/list/ArrayByteList.java index 6e30820..dcb2246 100644 --- a/list/src/main/java/de/vivi/list/list/ArrayByteList.java +++ b/list/src/main/java/de/vivi/list/list/ArrayByteList.java @@ -3,4 +3,49 @@ package de.vivi.list.list; public class ArrayByteList implements ByteList { private byte[] values; + + public ArrayByteList() { + values = new byte[0]; + } + + @Override + public void add(byte value) { + add(size(), value); + } + + @Override + public void add(int index, byte value) { + byte[] newValues = new byte[size() + 1]; + + System.arraycopy(values, 0, newValues, 0, index); + System.arraycopy(values, index, newValues, index + 1, size() - index); + + newValues[index] = value; + values = newValues; + } + + @Override + public void remove(int index) { + byte[] newValues = new byte[size() - 1]; + + System.arraycopy(values, 0, newValues, 0, index); + System.arraycopy(values, index + 1, newValues, index, size() - index - 1); + + values = newValues; + } + + @Override + public byte get(int index) { + return values[index]; + } + + @Override + public void set(int index, byte value) { + values[index] = value; + } + + @Override + public int size() { + return values.length; + } } diff --git a/list/src/main/java/de/vivi/list/list/ByteList.java b/list/src/main/java/de/vivi/list/list/ByteList.java index ebcfafe..5d22b3c 100644 --- a/list/src/main/java/de/vivi/list/list/ByteList.java +++ b/list/src/main/java/de/vivi/list/list/ByteList.java @@ -2,5 +2,15 @@ package de.vivi.list.list; public interface ByteList { + void add(byte value); + void add(int index, byte value); + + void remove(int index); + + byte get(int index); + + void set(int index, byte value); + + int size(); } diff --git a/list/src/main/java/de/vivi/list/list/LinkedByteList.java b/list/src/main/java/de/vivi/list/list/LinkedByteList.java new file mode 100644 index 0000000..383a1d6 --- /dev/null +++ b/list/src/main/java/de/vivi/list/list/LinkedByteList.java @@ -0,0 +1,136 @@ +package de.vivi.list.list; + +public class LinkedByteList implements ByteList { + + private static class Entry { + + public byte value; + + public Entry next; + } + + private Entry root; + + private int size; + + public LinkedByteList() { + root = null; + size = 0; + } + + @Override + public void add(byte value) { + add(size, value); + } + + @Override + public void add(int index, byte value) { + if (index < 0) { + throw new IndexOutOfBoundsException(); + } + + size += 1; + + // create the new entry + Entry entry = new Entry(); + entry.value = value; + + // check if we need to set the root + if (index == 0) { + entry.next = root; + root = entry; + + return; + } + + // the entry before the new entry + Entry prev = root; + + // find the spot to insert the entry + while (--index > 0) { + prev = prev.next; + } + + // insert the entry + entry.next = prev.next; + prev.next = entry; + } + + @Override + public void remove(int index) { + if (index < 0) { + throw new IndexOutOfBoundsException(); + } + + size -= 1; + + // check if we need to set the root + if (index == 0) { + root = root.next; + return; + } + + // the entry before the removed entry + Entry prev = root; + + // find the spot to remove the entry + while (--index > 0) { + prev = prev.next; + } + + // remove the entry + prev.next = prev.next.next; + } + + @Override + public byte get(int index) { + if (index < 0) { + throw new IndexOutOfBoundsException(); + } + + Entry entry = root; + + while (index-- > 0) { + entry = entry.next; + } + + return entry.value; + } + + @Override + public void set(int index, byte value) { + if (index < 0) { + throw new IndexOutOfBoundsException(); + } + + Entry entry = root; + + while (index-- > 0) { + entry = entry.next; + } + + entry.value = value; + } + + @Override + public int size() { + return size; + } + + @Override + public String toString() { + StringBuilder result = new StringBuilder("["); + Entry entry = root; + + while (entry != null) { + if (entry != root) { + result.append(", "); + } + + result.append(entry.value); + entry = entry.next; + } + + return result.append("]").toString(); + } +}