1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
| import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
public class StartUI {
private static final String[] OPERATION = {"Доход", "Расход"};
private static final String PATH = "C:\\list.txt";
public static void main(String[] args) {
//создаём объект MenuTracker и передаём в него "Массив опреаций", List, который считываем из файла методом
//readFile из класса WorkFile и путь к файлу (PATH)
//и сразу запускаем из объекта метод init()
//WorkFile.readFile(PATH) - это как раз мы при запуске читаем файл, если он есть
new MenuTracker(new BaseOperation(OPERATION, WorkFile.readFile(PATH)), new ReadConsole(), OPERATION, PATH).init();
}
}
abstract class MenuAbstract {
//номер меню
private int key;
//название меню
private String name;
public MenuAbstract(int key, String name) {
this.key = key;
this.name = name;
}
//метод действия меню
public abstract void execute(BaseOperation base, ReadConsole console);
//получаем номер меню
public int getKey() {
return this.key;
}
//получаем строку меню (номер + название)
public String info() {
return String.format("%2d: %s", this.key, this.name);
}
}
class MenuTracker {
//лист менюшек
private List<MenuAbstract> menus;
//ссылка нашей базы (класса работы с операциями)
private BaseOperation base;
//ссылка на класс работы с консолью
private ReadConsole console;
//массив операций (их 2 Доход, Расход)
private String[] operations;
//путь к файлу
private String path;
public MenuTracker(BaseOperation base, ReadConsole console, String[] operations, String path) {
this.base = base;
this.console = console;
this.operations = operations;
this.menus = new ArrayList<>();
this.path = path;
}
//метод заполнения листа меню
private void fillMenu() {
this.menus.add(new MenuAdd(1, "Добавить " + operations[0] + ";", operations[0]));
this.menus.add(new MenuAdd(2, "Добавить " + operations[1] + ";", operations[1]));
this.menus.add(new MenuSolution(3, "Расчитать " + operations[0] + ";"));
this.menus.add(new MenuPrintByDate(4, "Вывести " + operations[0] + "ы по дате;", operations[0]));
this.menus.add(new MenuPrintByDate(5, "Вывести " + operations[1] + "ы по дате;", operations[1]));
this.menus.add(new MenuPrintAll(6, "Вывести все " + operations[0] + "ы;", operations[0]));
this.menus.add(new MenuPrintAll(7, "Вывести все " + operations[1] + "ы;", operations[1]));
this.menus.add(new MenuPrintAll(8, "Вывести все данные;", null));
this.menus.add(new MenuExit(0, "Выход из программы;"));
}
//метод выводит меню в консоль (печатает лист менюшек)
private void showMenu() {
System.out.println();
for (MenuAbstract menu : this.menus) {
System.out.println(menu.info());
}
System.out.println();
}
//главный метод работы с меню и пользователем
public void init() {
fillMenu(); //заполняем меню
int key;
do {
showMenu(); //отрисовываем меню на экран
key = console.readInt("Введите пункт меню", 0, menus.size() - 1); //просим ввести номер меню используя метод из класса ReadConsole
for (MenuAbstract menu : this.menus) { //ищем введённый ключ в листе менюшек
if (menu.getKey() == key) { //если найден
menu.execute(base, console); //вызываем по нему действие меню
}
}
} while (key != 0); //выходим если ввели 0
//WorkFile.writeFile(base.toArray(null, null), path) - как раз при выходе записываем в файл
//base.toArray(null, null) - т.к. 2 параметра null, то метод возвращает нам все данные
//path - путь к файлу
WorkFile.writeFile(base.toArray(null, null), path); //в конце работы при выходе записываем всё в файл
}
class MenuExit extends MenuAbstract {
public MenuExit(int key, String name) {
super(key, name);
}
@Override
public void execute(BaseOperation base, ReadConsole console) {
System.out.printf("%sПрограмма завершена.%s", System.lineSeparator(), System.lineSeparator());
}
}
class MenuAdd extends MenuAbstract {
private String operation;
public MenuAdd(int key, String name, String operation) {
super(key, name);
this.operation = operation;
}
@Override
public void execute(BaseOperation base, ReadConsole console) {
System.out.println();
float money = console.readFloat("Введите " + operation, 0, Float.MAX_VALUE);
String comment = console.readString("Введите комментарий");
boolean result = base.addOperation(new Operation(operation, money, comment));
if (result) {
System.out.println(operation + " успешно добавлен.");
} else {
System.out.println(operation + " не добавлен.");
}
}
}
class MenuSolution extends MenuAbstract {
public MenuSolution(int key, String name) {
super(key, name);
}
@Override
public void execute(BaseOperation base, ReadConsole console) {
System.out.printf("%sСуммарный доход: %.2f;%s",
System.lineSeparator(), base.solutionOperation(), System.lineSeparator());
}
}
class MenuPrintAll extends MenuAbstract {
private String operation;
public MenuPrintAll(int key, String name, String operation) {
super(key, name);
this.operation = operation;
}
@Override
public void execute(BaseOperation base, ReadConsole console) {
String names = String.format("%s%s %10s %15s %25s", System.lineSeparator(), "ОПЕРАЦИЯ", "ДАТА", "СУММА", "КОММЕНТАРИЙ");
String title = String.format("=========================================================================");
System.out.println(names + System.lineSeparator() + title);
List<Operation> list = base.toArray(operation, null);
if (list.size() != 0) {
for (Operation element : list) {
System.out.println(element);
}
} else {
System.out.printf("%25s%s", "данные не найдены", System.lineSeparator());
}
System.out.println(title);
}
}
class MenuPrintByDate extends MenuAbstract {
private String operation;
public MenuPrintByDate(int key, String name, String operation) {
super(key, name);
this.operation = operation;
}
@Override
public void execute(BaseOperation base, ReadConsole console) {
System.out.println();
Date date = console.readDate("Введите дату для поиска", "dd.MM.yyyy");
String names = String.format("%s%s %10s %15s %25s", System.lineSeparator(), "ОПЕРАЦИЯ", "ДАТА", "СУММА", "КОММЕНТАРИЙ");
String title = String.format("=========================================================================");
System.out.println(names + System.lineSeparator() + title);
List<Operation> list = base.toArray(operation, date);
if (list.size() != 0) {
for (Operation element : list) {
System.out.println(element);
}
} else {
System.out.printf("%25s%s", "данные не найдены", System.lineSeparator());
}
System.out.println(title);
}
}
}
/**
* Класс работы с консолью. Имеет разные методы для получения данных с консоли
*/
class ReadConsole {
private Scanner read = new Scanner(System.in);
public String readString(String text) {
String result = "";
boolean correct = false;
while (!correct) {
System.out.print(text + ": ");
result = read.nextLine().trim();
if (result.length() > 0) {
correct = true;
} else {
System.out.println("Не корректный комментарий. Попробуйте снова...");
}
}
return result;
}
public float readFloat(String text, float startRange, float endRange) {
float result = 0;
boolean correct = false;
while (!correct) {
System.out.printf("%s: ", text);
String line = read.nextLine();
try {
result = Float.parseFloat(line);
if (result >= startRange && result <= endRange) {
correct = true;
} else {
System.out.printf("Число должно быть не меньше %f и не больше %f. Попробуйте снова...%s",
startRange, endRange, System.lineSeparator());
}
} catch (NumberFormatException e) {
System.out.println("Вы ввели не число. Попробуйте снова...");
}
}
return result;
}
public int readInt(String text, int startRange, int endRange) {
int result = -1;
boolean correct = false;
while (!correct) {
System.out.printf("%s: ", text);
String line = read.nextLine();
try {
result = Integer.parseInt(line);
if (result >= startRange && result <= endRange) {
correct = true;
} else {
System.out.printf("Число должно быть не меньше %d и не больше %d. Попробуйте снова...%s",
startRange, endRange, System.lineSeparator());
}
} catch (NumberFormatException e) {
System.out.println("Вы ввели не число. Попробуйте снова...");
}
}
return result;
}
public Date readDate(String text, String format) {
Date date = null;
boolean correct = false;
while (!correct) {
System.out.printf("%s [%s]: ", text, format);
String dateStr = read.nextLine();
try {
date = new SimpleDateFormat(format).parse(dateStr);
correct = true;
} catch (ParseException e) {
System.out.printf("Вы ввели не корректную дату. Формат даты [%s]. Попробуйте снова...%s",
format, System.lineSeparator());
}
}
return date;
}
}
/**
* Класс для хранения данных во время работы программы и
* набором методов для работы с коллекцией
*/
class BaseOperation {
private String[] nameOperations;
private Map<String, Map<Date, List<Operation>>> map; //главня коллекция для хранения данных
BaseOperation(String[] nameOperations) {
this.map = new HashMap<>();
this.nameOperations = nameOperations;
}
BaseOperation(String[] nameOperations, List<Operation> operations) {
this(nameOperations);
addAll(operations);
}
//добавляем операцию в коллекцию
public boolean addOperation(Operation operation) {
boolean result;
if (result = operation != null) {
Map<Date, List<Operation>> value;
if (!map.containsKey(operation.getOperation())) {
map.put(operation.getOperation(), new HashMap<>());
}
value = map.get(operation.getOperation());
List<Operation> list;
if (!value.containsKey(operation.getCreateDate())) {
value.put(operation.getCreateDate(), new ArrayList<>());
}
list = value.get(operation.getCreateDate());
list.add(operation);
}
return result;
}
//добавляем весь лист операций в коллекцию
private void addAll(List<Operation> operations) {
if (operations != null) {
for (Operation operation : operations) {
addOperation(operation);
}
}
}
//возвращаем лист данных в зависимости от параметров
//если 2 параметра null - возвращаем все данные коллекции
//если date = null, то возвращаем данные по operation
//если operation = null, то возвращаем данные по date
public List<Operation> toArray(String operation, Date date) {
List<Operation> list = new ArrayList<>();
if (map.size() != 0) {
for (Map.Entry<String, Map<Date, List<Operation>>> mapOperation : map.entrySet()) {
if (mapOperation.getValue().size() != 0) {
for (Map.Entry<Date, List<Operation>> mapDate : mapOperation.getValue().entrySet()) {
if (mapDate.getValue().size() != 0) {
if (operation == null || operation.equals(mapOperation.getKey()) &&
(date == null || date.equals(mapDate.getKey()))) {
for (Operation oper : mapDate.getValue()) {
list.add(oper);
}
}
}
}
}
}
}
return list;
}
//суммируем все доходы и отнимаем сумму всех расходов
public float solutionOperation() {
List<Operation> listIncome = toArray(nameOperations[0], null);
List<Operation> listExpense = toArray(nameOperations[1], null);
float sumIncome = 0;
float sumExpense = 0;
for (Operation operation : listIncome) {
sumIncome += operation.getMoney();
}
for (Operation operation : listExpense) {
sumExpense += operation.getMoney();
}
return sumIncome - sumExpense;
}
}
/**
* Класс для записи в файл или читание файла
*/
class WorkFile {
public static List<Operation> readFile(String path) {
List<Operation> list = new ArrayList<>();
if (path != null) {
try {
List<String> listStr = Files.readAllLines(Paths.get(path));
if (listStr != null) {
for (String line : listStr) {
Operation operation = convertStringToOperation(line);
if (operation != null) {
list.add(operation);
}
}
}
} catch (IOException e) {
//если файла нет, ничего не загружаем
}
}
return list;
}
public static void writeFile(List<Operation> list, String path) {
if (path != null && list != null) {
List<String> writeList = new ArrayList<>();
for (Operation operation : list) {
writeList.add(operation.toStringForWrite());
}
try {
Files.write(Paths.get(path), writeList);
} catch (IOException e) {
e.printStackTrace();
}
}
}
//метод конвертирует считанную строку в объект Operation
private static Operation convertStringToOperation(String line) {
Operation result = null;
boolean isOk = true;
if (line != null) {
String[] attribute = line.split(";");
if (attribute.length >= 4) {
String operation = attribute[0];
String comment = attribute[3];
Date date = null;
float money = 0;
try {
date = new SimpleDateFormat("dd.MM.yyyy").parse(attribute[1]);
money = Float.parseFloat(attribute[2]);
} catch (ParseException | NumberFormatException e) {
isOk = false;
}
if (isOk) {
result = new Operation(operation, money, date, comment);
}
}
}
return result;
}
}
//Класс-модель для хранения данных
class Operation {
private String operation;
private float money;
private Date createDate;
private String comment;
public String getOperation() {
return operation;
}
public float getMoney() {
return money;
}
public Date getCreateDate() {
return createDate;
}
public String getComment() {
return comment;
}
public Operation(String operation, float money, Date createDate, String comment) {
this.operation = operation;
this.money = money;
this.createDate = createDate;
this.comment = comment;
}
public Operation(String operation, float money, String comment) {
this(operation, money, new Date(), comment);
}
@Override
public String toString() {
return String.format("%6s %15s %18s %s",
this.operation, new SimpleDateFormat("dd.MM.yyyy").format(this.createDate), formatMoney(), this.comment);
}
public String toStringForWrite() {
return String.format("%s;%s;%s;%s", this.operation,
new SimpleDateFormat("dd.MM.yyyy").format(this.createDate), this.money, this.comment);
}
private String formatMoney() {
StringBuilder sb = new StringBuilder();
String money = String.format("%.2f", this.money);
String coin = money.substring(money.length() - 3, money.length());
money = money.substring(0, money.length() - 3);
int count = 0;
for (int i = money.length() - 1; i >= 0; i--) {
count++;
sb.append(money.charAt(i));
if (count == 3) {
sb.append(" ");
count = 0;
}
}
return sb.reverse().toString() + coin;
}
} |