Skip to content

Commit 6474377

Browse files
authored
They have no wine
When the wine ran out, Jesus' mother said to him, "They have no wine." (John 2:3)
1 parent eed16a5 commit 6474377

1 file changed

Lines changed: 208 additions & 0 deletions

File tree

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
2+
//When the wine ran out, Jesus' mother said to him, "They have no wine." (John 2:3)
3+
4+
package com.javarush.task.task30.task3008.client;
5+
6+
import java.io.IOException;
7+
import java.text.SimpleDateFormat;
8+
import java.util.Calendar;
9+
import com.javarush.task.task30.task3008.ConsoleHelper;
10+
11+
public class BotClient extends Client {
12+
13+
public static void main(String[] args) {
14+
new BotClient().run();
15+
16+
}
17+
18+
@Override
19+
protected SocketThread getSocketThread() {
20+
return new BotSocketThread();
21+
}
22+
23+
@Override
24+
protected boolean shouldSendTextFromConsole() {
25+
return false;
26+
}
27+
28+
@Override
29+
protected String getUserName() {
30+
String botName = "date_bot_" + ((int) (Math.random() * 100));
31+
return botName;
32+
}
33+
34+
public class BotSocketThread extends SocketThread {
35+
@Override
36+
protected void clientMainLoop() throws IOException, ClassNotFoundException {
37+
sendTextMessage("Привет чатику. Я бот. Понимаю команды: дата, день, месяц, год, время, час, минуты, секунды.");
38+
super.clientMainLoop();
39+
}
40+
41+
@Override
42+
protected void processIncomingMessage(String message) {
43+
if (message != null) {
44+
ConsoleHelper.writeMessage(message);
45+
SimpleDateFormat format = null;
46+
if (message.contains(": ")) {
47+
String[] massiv = message.split(": ");
48+
if (massiv.length == 2 && massiv[1] != null) {
49+
String name = massiv[0];
50+
String text = massiv[1];
51+
switch (text) {
52+
case "дата":
53+
format = new SimpleDateFormat("d.MM.YYYY");
54+
break;
55+
case "день":
56+
format = new SimpleDateFormat("d");
57+
break;
58+
case "месяц":
59+
format = new SimpleDateFormat("MMMM");
60+
break;
61+
case "год":
62+
format = new SimpleDateFormat("YYYY");
63+
break;
64+
case "время":
65+
format = new SimpleDateFormat("H:mm:ss");
66+
break;
67+
case "час":
68+
format = new SimpleDateFormat("H");
69+
break;
70+
case "минуты":
71+
format = new SimpleDateFormat("m");
72+
break;
73+
case "секунды":
74+
format = new SimpleDateFormat("s");
75+
break;
76+
77+
}
78+
if (format != null) {
79+
sendTextMessage(String.format("Информация для %s: %s", name, format.format(Calendar.getInstance().getTime())));
80+
}
81+
}
82+
}
83+
}
84+
}
85+
}
86+
}
87+
88+
/*
89+
Чат (22)
90+
Итак, подведем итог:
91+
• Ты написал сервер для обмена текстовыми сообщениями.
92+
• Ты написал консольный клиент, который умеет подключаться к серверу и
93+
обмениваться сообщениями с другими участниками.
94+
• Ты написал бот клиента, который может принимать запросы и отправлять данные о
95+
текущей дате и времени.
96+
• Ты написал клиента для чата с графическим интерфейсом.
97+
98+
Что можно добавить или улучшить:
99+
• Можно добавить поддержку приватных сообщений (когда сообщение отправляется не
100+
всем, а какому-то конкретному участнику).
101+
• Можно расширить возможности бота, попробовать научить его отвечать на
102+
простейшие вопросы или время от времени отправлять шутки.
103+
• Добавить возможность пересылки файлов между пользователями.
104+
• Добавить контекстное меню в графический клиент, например, для отправки
105+
приватного сообщения кому-то из списка участников.
106+
• Добавить раскраску сообщений в графическом клиенте в зависимости от отправителя.
107+
• Добавить блокировку сервером участников за что-либо, например, ненормативную
108+
лексику в сообщениях.
109+
• Добавить еще миллион фич и полезностей!
110+
111+
Ты научился:
112+
• Работать с сокетами.
113+
• Пользоваться сериализацией и десериализацией.
114+
• Создавать многопоточные приложения, синхронизировать их, применять модификатор
115+
volatile, пользоваться классами из библиотеки java.util.concurrent.
116+
• Применять паттерн MVC.
117+
• Использовать внутренние и вложенные классы.
118+
• Работать с библиотекой Swing.
119+
• Применять классы Calendar и SimpleDateFormat.
120+
121+
Так держать!
122+
123+
124+
Требования:
125+
1. Поздравляю, чат готов!
126+
Чат (21)
127+
У меня есть отличнейшая новость для тебя. Компонент представление (View) уже готов. Я добавил класс ClientGuiView. Он использует библиотеку javax.swing. Ты должен как следует разобраться в каждой строчке этого класса. Если тебе все понятно – это замечательно, если нет – обязательно найди ответы на свои вопросы с помощью дебага, документации или поиска в Интернет.
128+
129+
Осталось написать компонент контроллер (Controller):
130+
1. Создай класс ClientGuiController унаследованный от Client.
131+
2. Создай и инициализируй поле, отвечающее за модель ClientGuiModel model.
132+
3. Создай и инициализируй поле, отвечающее за представление ClientGuiView view. Подумай, что нужно передать в конструктор при инициализации объекта.
133+
4. Добавь внутренний класс GuiSocketThread унаследованный от SocketThread. Класс GuiSocketThread должен быть публичным. В нем переопредели следующие методы:
134+
а) void processIncomingMessage(String message) – должен устанавливать новое сообщение у модели и вызывать обновление вывода сообщений у представления.
135+
б) void informAboutAddingNewUser(String userName) – должен добавлять нового пользователя в модель и вызывать обновление вывода пользователей у отображения.
136+
в) void informAboutDeletingNewUser(String userName) – должен удалять пользователя из модели и вызывать обновление вывода пользователей у отображения.
137+
г) void notifyConnectionStatusChanged(boolean clientConnected) – должен вызывать аналогичный метод у представления.
138+
5. Переопредели методы в классе ClientGuiController:
139+
а) SocketThread getSocketThread() – должен создавать и возвращать объект типа GuiSocketThread.
140+
б) void run() – должен получать объект SocketThread через метод getSocketThread() и вызывать у него метод run(). Разберись, почему нет необходимости вызывать метод run в отдельном потоке, как мы это делали для консольного клиента.
141+
в) getServerAddress(), getServerPort(), getUserName(). Они должны вызывать одноименные методы из представления (view).
142+
6. Реализуй метод ClientGuiModel getModel(), который должен возвращать модель.
143+
7. Реализуй метод main(), который должен создавать новый объект ClientGuiController и вызывать у него метод run().
144+
Запусти клиента с графическим окном, нескольких консольных клиентов и убедись, что
145+
все работает корректно.
146+
147+
Чат (20)
148+
Консольный клиент мы уже реализовали, чат бота тоже сделали, почему бы не сделать клиента с графическим интерфейсом? Он будет так же работать с нашим сервером, но иметь графическое окно, кнопки и т.д.
149+
Итак, приступим. При написании графического клиента будет очень уместно воспользоваться паттерном MVC (Model-View-Controller). Ты уже должен был с ним сталкиваться, если необходимо, освежи свои знания про MVC с помощью Интернет. В нашей задаче самая простая реализация будет у класса, отвечающего за модель (Model).
150+
151+
Давай напишем его:
152+
1) Создай класс ClientGuiModel в пакете client. Все классы клиента должны быть созданы в этом пакете.
153+
2) Добавь в него множество(set) строк в качестве final поля allUserNames. В нем будет храниться список всех участников чата. Проинициализируй его.
154+
3) Добавь поле String newMessage, в котором будет храниться новое сообщение, которое получил клиент.
155+
4) Добавь геттер для allUserNames, запретив модифицировать возвращенное множество. Разберись, как это можно сделать с помощью метода класса Collections.
156+
5) Добавь сеттер и геттер для поля newMessage.
157+
6) Добавь метод void addUser(String newUserName), который должен добавлять имя участника во множество, хранящее всех участников.
158+
7) Добавь метод void deleteUser(String userName), который будет удалять имя участника из множества.
159+
160+
Чат (19)
161+
Сейчас будем реализовывать класс BotSocketThread, вернее переопределять некоторые его методы, весь основной функционал он уже унаследовал от SocketThread.
162+
163+
1. Переопредели метод clientMainLoop():
164+
а) С помощью метода sendTextMessage() отправь сообщение с текстом «Привет чатику. Я бот. Понимаю команды: дата, день, месяц, год, время, час, минуты, секунды.»
165+
б) Вызови реализацию clientMainLoop() родительского класса.
166+
2. Переопредели метод processIncomingMessage(String message). Он должен следующим образом обрабатывать входящие сообщения:
167+
а) Вывести в консоль текст полученного сообщения message.
168+
б) Получить из message имя отправителя и текст сообщения. Они разделены «: «.
169+
в) Отправить ответ в зависимости от текста принятого сообщения.
170+
Если текст сообщения:
171+
«дата» – отправить сообщение содержащее текущую дату в формате «d.MM.YYYY«;
172+
«день» – в формате «d«;
173+
«месяц» — «MMMM«;
174+
«год» — «YYYY«;
175+
«время» — «H:mm:ss«;
176+
«час» — «H«;
177+
«минуты» — «m«;
178+
«секунды» — «s«.
179+
Указанный выше формат используй для создания объекта SimpleDateFormat. Для получения текущей даты необходимо использовать класс Calendar и метод getTime().
180+
Ответ должен содержать имя клиента, который прислал запрос и ожидает ответ, например, если Боб отправил запрос «время«, мы должны отправить ответ «Информация для Боб: 12:30:47«.
181+
Наш бот готов. Запусти сервер, запусти бота, обычного клиента и убедись, что все работает правильно.
182+
Помни, что message бывают разных типов и не всегда содержат «:«
183+
184+
Чат (18)
185+
Иногда бывают моменты, что не находится достойного собеседника. Не общаться же с самим собой :). Давай напишем бота, который будет представлять собой клиента, который автоматически будет отвечать на некоторые команды. Проще всего реализовать бота, который сможет отправлять текущее время или дату, когда его кто-то об этом попросит.
186+
187+
С него и начнем:
188+
1) Создай новый класс BotClient в пакете client. Он должен быть унаследован от Client.
189+
2) В классе BotClient создай внутренний класс BotSocketThread унаследованный от SocketThread. Класс BotSocketThread должен быть публичным.
190+
3) Переопредели методы:
191+
а) getSocketThread(). Он должен создавать и возвращать объект класса BotSocketThread.
192+
б) shouldSendTextFromConsole(). Он должен всегда возвращать false. Мы не хотим, чтобы бот отправлял текст введенный в консоль.
193+
в) getUserName(), метод должен генерировать новое имя бота, например: date_bot_X, где X – любое число от 0 до 99. Для генерации X используй метод Math.random().
194+
4) Добавь метод main. Он должен создавать новый объект BotClient и вызывать у него метод run().
195+
196+
Чат (17)
197+
Последний, но самый главный метод класса SocketThread – это метод void run(). Добавь его. Его реализация с учетом уже созданных методов выглядит очень просто.
198+
199+
Давай напишем ее:
200+
1) Запроси адрес и порт сервера с помощью методов getServerAddress() и getServerPort().
201+
2) Создай новый объект класса java.net.Socket, используя данные, полученные в предыдущем пункте.
202+
3) Создай объект класса Connection, используя сокет из п.17.2.
203+
4) Вызови метод, реализующий «рукопожатие» клиента с сервером (clientHandshake()).
204+
5) Вызови метод, реализующий основной цикл обработки сообщений сервера.
205+
6) При возникновении исключений IOException или ClassNotFoundException сообщи главному потоку о проблеме, используя notifyConnectionStatusChanged и false в качестве параметра.
206+
207+
Клиент готов, можешь запустить сервер, несколько клиентов и проверить как все работает.
208+
*/

0 commit comments

Comments
 (0)