From b2aa9984098bc8b1e4d2fd3a0f19c5ffbd0937e9 Mon Sep 17 00:00:00 2001 From: PeucT Date: Mon, 27 Feb 2017 18:43:49 +0300 Subject: [PATCH 01/51] Task 2312 (big task) in progress. Part 13 has been done --- .../task23/task2312/KeyboardObserver.java | 81 ++++++++++ .../javarush/task/task23/task2312/Mouse.java | 19 +++ .../javarush/task/task23/task2312/Room.java | 142 ++++++++++++++++++ .../javarush/task/task23/task2312/Snake.java | 47 ++++++ .../task/task23/task2312/SnakeDirection.java | 9 ++ .../task/task23/task2312/SnakeSection.java | 20 +++ 6 files changed, 318 insertions(+) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2312/KeyboardObserver.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2312/Mouse.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2312/Room.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2312/Snake.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2312/SnakeDirection.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2312/SnakeSection.java diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2312/KeyboardObserver.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/KeyboardObserver.java new file mode 100644 index 0000000..0ff7a16 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/KeyboardObserver.java @@ -0,0 +1,81 @@ +package com.javarush.task.task23.task2312; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.util.Queue; +import java.util.concurrent.ArrayBlockingQueue; + +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; + +public class KeyboardObserver extends Thread +{ + private Queue keyEvents = new ArrayBlockingQueue(100); + + private JFrame frame; + + @Override + public void run() + { + frame = new JFrame("KeyPress Tester"); + frame.setTitle("Transparent JFrame Demo"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + frame.setUndecorated(true); + frame.setSize(400, 400); + frame.setExtendedState(JFrame.MAXIMIZED_BOTH); + frame.setLayout(new GridBagLayout()); + + frame.setOpacity(0.0f); + frame.setVisible(true); + + frame.addFocusListener(new FocusListener() + { + @Override + public void focusGained(FocusEvent e) + { + //do nothing + } + + @Override + public void focusLost(FocusEvent e) + { + System.exit(0); + } + }); + + + frame.addKeyListener(new KeyListener() + { + + public void keyTyped(KeyEvent e) + { + //do nothing + } + + public void keyReleased(KeyEvent e) + { + //do nothing + } + + public void keyPressed(KeyEvent e) + { + keyEvents.add(e); + } + }); + } + + + public boolean hasKeyEvents() + { + return !keyEvents.isEmpty(); + } + + public KeyEvent getEventFromTop() + { + return keyEvents.poll(); + } +} + diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Mouse.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Mouse.java new file mode 100644 index 0000000..2795c84 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Mouse.java @@ -0,0 +1,19 @@ +package com.javarush.task.task23.task2312; + +public class Mouse { + private int x; + private int y; + + public Mouse(int x, int y) { + this.x = x; + this.y = y; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Room.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Room.java new file mode 100644 index 0000000..cfc134b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Room.java @@ -0,0 +1,142 @@ +package com.javarush.task.task23.task2312; + + +import java.awt.event.KeyEvent; + +/** + * Основной класс программы. + */ +public class Room { + private int width; + private int height; + private Snake snake; + private Mouse mouse; + + public Room(int width, int height, Snake snake) { + this.width = width; + this.height = height; + this.snake = snake; + } + + public Snake getSnake() { + return snake; + } + + public Mouse getMouse() { + return mouse; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public void setWidth(int width) { + this.width = width; + } + + public void setHeight(int height) { + this.height = height; + } + + public void setSnake(Snake snake) { + this.snake = snake; + } + + public void setMouse(Mouse mouse) { + this.mouse = mouse; + } + + /** + * Основной цикл программы. + * Тут происходят все важные действия + */ + public void run() throws InterruptedException { + //Создаем объект "наблюдатель за клавиатурой" и стартуем его. + KeyboardObserver keyboardObserver = new KeyboardObserver(); + keyboardObserver.start(); + + //пока змея жива + while (snake.isAlive()) { + //"наблюдатель" содержит события о нажатии клавиш? + if (keyboardObserver.hasKeyEvents()) { + KeyEvent event = keyboardObserver.getEventFromTop(); + //Если равно символу 'q' - выйти из игры. + if (event.getKeyChar() == 'q') return; + + //Если "стрелка влево" - сдвинуть фигурку влево + if (event.getKeyCode() == KeyEvent.VK_LEFT) + snake.setDirection(SnakeDirection.LEFT); + //Если "стрелка вправо" - сдвинуть фигурку вправо + else if (event.getKeyCode() == KeyEvent.VK_RIGHT) + snake.setDirection(SnakeDirection.RIGHT); + //Если "стрелка вверх" - сдвинуть фигурку вверх + else if (event.getKeyCode() == KeyEvent.VK_UP) + snake.setDirection(SnakeDirection.UP); + //Если "стрелка вниз" - сдвинуть фигурку вниз + else if (event.getKeyCode() == KeyEvent.VK_DOWN) + snake.setDirection(SnakeDirection.DOWN); + } + + snake.move(); //двигаем змею + print(); //отображаем текущее состояние игры + sleep(); //пауза между ходами + } + + //Выводим сообщение "Game Over" + System.out.println("Game Over!"); + } + + /** + * Выводим на экран текущее состояние игры + */ + public void print() { + //Создаем массив, куда будем "рисовать" текущее состояние игры + //Рисуем все кусочки змеи + //Рисуем мышь + //Выводим все это на экран + } + + /** + * Метод вызывается, когда мышь съели + */ + public void eatMouse() { + createMouse(); + } + + /** + * Создает новую мышь + */ + public void createMouse() { + int x = (int) (Math.random() * width); + int y = (int) (Math.random() * height); + + mouse = new Mouse(x, y); + } + + + public static Room game; + + public static void main(String[] args) throws InterruptedException { + game = new Room(20, 20, new Snake(10, 10)); + game.snake.setDirection(SnakeDirection.DOWN); + game.createMouse(); + game.run(); + } + + + /** + * Программа делает паузу, длинна которой зависит от длинны змеи. + */ + public void sleep() throws InterruptedException { + if (getSnake().getSections().size() >= 15 ) { + Thread.currentThread().sleep(200); + } else { + Thread.currentThread().sleep(500 - ( getSnake().getSections().size() - 1) * 20); + } + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Snake.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Snake.java new file mode 100644 index 0000000..3bd3bdc --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Snake.java @@ -0,0 +1,47 @@ +package com.javarush.task.task23.task2312; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by ArchMage on 27.02.17. + */ +public class Snake { + private List sections; + private boolean isAlive; + private SnakeDirection direction; + + public List getSections() { + return sections; + } + + public boolean isAlive() { + return isAlive; + } + + public SnakeDirection getDirection() { + return direction; + } + + public void setDirection(SnakeDirection direction) { + this.direction = direction; + } + + public Snake(int x, int y) { + sections = new ArrayList(); + sections.add(new SnakeSection(x,y)); + isAlive = true; + } + + public int getX(){ + return sections.get(0).getX(); + } + + public int getY() { + return sections.get(0).getY(); + } + + public void move() { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2312/SnakeDirection.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/SnakeDirection.java new file mode 100644 index 0000000..d8a3b0d --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/SnakeDirection.java @@ -0,0 +1,9 @@ +package com.javarush.task.task23.task2312; + + +public enum SnakeDirection { + UP, + RIGHT, + DOWN, + LEFT +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2312/SnakeSection.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/SnakeSection.java new file mode 100644 index 0000000..87872f3 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/SnakeSection.java @@ -0,0 +1,20 @@ +package com.javarush.task.task23.task2312; + +public class SnakeSection { + private int x; + private int y; + + + public SnakeSection(int x, int y) { + this.x = x; + this.y = y; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } +} From b97acabba1af4d46e4fd9ae0d90d4c6da3bd0565 Mon Sep 17 00:00:00 2001 From: PeucT Date: Thu, 2 Mar 2017 18:03:28 +0300 Subject: [PATCH 02/51] Task 2312 parts 14-16 (must be 2213) --- .../javarush/task/task23/task2312/Room.java | 42 +++++++++++++++---- .../javarush/task/task23/task2312/Snake.java | 32 ++++++++++++++ .../task/task23/task2312/SnakeSection.java | 20 +++++++++ 3 files changed, 86 insertions(+), 8 deletions(-) diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Room.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Room.java index cfc134b..e42d0a7 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Room.java +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Room.java @@ -2,6 +2,7 @@ import java.awt.event.KeyEvent; +import java.util.ArrayList; /** * Основной класс программы. @@ -54,7 +55,7 @@ public void setMouse(Mouse mouse) { * Основной цикл программы. * Тут происходят все важные действия */ - public void run() throws InterruptedException { + public void run() { //Создаем объект "наблюдатель за клавиатурой" и стартуем его. KeyboardObserver keyboardObserver = new KeyboardObserver(); keyboardObserver.start(); @@ -95,9 +96,31 @@ else if (event.getKeyCode() == KeyEvent.VK_DOWN) */ public void print() { //Создаем массив, куда будем "рисовать" текущее состояние игры + int[][] matrix = new int[height][width]; + //Рисуем все кусочки змеи + ArrayList sections = new ArrayList(snake.getSections()); + for (SnakeSection snakeSection : sections) { + matrix[snakeSection.getY()][snakeSection.getX()] = 1; + } + + //Рисуем голову змеи (4 - если змея мертвая) + matrix[snake.getY()][snake.getX()] = snake.isAlive() ? 2 : 4; + //Рисуем мышь + matrix[mouse.getY()][mouse.getX()] = 3; + //Выводим все это на экран + String[] symbols = {" . ", " x ", " X ", "^_^", "RIP"}; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + System.out.print(symbols[matrix[y][x]]); + } + System.out.println(); + } + System.out.println(); + System.out.println(); + System.out.println(); } /** @@ -120,7 +143,7 @@ public void createMouse() { public static Room game; - public static void main(String[] args) throws InterruptedException { + public static void main(String[] args) { game = new Room(20, 20, new Snake(10, 10)); game.snake.setDirection(SnakeDirection.DOWN); game.createMouse(); @@ -128,15 +151,18 @@ public static void main(String[] args) throws InterruptedException { } + private int initialDelay = 520; + private int delayStep = 20; + /** * Программа делает паузу, длинна которой зависит от длинны змеи. */ - public void sleep() throws InterruptedException { - if (getSnake().getSections().size() >= 15 ) { - Thread.currentThread().sleep(200); - } else { - Thread.currentThread().sleep(500 - ( getSnake().getSections().size() - 1) * 20); + public void sleep() { + try { + int level = snake.getSections().size(); + int delay = level < 15 ? (initialDelay - delayStep * level) : 200; + Thread.sleep(delay); + } catch (InterruptedException e) { } - } } diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Snake.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Snake.java index 3bd3bdc..6d22156 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Snake.java +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Snake.java @@ -3,6 +3,8 @@ import java.util.ArrayList; import java.util.List; + + /** * Created by ArchMage on 27.02.17. */ @@ -42,6 +44,36 @@ public int getY() { } public void move() { + if (!isAlive) return; + + if (direction == SnakeDirection.UP) + move(0, -1); + else if (direction == SnakeDirection.RIGHT) + move(1, 0); + else if (direction == SnakeDirection.DOWN) + move(0, 1); + else if (direction == SnakeDirection.LEFT) + move(-1, 0); + } + + public void move(int x, int y) { + SnakeSection head = sections.get(0); + head = new SnakeSection(head.getX() + x, getY() + y); + checkBorders(head); + if (!isAlive) return; + checkBody(head); + if (!isAlive) return; + } + + public void checkBorders(SnakeSection head) { + if ((head.getX() < 0 || head.getX() >= Room.game.getWidth()) || + (head.getY() < 0 || head.getY() >= Room.game.getHeight())) { + isAlive = false; + } + } + + public void checkBody(SnakeSection head) { + if (sections.contains(head)) { isAlive = false;} } } diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2312/SnakeSection.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/SnakeSection.java index 87872f3..17f3977 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task23/task2312/SnakeSection.java +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/SnakeSection.java @@ -17,4 +17,24 @@ public int getX() { public int getY() { return y; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + SnakeSection that = (SnakeSection) o; + + if (x != that.x) return false; + if (y != that.y) return false; + return true; + + } + + @Override + public int hashCode() { + int result = x; + result = 31 * result + y; + return result; + } } From 7592a9ec206f77a2173386b3a024bc0f512804d2 Mon Sep 17 00:00:00 2001 From: PeucT Date: Fri, 3 Mar 2017 17:08:43 +0300 Subject: [PATCH 03/51] 2301 - 2311 --- .../task/task23/task2301/Solution.java | 21 +++++ .../task/task23/task2302/Solution.java | 21 +++++ .../task/task23/task2303/Solution.java | 24 ++++++ .../javarush/task/task23/task2304/DbMock.java | 18 ++++ .../task/task23/task2304/Solution.java | 51 ++++++++++++ .../task/task23/task2304/ViewMock.java | 17 ++++ .../task/task23/task2305/Solution.java | 26 ++++++ .../task/task23/task2306/Solution.java | 46 +++++++++++ .../task/task23/task2307/Solution.java | 22 +++++ .../task/task23/task2308/Solution.java | 59 +++++++++++++ .../task2309/AbstractDbSelectExecutor.java | 45 ++++++++++ .../task/task23/task2309/Solution.java | 82 +++++++++++++++++++ .../task/task23/task2309/vo/Location.java | 7 ++ .../task/task23/task2309/vo/NamedItem.java | 34 ++++++++ .../task/task23/task2309/vo/Server.java | 7 ++ .../task/task23/task2309/vo/Subject.java | 7 ++ .../task/task23/task2309/vo/Subscription.java | 7 ++ .../task/task23/task2309/vo/User.java | 7 ++ .../task/task23/task2310/Solution.java | 32 ++++++++ .../task/task23/task2311/Solution.java | 52 ++++++++++++ 20 files changed, 585 insertions(+) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2301/Solution.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2302/Solution.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2303/Solution.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2304/DbMock.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2304/Solution.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2304/ViewMock.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2305/Solution.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2306/Solution.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2307/Solution.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2308/Solution.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2309/AbstractDbSelectExecutor.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2309/Solution.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Location.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/NamedItem.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Server.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Subject.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Subscription.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/User.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2310/Solution.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task23/task2311/Solution.java diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2301/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2301/Solution.java new file mode 100644 index 0000000..490f536 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2301/Solution.java @@ -0,0 +1,21 @@ +package com.javarush.task.task23.task2301; + +/* +Запрети наследование +*/ +public class Solution { + + public static final class Listener { + public void onMouseDown(int x, int y) { + //do something on mouse down event + } + + public void onMouseUp(int x, int y) { + //do something on mouse up event + } + } + + public static void main(String[] args) { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2302/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2302/Solution.java new file mode 100644 index 0000000..bf0672c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2302/Solution.java @@ -0,0 +1,21 @@ +package com.javarush.task.task23.task2302; + +/* +Запрети переопределение +*/ +public class Solution { + + public static class Listener { + public final void onMouseDown(int x, int y) { + //do something on mouse down event + } + + public void onMouseUp(int x, int y) { + //do something on mouse up event + } + } + + public static void main(String[] args) { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2303/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2303/Solution.java new file mode 100644 index 0000000..17318f6 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2303/Solution.java @@ -0,0 +1,24 @@ +package com.javarush.task.task23.task2303; + +/* +Запрети создание экземпляров класса +*/ +public class Solution { + + public static abstract class Listener { + + public void onMouseDown(int x, int y) { + //do something on mouse down event + } + + public void onMouseUp(int x, int y) { + //do something on mouse up event + } + + + } + + public static void main(String[] args) { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2304/DbMock.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2304/DbMock.java new file mode 100644 index 0000000..44fdbf9 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2304/DbMock.java @@ -0,0 +1,18 @@ +package com.javarush.task.task23.task2304; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class DbMock { + private static final List FAKE_TASKS = new ArrayList<>(); + private static final List FAKE_NAMES = new ArrayList<>(); + + public static List getFakeTasks(Map criteria) { + return ViewMock.getFakeTasksCriteria().equals(criteria) ? FAKE_TASKS : null; + } + + public static List getFakeNames(Map criteria) { + return ViewMock.getFakeNamesCriteria().equals(criteria) ? FAKE_NAMES : null; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2304/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2304/Solution.java new file mode 100644 index 0000000..50adfb6 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2304/Solution.java @@ -0,0 +1,51 @@ +package com.javarush.task.task23.task2304; + +import java.util.List; +import java.util.Map; + +/* +Inner 3 +*/ +public class Solution { + + private List tasks; + private List names; + + private DbDataProvider taskDataProvider = new TaskDataProvider(); + private DbDataProvider nameDataProvider = new NameDataProvider(); + + public void refresh() { + Map taskCriteria = ViewMock.getFakeTasksCriteria(); + taskDataProvider.refreshAllData(taskCriteria); + + Map nameCriteria = ViewMock.getFakeNamesCriteria(); + nameDataProvider.refreshAllData(nameCriteria); + } + + private interface DbDataProvider { + void refreshAllData(Map criteria); + } + + class Task { + } + + private class TaskDataProvider implements DbDataProvider{ + + @Override + public void refreshAllData(Map criteria) { + tasks = DbMock.getFakeTasks(criteria); + } + } + + private class NameDataProvider implements DbDataProvider{ + + @Override + public void refreshAllData(Map criteria) { + names = DbMock.getFakeNames(criteria); + } + } + + public static void main(String[] args) { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2304/ViewMock.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2304/ViewMock.java new file mode 100644 index 0000000..53bb1cf --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2304/ViewMock.java @@ -0,0 +1,17 @@ +package com.javarush.task.task23.task2304; + +import java.util.HashMap; +import java.util.Map; + +public class ViewMock { + private static final Map FAKE_TASKS_CRITERIA = new HashMap(); + private static final Map FAKE_NAMES_CRITERIA = new HashMap(); + + public static Map getFakeTasksCriteria() { + return FAKE_TASKS_CRITERIA; + } + + public static Map getFakeNamesCriteria() { + return FAKE_NAMES_CRITERIA; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2305/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2305/Solution.java new file mode 100644 index 0000000..7f5cec6 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2305/Solution.java @@ -0,0 +1,26 @@ +package com.javarush.task.task23.task2305; + +/* +Inner +*/ +public class Solution { + public InnerClass[] innerClasses = new InnerClass[2]; + + public class InnerClass { + } + + public static Solution[] getTwoSolutions() { + Solution[] result = new Solution[2]; + for (int i = 0; i < 2; i++) { + Solution sol = new Solution(); + sol.innerClasses[0] = sol.new InnerClass(); + sol.innerClasses[1] = sol.new InnerClass(); + result[i] = sol; + } + return result; + } + + public static void main(String[] args) { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2306/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2306/Solution.java new file mode 100644 index 0000000..0ff5356 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2306/Solution.java @@ -0,0 +1,46 @@ +package com.javarush.task.task23.task2306; + +/* +Inner 2 +*/ +public class Solution { + private String country; + private String city; + + public Solution(String country, String city) { + this.country = country; + this.city = city; + } + + /*т.к. модификатор иннер класса private, то чтобы вызвать метод getDescription из другого внешнего класса, + нужно обернуть его вызов в какой-то public метод*/ + public String getDescriptionOfUser(String name) { + return getTrickyUser(name).getDescription(); + } + + public SuperUser getTrickyUser(String name) { + return new SuperUser(name); + } + + private class SuperUser { + private String name; + + //доступ к этому методу возможен только внутри класса Solution, т.к. модификатор иннер класса private + public SuperUser(String name) { + this.name = name; + } + + //доступ к этому методу возможен только внутри класса Solution, т.к. модификатор иннер класса private + public String getDescription() { + return String.format("My name is %s. I'm from %s, %s.", this.name, country, city); + } + } + + public static void main(String[] args) { + Solution solution = new Solution("the USA", "Seattle"); + //внутри класса Solution (а сейчас мы внутри) к методу getDescription можно обращаться обоими способами + System.out.println(solution.getTrickyUser("George").getDescription()); + //а из любого другого внешнего класса только так: + System.out.println(solution.getDescriptionOfUser("George")); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2307/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2307/Solution.java new file mode 100644 index 0000000..6d37e68 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2307/Solution.java @@ -0,0 +1,22 @@ +package com.javarush.task.task23.task2307; + +/* +Как выбрать нужное? +*/ +public class Solution { + public static final String TEST = "test"; + + public static class TEST { + @Override + public String toString() { + return "test class"; + } + } + + static Object obj; + + public static void main(String[] args) { + obj = new Solution.TEST(); + System.out.println(obj); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2308/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2308/Solution.java new file mode 100644 index 0000000..1d6f309 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2308/Solution.java @@ -0,0 +1,59 @@ +package com.javarush.task.task23.task2308; + +/* +Рефакторинг, вложенные классы +*/ +public class Solution { + public class ServerNotAccessibleException extends Exception { + public ServerNotAccessibleException() { + super(Constants.SERVER_IS_NOT_ACCESSIBLE_FOR_NOW); + } + + public ServerNotAccessibleException(Throwable cause) { + super(Constants.SERVER_IS_NOT_ACCESSIBLE_FOR_NOW, cause); + } + } + + public class UnauthorizedUserException extends Exception { + public UnauthorizedUserException() { + super(Constants.USER_IS_NOT_AUTHORIZED); + } + + public UnauthorizedUserException(Throwable cause) { + super(Constants.USER_IS_NOT_AUTHORIZED, cause); + } + } + + public class BannedUserException extends Exception { + public BannedUserException() { + super(Constants.USER_IS_BANNED); + } + + public BannedUserException(Throwable cause) { + super(Constants.USER_IS_BANNED, cause); + } + } + + public class RestrictionException extends Exception { + public RestrictionException() { + super(Constants.ACCESS_IS_DENIED); + } + + public RestrictionException(Throwable cause) { + super(Constants.ACCESS_IS_DENIED, cause); + } + } + + public static final class Constants{ + + public static final String SERVER_IS_NOT_ACCESSIBLE_FOR_NOW = "Server is not accessible for now."; + public static final String USER_IS_NOT_AUTHORIZED = "User is not authorized."; + public static final String USER_IS_BANNED = "User is banned."; + public static final String ACCESS_IS_DENIED = "Access is denied."; + + } + + public static void main(String[] args) { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2309/AbstractDbSelectExecutor.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/AbstractDbSelectExecutor.java new file mode 100644 index 0000000..0adab74 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/AbstractDbSelectExecutor.java @@ -0,0 +1,45 @@ +package com.javarush.task.task23.task2309; + +import com.javarush.task.task23.task2309.vo.*; + +import java.lang.reflect.ParameterizedType; +import java.util.ArrayList; +import java.util.List; + +public abstract class AbstractDbSelectExecutor { + + public abstract String getQuery(); + + /** + * It's fake method + * + * @return a list of 5 fake items + */ + public List execute() { + List result = new ArrayList<>(); + //assert the query is not null + String query = getQuery(); + if (query == null) return result; + + try { + //generate 5 fake items + for (int i = 1; i <= 5; i++) { + T newItem = getNewInstanceOfGenericType(); + newItem.setId(i); + newItem.setName(newItem.getClass().getSimpleName() + "-" + i); + newItem.setDescription("Got by executing '" + query + "'"); + result.add(newItem); + } + } catch (InstantiationException | IllegalAccessException e) { + e.printStackTrace(); + } + return result; + } + + //reflection + //you have to know that it is possible to create new instance of T (generic type) class by using its default constructor + private T getNewInstanceOfGenericType() throws InstantiationException, IllegalAccessException { + return (T) ((Class) ((ParameterizedType) this.getClass(). + getGenericSuperclass()).getActualTypeArguments()[0]).newInstance(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2309/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/Solution.java new file mode 100644 index 0000000..ad0ec87 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/Solution.java @@ -0,0 +1,82 @@ +package com.javarush.task.task23.task2309; + +import com.javarush.task.task23.task2309.vo.*; + +import java.lang.reflect.ParameterizedType; +import java.util.List; + +/* +Анонимность иногда так приятна! +*/ +public class Solution { + public static void main(String[] args) { + Solution solution = new Solution(); + print(solution.getUsers()); + print(solution.getLocations()); + } + + public static void print(List list) { + String format = "Id=%d, name='%s', description=%s"; + for (Object obj : list) { + NamedItem item = (NamedItem) obj; + System.out.println(String.format(format, item.getId(), item.getName(), item.getDescription())); + } + } + + public List getUsers() { + return new AbstractDbSelectExecutor(){ + + @Override + public String getQuery() { + + return "SELECT * FROM " + ((Class) ((ParameterizedType) this.getClass(). + getGenericSuperclass()).getActualTypeArguments()[0]).getSimpleName().toUpperCase(); + } + }.execute(); + } + + public List getLocations() { + return new AbstractDbSelectExecutor(){ + + @Override + public String getQuery() { + return "SELECT * FROM " + ((Class) ((ParameterizedType) this.getClass(). + getGenericSuperclass()).getActualTypeArguments()[0]).getSimpleName().toUpperCase(); + } + }.execute(); + } + + public List getServers() { + return new AbstractDbSelectExecutor(){ + + @Override + public String getQuery() { + return "SELECT * FROM " + ((Class) ((ParameterizedType) this.getClass(). + getGenericSuperclass()).getActualTypeArguments()[0]).getSimpleName().toUpperCase(); + } + }.execute(); + } + + public List getSubjects() { + return new AbstractDbSelectExecutor(){ + + @Override + public String getQuery() { + return "SELECT * FROM " + ((Class) ((ParameterizedType) this.getClass(). + getGenericSuperclass()).getActualTypeArguments()[0]).getSimpleName().toUpperCase(); + } + }.execute(); + } + + public List getSubscriptions() { + return new AbstractDbSelectExecutor(){ + + @Override + public String getQuery() { + return "SELECT * FROM " + ((Class) ((ParameterizedType) this.getClass(). + getGenericSuperclass()).getActualTypeArguments()[0]).getSimpleName().toUpperCase(); + } + }.execute(); + } + +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Location.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Location.java new file mode 100644 index 0000000..b035eab --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Location.java @@ -0,0 +1,7 @@ +package com.javarush.task.task23.task2309.vo; + +/** + * Created by ArchMage on 02.03.17. + */ +public class Location extends NamedItem { +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/NamedItem.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/NamedItem.java new file mode 100644 index 0000000..9a788e1 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/NamedItem.java @@ -0,0 +1,34 @@ +package com.javarush.task.task23.task2309.vo; + +public class NamedItem { + private int id; + private String name; + private String description; + + public NamedItem() { + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Server.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Server.java new file mode 100644 index 0000000..160a41e --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Server.java @@ -0,0 +1,7 @@ +package com.javarush.task.task23.task2309.vo; + +/** + * Created by ArchMage on 02.03.17. + */ +public class Server extends NamedItem { +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Subject.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Subject.java new file mode 100644 index 0000000..ae6121b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Subject.java @@ -0,0 +1,7 @@ +package com.javarush.task.task23.task2309.vo; + +/** + * Created by ArchMage on 02.03.17. + */ +public class Subject extends NamedItem { +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Subscription.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Subscription.java new file mode 100644 index 0000000..405d441 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Subscription.java @@ -0,0 +1,7 @@ +package com.javarush.task.task23.task2309.vo; + +/** + * Created by ArchMage on 02.03.17. + */ +public class Subscription extends NamedItem { +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/User.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/User.java new file mode 100644 index 0000000..da2eedf --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/User.java @@ -0,0 +1,7 @@ +package com.javarush.task.task23.task2309.vo; + +/** + * Created by ArchMage on 02.03.17. + */ +public class User extends NamedItem { +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2310/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2310/Solution.java new file mode 100644 index 0000000..b72195f --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2310/Solution.java @@ -0,0 +1,32 @@ +package com.javarush.task.task23.task2310; + +/* +Напряги извилины! +*/ +public class Solution { + private String name; + + Solution(String name) { + this.name = name; + } + + protected String getName() { + return name; + } + + private void sout() { + new Solution("sout") { + + + void printName() { + System.out.println(getName()); + } + + + }.printName(); + } + + public static void main(String[] args) { + new Solution("main").sout(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2311/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2311/Solution.java new file mode 100644 index 0000000..2b5a633 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2311/Solution.java @@ -0,0 +1,52 @@ +package com.javarush.task.task23.task2311; + +/* +Повторяем threads +*/ +public class Solution { + public final String name; + public final String food; + public final String sound; + + public Solution(String name, String food, String sound) { + this.name = name; + this.food = food; + this.sound = sound; + } + + public void eat() { + System.out.println(name + ": Mmmmm, " + food); + } + + public void play() { + System.out.println(name + ": " + sound + " " + sound); + } + + public void sleep(long milliseconds) { + System.out.println(name + ": Zzzzzzz..." + (milliseconds / 1000) + " sec"); + } + + public void live() throws InterruptedException { + Thread thread = new Thread() { + public void run() { + try { + someActions(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void someActions() throws InterruptedException { + eat(); + play(); + Solution.this.sleep(1000); + } + }; + thread.start(); + thread.join(); + } + + public static void main(String[] args) throws InterruptedException { + new Solution("Amigo", "beef", "knock").live(); + } +} From 92cdd8d576c25a588a2ab98c171c6a7064a1d72f Mon Sep 17 00:00:00 2001 From: PAKOT Date: Sun, 12 Mar 2017 04:57:43 +0300 Subject: [PATCH 04/51] lvl 24 --- .../task24/task2401/SelfInterfaceMarker.java | 7 + .../task2401/SelfInterfaceMarkerImpl.java | 14 ++ .../task/task24/task2401/Solution.java | 12 + .../UnsupportedInterfaceMarkerException.java | 7 + .../javarush/task/task24/task2401/Util.java | 16 ++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 11 + .../task/task24/task2402/Solution.java | 46 ++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 7 + .../task/task24/task2403/Solution.java | 33 +++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 9 + .../task/task24/task2404/HasHeight.java | 5 + .../task/task24/task2404/HasWidth.java | 5 + .../javarush/task/task24/task2404/Point.java | 19 ++ .../task/task24/task2404/Solution.java | 61 +++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 13 + .../javarush/task/task24/task2405/Action.java | 5 + .../task/task24/task2405/FirstClass.java | 14 ++ .../task/task24/task2405/SecondClass.java | 16 ++ .../task/task24/task2405/Solution.java | 79 ++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 12 + .../task/task24/task2406/Solution.java | 37 +++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 8 + .../javarush/task/task24/task2407/Cat.java | 48 ++++ .../javarush/task/task24/task2407/Mouse.java | 17 ++ .../javarush/task/task24/task2407/Pet.java | 5 + .../task/task24/task2407/Sayable.java | 5 + .../task/task24/task2407/Solution.java | 14 ++ .../javarush/task/task24/task2407/Util.java | 32 +++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 7 + .../javarush/task/task24/task2408/Dog.java | 66 +++++ .../javarush/task/task24/task2408/Mouse.java | 17 ++ .../javarush/task/task24/task2408/Pet.java | 5 + .../task/task24/task2408/Sayable.java | 5 + .../task/task24/task2408/Solution.java | 14 ++ .../task/task24/task2408/SuperDog.java | 12 + .../javarush/task/task24/task2408/Util.java | 32 +++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 7 + .../javarush/task/task24/task2409/Item.java | 10 + .../javarush/task/task24/task2409/Jeans.java | 9 + .../task/task24/task2409/Solution.java | 18 ++ .../javarush/task/task24/task2409/Util.java | 128 ++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 16 ++ .../task/task24/task2410/Iterator.java | 5 + .../task/task24/task2410/Solution.java | 48 ++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 9 + .../com/javarush/task/task24/task2411/C.java | 8 + .../task/task24/task2411/JustAnInterface.java | 11 + .../task/task24/task2411/Solution.java | 34 +++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 7 + .../task/task24/task2412/Solution.java | 135 ++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 15 ++ .../task/task24/task2413/Arkanoid.java | 238 ++++++++++++++++++ .../javarush/task/task24/task2413/Ball.java | 116 +++++++++ .../task/task24/task2413/BaseObject.java | 73 ++++++ .../javarush/task/task24/task2413/Brick.java | 35 +++ .../javarush/task/task24/task2413/Canvas.java | 86 +++++++ .../task24/task2413/KeyboardObserver.java | 69 +++++ .../javarush/task/task24/task2413/Stand.java | 64 +++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 107 ++++++++ .../task/task36/task3608/Solution.java | 30 +++ .../javarush/task/task36/task3608/Util.java | 17 ++ .../task/task36/task3608/bean/User.java | 69 +++++ .../task3608/controller/Controller.java | 53 ++++ .../task/task36/task3608/dao/UserDao.java | 82 ++++++ .../task36/task3608/dao/mock/DataSource.java | 59 +++++ .../task/task36/task3608/model/FakeModel.java | 52 ++++ .../task/task36/task3608/model/MainModel.java | 57 +++++ .../task/task36/task3608/model/Model.java | 14 ++ .../task/task36/task3608/model/ModelData.java | 40 +++ .../task3608/model/service/UserService.java | 21 ++ .../model/service/UserServiceImpl.java | 73 ++++++ .../task36/task3608/view/EditUserView.java | 33 +++ .../task/task36/task3608/view/UsersView.java | 46 ++++ .../task/task36/task3608/view/View.java | 12 + ...\273\320\276\320\262\320\270\320\265.jrtc" | 144 +++++++++++ 75 files changed, 2765 insertions(+) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2401/SelfInterfaceMarker.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2401/SelfInterfaceMarkerImpl.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2401/Solution.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2401/UnsupportedInterfaceMarkerException.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2401/Util.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task24/task2401/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2402/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task24/task2402/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2403/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task24/task2403/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2404/HasHeight.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2404/HasWidth.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2404/Point.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2404/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task24/task2404/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2405/Action.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2405/FirstClass.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2405/SecondClass.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2405/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task24/task2405/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2406/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task24/task2406/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2407/Cat.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2407/Mouse.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2407/Pet.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2407/Sayable.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2407/Solution.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2407/Util.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task24/task2407/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2408/Dog.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2408/Mouse.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2408/Pet.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2408/Sayable.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2408/Solution.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2408/SuperDog.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2408/Util.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task24/task2408/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2409/Item.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2409/Jeans.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2409/Solution.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2409/Util.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task24/task2409/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2410/Iterator.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2410/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task24/task2410/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2411/C.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2411/JustAnInterface.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2411/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task24/task2411/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2412/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task24/task2412/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2413/Arkanoid.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2413/Ball.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2413/BaseObject.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2413/Brick.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2413/Canvas.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2413/KeyboardObserver.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task24/task2413/Stand.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task24/task2413/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task36/task3608/Solution.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task36/task3608/Util.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task36/task3608/bean/User.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task36/task3608/controller/Controller.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task36/task3608/dao/UserDao.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task36/task3608/dao/mock/DataSource.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/FakeModel.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/MainModel.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/Model.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/ModelData.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/service/UserService.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/service/UserServiceImpl.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task36/task3608/view/EditUserView.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task36/task3608/view/UsersView.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task36/task3608/view/View.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task36/task3608/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2401/SelfInterfaceMarker.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/SelfInterfaceMarker.java new file mode 100644 index 0000000..ffa8084 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/SelfInterfaceMarker.java @@ -0,0 +1,7 @@ +package com.javarush.task.task24.task2401; + +/** + * Created by PAKOT on 08.03.2017. + */ +public interface SelfInterfaceMarker { +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2401/SelfInterfaceMarkerImpl.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/SelfInterfaceMarkerImpl.java new file mode 100644 index 0000000..3c1af58 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/SelfInterfaceMarkerImpl.java @@ -0,0 +1,14 @@ +package com.javarush.task.task24.task2401; + +/** + * Created by PAKOT on 08.03.2017. + */ +public class SelfInterfaceMarkerImpl implements SelfInterfaceMarker { + public void sowSomething(){ + System.out.println("Something"); + } + + public void calc(int i, int b){ + System.out.println(i + b); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2401/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/Solution.java new file mode 100644 index 0000000..3781821 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/Solution.java @@ -0,0 +1,12 @@ +package com.javarush.task.task24.task2401; + +/* +Создание своего интерфейса-маркера +*/ +public class Solution { + public static void main(String[] args) throws UnsupportedInterfaceMarkerException { + SelfInterfaceMarkerImpl obj = new SelfInterfaceMarkerImpl(); + Util.testClass(obj); + } + +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2401/UnsupportedInterfaceMarkerException.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/UnsupportedInterfaceMarkerException.java new file mode 100644 index 0000000..cb347a1 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/UnsupportedInterfaceMarkerException.java @@ -0,0 +1,7 @@ +package com.javarush.task.task24.task2401; + +/** + * Created by PAKOT on 08.03.2017. + */ +public class UnsupportedInterfaceMarkerException extends Exception { +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2401/Util.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/Util.java new file mode 100644 index 0000000..f3b95c1 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/Util.java @@ -0,0 +1,16 @@ +package com.javarush.task.task24.task2401; + +import java.lang.reflect.Method; + +public class Util { + //пример того, как можно использовать интерфейс-маркер + //this method is available only for a SelfInterfaceMarker implementation + public static void testClass(SelfInterfaceMarker interfaceMarker) throws UnsupportedInterfaceMarkerException { + if (interfaceMarker == null) throw new UnsupportedInterfaceMarkerException(); + + for (Method method : interfaceMarker.getClass().getDeclaredMethods()) { + System.out.println(method); + } + } + +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2401/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..05805d7 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,11 @@ +taskKey="com.javarush.task.task24.task2401" + +Создание своего интерфейса-маркера + +1. Создай интерфейс-маркер SelfInterfaceMarker. +2. Создай класс SelfInterfaceMarkerImpl, который реализует SelfInterfaceMarker. +3. Добавь в SelfInterfaceMarkerImpl минимум 2 любых public метода. +4. Создай исключение UnsupportedInterfaceMarkerException, унаследуй его от класса Exception. +5. В методе testClass класса Util: если параметр == null, то выбросьте UnsupportedInterfaceMarkerException. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2402/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2402/Solution.java new file mode 100644 index 0000000..bdfa9d6 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2402/Solution.java @@ -0,0 +1,46 @@ +package com.javarush.task.task24.task2402; + +/* +Cloneable +*/ +public class Solution { + + public static void main(String[] args) throws CloneNotSupportedException { + Test1 test1 = new Test1(); + test1.clone(); + + Test2 test2 = new Test2(); + test2.clone(new Test2()); + + Test3 test3 = new Test3(); + test3.c1one(); + + Test4 test4 = new Test4(); + test4.clone(); + } + + + public static class Test1 implements Cloneable{ + protected Test1 clone() throws CloneNotSupportedException { + return (Test1)super.clone(); + } + } + + public static class Test2 extends Test1 { + public Test2 clone(Test2 test2) throws CloneNotSupportedException { + return (Test2)test2.clone(); + } + } + + public static class Test3 { + protected Object c1one() throws CloneNotSupportedException { + return new Test3(); + } + } + + public static class Test4 extends Test3 implements Cloneable { + protected Object clone() throws CloneNotSupportedException { + return super.c1one(); + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2402/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2402/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..08a4012 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2402/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task24.task2402" + +Cloneable + +Добавьте java-код, чтобы метод main отработал без исключений. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2403/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2403/Solution.java new file mode 100644 index 0000000..338637b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2403/Solution.java @@ -0,0 +1,33 @@ +package com.javarush.task.task24.task2403; + +import java.io.Serializable; +import java.rmi.Remote; +import java.rmi.server.RemoteObject; +import java.util.ArrayDeque; +import java.util.EventListener; + +/* +Так-с... сопоставим +*/ +public class Solution { + public static class A implements Serializable { + } + + public static class B implements Remote { + } + + public static class C extends ArrayDeque { + public C clone() { + return (C) super.clone(); + } + } + + public static class D implements EventListener { + } + + + + public static void main(String[] args) { + + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2403/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2403/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..03bd329 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2403/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,9 @@ +taskKey="com.javarush.task.task24.task2403" + +Так-с... сопоставим + +Исправь ошибки: перемести методы clone в те классы, в которых они должны быть реализованы. +Лишние методы удали. +Не удаляй метод main. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2404/HasHeight.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2404/HasHeight.java new file mode 100644 index 0000000..cad7932 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2404/HasHeight.java @@ -0,0 +1,5 @@ +package com.javarush.task.task24.task2404; + +public interface HasHeight { + double getHeight(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2404/HasWidth.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2404/HasWidth.java new file mode 100644 index 0000000..8aff6ef --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2404/HasWidth.java @@ -0,0 +1,5 @@ +package com.javarush.task.task24.task2404; + +public interface HasWidth { + double getWidth(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2404/Point.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2404/Point.java new file mode 100644 index 0000000..dbb27ad --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2404/Point.java @@ -0,0 +1,19 @@ +package com.javarush.task.task24.task2404; + +public class Point { + private double x; + private double y; + + public Point(double x, double y) { + this.x = x; + this.y = y; + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2404/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2404/Solution.java new file mode 100644 index 0000000..01ab761 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2404/Solution.java @@ -0,0 +1,61 @@ +package com.javarush.task.task24.task2404; + +import com.javarush.task.task24.task2404.HasHeight; +import com.javarush.task.task24.task2404.HasWidth; +import com.javarush.task.task24.task2404.Point; + +/* +Рефакторинг Rectangle +*/ +public class Solution { + public static void main(String[] args) { + Rectangle rectangle = new Rectangle(1, 2, 3, 4); + //System.out.println(getHeight(rectangle)); + //System.out.println(getWidth(rectangle)); + /////////////////////expected////////////////// + System.out.println(getHeight(rectangle.castToHasHeight())); + System.out.println(getWidth(rectangle.castToHasWidth())); + } + + public static double getHeight(HasHeight rectangle) { + return rectangle.getHeight(); + } + + public static double getWidth(HasWidth rectangle) { + return rectangle.getWidth(); + } + + + public static class Rectangle { + private Point point1; + private Point point2; + + public Rectangle(double x1, double y1, double x2, double y2) { + point1 = new Point(x1, y1); + point2 = new Point(x2, y2); + } + + + public HasHeight castToHasHeight() { + class Height implements HasHeight{ + + @Override + public double getHeight() { + return Math.abs(point1.getY() - point2.getY()); + } + } + return new Height(); + } + + public HasWidth castToHasWidth() { + class Width implements HasWidth { + + @Override + public double getWidth() { + return Math.abs(point1.getX() - point2.getX()); + } + } + return new Width(); + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2404/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2404/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..506b195 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2404/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,13 @@ +taskKey="com.javarush.task.task24.task2404" + +Рефакторинг Rectangle + +В классе Rectangle: +1. Измени методы getHeight и getWidth, чтобы они возвращали объекты типов HasHeight и HasWidth соответственно. +2. Для этого внутри методов getHeight и getWidth создай локальные классы - реализации интерфейсов. +3. Переименуй getHeight в castToHasHeight, getWidth в castToHasWidth (на имени метода нажми Shift+F6). +4. Убери наследование интерфейсов в классе Rectangle. + +P.S. Ожидается, что после внесения требуемых изменений, закомментированный код в методе станет рабочим и должен быть раскомментирован. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2405/Action.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2405/Action.java new file mode 100644 index 0000000..e2d75ad --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2405/Action.java @@ -0,0 +1,5 @@ +package com.javarush.task.task24.task2405; + +public interface Action { + void someAction(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2405/FirstClass.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2405/FirstClass.java new file mode 100644 index 0000000..42a5668 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2405/FirstClass.java @@ -0,0 +1,14 @@ +package com.javarush.task.task24.task2405; + +public abstract class FirstClass implements Action { //first implementation + + protected FirstClass() { + Solution.countActionObjects++; + } + + public void someAction() { + System.out.println("class FirstClass, method someAction"); + } + + public abstract Action getDependantAction(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2405/SecondClass.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2405/SecondClass.java new file mode 100644 index 0000000..6d678dc --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2405/SecondClass.java @@ -0,0 +1,16 @@ +package com.javarush.task.task24.task2405; + +public class SecondClass implements Action { //second implementation + public static String SPECIFIC_ACTION_FOR_ANONYMOUS_SECOND_CLASS_PARAM = "\nSpecific action for anonymous SecondClass, param = "; + + private static String SECOND_CLASS_METHOD_STRING = "class SecondClass, method someAction"; + + public SecondClass() { + Solution.countActionObjects++; + } + protected StringBuilder sb = new StringBuilder(SECOND_CLASS_METHOD_STRING); + + public void someAction() { + System.out.println(sb.toString()); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2405/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2405/Solution.java new file mode 100644 index 0000000..feca245 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2405/Solution.java @@ -0,0 +1,79 @@ +package com.javarush.task.task24.task2405; + +/* +Black box +*/ +public class Solution implements Action { + public static int countActionObjects; + + private int param; + + private Action solutionAction = new Action() { + + //!!!!! Changes can be here + //!!!!! Изменения могут быть тут + class ThirdClass extends SecondClass{ + public void someAction() { + super.someAction(); + System.out.print(SPECIFIC_ACTION_FOR_ANONYMOUS_SECOND_CLASS_PARAM.substring(1) + param + "\n"); + } + } + + public void someAction() { + //!!!!! All changes have to be here + //!!!!! Все изменения должны быть только тут + + while (param > 0) { + System.out.println(param); + param--; + } + if (param == 0) { + new FirstClass(){ + + @Override + public Action getDependantAction() { + return null; + } + }.someAction(); + } + if (param <= 0) { + new SecondClass().someAction(); + System.out.print(SecondClass.SPECIFIC_ACTION_FOR_ANONYMOUS_SECOND_CLASS_PARAM.substring(1) + param + "\n"); + } + } + }; + + + public Solution(int param) { + this.param = param; + } + + @Override + public void someAction() { + solutionAction.someAction(); + } + + /** + * 5 + * 4 + * 3 + * 2 + * 1 + * class FirstClass, method someAction + * class SecondClass, method someAction + * Specific action for anonymous SecondClass, param = 0 + * Count of created Action objects is 2 + * class SecondClass, method someAction + * Specific action for anonymous SecondClass, param = -1 + * Count of created Action objects is 3 + */ + public static void main(String[] args) { + Solution solution = new Solution(5); + solution.someAction(); + System.out.println("Count of created Action objects is " + countActionObjects); + + solution = new Solution(-1); + solution.someAction(); + System.out.println("Count of created Action objects is " + countActionObjects); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2405/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2405/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..037a4ca --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2405/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,12 @@ +taskKey="com.javarush.task.task24.task2405" + +Black box + +1. Восстанови логику метода someAction для поля solutionAction. +2. Пример вывода смотри в комментарии к методу main. +3. Подсказка: метод someAction анонимного класса поля solutionAction должен вызвать метод сабкласса FirstClass, +если param > 0, иначе вызвать метод сабкласса SecondClass. + +Не изменяй метод main! + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2406/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2406/Solution.java new file mode 100644 index 0000000..2bfa72d --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2406/Solution.java @@ -0,0 +1,37 @@ +package com.javarush.task.task24.task2406; + +import java.math.BigDecimal; + +/* +Наследование от внутреннего класса +*/ +public class Solution { + public class Building { + public class Hall { + private BigDecimal square; + + public Hall(BigDecimal square) { + this.square = square; + } + } + + public class Apartments { + } + } + + public class Apt3Bedroom extends Building.Apartments{ + public Apt3Bedroom(Building building){ + building.super(); + } + } + + public class BigHall extends Solution.Building.Hall{ + public BigHall(Solution.Building building){ + building.super(new BigDecimal("323")); + } + } + + public static void main(String[] args) { + + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2406/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2406/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..5f0e7f4 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2406/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,8 @@ +taskKey="com.javarush.task.task24.task2406" + +Наследование от внутреннего класса + +Внутри класса Solution создай 2 внутренних public класса Apt3Bedroom, BigHall. +Унаследуй их от Apartments и Hall. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Cat.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Cat.java new file mode 100644 index 0000000..f8cde3f --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Cat.java @@ -0,0 +1,48 @@ +package com.javarush.task.task24.task2407; + +/* +В работе вам иногда будет нужно закастить класс к какому-нибудь интерфейсу (тут Sayable), +который не реализован в текущем классе + */ +public class Cat implements Pet { + private String name; + + public Cat(String name) { + this.name = name; + } + + /** + * Это - механизм адаптирования к другому интерфейсу - Sayable + * Внутри метода toSayable создайте class CatPet, реализующий интерфейс Sayable + * Логика метода say: + * Если i <= 0, то вывести на экран, что кот спит. Пример, "Васька спит."' + * Иначе вывести фразу: "имя_кота говорит мяу!". Пример для i=3, "Васька говорит мяяяу!" + *

+ * Пример вывода: + * Мурзик спит. + * Васька говорит мяяу! + * Кошка говорит мяяяяяу! + * Мышь пищит. + * Томас говорит мяу! + *

+ * @param i количество букв 'я' в слове мяу + * @return экземпляр класса CatPet + */ + public Sayable toSayable(final int i) { + class CatPet implements Sayable{ + + @Override + public String say() { + if (i <= 0) return name + " спит."; + else { + StringBuilder str = new StringBuilder(); + for (int j = 0; j < i; j++){ + str.append("я"); + } + return name + " говорит м" + str + "у!"; + } + } + } + return new CatPet(); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Mouse.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Mouse.java new file mode 100644 index 0000000..b5ff3fe --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Mouse.java @@ -0,0 +1,17 @@ +package com.javarush.task.task24.task2407; + +/* +обратите внимание, как именно Mouse отличается от Cat +Этот класс - привычный для вас. +*/ +public class Mouse implements Pet, Sayable { + @Override + public Sayable toSayable(int i) { + return this; + } + + @Override + public String say() { + return "Мышь пищит."; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Pet.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Pet.java new file mode 100644 index 0000000..d4c8f78 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Pet.java @@ -0,0 +1,5 @@ +package com.javarush.task.task24.task2407; + +public interface Pet { + public Sayable toSayable(int i); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Sayable.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Sayable.java new file mode 100644 index 0000000..aaea511 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Sayable.java @@ -0,0 +1,5 @@ +package com.javarush.task.task24.task2407; + +public interface Sayable { + String say(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Solution.java new file mode 100644 index 0000000..4e76c0d --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Solution.java @@ -0,0 +1,14 @@ +package com.javarush.task.task24.task2407; + +import java.util.List; + +/* +Реализация интерфейса используя локальный класс +*/ +public class Solution { + public static void main(String[] args) { + List pet = Util.getPets(); + List pets = Util.convertPetToSayable(pet); + Util.printDialog(pets); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Util.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Util.java new file mode 100644 index 0000000..33b1603 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Util.java @@ -0,0 +1,32 @@ +package com.javarush.task.task24.task2407; + +import java.util.LinkedList; +import java.util.List; + +public class Util { + //Util отлично работает со всеми классами Cat, Mouse. А ведь Mouse отличается от Cat. + public static void printDialog(List pets) { + for (int i = 0; i < pets.size(); i++) { + System.out.println(pets.get(i).say()); + } + } + + public static List getPets() { + List pets = new LinkedList<>(); + pets.add(new Cat("Мурзик")); + pets.add(new Cat("Васька")); + pets.add(new Cat("Кошка")); + pets.add(new Mouse()); + pets.add(new Cat("Томас")); + return pets; + } + + public static List convertPetToSayable(List pets) { + List result = new LinkedList<>(); + for (Pet pet : pets) { + int i = (int) (Math.random() * 7) - 2; + result.add(pet.toSayable(i)); + } + return result; + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2407/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..480215e --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task24.task2407" + +Реализация интерфейса используя локальный класс + +В классе Cat реализуй логику метода toSayable, которая описана в джавадоке. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Dog.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Dog.java new file mode 100644 index 0000000..2380df3 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Dog.java @@ -0,0 +1,66 @@ +package com.javarush.task.task24.task2408; + +import java.util.Date; + +/* +В работе вам иногда будет нужно закастить класс к какому-нибудь другому классу, не интерфейсу :))) +Класс DogPet использует 2 класса - SuperDog и Dog, разберись с getName в классе DogPet +Так намного лучше, чем Copy+Paste! + */ +public class Dog implements Pet { + private String name; + + public Dog(String name) { + this.name = name; + } + + /** + * Если так получилось, что есть готовый класс А (тут SuperDog) с логикой, которую вы хотите использовать. + * То возможны 3 способа: + * 1) из класса А скопировать логику себе (это плохо, т.к. поддерживать несколько копий одного и того же кода проблематично) + * 2) создать экземпляр класса А внутри нашего класса и использовать его, связь has-a (не всегда подходит, т.к. класс А сам по себе) + * 3) создать внутренний класс, который наследуется от А, использовать его методы вместе с + * методами и полями нашего класса, т.к. внутренний класс имеет доступ к своему родителю как наследник, + * а также ко всем полям и методам включая private того класса, в который он вложен. + *

+ * Итак, разбираемся с п.3: + * Внутри метода toSayable создайте class DogPet, который наследуется от SuperDog и реализует интерфейс Sayable + * создайте метод private String getName(), который будет использовать логику двух классов - Dog и SuperDog. + * Пусть этот метод возвращает имя собаки (класс Dog), которое с обеих сторон выделено getSuperQuotes (класс SuperDog) + * Пример, " *** Барбос *** " + * Логика метода say: + * Если i < 1, то используя метод getName вывести на экран, что собака спит. Пример, " *** Шарик *** спит."' + * Иначе вывести фразу: "имя_собаки лает гааав! сегодняшняя_дата". Пример для i=3, " *** Тузик *** лает гааав! 13-ноя-2013 Ср" + * Для форматирования даты используйте formatter из класса SuperDog. + *

+ * Пример вывода: + * *** Барбос *** лает гааааав! 13-ноя-2013 Ср + * *** Тузик *** лает гаав! 13-ноя-2013 Ср + * *** Бобик *** лает гааав! 13-ноя-2013 Ср + * Мыша пищит. + * *** Шарик *** спит. + * + * @param i количество букв 'а' в слове гав + * @return экземпляр класса DogPet + */ + public Sayable toSayable(final int i) { + class DogPet extends SuperDog implements Sayable{ + + private String getName(){ + return getSuperQuotes() + name + getSuperQuotes(); + } + @Override + public String say() { + if ( i < 1 ) { return getName() + " спит."; } + else { + StringBuilder str = new StringBuilder(); + for (int j = 0; j < i; j++) { + str.append("а"); + } + return getName() + " лает г" + str + "в! " + formatter.format(new Date()); + } + } + } + return new DogPet(); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Mouse.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Mouse.java new file mode 100644 index 0000000..1792006 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Mouse.java @@ -0,0 +1,17 @@ +package com.javarush.task.task24.task2408; + +/* +обратите внимание, как именно Mouse отличается от Dog +Этот класс - привычный для вас. +*/ +public class Mouse implements Pet, Sayable { + @Override + public Sayable toSayable(int i) { + return this; + } + + @Override + public String say() { + return "Мышь пищит."; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Pet.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Pet.java new file mode 100644 index 0000000..37bf044 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Pet.java @@ -0,0 +1,5 @@ +package com.javarush.task.task24.task2408; + +public interface Pet { + public Sayable toSayable(int i); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Sayable.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Sayable.java new file mode 100644 index 0000000..33c75aa --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Sayable.java @@ -0,0 +1,5 @@ +package com.javarush.task.task24.task2408; + +public interface Sayable { + String say(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Solution.java new file mode 100644 index 0000000..a909467 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Solution.java @@ -0,0 +1,14 @@ +package com.javarush.task.task24.task2408; + +import java.util.List; + +/* +Как избежать Copy+Paste +*/ +public class Solution { + public static void main(String[] args) { + List pet = Util.getPets(); + List pets = Util.convertPetToSayable(pet); + Util.printDialog(pets); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2408/SuperDog.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/SuperDog.java new file mode 100644 index 0000000..ad29824 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/SuperDog.java @@ -0,0 +1,12 @@ +package com.javarush.task.task24.task2408; + +import java.text.SimpleDateFormat; + +public abstract class SuperDog { + protected String getSuperQuotes() { + //some logic here + return " *** "; + } + + protected SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yyyy EEE"); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Util.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Util.java new file mode 100644 index 0000000..fd12c12 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Util.java @@ -0,0 +1,32 @@ +package com.javarush.task.task24.task2408; + +import java.util.LinkedList; +import java.util.List; + +public class Util { + //Util отлично работает с классами Dog, Mouse. + public static void printDialog(List pets) { + for (int i = 0; i < pets.size(); i++) { + System.out.println(pets.get(i).say()); + } + } + + public static List getPets() { + List pets = new LinkedList<>(); + pets.add(new Dog("Барбос")); + pets.add(new Dog("Тузик")); + pets.add(new Dog("Бобик")); + pets.add(new Mouse()); + pets.add(new Dog("Шарик")); + return pets; + } + + public static List convertPetToSayable(List pets) { + List result = new LinkedList<>(); + for (Pet pet : pets) { + int i = (int) (Math.random() * 7) - 2; + result.add(pet.toSayable(i)); + } + return result; + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2408/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..b7fa41f --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task24.task2408" + +Как избежать Copy+Paste + +В классе Dog реализуй логику метода toSayable, которая описана в джавадоке. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Item.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Item.java new file mode 100644 index 0000000..1c8934c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Item.java @@ -0,0 +1,10 @@ +package com.javarush.task.task24.task2409; + +/** + * Created by PAKOT on 09.03.2017. + */ +public interface Item { + public int getId(); + public double getPrice(); + public String getTM(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Jeans.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Jeans.java new file mode 100644 index 0000000..274644b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Jeans.java @@ -0,0 +1,9 @@ +package com.javarush.task.task24.task2409; + +/** + * Created by PAKOT on 09.03.2017. + */ +public interface Jeans extends Item { + public int getLength(); + public int getSize(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Solution.java new file mode 100644 index 0000000..ab9b9bc --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Solution.java @@ -0,0 +1,18 @@ +package com.javarush.task.task24.task2409; + +import java.util.List; + +/* +Интернет-магазин продажи джинсов +*/ +public class Solution { + + public static List allJeans = Util.getAllJeans(); + + public static void main(String[] args) { + for (Jeans jeans : allJeans) { + System.out.println(jeans); + } + } + +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Util.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Util.java new file mode 100644 index 0000000..7e01fae --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Util.java @@ -0,0 +1,128 @@ +package com.javarush.task.task24.task2409; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +public class Util { + protected static Collection jeansArray = new LinkedList<>(); + + static { + jeansArray.add(new Object[]{1, Company.Levis, 34, 6, 150.0}); + jeansArray.add(new Object[]{2, Company.Denim, 35, 8, 154.0}); + jeansArray.add(new Object[]{3, Company.Colins, 32, 6, 120.0}); + jeansArray.add(new Object[]{4, Company.CalvinKleinJeans, 31, 8, 125.0}); + } + + public static List getAllJeans() { + + //add your code here + abstract class AbstractJeans implements Jeans{ + protected int id; + protected int length; + protected int size; + protected double price; + + + public AbstractJeans(int id, int length, int size, double price){ + this.id = id; + this.length = length; + this.size = size; + this.price = price; + } + + public int getSize(){ + return size; + } + + public double getPrice(){ + return price; + } + + public int getId(){ + return id; + } + + public int getLength(){ + return length; + } + + @Override + public String toString() { + return this.getClass().getSimpleName() + "{" + + "id=" + id + + ", length=" + length + + ", size=" + size + + ", price=" + price + + '}'; + } + } + + class Levis extends AbstractJeans{ + + public Levis(int id, int length, int size, double price){ + super(id, length, size, price); + + } + @Override + public String getTM() { + return Company.Levis.fullName; + } + } + + class Denim extends AbstractJeans{ + public Denim(int id, int length, int size, double price){ + super(id, length, size, price); + + } + @Override + public String getTM() { + return Company.Denim.name(); + } + } + + List allJeans = new LinkedList<>(); + + for (Object[] obj : getJeansArray()) { + int id = (int) obj[0]; + final Company company = (Company ) obj[1]; + int length = (int) obj[2]; + int size = (int) obj[3]; + double price = (double) obj[4]; + + Jeans jeans = null; + if (Company.Levis == company) { + jeans = new Levis(id, length, size, price); + } else + if (Company.Denim == company) { + jeans = new Denim(id, length, size, price); + } else { + jeans = new AbstractJeans(id, length, size, price) { + public String getTM() { + return company.fullName; + } + }; + } + allJeans.add(jeans); + } + return allJeans; + } + + + + public static Collection getJeansArray() { + return jeansArray; + } + + static enum Company { + Levis ("Levi's"), + Denim("Denim"), + Colins("COLIN'S"), + CalvinKleinJeans("Calvin Klein Jeans"); + + final String fullName; + Company(String name) { + this.fullName = name; + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2409/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2409/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..ce5736c --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2409/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,16 @@ +taskKey="com.javarush.task.task24.task2409" + +Интернет-магазин продажи джинсов + +1. Создай 2 интерфейса в отдельных файлах: +1.1) Item с методами int getId(), double getPrice(), String getTM() +1.2) Jeans extends Item с методами int getLength() и int getSize() + +2. В классе Util в методе getAllJeans добавь пропущенную часть java-кода: +2.1) разберись в том, что уже есть в методе getAllJeans класса Util +2.2) создай абстрактный class AbstractJeans от интерфейса Jeans с одним абстрактным методом, реализуй остальные методы +2.3) создай классы Levis и Denim от AbstractJeans, реализуй оставшийся метод +2.4) в классе AbstractJeans реализуй метод toString() (можешь воспользоваться Alt+Insert -> toString()) +2.5) метод toString класса AbstractJeans должен начинаться с имени сабкласса, например, Levis{id=1, length=34, size=6, price=150.0} + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2410/Iterator.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2410/Iterator.java new file mode 100644 index 0000000..048d0e1 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2410/Iterator.java @@ -0,0 +1,5 @@ +package com.javarush.task.task24.task2410; + +public interface Iterator { + Iterator next(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2410/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2410/Solution.java new file mode 100644 index 0000000..4b150d4 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2410/Solution.java @@ -0,0 +1,48 @@ +package com.javarush.task.task24.task2410; + +import java.util.LinkedList; +import java.util.List; + +/* +Рефакторинг, анонимные классы +*/ +public class Solution { + public static List iterators = new LinkedList<>(); + + private int countItems; + + public Iterator getIterator(final String name) { + return new Iterator() { + { + countItems++; + System.out.println(name + " item " + countItems); + } + + @Override + public Iterator next() { + return getIterator(name); + } + }; + + /*class LocalIterator implements Iterator { + public LocalIterator() { + countItems++; + System.out.println(name + " item " + countItems); + } + + public Iterator next() { + return new LocalIterator(); + } + } + return new LocalIterator();*/ + } + + public static void main(String[] args) { + Solution solution = new Solution(); + + Iterator iterator = solution.getIterator("iterator"); + for (int i = 1; i < 5; i++) { + iterators.add(iterator.next()); + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2410/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2410/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..bda2251 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2410/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,9 @@ +taskKey="com.javarush.task.task24.task2410" + +Рефакторинг, анонимные классы + +Сделайте так, чтобы метод getIterator возвращал анонимный класс. +Перенесите логику LocalIterator в анонимный класс. +Меняйте только тело метода getIterator. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2411/C.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2411/C.java new file mode 100644 index 0000000..51b0fa6 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2411/C.java @@ -0,0 +1,8 @@ +package com.javarush.task.task24.task2411; + +public class C implements JustAnInterface { + public C() { + System.out.print("C"); + B localB = B; + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2411/JustAnInterface.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2411/JustAnInterface.java new file mode 100644 index 0000000..01492c7 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2411/JustAnInterface.java @@ -0,0 +1,11 @@ +package com.javarush.task.task24.task2411; + +public interface JustAnInterface { + public static final B B = new B(); + + class B extends C { + public B() { + System.out.print("B"); + } + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2411/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2411/Solution.java new file mode 100644 index 0000000..da43bde --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2411/Solution.java @@ -0,0 +1,34 @@ +package com.javarush.task.task24.task2411; + +/* +Вспомним наследование +*/ +public class Solution extends C { + private class A { + protected String value = "A"; + + public A() { + System.out.print(value); + } + } + + private A a = new A() { + { //у анонимных классов нет своих конструкторов, но что-то можно сделать в блоке инициализации класса + value = "Y"; + if (super.getClass().getName().contains(".Solution$")) { + System.out.print(value); + } + } + }; + + public Solution() { + System.out.print("S"); + } + + public static void main(String[] args) { + new Solution(); + } +} + + + diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2411/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2411/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..210c287 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2411/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task24.task2411" + +Вспомним наследование + +Исправить наследование во всех классах, чтобы вывод метода main был CCBAYS. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2412/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2412/Solution.java new file mode 100644 index 0000000..ec32daf --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2412/Solution.java @@ -0,0 +1,135 @@ +package com.javarush.task.task24.task2412; + +import java.text.ChoiceFormat; +import java.text.Format; +import java.text.MessageFormat; +import java.text.SimpleDateFormat; +import java.util.*; + +/* +Знания - сила! +*/ +public class Solution { + public static void main(String[] args) { + List stocks = getStocks(); + sort(stocks); + Date actualDate = new Date(); + printStocks(stocks, actualDate); + } + + public static void printStocks(List stocks, Date actualDate) { + SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy"); + + double[] filelimits = {0d, actualDate.getTime()}; + String[] filepart = {"closed {4}", "open {2} and last {3}"}; + + ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart); + Format[] testFormats = {null, null, dateFormat, fileform}; + MessageFormat pattform = new MessageFormat("{0} {1} | {5} {6}"); + pattform.setFormats(testFormats); + + for (Stock stock : stocks) { + String name = ((String) stock.get("name")); + String symbol = (String) stock.get("symbol"); + double open = !stock.containsKey("open") ? 0 : ((double) stock.get("open")); + double last = !stock.containsKey("last") ? 0 : ((double) stock.get("last")); + double change = !stock.containsKey("change") ? 0 : ((double) stock.get("change")); + Date date = (Date) stock.get("date"); + Object[] testArgs = {name, symbol, open, last, change, date, date.getTime()}; + System.out.println(pattform.format(testArgs)); + } + } + + + public static void sort(List list) { + + + Collections.sort(list, new Comparator() { + @Override + public int compare(Stock stock1, Stock stock2) { + int result = ((String) stock1.get("name")).compareTo( ((String) stock2.get("name"))); + if (result != 0) { return result; } + else{ + Date o1Date = (Date) stock1.get("date"); + Date o2Date = (Date) stock2.get("date"); + o1Date.setHours(0); + o1Date.setMinutes(0); + o1Date.setSeconds(0); + o2Date.setHours(0); + o2Date.setMinutes(0); + o2Date.setSeconds(0); + result = o2Date.compareTo(o1Date); + if (result != 0) { return result; } + else { + double stock1Change; + double stock2Change; + if (stock1.containsKey("change")) { + stock1Change = (double) stock1.get("change"); + } else { + stock1Change = (double) stock1.get("last") - (double) stock1.get("open"); + } + if (stock2.containsKey("change")) { + stock2Change = (double) stock2.get("change"); + } else { + stock2Change = (double) stock2.get("last") - (double) stock2.get("open"); + } + return Double.compare(stock2Change, stock1Change); + } + } + + } + }); + + } + + public static class Stock extends HashMap { + public Stock(String name, String symbol, double open, double last) { + put("name", name); + put("symbol", symbol); + put("open", open); + put("last", last); + put("date", getRandomDate(2020)); + } + + public Stock(String name, String symbol, double change, Date date) { + put("name", name); + put("symbol", symbol); + put("date", date); + put("change", change); + } + } + + public static List getStocks() { + List stocks = new ArrayList(); + + stocks.add(new Stock("Fake Apple Inc.", "AAPL", 125.64, 123.43)); + stocks.add(new Stock("Fake Cisco Systems, Inc.", "CSCO", 25.84, 26.3)); + stocks.add(new Stock("Fake Google Inc.", "GOOG", 516.2, 512.6)); + stocks.add(new Stock("Fake Intel Corporation", "INTC", 21.36, 21.53)); + stocks.add(new Stock("Fake Level 3 Communications, Inc.", "LVLT", 5.55, 5.54)); + stocks.add(new Stock("Fake Microsoft Corporation", "MSFT", 29.56, 29.72)); + + stocks.add(new Stock("Fake Nokia Corporation (ADR)", "NOK", .1, getRandomDate())); + stocks.add(new Stock("Fake Oracle Corporation", "ORCL", .15, getRandomDate())); + stocks.add(new Stock("Fake Starbucks Corporation", "SBUX", .03, getRandomDate())); + stocks.add(new Stock("Fake Yahoo! Inc.", "YHOO", .32, getRandomDate())); + stocks.add(new Stock("Fake Applied Materials, Inc.", "AMAT", .26, getRandomDate())); + stocks.add(new Stock("Fake Comcast Corporation", "CMCSA", .5, getRandomDate())); + stocks.add(new Stock("Fake Sirius Satellite", "SIRI", -.03, getRandomDate())); + + return stocks; + } + + public static Date getRandomDate() { + return getRandomDate(1970); + } + + public static Date getRandomDate(int startYear) { + int year = startYear + (int) (Math.random() * 30); + int month = (int) (Math.random() * 12); + int day = (int) (Math.random() * 28); + GregorianCalendar calendar = new GregorianCalendar(year, month, day); + return calendar.getTime(); + } +} + diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2412/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2412/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..ef7ae27 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2412/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,15 @@ +taskKey="com.javarush.task.task24.task2412" + +Знания - сила! + +1. В методе sort написать компаратор для Stock: +1.1. Первичная сортировка по name в алфавитном порядке +1.2. Вторичная сортировка по дате без учета часов, минут, секунд (сверху самые новые), потом по прибыли от положительных к отрицательным +... open 125,64 and last 126,74 - тут прибыль = 126,74-125,64 +... open 125,64 and last 123,43 - тут прибыль = 123,43-125,64 +2. Разобраться с *Format-ами и исправить IllegalArgumentException. Подсказка - это одна строчка. +Пример вывода: +Fake Apple Inc. AAPL | 17-11-2025 open 125,64 and last 123,43 +Fake Oracle Corporation ORCL | 21-08-1989 closed 0,15 + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Arkanoid.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Arkanoid.java new file mode 100644 index 0000000..d458ccf --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Arkanoid.java @@ -0,0 +1,238 @@ +package com.javarush.task.task24.task2413; + +import java.awt.event.KeyEvent; +import java.util.ArrayList; + +/** + * Главный класс игры + */ +public class Arkanoid { + //ширина и высота + private int width; + private int height; + + //список кирпичей + private ArrayList bricks = new ArrayList(); + //шарик + private Ball ball; + //подставка + private Stand stand; + + //игра закончена? + private boolean isGameOver = false; + + public Arkanoid(int width, int height) { + this.width = width; + this.height = height; + } + + public ArrayList getBricks() { + return bricks; + } + + public Ball getBall() { + return ball; + } + + public void setBall(Ball ball) { + this.ball = ball; + } + + public Stand getStand() { + return stand; + } + + public void setStand(Stand stand) { + this.stand = stand; + } + + /** + * Рисуем на холсте границы и все объекты. + */ + void draw(Canvas canvas) { + drawBorders(canvas); + + //draw bricks + for (Brick brick : bricks) { + brick.draw(canvas); + } + + //draw ball + ball.draw(canvas); + + //draw stand + stand.draw(canvas); + + } + + /** + * Рисуем на холсте границы + */ + private void drawBorders(Canvas canvas) { + //draw game + for (int i = 0; i < width + 2; i++) { + for (int j = 0; j < height + 2; j++) { + canvas.setPoint(i, j, '.'); + } + } + + for (int i = 0; i < width + 2; i++) { + canvas.setPoint(i, 0, '-'); + canvas.setPoint(i, height + 1, '-'); + } + + for (int i = 0; i < height + 2; i++) { + canvas.setPoint(0, i, '|'); + canvas.setPoint(width + 1, i, '|'); + } + } + + /** + * Основной цикл программы. + * Тут происходят все важные действия + */ + void run() throws Exception { + //Создаем холст для отрисовки. + Canvas canvas = new Canvas(width, height); + + //Создаем объект "наблюдатель за клавиатурой" и стартуем его. + KeyboardObserver keyboardObserver = new KeyboardObserver(); + keyboardObserver.start(); + + //Исполняем цикл, пока игра не окончека + while (!isGameOver) { + //"наблюдатель" содержит события о нажатии клавиш? + if (keyboardObserver.hasKeyEvents()) { + KeyEvent event = keyboardObserver.getEventFromTop(); + + //Если "стрелка влево" - сдвинуть фигурку влево + if (event.getKeyCode() == KeyEvent.VK_LEFT) + stand.moveLeft(); + //Если "стрелка вправо" - сдвинуть фигурку вправо + else if (event.getKeyCode() == KeyEvent.VK_RIGHT) + stand.moveRight(); + //Если "пробел" - запускаем шарик + else if (event.getKeyCode() == KeyEvent.VK_SPACE) + ball.start(); + } + + //двигаем все объекты + move(); + + //проверяем столкновения + checkBricksBump(); + checkStandBump(); + + //проверяем, что шарик мог улететь через дно. + checkEndGame(); + + //отрисовываем все объекты + canvas.clear(); + draw(canvas); + canvas.print(); + + //пауза + Thread.sleep(300); + } + + //Выводим сообщение "Game Over" + System.out.println("Game Over!"); + } + + /** + * Двигаем шарик и подставку. + */ + public void move() { + ball.move(); + stand.move(); + } + + /** + * Проверяем столкновение с кирпичами. + * Если столкновение было - шарик отлетает в случайном направлении 0..360 градусов + */ + void checkBricksBump() { + for (Brick brick : new ArrayList(bricks)) { + if (ball.isIntersec(brick)) { + double angle = Math.random() * 360; + ball.setDirection(angle); + + bricks.remove(brick); + } + } + } + + /** + * Проверяем столкновение с подставкой. + * Если столкновение было - шарик отлетает в случайном направлении вверх 80..100 градусов. + */ + void checkStandBump() { + if (ball.isIntersec(stand)) { + double angle = 90 + 20 * (Math.random() - 0.5); + ball.setDirection(angle); + } + } + + /** + * Проверяем - не улетел ли шарик через дно. + * Если да - игра окончена (isGameOver = true) + */ + void checkEndGame() { + if (ball.getY() > height && ball.getDy() > 0) + isGameOver = true; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public void setWidth(int width) { + this.width = width; + } + + public void setHeight(int height) { + this.height = height; + } + + public static Arkanoid game; + + public static void main(String[] args) throws Exception { + game = new Arkanoid(20, 30); + + Ball ball = new Ball(10, 29, 2, 95); + game.setBall(ball); + + Stand stand = new Stand(10, 30); + game.setStand(stand); + + game.getBricks().add(new Brick(3, 3)); + game.getBricks().add(new Brick(7, 5)); + game.getBricks().add(new Brick(12, 5)); + game.getBricks().add(new Brick(16, 3)); + + game.run(); + } +} + + + + + + + + + + + + + + + + + + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Ball.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Ball.java new file mode 100644 index 0000000..c9d1640 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Ball.java @@ -0,0 +1,116 @@ +package com.javarush.task.task24.task2413; + +/** + * Класс для шарика в игре + */ +public class Ball extends BaseObject { + //скорость + private double speed; + //направление (в градусах от 0 до 360) + private double direction; + + //текущее значение вектора движения (dx,dy) + private double dx; + private double dy; + + //заморожен ли объект или может двигаться + private boolean isFrozen; + + public Ball(double x, double y, double speed, double direction) { + super(x, y, 1); + + this.direction = direction; + this.speed = speed; + + this.isFrozen = true; + } + + public double getSpeed() { + return speed; + } + + public void setSpeed(double speed) { + this.speed = speed; + } + + public double getDirection() { + return direction; + } + + public double getDx() { + return dx; + } + + public double getDy() { + return dy; + } + + /** + * Устанавливаем новое направление движения. + * Тут же вычисляем и новый вектор. + * Такой подход удобно использовать при отскоках от стен. + */ + void setDirection(double direction) { + this.direction = direction; + + double angel = Math.toRadians(direction); + dx = Math.cos(angel) * speed; + dy = -Math.sin(angel) * speed; + } + + /** + * Рисуем себя на "канвасе". + */ + @Override + void draw(Canvas canvas) { + canvas.setPoint(x, y, 'O'); + } + + /** + * Двигаем себя на один шаг. + */ + public void move() { + if (isFrozen) return; + + x += dx; + y += dy; + + checkRebound(1, Arkanoid.game.getWidth(), 1, Arkanoid.game.getHeight() + 5); + } + + /** + * Проверяем не улетел ли шарик за стенку. + * Если да - отражаем его. + */ + void checkRebound(int minx, int maxx, int miny, int maxy) { + if (x < minx) { + x = minx + (minx - x); + dx = -dx; + } + + if (x > maxx) { + x = maxx - (x - maxx); + dx = -dx; + } + + if (y < miny) { + y = miny + (miny - y); + dy = -dy; + } + + if (y > maxy) { + y = maxy - (y - maxy); + dy = -dy; + } + } + + /** + * Запускам шарик. + * isFrozen = false. + * Пересчитываем вектор движения (dx,dy). + */ + void start() { + this.setDirection(direction); + this.isFrozen = false; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2413/BaseObject.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/BaseObject.java new file mode 100644 index 0000000..702d196 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/BaseObject.java @@ -0,0 +1,73 @@ +package com.javarush.task.task24.task2413; + +/** + * Базовый класс для всех объектов игры. + */ +public abstract class BaseObject { + //координаты + protected double x; + protected double y; + //радиус объекта + protected double radius; + + protected BaseObject(double x, double y, double radius) { + this.x = x; + this.y = y; + this.radius = radius; + } + + public double getX() { + return x; + } + + public void setX(double x) { + this.x = x; + } + + public double getY() { + return y; + } + + public void setY(double y) { + this.y = y; + } + + public double getRadius() { + return radius; + } + + public void setRadius(double radius) { + this.radius = radius; + } + + /** + * Метод рисует свой объект на "канвасе". + */ + abstract void draw(Canvas canvas); + + /** + * Двигаем себя на один ход. + */ + abstract void move(); + + /** + * Проверяем - не выходит ли (x,y) за границы. + */ + void checkBorders(double minx, double maxx, double miny, double maxy) { + if (x < minx) x = minx; + if (x > maxx) x = maxx; + if (y < miny) y = miny; + if (y > maxy) y = maxy; + } + + /** + * Проверяем - пересекаются ли переданный(o) и наш(this) объекты. + */ + boolean isIntersec(BaseObject o) { + double dx = x - o.x; + double dy = y - o.y; + double destination = Math.sqrt(dx * dx + dy * dy); + double destination2 = Math.max(radius, o.radius); + return destination <= destination2; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Brick.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Brick.java new file mode 100644 index 0000000..cf5aa72 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Brick.java @@ -0,0 +1,35 @@ +package com.javarush.task.task24.task2413; + +/** + * Класс для объекта "кирпич". + */ +public class Brick extends BaseObject { + //картинка для отрисовки + private static int[][] matrix = { + {0, 0, 0, 0, 0}, + {0, 1, 1, 1, 0}, + {0, 1, 1, 1, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }; + + public Brick(double x, double y) { + super(x, y, 3); + } + + /** + * Рисуем себя на холсте + */ + @Override + void draw(Canvas canvas) { + canvas.drawMatrix(x - radius + 1, y, matrix, 'H'); + } + + /** + * Ничего не делаем - кирпич неподвижен + */ + @Override + void move() { + //do nothing + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Canvas.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Canvas.java new file mode 100644 index 0000000..92bd8c4 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Canvas.java @@ -0,0 +1,86 @@ +package com.javarush.task.task24.task2413; + +/** + * Класс-холст для отрисовки. + */ +public class Canvas { + //ширина и высота + private int width; + private int height; + //матрица, где рисуем. символ - это цвет. + private char[][] matrix; + + public Canvas(int width, int height) { + this.width = width; + this.height = height; + this.matrix = new char[height + 2][width + 2]; + } + + /** + * Очищаем холст + */ + void clear() { + this.matrix = new char[height + 2][width + 2]; + } + + /** + * Печатаем переданную фигуру в указанных координатах цветом c. + * Если переданный массив содержит единицы, то на холсте им будут соответствовать символы - с. + */ + void drawMatrix(double x, double y, int[][] matrix, char c) { + int height = matrix.length; + int width = matrix[0].length; + + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + if (matrix[i][j] == 1) + setPoint(x + j, y + i, c); + } + } + } + + /** + * Ставим одну точку на холсте с координатами (x,y) и цветом - c. + */ + void setPoint(double x, double y, char c) { + int x0 = (int) Math.round(x); + int y0 = (int) Math.round(y); + if (y0 < 0 || y0 >= matrix.length) return; + if (x0 < 0 || x0 >= matrix[y0].length) return; + + matrix[y0][x0] = c; + } + + /** + * Печатаем содержимое холста на экран. + */ + void print() { + System.out.println(); + + for (int i = 0; i < height + 2; i++) { + for (int j = 0; j < width + 2; j++) { + System.out.print(" "); + System.out.print(matrix[i][j]); + System.out.print(" "); + } + + System.out.println(); + } + + System.out.println(); + System.out.println(); + System.out.println(); + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public char[][] getMatrix() { + return matrix; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2413/KeyboardObserver.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/KeyboardObserver.java new file mode 100644 index 0000000..32a0d01 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/KeyboardObserver.java @@ -0,0 +1,69 @@ +package com.javarush.task.task24.task2413; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.util.Queue; +import java.util.concurrent.ArrayBlockingQueue; + +public class KeyboardObserver extends Thread { + private Queue keyEvents = new ArrayBlockingQueue(100); + + private JFrame frame; + + @Override + public void run() { + frame = new JFrame("KeyPress Tester"); + frame.setTitle("Transparent JFrame Demo"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + frame.setUndecorated(true); + frame.setSize(400, 400); + frame.setExtendedState(JFrame.MAXIMIZED_BOTH); + frame.setLayout(new GridBagLayout()); + + frame.setOpacity(0.0f); + frame.setVisible(true); + + frame.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + //do nothing + } + + @Override + public void focusLost(FocusEvent e) { + System.exit(0); + } + }); + + + frame.addKeyListener(new KeyListener() { + + public void keyTyped(KeyEvent e) { + //do nothing + } + + public void keyReleased(KeyEvent e) { + //do nothing + } + + public void keyPressed(KeyEvent e) { + keyEvents.add(e); + } + }); + } + + + public boolean hasKeyEvents() { + return !keyEvents.isEmpty(); + } + + public KeyEvent getEventFromTop() { + return keyEvents.poll(); + } +} + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Stand.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Stand.java new file mode 100644 index 0000000..21a6beb --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Stand.java @@ -0,0 +1,64 @@ +package com.javarush.task.task24.task2413; + +/** + * Подставка, с помощью которой отражаем мячик. + */ +public class Stand extends BaseObject { + //картинка для отрисовки + private static int[][] matrix = { + {1, 1, 1, 1, 1}, + {1, 0, 0, 0, 1}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }; + + //скорость + private double speed = 1; + //направление (-1 влево, +1 вправо) + private double direction = 0; + + public Stand(double x, double y) { + super(x, y, 3); + } + + /** + * Метод передвигает подставку в соответствии с текущим значением direction. + */ + void move() { + double dx = speed * direction; + x = x + dx; + + checkBorders(radius, Arkanoid.game.getWidth() - radius + 1, 1, Arkanoid.game.getHeight() + 1); + } + + /** + * direction устанавливается равным -1 + */ + void moveLeft() { + direction = -1; + } + + /** + * direction устанавливается равным +1 + */ + void moveRight() { + direction = 1; + } + + public double getSpeed() { + return speed; + } + + public double getDirection() { + return direction; + } + + /** + * Отрисовываем себя на холсте + */ + @Override + void draw(Canvas canvas) { + canvas.drawMatrix(x - radius + 1, y, matrix, 'M'); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2413/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..8c010c5 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,107 @@ +taskKey="com.javarush.task.task24.task2413.big20" + +Арканоид(20) + +Отличная работа! Я добавил пару методов, а также класс KeyboardObserver. + +Немного отдохни перед новым уровнем и поиграй. + +P.S. Только не забудь отрегулировать высоту консоли. + + +Арканоид(19) + +Осталось совсем чуть-чуть. + +В классе Arkanoid создай поле приватное isGameOver типа boolean. + +Реализуй метод checkBricksBump. +В этом методе надо проверить - не столкнулся ли шарик с каким-нибудь из "кирпичей". +Для проверки столкновения используй метод isIntersec. +Если шарик все-таки попал в кирпич, то: +а) шарик отлетает в случайном направлении: +double angle = Math.random() * 360; +ball.setDirection(angle); +б) кирпич умирает - надо удалить его из списка всех кирпичей. + +Реализуй метод checkStandBump. +В этом методе надо проверить - не ударился ли шарик о подставку. +Для проверки столкновения используй метод isIntersec. +Если шарик все-таки ударился о подставку, то: +шарик отлетает в случайным направлении вверх: +double angle = 90 + 20 * (Math.random() - 0.5); +ball.setDirection(angel); + +Реализуй метод checkEndGame. +Если координата y шарика больше чем высота поля игры (height), значит шарик улетел вниз за границу экрана. +В этом случае надо переменную isGameOver установить в true. + + + +Арканоид(18) + +Теперь вернемся к классу Arkanoid. + +Реализуй методы: +а) move() +В этом методе нужно двигать все движимые объекты (stand, ball). +б) draw(Canvas canvas) +В этом методе надо вызвать метод draw всех существующих объектов, которые его имеют. + + + +Арканоид(17) + +Еще подставке нужны методы: +а) move - см. move в BaseObject +Движение доски осуществляется горизонтально, поэтому мы меняем только координату х. +Подумай, как координата х зависит от направления (direction) и скорости (speed). Реализуй зависимость. +б) draw - см. draw в BaseObject +Его кодом я займусь сам. +в) moveLeft() - задает постоянное движение "подставки" влево +Просто присвой правильное значение переменной direction. +г) moveRight() - задает постоянное движение "подставки" вправо +Просто присвой правильное значение переменной direction. + + + +Арканоид(16) + +И наконец "подставка"! +Ей понадобятся такие приватные поля: +а) speed (скорость шарика) типа double; +б) direction (направление движения по оси x: 1 - вправо, -1 - влево, 0 - начальное значение, стоим на месте) типа double. + +Также создай для них геттеры. + +А еще с тебя конструктор, примерно вот такой: +public Stand(double x, double y) { +super(x, y, 3); +speed = 1; +direction = 0; +} + + + +Арканоид(15) + +Не поверишь, но и это еще не все. + +Во-первых нужен метод setDirection, +который не только устанавливает значение переменной direction, +но и вычисляет новые значения переменных dx и dy. + +Код должен выглядеть примерно так: +this.direction = direction; +double angel = Math.toRadians(direction); +dx = Math.cos(angle) * speed; +dy = -Math.sin(angle) * speed. + +Во-вторых шарик может удариться о стенку. +При этом он должен от нее отскочить. +Для этого нам понадобится еще один метод: +void checkRebound(int minx, int maxx, int miny, int maxy) +Создай его, а кодом я займусь сам. + + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/Solution.java new file mode 100644 index 0000000..76334d6 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/Solution.java @@ -0,0 +1,30 @@ +package com.javarush.task.task36.task3608; + +import com.javarush.task.task36.task3608.controller.Controller; + +//import com.javarush.task.task36.task3608.model.FakeModel; +import com.javarush.task.task36.task3608.model.MainModel; +import com.javarush.task.task36.task3608.model.Model; +import com.javarush.task.task36.task3608.view.EditUserView; +import com.javarush.task.task36.task3608.view.UsersView; + +public class Solution { + public static void main(String[] args) { + Model model = new MainModel(); + UsersView usersView = new UsersView(); + Controller controller = new Controller(); + EditUserView editUserView = new EditUserView(); + + usersView.setController(controller); + editUserView.setController(controller); + controller.setModel(model); + controller.setUsersView(usersView); + + usersView.fireEventShowAllUsers(); + usersView.fireEventOpenUserEditForm(126L); + editUserView.fireEventUserDeleted(124L); + editUserView.fireEventUserChanged("Ivanov", 123l, 3); + + usersView.fireEventShowDeletedUsers(); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/Util.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/Util.java new file mode 100644 index 0000000..11e5239 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/Util.java @@ -0,0 +1,17 @@ +package com.javarush.task.task36.task3608; + +import com.javarush.task.task36.task3608.bean.User; + +public final class Util { + public static final String DELETED_MARKER = " (deleted)"; + + public static boolean isUserDeleted(User user) { + return user.getName().endsWith(DELETED_MARKER); + } + + public static void markDeleted(User user) { + if (User.NULL_USER != user && !Util.isUserDeleted(user)) { + user.setName(user.getName() + DELETED_MARKER); + } + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/bean/User.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/bean/User.java new file mode 100644 index 0000000..6c70185 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/bean/User.java @@ -0,0 +1,69 @@ +package com.javarush.task.task36.task3608.bean; + +public class User implements Cloneable { + private String name; + private final long id; + private int level; + + public static final User NULL_USER = new User(); + + public User(String name, long id, int level) { + this.name = name; + this.id = id; + this.level = level; + } + + public User() { + this("", 0, 0); + } + + + //methods with logic + public boolean isNew() { + return id == 0; + } + + public User clone() { + try { + return (User) super.clone(); + } catch (CloneNotSupportedException ignored) { + return NULL_USER; + } + } + + public User clone(long newId) { + if (this == NULL_USER) return NULL_USER; + + return new User(name, newId, level); + } + + ///// getters and setters + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getId() { + return id; + } + + public int getLevel() { + return level; + } + + public void setLevel(int level) { + this.level = level; + } + + @Override + public String toString() { + return "User{" + + "name='" + name + '\'' + + ", id=" + id + + ", level=" + level + + '}'; + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/controller/Controller.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/controller/Controller.java new file mode 100644 index 0000000..76c448f --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/controller/Controller.java @@ -0,0 +1,53 @@ +package com.javarush.task.task36.task3608.controller; + +import com.javarush.task.task36.task3608.model.Model; +import com.javarush.task.task36.task3608.view.EditUserView; +import com.javarush.task.task36.task3608.view.UsersView; + +/** + * Created by PAKOT on 11.03.2017. + */ +public class Controller { + private Model model; + private UsersView usersView = new UsersView(); + private EditUserView editUserView = new EditUserView(); + + public void setModel(Model model) { + this.model = model; + } + + public void onShowAllUsers(){ + model.loadUsers(); + usersView.refresh(model.getModelData()); + } + + public void onShowAllDeletedUsers() { + model.loadDeletedUsers(); + usersView.refresh(model.getModelData()); + + } + + public void setUsersView(UsersView usersView) { + this.usersView = usersView; + + } + + public void setEditUserView(EditUserView editUserView){ + this.editUserView = editUserView; + } + + public void onOpenUserEditForm(long userId) { + model.loadUserById(userId); + editUserView.refresh(model.getModelData()); + } + + public void onUserDelete(long id){ + model.deleteUserById(id); + usersView.refresh(model.getModelData()); + } + + public void onUserChange(String name, long id, int level){ + model.changeUserData(name, id, level); + usersView.refresh(model.getModelData()); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/dao/UserDao.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/dao/UserDao.java new file mode 100644 index 0000000..1cf69d7 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/dao/UserDao.java @@ -0,0 +1,82 @@ +package com.javarush.task.task36.task3608.dao; + +import com.javarush.task.task36.task3608.bean.User; +import com.javarush.task.task36.task3608.dao.mock.DataSource; + +import java.util.ArrayList; +import java.util.List; + +public class UserDao { + private DataSource dataSource = DataSource.getInstance(); + + public User getUserById(long id) { + List users = dataSource.getUsers(); + for (User user : users) { + if (user.getId() == id) { + return user.clone(); + } + } + return User.NULL_USER; + } + + public List getUsersByName(String name) { + if (name == null || name.trim().isEmpty()) throw new IllegalArgumentException(); + + List users = dataSource.getUsers(); + List result = new ArrayList<>(); + for (User user : users) { + if (name.equals(user.getName())) { + addUserToResult(result, user); + } + } + return result; + } + + public List getAllUsers() { + List users = dataSource.getUsers(); + List result = new ArrayList<>(); + for (User user : users) { + addUserToResult(result, user); + } + return result; + } + + public List getUsersByLevel(int level) { + if (level < 1) throw new IllegalArgumentException(); + + List users = dataSource.getUsers(); + List result = new ArrayList<>(); + + for (User user : users) { + if (level == user.getLevel()) { + addUserToResult(result, user); + } + } + return result; + } + + public void addUserToResult(List result, User user) { + User clone = user.clone(); + + //skip bad users + if (clone != User.NULL_USER) { + result.add(clone); + } + } + + public User createOrUpdate(User user) { + return dataSource.createOrUpdate(user); + } + + public User getUsersById(long userId) { + if (userId < 1) throw new IllegalArgumentException(); + + List users = dataSource.getUsers(); + for (User user : users) { + if (userId == user.getId()) { + return user; + } + } + return User.NULL_USER; + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/dao/mock/DataSource.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/dao/mock/DataSource.java new file mode 100644 index 0000000..8d8189a --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/dao/mock/DataSource.java @@ -0,0 +1,59 @@ +package com.javarush.task.task36.task3608.dao.mock; + +import com.javarush.task.task36.task3608.bean.User; + +import java.util.LinkedList; +import java.util.List; + +public class DataSource { + private static DataSource ourInstance = new DataSource(); + + public static DataSource getInstance() { + return ourInstance; + } + + private DataSource() { + } + + private List users = new LinkedList() {{ + add(new User("Ivanov", 123l, 1)); + add(new User("Petrov", 124l, 2)); + add(new User("Petrov", 125l, 1)); + add(new User("Sidorov", 126l, 2)); + }}; + + private long maxUserId = 126l; + + public List getUsers() { + return users; + } + + public User createOrUpdate(User newUser) { + if (newUser == User.NULL_USER) + return User.NULL_USER; + + //new User + if (newUser.getId() == 0) + return createNewUser(newUser); + else + return updateUser(newUser); + } + + private User createNewUser(User newUser) { + User clone = newUser.clone(++maxUserId); + users.add(clone); + return clone; + } + + private User updateUser(User newUser) { + for (User user : users) { + if (user.getId() == newUser.getId()) { + user.setName(newUser.getName()); + user.setLevel(newUser.getLevel()); + return user; + } + } + //if we didn't find such a user + return User.NULL_USER; + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/FakeModel.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/FakeModel.java new file mode 100644 index 0000000..24fc922 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/FakeModel.java @@ -0,0 +1,52 @@ +package com.javarush.task.task36.task3608.model; + +import com.javarush.task.task36.task3608.bean.User; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by PAKOT on 11.03.2017. + */ +public class FakeModel implements Model { + private ModelData modelData = new ModelData(); + + @Override + public ModelData getModelData() { + return modelData; + } + + @Override + public void loadUsers() { + List testUsers = new ArrayList(); + User user1 = new User("Amigo", 1, 24); + User user2 = new User("Zajaz", 2, 27); + User user3 = new User("Newbie", 3, 7); + User user4 = new User("Jaja", 4, 14); + testUsers.add(user1); + testUsers.add(user2); + testUsers.add(user3); + testUsers.add(user4); + modelData.setUsers(testUsers); + } + + @Override + public void loadDeletedUsers() { + throw new UnsupportedOperationException(); + } + + @Override + public void loadUserById(long userId) { + throw new UnsupportedOperationException(); + } + + @Override + public void deleteUserById(long id) { + throw new UnsupportedOperationException(); + } + + @Override + public void changeUserData(String name, long id, int level) { + throw new UnsupportedOperationException(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/MainModel.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/MainModel.java new file mode 100644 index 0000000..e367995 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/MainModel.java @@ -0,0 +1,57 @@ +package com.javarush.task.task36.task3608.model; + +import com.javarush.task.task36.task3608.bean.User; + +import com.javarush.task.task36.task3608.model.service.UserService; +import com.javarush.task.task36.task3608.model.service.UserServiceImpl; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by PAKOT on 11.03.2017. + */ +public class MainModel implements Model { + private ModelData modelData = new ModelData(); + private UserService userService = new UserServiceImpl(); + + @Override + public ModelData getModelData() { + return modelData; + } + + @Override + public void loadUsers() { + //List list = userService.getUsersBetweenLevels(1, 100); + modelData.setUsers(getAllUsers()); + modelData.setDisplayDeletedUserList(false); + } + + public void loadDeletedUsers() { + //List users = userService.getAllDeletedUsers(); + modelData.setUsers(userService.getAllDeletedUsers()); + modelData.setDisplayDeletedUserList(true); + } + + public void loadUserById(long userId) { + User user = userService.getUsersById(userId); + modelData.setActiveUser(user); + } + + public void deleteUserById(long id){ + userService.deleteUser(id); + modelData.setDisplayDeletedUserList(false); + modelData.setUsers(getAllUsers()); + + + } + + public void changeUserData(String name, long id, int level){ + userService.createOrUpdateUser(name, id, level); + modelData.setUsers(getAllUsers()); + } + + private List getAllUsers(){ + return userService.filterOnlyActiveUsers(userService.getUsersBetweenLevels(1, 100)); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/Model.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/Model.java new file mode 100644 index 0000000..1117b31 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/Model.java @@ -0,0 +1,14 @@ +package com.javarush.task.task36.task3608.model; + +/** + * Created by PAKOT on 11.03.2017. + */ +public interface Model { + ModelData getModelData(); + + void loadUsers(); + void loadDeletedUsers(); + void loadUserById(long userId); + void deleteUserById(long id); + void changeUserData(String name, long id, int level); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/ModelData.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/ModelData.java new file mode 100644 index 0000000..9013fb8 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/ModelData.java @@ -0,0 +1,40 @@ +package com.javarush.task.task36.task3608.model; + +import com.javarush.task.task36.task3608.bean.User; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by PAKOT on 11.03.2017. + */ +public class ModelData { + private List users; + private User activeUser; + private boolean displayDeletedUserList; + + public boolean isDisplayDeletedUserList() { + return displayDeletedUserList; + } + + public void setDisplayDeletedUserList(boolean displayDeletedUserList) { + this.displayDeletedUserList = displayDeletedUserList; + } + + public User getActiveUser() { + return activeUser; + } + + public void setActiveUser(User activeUser) { + this.activeUser = activeUser; + } + + public List getUsers() { + return users; + } + + public void setUsers(List users) { + this.users = users; + } + +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/service/UserService.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/service/UserService.java new file mode 100644 index 0000000..a78aa38 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/service/UserService.java @@ -0,0 +1,21 @@ +package com.javarush.task.task36.task3608.model.service; + +import com.javarush.task.task36.task3608.bean.User; + +import java.util.List; + +public interface UserService { + public User deleteUser(long id); + + public User createOrUpdateUser(String name, long id, int level); + + public List getUsersByName(String name); + + public List getAllDeletedUsers(); + + public List getUsersBetweenLevels(int fromLevel, int toLevel); + + List filterOnlyActiveUsers(List allUsers); + + User getUsersById(long userId); +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/service/UserServiceImpl.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/service/UserServiceImpl.java new file mode 100644 index 0000000..443a22c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/service/UserServiceImpl.java @@ -0,0 +1,73 @@ +package com.javarush.task.task36.task3608.model.service; + +import com.javarush.task.task36.task3608.Util; +import com.javarush.task.task36.task3608.bean.User; +import com.javarush.task.task36.task3608.dao.UserDao; + +import java.util.ArrayList; +import java.util.List; + +public class UserServiceImpl implements UserService { + private UserDao userDao = new UserDao(); + + @Override + public User deleteUser(long id) { + User user = userDao.getUserById(id); + Util.markDeleted(user); + userDao.createOrUpdate(user); + + return user; + } + + @Override + public User createOrUpdateUser(String name, long id, int level) { + User user = new User(name, id, level); + return userDao.createOrUpdate(user); + } + + @Override + public List getUsersByName(String name) { + return userDao.getUsersByName(name); + } + + @Override + public List getAllDeletedUsers() { + List result = new ArrayList<>(); + for (User user : userDao.getAllUsers()) { + if (Util.isUserDeleted(user)) { + result.add(user); + } + } + + return result; + } + + @Override + public List getUsersBetweenLevels(int fromLevel, int toLevel) { + //it's better to get all users from DAO by one DB request, but we will use what we have + List result = new ArrayList<>(); + for (int i = fromLevel; i <= toLevel; i++) { + result.addAll(userDao.getUsersByLevel(i)); + } + + return result; + } + + @Override + public List filterOnlyActiveUsers(List allUsers) { + //will not change allUsers list, create new one instead of that + List result = new ArrayList<>(); + for (User user : allUsers) { + if (User.NULL_USER != user && !Util.isUserDeleted(user)) { + result.add(user); + } + } + + return result; + } + + @Override + public User getUsersById(long userId) { + return userDao.getUsersById(userId); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/view/EditUserView.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/view/EditUserView.java new file mode 100644 index 0000000..e6687d9 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/view/EditUserView.java @@ -0,0 +1,33 @@ +package com.javarush.task.task36.task3608.view; + +import com.javarush.task.task36.task3608.bean.User; +import com.javarush.task.task36.task3608.controller.Controller; +import com.javarush.task.task36.task3608.model.ModelData; + +/** + * Created by PAKOT on 12.03.2017. + */ +public class EditUserView implements View { + private Controller controller; + + @Override + public void refresh(ModelData modelData) { + System.out.println("User to be edited:"); + System.out.println("\t" + modelData.getActiveUser().toString()); + System.out.println("==================================================="); + } + + @Override + public void setController(Controller controller) { + this.controller = controller; + } + + public void fireEventUserDeleted(long id){ + controller.onUserDelete(id); + } + + public void fireEventUserChanged(String name, long id, int level){ + controller.onUserChange(name, id, level); + } + +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/view/UsersView.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/view/UsersView.java new file mode 100644 index 0000000..1664257 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/view/UsersView.java @@ -0,0 +1,46 @@ +package com.javarush.task.task36.task3608.view; + +import com.javarush.task.task36.task3608.bean.User; +import com.javarush.task.task36.task3608.controller.Controller; +import com.javarush.task.task36.task3608.model.ModelData; + +/** + * Created by PAKOT on 11.03.2017. + */ +public class UsersView implements View { + private Controller controller; + + @Override + public void refresh(ModelData modelData) { + if (!modelData.isDisplayDeletedUserList()) { + System.out.println("All users:"); + for (User user : modelData.getUsers()) { + System.out.println("\t" + user.toString()); + } + System.out.println("==================================================="); + } else { + System.out.println("All deleted users:"); + for (User user : modelData.getUsers()) { + System.out.println("\t" + user.toString()); + } + System.out.println("==================================================="); + } + } + + @Override + public void setController(Controller controller) { + this.controller = controller; + } + + public void fireEventShowAllUsers(){ + controller.onShowAllUsers(); + } + + public void fireEventShowDeletedUsers() { + controller.onShowAllDeletedUsers(); + } + + public void fireEventOpenUserEditForm(long id) { + controller.onOpenUserEditForm(id); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/view/View.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/view/View.java new file mode 100644 index 0000000..b82324b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/view/View.java @@ -0,0 +1,12 @@ +package com.javarush.task.task36.task3608.view; + +import com.javarush.task.task36.task3608.controller.Controller; +import com.javarush.task.task36.task3608.model.ModelData; + +/** + * Created by PAKOT on 11.03.2017. + */ +public interface View { + void refresh(ModelData modelData); + void setController(Controller controller); +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..70746af --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,144 @@ +taskKey="com.javarush.task.task36.task3608.big09" + +MVC (9) + +Это последнее задание по MVC. + +1. Следуя принципу MVC аналогично реализации предыдущих методов сделай следующее: +напиши логику обновления пользователя. После обновления должен отображаться список пользователей. +Распредели методы по классам MVC, используя следующие сигнатуры публичных методов: +void fireEventUserChanged(String name, long id, int level) +void onUserChange(String name, long id, int level) +void changeUserData(String name, long id, int level) +где name и level - это новые значения для пользователя с выбранным id. +Примечание: метод, который ты собираешься добавить в Вью нужно добавить в EditUserView. + +2. Добавь в main вызов fireEventUserChanged перед вызовом метода fireEventShowDeletedUsers(). + +3. Добавь в интерфейс Model метод, который ты поместил в Модель, реализуй его в FakeModel: выброси UnsupportedOperationException. + + +MVC (8) + +1. Следуя принципу MVC аналогично реализации предыдущих методов сделай следующее: +напиши логику удаления пользователя. После удаления должен отображаться список пользователей. +Распредели методы по классам MVC, используя следующие сигнатуры публичных методов: +void fireEventUserDeleted(long id) +void onUserDelete(long id) +void deleteUserById(long id) +Примечание: метод, который ты собираешься добавить в Вью нужно добавить в EditUserView. + +2. Добавь в main вызов fireEventUserDeleted(124L) перед вызовом метода fireEventShowDeletedUsers(). + +3. Выполни рефакторинг класса MainModel. Теперь, когда есть удаленные пользователи, часть методов стала работать неправильно. +Почти во всех методах, где требуется список пользователей, нужно работать только с активными(живыми) пользователями. +Вынеси в отдельный приватный метод List getAllUsers() получение списка всех пользователей. +Фильтрация активных пользователей у тебя уже есть - метод List filterOnlyActiveUsers(List allUsers). +Отрефактори все методы, которые используют список пользователей. Они должны использовать список живых пользователей. + +4. Добавь в интерфейс Model метод, который ты поместил в Модель, реализуй его в FakeModel: выброси UnsupportedOperationException. + + + +MVC (7) + +1. Распредели методы по классам MVC: + +public void onOpenUserEditForm(long userId) { +...loadUserById(userId); +...refresh(...getModelData()); +} + +public void fireEventOpenUserEditForm(long id) { +...onOpenUserEditForm(id); +} + +public void loadUserById(long userId) { +User user = userService.getUsersById(userId); +...setActiveUser(user); +} + +!!!! Пользователь видит Вью со списком пользователей, нажимает на одного из них, запрос идет на сервер, +выгребаем новые данные и отображаем другую Вью, которая относится к одному выбранному пользователю. +Учти это при реализации этого задания. + +2. Добавь в метод main открытие формы редактирования для пользователя с id=126 перед вызовом метода fireEventShowDeletedUsers(). + +3. Добавь в интерфейс Model метод, который ты поместил в Модель, реализуй его в FakeModel: выброси UnsupportedOperationException. + + + +MVC (6) + +Функционал отображения удаленных пользователей есть, а самих таких пользователей нет. Давай это исправим. +Давай сделаем новую Вью, которая будет отвечать за редактирование одного конкретного пользователя. +UsersView отображает список пользователей. +EditUserView будет отображать данные о редактировании конкретного пользователя. +Для этого нам сначала нужен этот выбранный пользователь. +Как и любые данные его поместим в ModelData. + +1. Создай в ModelData поле User activeUser с геттером и сеттером (Alt+Insert -> Getter and Setter). + +2. Аналогично UsersView создай EditUserView. +Логика метода refresh: +2.1. Вывести в консоль "User to be edited:". +2.2. С новой строки вывести табуляцию и активного пользователя. +2.3. С новой строки вывести разделитель "===================================================". + +3. Создай в контроллере поле EditUserView editUserView с сеттером. + +Когда наши данные выводятся в консоль, то совсем не понятно, список каких пользователей - удаленных или нет - выводится. +Давай сделаем так, чтобы Вью отображала эту информацию. Все данные для отображения хранятся в Моделе. Поэтому: +4. создай в ModelData поле boolean displayDeletedUserList с геттером и сеттером. + +5. Измени метод refresh в UsersView так, чтобы он отображал "All users:" либо "All deleted users:" +в зависимости от того, какие пользователи находятся в списке. Добавь в необходимые методы модели изменение displayDeletedUserList. + + + +MVC (5) + +В сервисе есть метод, который возвращает всех удаленных пользователей. Давай их отобразим. + +1. Распредели методы по классам MVC: + +public void fireEventShowDeletedUsers() { +...onShowAllDeletedUsers(); +} + +public void onShowAllDeletedUsers() { +...loadDeletedUsers(); +} + +public void loadDeletedUsers() { +List users = userService.getAllDeletedUsers(); +} + +Не забудь, что данные, полученные с сервера, необходимо положить в ModelData. А потом обновить view. +Добавь это самостоятельно в нужные методы. + +2. Добавь в Solution.main вызов нового метода, который ты поместил в view. + +3. Добавь в интерфейс Model метод, который ты поместил в Модель, реализуй его в FakeModel: выброси UnsupportedOperationException. + + + +MVC (4) + +Пора заменять нашу фейковую Модель на реальную, которая будет получать данные из DataSource. +В пакет model.service я добавил сервис для работы с пользователями. +Также в корне этой задачи ты найдешь утильный класс Util. + +1. Аналогично FakeModel создай модель MainModel. + +2. Т.к. Модель обращается к сервисам, то в MainModel создай поле UserService userService, инициализируй объектом. + +3. Реализуй логику метода loadUsers: +3.1. Достань всех пользователей между 1 и 100 уровнями. (Метод getUsersBetweenLevels(1, 100)). +3.2. Положи всех пользователей в modelData. + +4. Обнови Solution.main: замени FakeModel на MainModel. +Преимущества MVC в том, что в любой момент времени легко можно заменить любую часть паттерна. + + + From 9aab7ba694776e2cc61e90ebe53628d9c91f1252 Mon Sep 17 00:00:00 2001 From: PeucT Date: Mon, 13 Mar 2017 22:07:39 +0300 Subject: [PATCH 05/51] 2501, 2502 --- .../task/task25/task2501/Solution.java | 22 ++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 7 ++++ .../task/task25/task2502/Solution.java | 41 +++++++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 10 +++++ 4 files changed, 80 insertions(+) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task25/task2501/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task25/task2501/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task25/task2502/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task25/task2502/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2501/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2501/Solution.java new file mode 100644 index 0000000..bc62663 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2501/Solution.java @@ -0,0 +1,22 @@ +package com.javarush.task.task25.task2501; + +/* +Новые возможности! +*/ +public class Solution { + public static void main(String[] args) { + System.out.println(Alphabet.G.getLetterPosition()); + } + + public enum Alphabet { + A, B, C, D, E, + F, G, H, I, J, + K, L, M, N, O, + P, Q, R, S, T, + U, V, W, X, Y, Z; + + int getLetterPosition() { + return this.ordinal() + 1; + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2501/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2501/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..a3266f5 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2501/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task25.task2501" + +Новые возможности! + +Используя возможности enum-а реализуй метод getLetterPosition, который должен возвращать позицию буквы. Позиция буквы A - 1. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2502/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2502/Solution.java new file mode 100644 index 0000000..6948745 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2502/Solution.java @@ -0,0 +1,41 @@ +package com.javarush.task.task25.task2502; + +import java.util.*; + +/* +Машину на СТО не повезем! +*/ +public class Solution { + public static enum Wheel { + FRONT_LEFT, + FRONT_RIGHT, + BACK_LEFT, + BACK_RIGHT + } + + public static class Car { + protected List wheels; + + public Car() throws Exception { + wheels = new ArrayList(); + Wheel wheelEntry = null; + String[] dbArray = loadWheelNamesFromDB(); + if (dbArray.length != 4) { throw new Exception(); }; + for (String entry: dbArray){ + if ( (wheelEntry = Wheel.valueOf(entry)) == null) { throw new Exception();} + else { + wheels.add(wheelEntry); + } + } + } + + protected String[] loadWheelNamesFromDB() { + //this method returns mock data + return new String[]{"FRONT_LEFT", "FRONT_RIGHT", "BACK_LEFT", "BACK_RIGHT"}; + } + } + + public static void main(String[] args) throws Exception { + Car car = new Car(); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2502/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2502/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..a8bffe8 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2502/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,10 @@ +taskKey="com.javarush.task.task25.task2502" + +Машину на СТО не повезем! + +Инициализируй поле wheels используя данные из loadWheelNamesFromDB. +Выкинь исключение в случае некорректных данных. +Подсказка: если что-то не то с колесами, то это не машина! +Сигнатуры не менять. + + From 715ba716b8aa75ae0fd81b3d11fbfa05b10443cb Mon Sep 17 00:00:00 2001 From: PeucT Date: Tue, 14 Mar 2017 23:53:20 +0300 Subject: [PATCH 06/51] 2503 - 2505 --- .../javarush/task/task25/task2503/Column.java | 89 +++++++++++++++++++ .../task/task25/task2503/Columnable.java | 27 ++++++ .../task/task25/task2503/Solution.java | 32 +++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 11 +++ .../task/task25/task2504/Solution.java | 36 ++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 12 +++ .../task/task25/task2505/Solution.java | 45 ++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 12 +++ 8 files changed, 264 insertions(+) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task25/task2503/Column.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task25/task2503/Columnable.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task25/task2503/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task25/task2503/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task25/task2504/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task25/task2504/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task25/task2505/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task25/task2505/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2503/Column.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2503/Column.java new file mode 100644 index 0000000..326ecb2 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2503/Column.java @@ -0,0 +1,89 @@ +package com.javarush.task.task25.task2503; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +public enum Column implements Columnable { + Customer("Customer"), + BankName("Bank Name"), + AccountNumber("Account Number"), + Amount("Available Amount"); + + private String columnName; + + @Override + public String getColumnName() { + return this.columnName; + } + @Override + public boolean isShown() { + if (realOrder[this.ordinal()] == -1 ) { + return false; + } else { return true; } + } + + @Override + public void hide() { + int startNumberToChange = realOrder[this.ordinal()]; + realOrder[this.ordinal()] = -1; + for (int i = 0; i < realOrder.length; i++) { + if ( realOrder[i] > startNumberToChange) { + realOrder[i]--; + } + } + } + + + private static int[] realOrder; + + private Column(String columnName) { + this.columnName = columnName; + } + + /** + * Задает новый порядок отображения колонок, который хранится в массиве realOrder. + * realOrder[индекс в энуме] = порядок отображения; -1, если колонка не отображается. + * + * @param newOrder новая последовательность колонок, в которой они будут отображаться в таблице + * @throws IllegalArgumentException при дубликате колонки + */ + public static void configureColumns(Column... newOrder) { + realOrder = new int[values().length]; + for (Column column : values()) { + realOrder[column.ordinal()] = -1; + boolean isFound = false; + + for (int i = 0; i < newOrder.length; i++) { + if (column == newOrder[i]) { + if (isFound) { + throw new IllegalArgumentException("Column '" + column.columnName + "' is already configured."); + } + realOrder[column.ordinal()] = i; + isFound = true; + } + } + } + } + + /** + * Вычисляет и возвращает список отображаемых колонок в сконфигурированом порядке (см. метод configureColumns) + * Используется поле realOrder. + * + * @return список колонок + */ + public static List getVisibleColumns() { + List result = new LinkedList<>(); + Column[] list = Column.values(); + for (int i = 0; i < list.length; i++) { + for (int j = 0; j < list.length; j++){ + if (realOrder[j] == i) { + result.add(list[j]); + break; + } + } + } + + return result; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2503/Columnable.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2503/Columnable.java new file mode 100644 index 0000000..f505209 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2503/Columnable.java @@ -0,0 +1,27 @@ +package com.javarush.task.task25.task2503; + +public interface Columnable { + + /** + * @return полное имя колонки + */ + String getColumnName(); + + /** + * Возвращает true, если колонка видимая, иначе false + */ + boolean isShown(); + + /** + * Скрывает колонку - маркирует колонку -1 в массиве realOrder. + * Сдвигает индексы отображаемых колонок, которые идут после скрытой + */ + void hide(); + + /** + * Возвращает порядок константы в энуме. + * + * @return порядок константы в энуме + */ + int ordinal(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2503/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2503/Solution.java new file mode 100644 index 0000000..7944917 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2503/Solution.java @@ -0,0 +1,32 @@ +package com.javarush.task.task25.task2503; + +/* +Свой enum +*/ +public class Solution { + /** + * Output: + *

+ * Available Amount + * Account Number + * Bank Name + * -------------------- + * Available Amount + * Bank Name + */ + public static void main(String[] args) { + + Column.configureColumns(Column.Amount, Column.AccountNumber, Column.BankName); + + for (Columnable columnable : Column.getVisibleColumns()) { + System.out.println(columnable.getColumnName()); + } + + System.out.println("--------------------"); + Column.AccountNumber.hide(); + + for (Columnable columnable : Column.getVisibleColumns()) { + System.out.println(columnable.getColumnName()); + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2503/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2503/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..0c7e803 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2503/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,11 @@ +taskKey="com.javarush.task.task25.task2503" + +Свой enum + +Реализуй интерфейс Columnable у Column, описание методов смотрите в джавадоках. +Реализуй логику метода Column.getVisibleColumns. +Метод Column.configureColumns уже реализован, его не меняй. +Создавать дополнительные поля нельзя. +Метод main не участвует в тестировании. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2504/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2504/Solution.java new file mode 100644 index 0000000..90ec962 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2504/Solution.java @@ -0,0 +1,36 @@ +package com.javarush.task.task25.task2504; + +/* +Switch для нитей +*/ +public class Solution { + public static void processThreads(Thread... threads) { + //implement this method - реализуйте этот метод + for (Thread entry: threads){ + switch (entry.getState()){ + case NEW: + entry.start(); + break; + case WAITING: + entry.interrupt(); + break; + case BLOCKED: + entry.interrupt(); + break; + case TIMED_WAITING: + entry.interrupt(); + break; + case RUNNABLE: + entry.isInterrupted(); + break; + case TERMINATED: + System.out.println(entry.getPriority()); + break; + } + } + } + + public static void main(String[] args) { + + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2504/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2504/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..fa13d8d --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2504/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,12 @@ +taskKey="com.javarush.task.task25.task2504" + +Switch для нитей + +Обработай список нитей в зависимости от состояния: +1. Если нить еще не запущена, то запусти ее. +2. Если нить в ожидании, то прерви ее. +3. Если нить работает, то проверь маркер isInterrupted. +4. Если нить прекратила работу, то выведи в консоль ее приоритет. +Используй switch. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2505/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2505/Solution.java new file mode 100644 index 0000000..97a8382 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2505/Solution.java @@ -0,0 +1,45 @@ +package com.javarush.task.task25.task2505; + +/* +Без дураков +*/ +public class Solution { + + public static void main(String[] args) { + MyThread myThread = new Solution().new MyThread("super secret key"); + myThread.start(); + } + + public class MyThread extends Thread { + private String secretKey; + + public MyThread(String secretKey) { + this.secretKey = secretKey; + setUncaughtExceptionHandler(new MyUncaughtExceptionHandler()); + setDaemon(false); + } + + @Override + public void run() { + throw new NullPointerException("it's an example"); + } + + private class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler { + + @Override + public void uncaughtException(Thread t, Throwable e) { + try { + Thread.currentThread().sleep(500); + System.out.println(String.format("%s, %s, %s", secretKey, t.getName(), e.getMessage() )); + + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + } + } + } + + + +} + diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2505/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2505/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..f6a0b5f --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2505/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,12 @@ +taskKey="com.javarush.task.task25.task2505" + +Без дураков + +1. Создай private class MyUncaughtExceptionHandler, который на перехват исключения должен подождать половину секунды, +а затем вывести на экран secretKey, имя трэда и сообщение возникшего исключения. +Используй String.format(...). Пример: +super secret key, Thread-0, it's an example +2. Разберись в последовательности выполняемого кода и обеспечь логирование возникновения исключения в п.1. +3. Метод main в тестировании не участвует. + + From 6c99cda059d819e6162c09cbc1d593f944c40f88 Mon Sep 17 00:00:00 2001 From: PeucT Date: Fri, 17 Mar 2017 19:21:48 +0300 Subject: [PATCH 07/51] Full lvl 25 --- .../task25/task2506/LoggingStateThread.java | 29 ++++++++ .../task/task25/task2506/Solution.java | 20 ++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 10 +++ .../task/task25/task2507/Solution.java | 48 +++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 8 +++ .../task2508/CustomThreadManipulator.java | 6 ++ .../task/task25/task2508/Solution.java | 40 +++++++++++ .../task/task25/task2508/TaskManipulator.java | 31 ++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 7 ++ .../task/task25/task2509/CancellableTask.java | 10 +++ .../task/task25/task2509/SocketTask.java | 38 ++++++++++ .../task/task25/task2509/Solution.java | 23 ++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 9 +++ .../task/task25/task2510/Solution.java | 28 ++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 11 +++ .../task/task25/task2511/Solution.java | 71 +++++++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 10 +++ .../task/task25/task2512/Solution.java | 33 +++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 14 ++++ .../task/task25/task2513/Solution.java | 34 +++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 10 +++ .../task/task25/task2514/Solution.java | 26 +++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 7 ++ 23 files changed, 523 insertions(+) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task25/task2506/LoggingStateThread.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task25/task2506/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task25/task2506/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task25/task2507/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task25/task2507/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task25/task2508/CustomThreadManipulator.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task25/task2508/Solution.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task25/task2508/TaskManipulator.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task25/task2508/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task25/task2509/CancellableTask.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task25/task2509/SocketTask.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task25/task2509/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task25/task2509/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task25/task2510/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task25/task2510/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task25/task2511/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task25/task2511/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task25/task2512/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task25/task2512/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task25/task2513/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task25/task2513/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task25/task2514/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task25/task2514/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2506/LoggingStateThread.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2506/LoggingStateThread.java new file mode 100644 index 0000000..496331e --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2506/LoggingStateThread.java @@ -0,0 +1,29 @@ +package com.javarush.task.task25.task2506; + +/** + * Created by PAKOT on 14.03.2017. + */ +public class LoggingStateThread extends Thread { + private Thread target; + private State prevState = null; + public LoggingStateThread (Thread target){ + this.target = target; + this.setDaemon(true); + } + + public void run(){ + + while (true){ + State state = target.getState(); + if (prevState == null) { + prevState = state; + System.out.println(state.toString()); + } else if (!state.equals(prevState)) { + System.out.println(state.toString()); + prevState = state; + } + if (state.equals(State.TERMINATED)) { break; } + + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2506/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2506/Solution.java new file mode 100644 index 0000000..f54a777 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2506/Solution.java @@ -0,0 +1,20 @@ +package com.javarush.task.task25.task2506; + +/* +Мониторинг состояния нити +*/ +public class Solution { + public static void main(String[] args) throws InterruptedException { + Thread target = new Thread(); + LoggingStateThread loggingStateThread = new LoggingStateThread(target); + + loggingStateThread.start(); + target.start(); //NEW + Thread.sleep(100); //RUNNABLE + target.join(100); + Thread.sleep(400); + target.interrupt(); //TERMINATED + Thread.sleep(500); + } + +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2506/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2506/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..17aceec --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2506/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,10 @@ +taskKey="com.javarush.task.task25.task2506" + +Мониторинг состояния нити + +Cоздай класс нити LoggingStateThread, +которая будет выводить в консоль все состояния (State) переданной в конструктор нити. +Нить LoggingStateThread должна сама завершаться после остановки переданной в конструктор нити. +Метод main не участвует в тестировании. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2507/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2507/Solution.java new file mode 100644 index 0000000..c8736e5 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2507/Solution.java @@ -0,0 +1,48 @@ +package com.javarush.task.task25.task2507; + +import java.io.IOException; +import java.io.InputStream; +import java.net.Socket; + +/* +Работать в поте лица! +*/ +public class Solution extends Thread { + private static final int BUFFER_SIZE = 2000; //2000 bytes + private final Socket socket; + private final InputStream in; + + public Solution(Socket socket) throws IOException { + this.socket = socket; + this.in = socket.getInputStream(); + } + + public void interrupt() { + try { + socket.close(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + super.interrupt(); + } + } + + public void run() { + try { + byte[] buf = new byte[BUFFER_SIZE]; + while (true) { + int count = in.read(buf); + if (count < 0) { + break; + } else { + if (count > 0) { + //process buffer here + } + } + } + } catch (IOException ignored) {} + } + + public static void main(String[] args) { + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2507/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2507/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..863d3ad --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2507/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,8 @@ +taskKey="com.javarush.task.task25.task2507" + +Работать в поте лица! + +Реализуй логику метода interrupt, который должен прерывать трэд предварительно закрыв используемые ресурсы. +Используй метод super-класса в блоке finally. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2508/CustomThreadManipulator.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2508/CustomThreadManipulator.java new file mode 100644 index 0000000..f4f6d2c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2508/CustomThreadManipulator.java @@ -0,0 +1,6 @@ +package com.javarush.task.task25.task2508; + +public interface CustomThreadManipulator { + public void start(String threadName); + public void stop(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2508/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2508/Solution.java new file mode 100644 index 0000000..0442fe3 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2508/Solution.java @@ -0,0 +1,40 @@ +package com.javarush.task.task25.task2508; + +/* +Не валять дурака +*/ +public class Solution +{ + /* + Output: + first + first + second + second + second + third + fifth + */ + public static void main(String[] args) throws InterruptedException { + CustomThreadManipulator manipulator = new TaskManipulator(); + + manipulator.start("first"); + Thread.sleep(150); + manipulator.stop(); + + manipulator.start("second"); + Thread.sleep(250); + manipulator.stop(); + + manipulator.start("third"); + Thread.sleep(50); + manipulator.stop(); + + manipulator.start("forth"); + manipulator.stop(); + + manipulator.start("fifth"); + Thread.sleep(1); + manipulator.stop(); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2508/TaskManipulator.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2508/TaskManipulator.java new file mode 100644 index 0000000..179166b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2508/TaskManipulator.java @@ -0,0 +1,31 @@ +package com.javarush.task.task25.task2508; + +public class TaskManipulator implements Runnable, CustomThreadManipulator { + private Thread thread; + + @Override + public void run() { + + while (!Thread.currentThread().isInterrupted()){ + try { + System.out.println(Thread.currentThread().getName()); + Thread.currentThread().sleep(75); + } catch (InterruptedException e) { + break; + } + } + } + + @Override + public void start(String threadName) { + TaskManipulator manipulator = new TaskManipulator(); + thread = new Thread(manipulator); + thread.setName(threadName); + thread.start(); + } + + @Override + public void stop() { + thread.interrupt(); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2508/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2508/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..d1a7675 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2508/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task25.task2508" + +Не валять дурака + +Восстанови логику класса TaskManipulator. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2509/CancellableTask.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2509/CancellableTask.java new file mode 100644 index 0000000..c7a3921 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2509/CancellableTask.java @@ -0,0 +1,10 @@ +package com.javarush.task.task25.task2509; + +import java.util.concurrent.Callable; +import java.util.concurrent.RunnableFuture; + +public interface CancellableTask extends Callable { + void cancel(); + + RunnableFuture newTask(); +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2509/SocketTask.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2509/SocketTask.java new file mode 100644 index 0000000..7d01940 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2509/SocketTask.java @@ -0,0 +1,38 @@ +package com.javarush.task.task25.task2509; + +import java.io.IOException; +import java.net.Socket; +import java.util.concurrent.FutureTask; +import java.util.concurrent.RunnableFuture; + +public abstract class SocketTask implements CancellableTask { + private Socket socket; + + protected synchronized void setSocket(Socket socket) { + this.socket = socket; + } + + public synchronized void cancel() { + try { + if (socket != null ) { + socket.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + public RunnableFuture newTask() { + return new FutureTask(this) { + public boolean cancel(boolean mayInterruptIfRunning) { + //close all resources here by using proper SocketTask method + //call super-class method in finally block + try { + SocketTask.this.cancel(); + } finally { + return super.cancel(mayInterruptIfRunning); + } + } + }; + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2509/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2509/Solution.java new file mode 100644 index 0000000..ef7f2f0 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2509/Solution.java @@ -0,0 +1,23 @@ +package com.javarush.task.task25.task2509; + +import java.util.concurrent.*; + +/* +Все не так легко, как кажется +*/ +public class Solution extends ThreadPoolExecutor { + public Solution(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue) { + super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); + } + + protected RunnableFuture newTaskFor(Callable callable) { + if (callable instanceof CancellableTask) { + return ((CancellableTask) callable).newTask(); + } else { + return super.newTaskFor(callable); + } + } + + public static void main(String[] args) { + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2509/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2509/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..2008a44 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2509/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,9 @@ +taskKey="com.javarush.task.task25.task2509" + +Все не так легко, как кажется + +1. Почитать в инете про Socket, ThreadPoolExecutor, RunnableFuture, Callable. +2. Реализуй логику метода cancel в классе SocketTask. +3. Реализуй логику метода cancel для локального класса внутри метода newTask в классе SocketTask. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2510/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2510/Solution.java new file mode 100644 index 0000000..a935a72 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2510/Solution.java @@ -0,0 +1,28 @@ +package com.javarush.task.task25.task2510; + +/* +Поживем - увидим +*/ +public class Solution extends Thread { + + public Solution() { + this.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler()); + } + + public class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler { + + @Override + public void uncaughtException(Thread t, Throwable e) { + if (e instanceof Error) { + System.out.println("Нельзя дальше работать"); + } else if (e instanceof Exception){ + System.out.println("Надо обработать"); + } else if (e instanceof Throwable){ + System.out.println("ХЗ"); + } + } + } + + public static void main(String[] args) { + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2510/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2510/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..e8bc081 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2510/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,11 @@ +taskKey="com.javarush.task.task25.task2510" + +Поживем - увидим + +Все исключения, которые возникают в процессе работы нити Solution, должны быть обработаны одним из вариантов: +1. Если это Error, то вывести в консоль "Нельзя дальше работать". +2. Если это Exception, то вывести в консоль "Надо обработать". +3. Если это Throwable, то вывести в консоль "ХЗ". +Реализуй эту логику. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2511/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2511/Solution.java new file mode 100644 index 0000000..a34dd52 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2511/Solution.java @@ -0,0 +1,71 @@ +package com.javarush.task.task25.task2511; + +import java.util.TimerTask; +import java.util.concurrent.ThreadFactory; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/* +Вооружаемся до зубов! +*/ +public class Solution extends TimerTask { + protected TimerTask original; + protected final Thread.UncaughtExceptionHandler handler; + + public Solution(TimerTask original) { + if (original == null) { + throw new NullPointerException(); + } + this.original = original; + + class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler{ + + @Override + public void uncaughtException(Thread t, Throwable e) { + String message = e.getMessage(); + String name = Thread.currentThread().getName(); + StringBuilder str = new StringBuilder(); + for (int i = 0; i < name.length(); i++){ + str.append("*"); + } + message = message.replaceAll(name, str.toString()); + System.out.println(message); + } + } + + this.handler = new MyUncaughtExceptionHandler(); //init handler here + + + } + + public void run() { + try { + original.run(); + throw new Throwable(); + } catch (Throwable cause) { + Thread currentThread = Thread.currentThread(); + handler.uncaughtException(currentThread, new Exception("Blah " + currentThread.getName() + " blah-blah-blah", cause)); + } + } + + public long scheduledExecutionTime() { + return original.scheduledExecutionTime(); + } + + public boolean cancel() { + return original.cancel(); + } + + public static void main(String[] args) { + Solution sol = new Solution(new TimerTask() { + @Override + public void run() { + + } + }); + Thread thread = new Thread(sol); + thread.start(); + } + + +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2511/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2511/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..d70c35f --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2511/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,10 @@ +taskKey="com.javarush.task.task25.task2511" + +Вооружаемся до зубов! + +Создай свой UncaughtExceptionHandler в виде локального класса внутри конструктора. +UncaughtExceptionHandler должен маскировать звездочками имя трэда и выводить в консоль описание возникшей ошибки. +"Thread-0" должно быть заменено на "********". +"Thread-4321" должно быть заменено на "***********". + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2512/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2512/Solution.java new file mode 100644 index 0000000..9e52a97 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2512/Solution.java @@ -0,0 +1,33 @@ +package com.javarush.task.task25.task2512; + +import java.util.ArrayList; + +/* +Живем своим умом +*/ +public class Solution implements Thread.UncaughtExceptionHandler { + + @Override + public void uncaughtException(Thread t, Throwable e) { + t.interrupt(); + ArrayList trace = new ArrayList(); + //trace.add(e.toString()); + while (true){ + if ( e.getCause() == null ) { + trace.add(e.toString()); + break; + } + trace.add(e.toString()); + e = e.getCause(); + + } + for (int i = trace.size() - 1; i >= 0; i--) { + System.out.println(trace.get(i)); + } + } + + public static void main(String[] args) throws Exception { + Solution sol = new Solution(); + sol.uncaughtException(Thread.currentThread(), new Exception("ABC", new RuntimeException("DEF", new IllegalAccessException("GHI")))); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2512/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2512/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..63c036a --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2512/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,14 @@ +taskKey="com.javarush.task.task25.task2512" + +Живем своим умом + +В классе Solution реализуй интерфейс UncaughtExceptionHandler, который должен: +1. прервать нить, которая бросила исключение. +2. вывести в консоль стек исключений, начиная с самого вложенного. +Пример исключения: new Exception("ABC", new RuntimeException("DEF", new IllegalAccessException("GHI"))) +Пример вывода: +java.lang.IllegalAccessException: GHI +java.lang.RuntimeException: DEF +java.lang.Exception: ABC + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2513/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2513/Solution.java new file mode 100644 index 0000000..997fee2 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2513/Solution.java @@ -0,0 +1,34 @@ +package com.javarush.task.task25.task2513; + +import java.util.Random; + +/* +Обеспечение отсутствия прерывания важной операции +*/ +public class Solution { + private static final Integer THRESHOLD_VALUE = 500; + private static final Random RANDOM = new Random(); + + public synchronized void moveMoney(Account from, Account to, int amount) { + from.setBalance(from.getBalance() - amount); + if (RANDOM.nextInt(5000) > THRESHOLD_VALUE) { + Thread.yield(); + } + to.setBalance(to.getBalance() + amount); + } + + class Account { + private int balance; + + public int getBalance() { + return balance; + } + + public void setBalance(int balance) { + this.balance = balance; + } + } + + public static void main(String[] args) { + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2513/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2513/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..4ea5ae3 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2513/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,10 @@ +taskKey="com.javarush.task.task25.task2513" + +Обеспечение отсутствия прерывания важной операции + +Просмотри метод moveMoney. +Если RANDOM.nextInt(5000) больше порогового значения THRESHOLD_VALUE, +то обеспечь переуступку кванта времени (переход хода для текущей нити). +Добавь этот код в единственное допустимое место. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2514/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2514/Solution.java new file mode 100644 index 0000000..91ed364 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2514/Solution.java @@ -0,0 +1,26 @@ +package com.javarush.task.task25.task2514; + +/* +Первый закон Финэйгла: если эксперимент удался, что-то здесь не так... +*/ +public class Solution { + public static class YieldRunnable implements Runnable { + private int index; + + public YieldRunnable(int index) { + this.index = index; + } + + public void run() { + System.out.println("begin-" + index); + Thread.yield(); + System.out.println("end-" + index); + } + } + + public static void main(String[] args) { + for (int i = 0; i < 10; i++){ + new Thread(new YieldRunnable(i)).start(); + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2514/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2514/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..5536615 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2514/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task25.task2514" + +Первый закон Финэйгла: если эксперимент удался, что-то здесь не так... + +Обеспечь переуступку кванта времени (переход хода для текущей нити) для последовательных выводов текста в консоль. + + From f6a493c26b87a156978ef4d897ed3ff03da5b777 Mon Sep 17 00:00:00 2001 From: PeucT Date: Sun, 19 Mar 2017 02:15:47 +0300 Subject: [PATCH 08/51] 2601 - 2606 --- .../task/task26/task2601/Solution.java | 46 +++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 14 +++ .../task/task26/task2602/Solution.java | 38 ++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 8 ++ .../task/task26/task2603/Solution.java | 29 +++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 13 ++ .../task/task26/task2604/Solution.java | 64 ++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 7 ++ .../task/task26/task2605/Solution.java | 70 +++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 7 ++ .../task/task26/task2606/Solution.java | 112 ++++++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 7 ++ 12 files changed, 415 insertions(+) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task26/task2601/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task26/task2601/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task26/task2602/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task26/task2602/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task26/task2603/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task26/task2603/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task26/task2604/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task26/task2604/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task26/task2605/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task26/task2605/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task26/task2606/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task26/task2606/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2601/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2601/Solution.java new file mode 100644 index 0000000..a916353 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2601/Solution.java @@ -0,0 +1,46 @@ +package com.javarush.task.task26.task2601; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; + +/* +Почитать в инете про медиану выборки +*/ +public class Solution { + + public static void main(String[] args) { + /*Integer[] array = {13, 8, 15, 5, 17, 14}; + array = sort(array); + for (Integer entry: array){ + System.out.println(entry); + }*/ + } + + public static Integer[] sort(Integer[] array) { + // Находим медианное значение + Arrays.sort(array); + final double mediana; + if ((array.length) % 2 == 0) { + int index = ( array.length / 2 ) - 1; + mediana = (array[index] + array[index + 1]) / 2d; + } else { + mediana = array[(array.length - 1) / 2]; + } + + // Сортируем массив по удаленности от медианного значения + Arrays.sort(array, new Comparator(){ + + @Override + public int compare(Object o1, Object o2) { + if (o1.equals(o2)) return 0; + if ((Math.abs(Double.parseDouble(o1.toString()) - mediana) - Math.abs(Double.parseDouble(o2.toString()) - mediana)) > 0 ) { return 1; } + else if ((Math.abs(Double.parseDouble(o1.toString()) - mediana) - Math.abs(Double.parseDouble(o2.toString()) - mediana)) < 0 ) { return -1; } + else return 0; + } + }); + + return array; + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2601/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2601/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..979f12d --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2601/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,14 @@ +taskKey="com.javarush.task.task26.task2601" + +Почитать в инете про медиану выборки + +Реализуй логику метода sort, который должен сортировать данные в массиве по удаленности от его медианы. +Верни отсортированный массив от минимального расстояния до максимального. +Если удаленность одинаковая у нескольких чисел, то сортируй их в порядке возрастания. +Пример входящего массива: +13, 8, 15, 5, 17 +медиана - 13 +отсортированный масив: +13, 15, 17, 8, 5 + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2602/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2602/Solution.java new file mode 100644 index 0000000..fbcdcde --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2602/Solution.java @@ -0,0 +1,38 @@ +package com.javarush.task.task26.task2602; + +import java.util.Comparator; +import java.util.Set; +import java.util.TreeSet; + +/* +Был бы ум - будет и успех +*/ +public class Solution { + public static void main(String[] args) { + Set soldiers = new TreeSet<>(); + soldiers.add(new Soldier("Ivanov", 170)); + soldiers.add(new Soldier("Petrov", 180)); + soldiers.add(new Soldier("Sidorov", 175)); + soldiers.add(new Soldier("Test", 170)); + + for (Soldier soldier : soldiers) { + System.out.println(soldier.name); + } + } + + public static class Soldier implements Comparable { + private String name; + private int height; + + public Soldier(String name, int height) { + this.name = name; + this.height = height; + } + + + @Override + public int compareTo(Soldier o) { + return o.height - this.height; + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2602/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2602/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..3515493 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2602/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,8 @@ +taskKey="com.javarush.task.task26.task2602" + +Был бы ум - будет и успех + +Солдаты всегда строились, строятся и будут строиться по убыванию роста. +Отсортируй солдат, предварительно подумав, что лучше использовать при таких условиях - Comparable или Comparator. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2603/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2603/Solution.java new file mode 100644 index 0000000..76a38db --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2603/Solution.java @@ -0,0 +1,29 @@ +package com.javarush.task.task26.task2603; + +import java.util.Comparator; + +/* +Убежденному убеждать других не трудно +*/ +public class Solution { + + public static class CustomizedComparator implements Comparator{ + private Comparator[] comparators; + public CustomizedComparator(Comparator... vararg){ + this.comparators = vararg; + } + + @Override + public int compare(Object o1, Object o2) { + for (int i = 0; i < comparators.length; i++){ + int compareValue = comparators[i].compare((T) o1, (T) o2); + if (compareValue != 0 ) { return compareValue; } + } + return 0; + } + } + + public static void main(String[] args) { + + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2603/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2603/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..5450d42 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2603/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,13 @@ +taskKey="com.javarush.task.task26.task2603" + +Убежденному убеждать других не трудно + +В таблице есть колонки, по которым можно сортировать. +Пользователь имеет возможность настроить под себя список колонок, которые будут сортироваться. +Напиши public static компаратор CustomizedComparator, который будет: +1. в конструкторе принимать массив компараторов. +2. сортировать данные в порядке, соответствующем последовательности компараторов. +Все переданные компараторы сортируют дженерик тип Т. +В конструктор передается как минимум один компаратор. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2604/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2604/Solution.java new file mode 100644 index 0000000..81d1ce2 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2604/Solution.java @@ -0,0 +1,64 @@ +package com.javarush.task.task26.task2604; + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Level; +import java.util.logging.Logger; + +/* +Для того, чтобы усовершенствовать ум, надо больше размышлять, чем заучивать +*/ +public class Solution extends Thread { + public static final String DEFAULT_JAVARUSH_THREAD_NAME = "JavaRushThread"; + + private static final AtomicInteger createdThreadIndex = new AtomicInteger(); + private static final AtomicInteger aliveThreadIndex = new AtomicInteger(); + private static final Logger log = Logger.getAnonymousLogger(); + + private static volatile boolean debugLifecycle = false; + + public Solution(Runnable runnable) { + this(runnable, DEFAULT_JAVARUSH_THREAD_NAME); + } + + public Solution(Runnable runnable, String name) { + super(runnable, name + "-" + createdThreadIndex.incrementAndGet()); + + setUncaughtExceptionHandler(new UncaughtExceptionHandler() { + public void uncaughtException(Thread t, Throwable e) { + log.log(Level.SEVERE, "An error occurred in thread " + t.getName(), e); + } + }); + } + + public static void main(String[] args) { + new Solution(new Runnable() { + @Override + public void run() { + System.out.println("test JavaRush Runnable for Solution class"); + } + }).start(); + + + new Solution(new Runnable() { + @Override + public void run() { + throw new RuntimeException("Oops"); + } + }).start(); + } + + public void run() { + if (debugLifecycle) { + log.log(Level.FINE, "Created " + getName()); + } + try { + aliveThreadIndex.incrementAndGet(); + super.run(); + } finally { + aliveThreadIndex.decrementAndGet(); + if (debugLifecycle) { + log.log(Level.FINE, "Exiting " + getName()); + } + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2604/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2604/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..adac129 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2604/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task26.task2604" + +Для того, чтобы усовершенствовать ум, надо больше размышлять, чем заучивать + +Расставь volatile там, где необходимо. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2605/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2605/Solution.java new file mode 100644 index 0000000..45122ab --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2605/Solution.java @@ -0,0 +1,70 @@ +package com.javarush.task.task26.task2605; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +/* +Трудолюбие - душа всякого дела и залог благосостояния +*/ +public class Solution { + private static ScheduledExecutorService interruptScheduledExecutor; + private static Thread taskThread; + private static RethrowableTask task; + + public static void main(String[] args) throws Exception { + runTaskBySchedule(new Runnable() { + @Override + public void run() { + System.out.println("A"); + throw new RuntimeException("it's test"); + } + }, 1_000, TimeUnit.MILLISECONDS + ); + + interruptScheduledExecutor.shutdown(); + } + + public static void runTaskBySchedule(final Runnable runnable, long timeout, TimeUnit unit) throws Exception { + task = new RethrowableTask(runnable); + taskThread = new Thread(task); + taskThread.start(); + + interruptScheduledExecutor = Executors.newScheduledThreadPool(1); + interruptScheduledExecutor.schedule(new Runnable() { + public void run() { + taskThread.interrupt(); + } + }, timeout, unit); + Thread.sleep(unit.toMillis(timeout)); + try { + task.rethrow(); + } catch (Throwable throwable) { + System.out.println(throwable.getMessage()); + } + } + + public static class RethrowableTask implements Runnable { + private volatile Throwable throwable; + private Runnable runnable; + + public RethrowableTask(Runnable runnable) { + this.runnable = runnable; + } + + public void run() { + try { + runnable.run(); + } catch (Throwable throwable) { + this.throwable = throwable; + } + } + + public void rethrow() throws Exception { + if (throwable != null) { + System.out.println("B"); + throw new Exception(throwable); + } + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2605/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2605/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..bac6868 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2605/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task26.task2605" + +Трудолюбие - душа всякого дела и залог благосостояния + +Расставь volatile там, где необходимо. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2606/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2606/Solution.java new file mode 100644 index 0000000..da937ed --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2606/Solution.java @@ -0,0 +1,112 @@ +package com.javarush.task.task26.task2606; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +/* +Тот, кто любит труд, не нуждается в развлечениях +*/ +public class Solution { + private final URL javarushUrl; + private final URL javarushUrl1Child; + private final URL javarushVkGroupUrl; + private final URL javarushVkGroupUrl1Child; + private final URL javarushVkGroupUrl2Child; + private final URL javarushVkGroupUrl3Child; + + private volatile ExecutorService executorService; + private final Set urlsForProcessing = Collections.synchronizedSet(new HashSet<>()); + + public static void main(String[] args) throws MalformedURLException, InterruptedException { + Solution solution = new Solution(); + solution.start(); + Thread.sleep(1000); + solution.stop(); + } + + public Solution() throws MalformedURLException { + javarushUrl = new URL("http://javarush.ru/"); + javarushVkGroupUrl = new URL("http://vk.com/javarush"); + javarushUrl1Child = new URL("http://info.javarush.ru/page/FAQ/"); + javarushVkGroupUrl1Child = new URL("https://plus.google.com/114772402300089087607/about"); + javarushVkGroupUrl2Child = new URL("https://www.facebook.com/pages/Javarush/524321077686033"); + javarushVkGroupUrl3Child = new URL("https://twitter.com/javarush_ru"); + + urlsForProcessing.add(javarushUrl); + urlsForProcessing.add(javarushVkGroupUrl); + } + + public synchronized void start() { + executorService = Executors.newCachedThreadPool(); + for (URL url : urlsForProcessing) { + submitUrlTask(url); + } + urlsForProcessing.clear(); + } + + public synchronized void stop() throws InterruptedException { + try { + saveUnprocessedUrls(executorService.shutdownNow()); + if (executorService.awaitTermination(1_000, TimeUnit.MILLISECONDS)) { + saveUnprocessedUrls(getCancelledTasksFromExecutor()); + } + } finally { + executorService = null; + } + } + + private List getCancelledTasksFromExecutor() { + return Collections.EMPTY_LIST; + } + + protected List processPage(URL url) { + System.out.println(url + " will be processed"); + return getChildUrlByParent(url); + } + + private List getChildUrlByParent(URL url) { + List result = new ArrayList<>(); + + if (javarushUrl.equals(url)) { + result.add(javarushUrl1Child); + } else if (javarushVkGroupUrl.equals(url)) { + result.add(javarushVkGroupUrl1Child); + result.add(javarushVkGroupUrl2Child); + result.add(javarushVkGroupUrl3Child); + } + return result; + } + + private void saveUnprocessedUrls(List unprocessed) { + for (Runnable task : unprocessed) { + urlsForProcessing.add(((UrlTask) task).getPage()); + } + } + + private void submitUrlTask(URL url) { + executorService.execute(new UrlTask(url)); + } + + public class UrlTask implements Runnable { + private final URL url; + + private UrlTask(URL url) { + this.url = url; + } + + public void run() { + for (URL link : processPage(url)) { + if (Thread.currentThread().isInterrupted()) return; + submitUrlTask(link); + } + } + + public URL getPage() { + return url; + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2606/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2606/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..4bb5e58 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2606/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task26.task2606" + +Тот, кто любит труд, не нуждается в развлечениях + +Расставь volatile там, где необходимо. + + From e95870af12b3a5108552346e2011afdfa7f0040b Mon Sep 17 00:00:00 2001 From: PeucT Date: Tue, 21 Mar 2017 21:21:12 +0300 Subject: [PATCH 09/51] 2607 - 2612 (Full) --- .../task/task26/task2607/Solution.java | 21 +++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 9 +++ .../task/task26/task2608/Solution.java | 39 ++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 9 +++ .../task/task26/task2609/Solution.java | 62 +++++++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 7 +++ .../task/task26/task2610/Consumer.java | 31 ++++++++++ .../task/task26/task2610/Producer.java | 23 +++++++ .../task/task26/task2610/Solution.java | 29 +++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 8 +++ .../task/task26/task2611/Consumer.java | 22 +++++++ .../task/task26/task2611/Producer.java | 29 +++++++++ .../task/task26/task2611/Solution.java | 26 ++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 10 +++ .../task/task26/task2612/Solution.java | 30 +++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 13 ++++ 16 files changed, 368 insertions(+) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task26/task2607/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task26/task2607/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task26/task2608/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task26/task2608/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task26/task2609/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task26/task2609/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task26/task2610/Consumer.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task26/task2610/Producer.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task26/task2610/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task26/task2610/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task26/task2611/Consumer.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task26/task2611/Producer.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task26/task2611/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task26/task2611/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task26/task2612/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task26/task2612/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2607/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2607/Solution.java new file mode 100644 index 0000000..2fab39f --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2607/Solution.java @@ -0,0 +1,21 @@ +package com.javarush.task.task26.task2607; + +/* +Вежливость - это искусственно созданное хорошее настроение +*/ +public class Solution { + public static void main(String[] args) { + } + + public static class IntegerHolder{ + private int value; + + public synchronized int get(){ + return value; + } + + public synchronized void set(int value){ + this.value = value; + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2607/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2607/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..8881c8b --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2607/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,9 @@ +taskKey="com.javarush.task.task26.task2607" + +Вежливость - это искусственно созданное хорошее настроение + +В классе Solution создай public static класс IntegerHolder. +IntegerHolder должен быть для типа int (имя переменной должно быть value), быть thread safe и изменяемым. +В этом классе должны быть два public метода get и set. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2608/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2608/Solution.java new file mode 100644 index 0000000..dd6b33d --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2608/Solution.java @@ -0,0 +1,39 @@ +package com.javarush.task.task26.task2608; + +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/* +Мудрый человек думает раз, прежде чем два раза сказать +*/ +public class Solution { + int var1; + int var2; + int var3; + int var4; + Object lock1 = new Object(); + Object lock2 = new Object(); + + public Solution(int var1, int var2, int var3, int var4) { + this.var1 = var1; + this.var2 = var2; + this.var3 = var3; + this.var4 = var4; + } + + public int getSumOfVar1AndVar2() { + synchronized (lock1) { + return var1 + var2; + } + } + + public int getSumOfVar3AndVar4() { + synchronized (lock2){ + return var3 + var4; + } + } + + public static void main(String[] args) { + + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2608/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2608/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..4b9e052 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2608/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,9 @@ +taskKey="com.javarush.task.task26.task2608" + +Мудрый человек думает раз, прежде чем два раза сказать + +Все методы, кроме метода main, класса Solution должны быть thread safe. +Сделайте так, чтобы оба метода могли выполняться одновременно двумя различными тредами. +synchronized(this) для этого не подходит, используй другой объект для лока. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2609/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2609/Solution.java new file mode 100644 index 0000000..9893445 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2609/Solution.java @@ -0,0 +1,62 @@ +package com.javarush.task.task26.task2609; + +/* +Распределение элементов по корзинам с собственным локом +*/ +public class Solution { + private static final int NUMBER_LOCKS = 12; + private final Node[] buckets; + private final Object[] locks; + + static class Node { + public Node next; + public Object key; + public Object value; + } + + public Solution(int numberBuckets) { + buckets = new Node[numberBuckets]; + locks = new Object[NUMBER_LOCKS]; + for (int i = 0; i < NUMBER_LOCKS; i++) { + locks[i] = new Object(); + } + } + + private final int hash(Object key) { + return Math.abs(key.hashCode() % buckets.length); + } + + public Object get(Object key) { + int hash = hash(key); + synchronized (locks[hash % NUMBER_LOCKS]) { + for (Node m = buckets[hash]; m != null; m = m.next) { + if (m.key.equals(key)) return m.value; + } + } + return null; + } + + public void clear() { + for (int i = 0; i < buckets.length; i++) { + synchronized (locks[i % NUMBER_LOCKS]) { + buckets[i] = null; + } + } + } + + public static void main(String[] args) { + Solution sol = new Solution(3); + Node node1 = new Node(); + node1.key = 1; + Node node2 = new Node(); + node1.key = 2; + Node node3 = new Node(); + node1.key = 3; + sol.buckets[0] = node1; + sol.buckets[1] = node2; + sol.buckets[2] = node3; + sol.get(1); + sol.clear(); + + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2609/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2609/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..c42bd8c --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2609/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task26.task2609" + +Распределение элементов по корзинам с собственным локом + +В синхронизированных блоках используй нужный лок. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2610/Consumer.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2610/Consumer.java new file mode 100644 index 0000000..f7ca641 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2610/Consumer.java @@ -0,0 +1,31 @@ +package com.javarush.task.task26.task2610; + +import java.util.concurrent.BlockingQueue; + +import static java.lang.Thread.sleep; + +/** + * Created by Archmage on 19.03.2017. + */ +public class Consumer implements Runnable { + private BlockingQueue queue; + + public Consumer(BlockingQueue queue) { + this.queue = queue; + } + + @Override + public void run() { + try{ + while (true){ + String input; + if ((input = (String) queue.take()) != null) { + System.out.println(input); + } + Thread.sleep(300); + } + } catch (InterruptedException e){ + System.out.println(String.format("[%s] thread was terminated", Thread.currentThread().getName())); + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2610/Producer.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2610/Producer.java new file mode 100644 index 0000000..8f52402 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2610/Producer.java @@ -0,0 +1,23 @@ +package com.javarush.task.task26.task2610; + +import java.util.concurrent.BlockingQueue; + +public class Producer implements Runnable { + private BlockingQueue queue; + + public Producer(BlockingQueue queue) { + this.queue = queue; + } + + public void run() { + try { + int i = 0; + while (true) { + queue.put(String.valueOf(i++)); + Thread.sleep(300); + } + } catch (InterruptedException e) { + System.out.println(String.format("[%s] thread was terminated", Thread.currentThread().getName())); + } + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2610/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2610/Solution.java new file mode 100644 index 0000000..88c1d54 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2610/Solution.java @@ -0,0 +1,29 @@ +package com.javarush.task.task26.task2610; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/* +Мир скучен для скучных людей +*/ +public class Solution { + + public static void main(String[] args) throws Exception { + + BlockingQueue queue = new ArrayBlockingQueue(32); + + Producer producer = new Producer(queue); + Consumer consumer = new Consumer(queue); + + ExecutorService executorService = Executors.newCachedThreadPool(); + executorService.submit(producer); + executorService.submit(consumer); + + Thread.sleep(2000); + + executorService.shutdownNow(); + + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2610/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2610/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..43db659 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2610/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,8 @@ +taskKey="com.javarush.task.task26.task2610" + +Мир скучен для скучных людей + +Разберись с BlockingQueue. +По образу и подобию класса Producer создай класс Consumer, который будет выводить данные из BlockingQueue в консоль. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2611/Consumer.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2611/Consumer.java new file mode 100644 index 0000000..b39bcc8 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2611/Consumer.java @@ -0,0 +1,22 @@ +package com.javarush.task.task26.task2611; + +import java.util.concurrent.ConcurrentHashMap; + +public class Consumer implements Runnable { + private ConcurrentHashMap map; + + public Consumer(ConcurrentHashMap map) { + this.map = map; + } + + public void run() { + Thread currentThread = Thread.currentThread(); + while (!currentThread.isInterrupted()) { + if (!map.isEmpty()) { + for (String key : map.keySet()) { + System.out.println(map.remove(key)); + } + } + } + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2611/Producer.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2611/Producer.java new file mode 100644 index 0000000..1886387 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2611/Producer.java @@ -0,0 +1,29 @@ +package com.javarush.task.task26.task2611; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedDeque; + +/** + * Created by Archmage on 19.03.2017. + */ +public class Producer implements Runnable { + private ConcurrentHashMap map; + + public Producer(ConcurrentHashMap map){ + this.map = map; + } + + @Override + public void run() { + int i = 0; + try{ + while(true) { + i++; + map.put(String.valueOf(i), String.format("Some text for %s", i)); + Thread.sleep(500); + } + }catch (InterruptedException e){ + System.out.println(String.format("%s thread was terminated", Thread.currentThread().getName())); + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2611/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2611/Solution.java new file mode 100644 index 0000000..d3ff7f9 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2611/Solution.java @@ -0,0 +1,26 @@ +package com.javarush.task.task26.task2611; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/* +Мир не меняется, меняемся мы +*/ +public class Solution { + public static void main(String[] args) throws Exception { + ConcurrentHashMap map = new ConcurrentHashMap<>(); + + Producer producer = new Producer(map); + Consumer consumer = new Consumer(map); + + ExecutorService executorService = Executors.newCachedThreadPool(); + executorService.submit(producer); + executorService.submit(consumer); + + Thread.sleep(2000); + + executorService.shutdownNow(); + //finally 5 lines have to be printed + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2611/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2611/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..6a05242 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2611/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,10 @@ +taskKey="com.javarush.task.task26.task2611" + +Мир не меняется, меняемся мы + +Разберись с ConcurrentHashMap. +В отдельном файле создайте класс Producer, который будет: +1. каждые полсекунды добавлять в ConcurrentHashMap ключ и значение, где ключ - счетчик начиная с 1, значение - фраза: "Some text for i" , пример "Some text for 1". +2. при возникновении исключения выводить в консоль: "[TREAD_NAME] thread was terminated", пример "[thread-1] thread was terminated". + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2612/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2612/Solution.java new file mode 100644 index 0000000..b4d8b61 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2612/Solution.java @@ -0,0 +1,30 @@ +package com.javarush.task.task26.task2612; + +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/* +Весь мир играет комедию +*/ +public class Solution { + private Lock lock = new ReentrantLock(); + + public void someMethod() { + + if (lock.tryLock()){ + try { + ifLockIsFree(); + } finally { + lock.unlock(); + } + } else { + ifLockIsBusy(); + } + } + + public void ifLockIsFree() { + } + + public void ifLockIsBusy() { + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2612/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2612/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..c80e675 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2612/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,13 @@ +taskKey="com.javarush.task.task26.task2612" + +Весь мир играет комедию + +Почитать про java.util.concurrent.locks.Lock на http://docs.oracle.com/ (там все есть в джавадоках!) +Написать реализацию метода someMethod: +1. попытаться захватить лок +1.1. если лок занят, то вызвать метод ifLockIsBusy +1.2. если лок свободен, то: +1.2.1 вызвать метод ifLockIsFree +1.2.2 отпустить лок при любых условиях, даже если ifLockIsFree будет кидать исключение + + From 70d80c34f751253a2dfe1b06e884d354bf0e5e1e Mon Sep 17 00:00:00 2001 From: PeucT Date: Wed, 22 Mar 2017 18:13:14 +0300 Subject: [PATCH 10/51] 2701-2708 --- .../task/task27/task2701/Solution.java | 28 +++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 9 +++ .../task/task27/task2702/Solution.java | 21 ++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 7 ++ .../task/task27/task2703/Solution.java | 48 ++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 8 ++ .../task/task27/task2704/Solution.java | 43 +++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 8 ++ .../task/task27/task2705/Solution.java | 46 ++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 8 ++ .../task/task27/task2706/Solution.java | 48 ++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 10 +++ .../task/task27/task2707/Solution.java | 73 +++++++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 11 +++ .../task/task27/task2708/Apartment.java | 24 ++++++ .../task/task27/task2708/RealEstate.java | 43 +++++++++++ .../task/task27/task2708/Solution.java | 51 +++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 14 ++++ 18 files changed, 500 insertions(+) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2701/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task27/task2701/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2702/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task27/task2702/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2703/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task27/task2703/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2704/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task27/task2704/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2705/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task27/task2705/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2706/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task27/task2706/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2707/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task27/task2707/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2708/Apartment.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2708/RealEstate.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2708/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task27/task2708/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2701/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2701/Solution.java new file mode 100644 index 0000000..22b2889 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2701/Solution.java @@ -0,0 +1,28 @@ +package com.javarush.task.task27.task2701; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +/* +Избавляемся от меток +*/ +public class Solution { + public static void main(String[] args) throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + String string = reader.readLine(); + String substring = reader.readLine(); + + if (isSubstringPresent(substring, string)) { + System.out.println("String: \n" + substring + "\nis present in the string: \n" + string); + } else { + System.out.println("String: \n" + substring + "\nis not present in the string: \n" + string); + } + } + + static boolean isSubstringPresent(String substring, String string) { + if (string.contains(substring)) { return true; } + else { return false; } + } +} + diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2701/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2701/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..e708ac5 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2701/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,9 @@ +taskKey="com.javarush.task.task27.task2701" + +Избавляемся от меток + +Избавьтесь от меток в методе isSubstringPresent сохранив логику. +Метод возвращает true, в случае если строка substring является подстрокой строки string, иначе false. +В коде должны отсутствовать операторы break и continue. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2702/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2702/Solution.java new file mode 100644 index 0000000..6b05881 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2702/Solution.java @@ -0,0 +1,21 @@ +package com.javarush.task.task27.task2702; + +/* +Нужный оператор +*/ +public class Solution { + public static void main(String args[]) { + label: + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 10; j++) { + if (j > i) { + + System.out.println(); + continue label; + } + System.out.print("S"); + + } + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2702/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2702/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..d072ea4 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2702/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task27.task2702" + +Нужный оператор + +Вставьте в код единственную строчку - оператор (не break), чтобы на экран выводился треугольник из букв S. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2703/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2703/Solution.java new file mode 100644 index 0000000..68414c0 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2703/Solution.java @@ -0,0 +1,48 @@ +package com.javarush.task.task27.task2703; + +/* +Создаем deadlock +*/ +public class Solution { + static class Friend { + private final String name; + + public Friend(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } + + public synchronized void bow(Friend bower) { + System.out.format("%s: %s" + + " has bowed to me!%n", + this.name, bower.getName()); + bower.bowBack(this); + } + + public synchronized void bowBack(Friend bower) { + System.out.format("%s: %s" + + " has bowed back to me!%n", + this.name, bower.getName()); + } + } + + public static void main(String[] args) { + final Friend alphonse = + new Friend("Alphonse"); + final Friend gaston = + new Friend("Gaston"); + new Thread(new Runnable() { + public void run() { + alphonse.bow(gaston); + } + }).start(); + new Thread(new Runnable() { + public void run() { + gaston.bow(alphonse); + } + }).start(); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2703/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2703/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..8b16d7c --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2703/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,8 @@ +taskKey="com.javarush.task.task27.task2703" + +Создаем deadlock + +Расставь модификаторы так, чтобы при работе с этим кодом появился deadlock. +Метод main порождает deadlock, поэтому не участвует в тестировании. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2704/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2704/Solution.java new file mode 100644 index 0000000..be33d5c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2704/Solution.java @@ -0,0 +1,43 @@ +package com.javarush.task.task27.task2704; + +/* +Модификаторы и deadlock +*/ +public class Solution { + private final String field; + + public Solution(String field) { + this.field = field; + } + + public String getField() { + return field; + } + + public synchronized void sout(Solution solution) { + System.out.format("111: %s: %s %n", this.field, solution.getField()); + solution.sout2(this); + } + + public synchronized void sout2(Solution solution) { + System.out.format("222: %s: %s %n", this.field, solution.getField()); + solution.sout(this); + } + + public static void main(String[] args) { + final Solution solution = new Solution("first"); + final Solution solution2 = new Solution("second"); + new Thread(new Runnable() { + public void run() { + solution.sout(solution2); + } + }).start(); + + new Thread(new Runnable() { + public void run() { + solution2.sout(solution); + } + }).start(); + + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2704/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2704/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..0a77bb9 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2704/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,8 @@ +taskKey="com.javarush.task.task27.task2704" + +Модификаторы и deadlock + +Расставь модификаторы так, чтобы при работе с этим кодом появился deadlock. +Метод main порождает deadlock, поэтому не участвует в тестировании. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2705/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2705/Solution.java new file mode 100644 index 0000000..69235b6 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2705/Solution.java @@ -0,0 +1,46 @@ +package com.javarush.task.task27.task2705; + +/* +Второй вариант deadlock +*/ +public class Solution { + private final Object lock = new Object(); + + public synchronized void firstMethod() { + synchronized (lock) { + doSomething(); + } + } + + public void secondMethod() { + synchronized (lock) { + synchronized (this) { + doSomething(); + } + } + } + + private void doSomething() { + } + + public static void main(String[] args) throws InterruptedException { + final Solution sol = new Solution(); + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + sol.firstMethod(); + } + }); + thread.start(); + + new Thread(new Runnable() { + @Override + public void run() { + sol.secondMethod(); + } + }).start(); + + Thread.sleep(1000); + System.out.println(thread.getState()); + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2705/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2705/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..6683ee4 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2705/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,8 @@ +taskKey="com.javarush.task.task27.task2705" + +Второй вариант deadlock + +В методе secondMethod расставь synchronized блоки так, +чтобы при использовании класса Solution нитями образовывался deadlock. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2706/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2706/Solution.java new file mode 100644 index 0000000..15aa45b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2706/Solution.java @@ -0,0 +1,48 @@ +package com.javarush.task.task27.task2706; + +/* +Убираем deadlock +*/ +public class Solution { + public void safeMethod(Object obj1, Object obj2) { + Object syncObjMax = obj1.hashCode() > obj2.hashCode() ? obj1 : obj2; + Object syncObjMin = obj1.hashCode() > obj2.hashCode() ? obj2 : obj1; + synchronized (syncObjMax) { + longTimeMethod(); + synchronized (syncObjMin) { + unsafeMethod(obj1, obj2); + } + } + } + + public void longTimeMethod() { + try { + Thread.sleep(100); + } catch (InterruptedException ignored) { + } + } + + protected void unsafeMethod(Object obj1, Object obj2) { + System.out.println(obj1 + " " + obj2); + } + + public static void main(String[] args) { + final Object o1 = new Object(); + final Object o2 = new Object(); + final Solution solution = new Solution(); + + new Thread() { + @Override + public void run() { + solution.safeMethod(o1, o2); + } + }.start(); + + new Thread() { + @Override + public void run() { + solution.safeMethod(o2, o1); + } + }.start(); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2706/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2706/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..78c26b0 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2706/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,10 @@ +taskKey="com.javarush.task.task27.task2706" + +Убираем deadlock + +Используя стратегию избегания deadlock-а сделай так, чтобы он не возник. +Метод main не участвует в тестировании. +Действуй аналогично примеру из лекций. +Изменения вноси только в safeMethod. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2707/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2707/Solution.java new file mode 100644 index 0000000..8fe8f0b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2707/Solution.java @@ -0,0 +1,73 @@ +package com.javarush.task.task27.task2707; + +import java.util.Date; + +/* +Определяем порядок захвата монитора +*/ +public class Solution { + + public void someMethodWithSynchronizedBlocks(Object obj1, Object obj2){ + synchronized (obj1) { + synchronized (obj2) { + System.out.println(obj1 + " " + obj2); + } + } + } + + private void referenceSyncMethod1(Object obj1) { + synchronized (obj1) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + } + } + + private void referenceSyncMethod2(Object obj1) { + synchronized (obj1) { + try { + Thread.sleep(1); + } catch (InterruptedException e) { + } + } + } + + public static boolean isNormalLockOrder(final Solution solution, final Object o1, final Object o2) throws Exception { + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + solution.someMethodWithSynchronizedBlocks(o1, o2); + } + }); + Thread thread2 = new Thread(new Runnable() { + @Override + public void run() { + solution.referenceSyncMethod1(o1); + } + }); + Thread thread3 = new Thread(new Runnable() { + @Override + public void run() { + solution.referenceSyncMethod2(o2); + } + }); + + thread2.start(); + Thread.sleep(100); + thread.start(); + thread3.start(); + Thread.sleep(100); + if (thread3.getState().equals(Thread.State.TERMINATED)) { return true;} + else { return false; } + + } + + public static void main(String[] args) throws Exception { + final Solution solution = new Solution(); + final Object o1 = new Object(); + final Object o2 = new Object(); + + System.out.println(isNormalLockOrder(solution, o1, o2)); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2707/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2707/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..2822a1e --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2707/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,11 @@ +taskKey="com.javarush.task.task27.task2707" + +Определяем порядок захвата монитора + +Реализуй логику метода isNormalLockOrder, который должен определять: +соответствует ли порядок synchronized блоков в методе someMethodWithSynchronizedBlocks - +порядку передаваемых в него аргументов. +В случае, если сначала происходит синхронизация по o1, а потом по o2, метод должен вернуть true. +Если наоборот - false. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2708/Apartment.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2708/Apartment.java new file mode 100644 index 0000000..39c790e --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2708/Apartment.java @@ -0,0 +1,24 @@ +package com.javarush.task.task27.task2708; + +public class Apartment { + private String location; + private final RealEstate realEstate; + + public Apartment(RealEstate realEstate) { + this.realEstate = realEstate; + setLocation(String.valueOf(Math.random() * 10)); + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public void revalidate(boolean isEmpty) { + if (isEmpty) + realEstate.up(this); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2708/RealEstate.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2708/RealEstate.java new file mode 100644 index 0000000..57d2a0a --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2708/RealEstate.java @@ -0,0 +1,43 @@ +package com.javarush.task.task27.task2708; + +import java.util.HashSet; +import java.util.Set; + +public class RealEstate { + + private final Set allApartments; + private final Set activeApartments; + + public RealEstate() { + allApartments = new HashSet(); + activeApartments = new HashSet(); + + //add some data + allApartments.add(new Apartment(this)); + allApartments.add(new Apartment(this)); + allApartments.add(new Apartment(this)); + allApartments.add(new Apartment(this)); + allApartments.add(new Apartment(this)); + allApartments.add(new Apartment(this)); + } + + public Set getAllApartments() { + return allApartments; + } + + public void up(Apartment apartment) { + activeApartments.add(apartment); + } + + public void revalidate() { + + activeApartments.clear(); + for (Apartment apartment : allApartments) { + boolean randomValue = Math.random() * 2 % 2 == 0; + synchronized (this) { + apartment.revalidate(randomValue); + } + } + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2708/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2708/Solution.java new file mode 100644 index 0000000..803bd09 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2708/Solution.java @@ -0,0 +1,51 @@ +package com.javarush.task.task27.task2708; + +import java.util.Set; + +/* +Убираем deadLock используя открытые вызовы +*/ +public class Solution { + public static void main(String[] args) { + final long deadLineTime = System.currentTimeMillis() + 5000; //waiting for 5 sec + + final RealEstate realEstate = new RealEstate(); + Set allApartments = realEstate.getAllApartments(); + + final Apartment[] apartments = allApartments.toArray(new Apartment[allApartments.size()]); + + for (int i = 0; i < 20; i++) { + new Thread(new Runnable() { + @Override + public void run() { + for (int i = 0; i < 10; i++) { + realEstate.revalidate(); + } + } + }, "RealEstateThread" + i).start(); + + new Thread(new Runnable() { + @Override + public void run() { + for (int i = 0; i < apartments.length; i++) { + apartments[i].revalidate(true); + } + } + }, "ApartmentThread" + i).start(); + } + + Thread deamonThread = new Thread(new Runnable() { + @Override + public void run() { + while (System.currentTimeMillis() < deadLineTime) + try { + Thread.sleep(2); + } catch (InterruptedException ignored) { + } + System.out.println("The dead lock occurred"); + } + }); + deamonThread.setDaemon(true); + deamonThread.start(); + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2708/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2708/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..abecc86 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2708/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,14 @@ +taskKey="com.javarush.task.task27.task2708" + +Убираем deadLock используя открытые вызовы + +Синхронизированные методы, которые вызывают внутри себя синхронизированные методы других классов, приводят к dead-lock-у. +1. Перенесите синхронизацию с метода в синхронизированный блок, куда поместите лишь необходимые части кода. +2. Уберите избыточную синхронизацию методов. +3. В стеке вызова методов не должно быть перекрестной синхронизации, +т.е. такого synchronizedMethodAClass().synchronizedMethodBClass().synchronizedMethodAClass() + +Этот способ избавления от дэдлока называется "открытые вызовы", о нем читайте в дополнительном материале к лекции. +Метод main не участвует в тестировании. + + From c739aac38b8da56d9056fc2c13fefbfd36fdff63 Mon Sep 17 00:00:00 2001 From: PeucT Date: Fri, 24 Mar 2017 18:44:17 +0300 Subject: [PATCH 11/51] 2709 - 2711, and lvl 27 big, parts 1 - 11 --- .../task/task27/task2709/ConsumerTask.java | 23 +++ .../task/task27/task2709/ProducerTask.java | 26 ++++ .../task/task27/task2709/Solution.java | 16 ++ .../task/task27/task2709/TransferObject.java | 33 ++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 23 +++ .../javarush/task/task27/task2710/Mail.java | 13 ++ .../task/task27/task2710/MailServer.java | 26 ++++ .../javarush/task/task27/task2710/Person.java | 26 ++++ .../task/task27/task2710/Solution.java | 15 ++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 9 ++ .../task/task27/task2711/Solution.java | 25 +++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 9 ++ .../task/task30/task3008/Connection.java | 46 ++++++ .../task/task30/task3008/ConsoleHelper.java | 42 ++++++ .../task/task30/task3008/Message.java | 31 ++++ .../task/task30/task3008/MessageType.java | 13 ++ .../javarush/task/task30/task3008/Server.java | 121 +++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 142 ++++++++++++++++++ 18 files changed, 639 insertions(+) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2709/ConsumerTask.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2709/ProducerTask.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2709/Solution.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2709/TransferObject.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task27/task2709/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2710/Mail.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2710/MailServer.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2710/Person.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2710/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task27/task2710/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2711/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task27/task2711/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3008/Connection.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3008/ConsoleHelper.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3008/Message.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3008/MessageType.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3008/Server.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task30/task3008/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2709/ConsumerTask.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2709/ConsumerTask.java new file mode 100644 index 0000000..ce0eaaa --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2709/ConsumerTask.java @@ -0,0 +1,23 @@ +package com.javarush.task.task27.task2709; + +public class ConsumerTask implements Runnable { + private TransferObject transferObject; + protected volatile boolean stopped; + + public ConsumerTask(TransferObject transferObject) { + this.transferObject = transferObject; + new Thread(this, "ConsumerTask").start(); + } + + public void run() { + while (!stopped) { + synchronized (transferObject) { + transferObject.get(); + } + } + } + + public void stop() { + stopped = true; + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2709/ProducerTask.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2709/ProducerTask.java new file mode 100644 index 0000000..1fae1d3 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2709/ProducerTask.java @@ -0,0 +1,26 @@ +package com.javarush.task.task27.task2709; + +import java.util.concurrent.atomic.AtomicInteger; + +public class ProducerTask implements Runnable { + private TransferObject transferObject; + protected volatile boolean stopped; + static volatile AtomicInteger i = new AtomicInteger(0); + + public ProducerTask(TransferObject transferObject) { + this.transferObject = transferObject; + new Thread(this, "ProducerTask").start(); + } + + public void run() { + while (!stopped) { + synchronized (transferObject) { + transferObject.put(i.incrementAndGet()); + } + } + } + + public void stop() { + stopped = true; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2709/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2709/Solution.java new file mode 100644 index 0000000..0097c0f --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2709/Solution.java @@ -0,0 +1,16 @@ +package com.javarush.task.task27.task2709; + +/* +Producer–consumer +*/ +public class Solution { + public static void main(String args[]) throws InterruptedException { + TransferObject transferObject = new TransferObject(); + ProducerTask producerTask = new ProducerTask(transferObject); + ConsumerTask consumerTask = new ConsumerTask(transferObject); + + Thread.sleep(50); + producerTask.stop(); + consumerTask.stop(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2709/TransferObject.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2709/TransferObject.java new file mode 100644 index 0000000..e3261ea --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2709/TransferObject.java @@ -0,0 +1,33 @@ +package com.javarush.task.task27.task2709; + +public class TransferObject { + private int value; + protected volatile boolean isValuePresent = false; //use this variable + + public synchronized int get() { + while (!isValuePresent) { + try { + wait(); + } catch (InterruptedException e) { + } + } + System.out.println("Got: " + value); + isValuePresent = false; + notify(); + return value; + } + + public synchronized void put(int value) { + while (isValuePresent) { + try { + wait(); + } catch (InterruptedException e) { + } + } + this.value = value; + System.out.println("Put: " + value); + isValuePresent = true; + notify(); + + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2709/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2709/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..38f51f7 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2709/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,23 @@ +taskKey="com.javarush.task.task27.task2709" + +Producer–consumer + +В классе TransferObject расставь вызовы методов wait/notify/notifyAll, +чтобы обеспечить последовательное создание и получение объекта. +В методах run классов ConsumerTask и ProducerTask создай необходимые synchronized блоки. +Ожидаемый вывод: +... +Put: M +Got: M +Put: N +Got: N +Put: K +Got: K +... +где M, N, K - числа +Метод main не участвует в тестировании + +P.S. Всегда старайся использовать concurrent коллекции вместо ручной реализации wait/notify/notifyAll. +Задачи подобные этой позволяют лучше понять основы работы многопоточных приложений. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2710/Mail.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2710/Mail.java new file mode 100644 index 0000000..b1ca3a0 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2710/Mail.java @@ -0,0 +1,13 @@ +package com.javarush.task.task27.task2710; + +public class Mail { + private volatile String text; + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2710/MailServer.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2710/MailServer.java new file mode 100644 index 0000000..0886292 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2710/MailServer.java @@ -0,0 +1,26 @@ +package com.javarush.task.task27.task2710; + +public class MailServer implements Runnable { + private Mail mail; + + public MailServer(Mail mail) { + this.mail = mail; + } + + @Override + public void run() { + long beforeTime = System.currentTimeMillis(); + synchronized (mail) + { + try { + mail.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + //сделайте что-то тут - do something here + String name = Thread.currentThread().getName(); + long afterTime = System.currentTimeMillis(); + System.out.format("%s MailServer has got: [%s] in %d ms after start", name, mail.getText(), (afterTime - beforeTime)); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2710/Person.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2710/Person.java new file mode 100644 index 0000000..c27c6d5 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2710/Person.java @@ -0,0 +1,26 @@ +package com.javarush.task.task27.task2710; + +public class Person implements Runnable { + private final Mail mail; + + public Person(Mail mail) { + this.mail = mail; + } + + @Override + public void run() { + String name = Thread.currentThread().getName(); + try { + Thread.sleep(1000); + + //сделайте что-то тут - do something here + mail.setText("Person [" + name + "] has written an email 'AAA'"); + synchronized (mail){ + mail.notifyAll(); + } + //сделайте что-то тут - do something here + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2710/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2710/Solution.java new file mode 100644 index 0000000..919fe2e --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2710/Solution.java @@ -0,0 +1,15 @@ +package com.javarush.task.task27.task2710; + +/* +Расставьте wait-notify +*/ +public class Solution { + public static void main(String[] args) { + Mail mail = new Mail(); + Thread server = new Thread(new MailServer(mail)); + Thread amigo = new Thread(new Person(mail)); + + server.start(); + amigo.start(); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2710/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2710/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..9893566 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2710/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,9 @@ +taskKey="com.javarush.task.task27.task2710" + +Расставьте wait-notify + +Расставь wait-notify. +Пример вывода: +Thread-0 MailServer has got: [Person [Thread-1] has written an email 'AAA'] in 1001 ms after start + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2711/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2711/Solution.java new file mode 100644 index 0000000..c600f24 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2711/Solution.java @@ -0,0 +1,25 @@ +package com.javarush.task.task27.task2711; + +import java.util.concurrent.CountDownLatch; + +/* +CountDownLatch +*/ +public class Solution { + + CountDownLatch latch = new CountDownLatch(1); + + public void someMethod() throws InterruptedException { + latch.await(); + retrieveValue(); + } + + void retrieveValue() { + System.out.println("Value retrieved."); + latch.countDown(); + } + + public static void main(String[] args) { + + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2711/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2711/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..86b3222 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2711/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,9 @@ +taskKey="com.javarush.task.task27.task2711" + +CountDownLatch + +Дана стандартная реализация методологии wait-notify. +Почитай про CountDownLatch и перепиши тело метода someMethod используя поле latch. +Весь лишний код удали из класса. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/Connection.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/Connection.java new file mode 100644 index 0000000..3aa1de7 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/Connection.java @@ -0,0 +1,46 @@ +package com.javarush.task.task30.task3008; + +import java.io.Closeable; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.net.Socket; +import java.net.SocketAddress; + +/** + * Created by ArchMage on 24.03.17. + */ +public class Connection implements Closeable{ + private final Socket socket; + private final ObjectOutputStream out; + private final ObjectInputStream in; + + public Connection(Socket socket) throws IOException { + this.socket = socket; + out = new ObjectOutputStream(socket.getOutputStream()); + in = new ObjectInputStream(socket.getInputStream()); + } + + public void send(Message message) throws IOException{ + synchronized (out) { + out.writeObject(message); + } + } + + public Message receive() throws IOException, ClassNotFoundException{ + synchronized (in){ + return (Message) in.readObject(); + } + } + + public SocketAddress getRemoteSocketAddress(){ + return socket.getRemoteSocketAddress(); + } + + @Override + public void close() throws IOException { + socket.close(); + in.close(); + out.close(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/ConsoleHelper.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/ConsoleHelper.java new file mode 100644 index 0000000..759faeb --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/ConsoleHelper.java @@ -0,0 +1,42 @@ +package com.javarush.task.task30.task3008; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +/** + * Created by ArchMage on 24.03.17. + */ +public class ConsoleHelper { + private static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + + public static void writeMessage(String message){ + System.out.println(message); + } + + public static String readString(){ + String line = null; + while (true) { + try { + line = reader.readLine(); + break; + } catch (IOException e) { + writeMessage("Произошла ошибка при попытке ввода текста. Попробуйте еще раз."); + } + } + + return line; + } + + public static int readInt(){ + int number = 0; + try { + number = Integer.parseInt(readString()); + } catch (NumberFormatException e) { + writeMessage("Произошла ошибка при попытке ввода текста. Попробуйте еще раз."); + number = Integer.parseInt(readString()); + } + + return number; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/Message.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/Message.java new file mode 100644 index 0000000..dbdc0eb --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/Message.java @@ -0,0 +1,31 @@ +package com.javarush.task.task30.task3008; + +import java.io.Serializable; + +/** + * Created by ArchMage on 24.03.17. + */ +public class Message implements Serializable { + private final MessageType type; + private final String data; + + public MessageType getType() { + return type; + } + + public String getData() { + return data; + } + + public Message(MessageType type, String data) { + this.type = type; + this.data = data; + } + + public Message(MessageType type) { + this.type = type; + this.data = null; + } + + +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/MessageType.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/MessageType.java new file mode 100644 index 0000000..505c792 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/MessageType.java @@ -0,0 +1,13 @@ +package com.javarush.task.task30.task3008; + +/** + * Created by ArchMage on 24.03.17. + */ +public enum MessageType { + NAME_REQUEST, + USER_NAME, + NAME_ACCEPTED, + TEXT, + USER_ADDED, + USER_REMOVED +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/Server.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/Server.java new file mode 100644 index 0000000..54db1e1 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/Server.java @@ -0,0 +1,121 @@ +package com.javarush.task.task30.task3008; + + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + + +/** + * Created by ArchMage on 24.03.17. + */ +public class Server { + private static Map connectionMap = new ConcurrentHashMap<>(); + + private static class Handler extends Thread { + Socket socket; + + public Handler(Socket socket) { + this.socket = socket; + } + + private String serverHandshake(Connection connection) throws IOException { + String name = null; + boolean isAccepted = false; + while (!isAccepted) { + Message output = new Message(MessageType.NAME_REQUEST); + connection.send(output); + Message input = null; + try { + input = connection.receive(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + if (input.getType().equals(MessageType.USER_NAME)) { + name = input.getData(); + if ((!name.isEmpty()) && (connectionMap.get(name) == null)) { + connectionMap.put(name, connection); + connection.send(new Message(MessageType.NAME_ACCEPTED)); + isAccepted = true; + } + } + } + return name; + } + + private void sendListOfUsers(Connection connection, String userName) throws IOException{ + for (Map.Entry entry: connectionMap.entrySet()){ + String name = entry.getKey(); + if (!userName.equals(name)) { + connection.send(new Message(MessageType.USER_ADDED, name)); + } + } + } + + private void serverMainLoop(Connection connection, String userName) throws IOException, ClassNotFoundException { + while (true){ + Message message = connection.receive(); + if (MessageType.TEXT.equals(message.getType())) { + sendBroadcastMessage(new Message(MessageType.TEXT, userName + ": " + message.getData())); + } else { ConsoleHelper.writeMessage("Not a message"); } + } + } + + public void run(){ + String userName = null; + if (socket != null && socket.getRemoteSocketAddress() != null) { + ConsoleHelper.writeMessage("Established a new connection to a remote socket address: " + socket.getRemoteSocketAddress()); + } + + //ConsoleHelper.writeMessage("Remote connection with address" + socket.getRemoteSocketAddress() + " established!"); + try (Connection connection = new Connection(socket);) + { + ConsoleHelper.writeMessage("Connection with port " + connection.getRemoteSocketAddress()); + userName = serverHandshake(connection); + sendBroadcastMessage(new Message(MessageType.USER_ADDED, userName)); + sendListOfUsers(connection, userName); + serverMainLoop(connection, userName); + } catch (IOException e) { + ConsoleHelper.writeMessage(e.getMessage()); + } catch (ClassNotFoundException e) { + ConsoleHelper.writeMessage(e.getMessage()); + } finally { + if ( userName != null) { + connectionMap.remove(userName); + sendBroadcastMessage(new Message(MessageType.USER_REMOVED, userName)); + ConsoleHelper.writeMessage("Remote connection closed successfully"); + } + } + } + + } + + public static void sendBroadcastMessage(Message message){ + for (Map.Entry entry: connectionMap.entrySet()){ + try { + entry.getValue().send(message); + } catch (IOException e) { + ConsoleHelper.writeMessage("Cannot send a message"); + } + } + } + + public static void main(String[] args){ + //int port = ConsoleHelper.readInt(); + try( + ServerSocket serverSocket = new ServerSocket(ConsoleHelper.readInt()); + ) + { + ConsoleHelper.writeMessage("Server started!"); + while (true) { + Socket incomeSocket = serverSocket.accept(); + new Handler(incomeSocket).start(); + } + + } catch (IOException e){ + ConsoleHelper.writeMessage(e.getMessage()); + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..f725ac3 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,142 @@ +taskKey="com.javarush.task.task30.task3008.big11" + +Чат (11) + +Пришло время написать главный метод класса Handler, который будет вызывать все +вспомогательные методы, написанные ранее. Реализуем метод void run() в классе Handler. + +Он должен: +1) Выводить сообщение, что установлено новое соединение с удаленным +адресом, который можно получить с помощью метода getRemoteSocketAddress. +2) Создавать Connection, используя поле socket. +3) Вызывать метод, реализующий рукопожатие с клиентом, сохраняя имя нового +клиента. +4) Рассылать всем участникам чата информацию об имени присоединившегося +участника (сообщение с типом USER_ADDED). Подумай, какой метод подойдет для +этого лучше всего. +5) Сообщать новому участнику о существующих участниках. +6) Запускать главный цикл обработки сообщений сервером. +7) Обеспечить закрытие соединения при возникновении исключения. +8) Отловить все исключения типа IOException и ClassNotFoundException, вывести в +консоль информацию, что произошла ошибка при обмене данными с удаленным +адресом. +9) После того как все исключения обработаны, если п.11.3 отработал и возвратил +нам имя, мы должны удалить запись для этого имени из connectionMap и разослать +всем остальным участникам сообщение с типом USER_REMOVED и сохраненным +именем. +10) Последнее, что нужно сделать в методе run() – вывести сообщение, +информирующее что соединение с удаленным адресом закрыто. + +Наш сервер полностью готов. Попробуй его запустить. + + +Чат (10) + +Этап третий – главный цикл обработки сообщений сервером. +Добавь приватный метод void serverMainLoop(Connection connection, String userName) throws +IOException, ClassNotFoundException, где значение параметров такое же, как и у метода +sendListOfUsers. + +Он должен: +1) Принимать сообщение клиента +2) Если принятое сообщение – это текст (тип TEXT), то формировать новое +текстовое сообщение путем конкатенации: имени клиента, двоеточия, пробела и +текста сообщения. Например, если мы получили сообщение с текстом "привет чат" от +пользователя "Боб", то нужно сформировать сообщение "Боб: привет чат". +3) Отправлять сформированное сообщение всем клиентам с помощью метода +sendBroadcastMessage. +4) Если принятое сообщение не является текстом, вывести сообщение об ошибке +5) Организовать бесконечный цикл, внутрь которого перенести функционал +пунктов 10.1-10.4. + + + +Чат (9) + +Этап второй, но не менее важный – отправка клиенту (новому участнику) информации об +остальных клиентах (участниках) чата. + +Для этого: +1) Добавь приватный метод void sendListOfUsers(Connection connection, String userName) throws +IOException, где connection – соединение с участником, которому будем слать +информацию, а userName – его имя. Метод должен: +2) Пройтись по connectionMap. +3) У каждого элемента из п.2 получить имя клиента, сформировать команду с типом +USER_ADDED и полученным именем. +4) Отправить сформированную команду через connection. +5) Команду с типом USER_ADDED и именем равным userName отправлять не нужно, +пользователь и так имеет информацию о себе. + + + +Чат (8) + +Класс Handler должен реализовывать протокол общения с клиентом. +Выделим из протокола отдельные этапы и реализуем их с помощью отдельных методов: +Этап первый – это этап рукопожатия (знакомства сервера с клиентом). Реализуем его с +помощью приватного метода String serverHandshake(Connection connection) throws IOException, +ClassNotFoundException. Метод в качестве параметра принимает соединение connection, а +возвращает имя нового клиента. + +Реализация метода должна: +1) Сформировать и отправить команду запроса имени пользователя +2) Получить ответ клиента +3) Проверить, что получена команда с именем пользователя +4) Достать из ответа имя, проверить, что оно не пустое и пользователь с таким именем +еще не подключен (используй connectionMap) +5) Добавить нового пользователя и соединение с ним в connectionMap +6) Отправить клиенту команду информирующую, что его имя принято +7) Если какая-то проверка не прошла, заново запросить имя клиента +8) Вернуть принятое имя в качестве возвращаемого значения + + + +Чат (7) + +Т.к. сервер может одновременно работать с несколькими клиентами, нам понадобится +метод для отправки сообщения сразу всем. + +Добавь в класс Server: +1) Статическое поле Map connectionMap, где ключом будет имя +клиента, а значением - соединение с ним. +2) Инициализацию поля из п.7.1 с помощью подходящего Map из библиотеки +java.util.concurrent, т.к. работа с этим полем будет происходить из разных потоков и +нужно обеспечить потокобезопасность. +3) Статический метод void sendBroadcastMessage(Message message), который должен +отправлять сообщение message всем соединениям из connectionMap. Если при +отправке сообщение произойдет исключение IOException, нужно отловить его и +сообщить пользователю, что не смогли отправить сообщение. + + + +Чат (6) + +Приступим к самому важному – написанию класса Server. Сервер должен поддерживать +множество соединений с разными клиентами одновременно. Это можно реализовать с +помощью следующего алгоритма: +- Сервер создает серверное сокетное соединение. +- В цикле ожидает, когда какой-то клиент подключится к сокету. +- Создает новый поток обработчик Handler, в котором будет происходить обмен +сообщениями с клиентом. +- Ожидает следующее соединение. + +Добавь: +1) В класс Server приватный статический вложенный класс Handler, унаследованный от +Thread. +2) В класс Handler поле socket типа Socket. +3) В класс Handler конструктор, принимающий в качестве параметра Socket и +инициализирующий им соответствующее поле класса. +4) Метод main класса Server, должен: +а) Запрашивать порт сервера, используя ConsoleHelper. +б) Создавать серверный сокет java.net.ServerSocket, используя порт из предыдущего пункта. +в) Выводить сообщение, что сервер запущен. +г) В бесконечном цикле слушать и принимать входящие сокетные соединения только что созданного +серверного сокета. +д) Создавать и запускать новый поток Handler, передавая в конструктор сокет из предыдущего пункта. +е) После создания потока обработчика Handler переходить на новый шаг цикла. +ж) Предусмотреть закрытие серверного сокета в случае возникновения исключения. +з) Если исключение Exception все же произошло, поймать его и вывести сообщение +об ошибке. + + + From 052d961182556115768446e8a353b0d511715ae7 Mon Sep 17 00:00:00 2001 From: PeucT Date: Mon, 27 Mar 2017 18:14:06 +0400 Subject: [PATCH 12/51] 2711 correction --- .../src/com/javarush/task/task27/task2711/Solution.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2711/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2711/Solution.java index c600f24..20213e5 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2711/Solution.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2711/Solution.java @@ -10,8 +10,8 @@ public class Solution { CountDownLatch latch = new CountDownLatch(1); public void someMethod() throws InterruptedException { - latch.await(); retrieveValue(); + latch.await(); } void retrieveValue() { From 55cab67f811df38ef3cfdbe50de69b8985225d71 Mon Sep 17 00:00:00 2001 From: PeucT Date: Mon, 27 Mar 2017 18:14:58 +0400 Subject: [PATCH 13/51] Full big 3008 task --- .../task30/task3008/client/BotClient.java | 84 +++++ .../task/task30/task3008/client/Client.java | 148 ++++++++ .../task3008/client/ClientGuiController.java | 74 ++++ .../task3008/client/ClientGuiModel.java | 33 ++ .../task30/task3008/client/ClientGuiView.java | 106 ++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 325 ++++++++++-------- 6 files changed, 631 insertions(+), 139 deletions(-) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/BotClient.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/Client.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/ClientGuiController.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/ClientGuiModel.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/ClientGuiView.java diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/BotClient.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/BotClient.java new file mode 100644 index 0000000..4afe136 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/BotClient.java @@ -0,0 +1,84 @@ +package com.javarush.task.task30.task3008.client; + +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +/** + * Created by ArchMage on 27.03.17. + */ +public class BotClient extends Client{ + public class BotSocketThread extends SocketThread{ + @Override + protected void clientMainLoop() throws IOException, ClassNotFoundException { + sendTextMessage("Привет чатику. Я бот. Понимаю команды: дата, день, месяц, год, время, час, минуты, секунды."); + super.clientMainLoop(); + } + + @Override + protected void processIncomingMessage(String message) { + super.processIncomingMessage(message); + String command = null; + String name = null; + SimpleDateFormat format = null; + if (message != null && message.contains(":")) { + int index = message.indexOf(": "); + if (index >= 0){ + name = message.substring(0, index ); + command = message.substring(index + 2); + switch (command) { + case "дата": + format = new SimpleDateFormat("d.MM.YYYY"); + break; + case "день": + format = new SimpleDateFormat("d"); + break; + case "месяц": + format = new SimpleDateFormat("MM"); + break; + case "год": + format = new SimpleDateFormat("YYYY"); + break; + case "время": + format = new SimpleDateFormat("H:mm:ss"); + break; + case "час": + format = new SimpleDateFormat("H"); + break; + case "минуты": + format = new SimpleDateFormat("m"); + break; + case "секунды": + format = new SimpleDateFormat("s"); + break; + } + Date currentDate = Calendar.getInstance().getTime(); + if (format != null && name != null) { + sendTextMessage(String.format("Информация для %s: %s", name, format.format(currentDate))); + } + } + } + } + } + + @Override + protected SocketThread getSocketThread() { + return new BotSocketThread(); + } + + @Override + protected boolean shouldSendTextFromConsole() { + return false; + } + + @Override + protected String getUserName() { + return "date_bot_" + (int) (Math.random() * 100); + } + + public static void main(String[] args){ + BotClient botClient = new BotClient(); + botClient.run(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/Client.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/Client.java new file mode 100644 index 0000000..d15677f --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/Client.java @@ -0,0 +1,148 @@ +package com.javarush.task.task30.task3008.client; + +import com.javarush.task.task30.task3008.Connection; +import com.javarush.task.task30.task3008.ConsoleHelper; +import com.javarush.task.task30.task3008.Message; +import com.javarush.task.task30.task3008.MessageType; + +import java.io.IOException; +import java.net.Socket; + +/** + * Created by ArchMage on 27.03.17. + */ +public class Client{ + protected Connection connection; + private volatile boolean clientConnected = false; + + public class SocketThread extends Thread{ + protected void processIncomingMessage(String message){ + ConsoleHelper.writeMessage(message); + } + + protected void informAboutAddingNewUser(String userName){ + ConsoleHelper.writeMessage("User " + userName + " is connected"); + } + + protected void informAboutDeletingNewUser(String userName){ + ConsoleHelper.writeMessage("User " + userName + " has left the conversation"); + } + + protected void notifyConnectionStatusChanged(boolean clientConnected){ + Client.this.clientConnected = clientConnected; + synchronized (Client.this){ + Client.this.notifyAll(); + } + } + + protected void clientHandshake() throws IOException, ClassNotFoundException{ + while (true){ + Message message = connection.receive(); + if (MessageType.NAME_REQUEST.equals(message.getType())) { + connection.send(new Message(MessageType.USER_NAME, getUserName())); + } else if (MessageType.NAME_ACCEPTED.equals(message.getType())) { + notifyConnectionStatusChanged(true); + break; + } else { + throw new IOException("Unexpected MessageType"); + } + + } + } + + protected void clientMainLoop() throws IOException, ClassNotFoundException { + while (true){ + Message message = connection.receive(); + if (MessageType.TEXT.equals(message.getType())) { + processIncomingMessage(message.getData()); + } else if (MessageType.USER_ADDED.equals(message.getType())) { + informAboutAddingNewUser(message.getData()); + } else if (MessageType.USER_REMOVED.equals(message.getType())) { + informAboutDeletingNewUser(message.getData()); + } else { + throw new IOException("Unexpected MessageType"); + } + + } + } + + public void run(){ + String ipAddress = getServerAddress(); + int port = getServerPort(); + try { + Socket socket = new Socket(ipAddress, port); + connection = new Connection(socket); + clientHandshake(); + clientMainLoop(); + } catch (IOException | ClassNotFoundException e) { + notifyConnectionStatusChanged(false); + } + } + } + + protected String getServerAddress(){ + System.out.println("Enter server ip address"); + return ConsoleHelper.readString(); + } + + protected int getServerPort(){ + System.out.println("Enter server port number"); + return ConsoleHelper.readInt(); + } + + protected String getUserName(){ + System.out.println("Enter your name"); + return ConsoleHelper.readString(); + } + + protected boolean shouldSendTextFromConsole(){ + return true; + } + + protected SocketThread getSocketThread(){ + return new SocketThread(); + } + + protected void sendTextMessage(String text){ + try { + connection.send(new Message(MessageType.TEXT ,text)); + } catch (IOException e) { + clientConnected = false; + ConsoleHelper.writeMessage(e.getMessage()); + } + } + + public void run(){ + SocketThread socketThread = getSocketThread(); + socketThread.setDaemon(true); + socketThread.start(); + synchronized (this){ + try { + wait(); + if (clientConnected) { + ConsoleHelper.writeMessage("Соединение установлено. Для выхода наберите команду ‘exit’."); + String message = null; + while (clientConnected){ + message = ConsoleHelper.readString(); + if ("exit".equals(message)) { break; } + if (shouldSendTextFromConsole()) { + sendTextMessage(message); + } + } + + } else { + ConsoleHelper.writeMessage("Произошла ошибка во время работы клиента."); + } + } catch (InterruptedException e) { + ConsoleHelper.writeMessage(e.getMessage()); + return; + } + } + } + + + public static void main(String[] args){ + Client client = new Client(); + client.run(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/ClientGuiController.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/ClientGuiController.java new file mode 100644 index 0000000..32d151d --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/ClientGuiController.java @@ -0,0 +1,74 @@ +package com.javarush.task.task30.task3008.client; + +/** + * Created by ArchMage on 27.03.17. + */ +public class ClientGuiController extends Client { + private ClientGuiModel model = new ClientGuiModel(); + private ClientGuiView view = new ClientGuiView(this); + + public ClientGuiController() { + + } + + public ClientGuiModel getModel(){ + return model; + } + + public class GuiSocketThread extends SocketThread{ + @Override + protected void processIncomingMessage(String message) { + model.setNewMessage(message); + view.refreshMessages(); + } + + @Override + protected void informAboutAddingNewUser(String userName) { + model.addUser(userName); + view.refreshUsers(); + } + + @Override + protected void informAboutDeletingNewUser(String userName) { + model.deleteUser(userName); + view.refreshUsers(); + } + + @Override + protected void notifyConnectionStatusChanged(boolean clientConnected) { + view.notifyConnectionStatusChanged(clientConnected); + } + + } + + @Override + protected SocketThread getSocketThread() { + return new GuiSocketThread(); + } + + @Override + public void run() { + SocketThread socketThread = getSocketThread(); + socketThread.run(); + } + + @Override + protected String getServerAddress() { + return view.getServerAddress(); + } + + @Override + protected int getServerPort() { + return view.getServerPort(); + } + + @Override + protected String getUserName() { + return view.getUserName(); + } + + public static void main(String[] args){ + ClientGuiController controller = new ClientGuiController(); + controller.run(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/ClientGuiModel.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/ClientGuiModel.java new file mode 100644 index 0000000..f9a61f0 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/ClientGuiModel.java @@ -0,0 +1,33 @@ +package com.javarush.task.task30.task3008.client; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +/** + * Created by ArchMage on 27.03.17. + */ +public class ClientGuiModel { + private final Set allUserNames = new HashSet(); + private String newMessage; + + public Set getAllUserNames() { + return Collections.unmodifiableSet(allUserNames); + } + + public String getNewMessage() { + return newMessage; + } + + public void setNewMessage(String newMessage) { + this.newMessage = newMessage; + } + + public void addUser(String newUserName){ + allUserNames.add(newUserName); + } + + public void deleteUser(String userName){ + allUserNames.remove(userName); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/ClientGuiView.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/ClientGuiView.java new file mode 100644 index 0000000..aee2ccd --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/ClientGuiView.java @@ -0,0 +1,106 @@ +package com.javarush.task.task30.task3008.client; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class ClientGuiView { + private final ClientGuiController controller; + + private JFrame frame = new JFrame("Чат"); + private JTextField textField = new JTextField(50); + private JTextArea messages = new JTextArea(10, 50); + private JTextArea users = new JTextArea(10, 10); + + public ClientGuiView(ClientGuiController controller) { + this.controller = controller; + initView(); + } + + private void initView() { + textField.setEditable(false); + messages.setEditable(false); + users.setEditable(false); + + frame.getContentPane().add(textField, BorderLayout.NORTH); + frame.getContentPane().add(new JScrollPane(messages), BorderLayout.WEST); + frame.getContentPane().add(new JScrollPane(users), BorderLayout.EAST); + frame.pack(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + + textField.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + controller.sendTextMessage(textField.getText()); + textField.setText(""); + } + }); + } + + public String getServerAddress() { + return JOptionPane.showInputDialog( + frame, + "Введите адрес сервера:", + "Конфигурация клиента", + JOptionPane.QUESTION_MESSAGE); + } + + public int getServerPort() { + while (true) { + String port = JOptionPane.showInputDialog( + frame, + "Введите порт сервера:", + "Конфигурация клиента", + JOptionPane.QUESTION_MESSAGE); + try { + return Integer.parseInt(port.trim()); + } catch (Exception e) { + JOptionPane.showMessageDialog( + frame, + "Был введен некорректный порт сервера. Попробуйте еще раз.", + "Конфигурация клиента", + JOptionPane.ERROR_MESSAGE); + } + } + } + + public String getUserName() { + return JOptionPane.showInputDialog( + frame, + "Введите ваше имя:", + "Конфигурация клиента", + JOptionPane.QUESTION_MESSAGE); + } + + public void notifyConnectionStatusChanged(boolean clientConnected) { + textField.setEditable(clientConnected); + if (clientConnected) { + JOptionPane.showMessageDialog( + frame, + "Соединение с сервером установлено", + "Чат", + JOptionPane.INFORMATION_MESSAGE); + } else { + JOptionPane.showMessageDialog( + frame, + "Клиент не подключен к серверу", + "Чат", + JOptionPane.ERROR_MESSAGE); + } + + } + + public void refreshMessages() { + messages.append(controller.getModel().getNewMessage() + "\n"); + } + + public void refreshUsers() { + ClientGuiModel model = controller.getModel(); + StringBuilder sb = new StringBuilder(); + for (String userName : model.getAllUserNames()) { + sb.append(userName).append("\n"); + } + users.setText(sb.toString()); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" index f725ac3..84f3a87 100644 --- "a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -1,142 +1,189 @@ -taskKey="com.javarush.task.task30.task3008.big11" - -Чат (11) - -Пришло время написать главный метод класса Handler, который будет вызывать все -вспомогательные методы, написанные ранее. Реализуем метод void run() в классе Handler. - -Он должен: -1) Выводить сообщение, что установлено новое соединение с удаленным -адресом, который можно получить с помощью метода getRemoteSocketAddress. -2) Создавать Connection, используя поле socket. -3) Вызывать метод, реализующий рукопожатие с клиентом, сохраняя имя нового -клиента. -4) Рассылать всем участникам чата информацию об имени присоединившегося -участника (сообщение с типом USER_ADDED). Подумай, какой метод подойдет для -этого лучше всего. -5) Сообщать новому участнику о существующих участниках. -6) Запускать главный цикл обработки сообщений сервером. -7) Обеспечить закрытие соединения при возникновении исключения. -8) Отловить все исключения типа IOException и ClassNotFoundException, вывести в -консоль информацию, что произошла ошибка при обмене данными с удаленным -адресом. -9) После того как все исключения обработаны, если п.11.3 отработал и возвратил -нам имя, мы должны удалить запись для этого имени из connectionMap и разослать -всем остальным участникам сообщение с типом USER_REMOVED и сохраненным -именем. -10) Последнее, что нужно сделать в методе run() – вывести сообщение, -информирующее что соединение с удаленным адресом закрыто. - -Наш сервер полностью готов. Попробуй его запустить. - - -Чат (10) - -Этап третий – главный цикл обработки сообщений сервером. -Добавь приватный метод void serverMainLoop(Connection connection, String userName) throws -IOException, ClassNotFoundException, где значение параметров такое же, как и у метода -sendListOfUsers. - -Он должен: -1) Принимать сообщение клиента -2) Если принятое сообщение – это текст (тип TEXT), то формировать новое -текстовое сообщение путем конкатенации: имени клиента, двоеточия, пробела и -текста сообщения. Например, если мы получили сообщение с текстом "привет чат" от -пользователя "Боб", то нужно сформировать сообщение "Боб: привет чат". -3) Отправлять сформированное сообщение всем клиентам с помощью метода -sendBroadcastMessage. -4) Если принятое сообщение не является текстом, вывести сообщение об ошибке -5) Организовать бесконечный цикл, внутрь которого перенести функционал -пунктов 10.1-10.4. - - - -Чат (9) - -Этап второй, но не менее важный – отправка клиенту (новому участнику) информации об -остальных клиентах (участниках) чата. - -Для этого: -1) Добавь приватный метод void sendListOfUsers(Connection connection, String userName) throws -IOException, где connection – соединение с участником, которому будем слать -информацию, а userName – его имя. Метод должен: -2) Пройтись по connectionMap. -3) У каждого элемента из п.2 получить имя клиента, сформировать команду с типом -USER_ADDED и полученным именем. -4) Отправить сформированную команду через connection. -5) Команду с типом USER_ADDED и именем равным userName отправлять не нужно, -пользователь и так имеет информацию о себе. - - - -Чат (8) - -Класс Handler должен реализовывать протокол общения с клиентом. -Выделим из протокола отдельные этапы и реализуем их с помощью отдельных методов: -Этап первый – это этап рукопожатия (знакомства сервера с клиентом). Реализуем его с -помощью приватного метода String serverHandshake(Connection connection) throws IOException, -ClassNotFoundException. Метод в качестве параметра принимает соединение connection, а -возвращает имя нового клиента. - -Реализация метода должна: -1) Сформировать и отправить команду запроса имени пользователя -2) Получить ответ клиента -3) Проверить, что получена команда с именем пользователя -4) Достать из ответа имя, проверить, что оно не пустое и пользователь с таким именем -еще не подключен (используй connectionMap) -5) Добавить нового пользователя и соединение с ним в connectionMap -6) Отправить клиенту команду информирующую, что его имя принято -7) Если какая-то проверка не прошла, заново запросить имя клиента -8) Вернуть принятое имя в качестве возвращаемого значения - - - -Чат (7) - -Т.к. сервер может одновременно работать с несколькими клиентами, нам понадобится -метод для отправки сообщения сразу всем. - -Добавь в класс Server: -1) Статическое поле Map connectionMap, где ключом будет имя -клиента, а значением - соединение с ним. -2) Инициализацию поля из п.7.1 с помощью подходящего Map из библиотеки -java.util.concurrent, т.к. работа с этим полем будет происходить из разных потоков и -нужно обеспечить потокобезопасность. -3) Статический метод void sendBroadcastMessage(Message message), который должен -отправлять сообщение message всем соединениям из connectionMap. Если при -отправке сообщение произойдет исключение IOException, нужно отловить его и -сообщить пользователю, что не смогли отправить сообщение. - - - -Чат (6) - -Приступим к самому важному – написанию класса Server. Сервер должен поддерживать -множество соединений с разными клиентами одновременно. Это можно реализовать с -помощью следующего алгоритма: -- Сервер создает серверное сокетное соединение. -- В цикле ожидает, когда какой-то клиент подключится к сокету. -- Создает новый поток обработчик Handler, в котором будет происходить обмен -сообщениями с клиентом. -- Ожидает следующее соединение. - -Добавь: -1) В класс Server приватный статический вложенный класс Handler, унаследованный от -Thread. -2) В класс Handler поле socket типа Socket. -3) В класс Handler конструктор, принимающий в качестве параметра Socket и -инициализирующий им соответствующее поле класса. -4) Метод main класса Server, должен: -а) Запрашивать порт сервера, используя ConsoleHelper. -б) Создавать серверный сокет java.net.ServerSocket, используя порт из предыдущего пункта. -в) Выводить сообщение, что сервер запущен. -г) В бесконечном цикле слушать и принимать входящие сокетные соединения только что созданного -серверного сокета. -д) Создавать и запускать новый поток Handler, передавая в конструктор сокет из предыдущего пункта. -е) После создания потока обработчика Handler переходить на новый шаг цикла. -ж) Предусмотреть закрытие серверного сокета в случае возникновения исключения. -з) Если исключение Exception все же произошло, поймать его и вывести сообщение -об ошибке. +taskKey="com.javarush.task.task30.task3008.big22" + +Чат (22) + +Итак, подведем итог: +• Ты написал сервер для обмена текстовыми сообщениями. +• Ты написал консольный клиент, который умеет подключаться к серверу и +обмениваться сообщениями с другими участниками. +• Ты написал бот клиента, который может принимать запросы и отправлять данные о +текущей дате и времени. +• Ты написал клиента для чата с графическим интерфейсом. + +Что можно добавить или улучшить: +• Можно добавить поддержку приватных сообщений (когда сообщение отправляется не +всем, а какому-то конкретному участнику). +• Можно расширить возможности бота, попробовать научить его отвечать на +простейшие вопросы или время от времени отправлять шутки. +• Добавить возможность пересылки файлов между пользователями. +• Добавить контекстное меню в графический клиент, например, для отправки +приватного сообщения кому-то из списка участников. +• Добавить раскраску сообщений в графическом клиенте в зависимости от отправителя. +• Добавить блокировку сервером участников за что-либо, например, ненормативную +лексику в сообщениях. +• Добавить еще миллион фич и полезностей! + +Ты научился: +• Работать с сокетами. +• Пользоваться сериализацией и десериализацией. +• Создавать многопоточные приложения, синхронизировать их, применять модификатор +volatile, пользоваться классами из библиотеки java.util.concurrent. +• Применять паттерн MVC. +• Использовать внутренние и вложенные классы. +• Работать с библиотекой Swing. +• Применять классы Calendar и SimpleDateFormat. + +Так держать! + + +Чат (21) + +У меня есть отличнейшая новость для тебя. Компонент представление (View) уже готов. Я +добавил класс ClientGuiView. Он использует библиотеку javax.swing. Ты должен как следует +разобраться в каждой строчке этого класса. Если тебе все понятно – это замечательно, если +нет – обязательно найди ответы на свои вопросы с помощью дебага, документации или +поиска в Интернет. + +Осталось написать компонент контроллер (Controller): +1) Создай класс ClientGuiController унаследованный от Client. +2) Создай и инициализируй поле, отвечающее за модель ClientGuiModel +model. +3) Создай и инициализируй поле, отвечающее за представление ClientGuiView +view. Подумай, что нужно передать в конструктор при инициализации объекта. +4) Добавь внутренний класс GuiSocketThread унаследованный от SocketThread. +Класс GuiSocketThread должен быть публичным. В нем переопредели следующие +методы: +а) void processIncomingMessage(String message) – должен устанавливать новое +сообщение у модели и вызывать обновление вывода сообщений у +представления. +б) void informAboutAddingNewUser(String userName) – должен добавлять нового +пользователя в модель и вызывать обновление вывода пользователей у +отображения. +в) void informAboutDeletingNewUser(String userName) – должен удалять +пользователя из модели и вызывать обновление вывода пользователей у +отображения. +г) void notifyConnectionStatusChanged(boolean clientConnected) – должен вызывать +аналогичный метод у представления. +5) Переопредели методы в классе ClientGuiController: +а) SocketThread getSocketThread() – должен создавать и возвращать объект типа +GuiSocketThread. +б) void run() – должен получать объект SocketThread через метод getSocketThread() +и вызывать у него метод run(). Разберись, почему нет необходимости вызывать +метод run в отдельном потоке, как мы это делали для консольного клиента. +в) getServerAddress(), getServerPort(),getUserName(). Они должны вызывать +одноименные методы из представления (view). +6) Реализуй метод ClientGuiModel getModel(), который должен возвращать модель. +7) Реализуй метод main(), который должен создавать новый объект +ClientGuiController и вызывать у него метод run(). +Запусти клиента с графическим окном, нескольких консольных клиентов и убедись, что +все работает корректно. + + + +Чат (20) + +Консольный клиент мы уже реализовали, чат бота тоже сделали, почему бы не сделать +клиента с графическим интерфейсом? Он будет так же работать с нашим сервером, но +иметь графическое окно, кнопки и т.д. +Итак, приступим. При написании графического клиента будет очень уместно воспользоваться +паттерном MVC (Model-View-Controller). Ты уже должен был с ним сталкиваться, если необходимо, +освежи свои знания про MVC с помощью Интернет. В нашей задаче самая простая реализация +будет у класса, отвечающего за модель (Model). + +Давай напишем его: +1) Создай класс ClientGuiModel в пакете client. Все классы клиента должны быть созданы в этом +пакете. +2) Добавь в него множество(set) строк в качестве final поля allUserNames. +В нем будет храниться список всех участников чата. Проинициализируй его. +3) Добавь поле String newMessage, в котором будет храниться новое сообщение, +которое получил клиент. +4) Добавь геттер для allUserNames, запретив модифицировать возвращенное +множество. Разберись, как это можно сделать с помощью метода класса Collections. +5) Добавь сеттер и геттер для поля newMessage. +6) Добавь метод void addUser(String newUserName), который должен добавлять +имя участника во множество, хранящее всех участников. +7) Добавь метод void deleteUser(String userName), который будет удалять имя +участника из множества. + + + +Чат (19) + +Сейчас будем реализовывать класс BotSocketThread, вернее переопределять некоторые +его методы, весь основной функционал он уже унаследовал от SocketThread. + +1) Переопредели метод clientMainLoop(): +а) С помощью метода sendTextMessage() отправь сообщение с текстом +"Привет чатику. Я бот. Понимаю команды: дата, день, месяц, год, время, час, минуты, секунды." +б) Вызови реализацию clientMainLoop() родительского класса. +2) Переопредели метод processIncomingMessage(String message). Он должен +следующим образом обрабатывать входящие сообщения: +а) Вывести в консоль текст полученного сообщения message. +б) Получить из message имя отправителя и текст сообщения. Они разделены ": ". +в) Отправить ответ в зависимости от текста принятого сообщения. Если текст +сообщения: +"дата" – отправить сообщение содержащее текущую дату в формате "d.MM.YYYY"; +"день" – в формате"d"; +"месяц" - "MMMM"; +"год" - "YYYY"; +"время" - "H:mm:ss"; +"час" - "H"; +"минуты" - "m"; +"секунды" - "s". +Указанный выше формат используй для создания объекта SimpleDateFormat. Для +получения текущей даты необходимо использовать класс Calendar и метод +getTime(). +Ответ должен содержать имя клиента, который прислал запрос и ожидает ответ, +например, если Боб отправил запрос "время", мы должны отправить ответ +"Информация для Боб: 12:30:47". +Наш бот готов. Запусти сервер, запусти бота, обычного клиента и убедись, что все работает правильно. +Помни, что message бывают разных типов и не всегда содержат ":" + + + +Чат (18) + +Иногда бывают моменты, что не находится достойного собеседника. Не общаться же с +самим собой :). Давай напишем бота, который будет представлять собой клиента, который +автоматически будет отвечать на некоторые команды. Проще всего реализовать бота, +который сможет отправлять текущее время или дату, когда его кто-то об этом попросит. + +С него и начнем: +1) Создай новый класс BotClient в пакете client. Он должен быть унаследован от +Client. +2) В классе BotClient создай внутренний класс BotSocketThread унаследованный от +SocketThread. Класс BotSocketThread должен быть публичным. +3) Переопредели методы: +а) getSocketThread(). Он должен создавать и возвращать объект класса +BotSocketThread. +б) shouldSendTextFromConsole(). Он должен всегда возвращать false. Мы не хотим, +чтобы бот отправлял текст введенный в консоль. +в) getUserName(), метод должен генерировать новое имя бота, например: +date_bot_XX, где XX – любое число от 0 до 99. Для генерации XX используй метод Math.random(). +4) Добавь метод main. Он должен создавать новый объект BotClient и вызывать у +него метод run(). + + + +Чат (17) + +Последний, но самый главный метод класса SocketThread – это метод void run(). Добавь +его. Его реализация с учетом уже созданных методов выглядит очень просто. + +Давай напишем ее: +1) Запроси адрес и порт сервера с помощью методов getServerAddress() и +getServerPort(). +2) Создай новый объект класса java.net.Socket, используя данные, полученные в +предыдущем пункте. +3) Создай объект класса Connection, используя сокет из п.17.2. +4) Вызови метод, реализующий "рукопожатие" клиента с сервером +(clientHandshake()). +5) Вызови метод, реализующий основной цикл обработки сообщений сервера. +6) При возникновении исключений IOException или ClassNotFoundException +сообщи главному потоку о проблеме, используя notifyConnectionStatusChanged и false +в качестве параметра. + +Клиент готов, можешь запустить сервер, несколько клиентов и проверить как все работает. From 9a38aeb7732082ae67221dd40c67faa6c0b4063f Mon Sep 17 00:00:00 2001 From: PeucT Date: Tue, 28 Mar 2017 19:11:54 +0400 Subject: [PATCH 14/51] lvl 27 big task (3110) (1-12) --- .../task/task31/task3110/Archiver.java | 37 ++++ .../task/task31/task3110/CommandExecutor.java | 26 +++ .../task/task31/task3110/ConsoleHelper.java | 23 +++ .../task/task31/task3110/FileManager.java | 42 ++++ .../task/task31/task3110/FileProperties.java | 55 +++++ .../task/task31/task3110/Operation.java | 10 + .../task/task31/task3110/ZipFileManager.java | 72 +++++++ .../task/task31/task3110/command/Command.java | 5 + .../task31/task3110/command/ExitCommand.java | 10 + .../task3110/command/ZipAddCommand.java | 11 + .../task31/task3110/command/ZipCommand.java | 16 ++ .../task3110/command/ZipContentCommand.java | 11 + .../task3110/command/ZipCreateCommand.java | 28 +++ .../task3110/command/ZipExtractCommand.java | 11 + .../task3110/command/ZipRemoveCommand.java | 11 + .../exception/PathIsNotFoundException.java | 4 + .../exception/WrongZipFileException.java | 4 + ...\273\320\276\320\262\320\270\320\265.jrtc" | 193 ++++++++++++++++++ 18 files changed, 569 insertions(+) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task31/task3110/Archiver.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task31/task3110/CommandExecutor.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task31/task3110/ConsoleHelper.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task31/task3110/FileManager.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task31/task3110/FileProperties.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task31/task3110/Operation.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task31/task3110/ZipFileManager.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/Command.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ExitCommand.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipAddCommand.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipCommand.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipContentCommand.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipCreateCommand.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipExtractCommand.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipRemoveCommand.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task31/task3110/exception/PathIsNotFoundException.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task31/task3110/exception/WrongZipFileException.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task31/task3110/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/Archiver.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/Archiver.java new file mode 100644 index 0000000..b5fe7c4 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/Archiver.java @@ -0,0 +1,37 @@ +package com.javarush.task.task31.task3110; + +import com.javarush.task.task31.task3110.exception.WrongZipFileException; + +import java.io.IOException; + +public class Archiver { + public static void main(String[] args) throws IOException { + + Operation operation = null; + do { + try { + operation = askOperation(); + CommandExecutor.execute(operation); + } catch (WrongZipFileException e) { + ConsoleHelper.writeMessage("Вы не выбрали файл архива или выбрали неверный файл."); + } catch (Exception e) { + ConsoleHelper.writeMessage("Произошла ошибка. Проверьте введенные данные."); + } + + } while (operation != Operation.EXIT); + } + + + public static Operation askOperation() throws IOException { + ConsoleHelper.writeMessage(""); + ConsoleHelper.writeMessage("Выберите операцию:"); + ConsoleHelper.writeMessage(String.format("\t %d - упаковать файлы в архив", Operation.CREATE.ordinal())); + ConsoleHelper.writeMessage(String.format("\t %d - добавить файл в архив", Operation.ADD.ordinal())); + ConsoleHelper.writeMessage(String.format("\t %d - удалить файл из архива", Operation.REMOVE.ordinal())); + ConsoleHelper.writeMessage(String.format("\t %d - распаковать архив", Operation.EXTRACT.ordinal())); + ConsoleHelper.writeMessage(String.format("\t %d - просмотреть содержимое архива", Operation.CONTENT.ordinal())); + ConsoleHelper.writeMessage(String.format("\t %d - выход", Operation.EXIT.ordinal())); + + return Operation.values()[ConsoleHelper.readInt()]; + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/CommandExecutor.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/CommandExecutor.java new file mode 100644 index 0000000..e3c0c86 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/CommandExecutor.java @@ -0,0 +1,26 @@ +package com.javarush.task.task31.task3110; + +import com.javarush.task.task31.task3110.command.*; + +import java.util.HashMap; +import java.util.Map; + +public class CommandExecutor { + private static final Map allKnownCommandsMap = new HashMap<>(); + + static { + allKnownCommandsMap.put(Operation.CREATE, new ZipCreateCommand()); + allKnownCommandsMap.put(Operation.ADD, new ZipAddCommand()); + allKnownCommandsMap.put(Operation.REMOVE, new ZipRemoveCommand()); + allKnownCommandsMap.put(Operation.EXTRACT, new ZipExtractCommand()); + allKnownCommandsMap.put(Operation.CONTENT, new ZipContentCommand()); + allKnownCommandsMap.put(Operation.EXIT, new ExitCommand()); + } + + private CommandExecutor() { + } + + public static void execute(Operation operation) throws Exception { + allKnownCommandsMap.get(operation).execute(); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/ConsoleHelper.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/ConsoleHelper.java new file mode 100644 index 0000000..426febb --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/ConsoleHelper.java @@ -0,0 +1,23 @@ +package com.javarush.task.task31.task3110; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class ConsoleHelper { + private static BufferedReader bis = new BufferedReader(new InputStreamReader(System.in)); + + public static void writeMessage(String message) { + System.out.println(message); + } + + public static String readString() throws IOException { + String text = bis.readLine(); + return text; + } + + public static int readInt() throws IOException { + String text = readString(); + return Integer.parseInt(text.trim()); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/FileManager.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/FileManager.java new file mode 100644 index 0000000..5228beb --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/FileManager.java @@ -0,0 +1,42 @@ +package com.javarush.task.task31.task3110; + +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +public class FileManager { + private Path rootPath; + private List fileList; + + public FileManager(Path rootPath) throws IOException { + this.rootPath = rootPath; + this.fileList = new ArrayList<>(); + collectFileList(rootPath); + } + + public List getFileList() { + return fileList; + } + + private void collectFileList(Path path) throws IOException { + // Добавляем только файлы + if (Files.isRegularFile(path)) { + Path relativePath = rootPath.relativize(path); + fileList.add(relativePath); + } + + // Добавляем содержимое директории + if (Files.isDirectory(path)) { + // Рекурсивно проходимся по всему содержмому директории + // Чтобы не писать код по вызову close для DirectoryStream, обернем вызов newDirectoryStream в try-with-resources + try (DirectoryStream directoryStream = Files.newDirectoryStream(path)) { + for (Path file : directoryStream) { + collectFileList(file); + } + } + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/FileProperties.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/FileProperties.java new file mode 100644 index 0000000..e149dc5 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/FileProperties.java @@ -0,0 +1,55 @@ +package com.javarush.task.task31.task3110; + +public class FileProperties { + private String name; + private long size; + private long compressedSize; + private int compressionMethod; + + public FileProperties(String name, long size, long compressedSize, int compressionMethod) { + this.name = name; + this.size = size; + this.compressedSize = compressedSize; + this.compressionMethod = compressionMethod; + } + + + public String getName() { + return name; + } + + public long getSize() { + return size; + } + + public long getCompressedSize() { + return compressedSize; + } + + public int getCompressionMethod() { + return compressionMethod; + } + + public long getCompressionRatio() { + // Вычисляем степень сжатия + return 100 - ((compressedSize * 100) / size); + } + + @Override + public String toString() { + // Строим красивую строку из свойств + StringBuilder builder = new StringBuilder(); + builder.append(name); + if (size > 0) { + builder.append("\t"); + builder.append(size / 1024); + builder.append(" Kb ("); + builder.append(compressedSize / 1024); + builder.append(" Kb) сжатие: "); + builder.append(getCompressionRatio()); + builder.append("%"); + } + + return builder.toString(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/Operation.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/Operation.java new file mode 100644 index 0000000..21a6c66 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/Operation.java @@ -0,0 +1,10 @@ +package com.javarush.task.task31.task3110; + +public enum Operation { + CREATE, + ADD, + REMOVE, + EXTRACT, + CONTENT, + EXIT +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/ZipFileManager.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/ZipFileManager.java new file mode 100644 index 0000000..76d1158 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/ZipFileManager.java @@ -0,0 +1,72 @@ +package com.javarush.task.task31.task3110; + +import com.javarush.task.task31.task3110.exception.PathIsNotFoundException; + +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +public class ZipFileManager { + // Полный путь zip файла + private final Path zipFile; + + public ZipFileManager(Path zipFile) { + this.zipFile = zipFile; + } + + public void createZip(Path source) throws Exception { + // Проверяем, существует ли директория, где будет создаваться архив + // При необходимости создаем ее + Path zipDirectory = zipFile.getParent(); + if (Files.notExists(zipDirectory)) + Files.createDirectories(zipDirectory); + + // Создаем zip поток + try (ZipOutputStream zipOutputStream = new ZipOutputStream(Files.newOutputStream(zipFile))) { + + if (Files.isDirectory(source)) { + // Если архивируем директорию, то нужно получить список файлов в ней + FileManager fileManager = new FileManager(source); + List fileNames = fileManager.getFileList(); + + // Добавляем каждый файл в архив + for (Path fileName : fileNames) + addNewZipEntry(zipOutputStream, source, fileName); + + } else if (Files.isRegularFile(source)) { + + // Если архивируем отдельный файл, то нужно получить его директорию и имя + addNewZipEntry(zipOutputStream, source.getParent(), source.getFileName()); + } else { + + // Если переданный source не директория и не файл, бросаем исключение + throw new PathIsNotFoundException(); + } + } + } + + private void addNewZipEntry(ZipOutputStream zipOutputStream, Path filePath, Path fileName) throws Exception { + Path fullPath = filePath.resolve(fileName); + try (InputStream inputStream = Files.newInputStream(fullPath)) { + ZipEntry entry = new ZipEntry(fileName.toString()); + + zipOutputStream.putNextEntry(entry); + + copyData(inputStream, zipOutputStream); + + zipOutputStream.closeEntry(); + } + } + + private void copyData(InputStream in, OutputStream out) throws Exception { + byte[] buffer = new byte[8 * 1024]; + int len; + while ((len = in.read(buffer)) > 0) { + out.write(buffer, 0, len); + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/Command.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/Command.java new file mode 100644 index 0000000..6a51a10 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/Command.java @@ -0,0 +1,5 @@ +package com.javarush.task.task31.task3110.command; + +public interface Command { + void execute() throws Exception; +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ExitCommand.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ExitCommand.java new file mode 100644 index 0000000..31cf0d7 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ExitCommand.java @@ -0,0 +1,10 @@ +package com.javarush.task.task31.task3110.command; + +import com.javarush.task.task31.task3110.ConsoleHelper; + +public class ExitCommand implements Command { + @Override + public void execute() throws Exception { + ConsoleHelper.writeMessage("До встречи!"); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipAddCommand.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipAddCommand.java new file mode 100644 index 0000000..e7591e1 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipAddCommand.java @@ -0,0 +1,11 @@ +package com.javarush.task.task31.task3110.command; + +/** + * Created by ArchMage on 28.03.17. + */ +public class ZipAddCommand extends ZipCommand { + @Override + public void execute() throws Exception { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipCommand.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipCommand.java new file mode 100644 index 0000000..bb31975 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipCommand.java @@ -0,0 +1,16 @@ +package com.javarush.task.task31.task3110.command; + +import com.javarush.task.task31.task3110.ConsoleHelper; +import com.javarush.task.task31.task3110.ZipFileManager; + +import java.nio.file.Path; +import java.nio.file.Paths; + +public abstract class ZipCommand implements Command { + + public ZipFileManager getZipFileManager() throws Exception{ + ConsoleHelper.writeMessage("Введите полный путь файла архива:"); + Path zipPath = Paths.get(ConsoleHelper.readString()); + return new ZipFileManager(zipPath); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipContentCommand.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipContentCommand.java new file mode 100644 index 0000000..0993be4 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipContentCommand.java @@ -0,0 +1,11 @@ +package com.javarush.task.task31.task3110.command; + +/** + * Created by ArchMage on 28.03.17. + */ +public class ZipContentCommand extends ZipCommand { + @Override + public void execute() throws Exception { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipCreateCommand.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipCreateCommand.java new file mode 100644 index 0000000..c775d66 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipCreateCommand.java @@ -0,0 +1,28 @@ +package com.javarush.task.task31.task3110.command; + +import com.javarush.task.task31.task3110.ConsoleHelper; +import com.javarush.task.task31.task3110.ZipFileManager; +import com.javarush.task.task31.task3110.exception.PathIsNotFoundException; + +import java.nio.file.Path; +import java.nio.file.Paths; + +public class ZipCreateCommand extends ZipCommand { + @Override + public void execute() throws Exception { + try { + ConsoleHelper.writeMessage("Создание архива."); + + ZipFileManager zipFileManager = getZipFileManager(); + + ConsoleHelper.writeMessage("Введите полное имя файла или директории для архивации:"); + Path sourcePath = Paths.get(ConsoleHelper.readString()); + zipFileManager.createZip(sourcePath); + + ConsoleHelper.writeMessage("Архив создан."); + + } catch (PathIsNotFoundException e) { + ConsoleHelper.writeMessage("Вы неверно указали имя файла или директории."); + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipExtractCommand.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipExtractCommand.java new file mode 100644 index 0000000..e28d049 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipExtractCommand.java @@ -0,0 +1,11 @@ +package com.javarush.task.task31.task3110.command; + +/** + * Created by ArchMage on 28.03.17. + */ +public class ZipExtractCommand extends ZipCommand { + @Override + public void execute() throws Exception { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipRemoveCommand.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipRemoveCommand.java new file mode 100644 index 0000000..6cecd8a --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipRemoveCommand.java @@ -0,0 +1,11 @@ +package com.javarush.task.task31.task3110.command; + +/** + * Created by ArchMage on 28.03.17. + */ +public class ZipRemoveCommand extends ZipCommand { + @Override + public void execute() throws Exception { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/exception/PathIsNotFoundException.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/exception/PathIsNotFoundException.java new file mode 100644 index 0000000..614e886 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/exception/PathIsNotFoundException.java @@ -0,0 +1,4 @@ +package com.javarush.task.task31.task3110.exception; + +public class PathIsNotFoundException extends Exception { +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/exception/WrongZipFileException.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/exception/WrongZipFileException.java new file mode 100644 index 0000000..e28d88c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/exception/WrongZipFileException.java @@ -0,0 +1,4 @@ +package com.javarush.task.task31.task3110.exception; + +public class WrongZipFileException extends Exception { +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..c0ae1e1 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,193 @@ +taskKey="com.javarush.task.task31.task3110.big13" + +Archiver (13) + +Продолжим наш путь к получению содержимого файла архива. Напишем метод getFilesList() в классе +ZipFileManager. Он будет возвращать список файлов в архиве, вернее список свойств этих файлов (класс +свойств FileProperties мы уже реализовали). Итак: +1. Добавь метод List getFilesList() throws Exception в класс ZipFileManager +2. Внутри метода проверь является ли содержимое zipFile обычным файлом с помощью +подходящего метода класса Files. Если это не файл, брось исключение WrongZipFileException(). +3. Создай список с элементами типа FileProperties, в него мы будем складывать свойства файлов +4. Создай входящий поток ZipInputStream, для файла из переменной zipFile. Как и в прошлые разы, оберни его создание +в try-with-resources +5. Пройдись по всем элементам ZipEntry потока ZipInputStream +6. Для каждого элемента ZipEntry вычитай его содержимое, иначе у нас не будет информации о его +размере. Нельзя узнать размер файла в архиве, не вычитав его. Это очень легко сделать с +помощью функции copyData, используя временный буфер типа ByteArrayOutputStream. +7. Получи имя, размер, сжатый размер и метод сжатия элемента архива. Посмотри, что еще можно +узнать о нем. +8. Создай объект класса FileProperties, используя полученные данные о файле. +9. Добавь созданный объект из п.8 в список из п.3 +10. После выхода из цикла верни собранную информацию вызвавшему методу. + + +Archiver (12) + +Сегодня мы подготовимся к реализации команды ZipContentCommand. Она будет заниматься получением +содержимого архива. Содержимое архива – это упакованные файлы и папки, но нам было бы интересно +узнать не только имена объектов архива, но и их размер до и после сжатия, степень сжатия и метод +сжатия. +Создадим класс FileProperties, который будет отвечать за свойства каждого файла в архиве. Свойства – это +набор, состоящий из: имя файла, размер файла до и после сжатия, метод сжатия. +1. Создай класс FileProperties +2. Добавь в него приватные переменные класса: +2.1. Имя String name +2.2. Размер в байтах long size +2.3. Размер после сжатия в байтах long compressedSize +2.4. Метод сжатия int compressionMethod +3. Добавь гетеры для них +4. Добавь конструктор FileProperties(String name, long size, long compressedSize, int +compressionMethod) +5. Добавь метод long getCompressionRatio(), который будет считать степень сжатия по формуле: +100 - ((compressedSize * 100) / size) +6. Перегрузи метод String toString(), чтобы он возвращал строку по шаблону: “name size Kb +(compressedSize Kb) сжатие: compressionRatio%”, если размер size больше нуля, иначе он должен +вернуть только имя файла. Нулевой размер может быть, например, у директории. Не забудь +перевести байты в килобайты, а их не столько же, сколько граммов в килограмме, и даже не +столько, сколько блинов у меня на столе… Хм, похоже мне пора перекусить… + + + +Archiver (11) + +Давай наконец попробуем нормально реализовать метод execute() класса ZipCreateCommand, который +мы добавляли раньше. Для этого нужно: +1. В начале метода добавить вывод сообщения "Создание архива." Не забудь, что мы работаем с +консолью через методы класса ConsoleHelper. +2. Создай новый объект класса ZipFileManager. Т.к. создание этого объекта будет необходимо и +другим командам, вынеси создание в отдельный метод ZipFileManager getZipFileManager() throws +Exception в класс ZipCommand. Этот метод должен: +2.1. Просить пользователя ввести полный путь файла архива +2.2. Считывать введенный путь в переменную типа String +2.3. Используя введенный String формировать путь Path +2.4. Создать объект ZipFileManager, передав в конструктор полученный путь +2.5. Вернуть созданный объект +3. Попроси пользователя ввести полное имя файла или директории для архивации +4. Создай путь Path, используя введенную строку +5. У объекта класса ZipFileManager вызови метод createZip(), передав в него путь из п.4 +6. Выведи в консоль сообщение "Архив создан." +7. Оберни содержимое метода execute() класса ZipCreateCommand в блок try-catch и отлавливай +исключение типа PathIsNotFoundException. Если оно произошло, выведи сообщение "Вы неверно +указали имя файла или директории." +8. Запусти программу и проверь, что команда "упаковать файлы в архив" работает + + + +Archiver (10) + +Пришло время отрефакторить класс ZipFileManager. В методе createZip есть код, который нам также +понадобится в методах, которые будут добавлять или удалять файл в архив, распаковывать его и т.д. Эти +методы мы будем реализовывать позже, но уже сейчас можем вынести общие части кода в отдельные +методы. +Кроме того, метод createZip мог создавать архив только из одного файла, а хотелось бы уметь +архивировать всю папку целиком. Создавать отдельный метод для этого не будем, т.к. в createZip(Path +source) можно передавать и директорию и обычный файл. +Задания на сегодня: +1. Реализуй приватный метод void addNewZipEntry(ZipOutputStream zipOutputStream, Path filePath, +Path fileName) throws Exception в классе ZipFileManager. Он должен: +1.1. Создавать InputStream, для файла с именем fileName, расположенным в +директории filePath +1.2. Создавать новый элемент архива ZipEntry, в качестве имени используй fileName, +преобразовав его в String +1.3. Копировать данные из InputStream (из п.1.1) в переданный zipOutputStream +1.4. Закрывать элемент архива +1.5. Закрывать InputStream, сделай это с помощью try-with-resources +2. Замени часть кода метода createZip вызовом нового метода addNewZipEntry. Передай значение +source.getParent() в параметр filePath, а source.getFileName() в filename. +3. Реализуй приватный метод void copyData(InputStream in, OutputStream out) throws Exception. Он +должен читать данные из in и записывать в out, пока не вычитает все. +4. Замени часть кода метода addNewZipEntry на вызов метода copyData +5. Вернемся к createZip: +5.1. В начале метода проверь, что существует директория (zipFile.getParent()), в которой мы +будем создавать zipFile, если ее нет, то создай ее. +5.2. Если source является обычным файлом (для проверки используй Files.isRegularFile), то оставим просто вызов +addNewZipEntry +5.3. Если source является директорией (для проверки используй Files.isDirectory), то: +5.3.1. Создай объект класса файловый менеджер FileManager, в конструктор передадим +source +5.3.2. Получи список файлов у файлового менеджера, сохраним его в переменную +fileNames +5.3.3. Для всех элементов fileNames, вызови метод addNewZipEntry(zipOutputStream, +source, fileName) +5.4. Если source не является ни папкой, ни файлом, то кинь исключение +PathIsNotFoundException. + + + +Archiver (9) + +Теперь займемся другой, не менее важной частью нашего архиватора. Очень часто пользователь хочет +создать архив не из одного файла, а из целой папки. Тогда архивация сводится к поочередному +добавлению элемента ZipEntry для каждого файла в архив. +Нам нужно написать класс FileManager для получения списка всех файлов в какой-то папке. У него должен +быть конструктор, который будет принимать путь Path rootPath, указывающий на корень (папку, файлы в +которой нас интересуют) и метод List getFileList(), который должен возвращать список +относительных путей всех файлов, которые находятся по пути rootPath, включая файлы в подпапках. +Директория, в которой будем искать, может задаваться только один раз в конструкторе. Поэтому, прямо в +конструкторе мы сразу можем сформировать список файлов (их относительных путей), сохранив его в +переменную класса List fileList. +Осталось только решить, как нам собрать все файлы, даже те, которые могут быть в папке, которая в папке, +которая в папке, которая в интересующей нас папке. Фух, чуть не вошел рекурсию. Хотя нам-то она и +поможет! Сделаем метод collectFileList(Path path), который будет складывать в переменную класса fileList +все файлы, обнаруженные внутри переданного пути path, вызывая сам себя для всех объектов, в +обнаруженных директориях. +1. Создай класс FileManager с конструктором FileManager(Path rootPath) throws IOException +2. Объяви и проинициализируй приватные переменные класса: +2.1. Path rootPath – корневой путь директории, файлы которой нас интересуют +2.2. List fileList – список относительных путей файлов внутри rootPath +3. Создай геттер для fileList +4. Реализуй метод void collectFileList(Path path) throws IOException, который должен: +4.1. Проверить, если переданный путь path является обычным файлом (используй метод +Files.isRegularFile), то получить его относительный путь относительно rootPath +и добавить его в список fileList. +4.2. Если переданный путь path, является директорией (узнать это поможет метод +Files.isDirectory), то пройтись по всему содержимому директории и вызвать +collectFileList(Path path), передав в path обнаруженные элементы. +Пройтись по всему содержимому директории можно предварительно получив DirectoryStream с помощью метода +newDirectoryStream класса Files. Не забудь закрыть созданный DirectoryStream. +5. Добавь вызов метода collectFileList(rootPath) в конструкторе FileManager. +6. Примени все свои знания об инкапсуляции к этому классу. +Выполняя это задание, ты написал алгоритм, который обходит дерево файлов. Но в Java есть специальный интерфейс +FileVisitor для этих целей. Очень рекомендую разобраться как им пользоваться. + + + +Archiver (8) + +Чтобы узнать какую команду сейчас хочет выполнить пользователь, добавим метод Operation +askOperation() в класс Archiver. Этот метод должен вывести в консоль список доступных команд и +попросить выбрать одну из них. Для удобства будем просить ввести номер команды, где номер – это +порядковый номер команды в enum Operation. Получить порядковый номер значения в enum’е можно с +помощью метода ordinal(). +Теперь все готово чтобы переписать main, используя последние достижения науки и техники, а именно +класс CommandExecutor и метод askOperation(). +1. Добавь публичный статический метод Operation askOperation() throws IOException в класс Archiver. +Он должен: +1.1. Использовать методы класса ConsoleHelper +1.2. Запрашивать у пользователя номер операции, которую он хочет совершить. Подсказка: +чтобы вывести номер операции «Создать архив», используй: Operation.CREATE.ordinal() +1.3. Возвращать выбранную операцию. +Пример вывода метода askOperation(): +Выберите операцию: +0 - упаковать файлы в архив +1 - добавить файл в архив +2 - удалить файл из архива +3 - распаковать архив +4 - просмотреть содержимое архива +5 – выход +2. Перепиши метод main(): +2.1. Объяви локальную переменную типа Operation +2.2. В цикле запрашивай новое значение для переменной п.2.1. с помощью метода askOperation() и +вызывай выполнение операции с помощью CommandExecutor.execute() +2.3. Обеспечь выход из цикла, если пользователь выбрал операцию Operation.EXIT +2.4. Оберни вызов askOperation() и execute(operation) в блок try-catch. Если произойдет +исключение WrongZipFileException выведи сообщение "Вы не выбрали файл архива или +выбрали неверный файл." с помощью ConsoleHelper, при любых других исключениях +выводи "Произошла ошибка. Проверьте введенные данные.". +2.5. Проследи, чтобы программа продолжила свою работу (перешла на новый шаг цикла), +после обработки исключений. +3. Запусти программу и проверь, что команда “выход” работает. + + + From 28894683b768d34419eeeb41e73c15cb8441b6ae Mon Sep 17 00:00:00 2001 From: PeucT Date: Wed, 29 Mar 2017 18:41:47 +0400 Subject: [PATCH 15/51] Lvl 27 big task (3110 FULL) --- .../task/task31/task3110/ZipFileManager.java | 158 ++++++++++ .../task3110/command/ZipAddCommand.java | 24 +- .../task3110/command/ZipContentCommand.java | 20 +- .../task3110/command/ZipExtractCommand.java | 23 +- .../task3110/command/ZipRemoveCommand.java | 19 +- ...\273\320\276\320\262\320\270\320\265.jrtc" | 289 ++++++++---------- 6 files changed, 351 insertions(+), 182 deletions(-) diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/ZipFileManager.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/ZipFileManager.java index 76d1158..49daac4 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/ZipFileManager.java +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/ZipFileManager.java @@ -1,13 +1,20 @@ package com.javarush.task.task31.task3110; import com.javarush.task.task31.task3110.exception.PathIsNotFoundException; +import com.javarush.task.task31.task3110.exception.WrongZipFileException; +import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; public class ZipFileManager { @@ -49,6 +56,157 @@ public void createZip(Path source) throws Exception { } } + public void extractAll(Path outputFolder) throws Exception { + // Проверяем существует ли zip файл + if (!Files.isRegularFile(zipFile)) { + throw new WrongZipFileException(); + } + + try (ZipInputStream zipInputStream = new ZipInputStream(Files.newInputStream(zipFile))) { + // Создаем директорию вывода, если она не существует + if (Files.notExists(outputFolder)) + Files.createDirectories(outputFolder); + + // Проходимся по содержимому zip потока (файла) + ZipEntry zipEntry = zipInputStream.getNextEntry(); + + while (zipEntry != null) { + String fileName = zipEntry.getName(); + Path fileFullName = outputFolder.resolve(fileName); + + // Создаем необходимые директории + Path parent = fileFullName.getParent(); + if (Files.notExists(parent)) + Files.createDirectories(parent); + + try (OutputStream outputStream = Files.newOutputStream(fileFullName)) { + copyData(zipInputStream, outputStream); + } + zipEntry = zipInputStream.getNextEntry(); + } + } + } + + public void removeFile(Path path) throws Exception { + removeFiles(Collections.singletonList(path)); + } + + public void removeFiles(List pathList) throws Exception { + // Проверяем существует ли zip файл + if (!Files.isRegularFile(zipFile)) { + throw new WrongZipFileException(); + } + + // Создаем временный файл + Path tempZipFile = Files.createTempFile(null, null); + + try (ZipOutputStream zipOutputStream = new ZipOutputStream(Files.newOutputStream(tempZipFile))) { + try (ZipInputStream zipInputStream = new ZipInputStream(Files.newInputStream(zipFile))) { + + ZipEntry zipEntry = zipInputStream.getNextEntry(); + while (zipEntry != null) { + + Path archivedFile = Paths.get(zipEntry.getName()); + + if (!pathList.contains(archivedFile)) { + String fileName = zipEntry.getName(); + zipOutputStream.putNextEntry(new ZipEntry(fileName)); + + copyData(zipInputStream, zipOutputStream); + + zipOutputStream.closeEntry(); + zipInputStream.closeEntry(); + } + else { + ConsoleHelper.writeMessage(String.format("Файл '%s' удален из архива.", archivedFile.toString())); + } + zipEntry = zipInputStream.getNextEntry(); + } + } + } + + // Перемещаем временный файл на место оригинального + Files.move(tempZipFile, zipFile, StandardCopyOption.REPLACE_EXISTING); + } + + public void addFile(Path absolutePath) throws Exception { + addFiles(Collections.singletonList(absolutePath)); + } + + public void addFiles(List absolutePathList) throws Exception { + // Проверяем существует ли zip файл + if (!Files.isRegularFile(zipFile)) { + throw new WrongZipFileException(); + } + + // Создаем временный файл + Path tempZipFile = Files.createTempFile(null, null); + List archiveFiles = new ArrayList<>(); + + try (ZipOutputStream zipOutputStream = new ZipOutputStream(Files.newOutputStream(tempZipFile))) { + try (ZipInputStream zipInputStream = new ZipInputStream(Files.newInputStream(zipFile))) { + + ZipEntry zipEntry = zipInputStream.getNextEntry(); + while (zipEntry != null) { + String fileName = zipEntry.getName(); + archiveFiles.add(Paths.get(fileName)); + + zipOutputStream.putNextEntry(new ZipEntry(fileName)); + copyData(zipInputStream, zipOutputStream); + + zipInputStream.closeEntry(); + zipOutputStream.closeEntry(); + + zipEntry = zipInputStream.getNextEntry(); + } + } + + // Архивируем новые файлы + for (Path file : absolutePathList) { + if (Files.isRegularFile(file)) + { + if (archiveFiles.contains(file.getFileName())) + ConsoleHelper.writeMessage(String.format("Файл '%s' уже существует в архиве.", file.toString())); + else { + addNewZipEntry(zipOutputStream, file.getParent(), file.getFileName()); + ConsoleHelper.writeMessage(String.format("Файл '%s' добавлен в архиве.", file.toString())); + } + } + else + throw new PathIsNotFoundException(); + } + } + + // Перемещаем временный файл на место оригинального + Files.move(tempZipFile, zipFile, StandardCopyOption.REPLACE_EXISTING); + } + + public List getFilesList() throws Exception { + // Проверяем существует ли zip файл + if (!Files.isRegularFile(zipFile)) { + throw new WrongZipFileException(); + } + + List files = new ArrayList<>(); + + try (ZipInputStream zipInputStream = new ZipInputStream(Files.newInputStream(zipFile))) { + ZipEntry zipEntry = zipInputStream.getNextEntry(); + + while (zipEntry != null) { + // Поля "размер" и "сжатый размер" не известны, пока элемент не будет прочитан + // Давайте вычитаем его в какой-то выходной поток + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + copyData(zipInputStream, baos); + + FileProperties file = new FileProperties(zipEntry.getName(), zipEntry.getSize(), zipEntry.getCompressedSize(), zipEntry.getMethod()); + files.add(file); + zipEntry = zipInputStream.getNextEntry(); + } + } + + return files; + } + private void addNewZipEntry(ZipOutputStream zipOutputStream, Path filePath, Path fileName) throws Exception { Path fullPath = filePath.resolve(fileName); try (InputStream inputStream = Files.newInputStream(fullPath)) { diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipAddCommand.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipAddCommand.java index e7591e1..ad9911b 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipAddCommand.java +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipAddCommand.java @@ -1,11 +1,29 @@ package com.javarush.task.task31.task3110.command; -/** - * Created by ArchMage on 28.03.17. - */ +import com.javarush.task.task31.task3110.ConsoleHelper; +import com.javarush.task.task31.task3110.ZipFileManager; +import com.javarush.task.task31.task3110.exception.PathIsNotFoundException; + +import java.nio.file.Path; +import java.nio.file.Paths; + public class ZipAddCommand extends ZipCommand { @Override public void execute() throws Exception { + try { + ConsoleHelper.writeMessage("Добавление нового файла в архив."); + + ZipFileManager zipFileManager = getZipFileManager(); + + ConsoleHelper.writeMessage("Введите полное имя файла для добавления:"); + Path sourcePath = Paths.get(ConsoleHelper.readString()); + + zipFileManager.addFile(sourcePath); + + ConsoleHelper.writeMessage("Добавление в архив завершено."); + } catch (PathIsNotFoundException e) { + ConsoleHelper.writeMessage("Файл не был найден."); + } } } diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipContentCommand.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipContentCommand.java index 0993be4..9b7c5c9 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipContentCommand.java +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipContentCommand.java @@ -1,11 +1,25 @@ package com.javarush.task.task31.task3110.command; -/** - * Created by ArchMage on 28.03.17. - */ +import com.javarush.task.task31.task3110.ConsoleHelper; +import com.javarush.task.task31.task3110.FileProperties; +import com.javarush.task.task31.task3110.ZipFileManager; + +import java.util.List; + public class ZipContentCommand extends ZipCommand { @Override public void execute() throws Exception { + ConsoleHelper.writeMessage("Просмотр содержимого архива."); + + ZipFileManager zipFileManager = getZipFileManager(); + + ConsoleHelper.writeMessage("Содержимое архива:"); + + List files = zipFileManager.getFilesList(); + for (FileProperties file : files) { + ConsoleHelper.writeMessage(file.toString()); + } + ConsoleHelper.writeMessage("Содержимое архива прочитано."); } } diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipExtractCommand.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipExtractCommand.java index e28d049..2da2667 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipExtractCommand.java +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipExtractCommand.java @@ -1,11 +1,28 @@ package com.javarush.task.task31.task3110.command; -/** - * Created by ArchMage on 28.03.17. - */ +import com.javarush.task.task31.task3110.ConsoleHelper; +import com.javarush.task.task31.task3110.ZipFileManager; +import com.javarush.task.task31.task3110.exception.PathIsNotFoundException; + +import java.nio.file.Path; +import java.nio.file.Paths; + public class ZipExtractCommand extends ZipCommand { @Override public void execute() throws Exception { + try { + ConsoleHelper.writeMessage("Распаковка архива."); + + ZipFileManager zipFileManager = getZipFileManager(); + + ConsoleHelper.writeMessage("Введите путь для распаковки:"); + Path destinationPath = Paths.get(ConsoleHelper.readString()); + zipFileManager.extractAll(destinationPath); + + ConsoleHelper.writeMessage("Архив был распакован."); + } catch (PathIsNotFoundException e) { + ConsoleHelper.writeMessage("Неверный путь для распаковки."); + } } } diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipRemoveCommand.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipRemoveCommand.java index 6cecd8a..4db7635 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipRemoveCommand.java +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipRemoveCommand.java @@ -1,11 +1,22 @@ package com.javarush.task.task31.task3110.command; -/** - * Created by ArchMage on 28.03.17. - */ +import com.javarush.task.task31.task3110.ConsoleHelper; +import com.javarush.task.task31.task3110.ZipFileManager; + +import java.nio.file.Path; +import java.nio.file.Paths; + public class ZipRemoveCommand extends ZipCommand { @Override public void execute() throws Exception { + ConsoleHelper.writeMessage("Удаление файла из архива."); + + ZipFileManager zipFileManager = getZipFileManager(); + + ConsoleHelper.writeMessage("Введите полный путь файла в архиве:"); + Path sourcePath = Paths.get(ConsoleHelper.readString()); + zipFileManager.removeFile(sourcePath); + ConsoleHelper.writeMessage("Удаление из архива завершено."); } -} +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" index c0ae1e1..2943cff 100644 --- "a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" +++ "b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -1,4 +1,123 @@ -taskKey="com.javarush.task.task31.task3110.big13" +taskKey="com.javarush.task.task31.task3110.big18" + +Archiver (18) + +Ты отличный ученик, я немного подправил твой код, можешь использовать этот архиватор для архивации +в повседневной жизни. Если будет время и желание, попробуй добавить операцию изменения степени +сжатия архива! + + +Требования: +1. Архиватор готов. + + +Archiver (17) + +Осталась ерунда. Добавить добавление файла в архив. Звучит подозрительно, но именно этим мы и +займемся. Добавление файлов похоже на удаление, мы создаем временный файл архив, переписываем в +него все содержимое старого архива и добавляем новые файлы. Потом заменяем старый файл архива +новым. +1. Добавь публичный метод void addFiles(List absolutePathList) throws Exception в класс +ZipFileManager, где absolutePathList – список абсолютных путей добавляемых файлов. Этот метод +должен: +1.1. Как обычно, бросать исключение WrongZipFileException, если файл архива не существует +1.2. Создать временный файл архива +1.3. Пройти по всем файлам оригинального архива, переписать каждый файл в новый архив, +добавить имя переписанного файла в какой-нибудь локальный список. +1.4. Пройтись по списку добавляемых файлов. +1.5. Для каждого файла проверить, есть ли он на диске и является ли он обычным файлом, +если что-то не так, кинь исключение PathIsNotFoundException() +1.6. Проверить, есть ли добавляемый файл уже в архиве (используй список из п.1.3). Такое +возможно, если пользователь уже когда-то добавлял его. +- Если файла нет в списке, добавь его в новый архив, выведи сообщение, что такой-то файл +добавлен в архив +- Если файл есть в списке, просто сообщи пользователю, что такой файл уже есть в архиве +1.7. Заменить оригинальный файл архива временным, в котором уже есть добавленные +файлы. +2. Добавь публичный метод void addFile(Path absolutePath) throws Exception в класс ZipFileManager, +реализуй его с помощью вызова метода addFiles(), аналогично тому, как мы это делали для +удаления файла. +3. Реализуй метод execute() класса ZipAddCommand: все как обычно, но не забудь спросить у +пользователя в какой архив и какой файл он хочет добавить, обработай исключение +PathIsNotFoundException, которое может кинуть метод addFile(). +4. Запусти программу и проверить, что добавление файла теперь работает. + + + +Archiver (16) + +Пришло время что-нибудь удалить из архива. Архив очень хитрая штука, нельзя вот так просто взять и +удалить какой-то элемент внутри него. +Почему? Представь, что мы решили сами придумать свой алгоритм сжатия текста. Посмотрев исходный +текст, мы видим, что в нем часто встречается фраза "быть программистом круто". Мы можем в месте, где +второй, третий, N-ый раз встречается наша фраза сделать пометку, что тут была фраза, как в строке S +начиная с символа номер K и длиной N, а саму фразу удалить. Когда мы заменим много повторяющихся +фраз, текст заметно сократится, но станет нечитаемым для тех, кто не знаком с нашим алгоритмом сжатия. +Мы же этот текст сможем восстановить (разархивировать). А теперь представь, что нам нужно удалить +часть текста, на которую ссылались сжатые фрагменты. В такой ситуации, весь наш архив перестанет +иметь смысл. Вот почему нельзя просто так удалить часть архива. Это очень примерное описание +варианта архивации, в реальности все намного сложнее. +Поэтому, чтобы что-то удалить из архива, нужно создать новый архив, переписать в него все, кроме +удаляемых файлов, а потом заменить старый архив вновь созданным. +1. Добавь публичный метод для удаления файлов из архива void removeFiles(List pathList) +throws Exception в класс ZipFileManager. В pathList будет передаваться список относительных путей на +файлы внутри архива. Он должен: +1.1. Бросать исключение WrongZipFileException, если файл архива не существует +1.2. Создать временный файл архива с помощью метода createTempFile() класса Files +1.3. Пройтись по всем файлам оригинального архива, проверить, есть ли текущий файл в списке +на удаление. +- Если файл есть в списке, вывести сообщение, что мы удалили файл с таким-то именем и +перейти к следующему файлу. +- Если файла нет в списке на удаление, переписать его в новый архив +1.4. Заменить оригинальный файл архива временным, в который мы записали нужные файлы. +Это нужно сделать с помощью метода move() класса Files +2. Добавь публичный метод void removeFile(Path path) throws Exception в класс ZipFileManager, +который будет вызывать метод removeFiles, создавая список из одного элемента. Это можно сделать с помощью +метода singletonList() класса Collections. Посмотри, как он работает. +3. Реализуй метод execute() класса ZipRemoveCommand, создав объект класса ZipFileManager, +спросив пользователя из какого архива и какой файл будем удалять, и вызвав метод removeFile(). +Все остальное, как и в других командах. Исключение PathIsNotFoundException можно не ловить, т.к. метод +removeFile() не должен его кидать. +4. Запусти программу и проверить, что удаление файла из архива работает. + + + +Archiver (15) + +Пора попробовать что-нибудь распаковать. Для этого добавим публичный метод void extractAll(Path +outputFolder) throws Exception в класс ZipFileManager. Path outputFolder - это путь, куда мы будем +распаковывать наш архив. У тебя уже большой опыт работы с элементами архива и потоками. Так что, я +дам только подсказки по реализации этого метода, а тебе придется хорошенько подумать, как это все +сделать: +1. Проверь, есть ли zip файл вообще +2. Если директория outputFolder не существует, то ее нужно создать, как и все папки, внутри которых +она лежит. +3. Внутри архива некоторые файлы могут лежат внутри папок, тогда метод getName() элемента +архива ZipEntry, вернет не совсем имя, как может показаться из названия, а относительный путь +внутри архива. Этот относительный путь должен сохраниться и после распаковки, но уже +относительно той директории, куда мы распаковали архив +4. Реализуй метод execute() класса ZipExtractCommand, по аналогии с таким же методом класса +ZipCreateCommand, сделай такой же блок try-catch, только поменяй сообщения выводимые +пользователю, чтобы он понял, что сейчас мы будем распаковывать архив, и что нужно ввести +полное имя архива и директорию, куда будем распаковывать. Не забудь вызвать метод extractAll +класса ZipFileManager, а не createZip, как это было в ZipCreateCommand +5. Запускай программу и наслаждайся результатом распаковки + + + +Archiver (14) + +Все готово, чтобы реализовать метод execute() класса ZipContentCommand: +1. Выведи сообщение "Просмотр содержимого архива." +2. Создай объект класса ZipFileManager с помощью метода getZipFileManager() +3. Выведи сообщение "Содержимое архива:" +4. Получи список файлов архива с помощью метода getFilesList() +5. Выведи свойства каждого файла в консоль. Тут нам и пригодится ранее реализованный метод +toString() класса FileProperties +6. Выведи сообщение "Содержимое архива прочитано." +7. Запусти программу и проверь, что команда "просмотреть содержимое архива" работает + + Archiver (13) @@ -22,172 +141,4 @@ ZipFileManager. Он будет возвращать список файлов 10. После выхода из цикла верни собранную информацию вызвавшему методу. -Archiver (12) - -Сегодня мы подготовимся к реализации команды ZipContentCommand. Она будет заниматься получением -содержимого архива. Содержимое архива – это упакованные файлы и папки, но нам было бы интересно -узнать не только имена объектов архива, но и их размер до и после сжатия, степень сжатия и метод -сжатия. -Создадим класс FileProperties, который будет отвечать за свойства каждого файла в архиве. Свойства – это -набор, состоящий из: имя файла, размер файла до и после сжатия, метод сжатия. -1. Создай класс FileProperties -2. Добавь в него приватные переменные класса: -2.1. Имя String name -2.2. Размер в байтах long size -2.3. Размер после сжатия в байтах long compressedSize -2.4. Метод сжатия int compressionMethod -3. Добавь гетеры для них -4. Добавь конструктор FileProperties(String name, long size, long compressedSize, int -compressionMethod) -5. Добавь метод long getCompressionRatio(), который будет считать степень сжатия по формуле: -100 - ((compressedSize * 100) / size) -6. Перегрузи метод String toString(), чтобы он возвращал строку по шаблону: “name size Kb -(compressedSize Kb) сжатие: compressionRatio%”, если размер size больше нуля, иначе он должен -вернуть только имя файла. Нулевой размер может быть, например, у директории. Не забудь -перевести байты в килобайты, а их не столько же, сколько граммов в килограмме, и даже не -столько, сколько блинов у меня на столе… Хм, похоже мне пора перекусить… - - - -Archiver (11) - -Давай наконец попробуем нормально реализовать метод execute() класса ZipCreateCommand, который -мы добавляли раньше. Для этого нужно: -1. В начале метода добавить вывод сообщения "Создание архива." Не забудь, что мы работаем с -консолью через методы класса ConsoleHelper. -2. Создай новый объект класса ZipFileManager. Т.к. создание этого объекта будет необходимо и -другим командам, вынеси создание в отдельный метод ZipFileManager getZipFileManager() throws -Exception в класс ZipCommand. Этот метод должен: -2.1. Просить пользователя ввести полный путь файла архива -2.2. Считывать введенный путь в переменную типа String -2.3. Используя введенный String формировать путь Path -2.4. Создать объект ZipFileManager, передав в конструктор полученный путь -2.5. Вернуть созданный объект -3. Попроси пользователя ввести полное имя файла или директории для архивации -4. Создай путь Path, используя введенную строку -5. У объекта класса ZipFileManager вызови метод createZip(), передав в него путь из п.4 -6. Выведи в консоль сообщение "Архив создан." -7. Оберни содержимое метода execute() класса ZipCreateCommand в блок try-catch и отлавливай -исключение типа PathIsNotFoundException. Если оно произошло, выведи сообщение "Вы неверно -указали имя файла или директории." -8. Запусти программу и проверь, что команда "упаковать файлы в архив" работает - - - -Archiver (10) - -Пришло время отрефакторить класс ZipFileManager. В методе createZip есть код, который нам также -понадобится в методах, которые будут добавлять или удалять файл в архив, распаковывать его и т.д. Эти -методы мы будем реализовывать позже, но уже сейчас можем вынести общие части кода в отдельные -методы. -Кроме того, метод createZip мог создавать архив только из одного файла, а хотелось бы уметь -архивировать всю папку целиком. Создавать отдельный метод для этого не будем, т.к. в createZip(Path -source) можно передавать и директорию и обычный файл. -Задания на сегодня: -1. Реализуй приватный метод void addNewZipEntry(ZipOutputStream zipOutputStream, Path filePath, -Path fileName) throws Exception в классе ZipFileManager. Он должен: -1.1. Создавать InputStream, для файла с именем fileName, расположенным в -директории filePath -1.2. Создавать новый элемент архива ZipEntry, в качестве имени используй fileName, -преобразовав его в String -1.3. Копировать данные из InputStream (из п.1.1) в переданный zipOutputStream -1.4. Закрывать элемент архива -1.5. Закрывать InputStream, сделай это с помощью try-with-resources -2. Замени часть кода метода createZip вызовом нового метода addNewZipEntry. Передай значение -source.getParent() в параметр filePath, а source.getFileName() в filename. -3. Реализуй приватный метод void copyData(InputStream in, OutputStream out) throws Exception. Он -должен читать данные из in и записывать в out, пока не вычитает все. -4. Замени часть кода метода addNewZipEntry на вызов метода copyData -5. Вернемся к createZip: -5.1. В начале метода проверь, что существует директория (zipFile.getParent()), в которой мы -будем создавать zipFile, если ее нет, то создай ее. -5.2. Если source является обычным файлом (для проверки используй Files.isRegularFile), то оставим просто вызов -addNewZipEntry -5.3. Если source является директорией (для проверки используй Files.isDirectory), то: -5.3.1. Создай объект класса файловый менеджер FileManager, в конструктор передадим -source -5.3.2. Получи список файлов у файлового менеджера, сохраним его в переменную -fileNames -5.3.3. Для всех элементов fileNames, вызови метод addNewZipEntry(zipOutputStream, -source, fileName) -5.4. Если source не является ни папкой, ни файлом, то кинь исключение -PathIsNotFoundException. - - - -Archiver (9) - -Теперь займемся другой, не менее важной частью нашего архиватора. Очень часто пользователь хочет -создать архив не из одного файла, а из целой папки. Тогда архивация сводится к поочередному -добавлению элемента ZipEntry для каждого файла в архив. -Нам нужно написать класс FileManager для получения списка всех файлов в какой-то папке. У него должен -быть конструктор, который будет принимать путь Path rootPath, указывающий на корень (папку, файлы в -которой нас интересуют) и метод List getFileList(), который должен возвращать список -относительных путей всех файлов, которые находятся по пути rootPath, включая файлы в подпапках. -Директория, в которой будем искать, может задаваться только один раз в конструкторе. Поэтому, прямо в -конструкторе мы сразу можем сформировать список файлов (их относительных путей), сохранив его в -переменную класса List fileList. -Осталось только решить, как нам собрать все файлы, даже те, которые могут быть в папке, которая в папке, -которая в папке, которая в интересующей нас папке. Фух, чуть не вошел рекурсию. Хотя нам-то она и -поможет! Сделаем метод collectFileList(Path path), который будет складывать в переменную класса fileList -все файлы, обнаруженные внутри переданного пути path, вызывая сам себя для всех объектов, в -обнаруженных директориях. -1. Создай класс FileManager с конструктором FileManager(Path rootPath) throws IOException -2. Объяви и проинициализируй приватные переменные класса: -2.1. Path rootPath – корневой путь директории, файлы которой нас интересуют -2.2. List fileList – список относительных путей файлов внутри rootPath -3. Создай геттер для fileList -4. Реализуй метод void collectFileList(Path path) throws IOException, который должен: -4.1. Проверить, если переданный путь path является обычным файлом (используй метод -Files.isRegularFile), то получить его относительный путь относительно rootPath -и добавить его в список fileList. -4.2. Если переданный путь path, является директорией (узнать это поможет метод -Files.isDirectory), то пройтись по всему содержимому директории и вызвать -collectFileList(Path path), передав в path обнаруженные элементы. -Пройтись по всему содержимому директории можно предварительно получив DirectoryStream с помощью метода -newDirectoryStream класса Files. Не забудь закрыть созданный DirectoryStream. -5. Добавь вызов метода collectFileList(rootPath) в конструкторе FileManager. -6. Примени все свои знания об инкапсуляции к этому классу. -Выполняя это задание, ты написал алгоритм, который обходит дерево файлов. Но в Java есть специальный интерфейс -FileVisitor для этих целей. Очень рекомендую разобраться как им пользоваться. - - - -Archiver (8) - -Чтобы узнать какую команду сейчас хочет выполнить пользователь, добавим метод Operation -askOperation() в класс Archiver. Этот метод должен вывести в консоль список доступных команд и -попросить выбрать одну из них. Для удобства будем просить ввести номер команды, где номер – это -порядковый номер команды в enum Operation. Получить порядковый номер значения в enum’е можно с -помощью метода ordinal(). -Теперь все готово чтобы переписать main, используя последние достижения науки и техники, а именно -класс CommandExecutor и метод askOperation(). -1. Добавь публичный статический метод Operation askOperation() throws IOException в класс Archiver. -Он должен: -1.1. Использовать методы класса ConsoleHelper -1.2. Запрашивать у пользователя номер операции, которую он хочет совершить. Подсказка: -чтобы вывести номер операции «Создать архив», используй: Operation.CREATE.ordinal() -1.3. Возвращать выбранную операцию. -Пример вывода метода askOperation(): -Выберите операцию: -0 - упаковать файлы в архив -1 - добавить файл в архив -2 - удалить файл из архива -3 - распаковать архив -4 - просмотреть содержимое архива -5 – выход -2. Перепиши метод main(): -2.1. Объяви локальную переменную типа Operation -2.2. В цикле запрашивай новое значение для переменной п.2.1. с помощью метода askOperation() и -вызывай выполнение операции с помощью CommandExecutor.execute() -2.3. Обеспечь выход из цикла, если пользователь выбрал операцию Operation.EXIT -2.4. Оберни вызов askOperation() и execute(operation) в блок try-catch. Если произойдет -исключение WrongZipFileException выведи сообщение "Вы не выбрали файл архива или -выбрали неверный файл." с помощью ConsoleHelper, при любых других исключениях -выводи "Произошла ошибка. Проверьте введенные данные.". -2.5. Проследи, чтобы программа продолжила свою работу (перешла на новый шаг цикла), -после обработки исключений. -3. Запусти программу и проверь, что команда “выход” работает. - - From d998d990b701d8f19fa87aad4c2c2a17d891bbd9 Mon Sep 17 00:00:00 2001 From: PeucT Date: Thu, 30 Mar 2017 18:16:50 +0400 Subject: [PATCH 16/51] Level 28. 2801-2805 --- .../task/task28/task2801/Solution.java | 37 +++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 25 ++++++ .../task/task28/task2802/Solution.java | 63 +++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 31 +++++++ .../task/task28/task2803/Solution.java | 24 ++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 18 +++++ .../task/task28/task2804/Solution.java | 81 +++++++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 19 +++++ .../task/task28/task2805/MyThread.java | 64 +++++++++++++++ .../task/task28/task2805/Solution.java | 25 ++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 17 ++++ 11 files changed, 404 insertions(+) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task28/task2801/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task28/task2801/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task28/task2802/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task28/task2802/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task28/task2803/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task28/task2803/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task28/task2804/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task28/task2804/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task28/task2805/MyThread.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task28/task2805/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task28/task2805/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2801/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2801/Solution.java new file mode 100644 index 0000000..fabd6a6 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2801/Solution.java @@ -0,0 +1,37 @@ +package com.javarush.task.task28.task2801; + +/* +Осваиваем switch +*/ +public class Solution { + public static enum E1 {A, B, C, Y} + + public static enum E2 {D, E, F} + + public static enum E3 {D, E, F} + + public static void main(String[] args) { + Solution.switchTest(E1.C); + Solution.switchTest(E3.D); + Solution.switchTest(E2.D); + /* output + it's E1.C + undefined + it's E2.D + */ + } + + public static void switchTest(Enum obj) { + //add your code here + switch (obj.getClass().getSimpleName()){ + case "E1": + System.out.println(String.format("it's %s.%s", obj.getClass().getSimpleName(), obj.toString())); + break; + case "E2": + System.out.println(String.format("it's %s.%s", obj.getClass().getSimpleName(), obj.toString())); + break; + default: + System.out.println("undefined"); + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2801/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2801/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..df0b363 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2801/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,25 @@ +taskKey="com.javarush.task.task28.task2801" + +Осваиваем switch + +Реализуй логику метода switchTest: +1. Не используй условные операторы. +2. Используй 1 switch, у которого 2 case и 1 default. +3. Ожидаемый вывод: +Вывод для E1.A - "it's E1.A" +Вывод для E1.B - "it's E1.B" +Вывод для E1.C - "it's E1.C" +Вывод для E1.Y - "it's E1.Y" +Вывод для E2.D - "it's E2.D" +Вывод для E2.E - "it's E2.E" +Вывод для E2.F - "it's E2.F" +Вывод для всех других значений - "undefined". + + +Требования: +1. Класс Solution должен содержать метод switchTest и enums E1, E2, E3. +2. Реализуйте метод switchTest, используя 1 switch, у которого 2 case и 1 default. +3. Вывод в консоль должен соответствовать условию задачи. +4. Использовать условные операторы нельзя. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2802/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2802/Solution.java new file mode 100644 index 0000000..6dd70ba --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2802/Solution.java @@ -0,0 +1,63 @@ +package com.javarush.task.task28.task2802; + + +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; + +/* +Пишем свою ThreadFactory +*/ +public class Solution { + + public static void main(String[] args) { + class EmulateThreadFactoryTask implements Runnable { + @Override + public void run() { + emulateThreadFactory(); + } + } + + ThreadGroup group = new ThreadGroup("firstGroup"); + Thread thread = new Thread(group, new EmulateThreadFactoryTask()); + + ThreadGroup group2 = new ThreadGroup("secondGroup"); + Thread thread2 = new Thread(group2, new EmulateThreadFactoryTask()); + + thread.start(); + thread2.start(); + } + + public static class AmigoThreadFactory implements ThreadFactory{ + private static AtomicInteger fabricsCount = new AtomicInteger(0); + private AtomicInteger threadsCount = new AtomicInteger(0); + + public AmigoThreadFactory(){ + fabricsCount.set(fabricsCount.incrementAndGet()); + } + + @Override + public Thread newThread(Runnable r) { + String groupName = Thread.currentThread().getThreadGroup().getName(); + + threadsCount.set(threadsCount.incrementAndGet()); + Thread thread = new Thread(String.format("%s-pool-%d-thread-%d", groupName, fabricsCount.get(), threadsCount.get() )); + thread.setDaemon(false); + thread.setPriority(Thread.NORM_PRIORITY); + System.out.println(thread.getName()); + return thread; + } + } + + private static void emulateThreadFactory() { + AmigoThreadFactory factory = new AmigoThreadFactory(); + Runnable r = new Runnable() { + @Override + public void run() { + System.out.println(Thread.currentThread().getName()); + } + }; + factory.newThread(r).start(); + factory.newThread(r).start(); + factory.newThread(r).start(); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2802/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2802/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..e17be84 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2802/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,31 @@ +taskKey="com.javarush.task.task28.task2802" + +Пишем свою ThreadFactory + +В классе Solution создай публичный статический класс AmigoThreadFactory, реализующий интерфейс ThreadFactory. +1. Реализация интерфейсного метода - создайте и верните трэд, который должен: +1.1. не быть демоном, +1.2. иметь нормальный приоритет, +1.3. имя трэда должно иметь шаблон "GN-pool-A-thread-B", где +GN - это имя группы, +A - это номер фабрики инкрементируется в пределах класса начиная с 1, используйте AtomicInteger, +B - номер треда инкрементируется в пределах конкретной фабрики начиная с 1, используйте AtomicInteger. +2. Каждая фабрика должна иметь ту группу тредов (ThreadGroup), в которой она была создана. +3. Методы main и emulateThreadFactory не участвуют в тестировании. +Пример вывода: +secondGroup-pool-2-thread-1 +firstGroup-pool-1-thread-1 +firstGroup-pool-1-thread-3 +secondGroup-pool-2-thread-3 +firstGroup-pool-1-thread-2 +secondGroup-pool-2-thread-2 + + +Требования: +1. В классе Solution нужно создать класс public static AmigoThreadFactory, который реализует интерфейс ThreadFactory. +2. Фабрика AmigoThreadFactory должна создавать трэды, которые не являются демоном. +3. Фабрика AmigoThreadFactory должна создавать трэды, которые имеют нормальный приоритет. +4. Фабрика AmigoThreadFactory должна создавать имена для трэдов по шаблону "GN-pool-A-thread-B". +5. Каждая фабрика должна производить трэды с группой (ThreadGroup), в которой она была создана. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2803/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2803/Solution.java new file mode 100644 index 0000000..7c23455 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2803/Solution.java @@ -0,0 +1,24 @@ +package com.javarush.task.task28.task2803; + +import java.util.concurrent.ThreadLocalRandom; + +/* +ThreadLocalRandom +*/ +public class Solution { + + public static int getRandomIntegerBetweenNumbers(int from, int to) { + return ThreadLocalRandom.current().nextInt(from, to); + } + + public static double getRandomDouble() { + return ThreadLocalRandom.current().nextDouble(); + } + + public static long getRandomLongBetween0AndN(long n) { + return ThreadLocalRandom.current().nextLong(n); + } + + public static void main(String[] args) { + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2803/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2803/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..170ddc8 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2803/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,18 @@ +taskKey="com.javarush.task.task28.task2803" + +ThreadLocalRandom + +Класс Solution будет использоваться трэдами. +Реализуй логику всех методов, используйте класс ThreadLocalRandom. +getRandomIntegerBetweenNumbers должен возвращать случайный int между from и to. +getRandomDouble должен возвращать случайный double. +getRandomLongBetween0AndN должен возвращать случайный long между 0 и n. + + +Требования: +1. В классе Solution должны быть только статические методы. +2. Метод getRandomIntegerBetweenNumbers с помощью ThreadLocalRandom должен возвращать случайный int между from и to. +3. Метод getRandomDouble с помощью ThreadLocalRandom должен возвращать случайный double от 0 до 1. +4. Метод getRandomLongBetween0AndN с помощью ThreadLocalRandom должен возвращать случайный long между 0 и n. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2804/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2804/Solution.java new file mode 100644 index 0000000..3bc7424 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2804/Solution.java @@ -0,0 +1,81 @@ +package com.javarush.task.task28.task2804; + +import java.util.List; +import java.util.concurrent.ConcurrentSkipListSet; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.ThreadLocalRandom; + +/* +Magic class +*/ +public class Solution { + public static void main(String[] args) throws InterruptedException { + Solution solution = new Solution(); + //List list = null/* create object of this magic class here*/; + List list = new CopyOnWriteArrayList(); + solution.startUpdatingThread(list); + solution.copyOnWriteSolution(list); + solution.stopUpdatingThread(); + + /* The output example +size = 0 +Element :s781859336 +Element :s1453499757 +Element :s911312405 +Element :s-877520242 +Element :s-1636258097 +size = 5 + +Element2 :s781859336 +Element2 :s1453499757 +Element2 :s911312405 +Element2 :s-877520242 +Element2 :s-1636258097 +Element2 :s-1739827856 +Element2 :s-938954654 +Element2 :s925086217 +size = 8 + */ + } + + public void copyOnWriteSolution(List list) throws InterruptedException { + System.out.println("size = " + list.size()); + System.out.println(); + Thread.sleep(20); + for (String element : list) { //создает новую копию на момент создания итератора + System.out.println("Element :" + element); + } + System.out.println("size = " + list.size()); + System.out.println(); + Thread.sleep(20); + + for (String element : list) { //создает новую копию на момент создания итератора + System.out.println("Element2 :" + element); + } + System.out.println("size = " + list.size()); + stopUpdatingThread(); + } + + public void stopUpdatingThread() throws InterruptedException { + t.stop(); + t.join(); + } + + private Thread t; + + private void startUpdatingThread(final List list) { + t = new Thread(new Runnable() { + @Override + public void run() { + for (int i = 0; i < 20; i++) { + list.add("s" + ThreadLocalRandom.current().nextInt()); + try { + Thread.sleep(5); + } catch (InterruptedException e) { + } + } + } + }); + t.start(); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2804/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2804/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..4105258 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2804/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,19 @@ +taskKey="com.javarush.task.task28.task2804" + +Magic class + +В пакете java.util.concurrent найди такую реализацию List, у которой: +1. Итератор не содержит какие-либо данные, вставленные в список после создания итератора; +2. Внутри данные хранятся в виде массива; +3. Итератор гарантированно не бросает ConcurrentModificationException; +4. Допускаются все элементы включая null; +5. Исправь строку List list = null ... в методе main. + + +Требования: +1. Класс Solution изменять нельзя. +2. Реализацию методов startUpdatingThread и stopUpdatingThread менять нельзя. +3. Реализацию метода copyOnWriteSolution менять нельзя. +4. Добавь в main создание нужного экземпляра List согласно заданию. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2805/MyThread.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2805/MyThread.java new file mode 100644 index 0000000..77f182c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2805/MyThread.java @@ -0,0 +1,64 @@ +package com.javarush.task.task28.task2805; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Created by ArchMage on 30.03.17. + */ +public class MyThread extends Thread{ + private static AtomicInteger count = new AtomicInteger(0); + + private int increment(){ + if (count.get() == Thread.MAX_PRIORITY) { + count.set(Thread.MIN_PRIORITY); + return 1; + } else { + count.set(count.incrementAndGet()); + int tempCount = count.get(); + if (tempCount > Thread.currentThread().getThreadGroup().getMaxPriority()) { + return Thread.currentThread().getPriority(); + } else { + return tempCount; + } + } + } + + public MyThread() { + this.setPriority(increment()); + } + + public MyThread(Runnable target) { + super(target); + this.setPriority(increment()); + } + + public MyThread(ThreadGroup group, Runnable target) { + super(group, target); + this.setPriority(increment()); + } + + public MyThread(String name) { + super(name); + this.setPriority(increment()); + } + + public MyThread(ThreadGroup group, String name) { + super(group, name); + this.setPriority(increment()); + } + + public MyThread(Runnable target, String name) { + super(target, name); + this.setPriority(increment()); + } + + public MyThread(ThreadGroup group, Runnable target, String name) { + super(group, target, name); + this.setPriority(increment()); + } + + public MyThread(ThreadGroup group, Runnable target, String name, long stackSize) { + super(group, target, name, stackSize); + this.setPriority(increment()); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2805/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2805/Solution.java new file mode 100644 index 0000000..bc23631 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2805/Solution.java @@ -0,0 +1,25 @@ +package com.javarush.task.task28.task2805; + +/* +Приоритеты в Threads +*/ +public class Solution { + + public static void main(String[] args) { + for (int i = 0; i < 12; i++) { + System.out.print(new MyThread().getPriority() + " "); + } + //output + //1 2 3 4 5 6 7 8 9 10 1 2 + + System.out.println(); + ThreadGroup group = new ThreadGroup("someName"); + group.setMaxPriority(7); + for (int i = 0; i < 12; i++) { + System.out.print(new MyThread(group, "name" + i).getPriority() + " "); + } + //output + //3 4 5 6 7 7 7 7 1 2 3 4 + } + +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2805/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2805/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..b546b57 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2805/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,17 @@ +taskKey="com.javarush.task.task28.task2805" + +Приоритеты в Threads + +В отдельном файле создай класс MyThread унаследовавшись от Thread. MyThread должен: +1. Иметь возможность быть созданным используя любой конструктор супер-класса (Alt+Insert). +2. Приоритет у трэдов должен проставляться циклично от минимального значения до максимального значения. +3. если у трэда установлена трэд-группа(ThreadGroup), то приоритет трэда не может быть больше максимального приоритета его трэд-группы. + + +Требования: +1. Создай класс MyThread в отдельном файле. Унаследуй его от Thread. +2. В классе MyThread должны присутствовать конструкторы, аналогичные конструкторам супер-класса. +3. Приоритет у объектов MyThread должен проставляться циклично, от MIN_PRIORITY до MAX_PRIORITY. +4. Если у объекта MyThread установлена ThreadGroup, приоритет MyThread не должен быть выше максимального приоритета ThreadGroup. + + From 1089864d0176cc53cc26a3302f2fa5db858828c4 Mon Sep 17 00:00:00 2001 From: PeucT Date: Mon, 3 Apr 2017 02:25:12 +0300 Subject: [PATCH 17/51] task 2026 --- .../task/task20/task2026/Solution.java | 28 +++++++++++++++- ...\273\320\276\320\262\320\270\320\265.jrtc" | 33 ++++++++++++------- 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/2.JavaCore/src/com/javarush/task/task20/task2026/Solution.java b/2.JavaCore/src/com/javarush/task/task20/task2026/Solution.java index 79f49af..d684518 100644 --- a/2.JavaCore/src/com/javarush/task/task20/task2026/Solution.java +++ b/2.JavaCore/src/com/javarush/task/task20/task2026/Solution.java @@ -16,6 +16,32 @@ public static void main(String[] args) { } public static int getRectangleCount(byte[][] a) { - return 0; + byte[][] temp; + temp = a.clone(); + for (int i = 0; i < temp.length; i++){ + for (int j = 0; j < temp.length - 1; j++){ + if (temp[i][j] == 1 && temp[i][j+1] == 1) { + temp[i][j] = 0; + } + } + } + + for (int i = 0; i < temp.length - 1; i++){ + for (int j = 0; j < temp.length; j++){ + if (temp[i][j] == 1 && temp[i+1][j] == 1) { + temp[i][j] = 0; + } + } + } + + int summ = 0; + for (int i = 0; i < temp.length; i++){ + for (int j = 0; j < temp.length; j++){ + if (temp[i][j] == 1) { + summ++; + } + } + } + return summ; } } diff --git "a/2.JavaCore/src/com/javarush/task/task20/task2026/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/2.JavaCore/src/com/javarush/task/task20/task2026/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" index 8716419..f0984cd 100644 --- "a/2.JavaCore/src/com/javarush/task/task20/task2026/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" +++ "b/2.JavaCore/src/com/javarush/task/task20/task2026/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -1,12 +1,21 @@ -

-

Алгоритмы-прямоугольники

-

1. Дан двумерный массив N*N, который содержит несколько прямоугольников.
-2. Различные прямоугольники не соприкасаются и не накладываются.
-3. Внутри прямоугольник весь заполнен 1.
-4. В массиве:
-4.1) a[i, j] = 1, если элемент (i, j) принадлежит какому-либо прямоугольнику
-4.2) a[i, j] = 0, в противном случае
-5. getRectangleCount должен возвращать количество прямоугольников.
-6. Метод main не участвует в тестировании

- -
+taskKey="com.javarush.task.task20.task2026" + +Алгоритмы-прямоугольники + +1. Дан двумерный массив N*N, который содержит несколько прямоугольников. +2. Различные прямоугольники не соприкасаются и не накладываются. +3. Внутри прямоугольник весь заполнен 1. +4. В массиве: +4.1) a[i, j] = 1, если элемент (i, j) принадлежит какому-либо прямоугольнику +4.2) a[i, j] = 0, в противном случае +5. getRectangleCount должен возвращать количество прямоугольников. +6. Метод main не участвует в тестировании + + +Требования: +1. В классе Solution должен существовать метод getRectangleCount с одним параметром типа byte[][]. +2. Метод getRectangleCount должен быть публичным. +3. Метод getRectangleCount должен быть статическим. +4. Метод getRectangleCount должен возвращать количество прямоугольников (в соответствии с заданием) найденное в полученном массиве. + + From 50314898f86db3039fd44ccf757df5a0be51ad79 Mon Sep 17 00:00:00 2001 From: PeucT Date: Mon, 3 Apr 2017 02:25:43 +0300 Subject: [PATCH 18/51] 2806 - 2813 --- .../task/task28/task2806/Solution.java | 45 +++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 19 +++++++ .../task/task28/task2807/Solution.java | 45 +++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 28 ++++++++++ .../task/task28/task2808/Solution.java | 56 +++++++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 16 ++++++ .../task/task28/task2809/Character.java | 26 +++++++++ .../javarush/task/task28/task2809/Plant.java | 12 ++++ .../task/task28/task2809/Solution.java | 45 +++++++++++++++ .../javarush/task/task28/task2809/Zombie.java | 13 +++++ .../javarush/task/task28/task2809/output.txt | 21 +++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 23 ++++++++ .../task/task28/task2811/ReadWriteMap.java | 35 ++++++++++++ .../task/task28/task2811/Solution.java | 13 +++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 21 +++++++ .../task/task28/task2812/Solution.java | 32 +++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 26 +++++++++ .../task28/task2813/FactorialCalculator.java | 29 ++++++++++ .../task/task28/task2813/Solution.java | 31 ++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 17 ++++++ 20 files changed, 553 insertions(+) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task28/task2806/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task28/task2806/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task28/task2807/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task28/task2807/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task28/task2808/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task28/task2808/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task28/task2809/Character.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task28/task2809/Plant.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task28/task2809/Solution.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task28/task2809/Zombie.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task28/task2809/output.txt create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task28/task2809/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task28/task2811/ReadWriteMap.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task28/task2811/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task28/task2811/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task28/task2812/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task28/task2812/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task28/task2813/FactorialCalculator.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task28/task2813/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task28/task2813/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2806/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2806/Solution.java new file mode 100644 index 0000000..5e079bf --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2806/Solution.java @@ -0,0 +1,45 @@ +package com.javarush.task.task28.task2806; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/* +Знакомство с Executors +*/ +public class Solution { + public static void main(String[] args) throws InterruptedException { + //Add your code here + + ExecutorService executor = Executors.newFixedThreadPool(5); + for (int i = 1; i <= 10; i++){ + final int j = i; + executor.submit(new Runnable() { + @Override + public void run() { + doExpensiveOperation(j); + } + }); + } + executor.shutdown(); + executor.awaitTermination(5, TimeUnit.SECONDS); + + /* output example +pool-1-thread-2, localId=2 +pool-1-thread-1, localId=1 +pool-1-thread-3, localId=3 +pool-1-thread-1, localId=7 +pool-1-thread-1, localId=9 +pool-1-thread-4, localId=4 +pool-1-thread-5, localId=5 +pool-1-thread-2, localId=6 +pool-1-thread-1, localId=10 +pool-1-thread-3, localId=8 + */ + } + + private static void doExpensiveOperation(int localId) { + System.out.println(Thread.currentThread().getName() + ", localId="+localId); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2806/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2806/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..7d559ee --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2806/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,19 @@ +taskKey="com.javarush.task.task28.task2806" + +Знакомство с Executors + +1. В методе main создай фиксированный пул из 5 трэдов используя класс Executors. +2. В цикле отправь на исполнение в пул 10 задач Runnable. +3. У каждой задачи в методе run вызови метод doExpensiveOperation с порядковым номером задачи начиная с 1, см. пример вывода. +4. Запрети добавление новых задач на исполнение в пул (метод shutdown). +5. Дай пулу 5 секунд на завершение всех задач (метод awaitTermination и параметр TimeUnit.SECONDS). + + +Требования: +1. Используя класс Executors, создай в методе main фиксированный пул из 5 трэдов. +2. Пул должен принимать на исполнение 10 задач Runnable. +3. Каждая задача должна вызывать метод doExpensiveOperation с порядковым номером задачи, начиная с 1. +4. Запрети добавление новых задач на исполнение в пул. +5. На завершение всех задач в пуле нужно установить 5 секунд. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2807/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2807/Solution.java new file mode 100644 index 0000000..4cad783 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2807/Solution.java @@ -0,0 +1,45 @@ +package com.javarush.task.task28.task2807; + +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/* +Знакомство с ThreadPoolExecutor +*/ +public class Solution { + public static void main(String[] args) throws InterruptedException { + //Add your code here + LinkedBlockingQueue queue = new LinkedBlockingQueue<>(); + for (int i = 1; i <= 10; i++){ + final int j = i; + queue.add(new Runnable() { + + @Override + public void run() { + doExpensiveOperation(j); + } + }); + } + ThreadPoolExecutor poolExecuter = new ThreadPoolExecutor(3, 5, 1000, TimeUnit.MILLISECONDS, queue); + poolExecuter.prestartAllCoreThreads(); + poolExecuter.shutdown(); + poolExecuter.awaitTermination(5, TimeUnit.SECONDS); + /* output example +pool-1-thread-2, localId=2 +pool-1-thread-3, localId=3 +pool-1-thread-1, localId=1 +pool-1-thread-3, localId=5 +pool-1-thread-2, localId=4 +pool-1-thread-3, localId=7 +pool-1-thread-1, localId=6 +pool-1-thread-3, localId=9 +pool-1-thread-2, localId=8 +pool-1-thread-1, localId=10 + */ + } + + private static void doExpensiveOperation(int localId) { + System.out.println(Thread.currentThread().getName() + ", localId=" + localId); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2807/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2807/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..4aed6c5 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2807/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,28 @@ +taskKey="com.javarush.task.task28.task2807" + +Знакомство с ThreadPoolExecutor + +1. В методе main создай очередь LinkedBlockingQueue. +2. В цикле добавь в очередь 10 задач Runnable. +3. У каждой задачи в методе run вызови метод doExpensiveOperation с порядковым номером задачи начиная с 1, см. пример вывода. +4. Создай объект ThreadPoolExecutor со следующими параметрами: +- основное количество трэдов (ядро) = 3, +- максимальное количество трэдов = 5, +- время удержания трэда живым после завершения работы = 1000, +- тайм-юнит - миллисекунды, +- созданная в п.1. очередь с задачами. +5. Запусти все трэды, которые входят в основное кол-во трэдов - ядро, используй метод prestartAllCoreThreads. +6. Запрети добавление новых задач на исполнение в пул (метод shutdown). +7. Дай объекту ThreadPoolExecutor 5 секунд на завершение всех тасок (метод awaitTermination и параметр TimeUnit.SECONDS). + + +Требования: +1. В методе main нужно создать очередь LinkedBlockingQueue. +2. В цикле добавь в очередь 10 задач Runnable. +3. Нужно создать объект ThreadPoolExecutor с параметрами, указанными в задании. +4. С помощью метода prestartAllCoreThreads нужно запустить основные трэды. +5. Каждая задача должна вызывать метод doExpensiveOperation с порядковым номером задачи, начиная с 1. +6. Запрети добавление новых задач на исполнение в пул. +7. На завершение всех задач в пуле нужно установить 5 секунд. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2808/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2808/Solution.java new file mode 100644 index 0000000..9275efe --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2808/Solution.java @@ -0,0 +1,56 @@ +package com.javarush.task.task28.task2808; + + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.*; + +/* +Осваиваем Callable +*/ +public class Solution { + public static void main(String[] args) throws InterruptedException, ExecutionException { + List> futures = new ArrayList<>(); + ExecutorService executor = Executors.newFixedThreadPool(5); + for (int i = 1000; i <= 1010; i++) { + futures.add(executor.submit(getTask(i))); + } + + futures.add(executor.submit(getTask(10000000))); + + for(Future future : futures) { + System.out.println(future.get()); + } + + executor.shutdown(); + executor.awaitTermination(10, TimeUnit.SECONDS); + +/* output +500500 +501501 +502503 +503506 +504510 +505515 +506521 +507528 +508536 +509545 +510555 +50000005000000 +*/ + } + + public static Callable getTask(final int i) { + return new Callable() { + @Override + public String call() throws Exception { + long summ = 0; + for (int j = 1; j <= i; j++ ){ + summ +=j; + } + return String.valueOf(summ); + } + }; + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2808/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2808/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..036951e --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2808/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,16 @@ +taskKey="com.javarush.task.task28.task2808" + +Осваиваем Callable + +Реализуй логику метода getTask, который должен возвращать объект Callable. +Объект Callable должен вычислять сумму всех чисел от 1 до переданного числа i включая его, и возвращать его в виде строки. +Метод main не участвует в тестировании. + + +Требования: +1. Класс Solution должен содержать статический метод getTask(int). +2. Метод getTask должен возвращать объект Callable. +3. Объект Callable должен возвращать в виде строки сумму всех чисел от 1 до переданного числа i, включая его +4. Сумма должна правильно считаться для чисел произвольной длины. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Character.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Character.java new file mode 100644 index 0000000..e276185 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Character.java @@ -0,0 +1,26 @@ +package com.javarush.task.task28.task2809; + +import java.util.concurrent.ThreadLocalRandom; + +public abstract class Character implements Runnable { + protected abstract int getId(); + + public void run() { + System.out.println(toString() + " вступил в игру"); + doSomething(); + System.out.println(toString() + " умер"); + } + + private void doSomething() { + try { + Thread.currentThread().sleep(ThreadLocalRandom.current().nextInt(10, 100)); + } catch (InterruptedException ignored) { + } + } + + @Override + public String toString() { + return getClass().getSimpleName() + " #" + getId(); + } + +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Plant.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Plant.java new file mode 100644 index 0000000..6ac7a67 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Plant.java @@ -0,0 +1,12 @@ +package com.javarush.task.task28.task2809; + +import java.util.concurrent.atomic.AtomicInteger; + +public class Plant extends Character { + private final static AtomicInteger idSequence = new AtomicInteger(); + private final int id = idSequence.incrementAndGet(); + + protected int getId() { + return id; + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Solution.java new file mode 100644 index 0000000..ddc65ac --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Solution.java @@ -0,0 +1,45 @@ +package com.javarush.task.task28.task2809; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Phaser; + +/* +Plants vs Zombies +*/ +public class Solution { + public static void main(String[] args) throws InterruptedException { + List characters = new ArrayList<>(); + characters.add(new Plant()); + characters.add(new Plant()); + characters.add(new Zombie()); + characters.add(new Zombie()); + characters.add(new Zombie()); + start(characters); + } + + private static boolean isEveryoneReady = false; + + private static void start(List characters) throws InterruptedException { + final Phaser phaser = new Phaser(1 + characters.size()); + + for (final Character character : characters) { + final String member = character.toString(); + System.out.println(member + " присоединился к игре"); + new Thread() { + @Override + public void run() { + System.out.println(member + " готовится играть"); + + phaser.arriveAndAwaitAdvance(); + if (!isEveryoneReady) { + isEveryoneReady = true; + System.out.println("Игра началась!"); + } + character.run(); + } + }.start(); + } + phaser.arriveAndDeregister(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Zombie.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Zombie.java new file mode 100644 index 0000000..13f671b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Zombie.java @@ -0,0 +1,13 @@ +package com.javarush.task.task28.task2809; + +import java.util.concurrent.atomic.AtomicInteger; + +public class Zombie extends Character { + private final static AtomicInteger idSequence = new AtomicInteger(); + private final int id = idSequence.incrementAndGet(); + + protected int getId() { + return id; + } +} + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2809/output.txt b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/output.txt new file mode 100644 index 0000000..a708313 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/output.txt @@ -0,0 +1,21 @@ +Plant #1 присоединился к игре +Plant #2 присоединился к игре +Plant #1 готовится играть +Zombie #1 присоединился к игре +Zombie #2 присоединился к игре +Zombie #3 присоединился к игре +Plant #2 готовится играть +Zombie #2 готовится играть +Zombie #1 готовится играть +Zombie #3 готовится играть +Игра началась! +Zombie #1 вступил в игру +Zombie #3 вступил в игру +Plant #1 вступил в игру +Zombie #2 вступил в игру +Plant #2 вступил в игру +Zombie #2 умер +Plant #2 умер +Plant #1 умер +Zombie #3 умер +Zombie #1 умер \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2809/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..a55f173 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,23 @@ +taskKey="com.javarush.task.task28.task2809" + +Plants vs Zombies + +1. Почитай про java.util.concurrent.Phaser. +2. Расставь методы в нужных местах: +-arriveAndDeregister() - начинает запускать методы run у тасок, +-arriveAndAwaitAdvance() - ждет, когда все трэды будут созданы. + +Пример вывода см. в output.txt. +Логика: +Сначала все персонажи присоединяются к игре. +После того, как все персонажи присоединятся к игре и готовы играть, выводится фраза "Игра началась!". +После этого персонажи вступают в игру, после чего умирают. + + +Требования: +1. Класс Character менять не нужно. +2. Классы Plant и Zombie менять не нужно. +3. В классе Solution вызови метод phaser.arriveAndDeregister в правильном месте. +4. В классе Solution вызови метод phaser.arriveAndAwaitAdvance в правильном месте. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2811/ReadWriteMap.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2811/ReadWriteMap.java new file mode 100644 index 0000000..375c8c2 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2811/ReadWriteMap.java @@ -0,0 +1,35 @@ +package com.javarush.task.task28.task2811; + +import java.util.Map; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +public class ReadWriteMap { + private final Map map; + private final ReadWriteLock lock = new ReentrantReadWriteLock(); + private final Lock readLock = lock.readLock(); + private final Lock writeLock = lock.writeLock(); + + public ReadWriteMap(Map map) { + this.map = map; + } + + public V put(K key, V value) { + try { + writeLock.lock(); + return map.put(key, value); + } finally { + writeLock.unlock(); + } + } + + public V get(K key) { + try { + readLock.lock(); + return map.get(key); + } finally { + readLock.unlock(); + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2811/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2811/Solution.java new file mode 100644 index 0000000..1097c94 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2811/Solution.java @@ -0,0 +1,13 @@ +package com.javarush.task.task28.task2811; + +/* +ReentrantReadWriteLock +*/ + +import java.util.LinkedHashMap; + +public class Solution { + public static void main(String[] args) { + ReadWriteMap linkedSafeMap = new ReadWriteMap<>(new LinkedHashMap<>()); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2811/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2811/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..9678539 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2811/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,21 @@ +taskKey="com.javarush.task.task28.task2811" + +ReentrantReadWriteLock + +Класс ReadWriteMap должен предоставлять корректный доступ к объекту Map из многих потоков, но в его реализации +были допущены ошибки. Найди их и исправь. + +P.S. Для корректной работы Map в многопоточной среде, желательно пользоваться стандартной реализацией, например +ConcurrentHashMap из пакета java.util.concurrent. Но иногда требуется работа с другим типом мапы, например +LinkedHashMap и тогда предложенное решение будет как никогда кстати. + + +Требования: +1. Поле readLock должно быть инициализировано с помощью метода readLock вызванного на объекте lock. +2. Поле writeLock должно быть инициализировано с помощью метода writeLock вызванного на объекте lock. +3. В методе put должен быть вызван метод lock на объекте writeLock. +4. В методе get должен быть вызван метод lock на объекте readLock. +5. В методе put в блоке finally должен быть вызван метод unlock на объекте writeLock. +6. В методе get в блоке finally должен быть вызван метод unlock на объекте readLock. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2812/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2812/Solution.java new file mode 100644 index 0000000..8ba6de7 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2812/Solution.java @@ -0,0 +1,32 @@ +package com.javarush.task.task28.task2812; + +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/* +ShutdownNow! +*/ + +public class Solution { + public static void main(String[] args) throws InterruptedException { + ExecutorService executor = Executors.newFixedThreadPool(5); + for (int i = 1; i <= 10; i++) { + final int localId = i; + executor.submit(new Runnable() { + public void run() { + doExpensiveOperation(localId); + } + }); + } + + List list = executor.shutdownNow(); + for (Runnable task: list){ + System.out.println(task.toString()); + } + } + + private static void doExpensiveOperation(int localId) { + System.out.println(Thread.currentThread().getName() + ", localId="+localId); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2812/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2812/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..daa9f22 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2812/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,26 @@ +taskKey="com.javarush.task.task28.task2812" + +ShutdownNow! + +Разберись в чем отличие методов shutdown и shutdownNow. Выведи список всех незавершенных задач на экран. + +Должно получиться что-то вроде: +pool-1-thread-1, localId=1 +pool-1-thread-2, localId=2 +pool-1-thread-3, localId=3 +pool-1-thread-4, localId=4 +pool-1-thread-5, localId=5 +java.util.concurrent.FutureTask@7e6cbb7a was not completed +java.util.concurrent.FutureTask@7c3df479 was not completed +java.util.concurrent.FutureTask@7106e68e was not completed +java.util.concurrent.FutureTask@7eda2dbb was not completed +java.util.concurrent.FutureTask@6576fe71 was not completed + + +Требования: +1. В методе main класса Solution должен быть вызван метод shutdownNow на объекте executor. +2. В методе main класса Solution на экран должны быть выведены все задачи которые не успел выполнить executor. +3. Метод main должен быть публичным. +4. Метод main должен быть статическим. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2813/FactorialCalculator.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2813/FactorialCalculator.java new file mode 100644 index 0000000..8ad76cf --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2813/FactorialCalculator.java @@ -0,0 +1,29 @@ +package com.javarush.task.task28.task2813; + +import java.util.concurrent.Callable; + +public class FactorialCalculator implements Callable { + private final int number; + + public FactorialCalculator(int number) { + this.number = number; + } + + @Override + public Long call() throws InterruptedException { + return factorial(number); + } + + public long factorial(int number) throws InterruptedException { + if (number < 0) { + throw new IllegalArgumentException("Number must be greater than zero"); + } + long result = 1; + while (number > 1) { + Thread.sleep(1); + result = result * number; + number--; + } + return result; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2813/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2813/Solution.java new file mode 100644 index 0000000..ee4359b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2813/Solution.java @@ -0,0 +1,31 @@ +package com.javarush.task.task28.task2813; + +import java.util.concurrent.*; + +/* +FutureTask +*/ + +public class Solution { + private static final ExecutorService threadpool = Executors.newFixedThreadPool(4); + private static final int n = 16; + + public static void main(String args[]) throws InterruptedException, ExecutionException { + FactorialCalculator task = new FactorialCalculator(n); + + System.out.println("Submitting Task ..."); + Future future = threadpool.submit(task); + System.out.println("Task was submitted successfully"); + + while (!future.isDone()) { + System.out.println("Task is not completed yet...."); + Thread.sleep(1); + } + + System.out.println("Task is completed, let's check the result"); + long factorial = (long) future.get(); + + System.out.println("Factorial of " + n + " is : " + factorial); + threadpool.shutdown(); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2813/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2813/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..6c78246 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2813/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,17 @@ +taskKey="com.javarush.task.task28.task2813" + +FutureTask + +Класс FactorialCalculator предназначен для вычисления факториала числа переданного в его конструктор в качестве +параметра. К сожалению, он реализован некорректно и тебе необходимо это исправить. + +Внимательно разбери метод main класса Solution. + + +Требования: +1. Класс FactorialCalculator должен поддерживать интерфейс Callable. +2. Метод call класса FactorialCalculator должен возвращать результат выполнения метода factorial. +3. Метод call класса FactorialCalculator должен быть публичным. +4. Поле number класса FactorialCalculator должно быть приватным. + + From 74185be3d7ecf7061737867015593533898f10ca Mon Sep 17 00:00:00 2001 From: PeucT Date: Mon, 3 Apr 2017 17:56:27 +0400 Subject: [PATCH 19/51] 2901 - 2904 --- .../task/task29/task2901/Solution.java | 51 +++++++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 18 +++++++ .../task/task29/task2902/Solution.java | 29 +++++++++++ .../javarush/task/task29/task2902/file.txt | 2 + ...\273\320\276\320\262\320\270\320\265.jrtc" | 18 +++++++ .../task/task29/task2903/Solution.java | 50 ++++++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 18 +++++++ .../task/task29/task2904/Solution.java | 24 +++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 15 ++++++ 9 files changed, 225 insertions(+) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2901/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task29/task2901/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2902/Solution.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2902/file.txt create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task29/task2902/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2903/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task29/task2903/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2904/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task29/task2904/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2901/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2901/Solution.java new file mode 100644 index 0000000..98b31b6 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2901/Solution.java @@ -0,0 +1,51 @@ +package com.javarush.task.task29.task2901; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.util.List; + +/* +Рефакторинг в соответствии с Naming and Code Convention +*/ +public class Solution { + public static final String DEFAULT_FILE_NAME = "C:/tmp/file_strange_name.tmp"; + + private final String LOCAL_FILE_NAME; + private List contentAslines; + private boolean isFileLoaded; + + public Solution(String firstFileName) { + LOCAL_FILE_NAME = firstFileName == null ? DEFAULT_FILE_NAME : firstFileName; + } + + public static void main(String[] args) throws FileNotFoundException { + String fileName = Solution.class.getResource("Solution.java").getPath(); + + Solution solution = new Solution(fileName); + solution.downloadFileContent(); + if (solution.isFileLoaded()) { + System.out.println(solution.hasFileExpectedLine("public class Solution {")); //expected true + System.out.println(solution.hasFileExpectedLine(" public class Solution {")); //expected false + } + } + + public boolean isFileLoaded() { + return isFileLoaded; + } + + public void downloadFileContent() { + try { + contentAslines = Files.readAllLines((new File(LOCAL_FILE_NAME)).toPath(), Charset.defaultCharset()); + isFileLoaded = true; + } catch (IOException e) { + System.out.println("Unsuccessful. What a surprise!"); + } + } + + public boolean hasFileExpectedLine(String expectedLine) { + return contentAslines.contains(expectedLine); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2901/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2901/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..16a2d01 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2901/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,18 @@ +taskKey="com.javarush.task.task29.task2901" + +Рефакторинг в соответствии с Naming and Code Convention + +Исправить код в соответствии с Naming and Code Convention (Shift+F6 для рефакторинга). + +Подсказка: IDEA не умеет правильно переименовывать имена классов, если меняется только регистр. +Переименуй имя класса во вспомогательное имя, а потом в это же в правильном регистре. + + +Требования: +1. Переименуй константу defaultFileName в соответствии с Naming and Code Convention. +2. Переименуй метод getFileLoaded в соответствии с Naming and Code Convention. +3. Переименуй метод DownloadFileContent в соответствии с Naming and Code Convention. +4. Переименуй метод isfileexpectedline в соответствии с Naming and Code Convention. +5. Переименуй параметр expectedline метода принимающего String в соответствии с Naming and Code Convention. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2902/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2902/Solution.java new file mode 100644 index 0000000..80f7914 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2902/Solution.java @@ -0,0 +1,29 @@ +package com.javarush.task.task29.task2902; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.Path; +import java.nio.file.Paths; + +/* +Рефакторинг в соответствии с Naming and Code Convention 2 +*/ +public class Solution { + public static void main(String[] args) throws IOException, InterruptedException, URISyntaxException { + Solution solution = new Solution(); + String fileNameToBeOpenedByNotepad = solution.getAbsolutePathToDefaultTxtFile().toString(); + Process notepad = solution.getProcessStartNotepad(fileNameToBeOpenedByNotepad); + notepad.waitFor(); + } + + public Process getProcessStartNotepad(String fileName) throws IOException { + String[] cmdArray = new String[]{"notepad.exe", fileName}; + return Runtime.getRuntime().exec(cmdArray); + } + + public Path getAbsolutePathToDefaultTxtFile() throws URISyntaxException { + URI uri = Solution.class.getResource("file.txt").toURI(); + return Paths.get(uri); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2902/file.txt b/3.JavaMultithreading/src/com/javarush/task/task29/task2902/file.txt new file mode 100644 index 0000000..2fe78f4 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2902/file.txt @@ -0,0 +1,2 @@ +This file will be opened by Notepad.exe +You can change the content. \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2902/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2902/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..dea4a4d --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2902/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,18 @@ +taskKey="com.javarush.task.task29.task2902" + +Рефакторинг в соответствии с Naming and Code Convention 2 + +Исправить код в соответствии с Naming and Code Convention (Shift+F6 для рефакторинга). + + +Требования: +1. Переименуй переменную Solution типа Solution в соответствии с Naming and Code Convention. +2. Переименуй переменную file_name_to_be_opened_by_notepad типа String в соответствии с Naming and Code Convention. +3. Переименуй переменную NOTEPAD типа Process в соответствии с Naming and Code Convention. +4. Переименуй метод getprocessstartnotepad в соответствии с Naming and Code Convention. +5. Переименуй параметр FILE_NAME метода принимающего String в соответствии с Naming and Code Convention. +6. Переименуй переменную cmd_array типа String[] в соответствии с Naming and Code Convention. +7. Переименуй метод Getabsolutepathtodefaulttxtfile в соответствии с Naming and Code Convention. +8. Переименуй переменную uRi типа URI в соответствии с Naming and Code Convention. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2903/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2903/Solution.java new file mode 100644 index 0000000..2db7802 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2903/Solution.java @@ -0,0 +1,50 @@ +package com.javarush.task.task29.task2903; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ThreadLocalRandom; + +/* +И еще раз рефакторинг +*/ +public class Solution { + public static final ThreadLocalRandom RANDOM = ThreadLocalRandom.current(); + + public static void main(String[] args) { + ConcurrentMap concurrentMap = new ConcurrentHashMap<>(); + for (int i = 0; i < 100; i++) { + new Thread(getRunnable(i, concurrentMap)).start(); + } + sleepASecond(); + } + + private static void sleepASecond() { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + public static Runnable getRunnable(final int i, final ConcurrentMap concurrentMap) { + return new Runnable() { + @Override + public void run() { + final String NAME = "Thread #" + i; + int randomInt = RANDOM.nextInt(20); + String text = NAME + " вставил запись для " + randomInt; + + //previousEntry is null if it is new entry + /* instead of null - call concurrentMap.someMethodName(randomInt, text)*/ + //String previousEntry = null; + String previousEntry = concurrentMap.putIfAbsent(randomInt, text); + + if (previousEntry != null) { + System.out.println(NAME + " хочет обновить " + randomInt + ", однако уже " + previousEntry); + } else { + System.out.println(text); + } + } + }; + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2903/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2903/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..fac6a84 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2903/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,18 @@ +taskKey="com.javarush.task.task29.task2903" + +И еще раз рефакторинг + +1. Исправить код в соответствии с Naming and Code Convention (Shift+F6 для рефакторинга) +2. Просмотри методы класса ConcurrentMap. +3. В строке "String previousEntry = null;" у concurrentMap вызови метод, +который вставит пару (randomInt, text) только для ключа, которого нет в concurrentMap. +(Вызванный метод должен возвращать предыдущее значение либо null для новой пары.) + + +Требования: +1. Переименуй константу random в соответствии с Naming and Code Convention. +2. Объект, возвращаемый методом getRunnable, должен быть экземпляром анонимного класса. +3. Метод run внутри метода getRunnable должен вызывать у concurrentMap метод, вставляющий пару (randomInt, text), если в concurrentMap еще нет пары со значением ключа randomInt. +4. Метод run класса, возвращаемого методом getRunnable, должен выводить текст на экран. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2904/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2904/Solution.java new file mode 100644 index 0000000..6de6207 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2904/Solution.java @@ -0,0 +1,24 @@ +package com.javarush.task.task29.task2904; + +/* +Особенности автобоксинга +*/ +public class Solution { + private Integer[] array = new Integer[]{1, 2, 3, 4}; + + public static void main(String[] args) { + Number value1 = new Solution().getValueByIndex(5); //-1.0, class java.lang.Double expected + Number value2 = new Solution().getValueByIndex(2); //3, class java.lang.Integer expected + + System.out.println(value1 + ", " + value1.getClass().toString()); + System.out.println(value2 + ", " + value2.getClass().toString()); + } + + Number getValueByIndex(int index) { + if (index >= 0 && index < array.length) { + return array[index]; + } else { + return new Double(-1); + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2904/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2904/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..ac38684 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2904/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,15 @@ +taskKey="com.javarush.task.task29.task2904" + +Особенности автобоксинга + +Исправь ошибку в методе getValueByIndex. +Читай доп. статью про особенности автобоксинга. + + +Требования: +1. Метод getValueByIndex должен возвращать объект типа Integer из массива array, если элемент с индексом index есть в массиве. +2. Метод getValueByIndex должен возвращать объект типа Double, равный -1, если в массиве array нет элемента с индексом index. +3. Метод main не изменять. +4. Программа должна вывести две строки: "-1.0, class java.lang.Double" и "3, class java.lang.Integer". + + From 4ed6f6b6ec1b432bb0a6a715ac89942b9567468e Mon Sep 17 00:00:00 2001 From: PeucT Date: Mon, 3 Apr 2017 17:57:54 +0400 Subject: [PATCH 20/51] 2027 --- .../task/task20/task2027/Solution.java | 90 ++++++++++++++++++- ...\273\320\276\320\262\320\270\320\265.jrtc" | 32 ++++--- 2 files changed, 110 insertions(+), 12 deletions(-) diff --git a/2.JavaCore/src/com/javarush/task/task20/task2027/Solution.java b/2.JavaCore/src/com/javarush/task/task20/task2027/Solution.java index 4cd979e..312bb4c 100644 --- a/2.JavaCore/src/com/javarush/task/task20/task2027/Solution.java +++ b/2.JavaCore/src/com/javarush/task/task20/task2027/Solution.java @@ -1,5 +1,6 @@ package com.javarush.task.task20.task2027; +import java.util.ArrayList; import java.util.List; /* @@ -20,11 +21,98 @@ public static void main(String[] args) { home - (5, 3) - (2, 0) same - (1, 1) - (4, 1) */ + } public static List detectAllWords(int[][] crossword, String... words) { + List list = new ArrayList<>(); + for (int k = 0; k < words.length; k++){ + Word resultString = new Word(words[k]); + for (int i = 0; i < crossword.length; i ++){ + for (int j = 0; j < crossword[0].length; j++){ + if (crossword[i][j] == words[k].charAt(0) ) { + + // Чтобы не заморачиваться проверкой выхода за границы массива, оборачиваем все обращения + // к ячейкам соседним с рассматриваемой ячейкой (в.т.ч. внутри метода сравнения) + + // Исходя из координат внутри массива 2ого символа слова, определяем вектор направления + // проверки на полное нахождение слова в массиве + try { + if (crossword[i][j + 1] == words[k].charAt(1)) { + checkMatch(list, crossword, words[k], resultString, 0, 1, i, j); + } + } catch (Exception e) { + } + try { + if (crossword[i - 1][j + 1] == words[k].charAt(1)) { + checkMatch(list, crossword, words[k], resultString, -1, 1, i, j); + } + } catch (Exception e) { + } + try { + if (crossword[i - 1][j] == words[k].charAt(1)) { + checkMatch(list, crossword, words[k], resultString, -1, 0, i, j); + } + } catch (Exception e) { + } + try { + if (crossword[i - 1][j - 1] == words[k].charAt(1)) { + checkMatch(list, crossword, words[k], resultString, -1, -1, i, j); + } + } catch (Exception e) { + } + try { + if (crossword[i][j - 1] == words[k].charAt(1)) { + checkMatch(list, crossword, words[k], resultString, 0, -1, i, j); + } + } catch (Exception e) { + } + try { + if (crossword[i + 1][j - 1] == words[k].charAt(1)) { + checkMatch(list, crossword, words[k], resultString, 1, -1, i, j); + } + } catch (Exception e) { + } + try { + if (crossword[i + 1][j] == words[k].charAt(1)) { + checkMatch(list, crossword, words[k], resultString, 1, 0, i, j); + } + } catch (Exception e) { + } + try { + if (crossword[i + 1][j + 1] == words[k].charAt(1)) { + checkMatch(list, crossword, words[k], resultString, 1, 1, i, j); + } + } catch (Exception e) { + } + } + + } + } + } + for (Word entry: list){ + System.out.println(entry.toString()); + } + return list; + } + + // Направление проверки получено, выполняем проверку для вхождения всего слова + private static void checkMatch(List list, int[][] crossword, String wordText,Word word, int deltaY, int deltaX, int startY, int startX) throws Exception{ + boolean isNotMatch = false; + int step = 1; + for (int i = 2; i < wordText.length(); i++){ + step++; + if (crossword[startY + step*deltaY][startX + step*deltaX] != wordText.charAt(i)) { + isNotMatch = true; + } - return null; + } + if (!isNotMatch){ + word.setStartPoint(startX, startY); + word.setEndPoint(startX + deltaX * step, startY + deltaY * step); + list.add(word); + word = new Word(wordText); + } } public static class Word { diff --git "a/2.JavaCore/src/com/javarush/task/task20/task2027/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/2.JavaCore/src/com/javarush/task/task20/task2027/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" index 7a38598..b0c319d 100644 --- "a/2.JavaCore/src/com/javarush/task/task20/task2027/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" +++ "b/2.JavaCore/src/com/javarush/task/task20/task2027/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -1,11 +1,21 @@ -
-

Кроссворд

-

1. Дан двумерный массив, который содержит буквы английского алфавита в нижнем регистре.
-2. Метод detectAllWords должен найти все слова из words в массиве crossword.
-3. Элемент(startX, startY) должен соответствовать первой букве слова, элемент(endX, endY) — последней.
-text — это само слово, располагается между начальным и конечным элементами
-4. Все слова есть в массиве.
-5. Слова могут быть расположены горизонтально, вертикально и по диагонали как в нормальном, так и в обратном порядке.
-6. Метод main не участвует в тестировании.

- -
+taskKey="com.javarush.task.task20.task2027" + +Кроссворд + +1. Дан двумерный массив, который содержит буквы английского алфавита в нижнем регистре. +2. Метод detectAllWords должен найти все слова из words в массиве crossword. +3. Элемент(startX, startY) должен соответствовать первой букве слова, элемент(endX, endY) - последней. +text - это само слово, располагается между начальным и конечным элементами +4. Все слова есть в массиве. +5. Слова могут быть расположены горизонтально, вертикально и по диагонали как в нормальном, так и в обратном порядке. +6. Метод main не участвует в тестировании. + + +Требования: +1. В классе Solution должен существовать метод detectAllWords. +2. В классе Solution должен существовать класс Word. +3. Метод detectAllWords должен быть статическим. +4. Метод detectAllWords должен быть публичным. +5. Метод detectAllWords должен возвращать список всех слов в кроссворде (согласно условию задачи). + + From e55fa71b8a3a97aec5842044a1ec7201036b1fd2 Mon Sep 17 00:00:00 2001 From: PeucT Date: Thu, 6 Apr 2017 17:54:25 +0400 Subject: [PATCH 21/51] 2905-2913 have been done --- .../task/task29/task2905/Solution.java | 91 +++++++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 17 ++++ .../task/task29/task2906/Solution.java | 20 ++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 16 ++++ .../task/task29/task2907/Solution.java | 16 ++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 16 ++++ .../task29/task2908/CacheComputeManager.java | 46 ++++++++++ .../task/task29/task2908/Computable.java | 6 ++ .../task/task29/task2908/Copyright.java | 46 ++++++++++ .../task/task29/task2908/Solution.java | 42 +++++++++ .../javarush/task/task29/task2908/Square.java | 9 ++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 15 +++ .../task/task29/task2910/Constants.java | 12 +++ .../javarush/task/task29/task2910/Game.java | 61 +++++++++++++ .../task/task29/task2910/Solution.java | 24 +++++ .../task/task29/task2910/Sportsman.java | 74 +++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 38 ++++++++ .../task/task29/task2911/Solution.java | 56 ++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 20 ++++ .../task/task29/task2912/AbstractLogger.java | 31 +++++++ .../task/task29/task2912/ConsoleLogger.java | 13 +++ .../task/task29/task2912/FileLogger.java | 13 +++ .../javarush/task/task29/task2912/Level.java | 8 ++ .../javarush/task/task29/task2912/Logger.java | 9 ++ .../task/task29/task2912/PhoneLogger.java | 13 +++ .../task/task29/task2912/SmsLogger.java | 13 +++ .../task/task29/task2912/Solution.java | 23 +++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 29 ++++++ .../task/task29/task2913/Solution.java | 41 +++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 21 +++++ 30 files changed, 839 insertions(+) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2905/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task29/task2905/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2906/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task29/task2906/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2907/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task29/task2907/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2908/CacheComputeManager.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2908/Computable.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2908/Copyright.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2908/Solution.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2908/Square.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task29/task2908/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2910/Constants.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2910/Game.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2910/Solution.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2910/Sportsman.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task29/task2910/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2911/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task29/task2911/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2912/AbstractLogger.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2912/ConsoleLogger.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2912/FileLogger.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2912/Level.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2912/Logger.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2912/PhoneLogger.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2912/SmsLogger.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2912/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task29/task2912/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task29/task2913/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task29/task2913/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2905/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2905/Solution.java new file mode 100644 index 0000000..3463802 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2905/Solution.java @@ -0,0 +1,91 @@ +package com.javarush.task.task29.task2905; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.logging.Level; +import java.util.logging.Logger; + +/* +Странные ошибки О_о +*/ +public class Solution { + final int NUMBER_OF_THREADS = 3; //3 треда будет обрабатывать нашу очередь + final int MAX_BATCH_SIZE = 100; //будем вытаскивать по 100 сообщений + + private Logger logger = Logger.getLogger(Solution.class.getName()); + private BlockingQueue messageQueue = new LinkedBlockingQueue();//тут будут храниться все сообщения + + private BlockingQueue fakeDataBase = new LinkedBlockingQueue(); + + public static void main(String[] args) throws InterruptedException { + // статики во многих местах неуместны, поэтому помещаем все данные в поля класса, + // затем создаем объект и вызываем его метод + Solution solution = new Solution(); + + solution.startMessageCreating(); + solution.startMessagePersisting(); + + Thread.sleep(100); + solution.printResults(); + + Thread.sleep(100); + solution.printResults(); + + Thread.sleep(100); + solution.printResults(); + + Thread.sleep(500); + solution.printResults(); + } + + public void startMessageCreating() { + new Thread() { + @Override + public void run() { + for (int i = 0; i < 100000; i++) { + messageQueue.add(String.valueOf(i)); + } + } + }.start(); + } + + public void startMessagePersisting() { + for (int i = 0; i < NUMBER_OF_THREADS; i++) { + new Thread() { + private final Collection batch = new ArrayList(MAX_BATCH_SIZE); + + { + setDaemon(true); + } + + @Override + public void run() { + while (true) { + try { + messageQueue.drainTo(batch, MAX_BATCH_SIZE); + persistData(batch); + batch.clear(); + Thread.sleep(1); + } catch (Throwable e) { + logger.log(Level.SEVERE, "impossible to persist a batch", e); + } + } + } + }.start(); + } + } + + private void persistData(Collection batch) { + //представим, что тут мы коннектимся к базе данных, и сохраняем данные в нее + //сохранение данных по 1 записи тратит много ресурсов, поэтому делают батчем (группой по несколько) + fakeDataBase.addAll(batch); + } + + private void printResults() { + System.out.println(); + System.out.println("messageQueue size is " + messageQueue.size()); + System.out.println("fakeDataBase size is " + fakeDataBase.size()); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2905/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2905/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..d3a1065 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2905/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,17 @@ +taskKey="com.javarush.task.task29.task2905" + +Странные ошибки О_о + +Исправь 2 ошибки: +1) возникновение исключения +2) подвисание +Сделай минимальные изменения. + + +Требования: +1. Метод startMessageCreating должен без зависаний добавлять в messageQueue 100000 элементов. +2. Исправь ошибку в строке "messageQueue.drainTo(messageQueue, MAX_BATCH_SIZE);". +3. Метод main не должен зависать. +4. Вывод программы должен показывать, что все сообщения из messageQueue были перенесены в fakeDataBase. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2906/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2906/Solution.java new file mode 100644 index 0000000..70ca5db --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2906/Solution.java @@ -0,0 +1,20 @@ +package com.javarush.task.task29.task2906; + +/* +Особенности автобоксинга - 2 +*/ +public class Solution { + public static void main(String[] args) { + Integer a = getValue(Boolean.TRUE, Boolean.TRUE); //100 expected + Integer b = getValue(Boolean.FALSE, Boolean.TRUE); //200 expected + Integer c = getValue(Boolean.FALSE, Boolean.FALSE); //null expected + + System.out.println(a); + System.out.println(b); + System.out.println(c); + } + + public static Integer getValue(boolean first, boolean second) { + return first ? Integer.valueOf(100) : second ? Integer.valueOf(200) : null ; + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2906/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2906/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..5885806 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2906/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,16 @@ +taskKey="com.javarush.task.task29.task2906" + +Особенности автобоксинга - 2 + +Исправь ошибку реализации, приводящую к NullPointerException, в методе getValue. +Читай доп. статью про особенности автобоксинга. + + +Требования: +1. Реализация метод getValue должна использовать тернарный оператор. +2. Метод getValue не должен кидать исключений при любых значениях параметров first и second. +3. Метод getValue должен вернуть 100, если в него передать Boolean.TRUE и Boolean.TRUE. +4. Метод getValue должен вернуть 200, если в него передать Boolean.FALSE и Boolean.TRUE. +5. Метод getValue должен вернуть null, если в него передать Boolean.FALSE и Boolean.FALSE. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2907/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2907/Solution.java new file mode 100644 index 0000000..108c8e3 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2907/Solution.java @@ -0,0 +1,16 @@ +package com.javarush.task.task29.task2907; + +import java.math.BigDecimal; + +/* +Этот странный BigDecimal +*/ +public class Solution { + public static void main(String[] args) { + System.out.println(getValue(1.1d, 1.2d)); + } + + public static BigDecimal getValue(double v1, double v2) { + return new BigDecimal(String.valueOf(v1)).add(new BigDecimal(String.valueOf(v2))); + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2907/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2907/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..97bf8cf --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2907/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,16 @@ +taskKey="com.javarush.task.task29.task2907" + +Этот странный BigDecimal + +Исправь ошибку реализации, приводящую к погрешности вычисления, в методе getValue. +Сигнатуру метода не менять. Округление не использовать. +Читай доп. статью про особенности автобоксинга. + + +Требования: +1. Метод getValue должен создавать два объекта типа BigDecimal. +2. Метод getValue должен вызывать метод add у созданного объекта BigDecimal. +3. Метод getValue НЕ должен использовать метод round. +4. Метод getValue должен возвращать результат без погрешности. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2908/CacheComputeManager.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/CacheComputeManager.java new file mode 100644 index 0000000..8f15e85 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/CacheComputeManager.java @@ -0,0 +1,46 @@ +package com.javarush.task.task29.task2908; + +import java.util.concurrent.*; + +/* Argument and Value are generic types*/ +public class CacheComputeManager implements Computable { + private final ConcurrentHashMap> cache = new ConcurrentHashMap<>(); + private final Computable computable; + + public CacheComputeManager(Computable computable) { + this.computable = computable; + } + + @Override + public Value compute(final Argument arg) throws InterruptedException { + Future f = cache.get(arg); + if (f == null) { + FutureTask ft = createFutureTaskForNewArgumentThatHaveToComputeValue(arg); + cache.putIfAbsent(arg, ft); + f = ft; + ft.run(); + System.out.print(arg + " will be cached "); + } else { + System.out.print(arg + " taken from cache "); + } + try { + return f.get(); + } catch (CancellationException e) { + cache.remove(arg, f); + } catch (ExecutionException e) { + throw new RuntimeException(e.getCause()); + } + return null; + } + + public FutureTask createFutureTaskForNewArgumentThatHaveToComputeValue(final Argument arg) { + + FutureTask task = new FutureTask(new Callable() { + @Override + public Value call() throws Exception { + return computable.compute(arg); + } + }); + return task; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Computable.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Computable.java new file mode 100644 index 0000000..9077d8c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Computable.java @@ -0,0 +1,6 @@ +package com.javarush.task.task29.task2908; + +/* Argument and Value are generic types*/ +public interface Computable { + Value compute(Argument argument) throws InterruptedException; +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Copyright.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Copyright.java new file mode 100644 index 0000000..1848490 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Copyright.java @@ -0,0 +1,46 @@ +package com.javarush.task.task29.task2908; + +public class Copyright implements Computable { + @Override + public String compute(Period period) throws InterruptedException { + return "All rights reserved (c) " + period.firstYear + "-" + period.secondYear; + } + + public static class Period { + int firstYear; + int secondYear; + + public Period(int firstYear, int secondYear) { + this.firstYear = firstYear; + this.secondYear = secondYear; + } + + @Override + public String toString() { + return "Period{" + + "firstYear=" + firstYear + + ", secondYear=" + secondYear + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Period)) return false; + + Period period = (Period) o; + + if (firstYear != period.firstYear) return false; + if (secondYear != period.secondYear) return false; + + return true; + } + + @Override + public int hashCode() { + int result = firstYear; + result = 31 * result + secondYear; + return result; + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Solution.java new file mode 100644 index 0000000..fab3e92 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Solution.java @@ -0,0 +1,42 @@ +package com.javarush.task.task29.task2908; + +/* +Кеширование +*/ +public class Solution { + public static void main(String[] args) throws InterruptedException { + //////////////first example/////////////////// + Square square = new Square(); + CacheComputeManager manager = new CacheComputeManager(square); + + for (int i = 0; i < 8; i++) { + int j = i % 4; + Integer result = manager.compute(j); + System.out.format("%d * %d = %d\n", j, j, result); + } + + /* output + 0 will be cached 0 * 0 = 0 + 1 will be cached 1 * 1 = 1 + 2 will be cached 2 * 2 = 4 + 3 will be cached 3 * 3 = 9 + 0 taken from cache 0 * 0 = 0 + 1 taken from cache 1 * 1 = 1 + 2 taken from cache 2 * 2 = 4 + 3 taken from cache 3 * 3 = 9 + */ + + //////////////second example/////////////////// + Copyright copyright = new Copyright(); + CacheComputeManager manager2 = new CacheComputeManager(copyright); + System.out.println(manager2.compute(new Copyright.Period(3012, 3147))); + System.out.println(manager2.compute(new Copyright.Period(3012, 3146))); + System.out.println(manager2.compute(new Copyright.Period(3012, 3147))); + + /* output + Period{firstYear=3012, secondYear=3147} will be cached All rights reserved (c) 3012-3147 + Period{firstYear=3012, secondYear=3146} will be cached All rights reserved (c) 3012-3146 + Period{firstYear=3012, secondYear=3147} taken from cache All rights reserved (c) 3012-3147 + */ + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Square.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Square.java new file mode 100644 index 0000000..ac4c227 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Square.java @@ -0,0 +1,9 @@ +package com.javarush.task.task29.task2908; + +public class Square implements Computable { + @Override + public Integer compute(Integer integer) throws InterruptedException { + int val = integer.intValue(); + return val * val; + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2908/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..5d94be6 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,15 @@ +taskKey="com.javarush.task.task29.task2908" + +Кеширование + +В CacheComputeManager реализуй логику пустого метода. +Догадайся, что он должен делать по названию метода и по логике класса. + + +Требования: +1. Метод createFutureTaskForNewArgumentThatHaveToComputeValue должен создавать и возвращать объект типа FutureTask. +2. В методе createFutureTaskForNewArgumentThatHaveToComputeValue должен создаваться объект анонимного класса, реализующего интерфейс Callable. +3. Внутри метода createFutureTaskForNewArgumentThatHaveToComputeValue должна встречаться строка "return computable.compute(arg);". +4. Программа должна выводить текст указанный в комментариях в классе Solution. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Constants.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Constants.java new file mode 100644 index 0000000..2b323ef --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Constants.java @@ -0,0 +1,12 @@ +package com.javarush.task.task29.task2910; + +import java.math.BigDecimal; + +public class Constants { + public static final Double RACE_LENGTH = new Double(20.0); + public static final int NUMBER_OF_FIRE_LINES = 4; + public static final int PENALTY_TIME_PER_ONE_MISS = 20; + public static final BigDecimal MIN_CHANCE_TO_HIT_IN_TARGET = new BigDecimal("0.815"); + public static final BigDecimal MAX_CHANCE_TO_HIT_IN_TARGET = new BigDecimal("0.900"); + public static final int SPORTSMAN_COUNT = 30; +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Game.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Game.java new file mode 100644 index 0000000..1e57471 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Game.java @@ -0,0 +1,61 @@ +package com.javarush.task.task29.task2910; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +import static com.javarush.task.task29.task2910.Constants.*; + +public class Game { + private List members; + Sportsman controlSportsman; + + public Game() { + initializeControlSportsman(); + members = new ArrayList<>(); + for (int i = 0; i < SPORTSMAN_COUNT; i++) { + members.add(new Sportsman(i + 1)); + } + } + + private void initializeControlSportsman() { + controlSportsman = new Sportsman(0); + controlSportsman.setAverageSpeed(new BigDecimal(20.)); + controlSportsman.setChanceToHit(MAX_CHANCE_TO_HIT_IN_TARGET); + controlSportsman.setCountHitOutTarget(2); + controlSportsman.setResultTime(new BigDecimal("3640.00")); + System.out.println("РЕЗУЛЬТАТ КОНТРОЛЬНО СПОРТСМЕНА:"); + controlSportsman.printResultInfo(); + } + + public void startCompetition() { + for (int i = 0; i < members.size(); i++) { + members.get(i).calculateNumberOfMiss(); + BigDecimal timeToRace = controlSportsman.getResultTime().subtract(BigDecimal.valueOf(members.get(i).getCountHitOutTarget() * PENALTY_TIME_PER_ONE_MISS)); + members.get(i).setAverageSpeed(new BigDecimal(RACE_LENGTH / (timeToRace.doubleValue() / 3600)).setScale(4, BigDecimal.ROUND_HALF_UP)); + members.get(i).calculateFullTime(); + } + } + + public void printAllResults() { + for (int i = 0; i < members.size(); i++) { + members.get(i).printResultInfo(); + } + } + + public void printSportsmanWithEqualTime() { + for (Sportsman sportsman : getSportsmanWithEqualTime()) { + sportsman.printResultInfo(); + } + } + + private List getSportsmanWithEqualTime() { + List result = new ArrayList<>(); + for (int i = 0; i < members.size(); i++) { + if (members.get(i).getResultTime().equals(controlSportsman.getResultTime())) { + result.add((members.get(i))); + } + } + return result; + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Solution.java new file mode 100644 index 0000000..e0b9987 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Solution.java @@ -0,0 +1,24 @@ +package com.javarush.task.task29.task2910; + +/* +Это архаичное слово "Биатлон" +*/ + +public class Solution { + + public static void main(String[] args) { + Game game = new Game(); + printDelimiter(); + game.startCompetition(); + System.out.println("\n\nВСЕ РЕЗУЛЬТАТЫ:"); + game.printAllResults(); + printDelimiter(); + System.out.println("\n\nСПОРТСМЕНЫ С ТАКИМ ЖЕ ИТОГОВЫМ ВРЕМЕНЕМ, КАК У КОНТРОЛЬНОГО СПОРТСМЕНА:"); + game.printSportsmanWithEqualTime(); + printDelimiter(); + } + + private static void printDelimiter() { + System.out.println("================================================================================================="); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Sportsman.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Sportsman.java new file mode 100644 index 0000000..7ebb84b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Sportsman.java @@ -0,0 +1,74 @@ +package com.javarush.task.task29.task2910; + +import java.math.BigDecimal; +import java.util.concurrent.ThreadLocalRandom; + +import static com.javarush.task.task29.task2910.Constants.*; + +public class Sportsman { + + private BigDecimal chanceToHit; + private BigDecimal averageSpeed; + private BigDecimal resultTime = new BigDecimal("0."); + private int number; + private int countHitOutTarget = 0; + + public Sportsman(int number) { + this.number = number; + chanceToHit = BigDecimal.valueOf(ThreadLocalRandom.current().nextDouble(MIN_CHANCE_TO_HIT_IN_TARGET.doubleValue(), MAX_CHANCE_TO_HIT_IN_TARGET.doubleValue())); + } + + public void calculateFullTime() { + resultTime = resultTime.add(BigDecimal.valueOf(countHitOutTarget * PENALTY_TIME_PER_ONE_MISS)); + resultTime = resultTime.add(calculateTimeToRace()); + } + + private BigDecimal calculateTimeToRace() { + return new BigDecimal(RACE_LENGTH / averageSpeed.doubleValue() * 3600).setScale(2, BigDecimal.ROUND_HALF_UP); + } + + public void calculateNumberOfMiss() { + for (int i = 0; i < NUMBER_OF_FIRE_LINES * 5; i++) { + double temp = Math.random(); + if (temp < (1 - chanceToHit.doubleValue())) { + countHitOutTarget++; + } + } + } + + public void setAverageSpeed(BigDecimal averageSpeed) { + this.averageSpeed = averageSpeed.setScale(4, BigDecimal.ROUND_HALF_UP); + } + + public BigDecimal getResultTime() { + return resultTime; + } + + public int getNumber() { + return number; + } + + public void setNumber(int number) { + this.number = number; + } + + public int getCountHitOutTarget() { + return countHitOutTarget; + } + + public void setCountHitOutTarget(int countHitOutTarget) { + this.countHitOutTarget = countHitOutTarget; + } + + public void setChanceToHit(BigDecimal chanceToHit) { + this.chanceToHit = chanceToHit; + } + + public void setResultTime(BigDecimal resultTime) { + this.resultTime = resultTime; + } + + public void printResultInfo() { + System.out.printf("Спортсмен № %02d: Время - %6.2f секунд. Средняя скорость - %2.4f км/час. Количество промахов %d\n", number, resultTime.doubleValue(), averageSpeed, countHitOutTarget); + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2910/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2910/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..b67d5a6 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2910/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,38 @@ +taskKey="com.javarush.task.task29.task2910" + +Это архаичное слово "Биатлон" + +Амиго, представляешь, в 21 веке существовал такой вид спорта – биатлон. Люди ездили на лыжах и стреляли на +подготовленных площадках по мишеням. За одну серию стрельбы нужно было закрыть 5 мишеней. Стрельбы +происходили как стоя, так и лежа, но не будем вдаваться в подробности. У лучших представителей рода +человеческого средняя точность стрельбы достигала 90%, у крепких середнячков – 81,5%. +Я написал программу, которая создает соревнование, добавляет в него 30 спортсменов-биатлонистов. Каждому из +них случайным образом выставляется точность (в диапазоне от 0,815 до 0,900). Штраф за каждый промах – плюс +20 секунд к результату. Еще у соревнования задается количество огневых рубежей – 4 и дистанция, которую +биатлонисты должны преодолеть – 20 км. +Так же я создал контрольного спортсмена, у которого захардкожены показатели: +Скорость: 20 км/час; +Вероятность попадания: 0,900 (90%); +Количество промахов: 2 (Всего нужно попасть 20 раз. При точности 90 процентов ожидается 2 промаха); +Нужно проехать 20 км со скоростью 20 км/час. Необходимое время - 1 час, то есть 3600 секунд. +Время гонки (с учетом штрафных секунд): 3600 + 2 * 20 = 3640 секунд. +Я хочу определить, с какой скоростью должен ехать каждый спортсмен, при его случайном количестве промахов, +чтобы результат в секундах был такой же, как и у контрольного спортсмена. В начале я вывожу результат +контрольного спортсмена, потом все результаты. В конце я вывожу всех спортсменов, у которых время такое же, +как и у контрольного спортсмена. У некоторых спортсменов за счет округления итоговое время отличается на доли +секунды. Такие нам не нужны. У остальных время гонки ровно 3640 секунд, как и у контрольного спортсмена, но +они не выводятся в секции "СПОРТСМЕНЫ С ТАКИМ ЖЕ ИТОГОВЫМ ВРЕМЕНЕМ, КАК У КОНТРОЛЬНОГО СПОРТСМЕНА:". + +Твоя задача: сделать одно изменение в коде, чтобы исправить найденный баг. +Обрати внимание: все округления правильные, и новых добавлять не нужно! + + +Требования: +1. Запрещено изменять типы данных констант. +2. Вывод на экран в секции "СПОРТСМЕНЫ С ТАКИМ ЖЕ ИТОГОВЫМ ВРЕМЕНЕМ, КАК У КОНТРОЛЬНОГО СПОРТСМЕНА:" должен содержать всех спортсменов, у которых такое же время, как и у контрольного спортсмена. +3. Сделай одно изменение в классе Game. +4. Класс Constants не изменяй. +5. Класс Solution не изменяй. +6. Класс Sportsman не изменяй. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2911/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2911/Solution.java new file mode 100644 index 0000000..9301442 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2911/Solution.java @@ -0,0 +1,56 @@ +package com.javarush.task.task29.task2911; + +import java.util.Random; +import java.util.Scanner; + +/* +И еще раз рефакторинг +*/ + +public class Solution { + public static boolean flagWin = false; + + public static void main(String[] args) { + new Solution().runGame(); + } + + private void runGame() { + Random random = new Random(); + int secret = random.nextInt(1000); + int tryNumber = -1; + Scanner scanner = new Scanner(System.in); + for (int i = 1; i <= 10; i++) { + System.out.printf("Попытка %d - вводи число: ", i); + tryNumber = scanner.nextInt(); + if (tryNumber < secret) + if (i < 10) + System.out.println("Загаданное число больше"); + if (tryNumber > secret) + if (i < 10) + System.out.println("Загаданное число меньше"); + if (tryNumber == secret) { + i = stopGame(); + flagWin = true; + } + } + if (flagWin) + printCongratulations(tryNumber); + else + printUpset(); + } + + private void printCongratulations(int number) { + System.out.println(); + System.out.println("Ты угадал!"); + System.out.println("Загаданное число: " + number); + } + + private void printUpset() { + System.out.println(); + System.out.println("Ты проиграл!"); + } + + private int stopGame() { + return 10; + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2911/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2911/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..531a412 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2911/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,20 @@ +taskKey="com.javarush.task.task29.task2911" + +И еще раз рефакторинг + +Задается целое число от 0 до 1000 включительно случайным образом. Пользователь вводит с клавиатуры число. +Программа отвечает, введенное число больше или меньше загаданного. Если за 10 попыток пользователь программы +угадывает число - программа выводит: +"Ты угадал!" +"Загаданное число: [number]", +иначе "Ты проиграл!". +Исправь одну ошибку, чтобы код выполнял описанные действия. + + +Требования: +1. Если за 10 попыток не введено правильного числа - программа должна вывести на экран "Ты проиграл!". +2. Если введено неправильное число, флаг boolean flagWin не должен иметь значение true. +3. Не изменяй сигнатуры методов. +4. Нужно сделать одно изменение в правильном месте программы. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2912/AbstractLogger.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/AbstractLogger.java new file mode 100644 index 0000000..4422c63 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/AbstractLogger.java @@ -0,0 +1,31 @@ +package com.javarush.task.task29.task2912; + +/** + * Created by ArchMage on 06.04.17. + */ +public abstract class AbstractLogger implements Logger { + int level; + Logger next; + + public AbstractLogger(int level) { + this.level = level; + } + + public void inform(String message, int level) { + if (this.level <= level) { + info(message); + } + if (next != null) { + next.inform(message, level); + } + } + + public void setNext(Logger next) { + this.next = next; + } + + public void info(String message) { + + }; + +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2912/ConsoleLogger.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/ConsoleLogger.java new file mode 100644 index 0000000..07c09cf --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/ConsoleLogger.java @@ -0,0 +1,13 @@ +package com.javarush.task.task29.task2912; + +public class ConsoleLogger extends AbstractLogger { + + public ConsoleLogger(int level) { + super(level); + } + + @Override + public void info(String message) { + System.out.println("Logging to console: " + message); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2912/FileLogger.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/FileLogger.java new file mode 100644 index 0000000..cc10544 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/FileLogger.java @@ -0,0 +1,13 @@ +package com.javarush.task.task29.task2912; + +public class FileLogger extends AbstractLogger { + + public FileLogger(int level) { + super(level); + } + + @Override + public void info(String message) { + System.out.println("Logging to file: " + message); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2912/Level.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/Level.java new file mode 100644 index 0000000..1ca38f5 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/Level.java @@ -0,0 +1,8 @@ +package com.javarush.task.task29.task2912; + +public class Level { + public static final int INFO = 100; + public static final int WARN = 200; + public static final int ERROR = 300; + public static final int FATAL = 400; +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2912/Logger.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/Logger.java new file mode 100644 index 0000000..4ed8bce --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/Logger.java @@ -0,0 +1,9 @@ +package com.javarush.task.task29.task2912; + +public interface Logger { + void inform(String message, int level); + + void setNext(Logger next); + + void info(String message); +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2912/PhoneLogger.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/PhoneLogger.java new file mode 100644 index 0000000..a1f2076 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/PhoneLogger.java @@ -0,0 +1,13 @@ +package com.javarush.task.task29.task2912; + +public class PhoneLogger extends AbstractLogger { + + public PhoneLogger(int level) { + super(level); + } + + @Override + public void info(String message) { + System.out.println("Call to director: " + message); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2912/SmsLogger.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/SmsLogger.java new file mode 100644 index 0000000..3a09e31 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/SmsLogger.java @@ -0,0 +1,13 @@ +package com.javarush.task.task29.task2912; + +public class SmsLogger extends AbstractLogger { + + public SmsLogger(int level) { + super(level); + } + + @Override + public void info(String message) { + System.out.println("Send sms to CEO: " + message); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2912/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/Solution.java new file mode 100644 index 0000000..0c2630b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/Solution.java @@ -0,0 +1,23 @@ +package com.javarush.task.task29.task2912; + +/* +Рефакторинг паттерна Chain of Responsibility +*/ + +public class Solution { + public static void main(String[] args) { + Logger logger3 = new PhoneLogger(Level.FATAL); + Logger logger2 = new SmsLogger(Level.ERROR); + Logger logger1 = new ConsoleLogger(Level.WARN); + Logger logger0 = new FileLogger(Level.INFO); + + logger3.setNext(logger2); + logger2.setNext(logger1); + logger1.setNext(logger0); + + logger3.inform("All OK", Level.INFO); + logger3.inform("We find a bug", Level.WARN); + logger3.inform("Database connection error", Level.ERROR); + logger3.inform("System shut down", Level.FATAL); + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2912/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..a299a88 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,29 @@ +taskKey="com.javarush.task.task29.task2912" + +Рефакторинг паттерна Chain of Responsibility + +Есть программа, в которой реализована система логирования по принципу: +- если событие уровня FATAL - происходит звонок директору, отправляется СМС-сообщение CEO, выводится +сообщение в консоль, происходит логирование в файл; +- если событие уровня ERROR - отправляется СМС-сообщение CEO, выводится сообщение в консоль, происходит +логирование в файл; +- если событие уровня WARN - выводится сообщение в консоль, происходит логирование в файл; +- если событие уровня INFO - происходит логирование в файл. + +В программе реализован паттерн "цепочка ответственности". Изучи его внимательно. В классах FileLogger, +ConsoleLogger, SmsLogger, PhoneLogger есть много повторяющегося кода. Подними весь повторяющийся код в +абстрактный класс AbstractLogger. +Подъемом в рефакторинге называется перенос полей, методов, конструкторов из всех наследников в одного общего +предка. Из наследников, при этом, удаляется код, который перенесен в класс предка. + +Логика работы программы не должна измениться. + + +Требования: +1. Класс AbstractLogger должен быть абстрактным. +2. Класс AbstractLogger должен поддерживать интерфейс Logger. +3. Необходимо поднять поля level и next в класс AbstractLogger. +4. Необходимо поднять методы setNext(Logger) и inform(String, int) в класс AbstractLogger. +5. Вывод программы должен остаться неизменным. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2913/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2913/Solution.java new file mode 100644 index 0000000..d956bbd --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2913/Solution.java @@ -0,0 +1,41 @@ +package com.javarush.task.task29.task2913; + +import java.util.Random; + +/* +Замена рекурсии +*/ + +public class Solution { + private static int numberA; + private static int numberB; + + + public static String getAllNumbersBetween(int a, int b){ + String result = null; + for (int i = 0; i <= Math.abs(a - b); i++) { + if (a > b) { + if (i == 0) { + result = "" + a; + } else { + result = result + " " + (a - i); + } + } else { + if (i == 0) { + result = "" + a; + } else { + result = result + " " + (a + i); + } + } + } + return result; + } + + public static void main(String[] args) { + Random random = new Random(); + numberA = random.nextInt() % 1_000; + numberB = random.nextInt() % 10_000; + System.out.println(getAllNumbersBetween(numberA, numberB)); + System.out.println(getAllNumbersBetween(numberB, numberA)); + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2913/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2913/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..7b9a8f1 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2913/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,21 @@ +taskKey="com.javarush.task.task29.task2913" + +Замена рекурсии + +В программе случайным образом генерируются два целых числа A и В. Нужно вывести все целые числа от A до B +включительно, в порядке возрастания, если A меньше B, или в порядке убывания в противном случае. + +Задача реализована с использованием рекурсии. +Иногда в результате работы программы получаем Exception in thread "main" java.lang.StackOverflowError. + +Твоя задача: перепиши код без использования рекурсии. +Метод recursion переименуй на getAllNumbersBetween. + + +Требования: +1. Метод recursion необходимо переименовать на getAllNumbersBetween. +2. Ни в одном методе класса Solution не должно быть рекурсивных вызовов. +3. В конце строчки вывода последовательности чисел не должно быть пробела. +4. Логика работы программы должна остаться прежней. + + From 164a9bb76c8c3725ec76c86588614465df023004 Mon Sep 17 00:00:00 2001 From: PeucT Date: Fri, 7 Apr 2017 18:13:35 +0400 Subject: [PATCH 22/51] level 28. big task (1-10) --- .../task/task32/task3209/Controller.java | 33 +++ .../task32/task3209/ExceptionHandler.java | 11 + .../javarush/task/task32/task3209/View.java | 102 ++++++++ .../task32/task3209/actions/RedoAction.java | 22 ++ .../task3209/actions/StrikeThroughAction.java | 20 ++ .../task3209/actions/SubscriptAction.java | 20 ++ .../task3209/actions/SuperscriptAction.java | 20 ++ .../task32/task3209/actions/UndoAction.java | 22 ++ .../task3209/listeners/FrameListener.java | 22 ++ .../listeners/TabbedPaneChangeListener.java | 22 ++ .../listeners/TextEditMenuListener.java | 32 +++ .../task3209/listeners/UndoMenuListener.java | 49 ++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 220 ++++++++++++++++++ 13 files changed, 595 insertions(+) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task32/task3209/Controller.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task32/task3209/ExceptionHandler.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task32/task3209/View.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/RedoAction.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/StrikeThroughAction.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/SubscriptAction.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/SuperscriptAction.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/UndoAction.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/FrameListener.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/TabbedPaneChangeListener.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/TextEditMenuListener.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/UndoMenuListener.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task32/task3209/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/Controller.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/Controller.java new file mode 100644 index 0000000..b2a5265 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/Controller.java @@ -0,0 +1,33 @@ +package com.javarush.task.task32.task3209; + +import javax.swing.text.html.HTMLDocument; +import java.io.File; + +/** + * Created by ArchMage on 07.04.17. + */ +public class Controller { + private View view; + private HTMLDocument document; + private File currentFile; + + public void init(){ + + } + + public void exit(){ + System.exit(0); + } + + public Controller(View view) { + this.view = view; + } + + public static void main(String[] args){ + View view = new View(); + Controller controller = new Controller(view); + view.setController(controller); + view.init(); + controller.init(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/ExceptionHandler.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/ExceptionHandler.java new file mode 100644 index 0000000..be9ad01 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/ExceptionHandler.java @@ -0,0 +1,11 @@ +package com.javarush.task.task32.task3209; + +/** + * Created by ArchMage on 07.04.17. + */ +public class ExceptionHandler { + + public static void log(Exception e){ + System.out.println(e.toString()); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/View.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/View.java new file mode 100644 index 0000000..e10617a --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/View.java @@ -0,0 +1,102 @@ +package com.javarush.task.task32.task3209; + +import com.javarush.task.task32.task3209.listeners.FrameListener; +import com.javarush.task.task32.task3209.listeners.TabbedPaneChangeListener; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * Created by ArchMage on 07.04.17. + */ +public class View extends JFrame implements ActionListener { + private Controller controller; + private JTabbedPane tabbedPane = new JTabbedPane(); + private JTextPane htmlTextPane = new JTextPane(); + private JEditorPane plainTextPane = new JEditorPane(); + + public View(){ + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (ClassNotFoundException e) { + ExceptionHandler.log(e); + } catch (InstantiationException e) { + ExceptionHandler.log(e); + } catch (IllegalAccessException e) { + ExceptionHandler.log(e); + } catch (UnsupportedLookAndFeelException e) { + ExceptionHandler.log(e); + } + } + + public void init(){ + initGui(); + FrameListener frameListener = new FrameListener(this); + addWindowListener(frameListener); + setVisible(true); + } + + public void selectedTabChanged(){ + + } + + public void initMenuBar(){ + JMenuBar menuBar = new JMenuBar(); + MenuHelper.initFileMenu(this, menuBar); + MenuHelper.initEditMenu(this, menuBar); + MenuHelper.initStyleMenu(this, menuBar); + MenuHelper.initAlignMenu(this, menuBar); + MenuHelper.initColorMenu(this, menuBar); + MenuHelper.initFontMenu(this, menuBar); + MenuHelper.initHelpMenu(this, menuBar); + getContentPane().add(menuBar, BorderLayout.NORTH); + + } + + public void initEditor(){ + Dimension d = new Dimension(800, 500); + htmlTextPane.setContentType("text/html"); + JScrollPane scrollHtml = new JScrollPane(htmlTextPane); + tabbedPane.addTab("HTML" ,scrollHtml); + plainTextPane.setContentType("text/html"); + JScrollPane scrollText = new JScrollPane(plainTextPane); + tabbedPane.addTab("Текст", scrollText); + tabbedPane.setPreferredSize(d); + TabbedPaneChangeListener tabChangeListener = new TabbedPaneChangeListener(this); + tabbedPane.addChangeListener(tabChangeListener); + this.getContentPane().add(tabbedPane, BorderLayout.CENTER); + } + + public void initGui(){ + initMenuBar(); + initEditor(); + pack(); + } + + public void exit(){ + controller.exit(); + } + + public Controller getController() { + return controller; + } + + public void setController(Controller controller) { + this.controller = controller; + } + + public boolean canUndo(){ + return false; + } + + public boolean canRedo(){ + return false; + } + + @Override + public void actionPerformed(ActionEvent e) { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/RedoAction.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/RedoAction.java new file mode 100644 index 0000000..e413ca0 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/RedoAction.java @@ -0,0 +1,22 @@ +package com.javarush.task.task32.task3209.actions; + +import com.javarush.task.task32.task3209.View; + +import javax.swing.*; +import java.awt.event.ActionEvent; + +/** + * Created by ArchMage on 07.04.17. + */ +public class RedoAction extends AbstractAction { + private View view; + + public RedoAction(View view) { + this.view = view; + } + + @Override + public void actionPerformed(ActionEvent e) { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/StrikeThroughAction.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/StrikeThroughAction.java new file mode 100644 index 0000000..2b139de --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/StrikeThroughAction.java @@ -0,0 +1,20 @@ +package com.javarush.task.task32.task3209.actions; + +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledEditorKit; +import java.awt.event.ActionEvent; + +/** + * Created by ArchMage on 07.04.17. + */ +public class StrikeThroughAction extends StyledEditorKit.StyledTextAction { + + public StrikeThroughAction() { + super(StyleConstants.StrikeThrough.toString()); + } + + @Override + public void actionPerformed(ActionEvent e) { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/SubscriptAction.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/SubscriptAction.java new file mode 100644 index 0000000..d8b9892 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/SubscriptAction.java @@ -0,0 +1,20 @@ +package com.javarush.task.task32.task3209.actions; + +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledEditorKit; +import java.awt.event.ActionEvent; + +/** + * Created by ArchMage on 07.04.17. + */ +public class SubscriptAction extends StyledEditorKit.StyledTextAction { + + public SubscriptAction() { + super(StyleConstants.Subscript.toString()); + } + + @Override + public void actionPerformed(ActionEvent e) { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/SuperscriptAction.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/SuperscriptAction.java new file mode 100644 index 0000000..31a4668 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/SuperscriptAction.java @@ -0,0 +1,20 @@ +package com.javarush.task.task32.task3209.actions; + +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledEditorKit; +import java.awt.event.ActionEvent; + +/** + * Created by ArchMage on 07.04.17. + */ +public class SuperscriptAction extends StyledEditorKit.StyledTextAction { + + public SuperscriptAction() { + super(StyleConstants.Superscript.toString()); + } + + @Override + public void actionPerformed(ActionEvent e) { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/UndoAction.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/UndoAction.java new file mode 100644 index 0000000..ad0313e --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/UndoAction.java @@ -0,0 +1,22 @@ +package com.javarush.task.task32.task3209.actions; + +import com.javarush.task.task32.task3209.View; + +import javax.swing.*; +import java.awt.event.ActionEvent; + +/** + * Created by ArchMage on 07.04.17. + */ +public class UndoAction extends AbstractAction { + private View view; + + public UndoAction(View view) { + this.view = view; + } + + @Override + public void actionPerformed(ActionEvent e) { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/FrameListener.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/FrameListener.java new file mode 100644 index 0000000..1b4e41d --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/FrameListener.java @@ -0,0 +1,22 @@ +package com.javarush.task.task32.task3209.listeners; + +import com.javarush.task.task32.task3209.View; + +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +/** + * Created by ArchMage on 07.04.17. + */ +public class FrameListener extends WindowAdapter { + private View view; + + public FrameListener(View view) { + this.view = view; + } + + @Override + public void windowClosing(WindowEvent e) { + view.exit(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/TabbedPaneChangeListener.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/TabbedPaneChangeListener.java new file mode 100644 index 0000000..652eb6a --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/TabbedPaneChangeListener.java @@ -0,0 +1,22 @@ +package com.javarush.task.task32.task3209.listeners; + +import com.javarush.task.task32.task3209.View; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +/** + * Created by ArchMage on 07.04.17. + */ +public class TabbedPaneChangeListener implements ChangeListener { + private View view; + + public TabbedPaneChangeListener(View view) { + this.view = view; + } + + @Override + public void stateChanged(ChangeEvent e) { + view.selectedTabChanged(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/TextEditMenuListener.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/TextEditMenuListener.java new file mode 100644 index 0000000..2244497 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/TextEditMenuListener.java @@ -0,0 +1,32 @@ +package com.javarush.task.task32.task3209.listeners; + +import com.javarush.task.task32.task3209.View; + +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; + +/** + * Created by ArchMage on 07.04.17. + */ +public class TextEditMenuListener implements MenuListener { + private View view; + + public TextEditMenuListener(View view){ + this.view = view; + } + + @Override + public void menuSelected(MenuEvent e) { + + } + + @Override + public void menuDeselected(MenuEvent e) { + + } + + @Override + public void menuCanceled(MenuEvent e) { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/UndoMenuListener.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/UndoMenuListener.java new file mode 100644 index 0000000..185f3ea --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/UndoMenuListener.java @@ -0,0 +1,49 @@ +package com.javarush.task.task32.task3209.listeners; + +import com.javarush.task.task32.task3209.View; + +import javax.swing.*; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; + +/** + * Created by ArchMage on 07.04.17. + */ +public class UndoMenuListener implements MenuListener { + private View view; + private JMenuItem undoMenuItem; + private JMenuItem redoMenuItem; + + public UndoMenuListener(View view, JMenuItem undoMenuItem, JMenuItem redoMenuItem){ + this.view = view; + this.undoMenuItem = undoMenuItem; + this.redoMenuItem = redoMenuItem; + } + + @Override + public void menuSelected(MenuEvent e) { + boolean canUndo = view.canUndo(); + boolean canRedo = view.canRedo(); + if (canUndo){ + undoMenuItem.setEnabled(true); + } else { + undoMenuItem.setEnabled(false); + } + + if (canRedo){ + redoMenuItem.setEnabled(true); + } else { + redoMenuItem.setEnabled(false); + } + } + + @Override + public void menuDeselected(MenuEvent e) { + + } + + @Override + public void menuCanceled(MenuEvent e) { + + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..e801d14 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,220 @@ +taskKey="com.javarush.task.task32.task3209.big11" + +HTML Editor (11) + +11.1. Добавь в представление поле UndoManager undoManager. Разберись для чего +используется этот класс. Проинициализируй поле класса новым объектом. +11.2. Добавь класс UndoListener реализующий интерфейс UndoableEditListener в пакет +listeners. Этот класс будет следить за правками, которые можно отменить или вернуть. +11.3. Добавь в класс UndoListener: +11.3.1. Поле UndoManager undoManager. +11.3.2. Конструктор, который принимает UndoManager и инициализирует поле класса. +11.3.3. Метод undoableEditHappened(UndoableEditEvent e). Он должен из переданного +события получать правку и добавлять ее в undoManager. +11.4. Добавь в представление поле UndoListener undoListener, проинициализируй его +используя undoManager. +11.5. Добавь в представление методы: +11.5.1. void undo() - отменяет последнее действие. Реализуй его используя undoManager. +Метод не должен кидать исключений, логируй их. +11.5.2. void redo() - возвращает ранее отмененное действие. Реализуй его по аналогии с +предыдущим пунктом. +11.5.3. Реализуй методы boolean canUndo() и boolean canRedo() используя undoManager. +11.5.4. Реализуй геттер для undoListener. +11.5.5. Добавь и реализуй метод void resetUndo(), который должен сбрасывать все правки в +менеджере undoManager. + + +Требования: +1. Класс View должен содержать приватное поле UndoManager undoManager, которое должно быть сразу проинициализовано. +2. Класс View должен содержать приватное поле UndoListener undoListener, которое должно быть сразу проинициализовано через поле undoManager. +3. Класс View должен содержать геттер к полю UndoListener undoListener. +4. Класс View должен содержать public void метод undo(). +5. Класс View должен содержать public void метод redo(). +6. Реализация метода canUndo() класса View должна использовать undoManager. +7. Реализация метода canRedo() класса View должна использовать undoManager. +8. Класс View должен содержать public void метод resetUndo(), который должен сбрасывать все правки в менеджере undoManager. +9. Класс UndoListener должен быть создан в отдельном файле. +10. Класс UndoListener должен содержать приватное поле UndoManager undoManager. +11. Конструктор UndoListener(UndoManager undoManager) должен корректно инициализировать поле undoManager. +12. Метод undoableEditHappened(UndoableEditEvent e) в классе UndoListener должен из переданного события получать правку и добавлять ее в undoManager. + + +HTML Editor (10) + +Наш редактор будет поддерживать механизм отмены/возврата (undo/redo) действий в +редакторе. +Реализуй класс UndoMenuListener. Этот слушатель будет следить за меню, а если конкретнее, +то за моментом, когда меню редактирования будет выбрано пользователем. В этот момент он +будет запрашивать у представления можем ли мы сейчас отменить или вернуть какое-то +действие, и в зависимости от этого делать доступными или не доступными пункты меню +"Отменить" и "Вернуть". +10.1. Добавь в класс UndoMenuListener следующие поля: +10.1.1. Представление View view. +10.1.2. Пункт меню "Отменить" JMenuItem undoMenuItem. +10.1.3. Пункт меню "Вернуть" JMenuItem redoMenuItem. +10.2. Реализуй конструктор UndoMenuListener(View view, JMenuItem undoMenuItem, +JMenuItem redoMenuItem), он должен инициализировать поля класса. +10.3. Реализуй метод menuSelected(MenuEvent menuEvent). Он будет вызываться перед +показом меню. Он должен: +10.3.1. Спрашивать у представления можем ли мы отменить действие с помощью метода +boolean canUndo(). Пока у представления нет такого метода, поэтому добавь заглушку, +которая всегда возвращает false. +10.3.2. Делать доступным или не доступным пункт меню undoMenuItem в зависимости от того, +что нам вернуло представление. Подсказка: используй метод setEnabled(). +10.3.3. Аналогично поступи и для пункта меню redoMenuItem, добавив метод-заглушку +canRedo() в представление. +Запусти программу и убедись, что пункты меню Отменить и Вернуть недоступны. + + + +HTML Editor (9) + +9.1. Реализуй метод initMenuBar(). Он должен: +9.1.1. Создавать новый объект типа JMenuBar. Это и будет наша панель меню. +9.1.2. С помощью MenuHelper инициализировать меню в следующем порядке: Файл, +Редактировать, Стиль, Выравнивание, Цвет, Шрифт и Помощь. +9.1.3. Добавлять в верхнюю часть панели контента текущего фрейма нашу панель меню, +аналогично тому, как это мы делали с панелью вкладок. +9.2. Добавь конструктор класса View. Он должен устанавливать внешний вид и поведение +(look and feel) нашего приложения такими же, как это определено в системе. +Конструктор не должен кидать исключений, только логировать их с помощью +ExceptionHandler. Подсказа: для реализации задания используй класс UIManager. + +Запусти приложение, теперь ты должен видеть панель с меню вверху окна. Некоторые из +пунктов меню (например: Вырезать, Копировать, Вставить, Стиль (частично), Выравнивание, +Цвет, Шрифт) должны уже работать. Убедись, что все работает и только затем продолжи +разработку. + + + +HTML Editor (8) + +Пришло время добавить все необходимые пункты меню и написать классы действий, +выполняемые при нажатии. Это довольно трудоемкая и рутинная работа, а ты отличный +ученик и не хотелось бы тебя огорчать. Поэтому, в качестве бонуса ты получаешь готовый класс +MenuHelper! А ты: +8.1. Напиши в пакете actions заглушки для следующих классов: +8.1.1. Класс отмены действия UndoAction. Он должен наследоваться от AbstractAction и +содержать конструктор UndoAction(View view). +8.1.2. Класс возврата действия RedoAction. Требования аналогичны требованиям к +UndoAction. +8.1.3. Класс StrikeThroughAction, который отвечает за стиль текста "Зачеркнутый". Унаследуй +его от StyledEditorKit.StyledTextAction. +8.1.4. Класс SubscriptAction, который отвечает за стиль текста "Подстрочный знак". Его также +унаследуй его от StyledEditorKit.StyledTextAction. +8.1.5. Класс SuperscriptAction. Он будет отвечать за стиль "Надстрочный знак". Добавь ему +правильный родительский класс. +8.2. Напиши в пакете listeners заглушки для классов: +8.2.1. UndoMenuListener, он должен реализовывать интерфейс MenuListener и иметь +конструктор UndoMenuListener(View view, JMenuItem undoMenuItem, JMenuItem +redoMenuItem). Чем он будет заниматься узнаешь чуть позже. +8.2.2. TextEditMenuListener. Этот класс также должен реализовывать интерфейс MenuListener. +Добавь ему конструктор TextEditMenuListener(View view). В следующих заданиях мы +рассмотрим его детальнее. + + + +HTML Editor (7) + +Добавь класс MenuHelper. Это будет вспомогательный класс для инициализации и настройки +меню. У меню будет следующая структура: +- Файл +-- Новый +-- Открыть +-- Сохранить +-- Сохранить как... +-- Выход + +- Редактировать +-- Отменить +-- Вернуть +-- Вырезать +-- Копировать +-- Вставить + +- Стиль +-- Полужирный +-- Подчеркнутый +-- Курсив +-- Подстрочный знак +-- Надстрочный знак +-- Зачеркнутый + +- Выравнивание +-- По левому краю +-- По центру +-- По правому краю + +- Цвет +-- Красный +-- Оранжевый +-- Желтый +-- Зеленый +-- Синий +-- Голубой +-- Пурпурный +-- Черный + +- Шрифт +-- Шрифт +--- SansSerif, Serif, Monospaced, Dialog, DialogInput, +-- Размер шрифта +--- 6, 8, 10, 12, 14, 16, 20, 24, 32, 36, 48, 72 + +- Помощь +-- О программе + +7.1. Реализуй в MenuHelper статический метод JMenuItem addMenuItem(JMenu parent, String +text, ActionListener actionListener), где parent - меню в которое мы добавляем пункт, text - +текст добавляемого пункта, actionListener - слушатель действий добавляемого пункта +меню. Он должен: +7.1.1. Создавать новый пункт меню JMenuItem, используя text. +7.1.2. Устанавливать этому пункту слушателя действий с помощью метода addActionListener(). +7.1.3. Добавлять в parent созданный пункт меню. +7.1.4. Возвращать созданный пункт меню. +7.2. Реализуй статический метод JMenuItem addMenuItem(JMenu parent, Action action). Этот +метод аналогичен предыдущему, но в качестве параметра принимает действие action, +которое необходимо выполнить при выборе пункта меню. Подсказка: при создании +JMenuItem передай в конструктор action. Разберись откуда возьмется имя пункта меню, +если его не устанавливать дополнительно. +7.3. Реализуй статический метод JMenuItem addMenuItem(JMenu parent, String text, Action +action), который добавляет в parent новый пункт меню с текстом text и действием action +при выборе этого метода. При реализации используй вызов метода из +предыдущего пункта. +7.4. Добавь в MenuHelper заглушки для следующих статический методов: +7.4.1. void initHelpMenu(View view, JMenuBar menuBar) - инициализация меню помощи. +7.4.2. void initFontMenu(View view, JMenuBar menuBar) - инициализация меню выбора +шрифта. +7.4.3. void initColorMenu(View view, JMenuBar menuBar) - инициализация меню выбора цвета. +7.4.4. void initAlignMenu(View view, JMenuBar menuBar) - инициализация меню +выравнивания. +7.4.5. void initStyleMenu(View view, JMenuBar menuBar) - инициализация меню выбора стиля +текста. +7.4.6. void initEditMenu(View view, JMenuBar menuBar) - инициализация меню +редактирования текста. +7.4.7. void initFileMenu(View view, JMenuBar menuBar) - инициализация меню Файл. + + + +HTML Editor (6) + +Реализуй метод инициализации панелей редактора initEditor(). Он должен: +6.1. Устанавливать значение "text/html" в качестве типа контента для компонента htmlTextPane. +Найди и используй подходящий метод. +6.2. Создавать новый локальный компонент JScrollPane на базе htmlTextPane. +6.3. Добавлять вкладку в панель tabbedPane с именем "HTML" и компонентом из предыдущего +пункта. +6.4. Создавать новый локальный компонент JScrollPane на базе plainTextPane. +6.5. Добавлять еще одну вкладку в tabbedPane с именем "Текст" и компонентом из +предыдущего пункта. +6.6. Устанавливать предпочтительный размер панели tabbedPane. +6.7. Создавать объект класса TabbedPaneChangeListener и устанавливать его в качестве +слушателя изменений в tabbedPane. +6.8. Добавлять по центру панели контента текущего фрейма нашу панель с вкладками. +Получить панель контента текущего фрейма можно с помощью метода +getContentPane(), его реализация унаследовалась от JFrame. +После запуска приложения можно будет увидеть текущие результаты: две независимые +закладки (HTML и Текст), в каждой из которых можно набирать свой текст. + + + From 21e2a60940f4577a30ad33161d384f80794d0cd2 Mon Sep 17 00:00:00 2001 From: PeucT Date: Mon, 10 Apr 2017 18:20:49 +0400 Subject: [PATCH 23/51] Level 28, 3209 big task (Full) --- .../task/task32/task3209/Controller.java | 113 +++++- .../task/task32/task3209/HTMLFileFilter.java | 31 ++ .../task/task32/task3209/MenuHelper.java | 132 +++++++ .../javarush/task/task32/task3209/View.java | 76 ++++- .../task32/task3209/actions/RedoAction.java | 2 +- .../task3209/actions/StrikeThroughAction.java | 17 +- .../task3209/actions/SubscriptAction.java | 11 +- .../task3209/actions/SuperscriptAction.java | 11 +- .../task32/task3209/actions/UndoAction.java | 2 +- .../listeners/TextEditMenuListener.java | 9 +- .../task3209/listeners/UndoListener.java | 21 ++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 323 ++++++------------ 12 files changed, 518 insertions(+), 230 deletions(-) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task32/task3209/HTMLFileFilter.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task32/task3209/MenuHelper.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/UndoListener.java diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/Controller.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/Controller.java index b2a5265..5687b9c 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/Controller.java +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/Controller.java @@ -1,7 +1,13 @@ package com.javarush.task.task32.task3209; +import com.javarush.task.task32.task3209.listeners.UndoListener; + +import javax.swing.*; +import javax.swing.event.DocumentListener; +import javax.swing.text.BadLocationException; import javax.swing.text.html.HTMLDocument; -import java.io.File; +import javax.swing.text.html.HTMLEditorKit; +import java.io.*; /** * Created by ArchMage on 07.04.17. @@ -12,7 +18,20 @@ public class Controller { private File currentFile; public void init(){ + createNewDocument(); + } + public HTMLDocument getDocument() { + return document; + } + + public void resetDocument(){ + if (document != null) { + document.removeUndoableEditListener(view.getUndoListener()); + } + document = (HTMLDocument) new HTMLEditorKit().createDefaultDocument(); + document.addUndoableEditListener(view.getUndoListener()); + view.update(); } public void exit(){ @@ -23,6 +42,98 @@ public Controller(View view) { this.view = view; } + public void setPlainText(String text){ + resetDocument(); + StringReader reader = new StringReader(text); + try { + new HTMLEditorKit().read(reader, document, 0); + } catch (IOException e) { + ExceptionHandler.log(e); + } catch (BadLocationException e) { + ExceptionHandler.log(e); + } + } + + public String getPlainText(){ + StringWriter writer = new StringWriter(); + try { + new HTMLEditorKit().write(writer, document, 0, document.getLength()); + } catch (IOException e) { + ExceptionHandler.log(e); + } catch (BadLocationException e) { + ExceptionHandler.log(e); + } + return writer.toString(); + } + + public void createNewDocument(){ + view.selectHtmlTab(); + resetDocument(); + view.setTitle("HTML редактор"); + view.resetUndo(); + currentFile = null; + + } + + public void saveDocumentAs(){ + view.selectHtmlTab(); + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setFileFilter(new HTMLFileFilter()); + int choose = fileChooser.showSaveDialog(view); + if (choose == JFileChooser.APPROVE_OPTION) { + currentFile = fileChooser.getSelectedFile(); + view.setTitle(currentFile.getName()); + try { + FileWriter writer = new FileWriter(currentFile); + new HTMLEditorKit().write(writer, document, 0, document.getLength()); + } catch (IOException e) { + ExceptionHandler.log(e); + } catch (BadLocationException e) { + ExceptionHandler.log(e); + } + } + } + + public void saveDocument(){ + if (currentFile == null){ + saveDocumentAs(); + } else { + view.selectHtmlTab(); + view.setTitle(currentFile.getName()); + try { + FileWriter writer = new FileWriter(currentFile); + new HTMLEditorKit().write(writer, document, 0, document.getLength()); + } catch (IOException e) { + ExceptionHandler.log(e); + } catch (BadLocationException e) { + ExceptionHandler.log(e); + } + } + } + + public void openDocument(){ + view.selectHtmlTab(); + JFileChooser chooser = new JFileChooser(); + chooser.setFileFilter(new HTMLFileFilter()); + int option = chooser.showOpenDialog(view); + if (option == JFileChooser.APPROVE_OPTION){ + currentFile = chooser.getSelectedFile(); + resetDocument(); + view.setTitle(currentFile.getName()); + try { + FileReader reader = new FileReader(currentFile); + new HTMLEditorKit().read(reader, document, 0); + view.resetUndo(); + } catch (FileNotFoundException e) { + ExceptionHandler.log(e); + } catch (BadLocationException e) { + ExceptionHandler.log(e); + } catch (IOException e) { + ExceptionHandler.log(e); + } + } + } + public static void main(String[] args){ View view = new View(); Controller controller = new Controller(view); diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/HTMLFileFilter.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/HTMLFileFilter.java new file mode 100644 index 0000000..bb00e90 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/HTMLFileFilter.java @@ -0,0 +1,31 @@ +package com.javarush.task.task32.task3209; + +import javax.swing.filechooser.FileFilter; +import java.io.File; + + +/** + * Created by ArchMage on 10.04.17. + */ +public class HTMLFileFilter extends FileFilter { + + + @Override + public boolean accept(File f) { + if (!f.isDirectory()) { + String fileName = f.getName(); + fileName = fileName.toLowerCase(); + if (fileName.endsWith(".html") || fileName.endsWith(".htm")) { + return true; + } else { + return false; + } + } + else { return true; } + } + + @Override + public String getDescription() { + return "HTML и HTM файлы"; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/MenuHelper.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/MenuHelper.java new file mode 100644 index 0000000..c115e7f --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/MenuHelper.java @@ -0,0 +1,132 @@ +package com.javarush.task.task32.task3209; + +import com.javarush.task.task32.task3209.actions.*; +import com.javarush.task.task32.task3209.listeners.TextEditMenuListener; +import com.javarush.task.task32.task3209.listeners.UndoMenuListener; + +import javax.swing.*; +import javax.swing.text.DefaultEditorKit; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledEditorKit; +import java.awt.*; +import java.awt.event.ActionListener; + +public class MenuHelper { + public static JMenuItem addMenuItem(JMenu parent, String text, ActionListener actionListener) { + JMenuItem menuItem = new JMenuItem(text); + menuItem.addActionListener(actionListener); + parent.add(menuItem); + return menuItem; + } + + public static JMenuItem addMenuItem(JMenu parent, String text, Action action) { + JMenuItem menuItem = addMenuItem(parent, action); + menuItem.setText(text); + return menuItem; + } + + public static JMenuItem addMenuItem(JMenu parent, Action action) { + JMenuItem menuItem = new JMenuItem(action); + parent.add(menuItem); + return menuItem; + } + + public static void initHelpMenu(View view, JMenuBar menuBar) { + JMenu helpMenu = new JMenu("Помощь"); + menuBar.add(helpMenu); + + addMenuItem(helpMenu, "О программе", view); + } + + public static void initFontMenu(View view, JMenuBar menuBar) { + JMenu fontMenu = new JMenu("Шрифт"); + menuBar.add(fontMenu); + + JMenu fontTypeMenu = new JMenu("Шрифт"); + fontMenu.add(fontTypeMenu); + + String[] fontTypes = {Font.SANS_SERIF, Font.SERIF, Font.MONOSPACED, Font.DIALOG, Font.DIALOG_INPUT}; + for (String fontType : fontTypes) { + addMenuItem(fontTypeMenu, fontType, new StyledEditorKit.FontFamilyAction(fontType, fontType)); + } + + JMenu fontSizeMenu = new JMenu("Размер шрифта"); + fontMenu.add(fontSizeMenu); + + String[] fontSizes = {"6", "8", "10", "12", "14", "16", "20", "24", "32", "36", "48", "72"}; + for (String fontSize : fontSizes) { + addMenuItem(fontSizeMenu, fontSize, new StyledEditorKit.FontSizeAction(fontSize, Integer.parseInt(fontSize))); + } + + fontMenu.addMenuListener(new TextEditMenuListener(view)); + } + + public static void initColorMenu(View view, JMenuBar menuBar) { + JMenu colorMenu = new JMenu("Цвет"); + menuBar.add(colorMenu); + + addMenuItem(colorMenu, new StyledEditorKit.ForegroundAction("Красный", Color.red)); + addMenuItem(colorMenu, new StyledEditorKit.ForegroundAction("Оранжевый", Color.orange)); + addMenuItem(colorMenu, new StyledEditorKit.ForegroundAction("Желтый", Color.yellow)); + addMenuItem(colorMenu, new StyledEditorKit.ForegroundAction("Зеленый", Color.green)); + addMenuItem(colorMenu, new StyledEditorKit.ForegroundAction("Синий", Color.blue)); + addMenuItem(colorMenu, new StyledEditorKit.ForegroundAction("Голубой", Color.cyan)); + addMenuItem(colorMenu, new StyledEditorKit.ForegroundAction("Пурпурный", Color.magenta)); + addMenuItem(colorMenu, new StyledEditorKit.ForegroundAction("Черный", Color.black)); + + colorMenu.addMenuListener(new TextEditMenuListener(view)); + } + + public static void initAlignMenu(View view, JMenuBar menuBar) { + JMenu alignMenu = new JMenu("Выравнивание"); + menuBar.add(alignMenu); + + addMenuItem(alignMenu, new StyledEditorKit.AlignmentAction("По левому краю", StyleConstants.ALIGN_LEFT)); + addMenuItem(alignMenu, new StyledEditorKit.AlignmentAction("По центру", StyleConstants.ALIGN_CENTER)); + addMenuItem(alignMenu, new StyledEditorKit.AlignmentAction("По правому краю", StyleConstants.ALIGN_RIGHT)); + + alignMenu.addMenuListener(new TextEditMenuListener(view)); + } + + public static void initStyleMenu(View view, JMenuBar menuBar) { + JMenu styleMenu = new JMenu("Стиль"); + menuBar.add(styleMenu); + + addMenuItem(styleMenu, "Полужирный", new StyledEditorKit.BoldAction()); + addMenuItem(styleMenu, "Подчеркнутый", new StyledEditorKit.UnderlineAction()); + addMenuItem(styleMenu, "Курсив", new StyledEditorKit.ItalicAction()); + + styleMenu.addSeparator(); + + addMenuItem(styleMenu, "Подстрочный знак", new SubscriptAction()); + addMenuItem(styleMenu, "Надстрочный знак", new SuperscriptAction()); + addMenuItem(styleMenu, "Зачеркнутый", new StrikeThroughAction()); + + styleMenu.addMenuListener(new TextEditMenuListener(view)); + } + + public static void initEditMenu(View view, JMenuBar menuBar) { + JMenu editMenu = new JMenu("Редактировать"); + menuBar.add(editMenu); + + JMenuItem undoItem = addMenuItem(editMenu, "Отменить", new UndoAction(view)); + JMenuItem redoItem = addMenuItem(editMenu, "Вернуть", new RedoAction(view)); + addMenuItem(editMenu, "Вырезать", new DefaultEditorKit.CutAction()); + addMenuItem(editMenu, "Копировать", new DefaultEditorKit.CopyAction()); + addMenuItem(editMenu, "Вставить", new DefaultEditorKit.PasteAction()); + + editMenu.addMenuListener(new UndoMenuListener(view, undoItem, redoItem)); + } + + public static void initFileMenu(View view, JMenuBar menuBar) { + JMenu fileMenu = new JMenu("Файл"); + menuBar.add(fileMenu); + + addMenuItem(fileMenu, "Новый", view); + addMenuItem(fileMenu, "Открыть", view); + addMenuItem(fileMenu, "Сохранить", view); + addMenuItem(fileMenu, "Сохранить как...", view); + fileMenu.addSeparator(); + addMenuItem(fileMenu, "Выход", view); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/View.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/View.java index e10617a..afabdfa 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/View.java +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/View.java @@ -2,8 +2,11 @@ import com.javarush.task.task32.task3209.listeners.FrameListener; import com.javarush.task.task32.task3209.listeners.TabbedPaneChangeListener; +import com.javarush.task.task32.task3209.listeners.UndoListener; import javax.swing.*; +import javax.swing.text.html.HTMLDocument; +import javax.swing.undo.UndoManager; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -16,6 +19,8 @@ public class View extends JFrame implements ActionListener { private JTabbedPane tabbedPane = new JTabbedPane(); private JTextPane htmlTextPane = new JTextPane(); private JEditorPane plainTextPane = new JEditorPane(); + private UndoManager undoManager = new UndoManager(); + private UndoListener undoListener = new UndoListener(undoManager); public View(){ try { @@ -39,7 +44,12 @@ public void init(){ } public void selectedTabChanged(){ - + if (tabbedPane.getSelectedIndex() == 0) { + controller.setPlainText(plainTextPane.getText()); + } else { + plainTextPane.setText(controller.getPlainText()); + } + resetUndo(); } public void initMenuBar(){ @@ -75,6 +85,14 @@ public void initGui(){ pack(); } + public UndoListener getUndoListener() { + return undoListener; + } + + public void resetUndo(){ + undoManager.discardAllEdits(); + } + public void exit(){ controller.exit(); } @@ -88,15 +106,65 @@ public void setController(Controller controller) { } public boolean canUndo(){ - return false; + return undoManager.canUndo(); } public boolean canRedo(){ - return false; + return undoManager.canRedo(); + } + + public void undo(){ + try { + undoManager.undo(); + } catch (Exception e){ + ExceptionHandler.log(e); + } + } + + public void redo(){ + try{ + undoManager.redo(); + } catch (Exception e){ + ExceptionHandler.log(e); + } + } + + public boolean isHtmlTabSelected(){ + if (tabbedPane.getSelectedIndex() == 0) { return true; } + else {return false;} } + public void selectHtmlTab(){ + tabbedPane.setSelectedIndex(0); + resetUndo(); + } + + public void update(){ + HTMLDocument document = controller.getDocument(); + selectHtmlTab(); + htmlTextPane.setDocument(document); + } + + public void showAbout(){ + JOptionPane.showMessageDialog(this, "Сообщение", "Текст сообщения", JOptionPane.INFORMATION_MESSAGE); + } + + @Override public void actionPerformed(ActionEvent e) { - + String action = e.getActionCommand(); + if ("Новый".equals(action)) { + controller.createNewDocument(); + }else if ("Открыть".equals(action)){ + controller.openDocument(); + }else if ("Сохранить".equals(action)){ + controller.saveDocument(); + }else if ("Сохранить как...".equals(action)){ + controller.saveDocumentAs(); + }else if ("Выход".equals(action)){ + controller.exit(); + }else if ("О программе".equals(action)){ + showAbout(); + } } } diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/RedoAction.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/RedoAction.java index e413ca0..b7fc221 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/RedoAction.java +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/RedoAction.java @@ -17,6 +17,6 @@ public RedoAction(View view) { @Override public void actionPerformed(ActionEvent e) { - + view.redo(); } } diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/StrikeThroughAction.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/StrikeThroughAction.java index 2b139de..12c8f70 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/StrikeThroughAction.java +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/StrikeThroughAction.java @@ -1,20 +1,25 @@ package com.javarush.task.task32.task3209.actions; +import javax.swing.*; +import javax.swing.text.MutableAttributeSet; +import javax.swing.text.SimpleAttributeSet; import javax.swing.text.StyleConstants; import javax.swing.text.StyledEditorKit; import java.awt.event.ActionEvent; -/** - * Created by ArchMage on 07.04.17. - */ public class StrikeThroughAction extends StyledEditorKit.StyledTextAction { public StrikeThroughAction() { super(StyleConstants.StrikeThrough.toString()); } - @Override - public void actionPerformed(ActionEvent e) { - + public void actionPerformed(ActionEvent actionEvent) { + JEditorPane editor = getEditor(actionEvent); + if (editor != null) { + MutableAttributeSet mutableAttributeSet = getStyledEditorKit(editor).getInputAttributes(); + SimpleAttributeSet simpleAttributeSet = new SimpleAttributeSet(); + StyleConstants.setStrikeThrough(simpleAttributeSet, !StyleConstants.isStrikeThrough(mutableAttributeSet)); + setCharacterAttributes(editor, simpleAttributeSet, false); + } } } diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/SubscriptAction.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/SubscriptAction.java index d8b9892..6c137ca 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/SubscriptAction.java +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/SubscriptAction.java @@ -1,5 +1,8 @@ package com.javarush.task.task32.task3209.actions; +import javax.swing.*; +import javax.swing.text.MutableAttributeSet; +import javax.swing.text.SimpleAttributeSet; import javax.swing.text.StyleConstants; import javax.swing.text.StyledEditorKit; import java.awt.event.ActionEvent; @@ -15,6 +18,12 @@ public SubscriptAction() { @Override public void actionPerformed(ActionEvent e) { - + JEditorPane editor = getEditor(e); + if (editor != null) { + MutableAttributeSet mutableAttributeSet = getStyledEditorKit(editor).getInputAttributes(); + SimpleAttributeSet simpleAttributeSet = new SimpleAttributeSet(); + StyleConstants.setSubscript(simpleAttributeSet, !StyleConstants.isSubscript(mutableAttributeSet)); + setCharacterAttributes(editor, simpleAttributeSet, false); + } } } diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/SuperscriptAction.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/SuperscriptAction.java index 31a4668..df2242a 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/SuperscriptAction.java +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/SuperscriptAction.java @@ -1,5 +1,8 @@ package com.javarush.task.task32.task3209.actions; +import javax.swing.*; +import javax.swing.text.MutableAttributeSet; +import javax.swing.text.SimpleAttributeSet; import javax.swing.text.StyleConstants; import javax.swing.text.StyledEditorKit; import java.awt.event.ActionEvent; @@ -15,6 +18,12 @@ public SuperscriptAction() { @Override public void actionPerformed(ActionEvent e) { - + JEditorPane editor = getEditor(e); + if (editor != null) { + MutableAttributeSet mutableAttributeSet = getStyledEditorKit(editor).getInputAttributes(); + SimpleAttributeSet simpleAttributeSet = new SimpleAttributeSet(); + StyleConstants.setSuperscript(simpleAttributeSet, !StyleConstants.isSuperscript(mutableAttributeSet)); + setCharacterAttributes(editor, simpleAttributeSet, false); + } } } diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/UndoAction.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/UndoAction.java index ad0313e..68d85b2 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/UndoAction.java +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/UndoAction.java @@ -17,6 +17,6 @@ public UndoAction(View view) { @Override public void actionPerformed(ActionEvent e) { - + view.undo(); } } diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/TextEditMenuListener.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/TextEditMenuListener.java index 2244497..75d45b2 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/TextEditMenuListener.java +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/TextEditMenuListener.java @@ -2,8 +2,10 @@ import com.javarush.task.task32.task3209.View; +import javax.swing.*; import javax.swing.event.MenuEvent; import javax.swing.event.MenuListener; +import java.awt.*; /** * Created by ArchMage on 07.04.17. @@ -17,7 +19,12 @@ public TextEditMenuListener(View view){ @Override public void menuSelected(MenuEvent e) { - + JMenu editObject = (JMenu) e.getSource(); + Component[] menuList = editObject.getMenuComponents(); + boolean isEnable = view.isHtmlTabSelected(); + for (Component entry : menuList){ + entry.setEnabled(isEnable); + } } @Override diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/UndoListener.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/UndoListener.java new file mode 100644 index 0000000..d5c4242 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/UndoListener.java @@ -0,0 +1,21 @@ +package com.javarush.task.task32.task3209.listeners; + +import javax.swing.event.UndoableEditEvent; +import javax.swing.event.UndoableEditListener; +import javax.swing.undo.UndoManager; + +/** + * Created by ArchMage on 10.04.17. + */ +public class UndoListener implements UndoableEditListener { + private UndoManager undoManager; + + public UndoListener(UndoManager undoManager) { + this.undoManager = undoManager; + } + + @Override + public void undoableEditHappened(UndoableEditEvent e) { + undoManager.addEdit(e.getEdit()); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" index e801d14..24cebe9 100644 --- "a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" +++ "b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -1,220 +1,115 @@ -taskKey="com.javarush.task.task32.task3209.big11" - -HTML Editor (11) - -11.1. Добавь в представление поле UndoManager undoManager. Разберись для чего -используется этот класс. Проинициализируй поле класса новым объектом. -11.2. Добавь класс UndoListener реализующий интерфейс UndoableEditListener в пакет -listeners. Этот класс будет следить за правками, которые можно отменить или вернуть. -11.3. Добавь в класс UndoListener: -11.3.1. Поле UndoManager undoManager. -11.3.2. Конструктор, который принимает UndoManager и инициализирует поле класса. -11.3.3. Метод undoableEditHappened(UndoableEditEvent e). Он должен из переданного -события получать правку и добавлять ее в undoManager. -11.4. Добавь в представление поле UndoListener undoListener, проинициализируй его -используя undoManager. -11.5. Добавь в представление методы: -11.5.1. void undo() - отменяет последнее действие. Реализуй его используя undoManager. -Метод не должен кидать исключений, логируй их. -11.5.2. void redo() - возвращает ранее отмененное действие. Реализуй его по аналогии с -предыдущим пунктом. -11.5.3. Реализуй методы boolean canUndo() и boolean canRedo() используя undoManager. -11.5.4. Реализуй геттер для undoListener. -11.5.5. Добавь и реализуй метод void resetUndo(), который должен сбрасывать все правки в -менеджере undoManager. +taskKey="com.javarush.task.task32.task3209.big24" + +HTML Editor (24) + +Твой html редактор готов! +Ты научился: +- Создавать приложения с графическим интерфейсом. +- Работать с диалоговыми окнами. +- Пользоваться классами из библиотеки Swing. +- Реализовывать взаимодействие компонентов программы с помощью событий, слушателей, +действий. +- Усилил свои знания в области MVC. + +Что можно улучшить в разработанном редакторе: +- Добавить панель инструментов, повторяющую функционал меню. +- Добавить подсветку html тегов на второй вкладке. +- Добавить возможность загрузки документа из Интернет. +- Расширить возможности редактора (вставка картинки, ссылки и т.д.) + +Поздравляю, так держать! Требования: -1. Класс View должен содержать приватное поле UndoManager undoManager, которое должно быть сразу проинициализовано. -2. Класс View должен содержать приватное поле UndoListener undoListener, которое должно быть сразу проинициализовано через поле undoManager. -3. Класс View должен содержать геттер к полю UndoListener undoListener. -4. Класс View должен содержать public void метод undo(). -5. Класс View должен содержать public void метод redo(). -6. Реализация метода canUndo() класса View должна использовать undoManager. -7. Реализация метода canRedo() класса View должна использовать undoManager. -8. Класс View должен содержать public void метод resetUndo(), который должен сбрасывать все правки в менеджере undoManager. -9. Класс UndoListener должен быть создан в отдельном файле. -10. Класс UndoListener должен содержать приватное поле UndoManager undoManager. -11. Конструктор UndoListener(UndoManager undoManager) должен корректно инициализировать поле undoManager. -12. Метод undoableEditHappened(UndoableEditEvent e) в классе UndoListener должен из переданного события получать правку и добавлять ее в undoManager. - - -HTML Editor (10) - -Наш редактор будет поддерживать механизм отмены/возврата (undo/redo) действий в -редакторе. -Реализуй класс UndoMenuListener. Этот слушатель будет следить за меню, а если конкретнее, -то за моментом, когда меню редактирования будет выбрано пользователем. В этот момент он -будет запрашивать у представления можем ли мы сейчас отменить или вернуть какое-то -действие, и в зависимости от этого делать доступными или не доступными пункты меню -"Отменить" и "Вернуть". -10.1. Добавь в класс UndoMenuListener следующие поля: -10.1.1. Представление View view. -10.1.2. Пункт меню "Отменить" JMenuItem undoMenuItem. -10.1.3. Пункт меню "Вернуть" JMenuItem redoMenuItem. -10.2. Реализуй конструктор UndoMenuListener(View view, JMenuItem undoMenuItem, -JMenuItem redoMenuItem), он должен инициализировать поля класса. -10.3. Реализуй метод menuSelected(MenuEvent menuEvent). Он будет вызываться перед -показом меню. Он должен: -10.3.1. Спрашивать у представления можем ли мы отменить действие с помощью метода -boolean canUndo(). Пока у представления нет такого метода, поэтому добавь заглушку, -которая всегда возвращает false. -10.3.2. Делать доступным или не доступным пункт меню undoMenuItem в зависимости от того, -что нам вернуло представление. Подсказка: используй метод setEnabled(). -10.3.3. Аналогично поступи и для пункта меню redoMenuItem, добавив метод-заглушку -canRedo() в представление. -Запусти программу и убедись, что пункты меню Отменить и Вернуть недоступны. - - - -HTML Editor (9) - -9.1. Реализуй метод initMenuBar(). Он должен: -9.1.1. Создавать новый объект типа JMenuBar. Это и будет наша панель меню. -9.1.2. С помощью MenuHelper инициализировать меню в следующем порядке: Файл, -Редактировать, Стиль, Выравнивание, Цвет, Шрифт и Помощь. -9.1.3. Добавлять в верхнюю часть панели контента текущего фрейма нашу панель меню, -аналогично тому, как это мы делали с панелью вкладок. -9.2. Добавь конструктор класса View. Он должен устанавливать внешний вид и поведение -(look and feel) нашего приложения такими же, как это определено в системе. -Конструктор не должен кидать исключений, только логировать их с помощью -ExceptionHandler. Подсказа: для реализации задания используй класс UIManager. - -Запусти приложение, теперь ты должен видеть панель с меню вверху окна. Некоторые из -пунктов меню (например: Вырезать, Копировать, Вставить, Стиль (частично), Выравнивание, -Цвет, Шрифт) должны уже работать. Убедись, что все работает и только затем продолжи -разработку. - - - -HTML Editor (8) - -Пришло время добавить все необходимые пункты меню и написать классы действий, -выполняемые при нажатии. Это довольно трудоемкая и рутинная работа, а ты отличный -ученик и не хотелось бы тебя огорчать. Поэтому, в качестве бонуса ты получаешь готовый класс -MenuHelper! А ты: -8.1. Напиши в пакете actions заглушки для следующих классов: -8.1.1. Класс отмены действия UndoAction. Он должен наследоваться от AbstractAction и -содержать конструктор UndoAction(View view). -8.1.2. Класс возврата действия RedoAction. Требования аналогичны требованиям к -UndoAction. -8.1.3. Класс StrikeThroughAction, который отвечает за стиль текста "Зачеркнутый". Унаследуй -его от StyledEditorKit.StyledTextAction. -8.1.4. Класс SubscriptAction, который отвечает за стиль текста "Подстрочный знак". Его также -унаследуй его от StyledEditorKit.StyledTextAction. -8.1.5. Класс SuperscriptAction. Он будет отвечать за стиль "Надстрочный знак". Добавь ему -правильный родительский класс. -8.2. Напиши в пакете listeners заглушки для классов: -8.2.1. UndoMenuListener, он должен реализовывать интерфейс MenuListener и иметь -конструктор UndoMenuListener(View view, JMenuItem undoMenuItem, JMenuItem -redoMenuItem). Чем он будет заниматься узнаешь чуть позже. -8.2.2. TextEditMenuListener. Этот класс также должен реализовывать интерфейс MenuListener. -Добавь ему конструктор TextEditMenuListener(View view). В следующих заданиях мы -рассмотрим его детальнее. - - - -HTML Editor (7) - -Добавь класс MenuHelper. Это будет вспомогательный класс для инициализации и настройки -меню. У меню будет следующая структура: -- Файл --- Новый --- Открыть --- Сохранить --- Сохранить как... --- Выход - -- Редактировать --- Отменить --- Вернуть --- Вырезать --- Копировать --- Вставить - -- Стиль --- Полужирный --- Подчеркнутый --- Курсив --- Подстрочный знак --- Надстрочный знак --- Зачеркнутый - -- Выравнивание --- По левому краю --- По центру --- По правому краю - -- Цвет --- Красный --- Оранжевый --- Желтый --- Зеленый --- Синий --- Голубой --- Пурпурный --- Черный - -- Шрифт --- Шрифт ---- SansSerif, Serif, Monospaced, Dialog, DialogInput, --- Размер шрифта ---- 6, 8, 10, 12, 14, 16, 20, 24, 32, 36, 48, 72 - -- Помощь --- О программе - -7.1. Реализуй в MenuHelper статический метод JMenuItem addMenuItem(JMenu parent, String -text, ActionListener actionListener), где parent - меню в которое мы добавляем пункт, text - -текст добавляемого пункта, actionListener - слушатель действий добавляемого пункта -меню. Он должен: -7.1.1. Создавать новый пункт меню JMenuItem, используя text. -7.1.2. Устанавливать этому пункту слушателя действий с помощью метода addActionListener(). -7.1.3. Добавлять в parent созданный пункт меню. -7.1.4. Возвращать созданный пункт меню. -7.2. Реализуй статический метод JMenuItem addMenuItem(JMenu parent, Action action). Этот -метод аналогичен предыдущему, но в качестве параметра принимает действие action, -которое необходимо выполнить при выборе пункта меню. Подсказка: при создании -JMenuItem передай в конструктор action. Разберись откуда возьмется имя пункта меню, -если его не устанавливать дополнительно. -7.3. Реализуй статический метод JMenuItem addMenuItem(JMenu parent, String text, Action -action), который добавляет в parent новый пункт меню с текстом text и действием action -при выборе этого метода. При реализации используй вызов метода из -предыдущего пункта. -7.4. Добавь в MenuHelper заглушки для следующих статический методов: -7.4.1. void initHelpMenu(View view, JMenuBar menuBar) - инициализация меню помощи. -7.4.2. void initFontMenu(View view, JMenuBar menuBar) - инициализация меню выбора -шрифта. -7.4.3. void initColorMenu(View view, JMenuBar menuBar) - инициализация меню выбора цвета. -7.4.4. void initAlignMenu(View view, JMenuBar menuBar) - инициализация меню -выравнивания. -7.4.5. void initStyleMenu(View view, JMenuBar menuBar) - инициализация меню выбора стиля -текста. -7.4.6. void initEditMenu(View view, JMenuBar menuBar) - инициализация меню -редактирования текста. -7.4.7. void initFileMenu(View view, JMenuBar menuBar) - инициализация меню Файл. - - - -HTML Editor (6) - -Реализуй метод инициализации панелей редактора initEditor(). Он должен: -6.1. Устанавливать значение "text/html" в качестве типа контента для компонента htmlTextPane. -Найди и используй подходящий метод. -6.2. Создавать новый локальный компонент JScrollPane на базе htmlTextPane. -6.3. Добавлять вкладку в панель tabbedPane с именем "HTML" и компонентом из предыдущего -пункта. -6.4. Создавать новый локальный компонент JScrollPane на базе plainTextPane. -6.5. Добавлять еще одну вкладку в tabbedPane с именем "Текст" и компонентом из -предыдущего пункта. -6.6. Устанавливать предпочтительный размер панели tabbedPane. -6.7. Создавать объект класса TabbedPaneChangeListener и устанавливать его в качестве -слушателя изменений в tabbedPane. -6.8. Добавлять по центру панели контента текущего фрейма нашу панель с вкладками. -Получить панель контента текущего фрейма можно с помощью метода -getContentPane(), его реализация унаследовалась от JFrame. -После запуска приложения можно будет увидеть текущие результаты: две независимые -закладки (HTML и Текст), в каждой из которых можно набирать свой текст. +1. html редактор готов! + + +HTML Editor (23) + +23.1. Напишем метод для сохранения открытого файла saveDocument(). Метод должен +работать также, как saveDocumentAs(), но не запрашивать файл у пользователя, а +использовать currentFile. Если currentFile равен null, то вызывать метод saveDocumentAs(). +23.2. Пришло время реализовать метод openDocument(). Метод должен работать +аналогично методу saveDocumentAs(), в той части, которая отвечает за выбор файла. +Подсказка: Обрати внимание на имя метода для показа диалогового окна. +Когда файл выбран, необходимо: +23.2.1. Установить новое значение currentFile. +23.2.2. Сбросить документ. +23.2.3. Установить имя файла в заголовок у представления. +23.2.4. Создать FileReader, используя currentFile. +23.2.5. Вычитать данные из FileReader-а в документ document с помощью объекта класса +HTMLEditorKit. +23.2.6. Сбросить правки (вызвать метод resetUndo представления). +23.2.7. Если возникнут исключения - залогируй их и не пробрасывай наружу. +Проверь работу пунктов меню Сохранить и Открыть. + + + +HTML Editor (22) + +Реализуем в контроллере метод для сохранения файла под новым именем saveDocumentAs(). +Реализация должна: +22.1. Переключать представление на html вкладку. +22.2. Создавать новый объект для выбора файла JFileChooser. +22.3. Устанавливать ему в качестве фильтра объект HTMLFileFilter. +22.4. Показывать диалоговое окно "Save File" для выбора файла. +22.5. Если пользователь подтвердит выбор файла: +22.5.1. Сохранять выбранный файл в поле currentFile. +22.5.2. Устанавливать имя файла в качестве заголовка окна представления. +22.5.3. Создавать FileWriter на базе currentFile. +22.5.4. Переписывать данные из документа document в объекта FileWriter-а аналогично тому, +как мы это делали в методе getPlainText(). +22.6. Метод не должен кидать исключения. +Проверь работу пункта меню Сохранить как... + + + +HTML Editor (21) + +Для открытия или сохранения файла мы будем использовать JFileChooser из библиотеки swing. +Объекты этого типа поддерживают фильтры, унаследованные от FileFilter. Сейчас мы напишем +свой фильтр: +21.1. Создай публичный класс HTMLFileFilter унаследованный от FileFilter. +21.2. Мы хотим, чтобы окно выбора файла отображало только html/htm файлы или папки. +Переопредели метод accept(File file), чтобы он возвращал true, если переданный файл +директория или содержит в конце имени ".html" или ".htm" без учета регистра. +21.3. Чтобы в окне выбора файла в описании доступных типов файлов отображался текст +"HTML и HTM файлы" переопредели соответствующим образом метод getDescription(). + + + +HTML Editor (20) + +20.1. Реализуй метод создания нового документа createNewDocument() в контроллере. Он +должен: +20.1.1. Выбирать html вкладку у представления. +20.1.2. Сбрасывать текущий документ. +20.1.3. Устанавливать новый заголовок окна, например: "HTML редактор". Воспользуйся +методом setTitle(), который унаследован в нашем представлении. +20.1.4. Сбрасывать правки в Undo менеджере. Используй метод resetUndo представления. +20.1.5. Обнулить переменную currentFile. +20.2. Реализуй метод инициализации init() контроллера. Он должен просто вызывать метод +создания нового документа. +Проверь работу пункта меню Новый. + + + +HTML Editor (19) + +Реализуем метод actionPerformed(ActionEvent actionEvent) у представления, этот метод +наследуется от интерфейса ActionListener и будет вызваться при выборе пунктов меню, у +которых наше представление указано в виде слушателя событий. +19.1. Получи из события команду с помощью метода getActionCommand(). Это будет +обычная строка. По этой строке ты можешь понять какой пункт меню создал данное +событие. +19.2. Если это команда "Новый", вызови у контроллера метод createNewDocument(). В этом +пункте и далее, если необходимого метода в контроллере еще нет - создай заглушки. +19.3. Если это команда "Открыть", вызови метод openDocument(). +19.4. Если "Сохранить", то вызови saveDocument(). +19.5. Если "Сохранить как..." - saveDocumentAs(). +19.6. Если "Выход" - exit(). +19.7. Если "О программе", то вызови метод showAbout() у представления. +Проверь, что заработали пункты меню Выход и О программе. From 9c84632f90c2982166d1e93e3a0e1affd60a02c7 Mon Sep 17 00:00:00 2001 From: PeucT Date: Tue, 11 Apr 2017 18:24:05 +0400 Subject: [PATCH 24/51] Level 30. Big task (1-10) --- .../task/task35/task3513/Controller.java | 64 +++++ .../javarush/task/task35/task3513/Main.java | 21 ++ .../javarush/task/task35/task3513/Model.java | 242 ++++++++++++++++++ .../javarush/task/task35/task3513/Tile.java | 58 +++++ .../javarush/task/task35/task3513/View.java | 69 +++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 154 +++++++++++ 6 files changed, 608 insertions(+) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task35/task3513/Controller.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task35/task3513/Main.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task35/task3513/Model.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task35/task3513/Tile.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task35/task3513/View.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task35/task3513/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Controller.java b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Controller.java new file mode 100644 index 0000000..8498d5e --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Controller.java @@ -0,0 +1,64 @@ +package com.javarush.task.task35.task3513; + +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + +/** + * Created by ArchMage on 11.04.17. + */ +public class Controller extends KeyAdapter { + private Model model; + private View view; + private final static int WINNING_TILE = 2048; + + public Controller(Model model) { + this.model = model; + view = new View(this); + } + + public void resetGame(){ + view.isGameLost = false; + view.isGameWon = false; + model.score = 0; + model.resetGameTiles(); + } + + public View getView() { + return view; + } + + public Tile[][] getGameTiles(){ + return model.getGameTiles(); + } + + public int getScore(){ + return model.score; + } + + @Override + public void keyPressed(KeyEvent e) { + int code = e.getKeyCode(); + if (code == 27) { + resetGame(); + } else { + if (!model.canMove()) { + view.isGameLost = true; + } else{ + if (!view.isGameLost && !view.isGameWon) { + if (e.getKeyCode() == KeyEvent.VK_LEFT) { + model.left(); + } else if (e.getKeyCode() == KeyEvent.VK_UP) { + model.up(); + }else if (e.getKeyCode() == KeyEvent.VK_RIGHT) { + model.right(); + }else if (e.getKeyCode() == KeyEvent.VK_DOWN) { + model.down(); + } + if (model.maxTile == WINNING_TILE) { view.isGameWon = true; } + } + } + } + view.repaint(); + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Main.java b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Main.java new file mode 100644 index 0000000..52be888 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Main.java @@ -0,0 +1,21 @@ +package com.javarush.task.task35.task3513; + +import javax.swing.*; + +/** + * Created by ArchMage on 11.04.17. + */ +public class Main { + public static void main(String[] args){ + Model gameModel = new Model(); + Controller controller = new Controller(gameModel); + JFrame game = new JFrame(); + game.setTitle("2048"); + game.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + game.setSize(450, 500); + game.setResizable(false); + game.add(controller.getView()); + game.setLocationRelativeTo(null); + game.setVisible(true); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Model.java b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Model.java new file mode 100644 index 0000000..31b6a14 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Model.java @@ -0,0 +1,242 @@ +package com.javarush.task.task35.task3513; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by ArchMage on 11.04.17. + */ +public class Model { + private static final int FIELD_WIDTH = 4; + private Tile[][] gameTiles; + protected int score; + protected int maxTile; + + public Model(){ + resetGameTiles(); + } + + private void addTile(){ + List emptyList = getEmptyTiles(); + if (emptyList != null && emptyList.size() != 0) { + Tile tile = emptyList.get((int) (Math.random() * emptyList.size())); + int tileWeight = Math.random() < 0.9 ? 2 : 4; + tile.value = tileWeight; + } + } + + protected void resetGameTiles(){ + gameTiles = new Tile[FIELD_WIDTH][FIELD_WIDTH]; + for (int i = 0; i < FIELD_WIDTH; i++){ + for (int j = 0; j < FIELD_WIDTH; j++){ + gameTiles[i][j] = new Tile(); + } + } + addTile(); + addTile(); + maxTile = 2; + score = 0; + } + + private List getEmptyTiles(){ + ArrayList emptyTilesList = new ArrayList(); + for (int i = 0; i < FIELD_WIDTH; i++){ + for (int j = 0; j < FIELD_WIDTH; j++){ + if (gameTiles[i][j].isEmpty()) { + emptyTilesList.add(gameTiles[i][j]); + } + } + } + return emptyTilesList; + } + + /*private boolean compressTiles(Tile[] tiles){ + boolean isChanged = true; + for (int i = 0; i < tiles.length; i++){ + if (tiles[i].value == 0) { + boolean isAllZero = false; + for (int j = 1; j <= tiles.length - i; j++) { + try { + if (tiles[i+j].value != 0) { isAllZero = false; } + tiles[i + j - 1].value = tiles[i + j].value; + + } catch (Exception e) { + tiles[i + j - 1].value = 0; + + } + } + if (tiles[i].value == 0 && !isAllZero) { i--; } + } + } + + return false; + }*/ + + private boolean compressTiles(Tile[] tiles){ + int counter = 0; + boolean isChanged = false; + int values[] = new int[tiles.length]; + for (int i = 0; i < values.length; i++){ + values[i] = 0; + } + + for (int i = 0; i < tiles.length; i++){ + if (tiles[i].value != 0) { + values[counter] = tiles[i].value; + counter++; + } + } + + for (int i = 0; i < tiles.length; i++){ + if (values[i] != tiles[i].value) { isChanged = true; } + tiles[i].value = values[i]; + } + + return isChanged; + + } + + private boolean mergeTiles(Tile[] tiles){ + boolean isChanged = false; + for (int i = 0; i < tiles.length - 1; i++){ + if (tiles[i].value == tiles[i+1].value && tiles[i].value != 0) { + tiles[i].value = tiles[i].value * 2; + score = score + tiles[i].value; + if (tiles[i].value > maxTile) { maxTile = tiles[i].value; } + for (int j = 2; j <= tiles.length - i; j++){ + try { + tiles[i + j - 1 ].value = tiles[i + j].value; + } catch (Exception e){ + tiles[i + j - 1].value = 0; + isChanged = true; + } + } + } + } + return isChanged; + } + + public void left(){ + boolean isChanged = false; + for (int i = 0; i < FIELD_WIDTH; i++){ + if (compressTiles(gameTiles[i])) { isChanged = true; } + if (mergeTiles(gameTiles[i])) { isChanged = true; } + } + if (isChanged) {addTile(); } + } + + public void up(){ + rotate(gameTiles); + rotate(gameTiles); + rotate(gameTiles); + left(); + rotate(gameTiles); + } + + public void right(){ + rotate(gameTiles); + rotate(gameTiles); + left(); + rotate(gameTiles); + rotate(gameTiles); + } + + public void down(){ + rotate(gameTiles); + left(); + rotate(gameTiles); + rotate(gameTiles); + rotate(gameTiles); + } + + private void rotate(Tile[][] arrayGameTiles){ + int[][] values = new int[FIELD_WIDTH][FIELD_WIDTH]; + for (int i = 0; i < FIELD_WIDTH; i++){ + for (int j = 0; j < FIELD_WIDTH; j++){ + values[i][j] = arrayGameTiles[i][j].value; + } + } + + for (int i = 0; i < FIELD_WIDTH; i++){ + for (int j = 0; j < FIELD_WIDTH; j++){ + arrayGameTiles[j][FIELD_WIDTH - i - 1].value = values[i][j]; + } + } + } + + public Tile[][] getGameTiles() { + return gameTiles; + } + + public boolean canMove(){ + Tile[][] tempArray = new Tile[FIELD_WIDTH][FIELD_WIDTH]; + for (int i = 0; i < FIELD_WIDTH; i++){ + for (int j = 0; j < FIELD_WIDTH; j++){ + tempArray[i][j] = new Tile(gameTiles[i][j].value); + } + } + + + for (int i = 0; i < 4; i++) { + if (canMoveLeft(tempArray)) { + return true; + } + rotate(tempArray); + } + return false; + } + + private boolean canMoveLeft(Tile[][] arrayGameTiles){ + for (int i = 0; i < FIELD_WIDTH; i++){ + if (testCompressTiles(arrayGameTiles[i])) { return true; } + if (testMergeTiles(arrayGameTiles[i])) { return true; } + } + return false; + } + + // Вынесем тестовые методы сюда. Лучше, конечно, добавить возможность тестового вызова в аналогичные "настоящие" методы, + // но непонятно, как на смену сигнатуры методов отреагирует валидатор + + private boolean testCompressTiles(Tile[] tiles){ + int counter = 0; + int values[] = new int[tiles.length]; + for (int i = 0; i < values.length; i++){ + values[i] = 0; + } + + for (int i = 0; i < tiles.length; i++){ + if (tiles[i].value != 0) { + values[counter] = tiles[i].value; + counter++; + } + } + + for (int i = 0; i < tiles.length; i++){ + if (values[i] != tiles[i].value) { return true; } + tiles[i].value = values[i]; + } + + return false; + + } + + private boolean testMergeTiles(Tile[] tiles){ + for (int i = 0; i < tiles.length - 1; i++){ + if (tiles[i].value == tiles[i+1].value && tiles[i].value != 0) { + tiles[i].value = tiles[i].value * 2; + // В настоящих методах, тут шло изменение счета и максимальной плашки, но в тестовом методе, + // их затрагивать нельзя + + for (int j = 2; j <= tiles.length - i; j++){ + try { + tiles[i + j - 1 ].value = tiles[i + j].value; + } catch (Exception e){ + tiles[i + j - 1].value = 0; + return true; + } + } + } + } + return false; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Tile.java b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Tile.java new file mode 100644 index 0000000..e944b8f --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Tile.java @@ -0,0 +1,58 @@ +package com.javarush.task.task35.task3513; + +import java.awt.*; + +/** + * Created by ArchMage on 11.04.17. + */ +public class Tile { + int value; + + public Tile(int value) { + this.value = value; + } + + public Tile() { + } + + public boolean isEmpty(){ + if (value == 0) { return true; } + else { return false; } + } + + public Color getFontColor(){ + if (value < 16) { return new Color(0x776e65); } + else { return new Color(0xf9f6f2); } + } + + public Color getTileColor(){ + switch (value) { + case 0: return new Color(0xcdc1b4); + + case 2: return new Color(0xeee4da); + + case 4: return new Color(0xede0c8); + + case 8: return new Color(0xf2b179); + + case 16: return new Color(0xf59563); + + case 32: return new Color(0xf67c5f); + + case 64: return new Color(0xf65e3b); + + case 128: return new Color(0xedcf72); + + case 256: return new Color(0xedcc61); + + case 512: return new Color(0xedc850); + + case 1024: return new Color(0xedc53f); + + case 2048: return new Color(0xedc22e); + + default: return new Color(0xff0000); + + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task35/task3513/View.java b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/View.java new file mode 100644 index 0000000..0bd0ec2 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/View.java @@ -0,0 +1,69 @@ +package com.javarush.task.task35.task3513; + +import javax.swing.*; +import java.awt.*; + +public class View extends JPanel { + private static final Color BG_COLOR = new Color(0xbbada0); + private static final String FONT_NAME = "Arial"; + private static final int TILE_SIZE = 96; + private static final int TILE_MARGIN = 12; + + private Controller controller; + + boolean isGameWon = false; + boolean isGameLost = false; + + public View(Controller controller) { + setFocusable(true); + this.controller = controller; + addKeyListener(controller); + } + + @Override + public void paint(Graphics g) { + super.paint(g); + g.setColor(BG_COLOR); + g.fillRect(0, 0, this.getSize().width, this.getSize().height); + for (int x = 0; x < 4; x++) { + for (int y = 0; y < 4; y++) { + drawTile(g, controller.getGameTiles()[y][x], x, y); + } + } + + g.drawString("Score: " + controller.getScore(), 140, 465); + + if (isGameWon) { + JOptionPane.showMessageDialog(this, "You've won!"); + } else if(isGameLost) { + JOptionPane.showMessageDialog(this, "You've lost :("); + } + } + + private void drawTile(Graphics g2, Tile tile, int x, int y) { + Graphics2D g = ((Graphics2D) g2); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + int value = tile.value; + int xOffset = offsetCoors(x); + int yOffset = offsetCoors(y); + g.setColor(tile.getTileColor()); + g.fillRoundRect(xOffset, yOffset, TILE_SIZE, TILE_SIZE , 8, 8); + g.setColor(tile.getFontColor()); + final int size = value < 100 ? 36 : value < 1000 ? 32 : 24; + final Font font = new Font(FONT_NAME, Font.BOLD, size); + g.setFont(font); + + String s = String.valueOf(value); + final FontMetrics fm = getFontMetrics(font); + + final int w = fm.stringWidth(s); + final int h = -(int) fm.getLineMetrics(s, g).getBaselineOffsets()[2]; + + if (value != 0) + g.drawString(s, xOffset + (TILE_SIZE - w) / 2, yOffset + TILE_SIZE - (TILE_SIZE - h) / 2 - 2); + } + + private static int offsetCoors(int arg) { + return arg * (TILE_MARGIN + TILE_SIZE) + TILE_MARGIN; + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task35/task3513/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..509eed8 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,154 @@ +taskKey="com.javarush.task.task35.task3513.big10" + +2048 (10) + +Пора приступить к реализации метода main в классе Main, чтобы иметь возможность наконец-то запустить игру и отдохнуть! + +Метод main нам нужен только для того чтобы запустить приложение, все внутренности мы уже реализовали. +Для этого мы создадим в нем модель и контроллер, а также объект типа JFrame. Для примера я назову его game, +но ты можешь выбрать любое другое имя. + +У нашей игры (объекта типа JFrame) мы должны будем вызвать некоторые методы для того чтобы все корректно отображалось +на экране: + +game.setTitle("2048"); +game.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); +game.setSize(450, 500); +game.setResizable(false); + +game.add(controller.getView()); + +game.setLocationRelativeTo(null); +game.setVisible(true); + +Обрати внимание на метод add в который мы передаем представление из контроллера. У нас еще нет геттера для поля view +в классе Controller. Не забудь его добавить. + +P.S. Результатом выполнения этого задания будет рабочая версия игры 2048, если у тебя вдруг что-то не работает, +или работает не так как ожидалось, обязательно разберись и исправь прежде чем переходить к следующим задачам. + + +Требования: +1. В классе Controller должен быть создан корректный геттер для поля view. +2. В методе main класса Main должна быть создана новая модель и контроллер на базе этой модели. +3. В методе main класса Main должен быть создан объект типа JFrame. +4. В методе main класса Main на объекте JFrame должны быть выполнены методы перечисленные в условии задачи. + + +2048 (9) + +Ты отлично справляешься! Так хорошо, что я решил тебе немного помочь и уже реализовал класс View. +Он достаточно прост. Наследуемся от класса JPanel, переопределяем метод paint и выводим на экран +текущее состояние модели, полученное через контроллер. + +Тебе же, предстоит закончить реализацию класса Controller. + +Для начала нам понадобится конструктор, он будет принимать один параметр типа Model, инициализировать поле +model, а также сохранять в поле view новый объект типа View с текущим контроллером(this) в качестве параметра +конструктора. + +Далее, нам нужен метод resetGame, который позволит вернуть игровое поле в начальное состояние. +Необходимо обнулить счет, установить флаги isGameWon и isGameLost у представления в false и вызывать метод +resetGameTiles у модели. + +Добавим приватную константу int WINNING_TILE = 2048. Она будет определять вес плитки при достижении которого +игра будет считаться выигранной. + +Ну а теперь, самое главное! Для того чтобы иметь возможность обрабатывать пользовательский ввод, необходимо +переопределить метод keyPressed с одним параметром типа KeyEvent. +Логика метода должна быть следующей: +1) Если была нажата клавиша ESC - вызови метод resetGame. +2) Если метод canMove модели возвращает false - установи флаг isGameLost в true. +3) Если оба флага isGameLost и isGameWon равны false - обработай варианты движения: +а) для клавиши KeyEvent.VK_LEFT вызови метод left у модели; +б) для клавиши KeyEvent.VK_RIGHT вызови метод right у модели; +в) для клавиши KeyEvent.VK_UP вызови метод up у модели; +г) для клавиши KeyEvent.VK_DOWN вызови метод down у модели. +4) Если поле maxTile у модели стало равно WINNING_TILE, установи флаг isGameWon в true. +5) В самом конце, вызови метод repaint у view. + +P.S. Для получения кода нажатой клавиши используй метод getKeyCode класса KeyEvent. + + + +2048 (8) + +Итак, модель почти готова, добавим еще пару простых методов и начнем реализацию контроллера. + +В модели нам не хватает способа получить игровое поле, чтобы передать его представлению на отрисовку, +а также метода, выполнив который, можно было бы определить возможен ли ход в текущей позиции, +или нет. + +Контроллер, в свою очередь, будет в основном использоваться для обработки пользовательского ввода с клавиатуры, +поэтому сделаем его наследником класса KeyAdapter. + +Нам понадобятся приватные поля model и view соответствующих типов и методы getGameTiles и getScore, +возвращающие подходящие свойства модели. + +По пунктам: +1. Добавь в класс Model геттер для поля gameTiles. +2. Добавь в класс Model метод canMove возвращающий true в случае, если в текущей позиции +возможно сделать ход так, чтобы состояние игрового поля изменилось. Иначе - false. +3. Сделай класс Controller потомком класса KeyAdapter. +4. Добавь в класс Controller метод getGameTiles вызывающий такой же метод у модели. +5. Добавь в класс Controller метод getScore возвращающий текущий счет (model.score). + + + +2048 (7) + +Движение влево мы реализовали, теперь необходимо реализовать методы right, up, down. Уверен, что ты с этим справишься +и без моей помощи, так что дам только одну подсказку. + +Что будет, если повернуть двумерный массив на 90 градусов по часовой стрелке, сдвинуть влево, а потом еще +трижды выполнить поворот? + + + +2048 (6) + +Итак, ты реализовал сжатие и слияние плиток, что в комбинации дает нам возможность осуществить движение влево. +Отлично! Но нам нужно еще и добавлять новую плитку в случае, если после передвижения игровое поле изменилось. + +Давай сделаем так: +1. Изменим метод compressTiles, чтобы он возвращал true в случае, если он вносил изменения во входящий массив, +иначе - false. +2. То же самое сделаем и для метода mergeTiles. +3. Реализуем метод left, который будет для каждой строки массива gameTiles вызывать методы compressTiles +и mergeTiles и добавлять одну плитку с помощью метода addTile в том случае, если это необходимо. +4. Метод left не должен быть приватным, т.к. вызваться он будет, помимо прочего, из класса Controller. + + + +2048 (5) + +Основными возможностями, которые мы должны реализовать, являются перемещения влево, вправо, вверх и вниз. +Если ты раньше уже играл в 2048, то знаешь, что при перемещении в одну из сторон, происходит перемещение +плиток со значениями на место пустых, а также объединение плиток одного номинала. + +В качестве базового сценария рассмотрим движение влево и подумаем что же происходит, когда мы хотим выполнить +это действие. + +Для каждого ряда или столбца, происходят на самом деле две вещи: +а) Сжатие плиток, таким образом, чтобы все пустые плитки были справа, т.е. +ряд {4, 2, 0, 4} становится рядом {4, 2, 4, 0} +б) Слияние плиток одного номинала, т.е. ряд {4, 4, 2, 0} становится рядом {8, 2, 0, 0}. +Обрати внимание, что ряд {4, 4, 4, 4} превратится в {8, 8, 0, 0}, а {4, 4, 4, 0} в {8, 4, 0, 0}. + +Создай методы compressTiles(Tile[] tiles) и mergeTiles(Tile[] tiles), которые будут реализовывать пункты +а) и б) соответственно. Использовать мы их будем только внутри класса Model, поэтому уровень доступа сделай +максимально узким. + +Также добавь поля score и maxTile типа int, которые должны хранить текущий счет и максимальный вес плитки +на игровом поле. Счет увеличивается после каждого слияния, например если текущий счет 20 и было выполнено +слияние ряда {4, 4, 4, 0}, счет должен увеличиться на 8. Уровень доступа к полям должен быть шире приватного. +Проще всего организовать обновление значений этих полей в методе mergeTiles, например так: +1) Если выполняется условие слияния плиток, проверяем является ли новое значения больше максимального и +при необходимости меняем значение поля maxTile. +2) Увеличиваем значение поля score на величину веса плитки образовавшейся в результате слияния. + +P.S. Когда мы будем реализовывать методы движения, сжатие будет всегда выполнено перед слиянием, таким образом +можешь считать, что в метод mergeTiles всегда передается массив плиток без пустых в середине. + + + From fb57d6480798b161908019508d3f57558beada4d Mon Sep 17 00:00:00 2001 From: PeucT Date: Wed, 12 Apr 2017 17:32:07 +0400 Subject: [PATCH 25/51] Level 30. Big task 3513 (1-17) (Full) --- .../task/task35/task3513/Controller.java | 7 + .../javarush/task/task35/task3513/Model.java | 117 +++++++++- .../javarush/task/task35/task3513/Move.java | 9 + .../task/task35/task3513/MoveEfficiency.java | 27 +++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 202 +++++++++--------- 5 files changed, 255 insertions(+), 107 deletions(-) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task35/task3513/Move.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task35/task3513/MoveEfficiency.java diff --git a/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Controller.java b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Controller.java index 8498d5e..7efa1db 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Controller.java +++ b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Controller.java @@ -53,7 +53,14 @@ public void keyPressed(KeyEvent e) { model.right(); }else if (e.getKeyCode() == KeyEvent.VK_DOWN) { model.down(); + }else if (e.getKeyCode() == KeyEvent.VK_Z){ + model.rollback(); + }else if (e.getKeyCode() == KeyEvent.VK_R){ + model.randomMove(); + }else if (e.getKeyCode() == KeyEvent.VK_A){ + model.autoMove(); } + if (model.maxTile == WINNING_TILE) { view.isGameWon = true; } } } diff --git a/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Model.java b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Model.java index 31b6a14..ef4dc31 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Model.java +++ b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Model.java @@ -1,7 +1,6 @@ package com.javarush.task.task35.task3513; -import java.util.ArrayList; -import java.util.List; +import java.util.*; /** * Created by ArchMage on 11.04.17. @@ -11,6 +10,9 @@ public class Model { private Tile[][] gameTiles; protected int score; protected int maxTile; + private Stack previousStates = new Stack(); + private Stack previousScores = new Stack(); + private boolean isSaveNeeded = true; public Model(){ resetGameTiles(); @@ -25,6 +27,25 @@ private void addTile(){ } } + private void saveState(Tile[][] tiles){ + Tile[][] tempTile = new Tile[FIELD_WIDTH][FIELD_WIDTH]; + for (int i = 0; i < FIELD_WIDTH; i++){ + for (int j = 0; j < FIELD_WIDTH; j++) { + tempTile[i][j] = new Tile(tiles[i][j].value); + } + } + previousStates.push(tempTile); + previousScores.push(score); + isSaveNeeded = false; + } + + public void rollback(){ + if (!previousStates.isEmpty() && !previousScores.isEmpty()) { + gameTiles = (Tile[][]) previousStates.pop(); + score = (int) previousScores.pop(); + } + } + protected void resetGameTiles(){ gameTiles = new Tile[FIELD_WIDTH][FIELD_WIDTH]; for (int i = 0; i < FIELD_WIDTH; i++){ @@ -117,15 +138,18 @@ private boolean mergeTiles(Tile[] tiles){ } public void left(){ + if (isSaveNeeded) { saveState(gameTiles); } boolean isChanged = false; for (int i = 0; i < FIELD_WIDTH; i++){ if (compressTiles(gameTiles[i])) { isChanged = true; } if (mergeTiles(gameTiles[i])) { isChanged = true; } } if (isChanged) {addTile(); } + isSaveNeeded = true; } public void up(){ + saveState(gameTiles); rotate(gameTiles); rotate(gameTiles); rotate(gameTiles); @@ -134,6 +158,7 @@ public void up(){ } public void right(){ + saveState(gameTiles); rotate(gameTiles); rotate(gameTiles); left(); @@ -142,6 +167,7 @@ public void right(){ } public void down(){ + saveState(gameTiles); rotate(gameTiles); left(); rotate(gameTiles); @@ -239,4 +265,91 @@ private boolean testMergeTiles(Tile[] tiles){ } return false; } + + public void randomMove(){ + int n = ((int) (Math.random() * 100)) % 4; + switch (n){ + case 0: + left(); + break; + case 1: + right(); + break; + case 2: + up(); + break; + case 3: + down(); + break; + } + } + + private boolean hasBoardChanged(){ + Tile[][] prev = (Tile[][]) previousStates.peek(); + int currTile = 0; + int prevTile = 0; + for (int i = 0; i < FIELD_WIDTH; i++) { + for (int j = 0; j < FIELD_WIDTH; j++) { + currTile += gameTiles[i][j].value; + prevTile += prev[i][j].value; + } + } + + return currTile != prevTile; + } + + public MoveEfficiency getMoveEfficiency(Move move){ + MoveEfficiency movEff = null; + move.move(); + + if (!hasBoardChanged()) { + movEff = new MoveEfficiency(-1 ,0 ,move); + } else { + movEff = new MoveEfficiency(getEmptyTiles().size() ,score ,move); + } + rollback(); + return movEff; + } + + public void autoMove(){ + PriorityQueue queue = new PriorityQueue(4, Collections.reverseOrder()); + queue.add(getMoveEfficiency(this::randomMove)); + queue.offer(getMoveEfficiency(this::right)); + queue.offer(getMoveEfficiency(this::up)); + queue.offer(getMoveEfficiency(this::down)); + MoveEfficiency efficientMove = (MoveEfficiency) queue.poll(); + efficientMove.getMove().move(); + } + + private class MoveLeft implements Move{ + + @Override + public void move() { + Model.this.left(); + } + } + + private class MoveUp implements Move{ + + @Override + public void move() { + Model.this.up(); + } + } + + private class MoveRight implements Move{ + + @Override + public void move() { + Model.this.right(); + } + } + + private class MoveDown implements Move{ + + @Override + public void move() { + Model.this.down(); + } + } } diff --git a/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Move.java b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Move.java new file mode 100644 index 0000000..d2ce60a --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Move.java @@ -0,0 +1,9 @@ +package com.javarush.task.task35.task3513; + +/** + * Created by ArchMage on 12.04.17. + */ +@FunctionalInterface +public interface Move { + void move(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task35/task3513/MoveEfficiency.java b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/MoveEfficiency.java new file mode 100644 index 0000000..ba1cbc4 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/MoveEfficiency.java @@ -0,0 +1,27 @@ +package com.javarush.task.task35.task3513; + +/** + * Created by ArchMage on 12.04.17. + */ +public class MoveEfficiency implements Comparable { + private int numberOfEmptyTiles; + private int score; + private Move move; + + public MoveEfficiency(int numberOfEmptyTiles, int score, Move move) { + this.numberOfEmptyTiles = numberOfEmptyTiles; + this.score = score; + this.move = move; + } + + public Move getMove() { + return move; + } + + @Override + public int compareTo(MoveEfficiency o) { + if (numberOfEmptyTiles != o.numberOfEmptyTiles) { + return Integer.compare(numberOfEmptyTiles, o.numberOfEmptyTiles); + } else return Integer.compare(score, o.score); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task35/task3513/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" index 509eed8..c3d151a 100644 --- "a/3.JavaMultithreading/src/com/javarush/task/task35/task3513/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" +++ "b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -1,154 +1,146 @@ -taskKey="com.javarush.task.task35.task3513.big10" +taskKey="com.javarush.task.task35.task3513.big16" -2048 (10) +2048 (16) -Пора приступить к реализации метода main в классе Main, чтобы иметь возможность наконец-то запустить игру и отдохнуть! +Осталось совсем немного! У нас есть способ вычислить эффективность любого хода, а также мы можем их сравнивать +между собой. -Метод main нам нужен только для того чтобы запустить приложение, все внутренности мы уже реализовали. -Для этого мы создадим в нем модель и контроллер, а также объект типа JFrame. Для примера я назову его game, -но ты можешь выбрать любое другое имя. +Давай реализуем метод autoMove в классе Model, который будет выбирать лучший из возможных ходов и выполнять его. -У нашей игры (объекта типа JFrame) мы должны будем вызвать некоторые методы для того чтобы все корректно отображалось -на экране: +Сделаем так: +1) Создадим локальную PriorityQueue с параметром Collections.reverseOrder() (для того, +чтобы вверху очереди всегда был максимальный элемент) и размером равным четырем. +2) Заполним PriorityQueue четырьмя объектами типа MoveEfficiency (по одному на каждый вариант хода). +3) Возьмем верхний элемент и выполним ход связанный с ним. -game.setTitle("2048"); -game.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); -game.setSize(450, 500); -game.setResizable(false); +После реализации метода autoMove добавим его вызов в метод keyPressed класса Controller +по нажатию на клавишу A (код - KeyEvent.VK_A). -game.add(controller.getView()); +P.S. В качестве факультативного задания можешь почитать про указатели на методы и попробовать передать +аргумент в метод getMoveEfficiency используя оператор "::". Для метода left должно получиться +getMoveEfficiency(this::left). Альтернативно можешь использовать внутренний анонимный класс. -game.setLocationRelativeTo(null); -game.setVisible(true); -Обрати внимание на метод add в который мы передаем представление из контроллера. У нас еще нет геттера для поля view -в классе Controller. Не забудь его добавить. - -P.S. Результатом выполнения этого задания будет рабочая версия игры 2048, если у тебя вдруг что-то не работает, -или работает не так как ожидалось, обязательно разберись и исправь прежде чем переходить к следующим задачам. +Требования: +1. В методе autoMove должен быть создан объект типа PriorityQueue. +2. В методе autoMove в PriorityQueue должно быть добавлено 4 объекта типа MoveEfficiency с помощью метода offer (по одному на каждый вариант хода). +3. Метод keyPressed класса Controller должен вызывать метод autoMove у модели в случае, если была нажата клавиша с кодом KeyEvent.VK_A. +4. В методе autoMove должен быть выполнен метод move связанный с объектом MoveEfficiency полученном с помощью метода peek или poll. -Требования: -1. В классе Controller должен быть создан корректный геттер для поля view. -2. В методе main класса Main должна быть создана новая модель и контроллер на базе этой модели. -3. В методе main класса Main должен быть создан объект типа JFrame. -4. В методе main класса Main на объекте JFrame должны быть выполнены методы перечисленные в условии задачи. +2048 (15) +Для того, чтобы эффективности различных ходов можно было сравнивать, необходимо реализовать в классе +MoveEfficiency поддержку интерфейса Comparable. -2048 (9) +В методе compareTo первым делом сравни количество пустых плиток (numberOfEmptyTiles), потом счет (score), +если количество пустых плиток равное. Если и счет окажется равным, будем считать эффективность ходов +равной и вернем ноль. -Ты отлично справляешься! Так хорошо, что я решил тебе немного помочь и уже реализовал класс View. -Он достаточно прост. Наследуемся от класса JPanel, переопределяем метод paint и выводим на экран -текущее состояние модели, полученное через контроллер. +Далее перейдем в класс Model и реализуем два метода: +1) boolean hasBoardChanged - будет возвращать true, в случае, если вес плиток в массиве gameTiles +отличается от веса плиток в верхнем массиве стека previousStates. Обрати внимание на то, что мы +не должны удалять из стека верхний элемент, используй метод peek. +2) MoveEfficiency getMoveEfficiency(Move move) - принимает один параметр типа move, и возвращает +объект типа MoveEfficiency описывающий эффективность переданного хода. Несколько советов: +а) не забудь вызывать метод rollback, чтобы восстановить корректное игровое состояние; +б) в случае, если ход не меняет состояние игрового поля, количество пустых плиток и счет у объекта MoveEfficiency +сделай равными -1 и 0 соответственно; +в) выполнить ход можно вызвав метод move на объекте полученном в качестве параметра. -Тебе же, предстоит закончить реализацию класса Controller. -Для начала нам понадобится конструктор, он будет принимать один параметр типа Model, инициализировать поле -model, а также сохранять в поле view новый объект типа View с текущим контроллером(this) в качестве параметра -конструктора. -Далее, нам нужен метод resetGame, который позволит вернуть игровое поле в начальное состояние. -Необходимо обнулить счет, установить флаги isGameWon и isGameLost у представления в false и вызывать метод -resetGameTiles у модели. +2048 (14) -Добавим приватную константу int WINNING_TILE = 2048. Она будет определять вес плитки при достижении которого -игра будет считаться выигранной. +Случайный ход конечно неплох, но намного круче реализовать возможность умного хода. В дебри нейронных сетей +мы заходить не будем, для начала сконцентрируемся на достаточно простой идее. -Ну а теперь, самое главное! Для того чтобы иметь возможность обрабатывать пользовательский ввод, необходимо -переопределить метод keyPressed с одним параметром типа KeyEvent. -Логика метода должна быть следующей: -1) Если была нажата клавиша ESC - вызови метод resetGame. -2) Если метод canMove модели возвращает false - установи флаг isGameLost в true. -3) Если оба флага isGameLost и isGameWon равны false - обработай варианты движения: -а) для клавиши KeyEvent.VK_LEFT вызови метод left у модели; -б) для клавиши KeyEvent.VK_RIGHT вызови метод right у модели; -в) для клавиши KeyEvent.VK_UP вызови метод up у модели; -г) для клавиши KeyEvent.VK_DOWN вызови метод down у модели. -4) Если поле maxTile у модели стало равно WINNING_TILE, установи флаг isGameWon в true. -5) В самом конце, вызови метод repaint у view. +Очевидно, хороший ход должен в итоге приближать нас к победе, а именно к получению плитки 2048. +Предлагаю рассмотреть такой вариант сравнения эффективности хода: +1) Первый ход является лучше второго, если после его совершения на поле находится больше пустых плиток, +чем в результате второго хода. +2) Первый ход является лучше второго, если общий счет после его совершения больше, чем счет +полученный в результате второго хода. -P.S. Для получения кода нажатой клавиши используй метод getKeyCode класса KeyEvent. +Для того, чтобы реализовать такое сравнение, мы можем совершить ход, оценить его эффективность и потом +отменить совершенный ход, чтобы вернуть игру в начальное состояние. Применив эту последовательность действий +ко всем четырем вариантам хода, сможем выбрать наиболее эффективный ход и выполнить его. +Концептуально, нам понадобятся два класса, один будет описывать ход, а другой эффективность хода. +Создай интерфейс Move с одним void методом move. Отметь интерфейс аннотацией @FunctionalInterface, которая +будет сигнализировать о том что в этом интерфейсе будет только один абстрактный метод. -2048 (8) +Создай класс MoveEfficiency, описывающий эффективность хода. В нем нам понадобятся приватные поля +numberOfEmptyTiles и score типа int, а также приватное поле поле move типа Move. +В классе MoveEfficiency необходим конструктор с тремя параметрами (int numberOfEmptyTiles, int score, Move move) +для инициализации полей класса и геттер для поля move. -Итак, модель почти готова, добавим еще пару простых методов и начнем реализацию контроллера. -В модели нам не хватает способа получить игровое поле, чтобы передать его представлению на отрисовку, -а также метода, выполнив который, можно было бы определить возможен ли ход в текущей позиции, -или нет. -Контроллер, в свою очередь, будет в основном использоваться для обработки пользовательского ввода с клавиатуры, -поэтому сделаем его наследником класса KeyAdapter. +2048 (13) -Нам понадобятся приватные поля model и view соответствующих типов и методы getGameTiles и getScore, -возвращающие подходящие свойства модели. +Твой прогресс впечатляет! Для разнообразия, предлагаю дать игре возможность самостоятельно +выбирать следующий ход. -По пунктам: -1. Добавь в класс Model геттер для поля gameTiles. -2. Добавь в класс Model метод canMove возвращающий true в случае, если в текущей позиции -возможно сделать ход так, чтобы состояние игрового поля изменилось. Иначе - false. -3. Сделай класс Controller потомком класса KeyAdapter. -4. Добавь в класс Controller метод getGameTiles вызывающий такой же метод у модели. -5. Добавь в класс Controller метод getScore возвращающий текущий счет (model.score). +Начнем с простого, реализуем метод randomMove в классе Model, который будет вызывать один из методов движения +случайным образом. Можешь реализовать это вычислив целочисленное n = ((int) (Math.random() * 100)) % 4. +Это число будет содержать целое псевдослучайное число в диапазоне [0..3], по каждому из которых можешь вызывать +один из методов left, right, up, down. +Не забудь добавить в метод keyPressed класса Controller вызов метода randomMove по нажатию на клавишу R +(код - KeyEvent.VK_R). +P.S. Проверку корректности работы метода randomMove оставляю полностью под твою ответственность, +проверю только наличие вызова метода Math.random(). -2048 (7) -Движение влево мы реализовали, теперь необходимо реализовать методы right, up, down. Уверен, что ты с этим справишься -и без моей помощи, так что дам только одну подсказку. -Что будет, если повернуть двумерный массив на 90 градусов по часовой стрелке, сдвинуть влево, а потом еще -трижды выполнить поворот? +2048 (12) +Ну что, попробуем наш алгоритм в действии? Осталось добавить сохранение игрового состояния в начало каждого +метода движения, а также еще один кейс для обработки клавиши, которой будем выполнять отмену последнего хода. +При сохранении текущего состояния в стек, обрати внимание на то, чтобы всегда сохранялось актуальное состояние +и только однажды. Если ты послушал мой совет и реализовал методы right, up, down с помощью поворотов и вызова +метода left, можешь использовать следующий подход: +1) В самом начале методов right, up, down вызываем метод saveState с gameTiles в качестве параметра. +2) В методе left организуем проверку того, вызывался ли уже метод saveState. За это у нас отвечает +флаг isSaveNeeded, соответственно, если он равен true, выполняем сохранение. После выполнения +сдвига влево устанавливаем флаг isSaveNeeded равным true. -2048 (6) +Также добавим в метод keyPressed класса Controller вызов метода rollback по нажатию на клавишу Z (код - KeyEvent.VK_Z). -Итак, ты реализовал сжатие и слияние плиток, что в комбинации дает нам возможность осуществить движение влево. -Отлично! Но нам нужно еще и добавлять новую плитку в случае, если после передвижения игровое поле изменилось. -Давай сделаем так: -1. Изменим метод compressTiles, чтобы он возвращал true в случае, если он вносил изменения во входящий массив, -иначе - false. -2. То же самое сделаем и для метода mergeTiles. -3. Реализуем метод left, который будет для каждой строки массива gameTiles вызывать методы compressTiles -и mergeTiles и добавлять одну плитку с помощью метода addTile в том случае, если это необходимо. -4. Метод left не должен быть приватным, т.к. вызваться он будет, помимо прочего, из класса Controller. +2048 (11) +Отличная работа! На этом этапе у нас уже есть полнофункциональное приложение, но ведь нет предела совершенству, +давай еще поработаем. -2048 (5) +Если ты успел какое-то время поиграть в 2048, то заметил, что порой очень хочется иметь возможность отменить +последний ход. -Основными возможностями, которые мы должны реализовать, являются перемещения влево, вправо, вверх и вниз. -Если ты раньше уже играл в 2048, то знаешь, что при перемещении в одну из сторон, происходит перемещение -плиток со значениями на место пустых, а также объединение плиток одного номинала. +Давай создадим в классе Model два стека, в одном будем хранить предыдущие состояния игрового поля, а в другом +предыдущие счета. Назовем их previousStates и previousScores. Инициализировать можешь прямо в строке объявления +или в конструкторе. Используй стандартную реализацию стека (java.util.Stack). -В качестве базового сценария рассмотрим движение влево и подумаем что же происходит, когда мы хотим выполнить -это действие. +Добавим boolean поле isSaveNeeded = true, оно нам понадобится в будущем. -Для каждого ряда или столбца, происходят на самом деле две вещи: -а) Сжатие плиток, таким образом, чтобы все пустые плитки были справа, т.е. -ряд {4, 2, 0, 4} становится рядом {4, 2, 4, 0} -б) Слияние плиток одного номинала, т.е. ряд {4, 4, 2, 0} становится рядом {8, 2, 0, 0}. -Обрати внимание, что ряд {4, 4, 4, 4} превратится в {8, 8, 0, 0}, а {4, 4, 4, 0} в {8, 4, 0, 0}. +Хранилище состояний у нас есть, теперь реализуем два метода для работы с ними. +1. Приватный метод saveState с одним параметром типа Tile[][] будет сохранять текущее +игровое состояние и счет в стеки с помощью метода push и устанавливать флаг isSaveNeeded равным false. +2. Публичный метод rollback будет устанавливать текущее игровое состояние равным последнему находящемуся +в стеках с помощью метода pop. -Создай методы compressTiles(Tile[] tiles) и mergeTiles(Tile[] tiles), которые будут реализовывать пункты -а) и б) соответственно. Использовать мы их будем только внутри класса Model, поэтому уровень доступа сделай -максимально узким. +Обрати внимание на то, что при сохранении массива gameTiles необходимо создать новый массив и заполнить его +новыми объектами типа Tile перед сохранением в стек. -Также добавь поля score и maxTile типа int, которые должны хранить текущий счет и максимальный вес плитки -на игровом поле. Счет увеличивается после каждого слияния, например если текущий счет 20 и было выполнено -слияние ряда {4, 4, 4, 0}, счет должен увеличиться на 8. Уровень доступа к полям должен быть шире приватного. -Проще всего организовать обновление значений этих полей в методе mergeTiles, например так: -1) Если выполняется условие слияния плиток, проверяем является ли новое значения больше максимального и -при необходимости меняем значение поля maxTile. -2) Увеличиваем значение поля score на величину веса плитки образовавшейся в результате слияния. +В методе rollback достаточно просто выполнить присваивание (gameTiles = previousStates.pop()) и то же для счета, +нет необходимости в глубоком копировании. -P.S. Когда мы будем реализовывать методы движения, сжатие будет всегда выполнено перед слиянием, таким образом -можешь считать, что в метод mergeTiles всегда передается массив плиток без пустых в середине. +Перед восстановлением игрового состояния с помощью метода rollback не забудь проверить что стеки не пусты, +чтобы избежать возникновения исключения EmptyStackException. From ac99a59ee2d8f6f1856a3a43b021934944125f0c Mon Sep 17 00:00:00 2001 From: PeucT Date: Fri, 14 Apr 2017 16:32:06 +0400 Subject: [PATCH 26/51] Level 29. Big task (1-2) --- .../task/task27/task2712/ConsoleHelper.java | 41 ++++++ .../task/task27/task2712/Restaurant.java | 10 ++ .../javarush/task/task27/task2712/Tablet.java | 37 +++++ .../task/task27/task2712/kitchen/Dish.java | 24 ++++ .../task/task27/task2712/kitchen/Order.java | 42 ++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 136 ++++++++++++++++++ 6 files changed, 290 insertions(+) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2712/ConsoleHelper.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2712/Restaurant.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2712/Tablet.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Dish.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Order.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task27/task2712/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ConsoleHelper.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ConsoleHelper.java new file mode 100644 index 0000000..74c435c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ConsoleHelper.java @@ -0,0 +1,41 @@ +package com.javarush.task.task27.task2712; + +import com.javarush.task.task27.task2712.kitchen.Dish; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by ArchMage on 14.04.17. + */ +public class ConsoleHelper { + private static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + + public static void writeMessage(String message){ + System.out.println(message); + } + public static String readString() throws IOException { + return reader.readLine(); + } + + public static List getAllDishesForOrder() throws IOException{ + writeMessage(Dish.allDishesToString()); + writeMessage("Выберите блюда"); + List list = new ArrayList<>(); + String input = null; + while (!"exit".equals(input = reader.readLine())) { + try{ + Dish inputDish = Dish.valueOf(input); + list.add(inputDish); + } catch (IllegalArgumentException e){ + writeMessage("Блюдо отсутствует в меню"); + } + + } + return list; + } + +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Restaurant.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Restaurant.java new file mode 100644 index 0000000..f274a25 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Restaurant.java @@ -0,0 +1,10 @@ +package com.javarush.task.task27.task2712; + +/** + * Created by ArchMage on 14.04.17. + */ +public class Restaurant { + public static void main(String[] args){ + new Tablet(5).createOrder(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Tablet.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Tablet.java new file mode 100644 index 0000000..e293070 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Tablet.java @@ -0,0 +1,37 @@ +package com.javarush.task.task27.task2712; + +import com.javarush.task.task27.task2712.kitchen.Order; + +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Created by ArchMage on 14.04.17. + */ +public class Tablet { + protected final int number; + private static Logger logger = Logger.getLogger(Tablet.class.getName()); + + public Tablet(int number) { + this.number = number; + } + + public void createOrder(){ + + try { + Order order = new Order(this); + } + catch (IOException e){ + logger.log(Level.SEVERE, "Console is unavailable."); + } + + } + + @Override + public String toString() { + return "Tablet{" + + "number=" + number + + '}'; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Dish.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Dish.java new file mode 100644 index 0000000..12003e9 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Dish.java @@ -0,0 +1,24 @@ +package com.javarush.task.task27.task2712.kitchen; + +/** + * Created by ArchMage on 14.04.17. + */ +public enum Dish { + Fish, + Steak, + Soup, + Juice, + Water; + + public static String allDishesToString(){ + StringBuilder strB = new StringBuilder(); + boolean isFirst = true; + for (Dish entry : Dish.values()){ + if (!isFirst) { + strB.append(", "); + } else { isFirst = false; } + strB.append(entry.toString()); + } + return strB.toString(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Order.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Order.java new file mode 100644 index 0000000..8358d78 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Order.java @@ -0,0 +1,42 @@ +package com.javarush.task.task27.task2712.kitchen; + +import com.javarush.task.task27.task2712.ConsoleHelper; +import com.javarush.task.task27.task2712.Tablet; + +import java.io.IOException; +import java.util.List; + +/** + * Created by ArchMage on 14.04.17. + */ +public class Order { + protected List dishes; + private final Tablet tablet; + + public Order(Tablet tablet) throws IOException { + this.tablet = tablet; + dishes = ConsoleHelper.getAllDishesForOrder(); + } + + @Override + public String toString() { + StringBuilder strB = new StringBuilder(); + if (dishes == null || dishes.size() == 0) { return ""; } + else { + strB.append("Your order: ["); + boolean isFirst = true; + for (int i = 0; i < dishes.size(); i++){ + if (isFirst) { + isFirst = false; + } else { + strB.append(", "); + } + strB.append(dishes.get(i)); + + } + strB.append("] of "); + strB.append(tablet.toString()); + } + return strB.toString(); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..59a0583 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,136 @@ +taskKey="com.javarush.task.task27.task2712.big03" + +Ресторан(3) + +Сейчас мы можем создавать заказы. Давай сделаем так, чтобы они автоматически поступали к повару. +Есть много различных способов реализации данной функциональности. +Почитай про паттерн Observer - http://en.wikipedia.org/wiki/Observer_pattern +Он уже реализован в java, и мы его будем использовать. + +1. Создадим класс Cook(Повар) в пакете kitchen, он будет готовить. Пусть в конструкторе приходит его имя, которое выводится методом toString. + +2. Tablet создает заказы, а Cook их обрабатывает. Расставь правильно Observer и Observable между Tablet и Cook. + +3. Метод void update(Observable observable, Object arg), который необходимо реализовать, принимает два параметра. +-observable - объект, который отправил нам значение +-arg - само значение, в нашем случае - это объект Order +На данном этапе мы будем лишь имитировать обработку и выведем в консоль "Start cooking - " + order + +3. Пишем main. +Для объекта Observable добавляем свой объект Observer. См. п.2 и описание паттерна в wikipedia +Называем повара, имя не влияет на тесты. В моем варианте - это Amigo : ) + +Сверим выводы в консоль. Пример моего вывода: +Your order: [Soup] of Tablet{number=5} +Start cooking - Your order: [Soup] of Tablet{number=5} + +4. Не забудь сразу после создания заказа и вывода информации о нем в консоль (найдите это место в коде) сделать следующее: +4.1. Установить флаг setChanged() +4.2. Отправить обсерверу заказ - notifyObservers(order); + +5. Также внесем небольшое изменение. Сделай так чтобы метод createOrder возвращал текущий заказ или null, если заказ создать не удалось. + + +Требования: +1. Конструктор класса Cook должен принимать в качестве параметра строку и инициализировать имя повара (поле name). +2. Метод toString класса Cook должен возвращать значение поля name. +3. Класс Cook должен реализовывать интерфейс Observer. +4. Класс Tablet должен быть потомком класса Observable. +5. В методе createOrder класса Tablet должен быть вызван метод setChanged. +6. В методе createOrder класса Tablet должен быть вызван метод notifyObservers с текущим заказом в качестве параметра. +7. Метод update в классе Cook должен выводить на экран строку форматированную согласно заданию. +8. В методе main класса Restaurant должен быть создан новый повар и добавлен планшету в качестве наблюдателя с помощью метода addObserver. + + +Ресторан(2) + +1. Мы много работаем с консолью. Пора создать единую точку взаимодействия. +Создай класс ConsoleHelper с единственным BufferedReader, через который будем работать с консолью. +Запомни, этот класс не хранит никаких данных и состояний, поэтому все методы будут статическими. +Создай в нем три метода: +-writeMessage(String message) - для вывода message в консоль +-String readString() - для чтения строки с консоли +-List getAllDishesForOrder() - просит пользователя выбрать блюдо и добавляет его в список. +Выведи список всех блюд и попроси пользователя ввести строку - название блюда. +Введенное 'exit' означает завершение заказа. +В случае, если введенное блюдо не представлено в меню, выведи сообщение о том, что такого блюда нет и продолжи формирование заказа. +Исключения ввода-вывода бросай выше, на этом уровне не понятно, что с ними делать. + +2. Сделай рефакторинг - работа с консолью должна быть только через класс ConsoleHelper. + +3. Вернемся к классу Order: в нем есть ссылка на планшет, и еще есть список выбранных блюд. +Инициализируй список dishes в конструкторе, вызвав метод getAllDishesForOrder из ConsoleHelper. + +4. Перепиши метод toString в классе Order. Пусть он возвращает пустую строку, если нет блюд в заказе, иначе +вывод должен быть аналогичным примеру в порядке добавления блюд. Используй ConsoleHelper. +Также измени метод toString в классе Tablet (внутри класса Tablet нажмите Alt+Insert -> toString()). +Пример: +Your order: [Juice, Fish] of Tablet{number=5} + +5. У нас все завязано на работу с консолью. Однако, при возникновении исключений, наше приложение умрет. +Чтобы узнать причину - добавим в Tablet статическое поле logger типа java.util.logging.Logger, инициализированное именем класса (Logger.getLogger(Tablet.class.getName())). + +6. В методе createOrder класса Tablet обработаем исключения ввода-вывода. +Запишем в лог "Console is unavailable.". Уровень лога - SEVERE - это самый серьезный уровень, мы не можем работать. +Также в методе createOrder класса Tablet должен быть создан новый заказ. + +7. Надо начинать тестировать наше приложение. +Добавьте в main создание планшета и создание заказа - new Tablet(5).createOrder(); + + + +Ресторан(1) + +Давай напишем программу для автоматизации работы в ресторане. + +Пусть задание сформулировано так - директор ресторана хочет, чтобы: +1) на каждом столике лежал планшет, через который можно было бы сделать заказ; +2) пока заказ готовится, на планшете показывалась реклама; +3) в конце рабочего дня была возможность посмотреть различную статистику: +а) загрузки повара; +б) сумму выручки за заказы; +в) сумму выручки за показы рекламы. + +Мы будем разрабатывать ядро, без UI. UI ты потом сможешь дописать самостоятельно, сейчас ограничимся консольным интерфейсом. +Также мы часть данных захардкодим, ты потом сможешь прикрутить БД, и работать с ней. + +Выделим несколько фич, которые будем реализовывать: + +Первая: +-созданный посетителем заказ будет автоматически поступать к повару; +-повар будет готовить его какое-то время и отмечать приготовленным; +-после этого официант будет относить его. + +Вторая: +-подобрать нужные рекламные ролики из списка оплаченных; +-отображение рекламных роликов во время приготовления заказа; +-максимизировать прибыль от показа рекламы. + +Третья: +-подсчет статистики; +-отображение статистики директору. + +Начнем с первой фичи - автоматизация обработки заказа: + +Итак.. +1. Создай класс Restaurant с методом main. + +2. Начнем с планшета, создадим класс Tablet, в котором создадим поле final int number - это номер планшета, +чтобы можно было однозначно установить, откуда поступил заказ. Номер планшета должен инициализироваться в конструкторе переданным параметром. + +3. В классе Tablet создадим метод public void createOrder(), который будет создавать заказ из тех блюд, которые выберет пользователь. +Для этого создадим класс Order, который поместим в пакет kitchen. + +4. В классе Order (заказ) должна быть информация, относящаяся к списку выбранных пользователем блюд. +Т.е. где-то должен быть список всех блюд, и должен быть список выбранных блюд в классе Order. +В классе Order нужны поля private final int number и protected List dishes. +Конструктор должен принимать один параметр типа Tablet и инициализировать поле tablet. + +5. Нам нужен класс Dish(Блюдо), создадим его в пакете kitchen. Пусть это будет enum со списком блюд: Fish, Steak, Soup, Juice, Water. + +6. Чтобы пользователь мог выбрать себе блюда, нужно их все ему отобразить. Для этого в Dish создай метод +public static String allDishesToString(), который сформирует строку из всех блюд. +Пример: "Fish, Steak, Soup, Juice, Water". Формируй строку динамически. + + + From 7c47e1cebfdfee445a484e6b44226e4651b8914b Mon Sep 17 00:00:00 2001 From: PeucT Date: Mon, 17 Apr 2017 17:39:17 +0400 Subject: [PATCH 27/51] 2712 Big task at level 29. part 3 --- ...\273\320\276\320\262\320\270\320\265.jrtc" | 48 ++++++++++++++----- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" index 59a0583..f85338e 100644 --- "a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -1,4 +1,40 @@ -taskKey="com.javarush.task.task27.task2712.big03" +taskKey="com.javarush.task.task27.task2712.big04" + +Ресторан(4) + +Что мы имеем? Повар приготовил блюда, пора их уносить, а официант не знает об этом. +Нужно уведомить официанта, что пора забирать заказ с кухни. +Ситуация аналогична предыдущему заданию, поэтому снова будем использовать паттерн Observer. + +1. Создадим класс Waiter(Официант) в пакете kitchen, он будет относить заказы назад к столику. Официант будет безымянным. + +2. Cook(Повар) готовит заказы, а Waiter их обрабатывает. Расставь правильно Observer и Observable между Waiter и Cook. + +3. Метод void update будет выводить в консоль сообщение о том, какой заказ и кем был приготовлен: +order + " was cooked by " + cook + +4. В классе наследнике Observable перед отправкой заказа сделаем следующее: +4.1. Установим флаг setChanged() +4.2. Отправим наблюдателю заказ - notifyObservers(order); + +5. Пишем main. +Для объекта Observable добавляем свой объект Observer. См. п.2 и описание паттерна в wikipedia +Называем повара, имя не влияет на тесты. В моем варианте - это Amigo :) + +Сверим выводы в консоль. Пример моего вывода: +Your order: [Water] of Tablet{number=5} +Start cooking - Your order: [Water] of Tablet{number=5} +Your order: [Water] of Tablet{number=5} was cooked by Amigo + + +Требования: +1. Класс Waiter должен реализовывать интерфейс Observer. +2. Класс Cook должен быть потомком класса Observable. +3. В методе update класса Cook должен быть вызван метод setChanged. +4. В методе update класса Cook должен быть вызван метод notifyObservers с текущим заказом в качестве параметра. +5. Метод update в классе Waiter должен выводить на экран строку форматированную согласно заданию. +6. В методе main класса Restaurant должен быть создан новый официант и добавлен повару в качестве наблюдателя с помощью метода addObserver. + Ресторан(3) @@ -31,16 +67,6 @@ Start cooking - Your order: [Soup] of Tablet{number=5} 5. Также внесем небольшое изменение. Сделай так чтобы метод createOrder возвращал текущий заказ или null, если заказ создать не удалось. -Требования: -1. Конструктор класса Cook должен принимать в качестве параметра строку и инициализировать имя повара (поле name). -2. Метод toString класса Cook должен возвращать значение поля name. -3. Класс Cook должен реализовывать интерфейс Observer. -4. Класс Tablet должен быть потомком класса Observable. -5. В методе createOrder класса Tablet должен быть вызван метод setChanged. -6. В методе createOrder класса Tablet должен быть вызван метод notifyObservers с текущим заказом в качестве параметра. -7. Метод update в классе Cook должен выводить на экран строку форматированную согласно заданию. -8. В методе main класса Restaurant должен быть создан новый повар и добавлен планшету в качестве наблюдателя с помощью метода addObserver. - Ресторан(2) From 277fe98f5b841378c54b2dc29a2814abfd8de04b Mon Sep 17 00:00:00 2001 From: PeucT Date: Mon, 17 Apr 2017 17:39:43 +0400 Subject: [PATCH 28/51] 2712 big task at level 29. part 3 --- .../task/task27/task2712/Restaurant.java | 7 ++++- .../javarush/task/task27/task2712/Tablet.java | 16 +++++++++-- .../task/task27/task2712/kitchen/Cook.java | 28 +++++++++++++++++++ .../task/task27/task2712/kitchen/Dish.java | 7 +++++ .../task/task27/task2712/kitchen/Order.java | 20 ++----------- 5 files changed, 57 insertions(+), 21 deletions(-) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Cook.java diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Restaurant.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Restaurant.java index f274a25..70e0b3f 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Restaurant.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Restaurant.java @@ -1,10 +1,15 @@ package com.javarush.task.task27.task2712; +import com.javarush.task.task27.task2712.kitchen.Cook; + /** * Created by ArchMage on 14.04.17. */ public class Restaurant { public static void main(String[] args){ - new Tablet(5).createOrder(); + Tablet tablet = new Tablet(5); + Cook cook = new Cook("Amigo"); + tablet.addObserver(cook); + tablet.createOrder(); } } diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Tablet.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Tablet.java index e293070..d77cdaa 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Tablet.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Tablet.java @@ -2,30 +2,40 @@ import com.javarush.task.task27.task2712.kitchen.Order; + import java.io.IOException; +import java.util.Observable; +import java.util.Observer; import java.util.logging.Level; import java.util.logging.Logger; /** * Created by ArchMage on 14.04.17. */ -public class Tablet { +public class Tablet extends Observable { protected final int number; private static Logger logger = Logger.getLogger(Tablet.class.getName()); + private Observer observer; public Tablet(int number) { this.number = number; } - public void createOrder(){ + public Order createOrder(){ try { Order order = new Order(this); + ConsoleHelper.writeMessage(order.toString()); + setChanged(); + notifyObservers(order); + return order; } catch (IOException e){ logger.log(Level.SEVERE, "Console is unavailable."); + return null; } + } @Override @@ -34,4 +44,6 @@ public String toString() { "number=" + number + '}'; } + + } diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Cook.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Cook.java new file mode 100644 index 0000000..8d19c9c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Cook.java @@ -0,0 +1,28 @@ +package com.javarush.task.task27.task2712.kitchen; + +import com.javarush.task.task27.task2712.ConsoleHelper; + +import java.util.Observable; +import java.util.Observer; + +/** + * Created by ArchMage on 17.04.17. + */ +public class Cook implements Observer { + private String name; + + + public Cook(String name) { + this.name = name; + } + + @Override + public void update(Observable o, Object arg) { + ConsoleHelper.writeMessage("Start cooking - " + arg); + } + + @Override + public String toString() { + return name; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Dish.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Dish.java index 12003e9..7f46511 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Dish.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Dish.java @@ -1,5 +1,7 @@ package com.javarush.task.task27.task2712.kitchen; +import java.util.Arrays; + /** * Created by ArchMage on 14.04.17. */ @@ -11,6 +13,11 @@ public enum Dish { Water; public static String allDishesToString(){ + /*if (values().length == 0) { + return ""; + } + return Arrays.toString(values()).substring(1, Arrays.toString(values()).length() - 1);*/ + StringBuilder strB = new StringBuilder(); boolean isFirst = true; for (Dish entry : Dish.values()){ diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Order.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Order.java index 8358d78..cdb3edd 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Order.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Order.java @@ -20,23 +20,7 @@ public Order(Tablet tablet) throws IOException { @Override public String toString() { - StringBuilder strB = new StringBuilder(); - if (dishes == null || dishes.size() == 0) { return ""; } - else { - strB.append("Your order: ["); - boolean isFirst = true; - for (int i = 0; i < dishes.size(); i++){ - if (isFirst) { - isFirst = false; - } else { - strB.append(", "); - } - strB.append(dishes.get(i)); - - } - strB.append("] of "); - strB.append(tablet.toString()); - } - return strB.toString(); + if (dishes.isEmpty()) return ""; + else return "Your order: " + dishes + " of " + tablet; } } From ad226ce26649e1591c18b3cca5eb027d1ee8b394 Mon Sep 17 00:00:00 2001 From: PeucT Date: Tue, 18 Apr 2017 18:32:28 +0400 Subject: [PATCH 29/51] Level 29. Big task 2712,till part 09 + part per part code listing 01 - 08. --- .../task/task27/task2712 Restaurant (29).rar | Bin 0 -> 65451 bytes .../task/task27/task2712/Restaurant.java | 7 +- .../javarush/task/task27/task2712/Tablet.java | 17 +- .../task27/task2712/ad/Advertisement.java | 40 +++ .../task2712/ad/AdvertisementManager.java | 27 ++ .../task2712/ad/AdvertisementStorage.java | 46 ++++ .../ad/NoVideoAvailableException.java | 11 + .../task/task27/task2712/kitchen/Cook.java | 6 +- .../task/task27/task2712/kitchen/Dish.java | 20 +- .../task/task27/task2712/kitchen/Order.java | 12 + .../task/task27/task2712/kitchen/Waiter.java | 18 ++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 243 ++++++++++-------- 12 files changed, 323 insertions(+), 124 deletions(-) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2712 Restaurant (29).rar create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/Advertisement.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementManager.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementStorage.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/NoVideoAvailableException.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Waiter.java diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712 Restaurant (29).rar b/3.JavaMultithreading/src/com/javarush/task/task27/task2712 Restaurant (29).rar new file mode 100644 index 0000000000000000000000000000000000000000..5fffc0c9dab77a6af12b3c11caf9e9f0a67fe3b0 GIT binary patch literal 65451 zcmeFZQ;J3%s@k<%JFCthR;Ik(HK+ zsr^qnGkqt0fNO6UCJ0oS8R!kQ4e*_#LJra;7C~_Fo&|gmd{XdL%hAgvX3K&xM@0Nb zLCWIQ+C#m|E_f(Snv5%w7b=}z$rWxA4hPP@E`%OlzXAZqGxp?jw9X4Ln+>CPqr;)m z+SLB$m+10!9&D}nIRHwy!fdV3KJj9QrYpBXsCiVov^YzZUo0zpf&8K+90H!zXENFF z2Gxqo$~Qag?t$2ZwC8@SPa6pC(kN?pb*~}lo_zc1nGIC4z?OA9VeRMvSR6G2atsBT zlA2nlf*Ar8 zVSH)>y#xCCb#|#oY6r;1Zn~g@gdFplYfgz(GlG!Th7j`OE=_NmWZtkT;|Ufq7|rj`Kc2Xv|*h2vDYNPAx1Mo2n;R*y=(U zxOj6n7OMC>Kt30`&hc-c@G5K;1*BVg0GnxG)e-K{1K~eHk~8i% ztKOt>`x(=_>P51~^kbrl&jM4%T93inKy>63`4M(p6o;{Q4d7*e!QU&s-^j=QsN`pu zqX=6NN+W59-w(eY9qohx=8&oeTcH~5R8G$5Z&TSGtg^GBZ*RTy_ug|+UrSd9==oYU z%pW-eTBgtckEOHxwWX`*8(0`Q{Bzj^HFS^(3gc-T=w91Td=`zzVL$zHa3L`GYFm|fP*Bfnga0yc9158DTD&y8ZKDE-kYXcQI>K}YGG#q%;OC0 zGxZLNjTTUJ12xbEWt%`pHHd2OF=-d?-b@W)uf%^yvL#W@%XsuT{j|{W8dde%G1dP3 zMJ7Fd_uCMLGyUE>RnvhW))0UU1^|Ga^h=pcmBq4uD8v8Pl!@CZtIRDfpfj^`_yGX2 zL{2Q|7u^jEa9w@N0)xANFh2g4vEWv6T@GJ}L`fo+Zo8Th4QXkkX3+?+-WW>J0h+I2 zTpy!Pq!q6yAd;ABL#mD#4C)(rRe_sa3JHs#XS9(!1X4&)br$KzL4F~Mp#gF zVju2K&A--j-r)~^K=zt!(x8|Zof?u>T$vVBTyiWzOQZX{l_}KW+P2T!2 zy<{1f)_E7EIshjNK7ke)uqVl zc>&;w?b8BVEmVf>bt@JOw;OPoH>kyI&kL8#iX7XBS(7aTnJ}F}aZ0Q?pbFe1dXy#C zsXSn%8W3dR6qmHNJ_}gIas}IRj!5GY$gf4ns}HS`ExrV*crR^SUM|dequ*xwt(?Qt z{Pq2EC|h1QL;+_V7Qe$D5lss{k}%Vv`@J?>WGfQO?YtQ zOX{x0@zK|3diJ9Xjfr8Xo^Q63AVm*MTp29VHHd?JJsBJy(Ua91gAnV%77mOCGz$OtP2IVQ!*0AQ* z8qqr>w`A9@=K_dW3%|LDZ4Yzhr*rdm`A#m%)2g~TWG)Q5-}21_n#`O)C+!Kp3`M{_ zj;AaK6@7KS7&1bYp#!S=f&fAef&DsCm$ym2AwdTWbK&Aub$&k-LqbA+V205!hZo1QsZ zX%;}?DYmmqM!wunIzyoa1V-$^tg~e6C0>BDTu7AY79i5u`)6ncfzZ_6k;mj^e-)JB zgKAh|a5GeZ&xgKm?N;;rI3N|9XaU2N`PbLp-eOJ>qpO9#5&2X=pa;n9cXsjW8C4&8 zJiAFWD`J=>;8vhPmT0+F+d@O;65A{wNuv3(WffD@+P|T(6_R%$3$2F6kBh|nQDy<% z^a;1g1~4E>Oe?%W_<&B$wv246MwfPWqt&rN#Vi9ctua1PE0+Q;kqYBn_e4uL!$G!% zX<_XL-A2+k0%R)G|)VrZ}^J5fZJbtP>^~CFBv~_=*eA1(rPGLZ};-L=Is@jpO zjHOI>^TMA~O*FzRe(HtjiaS|Tw0=2Wn7-iu1ebr6N|*!f`#`K=&8}>LNwrA2ya|;p zB-dwSLTmrbHdhN5JuK;~gqj@U?nme!6Q4ginWnu6yd7xQM6D$LK!7nqs+++_p{#dHXLm2eg8&Ip^W zJ`T-#sz_NG=Ra*YQ^ogd(@QLw&cZ=!rCvBG-vO0)xS%k!m0;M^BxKf0K;Kjb#%!v( z!kefrX64NDvgt>8$Y=o-RI-}XwL$HW0_jbUtI2Nl2%Z_ZQmNsF3cPsxL`!kgMR>0S zPR@2dpHld&_zsMK{f4}J%9(U6+)TgF)lj8_Odz=Q#DsV@CBDWU0BK=M$tnuv&-!4v zQc^~+)XHH~jGAs7vH5y}k#oird#?5(U{NaU^FE_gi-RD{&+f-WfGgvd##J{V zXT&mL=*vXLVUZgsrX%2xf-~63V34f>TiwrVIlqOv z+2|pq$-pRR6?PuZ^xeYTJ3V?OFGG753XZ(FO%)Bk&qN__pSzTvY@m?UW<44}Y}CBg+hcTL|K71q|WL6(g<+HQLv`>86U z@f8Dtr3iJu)x>C6cPxRkRE!SSg5w;er^a_^t-dBc8B*cd*Wq$!yDapMjeA0 zcb?n!UEB6sjBz_k=wNMjvRY5qNUfn-Ge0tR%?7Xqj&&>_OXnjE3o8g!#l9F8u1a=- z*3*&?4K$m>ELwl168Y`920rXi;3 z*;hgGe6WfeeI9DCR=;Sx=>uBRRHA;BS4gWznL1Gqf=ZJDw*0zdohK4u=K>Q{yDUb*RAIS`T#uqmE%{VJ7n9UJ%h#hYz1bS2Yt;e;7#f=r|UYGW)s%(u`G+N%38L_&4 z0o+vJC*Q#+=n26mz`w`qQ3oY6wdoBMu%~<%_GHNsInxjqUS_R1zW%JhVmH7HB?p6F zX)6ndf4ve&b@}sLFAf9%un+Qe5*f|b8sc^S1D^b)b3K!mu(g%FwS|#{k%i5_o$IR+ zkc41RQO3vLQBe7h(S=h#V!goBK!M&k36P$`0HPU4T0#29ELGJ4C<^yb1ZbRZeFT~$ zH9@l#=mP_#6=zI*?cxz-`_{!<=C%OGx5r;6AR*FwsrP`R zdGIA_AZiA@$xyzVwwd&{(^{-uK9Xs>VnA7cP;h87Cxbn?N2b&CsvxuhxGQe9GeurO z3^=ndv9vr^{`!T3Lv}8I#)%)uY>V-Myn4KuGYjrefF}F=!7iWF#av@NsfQ-GCsRDk zf%6N%oj4PeiNGDL9q?*GBPRfSd0f5=6W14|b1YScxHix=7js$XR zJf9YC1JJC`0zL{a30rD){xo%Wgp=4cLf5iYbv}toP#s2rE8=FVW}=&gDxps@4)?M9 zK_g8=sk}uCc^IV>pAp}z+VWmU+Z1#nzO9T|)_WNmjKg~<9?;jXcqZZD_jDQT-LhAI z%<<~%X}j0zH;i>4M79%%@?)$!x1I37G?rhlAvw z4|guca6aOTupYeLVt?_ur);Ws<%4$a%9fQ*)G_s_-%6D8>`i*4e`q=E!Zpl_OC8Jw zb@0@Qpt6zbs!J!?cojJ3`ASn=0D&)zK>wAhKu;I5K=2NKnej3GcZ@HZnF#_@VR~%A zN3Ap9+TB`pRY~oqFDzbQ@jbx<1@D~GL?bud1o>_O(rYVZGsfgMI|fY3vbttNn5t6yHn#?9K=NFJPP z&62E|?~2_wSI$rxr%!eYS?l83=6bXU0%puJfBBS)I5h0!PTGWw5^P}!+jg>#| zR+vQV%;+Ol3lE|N>I#^!Kt^d2ATn;rkW1XCXVvM`ItsMW5&hWN9H%FmackD$>Y&@g zhu`PIg^6joG#Gs#Y_yk$lZG)Vz8f;^lH=G_o1e;!8X{F)F;L^+!9QCW` zGpEdrkE>UG27MqRY|iuf0uP;_Z@Uf#&*e*DIVzvgS9YZ^g(<51jupBpn%PV$B+k*@ z5stpjKP2xD3=Vewpz`#aVNGzT$@5nZOXKe=*%he*g>E_&r%cv5kX3nos*wOA*cSxL z<-_9Y3qb+CHE*;8lLP#5RZCCi(?y74-d!a(QUpqv0Y7EqsZJS#1kb){8Pn8>rw+@v z?U6a0WPwNZkqii^kLgRE{;LNr`f6YK!+n^ZX_nPx%nJAO& z`63mm8e+tl%=nO~IGmbdV}DZ@UyFv9QQIg!tCYe$UEaboYh~U`^V1$>T8Q$F%d#^h zn{LdmX!Uns*ia|vNXNdW#)jcoonC$0TE^;ZM82EcsB1k3wl!;oR7pp`>Nz4D6?Nz* z8xMI_feV}8;A^0BgM)r`FcD@|I0Hha!^h#70t9Ju69P;p>ipQ{&wUn}ojA z0X4~5g}2!2S}TjUY1YBq-FrVnedU!lK;0KXT=)Z?s%ae~bU6KySAPkfGHLx+cv>xx z4gi^f2-A@cYb|)~Q7b7fCMXu7#7+dY7=g`YN@8;F><}FM+9oA|9G7nrs9&gO<;k)| z-2M9SOMc76!{ApS6YzpyTSRUcGGRPr8kv`s&E2)>jNMtJ2e3~E2o;4dK4A-ZTp-Va z61+KESy6Q%;o9hV;4itxqwl70A_++bUxH5XQuP#=rskJZbNLW_z2ba$&Hx8j+dZ+`Wf9*3K;4eK|CNw4sT>jAGFA-HH zt^Y(+^$Z0ddt}BZI&e_kKH%GNkqbwha2K<{jtgKz<-)Peu=Xw=wOyCWVtR(?<_jJ@ zW_&-fBtAnVjToD}a}kS^@R78Xhhi=HM3HuP`SIJi1mgtmP#}T>PI-xCW{;49=mK9l zmekO#bw57Y3PVLmb(@K%jgUEipphI<{c@8zMvSIAS9p!CrFM;cPl>Z(4nCepo;gJS z9fyiDcX(CW56hRsMOqF@-EmO>cU`aST+@+rY5k{cK`ndm zF7>s*TA#GGQ8V~iu3tpupsKxx?MxqN8oLRjTs&6f@I0SYkSDCWa7}!MRuMm&H-wxT zCVgFY=V(9r8G3C~2zUM@{H?_sG&o}r@u1nzT5Uii{u`gdz2CBD1{GyJxeHl@n_%Sl zaOPpo;gB1n9FekgKuzqB6!aTiLi7=Sb+Y6)rk|!qRF3VqsAIcRoHE@l3Do>QA1V^d zG}VrJe>41FfyGQ(f5YOxVe#Lv_-|PJH!S`e7XJ;4|AxhX!{WbT@!zocZ&>{Q7#2&o z|A~426D+p!jrpsvnEAhj#ntvYf5YOxVe$V3SnNOkm8QA?3}2K)@DEt*ZkThv3txhQ_^66bmB3eTAR1U>>-Zz zt)Nn<3l+VuP4yp!{}~R2uW(5J5e{jk9;V0tH{tjX{ka6{(GZyb2uC~Q_NxgwAt-eK z6dHO!Vp0I~=yXS%tt6^x{lHVa5qaBmo*g2&l4W9>&=X#;Zp8Zf_`*I$_=cnvjb_nM z&u`2fM^lFRfQwAT~3FYZZ$= zgABQN%^vyrd>m=7Iy6hG)H*%f`~#&{2UvYo243mhYqS`yj0tE%orX!{+e1^2V@>-K z@*w_b0=-4B{p6gZU>Jo#=a6zoT?&b@HM_>(2^X*@4*rSLU=H=w{uW1vn;=TPtmV?S zGdzdw>XQJm-=9VP$5*&A{|MJmQ-S%9Kg0Ex9KnC>p8vq|s|l>+{$Tkd9Tz>+m9+BFHwyOyJ<5LfmBVKfoTd)2k(uot4Sl#?dR>mI^c znLiF~n?io&O@;+qpWyidAI;MXo?#Ko04dBBhUy;foIc!`Qe}BZcYJfSGNW*pNA z48$6|r_I$8^it8zvWlLprR`6IUlYfG5-4J9)N{q9d`p67-MQ>EdOSb~u3(&*FFoJ* z2fQ>#g3HL2O`W)q>~8K*tB{rDl-+M_?LYFF8x-I2#+<2G59s`+$5^9K zq(6PWQHkz_65+VNM9sWnRU;o-K;b}_*S2f^4L*rO-APZ0yrOf`^^R2hQ`BwswOU(v^5t+udp8MJbi} zZ;|Y)+hKeyq)a*=X%wA61Z%|5uoU8sSxa|Z`9Gw9c=m5=BeL7a8{-$qkrV1|&7k3x zY0Fh|gn#WHZD6#Yj@zlmH9&zJ`>ljFq&Zz*&W{Bl@$n8GV_h+W+<{;pVcGl)Qrpf- z^3kOM__#J)5xw3xjod^4+s5-#ImzoBD z7+g2cer~0IZi>GI-kJXkc(+4=+)x;we#by{yJzpY_TXBt*EFQiiD0261e$KsQPL5*C&+K7}`~eyg57-u?O7&Hscl6D8vc z0W6l|N&GgLN**s2=|T4#wxN@3>*R3%wHpjcbw32^6NKY~&{T#++8V}kI$}_Po{dI! znPe)C-_v&$yC>xAr(U<1lQWa^)6aVRY%qYaB(XvWOcwD$ z%JB~Cv~*$kX5848)qss$ACVOY?83o}wm3Xe3rcQX=KMywG+N-v} zc&;qZ zz%y`6pQ7g&gRUjblA6N~60Oh?AtfeMWLll76NR2sIe+Ys#A5H@LeYD+VX1F^^ZaH? z<)3jH=3~)hvy^-QVP&j`M7;pM{%X66ZdhDr_`3hH|KN{0C(r@pS4R@=im0KV-U4|rP7O$5G;ZVplf^tNJEk)dYO(O{gF z@0$E4(eH!<0I;C>$|hqWmhb=ApMR;O;n6;4e0Bx;`i3mV@UWX zY1pm^B?^!x^!(PO^%kei4W-Dg50e>GqQDEHK~X>?EsiT0_BT-cnagn`3iJ}MwAg@} zU)5vpMf`#(MHWhGpT}&^>?~#GR*l6ylYw*kaU^EFyZ#Bm=Y9lsXz$0lld{w4c&vK) z(aKL=lai$@#We;n%zEY&X{Pxp}Dap?RNGhCv** z0aFByq+TW*ly>wmWFxkGhUfZ%cLyfYZXH<=Ot6Hcjvlno8xEwi1pZk`wpbzR%C$fsrBmS>gID*HV`j2L|sA zt*`XPwZ9C;igRdLVqtspEw~#Sy5GuPI2=|PAZ|DC0x)8%s^#i;nPS=IetP3`e$U4Q(^%wlnVKLS>8O}W^VQ8oKg^D`|nJ4&+5q@3*|KiBUvxDm`l=D=^5p zmMw8q&+n6Vg|S0H_5)f12sRoteFF`<_+&In1+Zw>`_k=bQ1qnP+ALlZw0e(Lk!Hv| zki~3;iTWJlz>#fJv2-`bEblpb4CK)LFqsFg8L1DZrpG>OY5q??ol0gZ#|#iP`t-mC zY@&R`UV1Go<47%IS#Yas^?rH;hDf?=BWwEC0JxL{FLq4dx(;~}1*0Wi@l%l?+*s); zIr^!;#Ot+emPiYZVWpx_&m<1|DB+bS8CZu#dNTa{Hj_Mx=Vz$FP7oR68=pxZMKHWu zU|hfpJ(Tl67%}sRbVqCvJAJ>OYd6ebskFl1i;EhE6M#2}upQe|5b6Zy<5|0bJD7|S zDTm5!6Pnx%nLi}FyR0C34NP?wqQU8v>?{`C#QV~UNg5x8MaT3CpGlu&lQZ8^2d6_| zQcW$OAl#4mQYH#h9i4`8&`9-6i*#Bq+JxCQmXeYBcBN*|gU-NWgSryw8mU6$l2jD! ztTb_=aQO9qXcp75FnnIiG{#wcQBr{sN(fzoc4f48I{!T?=rPdK6iusthXAM9)RjOZ zcRRT{fRaSSnzB3k6&P}4LV7xm6HF_XY^IjrgtQd;5eC9t9297JitjqwM#Jcbn}$lg z8E5)Vuh0pS9`ZSVJT~JTL%v@>oS-Hr5L9>Rp+nW4(txsj^UjBMrh3WSv$Z8X_Iv%g zsZ))3&C*|M&V)Uy|Fq2{BrBiu3% z2U2H&8INehqZUi5-{AJ4tfWf_4BYsQY^C*2gSuT<@_m_{d#{jLe7tB4}9ROh#Cb}NgVji_L9WE6{DaL`;GAf0@((osc9D;8!@8Ut_3U3`IX$E7 zknvrXFA|qDr}ye^cRq9ZB$zaCDVWsyMP+Xu;jIy2nQ4VH?)KyE#HIW2&}O@O#2Q@DsHW#e3mWxgcEUDqaHEtDV=(M9L`9&kQtdmt7_@H=Rf8CV92yif9&lFy0jnHI> z=-e2^Ox-Js=#hxs&kqJd%OrpUZv2oYmuU7xPTu6Ad{mm%BwoHDHZ0!A9k8AtO?KVI zCoz=cX()o(?oOiRP+v|M45U3SVLQ!tBWLGWi;-n_Pb;b zuif1(fhyWHv+~=apy8aq*>v>jSZ%gQ5)NIAFZD2$&4VnS6A4})yAQQXP7df{hvYW~ zbK#2SG-7B9E+iL6;To-F3pw_uO_eaBo@j51nCqELht%CGxu}N%-8o1r{jeXX**MK< z&|xn_GWClkmBxzPHH}V67)>KMJHANI`pu>Y2Wy8Gi>AKp0F?Ia&?F2TmQQ60l1V3o z40Y#Cf~=X+fI>|2bb#gEWCE9;hKGd3RFbF^xmKJLQzeZF;a1u3LDdreJ5)x=GHe;$ z(LP=rlJ$+*^%S(m1#y5w{hbExeYHUATLK9J(=D*c;LRIDRkYb zM35*6?PMcA5e*;^APab3~Z%>(pM3r;uO5qS6VcH~B5YwFr0*q9xcoogN3cU9ztl5q> z2kIu(nodKY^t**KVb{rL)|bSvqz9INXGX3tGI*>V1K?(z`VjeCtw7G@MeKU3{X1p{ zsz#Xq-t@9uh#XAa%#q&-zDym3$%W@YUN@Lv8OE2( zB81jJuH=kKhtdnw$FTH*O_ix~>!7A|N|T~Xe1`$4IVY!nJpSf`>%CaXSc^@^I6wF6 zTXXOd{fm$ZZ>S4Dx4}Oo&kY+@kq4kbo?U{20FACKa>_ z-e2ljz2Fo)u0P#9E6Z0Pp-v zMK=cE{mDubd^VfhrI2wTco=_aBoK~NpE&q_?_Zg%f$8I72jlXYWtph6@gwB~Nah?f zGa*c8Rw-to(Ycc-Lk$$V#0x}ZmN0{j`FT~+iGRtt88&oiA|UZZO9sVnk&OK4R@e8j zy@S!zypxOQmA5Otp$jeL3&7Egt_@^bc3tRhPIK2qxm{IAXqFz3yhf$Wu|(+~VWEJJ z0-`a4NW092KD7vud?|b&{HRzq`1QcekB5m$T5{W3+!U$MPL#s)T9QPwSUMK(3 z#`ImHuwLM;S%#CHiy6cj^=TD8RdGMFc8Lte9GtD4e*Kk6UwUc$*pF_>paV4=Xpv6f z5@To{HC8JrTFUPcmJ5~ z#T~rYePeb$Q8=9Tkwypq73@smcRt zi8qLzO(J?r_x}1zZ?F>ms@H@c|6(5UgxsHQfdan68o-8xGa8FXc7KoKFa)w0v==Rt zDUB??cRdh~IXS77V8l3=duB9WGft&`aO23zT5lafsLwwAHa!9gEvwBO1;SK!YkaA5 z`5B-KBMoFeT{nUrGggUG2JGs*`m7Xpn@=`HA`++(7Q1LYKC0;%aSewuWE06CF}DrR zH)|-Qr3J+dcNIA7%kMqO(_~K1IA>k2I4=f!JO#-W861WOqOF3qR2Bt;HQEk`Qsm?;$NL zF1!{SBc9S2S+;9lnH@a=yt>{i8~=om|H)~B4*1JX6U%?=G%>K)|LrvW?KJ&gaGKa0 zztU6}K<*0*hW^3Iuh3+Djeo`dRi}yNzjK-x4uN35Q0v$RdUMS7OBI;{F0GI_l)sN0 zIaU>LcX~`BH>qXedX7SrGZKROk7z4(L~_8dqY~P1L)RVS`OW)KOY>rfHNO1P*e94I zQG9ABBC*~>oGB{TJ~l*)MWNN0htW8v%y2&C-R-TlYz>7nf483CVo2Dwdh9n{jvF{9 zEd7%Jhb2g8>8#%y_2bDm(_jofqQuY`!p+*R;f1Z5J+%T{oxf`tPbK|B#lwE$%SD}yQEKzy4w{QV+Gc4`-BGR_)U{5>S5!k zb?)1r!3y~b*7G01g8bR!^pBeImu$g*1?yivR5gL8BkT&y_yjKwqTAPuLWX;q?>AyU zfoax|-Z7CKf%XcZ---hy--_p;pXvog9^D33EKKXu>@`;eIzfbCN#ux=tDl~G)k(|0 zhu{YS{&rF6ixfN~5c9~r!_S_sKSv5op?;5hwu;_I2~cr^q|xTZLAppjR^TotEiOdY zK;Rvz%%s8K1N7!b5G+m=7TeydH|ZE4k0*Q&!-qm+*!fK#Yjn)`19EH?x4^{bd=)nQ zVk>ZB69&UhezK*gElG5QcYl_m{AS&;!q&jid`SUmN9ATi{(B z(*ZafVm_-vB`JyGhc`WxgGy^+Xz;J&%B-%UywrwpALxz2niOQyB#xM28P^R&jUGGrrzk~%R`^BXWn#qIUD)!flg_#^hp^W1 zSFiQDMy!lUCrnP)=IJ3#Og zA*$M&sl_#DyWFxv9R7TF{3iqJfAsG7Z-!B-yFr})Hn9FbH?Y)?zCx(~=ao*We;8Ol zCQ9lsUH_=7JOBh=uGYWb-1M)xj{ojTr+;l#HGNZue;-Q}(6s-LCYBPnD78Pd;7xtH zHHKVLt?BV@M00ek9ZJEYD|$dee`X0TZ99c7z$TV|ll}X;j$mrk;`R7<;!AuNgUQe+ z313wGMts{9bH|h+ORa*mCOFb@v)Fxe+&YJQcgh;GA6>mH)aKv5KSh|Mc`Ap_Y3wgr zDmR`!$KB9uEoh;Pk)#7evoOf*WRu^)g9*wq8h8NG+qN;Ms=Z?~U89@NOMTsZ#G143 z;(6m;oh6zSein3GeIMejxK-T7$O7L5`aaq$v@orH$luZa#x-o*BSPEtVkZLV@0p41 zHoX@?3=n3uN3B1P;pdJ--&)#I-LGRd!p@jkGaKI#o#XK(vo-+Em&6i(RK$brB2d6T zW&TS(A7c0-xQ z2TQh3YQNH{pV!N|ZRcN>B5Y zlL|=P4<<#fvE~P414OY(LEI9?x#5Cce!{UOF5<{*V%QLlcT8Vhg~fEp)s0*#NG{14 zM`GaJnP1wmSLx+tZb%BwxH4w_5i(b6I8Xh|KYqE)&dc>v8aaw?)^AQ69O7HalwV{2 z=(h2>zTJ}RE`B4lqAP#t6514iTHzV|97xk<9uHp;`YnQtZBhCbx>lUp77xD>1U_?t zZ$(qsV0{y|#N@MaOh~pD)J5G&ZeXt#xA}_SiSVoGOZfj{C;p>E{Utk*7LL{StpL<@gNqCio$fuev(nUS2?#t_775JXC9W$T)X zBE?7|sr9&Zii>>RltLVl?h^!jbXpOvcsJg?v$2$#S~K%!koS*k>!Iee1maC%kk9mGYMI;#TRq zNmbXnYu{4AeIdI2N0z?4wpZ7n)*eG}SCSWb$~#Z!LpoV+71NGavkq-j)idE4=~B;d znvUWp^kQ|OsU9*DjnBIye?>^{`vU!d$s4kY$0yt6wkLWeUe)j@4Qv->>%;E*S`S9z zYF|{a$)m{+<$iUto&BN26%w(TCuGLGl5F{N{Ki@2Rvq3-mM+Ls{2%UJZOv+G6V5mE zk-5`!Xel30M<~DHnLJygSn00-%{0A?dp;C}kl;Q&&O|RBBb1&UCMw{?q1>qzrI!y5 zNuhtCaZ&?KSKybMrIze+j9c)wHcTSPA)uFtu4;y$T$36-bASKrS8Rd9 z7{iNXl!bqom3m{`vl-M$uC3g&FUbBxP>{ol{KPluQoFxsCIe{(Z8;r zv5l6h3dJ&CcB4DW3&LVMJg_+L6O!%VhAN^%kd936vaW{Q^S+-1^9!aj@}$|o{$NtO zE+~@~^fIP?dK~~``AkZ4T)0eKE_ruoaByAsJH7v`udI-~KLsz$E69}CVtsfn#3O-( zJ)md`3g_FLrQPOOxH+26c*1+mg*xRRC%nXAEp}~$^&r^Jqn5aD4)Yr3-=HD8d(gm1 zZ(@!E9kRENM3bN;b~@IXh_a7j521?$VKeeSTik{$e5X^BW_fi)0ah1QL=V+Tgx@6j zhI7C{_ab>0DNUGC`AA zL~BZGlsGoBt3Z`A4$S_D9_Z0S{^EUbiyE5>Z*El6>vF$W@8;l8{@eMn?xDamE($oZ zFR$MQH4CG!+%_~>V?px3FkshhQOL#dtb4hO6Ncde19{5T?7g^Uc)ykJ_$6#I)@C(j z72xltb>#x0sq1$YA*+CK{arTCV~hwta?EtBQlp@XtoCD!Wf%d5=mR22`bWXZ$D#1q zHW<>7Q-TFUrQK;O*p_yG@U9rf8Yp~&0$H9(FTTL|W0EGW1fGvyAHUA~K6yExWDn|V zxbLwq%&}g>v5!wTZRG+>a;E#JzCXD#TfQ*s4>5SLv91MjXcampkLV|~Jw#-8bT;`k z*5-9p4xjj$gj7x7_1*-~HfPfYzg%?L`cFt{Ys8PL4O^kaBU^`9iL4%V^4+nO&cM+y ztqxNPE<|36JsunHf_d;fN0jV?#gf=8Q>!0g+`>h+1}H461!9^R%sl4@kyD|-s>`7c zazT6ap4zh2Sl7vUk` z_On?NMDtofkhG4x37*8Q%a}O{zC1UGo27tD^SmAkL2{p{r=Q{B@koep@>5fQB6mfNygS@ zvF;Ou$IGk_Y%nY%5(!khsh%}*3fk(#yLgw+K09BKBYdwgJ(nXx2s0J8-Z&;V`qtXv z*@>ty`A8v8+G~uZ9g(p-E8_nXdqa?Sw+%aMAMX9S_)=E$jbFV!2feVBHlEl{-HJ_u z{4Itike|%c6=>PgHgq$>*5{1U1P)x-S319mnzS`JaGyqdxQuO#SVFdUFKA#qAz`gh zCFY|QD>d%!SX#)YOq5?4&h~etkd@Eu+e~*9V%ad{%UxWlraFO7m^tLIsWBAmcu}-V zlvQMb{LpiI(T_z{s#4b%EbyhUs41yrf0l`Hz$JTi#R;Z|X624zYqZ+PvKv!6!<1y6 zVNbVYa`(ih5s*VV&RtDPFCCZ*>6}g!zXb6p7AZjOk~_*IS$4q z-NRZvcw7XD{D2V$V)rmQ&g-yHG3V8L$x{%CLl#(x=VPhVBDe2Ly;P6QVr%W@5cr`x zdy+la54Zsh1Ls8UO%QCM563j#qzI3o0PLUno7jtGYFeX(9KLC+n28kvu>KGD^QYugvF==*L-;Jer+N{jG zBbu69O>DN7rb|v1DirEt`b z&h@@F>*_s?u*FiUWFascQ#-PU54_Y79e9GcqDHGo@y}zt67Fq?GZ^I;e$Fe)73?5^3*oW1DYhdH4)CV8by=K(7sFOwrm)oADcxh zyXaW6aEiMa?zVcdyh(81-a%snIst`c4OfPYph(T>HA83wH7o)Vb2)Go>bcD~XJ72e zSqhEDPbHQ4r@I^6Vb3O;N0Ij|o#q0-Ae??Sb+2}iLi0%D$v@)GPY8`#DO}i?K*P{b zodC!KN8k4@WCLdfu93CiixM0z?KvTMGc4+8*~cLW`Zld=FC}(DGHV=>yibz*5`!O< zJc#$OK-ok^P~d_!!<95XXx%*<@ZOffSv+c7gUGcz+YGutsU zGc&wSw^lRV^E}eqJEN6$l@I=E=~UHy*E#k7)pbdp(756*l^TE>u^r};vcNvzUuabZ zkZ$MXzG06Jsrk?{3oTAaH%lhfpN{Jmpd!Go%=-;V?>;YN6Z1uZ{?rpXqP+CBX~>Q_s{N!PsGm8sZx#=o-(- zI^lZlwpbMy97y?OIt9 z0$ohTGRGVt(ofYkad8}f&2-?!`5uWau_NGi_>#9v%g+NltTk`t9ivpEwJ{YbfM(3! z_@heUFw4?yZL`>LY<~boLP+eReK&RJ3Qb*^c3l}wOi^$vmy_0rY5kd9GxIx|~ zgWi{FHS~9}7^}ym1}R=H-@W8NME3V5K3;Rcz|o^EP&ZzbgCZne0$M98lbvyEFvHs> z1WB$dFWeyHrm?6$4654&Y=pa)YDmkGI-kf3i>r|)!iOf%1S1lg5}krkN-V-E#3I~Y z+H>>Di=v1rCT|x}v(#J73i9Uh2|m&Rr7yM4)!^Mq2yetC=UdO9vmB7Zhzz1=$t5B3 z;kB`fF-Xaa67QU-_FQlB5GUwf)dbP!r8bcd>sE-E>d(w|ld~3$dT*BHTupQ%xK{Ku zS4x-e&ahnZf1Hz9?3|rH;O=Y~N&NW!1ANEs*w3sBKm9lZ1mX?+ahm%Z>8JuVRtG(v z`4cxrBJB!rsDSY~ihJ{*?_?8q*{>{B^mC-iB2Ku~R?%`7WSo#tf`#l|v})0wM!(Ri zJKxXVBE}4;Lgl9863H~|Dc3eQPoiVL?Ytq@4)fIfMwsaJE+b8bP#l59(--8?1{ju< z96nzr3fu?vS15fxG$gPBRw~Gc2u6d`&m3PBUEo#MF}~J|Mb6|9HS*4Rp$d6*(;Wj5y3 zhOWdifnwIj_2{tovw0#?g$9UIkK%4F{+hRf0(4kC4)RUCH|eBh?ySr5iUz4iiSC>! zdDzx}XL-koFUT5B?VP86eEjE&t;kwX4p=HPx7jLxLc=?5tntTzlNP{V@>IS*PWt}Q zr4Gh_nWtXJa{ta#f9I+H19@sm+Q%~01hD-$kRJVYAT7r$pxf*6kMmT>$dA^|QU?f#AeTb>s1MsGIJM``I%_nLA?7rPAU2ZlG@{k2L}LXEz~LPw=*e&j zizuIOaDzCBdbnLvYgXbwYek$M2lXmDAXB6^?&R4%Qd=p*S^*gBL}#tw#@uz*4Ye~! z*WU=1TnK*zE>fd7V4xu!#udDmV2-**jzDPMjCB`gejf5I9c>}GjYqY=9w*TEny0Ty z%^n95(?0GN5U%)&eMaQfnAd4kb950BA&x=pT|vIg`WOtjDCeXk(ZiB-8o3p};1h4t z(iF6ZqR&~_naT~lo@A|j?02k@G4I0J8$zXTAA~E;l{x=|vLi^cu^>hJ;UsicILykK z9VDC^W{_Uz|1qQOA2XW%t74UT23%|Me`iMjQ|L-_M+WWnD|AJLb2-4+*f%8Hs1w;c zMTF?v^Z>HT)KK(li;en*WWmt=B8Hpo(zZ>RRl6j0Plfyd55+W(NkR+X>J%NXEzn9C z5wM1ZN8c@l?{9mIlf(oEDVbFme=VB18%O29jJL0^;r5nE{E3pgVTdlRRH$Z1EGddSSoWuDZBUt@LVNEY1uon zq+t{J>PC0a=Z?nHHTyx5)3B9#P#M*hx4B&LpGBrD;9tzcprA3I4%BWZlD6v!VuL2d zZ$rZ8{Q2{hyt5jVX;pg)YAMT?#vp?oBIYOt%wZQr!~*kQvK}`h2Eh>}4Uo7<3XzGN zD?-3)Jqz)PM!~hLku?=F57S;;za0-(YI$$oyJ6fa4bJIMP?(w1Hz)ge#9R>P^Z%G2 z<+_0xY9Jw}C^HD*m0pt#uU{z~IUE2oU$fm~T?isk8yeP=Ku%lJXAUuD2S?(>A15ly znv!H-S6Qb3obP!1E_hRiab|=@80CL}3_;rE7PPc7v?XdVw$~obfckYslg&APb-rr9 zgAy~}WUKrT`SHYa>d)e%b03Ri`q$#%$%jA!bN%(W|HEDBUnI2`mAK!bKCXt2emw8L zBKd>VR5M@_|wP>-|3cA7%mdNMdV_l%~P5)MBVHKd0uEh-)$ zdcFp9Wt09Rx9>a<1i0f|XaoIfRr$D(6w`AhE=oZ|39UBL<&IXCpF(dr`!w7qojG)* zd#mVu#7tZzL*5K!Ry+HMg=FA#+_bKvyPeYPU|F-;$2}((>sDHLYo%V6v+Mg+As%r; zUZO?str9Om%>T5n&zLBeFqPCTf&t8#AY&R75}D=)n16ao82h`?ZjQ`$a?^NqaxiS! z5ZVYF+FWe{sN4YE@VkSn53Y7?I^V?d@}}a)rB*H5`M`RqN7r_!IB3_>vn3Z6QH7GZ z%c}Ke(O2{(QtVLBdaFqDHwa7R<1h$Tajn(ny25BpFm4=v=n5srHBu^`k2lKSvf)3! z%KW2j_&@fDzhuL>>(alo;a}M>@xRE1{~YFjlnpcfmu$GQ(~RSHHvI3i;Vj*c^{ou> z`Q!Uf_OGj^C$xFtf4&s|Q8vu@mu&bV6GayKqi(?;Z^KR!pHnp*$w_@H>93%u$o^lD zz4Wz|1!F3grTkTy;mthsD-OY>i;=ncE0aU~qYrkv_Ck`g(zei)x z;b&@MR^IoDe&34-J`rt5Dj3&yZ{5>HcY>AW;H`JjCV`Ln)992#<_G2R4)k{7P1jrZ0h!Dr_@11w@fr3u;$b4)DO zvM||lxko#Z8KL%CG`ak;GlYZrfy^ZyqlpI8Vd3~0dDY_9Z8fp@JZ0<})7Sm;SLB7C zML_d@S}X0=>~}etRfby{-WS#@o8d$ZzSgTt|kYz+}n3ZSaeAr43Pm*++@#_qolC2yrAWwEyGzU4DK%4aI#{smBQDNzbQ6Byi?NQC+xOv6-JoK_O=IBMnrTT%8r=^$ zXB}M^yMExk-e0rW*bChQ^l>TqXnf;R%g)t6L7s1R9_*pvrVjO1x_OrHHgGHVvZp&f zl#_IL{V1Eqeb-?DO-j+>42^Qq;h@Q-<;Zos{Tykc1%()Jf1!HkQzGHzlSGvq6Lk`4$Mx`llo0X55TpF9fOh#k|j zwd_7*Zd4FP!lb2J?xPAs z7Ewu8Ig2{Qfm5hAmOOWj)B7x?MnBSEKg!moJ?Qv?+a@znPJBq8`6i)f)SUamT?IG{ z)_#EdIcOBvpfU;wVGwCye#zGv1{} z=_SSXX}(%Aq)k@*$c-5wlGljaXT11Rcz~r#0n%xeOPtrzJ53V3I31Tn$@NIKFg$6WXX#f5ERf8T2EDVs+rJ#;)t)&c#NC-}Yc_?~P=J zvnZY2(H^+UVUi}Hxp6L^6S6Guh}WSW=ZtQ9V1gNr3BK}GM9CD1f1Xm)QqY<=kH%_* z2zj8QsVpPRU86S6==hwheUh`7r#gL4wtpGpcfUsDj$i5-4Gjq)yC3gU@` zb*VkMj=W7fL4*zN$_dLq^ZM?fDU_&p4JbxCLJ2fV!xRRog1@&(7DyTqMCH@2uHqN9 zC}q^pKZWiAz8`GL_|)#)yJ77fNQs_DGE&>^YAdDNFE&7g{TNn&B~R$0KyII(`76*h;BAc)l_d=W~=Qv3fE|rJgT(@6wvMw;uHrCwH&4<~HnC zyV$)&!)6mb9m8oR;Cg)hic=D8YcSW(3@A-+ek0q<1m6eJIZl2Mq@2%?7_G@snWZ{}vOMv2zPHX!mFI%^C zXEM!L=W|!-yaD?l4X)}U35zBC<%Wd7Ip4IPW=n7wwm^BD@y5AY4ja#N#=ab1F*!t& z9>EjjiR{yCd&$#Adp4Wxm9cc$8{n%l3)uYrdpexPs}`Tpz~0^?W=?omb|3(16T(80Ti~@l*(yc(h~!B8~R$XB4#K;=zDimSTid%RviT5 z(4HnC5~ zsHpfLgdFUbuRYqmd5-t|_}k~LCzhgpWBnCYKT+*%9rNOuWvW6#7e&w-i1WncNoGEp zhlN|%TMW{Ze?6ILwM5=yAjZg4^f!Uk2|6XP(0+6pSsz{qh9p6gN4)P;PVY*dF?#U? zB*}btiDDdH>XO_b@dS^<)XxSmh_Z|KG%M4Jp$%1S){FFfK_XSnfz{OE#jWHc#l}Y< zvCEQkSPN7^!-4dUhkxa^g&Ce^6ql(gwv-VOBMGeXcV;8Iui!MNsZaHrZu>f9>hjP zBN>w5RD_LOPI@jf2V|Hg4P5g!_1OpZwkq9UcQ-~s&>%9e%(EpBUnxIh*vm)<+u2gOm6jxUL6MXR-|c*K#Y&qSGPvK)aFwHT`Mwt z@{l4JZBTr*PJdt&jl`(PR16w^pLK1YkQjJR$^y&kKtCrX^(PMWtT!egT$H@=+|sn! z#M~3BYe2tdLo7=l64JaE{8#n*v|OwairC;I&X>rTm z=;huL#9^wZQ3a3D5y3bF0?Es*_?P-&m%)qcnAr;xU~zn&sH4O9PAlCHnP;e_S?{I; zPv>$m@eRb^*cd136JVJ3&mv(ebhJfXW_FjV$um=-z$ILJe*MhZZd1~xGp2elG<>;8 zTj1wun7zSRK5*gOa9MVQ>p_lLmc5~qfb;3E6M=9Ze7=W}?;_Py*@XOJR>SAf17LAK zP5H^fW1@ZNh)ik}c{9SPtwl2K^I%sQmRQ=SoR>*^+AK{=xY7-A==MOFG2?zD7YFDJ zaOV=d&X0xDkD+v+zv2JIOsh zO{iX6Lm-{*LBhv312O2w*^YI6;F%~V&Cdr2y=eXdE5!1MP&VC_3jAno1S4RoI6sCc z;~2LPpaF+^wC-XgSX>?blrS>SWO%?f%U!X0CyS%}m59R2Ocob0+tnd# z_Tx*r@5a*^&JH&nk74aRvCOCI=oleJp&dnYM|*>#E88uou`MXzv_*%qGk54^`{ogY zl!hX|lWVjTDItB&QJ_Gjs4$FiW~N@K@wEp584OhzEs;M|EQZRrc3?s=x2Edvt8^SV zur?9J>zbh|_0E23JnLLXf-1$GC`m$No;Bw|Ee?-TfO~Qnq@MD>cU`+PG;(%2=+_1f zHN=HR^lROrX-Lp!IlMR`1$2^w4h+>_YzgvA7PD(sBnV_9nOAjpsfZHSg?%a|xy}@Ry*Ryr) z+03E$hrwVHXmd?e3JBZD?$;$agdk>U0f}HiCh>|DJw=j8BUrx|3ZFVJWH$uDb7btc zfmaJ-g^QEH{8U0Fu&a;>>q3IxoB8y1ZRe*EKvV@(p6*93b3=l+e1pu)u55Y!1*NV) z7&HJ|yMO)AM-i8OY??gk4c?D;6&aHwow&s;lhaO)4N`oT*-Yi*|5yo)SToE85BD_i zqyV;YT$E5e8_AB7x13Bwtkf5EPd(kRrAgvRk35h{u?w>W#kE)nl~deft_o;e=#w5V zggk?=jfuVRs#j-DbGrwkwRHtz2DpMSoBG!hulw2Ok^bSDf{@L6+9) z)*Qvpi-^+{2Z3VX-rkG!H^pvX1Fz*|sNO;wd{r}9d1fer)xhR#juVZXU`7GX4^hDn z)_*pmzC-&4F82e;f6(gLNDw(m;RHga@}O~)V?UT_F=}wF+Xr5X!W;ftNFEUwO+J*0 zjsh~hRphRCJ*~W_mI?NY5(heBQ>$ftfd+r8&zco(SyS<>1XfLeJ--3fq_f}bG6BQx?!MX)IK7E6MgTRq>#WGQV1QOOm^_nT+)(*FWOb+^mM!|R z;_;JmhY>}dHZT_Wj?9FOc;Md-TJej zZoEqlmPu)$S7BvyD(8U=B0doO4tsm?a1qB~Ew=$1@oMWeVx61P!y5JcbWzOxX#h2T zg>ljlv>7bR`t9ZKbf4UU?hO{&&~!o{s6@LFzb{#vnrp>l#ndWY<-x@E?MKys!MD>c zkFRSDKp+`c8o}}}q1~!E_kN4TYvFP@Ad05-wM~H<0lFR>4>p8~r@{d7DNN7g7I6t@T*%U*uUv)RMMZx>A~?_7J;M&v8U z(pMKrO-x|lU!-F)UP@fG35vI8#xL7BSr;dtJRvKK|BU9%(=n5Oz;F39A+k#p;Jr`I zK<1T|BVsSQk{t&rC_2~(>(hDpiD>%ZojRgxN^etGfX5%oCJ~rR6*1qf1bXLMj-LZB zdRNtmpWeQh>c?i~4$3vStw@G$6(Fp0LAQtq?n!blsnae`G!+Vz*b@?bfKxS7a4@2z zG(lxA*^Dkt7+|M?U)F-;UBW~XYYsiNAs?IaoBnO_hUKcgkT?zoS$?W4D(Yg^PhgYU z7`V;JD<8pCadFE0O_;ewo6PRaavyKURKq;b(iIpk43pp;bwsSOd^xB{0A*HpfeLE< zrlsAR6`Mm|s~OOOOi9x(;E6$Q-v{B?J&Fzj_|gJrvM8{%n?nH|cCKLNqo>J-s(5P) ztj_AbRW1OonX0EUTpKWecZ5Bg38IJW3IjyTt1tH1j107@kxifRRe5J(CWmLBV*>a@ zQ2>l`PF2&+!bHWJH`}J#U3$@~`Q>b%hEqd-doyn|sZ?@CuDD?^PNkPN2_A5xo>SN? zYqXz^umivW(c8;^bmop|V&U#$9!Wi)x7l?u94=E32Vn!Cz^HZxZ4#If9-b>xU_hGf zrQ*l4U>e@?!V=9~f6X2Y7_6cJth2wDz4f*F-r^jCLirU)~X?e(RU(_ z=B+VRqq{QXD^-u43M=!;o@Z{Q6lv2;eu9frENc;pSbj#N0%2LDeE;JI6&!EQ!UsgyNwhV+uN5ITl5(4 z1lvD0N`pf7zbg#5QPMa@K#v6WM~CmAUs92>1yiFOSMJ`oe@t6P| zx*R|UHh|3Xca?lSHJgWeB7-c&L*G>UVGtWy!^+T|AiU2Si9rm)@+`zdlMRM&>Xr;m z$j7X_sRz3Ql5&Vo{JU9kJ18LLfqRiUPV7ZCevafx-6N`xsHa17>+|a4py{S4hWrol z*)OCNb+H;DY7mGQB>O^_?jf`S_2!S!i0j!erp?zX?lgb}jaaXCUf=~yygF=&0@l&Q zktRtv-qtEbiya6ML1^k#NVVZyfs}E>2hK&%<_S*^?M>xE6DZl&_OIm`V=JKwUD5rHjH0k;55%h8Z=6 zrq>?9pjUnBg;?A&PRyXGYOFgg38aGSj94OYKkub%FdgnV;IFRqK#(DJF21$8GpOvqFCbPFw)E0RO-5l`*Ml>#6bTIq2Ki8Qbcc>s$P<-sF{Dbl{8fk-x4z zxj}BcE?S_{?cj=hvEw_-n{ovofY*(o9i)gP`*wCOULO*vWPso8gpVKaqo?(a!{_Yc zQCjj^_;jqR~OLsKSKpu{pF;5ys5$y@7IG_Xb<@x^~9 zzQgda4N$1d*#rr?WhCcz0K%Nr+IdAtPUbrSk)cdE9Wst2?aJVO8xv}YEys{miXQBy zF&ne@=jA64RhOFTiD2Ib`=1+rcL*tn$A;wU5hIG=MlkEQ5%@5|T(S){{Sy-_ zsvL;v0^2Y)oTFHB)G!4fCEf`B9&lknO;9@c&sNoDVKSyr!<(?U(View+lW- z+62J+V^9M>{(zbnqR0#X7-_-(-bhPmTWA~pud93)0ITNENYbP2&|l$MxK<7pSbV+k zv%ZDHRkaEDnh(}B!G8%qlZ6j}#|_7Ompk`}*|WkN$MK@uI?@_h;|#$U*VP)#aXcvq zxM&tg8L=2$Lafk|miL!s@^kA+rW;SbdjNU}Kiz6t|1R8*I)AL3Gd^iF20b{f*t=#G zyA4|f+&i?-J}u$?$7kL6_?(3wD+@@!De6Kb?ANOLZ+=!eJ4>675Bq27;mS-Ex{s@; zgEK4Buiu=wlo_(dK;WbB#2C$0h2~npLx;c!LXnx!>jWHsh#-FQ^I?4c1#g(-EK1rv>`FaQvr>j|3T!m#AO_c~_DOUZQA`))i92WmVkdzR~H9Z&I1- zbr6N2%)D27)LTN%GIGJ-_|19JTTzD+M+J*m0g08-fDML&_pWTUMPSKJ-m*f(nLfw6 zk0GEO7_AVSor5N%%ajMk$4LH-DbfG)K$z)YF{O(SPV$>6{box415Bw!;A5HojVb-P zO#e|O0j7V!lrE(En2Z_Vg`Fr|yi3i;nm>HlV?lso&!uJjkC z^uM(${VS#fV5{((Dg8gllvFc67R}$7(w~dwA2Fr>*dzWkQ@YSnSNzSCelaDZ?T=yp zTM3Ilhxs2dC8qzvlrAc{WPdZIf6tV996kpAZ%paWf&WKLiRrIQNm^d!H&gn}lzuTK zh(Fujt|0;d&H}Qj_BbPFPbcKLjI3aNpwGotdr~4hJ*wQZUR6Vs z?C{F!HKollox1xyUgH}%^ig75JCI)*>jr{wN=_g1P@=<$9%EhY6x+VKI!NlDAba`d zlQd$wEm-1==sAQdKDcRw13t5$%r=Q}esN_P4sfzRHP@~^wOu{T=?g*#E7Li6SqahN z9e1GAn}Zm!HLL}m~)pB(Zm z4ke5wzRuSKqpvN%5W9I2Ig*<%o!~CV)Mm1s7MNdF1f!r4jo1S{hQY2o4LDra8wi>? znW%g(&-lG^h;dHGqfl*(m6E^-8S zUcdD8M0NmPI)a4x3=@QTDV)mV-)6UP#3K!RiBG@#0Oo^-|>Fqh;kY*pmzsFVKS^)xi{Wd zQna_Q1_)39jgK~L&}oyP0x_1|5A*;yz??dY@W zOqIQgFSRdp;c;xcE4ysCMiqVXB9PCwsU;!f#IyfWWtwFlrt!H9egc-OE*9pv+7zo1 zC;hQ3cu~p*n?dc8-Bl@+33^SPR(#k~{l5A0tOD$Q!smL9SCyMm`F(YHPC3KqqhNfP z2eFA(&SE`oR;SeQ3y2kdv+0G~v7O6P2p{k|B1sZqHH5HoQ>)1AWy=VV*kiX0gm2K$ zKNaz1?0tJRu^Phy;GzhvIeJA;{c{30>uI`I35P+Q)@eEJF+W*J!fIdY^l7L;pT#8J zt~se}K?uFz$PsN;u!!5cQr$kgq1|5026Ju)`h*7TF9y9B0`u&wEZZ8en6|Ybl}t|} zW9`j}P>f!DH@wX3gSus#^63a#U8N2}3mNYY|U zbItJhS~Lt^EN9R$!^iZiEDWwWD{i2ujOfbvAw|(1o9SMHblijKy5xs!@{eEK_?oew z-KTdfrbW#h?s;!bicDpS%WHcLxxb7(x|kl`(06AegBQlmF|V#e-41O;Vp;P%`^0H$kL7Vsv3F=&6W zO?KSg*Ug9;WrC6}=Rq$h!(K>?j7n6mm>fo#hpi9A1;|-j5TnG!f!m7uHW< z{^)q$W25}|Nl~!;(DfVTKF=LZ2a__W-teRSynCWXKiVyVH$*^vk%F_g);h5H6*x<_ z_0^`Tc@#d>B`U)D}hYwrAnO?UA$TLr+e~Y&C)pATfJCo!Bn-{lz43?rM?rjgg92%q!?8y24`8qDyTl;C zF4M6{H|>Kr;7cOkLGU|Ch$+ZunFqNK3UZ^3t>^eo=S5#`fjV#xfG69PoKWU4b+W~= zaH4Q$Q-TZfO0wZ9UID8lMo%OUYL=@c6WlFTFCvEP%Tw3Y+$YZGiqa&FUOdbxH8oKr zPXe${fnO-2UsddnT)GP6VhDo|&SKaX)#$rqJYo=_^o@y#Z*50k&x7)D^3;p#IW1@M z3ZX%B;(+xGsY8^xEd&lOsw++lv><_U#~1s^<cQ8nn}a|DVa+R@qC`krqQ2ibxwq?Q&$xW{1AlHtiPD;A|xVMD^W_%0*U7Ye)wjy zFt>;j8M}9A*^X4rz(Oc)v9`2|u)*8Jkg6Cs7wY#Ti6G_V=R|?JA&b*2Bm+&#u8PGd6kJ8iCn1aKWk9%Itv)J_k|iK^gEK=wt=P>%Gg z+FO@6`k?k&vW0sJr963w$nVf+@>2y&c1ag2I@*iLW!Y5v(eGB?QltYP5HU>EA}HW^ z$PAFf9e=%yp_AC(L9`*lSQJ^Z<+h96Uq(ZOT8eZqUqmZPSmT8E{T zcM$ITBHau8o+xkYj7M48h5`LfEt$SLGz375EU$*y;V(|Iarb&u&41uSXA^lKnC53z zNJ?#7PrAYWSe9KyydSs%ANCM43Md*E*U?EL0FEM%;KqQPg_WhLaqc2{8_O~^M`?ItW+YZa4j(5VH}9ROlJL#^Gd>L8AE zyY}tIPAPxWd~^KQWy~pPID&PIWWcN&e@QC|I44Q{K=j}d8W1-bQ#=4vZ77mJlhXta9#NvL7CC2B_f5FYWij&P#vCW3zR<(d>F4iq30449>9KOZ+FCoJEPDCXIdsGC7_VQzrN# zi$lv?_d%I33fFbdXU}J64%YGrBBX$Rs$h(*b~bRv2E^F&VP|Ps#!+^OLda_uQPA%Z%Rz@KBrBcz2|)UR=ynZj$iWW^ zu7ln|cbdC==yW3BT+JsTr*T^LA}=2i4Os22Yj0rOMtXOgCfDEZC2pwUE7B;+X0_Mc zn#N!cCH#PMUl_+)g<^Uf@>f6fxf`~em)q|J@8)cL0PWGR{6K6ptI(sKnW3<+_WphPX&fn2O<{ehM1`e#6TO)B!2|ZO zTPJ4JXYiPb^{`HF0m!+8tSkm~m5PQV={v1mV(q@UN7I?qLHqVH($<7Uw z)YGmCF&T&S^}FMVeZe)Ofv?XhG#3acwf@3xsuVXHM=aHzbH0T}bPUHKI`jUDX2u2a z=7nYrq?s@ia~W)qk>x-+^0~mc6D!FPe6uSZ?jed^u(y)cg!Wy3ZpoP55WLkJqdF6^ zz#r0@wQv#s_U5n(R&~apKP>8Y0z;bnjY88Z1)f6%!xy}~>Hhi9fs%ca&f-&Fm-YgOa^2?>!U`*>OelyORbk<$5`v5p~`2b z8D_r->VK%Y>;%Y}9;AF&SsEpSF`;pG6ot3IfFy8gTpI$dTaBH|qv0v}2cwy!Bo z0hFOVygMrgda~LY^OkA_P96ItD=CGANfSYU+2*?1saG~*jDB!7OOOL9|6Jo?=P*%gs-zW}YAvVB(|)s#v|kRW+X`_Ymz^)Vq0Xrh=&n5O-xZ=6GP zc++au$dyHCTc%wgg~U-~#$)1Gk+lFAN*O`o>wpP$P7hHJ;nhowCzf1-pAkc#?;!N- z_&XJVFIuV%W5TcMP_oBU7*~vUqQ~9HfOgQ!n*@}`6R+J#u$P7-aXNoe4K39}RDRzf zVs9MEC9SC4nqTT#=8jnCL)dHP&lhUFdT_oH?k8=?<8Vx%a2udYqHeqmT=W7bWA(-S znz~;zJ~X&WbC9PUBbcL8+vqBs)euk`59tOwIQC?A*bQ~#)^+$QyThVQwL{W(qU{k3 zB`|m#3~%7jrQK4y45uRRGErx82$)qQ|3i$EFAq}Lc<{^&X?BuNW8Lzl#r>xRTX!fN zP%7#n4XA4~nfP0Y#L4v})P?^y?`2NblrkCHGyk5s9XI&BC~k}o8|O~gCKAoN%owQl zumeaKsYX|Fz!S^vvux$X7Zut?z#I)OK_JTlEnWM1b2j6GP*`hVFn%&3$9=r1f(e6h zRyZ_t+3Zz-1PaDZzwK4a5NmYNdF4TOU}??#*`a(S5{e?u4ilk&o0D3l#){>Q`NQ>c zkg}(AD?r71(#~t9(C5&doa*7PeZaW&LL8BPY*u(;eX?5v0^{XZDW46w{xEiWdJ>PD z+v?TZiYQO4p@D{v-Yk2$DX){OVTfk*7=^^5%8r&)5y;%u{L_bS5lUTZ0mL~4e*N&c zd!xPd5w#Yf_P|>VWA&K(oE#gH8bnoF7~$nqp)4C#b2^n5)Y=!UL7q4D?E2+R}VF`RzRxNt?|J3-a5laru z(UoR(uI3MZ+G02k;MFzk{Nus4kx#A32BT8OJnmtYKpz4w9hcy3vB{#W)tyzcq*x zZkJ0_M1^wt8qyK^%sA_lPHDC+#{#W!2s&^~-=vi8g8q;)7N6wEy73@7slaVwtd}FY zrtoPFm#*H(w=^$%LbDLHokI~5r(|zazuuYAY~IgTd57-FOtlgIr!F0WK!S=B_gk9>@WZ$hk(lNlTa+#lfOSSR&dFg?E%3)KU#%XPZc^o$?{vf{h{4HdNu#jZs;HSE8>>` zI}Hob1d05|0_?wz^k1}FWo4lWc-$Bqu&X#L|6Fr9fdxH^b|C)JG>8!_xcVd=&*P)F z^bG20DZ-uP13kDU2rJApg2*34uJ=viX0R*NPd;-OkBaMoxvd?h|17}Xuj3#Vjs0GE zn!>WhhI!CL?b@=?s*gj6`hj#&m8qsG{wbs(r`b?bn`WTq^3?z-Qs2?E>HX+}PC?E< z+QMf!GU_sSgIFB0*t+IK!5?#g_fbeh z5bR?POw}_N|3~KFuL|!AzA+S<4Af}bN6+To2(UTlyx?$QsysMjStJn=5x6M<$L8%k zhsGU=CJ+S$GC&>$X>vZc34pfh5iP!NR2S;&ARHo!AW==Vqw_0eaZ7}btT@|_Kbju* znK^82>60E-Ucc6a!0)fFoaJV>KsYPn*BTL(=Lw?cuT@Kuu61)rj{8j8M$5W;Sk`%I z_>ohw@FK=BqiBDHlpw3wQE#B%VZ@!-C;pb;OIU5pP#sRik(@%<=V#xV{ggd~a8ATb zOE_WWMGr2Po&#AjSps(3Dv}|iTWq74Swn5y=p?Lb1lCh5@l_gQ3)_tRXedZMa!&ud zuxDu5Q8YLO5gci4zBr!ah}K-#F>`Cu!Zm{E{v-0DQ;1QkFRYqhvu2Sc3=G`ZnU1Gh za#QivfuSna1+8Os`kR~!t|7*TXWoXBu+hnDT>92BED6_^%r1HxW?>g-wvkY%QFQk8 zeD(_66Felp5I9cy?s_7H=W=TxL?P!H6et{3)?{-~?%RU9+{WjlLGf0LW7@1l4gE%d za$8bT6sYq-8@5^K10=_HXO(O7M3lAm4WB5W|74Kp|lZgFCJHY9zN{aP-hT?8rAz z>|iTw_g=TQkrV-0(pDeBH#SNDGB!-z$zLXualRR>B6CJAaHBMbq%ue-(VJd_fjUAO z$uF7(toJT^A~z#y?R~=8Mg20jB{-QMaPp0y`}!g#r*Gw<1~>==<( z%w$i58DoZJc@r~oPTaS z|ER7H^S@-Ao@Y$I8Ru`t`9Huo$#FiG>E9UVpUdrApFNt5`f_-)Wo4UiNh*k7Y*o zZmfyKJdWLW(7!0Tzo4Bjx!<&hle(u%KXDYCcICch*;$Bx2X_M2W2Z`+des!-mMD9{ z)(F@-NAcNRgMI5ow?!0$)b#IkeG#1Z(Bc+{K#tSVdi*(|2#uiY!STthlFD2Q@SOo! z>*B%?$P`R*(6|EJ^LfgZcRr(;=%c<&iwtAXu(PjfSuA?PB)BnNoQ z^EUjzwox*e+s1Mu$OV|V@B_?9cE##udXkjmU@1!u^e*_WU3dE zc+fE`bnCFE?-VI@M!8?n+2c+N69`z5E=wm5Ps0UB2yD`bmGHBJG-S+DRjd)+S_@et zFHH|ZV$uEq%L+PR09}K;)(HMap=R5#$Ul0&3ljvN4nP!XBdhqk zH3Tik@OM{~D;q94ebtkIlXf*+f|ss;s1+k*LIK`6TrjaiH_d4JoNGZSj#eEGVnc|7 zKCRi}OID5&K~*Qpj!~@!O@F3yAv8G{cYfPWj>ci9STq3JA{S1(mOfoHd0O}cf9aOQ ze`^i-&9p7CRLVI_WrgwKQ&;c$!pl1EL+j={>(P6h3+9S~EvwhnXpYnjymKP$`VVm; z+lG3aH?C9Ls(ad77fdlekpl~HZK5ok3D%b6xJe@LwuzGral8h3Imn8lpPRl<;ts~y z`I*zO@uSFM)R}Rbi?E+?c-SQ}?Okt0dKWU$v7X;_bZ$JJgG=4C+&c=_(5Je(p*aX) zA;(o)Xii!sV66j$U#v&GaB6e<3f;lsUz7piCPv@G>W!L+z14k`cp$j)+>&kXXm4+W zPHsCpHmC-015+)65H-GX52byMCtQ&+++ZF*4Mx*k2HWtd56Px!Xci8Dea`!8Dsst- zvajV~v_KMM;l8J&Jt(~rXpCua+LbO66~e|f_#@|uQkGAE6ZShjANI#NF64d+V}Pl# zQEq_=g=g1>jl#sWCrmf*xKXcd55#G1^c7I~u&BmmA3!Yi)t9>-fgEhdz1=C2m^FAA zs&1wd!znCcLj z>!;qp^LyHA-9bIm$*^*OtR9&|ve)C~C@Z-m{VZTV3qT&o9QHt^S>sz(w5t0+3nEDS zEN6^};xu1+#(GH6-6iCF*7mUW8-_sAs}lbb=wX)0z>Z0Tvqt1A1|ae@;z#I4`R#*W zH%RzShKVlgE|@_b4fFzY=IHPei?ghR5`f9VeYAu&51^un1vZ>kQxhJwGq?+t)_+Va zdyI_X-(QlXsP*RYX1uy@>^FRoCa4?!`|oM~{9k(Ln|tKNeS7({IUUwdaA z69@b4d5Y8GZbNYx+}&LY#f!T;#VM}Eo#O5kcPZ}f4#nN2IPCOo?(gnjK~XA)!`%QGmTbA_p2gC<5~-%rN#en3j-G zvj^6bHJ9I(rN}>9l_qY161s$(wUW?+#^eZGlYktyj|@_SH9t3gx?Clkr&cke2l)y@ z*S0UwdtZRtHeH#@XW=ByWhg^BFG-Q3zexRnb&}>hrv_ilFl5P!I~+A(B-&{Zyo-AU zS@MNPec%-^qO~p#`vFhf9Ok{|Vvlt`nvU2QdVN*=wDlb1U^dKmgRqdnlsn^2VgeOM zwd=iex}w&k%Yj-^dHD36r0XC@DBBCdWDlNq_KM zKMP6O%oy?oTu;IiHdze=8d_DFJk(i)tIs*^M<{}Niyy;BLihuqd0|0k*&UK^{ml)! z*+?P#n&)j{Eiz@uBOP`KH?#Uy-I3NfaiR0q*@=~+Nb{eihH3T{gwvBFv%0K4u5R6p z4hc<5W9d?Gba;}%N*rp&A{51B&wPi2kKVbTrXort4zG$1pJ`>h{SwoG=q{7&BuY53 z{d&HOjxiv#F%6<1N<3O0$BD&xiEe-EEjGRAHxi{RT-FASt1m-?0$2yAU*~k}5&K;5 zBLVh$QfvIAb!Wa!QFVrPMX%BFh7|r>l21zQ%(m=Vbgs5 zv`yqTT`MhMM=35cz7?|Q#+1YE}VUCaO~KAz8G zENWj#DN!np4#QeLvjYJi{~9zC!uo%Q08` z-RmG92dSW0s^fBWjkc2jTOL^Hx(LJ=z-50qJiWhy^ZT0@rPf4f;xa1Om#tviWZBaS z(QgwI7nxl5)v>;!_pcc+6T1;Kdr=D-_YhB0UVtr|U;WFS@?-~vF$%c^GgBmVF`jJ< zxjZ}Dt`CXl`8VBS9WVSWT=|3&;_he7Mx-R`k3;N_OZh@XV;54`vfwwR&4nM zZk_5@NtDtXuA|zteV__Z&fQ!C-H@QFd?jd%QPIDbs-#<$3YoDY$XPrU|D^3lOq5zy&48lulR^t{5jUY=B%m-USyf!gHjPQDVC{)1$@3zN2cd zpCRzj!_CD?ZqIbIwA7x=m8f4BB0p$&dwliU-^JRUgChTG?W&Ul+*^`vHJJSY;CrHc+G&< z*6N$wy_e{p&=t){ob2qdR-Po*s?4Y*Lxr;%`L0BQbZ&ii9hy%d!aHdj%2QQ37xMBJ z<$wU}3N`aXm86yU74EO=wJq-c)Z04R=hH?q;MDoAN8eCR)sK33x+15*X5%u6dvdn#T!)s3}FWchwQLqz!CC3>2fV6NQ6|Bg2VefD6aI^|1$iWqnoh4~R{ zbmFAC|Drg9l9pO$!{U2z34NT8%l2-YQXJ8?e`51eiX|OsyJE8g(G~MKZ;=4G9tqjqvGBO z>hNu{|AA)#;kjWD6}(F=UC?4P8yBlzWe`+m-kWsh`Y9`)ces;j=y*f^+Vj0=jB7xio* z&+5^h{9MRk64(r_WGKwfOA!54E5+q{ks;-RfS=}ggCp7o2n@O0RNHB4Vy~TT{eT^6m)j&cwZ#|vfRZXEK*T=S z4&s6DzA%40%>YDyt2@=qebIuc$9zl8$duGYF1Q|)YH0^GoG6pxex8zmyd9?JVl;1! zuX0L~Kod#{(7_kORMV~F#yH&BvgeEgjvBbg7JZ;k$0)%f5Z#K$Ra=NOnE=v1t%pjmT#uDTqP zUFqvdZ8vl97TtAZep#D>+tRfT@%BZWEtiGecF5F6J_8sODpqv;aSOVXM9+zvB(pfB z;~EVv6-RdMEg?6J|ual^Sl|(zfU`s+Gs%%UMxh4 zwzX&KvUXD_@rD^s_f+225EkW!r zf?de;QE=0pZ6(sT?d;xwi7OVGQCQ_SQT&4qs&k&f-s^OVb2As?(|U6pSGEfREoIO>qvT7J_4G{r?G7{0@_ot zl{Voa_VxF=lVOOLBfb()-MU#l8y86gY)!3V$eP=Gnm0ifdUx+$ALq1Ck9e=9=~i#P z!~u=tb6VKEGWJFfuWv<#sc+=co%22oNIR#zF%5XAQX8psmNzH^6l-+tNw^!zR4j~} zP2#`EKWa;5jdAo&F<1t!4>3p#HO+?`OqWJ9rseM7)?gBcMse3?=Pp@z5U2Q!p!H%+ zeR33PqF)fI)!liU;9|`g^aKBZWJ~@djO1)2I1h9d7+yK$v%(@VS{U6A6p-U(S$as? zEzB$avT*a4RF_AO%GS2YJPA)1j+vkO6W=r2EKx-6d(yxN9uTIc-|{wqtEPZb|u@D5n~rk{#Tz)6DcuM0LPzNZj~asSIzR!WA_GhQnyJ25q%J0Y2LU0Kw>Snz5KYyi8wC(nz>zT?l6& zFE|kdi@q%2?3weM3)7eiFSf|;xr=LA5&Xc;Ac1_{6MHSl1|T*)Ng2TIB1z&a=DWIxhrOP}`nGS-< zQGr2VhfT_H#W#9%-r$5ngwOm+TS4$-ErjQG-I|BPWkAea!?{FARqJEEZcJMr*9(jt z@Xt+$78)3d_`_xt81j8+!H6*s>dJQ%12sI8JuuA(YZ~Ia1(?W$KZ-5A)a1rRK2xb* zqhm7!6&2F<_3qrd^NQ90t(NeaNjQ8HJhT53A-dF`Ud$ zuXz4m=W@9cavFaG&xZ$R)h8ZAJWw{5WsYauQYAx!rvFqBYBpH>Rm5&>>p{hlL4?H& zv4|VFNN7y`f=|YGTLy}3djAo?zcLkAkyAyOz9wlu1@AS*l|N+Y8f?Hr7PGx%>c{MO zKzpCf5aSo?X!y1Ybg_}48;W;A)?5S{MKiB%o+F}uUP$qc`oc7Bd8x6`NZ z)vgZ?DOwRx$=ZSE>^`?k$X@H;P%+!?<$mOz6D8`CL-MnbjHbtsD|vzyzfWi|U~U;Q zDn7O=5mQuVlwoLpPy|;A@rsjXgRvC!k$Bw!W6?=f(<{Mkg`fnK$aHEEDpAVsSUe|x zRd02)-O;rBgpuFeMyI^$^*+E{_6hCE*Zgj5PU$;aPa6gu!gg~8jdV{RN59UbD$c?1z*B_0IJp`$oYm-}rr<%UF{W>Jw+XMT_{Z7LSK z(d_K~fEQe^>rVt6hk~M|^tVAN95<_tFB#tz`p};40^AT1fz#}jwP$QL49?_v)i)8E zG@8-6yTD_gG}_jfx~J3j_+=GKO}QRp35aQ4oGxlnym}aq?)ZTnG$>KT@uVR_0MUt0fsUMP_-lCwWoev%eUmpQPbGJDMI^o+Bb4gfVUi_=CVx5?#~Z7)5-xZ+uW6Pl|DedhvR26+ZkfNz9EbVjgZcQ>8>lU{u*!6 zpu+TC9@ct@7~3x9`(Te3{Qw2yu!ZaAP6jvQ;dm^KpfHN%-qrXRi z-4Ifh)HMEg!F_vMSIP5ITnLA7p?e#K;Bf7zFO@usE|$m$Hl-MT+Di7Uu+C_4kT-dx zhV{V|++Aoi`O1&6t+E-#gB6`e$2&{8#UIRB-{-@3YcRnK3cF^knY(IeO&&pbk4)9H zmEuWx>2o5!z?NM6)iHm=O96k5`2OB8f5S`9Dnxny!At+aOaH-3{~NqCeg@Qv{{b)k z)rx^w%=~5njsiJ6`Io!}$+h`d{Ov z{Xc&-tAY7|E@h7Wyp*}q`WP)3^YgFBKf+5n{)U%UFys)!V}RJ5sS!aecW`%J{mB8B zfc&*FSa5jQPFOgwNNgPJlp(53F=7zym*K7FeMt_V%w%kw2yHRaSZf%43q7T{Zuv-a zM@b^%5)&?8B?J`eMswArW_MmZb~*^Zeq2%3n)zTcY@dow`FctR%FO79w!v1bnf$V} zsXAe$%p}37+biv~_Z{n}>4$H_)Rz z#2RaZ#x0FBRz*a?Ca^d> zS4?hfx|>&eM{9UMRpw(@^9>oNNYi`rnW79fc-q^~|z5BuPtVi^BoG zBS!l$(B9Xq!zEE{`D<*~DTSy|@=&|f^q`vY>;oyR0;yvyYHwao&zJjW`tLm+p{l#LOEuX^!;3`PNaR7Xt_IRBQW z*Ok|`*EHa6O~=*$6Gip~|ILf{TUjC82G{y;?wl2GaTSag;g@NMr%K`2td~{r zHMby({9BIIcLB(RD1+)`$P};*WIRuC`t4}b_v6?6Nyr`Q*s0p)PSX4uS3qao(8{Q(-u*-feEDgbcU{}`JK}{IyTZiI>JiTTGrLl8FOyFV)E$LSd))6AJdfHwVDqFC z-t)pZKAo^B{%F9cKM^eNF6VD0aJxnEMYfMIODf~mq8h6#IPyiA9EN@fx1#^4o%WtmHf zUfC*B72*xXCUxY}+d9ZIFeUa@jkY>~kpqR@%i}hK6cQ$?yUj85WrHF4neG*Ea#ZOF z*UbguWX(i29%;tsULEa$#buu3L%>5p7Yt6Fju0niLo^m{w-(MigtUDC(#SgJC*cS$ zqldma>p%^pI&pr>!4Du0RW!6`hPbCJGKk?T-2GwE*LD$WyK6H_t)hE(@)=o^#C>o1 zLzH_{YjQN1=Yk?!#vc-5o@%x$oEM6;P!o}8gKp%-X?;5T+xDv{9hhf(uoyYA=Ha1$ zw?Iavc0|7K`|)BUU`OSEB=ZZWDh5H~}X{RN|#vJdywN^P~)=w7A>$W0U`*}wI!2$>jZ9u3^%f^C>cDw~d%X1r%1>Wf3b`4Ro8 z0x^)l$;OX7qo(#;Bdk3xW^JT)xCfEw?W%1)#a#d1%6wnmdx68K-4GCsj_i1!OaFw{pfD}bji@2=rau=8&pnVOjw3m zttty!?}r!St7xy44a!oEBWLXfSy=ecNZ2xYQs{kcT~;sfF?ihGdQDsohYgyF6S?dF z?-s@RI*MlQ!q<#f{FcLTJUoIW%byiWr^e3#N5Zpb)yotlYT`Vprq*aos(y0cKR$hN zY!UI)J(Xxh8{e8IY*qE})94~*YR7BKev0x9bIjC@R=`4Maev6Y6Czrh)|B(2h~N`v z2kLzD3_2Bh`YCb`h*XF0ljx+LO`sm54aEx^g_HEmXsih&48dv9Vd( zRbS=c0(yrt4?3>U`DDo;_oGd3{B&Rpb0$|UKhTLpQd~qJ_kMItCC9rLH7fPNGDa0i zQH8vUY}e4HtrDNAanEnEmz7*)fj_)|%-PlnL>A22QOe@0MNE6QhyjRxDB%a4uhuhd z2<7;STI<7?^y8uhv7~3G>d(=bQAkC_PffQ`WLsk8FL%m!x}t7D+eFeSR{IB=Ll=As zjceJQK5r9O;Lz$71YAMBgvG@^CmhS|JF2lgjGFyhG&cN0&+w6I_pe?8E8Bx2dof=>#zAv#>)mm2`I$G73 zB;aunKfPwP07EnG(am-i!z=6MU*Gp_aCP)tV_$1Rltl7w%C!*h$9uk~hcIaAYWRqA z*H~6gRZxE&O{$5m&aF=BM|9!v^@w%~fTH$Q>E#^%c6Rb7U_BvWmQBBLbpE- zFIbJ#hiCZEcrpDM_Wig4vkW>bj0>Mekst?R$wO8&^thM1usN7bv};uiZAn;V{Zp+n zzr((KuMGKSZ=Rer^&#E`27!MOwy&G>G818KhG70ME!grC83{z3KD-r46fh-P6*XD! zGuP`Ao140+!vsE}ahbjt~6KYj!P zzB-Pf7&jnv&qw&>XVk>8!l~FRTStsOpLfk=xEnHUwy@UrLJ=Pfql-9_7WA-UR_;MOKJw%OfNOj1L;jD@wk z-7wbf6BowReceaY2|WsP#h6O4`AS z!4tC)ShFgQ!VhJutMgKg0Z|FG3FKbK7o^u+C{4CY*m{;7df=ReR(XRe^I~ii&uEE< z-T&sM4Op+lCwFkdLkj6&Y8n(rfx$uKXRcG&fthA!XIXAk5C}@SE%M!!>RuQnAMdcL z|B+QUxy(Y-9S=nt$!b~(B_wue8Htb-lVu0wF)D=*-$k7#3?#t~qpU^kU3kkps3i$} zkmoQPVudbe0PPD*sg|ol)ohX(mP6Uf=-f`k0N zaU3?ssVWHA^o)&>=029jUNCky`s?Ssk2Io9ujP|#X7@||Tyjy~Ru~=)9iPSD{o4C2 z*i`ej`sYZYC9MREkQ&hh&T)w?=s>FKgFeFTYUN34&C+4?1teI5ij`1rR5W~bC7i}m z8&%mu^YJ4jT!4}jS{T%!HE?5+*`WHT^)w_>FvOL0Ws4KBiZFd<8a7qSSd54fW(>Oe zy|>7t-*bqY_y+CwJ*{T&s8Zz&4i2z0`nW>hgniWE2}xrSKRIaS*XnMB#~GF^Kvx_= ztKA}X|L2z0NFGn6tE;>#n1Kg}y&X9aH10wbuC%$9x`a>`KvvwtrA+w)0E3gz%@hJf5eL$1Em){ZHg=5{go|Gia@}2``SjccpJA%zqRC5bi}yRfpz#6Ah7gRbwYqInz&BA5MJ3MG$Pgl-Z&tt z+3@Ox$j}heuZ@XcTxK!#yk@p51`;p&n{NkhO@78_&OF_14-Ddhm-4sDdcMBhK)uKb zzKj|FBITFL3)F7^zSmC#EOFs(%wJf7S6=z2ntwchtl~Q^td~=-|ROkN^jt?kfWY`;#B!e+CY)ciS@HdzPO$jKi>+ag>vxHWa_w9NI0TozE z(YJ?AidIjGu~i7;l2z71`86;Lx>`MzCG;~K6bx_dS0~N!J`u&1T+@qAoq@Ge%`Ps1 zhm7_2ve`u;jYcK6p-1x9h4@_f#PDT2ccGx*fGH$T*t8DY4ng+%p_$U#vbm6j2PW*K1vJE(rxTuCc;G zNTfw^<$uzxd-?)<9MmHyK>8k-n3A0|pR zagfX|iJV<=K2-~~lQlPuXJv1Ee z;+_1NJa4Ymf>vhh>5({8tho9+bsYBZi-A$QFUUM+SiIhP4WjiJ)gg%*Y&9iPxX}Zl zP=Up@763JEh`PZ(XW1UEql@yyBPL@Xj43D+D1Wu3K7v*(G#P(+kYDr|eu8`;%Som0 z?m;LF>I`DJ?lL|3ijz_eF>JZ%(OF9NQi%MBbezb&00Eh%xIbmZp<`WXpkTu_-+4vA%>QiqA?B_XtIucQ3+D6Aw z-ltA25A;y*#Xyv7T8VnN7roX3Q2exqjsu89BNTN}#U*`TbUb5}GCAr=3#8XsCgzS2 zD0x6ZT47n_Xk9R>Qx0-l9d*A~TTUJ7g|`-@y5cTw$9t18XMA04z^YUZ=K^2*(F{s zE9sA2e_G!cXhfw@L2zcpDjR7bfJ4l9-U* zZ~+X)(|8%2E5|r~65wBs8CC2wzD9WTIreik+hHdf`KpeUYDm++B?tfx>%dJPm>5LP z0bIOx^LR|(OiCp=K|VF9tjd=3#mPPD2z3^QgzLHbYw|3skaWhThzc%!RUegD34Nq1 zeCip+)smKp!Ps~(m0PT=CnGa}d{o*jQRJ52#WK)y`LbltQ{mdTV`nZT?3b^h4#no4 z|5hST@xVj^L0!!E$WdHSS^N=o-++q3IFT|`#@|nAjt~Jqpk<4pK1rcywLlEL%a_W6 z`b}^9J2I|Ifa8rGDLpPFW!(}M5|*JsQ<&uxR%qBm-ozDAQ}=0FXSQ%JOz!asRpD*?F3D}cEaWTcqJowk1I}Aplf{~=@CgfSm+@JTK!7FwJ z2I^z;W}B09TQ1{?#C+PNs$gZEHDsGav(q#--uBH4d#(UM=r^^zSXa74{C* z6Hr|~jBRTX(8eD3*nJZCsO+#7r3{*9`|AOs1i`=rK1N8PGcbT5gI+u6*;_ENGcpk> z7}-1MIeyf$b|9o=;sk2`>kWM~6G8^Ye>=JcI|Fl%fz9|`w9e&^MVbCxR5$5e<;m}& z5CPGD8Y%O?L@P3diCoEl7v*q^`BPDre;1A7!mkMXT@)KM+x8FFl=a_5ZSkXz{Xn8} zzp?~+{wq<+Ad63Q2I@aa)X#y|U=?yLn1&I*2l-3yj}rf{sdZo#U>T&xZ+;IF5roeD zVUR!FF+qidO!3h7dyv2M{wTWtinwKKmB*H zUw!yTV$5I_gbmnrsK1N->c2k{V*#tseT5ps^1IltzWXCFRP1(V;!e%0F_iE)5BRy+`Q0VKxz_c~Mgs~NEW+d2a~ Q)3u=L=KTaF00Z_v076(5X8-^I literal 0 HcmV?d00001 diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Restaurant.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Restaurant.java index 70e0b3f..79cd045 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Restaurant.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Restaurant.java @@ -1,6 +1,8 @@ package com.javarush.task.task27.task2712; import com.javarush.task.task27.task2712.kitchen.Cook; +import com.javarush.task.task27.task2712.kitchen.Order; +import com.javarush.task.task27.task2712.kitchen.Waiter; /** * Created by ArchMage on 14.04.17. @@ -10,6 +12,9 @@ public static void main(String[] args){ Tablet tablet = new Tablet(5); Cook cook = new Cook("Amigo"); tablet.addObserver(cook); - tablet.createOrder(); + Waiter waiter = new Waiter(); + cook.addObserver(waiter); + Order order = tablet.createOrder(); + } } diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Tablet.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Tablet.java index d77cdaa..5838425 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Tablet.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Tablet.java @@ -1,5 +1,6 @@ package com.javarush.task.task27.task2712; +import com.javarush.task.task27.task2712.ad.AdvertisementManager; import com.javarush.task.task27.task2712.kitchen.Order; @@ -25,9 +26,19 @@ public Order createOrder(){ try { Order order = new Order(this); - ConsoleHelper.writeMessage(order.toString()); - setChanged(); - notifyObservers(order); + if (!order.isEmpty()) { + ConsoleHelper.writeMessage(order.toString()); + setChanged(); + notifyObservers(order); + + // Часть 8 + // 5. Чтобы тестировать данную функциональность, нужно добавить вызов processVideos метода у AdvertisementManager. + // Очевидно, что этот метод должен вызываться во время создания заказа, а точнее — в параллельном режиме. + // Заказ готовится в то время, как видео смотрится. + // Добавьте вызов метода processVideos() в нужное место. + + new AdvertisementManager(order.getTotalCookingTime() * 60).processVideos(); + } return order; } catch (IOException e){ diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/Advertisement.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/Advertisement.java new file mode 100644 index 0000000..40d306c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/Advertisement.java @@ -0,0 +1,40 @@ +package com.javarush.task.task27.task2712.ad; + +/** + * Created by ArchMage on 18.04.17. + */ +public class Advertisement { + public Object content; + public String name; + private long initialAmount; + private int hits; + public int duration; + + // Часть 8 + //1. В классе Advertisement создай поле long amountPerOneDisplaying. + private long amountPerOneDisplaying; + + public Advertisement(Object content, String name, long initialAmount, int hits, int duration) { + this.content = content; + this.name = name; + this.initialAmount = initialAmount; + this.hits = hits; + this.duration = duration; + this.amountPerOneDisplaying = initialAmount / hits; + } + + // 2. В классе Advertisement создай геттеры для полей name, duration и amountPerOneDisplaying. + + + public String getName() { + return name; + } + + public int getDuration() { + return duration; + } + + public long getAmountPerOneDisplaying() { + return amountPerOneDisplaying; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementManager.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementManager.java new file mode 100644 index 0000000..7ad857c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementManager.java @@ -0,0 +1,27 @@ +package com.javarush.task.task27.task2712.ad; + +import com.javarush.task.task27.task2712.ConsoleHelper; + +/** + * Created by ArchMage on 18.04.17. + */ +public class AdvertisementManager { + // Часть 7 + // 4. В AdvertisementManager создадим final поле-ссылку на экземпляр AdvertisementStorage и назовем ее storage. + public final AdvertisementStorage storage = AdvertisementStorage.getInstance(); + + // В классе AdvertisementManager создай конструктор, который принимает один параметр — int timeSeconds. + // Создай соответствующее поле и сохраните это значение в него. + private int timeSeconds; + + public AdvertisementManager(int timeSeconds) { + this.timeSeconds = timeSeconds; + } + + // 4. AdvertisementManager выполняет только одно единственное действие — обрабатывает рекламное видео. + // Поэтому создайте единственный публичный метод void processVideos(), его функционал опишем в следующем задании. + // А пока выведем в консоль «calling processVideos method» + public void processVideos(){ + ConsoleHelper.writeMessage("calling processVideos method"); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementStorage.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementStorage.java new file mode 100644 index 0000000..2a8e7bd --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementStorage.java @@ -0,0 +1,46 @@ +package com.javarush.task.task27.task2712.ad; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by ArchMage on 18.04.17. + */ +public class AdvertisementStorage { + private static AdvertisementStorage instance = new AdvertisementStorage(); + + // Часть 7 + // 1. Видео должно где-то храниться, пусть это будет список. + private final List videos = new ArrayList<>(); + + + // 3. В конструкторе класса добавим в список videos какие-то данные. + private AdvertisementStorage() { + Object someContent = new Object(); + videos.add(new Advertisement(someContent, "First Video", 5000, 100, 3 * 60)); // 3 min + videos.add(new Advertisement(someContent, "Second Video", 100, 10, 15 * 60)); //15 min + videos.add(new Advertisement(someContent, "Third Video", 400, 2, 10 * 60)); //10 min + } + // 2. Чтобы как-то работать с видео, создай публичные методы: + // 2.1. list() — который вернет список всех существующих доступных видео. + public List list(){ + return videos; + } + // 2.2. add(Advertisement advertisement) — который добавит новое видео в список videos. + public void add(Advertisement advertisement){ + videos.add(advertisement); + } + + + + public static AdvertisementStorage getInstance(){ + return instance; + + // Ленивую инициализацию делать нельзя. Валидатор ругается. + /*if (instance == null) { + return new AdvertisementStorage(); + } else { + return instance; + }*/ + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/NoVideoAvailableException.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/NoVideoAvailableException.java new file mode 100644 index 0000000..5aced5d --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/NoVideoAvailableException.java @@ -0,0 +1,11 @@ +package com.javarush.task.task27.task2712.ad; + +/** + * Created by ArchMage on 18.04.17. + */ + +// Часть 9 +// 1. Создадим unchecked исключение NoVideoAvailableException в пакете ad. + +public class NoVideoAvailableException extends RuntimeException { +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Cook.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Cook.java index 8d19c9c..e3f7271 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Cook.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Cook.java @@ -8,7 +8,7 @@ /** * Created by ArchMage on 17.04.17. */ -public class Cook implements Observer { +public class Cook extends Observable implements Observer { private String name; @@ -18,7 +18,9 @@ public Cook(String name) { @Override public void update(Observable o, Object arg) { - ConsoleHelper.writeMessage("Start cooking - " + arg); + ConsoleHelper.writeMessage("Start cooking - " + arg + ", cooking time " + ((Order) arg).getTotalCookingTime() + "min"); + setChanged(); + notifyObservers(arg); } @Override diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Dish.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Dish.java index 7f46511..ea4e09a 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Dish.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Dish.java @@ -6,11 +6,21 @@ * Created by ArchMage on 14.04.17. */ public enum Dish { - Fish, - Steak, - Soup, - Juice, - Water; + Fish(25), + Steak(30), + Soup(15), + Juice(5), + Water(3); + + private int duration; + + Dish(int i) { + duration = i; + } + + public int getDuration() { + return duration; + } public static String allDishesToString(){ /*if (values().length == 0) { diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Order.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Order.java index cdb3edd..05dd194 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Order.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Order.java @@ -23,4 +23,16 @@ public String toString() { if (dishes.isEmpty()) return ""; else return "Your order: " + dishes + " of " + tablet; } + + public int getTotalCookingTime(){ + int totalDureation = 0; + for (Dish entry : dishes){ + totalDureation += entry.getDuration(); + } + return totalDureation; + } + + public boolean isEmpty(){ + return (dishes == null || dishes.size() == 0); + } } diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Waiter.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Waiter.java new file mode 100644 index 0000000..ced8c9c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Waiter.java @@ -0,0 +1,18 @@ +package com.javarush.task.task27.task2712.kitchen; + +import com.javarush.task.task27.task2712.ConsoleHelper; + +import java.util.Observable; +import java.util.Observer; + +/** + * Created by ArchMage on 18.04.17. + */ +public class Waiter implements Observer { + + @Override + public void update(Observable o, Object arg) { + ConsoleHelper.writeMessage(arg + " was cooked by " + o); + } + +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" index f85338e..d833ce3 100644 --- "a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -1,162 +1,179 @@ -taskKey="com.javarush.task.task27.task2712.big04" +taskKey="com.javarush.task.task27.task2712.big09" + +Ресторан(9) + +Нам понадобится исключение, которое поможет обработать ситуацию, если у нас не будет получаться подобрать рекламные ролики. + +1. Создадим unchecked исключение NoVideoAvailableException в пакете ad. + +2. Разберем подробно метод void processVideos() в AdvertisementManager. +2.1. Удаляем из него вывод в консоль "calling processVideos method" +Метод должен: +2.2. Подобрать список видео из доступных, просмотр которых обеспечивает максимальную выгоду. (Пока делать не нужно, сделаем позже). +2.3. Если нет рекламных видео, которые можно показать посетителю, то бросить NoVideoAvailableException, +которое перехватить в оптимальном месте (подумать, где это место) и с уровнем Level.INFO логировать фразу +"No video is available for the order " + order +2.4. Отобразить все рекламные ролики, отобранные для показа, в порядке уменьшения стоимости показа одного рекламного ролика +в копейках. Вторичная сортировка - по увеличению стоимости показа одной секунды рекламного ролика в тысячных частях копейки +Используйте метод Collections.sort +(Тоже пока делать не нужно, сделаем позже). +Пример для заказа [Water]: +First Video is displaying... 50, 277 +где First Video - название рекламного ролика +где 50 - стоимость показа одного рекламного ролика в копейках +где 277 - стоимость показа одной секунды рекламного ролика в тысячных частях копейки (равно 0.277 коп) +Используйте методы из класса Advertisement. +2.5. В классе Advertisement создайте метод void revalidate(). Этот метод должен: +2.5.1. Бросать UnsupportedOperationException, если количество показов не положительное число. +2.5.2. Уменьшать количество показов. -Ресторан(4) -Что мы имеем? Повар приготовил блюда, пора их уносить, а официант не знает об этом. -Нужно уведомить официанта, что пора забирать заказ с кухни. -Ситуация аналогична предыдущему заданию, поэтому снова будем использовать паттерн Observer. +Требования: +1. В случае, если список видео для воспроизведения пуст, должно быть брошено исключение NoVideoAvailableException из метода processVideos. +2. Исключение NoVideoAvailableException должно быть перехвачено и в лог должна быть записана строка об отсутствии видео для данного заказа (пример в условии). +3. Класс NoVideoAvailableException в пакете ad должен быть потомком класса RuntimeException. +4. Метод revalidate должен быть реализован в соответствии с условием задачи. -1. Создадим класс Waiter(Официант) в пакете kitchen, он будет относить заказы назад к столику. Официант будет безымянным. -2. Cook(Повар) готовит заказы, а Waiter их обрабатывает. Расставь правильно Observer и Observable между Waiter и Cook. +Ресторан(8) -3. Метод void update будет выводить в консоль сообщение о том, какой заказ и кем был приготовлен: -order + " was cooked by " + cook +Пришло время описать функционал класса AdvertisementManager. +Но для начала нам понадобятся некоторые методы в классе Advertisement. -4. В классе наследнике Observable перед отправкой заказа сделаем следующее: -4.1. Установим флаг setChanged() -4.2. Отправим наблюдателю заказ - notifyObservers(order); +1. В классе Advertisement создай поле long amountPerOneDisplaying. +Оно должно равняться стоимости одного показа рекламного объявления в копейках (initialAmount/hits). +Присвой значение полю в конструкторе. -5. Пишем main. -Для объекта Observable добавляем свой объект Observer. См. п.2 и описание паттерна в wikipedia -Называем повара, имя не влияет на тесты. В моем варианте - это Amigo :) +2. В классе Advertisement создай геттеры для полей name, duration и amountPerOneDisplaying. -Сверим выводы в консоль. Пример моего вывода: -Your order: [Water] of Tablet{number=5} -Start cooking - Your order: [Water] of Tablet{number=5} -Your order: [Water] of Tablet{number=5} was cooked by Amigo +3. Определим необходимые данные для объекта AdvertisementManager - это время выполнения заказа поваром. +Т.к. продолжительность видео у нас хранится в секундах, то и и время выполнения заказа тоже будем принимать в секундах. +В классе AdvertisementManager создай конструктор, который принимает один параметр - int timeSeconds. +Создай соответствующее поле и сохраните это значение в него. +4. AdvertisementManager выполняет только одно единственное действие - обрабатывает рекламное видео. +Поэтому создайте единственный публичный метод void processVideos(), его функционал опишем в следующем задании. +А пока выведем в консоль "calling processVideos method" -Требования: -1. Класс Waiter должен реализовывать интерфейс Observer. -2. Класс Cook должен быть потомком класса Observable. -3. В методе update класса Cook должен быть вызван метод setChanged. -4. В методе update класса Cook должен быть вызван метод notifyObservers с текущим заказом в качестве параметра. -5. Метод update в классе Waiter должен выводить на экран строку форматированную согласно заданию. -6. В методе main класса Restaurant должен быть создан новый официант и добавлен повару в качестве наблюдателя с помощью метода addObserver. +5. Чтобы тестировать данную функциональность, нужно добавить вызов processVideos метода у AdvertisementManager. +Очевидно, что этот метод должен вызываться во время создания заказа, а точнее - в параллельном режиме. +Заказ готовится в то время, как видео смотрится. +Добавьте вызов метода processVideos() в нужное место. +P.S. Не забудь что время приготовления заказа считается в минутах, а время показа рекламы в секундах! -Ресторан(3) -Сейчас мы можем создавать заказы. Давай сделаем так, чтобы они автоматически поступали к повару. -Есть много различных способов реализации данной функциональности. -Почитай про паттерн Observer - http://en.wikipedia.org/wiki/Observer_pattern -Он уже реализован в java, и мы его будем использовать. -1. Создадим класс Cook(Повар) в пакете kitchen, он будет готовить. Пусть в конструкторе приходит его имя, которое выводится методом toString. +Ресторан(7) -2. Tablet создает заказы, а Cook их обрабатывает. Расставь правильно Observer и Observable между Tablet и Cook. +При выборе, с какого класса начать, старайся найти тот, который используют другие, и который сам ничего не использует. +В нашем случае - это хранилище рекламных роликов (AdvertisementStorage). +Мы решили, что оно будет единственным в ресторане и сделали его синглтоном. +Опишем его. -3. Метод void update(Observable observable, Object arg), который необходимо реализовать, принимает два параметра. --observable - объект, который отправил нам значение --arg - само значение, в нашем случае - это объект Order -На данном этапе мы будем лишь имитировать обработку и выведем в консоль "Start cooking - " + order +1. Видео должно где-то храниться, пусть это будет список. +Создадим поле videos и инициализируем его пустым листом. +Подумай, должно ли поле videos иметь возможность менять свое значение? -3. Пишем main. -Для объекта Observable добавляем свой объект Observer. См. п.2 и описание паттерна в wikipedia -Называем повара, имя не влияет на тесты. В моем варианте - это Amigo : ) +2. Чтобы как-то работать с видео, создай публичные методы: +2.1. list() - который вернет список всех существующих доступных видео. +2.2. add(Advertisement advertisement) - который добавит новое видео в список videos. -Сверим выводы в консоль. Пример моего вывода: -Your order: [Soup] of Tablet{number=5} -Start cooking - Your order: [Soup] of Tablet{number=5} - -4. Не забудь сразу после создания заказа и вывода информации о нем в консоль (найдите это место в коде) сделать следующее: -4.1. Установить флаг setChanged() -4.2. Отправить обсерверу заказ - notifyObservers(order); +3. В конструкторе класса добавим в список videos какие-то данные. У меня это: +Object someContent = new Object(); +new Advertisement(someContent, "First Video", 5000, 100, 3 * 60) // 3 min +new Advertisement(someContent, "Second Video", 100, 10, 15 * 60) //15 min +new Advertisement(someContent, "Third Video", 400, 2, 10 * 60) //10 min -5. Также внесем небольшое изменение. Сделай так чтобы метод createOrder возвращал текущий заказ или null, если заказ создать не удалось. +4. В AdvertisementManager создадим final поле-ссылку на экземпляр AdvertisementStorage и назовем ее storage. +Не забудь инициализировать созданное поле! -Ресторан(2) +Ресторан(6) -1. Мы много работаем с консолью. Пора создать единую точку взаимодействия. -Создай класс ConsoleHelper с единственным BufferedReader, через который будем работать с консолью. -Запомни, этот класс не хранит никаких данных и состояний, поэтому все методы будут статическими. -Создай в нем три метода: --writeMessage(String message) - для вывода message в консоль --String readString() - для чтения строки с консоли --List getAllDishesForOrder() - просит пользователя выбрать блюдо и добавляет его в список. -Выведи список всех блюд и попроси пользователя ввести строку - название блюда. -Введенное 'exit' означает завершение заказа. -В случае, если введенное блюдо не представлено в меню, выведи сообщение о том, что такого блюда нет и продолжи формирование заказа. -Исключения ввода-вывода бросай выше, на этом уровне не понятно, что с ними делать. +Заказ создается, потом готовится поваром, а после этого относится посетителю. К тому же считается время выполнения заказа. +Будем считать, что первая часть задания выполнена. +Перейдем ко второй - пока заказ готовится, на планшете должна показываться реклама. +Определим, что такое реклама. -2. Сделай рефакторинг - работа с консолью должна быть только через класс ConsoleHelper. +Реклама - это видео определенной продолжительности. Также известно, что кто-то оплатил количество показов. +Будем считать, что у нас известно количество оплаченных показов, общая стоимость всех показов и сам рекламный ролик. -3. Вернемся к классу Order: в нем есть ссылка на планшет, и еще есть список выбранных блюд. -Инициализируй список dishes в конструкторе, вызвав метод getAllDishesForOrder из ConsoleHelper. +1. Для связанного с рекламой функционала создадим пакет ad. -4. Перепиши метод toString в классе Order. Пусть он возвращает пустую строку, если нет блюд в заказе, иначе -вывод должен быть аналогичным примеру в порядке добавления блюд. Используй ConsoleHelper. -Также измени метод toString в классе Tablet (внутри класса Tablet нажмите Alt+Insert -> toString()). -Пример: -Your order: [Juice, Fish] of Tablet{number=5} +2. Создадим класс Advertisement(Рекламное объявление) в пакете ad, у которого будут следующие поля: +Object content - видео +String name - имя/название +long initialAmount - начальная сумма, стоимость рекламы в копейках. Используем long, чтобы избежать проблем с округлением +int hits - количество оплаченных показов +int duration - продолжительность в секундах +Модификаторы доступа расставь самостоятельно. -5. У нас все завязано на работу с консолью. Однако, при возникновении исключений, наше приложение умрет. -Чтобы узнать причину - добавим в Tablet статическое поле logger типа java.util.logging.Logger, инициализированное именем класса (Logger.getLogger(Tablet.class.getName())). +3. В классе Advertisement создадим конструктор с порядком аргументов, соответствующим перечисленной последовательности всех полей класса -6. В методе createOrder класса Tablet обработаем исключения ввода-вывода. -Запишем в лог "Console is unavailable.". Уровень лога - SEVERE - это самый серьезный уровень, мы не можем работать. -Также в методе createOrder класса Tablet должен быть создан новый заказ. +4. В этом же пакете создадим еще два класса: +AdvertisementStorage - хранилище рекламных роликов. +AdvertisementManager - у каждого планшета будет свой объект менеджера, +который будет подбирать оптимальный набор роликов и их последовательность для каждого заказа. +Он также будет взаимодействовать с плеером и отображать ролики. -7. Надо начинать тестировать наше приложение. -Добавьте в main создание планшета и создание заказа - new Tablet(5).createOrder(); +5. Так как хранилище рекламных роликов AdvertisementStorage единственное для всего ресторана, то сделаем его синглтоном. -Ресторан(1) +Ресторан(5) -Давай напишем программу для автоматизации работы в ресторане. +Сейчас повар готовит блюда моментально. На самом деле приготовление занимает какое-то время. +Нам нужно вычислить время приготовления всего заказа, чтобы потом подбирать рекламные ролики для этого времени. -Пусть задание сформулировано так - директор ресторана хочет, чтобы: -1) на каждом столике лежал планшет, через который можно было бы сделать заказ; -2) пока заказ готовится, на планшете показывалась реклама; -3) в конце рабочего дня была возможность посмотреть различную статистику: -а) загрузки повара; -б) сумму выручки за заказы; -в) сумму выручки за показы рекламы. +1. Предположим, что нам известно время приготовления каждого блюда в минутах. Захардкодим его в классе Dish. +1.1. Измени создание элементов enum - Fish(25), Steak(30), Soup(15), Juice(5), Water(3); +1.2. Создай поле private int duration с геттером. +Чтобы создать геттер, нажмите Alt+Insert и выберите пункт Getter. Далее выберите имя поля и нажмите OK(Enter). -Мы будем разрабатывать ядро, без UI. UI ты потом сможешь дописать самостоятельно, сейчас ограничимся консольным интерфейсом. -Также мы часть данных захардкодим, ты потом сможешь прикрутить БД, и работать с ней. +2. Добавим возможность посчитать продолжительность приготовления всего заказа. +Куда его добавить??? +2.1. Если в класс Cook, то повар сможет считать продолжительность приготовления заказа. +Чтобы другие классы могли получить эту информацию, необходимо будет получить доступ к объекту Cook. +2.2. Если в класс Order, то имея доступ к заказу всегда можно узнать продолжительность приготовления. +2.3. Выбери правильное место из п.2.1. и п.2.2. и добавьте метод pubic int getTotalCookingTime(), +который посчитает суммарное время приготовления всех блюд в заказе. +2.4. Добавим нашему повару вывод в консоль этой информации. Пусть теперь выводится аналогичное сообщение: +Start cooking - Your order: [Soup, Juice, Water] of Tablet{number=5}, cooking time 23min -Выделим несколько фич, которые будем реализовывать: +Наведем красоту: +3. Запустим приложение и сразу введем 'exit'. Вывод получился не очень красивым. +Сделай так, чтобы если в заказе нет блюд, он не отправлялся повару. Найди это место и реализуйте логику. +В классе Order создай вспомогательный метод public boolean isEmpty(), который будет определять, есть ли какие либо блюда в заказе. -Первая: --созданный посетителем заказ будет автоматически поступать к повару; --повар будет готовить его какое-то время и отмечать приготовленным; --после этого официант будет относить его. -Вторая: --подобрать нужные рекламные ролики из списка оплаченных; --отображение рекламных роликов во время приготовления заказа; --максимизировать прибыль от показа рекламы. -Третья: --подсчет статистики; --отображение статистики директору. +Ресторан(4) -Начнем с первой фичи - автоматизация обработки заказа: +Что мы имеем? Повар приготовил блюда, пора их уносить, а официант не знает об этом. +Нужно уведомить официанта, что пора забирать заказ с кухни. +Ситуация аналогична предыдущему заданию, поэтому снова будем использовать паттерн Observer. -Итак.. -1. Создай класс Restaurant с методом main. +1. Создадим класс Waiter(Официант) в пакете kitchen, он будет относить заказы назад к столику. Официант будет безымянным. -2. Начнем с планшета, создадим класс Tablet, в котором создадим поле final int number - это номер планшета, -чтобы можно было однозначно установить, откуда поступил заказ. Номер планшета должен инициализироваться в конструкторе переданным параметром. +2. Cook(Повар) готовит заказы, а Waiter их обрабатывает. Расставь правильно Observer и Observable между Waiter и Cook. -3. В классе Tablet создадим метод public void createOrder(), который будет создавать заказ из тех блюд, которые выберет пользователь. -Для этого создадим класс Order, который поместим в пакет kitchen. +3. Метод void update будет выводить в консоль сообщение о том, какой заказ и кем был приготовлен: +order + " was cooked by " + cook -4. В классе Order (заказ) должна быть информация, относящаяся к списку выбранных пользователем блюд. -Т.е. где-то должен быть список всех блюд, и должен быть список выбранных блюд в классе Order. -В классе Order нужны поля private final int number и protected List dishes. -Конструктор должен принимать один параметр типа Tablet и инициализировать поле tablet. +4. В классе наследнике Observable перед отправкой заказа сделаем следующее: +4.1. Установим флаг setChanged() +4.2. Отправим наблюдателю заказ - notifyObservers(order); -5. Нам нужен класс Dish(Блюдо), создадим его в пакете kitchen. Пусть это будет enum со списком блюд: Fish, Steak, Soup, Juice, Water. +5. Пишем main. +Для объекта Observable добавляем свой объект Observer. См. п.2 и описание паттерна в wikipedia +Называем повара, имя не влияет на тесты. В моем варианте - это Amigo :) -6. Чтобы пользователь мог выбрать себе блюда, нужно их все ему отобразить. Для этого в Dish создай метод -public static String allDishesToString(), который сформирует строку из всех блюд. -Пример: "Fish, Steak, Soup, Juice, Water". Формируй строку динамически. +Сверим выводы в консоль. Пример моего вывода: +Your order: [Water] of Tablet{number=5} +Start cooking - Your order: [Water] of Tablet{number=5} +Your order: [Water] of Tablet{number=5} was cooked by Amigo From 0f8d968be9d0adb5f1d5d858539827d10fd512e5 Mon Sep 17 00:00:00 2001 From: PeucT Date: Mon, 24 Apr 2017 17:02:56 +0400 Subject: [PATCH 30/51] Level 29 big task. 2712. Parts 9, 10, 11 --- .../javarush/task/task27/task2712/Tablet.java | 9 +- .../task27/task2712/ad/Advertisement.java | 9 + .../task2712/ad/AdvertisementManager.java | 96 ++++++++- .../task2712/ad/AdvertisementStorage.java | 11 +- .../task/task27/task2712/kitchen/Dish.java | 3 +- .../task2712/statistic/StatisticManager.java | 22 ++ .../statistic/event/EventDataRow.java | 7 + ...\273\320\276\320\262\320\270\320\265.jrtc" | 202 ++++++++++-------- 8 files changed, 259 insertions(+), 100 deletions(-) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/StatisticManager.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/EventDataRow.java diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Tablet.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Tablet.java index 5838425..cf63083 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Tablet.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Tablet.java @@ -1,6 +1,7 @@ package com.javarush.task.task27.task2712; import com.javarush.task.task27.task2712.ad.AdvertisementManager; +import com.javarush.task.task27.task2712.ad.NoVideoAvailableException; import com.javarush.task.task27.task2712.kitchen.Order; @@ -37,10 +38,16 @@ public Order createOrder(){ // Заказ готовится в то время, как видео смотрится. // Добавьте вызов метода processVideos() в нужное место. - new AdvertisementManager(order.getTotalCookingTime() * 60).processVideos(); + try { + new AdvertisementManager(order.getTotalCookingTime() * 60).processVideos(); + } + catch (NoVideoAvailableException e){ + logger.log(Level.INFO, "No video is available for the order " + order.toString()); + } } return order; } + catch (IOException e){ logger.log(Level.SEVERE, "Console is unavailable."); return null; diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/Advertisement.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/Advertisement.java index 40d306c..aee579a 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/Advertisement.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/Advertisement.java @@ -30,6 +30,10 @@ public String getName() { return name; } + public int getHits() { + return hits; + } + public int getDuration() { return duration; } @@ -37,4 +41,9 @@ public int getDuration() { public long getAmountPerOneDisplaying() { return amountPerOneDisplaying; } + + public void revalidate(){ + if (hits <= 0) { throw new UnsupportedOperationException(); } + hits--; + } } diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementManager.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementManager.java index 7ad857c..4f7d56f 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementManager.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementManager.java @@ -2,6 +2,11 @@ import com.javarush.task.task27.task2712.ConsoleHelper; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + /** * Created by ArchMage on 18.04.17. */ @@ -13,6 +18,7 @@ public class AdvertisementManager { // В классе AdvertisementManager создай конструктор, который принимает один параметр — int timeSeconds. // Создай соответствующее поле и сохраните это значение в него. private int timeSeconds; + private List videosList; public AdvertisementManager(int timeSeconds) { this.timeSeconds = timeSeconds; @@ -21,7 +27,93 @@ public AdvertisementManager(int timeSeconds) { // 4. AdvertisementManager выполняет только одно единственное действие — обрабатывает рекламное видео. // Поэтому создайте единственный публичный метод void processVideos(), его функционал опишем в следующем задании. // А пока выведем в консоль «calling processVideos method» - public void processVideos(){ - ConsoleHelper.writeMessage("calling processVideos method"); + + //Часть 9 + //2.2. Подобрать список видео из доступных, просмотр которых обеспечивает максимальную выгоду. + //2.4. Отобразить все рекламные ролики, отобранные для показа, в порядке уменьшения стоимости показа + // одного рекламного ролика в копейках. Вторичная сортировка — по увеличению стоимости показа одной секунды + // рекламного ролика в тысячных частях копейки. + + public void processVideos() throws NoVideoAvailableException{ + List availableVideos = new ArrayList(); + for (Advertisement entry: storage.list()){ + if (entry.getHits() > 0) { availableVideos.add(entry); } + } + //Collections.copy(storage.list(), availableVideos); + if (availableVideos == null || availableVideos.size() == 0) { + throw new NoVideoAvailableException(); + } else videoFitting(availableVideos, new ArrayList()); + + if (videosList == null || videosList.size() == 0) { + throw new NoVideoAvailableException(); + } + + Collections.sort(videosList, new Comparator() { + @Override + public int compare(Advertisement o1, Advertisement o2) { + if (Long.compare(o1.getAmountPerOneDisplaying(), o2.getAmountPerOneDisplaying()) == 0){ + return Long.compare(o1.getAmountPerOneDisplaying() * 1000 / o1.duration, o2.getAmountPerOneDisplaying() * 1000 / o2.duration); + }else return Long.compare(o2.getAmountPerOneDisplaying(), o1.getAmountPerOneDisplaying()); + } + }); + + for (Advertisement entry: videosList) { + ConsoleHelper.writeMessage(String.format("%s is displaying... %d, %d", + entry.getName(), + entry.getAmountPerOneDisplaying(), + entry.getAmountPerOneDisplaying() * 1000 / entry.getDuration())); + entry.revalidate(); + } + } + + private void videoFitting(List availableVideos, List fittingList){ + //List newAvailableList = new ArrayList(); + boolean isAlreadyMadeAdd = false; + for (int i = 0; i < availableVideos.size(); i++){ + if (isAlreadyMadeAdd) { + fittingList.remove(fittingList.size() - 1); + isAlreadyMadeAdd = false; + } + if (totalDuration(fittingList) + availableVideos.get(i).duration <= timeSeconds) { + fittingList.add(availableVideos.get(i)); + isAlreadyMadeAdd = true; + ArrayList newAvailableList = new ArrayList(availableVideos); + newAvailableList.remove(i); + videoFitting(newAvailableList, fittingList); + } + } + if (isAlreadyMadeAdd) { + fittingList.remove(fittingList.size() - 1); + isAlreadyMadeAdd = false; + } + if (totalAmount(videosList) < totalAmount(fittingList)) { + videosList = new ArrayList(fittingList); + } else if (totalAmount(videosList) == totalAmount(fittingList)) { + if (totalDuration(videosList) < totalDuration(fittingList)) { + videosList = new ArrayList(fittingList); + } else if (totalDuration(videosList) == totalDuration(fittingList)) { + if (videosList.size() > fittingList.size()) { + videosList = new ArrayList(fittingList); + } + } + } + } + + private static int totalDuration(List list){ + if (list == null || list.size() == 0) { return 0; } + int duration = 0; + for (Advertisement entry: list){ + duration += entry.duration; + } + return duration; + } + + private static long totalAmount(List list){ + if (list == null || list.size() == 0) { return 0; } + long amount = 0; + for (Advertisement entry: list){ + amount += entry.getAmountPerOneDisplaying(); + } + return amount; } } diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementStorage.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementStorage.java index 2a8e7bd..09825c7 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementStorage.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementStorage.java @@ -17,9 +17,16 @@ public class AdvertisementStorage { // 3. В конструкторе класса добавим в список videos какие-то данные. private AdvertisementStorage() { Object someContent = new Object(); - videos.add(new Advertisement(someContent, "First Video", 5000, 100, 3 * 60)); // 3 min + /*videos.add(new Advertisement(someContent, "First Video", 5000, 100, 3 * 60)); // 3 min videos.add(new Advertisement(someContent, "Second Video", 100, 10, 15 * 60)); //15 min - videos.add(new Advertisement(someContent, "Third Video", 400, 2, 10 * 60)); //10 min + videos.add(new Advertisement(someContent, "Third Video", 400, 2, 10 * 60)); //10 min*/ + videos.add(new Advertisement(someContent, "First Video", 100, 1, 100)); + videos.add(new Advertisement(someContent, "Second Video", 120, 1, 120)); + videos.add(new Advertisement(someContent, "Third Video", 400, 1, 400)); + videos.add(new Advertisement(someContent, "Fourth Video", 360, 1, 359)); + videos.add(new Advertisement(someContent, "FourthMoreMoney Video", 360, 1, 360)); + videos.add(new Advertisement(someContent, "Fifth Video", 30, 1, 30)); + videos.add(new Advertisement(someContent, "Sixth Video", 45, 1, 45)); } // 2. Чтобы как-то работать с видео, создай публичные методы: // 2.1. list() — который вернет список всех существующих доступных видео. diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Dish.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Dish.java index ea4e09a..01d6a5d 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Dish.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Dish.java @@ -6,7 +6,8 @@ * Created by ArchMage on 14.04.17. */ public enum Dish { - Fish(25), + Fish(11), + //Fish(25), Steak(30), Soup(15), Juice(5), diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/StatisticManager.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/StatisticManager.java new file mode 100644 index 0000000..a8a1dd5 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/StatisticManager.java @@ -0,0 +1,22 @@ +package com.javarush.task.task27.task2712.statistic; + +import com.javarush.task.task27.task2712.statistic.event.EventDataRow; + +/** + * Created by ArchMage on 24.04.17. + */ +public class StatisticManager { + private StatisticManager instance = new StatisticManager(); + + private StatisticManager(){ + + } + + public StatisticManager getInstance() { + return instance; + } + + public void register(EventDataRow data){ + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/EventDataRow.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/EventDataRow.java new file mode 100644 index 0000000..f3e861e --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/EventDataRow.java @@ -0,0 +1,7 @@ +package com.javarush.task.task27.task2712.statistic.event; + +/** + * Created by ArchMage on 24.04.17. + */ +public interface EventDataRow { +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" index d833ce3..0c6fe95 100644 --- "a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -1,4 +1,111 @@ -taskKey="com.javarush.task.task27.task2712.big09" +taskKey="com.javarush.task.task27.task2712.big12" + +Ресторан(12) + +У нас выделяются несколько событий: +*повар приготовил заказ +*выбрали набор видео-роликов для заказа +*нет ни одного видео-ролика, который можно показать во время приготовления заказа + +Это постоянные данные, поэтому для их хранения подходит энам. + +1. В пакете event создай enum EventType {COOKED_ORDER, SELECTED_VIDEOS, NO_AVAILABLE_VIDEO} + +2. В пакете event создай три класса, соответствующих значениям энама. Они будут(должны) представлять собой события. +Мы будем регистрировать их экземпляры в хранилище. +Имена классов с параметрами для конструкторов: +2.1. CookedOrderEventDataRow(String tabletName, String cookName, int cookingTimeSeconds, List cookingDishs) +где - tabletName - имя планшета +cookName - имя повара +cookingTimeSeconds - время приготовления заказа в секундах +cookingDishs - список блюд для приготовления +2.2. NoAvailableVideoEventDataRow(int totalDuration) +totalDuration - время приготовления заказа в секундах +2.3. VideoSelectedEventDataRow(List optimalVideoSet, long amount, int totalDuration) +optimalVideoSet - список видео-роликов, отобранных для показа +amount - сумма денег в копейках +totalDuration - общая продолжительность показа отобранных рекламных роликов +3. В классы, созданные в п.2., добавьте поле Date currentDate, которое проинициализируй в конструкторе текущей датой. + + +Требования: +1. В пакете event должен быть создан enum EventType с элементами {COOKED_ORDER, SELECTED_VIDEOS, NO_AVAILABLE_VIDEO}. +2. В пакете event должен быть создан класс CookedOrderEventDataRow реализующий интерфейс EventDataRow с конструктором и полями описанными в условии. +3. В пакете event должен быть создан класс NoAvailableVideoEventDataRow реализующий интерфейс EventDataRow с конструктором и полями описанными в условии. +4. В пакете event должен быть создан класс VideoSelectedEventDataRow реализующий интерфейс EventDataRow с конструктором и полями описанными в условии. + + +Ресторан(11) + +Мы реализовали первые две фичи из трех. Напомню, первой была автоматизация приготовления заказа, +второй - подбор рекламных роликов, а третья - статистика для директора. Собственно, к ней мы и добрались. + +Нам нужно будет реализовать следующую функциональность: +1) подсчет статистики +2) отображение статистики директору + +Попробуем определиться с последовательностью действий. Чтобы отображать данные, сначала нужно их откуда-то получить. + +Есть два подхода: +ПЕРВЫЙ - применяется, когда сложно получить реальные данные, либо когда другой человек работает над получением данных: +1. захардкодить данные в приложении +2. отобразить хардкоженную статистику +3. сделать получение реальных данных - реальную статистику (интеграция с чужим кодом) + +ВТОРОЙ: +1. сделать получение реальных данных - реальную статистику +2. отобразить статистику + +Т.к. мы сами реализовываем данную функциональность, и статистика у нас не сложная, то выберем второй подход. +Начнем с получения реальных данных - реальной статистики. + +Идея такая: +Есть хранилище событий. +Когда у нас случается событие, то мы будем регистрировать это событие в хранилище. +На запрос директора мы будем фильтровать события из хранилища, вычислять необходимые данные и отображать их. + +Для начала нам нужно несколько классов. +1. Создадим пакет statistic, в котором создадим класс StatisticManager. С его помощью будем регистрировать события в хранилище. +2. У нас должно быть одно хранилище с одной точкой входа. Поэтому сделаем StatisticManager синглтоном. +3. Внутри пакета statistic создадим вложенный пакет event, в котором будут храниться классы, связанные с событиями. +4. Создадим в пакете event интерфейс EventDataRow. На данный момент он является интерфейсом-маркером, +т.к. не содержит методов, и по нему мы определяем, является ли переданный объект событием или нет. +5. В StatisticManager создадим публичный метод void register(EventDataRow data), который будет регистрировать событие в хранилище. +Мы вернемся к реализации позднее. + + + +Ресторан(10) + +Рекурсию используют тогда, когда алгоритм решения задачи совпадает с алгоритмом решения подзадачи (части). +У нас как раз такой случай. Нам нужно сделать полный перебор всех вариантов и выбрать из них лучший. + +Напомню, рекурсия пишется по следующему принципу: +а) условие выхода/окончания рекурсии +б) условие продолжения - вызов самой себя с набором параметров предыдущего шага. +В любое время ты можешь почитать в инете подробную информацию по написанию рекурсии. + +Текущее задание - реализовать п.2.2 предыдущего задания с помощью рекурсии. +(подобрать список видео из доступных, просмотр которых обеспечивает максимальную выгоду) +Рекурсивный метод должен выбрать набор рекламных роликов, которые будут показаны посетителю. + +Этот набор должен удовлетворять следующим требованиям: +1) сумма денег, полученная от показов, должна быть максимальной из всех возможных вариантов +2) общее время показа рекламных роликов НЕ должно превышать время приготовления блюд для текущего заказа; +3) для одного заказа любой видео-ролик показывается не более одного раза; +4) если существует несколько вариантов набора видео-роликов с одинаковой суммой денег, полученной от показов, то: +4.1) выбрать тот вариант, у которого суммарное время максимальное; +4.2) если суммарное время у этих вариантов одинаковое, то выбрать вариант с минимальным количеством роликов; +5) количество показов у любого рекламного ролика из набора - положительное число. + +При локальном тестировании учитывайте, что необходимо отобразить все рекламные ролики, отобранные для показа, +в порядке уменьшения стоимости показа одного рекламного ролика в копейках. + +Также не забудь реализовать п.2.4 из предыдущего задания (вывести на экран все подходящие ролики). + +Для каждого показанного видео-ролика должен быть вызван метод revalidate(). + + Ресторан(9) @@ -28,12 +135,6 @@ First Video is displaying... 50, 277 2.5.2. Уменьшать количество показов. -Требования: -1. В случае, если список видео для воспроизведения пуст, должно быть брошено исключение NoVideoAvailableException из метода processVideos. -2. Исключение NoVideoAvailableException должно быть перехвачено и в лог должна быть записана строка об отсутствии видео для данного заказа (пример в условии). -3. Класс NoVideoAvailableException в пакете ad должен быть потомком класса RuntimeException. -4. Метод revalidate должен быть реализован в соответствии с условием задачи. - Ресторан(8) @@ -90,90 +191,3 @@ new Advertisement(someContent, "Third Video", 400, 2, 10 * 60) //10 min -Ресторан(6) - -Заказ создается, потом готовится поваром, а после этого относится посетителю. К тому же считается время выполнения заказа. -Будем считать, что первая часть задания выполнена. -Перейдем ко второй - пока заказ готовится, на планшете должна показываться реклама. -Определим, что такое реклама. - -Реклама - это видео определенной продолжительности. Также известно, что кто-то оплатил количество показов. -Будем считать, что у нас известно количество оплаченных показов, общая стоимость всех показов и сам рекламный ролик. - -1. Для связанного с рекламой функционала создадим пакет ad. - -2. Создадим класс Advertisement(Рекламное объявление) в пакете ad, у которого будут следующие поля: -Object content - видео -String name - имя/название -long initialAmount - начальная сумма, стоимость рекламы в копейках. Используем long, чтобы избежать проблем с округлением -int hits - количество оплаченных показов -int duration - продолжительность в секундах -Модификаторы доступа расставь самостоятельно. - -3. В классе Advertisement создадим конструктор с порядком аргументов, соответствующим перечисленной последовательности всех полей класса - -4. В этом же пакете создадим еще два класса: -AdvertisementStorage - хранилище рекламных роликов. -AdvertisementManager - у каждого планшета будет свой объект менеджера, -который будет подбирать оптимальный набор роликов и их последовательность для каждого заказа. -Он также будет взаимодействовать с плеером и отображать ролики. - -5. Так как хранилище рекламных роликов AdvertisementStorage единственное для всего ресторана, то сделаем его синглтоном. - - - -Ресторан(5) - -Сейчас повар готовит блюда моментально. На самом деле приготовление занимает какое-то время. -Нам нужно вычислить время приготовления всего заказа, чтобы потом подбирать рекламные ролики для этого времени. - -1. Предположим, что нам известно время приготовления каждого блюда в минутах. Захардкодим его в классе Dish. -1.1. Измени создание элементов enum - Fish(25), Steak(30), Soup(15), Juice(5), Water(3); -1.2. Создай поле private int duration с геттером. -Чтобы создать геттер, нажмите Alt+Insert и выберите пункт Getter. Далее выберите имя поля и нажмите OK(Enter). - -2. Добавим возможность посчитать продолжительность приготовления всего заказа. -Куда его добавить??? -2.1. Если в класс Cook, то повар сможет считать продолжительность приготовления заказа. -Чтобы другие классы могли получить эту информацию, необходимо будет получить доступ к объекту Cook. -2.2. Если в класс Order, то имея доступ к заказу всегда можно узнать продолжительность приготовления. -2.3. Выбери правильное место из п.2.1. и п.2.2. и добавьте метод pubic int getTotalCookingTime(), -который посчитает суммарное время приготовления всех блюд в заказе. -2.4. Добавим нашему повару вывод в консоль этой информации. Пусть теперь выводится аналогичное сообщение: -Start cooking - Your order: [Soup, Juice, Water] of Tablet{number=5}, cooking time 23min - -Наведем красоту: -3. Запустим приложение и сразу введем 'exit'. Вывод получился не очень красивым. -Сделай так, чтобы если в заказе нет блюд, он не отправлялся повару. Найди это место и реализуйте логику. -В классе Order создай вспомогательный метод public boolean isEmpty(), который будет определять, есть ли какие либо блюда в заказе. - - - -Ресторан(4) - -Что мы имеем? Повар приготовил блюда, пора их уносить, а официант не знает об этом. -Нужно уведомить официанта, что пора забирать заказ с кухни. -Ситуация аналогична предыдущему заданию, поэтому снова будем использовать паттерн Observer. - -1. Создадим класс Waiter(Официант) в пакете kitchen, он будет относить заказы назад к столику. Официант будет безымянным. - -2. Cook(Повар) готовит заказы, а Waiter их обрабатывает. Расставь правильно Observer и Observable между Waiter и Cook. - -3. Метод void update будет выводить в консоль сообщение о том, какой заказ и кем был приготовлен: -order + " was cooked by " + cook - -4. В классе наследнике Observable перед отправкой заказа сделаем следующее: -4.1. Установим флаг setChanged() -4.2. Отправим наблюдателю заказ - notifyObservers(order); - -5. Пишем main. -Для объекта Observable добавляем свой объект Observer. См. п.2 и описание паттерна в wikipedia -Называем повара, имя не влияет на тесты. В моем варианте - это Amigo :) - -Сверим выводы в консоль. Пример моего вывода: -Your order: [Water] of Tablet{number=5} -Start cooking - Your order: [Water] of Tablet{number=5} -Your order: [Water] of Tablet{number=5} was cooked by Amigo - - - From dc89df151c7be2b62b9f43ec187c742676559871 Mon Sep 17 00:00:00 2001 From: PeucT Date: Tue, 25 Apr 2017 18:01:50 +0400 Subject: [PATCH 31/51] Level 29, big task 2712. Parts up to 16. --- .../task/task27/task2712/DirectorTablet.java | 39 +++ .../task/task27/task2712/Restaurant.java | 8 + .../task2712/ad/AdvertisementManager.java | 8 + .../task2712/ad/AdvertisementStorage.java | 17 +- .../task/task27/task2712/kitchen/Cook.java | 7 + .../task/task27/task2712/kitchen/Dish.java | 4 +- .../task/task27/task2712/kitchen/Order.java | 5 + .../task2712/statistic/StatisticManager.java | 95 ++++++- .../event/CookedOrderEventDataRow.java | 44 +++ .../statistic/event/EventDataRow.java | 5 + .../task2712/statistic/event/EventType.java | 10 + .../event/NoAvailableVideoEventDataRow.java | 31 +++ .../event/VideoSelectedEventDataRow.java | 49 ++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 255 +++++++++--------- 14 files changed, 446 insertions(+), 131 deletions(-) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2712/DirectorTablet.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/CookedOrderEventDataRow.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/EventType.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/NoAvailableVideoEventDataRow.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/VideoSelectedEventDataRow.java diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/DirectorTablet.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/DirectorTablet.java new file mode 100644 index 0000000..5845388 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/DirectorTablet.java @@ -0,0 +1,39 @@ +package com.javarush.task.task27.task2712; + +import com.javarush.task.task27.task2712.statistic.StatisticManager; + +import java.math.BigDecimal; +import java.text.SimpleDateFormat; +import java.util.Collections; +import java.util.Date; +import java.util.Locale; +import java.util.Map; + +/** + * Created by ArchMage on 25.04.17. + */ +public class DirectorTablet { + + public void printAdvertisementProfit(){ + Map amountPerDay = StatisticManager.getInstance().getAmountPerDay(); + Double totalValue = 0d; + SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy", Locale.ENGLISH); + + for (Map.Entry entry : amountPerDay.entrySet()){ + Double amount = ((double) entry.getValue()) / 1000; + Double roundedAmount = new BigDecimal(amount).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); + ConsoleHelper.writeMessage(dateFormat.format(entry.getKey()) + " - " + roundedAmount); + totalValue += roundedAmount; + } + ConsoleHelper.writeMessage("Total - " + totalValue); + } + public void printCookWorkloading(){ + + } + public void printActiveVideoSet(){ + + } + public void printArchivedVideoSet(){ + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Restaurant.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Restaurant.java index 79cd045..d894521 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Restaurant.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Restaurant.java @@ -4,6 +4,7 @@ import com.javarush.task.task27.task2712.kitchen.Order; import com.javarush.task.task27.task2712.kitchen.Waiter; + /** * Created by ArchMage on 14.04.17. */ @@ -15,6 +16,13 @@ public static void main(String[] args){ Waiter waiter = new Waiter(); cook.addObserver(waiter); Order order = tablet.createOrder(); + DirectorTablet directorTablet = new DirectorTablet(); + + + directorTablet.printAdvertisementProfit(); + directorTablet.printCookWorkloading(); + directorTablet.printArchivedVideoSet(); + directorTablet.printActiveVideoSet(); } } diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementManager.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementManager.java index 4f7d56f..e31539e 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementManager.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementManager.java @@ -1,6 +1,8 @@ package com.javarush.task.task27.task2712.ad; import com.javarush.task.task27.task2712.ConsoleHelper; +import com.javarush.task.task27.task2712.statistic.StatisticManager; +import com.javarush.task.task27.task2712.statistic.event.VideoSelectedEventDataRow; import java.util.ArrayList; import java.util.Collections; @@ -57,6 +59,12 @@ public int compare(Advertisement o1, Advertisement o2) { } }); + StatisticManager.getInstance().register( + new VideoSelectedEventDataRow( + videosList, + totalAmount(videosList), + totalDuration(videosList))); + for (Advertisement entry: videosList) { ConsoleHelper.writeMessage(String.format("%s is displaying... %d, %d", entry.getName(), diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementStorage.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementStorage.java index 09825c7..d4db8d8 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementStorage.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementStorage.java @@ -15,18 +15,27 @@ public class AdvertisementStorage { // 3. В конструкторе класса добавим в список videos какие-то данные. + // ЕСЛИ НЕ ВЕРНУТЬ СПИСОК ВИДЕО В ИСХОДНОЕ СОСТОЯНИЕ, ТО 14 ПУНКТ ЗАДАЧИ НЕ ПРОХОДИТ!!! + // ОШИБКА: "Перед отображением видео должно быть зарегистрировано событие "видео выбрано". + private AdvertisementStorage() { Object someContent = new Object(); - /*videos.add(new Advertisement(someContent, "First Video", 5000, 100, 3 * 60)); // 3 min + videos.add(new Advertisement(someContent, "First Video", 5000, 100, 3 * 60)); // 3 min videos.add(new Advertisement(someContent, "Second Video", 100, 10, 15 * 60)); //15 min - videos.add(new Advertisement(someContent, "Third Video", 400, 2, 10 * 60)); //10 min*/ - videos.add(new Advertisement(someContent, "First Video", 100, 1, 100)); + videos.add(new Advertisement(someContent, "Third Video", 400, 2, 10 * 60)); //10 min + /*videos.add(new Advertisement(someContent, "First Video", 100, 1, 100)); videos.add(new Advertisement(someContent, "Second Video", 120, 1, 120)); videos.add(new Advertisement(someContent, "Third Video", 400, 1, 400)); videos.add(new Advertisement(someContent, "Fourth Video", 360, 1, 359)); videos.add(new Advertisement(someContent, "FourthMoreMoney Video", 360, 1, 360)); videos.add(new Advertisement(someContent, "Fifth Video", 30, 1, 30)); - videos.add(new Advertisement(someContent, "Sixth Video", 45, 1, 45)); + videos.add(new Advertisement(someContent, "Sixth Video", 45, 1, 45));*//* + videos.add(new Advertisement(someContent, "First Video", 5000, 100, 15 * 60)); // 15 min + videos.add(new Advertisement(someContent, "Second Video", 100, 10, 3 * 60)); //3 min + videos.add(new Advertisement(someContent, "Third Video", 400, 2, 10 * 60)); //10 min + //videos.add(new Advertisement(someContent, "Forth Video", 12, 3, 1 * 60)); //1 min + //videos.add(new Advertisement(someContent, "Fifth Video", 8, 2, 1 * 60)); //1 min + //videos.add(new Advertisement(someContent, "Sixth Video", 16, 8, 1 * 60)); //1 min*/ } // 2. Чтобы как-то работать с видео, создай публичные методы: // 2.1. list() — который вернет список всех существующих доступных видео. diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Cook.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Cook.java index e3f7271..e21f5cd 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Cook.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Cook.java @@ -1,6 +1,9 @@ package com.javarush.task.task27.task2712.kitchen; import com.javarush.task.task27.task2712.ConsoleHelper; +import com.javarush.task.task27.task2712.Tablet; +import com.javarush.task.task27.task2712.statistic.StatisticManager; +import com.javarush.task.task27.task2712.statistic.event.CookedOrderEventDataRow; import java.util.Observable; import java.util.Observer; @@ -19,6 +22,10 @@ public Cook(String name) { @Override public void update(Observable o, Object arg) { ConsoleHelper.writeMessage("Start cooking - " + arg + ", cooking time " + ((Order) arg).getTotalCookingTime() + "min"); + StatisticManager statisticManager = StatisticManager.getInstance(); + Order order = (Order) arg; + Tablet tablet = (Tablet) o; + statisticManager.register(new CookedOrderEventDataRow(tablet.toString(), name, order.getTotalCookingTime() * 60, order.getDishes())); setChanged(); notifyObservers(arg); } diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Dish.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Dish.java index 01d6a5d..85fc501 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Dish.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Dish.java @@ -6,8 +6,8 @@ * Created by ArchMage on 14.04.17. */ public enum Dish { - Fish(11), - //Fish(25), + //Fish(11), + Fish(25), Steak(30), Soup(15), Juice(5), diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Order.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Order.java index 05dd194..e49e40b 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Order.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Order.java @@ -35,4 +35,9 @@ public int getTotalCookingTime(){ public boolean isEmpty(){ return (dishes == null || dishes.size() == 0); } + + public List getDishes() { + return dishes; + } + } diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/StatisticManager.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/StatisticManager.java index a8a1dd5..2d5c0fb 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/StatisticManager.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/StatisticManager.java @@ -1,22 +1,113 @@ package com.javarush.task.task27.task2712.statistic; +import com.javarush.task.task27.task2712.ad.Advertisement; +import com.javarush.task.task27.task2712.kitchen.Cook; import com.javarush.task.task27.task2712.statistic.event.EventDataRow; +import com.javarush.task.task27.task2712.statistic.event.EventType; +import com.javarush.task.task27.task2712.statistic.event.VideoSelectedEventDataRow; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.util.*; /** * Created by ArchMage on 24.04.17. */ public class StatisticManager { - private StatisticManager instance = new StatisticManager(); + private static StatisticManager instance = new StatisticManager(); + private StatisticStorage statisticStorage = new StatisticStorage(); + private Set cooks = new HashSet(); private StatisticManager(){ } - public StatisticManager getInstance() { + public static StatisticManager getInstance() { return instance; } public void register(EventDataRow data){ + statisticStorage.put(data); + } + + public void register(Cook cook){ + cooks.add(cook); + } + + public Map getAmountPerDay(){ + return statisticStorage.amountPerDay(); + } + + private class StatisticStorage{ + private Map> storage = new HashMap>();; + + public StatisticStorage(){ + + for (EventType entry: EventType.values()){ + storage.put(entry, new ArrayList()); + } + } + + private void put(EventDataRow data){ + EventType eventType = data.getType(); + List list = storage.get(eventType); + list.add(data); + } + + private Map amountPerDay(){ + //generateStatistic(); + + Map amountPerDay = new TreeMap(Collections.reverseOrder()); + List advertismentList = storage.get(EventType.SELECTED_VIDEOS); + for (EventDataRow entry: advertismentList){ + VideoSelectedEventDataRow row = (VideoSelectedEventDataRow) entry; + Date advDate = row.getDate(); + + Date referenceDate = null; + try { + referenceDate = new SimpleDateFormat( "dd.MM.yyyy" ).parse("" + advDate.getDate() + "." + + (advDate.getMonth() + 1) + "." + + (advDate.getYear() + 1900) ); + + } catch (ParseException e) { + } + + Long amountEntry = amountPerDay.get(referenceDate); + if (amountEntry == null) { + amountPerDay.put(referenceDate, row.getAmount()); + } else { + amountPerDay.put(referenceDate, row.getAmount() + amountEntry); + } + } + + return amountPerDay; + } + + private void generateStatistic(){ + List dataList = storage.get(EventType.SELECTED_VIDEOS); + + VideoSelectedEventDataRow row = new VideoSelectedEventDataRow(new ArrayList(), 2500, 50); + + Date date = null; + Date date2 = null; + Date date3 = null; + try { + date = new SimpleDateFormat( "dd.MM.yyyy" ).parse( "14.05.2013" ); + date2 = new SimpleDateFormat( "dd.MM.yyyy" ).parse( "13.05.2013" ); + date3 = new SimpleDateFormat( "dd.MM.yyyy" ).parse( "12.05.2013" ); + } catch (ParseException e) { + } + row.setCurrentDate(date); + dataList.add(row); + + row = new VideoSelectedEventDataRow(new ArrayList(), 1020, 50); + row.setCurrentDate(date2); + dataList.add(row); + row = new VideoSelectedEventDataRow(new ArrayList(), 543980, 50); + row.setCurrentDate(date3); + dataList.add(row); + } } } diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/CookedOrderEventDataRow.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/CookedOrderEventDataRow.java new file mode 100644 index 0000000..d88748c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/CookedOrderEventDataRow.java @@ -0,0 +1,44 @@ +package com.javarush.task.task27.task2712.statistic.event; + +import com.javarush.task.task27.task2712.kitchen.Dish; + +import java.util.Date; +import java.util.List; + +/** + * Created by ArchMage on 25.04.17. + */ +public class CookedOrderEventDataRow implements EventDataRow { + private String tabletName; + private String cookName; + private int cookingTimeSeconds; + private List cookingDishs; + private Date currentDate; + + public CookedOrderEventDataRow(String tabletName, String cookName, int cookingTimeSeconds, List cookingDishs){ + this.tabletName = tabletName; + this.cookName = cookName; + this.cookingTimeSeconds = cookingTimeSeconds; + this.cookingDishs = cookingDishs; + currentDate = new Date(); + } + + @Override + public EventType getType() { + return EventType.COOKED_ORDER; + } + + @Override + public Date getDate() { + return currentDate; + } + + @Override + public int getTime() { + return cookingTimeSeconds; + } + + public String getCookName() { + return cookName; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/EventDataRow.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/EventDataRow.java index f3e861e..4debd8c 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/EventDataRow.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/EventDataRow.java @@ -1,7 +1,12 @@ package com.javarush.task.task27.task2712.statistic.event; +import java.util.Date; + /** * Created by ArchMage on 24.04.17. */ public interface EventDataRow { + EventType getType(); + Date getDate(); + int getTime(); } diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/EventType.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/EventType.java new file mode 100644 index 0000000..2b99a0e --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/EventType.java @@ -0,0 +1,10 @@ +package com.javarush.task.task27.task2712.statistic.event; + +/** + * Created by ArchMage on 25.04.17. + */ +public enum EventType { + COOKED_ORDER, + SELECTED_VIDEOS, + NO_AVAILABLE_VIDEO +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/NoAvailableVideoEventDataRow.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/NoAvailableVideoEventDataRow.java new file mode 100644 index 0000000..c52e200 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/NoAvailableVideoEventDataRow.java @@ -0,0 +1,31 @@ +package com.javarush.task.task27.task2712.statistic.event; + +import java.util.Date; + +/** + * Created by ArchMage on 25.04.17. + */ +public class NoAvailableVideoEventDataRow implements EventDataRow { + private int totalDuration; + private Date currentDate; + + public NoAvailableVideoEventDataRow(int totalDuration){ + this.totalDuration = totalDuration; + currentDate = new Date(); + } + + @Override + public EventType getType() { + return EventType.NO_AVAILABLE_VIDEO; + } + + @Override + public Date getDate() { + return currentDate; + } + + @Override + public int getTime() { + return totalDuration; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/VideoSelectedEventDataRow.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/VideoSelectedEventDataRow.java new file mode 100644 index 0000000..39a2720 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/VideoSelectedEventDataRow.java @@ -0,0 +1,49 @@ +package com.javarush.task.task27.task2712.statistic.event; + +import com.javarush.task.task27.task2712.ad.Advertisement; + +import java.util.Date; +import java.util.List; + +/** + * Created by ArchMage on 25.04.17. + */ +public class VideoSelectedEventDataRow implements EventDataRow { + private List optimalVideoSet; + private long amount; + private int totalDuration; + private Date currentDate; + + + public VideoSelectedEventDataRow(List optimalVideoSet, long amount, int totalDuration){ + this.optimalVideoSet = optimalVideoSet; + this.amount = amount; + this.totalDuration = totalDuration; + currentDate = new Date(); + + } + + @Override + public EventType getType() { + return EventType.SELECTED_VIDEOS; + } + + @Override + public Date getDate() { + return currentDate; + } + + // TODO: 25.04.17 Удалить после тестирования + public void setCurrentDate(Date currentDate) { + this.currentDate = currentDate; + } + + @Override + public int getTime() { + return totalDuration; + } + + public long getAmount() { + return amount; + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" index 0c6fe95..486c72e 100644 --- "a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -1,4 +1,135 @@ -taskKey="com.javarush.task.task27.task2712.big12" +taskKey="com.javarush.task.task27.task2712.big16" + +Ресторан(16) + +Реализуем первый пункт статистики - какую сумму заработали на рекламе, сгруппировать по дням. + +1. В классе VideoSelectedEventDataRow создай геттер для поля amount. +В классе CookedOrderEventDataRow создай геттер для поля cookName. + +2. В StatisticManager создай метод (придумать самостоятельно), который из хранилища достанет все данные, +относящиеся к отображению рекламы, и посчитает общую прибыль за каждый день. +Дополнительно добавь вспомогательный метод get в класс хранилища, чтобы получить доступ к данным. + +3. Начнем с логики метода printAdvertisementProfit в классе DirectorTablet. +Используя метод из предыдущего пункта вывести в консоль в убывающем порядке даты и суммы. +Для каждой даты из хранилища событий, для которой есть показанная реклама, должна выводится сумма прибыли за показы рекламы для этой даты. +В конце вывести слово Total и общую сумму. +Пример: +14-May-2013 - 2.50 +13-May-2013 - 1.02 +12-May-2013 - 543.98 +Total - 547.50 + +4.Реализуем второй пункт статистики - загрузка (рабочее время) повара, сгруппировать по дням. + +В StatisticManager создай метод (придумать самостоятельно), который из хранилища достанет все данные, +относящиеся к работе повара, и посчитает общую продолжительность работы для каждого повара отдельно. + +5. Реализуем логику метода printCookWorkloading в классе DirectorTablet. +Используя метод из предыдущего пункта вывести в консоль в убывающем порядке даты, имена поваров и время работы в минутах (округлить в большую сторону). +Для каждой даты из хранилища событий, для которой есть запись о работе повара, должна выводится продолжительность работы в минутах для этой даты. +Если повар не работал в какой-то из дней, то с пустыми данными его НЕ выводить (см. 13-May-2013) +Поваров сортировать по имени +Пример: +14-May-2013 +Ivanov - 60 min +Petrov - 35 min + +13-May-2013 +Ivanov - 129 min + +12-May-2013 +Ivanov - 6 min +Petrov - 5 min + + +Требования: +1. В классе VideoSelectedEventDataRow должен быть создан геттер для поля amount. +2. В классе CookedOrderEventDataRow должен быть создан геттер для поля cookName. +3. Метод printAdvertisementProfit класса DirectorTablet должен быть реализован в соответствии с условием задачи. +4. Метод printCookWorkloading класса DirectorTablet должен быть реализован в соответствии с условием задачи. + + +Ресторан(15) + +Давай подумаем что нужно сделать, чтобы директор мог посмотреть: +1) какую сумму заработали на рекламе, сгруппировать по дням; +2) загрузка (рабочее время) повара, сгруппировать по дням; +3) список активных роликов и оставшееся количество показов по каждому; +4) список неактивных роликов (с оставшемся количеством показов равным нулю). + +Для каждого пункта добавим соответствующий метод в StatisticManager. +Директор будет вызывать метод, StatisticManager будет делать различные подсчеты. +Но директор должен из какого-то места вызвать эти методы. Дадим ему планшет, но с другим ПО. +Для этого создадим класс DirectorTablet, в котором будут дружелюбный интерфейс и возможность обращения к статистике. + +1. В корне задачи-проекта создай класс DirectorTablet. + +2. В классе DirectorTablet создай четыре void метода: +printAdvertisementProfit(), printCookWorkloading(), printActiveVideoSet(), printArchivedVideoSet() +Они соответствуют перечисленным четырем пунктам. + +3. Чтобы можно было проверить результат, добавим в метод main создание директорского планшета и вывод статистики +с помощью методов перечисленных выше. + +Нам понадобятся еще некоторые методы. +4. В EventDataRow создай методы: +Date getDate(), реализация которого вернет дату создания записи +int getTime(), реализация которого вернет время - продолжительность + +5. В StatisticManager void register(Cook cook), который зарегистрирует полученного повара. +Создай в классе StatisticManager множество (Set) поваров (cooks) и добавь в него повара. + +6. Реализуй необходимые геттеры у классов CookedOrderEventDataRow, NoAvailableVideoEventDataRow и VideoSelectedEventDataRow. + + + +Ресторан(14) + +1. Внутри StatisticStorage создай метод void put(EventDataRow data). + +2. Чтобы методом put(EventDataRow data) добавить объект data в данные карты, нужен тип события - EventType. +Будет правильно, если событие будет хранить в себе свой тип. Поэтому: +2.1. В интерфейс EventDataRow добавь метод EventType getType() +2.2. Реализуй этот метод в каждом классе-событии: CookedOrderEventDataRow, NoAvailableVideoEventDataRow, VideoSelectedEventDataRow + +3. Сделай так, чтобы к методу void put(EventDataRow data) нельзя было получить доступ за пределами класса StatisticManager. +Воспользуйся особенностями вложенных классов. + +Теперь остается расставить вызовы StatisticManager в те места, которые генерируют события. + +4. Зарегистрируй событие для повара во время приготовления еды. +Добавь геттер для поля dishes в класс Order, используйте его при создании события. + +5. Зарегистрируй событие "видео выбрано" перед отображением рекламы пользователю. + +6. Метод register с одним параметром типа EventDataRow должен регистрировать полученное событие в statisticStorage. + + + +Ресторан(13) + +Вернемся к методу register в классе StatisticManager. Он должен регистрировать события в хранилище. +Создадим хранилище : ) +Хранилище связано 1 к 1 с менеджером, т.е. один менеджер и одно хранилище на приложение. +К хранилищу может доступиться только StatisticManager. Поэтому... +Из вышеперечисленного следует, что хранилище должно быть приватным иннер классом. +Назовем его StatisticStorage. + +1. Внутри класса StatisticManager создать приватный иннер класс StatisticStorage. + +2. Чтобы менеджер мог получить доступ к хранилищу, нужно в классе StatisticManager создать поле statisticStorage типа StatisticStorage. +Инициализируй его экземпляром класса. + +3. StatisticStorage будет хранить данные внутри себя в виде мапы/словаря storage. +Связь StatisticStorage и Map должна быть has-a +Типы для мапы - > + +4. В конструкторе StatisticStorage инициализируй хранилище данными по-умолчанию: +например используя цикл, для каждого EventType добавь new ArrayList() + + Ресторан(12) @@ -28,12 +159,6 @@ totalDuration - общая продолжительность показа от 3. В классы, созданные в п.2., добавьте поле Date currentDate, которое проинициализируй в конструкторе текущей датой. -Требования: -1. В пакете event должен быть создан enum EventType с элементами {COOKED_ORDER, SELECTED_VIDEOS, NO_AVAILABLE_VIDEO}. -2. В пакете event должен быть создан класс CookedOrderEventDataRow реализующий интерфейс EventDataRow с конструктором и полями описанными в условии. -3. В пакете event должен быть создан класс NoAvailableVideoEventDataRow реализующий интерфейс EventDataRow с конструктором и полями описанными в условии. -4. В пакете event должен быть создан класс VideoSelectedEventDataRow реализующий интерфейс EventDataRow с конструктором и полями описанными в условии. - Ресторан(11) @@ -75,119 +200,3 @@ totalDuration - общая продолжительность показа от -Ресторан(10) - -Рекурсию используют тогда, когда алгоритм решения задачи совпадает с алгоритмом решения подзадачи (части). -У нас как раз такой случай. Нам нужно сделать полный перебор всех вариантов и выбрать из них лучший. - -Напомню, рекурсия пишется по следующему принципу: -а) условие выхода/окончания рекурсии -б) условие продолжения - вызов самой себя с набором параметров предыдущего шага. -В любое время ты можешь почитать в инете подробную информацию по написанию рекурсии. - -Текущее задание - реализовать п.2.2 предыдущего задания с помощью рекурсии. -(подобрать список видео из доступных, просмотр которых обеспечивает максимальную выгоду) -Рекурсивный метод должен выбрать набор рекламных роликов, которые будут показаны посетителю. - -Этот набор должен удовлетворять следующим требованиям: -1) сумма денег, полученная от показов, должна быть максимальной из всех возможных вариантов -2) общее время показа рекламных роликов НЕ должно превышать время приготовления блюд для текущего заказа; -3) для одного заказа любой видео-ролик показывается не более одного раза; -4) если существует несколько вариантов набора видео-роликов с одинаковой суммой денег, полученной от показов, то: -4.1) выбрать тот вариант, у которого суммарное время максимальное; -4.2) если суммарное время у этих вариантов одинаковое, то выбрать вариант с минимальным количеством роликов; -5) количество показов у любого рекламного ролика из набора - положительное число. - -При локальном тестировании учитывайте, что необходимо отобразить все рекламные ролики, отобранные для показа, -в порядке уменьшения стоимости показа одного рекламного ролика в копейках. - -Также не забудь реализовать п.2.4 из предыдущего задания (вывести на экран все подходящие ролики). - -Для каждого показанного видео-ролика должен быть вызван метод revalidate(). - - - -Ресторан(9) - -Нам понадобится исключение, которое поможет обработать ситуацию, если у нас не будет получаться подобрать рекламные ролики. - -1. Создадим unchecked исключение NoVideoAvailableException в пакете ad. - -2. Разберем подробно метод void processVideos() в AdvertisementManager. -2.1. Удаляем из него вывод в консоль "calling processVideos method" -Метод должен: -2.2. Подобрать список видео из доступных, просмотр которых обеспечивает максимальную выгоду. (Пока делать не нужно, сделаем позже). -2.3. Если нет рекламных видео, которые можно показать посетителю, то бросить NoVideoAvailableException, -которое перехватить в оптимальном месте (подумать, где это место) и с уровнем Level.INFO логировать фразу -"No video is available for the order " + order -2.4. Отобразить все рекламные ролики, отобранные для показа, в порядке уменьшения стоимости показа одного рекламного ролика -в копейках. Вторичная сортировка - по увеличению стоимости показа одной секунды рекламного ролика в тысячных частях копейки -Используйте метод Collections.sort -(Тоже пока делать не нужно, сделаем позже). -Пример для заказа [Water]: -First Video is displaying... 50, 277 -где First Video - название рекламного ролика -где 50 - стоимость показа одного рекламного ролика в копейках -где 277 - стоимость показа одной секунды рекламного ролика в тысячных частях копейки (равно 0.277 коп) -Используйте методы из класса Advertisement. -2.5. В классе Advertisement создайте метод void revalidate(). Этот метод должен: -2.5.1. Бросать UnsupportedOperationException, если количество показов не положительное число. -2.5.2. Уменьшать количество показов. - - - -Ресторан(8) - -Пришло время описать функционал класса AdvertisementManager. -Но для начала нам понадобятся некоторые методы в классе Advertisement. - -1. В классе Advertisement создай поле long amountPerOneDisplaying. -Оно должно равняться стоимости одного показа рекламного объявления в копейках (initialAmount/hits). -Присвой значение полю в конструкторе. - -2. В классе Advertisement создай геттеры для полей name, duration и amountPerOneDisplaying. - -3. Определим необходимые данные для объекта AdvertisementManager - это время выполнения заказа поваром. -Т.к. продолжительность видео у нас хранится в секундах, то и и время выполнения заказа тоже будем принимать в секундах. -В классе AdvertisementManager создай конструктор, который принимает один параметр - int timeSeconds. -Создай соответствующее поле и сохраните это значение в него. - -4. AdvertisementManager выполняет только одно единственное действие - обрабатывает рекламное видео. -Поэтому создайте единственный публичный метод void processVideos(), его функционал опишем в следующем задании. -А пока выведем в консоль "calling processVideos method" - -5. Чтобы тестировать данную функциональность, нужно добавить вызов processVideos метода у AdvertisementManager. -Очевидно, что этот метод должен вызываться во время создания заказа, а точнее - в параллельном режиме. -Заказ готовится в то время, как видео смотрится. -Добавьте вызов метода processVideos() в нужное место. - -P.S. Не забудь что время приготовления заказа считается в минутах, а время показа рекламы в секундах! - - - -Ресторан(7) - -При выборе, с какого класса начать, старайся найти тот, который используют другие, и который сам ничего не использует. -В нашем случае - это хранилище рекламных роликов (AdvertisementStorage). -Мы решили, что оно будет единственным в ресторане и сделали его синглтоном. -Опишем его. - -1. Видео должно где-то храниться, пусть это будет список. -Создадим поле videos и инициализируем его пустым листом. -Подумай, должно ли поле videos иметь возможность менять свое значение? - -2. Чтобы как-то работать с видео, создай публичные методы: -2.1. list() - который вернет список всех существующих доступных видео. -2.2. add(Advertisement advertisement) - который добавит новое видео в список videos. - -3. В конструкторе класса добавим в список videos какие-то данные. У меня это: -Object someContent = new Object(); -new Advertisement(someContent, "First Video", 5000, 100, 3 * 60) // 3 min -new Advertisement(someContent, "Second Video", 100, 10, 15 * 60) //15 min -new Advertisement(someContent, "Third Video", 400, 2, 10 * 60) //10 min - -4. В AdvertisementManager создадим final поле-ссылку на экземпляр AdvertisementStorage и назовем ее storage. -Не забудь инициализировать созданное поле! - - - From ee5804c3c0c584bee515a2dc3ebcf1b103a9f45c Mon Sep 17 00:00:00 2001 From: PeucT Date: Tue, 25 Apr 2017 21:17:39 +0300 Subject: [PATCH 32/51] Level 29. Big task 2712. Some changes are made at home. --- .../com/javarush/task/task27/task2712/DirectorTablet.java | 6 +++--- .../task/task27/task2712/statistic/StatisticManager.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/DirectorTablet.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/DirectorTablet.java index 5845388..6d26d03 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/DirectorTablet.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/DirectorTablet.java @@ -20,12 +20,12 @@ public void printAdvertisementProfit(){ SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy", Locale.ENGLISH); for (Map.Entry entry : amountPerDay.entrySet()){ - Double amount = ((double) entry.getValue()) / 1000; + Double amount = ((double) entry.getValue()) / 100; Double roundedAmount = new BigDecimal(amount).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); - ConsoleHelper.writeMessage(dateFormat.format(entry.getKey()) + " - " + roundedAmount); + ConsoleHelper.writeMessage(dateFormat.format(entry.getKey()) + " - " + String.format("%.2f", roundedAmount).replaceAll(",", ".")); totalValue += roundedAmount; } - ConsoleHelper.writeMessage("Total - " + totalValue); + ConsoleHelper.writeMessage("Total - " + String.format("%.2f", totalValue).replaceAll(",", ".")); } public void printCookWorkloading(){ diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/StatisticManager.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/StatisticManager.java index 2d5c0fb..17f0ef4 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/StatisticManager.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/StatisticManager.java @@ -87,7 +87,7 @@ private Map amountPerDay(){ private void generateStatistic(){ List dataList = storage.get(EventType.SELECTED_VIDEOS); - VideoSelectedEventDataRow row = new VideoSelectedEventDataRow(new ArrayList(), 2500, 50); + VideoSelectedEventDataRow row = new VideoSelectedEventDataRow(new ArrayList(), 250, 50); Date date = null; Date date2 = null; @@ -101,11 +101,11 @@ private void generateStatistic(){ row.setCurrentDate(date); dataList.add(row); - row = new VideoSelectedEventDataRow(new ArrayList(), 1020, 50); + row = new VideoSelectedEventDataRow(new ArrayList(), 102, 50); row.setCurrentDate(date2); dataList.add(row); - row = new VideoSelectedEventDataRow(new ArrayList(), 543980, 50); + row = new VideoSelectedEventDataRow(new ArrayList(), 54398, 50); row.setCurrentDate(date3); dataList.add(row); } From 52c499449743cfa267d1779cf9bc77ec9b7dd6a8 Mon Sep 17 00:00:00 2001 From: PeucT Date: Tue, 25 Apr 2017 22:22:35 +0300 Subject: [PATCH 33/51] Level 29. Big task 2712. Some improvements at Advertisment/amountPerOneDisplay calculation --- .../src/com/javarush/task/task27/task2712/ad/Advertisement.java | 1 + 1 file changed, 1 insertion(+) diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/Advertisement.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/Advertisement.java index aee579a..9bb1ddc 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/Advertisement.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/Advertisement.java @@ -45,5 +45,6 @@ public long getAmountPerOneDisplaying() { public void revalidate(){ if (hits <= 0) { throw new UnsupportedOperationException(); } hits--; + if (hits == 1) amountPerOneDisplaying += initialAmount % (initialAmount / amountPerOneDisplaying); } } From f2c84c79b669f56d16675072461de4c7f69a0c98 Mon Sep 17 00:00:00 2001 From: PeucT Date: Wed, 26 Apr 2017 18:30:06 +0400 Subject: [PATCH 34/51] Level 29. Big task 2712. Part 16 (hasn't been accepted) --- 1.JavaSyntax/1.JavaSyntax.iml | 11 +++++ 1.JavaSyntax/src/Quest.info | 1 + .../task/task20/task2025/Solution.java | 21 +++++---- 3.JavaMultithreading/3.JavaMultithreading.iml | 11 +++++ 3.JavaMultithreading/src/Quest.info | 1 + .../task/task26/task2606/Solution.java | 4 +- .../task/task27/task2712/DirectorTablet.java | 21 ++++++--- .../task27/task2712/ad/Advertisement.java | 4 +- .../task2712/statistic/StatisticManager.java | 45 ++++++++++++++++++- .../task/task28/task2811/Solution.java | 2 +- 4.JavaCollections/4.JavaCollections.iml | 11 +++++ 4.JavaCollections/src/Quest.info | 1 + 5.OnlineInternship/5.OnlineInternship.iml | 11 +++++ 5.OnlineInternship/src/Internship.info | 1 + 14 files changed, 126 insertions(+), 19 deletions(-) create mode 100644 1.JavaSyntax/1.JavaSyntax.iml create mode 100644 1.JavaSyntax/src/Quest.info create mode 100644 3.JavaMultithreading/3.JavaMultithreading.iml create mode 100644 3.JavaMultithreading/src/Quest.info create mode 100644 4.JavaCollections/4.JavaCollections.iml create mode 100644 4.JavaCollections/src/Quest.info create mode 100644 5.OnlineInternship/5.OnlineInternship.iml create mode 100644 5.OnlineInternship/src/Internship.info diff --git a/1.JavaSyntax/1.JavaSyntax.iml b/1.JavaSyntax/1.JavaSyntax.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/1.JavaSyntax/1.JavaSyntax.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/1.JavaSyntax/src/Quest.info b/1.JavaSyntax/src/Quest.info new file mode 100644 index 0000000..e4836af --- /dev/null +++ b/1.JavaSyntax/src/Quest.info @@ -0,0 +1 @@ +Синтаксис Java \ No newline at end of file diff --git a/2.JavaCore/src/com/javarush/task/task20/task2025/Solution.java b/2.JavaCore/src/com/javarush/task/task20/task2025/Solution.java index 468e549..b248954 100644 --- a/2.JavaCore/src/com/javarush/task/task20/task2025/Solution.java +++ b/2.JavaCore/src/com/javarush/task/task20/task2025/Solution.java @@ -10,7 +10,7 @@ public class Solution { private static int[][] matrix; private static void fillMatrix() { - int n = 11; + int n = 10; matrix = new int[n][n]; for (int i = 1; i < n; i++) { for (int j = 1; j < n; j++){ @@ -23,13 +23,14 @@ private static void fillMatrix() { } } - public static long[] getNumbers(long N) { - long[] result = null; + public static int[] getNumbers(long N) { + int[] result = null; + //long[] result = null; fillMatrix(); TreeSet list = new TreeSet(); - for (long i = 1; i <= N; i++) { + for (long i = 1; i < N; i++) { int power = 0; long tempNumber = i; boolean isNotChecked = false; @@ -67,15 +68,16 @@ public static long[] getNumbers(long N) { } if (!list.isEmpty()) { - result = new long[list.size()]; + result = new int[list.size()]; + //result = new long[list.size()]; int count = 0; for (long entry: list) { - result[count] = entry; + result[count] = (int) entry; count++; } return result; //return list.toArray(new Long[list.size() - 1]); - } else return new long[1]; + } else return new int[1]; } @@ -105,6 +107,7 @@ private static long getPoweredSumm(long number, int power) { public static void main(String[] args) { //long N = Long.MAX_VALUE; long baseN = 1000000; + //long N = 372; long N = 100000000; //long N = 146511208; @@ -112,13 +115,13 @@ public static void main(String[] args) { long startTime = new Date().getTime(); //Long[] result = getNumbersBaseAlg(baseN); //Long[] result = getNumbers(N); - long[] result = getNumbers(N); + int[] result = getNumbers(N); long endTime = new Date().getTime(); long memoryVolumeEnd = Runtime.getRuntime().freeMemory(); for (int i = 0; i < result.length ; i++) { System.out.println(result[i]); } - System.out.println("Memory consumption: " + ( ( memoryVolumeStart - memoryVolumeEnd ) / 1024 / 1024) + " Mb"); + System.out.println("Memory consumption: " + ( ( memoryVolumeStart - memoryVolumeEnd ) ) + " Mb"); System.out.println("Time consumption: " + (( endTime - startTime ) / 1000) + " s"); } } diff --git a/3.JavaMultithreading/3.JavaMultithreading.iml b/3.JavaMultithreading/3.JavaMultithreading.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/3.JavaMultithreading/3.JavaMultithreading.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/3.JavaMultithreading/src/Quest.info b/3.JavaMultithreading/src/Quest.info new file mode 100644 index 0000000..9ec72fe --- /dev/null +++ b/3.JavaMultithreading/src/Quest.info @@ -0,0 +1 @@ +Многопоточность в Java \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2606/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2606/Solution.java index da937ed..ca2232e 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task26/task2606/Solution.java +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2606/Solution.java @@ -11,7 +11,7 @@ Тот, кто любит труд, не нуждается в развлечениях */ public class Solution { - private final URL javarushUrl; + /*private final URL javarushUrl; private final URL javarushUrl1Child; private final URL javarushVkGroupUrl; private final URL javarushVkGroupUrl1Child; @@ -108,5 +108,5 @@ public void run() { public URL getPage() { return url; } - } + }*/ } diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/DirectorTablet.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/DirectorTablet.java index 6d26d03..cc416fc 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/DirectorTablet.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/DirectorTablet.java @@ -4,10 +4,7 @@ import java.math.BigDecimal; import java.text.SimpleDateFormat; -import java.util.Collections; -import java.util.Date; -import java.util.Locale; -import java.util.Map; +import java.util.*; /** * Created by ArchMage on 25.04.17. @@ -28,7 +25,21 @@ public void printAdvertisementProfit(){ ConsoleHelper.writeMessage("Total - " + String.format("%.2f", totalValue).replaceAll(",", ".")); } public void printCookWorkloading(){ - + Map> cookStatistic = StatisticManager.getInstance().getCookStatistic(); + SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy", Locale.ENGLISH); + boolean isFirstDisplay = true; + for (Map.Entry> entry : cookStatistic.entrySet()){ + if (isFirstDisplay) { + ConsoleHelper.writeMessage(dateFormat.format(entry.getKey())); + isFirstDisplay = false; + } else { + ConsoleHelper.writeMessage(""); + ConsoleHelper.writeMessage(dateFormat.format(entry.getKey())); + } + for (Map.Entry entryInList : entry.getValue().entrySet()){ + ConsoleHelper.writeMessage(String.format("%s - %d min", entryInList.getKey(), (entryInList.getValue() / 60))); + } + } } public void printActiveVideoSet(){ diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/Advertisement.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/Advertisement.java index 9bb1ddc..54c7e1f 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/Advertisement.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/Advertisement.java @@ -45,6 +45,8 @@ public long getAmountPerOneDisplaying() { public void revalidate(){ if (hits <= 0) { throw new UnsupportedOperationException(); } hits--; - if (hits == 1) amountPerOneDisplaying += initialAmount % (initialAmount / amountPerOneDisplaying); + initialAmount -= amountPerOneDisplaying; + if (hits == 1) amountPerOneDisplaying = initialAmount; + } } diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/StatisticManager.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/StatisticManager.java index 17f0ef4..6cd1641 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/StatisticManager.java +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/StatisticManager.java @@ -2,13 +2,13 @@ import com.javarush.task.task27.task2712.ad.Advertisement; import com.javarush.task.task27.task2712.kitchen.Cook; +import com.javarush.task.task27.task2712.statistic.event.CookedOrderEventDataRow; import com.javarush.task.task27.task2712.statistic.event.EventDataRow; import com.javarush.task.task27.task2712.statistic.event.EventType; import com.javarush.task.task27.task2712.statistic.event.VideoSelectedEventDataRow; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.time.LocalDate; import java.util.*; /** @@ -39,6 +39,8 @@ public Map getAmountPerDay(){ return statisticStorage.amountPerDay(); } + public Map> getCookStatistic() { return statisticStorage.cookStatistic(); } + private class StatisticStorage{ private Map> storage = new HashMap>();; @@ -55,6 +57,8 @@ private void put(EventDataRow data){ list.add(data); } + + private Map amountPerDay(){ //generateStatistic(); @@ -84,6 +88,40 @@ private Map amountPerDay(){ return amountPerDay; } + private Map> cookStatistic(){ + Map> cookStatistic = new TreeMap>(Collections.reverseOrder()); + List cookStatisticsAll = storage.get(EventType.COOKED_ORDER); + for (EventDataRow entry: cookStatisticsAll){ + CookedOrderEventDataRow order = (CookedOrderEventDataRow) entry; + Date advDate = order.getDate(); + + Date referenceDate = null; + try { + referenceDate = new SimpleDateFormat( "dd.MM.yyyy" ).parse("" + advDate.getDate() + "." + + (advDate.getMonth() + 1) + "." + + (advDate.getYear() + 1900) ); + + } catch (ParseException e) { + } + Map currentCookStat = cookStatistic.get(referenceDate); + + if (currentCookStat == null) { + Map map = new TreeMap(); + map.put(order.getCookName(), Long.valueOf(order.getTime())); + cookStatistic.put(referenceDate, map); + } else { + Long cookerTime = currentCookStat.get(order.getCookName()); + if (cookerTime == null) { + currentCookStat.put(order.getCookName(), Long.valueOf(order.getTime())); + }else { + cookerTime += Long.valueOf(order.getTime()); + currentCookStat.put(order.getCookName(), cookerTime); + } + } + } + return cookStatistic; + } + private void generateStatistic(){ List dataList = storage.get(EventType.SELECTED_VIDEOS); @@ -105,9 +143,14 @@ private void generateStatistic(){ row.setCurrentDate(date2); dataList.add(row); + row = new VideoSelectedEventDataRow(new ArrayList(), 250, 50); + row.setCurrentDate(date2); + dataList.add(row); + row = new VideoSelectedEventDataRow(new ArrayList(), 54398, 50); row.setCurrentDate(date3); dataList.add(row); } + } } diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2811/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2811/Solution.java index 1097c94..fbb00a6 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task28/task2811/Solution.java +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2811/Solution.java @@ -8,6 +8,6 @@ public class Solution { public static void main(String[] args) { - ReadWriteMap linkedSafeMap = new ReadWriteMap<>(new LinkedHashMap<>()); + ReadWriteMap linkedSafeMap = new ReadWriteMap(new LinkedHashMap()); } } diff --git a/4.JavaCollections/4.JavaCollections.iml b/4.JavaCollections/4.JavaCollections.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/4.JavaCollections/4.JavaCollections.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/4.JavaCollections/src/Quest.info b/4.JavaCollections/src/Quest.info new file mode 100644 index 0000000..ee4da74 --- /dev/null +++ b/4.JavaCollections/src/Quest.info @@ -0,0 +1 @@ +Коллекции Java \ No newline at end of file diff --git a/5.OnlineInternship/5.OnlineInternship.iml b/5.OnlineInternship/5.OnlineInternship.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/5.OnlineInternship/5.OnlineInternship.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/5.OnlineInternship/src/Internship.info b/5.OnlineInternship/src/Internship.info new file mode 100644 index 0000000..5f803a8 --- /dev/null +++ b/5.OnlineInternship/src/Internship.info @@ -0,0 +1 @@ +Стажировка JavaRush \ No newline at end of file From 6666f9ed88865686eb83a3937d43fb96ba0f95ac Mon Sep 17 00:00:00 2001 From: PeucT Date: Thu, 27 Apr 2017 17:45:57 +0400 Subject: [PATCH 35/51] Level 30. Tasks 1-2 --- .../javarush/task/task30/task3001/Number.java | 27 ++++ .../task30/task3001/NumerationSystem.java | 5 + .../task30/task3001/NumerationSystemType.java | 20 +++ .../task/task30/task3001/Solution.java | 126 ++++++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 19 +++ .../task/task30/task3002/Solution.java | 29 ++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 16 +++ .../task/task30/task3009/Solution.java | 23 ++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 23 ++++ 9 files changed, 288 insertions(+) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3001/Number.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3001/NumerationSystem.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3001/NumerationSystemType.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3001/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task30/task3001/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3002/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task30/task3002/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3009/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task30/task3009/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3001/Number.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3001/Number.java new file mode 100644 index 0000000..d01e38d --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3001/Number.java @@ -0,0 +1,27 @@ +package com.javarush.task.task30.task3001; + +public class Number { + private NumerationSystem numerationSystem; + private String digit; + + public Number(NumerationSystem numerationSystem, String digit) { + this.numerationSystem = numerationSystem; + this.digit = digit; + } + + public NumerationSystem getNumerationSystem() { + return numerationSystem; + } + + public String getDigit() { + return digit; + } + + @Override + public String toString() { + return "Number{" + + "numerationSystem=" + numerationSystem + + ", digit='" + digit + '\'' + + '}'; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3001/NumerationSystem.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3001/NumerationSystem.java new file mode 100644 index 0000000..7d60816 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3001/NumerationSystem.java @@ -0,0 +1,5 @@ +package com.javarush.task.task30.task3001; + +public interface NumerationSystem { + int getNumerationSystemIntValue(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3001/NumerationSystemType.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3001/NumerationSystemType.java new file mode 100644 index 0000000..5d492c1 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3001/NumerationSystemType.java @@ -0,0 +1,20 @@ +package com.javarush.task.task30.task3001; + +public enum NumerationSystemType implements NumerationSystem { + _16, + _12, + _10, + _9, + _8, + _7, + _6, + _5, + _4, + _3, + _2; + + @Override + public int getNumerationSystemIntValue() { + return Integer.parseInt(this.name().substring(1)); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3001/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3001/Solution.java new file mode 100644 index 0000000..725d839 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3001/Solution.java @@ -0,0 +1,126 @@ +package com.javarush.task.task30.task3001; + +import java.math.BigInteger; +import java.util.HashMap; +import java.util.Map; + +/* +Конвертер систем счислений +*/ +public class Solution { + public static void main(String[] args) { + Number number = new Number(NumerationSystemType._10, "6"); + Number result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._2); + System.out.println(result); //expected 110 + + number = new Number(NumerationSystemType._16, "6df"); + result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._8); + System.out.println(result); //expected 3337 + + /*Number number = new Number(NumerationSystemType._2, "1101001000000001100001001110110111111100110010101000100111011011011001001011001100011001100000111101111"); + Number result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._3); + System.out.println(result); + number = new Number(NumerationSystemType._2, "1101001000000001100001001110110111111100110010101000100111011011011001001011001100011001100000111101111"); + result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._4); + System.out.println(result); + number = new Number(NumerationSystemType._2, "1101001000000001100001001110110111111100110010101000100111011011011001001011001100011001100000111101111"); + result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._5); + System.out.println(result); + number = new Number(NumerationSystemType._2, "1101001000000001100001001110110111111100110010101000100111011011011001001011001100011001100000111101111"); + result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._6); + System.out.println(result); + number = new Number(NumerationSystemType._2, "1101001000000001100001001110110111111100110010101000100111011011011001001011001100011001100000111101111"); + result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._7); + System.out.println(result); + number = new Number(NumerationSystemType._2, "1101001000000001100001001110110111111100110010101000100111011011011001001011001100011001100000111101111"); + result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._8); + System.out.println(result); + number = new Number(NumerationSystemType._2, "1101001000000001100001001110110111111100110010101000100111011011011001001011001100011001100000111101111"); + result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._9); + System.out.println(result); + number = new Number(NumerationSystemType._2, "1101001000000001100001001110110111111100110010101000100111011011011001001011001100011001100000111101111"); + result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._10); + System.out.println(result); + number = new Number(NumerationSystemType._2, "1101001000000001100001001110110111111100110010101000100111011011011001001011001100011001100000111101111"); + result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._12); + System.out.println(result); + number = new Number(NumerationSystemType._2, "1101001000000001100001001110110111111100110010101000100111011011011001001011001100011001100000111101111"); + result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._16); + System.out.println(result);*/ + } + + public static Number convertNumberToOtherNumerationSystem(Number number, NumerationSystem expectedNumerationSystem) { + + BigInteger tempNumber = new BigInteger(number.getDigit(), number.getNumerationSystem().getNumerationSystemIntValue()); + + return new Number(expectedNumerationSystem, tempNumber.toString(expectedNumerationSystem.getNumerationSystemIntValue())); + + // Собственная реализация для небольших чисел + + /*String digits = number.getDigit().toLowerCase(); + int sourceNumSystem = number.getNumerationSystem().getNumerationSystemIntValue(); + Alphabet alphabet = new Alphabet(); + Map map = alphabet.getMap(); + int power = 1; + int decimalNumber = 0; + boolean isMinus = false; + for (int i = digits.length() - 1; i >= 0; i--){ + if (i == 0 && "-".equals(String.valueOf(digits.charAt(i)))) { + isMinus = true; + break; + } + Integer value = map.get(digits.charAt(i)); + //int value = map.get(digits.charAt(i)); + if (value == null || value >= sourceNumSystem) { throw new NumberFormatException(); } + if (power != 0) { + decimalNumber += value * power; + } else { decimalNumber += value; } + power *= sourceNumSystem; + } + + StringBuilder convertedNumberDigits = new StringBuilder(); + while (decimalNumber != 0) { + int digitValue = decimalNumber % expectedNumerationSystem.getNumerationSystemIntValue(); + convertedNumberDigits.append(alphabet.getByValue(digitValue)); + decimalNumber /= expectedNumerationSystem.getNumerationSystemIntValue(); + } + if (isMinus) { convertedNumberDigits.append("-"); } + convertedNumberDigits = convertedNumberDigits.reverse(); + return new Number(expectedNumerationSystem, convertedNumberDigits.toString());*/ + } + + // Собственная реализация для небольших чисел + /*private static class Alphabet{ + private Map map = new HashMap<>(); + + public Alphabet(){ + map.put('0', 0); + map.put('1', 1); + map.put('2', 2); + map.put('3', 3); + map.put('4', 4); + map.put('5', 5); + map.put('6', 6); + map.put('7', 7); + map.put('8', 8); + map.put('9', 9); + map.put('a', 10); + map.put('b', 11); + map.put('c', 12); + map.put('d', 13); + map.put('e', 14); + map.put('f', 15); + } + + public Map getMap() { + return map; + } + + public Character getByValue(int value){ + for (Map.Entry entry : map.entrySet()){ + if (entry.getValue().equals(value)) { return entry.getKey(); } + } + return null; + } + }*/ +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3001/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3001/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..fef2ef0 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3001/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,19 @@ +taskKey="com.javarush.task.task30.task3001" + +Конвертер систем счислений + +Реализуй логику метода convertNumberToOtherNumerationSystem, который должен переводить число number.getDigit(). +из одной системы счисления(numerationSystem) в другую (expectedNumerationSystem). +Брось NumberFormatException, если переданное число некорректно, например, число "120" с системой счисления 2. +Валидация для - number.getDigit() - целое не отрицательное. +Метод main не участвует в тестировании. + + +Требования: +1. Метод convertNumberToOtherNumerationSystem (Number, NumerationSystem), возвращающий тип Number, должен существовать. +2. Должно бросаться исключение NumberFormatException, если переданное число некорректно в заданной системе счисления. +3. Необходимо корректно реализовать метод convertNumberToOtherNumerationSystem - перевод числа в указанную систему счисления. +4. Enum NumerationSystemType должен поддерживать интерфейс NumerationSystem. +5. В enum-е NumerationSystemType должно присутствовать 11 значений оснований систем счисления. Основания: 2, 3, 4, 5, 6, 7, 8, 9, 10, 12 и 16. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3002/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3002/Solution.java new file mode 100644 index 0000000..234e9bb --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3002/Solution.java @@ -0,0 +1,29 @@ +package com.javarush.task.task30.task3002; + +/* +Осваиваем методы класса Integer +*/ +public class Solution { + + public static void main(String[] args) { + System.out.println(convertToDecimalSystem("0x16")); //22 + System.out.println(convertToDecimalSystem("012")); //10 + System.out.println(convertToDecimalSystem("0b10")); //2 + System.out.println(convertToDecimalSystem("62")); //62 + } + + public static String convertToDecimalSystem(String s) { + //напишите тут ваш код + if (s.length() > 1 && "0".equals(String.valueOf(s.charAt(0)))) { + if ("x".equals(String.valueOf(s.charAt(1)))) { + s = String.valueOf(Integer.parseInt(s.substring(2), 16)); + }else if ("b".equals(String.valueOf(s.charAt(1)))){ + s = String.valueOf(Integer.parseInt(s.substring(2), 2)); + }else { + s = String.valueOf(Integer.parseInt(s, 8)); + } + } + + return s; + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3002/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3002/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..01edae3 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3002/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,16 @@ +taskKey="com.javarush.task.task30.task3002" + +Осваиваем методы класса Integer + +Используя метод Integer.parseInt(String, int) реализуй логику метода convertToDecimalSystem, +который должен переводить переданную строку в десятичное число и возвращать его в виде строки. + + +Требования: +1. Метод convertToDecimalSystem (String), возвращающий String, должен существовать. +2. Метод convertToDecimalSystem (String), возвращающий String, должен иметь модификаторы доступа: public, static. +3. Метод convertToDecimalSystem (String), возвращающий String, должен переводить переданную строку в десятичное число и возвращать его в виде строки. +4. Метод convertToDecimalSystem (String) должен вызывать метод Integer.parseInt(String, int). +5. Метод main (String[]), возвращающий void, должен иметь модификаторы доступа: public, static. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3009/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3009/Solution.java new file mode 100644 index 0000000..b58c99e --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3009/Solution.java @@ -0,0 +1,23 @@ +package com.javarush.task.task30.task3009; + +import java.util.HashSet; +import java.util.Set; + +/* +Палиндром? +*/ + +public class Solution { + public static void main(String[] args) { + System.out.println(getRadix("112")); //expected output: [3, 27, 13, 15] + System.out.println(getRadix("123")); //expected output: [6] + System.out.println(getRadix("5321")); //expected output: [] + System.out.println(getRadix("1A")); //expected output: [] + } + + private static Set getRadix(String number){ + Set result = new HashSet<>(); + + return result; + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3009/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3009/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..314e727 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3009/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,23 @@ +taskKey="com.javarush.task.task30.task3009" + +Палиндром? + +Объяви и реализуй логику приватного статического метода Set getRadix(String number), в +котором нужно определить, в каких системах счисления (от 2 до 36 включительно) представление числа number +(передается в десятичной системе счисления) является палиндромом и добавить индекс таких систем в результат. +Если переданное число некорректно - возвращай пустой HashSet. +В системах счисления с основанием большим 10 в качестве цифр используются латинские буквы. К примеру, числу +35 в десятичной системе соответствует число "Z" в системе с основанием 36. + +Метод main не принимает участие в тестировании. +P.S.: В методе getRadix перехватывай NumberFormatException. Стек-трейс выводить не нужно. + + +Требования: +1. Необходимо объявить приватный статический метод Set getRadix(String number). +2. Метод getRadix в случае некорректных входных данных должен возвращать пустой HashSet. +3. Методе getRadix не должен бросать NumberFormatException. +4. Метод getRadix не должен ничего выводить в консоль. +5. Метод getRadix должен возвращать множество согласно условию задачи. + + From 1717022701fa36d84c640bcfee461d73282cef38 Mon Sep 17 00:00:00 2001 From: PeucT Date: Fri, 28 Apr 2017 17:53:11 +0400 Subject: [PATCH 36/51] 3009 --- .../com/javarush/task/task30/task3009/Solution.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3009/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3009/Solution.java index b58c99e..0dccfe0 100644 --- a/3.JavaMultithreading/src/com/javarush/task/task30/task3009/Solution.java +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3009/Solution.java @@ -1,5 +1,6 @@ package com.javarush.task.task30.task3009; +import java.math.BigInteger; import java.util.HashSet; import java.util.Set; @@ -17,6 +18,18 @@ public static void main(String[] args) { private static Set getRadix(String number){ Set result = new HashSet<>(); + try { + BigInteger bigInt = new BigInteger(number); + for (int i = 2; i <= 36; i++) { + + String input = bigInt.toString(i); + StringBuilder inputInBuilder = new StringBuilder(input); + StringBuilder compareString = new StringBuilder(input).reverse(); + if (inputInBuilder.toString().equals(compareString.toString())) { result.add(i); } + + } + } catch (NumberFormatException e) { + } return result; } From 024e9d5afce7f34d6bb0e1767b93bd4696a395ce Mon Sep 17 00:00:00 2001 From: PeucT Date: Fri, 28 Apr 2017 18:10:36 +0400 Subject: [PATCH 37/51] 3010 --- .../task/task30/task3010/Solution.java | 28 +++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 36 +++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3010/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task30/task3010/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3010/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3010/Solution.java new file mode 100644 index 0000000..86f500a --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3010/Solution.java @@ -0,0 +1,28 @@ +package com.javarush.task.task30.task3010; + +/* +Минимальное допустимое основание системы счисления +*/ + +import java.math.BigInteger; + +public class Solution { + public static void main(String[] args) { + //напишите тут ваш код + if (args == null || args.length == 0) { return; } + String input = new String(args[0]); + input = input.replaceAll("[0-9a-zA-Z]", ""); + if (input.length() != 0) { System.out.println("incorrect"); } + else { + input = new String(args[0]).toLowerCase(); + for (int i = 2; i <= 36; i++){ + try { + BigInteger bigI = new BigInteger(input, i); + System.out.println(i); + break; + } catch (NumberFormatException e){ + } + } + } + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3010/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3010/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..1a1839c --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3010/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,36 @@ +taskKey="com.javarush.task.task30.task3010" + +Минимальное допустимое основание системы счисления + +В метод main первым аргументом приходит строка, которая содержит последовательность символов (Все символы в +строке имеют коды в таблице ASCII от 32 до 127 включительно). Длина строки не превышает 255 символов. Нужно +реализовать программу, которая по входящей строке определит, является ли содержимое строки записью числа в +системе счисления с основанием не больше 36 включительно. Если является - нужно вывести минимальное +основание системы счисления, в которой это число может существовать. Если не является - необходимо вывести +"incorrect". +В системах счисления с основанием большим 10 в качестве цифр используются латинские буквы. К примеру, числу +35 в десятичной системе соответствует число "Z" в системе с основанием 36. Так как рассматриваем +позиционные системы счисления - минимальное основание, которое должна выводить программа, это 2. +Если возникают любые исключения - перехватывай их и не выводи стек-трейс. + +Пример1: +Вход: 00 +Ожидаемый вывод: 2 + +Пример2: +Вход: 12AS08z +Ожидаемый вывод: 36 + +Пример3: +Вход: 12AS08Z/ +Ожидаемый вывод: incorrect + + +Требования: +1. Если возникло любое исключение - необходимо перехватить его и не выводить стек-трейс. +2. Если входящая строка содержит что-либо, кроме латинских букв и цифр - необходимо вывести "incorrect". +3. Если входящая строка корректна - необходимо вывести основание системы счисления. +4. Минимальное основание, которое выводит программа должно равняться 2. +5. Вывод программы должен соответствовать условию. + + From edb12795d16cbb2e76d9f62ef85d8c4f033c9c4d Mon Sep 17 00:00:00 2001 From: PeucT Date: Tue, 2 May 2017 16:54:32 +0400 Subject: [PATCH 38/51] Level 30. task 3003 --- .../task/task30/task3003/Consumer.java | 29 +++++++++ .../task/task30/task3003/Producer.java | 33 +++++++++++ .../task/task30/task3003/ShareItem.java | 59 +++++++++++++++++++ .../task/task30/task3003/Solution.java | 31 ++++++++++ .../javarush/task/task30/task3003/output.txt | 23 ++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 36 +++++++++++ 6 files changed, 211 insertions(+) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3003/Consumer.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3003/Producer.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3003/ShareItem.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3003/Solution.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3003/output.txt create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task30/task3003/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3003/Consumer.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/Consumer.java new file mode 100644 index 0000000..90ba2b5 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/Consumer.java @@ -0,0 +1,29 @@ +package com.javarush.task.task30.task3003; + +import java.util.concurrent.TransferQueue; + +/** + * Created by ArchMage on 02.05.17. + */ +public class Consumer implements Runnable { + private TransferQueue queue; + + public Consumer(TransferQueue queue) { + this.queue = queue; + } + + @Override + public void run() { + try { + Thread.sleep(450); + while (true) { + ShareItem item = queue.take(); + System.out.format("Processing %s\r\n", item.toString()); + + } + } catch (InterruptedException e) { + return; + } + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3003/Producer.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/Producer.java new file mode 100644 index 0000000..a87ec87 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/Producer.java @@ -0,0 +1,33 @@ +package com.javarush.task.task30.task3003; + +import java.util.concurrent.TransferQueue; + +/** + * Created by ArchMage on 02.05.17. + */ +public class Producer implements Runnable { + private TransferQueue queue; + + public Producer(TransferQueue queue) { + this.queue = queue; + } + + @Override + public void run() { + + try { + for (int i = 1; i <= 9; i++ ) { + System.out.format("Элемент 'ShareItem-%d' добавлен\r\n", i); + queue.offer(new ShareItem("ShareItem-" + i, i)); + + Thread.sleep(100); + + if (queue.hasWaitingConsumer()) { + System.out.format("Consumer в ожидании!\r\n"); + } + } + } catch (InterruptedException e) { + return; + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3003/ShareItem.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/ShareItem.java new file mode 100644 index 0000000..b57f012 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/ShareItem.java @@ -0,0 +1,59 @@ +package com.javarush.task.task30.task3003; + +//This class shows how to call other constructors using 'this' +public class ShareItem { + public String description; + public int itemId; + + public ShareItem() { + this("Test Item", 0); + } + + public ShareItem(String description) { + this(description, 0); + } + + public ShareItem(int itemId) { + this("Test Item", itemId); + } + + public ShareItem(String description, int itemId) { + this.description = description; + this.itemId = itemId; + } + + public String getDescription() { + return description; + } + + public int getItemId() { + return itemId; + } + + @Override + public String toString() { + return "ShareItem{" + + "description='" + description + '\'' + + ", itemId=" + itemId + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ShareItem shareItem = (ShareItem) o; + + if (itemId != shareItem.itemId) return false; + return description != null ? description.equals(shareItem.description) : shareItem.description == null; + + } + + @Override + public int hashCode() { + int result = description != null ? description.hashCode() : 0; + result = 31 * result + itemId; + return result; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3003/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/Solution.java new file mode 100644 index 0000000..c529130 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/Solution.java @@ -0,0 +1,31 @@ +package com.javarush.task.task30.task3003; + +import java.util.concurrent.LinkedTransferQueue; +import java.util.concurrent.TransferQueue; + +/* +Экономим время +*/ +public class Solution { + /* + 1. Создай класс Producer. Для этого на красном имени класса нажми Alt+Enter -> Create Class ... + 2. Стань на имени аргумента в конструкторе (queue) и нажми Alt+Enter -> Create Field for Parameter 'queue' -> Enter -> Enter. Имя поля - queue. + 3. Стань на подчеркнутой строке - описании класса. Далее Alt+Enter -> Implement Methods -> Enter. + 4. Проделай п.1-3 для класса Consumer. + */ + + public static void main(String[] args) throws InterruptedException { + TransferQueue queue = new LinkedTransferQueue<>(); + + Thread producer = new Thread(new Producer(queue)); + Thread consumer = new Thread(new Consumer(queue)); + producer.start(); + consumer.start(); + + Thread.sleep(1500); + + producer.interrupt(); + consumer.interrupt(); + } + +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3003/output.txt b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/output.txt new file mode 100644 index 0000000..4f11512 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/output.txt @@ -0,0 +1,23 @@ +Элемент 'ShareItem-1' добавлен +Элемент 'ShareItem-2' добавлен +Элемент 'ShareItem-3' добавлен +Элемент 'ShareItem-4' добавлен +Элемент 'ShareItem-5' добавлен +Processing ShareItem{description='ShareItem-1', itemId=1} +Processing ShareItem{description='ShareItem-2', itemId=2} +Processing ShareItem{description='ShareItem-3', itemId=3} +Processing ShareItem{description='ShareItem-4', itemId=4} +Processing ShareItem{description='ShareItem-5', itemId=5} +Consumer в ожидании! +Элемент 'ShareItem-6' добавлен +Processing ShareItem{description='ShareItem-6', itemId=6} +Consumer в ожидании! +Элемент 'ShareItem-7' добавлен +Processing ShareItem{description='ShareItem-7', itemId=7} +Consumer в ожидании! +Элемент 'ShareItem-8' добавлен +Processing ShareItem{description='ShareItem-8', itemId=8} +Consumer в ожидании! +Элемент 'ShareItem-9' добавлен +Processing ShareItem{description='ShareItem-9', itemId=9} +Consumer в ожидании! \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3003/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..6cbafc1 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,36 @@ +taskKey="com.javarush.task.task30.task3003" + +Экономим время + +1. Создай Producer и Consumer (См. комментарий к методу main). +2. Создай методы toString, equals и hashCode в классе ShareItem. Для этого в IntelliJ IDEA в теле класса ShareItem выполни: +2.1. Alt+Enter -> toString() -> Enter. +2.2. Alt+Enter -> equals() and hashCode() -> click all 'Next'-s. +2.3. Реализацию методов toString(), equals() и hashCode() оставь такими, какими их сгенерировала IntelliJ IDEA. +3. В Producer и Consumer реализуй метод run так, чтобы вызов метода interrupt прерывал работу consumer и producer трэдов. + +4. Реализация метода run для Producer: +4.1. Используя метод offer добавь в очередь 9 ShareItem-ов с такими параметрами: ("ShareItem-N", N), где N - номер элемента от 1 до 9. +4.2. Перед каждым добавлением выведи фразу "Элемент 'ShareItem-N' добавлен". Используй System.out.format. +4.3. Усыпи трэд на 0.1 секунды. +4.4. Если у очереди есть Consumer, не занятый работой, то выведи фразу "Consumer в ожидании!". +Просмотри методы интерфейса TransferQueue, там есть нужный метод. + +5. Реализация метода run для Consumer: +5.1. Усыпи трэд на 0.45 секунды. +5.2. В бесконечном цикле забери элемент из очереди методом take и выведи в консоль "Processing item.toString()". + +6. Сверь вывод с файлом output.txt. +7. Стек-трейс не выводи в консоль. +8. Для вывода любой информации на экран используй System.out.format. + + +Требования: +1. Создай класс Producer. +2. Создай класс Consumer. +3. В классе ShareItem должны быть созданы методы: toString(), equals(Object) и hashCode(). +4. Метод run() класса Producer должен быть реализован согласно условию задачи. +5. Метод run() класса Consumer должен быть реализован согласно условию задачи. +6. Вывод должен совпадать с файлом output.txt. + + From 2f93b1a1540d9a1fc2c6e8fb88ceddcc78ecae0b Mon Sep 17 00:00:00 2001 From: PeucT Date: Wed, 3 May 2017 18:46:01 +0400 Subject: [PATCH 39/51] Level 30. Full. --- .../task3004/BinaryRepresentationTask.java | 27 +++++ .../task/task30/task3004/Solution.java | 31 +++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 18 +++ .../task/task30/task3005/Solution.java | 60 ++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 20 ++++ .../javarush/task/task30/task3006/Pair.java | 22 ++++ .../task/task30/task3006/Solution.java | 18 +++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 19 ++++ .../task/task30/task3007/Solution.java | 22 ++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 25 ++++ .../task/task30/task3011/Solution.java | 107 ++++++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 18 +++ .../task/task30/task3012/Solution.java | 49 ++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 37 ++++++ .../task/task30/task3013/Solution.java | 27 +++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 47 ++++++++ 16 files changed, 547 insertions(+) create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3004/BinaryRepresentationTask.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3004/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task30/task3004/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3005/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task30/task3005/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3006/Pair.java create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3006/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task30/task3006/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3007/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task30/task3007/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3011/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task30/task3011/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3012/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task30/task3012/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 3.JavaMultithreading/src/com/javarush/task/task30/task3013/Solution.java create mode 100644 "3.JavaMultithreading/src/com/javarush/task/task30/task3013/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3004/BinaryRepresentationTask.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3004/BinaryRepresentationTask.java new file mode 100644 index 0000000..44049b1 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3004/BinaryRepresentationTask.java @@ -0,0 +1,27 @@ +package com.javarush.task.task30.task3004; + +import java.util.concurrent.RecursiveTask; + +/** + * Created by ArchMage on 02.05.17. + */ +public class BinaryRepresentationTask extends RecursiveTask { + private int i; + + public BinaryRepresentationTask(int i) { + this.i = i; + } + + @Override + protected String compute() { + int a = i % 2; + int b = i / 2; + String result = String.valueOf(a); + if (b > 0) { + BinaryRepresentationTask task = new BinaryRepresentationTask(b); + task.fork(); + return task.join() + result; + } + return result; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3004/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3004/Solution.java new file mode 100644 index 0000000..89aac39 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3004/Solution.java @@ -0,0 +1,31 @@ +package com.javarush.task.task30.task3004; + +import java.util.concurrent.ForkJoinPool; + +/* +Fork/Join +*/ +public class Solution { + private String binaryRepresentationMethod(int x) { + int a = x % 2; + int b = x / 2; + String result = String.valueOf(a); + if (b > 0) { + return binaryRepresentationMethod(b) + result; + } + return result; + } + + + public static void main(String[] args) { + Solution solution = new Solution(); + String result1 = solution.binaryRepresentationMethod(6); + System.out.println(result1); + + System.out.println(); + ForkJoinPool forkJoinPool = new ForkJoinPool(); + String result2 = forkJoinPool.invoke(new BinaryRepresentationTask(6)); + System.out.println(result2); + } + +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3004/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3004/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..e179689 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3004/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,18 @@ +taskKey="com.javarush.task.task30.task3004" + +Fork/Join + +1. Создай класс BinaryRepresentationTask. Для этого в IntelliJ IDEA на красном имени класса нажми Alt+Enter -> Create Class ... +(класс должен наследоваться от RecursiveTask). Параметр конструктора - int x. +2. Реализуй логику метода compute - число должно переводиться в двоичное представление. +3. Используй методы fork и join. +4. Пример функциональной реализации - метод binaryRepresentationMethod. + + +Требования: +1. Создай класс BinaryRepresentationTask. +2. В классе BinaryRepresentationTask должен быть переопределен метод compute(). +3. В классе BinaryRepresentationTask в методе compute() используй методы fork() и join(). +4. Метод compute() должен правильно переводить число в двоичную систему счисления. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3005/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3005/Solution.java new file mode 100644 index 0000000..ae2982a --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3005/Solution.java @@ -0,0 +1,60 @@ +package com.javarush.task.task30.task3005; + +import java.util.ArrayList; +import java.util.List; + +/* +Такие хитрые исключения! +*/ +public class Solution { + public static void main(String[] args) { + checkAFlag(new D()); + } + + public static void checkAFlag(D d) { + if ( + d != null + && d.cs != null + && d.cs.size() > 0 + && d.cs.get(0).bs != null + && d.cs.get(0).bs.size() > 0 + && d.cs.get(0).bs.get(0).as != null + && d.cs.get(0).bs.get(0).as.size() > 0 + && d.cs.get(0).bs.get(0).as.get(0) != null + && d.cs.get(0).bs.get(0).as.get(0).flag ) + + { + System.out.println("A's flag is true"); + } else { //all other cases + System.out.println("Oops!"); + } + } + + static class A { + boolean flag = true; + } + + static class B { + List as = new ArrayList<>(); + + { + as.add(new A()); + } + } + + static class C { + List bs = new ArrayList<>(); + + { + bs.add(new B()); + } + } + + static class D { + List cs = new ArrayList<>(); + + { + cs.add(new C()); + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3005/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3005/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..9ea4b0b --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3005/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,20 @@ +taskKey="com.javarush.task.task30.task3005" + +Такие хитрые исключения! + +Исправь реализацию метода checkAFlag, чтобы во всех случаях он не приводил к бросанию исключений. +Сохрани логику вывода данных. +Метод main не участвует в тестировании. + + +Требования: +1. В методе checkAFlag должна быть проверка, что d, пришедший в качестве параметра не null. Иначе вывод "Oops!". +2. В методе checkAFlag должна быть проверка, что d.cs не null. Иначе вывод "Oops!". +3. В методе checkAFlag должна быть проверка, что d.cs содержит хотя бы один элемент. Иначе вывод "Oops!". +4. В методе checkAFlag должна быть проверка, что d.cs.get(0).bs не null. Иначе вывод "Oops!". +5. В методе checkAFlag должна быть проверка, что d.cs.get(0).bs содержит хотя бы один элемент. Иначе вывод "Oops!". +6. В методе checkAFlag должна быть проверка, что d.cs.get(0).bs.get(0).as не null. Иначе вывод "Oops!". +7. В методе checkAFlag должна быть проверка, что d.cs.get(0).bs.get(0).as содержит хотя бы один элемент. Иначе вывод "Oops!". +8. В методе checkAFlag должна быть проверка, что d.cs.get(0).bs.get(0).as.get(0).flag равен true. Иначе вывод "Oops!". + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3006/Pair.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3006/Pair.java new file mode 100644 index 0000000..3d0173b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3006/Pair.java @@ -0,0 +1,22 @@ +package com.javarush.task.task30.task3006; + +public class Pair { + private int x; + private int y; + + public Pair(int x, int y) { + this.x = x; + this.y = y; + } + + @Override + public String toString() { + return String.format("x=%d, y=%d", x, y); + } + + public void swap() { + y = x ^ y; + x = x ^ y; + y = x ^ y; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3006/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3006/Solution.java new file mode 100644 index 0000000..e6ecbe6 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3006/Solution.java @@ -0,0 +1,18 @@ +package com.javarush.task.task30.task3006; + +/* +Swap по-новому +*/ +public class Solution { + public static void main(String[] args) { + /* expected output + x=4, y=5 + x=5, y=4 + */ + + Pair pair = new Pair(4, 5); + System.out.println(pair); + pair.swap(); + System.out.println(pair); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3006/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3006/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..9e290c5 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3006/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,19 @@ +taskKey="com.javarush.task.task30.task3006" + +Swap по-новому + +В классе Pair реализуй метод swap, который должен для x, y менять местами их значения. +Можно использовать только операции: +1) Исключающее или. +2) Присваивание. +3) Исключающее или с присваиванием. +Не оставляй комментарии, не меняй остальной код. + + +Требования: +1. В классе Pair должен присутствовать метод swap(). +2. В классе Pair в методе swap() используй только разрешенные операции. +3. Вызов метода swap() должен поменять значения полей x и y. +4. Не изменяй никакой код, кроме метода swap(). + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3007/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3007/Solution.java new file mode 100644 index 0000000..d9d0752 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3007/Solution.java @@ -0,0 +1,22 @@ +package com.javarush.task.task30.task3007; + +/* +Найдем число 2 в максимальной степени +*/ +public class Solution { + public static void main(String[] args) { + System.out.println(maxPowerOf2(140_000)); //131072 + System.out.println(maxPowerOf2(1026)); //1024 + System.out.println(maxPowerOf2(17)); //16 + } + + public static int maxPowerOf2(int x) { + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x = x & (~(x>>1)); + return x; + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3007/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3007/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..3acc942 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3007/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,25 @@ +taskKey="com.javarush.task.task30.task3007" + +Найдем число 2 в максимальной степени + +Реализуй логику метода maxPowerOf2, который должен возвращать число 2 в максимальной степени, которое получается поместить в переданное число. +Аргументом maxPowerOf2 может быть только положительное целое число. +Используй только операции: +1) Побитовые сдвиги. +2) Побитовое OR. +3) Побитовое AND. +4) Побитовый унарный оператор NOT. +5) Присваивание (можно совмещать разрешенные операции с присваивание, например, &=). +6) Круглые скобки. +Не оставляй комментарии. +Не объявляй никаких переменных, используй только x, который приходит как аргумент метода maxPowerOf2. +Метод main не принимает участия в тестировании. + + +Требования: +1. В классе Solution должен присутствовать метод maxPowerOf2(int). +2. В классе Solution в методе maxPowerOf2(int) используй только разрешенные операции. +3. В классе Solution в методе maxPowerOf2(int) используй только разрешенные операции. +4. Метод maxPowerOf2(int) должен возвращать число 2 в максимальной степени, которое получается поместить в переданное число. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3011/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3011/Solution.java new file mode 100644 index 0000000..f342766 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3011/Solution.java @@ -0,0 +1,107 @@ +package com.javarush.task.task30.task3011; + +/* +Сделай одно изменение кода +*/ + +public class Solution { + public static void main(String[] args) { + Solution solution = new Solution(); + solution.doSmth(new A(), null, null); + } + + public void doSmth(A a, B b, C c) { + try { + if (a != null && a.getName() != null) { + //do nothing + } + } catch (NullPointerException e) { + a = new A(); + a.setName("A"); + } + try { + if (a != null && a.getName() == null) { + a.setName("A"); + } + } catch (NullPointerException e) { + } + if (a == null) { + a = new A(); + a.setName("A"); + } + try { + if (b != null && b.getName() != null) { + //do nothing + } + } catch (NullPointerException e) { + b = new B(); + b.setName("B"); + } + try { + if (b != null && b.getName() == null) { + b.setName("B"); + } + } catch (NullPointerException e) { + } + if (b == null) { + b = new B(); + b.setName("B"); + } + try { + if (c != null & c.getName() != null) { + } + } catch (NullPointerException e) { + c = new C(); + c.setName("C"); + } + try { + if (c != null && c.getName() == null) { + c.setName("C"); + } + } catch (NullPointerException e) { + } + if (c == null) { + c = new C(); + c.setName("null"); + } + System.out.print(a.getName()); + System.out.print(b.getName()); + System.out.print(c.getName()); + } + + static class A { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + static class B { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + static class C { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3011/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3011/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..8eeca71 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3011/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,18 @@ +taskKey="com.javarush.task.task30.task3011" + +Сделай одно изменение кода + +Внеси одну правку в код программы, чтобы вывод всегда был "ABC", даже если в метод doSmth +передавать параметрами null. +Не изменяй и не добавляй строковые литералы. Не изменяй строки с выводом данных на экран. +Не добавляй сеттеры. + + +Требования: +1. Вывод метода doSmth должен быть "ABC", если в него передать объекты типа A, B и C. +2. Вывод метода doSmth должен быть "ABC", если в него передать null, null, null. +3. Запрещено изменять или добавлять строковые литералы, запрещено добавлять сеттеры. +4. Запрещено изменять строки с выводом данных на экран. +5. Необходимо внести одну правку в код программы. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3012/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3012/Solution.java new file mode 100644 index 0000000..5f13255 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3012/Solution.java @@ -0,0 +1,49 @@ +package com.javarush.task.task30.task3012; + +/* +Получи заданное число +*/ + + +public class Solution { + public static void main(String[] args) { + Solution solution = new Solution(); + solution.createExpression(74); + //System.out.println(Integer.toString(74, 3)); + } + + + public void createExpression(int number) { + int[] array = {1, 3, 9, 27, 81, 243, 729, 2187}; + String resultStr = number + " ="; + for (int i = 0; i < 6560; i++){ + String tryString = String.format("%08d" ,Integer.parseInt(Integer.toString(i, 3))); + int summ = 0; + for (int j = 0; j < 8; j++){ + if ("0".equals(String.valueOf(tryString.charAt(j)))){ + summ += array[j]; + }else if ("1".equals(String.valueOf(tryString.charAt(j)))) { + + }else if ("2".equals(String.valueOf(tryString.charAt(j)))) { + summ -= array[j]; + } + } + if (summ == number) { + for (int j = 0; j < 8; j++){ + if ("0".equals(String.valueOf(tryString.charAt(j)))) { + resultStr = resultStr + " + " + array[j]; + }else if ("1".equals(String.valueOf(tryString.charAt(j)))) { + + }else if ("2".equals(String.valueOf(tryString.charAt(j)))) { + resultStr = resultStr + " - " + array[j]; + } + } + break; + } + } + System.out.println(resultStr); + //напишите тут ваш код + } + + +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3012/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3012/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..899d525 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3012/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,37 @@ +taskKey="com.javarush.task.task30.task3012" + +Получи заданное число + +Реализуй метод createExpression(int number). +Метод createExpression вызывается с одним параметром number. Этот параметр - число от 1 до 3000 включительно. +Нужно вывести арифметическое выражение, результатом которого является число number. +Можно использовать числа: 1, 3, 9, 27, 81, 243, 729, 2187 не более, чем по одному разу. +Можно использовать знаки: "+" и "-" любое количество раз. +Обрати внимание, что перед каждым числом в искомой строке обязательно должен быть знак плюс или минус. +Перед выражением выведи [переданное число] =. (Смотри примеры вывода ниже). + +Пример1: +Переданное число: 74 +Ожидаемый вывод: 74 = - 1 + 3 - 9 + 81 + +Пример2: +Переданное число: 1234 +Ожидаемый вывод: 1234 = + 1 - 9 + 27 - 243 - 729 + 2187 + +При выводе выражения используй числа ТОЛЬКО В ВОЗРАСТАЮЩЕМ порядке! +Переданное число: 2 +Ожидаемый вывод: 2 = - 1 + 3 //правильно +Ожидаемый вывод: 2 = + 3 - 1 //НЕ правильно +Метод main не участвует в тестировании. + +Подсказка: +Почитай в интернете про троичную симметричную систему счисления. + + +Требования: +1. В начале строчки вывода должно быть расположено число, которое передано в метод createExpression в качестве параметра и знак "=". +2. В выражении можно использовать только числа: 1, 3, 9, 27, 81, 243, 729, 2187 не более, чем по одному разу. +3. В выражении можно использовать только знаки "+" и "-" любое количество раз. +4. Метод createExpression должен быть реализован согласно условию. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3013/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3013/Solution.java new file mode 100644 index 0000000..f10ad6a --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3013/Solution.java @@ -0,0 +1,27 @@ +package com.javarush.task.task30.task3013; + +/* +Набираем код +*/ + +public class Solution { + public static void main(String[] args) { + Solution solution = new Solution(); + int number = Integer.MAX_VALUE - 133; + System.out.println(Integer.toString(number, 2)); + + String result = Integer.toString(solution.resetLowerBits(number), 2); + System.out.println(result); + } + + public int resetLowerBits(int number) { + number |= number >> 1; + number |= number >> 2; + number |= number >> 4; + number |= number >> 8; + number |= number >> 16; + number = number & (~number >> 1); + return number; + //напишите тут ваш код + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3013/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3013/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..0a7ab12 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3013/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,47 @@ +taskKey="com.javarush.task.task30.task3013" + +Набираем код + +Необходимо реализовать публичный метод int resetLowerBits(int number), который обнуляет все биты в числе +number, кроме самого старшего равного единице, и возвращает это число. +Число типа int это 4 байта = 32 бита. Если в метод передано число 3456, его представление в виде битов +будет 00000000 00000000 00001101 10000000. В методе нужно обнулить все младшие биты, то есть на выходе +ожидается что число, представленное в виде битов, будет иметь вид: 00000000 00000000 00001000 00000000. +Это число 2048. +Еще несколько примеров: +Пример 1: +на входе: 1 +на выходе: 1 + +Пример 2: +на входе: 4 +на выходе: 4 + +Пример 3: +на входе: 255 +на выходе: 128 + +Параметр метода resetLowerBits может быть от 1 до Integer.MAX_VALUE включительно. +Используй только операции: +1) = +2) | +3) & +4) >> +5) << +6) ~ +7) цифры от 0 до 9 включительно +8) круглые скобки +9) оператор "return" для возврата результата метода. + +ЗАПРЕЩЕНО создавать переменные, использовать циклы, условные операторы и прочее. +Имя параметра метода resetLowerBits не изменяй (должно быть "number"). +Метод main не принимает участия в тестировании. + + +Требования: +1. В классе Solution должен присутствовать публичный метод int resetLowerBits(int). +2. Параметр метода resetLowerBits(int) должен называться number. +3. В классе Solution в методе resetLowerBits(int) используй только разрешенные операции. +4. Метод resetLowerBits должен работать согласно условию задачи. + + From 57f17a7d92ce7f6b2a5e154afb5e3f977a62d894 Mon Sep 17 00:00:00 2001 From: PeucT Date: Tue, 9 May 2017 21:13:12 +0300 Subject: [PATCH 40/51] Level 31. 3101, 3102, 3111 --- .../task/task31/task3101/FileUtils.java | 14 ++++ .../task/task31/task3101/Solution.java | 65 ++++++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 23 +++++++ .../task/task31/task3102/Solution.java | 34 ++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 17 +++++ .../task31/task3111/SearchFileVisitor.java | 66 +++++++++++++++++++ .../task/task31/task3111/Solution.java | 30 +++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 32 +++++++++ 8 files changed, 281 insertions(+) create mode 100644 4.JavaCollections/src/com/javarush/task/task31/task3101/FileUtils.java create mode 100644 4.JavaCollections/src/com/javarush/task/task31/task3101/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task31/task3101/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task31/task3102/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task31/task3102/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task31/task3111/SearchFileVisitor.java create mode 100644 4.JavaCollections/src/com/javarush/task/task31/task3111/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task31/task3111/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3101/FileUtils.java b/4.JavaCollections/src/com/javarush/task/task31/task3101/FileUtils.java new file mode 100644 index 0000000..401986f --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3101/FileUtils.java @@ -0,0 +1,14 @@ +package com.javarush.task.task31.task3101; + +import java.io.File; + +public class FileUtils { + + public static void deleteFile(File file) { + if (!file.delete()) System.out.println("Can not delete file with name " + file.getName()); + } + + public static void renameFile(File source, File destination) { + if (!source.renameTo(destination)) System.out.println("Can not rename file with name " + source.getName()); + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3101/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3101/Solution.java new file mode 100644 index 0000000..02f1b6b --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3101/Solution.java @@ -0,0 +1,65 @@ +package com.javarush.task.task31.task3101; + +import java.io.File; +import java.io.FileOutputStream; + +import java.io.IOException; +import java.nio.file.*; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +/* +Проход по дереву файлов +*/ +public class Solution { + public static void main(String[] args) { + if (args[0] == null || args[1] == null){ return; } + File baseOutFile = new File(args[1]); + Path dirPath = Paths.get(args[0]); + File outFile = new File(baseOutFile.getParent() + File.separator + "allFilesContent.txt"); + FileUtils.renameFile(baseOutFile, outFile); + ArrayList fileList = new ArrayList<>(); + + try (FileOutputStream outputStream = new FileOutputStream(outFile)) { + Files.walkFileTree(dirPath, new SimpleFileVisitor(){ + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs){ + File currentFile = new File(file.toString()); + if (currentFile.isFile()) { + if (currentFile.length() > 50) { + FileUtils.deleteFile(currentFile); + } else { + fileList.add(currentFile); + } + } + return FileVisitResult.CONTINUE; + } + + }); + + Collections.sort(fileList, new Comparator() { + @Override + public int compare(File o1, File o2) { + return o1.getName().compareTo(o2.getName()); + } + }); + + for (File entry: fileList) { + byte[] content = Files.readAllBytes(entry.toPath()); + outputStream.write(content); + outputStream.write('\n'); + } + + + + } catch (IOException e) { + + } + } + + public static void deleteFile(File file) { + if (!file.delete()) System.out.println("Can not delete file with name " + file.getName()); + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3101/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3101/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..52d4290 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3101/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,23 @@ +taskKey="com.javarush.task.task31.task3101" + +Проход по дереву файлов + +1. На вход метода main подаются два параметра. +Первый - path - путь к директории, второй - resultFileAbsolutePath - имя файла, который будет содержать результат. +2. Для каждого файла в директории path и в ее всех вложенных поддиректориях выполнить следующее: +2.1. Если у файла длина в байтах больше 50, то удалить его (используй метод FileUtils.deleteFile). +2.2. Если у файла длина в байтах НЕ больше 50, то для всех таких файлов: +2.2.1. Отсортировать их по имени файла в возрастающем порядке, путь не учитывать при сортировке. +2.2.2. Переименовать resultFileAbsolutePath в 'allFilesContent.txt' (используй метод FileUtils.renameFile). +2.2.3. В allFilesContent.txt последовательно записать содержимое всех файлов из п. 2.2.1. Тела файлов разделять "n". +Все файлы имеют расширение txt. + + +Требования: +1. Файл, который приходит вторым параметром в main, должен быть переименован в allFilesContent.txt. +2. Нужно создать поток для записи в переименованный файл. +3. Пройдись по всем файлам в директории, которая приходит первым параметром в main, и всех ее поддиректориях. Файлы с размером более 50 байт нужно удалить используя метод FileUtils.deleteFile. +4. Содержимое всех файлов, размер которых не превышает 50 байт, должно быть записано в файл allFilesContent.txt в отсортированном по имени файла порядке. +5. Поток для записи в файл нужно закрыть. + + diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3102/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3102/Solution.java new file mode 100644 index 0000000..c82a89e --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3102/Solution.java @@ -0,0 +1,34 @@ +package com.javarush.task.task31.task3102; + +import java.io.IOException; +import java.nio.file.*; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.List; +import java.util.PriorityQueue; +import java.util.Queue; + + +/* +Находим все файлы +*/ +public class Solution { + public static List getFileTree(String root) throws IOException { + //Queue queue = new PriorityQueue<>(); + List list = new ArrayList<>(); + Files.walkFileTree(Paths.get(root), new SimpleFileVisitor(){ + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + list.add(file.toString()); + return FileVisitResult.CONTINUE; + } + + }); + return list; + + } + + public static void main(String[] args) { + + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3102/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3102/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..6850d66 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3102/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,17 @@ +taskKey="com.javarush.task.task31.task3102" + +Находим все файлы + +Реализовать логику метода getFileTree, который должен в директории root найти список всех файлов включая вложенные. +Используй очередь, рекурсию не используй. +Верни список всех путей к найденным файлам, путь к директориям возвращать не надо. +Путь должен быть абсолютный. + + +Требования: +1. Метод getFileTree должен принимать аргументом String root, по которому нужно найти все вложенные файлы. +2. Метод getFileTree должен возвращать список строк. +3. Нужно реализовать метод getFileTree: найти все файлы по указанному пути и добавить их в список. +4. Метод getFileTree должен быть вызван только 1 раз (рекурсию не использовать). + + diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3111/SearchFileVisitor.java b/4.JavaCollections/src/com/javarush/task/task31/task3111/SearchFileVisitor.java new file mode 100644 index 0000000..24ded0e --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3111/SearchFileVisitor.java @@ -0,0 +1,66 @@ +package com.javarush.task.task31.task3111; + +import java.io.File; +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.List; + +public class SearchFileVisitor extends SimpleFileVisitor { + private int maxSize; + private String partOfName; + private String partOfContent; + private int minSize; + + private List foundFiles = new ArrayList<>(); + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + boolean found = true; + if (maxSize != 0) { + if (Files.size(file) > maxSize) { found = false; } + } + + if (minSize != 0) { + if (Files.size(file) < minSize) { found = false; } + } + + if (partOfName != null) { + if (!(file.getName(file.getNameCount() - 1).toString()).contains(partOfName)) { found = false; } + } + + if (partOfContent != null) { + String content = new String(Files.readAllBytes(file)); + if (!content.contains(partOfContent)) { found = false; } + + + } + + if (found) { + foundFiles.add(file); + } + return super.visitFile(file, attrs); + } + + public void setPartOfName(String partOfName){ + this.partOfName = partOfName; + } + public void setPartOfContent(String partOfContent){ + this.partOfContent = partOfContent; + } + public void setMinSize(int minSize){ + this.minSize = minSize; + + } + public void setMaxSize(int maxSize){ + this.maxSize = maxSize; + } + + public List getFoundFiles(){ + return foundFiles; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3111/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3111/Solution.java new file mode 100644 index 0000000..6517e00 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3111/Solution.java @@ -0,0 +1,30 @@ +package com.javarush.task.task31.task3111; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +/* +Продвинутый поиск файлов +*/ +public class Solution { + + public static void main(String[] args) throws IOException { + SearchFileVisitor searchFileVisitor = new SearchFileVisitor(); + + searchFileVisitor.setPartOfName("amigo"); + searchFileVisitor.setPartOfContent("programmer"); + searchFileVisitor.setMinSize(500); + searchFileVisitor.setMaxSize(10000); + + Files.walkFileTree(Paths.get("D:/SecretFolder"), searchFileVisitor); + + List foundFiles = searchFileVisitor.getFoundFiles(); + for (Path file : foundFiles) { + System.out.println(file); + } + } + +} diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3111/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3111/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..f070a56 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3111/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,32 @@ +taskKey="com.javarush.task.task31.task3111" + +Продвинутый поиск файлов + +Давай реализуем настраиваемый поиск файлов в директории. +Просмотри интерфейс java.nio.file.FileVisitor и его базовую реализацию java.nio.file.SimpleFileVisitor. +Во время поиска по дереву файлов с помощью метода Files.walkFileTree(Path start, FileVisitor visitor) +мы используем объект FileVisitor для выполнения необходимых операций над найденными объектами Path. + +Наш класс для поиска будет называться SearchFileVisitor и расширять SimpleFileVisitor. + +Поиск можно будет выполнять по таким критериям: +- выражение, встречающееся в названии файла (String); +- выражение, встречающееся в содержимом файла (String); +- максимальный и минимальный размер файла (int). +Можно задавать либо один, либо сразу несколько критериев для поиска. + +Я в main написал код, который использует готовый SearchFileVisitor для поиска файлов, тебе осталась совсем легкая задача - выполнить его реализацию. +Подсказка 1: методы get... , set... - это геттеры и сеттеры полей. Основная логика класса по поиску выполняется в методе visitFile(Path file, BasicFileAttributes attrs). +Подсказка 2: для работы с файлами используй только классы из пакета java.nio. + + +Требования: +1. В классе SearchFileVisitor нужно создать поля partOfName, partOfContent, minSize, maxSize и сеттеры для них. +2. В классе SearchFileVisitor нужно создать поле foundFiles и геттер для него. Поле должно быть сразу инициализировано. +3. Если в SearchFileVisitor задан критерий поиска partOfName, метод visitFile должен добавить файл в foundFiles, если в названии содержится строка partOfName. +4. Если в SearchFileVisitor задан критерий поиска partOfContent, метод visitFile должен добавить файл в foundFiles, если в содержимом встречается строка partOfContent. +5. Если в SearchFileVisitor задан критерий поиска maxSize, метод visitFile должен добавить файл в foundFiles, если размер файла меньше maxSize. +6. Если в SearchFileVisitor задан критерий поиска minSize, метод visitFile должен добавить файл в foundFiles, если размер файла больше maxSize. +7. Метод visitFile должен быть реализован так, чтобы учитывать сразу несколько критериев поиска. + + From bf213619fb6b788514683b0aec4e4e896efac191 Mon Sep 17 00:00:00 2001 From: PeucT Date: Wed, 10 May 2017 18:36:33 +0400 Subject: [PATCH 41/51] Level 31. 3103, 3104, 3107, 3108, 3112, 3113 --- .../task/task31/task3103/Solution.java | 28 +++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 22 +++++++ .../task/task31/task3104/Solution.java | 59 +++++++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 19 ++++++ .../task31/task3107/ConcreteFileData.java | 36 +++++++++++ .../task/task31/task3107/FileData.java | 11 ++++ .../task/task31/task3107/NullFileData.java | 33 +++++++++++ .../task/task31/task3107/Solution.java | 28 +++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 18 ++++++ .../task/task31/task3108/Solution.java | 21 +++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 17 ++++++ .../task/task31/task3112/Solution.java | 41 +++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 24 ++++++++ .../task/task31/task3113/Solution.java | 47 +++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 25 ++++++++ 15 files changed, 429 insertions(+) create mode 100644 4.JavaCollections/src/com/javarush/task/task31/task3103/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task31/task3103/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task31/task3104/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task31/task3104/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task31/task3107/ConcreteFileData.java create mode 100644 4.JavaCollections/src/com/javarush/task/task31/task3107/FileData.java create mode 100644 4.JavaCollections/src/com/javarush/task/task31/task3107/NullFileData.java create mode 100644 4.JavaCollections/src/com/javarush/task/task31/task3107/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task31/task3107/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task31/task3108/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task31/task3108/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task31/task3112/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task31/task3112/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task31/task3113/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task31/task3113/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3103/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3103/Solution.java new file mode 100644 index 0000000..e7cf411 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3103/Solution.java @@ -0,0 +1,28 @@ +package com.javarush.task.task31.task3103; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; + +/* +Своя реализация +*/ +public class Solution { + public static byte[] readBytes(String fileName) throws IOException { + return Files.readAllBytes(Paths.get(fileName)); + } + + public static List readLines(String fileName) throws IOException { + return Files.readAllLines(Paths.get(fileName)); + } + + public static void writeBytes(String fileName, byte[] bytes) throws IOException { + Files.write(Paths.get(fileName), bytes); + } + + public static void copy(String resourceFileName, String destinationFileName) throws IOException { + Files.copy(Paths.get(resourceFileName), Paths.get(destinationFileName)); + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3103/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3103/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..801e0c2 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3103/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,22 @@ +taskKey="com.javarush.task.task31.task3103" + +Своя реализация + +Реализуй логику методов: +1. readBytes - должен возвращать все байты файла fileName. +2. readLines - должен возвращать все строки файла fileName. Используй кодировку по умолчанию. +3. writeBytes - должен записывать массив bytes в файл fileName. +4. copy - должен копировать файл resourceFileName на место destinationFileName. + +ГЛАВНОЕ УСЛОВИЕ: +Никаких других импортов! + + +Требования: +1. Импорты в классе Solution менять нельзя. +2. Метод readBytes должен возвращать все байты файла fileName. +3. Метод readLines должен возвращать все строки файла fileName с кодировкой по умолчанию. +4. Метод writeBytes должен записывать массив bytes в файл fileName. +5. Метод copy должен копировать файл resourceFileName на место destinationFileName. + + diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3104/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3104/Solution.java new file mode 100644 index 0000000..ee7d5db --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3104/Solution.java @@ -0,0 +1,59 @@ +package com.javarush.task.task31.task3104; + +import java.io.File; +import java.io.IOException; +import java.nio.file.*; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; + +/* +Поиск скрытых файлов +*/ +public class Solution extends SimpleFileVisitor { + public static void main(String[] args) throws IOException { + EnumSet options = EnumSet.of(FileVisitOption.FOLLOW_LINKS); + final Solution solution = new Solution(); + Files.walkFileTree(Paths.get("D:/"), options, 20, solution); + + List result = solution.getArchived(); + System.out.println("All archived files:"); + for (String path : result) { + System.out.println("\t" + path); + } + + List failed = solution.getFailed(); + System.out.println("All failed files:"); + for (String path : failed) { + System.out.println("\t" + path); + } + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + if (file.toString().endsWith(".zip") || file.toString().endsWith(".rar")) { + archived.add(file.toString()); + } + return super.visitFile(file, attrs); + } + + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { + //FileVisitResult result = super.visitFileFailed(file, exc); + failed.add(file.toString()); + return FileVisitResult.SKIP_SUBTREE; + + } + + private List archived = new ArrayList<>(); + private List failed = new ArrayList<>(); + + public List getArchived() { + return archived; + } + + public List getFailed() { + return failed; + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3104/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3104/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..8e82448 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3104/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,19 @@ +taskKey="com.javarush.task.task31.task3104" + +Поиск скрытых файлов + +В классе Solution переопредели логику двух методов: +-visitFile кроме своей логики должен добавлять в archived все пути к zip и rar файлам +-visitFileFailed должен добавлять в failed все пути к недоступным файлам и возвращать SKIP_SUBTREE +Пример вывода: +D:/mydir/BCD.zip +Метод main не участвует в тестировании + + +Требования: +1. В классе Solution нужно переопределить метод visitFile. +2. Метод visitFile, кроме своей логики, должен добавлять в поле archived все пути к zip и rar файлам. +3. В классе Solution нужно переопределить метод visitFileFailed. +4. Метод visitFileFailed должен добавлять в поле failed все пути к недоступным файлам и возвращать SKIP_SUBTREE. + + diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3107/ConcreteFileData.java b/4.JavaCollections/src/com/javarush/task/task31/task3107/ConcreteFileData.java new file mode 100644 index 0000000..22fabc8 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3107/ConcreteFileData.java @@ -0,0 +1,36 @@ +package com.javarush.task.task31.task3107; + +public class ConcreteFileData implements FileData { + + private boolean hidden; + private boolean executable; + private boolean directory; + private boolean writable; + + public ConcreteFileData(boolean hidden, boolean executable, boolean directory, boolean writable) { + this.hidden = hidden; + this.executable = executable; + this.directory = directory; + this.writable = writable; + } + + @Override + public boolean isHidden() { + return hidden; + } + + @Override + public boolean isExecutable() { + return executable; + } + + @Override + public boolean isDirectory() { + return directory; + } + + @Override + public boolean isWritable() { + return writable; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3107/FileData.java b/4.JavaCollections/src/com/javarush/task/task31/task3107/FileData.java new file mode 100644 index 0000000..30924ad --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3107/FileData.java @@ -0,0 +1,11 @@ +package com.javarush.task.task31.task3107; + +public interface FileData { + boolean isHidden(); + + boolean isExecutable(); + + boolean isDirectory(); + + boolean isWritable(); +} diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3107/NullFileData.java b/4.JavaCollections/src/com/javarush/task/task31/task3107/NullFileData.java new file mode 100644 index 0000000..a59ef39 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3107/NullFileData.java @@ -0,0 +1,33 @@ +package com.javarush.task.task31.task3107; + +public class NullFileData implements FileData { + private Exception exception; + + public NullFileData(Exception e) { + this.exception = e; + } + + public Exception getException() { + return exception; + } + + @Override + public boolean isHidden() { + return false; + } + + @Override + public boolean isExecutable() { + return false; + } + + @Override + public boolean isDirectory() { + return false; + } + + @Override + public boolean isWritable() { + return false; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3107/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3107/Solution.java new file mode 100644 index 0000000..0c0455c --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3107/Solution.java @@ -0,0 +1,28 @@ +package com.javarush.task.task31.task3107; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +/* +Null Object Pattern +*/ +public class Solution { + private FileData fileData; + + public Solution(String pathToFile) { + try { + + fileData = new ConcreteFileData(Files.isHidden(Paths.get(pathToFile)), + Files.isExecutable(Paths.get(pathToFile)), + Files.isDirectory(Paths.get(pathToFile)), + Files.isWritable(Paths.get(pathToFile))); + } catch (Exception e) { + fileData = new NullFileData(e); + } + } + + public FileData getFileData() { + return fileData; + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3107/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3107/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..d989249 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3107/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,18 @@ +taskKey="com.javarush.task.task31.task3107" + +Null Object Pattern + +Почитай на вики про паттерн "Null Object". +Используй Files, чтобы в конструкторе класса Solution правильно инициализировать поле fileData объектом ConcreteFileData. +Если возникли какие-то проблемы со чтением файла по пути pathToFile, то инициализируй поле объектом NullFileData. + + +Требования: +1. Конструктор Solution должен инициализировать поле fileData объектом ConcreteFileData. +2. Если в конструкторе Solution возникла ошибка, нужно инициализировать поле fileData объектом NullFileData. +3. Конструктор Solution должен корректно устанавливать значение поля hidden у объекта ConcreteFileData. +4. Конструктор Solution должен корректно устанавливать значение поля executable у объекта ConcreteFileData. +5. Конструктор Solution должен корректно устанавливать значение поля directory у объекта ConcreteFileData. +6. Конструктор Solution должен корректно устанавливать значение поля writable у объекта ConcreteFileData. + + diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3108/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3108/Solution.java new file mode 100644 index 0000000..9caf9fd --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3108/Solution.java @@ -0,0 +1,21 @@ +package com.javarush.task.task31.task3108; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; + +/* +Исследуем Path +*/ +public class Solution { + public static void main(String[] args) throws IOException { + Path path1 = Paths.get("D:/test/data/firstDir"); + Path path2 = Paths.get("D:/test/data/secondDir/third"); + Path resultPath = getDiffBetweenTwoPaths(path1, path2); + System.out.println(resultPath); //expected output '../secondDir/third' or '..\secondDir\third' + } + + public static Path getDiffBetweenTwoPaths(Path path1, Path path2) { + return path1.relativize(path2); + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3108/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3108/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..cd99cd7 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3108/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,17 @@ +taskKey="com.javarush.task.task31.task3108" + +Исследуем Path + +Почитай про все методы класса Path. +Найди такой, который создает относительный путь между текущим и переданным путем. +Реализуй логику метода getDiffBetweenTwoPaths, он должен возвращать относительный путь. +Метод main не участвует в тестировании. + + +Требования: +1. Класс Solution должен содержать метод Path getDiffBetweenTwoPaths(Path path1, Path path2). +2. Метод Path getDiffBetweenTwoPaths(Path path1, Path path2) должен быть статическим. +3. Метод getDiffBetweenTwoPaths должен возвращать относительный путь между первым аргументом и вторым. +4. Для реализации метода getDiffBetweenTwoPaths используй правильный метод объекта Path. + + diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3112/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3112/Solution.java new file mode 100644 index 0000000..2c55ddf --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3112/Solution.java @@ -0,0 +1,41 @@ +package com.javarush.task.task31.task3112; + +import com.sun.webkit.network.URLs; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.FileAttribute; + +/* +Загрузчик файлов +*/ +public class Solution { + + public static void main(String[] args) throws IOException { + Path passwords = downloadFile("https://www.amigo.com/ship/secretPassword.txt", Paths.get("D:/MyDownloads")); + + for (String line : Files.readAllLines(passwords)) { + System.out.println(line); + } + } + + public static Path downloadFile(String urlString, Path downloadDirectory) throws IOException { + URL url = new URL(urlString); + Path tempFile = Files.createTempFile("temp", "temp"); + + InputStream input = url.openStream(); + Files.copy(input, tempFile); + String fileName = urlString.substring(urlString.lastIndexOf("/") + 1); + Path outFile = Paths.get(downloadDirectory + File.separator + fileName); + Files.move(tempFile, outFile); + + return outFile; + // implement this method + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3112/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3112/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..a1cae6c --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3112/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,24 @@ +taskKey="com.javarush.task.task31.task3112" + +Загрузчик файлов + +Реализуй метод downloadFile(String urlString, Path downloadDirectory), на вход которого подается ссылка для скачивания файла и папка, куда нужно закачать файл. +Все ссылки имеют вид: +https://yastatic.net/morda-logo/i/citylogos/yandex19-logo-ru.png +http://toogle.com/files/rules.txt +https://pacemook.com/photos/image1.jpg + +Метод должен создать объект URL и загрузить содержимое файла на локальный диск. +Выкачивай сначала во временную директорию, чтобы в случае неуспешной загрузки в твоей директории не оставались недокачанные файлы. +Затем перемести файл в пользовательскую директорию. Имя для файла возьми из ссылки. +Используй только классы и методы из пакета java.nio. + + +Требования: +1. Метод downloadFile должен создавать объект URL для переданной ссылки. +2. Метод downloadFile должен создать временный файл с помощью метода Files.createTempFile. +3. Метод downloadFile должен скачать файл по ссылке во временный файл, используя метод Files.copy. +4. Метод downloadFile должен переместить файл из временной директории в пользовательскую, используя метод Files.move. +5. Имя сохраненного файла должно быть таким же, как в URL-ссылке. + + diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3113/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3113/Solution.java new file mode 100644 index 0000000..6baa318 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3113/Solution.java @@ -0,0 +1,47 @@ +package com.javarush.task.task31.task3113; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.file.*; +import java.nio.file.attribute.BasicFileAttributes; + +/* +Что внутри папки? +*/ +public class Solution { + private static int dirCount; + private static int filesCount; + private static long volume; + + public static void main(String[] args) throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + String pathToDirectory = reader.readLine(); + reader.close(); + Path path = Paths.get(pathToDirectory); + if (path == null || !Files.isDirectory(path)) { + System.out.println(path.toString() + " - не папка"); + return; + } + Files.walkFileTree(path, new SimpleFileVisitor(){ + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + filesCount++; + volume += Files.size(file); + return super.visitFile(file, attrs); + } + + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException{ + dirCount++; + return super.preVisitDirectory(dir, attrs); + } + }); + + System.out.println("Всего папок - " + (dirCount - 1)); + System.out.println("Всего файлов - " + filesCount); + System.out.println("Общий размер - " + volume); + + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3113/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3113/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..5538f22 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3113/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,25 @@ +taskKey="com.javarush.task.task31.task3113" + +Что внутри папки? + +Напиши программу, которая будет считать подробную информацию о папке и выводить ее на консоль. + +Первым делом считай путь к папке с консоли. +Если введенный путь не является директорией - выведи "[полный путь] - не папка" и заверши работу. +Затем посчитай и выведи следующую информацию: + +Всего папок - [количество папок в директории] +Всего файлов - [количество файлов в директории и поддиректориях] +Общий размер - [общее количество байт, которое хранится в директории] + +Используй только классы и методы из пакета java.nio. + + +Требования: +1. Метод main должен считывать путь к папке с консоли. +2. Если введенный путь не является директорией - нужно вывести "[полный путь] - не папка" и завершить работу. +3. На консоль должна быть выведена следующая информация: "Всего папок - [количество папок в директории]". +4. На консоль должна быть выведена следующая информация: "Всего файлов - [количество файлов в директории и поддиректориях]". +5. На консоль должна быть выведена следующая информация: "Общий размер - [общее количество байт, которое хранится в директории]". + + From 4fc6b3382c3cd0390c241a3b37082fc3d1cea508 Mon Sep 17 00:00:00 2001 From: PeucT Date: Thu, 11 May 2017 18:30:38 +0400 Subject: [PATCH 42/51] Level 31. 3105, 3106 --- .../task/task31/task3105/Solution.java | 86 +++++++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 36 ++++++++ .../task/task31/task3106/Solution.java | 41 +++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 26 ++++++ 4 files changed, 189 insertions(+) create mode 100644 4.JavaCollections/src/com/javarush/task/task31/task3105/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task31/task3105/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task31/task3106/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task31/task3106/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3105/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3105/Solution.java new file mode 100644 index 0000000..e47e458 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3105/Solution.java @@ -0,0 +1,86 @@ +package com.javarush.task.task31.task3105; + + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + + +/* +Добавление файла в архив +*/ +public class Solution { + private static Map map = new HashMap<>(); + + public static void main(String[] args) throws IOException { + if (args[0] == null || args[1] == null) { return; } + if (!args[1].toString().endsWith(".zip")) { return; } + Path pathToFile = Paths.get(args[0]); + + FileInputStream zipInputAsFile = new FileInputStream(args[1]); + ZipInputStream zipInput = new ZipInputStream(zipInputAsFile); + + + ZipEntry zipEntry; + while ((zipEntry = zipInput.getNextEntry()) != null) { + if (!zipEntry.isDirectory()) { + StringBuilder buffer = new StringBuilder(); + + while (zipInput.available() > 0) { + int symbol = zipInput.read(); + if (symbol != -1) { + buffer.append((char) symbol); + } + } + + map.put(zipEntry.getName(), buffer.toString()); + } + } + zipInput.close(); + zipInputAsFile.close(); + + + + FileOutputStream zipOutAsFile = new FileOutputStream(args[1]); + ZipOutputStream zipOut = new ZipOutputStream(zipOutAsFile); + + boolean isPresent = false; + + for (Map.Entry mapEntry : map.entrySet()) { + zipOut.putNextEntry(new ZipEntry(mapEntry.getKey())); + + if (mapEntry.getKey().contains("/")) { + if (mapEntry.getKey().substring(mapEntry.getKey().lastIndexOf("/") + 1).equals(Paths.get(args[0]).getFileName().toString())){ + Files.copy(Paths.get(args[0]), zipOut); + isPresent = true; + } else { + zipOut.write((mapEntry.getValue().getBytes())); + + } + }else { + if (mapEntry.getKey().equals(Paths.get(args[0]).getFileName().toString())) { + Files.copy(Paths.get(args[0]), zipOut); + isPresent = true; + } else { + zipOut.write((mapEntry.getValue().getBytes())); + } + } + //zipOut.write((mapEntry.getValue().getBytes())); + } + if (!isPresent) { + zipOut.putNextEntry(new ZipEntry("new/" + Paths.get(args[0]).getFileName().toString())); + Files.copy(Paths.get(args[0]), zipOut); + } + + zipOut.close(); + zipOutAsFile.close(); + + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3105/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3105/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..4d96869 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3105/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,36 @@ +taskKey="com.javarush.task.task31.task3105" + +Добавление файла в архив + +В метод main приходит список аргументов. +Первый аргумент - полный путь к файлу fileName. +Второй аргумент - путь к zip-архиву. +Добавить файл (fileName) внутрь архива в директорию 'new'. +Если в архиве есть файл с таким именем, то заменить его. + +Пример входных данных: +C:/result.mp3 +C:/pathToTest/test.zip + +Файлы внутри test.zip: +a.txt +b.txt + +После запуска Solution.main архив test.zip должен иметь такое содержимое: +new/result.mp3 +a.txt +b.txt + +Подсказка: нужно сначала куда-то сохранить содержимое всех энтри, +а потом записать в архив все энтри вместе с добавленным файлом. +Пользоваться файловой системой нельзя. + + +Требования: +1. В методе main создай ZipInputStream для архивного файла (второй аргумент main). Нужно вычитать из него все содержимое. +2. В методе main создай ZipOutputStream для архивного файла (второй аргумент main). +3. В ZipOutputStream нужно записать содержимое файла, который приходит первым аргументом в main. +4. В ZipOutputStream нужно записать все остальное содержимое, которое было вычитано из ZipInputStream. +5. Потоки для работы с архивом должны быть закрыты. + + diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3106/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3106/Solution.java new file mode 100644 index 0000000..719ba94 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3106/Solution.java @@ -0,0 +1,41 @@ +package com.javarush.task.task31.task3106; + +import java.io.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + +/* +Разархивируем файл +*/ +public class Solution { + public static void main(String[] args) throws IOException { + if (args.length < 2) { + return; + } + List list = new ArrayList<>(); + List list1 = new ArrayList<>(); + for (int i = 1; i< args.length; i++) { + list.add(args[i]); + } + Collections.sort(list); + for (int i = 0; i < list.size(); i++) { + list1.add(new FileInputStream(list.get(i))); + } + byte[] bytes = new byte[1024]; + String resultFileName = args[0]; + int readByteCnt; + try (ZipInputStream zipInputStream = new ZipInputStream(new SequenceInputStream(Collections.enumeration(list1))); + ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(resultFileName))) { + while (zipInputStream.available() >0) { + zipInputStream.getNextEntry(); + while ((readByteCnt = zipInputStream.read(bytes)) > 0) { + outputStream.write(bytes, 0, readByteCnt); + outputStream.flush(); + } + } + } + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3106/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3106/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..5c6e425 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3106/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,26 @@ +taskKey="com.javarush.task.task31.task3106" + +Разархивируем файл + +В метод main приходит список аргументов. +Первый аргумент - имя результирующего файла resultFileName, остальные аргументы - имена файлов fileNamePart. +Каждый файл (fileNamePart) - это кусочек zip архива. Нужно разархивировать целый файл, собрав его из кусочков. +Записать разархивированный файл в resultFileName. +Архив внутри может содержать файл большой длины, например, 50Mb. +Внутри архива может содержаться файл с любым именем. + +Пример входных данных. Внутри архива находится один файл с именем abc.mp3: +C:/result.mp3 +C:/pathToTest/test.zip.003 +C:/pathToTest/test.zip.001 +C:/pathToTest/test.zip.004 +C:/pathToTest/test.zip.002 + + +Требования: +1. В методе main нужно создать ZipInputStream для архива, собранного из кусочков файлов. Файлы приходят аргументами в main, начиная со второго. +2. Создай поток для записи в файл, который приходит первым аргументом в main. Запиши туда содержимое файла из архива. +3. Поток для чтения из архива должен быть закрыт. +4. Поток для записи в файл должен быть закрыт. + + From 2066a9d9b409a7d4af017593120c972557b906bb Mon Sep 17 00:00:00 2001 From: PeucT Date: Fri, 12 May 2017 16:35:08 +0400 Subject: [PATCH 43/51] Level 31. 3106 --- .../task/task31/task3106/Solution.java | 54 +++++++++++-------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3106/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3106/Solution.java index 719ba94..e5b4bb1 100644 --- a/4.JavaCollections/src/com/javarush/task/task31/task3106/Solution.java +++ b/4.JavaCollections/src/com/javarush/task/task31/task3106/Solution.java @@ -3,39 +3,49 @@ import java.io.*; import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.List; +import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; -import java.util.zip.ZipOutputStream; /* Разархивируем файл */ public class Solution { public static void main(String[] args) throws IOException { - if (args.length < 2) { - return; - } - List list = new ArrayList<>(); - List list1 = new ArrayList<>(); - for (int i = 1; i< args.length; i++) { - list.add(args[i]); + if (args == null) { return; } + List pathsList = new ArrayList(); + + for (int i = 1; i < args.length; i++) { + pathsList.add(args[i]); } - Collections.sort(list); - for (int i = 0; i < list.size(); i++) { - list1.add(new FileInputStream(list.get(i))); + + Collections.sort(pathsList, new Comparator() { + @Override + public int compare(String o1, String o2) { + return o1.substring(o1.length() - 3).compareTo(o2.substring(o2.length() - 3)); + } + }); + + List streamsLists = new ArrayList<>(); + for (int i = 0; i < pathsList.size(); i++) { + streamsLists.add(new FileInputStream(pathsList.get(i))); } - byte[] bytes = new byte[1024]; - String resultFileName = args[0]; - int readByteCnt; - try (ZipInputStream zipInputStream = new ZipInputStream(new SequenceInputStream(Collections.enumeration(list1))); - ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(resultFileName))) { - while (zipInputStream.available() >0) { - zipInputStream.getNextEntry(); - while ((readByteCnt = zipInputStream.read(bytes)) > 0) { - outputStream.write(bytes, 0, readByteCnt); - outputStream.flush(); - } + + ZipInputStream fullZipInput = new ZipInputStream(new SequenceInputStream(Collections.enumeration(streamsLists))); + ZipEntry zipEntry = null; + FileOutputStream out = new FileOutputStream(new File(args[0])); + while ((zipEntry = fullZipInput.getNextEntry()) != null) { + int symbol = 0; + int count; + byte[] buff = new byte[1024 * 1024]; + while ((count = fullZipInput.read(buff)) != -1) { + out.write(buff, 0, count); } + out.flush(); } + fullZipInput.close(); + out.close(); + } } From 80b1018f796fbaeefd55ae3f16e04c19a6b0eb68 Mon Sep 17 00:00:00 2001 From: PeucT Date: Sun, 21 May 2017 00:40:00 +0300 Subject: [PATCH 44/51] Level 31. 3109, 2028 (Big task (without part 4)). --- .../task/task20/task2028/CustomTree.java | 197 +++++++++++++++++- ...\273\320\276\320\262\320\270\320\265.jrtc" | 80 +++++++ .../task/task31/task3109/Solution.java | 46 ++++ .../task/task31/task3109/properties.txt | 2 + .../task/task31/task3109/properties.xml | 6 + ...\273\320\276\320\262\320\270\320\265.jrtc" | 19 ++ 6 files changed, 345 insertions(+), 5 deletions(-) create mode 100644 "4.JavaCollections/src/com/javarush/task/task20/task2028/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task31/task3109/Solution.java create mode 100644 4.JavaCollections/src/com/javarush/task/task31/task3109/properties.txt create mode 100644 4.JavaCollections/src/com/javarush/task/task31/task3109/properties.xml create mode 100644 "4.JavaCollections/src/com/javarush/task/task31/task3109/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/4.JavaCollections/src/com/javarush/task/task20/task2028/CustomTree.java b/4.JavaCollections/src/com/javarush/task/task20/task2028/CustomTree.java index e43d49f..34cc80f 100644 --- a/4.JavaCollections/src/com/javarush/task/task20/task2028/CustomTree.java +++ b/4.JavaCollections/src/com/javarush/task/task20/task2028/CustomTree.java @@ -1,18 +1,205 @@ package com.javarush.task.task20.task2028; -import java.util.List; +import java.io.Serializable; +import java.util.*; /* Построй дерево(1) */ -public class CustomTree { +public class CustomTree extends AbstractList implements Cloneable, Serializable { + static Entry root = new Entry("0"); + private int size = 0; + private Queue> queue = new LinkedList<>(); + { + queue.add(root); + } + public static void main(String[] args) { -/* List list = new CustomTree(); + List list = new CustomTree(); + //CustomTree list = new CustomTree(); for (int i = 1; i < 16; i++) { list.add(String.valueOf(i)); } //System.out.println("Expected 3, actual is " + ((CustomTree) list).getParent("8")); - list.remove("5"); - //System.out.println("Expected null, actual is " + ((CustomTree) list).getParent("11"));*/ + list.remove("3"); + list.add("16"); + //System.out.println(list.size()); + //System.out.println("Expected null, actual is " + ((CustomTree) list).getParent("11")); + + + } + + + + @Override + public String get(int index) { + throw new UnsupportedOperationException(); + } + + @Override + public String set(int index, String element) { + throw new UnsupportedOperationException(); + } + + @Override + public void add(int index, String s) { + throw new UnsupportedOperationException(); + } + + @Override + public String remove(int index){ + throw new UnsupportedOperationException(); } + + @Override + public List subList(int fromIndex, int toIndex){ + throw new UnsupportedOperationException(); + } + + @Override + protected void removeRange(int fromIndex, int toIndex){ + throw new UnsupportedOperationException(); + } + + @Override + public boolean addAll(int index, Collection c){ + throw new UnsupportedOperationException(); + } + + @Override + public int size() { + //return queue.size() - 1; + //return recurrSize(root) - 1; + return size; + } + + private int recurrSize(Entry entry){ + if (entry.availableToAddLeftChildren) { + if (entry.availableToAddRightChildren) { return 1; } + else { return 1 + recurrSize(entry.rightChild); } + } else if (entry.availableToAddRightChildren) { + return 1 + recurrSize(entry.leftChild); + } else { + return 1 + recurrSize(entry.leftChild) + recurrSize(entry.rightChild); + } + } + + public boolean add(String s){ + + for (Entry entry: queue) { + if (entry.isAvailableToAddChildren()) { + if (entry.availableToAddLeftChildren) { + entry.leftChild = new Entry(s); + if (!"0".equals(entry.elementName)) { + entry.leftChild.parent = entry; + } + size++; + queue.add(entry.leftChild); + entry.checkChildren(); + + return true; + }else { + entry.rightChild = new Entry(s); + if (!"0".equals(entry.elementName)) { + entry.rightChild.parent = entry; + } + entry.checkChildren(); + size++; + queue.add(entry.rightChild); + return true; + } + } + } + return false; + } + + public String getParent(String s){ + for (Entry entry : queue){ + if (s.equals(entry.elementName)) { + return entry.parent.elementName; + } + } + return null; + } + + private int getDepth(int index){ + int power = 0; + int value = 0; + while (value + (int) Math.round(Math.pow(2, power)) < index + 1){ + value = value + (int) Math.round(Math.pow(2, power)); + power += 1; + + } + return power; + } + + @Override + public boolean remove(Object o) { + return remove((String) o); + } + + public boolean remove(String s){ + + Entry forRemove = null; + for (Entry entry: queue){ + if (s.equals(entry.elementName)) { + forRemove = entry; + break; + } + } + if (forRemove != null){ + recurrRemove(forRemove); + if (forRemove.parent.leftChild.elementName.equals(forRemove.elementName)){ + forRemove.parent.leftChild = null; + return true; + } else { + forRemove.parent.rightChild = null; + return true; + } + //queue.remove(forRemove); + } else { return false; } + + } + + private void recurrRemove(Entry entry){ + if (!entry.isAvailableToAddChildren()) { + recurrRemove(entry.rightChild); + recurrRemove(entry.leftChild); + queue.remove(entry); + size--; + }else if (!entry.availableToAddLeftChildren){ + recurrRemove(entry.leftChild); + queue.remove(entry); + size--; + }else { + queue.remove(entry); + size--; + } + } + + static class Entry implements Serializable{ + String elementName; + int lineNumber; + boolean availableToAddLeftChildren; + boolean availableToAddRightChildren; + Entry parent; + Entry leftChild; + Entry rightChild; + + public Entry(String elementName) { + this.elementName = elementName; + availableToAddLeftChildren = true; + availableToAddRightChildren = true; + } + + void checkChildren(){ + if (leftChild != null) { availableToAddLeftChildren = false; } + if (rightChild != null) { availableToAddRightChildren = false; } + } + boolean isAvailableToAddChildren() { + if (availableToAddLeftChildren || availableToAddRightChildren) { return true; } + else { return false; } + } + } + } diff --git "a/4.JavaCollections/src/com/javarush/task/task20/task2028/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task20/task2028/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..aaf630b --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task20/task2028/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,80 @@ +taskKey="com.javarush.task.task20.task2028.big04" + +Построй дерево(4) + +Итак, основа дерева создана, пора тебе поработать немного самому. +Вспомним как должно выглядеть наше дерево. + +Элементы дерева должны следовать так как показано на картинке: +http://info.javarush.ru/uploads/images/00/04/89/2014/03/21/ee9a9b.jpg + +Необходимо написать методы, которые бы позволили создать такую структуру дерева и проводить операции над ней. +Тебе необходимо реализовать: +1) метод add(String s) - добавляет элементы дерева, в качестве параметра принимает имя элемента(elementName), искать место для вставки начинаем слева направо. +2) метод remove(String s) - удаляет элемент дерева имя которого было полученного в качестве параметра. +3) метод size() - возвращает текущее количество элементов в дереве. +4) метод getParent(String s) - возвращает имя родителя элемента дерева, имя которого было полученного в качестве параметра. + + +Требования: +1. После добавления N элементов в дерево с помощью метода add, метод size должен возвращать N. +2. После удаления последнего добавленного элемента из дерева с помощью метода remove, метод size должен возвращать N-1. +3. После удаления второго элемента добавленного в дерево, метод size должен возвращать N/2 + 1 (для случаев где N > 2 и является степенью двойки), N - размер дерева до удаления. +4. Метод getParent должен возвращать имя родителя для любого элемента дерева. + + +Построй дерево(3) + +Класс описывающий дерево мы создали, теперь нужен класс описывающий тип элементов дерева: +1) В классе CustomTree создай вложенный статический параметризированный класс Entry с модификатором доступа по умолчанию. +2) Обеспечь поддержку этим классом интерфейса Serializable. +3) Создай такие поля (модификатор доступа по умолчанию): +- String elementName; +- int lineNumber; +- boolean availableToAddLeftChildren, availableToAddRightChildren; +- Entry parent, leftChild, rightChild; +4) Реализуй публичный конструктор с одним параметром типа String: +- установи поле elementName равным полученному параметру; +- установи поле availableToAddLeftChildren равным true; +- установи поле availableToAddRightChildren равным true; +5) Реализуй метод void checkChildren, устанавливающий поле availableToAddLeftChildren в false, если leftChild не равен null +и availableToAddRightChildren в false, если rightChild не равен null. +6) Реализуй метод boolean isAvailableToAddChildren, возвращающий дизъюнкцию полей availableToAddLeftChildren и availableToAddRightChildren. + +Любое дерево начинается с корня, поэтому не забудь в класс CustomTree добавить поле root типа Entry c модификатором доступа по умолчанию. + + + +Построй дерево(2) + +Несмотря на то что наше дерево является потомком класса AbstractList, это не список в привычном понимании. +В частности нам недоступны принимающие в качестве параметра индекс элемента. +Такие методы необходимо переопределить и бросить новое исключение типа UnsupportedOperationException. + +Вот их список: +public String get(int index) +public String set(int index, String element) +public void add(int index, String element) +public String remove(int index) +public List subList(int fromIndex, int toIndex) +protected void removeRange(int fromIndex, int toIndex) +public boolean addAll(int index, Collection c) + + + +Построй дерево(1) + +Амиго, похоже ты уже достаточно окреп. Самое время проверить свои навыки в большой задаче! +Сегодня реализуем свое дерево немного нестандартным способом(на базе AbstractList). +Вводную информацию можешь получить используя свой любимый поисковик и текст ниже. + +Элементы дерева должны следовать так как показано на картинке: +http://info.javarush.ru/uploads/images/00/04/89/2014/03/21/ee9a9b.jpg + +Для начала сделаем наше дерево потомком класса AbstractList с параметром типа String, а также +реализуем интерфейсы Cloneable и Serializable. + +Реализацию методов get(int index) и size() пока оставь стандартной. + + + diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3109/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3109/Solution.java new file mode 100644 index 0000000..969ea47 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3109/Solution.java @@ -0,0 +1,46 @@ +package com.javarush.task.task31.task3109; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.IOException; +import java.net.URL; +import java.util.Properties; + +/* +Читаем конфиги +*/ +public class Solution { + public static void main(String[] args) { + Solution solution = new Solution(); + Properties properties = solution.getProperties("src/com/javarush/task/task31/task3109/properties.xml"); + properties.list(System.out); + + properties = solution.getProperties("src/com/javarush/task/task31/task3109/properties.txt"); + properties.list(System.out); + + properties = solution.getProperties("src/com/javarush/task/task31/task3109/notExists"); + properties.list(System.out); + } + + public Properties getProperties(String fileName) { + Properties properties = new Properties(); + + /*URL className = Solution.class.getProtectionDomain().getCodeSource().getLocation(); + String classPath = className.getPath(); + classPath = classPath.replace("/out/production", ""); + String absoluteStringPath = classPath.substring(1) + fileName;*/ + String absoluteStringPath = fileName; + try { + if ("xml".equals(absoluteStringPath.substring(absoluteStringPath.lastIndexOf(".") + 1))) { + properties.loadFromXML(new FileInputStream(new File(absoluteStringPath))); + } else { + properties.load(new FileReader(absoluteStringPath)); + } + + }catch (IOException e) { + } + + return properties; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3109/properties.txt b/4.JavaCollections/src/com/javarush/task/task31/task3109/properties.txt new file mode 100644 index 0000000..af44458 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3109/properties.txt @@ -0,0 +1,2 @@ +name=Amigo +level=31 diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3109/properties.xml b/4.JavaCollections/src/com/javarush/task/task31/task3109/properties.xml new file mode 100644 index 0000000..f7dfc45 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3109/properties.xml @@ -0,0 +1,6 @@ + + + +Amigo +31 + diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3109/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3109/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..e8dc6a1 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3109/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,19 @@ +taskKey="com.javarush.task.task31.task3109" + +Читаем конфиги + +Реализовать метод getProperties, который должен считывать свойства из переданного файла fileName. +fileName может иметь любое расширение - как xml, так и любое другое, или вообще не иметь. +Нужно обеспечить корректное чтение свойств. +При возникновении ошибок должен возвращаться пустой объект. +Метод main не участвует в тестировании. +Подсказка: возможно тебе понадобится File.separator. + + +Требования: +1. Класс Solution должен содержать метод Properties getProperties(String fileName). +2. Метод getProperties должен корректно считывать свойства из xml-файла. +3. Метод getProperties должен корректно считывать свойства из любого другого файла с любым расширением. +4. Метод getProperties должен возвращать пустой объект, если во время чтения свойств возникла ошибка. + + From c145b038356f02df3ffae0323d6bf6e681c32c52 Mon Sep 17 00:00:00 2001 From: PeucT Date: Sun, 28 May 2017 22:26:02 +0300 Subject: [PATCH 45/51] Level 32. Full. --- .../task/task32/task3201/Solution.java | 24 +++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 20 ++++++ .../task/task32/task3202/Solution.java | 29 +++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 16 +++++ .../task/task32/task3203/Solution.java | 20 ++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 16 +++++ .../task/task32/task3204/Solution.java | 39 +++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 24 +++++++ .../task3205/CustomInvocationHandler.java | 23 +++++++ .../task/task32/task3205/Solution.java | 31 +++++++++ .../task3205/SomeInterfaceWithMethods.java | 9 +++ .../SomeInterfaceWithMethodsImpl.java | 17 +++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 23 +++++++ .../javarush/task/task32/task3206/Big.java | 4 ++ .../javarush/task/task32/task3206/Item.java | 4 ++ .../task3206/ItemInvocationHandler.java | 11 ++++ .../javarush/task/task32/task3206/Small.java | 4 ++ .../task/task32/task3206/Solution.java | 40 ++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 21 ++++++ .../task/task32/task3207/DoubleString.java | 8 +++ .../task32/task3207/DoubleStringImpl.java | 9 +++ .../task/task32/task3207/Solution.java | 53 +++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 20 ++++++ .../javarush/task/task32/task3208/Animal.java | 11 ++++ .../javarush/task/task32/task3208/Cat.java | 22 +++++++ .../javarush/task/task32/task3208/Dog.java | 22 +++++++ .../task/task32/task3208/Solution.java | 64 +++++++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 22 +++++++ .../task/task32/task3210/Solution.java | 36 +++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 24 +++++++ .../task/task32/task3211/Solution.java | 39 +++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 20 ++++++ .../javarush/task/task32/task3212/Cache.java | 36 +++++++++++ .../task/task32/task3212/ServiceLocator.java | 32 ++++++++++ .../task/task32/task3212/Solution.java | 25 ++++++++ .../task3212/contex/InitialContext.java | 18 ++++++ .../task/task32/task3212/service/Service.java | 7 ++ .../task3212/service/impl/EJBServiceImpl.java | 17 +++++ .../task3212/service/impl/JMSServiceImpl.java | 17 +++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 24 +++++++ .../task/task32/task3213/Solution.java | 28 ++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 21 ++++++ 42 files changed, 950 insertions(+) create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3201/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task32/task3201/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3202/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task32/task3202/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3203/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task32/task3203/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3204/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task32/task3204/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3205/CustomInvocationHandler.java create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3205/Solution.java create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3205/SomeInterfaceWithMethods.java create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3205/SomeInterfaceWithMethodsImpl.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task32/task3205/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3206/Big.java create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3206/Item.java create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3206/ItemInvocationHandler.java create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3206/Small.java create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3206/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task32/task3206/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3207/DoubleString.java create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3207/DoubleStringImpl.java create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3207/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task32/task3207/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3208/Animal.java create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3208/Cat.java create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3208/Dog.java create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3208/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task32/task3208/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3210/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task32/task3210/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3211/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task32/task3211/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3212/Cache.java create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3212/ServiceLocator.java create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3212/Solution.java create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3212/contex/InitialContext.java create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3212/service/Service.java create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3212/service/impl/EJBServiceImpl.java create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3212/service/impl/JMSServiceImpl.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task32/task3212/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task32/task3213/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task32/task3213/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3201/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3201/Solution.java new file mode 100644 index 0000000..b473fe3 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3201/Solution.java @@ -0,0 +1,24 @@ +package com.javarush.task.task32.task3201; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/* +Запись в существующий файл +*/ +public class Solution { + public static void main(String... args) { + if (args[0] == null || args[1] == null || args[2] == null) { return; } + try ( RandomAccessFile raf = new RandomAccessFile(args[0], "rw"); + ) { + if (args[2].length() + Integer.parseInt(args[1]) > raf.length()) { + raf.seek(raf.length()); + raf.write(args[2].getBytes()); + }else { + raf.seek(Integer.parseInt(args[1])); + raf.write(args[2].getBytes()); + } + } catch (IOException e) { + } + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3201/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3201/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..3a5ffd8 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3201/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,20 @@ +taskKey="com.javarush.task.task32.task3201" + +Запись в существующий файл + +В метод main приходят три параметра: +1) fileName - путь к файлу; +2) number - число, позиция в файле; +3) text - текст. +Записать text в файл fileName начиная с позиции number. Запись должна производиться поверх старых данных, содержащихся в файле. +Если файл слишком короткий, то записать в конец файла. +Используй RandomAccessFile и его методы seek и write. + + +Требования: +1. В методе main класса Solution необходимо использовать RandomAccessFile. +2. В методе main класса Solution программа должна записывать данные в файл при помощи метода метода write класса RandomAccessFile. +3. Запись в файл должна происходить с указанной позиции с заменой содержимого. +4. Если файл слишком короткий, то запись text должна происходить в конец файла. + + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3202/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3202/Solution.java new file mode 100644 index 0000000..2b47af3 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3202/Solution.java @@ -0,0 +1,29 @@ +package com.javarush.task.task32.task3202; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; + +/* +Читаем из потока +*/ +public class Solution { + public static void main(String[] args) throws IOException { + //StringWriter writer = getAllDataFromInputStream(new FileInputStream("F:\\JavaProjects\\InputSource\\raf.txt")); + StringWriter writer = getAllDataFromInputStream(new FileInputStream("testFile.log")); + System.out.println(writer.toString()); + } + + public static StringWriter getAllDataFromInputStream(InputStream is) throws IOException { + StringWriter writer = new StringWriter(); + StringBuilder strB = new StringBuilder(); + if (is != null) { + while (is.available() > 0) { + strB.append((char) is.read()); + } + writer.write(strB.toString()); + } + return writer; + } +} \ No newline at end of file diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3202/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3202/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..475ecee --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3202/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,16 @@ +taskKey="com.javarush.task.task32.task3202" + +Читаем из потока + +Реализуй логику метода getAllDataFromInputStream. Он должен вернуть StringWriter, содержащий все данные из переданного потока. +Возвращаемый объект ни при каких условиях не должен быть null. +Метод main не участвует в тестировании. + + +Требования: +1. Публичный статический метод getAllDataFromInputStream (InputStream) должен существовать. +2. Метод getAllDataFromInputStream (InputStream) должен возвращать StringWriter. +3. Метод getAllDataFromInputStream (InputStream) должен вернуть StringWriter, который содержит все данные из переданного потока. +4. Возвращаемый объект ни при каких условиях не должен быть null. + + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3203/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3203/Solution.java new file mode 100644 index 0000000..3aaacbe --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3203/Solution.java @@ -0,0 +1,20 @@ +package com.javarush.task.task32.task3203; + +import java.io.PrintWriter; +import java.io.StringWriter; + +/* +Пишем стек-трейс +*/ +public class Solution { + public static void main(String[] args) { + String text = getStackTrace(new IndexOutOfBoundsException("fff")); + System.out.println(text); + } + + public static String getStackTrace(Throwable throwable) { + StringWriter writer = new StringWriter(); + throwable.printStackTrace(new PrintWriter(writer)); + return writer.toString(); + } +} \ No newline at end of file diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3203/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3203/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..f9b91d6 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3203/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,16 @@ +taskKey="com.javarush.task.task32.task3203" + +Пишем стек-трейс + +Реализуй логику метода getStackTrace, который в виде одной строки (одного объекта типа String) должен возвращать весь стек-трейс переданного исключения. +Используй подходящий метод класса Throwable, который поможет записать стек-трейс в StringWriter. +Метод main не участвует в тестировании. + + +Требования: +1. Публичный статический метод String getStackTrace (Throwable) должен существовать. +2. В методе getStackTrace необходимо создать объект типа StringWriter. +3. В методе getStackTrace (Throwable) необходимо использовать метод класса Throwable, который принимает объект типа PrintWriter. +4. Метод getStackTrace (Throwable) должен возвращать весь стек-трейс переданного исключения. + + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3204/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3204/Solution.java new file mode 100644 index 0000000..54799c2 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3204/Solution.java @@ -0,0 +1,39 @@ +package com.javarush.task.task32.task3204; + +import java.io.ByteArrayOutputStream; + +/* +Генератор паролей +*/ +public class Solution { + public static void main(String[] args) { + ByteArrayOutputStream password = getPassword(); + System.out.println(password.toString()); + } + + public static ByteArrayOutputStream getPassword() { + String alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + boolean isAddedLow = false; + boolean isAddedUpper = false; + boolean isAddedNumber = false; + char lowerCaseChar = alphabet.charAt ((int) (Math.random() * 25)); + char upperCaseChar = alphabet.charAt (26 + (int) (Math.random() * 25)); + char number = alphabet.charAt (52 + (int) (Math.random() * 9)); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for (int i = 0; i < 8; i++){ + if (!isAddedLow) { + out.write((byte)lowerCaseChar); + isAddedLow = true; + }else if (!isAddedNumber) { + out.write((byte) number); + isAddedNumber = true; + }else if (!isAddedUpper) { + out.write((byte) upperCaseChar); + isAddedUpper = true; + }else { + out.write((byte) alphabet.charAt((int) (Math.random() * alphabet.length()) )); + } + } + return out; + } +} \ No newline at end of file diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3204/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3204/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..e2354b5 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3204/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,24 @@ +taskKey="com.javarush.task.task32.task3204" + +Генератор паролей + +Реализуй логику метода getPassword, который должен возвращать ByteArrayOutputStream, в котором будут байты пароля. +Требования к паролю: +1) 8 символов. +2) только цифры и латинские буквы разного регистра. +3) обязательно должны присутствовать цифры, и буквы разного регистра. +Все сгенерированные пароли должны быть уникальные. +Пример правильного пароля: +wMh7smNu + + +Требования: +1. Класс Solution должен содержать метод getPassword(), который возвращает ByteArrayOutputStream со сгенерированным паролем. +2. Длина пароля должна составлять 8 символов. +3. Пароль должен содержать хотя бы одну цифру. +4. Пароль должен содержать хотя бы одну латинскую букву нижнего регистра. +5. Пароль должен содержать хотя бы одну латинскую букву верхнего регистра. +6. Пароль не должен содержать других символов, кроме цифр и латинских букв разного регистра. +7. Сгенерированные пароли должны быть уникальными. + + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3205/CustomInvocationHandler.java b/4.JavaCollections/src/com/javarush/task/task32/task3205/CustomInvocationHandler.java new file mode 100644 index 0000000..8cfec3b --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3205/CustomInvocationHandler.java @@ -0,0 +1,23 @@ +package com.javarush.task.task32.task3205; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +/** + * Created by Archmage on 22.05.2017. + */ +public class CustomInvocationHandler implements InvocationHandler { + private SomeInterfaceWithMethods someInterfaceWithMethods; + + public CustomInvocationHandler(SomeInterfaceWithMethods someInterfaceWithMethods){ + this.someInterfaceWithMethods = someInterfaceWithMethods; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + System.out.println(method.getName() + " in"); + Object returnObj = method.invoke(someInterfaceWithMethods, args); + System.out.println(method.getName() + " out"); + return returnObj; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3205/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3205/Solution.java new file mode 100644 index 0000000..b2c7c28 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3205/Solution.java @@ -0,0 +1,31 @@ +package com.javarush.task.task32.task3205; + +import java.lang.reflect.Proxy; + +/* +Создание прокси-объекта +*/ +public class Solution { + public static void main(String[] args) { + SomeInterfaceWithMethods obj = getProxy(); + obj.stringMethodWithoutArgs(); + obj.voidMethodWithIntArg(1); + + /* expected output + stringMethodWithoutArgs in + inside stringMethodWithoutArgs + stringMethodWithoutArgs out + voidMethodWithIntArg in + inside voidMethodWithIntArg + inside voidMethodWithoutArgs + voidMethodWithIntArg out + */ + } + + public static SomeInterfaceWithMethods getProxy() { + return (SomeInterfaceWithMethods) Proxy.newProxyInstance( + SomeInterfaceWithMethodsImpl.class.getClassLoader(), + SomeInterfaceWithMethodsImpl.class.getInterfaces(), + new CustomInvocationHandler(new SomeInterfaceWithMethodsImpl())); + } +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3205/SomeInterfaceWithMethods.java b/4.JavaCollections/src/com/javarush/task/task32/task3205/SomeInterfaceWithMethods.java new file mode 100644 index 0000000..c9eabdc --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3205/SomeInterfaceWithMethods.java @@ -0,0 +1,9 @@ +package com.javarush.task.task32.task3205; + +public interface SomeInterfaceWithMethods { + void voidMethodWithoutArgs(); + + String stringMethodWithoutArgs(); + + void voidMethodWithIntArg(int i); +} diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3205/SomeInterfaceWithMethodsImpl.java b/4.JavaCollections/src/com/javarush/task/task32/task3205/SomeInterfaceWithMethodsImpl.java new file mode 100644 index 0000000..1c5ecb1 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3205/SomeInterfaceWithMethodsImpl.java @@ -0,0 +1,17 @@ +package com.javarush.task.task32.task3205; + +public class SomeInterfaceWithMethodsImpl implements SomeInterfaceWithMethods { + public void voidMethodWithoutArgs() { + System.out.println("inside voidMethodWithoutArgs"); + } + + public String stringMethodWithoutArgs() { + System.out.println("inside stringMethodWithoutArgs"); + return null; + } + + public void voidMethodWithIntArg(int i) { + System.out.println("inside voidMethodWithIntArg"); + voidMethodWithoutArgs(); + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3205/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3205/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..96a76b5 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3205/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,23 @@ +taskKey="com.javarush.task.task32.task3205" + +Создание прокси-объекта + +1) В отдельном файле создай публичный класс CustomInvocationHandler, который будет хэндлером при создании прокси-объекта. +2) CustomInvocationHandler должен поддерживать интерфейс InvocationHandler. +3) CustomInvocationHandler должен иметь один публичный конструктор с одним аргументом типа SomeInterfaceWithMethods. +4) Перед вызовом любого метода у оригинального объекта должна выводиться фраза [methodName in]. +5) После вызова любого метода у оригинального объекта должна выводиться фраза [methodName out]. +6) Реализуй логику метода getProxy, который должен создавать прокси (Proxy.newProxyInstance(...)). +См. пример вывода в методе main. +Метод main не участвует в тестировании. + + +Требования: +1. Класс CustomInvocationHandler должен существовать. +2. Класс CustomInvocationHandler должен поддерживать интерфейс InvocationHandler. +3. Класс CustomInvocationHandler должен иметь один публичный конструктор с одним аргументом типа SomeInterfaceWithMethods. +4. Перед вызовом любого метода у оригинального объекта должна выводиться фраза [methodName in]. +5. После вызова любого метода у оригинального объекта должна выводиться фраза [methodName out]. +6. Метод getProxy должен создавать прокси для интерфейса SomeInterfaceWithMethods. + + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3206/Big.java b/4.JavaCollections/src/com/javarush/task/task32/task3206/Big.java new file mode 100644 index 0000000..816baca --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3206/Big.java @@ -0,0 +1,4 @@ +package com.javarush.task.task32.task3206; + +public interface Big extends Item { +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3206/Item.java b/4.JavaCollections/src/com/javarush/task/task32/task3206/Item.java new file mode 100644 index 0000000..00df753 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3206/Item.java @@ -0,0 +1,4 @@ +package com.javarush.task.task32.task3206; + +public interface Item { +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3206/ItemInvocationHandler.java b/4.JavaCollections/src/com/javarush/task/task32/task3206/ItemInvocationHandler.java new file mode 100644 index 0000000..6ba8188 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3206/ItemInvocationHandler.java @@ -0,0 +1,11 @@ +package com.javarush.task.task32.task3206; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +public class ItemInvocationHandler implements InvocationHandler { + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + return null; + } +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3206/Small.java b/4.JavaCollections/src/com/javarush/task/task32/task3206/Small.java new file mode 100644 index 0000000..5b10b28 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3206/Small.java @@ -0,0 +1,4 @@ +package com.javarush.task.task32.task3206; + +public interface Small { +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3206/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3206/Solution.java new file mode 100644 index 0000000..3b18403 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3206/Solution.java @@ -0,0 +1,40 @@ +package com.javarush.task.task32.task3206; + +import java.lang.reflect.Proxy; +import java.util.Arrays; + +/* +Дженерики для создания прокси-объекта +*/ +public class Solution { + + public static void main(String[] args) { + Solution solution = new Solution(); + test(solution.getProxy(Item.class)); //true false false + test(solution.getProxy(Item.class, Small.class)); //true false true + test(solution.getProxy(Item.class, Big.class, Small.class));//true true true + test(solution.getProxy(Big.class, Small.class)); //true true true т.к. Big наследуется от Item + test(solution.getProxy(Big.class)); //true true false т.к. Big наследуется от Item + } + + + private static void test(Object proxy) { + boolean isItem = proxy instanceof Item; + boolean isBig = proxy instanceof Big; + boolean isSmall = proxy instanceof Small; + + System.out.format("%b %b %b\n", isItem, isBig, isSmall); + } + + public T getProxy(Class className, Class... supportedInterfaces){ + Class[] interfaces = Arrays.copyOf(supportedInterfaces, supportedInterfaces.length + 1); + interfaces[supportedInterfaces.length] = className; + + T proxy = (T) Proxy.newProxyInstance( + this.getClass().getClassLoader(), + interfaces, + new ItemInvocationHandler()); + + return proxy; + } +} \ No newline at end of file diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3206/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3206/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..203ba07 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3206/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,21 @@ +taskKey="com.javarush.task.task32.task3206" + +Дженерики для создания прокси-объекта + +В классе Solution создай публичный метод getProxy: +1) Метод getProxy должен возвращать прокси для любого интерфейса, который наследуется от Item. +2) getProxy должен иметь два параметра. Первый - класс возвращаемого типа, второй - классы дополнительных интерфейсов (используй аргумент переменной длины ...). +3) Используй ItemInvocationHandler для создания прокси. +Метод main не участвует в тестировании. + + +Требования: +1. В классе Solution должен существовать метод getProxy. +2. Метод getProxy должен иметь два параметра. Первый - класс возвращаемого типа, второй - классы дополнительных интерфейсов. +3. Метод getProxy должен возвращать прокси для любого интерфейса, который наследуется от Item. +4. В методе getProxy при вызове Proxy.newProxyInstance передай this.getClass().getClassLoader() в качестве первого аргумента. +5. В методе getProxy при вызове Proxy.newProxyInstance передай вторым аргументом все интерфейсы, которые прокси должен реализовать. +6. В методе getProxy при вызове Proxy.newProxyInstance передай new ItemInvocationHandler() как третий аргумент. +7. Метод getProxy должен работать согласно с условием. + + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3207/DoubleString.java b/4.JavaCollections/src/com/javarush/task/task32/task3207/DoubleString.java new file mode 100644 index 0000000..88fa4fd --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3207/DoubleString.java @@ -0,0 +1,8 @@ +package com.javarush.task.task32.task3207; + +import java.rmi.Remote; +import java.rmi.RemoteException; + +public interface DoubleString extends Remote { + String doubleString(String str) throws RemoteException; +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3207/DoubleStringImpl.java b/4.JavaCollections/src/com/javarush/task/task32/task3207/DoubleStringImpl.java new file mode 100644 index 0000000..2dc28ae --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3207/DoubleStringImpl.java @@ -0,0 +1,9 @@ +package com.javarush.task.task32.task3207; + +import java.rmi.RemoteException; + +public class DoubleStringImpl implements DoubleString { + public String doubleString(String str) throws RemoteException { + return str + str; + } +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3207/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3207/Solution.java new file mode 100644 index 0000000..8efca6c --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3207/Solution.java @@ -0,0 +1,53 @@ +package com.javarush.task.task32.task3207; + +import java.rmi.AlreadyBoundException; +import java.rmi.NotBoundException; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.rmi.server.UnicastRemoteObject; + +/* +К серверу по RMI +*/ +public class Solution { + public static final String UNIC_BINDING_NAME = "double.string"; + public static Registry registry; + + //pretend we start rmi client as CLIENT_THREAD thread + public static Thread CLIENT_THREAD = new Thread(new Runnable() { + @Override + public void run() { + try { + DoubleString clientService = (DoubleString) registry.lookup(UNIC_BINDING_NAME); + System.out.println(clientService.doubleString("Hello")); + + } catch (RemoteException e) { + e.printStackTrace(); + } catch (NotBoundException e) { + e.printStackTrace(); + } + //напишите тут ваш код + } + }); + + public static void main(String[] args) { + //pretend we start rmi server as main thread + Remote stub = null; + try { + registry = LocateRegistry.createRegistry(2099); + final DoubleStringImpl service = new DoubleStringImpl(); + + stub = UnicastRemoteObject.exportObject(service, 0); + registry.bind(UNIC_BINDING_NAME, stub); + } catch (RemoteException e) { + e.printStackTrace(); + } catch (AlreadyBoundException e) { + e.printStackTrace(); + } + + //start client + CLIENT_THREAD.start(); + } +} \ No newline at end of file diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3207/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3207/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..4c560c5 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3207/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,20 @@ +taskKey="com.javarush.task.task32.task3207" + +К серверу по RMI + +Реализуй логику метода run в CLIENT_THREAD. В нем будет имитироваться клиентская часть, которая коннектится к серверу. +1) Из registry получи сервис с именем UNIC_BINDING_NAME. +2) Вызови метод у полученного сервиса, передай любой не пустой аргумент. +3) Выведи в консоль результат вызова метода. +4) Обработай специфические исключения. +Метод main не участвует в тестировании. + + +Требования: +1. В методе run() необходимо из registry получить сервис с именем UNIC_BINDING_NAME. +2. В методе run() необходимо вызвать метод doubleString (String) у полученного сервиса. +3. В методе run() необходимо вывести в консоль результат вызова метода doubleString (String). +4. В методе run() должен быть перехват исключения RemoteException. +5. В методе run() должен быть перехват исключения NotBoundException. + + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3208/Animal.java b/4.JavaCollections/src/com/javarush/task/task32/task3208/Animal.java new file mode 100644 index 0000000..ff03598 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3208/Animal.java @@ -0,0 +1,11 @@ +package com.javarush.task.task32.task3208; + +import java.rmi.Remote; +import java.rmi.RemoteException; + +public interface Animal extends Remote { + void say() throws RemoteException; + + void printName() throws RemoteException; +} + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3208/Cat.java b/4.JavaCollections/src/com/javarush/task/task32/task3208/Cat.java new file mode 100644 index 0000000..1209248 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3208/Cat.java @@ -0,0 +1,22 @@ +package com.javarush.task.task32.task3208; + +import java.rmi.RemoteException; + +public class Cat implements Animal { + + private String name; + + public Cat(String name) { + this.name = name; + } + + @Override + public void say() throws RemoteException { + System.out.println("meow"); + } + + @Override + public void printName() throws RemoteException { + System.out.print("Cat " + name + " "); + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3208/Dog.java b/4.JavaCollections/src/com/javarush/task/task32/task3208/Dog.java new file mode 100644 index 0000000..95ae059 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3208/Dog.java @@ -0,0 +1,22 @@ +package com.javarush.task.task32.task3208; + +import java.rmi.RemoteException; + +public class Dog implements Animal { + + private String name; + + public Dog(String name) { + this.name = name; + } + + @Override + public void say() throws RemoteException { + System.out.println("woof"); + } + + @Override + public void printName() throws RemoteException { + System.out.print("Dog " + name + " "); + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3208/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3208/Solution.java new file mode 100644 index 0000000..94566cf --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3208/Solution.java @@ -0,0 +1,64 @@ +package com.javarush.task.task32.task3208; + +import java.rmi.AlreadyBoundException; +import java.rmi.NotBoundException; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.rmi.server.UnicastRemoteObject; + +/* +RMI-2 +*/ +public class Solution { + public static Registry registry; + + //pretend we start rmi client as CLIENT_THREAD thread + public static Thread CLIENT_THREAD = new Thread(new Runnable() { + @Override + public void run() { + try { + for (String bindingName : registry.list()) { + Animal service = (Animal) registry.lookup(bindingName); + service.printName(); + service.say(); + } + } catch (RemoteException e) { + e.printStackTrace(); + } catch (NotBoundException e) { + e.printStackTrace(); + } + } + }); + + //pretend we start rmi server as SERVER_THREAD thread + public static Thread SERVER_THREAD = new Thread(new Runnable() { + @Override + public void run() { + Remote stub = null; + try { + registry = LocateRegistry.createRegistry(2099); + Cat catService = new Cat("Cat"); + Dog dogService = new Dog("Dog"); + stub = UnicastRemoteObject.exportObject(catService, 0); + registry.bind("CAT_NAME", stub); + stub = UnicastRemoteObject.exportObject(dogService, 0); + registry.bind("DOG_NAME", stub); + } catch (RemoteException e){ + e.printStackTrace(); + } catch (AlreadyBoundException e) { + e.printStackTrace(); + } + //напишите тут ваш код + } + }); + + public static void main(String[] args) throws InterruptedException { + //start rmi server thread + SERVER_THREAD.start(); + Thread.sleep(1000); + //start client + CLIENT_THREAD.start(); + } +} \ No newline at end of file diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3208/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3208/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..1094864 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3208/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,22 @@ +taskKey="com.javarush.task.task32.task3208" + +RMI-2 + +Реализуй логику метода run в SERVER_THREAD. В нем будет имитироваться серверная часть: +1) Инициализируй поле registry, которое будет принимать и обрабатывать запросы на 2099 порту. +2) Создай два объекта - Cat и Dog. +3) Используй класс UnicastRemoteObject, чтобы создать Remote объекты для созданных Cat и Dog. +Remote объекты будут в состоянии принимать обращения к своим методам используя выбранный порт (2099). +4) Для Cat и Dog добавь в registry связь уникального текстового ключа и Remote объекта. Текстовый ключ придумай сам. +5) При возникновении любого исключения выведи его стек-трейс в поток System.err. +Метод main не участвует в тестировании. + + +Требования: +1. В методе run() необходимо инициализировать поле registry. Для этого используй LocateRegistry.createRegistry (2099). +2. В методе run() необходимо создать два объекта - Cat и Dog. +3. В методе run() необходимо создать Remote объекты для созданных Cat и Dog используя UnicastRemoteObject.exportObject (Remote, int). +4. Для Cat и Dog нужно добавить в registry связь уникального текстового ключа и Remote объекта используя registry.bind (String, Remote). +5. При возникновении любого исключения нужно вывести его стек-трейс в поток System.err используя метод printStackTrace (). + + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3210/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3210/Solution.java new file mode 100644 index 0000000..c3a17fc --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3210/Solution.java @@ -0,0 +1,36 @@ +package com.javarush.task.task32.task3210; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/* +Используем RandomAccessFile +*/ + +public class Solution { + public static void main(String... args) { + if (args[0] == null || args[1] == null || args[2] == null) { return; } + try ( RandomAccessFile raf = new RandomAccessFile(args[0], "rw"); + ) { + byte[] buffer = new byte[args[2].length()]; + raf.seek(Integer.parseInt(args[1])); + long length = 0; + if ( (length = (raf.length() - Integer.parseInt(args[1]))) > buffer.length ) { + raf.read(buffer, 0, buffer.length); + } else { + raf.read(buffer, 0, (int) length); + } + raf.seek(raf.length()); + if (args[2].equals(convertByteToString(buffer))){ + raf.write("true".getBytes()); + }else { + raf.write("false".getBytes()); + } + } catch (IOException e) { + } + } + + public static String convertByteToString(byte[] readBytes){ + return new String(readBytes); + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3210/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3210/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..c56579d --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3210/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,24 @@ +taskKey="com.javarush.task.task32.task3210" + +Используем RandomAccessFile + +В метод main приходят три параметра: +1) fileName - путь к файлу; +2) number - число, позиция в файле; +3) text - текст. + +Считать текст с файла начиная с позиции number, длинной такой же как и длинна переданного текста в третьем параметре. +Если считанный текст такой же как и text, то записать в конец файла строку 'true', иначе записать 'false'. +Используй RandomAccessFile и его методы seek(long pos), read(byte b[], int off, int len), write(byte b[]). +Используй convertByteToString(byte readBytes[]) для конвертации считанной строчки в текст. + + +Требования: +1. В методе main класса Solution необходимо использовать RandomAccessFile, который должен использовать файл, который приходит первым параметром. +2. В методе main класса Solution программа должна устанавливать позицию в файле, которая передана во втором параметре. +3. В методе main класса Solution программа должна считывать данные с файла при помощи метода read(byte b[], int off, int len). +4. Запись должна происходить в конец файла. +5. Если считанный текст такой же как и text, то программа должна записать в конец переданного файла строку 'true'. +6. Если считанный текст НЕ такой же как и text, то программа должна записать в конец переданного файла строку 'false'. + + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3211/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3211/Solution.java new file mode 100644 index 0000000..1f07d9a --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3211/Solution.java @@ -0,0 +1,39 @@ +package com.javarush.task.task32.task3211; + +import java.io.ByteArrayOutputStream; +import java.io.ObjectOutputStream; +import java.security.MessageDigest; +import java.util.Arrays; + +/* +Целостность информации +*/ + +public class Solution { + public static void main(String... args) throws Exception { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(new String("test string")); + oos.flush(); + System.out.println(compareMD5(bos, "5a47d12a2e3f9fecf2d9ba1fd98152eb")); //true + + } + + public static boolean compareMD5(ByteArrayOutputStream byteArrayOutputStream, String md5) throws Exception { + if (byteArrayOutputStream != null){ + MessageDigest messageDigest = MessageDigest.getInstance("MD5"); + messageDigest.update(byteArrayOutputStream.toByteArray()); + byte[] md = messageDigest.digest(); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < md.length; i++){ + String s = Integer.toHexString(0xff & md[i]); + s = (s.length() == 1) ? "0" + s : s; + sb.append(s); + } + if (md5.equals(sb.toString())) { return true; } + else { return false; } + } + + return false; + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3211/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3211/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..cd26c3e --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3211/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,20 @@ +taskKey="com.javarush.task.task32.task3211" + +Целостность информации + +Представь ситуацию, ты выкачал архив с интернета, и в момент скачивания у тебя на несколько секунд пропало соединение. +Нужно убедиться, валидный ли архив ты скачал. Для этого сверим его MD5 хеш. +Прочитать о MD5 на wiki. +Прочитать о MessageDigest. + +Реализуй логику метода compareMD5, который должен получать MD5 хеш из переданного ByteArrayOutputStream и сравнивать с эталонным MD5 переданным вторым параметром. +Метод main не участвует в тестировании. + + +Требования: +1. Класс Solution должен содержать метод compareMD5(ByteArrayOutputStream byteArrayOutputStream, String md5). +2. Метод compareMD5(ByteArrayOutputStream byteArrayOutputStream, String md5) должен использовать MessageDigest. +3. Метод compareMD5(ByteArrayOutputStream byteArrayOutputStream, String md5) должен возвращать результат сравнения вычисленного MD5 хеша для byteArrayOutputStream с переданным параметром md5. +4. Класс Solution должен содержать метод main. + + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3212/Cache.java b/4.JavaCollections/src/com/javarush/task/task32/task3212/Cache.java new file mode 100644 index 0000000..9d0537b --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3212/Cache.java @@ -0,0 +1,36 @@ +package com.javarush.task.task32.task3212; + +import com.javarush.task.task32.task3212.service.Service; + +import java.util.ArrayList; +import java.util.List; + +public class Cache { + private List services; + + public Cache() { + services = new ArrayList<>(); + } + + public Service getService(String serviceName) { + for (Service service : services) { + if (service.getName().equalsIgnoreCase(serviceName)) { + System.out.println("Return cached " + serviceName + " object"); + return service; + } + } + return null; + } + + public void addService(Service newService) { + boolean exists = false; + for (Service service : services) { + if (service.getName().equalsIgnoreCase(newService.getName())) { + exists = true; + } + } + if (!exists) { + services.add(newService); + } + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3212/ServiceLocator.java b/4.JavaCollections/src/com/javarush/task/task32/task3212/ServiceLocator.java new file mode 100644 index 0000000..b189022 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3212/ServiceLocator.java @@ -0,0 +1,32 @@ +package com.javarush.task.task32.task3212; + +import com.javarush.task.task32.task3212.contex.InitialContext; +import com.javarush.task.task32.task3212.service.Service; + + + +public class ServiceLocator { + private static Cache cache; + + static { + cache = new Cache(); + } + + /** + * First check the service object available in cache + * If service object not available in cache do the lookup using + * JNDI initial context and get the service object. Add it to + * the cache for future use. + * + * @param jndiName The name of service object in context + * @return Object mapped to name in context + */ + public static Service getService(String jndiName) { + Service service = cache.getService(jndiName); + if (service == null) { + service = (Service) new InitialContext().lookup(jndiName); + cache.addService(service); + } + return service; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3212/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3212/Solution.java new file mode 100644 index 0000000..7c4dc37 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3212/Solution.java @@ -0,0 +1,25 @@ +package com.javarush.task.task32.task3212; + +import com.javarush.task.task32.task3212.service.Service; + +/* +Service Locator +*/ + +public class Solution { + public static void main(String[] args) { + Service service = ServiceLocator.getService("EJBService"); + service.execute(); + System.out.println(); + service = ServiceLocator.getService("JMSService"); + service.execute(); + System.out.println(); + service = ServiceLocator.getService("EJBService"); + service.execute(); + System.out.println(); + service = ServiceLocator.getService("JMSService"); + service.execute(); + + } + +} diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3212/contex/InitialContext.java b/4.JavaCollections/src/com/javarush/task/task32/task3212/contex/InitialContext.java new file mode 100644 index 0000000..a6c75a9 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3212/contex/InitialContext.java @@ -0,0 +1,18 @@ +package com.javarush.task.task32.task3212.contex; + +import com.javarush.task.task32.task3212.service.impl.EJBServiceImpl; +import com.javarush.task.task32.task3212.service.impl.JMSServiceImpl; + +public class InitialContext { + public Object lookup(String jndiName) { + + if (jndiName.equalsIgnoreCase("EJBService")) { + System.out.println("Looking up and creating a new EJBService object"); + return new EJBServiceImpl(); + } else if (jndiName.equalsIgnoreCase("JMSService")) { + System.out.println("Looking up and creating a new JMSService object"); + return new JMSServiceImpl(); + } + return null; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3212/service/Service.java b/4.JavaCollections/src/com/javarush/task/task32/task3212/service/Service.java new file mode 100644 index 0000000..4dba150 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3212/service/Service.java @@ -0,0 +1,7 @@ +package com.javarush.task.task32.task3212.service; + +public interface Service { + String getName(); + + void execute(); +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3212/service/impl/EJBServiceImpl.java b/4.JavaCollections/src/com/javarush/task/task32/task3212/service/impl/EJBServiceImpl.java new file mode 100644 index 0000000..5f6f65f --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3212/service/impl/EJBServiceImpl.java @@ -0,0 +1,17 @@ +package com.javarush.task.task32.task3212.service.impl; + +import com.javarush.task.task32.task3212.service.Service; + +public class EJBServiceImpl implements Service { + + @Override + public void execute() { + System.out.println("Executing EJBService"); + } + + @Override + public String getName() { + return "EJBService"; + } + +} diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3212/service/impl/JMSServiceImpl.java b/4.JavaCollections/src/com/javarush/task/task32/task3212/service/impl/JMSServiceImpl.java new file mode 100644 index 0000000..a9169e6 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3212/service/impl/JMSServiceImpl.java @@ -0,0 +1,17 @@ +package com.javarush.task.task32.task3212.service.impl; + +import com.javarush.task.task32.task3212.service.Service; + +public class JMSServiceImpl implements Service { + + @Override + public void execute() { + System.out.println("Executing JMSService"); + } + + @Override + public String getName() { + return "JMSService"; + } + +} diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3212/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3212/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..d4ea661 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3212/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,24 @@ +taskKey="com.javarush.task.task32.task3212" + +Service Locator + +Прочитать о паттерне Service locator. + +Реализуй логику метода getService(String jndiName) в ServiceLocator. +В нем будет реализована работа с контекстом и кэшем. + +1) Верни из кэша нужный сервис. +2) Если в кэше нет нужного сервиса то: +2.1) Создай контекст. +2.2) Возьми у контекста нужный сервис. +2.3) Добавь сервис в кеш и верни его. + + +Требования: +1. Класс ServiceLocator должен содержать метод Service getService(String jndiName). +2. Если нужный сервис находится в кэше, метод getService(String jndiName) должен возвращать сервис из кэша. +3. Если нужный сервис НЕ находится в кэше, метод getService(String jndiName) должен создавать контекст. +4. Если нужный сервис НЕ находится в кэше, метод getService(String jndiName) должен искать нужный сервис в контексте. +5. Если нужный сервис НЕ находится в кэше, метод getService(String jndiName) должен добавлять в кэш сервис, найденный в контексте и возвращать его. + + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3213/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3213/Solution.java new file mode 100644 index 0000000..3c4994f --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3213/Solution.java @@ -0,0 +1,28 @@ +package com.javarush.task.task32.task3213; + +import java.io.IOException; +import java.io.StringReader; + +/* +Шифр Цезаря +*/ + +public class Solution { + public static void main(String[] args) throws IOException { + StringReader reader = new StringReader("Khoor Dpljr"); + System.out.println(decode(reader, -3)); //Hello Amigo + + } + + public static String decode(StringReader reader, int key) throws IOException { + StringBuilder builder = new StringBuilder(); + int symbol = 0; + if (reader != null) { + while ((symbol = reader.read()) != -1) { + builder.append((char) (symbol + key)); + } + } + return builder.toString(); + } + +} diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3213/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3213/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..4e441ff --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3213/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,21 @@ +taskKey="com.javarush.task.task32.task3213" + +Шифр Цезаря + +Привет Амиго. Ты знаешь, за нами следят, просматривают нашу переписку. Поэтому нужно шифровать трафик. +Для тебя не составит труда реализовать шифр Цезаря, напомню что это просто сдвиг вправо по алфавиту на key букв. +В методе main есть хороший пример. + +Реализуй логику метода String decode(StringReader reader, int key). +Метод получает данные в закодированном виде. +Он должен вернуть дешифрованную строку, что хранится в StringReader - е. +Возвращаемый объект ни при каких условиях не должен быть null. +Метод main не участвует в тестировании. + + +Требования: +1. Класс Solution должен содержать метод String decode(StringReader reader, int key). +2. Метод decode(StringReader reader, int key) должен вернуть дешифрованную строку что хранится в StringReader - е. +3. Возвращаемый объект ни при каких условиях не должен быть null. + + From df0a553485a3185212a155749e2f8868eff73f2f Mon Sep 17 00:00:00 2001 From: PeucT Date: Sun, 9 Jul 2017 17:41:16 +0300 Subject: [PATCH 46/51] Level 33. Full. (except big task) --- .../task/task33/task3301/Solution.java | 76 +++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 19 ++++ .../task/task33/task3302/Solution.java | 44 ++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 18 +++ .../task/task33/task3303/Solution.java | 21 ++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 18 +++ .../task/task33/task3304/Solution.java | 46 ++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 22 ++++ .../javarush/task/task33/task3305/Auto.java | 14 +++ .../javarush/task/task33/task3305/Car.java | 4 + .../task/task33/task3305/Motorbike.java | 29 +++++ .../task/task33/task3305/Parking.java | 31 ++++++ .../task/task33/task3305/RaceBike.java | 33 ++++++ .../task/task33/task3305/Solution.java | 33 ++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 35 ++++++ .../task/task33/task3306/Solution.java | 70 ++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 14 +++ .../task/task33/task3307/Solution.java | 45 ++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 16 +++ .../javarush/task/task33/task3308/Shop.java | 23 ++++ .../task/task33/task3308/Solution.java | 42 +++++++ .../javarush/task/task33/task3308/data.xml | 14 +++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 22 ++++ .../task/task33/task3309/Solution.java | 103 ++++++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 31 ++++++ .../task/task33/task3311/RealBean.java | 40 +++++++ .../task/task33/task3311/Solution.java | 22 ++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 20 ++++ .../task/task33/task3312/Solution.java | 21 ++++ .../javarush/task/task33/task3312/Zoo.java | 47 ++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 22 ++++ 31 files changed, 995 insertions(+) create mode 100644 4.JavaCollections/src/com/javarush/task/task33/task3301/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task33/task3301/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task33/task3302/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task33/task3302/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task33/task3303/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task33/task3303/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task33/task3304/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task33/task3304/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task33/task3305/Auto.java create mode 100644 4.JavaCollections/src/com/javarush/task/task33/task3305/Car.java create mode 100644 4.JavaCollections/src/com/javarush/task/task33/task3305/Motorbike.java create mode 100644 4.JavaCollections/src/com/javarush/task/task33/task3305/Parking.java create mode 100644 4.JavaCollections/src/com/javarush/task/task33/task3305/RaceBike.java create mode 100644 4.JavaCollections/src/com/javarush/task/task33/task3305/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task33/task3305/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task33/task3306/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task33/task3306/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task33/task3307/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task33/task3307/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task33/task3308/Shop.java create mode 100644 4.JavaCollections/src/com/javarush/task/task33/task3308/Solution.java create mode 100644 4.JavaCollections/src/com/javarush/task/task33/task3308/data.xml create mode 100644 "4.JavaCollections/src/com/javarush/task/task33/task3308/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task33/task3309/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task33/task3309/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task33/task3311/RealBean.java create mode 100644 4.JavaCollections/src/com/javarush/task/task33/task3311/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task33/task3311/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task33/task3312/Solution.java create mode 100644 4.JavaCollections/src/com/javarush/task/task33/task3312/Zoo.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task33/task3312/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3301/Solution.java b/4.JavaCollections/src/com/javarush/task/task33/task3301/Solution.java new file mode 100644 index 0000000..ce2bdf5 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3301/Solution.java @@ -0,0 +1,76 @@ +package com.javarush.task.task33.task3301; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.ArrayList; + +/* +Первая сериализация в JSON +*/ +public class Solution { + public static void main(String[] args) throws IOException { + Cat cat = new Cat(); + cat.name = "Murka"; + cat.age = 5; + cat.weight = 3; + + Dog dog = new Dog(); + dog.name = "Killer"; + dog.age = 8; + dog.owner = "Bill Jeferson"; + + ArrayList pets = new ArrayList<>(); + pets.add(cat); + pets.add(dog); + + StringWriter writer = new StringWriter(); + convertToJSON(writer, pets); + System.out.println(writer.toString()); + //[{"name":"Murka","age":5,"weight":3},{"name":"Killer","age":8,"owner":"Bill Jeferson"}] + } + + public static void convertToJSON(StringWriter writer, Object object) throws IOException { + ObjectMapper mapper = new ObjectMapper(); + mapper.writeValue(writer, object); + } + + @JsonAutoDetect + public static class Pet { + String name; + + public String getName() { + return name; + } + } + + @JsonAutoDetect + public static class Cat extends Pet { + int age; + int weight; + + public int getAge() { + return age; + } + + public int getWeight() { + return weight; + } + } + + @JsonAutoDetect + public static class Dog extends Pet { + int age; + String owner; + + public int getAge() { + return age; + } + + public String getOwner() { + return owner; + } + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task33/task3301/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task33/task3301/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..3d9603c --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task33/task3301/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,19 @@ +taskKey="com.javarush.task.task33.task3301" + +Первая сериализация в JSON + +НЕОБХОДИМО: подключенные библиотеки Jackson Core, Bind и Annotation версии 2.6.1 + +1) В программе не выполнено основное требование к сериализации в JSON. +Найди ошибку и исправь. +2) Расставь правильно JSON аннотации у классов. +Все данные должны сериализоваться. + + +Требования: +1. Класс Pet должен быть помечен как готовый к сериализации в JSON. +2. Класс Cat должен быть помечен как готовый к сериализации в JSON. +3. Класс Dog должен быть помечен как готовый к сериализации в JSON. +4. Все данные у классов Pet, Cat, Dog должны сериализоваться. + + diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3302/Solution.java b/4.JavaCollections/src/com/javarush/task/task33/task3302/Solution.java new file mode 100644 index 0000000..4f6c9d7 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3302/Solution.java @@ -0,0 +1,44 @@ +package com.javarush.task.task33.task3302; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.io.StringWriter; + +/* +Вторая сериализация в JSON +*/ +public class Solution { + public static void main(String[] args) throws IOException { + Cat cat = new Cat(); + cat.name = "Murka"; + cat.age = 5; + cat.weight = 3; + + StringWriter writer = new StringWriter(); + convertToJSON(writer, cat); + System.out.println(writer.toString()); + } + + public static void convertToJSON(StringWriter writer, Object object) throws IOException { + ObjectMapper mapper = new ObjectMapper(); + mapper.writeValue(writer, object); + } + + @JsonAutoDetect + public static class Cat { + @JsonProperty("wildAnimal") public String name; + + @JsonIgnore public int age; + + @JsonProperty("over") + public int weight; + + Cat() { + } + } + +} diff --git "a/4.JavaCollections/src/com/javarush/task/task33/task3302/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task33/task3302/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..db628a2 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task33/task3302/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,18 @@ +taskKey="com.javarush.task.task33.task3302" + +Вторая сериализация в JSON + +НЕОБХОДИМО: подключенные библиотеки Jackson Core, Bind и Annotation версии 2.6.1 + +Расставь JSON аннотации так, чтобы результат работы метода main был следующим +{"wildAnimal":"Murka","over":3} + + +Требования: +1. Поле name класса Cat должно быть отмечено аннотацией JsonProperty. +2. Поле age класса Cat должно быть отмечено аннотацией JsonIgnore. +3. Поле weight класса Cat должно быть отмечено аннотацией JsonProperty. +4. Значение (value) аннотации JsonProperty у поля name должно быть равно "wildAnimal". +5. Значение (value) аннотации JsonProperty у поля weight должно быть равно "over". + + diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3303/Solution.java b/4.JavaCollections/src/com/javarush/task/task33/task3303/Solution.java new file mode 100644 index 0000000..366f8dd --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3303/Solution.java @@ -0,0 +1,21 @@ +package com.javarush.task.task33.task3303; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.File; +import java.io.IOException; + +/* +Десериализация JSON объекта +*/ +public class Solution { + public static T convertFromJsonToNormal(String fileName, Class clazz) throws IOException { + ObjectMapper mapper = new ObjectMapper(); + T returnObject = mapper.readValue(new File(fileName), clazz); + return returnObject; + } + + public static void main(String[] args) { + + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task33/task3303/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task33/task3303/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..3fc88dc --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task33/task3303/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,18 @@ +taskKey="com.javarush.task.task33.task3303" + +Десериализация JSON объекта + +НЕОБХОДИМО: подключенные библиотеки Jackson Core, Bind и Annotation версии 2.6.1 + +В метод convertFromJsonToNormal первым параметром приходит имя файла, который содержит один ДЖЕЙСОН объект. +Вторым параметром приходит имя класса, объект которого находится в файле. +Метод convertFromJsonToNormal должен вычитать объект из файла, преобразовать его из JSON и вернуть. + + +Требования: +1. В методе convertFromJsonToNormal должен быть создан объект типа ObjectMapper с помощью конструктора без параметров. +2. Объект возвращаемый методом convertFromJsonToNormal должен быть получен с помощью метода readValue класса ObjectMapper. +3. Метод convertFromJsonToNormal должен быть статическим. +4. Метод convertFromJsonToNormal должен быть публичным. + + diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3304/Solution.java b/4.JavaCollections/src/com/javarush/task/task33/task3304/Solution.java new file mode 100644 index 0000000..308c1e5 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3304/Solution.java @@ -0,0 +1,46 @@ +package com.javarush.task.task33.task3304; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.lang.annotation.Annotation; + +/* +Конвертация из одного класса в другой используя JSON +*/ +public class Solution { + public static void main(String[] args) throws IOException { + Second s = (Second) convertOneToAnother(new First(), Second.class); + First f = (First) convertOneToAnother(new Second(), First.class); + } + + public static Object convertOneToAnother(Object one, Class resultClassObject) throws IOException { + ObjectMapper mapper = new ObjectMapper(); + StringWriter writer = new StringWriter(); + mapper.writeValue(writer, one); + + String outString = writer.toString().replaceFirst(one.getClass().getSimpleName().toLowerCase(), resultClassObject.getSimpleName().toLowerCase()); + return mapper.readValue(outString, resultClassObject); + } + + @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property="className") + @JsonSubTypes(@JsonSubTypes.Type(value=First.class, name="first")) + public static class First { + public int i; + public String name; + } + + @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property="className") + @JsonSubTypes(@JsonSubTypes.Type(value=Second.class, name="second")) + public static class Second { + public int i; + public String name; + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task33/task3304/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task33/task3304/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..d3d43ca --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task33/task3304/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,22 @@ +taskKey="com.javarush.task.task33.task3304" + +Конвертация из одного класса в другой используя JSON + +НЕОБХОДИМО: подключенные библиотеки Jackson Core, Bind и Annotation версии 2.6.1 + +Два класса имеют одинаковые поля, но не имеют общий суперкласс. Пример, классы First и Second. +Реализовать логику метода convertOneToAnother, который должен возвращать объект класса resultClassObject, +значения полей которого равны значениям полей в объекте one. +Используй объект типа ObjectMapper. +Известно, что у классов есть JSON аннотация, у которой значение property равно имени класса в нижнем регистре. +На примере класса First, это className="first" +Классы First и Second не участвуют в тестировании, они предоставлены в качестве тестовых данных. + + +Требования: +1. Метод convertOneToAnother должен возвращать объект класса resultClassObject значения полей которого равны значениям полей объекта one. +2. В методе convertOneToAnother должен быть создан объект типа ObjectMapper. +3. Метод convertOneToAnother должен быть статическим. +4. Метод convertOneToAnother должен быть публичным. + + diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3305/Auto.java b/4.JavaCollections/src/com/javarush/task/task33/task3305/Auto.java new file mode 100644 index 0000000..885a28a --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3305/Auto.java @@ -0,0 +1,14 @@ +package com.javarush.task.task33.task3305; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; + +@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "className" ) +@JsonSubTypes({ @JsonSubTypes.Type(value = Car.class, name = "car"), + @JsonSubTypes.Type(value = Motorbike.class, name = "motorbike"), + @JsonSubTypes.Type(value = RaceBike.class, name = "race-bike")}) +public abstract class Auto { + protected String name; + protected String owner; + protected int age; +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3305/Car.java b/4.JavaCollections/src/com/javarush/task/task33/task3305/Car.java new file mode 100644 index 0000000..b740f1b --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3305/Car.java @@ -0,0 +1,4 @@ +package com.javarush.task.task33.task3305; + +public class Car extends Auto { +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3305/Motorbike.java b/4.JavaCollections/src/com/javarush/task/task33/task3305/Motorbike.java new file mode 100644 index 0000000..630a237 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3305/Motorbike.java @@ -0,0 +1,29 @@ +package com.javarush.task.task33.task3305; + +public class Motorbike extends Auto { + private String owner; + + public Motorbike(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + @Override + public String toString() { + return "Motorbike{" + + "name='" + name + '\'' + + ", owner='" + owner + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3305/Parking.java b/4.JavaCollections/src/com/javarush/task/task33/task3305/Parking.java new file mode 100644 index 0000000..d54cf3a --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3305/Parking.java @@ -0,0 +1,31 @@ +package com.javarush.task.task33.task3305; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonTypeInfo; + +import java.util.List; + +//@JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS, property = "className" ) +public class Parking { + public String name; + public String city; + public List autos; + + public Parking(String name, String city) { + this.name = name; + this.city = city; + } + + public void setAutos(List autos) { + this.autos = autos; + } + + @Override + public String toString() { + return "Parking{" + + "name='" + name + '\'' + + ", city='" + city + '\'' + + ", autos=" + autos + + '}'; + } +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3305/RaceBike.java b/4.JavaCollections/src/com/javarush/task/task33/task3305/RaceBike.java new file mode 100644 index 0000000..0ff3d34 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3305/RaceBike.java @@ -0,0 +1,33 @@ +package com.javarush.task.task33.task3305; + +public class RaceBike extends Motorbike { + private String owner; + private int age; + + public RaceBike(String name, String owner, int age) { + super(name); + this.owner = owner; + this.age = age; + } + + public String getName() { + return name; + } + + public String getOwner() { + return owner; + } + + public int getAge() { + return age; + } + + @Override + public String toString() { + return "RaceBike{" + + "name='" + name + '\'' + + ", owner='" + owner + '\'' + + ", age=" + age + + '}'; + } +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3305/Solution.java b/4.JavaCollections/src/com/javarush/task/task33/task3305/Solution.java new file mode 100644 index 0000000..24dc392 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3305/Solution.java @@ -0,0 +1,33 @@ +package com.javarush.task.task33.task3305; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; + +/* +Конвертация из одного класса в другой используя JSON +*/ +public class Solution { + public static void main(String[] args) throws IOException { + Parking parking = new Parking("Super Parking", "Kyiv"); + RaceBike raceBike = new RaceBike("Simba", "Peter", 2); + Motorbike motorbike = new Motorbike("Manny"); + Car car = new Car(); + List autos = new ArrayList<>(); + autos.add(raceBike); + autos.add(motorbike); + autos.add(car); + parking.setAutos(autos); + convertToJson(parking); + } + + public static void convertToJson(Parking parking) throws IOException { + StringWriter writer = new StringWriter(); + ObjectMapper mapper = new ObjectMapper(); + mapper.writerWithDefaultPrettyPrinter().writeValue(writer, parking); + System.out.println(writer.toString()); + } +} \ No newline at end of file diff --git "a/4.JavaCollections/src/com/javarush/task/task33/task3305/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task33/task3305/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..93ce0d2 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task33/task3305/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,35 @@ +taskKey="com.javarush.task.task33.task3305" + +Конвертация из одного класса в другой используя JSON + +НЕОБХОДИМО: подключенные библиотеки Jackson Core, Bind и Annotation версии 2.6.1 + +Расставь JSON аннотации так, чтобы результат выполнения метода main был следующим: +{ +"className" : ".Parking", +"name" : "Super Parking", +"city" : "Kyiv", +"autos" : [ { +"className" : "com.javarush.task.task33.task3305.RaceBike", +"name" : "Simba", +"owner" : "Peter", +"age" : 2 +}, { +"className" : "com.javarush.task.task33.task3305.Motorbike", +"name" : "Manny", +"owner" : null +}, { +"className" : "com.javarush.task.task33.task3305.Car" +} ] +} + +Подсказка: это всего два класса. + + +Требования: +1. Вывод на экран должен соответствовать условию задачи. +2. Класс Parking должен быть отмечен аннотацией @JsonTypeInfo с подходящим набором параметров. +3. Класс Auto должен быть отмечен аннотацией @JsonTypeInfo с подходящим набором параметров. +4. Класс Auto должен быть отмечен аннотацией @JsonSubTypes с подходящим набором параметров. + + diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3306/Solution.java b/4.JavaCollections/src/com/javarush/task/task33/task3306/Solution.java new file mode 100644 index 0000000..4295ad0 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3306/Solution.java @@ -0,0 +1,70 @@ +package com.javarush.task.task33.task3306; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; +import java.io.IOException; +import java.io.StringWriter; + +/* +Первая сериализация в XML +*/ +public class Solution { + public static void main(String[] args) throws IOException, JAXBException { + Cat cat = new Cat(); + cat.name = "Murka"; + cat.age = 5; + cat.weight = 3; + + Dog dog = new Dog(); + dog.name = "Killer"; + dog.age = 8; + dog.owner = "Bill Jeferson"; + + StringWriter writer = new StringWriter(); + convertToXml(writer, cat); + convertToXml(writer, dog); + System.out.println(writer.toString()); + /* expected output + + + Murka + 5 + 3 + + + + Killer + 8 + Bill Jeferson + + */ + } + + public static void convertToXml(StringWriter writer, Object obj) throws IOException, JAXBException { + JAXBContext context = JAXBContext.newInstance(obj.getClass()); + Marshaller marshaller = context.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); + marshaller.marshal(obj, writer); + } + + public static class Pet { + public String name; + } + + @XmlType(name = "cat") + @XmlRootElement + public static class Cat extends Pet { + public int age; + public int weight; + } + + @XmlType(name = "dog") + @XmlRootElement + public static class Dog extends Pet { + public int age; + public String owner; + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task33/task3306/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task33/task3306/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..c586af3 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task33/task3306/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,14 @@ +taskKey="com.javarush.task.task33.task3306" + +Первая сериализация в XML + +Расставь правильно JAXB аннотации у статических классов. + + +Требования: +1. Класс Cat должен быть отмечен аннотацией @XmlRootElement. +2. Класс Cat должен быть отмечен аннотацией @XmlType с параметром name = "cat". +3. Класс Dog должен быть отмечен аннотацией @XmlRootElement. +4. Класс Dog должен быть отмечен аннотацией @XmlType с параметром name = "dog". + + diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3307/Solution.java b/4.JavaCollections/src/com/javarush/task/task33/task3307/Solution.java new file mode 100644 index 0000000..d69fff6 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3307/Solution.java @@ -0,0 +1,45 @@ +package com.javarush.task.task33.task3307; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; +import java.io.IOException; +import java.io.StringReader; + +/* +Десериализация XML объекта +*/ +public class Solution { + public static void main(String[] args) throws IOException, JAXBException { + String xmlData = "Murka54"; + Cat cat = convertFromXmlToNormal(xmlData, Cat.class); + System.out.println(cat); + } + + public static T convertFromXmlToNormal(String xmlData, Class clazz) throws IOException, JAXBException { + JAXBContext context = JAXBContext.newInstance(clazz); + Unmarshaller unmarshaller = context.createUnmarshaller(); + StringReader reader = new StringReader(xmlData); + return (T) unmarshaller.unmarshal(reader); + } + + @XmlType(name = "cat") + @XmlRootElement + public static class Cat { + public String name; + public int age; + public int weight; + + @Override + public String toString() { + return "Cat{" + + "name='" + name + '\'' + + ", age=" + age + + ", weight=" + weight + + '}'; + } + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task33/task3307/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task33/task3307/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..8dc4636 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task33/task3307/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,16 @@ +taskKey="com.javarush.task.task33.task3307" + +Десериализация XML объекта + +В метод convertFromXmlToNormal первым параметром приходит строка, содержащая xml объект. +Вторым параметром приходит класс, объект которого необходимо вернуть. +Метод convertFromXmlToNormal должен создать объект из xml-строки и вернуть его. + + +Требования: +1. В методе convertFromXmlToNormal должен быть создан новый объект типа JAXBContext с помощью статического метода JAXBContext.newInstance, в качестве параметра используй целевой класс. +2. В методе convertFromXmlToNormal должен быть создан новый объект типа Unmarshaller с помощью метода createUnmarshaller вызванного на объекте типа JAXBContext. +3. Метод convertFromXmlToNormal должен корректно преобразовывать входящую xml строку в объект требуемого класса. +4. Метод convertFromXmlToNormal должен быть статическим. + + diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3308/Shop.java b/4.JavaCollections/src/com/javarush/task/task33/task3308/Shop.java new file mode 100644 index 0000000..9c6de8b --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3308/Shop.java @@ -0,0 +1,23 @@ +package com.javarush.task.task33.task3308; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; +import java.util.List; + +/** + * Created by Archmage on 29.05.2017. + */ + +@XmlType(name = "shop") +@XmlRootElement +public class Shop { + public Goods goods; + public int count; + public double profit; + public String[] secretData; + + + public static class Goods{ + public List names; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3308/Solution.java b/4.JavaCollections/src/com/javarush/task/task33/task3308/Solution.java new file mode 100644 index 0000000..ec70db1 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3308/Solution.java @@ -0,0 +1,42 @@ +package com.javarush.task.task33.task3308; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import java.io.StringReader; + +/* +Создание класса по строке xml +*/ +public class Solution { + public static void main(String[] args) throws JAXBException { + String xmlData = + "\n" + + "\n" + + " \n" + + " S1\n" + + " S2\n" + + " \n" + + " 12\n" + + " 123.4\n" + + " String1\n" + + " String2\n" + + " String3\n" + + " String4\n" + + " String5\n" + + ""; + + StringReader reader = new StringReader(xmlData); + + JAXBContext context = JAXBContext.newInstance(getClassName()); + Unmarshaller unmarshaller = context.createUnmarshaller(); + + Object o = unmarshaller.unmarshal(reader); + + System.out.println(o.toString()); + } + + public static Class getClassName() { + return Shop.class; //your class name + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3308/data.xml b/4.JavaCollections/src/com/javarush/task/task33/task3308/data.xml new file mode 100644 index 0000000..f135b1a --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3308/data.xml @@ -0,0 +1,14 @@ + + + + S1 + S2 + + 12 + 123.4 + String1 + String2 + String3 + String4 + String5 + \ No newline at end of file diff --git "a/4.JavaCollections/src/com/javarush/task/task33/task3308/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task33/task3308/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..b4ef9a4 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task33/task3308/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,22 @@ +taskKey="com.javarush.task.task33.task3308" + +Создание класса по строке xml + +Восстанови класс по переданной строке xml. +Класс должен быть в отдельном файле. +Метод getClassName должен возвращать восстановленный класс. +Метод main не участвует в тестировании. + + +Требования: +1. Класс Shop должен быть создан в отдельном файле. +2. В классе Shop должно быть создано поле goods типа Goods. +3. В классе Shop должно быть создано поле count типа int. +4. В классе Shop должно быть создано поле profit типа double. +5. В классе Shop должен быть создан массив строк secretData. +6. В классе Shop должен содержаться вложенный статический класс Goods. +7. В классе Shop.Goods должен быть создан список строк names. +8. Все поля класса Shop должны быть публичными. +9. Метод getClassName класса Solution должен возвращать класс Shop. + + diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3309/Solution.java b/4.JavaCollections/src/com/javarush/task/task33/task3309/Solution.java new file mode 100644 index 0000000..fb59262 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3309/Solution.java @@ -0,0 +1,103 @@ +package com.javarush.task.task33.task3309; + + + +import org.w3c.dom.*; +import org.xml.sax.SAXException; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.*; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.IOException; +import java.io.StringWriter; + +/* +Комментарий внутри xml +*/ +public class Solution { + public static String toXmlWithComment(Object obj, String tagName, String comment) throws JAXBException, ParserConfigurationException, IOException, SAXException, TransformerException { + + JAXBContext context = JAXBContext.newInstance(obj.getClass()); + Marshaller marshaller = context.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); + + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document doc = builder.newDocument(); + + StringWriter wr = new StringWriter(); + + marshaller.marshal(obj, doc); + NodeList nodes = doc.getElementsByTagName(tagName); + + //Element element = doc.getDocumentElement(); + Comment jcomment = null; + + createCdata(doc); + + for (int i = 0; i < nodes.getLength(); i++){ + jcomment = doc.createComment(comment); + /*nodes.item(i).getNodeType();*/ + nodes.item(i).getParentNode().insertBefore(jcomment ,nodes.item(i)); + } + /*for (int i = 0; i < nodes.getLength(); i++){ + *//*if (nodes.item(i).getNodeType() == Node.TEXT_NODE) {*//* + if (nodes.item(i).getTextContent().matches(".*[<>&'\"].*")){ + nodes.item(i).getParentNode().replaceChild(doc.createCDATASection(nodes.item(i).getTextContent()),nodes.item(i)); + } + *//*}*//* + //System.out.println(nodes.item(i).getTextContent()); + }*/ + + /*String xmlData = "\n" + + "\n" + + " name1\n" + + " name2 with second word\n" + + ""; + + Marshaller marshaller1 = JAXBContext.newInstance(String.class).createMarshaller(); + marshaller1.marshal(xmlData, doc);*/ + + + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer t = tf.newTransformer(); + t.setOutputProperty(OutputKeys.INDENT, "yes"); + t.transform(new DOMSource(doc), new StreamResult(wr)); + + //marshaller.marshal(obj, wr); + return wr.toString(); + } + + private static void createCdata(Document doc){ + Node topNode = doc.getDocumentElement(); + Node currentNode = null; + for (currentNode = topNode.getFirstChild(); currentNode != null; currentNode = currentNode.getNextSibling()){ + if (currentNode.getTextContent().matches(".*[<>&'\"].*")) { + CDATASection cdata = doc.createCDATASection(currentNode.getTextContent()); + currentNode.replaceChild(cdata,currentNode.getFirstChild()); + /*Node parentNode = currentNode.getParentNode(); + parentNode.removeChild(currentNode); + parentNode.appendChild(cdata);*/ + //currentNode.getParentNode().replaceChild(doc.createCDATASection(currentNode.getTextContent()), currentNode); + } + } + } + + public static void main(String[] args) throws JAXBException, ParserConfigurationException, IOException, SAXException, TransformerException { + System.out.println(toXmlWithComment(new TestClass(), "needCDATA", "it's a comment - ")); + } + + @XmlType + @XmlRootElement(name = "first") + private static class TestClass { + public String[] needCDATA = new String[]{"some text1","some text 2", "need CDATA because of < and >", ""}; + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task33/task3309/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task33/task3309/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..a1715aa --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task33/task3309/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,31 @@ +taskKey="com.javarush.task.task33.task3309" + +Комментарий внутри xml + +Реализовать метод toXmlWithComment, который должен возвращать строку - xml представление объекта obj. +В строке перед каждым тегом tagName должен быть вставлен комментарий comment. +Сериализация obj в xml может содержать CDATA с искомым тегом. Перед ним вставлять комментарий не нужно. + +Пример вызова: toXmlWithComment(firstSecondObject, "second", "it's a comment") +Пример результата: + + + +some string + +some string + +]]> + + + + + +Требования: +1. Количество комментариев вставленных в xml должно быть равно количеству тегов tagName. +2. Метод toXmlWithComment должен возвращать xml в виде строки преобразованной в соответствии с условием задачи. +3. Метод toXmlWithComment не должен изменять входящий xml в случае, если искомый тег отсутствует в нём. +4. Метод toXmlWithComment должен быть статическим. +5. Метод toXmlWithComment должен быть публичным. + + diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3311/RealBean.java b/4.JavaCollections/src/com/javarush/task/task33/task3311/RealBean.java new file mode 100644 index 0000000..821c200 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3311/RealBean.java @@ -0,0 +1,40 @@ +package com.javarush.task.task33.task3311; + +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import java.util.HashMap; +import java.util.Map; + +public class RealBean { + protected final int id; + protected final String name; + + protected Map additionalMap = new HashMap<>(); + + @JsonCreator + public RealBean(@JsonProperty("id") int id, @JsonProperty("name") String name) { + this.id = id; + this.name = name; + } + + public int getId() { + return id; + } + + public String getName() { + return name; + } + + + @JsonAnyGetter + public Map getAdditionalMap() { + return additionalMap; + } + + @JsonAnySetter + public void setAdditionalMap(String name, Object value) { + additionalMap.put(name, value); + } +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3311/Solution.java b/4.JavaCollections/src/com/javarush/task/task33/task3311/Solution.java new file mode 100644 index 0000000..8154d98 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3311/Solution.java @@ -0,0 +1,22 @@ +package com.javarush.task.task33.task3311; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.io.StringWriter; + +/* +Странная ошибка +*/ +public class Solution { + public static void main(String[] args) throws IOException { + StringWriter stringWriter = new StringWriter(); + ObjectMapper objectMapper = new ObjectMapper(); + /*String sampleJsonString = "{\"id\":1,\"name\":\"first\",\"additionalMap\":{\"KEY#1\":\"VALUE#1\",\"KEY#3\":\"VALUE#3\",\"KEY#2\":\"VALUE#2\"}}";*/ + String sampleJsonString = "{\"id\":1,\"name\":\"first\",\"KEY#1\":\"VALUE#1\",\"KEY#3\":\"VALUE#3\",\"KEY#2\":\"VALUE#2\"}"; + RealBean realBean = objectMapper.readValue(sampleJsonString, RealBean.class); + + objectMapper.writeValue(stringWriter, realBean); + System.out.println(stringWriter.toString()); + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task33/task3311/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task33/task3311/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..54f7496 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task33/task3311/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,20 @@ +taskKey="com.javarush.task.task33.task3311" + +Странная ошибка + +НЕОБХОДИМО: подключенные библиотеки Jackson Core, Bind и Annotation версии 2.6.1 + +В результате выполнения кода в методе main класса Solution возникает странная ошибка +при сериализации/десериализации в JSON. На экран должна быть выведена строка sampleJsonString, +а выводится не совсем она. + +Разберись в чем проблема и исправь. Обрати внимание на класс RealBean. + + +Требования: +1. Метод getAdditionalMap должен быть отмечен одной подходящей Jackson аннотацией. +2. Сериализация элементов additionalMap в json должна происходить, как сериализация обычных полей класса. +3. Десериализация элементов additionalMap из json должна происходить, как десериализация обычных полей класса. +4. Метод main должен выводить данные на экран. + + diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3312/Solution.java b/4.JavaCollections/src/com/javarush/task/task33/task3312/Solution.java new file mode 100644 index 0000000..69bd030 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3312/Solution.java @@ -0,0 +1,21 @@ +package com.javarush.task.task33.task3312; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +/* +Сериализация зоопарка +*/ +public class Solution { + public static void main(String[] args) throws JsonProcessingException { + Zoo.Dog dog = new Zoo.Dog("doggy"); + Zoo.Cat cat = new Zoo.Cat("catty"); + Zoo zoo = new Zoo(); + zoo.animals.add(dog); + zoo.animals.add(cat); + + String result = new ObjectMapper().writeValueAsString(zoo); + + System.out.println(result); + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3312/Zoo.java b/4.JavaCollections/src/com/javarush/task/task33/task3312/Zoo.java new file mode 100644 index 0000000..40f1159 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3312/Zoo.java @@ -0,0 +1,47 @@ +package com.javarush.task.task33.task3312; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.JsonTypeName; + +import java.util.ArrayList; +import java.util.List; + +public class Zoo { + public List animals = new ArrayList<>(); + + @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type" ) + @JsonSubTypes({ + @JsonSubTypes.Type(value = Dog.class, name = "dog"), + @JsonSubTypes.Type(value = Cat.class, name = "cat"), + @JsonSubTypes.Type(value = Animal.class, name = "animal") + }) + + public static class Animal { + public Animal(String name) { + this.name = name; + } + + public String name; + } + + @JsonTypeName("dog") + public static class Dog extends Animal { + + public double barkVolume; + + public Dog(String name) { + super(name); + } + } + + @JsonTypeName("cat") + public static class Cat extends Animal { + boolean likesCream; + public int lives; + + public Cat(String name) { + super(name); + } + } +} \ No newline at end of file diff --git "a/4.JavaCollections/src/com/javarush/task/task33/task3312/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task33/task3312/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..f530c94 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task33/task3312/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,22 @@ +taskKey="com.javarush.task.task33.task3312" + +Сериализация зоопарка + +Сделай так, чтобы при сериализации объекта типа Zoo, каждому элементу списка animals был добавлен тип +(dog для класса Dog, cat для класса Cat). +Для проверки можешь использовать метод main класса Solution. + +Было: +{"animals":[{"name":"doggy","barkVolume":0.0},{"name":"catty","lives":0}]} +Должно стать: +{"animals":[{"type":"dog","name":"doggy","barkVolume":0.0},{"type":"cat","name":"catty","lives":0}]} + + +Требования: +1. Класс Zoo.Animal должен быть отмечен аннотацией @JsonTypeInfo. +2. Класс Zoo.Animal должен быть отмечен аннотацией @JsonSubTypes. +3. Класс Zoo.Dog должен быть отмечен аннотацией @JsonTypeName. +4. Класс Zoo.Cat должен быть отмечен аннотацией @JsonTypeName. +5. При сериализации в JSON всем объектам списка animals должен быть добавлен тип и сохранен основной формат (пример в задании). + + From aa2195d7ef16c55e36762ce1b3df7baa754946a2 Mon Sep 17 00:00:00 2001 From: PeucT Date: Wed, 26 Jul 2017 07:55:14 +0300 Subject: [PATCH 47/51] Level 33. Big Task --- .../task/task25/task2515/BaseObject.java | 92 +++++++ .../javarush/task/task25/task2515/Bomb.java | 26 ++ .../javarush/task/task25/task2515/Canvas.java | 66 +++++ .../task25/task2515/KeyboardObserver.java | 70 +++++ .../javarush/task/task25/task2515/Rocket.java | 27 ++ .../javarush/task/task25/task2515/Space.java | 246 ++++++++++++++++++ .../task/task25/task2515/SpaceShip.java | 64 +++++ .../javarush/task/task25/task2515/Ufo.java | 53 ++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 117 +++++++++ 9 files changed, 761 insertions(+) create mode 100644 4.JavaCollections/src/com/javarush/task/task25/task2515/BaseObject.java create mode 100644 4.JavaCollections/src/com/javarush/task/task25/task2515/Bomb.java create mode 100644 4.JavaCollections/src/com/javarush/task/task25/task2515/Canvas.java create mode 100644 4.JavaCollections/src/com/javarush/task/task25/task2515/KeyboardObserver.java create mode 100644 4.JavaCollections/src/com/javarush/task/task25/task2515/Rocket.java create mode 100644 4.JavaCollections/src/com/javarush/task/task25/task2515/Space.java create mode 100644 4.JavaCollections/src/com/javarush/task/task25/task2515/SpaceShip.java create mode 100644 4.JavaCollections/src/com/javarush/task/task25/task2515/Ufo.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task25/task2515/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/4.JavaCollections/src/com/javarush/task/task25/task2515/BaseObject.java b/4.JavaCollections/src/com/javarush/task/task25/task2515/BaseObject.java new file mode 100644 index 0000000..35d64e5 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task25/task2515/BaseObject.java @@ -0,0 +1,92 @@ +package com.javarush.task.task25.task2515; + +/** + * Базовый класс для всех объектов игры. + */ +public abstract class BaseObject { + //координаты + protected double x; + protected double y; + //радиус объекта + protected double radius; + //состояние объект - жив ли объект + private boolean isAlive; + + public BaseObject(double x, double y, double radius) { + this.x = x; + this.y = y; + this.radius = radius; + this.isAlive = true; + } + + public double getX() { + return x; + } + + public void setX(double x) { + this.x = x; + } + + public double getY() { + return y; + } + + public void setY(double y) { + this.y = y; + } + + public double getRadius() { + return radius; + } + + public void setRadius(double radius) { + this.radius = radius; + } + + /** + * Метод рисует свой объект на "канвасе". + */ + public void draw(Canvas canvas) { + //do nothing + } + + /** + * Двигаем себя на один ход. + */ + public void move() { + //do nothing + } + + /** + * Проверяем - не выходит ли (x,y) за границы. + */ + public void checkBorders(double minx, double maxx, double miny, double maxy) { + if (x < minx) x = minx; + if (x > maxx) x = maxx; + if (y < miny) y = miny; + if (y > maxy) y = maxy; + } + + public boolean isAlive() { + return isAlive; + } + + public void setAlive(boolean alive) { + isAlive = alive; + } + + public void die() { + isAlive = false; + } + + /** + * Проверяем - пересекаются ли переданный(o) и наш(this) объекты. + */ + public boolean isIntersect(BaseObject o) { + double dx = x - o.x; + double dy = y - o.y; + double destination = Math.sqrt(dx * dx + dy * dy); + double destination2 = Math.max(radius, o.radius); + return destination <= destination2; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task25/task2515/Bomb.java b/4.JavaCollections/src/com/javarush/task/task25/task2515/Bomb.java new file mode 100644 index 0000000..4f97436 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task25/task2515/Bomb.java @@ -0,0 +1,26 @@ +package com.javarush.task.task25.task2515; + +/** + * Класс для бомбы. + */ +public class Bomb extends BaseObject { + public Bomb(double x, double y) { + super(x, y, 1); + } + + /** + * Отрисовываем себя на холсте. + */ + @Override + public void draw(Canvas canvas) { + canvas.setPoint(x, y, 'B'); + } + + /** + * Двигаем себя вниз на один ход. + */ + @Override + public void move() { + y++; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task25/task2515/Canvas.java b/4.JavaCollections/src/com/javarush/task/task25/task2515/Canvas.java new file mode 100644 index 0000000..12500b2 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task25/task2515/Canvas.java @@ -0,0 +1,66 @@ +package com.javarush.task.task25.task2515; + + +public class Canvas { + private int width; + private int height; + private char[][] matrix; + + public Canvas(int width, int height) { + this.width = width; + this.height = height; + this.matrix = new char[height + 2][width + 2]; + } + + public void clear() { + this.matrix = new char[height + 2][width + 2]; + } + + public void drawMatrix(double x, double y, int[][] matrix, char c) { + for (int i = 0; i < matrix.length; i++) { + for (int j = 0; j < matrix[0].length; j++) { + if (matrix[i][j] != 0) { + setPoint(x + j, y + i, c); + } + } + } + } + + public void setPoint(double x, double y, char c) { + int xRounded = (int) Math.round(x); + int yRounded = (int) Math.round(y); + if (xRounded >= 0 && xRounded < matrix[0].length && yRounded >= 0 && yRounded < matrix.length) { + matrix[yRounded][xRounded] = c; + } + } + + public void print() { + System.out.println(); + + for (int i = 0; i < height + 2; i++) { + for (int j = 0; j < width + 2; j++) { + System.out.print(" "); + System.out.print(matrix[i][j]); + System.out.print(" "); + } + + System.out.println(); + } + + System.out.println(); + System.out.println(); + System.out.println(); + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public char[][] getMatrix() { + return matrix; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task25/task2515/KeyboardObserver.java b/4.JavaCollections/src/com/javarush/task/task25/task2515/KeyboardObserver.java new file mode 100644 index 0000000..404e739 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task25/task2515/KeyboardObserver.java @@ -0,0 +1,70 @@ +package com.javarush.task.task25.task2515; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.util.Queue; +import java.util.concurrent.ArrayBlockingQueue; + +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; + +public class KeyboardObserver extends Thread { + private Queue keyEvents = new ArrayBlockingQueue(100); + + private JFrame frame; + + @Override + public void run() { + frame = new JFrame("KeyPress Tester"); + frame.setTitle("Transparent JFrame Demo"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + frame.setUndecorated(true); + frame.setSize(400, 400); + frame.setExtendedState(JFrame.MAXIMIZED_BOTH); + frame.setLayout(new GridBagLayout()); + + frame.setOpacity(0.0f); + frame.setVisible(true); + + frame.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + //do nothing + } + + @Override + public void focusLost(FocusEvent e) { + System.exit(0); + } + }); + + + frame.addKeyListener(new KeyListener() { + + public void keyTyped(KeyEvent e) { + //do nothing + } + + public void keyReleased(KeyEvent e) { + //do nothing + } + + public void keyPressed(KeyEvent e) { + keyEvents.add(e); + } + }); + } + + + public boolean hasKeyEvents() { + return !keyEvents.isEmpty(); + } + + public KeyEvent getEventFromTop() { + return keyEvents.poll(); + } +} + diff --git a/4.JavaCollections/src/com/javarush/task/task25/task2515/Rocket.java b/4.JavaCollections/src/com/javarush/task/task25/task2515/Rocket.java new file mode 100644 index 0000000..05f9327 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task25/task2515/Rocket.java @@ -0,0 +1,27 @@ +package com.javarush.task.task25.task2515; + +/** + * Класс для объектов-ракета + */ +public class Rocket extends BaseObject { + + public Rocket(double x, double y) { + super(x, y, 1); + } + + /** + * Метод рисует свой объект на "канвасе". + */ + @Override + public void draw(Canvas canvas) { + canvas.setPoint(x, y, 'R'); + } + + /** + * Двигаем себя вверх на один ход. + */ + @Override + public void move() { + y--; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task25/task2515/Space.java b/4.JavaCollections/src/com/javarush/task/task25/task2515/Space.java new file mode 100644 index 0000000..103bf61 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task25/task2515/Space.java @@ -0,0 +1,246 @@ +package com.javarush.task.task25.task2515; + +import java.awt.event.KeyEvent; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +/** + * Главный класс игры - Космос (Space) + */ +public class Space { + //Ширина и высота игрового поля + private int width; + private int height; + + //Космический корабль + private SpaceShip ship; + //Список НЛО + private ArrayList ufos = new ArrayList(); + //Список бомб + private ArrayList bombs = new ArrayList(); + //Список ракет + private ArrayList rockets = new ArrayList(); + + public Space(int width, int height) { + this.width = width; + this.height = height; + } + + /** + * Основной цикл программы. + * Тут происходят все важные действия + */ + public void run() { + //Создаем холст для отрисовки. + Canvas canvas = new Canvas(width, height); + + //Создаем объект "наблюдатель за клавиатурой" и стартуем его. + KeyboardObserver keyboardObserver = new KeyboardObserver(); + keyboardObserver.start(); + + //Игра работает, пока корабль жив + while (ship.isAlive()) { + //"наблюдатель" содержит события о нажатии клавиш? + if (keyboardObserver.hasKeyEvents()) { + KeyEvent event = keyboardObserver.getEventFromTop(); + //Если "стрелка влево" - сдвинуть фигурку влево + System.out.print(event.getKeyCode()); + if (event.getKeyCode() == KeyEvent.VK_LEFT) + ship.moveLeft(); + //Если "стрелка вправо" - сдвинуть фигурку вправо + else if (event.getKeyCode() == KeyEvent.VK_RIGHT) + ship.moveRight(); + //Если "пробел" - запускаем шарик + else if (event.getKeyCode() == KeyEvent.VK_SPACE) + ship.fire(); + } + + //двигаем все объекты игры + moveAllItems(); + + //проверяем столкновения + checkBombs(); + checkRockets(); + //удаляем умершие объекты из списков + removeDead(); + + //Создаем НЛО (1 раз в 10 ходов) + createUfo(); + + //Отрисовываем все объекты на холст, а холст выводим на экран + canvas.clear(); + draw(canvas); + canvas.print(); + + //Пауза 300 миллисекунд + Space.sleep(300); + } + + //Выводим сообщение "Game Over" + System.out.println("Game Over!"); + } + + /** + * Двигаем все объекты игры + */ + public void moveAllItems() { + //нужно получить список всех игрвых объектов и у каждого вызвать метод move(). + List list = game.getAllItems(); + for (BaseObject entry:list){ + entry.move(); + } + } + + /** + * Метод возвращает общий список, который содержит все объекты игры + */ + public List getAllItems() { + //нужно создать новый список и положить в него все игровые объекты. + List list = new ArrayList<>(); + list.addAll(game.getBombs()); + list.addAll(game.getUfos()); + list.addAll(game.getRockets()); + list.add(game.getShip()); + return list; + } + + /** + * Создаем новый НЛО. 1 раз на 10 вызовов. + */ + + public void createUfo() { + if (ufos.size() > 0) return; + + int random10 = (int) (Math.random() * 10); + if (random10 == 0) { + double x = Math.random() * width; + double y = Math.random() * height / 2; + ufos.add(new Ufo(x, y)); + } + } + + /** + * Проверяем бомбы. + * а) столкновение с кораблем (бомба и корабль умирают) + * б) падение ниже края игрового поля (бомба умирает) + */ + public void checkBombs() { + //тут нужно проверить все возможные столкновения для каждой бомбы. + for (Bomb entry:bombs){ + if (ship.isIntersect(entry)) { + ship.die(); + entry.die(); + } + if (entry.getY() > height) { + entry.die(); + } + } + + } + + /** + * Проверяем рокеты. + * а) столкновение с НЛО (ракета и НЛО умирают) + * б) вылет выше края игрового поля (ракета умирает) + */ + public void checkRockets() { + //тут нужно проверить все возможные столкновения для каждой ракеты. + for (BaseObject rocket:rockets){ + for (BaseObject ufo:ufos){ + if (rocket.isIntersect(ufo)){ + rocket.die(); + ufo.die(); + } + } + if (rocket.getY() < 0) { rocket.die(); } + } + } + + /** + * Удаляем умерсшие объекты (бомбы, ракеты, НЛО) из списков + */ + public void removeDead() { + //тут нужно удалить все умершие объекты из списков. + //Кроме космического корабля - по нему определяем ищет еще игра или нет. + + Iterator iterator = ufos.iterator(); + while (iterator.hasNext()) { + if (!iterator.next().isAlive()){ + iterator.remove(); + } + } + + iterator = bombs.iterator(); + while (iterator.hasNext()) { + if (!iterator.next().isAlive()){ + iterator.remove(); + } + } + + iterator = rockets.iterator(); + while (iterator.hasNext()) { + if (!iterator.next().isAlive()){ + iterator.remove(); + } + } + + } + + /** + * Отрисовка всех объектов игры: + * а) заполняем весь холст точесками. + * б) отрисовываем все объекты на холст. + */ + public void draw(Canvas canvas) { + //тут нужно отрисовать все объекты игры + } + + + public SpaceShip getShip() { + return ship; + } + + public void setShip(SpaceShip ship) { + this.ship = ship; + } + + public ArrayList getUfos() { + return ufos; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public ArrayList getBombs() { + return bombs; + } + + public ArrayList getRockets() { + return rockets; + } + + public static Space game; + + public static void main(String[] args) throws Exception { + game = new Space(20, 20); + game.setShip(new SpaceShip(10, 18)); + game.run(); + } + + /** + * Метод делает паузу длинной delay миллисекунд. + */ + public static void sleep(int delay) { + try { + Thread.sleep(delay); + } catch (InterruptedException e) { + } + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task25/task2515/SpaceShip.java b/4.JavaCollections/src/com/javarush/task/task25/task2515/SpaceShip.java new file mode 100644 index 0000000..40563b2 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task25/task2515/SpaceShip.java @@ -0,0 +1,64 @@ +package com.javarush.task.task25.task2515; + +/** + * Класс для космического корабля + */ +public class SpaceShip extends BaseObject { + //картинка корабля для отрисовки + private static int[][] matrix = { + {0, 0, 0, 0, 0}, + {0, 0, 1, 0, 0}, + {0, 0, 1, 0, 0}, + {1, 0, 1, 0, 1}, + {1, 1, 1, 1, 1}, + }; + + //вектор движения (-1 влево,+1 вправо) + private double dx = 0; + + public SpaceShip(int x, int y) { + super(x, y, 3); + } + + /** + * Устанавливаем вектор движения влево + */ + public void moveLeft() { + dx = -1; + } + + /** + * Устанавливаем вектор движения вправо + */ + public void moveRight() { + dx = 1; + } + + /** + * Метод рисует свой объект на "канвасе". + */ + @Override + public void draw(Canvas canvas) { + canvas.drawMatrix(x - radius + 1, y - radius + 1, matrix, 'M'); + } + + /** + * Двигаем себя на один ход. + * Проверяем столкновение с границами. + */ + @Override + public void move() { + x = x + dx; + + checkBorders(radius, Space.game.getWidth() - radius + 1, 1, Space.game.getHeight() + 1); + } + + /** + * Стреляем. + * Создаем две ракеты: слева и справа от корабля. + */ + public void fire() { + Space.game.getRockets().add(new Rocket(x - 2, y)); + Space.game.getRockets().add(new Rocket(x + 2, y)); + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task25/task2515/Ufo.java b/4.JavaCollections/src/com/javarush/task/task25/task2515/Ufo.java new file mode 100644 index 0000000..745b021 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task25/task2515/Ufo.java @@ -0,0 +1,53 @@ +package com.javarush.task.task25.task2515; + +/** + * Класс для НЛО + */ +public class Ufo extends BaseObject { + //картинка для отрисовки + private static int[][] matrix = { + {0, 0, 0, 0, 0}, + {0, 0, 1, 0, 0}, + {1, 1, 1, 1, 1}, + {0, 1, 1, 1, 0}, + {0, 0, 0, 0, 0}, + }; + + public Ufo(double x, double y) { + super(x, y, 3); + } + + /** + * Метод рисует свой объект на "канвасе". + */ + @Override + public void draw(Canvas canvas) { + canvas.drawMatrix(x - radius + 1, y - radius + 1, matrix, 'U'); + } + + /** + * Двигаем себя на один ход в случайном направлении. + */ + @Override + public void move() { + double dx = Math.random() * 2 - 1; + double dy = Math.random() * 2 - 1; + + x += dx; + y += dy; + + checkBorders(radius, Space.game.getWidth() - radius + 1, radius - 1, Space.game.getHeight() / 2 - 1); + + int random10 = (int) (Math.random() * 10); + if (random10 == 0) + fire(); + } + + /** + * Стреляем. + * Сбрасываем(создаем) одну бомбу прямо под собой. + */ + public void fire() { + Space.game.getBombs().add(new Bomb(x, y + 3)); + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task25/task2515/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task25/task2515/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..eac1c60 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task25/task2515/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,117 @@ +taskKey="com.javarush.task.task25.task2515.big17" + +Space (17) + +Надо закончить метод draw(). +Поступим по аналогии с методом move - сегодня я напишу его сам. + + +Требования: +1. Перейди на следующий этап задачи. + + +Space (16) + +И еще немного: + +Напиши метод createUfo(): +Если список НЛО пуст - создай один корабль в центре сверху. + +Напиши метод checkBombs(): +Надо проверить - не пересеклись между собой какая-нибудь бомба и корабль. +Если пересеклись - корабль и бомба умирают - die(). +Если бомба упала за границу экрана y > height бомба тоже умирает. + +Напиши метод checkRockets(): +Надо проверить - не пересеклись между собой какая-нибудь ракета и НЛО. +Если пересеклись - ракета и нло умирают - die(). +Если ракета улетела за границу экрана y < 0, ракета тоже умирает. + +Напиши метод removeDead(): +В это методе удали из списков ufos, rockets, bombs все мертвые объекты (isAlive() == false). + + + +Space (15) + +Надо еще закончить класс Space. + +Напиши метод getAllItems: +Метод должен возвращать один общий список всех объектов типа BaseObject. + +Напиши метод moveAllItems: +Метод должен двигать все объекты по одному разу. +Надо: +а) получить список всех объектов типа BaseObject; +б) вызвать у каждого из них метод move(). + + + +Space (14) + +Теперь напиши класс Ufo. +Он чуть сложнее класса Bomb и проще SpaceShip. +Тебе понадобятся методы draw(), move(), fire(). +Также не забудь о конструкторе. Типы параметров double, а радиус ufo будет равен 3. + +Метод draw() сделай по аналогии с SpaceShip. Рисовать UFO будем символом 'U'. +И добавь матрицу, по аналогии с SpaceShip. + +Метод move() надо сделать так: +а) корабль перемещается по случайной траектории; +Подсказка: +double dx = Math.random() * 2 - 1; //-1..1 +double dy = Math.random() * 2 - 1; //-1..1 +б) корабль не опускается в нижнюю половину экрана; +y <= height/2 +в) С вероятностью 10% корабль должен стрелять - вызывать метод fire. + +Метод fire(): +Корабль сбрасывает одну бомбу по середине. +Сделать аналогично классу SpaceShip. + + + +Space (13) + +Теперь перейдем к методам draw, move. +В методе move() надо: +а) увеличить x на dx; +б) проверить, не вылез ли корабль за границы космоса [0, Space.game.getWidth()]. Используй метод checkBorders. +Учти, что ширина корабля равна двум его радиусам. + +Метод draw я напишу сам - просто объяви пустой метод. + +Еще нам понадобится метод fire(), ведь корабль умеет стрелять. +Этот метод вызывается, когда надо произвести выстрел. +В этом методе надо: +а) создать две ракеты; +б) установить им координаты левого края корабля и правого края корабля (пушки находятся на расстоянии 2 от центра корабля); +в) добавить эти ракеты в список ракет объекта game. + +Его можно получить так: +Space.game.getRockets() + + + +Space (12) + +Теперь займемся кораблем. +Для сложности сделаем так: если пользователь нажал кнопку влево, то корабль начинает все время двигаться влево. +Если нажал кнопку вправо - все время в право до упора. +Поэтому заведем специальную переменную dx, которая будет хранить направление движения корабля. +если dx = 1, корабль каждый ход идет на 1 вправо, +если dx = -1, корабль каждый ход идет на 1 влево. +Надо: +а) добавь конструктор, можно такой: +Радиус корабля будет равен 3. Корабль большой - это вам не ракета и не бомба. +public SpaceShip(int x, int y) +{ +super(x, y, 3); +} +б) добавь в класс SpaceShip переменную dx (double, по умолчанию равна 0); +в) метод moveLeft(), устанавливает dx равной -1; +г) метод moveRight(), устанавливает dx равной 1. + + + From 5315f1100984a8fcab99e59660c672bb84017bfa Mon Sep 17 00:00:00 2001 From: PeucT Date: Wed, 26 Jul 2017 07:56:37 +0300 Subject: [PATCH 48/51] Level 34. (Without phantom ref and big task) --- .../task/task34/task3401/Solution.java | 21 + ...\273\320\276\320\262\320\270\320\265.jrtc" | 16 + .../task/task34/task3402/Solution.java | 20 + ...\273\320\276\320\262\320\270\320\265.jrtc" | 16 + .../task/task34/task3403/Solution.java | 22 + ...\273\320\276\320\262\320\270\320\265.jrtc" | 22 + .../task/task34/task3404/Solution.java | 422 ++++++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 25 ++ .../task/task34/task3405/Solution.java | 82 ++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 15 + .../task/task34/task3406/Solution.java | 81 ++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 15 + .../task/task34/task3407/Solution.java | 91 ++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 18 + .../task/task34/task3411/Solution.java | 18 + ...\273\320\276\320\262\320\270\320\265.jrtc" | 42 ++ .../task/task34/task3413/AnyObject.java | 57 +++ .../task/task34/task3413/SoftCache.java | 51 +++ .../task/task34/task3413/Solution.java | 15 + ...\273\320\276\320\262\320\270\320\265.jrtc" | 29 ++ 20 files changed, 1078 insertions(+) create mode 100644 4.JavaCollections/src/com/javarush/task/task34/task3401/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task34/task3401/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task34/task3402/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task34/task3402/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task34/task3403/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task34/task3403/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task34/task3404/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task34/task3404/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task34/task3405/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task34/task3405/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task34/task3406/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task34/task3406/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task34/task3407/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task34/task3407/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task34/task3411/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task34/task3411/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task34/task3413/AnyObject.java create mode 100644 4.JavaCollections/src/com/javarush/task/task34/task3413/SoftCache.java create mode 100644 4.JavaCollections/src/com/javarush/task/task34/task3413/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task34/task3413/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3401/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3401/Solution.java new file mode 100644 index 0000000..4d89a8b --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3401/Solution.java @@ -0,0 +1,21 @@ +package com.javarush.task.task34.task3401; + +/* +Числа Фибоначчи с помощью рекурсии +*/ +public class Solution { + public static void main(String[] args) { + Solution solution = new Solution(); + + System.out.println(solution.fibonacci(9)); //34 + System.out.println(solution.fibonacci(5)); //5 + System.out.println(solution.fibonacci(2)); //1 + System.out.println(solution.fibonacci(1)); //1 + } + + public int fibonacci(int n) { + if (n == 1) { return 1; } + if (n == 0) { return 0; } + return fibonacci(n - 1) + fibonacci(n - 2); + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3401/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3401/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..3b55209 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3401/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,16 @@ +taskKey="com.javarush.task.task34.task3401" + +Числа Фибоначчи с помощью рекурсии + +Почитай про числа Фибоначчи. +Реализуй рекурсивную логику метода fibonacci, где n - это номер элемента в последовательности Фибоначчи. +Не создавай в классе Solution дополнительные поля. + + +Требования: +1. В классе Solution не должны быть созданы дополнительные поля. +2. Метод fibonacci должен принимать порядковый номер искомого числа последовательности Фибоначчи и возвращать его значение. +3. Метод fibonacci не должен быть статическим. +4. Метод fibonacci должен быть рекурсивным. + + diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3402/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3402/Solution.java new file mode 100644 index 0000000..c1585d1 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3402/Solution.java @@ -0,0 +1,20 @@ +package com.javarush.task.task34.task3402; + +/* +Факториал с помощью рекурсии +*/ +public class Solution { + public static void main(String[] args) { + Solution solution = new Solution(); + + System.out.println(solution.factorial(9)); //362880 + System.out.println(solution.factorial(0)); //1 + System.out.println(solution.factorial(1)); //1 + } + + public int factorial(int n) { + if (n == 0) return 1; + if (n == 1) return 1; + return n * factorial(n - 1); + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3402/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3402/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..45fbc92 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3402/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,16 @@ +taskKey="com.javarush.task.task34.task3402" + +Факториал с помощью рекурсии + +Почитай про вычисление факториала. +Реализуй рекурсивную логику метода factorial, где n - это число, факториал которого нужно вычислить. +Не создавай в классе Solution дополнительные поля. + + +Требования: +1. В классе Solution не должны быть созданы дополнительные поля. +2. Метод factorial должен возвращать факториал числа принятого в качестве параметра. +3. Метод factorial не должен быть статическим. +4. Метод factorial должен быть рекурсивным. + + diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3403/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3403/Solution.java new file mode 100644 index 0000000..646dba7 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3403/Solution.java @@ -0,0 +1,22 @@ +package com.javarush.task.task34.task3403; + +/* +Разложение на множители с помощью рекурсии +*/ +public class Solution { + public void recursion(int n) { + for (int i = 2; i <= n; i++){ + if (n % i == 0){ + System.out.println(i); + recursion(n / i); + break; + } + } + + } + + public static void main(String[] args){ + Solution sol = new Solution(); + sol.recursion(7635); + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3403/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3403/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..967aa24 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3403/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,22 @@ +taskKey="com.javarush.task.task34.task3403" + +Разложение на множители с помощью рекурсии + +Разложить целое число n > 1 на простые множители. +Вывести в консоль через пробел все множители в порядке возрастания. +Написать рекурсивный метод для вычисления простых множителей. +Не создавай в классе Solution дополнительные поля. + +Пример: +132 +Вывод на консоль: +2 2 3 11 + + +Требования: +1. В классе Solution не должны быть созданы дополнительные поля. +2. Метод recursion должен выводить на экран все простые множители числа полученного в качестве параметра (пример в условии). +3. Метод recursion не должен быть статическим. +4. Метод recursion должен быть рекурсивным. + + diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3404/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3404/Solution.java new file mode 100644 index 0000000..fe6e8e4 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3404/Solution.java @@ -0,0 +1,422 @@ +package com.javarush.task.task34.task3404; + +import java.io.*; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/* +Рекурсия для мат. выражения +*/ +public class Solution { + public static void main(String[] args) { + Solution solution = new Solution(); + //solution.recursion("sin(2*(-5+1.5*4)+28)", 0); + //solution.recursion("sin(2*(-5+1.5*4 + 3^3)+28)+cos(4) ", 0); //expected output 0.5 6 + //solution.recursion("2*(-5+1.5*4 + 3^3)+(28 +5)*2 ", 0); //expected output 0.5 6 + //Double x = 2*(-5+1.5*4 + 27)+(28 +5)*2; + //System.out.println(); + //System.out.println(x); + String s = "28^sin(1-98098^0)"; + /*System.out.print(s + " expected output 1 4 actually "); + solution.recursion(s, 0); + System.out.println();*/ + + /*s="(-2)^(-2)"; + System.out.print(s + " expected output 0.25 3 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "tan(44+sin(89-cos(180)^2))"; + System.out.print(s + " expected output 1 6 actually "); + solution.recursion(s, 0); + System.out.println(); + + s="89-cos(180)^2"; + System.out.print(s + " expected output 88 3 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "sin(2*(-5+1.5*4)+28)"; + System.out.print(s + " expected output 0.5 6 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "tan(45)"; + System.out.print(s + " expected output 1 1 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "tan(-45)"; + System.out.print(s + " expected output -1 2 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "0.305"; + System.out.print(s + " expected output 0.3 0 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "0.3051"; + System.out.print(s + " expected output 0.31 0 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "(0.3051)"; + System.out.print(s + " expected output 0.31 0 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "1+(1+(1+1)*(1+1))*(1+1)+1"; + System.out.print(s + " expected output 12 8 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "tan(44+sin(89-cos(180)^2))"; + System.out.print(s + " expected output 1 6 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "-2+(-2+(-2)-2*(2+2))"; + System.out.print(s + " expected output -14 8 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "sin(80+(2+(1+1))*(1+1)+2)"; + System.out.print(s + " expected output 1 7 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "1+4/2/2+2^2+2*2-2^(2-1+1)"; + System.out.print(s + " expected output 6 11 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "2^10+2^(5+5)"; + System.out.print(s + " expected output 2048 4 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "1.01+(2.02-1+1/0.5*1.02)/0.1+0.25+41.1"; + System.out.print(s + " expected output 72.96 8 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "0.000025+0.000012"; + System.out.print(s + " expected output 0 1 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "-2-(-2-1-(-2)-(-2)-(-2-2-(-2)-2)-2-2)"; + System.out.print(s + " expected output -3 16 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "cos(3 + 19*3)"; + System.out.print(s + " expected output 0.5 3 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "2*(589+((2454*0.1548/0.01*(-2+9^2))+((25*123.12+45877*25)+25))-547)"; + System.out.print(s + " expected output 8302231.36 14 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "(-1 + (-2))"; + System.out.print(s + " expected output -3 3 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "-sin(2*(-5+1.5*4)+28)"; + System.out.print(s + " expected output -0.5 7 actually "); + solution.recursion(s, 0); + System.out.println(); + + + s = "sin(100)-sin(100)"; + System.out.print(s + " expected output 0 3 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "-(-22+22*2)"; + System.out.print(s + " expected output -22 4 actually "); + solution.recursion(s, 0); + System.out.println();*/ + + s = "-2^(-2)"; + System.out.print(s + " expected output -0.25 3 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "-(-2^(-2))+2+(-(-2^(-2)))"; + System.out.print(s + " expected output 2.5 10 actually "); + solution.recursion(s, 0); + System.out.println(); + + /*s = "(-2)*(-2)"; + System.out.print(s + " expected output 4 3 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "(-2)/(-2)"; + System.out.print(s + " expected output 1 3 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "sin(-30)"; + System.out.print(s + " expected output -0.5 2 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "cos(-30)"; + System.out.print(s + " expected output 0.87 2 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "tan(-30)"; + System.out.print(s + " expected output -0.58 2 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "2+8*(9/4-1.5)^(1+1)"; + System.out.print(s + " expected output 6.5 6 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "0.005 "; + System.out.print(s + " expected output 0.01 0 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "0.0049 "; + System.out.print(s + " expected output 0 0 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "0+0.304"; + System.out.print(s + " expected output 0.3 1 actually "); + solution.recursion(s, 0);*/ + } + + public void recursion(final String expression, int countOperation) { + //System.out.println(expression); + Locale.setDefault(Locale.ENGLISH); + + String handledExpression = ""; + /*if (!expression.contains("(")) { + handledExpression = new String(expression); + }*/ + boolean isFirstEntry = countOperation == 0; + int countOperForOutput = 0; + + // Считаем операции сразу же, при первом входе в рекурсию. + // Все остальные обращения к countOperation - старая реализация + + if (isFirstEntry) { + Pattern pattern = Pattern.compile("[\\+\\-\\*\\^\\/]"); + Pattern patternSin = Pattern.compile("sin"); + Pattern patternCos = Pattern.compile("cos"); + Pattern patternTan = Pattern.compile("tan"); + Matcher match = pattern.matcher(expression); + while (match.find()) { + countOperation +=1; + } + + Matcher matchSin = patternSin.matcher(expression); + while (matchSin.find()){ + countOperation +=1; + } + + Matcher matchCos = patternCos.matcher(expression); + while (matchCos.find()){ + countOperation +=1; + } + + Matcher matchTan = patternTan.matcher(expression); + while (matchTan.find()){ + countOperation +=1; + } + + countOperForOutput = countOperation; + } + + int handledExpressionStartIndex = 0; + for (int i = 0; i < expression.length(); i ++){ + if (String.valueOf(expression.charAt(i)).equals("(")) { + /*handledExpression = "";*/ + int newExpressionStartIndex = i + 1; + int parenthesisCounter = 1; + //int lengthCounter = i; + i++; + while ( (parenthesisCounter != 0) && (i < expression.length() )) { + if (String.valueOf(expression.charAt(i)).equals("(")) { + parenthesisCounter += 1; + }else if (String.valueOf(expression.charAt(i)).equals(")")) { + parenthesisCounter -= 1; + } + i++; + } + + Double result = 0.0; + /*try ( + BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + ) { + result = Double.valueOf(reader.readLine()); + } catch (IOException e) { + }*/ + PrintStream oldOut = System.out; + ByteArrayOutputStream outArray = new ByteArrayOutputStream(); + PrintStream out = new PrintStream(outArray); + System.setOut(out); + + recursion(expression.substring(newExpressionStartIndex, i - 1), countOperation); + System.setOut(oldOut); + result = Double.valueOf(outArray.toString().substring(0, outArray.toString().indexOf(" "))); + countOperation = Integer.valueOf(outArray.toString().substring(outArray.toString().indexOf(" ") + 1)); + + handledExpression = handledExpression + expression.substring(handledExpressionStartIndex, newExpressionStartIndex - 1) + + new BigDecimal(result).setScale(4, RoundingMode.HALF_UP).toString(); + /*expression.substring(i);*/ + handledExpressionStartIndex = i; + int j = 0; + } + } + handledExpression = handledExpression + expression.substring(handledExpressionStartIndex); + if (!handledExpression.contains("(") && !handledExpression.contains(")")) { + int[] forCountOperRet = new int[1]; + forCountOperRet[0] = countOperation; + Double result = letsCountExpression(handledExpression, forCountOperRet); + /*byte[] byteArray = new byte[1]; + byteArray[0] = result.byteValue(); + ByteArrayInputStream newIn = new ByteArrayInputStream(byteArray); + System.setIn(newIn);*/ + countOperation = forCountOperRet[0]; + + DecimalFormat df = isFirstEntry ? new DecimalFormat("#.##") : new DecimalFormat("#.######"); + + System.out.format("%s %d", df.format(result), countOperForOutput); + + /*ByteArrayOutputStream outArray = new ByteArrayOutputStream(); + outArray.write(result.byteValue()); + PrintStream out = new PrintStream(outArray); + System.setOut(out);*/ + + } + //implement + } + + public double letsCountExpression(String expression, int[] countOperations){ + ArrayList numbers = new ArrayList(); + ArrayList almostNumbers = new ArrayList(); + ArrayList operations = new ArrayList<>(); + expression = expression.replaceAll(" ", ""); + int startIndex = 0; + /*if (expression.charAt(0) == '-') { + expression = "0" + expression; + }*/ + + for (int i = 1; i < expression.length(); i++) { + if (expression.charAt(i) == '+' + || expression.charAt(i) == '/' + || expression.charAt(i) == '-' + || expression.charAt(i) == '*' + || expression.charAt(i) == '^') { + if (expression.charAt(i+1) == '-' ) { + almostNumbers.add(expression.substring(startIndex, i)); + operations.add(String.valueOf(expression.charAt(i))); + startIndex = i + 1; + i++; + } else if (expression.charAt(i-1) == 's' || expression.charAt(i-1) == 'n' ){ + + } else { + almostNumbers.add(expression.substring(startIndex, i)); + operations.add(String.valueOf(expression.charAt(i))); + startIndex = i + 1; + } + } + } + /*for (int i = 0; i < expression.length(); i++){ + if (expression.charAt(i) == '+' + || expression.charAt(i) == '-' + || expression.charAt(i) == '*' + || expression.charAt(i) == '^' ) { + + + almostNumbers.add(expression.substring(startIndex, i)); + //numbers.add(Double.valueOf(expression.substring(startIndex, i))); + operations.add(String.valueOf(expression.charAt(i))); + startIndex = i + 1; + } + }*/ + almostNumbers.add(expression.substring(startIndex, expression.length())); + //numbers.add(Double.valueOf(expression.substring(startIndex, expression.length()))); + + for (int i = 0; i < almostNumbers.size(); i++){ + if (almostNumbers.get(i).contains("sin")) { + numbers.add(Math.sin(Math.toRadians(Double.valueOf(almostNumbers.get(i).replace("sin", ""))))); + countOperations[0] += 1; + }else if (almostNumbers.get(i).contains("cos")){ + numbers.add(Math.cos(Math.toRadians(Double.valueOf(almostNumbers.get(i).replace("cos", ""))))); + countOperations[0] += 1; + }else if (almostNumbers.get(i).contains("tan")){ + numbers.add(Math.tan(Math.toRadians(Double.valueOf(almostNumbers.get(i).replace("tan", ""))))); + countOperations[0] += 1; + }else { + numbers.add(Double.valueOf(almostNumbers.get(i))); + } + } + + countOperations[0] += operations.size(); + if (operations.size() == 0){ + return numbers.get(0); + } else { + for (int i = 0; i < operations.size(); i++){ + if (operations.get(i).equals("^")){ + numbers.add(i, Math.pow(numbers.get(i), numbers.get(i+1))); + numbers.remove(i + 1); + numbers.remove(i + 1); + operations.remove(i); + i--; + } + } + + for (int i = 0; i < operations.size(); i++){ + if (operations.get(i).equals("/")){ + numbers.add(i, numbers.get(i) / numbers.get(i+1)); + numbers.remove(i + 1); + numbers.remove(i + 1); + operations.remove(i); + i--; + } + } + + for (int i = 0; i < operations.size(); i++){ + if (operations.get(i).equals("*")){ + numbers.add(i, numbers.get(i) * numbers.get(i+1)); + numbers.remove(i + 1); + numbers.remove(i + 1); + operations.remove(i); + i--; + } + } + + double result = numbers.get(0); + for (int i = 0; i < operations.size(); i++){ + if (operations.get(i).equals("+")){ + result = result + numbers.get(i+1); + }else { + result = result - numbers.get(i+1); + } + } + return result; + } + } + + public Solution() { + //don't delete + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3404/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3404/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..6850424 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3404/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,25 @@ +taskKey="com.javarush.task.task34.task3404" + +Рекурсия для мат. выражения + +На вход подается строка - математическое выражение. +Выражение включает целые и дробные числа, скобки (), пробелы, знак отрицания -, возведение в степень ^, sin(x), cos(x), tan(x) +Для sin(x), cos(x), tan(x) выражение внутри скобок считать градусами, например, cos(3 + 19*3)=0.5 +Степень задается так: a^(1+3) и так a^4, что эквивалентно a*a*a*a. +С помощью рекурсии вычислить выражение и количество математических операций. Вывести через пробел результат в консоль. +Результат выводить с точностью до двух знаков, для 0.33333 вывести 0.33, использовать стандартный принцип округления. +Не создавай в классе Solution дополнительные поля. +Не пиши косвенную рекурсию. +Пример, состоящий из операций sin * - + * +: +sin(2*(-5+1.5*4)+28) +Результат: +0.5 6 + + +Требования: +1. В классе Solution не должны быть созданы дополнительные поля. +2. Метод recursion должен выводить на экран результат вычисления заданного выражения (пример в условии). +3. Метод recursion не должен быть статическим. +4. Метод recursion должен быть рекурсивным. + + diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3405/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3405/Solution.java new file mode 100644 index 0000000..5f63b3a --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3405/Solution.java @@ -0,0 +1,82 @@ +package com.javarush.task.task34.task3405; + +import java.lang.ref.SoftReference; +import java.util.ArrayList; +import java.util.List; + +/* +Мягкие ссылки +*/ +public class Solution { + public static Helper helper = new Helper(); + + public static class Monkey { + private String name; + + public Monkey(String name) { + this.name = name; + } + + protected void finalize() { + Helper.isFinalized = true; + System.out.format("Bye-Bye, %s!\n", name); + } + } + + public static void main(String args[]) throws InterruptedException { + helper.startTime(); + + Monkey monkey = new Monkey("Simka"); + + SoftReference reference = new SoftReference(monkey); + //Add reference here + + helper.callGC(); + + monkey = null; + + helper.callGC(); + helper.heapConsuming(); + + if (reference.get() == null) + System.out.println("Finalized"); + + helper.finish(); + } + + public static class Helper { + public static boolean isFinalized; + + private long startTime; + + void startTime() { + this.startTime = System.currentTimeMillis(); + } + + int getTime() { + return (int) (System.currentTimeMillis() - startTime) / 1000; + } + + void callGC() throws InterruptedException { + System.gc(); + Thread.sleep(1000); + } + + void heapConsuming() { + try { + List heap = new ArrayList(10000000); + while (!isFinalized) { + heap.add(new Solution()); + } + } catch (OutOfMemoryError e) { + System.out.println("Out of memory error raised"); + } + } + + public void finish() { + System.out.println("Done"); + System.out.println("It took " + getTime() + " sec"); + + } + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3405/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3405/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..e433a41 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3405/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,15 @@ +taskKey="com.javarush.task.task34.task3405" + +Мягкие ссылки + +Разберись в примере. +Внутри метода main после создания объекта типа Monkey создай мягкую ссылку (SoftReference) на него. + + +Требования: +1. В методе main должен быть создан объект типа Monkey с именем "Simka". +2. В методе main должен быть создан SoftReference на объект monkey. +3. Класс Monkey должен быть публичным. +4. Класс Monkey должен быть статическим. + + diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3406/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3406/Solution.java new file mode 100644 index 0000000..487e123 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3406/Solution.java @@ -0,0 +1,81 @@ +package com.javarush.task.task34.task3406; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; + +/* +Слабые ссылки +*/ +public class Solution { + public static Helper helper = new Helper(); + + public static class Monkey { + private String name; + + public Monkey(String name) { + this.name = name; + } + + protected void finalize() { + Helper.isFinalized = true; + System.out.format("Bye-Bye, %s!\n", name); + } + } + + public static void main(String args[]) throws InterruptedException { + helper.startTime(); + + Monkey monkey = new Monkey("Simka"); + + WeakReference reference = new WeakReference(monkey); + //Add reference here + + helper.callGC(); + + monkey = null; + + helper.callGC(); + helper.heapConsuming(); + + if (reference.get() == null) + System.out.println("Finalized"); + + helper.finish(); + } + + public static class Helper { + public static boolean isFinalized; + + private long startTime; + + void startTime() { + this.startTime = System.currentTimeMillis(); + } + + int getTime() { + return (int) (System.currentTimeMillis() - startTime) / 1000; + } + + void callGC() throws InterruptedException { + System.gc(); + Thread.sleep(1000); + } + + void heapConsuming() { + try { + List heap = new ArrayList(100000); + while (!isFinalized) { + heap.add(new Solution()); + } + } catch (OutOfMemoryError e) { + System.out.println("Out of memory error raised"); + } + } + + public void finish() { + System.out.println("Done"); + System.out.println("It took " + getTime() + " sec"); + } + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3406/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3406/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..3a81f61 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3406/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,15 @@ +taskKey="com.javarush.task.task34.task3406" + +Слабые ссылки + +Разберись в примере. +Внутри метода main после создания объекта типа Monkey создай слабую ссылку (WeakReference) на него. + + +Требования: +1. В методе main должен быть создан объект типа Monkey с именем "Simka". +2. В методе main должен быть создан WeakReference на объект monkey. +3. Класс Monkey должен быть публичным. +4. Класс Monkey должен быть статическим. + + diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3407/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3407/Solution.java new file mode 100644 index 0000000..f9b8f33 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3407/Solution.java @@ -0,0 +1,91 @@ +package com.javarush.task.task34.task3407; + +import java.lang.ref.PhantomReference; +import java.lang.ref.ReferenceQueue; +import java.util.ArrayList; +import java.util.List; + +/* +Призрачные ссылки +*/ +public class Solution { + public static Helper helper = new Helper(); + + public static class Monkey { + } + + public static void main(String args[]) throws InterruptedException { + helper.startTime(); + List> list = helper.getFilledList(); + + //before GC + helper.checkListWithReferences(list, "before"); + + helper.callGC(); + helper.heapConsuming(); + + //after GC + helper.checkListWithReferences(list, "after"); + + helper.finish(); + } + + public static class Helper { + private ReferenceQueue queue = new ReferenceQueue<>(); + + private long startTime; + + void startTime() { + this.startTime = System.currentTimeMillis(); + } + + int getTime() { + return (int) (System.currentTimeMillis() - startTime) / 1000; + } + + void callGC() throws InterruptedException { + System.gc(); + Thread.sleep(1000); + } + + + public ReferenceQueue getQueue() { + return queue; + } + + void heapConsuming() { + try { + List heap = new ArrayList(100000); + while (true) { + heap.add(new Solution()); + } + } catch (OutOfMemoryError e) { + System.out.println("Out of memory error raised"); + } + } + + public void checkListWithReferences(List> list, String string) { + int count = 0; + for (PhantomReference reference : list) { + if (reference.isEnqueued()) { + count++; + } + } + + System.out.println(String.format("The enqueue reference count is %d (%s GC was called)", count, string)); + } + + public List> getFilledList() { + return null; + } + + public void finish() throws InterruptedException { + int count = 0; + while (queue.poll() != null) { + count++; + } + System.out.println(count + " objects are in the queue of phantom reference"); + System.out.println("It took " + getTime() + " sec"); + } + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3407/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3407/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..39a9f4a --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3407/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,18 @@ +taskKey="com.javarush.task.task34.task3407" + +Призрачные ссылки + +Разберись в примере. +Реализуй логику метода getFilledList класса Helper: +1) создай список, который сможет хранить призрачные ссылки на объекты Monkey +2) добавь в список 200 ссылок, используйте очередь helper.getQueue() +3) верни заполненный список + + +Требования: +1. Метод getFilledList должен возвращать список заполненный фантомными ссылками на объекты типа Monkey. +2. Метод getFilledList должен возвращать список из 200 элементов. +3. Класс Helper не должен быть приватным. +4. Метод getFilledList не должен быть приватным. + + diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3411/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3411/Solution.java new file mode 100644 index 0000000..140f328 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3411/Solution.java @@ -0,0 +1,18 @@ +package com.javarush.task.task34.task3411; + +/* +Ханойские башни +*/ + +import java.util.HashSet; + +public class Solution { + public static void main(String[] args) { + int count = 3; + moveRing('A', 'B', 'C', count); + } + + public static void moveRing(char a, char b, char c, int count) { + //напишите тут ваш код + } +} \ No newline at end of file diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3411/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3411/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..9b93a5a --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3411/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,42 @@ +taskKey="com.javarush.task.task34.task3411" + +Ханойские башни + +Имеется три стержня. На стержень A нанизаны count колец, причем кольца отличаются размером и лежат меньшее +на большем. Требуется перенести пирамиду из count колец с стержня A на стержень B за наименьшее число ходов. +За один раз разрешается переносить только одно кольцо, причем нельзя класть большее кольцо на меньшее. +Нужно реализовать публичный статический метод void moveRing(char a, char b, char c, int count), который +выведет последовательность действий, необходимых для перемещения колец со стержня A на стержень B. +Параметры метода: +char a - имя стержня, на котором в начале находятся все кольца; +char b - имя стержня, на который нужно перенести все кольца; +char c - имя вспомогательного стержня; +int count - общее количество колец, которые необходимо перенести. +Задачу нужно решать используя рекурсивный вызов метода moveRing. + +Пример1: +Метод moveRing вызывается с параметрами: 'A', 'B', 'C', 1 +Ожидаемый вывод: +from A to B + +Пример2: +Метод moveRing вызывается с параметрами: 'A', 'B', 'C', 3 +Ожидаемый вывод: +from A to B +from A to C +from B to C +from A to B +from C to A +from C to B +from A to B + +Подсказка: общее количество действий равно 2 в степени count минус 1. + + +Требования: +1. В классе Solution должен существовать публичный статический метод void moveRing(char, char, char, int). +2. Методе moveRing должен быть рекурсивным. +3. Количество действий по перемещению колец должно быть равно 2 в степени count минус 1. +4. Вывод метода moveRing должен соответствовать условию. + + diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3413/AnyObject.java b/4.JavaCollections/src/com/javarush/task/task34/task3413/AnyObject.java new file mode 100644 index 0000000..b4a3109 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3413/AnyObject.java @@ -0,0 +1,57 @@ +package com.javarush.task.task34.task3413; + +import java.util.Calendar; +import java.util.GregorianCalendar; + +public class AnyObject { + + private Long id; + private String name; + private Calendar creationTime = new GregorianCalendar(); + private String additionalDescription; + + public AnyObject(Long id, String name, String additionalDescription) { + this.id = id; + if (name != null) { + this.name = name; + } else { + this.name = "AnyObject#" + id; + } + if (additionalDescription != null) { + this.additionalDescription = additionalDescription; + } else { + this.additionalDescription = "This is object #" + id; + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + AnyObject that = (AnyObject) o; + + if (!id.equals(that.id)) return false; + if (!name.equals(that.name)) return false; + return creationTime.equals(that.creationTime); + + } + + @Override + public int hashCode() { + int result = id.hashCode(); + result = 31 * result + name.hashCode(); + result = 31 * result + creationTime.hashCode(); + return result; + } + + @Override + public String toString() { + return "AnyObject{" + + "id = " + id + + ", name = '" + name + '\'' + + ", creationTime = " + creationTime.getTime() + + ", additionalDescription = '" + additionalDescription + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3413/SoftCache.java b/4.JavaCollections/src/com/javarush/task/task34/task3413/SoftCache.java new file mode 100644 index 0000000..81211b3 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3413/SoftCache.java @@ -0,0 +1,51 @@ +package com.javarush.task.task34.task3413; + +import java.lang.ref.SoftReference; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class SoftCache { + private Map> cacheMap = new ConcurrentHashMap<>(); + + public AnyObject get(Long key) { + SoftReference softReference = cacheMap.get(key); + AnyObject obj = null; + if (softReference == null) { + return null; + }else { + obj = softReference.get(); + softReference.clear(); + return obj; + } + + //напишите тут ваш код + } + + public AnyObject put(Long key, AnyObject value) { + + SoftReference softReference = cacheMap.put(key, new SoftReference<>(value)); + value = null; + AnyObject obj = null; + if (softReference == null) { + return null; + }else { + obj = softReference.get(); + softReference.clear(); + return obj; + } + //напишите тут ваш код + } + + public AnyObject remove(Long key) { + SoftReference softReference = cacheMap.remove(key); + AnyObject obj = null; + if (softReference == null) { + return null; + }else { + obj = softReference.get(); + softReference.clear(); + return obj; + } + //напишите тут ваш код + } +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3413/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3413/Solution.java new file mode 100644 index 0000000..b37d74e --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3413/Solution.java @@ -0,0 +1,15 @@ +package com.javarush.task.task34.task3413; + +/* +Кеш на основании SoftReference +*/ + +public class Solution { + public static void main(String[] args) { + SoftCache cache = new SoftCache(); + + for (long i = 0; i < 2_500_000; i++) { + cache.put(i, new AnyObject(i, null, null)); + } + } +} \ No newline at end of file diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3413/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3413/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..68d93d4 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3413/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,29 @@ +taskKey="com.javarush.task.task34.task3413" + +Кеш на основании SoftReference + +Реализуй логику методов get, put, remove класса SoftCache: + +Метод AnyObject get(Long key) должен возвращать объект типа AnyObject из мапы cacheMap по ключу key. Если +такого ключа в cacheMap нет - верни null. + +Метод AnyObject put(Long key, AnyObject value) должен добавлять в мапу пару key : value. Метод должен +вернуть null, если в cacheMap по такому ключу ранее не было значения. Иначе - верни предыдущее значение +value по этому ключу. Не забудь вызвать метод clear() у объекта типа SoftReference. + +Метод AnyObject remove(Long key) должен удалить из мапы cacheMap пару key : value по ключу key. Метод должен +вернуть null, если в cacheMap по такому ключу ранее не было значения. Иначе - верни предыдущее значение +value по этому ключу. Не забудь вызвать метод clear() у объекта типа SoftReference. + +Не изменяй класс AnyObject. +Метод main не принимает участия в тестировании. + + +Требования: +1. Класс AnyObject не должен быть изменен. +2. В классе SoftCache должно существовать приватное поле Map> cacheMap. +3. Реализуй метод get согласно условию. +4. Реализуй метод put согласно условию. +5. Реализуй метод remove согласно условию. + + From aa10b035248b89bdbded76045c82cda5bac70a76 Mon Sep 17 00:00:00 2001 From: PeucT Date: Wed, 26 Jul 2017 07:57:47 +0300 Subject: [PATCH 49/51] Level 34. Big task --- .../task/task37/task3707/AmigoSet.java | 106 ++++++++++++++++++ .../task3707/HashMapReflectionHelper.java | 17 +++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 106 ++++++++++++++++++ 3 files changed, 229 insertions(+) create mode 100644 4.JavaCollections/src/com/javarush/task/task37/task3707/AmigoSet.java create mode 100644 4.JavaCollections/src/com/javarush/task/task37/task3707/HashMapReflectionHelper.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task37/task3707/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3707/AmigoSet.java b/4.JavaCollections/src/com/javarush/task/task37/task3707/AmigoSet.java new file mode 100644 index 0000000..ebce865 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3707/AmigoSet.java @@ -0,0 +1,106 @@ +package com.javarush.task.task37.task3707; + +import java.io.*; +import java.util.*; + +/** + * Created by Archmage on 31.05.2017. + */ +public class AmigoSet extends AbstractSet implements Serializable, Cloneable, Set { + private final static Object PRESENT = new Object(); + private transient HashMap map; + + + @Override + public Iterator iterator() { + return map.keySet().iterator(); + } + + + @Override + public Object clone(){ + try { + HashMap newMap = (HashMap) map.clone(); + AmigoSet newAmigoSet = new AmigoSet(); + newAmigoSet.map = newMap; + return newAmigoSet; + }catch (Exception ex){ + throw new InternalError(); + } + } + + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + out.writeFloat(HashMapReflectionHelper.callHiddenMethod(map, "loadFactor")); + out.writeInt(HashMapReflectionHelper.callHiddenMethod(map, "capacity")); + out.writeInt(map.size()); + for (E entry: map.keySet()){ + out.writeObject(entry); + } + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + Float loadFactor = in.readFloat(); + int capacity = in.readInt(); + int size = in.readInt(); + map = new HashMap(capacity, loadFactor); + for (int i = 0; i < size; i++){ + map.put((E) in.readObject(), PRESENT); + } + + + } + + @Override + public boolean isEmpty() { + return map.isEmpty(); + } + + public boolean contains(Object o) { + return null != map.get((E) o); + } + + public void clear(){ + map.clear(); + } + + @Override + public boolean remove(Object o) { + return null != map.remove(o); + } + + @Override + public int size() { + return map.size(); + } + + public AmigoSet(){ + map = new HashMap<>(); + } + + public AmigoSet(Collection collection){ + map = new HashMap((16 > collection.size()/.75f ? 16 : (int)(collection.size()/.75f + 1))); + addAll(collection); + } + + @Override + public boolean add(E e) { + return null == map.put(e, PRESENT); + } + + + public static void main(String[] args) throws IOException, ClassNotFoundException { + AmigoSet amigoSet = new AmigoSet<>(); + amigoSet.add(4); + amigoSet.add(5); + + /*ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(new File("F:\\JavaProjects\\InputSource\\out.txt"))); + out.writeObject(amigoSet); + out.close();*/ + //System.out.println(amigoSet.remove(3)); + ObjectInputStream in = new ObjectInputStream(new FileInputStream(new File("F:\\JavaProjects\\InputSource\\out.txt"))); + amigoSet = (AmigoSet) in.readObject(); + System.out.println(amigoSet); + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3707/HashMapReflectionHelper.java b/4.JavaCollections/src/com/javarush/task/task37/task3707/HashMapReflectionHelper.java new file mode 100644 index 0000000..5cf7740 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3707/HashMapReflectionHelper.java @@ -0,0 +1,17 @@ +package com.javarush.task.task37.task3707; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; + +public class HashMapReflectionHelper { + public static T callHiddenMethod(HashMap map, String methodName) { + try { + Method method = map.getClass().getDeclaredMethod(methodName); + method.setAccessible(true); + return (T) method.invoke(map); + } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ignored) { + } + return null; + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task37/task3707/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task37/task3707/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..6bca8eb --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task37/task3707/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,106 @@ +taskKey="com.javarush.task.task37.task3707.big06" + +AmigoSet (6) + +Открой исходники HashSet (если у тебя нет исходников джавы, то скачай их и подключи), сравни со своим кодом. +Быстро это можно сделать сравнив через буфер. Скопируй код класса HashSet в буфер. +Зайди в класс AmigoSet, далее правая кнопка мыши -> Compare with Clipboard. + +Ты только что реализовал сет, аналогичный HashSet. Теперь будешь знать, как внутри устроен HashSet. +Молодец, теперь коллекции тебе не страшны! + + +Требования: +1. Поздравляю, ты написал собственную реализацию множества и изучил HashSet во всех деталях! + + +AmigoSet (5) + +Твое собственное множество AmigoSet реализует интерфейс Serializable. Однако, не сериализуется правильно. + +1. Реализуй свою логику сериализации и десериализации. +Вспоминай, какие именно приватные методы нужно добавить, чтоб сериализация пошла по твоему сценарию. +Для сериализации: +* сериализуй сет +* сериализуй capacity и loadFactor у объекта map, они понадобятся для десериализации. +Т.к. эти данные ограничены пакетом, то воспользуйся утилитным классом HashMapReflectionHelper, чтобы достать их. + +Для десериализации: +* вычитай все данные +* создай мапу используя конструктор с capacity и loadFactor + +2. Помнишь, что такое transient? + + + +AmigoSet (4) + +Твое собственное множество AmigoSet реализует интерфейс Cloneable. Однако, не клонируется правильно. +Напиши свою реализацию метода Object clone(), сделай поверхностное клонирование. + +* Клонируй множество, клонируй map. +* В случае возникновения исключений выбрось InternalError. +* Убери лишнее пробрасывание исключения. + +Расширь модификатор доступа до public. + + + +AmigoSet (3) + +Напиши свою реализацию следующих методов при условии, что нужно работать с ключами мапы: +* Iterator iterator() - очевидно, что это итератор ключей. Получи множество ключей в map, верни его итератор +* int size() - это количество ключей в map, равно количеству элементов в map +* boolean isEmpty() +* boolean contains(Object o) +* void clear() +* boolean remove(Object o) + +Ничего своего писать не нужно, используй то, что уже реализовано для множества ключей map. +Используй Alt+Insert => Override methods + + + +AmigoSet (2) + +Изобретать механизм работы с хешем не будем, он уже реализован во многих коллекциях. +Мы возьмем коллекцию HashMap и воспользуемся ей. + +1. Создай приватную константу Object PRESENT, которую инициализируй объектом Object, это будет наша заглушка. + +2. Создай private transient поле HashMap map. Список ключей будет нашим сэтом, а вместо значений будем пихать в мапу заглушку PRESENT. +Напомню, нам нужны только ключи, а вместо значений для всех ключей будем вставлять PRESENT. Там же должно что-то быть :) +Посмотрим, что из этого получится :) + +Коллекции обычно имеют несколько конструкторов, поэтому: + +3. Создай конструктор без параметров, в котором инициализируй поле map. + +4. Создай конструктор с одним параметром Collection collection. +Для инициализации поля map воспользуйся конструктором, в который передается Capacity. +Вычисли свою Capacity по такой формуле: максимальное из 16 и (collection.size()/.75f) +Добавь все элементы из collection в нашу коллекцию. +Нужный метод добавления всех элементов у нас есть благодаря тому, что AbstractSet наследуется от AbstractCollection. + +5. Напиши свою реализацию для метода метод add(E e): добавь в map элемент 'e' в качестве ключа и PRESENT в качестве значения. +Верни true, если был добавлен новый элемент, иначе верни false. + + + +AmigoSet (1) + +Давай напишем какую-нибудь коллекцию. Пусть это будет твой собственный Set. +Пусть этот класс позволяет вставку NULL. + +1. Создай класс AmigoSet. Пусть этот класс наследуется от AbstractSet. +Этот сэт должен поддерживать интерфейсы Serializable и Cloneable (как же без этого??). +Также очевидно, что он должен реализовывать интерфейс Set. + +2. Этот класс должен работать с любыми типами, поэтому сделай его дженериком: добавь тип, например, E. +Стандартные буквы, которые используют для дженериков - это E (element), T (type), K (key), V (value). +Названия не принципиальны, но облегчают чтение кода. + +3. Воспользуйся горячими клавишами Идеи и реализуй необходимые методы, оставь реализацию по умолчанию. + + + From 19a4dad6e68555539f76f109b4185a005856f844 Mon Sep 17 00:00:00 2001 From: PeucT Date: Fri, 28 Jul 2017 23:28:18 +0300 Subject: [PATCH 50/51] Level 34. Phantom ref + logging --- .../task/task34/task3407/Solution.java | 8 +- .../javarush/task/task34/task3408/Cache.java | 44 ++++++++++ .../task/task34/task3408/Solution.java | 65 +++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 31 +++++++ .../task/task34/task3409/Solution.java | 22 +++++ .../task/task34/task3409/log4j.properties | 21 +++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 26 ++++++ .../task/task34/task3412/Solution.java | 80 +++++++++++++++++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 26 ++++++ 9 files changed, 321 insertions(+), 2 deletions(-) create mode 100644 4.JavaCollections/src/com/javarush/task/task34/task3408/Cache.java create mode 100644 4.JavaCollections/src/com/javarush/task/task34/task3408/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task34/task3408/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task34/task3409/Solution.java create mode 100644 4.JavaCollections/src/com/javarush/task/task34/task3409/log4j.properties create mode 100644 "4.JavaCollections/src/com/javarush/task/task34/task3409/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" create mode 100644 4.JavaCollections/src/com/javarush/task/task34/task3412/Solution.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task34/task3412/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3407/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3407/Solution.java index f9b8f33..fff39b5 100644 --- a/4.JavaCollections/src/com/javarush/task/task34/task3407/Solution.java +++ b/4.JavaCollections/src/com/javarush/task/task34/task3407/Solution.java @@ -48,7 +48,6 @@ void callGC() throws InterruptedException { Thread.sleep(1000); } - public ReferenceQueue getQueue() { return queue; } @@ -76,7 +75,12 @@ public void checkListWithReferences(List> list, String } public List> getFilledList() { - return null; + ReferenceQueue queue = getQueue(); + List> list = new ArrayList<>(); + for (int i = 0; i < 200; i++){ + list.add(new PhantomReference(new Monkey(), queue)); + } + return list; } public void finish() throws InterruptedException { diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3408/Cache.java b/4.JavaCollections/src/com/javarush/task/task34/task3408/Cache.java new file mode 100644 index 0000000..3e540db --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3408/Cache.java @@ -0,0 +1,44 @@ +package com.javarush.task.task34.task3408; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Map; +import java.util.WeakHashMap; + +public class Cache { + private Map cache = new WeakHashMap(); //TODO add your code here + + public V getByKey(K key, Class clazz) throws Exception { + V object = cache.get(key); + if (object == null) { + Constructor constr = clazz.getConstructor(key.getClass()); + object = constr.newInstance(key); + cache.put(key, object); + } + //TODO add your code here + return object; + } + + public boolean put(V obj) { + try { + Method meth = obj.getClass().getDeclaredMethod("getKey", null); + meth.setAccessible(true); + K key = (K) meth.invoke(obj,null); + cache.put(key, obj); + return true ; + } catch (NoSuchMethodException e) { + return false; + } catch (InvocationTargetException e) { + return false; + } catch (IllegalAccessException e) { + return false; + } + //TODO add your code here + + } + + public int size() { + return cache.size(); + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3408/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3408/Solution.java new file mode 100644 index 0000000..27a540e --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3408/Solution.java @@ -0,0 +1,65 @@ +package com.javarush.task.task34.task3408; + +/* +Кэширование +*/ +public class Solution { + public static void main(String[] args) throws Exception { + SomeKey someKey = new SomeKey(); + someKey.name = "test"; + + SomeKey someKeyNew = new SomeKey(); + someKeyNew.name = "testNew"; + + SomeValue value = new SomeValue(someKey); + + Cache cache = new Cache<>(); + cache.put(value); + + SomeValue valueFromCacheExisted = cache.getByKey(someKey, SomeValue.class); + System.out.println(valueFromCacheExisted); + + SomeValue valueFromCacheNew = cache.getByKey(someKeyNew, SomeValue.class); + System.out.println(valueFromCacheNew); + + System.out.println(cache.size()); + /* expected output: + SomeValue{myKey=SomeKey{name='test'}} + SomeValue{myKey=SomeKey{name='testNew'}} + 2 + */ + } + + public static class SomeKey { + String name; + + @Override + public String toString() { + return "SomeKey{" + + "name='" + name + '\'' + + '}'; + } + } + + public static class SomeValue { + private SomeKey myKey; + + public SomeValue() { + } + + public SomeValue(SomeKey myKey) { //use this constructor + this.myKey = myKey; + } + + private SomeKey getKey() { + return myKey; + } + + @Override + public String toString() { + return "SomeValue{" + + "myKey=" + myKey + + '}'; + } + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3408/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3408/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..15ab328 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3408/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,31 @@ +taskKey="com.javarush.task.task34.task3408" + +Кэширование + +Класс Cache - универсальный параметризированный класс для кеширования объектов. +Он работает с классами(дженерик тип Т), у которых обязан быть: +а) публичный конструктор с одним параметром типа K; +б) метод K getKey() с любым модификатором доступа. + +Задание: +1. Выбери правильный тип для поля cache. Map cache должен хранить ключи, на которые есть активные ссылки. +Если нет активных ссылок на ключи, то они вместе со значениями должны автоматически удаляться из cache. +2. Реализуй логику метода getByKey: +2.1. Верни объект из cache для ключа key. +2.2. Если объекта не существует в кэше, то добавьте в кэш новый экземпляр используя рефлексию, см. пункт а). +3. Реализуй логику метода put: +3.1. Используя рефлексию получи ссылку на метод, описанный в пункте б). +3.2. Используя рефлексию разреши к нему доступ. +3.3. Используя рефлексию вызови метод getKey у объекта obj, таким образом ты получишь ключ key. +3.4. Добавь в кэш пару . +3.5. Верни true, если метод отработал корректно, false в противном случае. Исключения игнорируй. + + +Требования: +1. Поле cache должно быть инициализировано объектом типа WeakHashMap. +2. Метод getByKey должен возвращать объект из кеша. +3. Метод getByKey должен добавлять объект в кеш если его там нет. +4. Метод put должен извлекать из переданного объекта ключ и добавлять в кеш пару . +5. Метод put должен возвращать true, если он отработал корректно, иначе false. + + diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3409/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3409/Solution.java new file mode 100644 index 0000000..61bf5ff --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3409/Solution.java @@ -0,0 +1,22 @@ +package com.javarush.task.task34.task3409; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Properties; + +/* +Настраиваем логгер +*/ +public class Solution { + public static void main(String args[]) throws IOException { + String logProperties = "src/" + Solution.class.getPackage().getName().replaceAll("[.]", "/") + "/log4j.properties"; + Path path = Paths.get(logProperties).toAbsolutePath(); + try (InputStream is = new FileInputStream(path.toFile())) { + Properties properties = new Properties(); + properties.load(is); + } + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3409/log4j.properties b/4.JavaCollections/src/com/javarush/task/task34/task3409/log4j.properties new file mode 100644 index 0000000..ef04276 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3409/log4j.properties @@ -0,0 +1,21 @@ +log4j.rootLogger=WARN, file, stdout + +# Direct log messages to a log file +log4j.appender.file=org.apache.log4j.RollingFileAppender +log4j.appender.file.threshold=WARN +log4j.appender.file.File=D:\\log\\runApp.log +log4j.appender.file.MaxFileSize=5MB +log4j.appender.file.MaxBackupIndex=6 +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern= %-5p %c{1}:%L - %m%n + +# Direct log messages to stdout +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.threshold=ERROR +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} + +log4j.logger.org.springframework=ERROR +log4j.logger.org.hibernate=ERROR +log4j.logger.org.apache.cxf=ERROR diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3409/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3409/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..d797af1 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3409/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,26 @@ +taskKey="com.javarush.task.task34.task3409" + +Настраиваем логгер + +Дан файл log4j.properties, который содержит настройки логгера для разработчиков. +Изменились требования к логированию для продакшена. + +Список изменений, которые нужно сделать: +1) Размер файла для логирования не должен превышать 5 мегабайт. +2) Файлы лога должны храниться на диске D в директории log, называться должны runApp.log. +3) Файлы лога должны содержать 6 последних файлов. Если шестой файл уже заполнен(имеет размер 5Мб), +то нужно удалить самый первый и создать новый. +4) Уровень вывода сообщений в консоль нужно установить на уровне ERROR. +5) Минимальный уровень логирования выставить в WARN. + +Отредактируй файл log4j.properties в соответствии с предоставленными требованиями. + + +Требования: +1. Размер файла для логирования не должен превышать 5 мегабайт. +2. Файлы лога должны храниться на диске D в директории log, называться должны runApp.log. +3. Файлы лога должны содержать 6 последних файлов. Если шестой файл уже заполнен(имеет размер 5Мб), то нужно удалить самый первый и создать новый. +4. Уровень вывода сообщений в консоль нужно установить на уровне ERROR. +5. Минимальный уровень логирования выставить в WARN. + + diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3412/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3412/Solution.java new file mode 100644 index 0000000..df0f29d --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3412/Solution.java @@ -0,0 +1,80 @@ +package com.javarush.task.task34.task3412; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Date; + +/* +Добавление логирования в класс +*/ + +public class Solution { + private static final Logger logger = LoggerFactory.getLogger(Solution.class); + + private int value1; + private String value2; + private Date value3; + + public Solution(int value1, String value2, Date value3) { + logger.debug("constructor"); + this.value1 = value1; + this.value2 = value2; + this.value3 = value3; + } + + public static void main(String[] args) { + + } + + public void calculateAndSetValue3(long value) { + logger.trace("calculateAndSetValue3" + value); + value -= 133; + + if (value > Integer.MAX_VALUE) { + value1 = (int) (value / Integer.MAX_VALUE); + logger.debug("value1 if true"); + } else { + value1 = (int) value; + logger.debug("value1 if false"); + } + } + + public void printString() { + logger.trace("printString"); + if (value2 != null) { + System.out.println(value2.length()); + } + } + + public void printDateAsLong() { + logger.trace("printDateAsLong"); + if (value3 != null) { + System.out.println(value3.getTime()); + } + } + + public void divide(int number1, int number2) { + logger.trace("divide" + "number1=" + number1 + " number2=" + number2); + try { + System.out.println(number1 / number2); + } catch (ArithmeticException e) { + logger.error("ArichmeticExceprion", e); + } + } + + public void setValue1(int value1) { + logger.debug("setValue1"); + this.value1 = value1; + } + + public void setValue2(String value2) { + logger.debug("setValue2"); + this.value2 = value2; + } + + public void setValue3(Date value3) { + logger.debug("setValue3"); + this.value3 = value3; + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3412/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3412/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..d0f9aca --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3412/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,26 @@ +taskKey="com.javarush.task.task34.task3412" + +Добавление логирования в класс + +В Intellij IDEA Alt+Ctrl+Shift+S -> Global Libraries -> New Global Library -> From Maven... +В строке поиска в открывшемся окне укажи: org.slf4j:slf4j-api:1.7.23 -> Поиск (Shift+Enter) +Укажи куда скачать библиотеку логирования. +Выбрери к какому модулю проекта подключить библиотеку slf4j-api: нужно выбрать 4.JavaCollections -> OK +Apply -> OK. + +Посмотри где бы ты в классе Solution применил какой уровень логирования? + +В класс Solution нужно добавить вызовы методов уровня: +error - 1 раз; +debug - 6 раз - используй при изменениях значений полей класса; +trace - 4 раза - используй для отслеживания пути выполнения програмы; +Сообщения в логах старайся писать информативные. +Остальной код не изменяй. + +Требования: +1. В классе Solution должно существовать приватное статическое финальное поле logger. +2. Добавь логирование уровня error один раз. +3. Добавь логирование уровня debug шесть раз. +4. Добавь логирование уровня trace четыре раза. + + From 2e16400f8bda8bccf604441f9de7dd0d4f01404d Mon Sep 17 00:00:00 2001 From: PeucT Date: Fri, 28 Jul 2017 23:28:54 +0300 Subject: [PATCH 51/51] Level 35. Big task --- .../task/task37/task3702/AbstractFactory.java | 8 ++ .../task/task37/task3702/FactoryProducer.java | 26 ++++++ .../javarush/task/task37/task3702/Human.java | 7 ++ .../task/task37/task3702/Solution.java | 18 ++++ .../task37/task3702/female/FemaleFactory.java | 19 +++++ .../task/task37/task3702/female/KidGirl.java | 15 ++++ .../task/task37/task3702/female/TeenGirl.java | 15 ++++ .../task/task37/task3702/female/Woman.java | 13 +++ .../task/task37/task3702/male/KidBoy.java | 15 ++++ .../task37/task3702/male/MaleFactory.java | 19 +++++ .../task/task37/task3702/male/Man.java | 14 ++++ .../task/task37/task3702/male/TeenBoy.java | 15 ++++ ...\273\320\276\320\262\320\270\320\265.jrtc" | 83 +++++++++++++++++++ 13 files changed, 267 insertions(+) create mode 100644 4.JavaCollections/src/com/javarush/task/task37/task3702/AbstractFactory.java create mode 100644 4.JavaCollections/src/com/javarush/task/task37/task3702/FactoryProducer.java create mode 100644 4.JavaCollections/src/com/javarush/task/task37/task3702/Human.java create mode 100644 4.JavaCollections/src/com/javarush/task/task37/task3702/Solution.java create mode 100644 4.JavaCollections/src/com/javarush/task/task37/task3702/female/FemaleFactory.java create mode 100644 4.JavaCollections/src/com/javarush/task/task37/task3702/female/KidGirl.java create mode 100644 4.JavaCollections/src/com/javarush/task/task37/task3702/female/TeenGirl.java create mode 100644 4.JavaCollections/src/com/javarush/task/task37/task3702/female/Woman.java create mode 100644 4.JavaCollections/src/com/javarush/task/task37/task3702/male/KidBoy.java create mode 100644 4.JavaCollections/src/com/javarush/task/task37/task3702/male/MaleFactory.java create mode 100644 4.JavaCollections/src/com/javarush/task/task37/task3702/male/Man.java create mode 100644 4.JavaCollections/src/com/javarush/task/task37/task3702/male/TeenBoy.java create mode 100644 "4.JavaCollections/src/com/javarush/task/task37/task3702/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/AbstractFactory.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/AbstractFactory.java new file mode 100644 index 0000000..e14082c --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/AbstractFactory.java @@ -0,0 +1,8 @@ +package com.javarush.task.task37.task3702; + +/** + * Created by Archmage on 28.07.2017. + */ +public interface AbstractFactory { + Human getPerson(int age); +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/FactoryProducer.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/FactoryProducer.java new file mode 100644 index 0000000..e987b43 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/FactoryProducer.java @@ -0,0 +1,26 @@ +package com.javarush.task.task37.task3702; + +import com.javarush.task.task37.task3702.female.FemaleFactory; +import com.javarush.task.task37.task3702.male.MaleFactory; + +/** + * Created by Archmage on 28.07.2017. + */ +public class FactoryProducer { + public enum HumanFactoryType{ + MALE, + FEMALE + } + + public static AbstractFactory getFactory(HumanFactoryType type){ + switch (type){ + case MALE: + return new MaleFactory(); + + case FEMALE: + return new FemaleFactory(); + + } + return null; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/Human.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/Human.java new file mode 100644 index 0000000..7a71a45 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/Human.java @@ -0,0 +1,7 @@ +package com.javarush.task.task37.task3702; + +/** + * Created by Archmage on 28.07.2017. + */ +public interface Human { +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/Solution.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/Solution.java new file mode 100644 index 0000000..f33bf8f --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/Solution.java @@ -0,0 +1,18 @@ +package com.javarush.task.task37.task3702; + +public class Solution { + public static void main(String[] args) { + AbstractFactory factory = FactoryProducer.getFactory(FactoryProducer.HumanFactoryType.FEMALE); + useFactory(factory); + + factory = FactoryProducer.getFactory(FactoryProducer.HumanFactoryType.MALE); + useFactory(factory); + } + + public static void useFactory(AbstractFactory factory) { + System.out.println(factory.getPerson(99)); + System.out.println(factory.getPerson(4)); + System.out.println(factory.getPerson(15)); + } + +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/female/FemaleFactory.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/female/FemaleFactory.java new file mode 100644 index 0000000..c309e38 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/female/FemaleFactory.java @@ -0,0 +1,19 @@ +package com.javarush.task.task37.task3702.female; + +import com.javarush.task.task37.task3702.AbstractFactory; +import com.javarush.task.task37.task3702.Human; + +/** + * Created by Archmage on 28.07.2017. + */ +public class FemaleFactory implements AbstractFactory { + public Human getPerson(int age){ + if (age <= KidGirl.MAX_AGE){ + return new KidGirl(); + }else if (age <= TeenGirl.MAX_AGE){ + return new TeenGirl(); + }else { + return new Woman(); + } + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/female/KidGirl.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/female/KidGirl.java new file mode 100644 index 0000000..effea4b --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/female/KidGirl.java @@ -0,0 +1,15 @@ +package com.javarush.task.task37.task3702.female; + +import com.javarush.task.task37.task3702.Human; + +/** + * Created by Archmage on 28.07.2017. + */ +public class KidGirl implements Human { + public static final int MAX_AGE = 12; + + @Override + public String toString() { + return "KidGirl{}"; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/female/TeenGirl.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/female/TeenGirl.java new file mode 100644 index 0000000..b241727 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/female/TeenGirl.java @@ -0,0 +1,15 @@ +package com.javarush.task.task37.task3702.female; + +import com.javarush.task.task37.task3702.Human; + +/** + * Created by Archmage on 28.07.2017. + */ +public class TeenGirl implements Human { + public static final int MAX_AGE = 19; + + @Override + public String toString() { + return "TeenGirl{}"; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/female/Woman.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/female/Woman.java new file mode 100644 index 0000000..6e09793 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/female/Woman.java @@ -0,0 +1,13 @@ +package com.javarush.task.task37.task3702.female; + +import com.javarush.task.task37.task3702.Human; + +/** + * Created by Archmage on 28.07.2017. + */ +public class Woman implements Human { + @Override + public String toString() { + return "Woman{}"; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/male/KidBoy.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/male/KidBoy.java new file mode 100644 index 0000000..d6d33a6 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/male/KidBoy.java @@ -0,0 +1,15 @@ +package com.javarush.task.task37.task3702.male; + +import com.javarush.task.task37.task3702.Human; + +/** + * Created by Archmage on 28.07.2017. + */ +public class KidBoy implements Human { + public static final int MAX_AGE = 12; + + @Override + public String toString() { + return "KidBoy{}"; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/male/MaleFactory.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/male/MaleFactory.java new file mode 100644 index 0000000..dc50da0 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/male/MaleFactory.java @@ -0,0 +1,19 @@ +package com.javarush.task.task37.task3702.male; + +import com.javarush.task.task37.task3702.AbstractFactory; +import com.javarush.task.task37.task3702.Human; + +/** + * Created by Archmage on 28.07.2017. + */ +public class MaleFactory implements AbstractFactory { + public Human getPerson(int age){ + if (age <= KidBoy.MAX_AGE){ + return new KidBoy(); + }else if (age <= TeenBoy.MAX_AGE){ + return new TeenBoy(); + }else { + return new Man(); + } + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/male/Man.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/male/Man.java new file mode 100644 index 0000000..5eb37b1 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/male/Man.java @@ -0,0 +1,14 @@ +package com.javarush.task.task37.task3702.male; + +import com.javarush.task.task37.task3702.Human; + +/** + * Created by Archmage on 28.07.2017. + */ +public class Man implements Human { + + @Override + public String toString() { + return "Man{}"; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/male/TeenBoy.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/male/TeenBoy.java new file mode 100644 index 0000000..4652a95 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/male/TeenBoy.java @@ -0,0 +1,15 @@ +package com.javarush.task.task37.task3702.male; + +import com.javarush.task.task37.task3702.Human; + +/** + * Created by Archmage on 28.07.2017. + */ +public class TeenBoy implements Human { + public static final int MAX_AGE = 19; + + @Override + public String toString() { + return "TeenBoy{}"; + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task37/task3702/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task37/task3702/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..4852fad --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task37/task3702/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,83 @@ +taskKey="com.javarush.task.task37.task3702.big04" + +Фабрики (4) + +1. В корне задачи создай интерфейс AbstractFactory, в который вынеси сигнатуру общего в фабриках метода. + +2. Реализуй интерфейс AbstractFactory в обеих фабриках. + +3. В корне задачи создай класс FactoryProducer, в котором создай публичный статический энум HumanFactoryType +со значениями MALE, FEMALE. + +4. В FactoryProducer создай публичный статический метод getFactory с аргументом HumanFactoryType. +Этот метод должен возвращать одну из фабрик: для ключа MALE - MaleFactory, для FEMALE - FemaleFactory. + +Молодец, Фабрика фабрик готова! Это паттерн Abstract Factory. +В коде тебе не важно, какая фабрика используется. + +Твои успехи: +1. Освоен паттерн Factory Method. +2. Освоен паттерн Abstract Factory. +3. +2 паттерна для прохождения собеседования. +Работа джава программистом стала еще ближе, скоро достигнешь цели! + + +Требования: +1. Класс MaleFactory должен поддерживать интерфейс AbstractFactory. +2. Класс FemaleFactory должен поддерживать интерфейс AbstractFactory. +3. В классе FactoryProducer должен быть создан enum HumanFactoryType со значениями MALE, FEMALE. +4. Метод getFactory в классе FactoryProducer должен принимать один параметр типа HumanFactoryType. +5. Метод getFactory в классе FactoryProducer должен возвращать одну из фабрик в зависимости от принятого параметра. + + +Фабрики (3) + +1. Создай пакет female, в котором создай KidGirl, TeenGirl и Woman аналогично классам из пакета male. + +2. Создай в пакете female фабрику FemaleFactory аналогичную MaleFactory с тем же принципом получения объектов. + +3. Подумай, что общего у двух фабрик? Что можно сделать, чтобы легко можно было переключаться между ними? +Ответ - в следующем задании. + + + +Фабрики (2) + +1. Создай публичный класс MaleFactory в пакете male с публичным методом getPerson, который принимает один параметр int age (возраст) и +возвращает нужный объект одного из классов, реализующих интерфейс Human. + +2. Логика метода getPerson: используя константу MAX_AGE определи, какой класс соответствует переданному возрасту. +Например, age=4 соответствует мальчику (KidBoy), age=15 - подростку (TeenBoy), остальной возраст - взрослому мужчине. + +3. В методе main класса Solution создай фабрику и вызови у нее метод getPerson три раза с такими параметрами: 99, 4, 15. +Выведи результат в консоль. +Вывод должен быть следующий: +Man{} +KidBoy{} +TeenBoy{} + +Молодец, Фабрика готова! Это паттерн Factory Method. + + + +Фабрики (1) + +Привет! +Сейчас ты будешь разбираться с паттерном Factory Method. Возьмем пример с людьми. +Будем определять, к какому типу относится человек в зависимости от его возраста. + +В этом задании подготовим данные, которые будем использовать в фабрике. + +1. Для всех типов людей создай общий интерфейс Human. + +2. Будем делать Factory для мужчин. Для этого создай пакет male, в котором создай классы KidBoy, TeenBoy, Man. +Во всех этих классах реализуй интерфейс Human. + +3. В каждом классе KidBoy, TeenBoy создай свою публичную константу MAX_AGE с соответствующими значениями: 12, 19. + +4. Сгенерируй автоматические методы toString для каждого класса KidBoy, TeenBoy, Man. Получится "KidBoy{}" и т.п. + +5. Создай класс Solution с методом main. + + +