diff --git a/basics/src/main/java/ru/msu/vmk/NumberSample.java b/basics/src/main/java/ru/msu/vmk/NumberSample.java index 9961ed3..9405c88 100644 --- a/basics/src/main/java/ru/msu/vmk/NumberSample.java +++ b/basics/src/main/java/ru/msu/vmk/NumberSample.java @@ -1,11 +1,23 @@ package ru.msu.vmk; - import java.math.BigDecimal; - public class NumberSample { + public static BigDecimal[] split(BigDecimal amount, int n) { - // разделить amount на n частей - // если остается остаток, прибавить его к первому числу - return null; + var array = new BigDecimal[n]; + double temp = amount.doubleValue(); + int previousSize = n; + for (int i = 0; n > 0; i++, n--) { + double size = temp / n; + if (previousSize > 2) { + array[i] = BigDecimal.valueOf((int) size); + } else { + array[i] = BigDecimal.valueOf(size); + } + temp -= size; + } + if (previousSize > 2) { + array[0] = BigDecimal.valueOf((int) (amount.doubleValue() / previousSize)).add(BigDecimal.valueOf(amount.doubleValue() % previousSize)); + } + return array; } } diff --git a/collections/pom.xml b/collections/pom.xml index 38c543e..4b1b835 100644 --- a/collections/pom.xml +++ b/collections/pom.xml @@ -23,6 +23,16 @@ junit-jupiter 5.9.2 + + org.apache.derby + derby + 10.14.2.0 + + + org.apache.derby + derbynet + 10.6.2.1 + org.junit.jupiter junit-jupiter-api @@ -47,4 +57,4 @@ - \ No newline at end of file + diff --git a/collections/src/main/java/ru/msu/vmk/Book.java b/collections/src/main/java/ru/msu/vmk/Book.java index f2af0e5..4e0b36f 100644 --- a/collections/src/main/java/ru/msu/vmk/Book.java +++ b/collections/src/main/java/ru/msu/vmk/Book.java @@ -1,13 +1,55 @@ package ru.msu.vmk; +import java.util.Objects; + public class Book { + + private int bookId; private String title; + private int isReserved; + + public Book() { + } + public Book(String title){ this.title = title; } + public int getBookId() { + return bookId; + } + + public void setBookId(int bookId) { + this.bookId = bookId; + } + public String getTitle(){ return title; } + + public void setTitle(String title) { + this.title = title; + } + + public int getIsReserved() { + return isReserved; + } + + public void setIsReserved(int isReserved) { + this.isReserved = isReserved; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Book book = (Book) o; + return bookId == book.bookId && isReserved == book.isReserved && Objects.equals(title, book.title); + } + + @Override + public int hashCode() { + return Objects.hash(bookId, title, isReserved); + } } diff --git a/collections/src/main/java/ru/msu/vmk/Library.java b/collections/src/main/java/ru/msu/vmk/Library.java index b5e3b9b..c9fd666 100644 --- a/collections/src/main/java/ru/msu/vmk/Library.java +++ b/collections/src/main/java/ru/msu/vmk/Library.java @@ -1,15 +1,38 @@ package ru.msu.vmk; +import java.sql.Connection; +import java.sql.SQLException; import java.util.List; /* Институтская библиотека */ public interface Library { /* Регистрация новой книги */ - void addNewBook(Book book); + void addNewBook(Book book) throws SQLException; + /* Студент берет книгу */ - void borrowBook(Book book, String student); + void borrowBook(Book book, String student) throws SQLException; + /* Студент возвращает книгу */ - void returnBook(Book book, String student); + void returnBook(Book book, String student) throws SQLException; + /* Получить список свободных книг */ - List findAvailableBooks(); + List findAvailableBooks() throws SQLException; + /*Инициализация базы данных*/ + void init() throws SQLException; + + Connection getConnection() throws SQLException; + + Book getBookByTitle(String title) throws SQLException; + + void updateIsReservedFlag(int bookId, int isReserved) throws SQLException; + + Student getStudentByName(String name) throws SQLException; + + List getRelationByStudentId(int studentId) throws SQLException; + + void insertNewStudent(String student) throws SQLException; + + void insertNewRelation(int bookId, int studentId) throws SQLException; + + boolean deleteRelation(int relationId) throws SQLException; } diff --git a/collections/src/main/java/ru/msu/vmk/LibraryImpl.java b/collections/src/main/java/ru/msu/vmk/LibraryImpl.java index 60162b9..5e28963 100644 --- a/collections/src/main/java/ru/msu/vmk/LibraryImpl.java +++ b/collections/src/main/java/ru/msu/vmk/LibraryImpl.java @@ -1,25 +1,240 @@ package ru.msu.vmk; +import java.sql.*; +import java.util.ArrayList; import java.util.List; +import java.util.logging.Logger; + +public class LibraryImpl implements Library { + + private final Logger logger = Logger.getLogger(LibraryImpl.class.getName()); + + private final String jdbcUrl; + private final String user; + private final String password; + + public LibraryImpl(String jdbcUrl, String user, String password) { + this.jdbcUrl = jdbcUrl; + this.user = user; + this.password = password; + } -public class LibraryImpl implements Library{ @Override - public void addNewBook(Book book) { + public void addNewBook(Book book) throws SQLException { + Book bookInLibrary = getBookByTitle(book.getTitle()); + if (bookInLibrary == null) { + String sql = "insert into LIBRARY.BOOK (TITLE, IS_RESERVED) values (?,?)"; + try (Connection connection = getConnection(); PreparedStatement pr = connection.prepareStatement(sql)) { + pr.setString(1, book.getTitle()); + pr.setInt(2, 0); + int row = pr.executeUpdate(); + if (row > 0) { + logger.info("Книга добавлена."); + } + } + } else { + logger.info("Книга уже есть в библиотеке!"); + } + } + @Override + public void borrowBook(Book book, String student) throws SQLException { + Book bookInLibrary = getBookByTitle(book.getTitle()); + if (bookInLibrary != null && bookInLibrary.getIsReserved() != 1) { + updateIsReservedFlag(bookInLibrary.getBookId(), 1); + Student studentInDB = getStudentByName(student); + if (studentInDB == null) { + insertNewStudent(student); + studentInDB = getStudentByName(student); + } + List relations = getRelationByStudentId(studentInDB.getStudentId()); + if (!relations.isEmpty()) { + if (relations.stream().anyMatch(rel -> rel.getBookId() != bookInLibrary.getBookId())) { + insertNewRelation(bookInLibrary.getBookId(), studentInDB.getStudentId()); + } + } else { + insertNewRelation(bookInLibrary.getBookId(), studentInDB.getStudentId()); + } + logger.info("Книга выдана."); + } else { + logger.info("Книги нет в библиотеки."); + } } @Override - public void borrowBook(Book book, String student) { + public void returnBook(Book book, String student) throws SQLException { + Student studentInDB = getStudentByName(student); + if (studentInDB != null) { + List relations = getRelationByStudentId(studentInDB.getStudentId()); + if (!relations.isEmpty()) { + relations.stream().filter(rel -> rel.getBookId() == book.getBookId()).forEach(relation -> { + try { + updateIsReservedFlag(relation.getBookId(), 0); + deleteRelation(relation.getRelationId()); + logger.info("Книгу вернули."); + } catch (SQLException e) { + logger.severe(e.getMessage()); + } + }); + } else { + logger.info("За студентом не числится эта книга!"); + } + } else { + logger.info("Студент не найден!"); + } + } + @Override + public List findAvailableBooks() throws SQLException { + List out = new ArrayList<>(); + String sql = "select * from LIBRARY.BOOK where is_reserved = 0"; + try (Connection connection = getConnection(); PreparedStatement pr = connection.prepareStatement(sql)) { + ResultSet resultSet = pr.executeQuery(); + while (resultSet.next()) { + Book book = new Book(); + book.setBookId(resultSet.getInt("BOOK_ID")); + book.setTitle(resultSet.getString("TITLE")); + book.setIsReserved(resultSet.getInt("IS_RESERVED")); + out.add(book); + } + } + return out; } @Override - public void returnBook(Book book, String student) { + public void init() throws SQLException { + try (Statement stmt = getConnection().createStatement()) { + stmt.execute("create schema LIBRARY"); + stmt.execute("set schema LIBRARY"); + stmt.execute("CREATE TABLE LIBRARY.BOOK " + + " (BOOK_ID INT NOT NULL GENERATED ALWAYS AS IDENTITY " + + " (START WITH 1, INCREMENT BY 1), TITLE VARCHAR(1000), IS_RESERVED INT)"); + stmt.execute("CREATE TABLE LIBRARY.STUDENT " + + " (STUDENT_ID INT NOT NULL GENERATED ALWAYS AS IDENTITY " + + " (START WITH 1, INCREMENT BY 1), NAME VARCHAR(100))"); + stmt.execute("CREATE TABLE LIBRARY.RELATION " + + " (RELATION_ID INT NOT NULL GENERATED ALWAYS AS IDENTITY " + + " (START WITH 1, INCREMENT BY 1), STUDENT_ID INT NOT NULL, BOOK_ID INT NOT NULL)"); + } + } + @Override + public Connection getConnection() throws SQLException { + return DriverManager.getConnection(jdbcUrl, user, password); + } + + @Override + public Book getBookByTitle(String title) throws SQLException { + Book out = null; + String sql = "select * from LIBRARY.BOOK where title = ?"; + try (Connection connection = getConnection(); PreparedStatement pr = connection.prepareStatement(sql)) { + pr.setString(1, title); + ResultSet resultSet = pr.executeQuery(); + while (resultSet.next()) { + out = new Book(); + out.setBookId(resultSet.getInt("BOOK_ID")); + out.setTitle(resultSet.getString("TITLE")); + out.setIsReserved(resultSet.getInt("IS_RESERVED")); + } + } + return out; + } + + @Override + public void updateIsReservedFlag(int bookId, int isReserved) throws SQLException { + String sql = "update LIBRARY.BOOK set is_reserved = ? where book_id = ?"; + try (Connection connection = getConnection(); PreparedStatement pr = connection.prepareStatement(sql)) { + pr.setInt(1, isReserved); + pr.setInt(2, bookId); + pr.executeUpdate(); + } + } + + @Override + public Student getStudentByName(String name) throws SQLException { + Student out = null; + String sql = "select * from LIBRARY.STUDENT where name = ?"; + try (Connection connection = getConnection(); PreparedStatement pr = connection.prepareStatement(sql)) { + pr.setString(1, name); + ResultSet resultSet = pr.executeQuery(); + while (resultSet.next()) { + out = new Student(); + out.setStudentId(resultSet.getInt("STUDENT_ID")); + out.setStudentName(resultSet.getString("NAME")); + } + } + return out; + } + + @Override + public List getRelationByStudentId(int studentId) throws SQLException { + List out = new ArrayList<>(); + String sql = "select * from LIBRARY.RELATION where student_id = ?"; + try (Connection connection = getConnection(); PreparedStatement pr = connection.prepareStatement(sql)) { + pr.setInt(1, studentId); + ResultSet resultSet = pr.executeQuery(); + while (resultSet.next()) { + Relation relation = new Relation(); + relation.setRelationId(resultSet.getInt("RELATION_ID")); + relation.setStudentId(resultSet.getInt("STUDENT_ID")); + relation.setBookId(resultSet.getInt("BOOK_ID")); + out.add(relation); + } + } + return out; + } + + @Override + public void insertNewStudent(String student) throws SQLException { + String sql = "insert into LIBRARY.STUDENT (NAME) " + + "values (?)"; + try (Connection connection = getConnection()) { + connection.setAutoCommit(false); + try (PreparedStatement pr = connection.prepareStatement(sql)) { + pr.setString(1, student); + pr.execute(); + connection.commit(); + } catch (SQLException e) { + logger.severe(e.getMessage()); + getConnection().rollback(); + } + } + } + + @Override + public void insertNewRelation(int bookId, int studentId) throws SQLException { + String sql = "insert into LIBRARY.RELATION (STUDENT_ID, BOOK_ID) " + + "values (?, ?)"; + try (Connection connection = getConnection()) { + connection.setAutoCommit(false); + try (PreparedStatement pr = connection.prepareStatement(sql)) { + pr.setInt(1, studentId); + pr.setInt(2, bookId); + pr.execute(); + connection.commit(); + } catch (SQLException e) { + logger.severe(e.getMessage()); + getConnection().rollback(); + } + } } @Override - public List findAvailableBooks() { - return null; + public boolean deleteRelation(int relationId) throws SQLException { + boolean flag = false; + String sql = "delete from LIBRARY.RELATION where relation_id = ?"; + try (Connection connection = getConnection()) { + try (PreparedStatement pr = connection.prepareStatement(sql)) { + pr.setInt(1, relationId); + int row = pr.executeUpdate(); + if (row > 0) { + flag = true; + } + } catch (SQLException e) { + logger.severe(e.getMessage()); + getConnection().rollback(); + } + } + return flag; } } diff --git a/collections/src/main/java/ru/msu/vmk/Main.java b/collections/src/main/java/ru/msu/vmk/Main.java index 50c42f1..dbbe6f7 100644 --- a/collections/src/main/java/ru/msu/vmk/Main.java +++ b/collections/src/main/java/ru/msu/vmk/Main.java @@ -1,62 +1,34 @@ package ru.msu.vmk; +import org.apache.derby.drda.NetworkServerControl; + +import java.io.PrintWriter; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.sql.*; import java.util.*; public class Main { - public static void main(String[] args) { - var set = new HashSet(); - - set.add("test"); - set.add("test1"); - - for (var element: set){ - // System.out.println(element); - } - - var map = new HashMap(); - - map.putIfAbsent(1, "test1"); - map.putIfAbsent(1, "test3"); - map.putIfAbsent(2, "test2"); - + public static void main(String[] args) throws Exception { - for (var key: map.keySet()){ - System.out.println("key=" + key + " value=" + map.get(key)); - } - - var array = new ArrayList(); + Library library = new LibraryImpl("jdbc:derby:memory:testdb;create=true", "test", "test"); + library.init(); - array.add("first"); - array.add("second"); - array.add("third"); + NetworkServerControl nsc = new NetworkServerControl(InetAddress.getByName("localhost"), 1527); + nsc.start(new PrintWriter(System.out, true)); - array.add(1, "modified"); - System.out.println(array.set(1, "modified1")); - - for (var element: array){ - System.out.println("index = " + array.indexOf(element) + " element =" + element); - } + Class.forName("org.apache.derby.jdbc.EmbeddedDriver"); - var deque = new ArrayDeque(); + Connection c = DriverManager.getConnection("jdbc:derby:memory:testdb;create=true"); + try(Connection conn = c; + PreparedStatement ps = conn.prepareStatement("create schema TEST");) { - deque.offer("first"); - deque.offer("second"); - deque.offer("third"); + boolean success = ps.execute(); + System.out.println("Memory database created: " + success); - while (!deque.isEmpty()){ - var element = deque.removeLast(); - System.out.println(element); + } catch (SQLException e) { + e.printStackTrace(); } - var stack = new Stack(); - - stack.push("first"); - stack.push("second"); - stack.push("third"); - - while (!stack.isEmpty()){ - var element = stack.pop(); - System.out.println(element); - } } -} \ No newline at end of file +} diff --git a/collections/src/main/java/ru/msu/vmk/Relation.java b/collections/src/main/java/ru/msu/vmk/Relation.java new file mode 100644 index 0000000..aaaa608 --- /dev/null +++ b/collections/src/main/java/ru/msu/vmk/Relation.java @@ -0,0 +1,50 @@ +package ru.msu.vmk; + +import java.util.Objects; + +public class Relation { + + private int relationId; + private int bookId; + private int studentId; + + public Relation() { + } + + public int getRelationId() { + return relationId; + } + + public void setRelationId(int relationId) { + this.relationId = relationId; + } + + public int getBookId(){ + return bookId; + } + + public void setBookId(int bookId) { + this.bookId = bookId; + } + + public int getStudentId() { + return studentId; + } + + public void setStudentId(int studentId) { + this.studentId = studentId; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Relation relation = (Relation) o; + return relationId == relation.relationId && bookId == relation.bookId && studentId == relation.studentId; + } + + @Override + public int hashCode() { + return Objects.hash(relationId, bookId, studentId); + } +} diff --git a/collections/src/main/java/ru/msu/vmk/Student.java b/collections/src/main/java/ru/msu/vmk/Student.java new file mode 100644 index 0000000..e0514e6 --- /dev/null +++ b/collections/src/main/java/ru/msu/vmk/Student.java @@ -0,0 +1,45 @@ +package ru.msu.vmk; + +import java.util.Objects; + +public class Student { + + private int studentId; + private String studentName; + + public Student() { + } + + public Student(String studentName){ + this.studentName = studentName; + } + + public int getStudentId() { + return studentId; + } + + public void setStudentId(int studentId) { + this.studentId = studentId; + } + + public String getStudentName(){ + return studentName; + } + + public void setStudentName(String studentName) { + this.studentName = studentName; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Student book = (Student) o; + return studentId == book.studentId && Objects.equals(studentName, book.studentName); + } + + @Override + public int hashCode() { + return Objects.hash(studentId, studentName); + } +} diff --git a/object-oriented-programming/pom.xml b/object-oriented-programming/pom.xml index 08c5893..6d9c60d 100644 --- a/object-oriented-programming/pom.xml +++ b/object-oriented-programming/pom.xml @@ -23,6 +23,12 @@ junit-jupiter 5.9.2 + + ru.msu.vmk + basics + 1.0-SNAPSHOT + compile + @@ -35,4 +41,4 @@ - \ No newline at end of file + diff --git a/object-oriented-programming/src/main/java/ru/msu/vmk/Quantity.java b/object-oriented-programming/src/main/java/ru/msu/vmk/Quantity.java index 6c1810e..ea1b336 100644 --- a/object-oriented-programming/src/main/java/ru/msu/vmk/Quantity.java +++ b/object-oriented-programming/src/main/java/ru/msu/vmk/Quantity.java @@ -1,6 +1,9 @@ package ru.msu.vmk; import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicInteger; /** * По примеру класса {@link Money} реализовать класс Quantity: @@ -13,11 +16,23 @@ *
- для проверки работы реализовать функцию main() или Unit-test */ public class Quantity { + + private final BigDecimal amount; + private final String unitOfMeasurement; + /** * @param amount - сумма * @param unitOfMeasurement - единица измерения */ public Quantity(BigDecimal amount, String unitOfMeasurement) { + if (amount == null) { + throw new IllegalArgumentException("amount cannot be null"); + } + if (unitOfMeasurement == null || unitOfMeasurement.isBlank()) { + throw new IllegalArgumentException("currency cannot be empty"); + } + this.amount = amount.setScale(2, RoundingMode.HALF_EVEN); + this.unitOfMeasurement = unitOfMeasurement; } /** @@ -25,7 +40,7 @@ public Quantity(BigDecimal amount, String unitOfMeasurement) { * @return {@link Quantity#amount} */ public BigDecimal getAmount() { - return null; + return amount; } /** @@ -35,7 +50,9 @@ public BigDecimal getAmount() { * @return сумма чисел */ public Quantity add(Quantity quantity) throws Exception { - return null; + validateCurrenciesAreEqual(quantity); + BigDecimal sum = this.amount.add(quantity.amount); + return new Quantity(sum, this.unitOfMeasurement); } /** @@ -45,7 +62,9 @@ public Quantity add(Quantity quantity) throws Exception { * @return разность чисел */ public Quantity subtract(Quantity quantity) throws Exception { - return null; + validateCurrenciesAreEqual(quantity); + BigDecimal result = this.amount.subtract(quantity.amount); + return new Quantity(result, this.unitOfMeasurement); } /** @@ -55,7 +74,9 @@ public Quantity subtract(Quantity quantity) throws Exception { * @return произведение */ public Quantity multiply(Quantity quantity) throws Exception { - return null; + validateCurrenciesAreEqual(quantity); + BigDecimal result = this.amount.multiply(quantity.amount); + return new Quantity(result, this.unitOfMeasurement); } /** @@ -65,7 +86,9 @@ public Quantity multiply(Quantity quantity) throws Exception { * @return частное */ public Quantity divide(Quantity quantity) throws Exception { - return null; + validateCurrenciesAreEqual(quantity); + BigDecimal result = this.amount.divide(quantity.amount, RoundingMode.HALF_EVEN); + return new Quantity(result, this.unitOfMeasurement); } /** @@ -75,6 +98,12 @@ public Quantity divide(Quantity quantity) throws Exception { * @return равные части числа */ public Quantity[] divide(int n) throws Exception { - return null; + return Arrays.stream(NumberSample.split(this.amount, n)).map(bigDecimal -> new Quantity(bigDecimal, this.unitOfMeasurement)).toArray(Quantity[]::new); + } + + private void validateCurrenciesAreEqual(Quantity quantity) { + if (!this.unitOfMeasurement.equals(quantity.unitOfMeasurement)) { + throw new IllegalArgumentException("Валюты не совпадают: " + this.unitOfMeasurement + " " + quantity.unitOfMeasurement); + } } }