feat(search): add occurrence counting menu and student settings
- add occurrence counting menu using StudentOccurrenceIndexFinder - add student settings window for configuring search target - display occurrence count and matching indices - update current collection menu to delegate occurrence counting
This commit is contained in:
@@ -4,6 +4,7 @@ import com.googlecode.lanterna.gui2.ActionListBox;
|
||||
import com.googlecode.lanterna.gui2.WindowBasedTextGUI;
|
||||
import ru.project.model.AppState;
|
||||
import ru.project.ui.base.BaseModalWindow;
|
||||
import ru.project.ui.collection.counting.CountOccurrencesMenu;
|
||||
import ru.project.ui.collection.search.SearchCollectionMenu;
|
||||
import ru.project.ui.collection.sorting.SortCollectionMenu;
|
||||
import ru.project.ui.common.CollectionDisplayWindow;
|
||||
@@ -15,8 +16,7 @@ public class CurrentCollectionMenu extends BaseModalWindow {
|
||||
|
||||
private final SortCollectionMenu sortCollectionMenu;
|
||||
private final SearchCollectionMenu searchCollectionMenu;
|
||||
|
||||
// private final CountOccurrencesMenu countOccurrencesMenu;
|
||||
private final CountOccurrencesMenu countOccurrencesMenu;
|
||||
|
||||
public CurrentCollectionMenu(WindowBasedTextGUI gui, AppState state) {
|
||||
|
||||
@@ -28,7 +28,7 @@ public class CurrentCollectionMenu extends BaseModalWindow {
|
||||
|
||||
this.searchCollectionMenu = new SearchCollectionMenu(gui, state);
|
||||
|
||||
// this.countCollectionMenu = new CountOccurrencesMenu(gui, state);
|
||||
this.countOccurrencesMenu = new CountOccurrencesMenu(gui, state);
|
||||
|
||||
ActionListBox menu = new ActionListBox();
|
||||
menu.addItem("Показать коллекцию...", this::showCurrentCollection);
|
||||
@@ -39,7 +39,7 @@ public class CurrentCollectionMenu extends BaseModalWindow {
|
||||
|
||||
menu.addItem("Меню поиска элемента в коллекции", searchCollectionMenu::showModal);
|
||||
|
||||
menu.addItem("Меню подсчёта количества вхождений элемента", this::countOccurrences);
|
||||
menu.addItem("Меню подсчёта количества вхождений элемента", countOccurrencesMenu::showModal);
|
||||
|
||||
menu.addItem("Выйти", this::close);
|
||||
|
||||
@@ -57,10 +57,4 @@ public class CurrentCollectionMenu extends BaseModalWindow {
|
||||
|
||||
window.showModal();
|
||||
}
|
||||
|
||||
private void countOccurrences() {
|
||||
// CountOccurrencesMenu countOccurrencesMenu = new CountOccurrencesMenu(gui, state);
|
||||
//
|
||||
// countOccurrencesMenu.showModal();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
package ru.project.ui.collection.counting;
|
||||
|
||||
import com.googlecode.lanterna.gui2.Button;
|
||||
import com.googlecode.lanterna.gui2.Label;
|
||||
import com.googlecode.lanterna.gui2.LinearLayout;
|
||||
import com.googlecode.lanterna.gui2.Panel;
|
||||
import com.googlecode.lanterna.gui2.WindowBasedTextGUI;
|
||||
import ru.project.collection.MyList;
|
||||
import ru.project.finder.StudentOccurrenceIndexFinder;
|
||||
import ru.project.model.AppState;
|
||||
import ru.project.student.Student;
|
||||
import ru.project.ui.base.BaseModalWindow;
|
||||
import ru.project.ui.common.MessageWindow;
|
||||
|
||||
public class CountOccurrencesMenu extends BaseModalWindow {
|
||||
|
||||
private final AppState state;
|
||||
|
||||
private final OccurrenceStudentSettingsWindow occurrenceStudentSettingsWindow;
|
||||
|
||||
private Student selectedStudent;
|
||||
private int occurrences;
|
||||
|
||||
private final Label studentLabel;
|
||||
private final Label occurrencesLabel;
|
||||
|
||||
public CountOccurrencesMenu(WindowBasedTextGUI gui, AppState state) {
|
||||
|
||||
super("Меню подсчёта количества вхождений элемента", gui);
|
||||
|
||||
this.state = state;
|
||||
this.selectedStudent = null;
|
||||
this.occurrences = 0;
|
||||
|
||||
this.studentLabel = new Label("Элемент для поиска: не задан");
|
||||
|
||||
this.occurrencesLabel = new Label("Количество вхождений: не подсчитано");
|
||||
|
||||
this.occurrenceStudentSettingsWindow =
|
||||
new OccurrenceStudentSettingsWindow(
|
||||
gui,
|
||||
student -> {
|
||||
selectedStudent = student;
|
||||
|
||||
studentLabel.setText("Элемент для поиска: задан");
|
||||
});
|
||||
|
||||
Panel panel = new Panel();
|
||||
panel.setLayoutManager(new LinearLayout());
|
||||
|
||||
panel.addComponent(studentLabel);
|
||||
panel.addComponent(occurrencesLabel);
|
||||
|
||||
panel.addComponent(new Button("Настроить элемент для поиска...", this::setupStudent));
|
||||
|
||||
panel.addComponent(new Button("Выполнить подсчёт", this::countOccurrences));
|
||||
|
||||
panel.addComponent(new Button("Выйти", this::close));
|
||||
|
||||
setComponent(panel);
|
||||
}
|
||||
|
||||
private void setupStudent() {
|
||||
occurrenceStudentSettingsWindow.showModal();
|
||||
}
|
||||
|
||||
private void countOccurrences() {
|
||||
MyList<Student> collection = state.getMainCollection();
|
||||
|
||||
if (collection == null || collection.isEmpty()) {
|
||||
MessageWindow.showModal(gui, "Текущая коллекция пуста.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (selectedStudent == null) {
|
||||
MessageWindow.showModal(gui, "Сначала настройте элемент для поиска.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
StudentOccurrenceIndexFinder finder = new StudentOccurrenceIndexFinder();
|
||||
|
||||
int[] occurrenceIndices = finder.findOccurrences(collection, selectedStudent);
|
||||
|
||||
occurrences = occurrenceIndices.length;
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
result.append("Количество вхождений: ").append(occurrences);
|
||||
|
||||
result.append("\nИндексы: ");
|
||||
|
||||
if (occurrenceIndices.length == 0) {
|
||||
result.append("нет");
|
||||
} else {
|
||||
for (int i = 0; i < occurrenceIndices.length; i++) {
|
||||
|
||||
if (i > 0) {
|
||||
result.append(", ");
|
||||
}
|
||||
|
||||
result.append(occurrenceIndices[i]);
|
||||
}
|
||||
}
|
||||
|
||||
occurrencesLabel.setText(result.toString());
|
||||
}
|
||||
}
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
package ru.project.ui.collection.counting;
|
||||
|
||||
import com.googlecode.lanterna.gui2.Button;
|
||||
import com.googlecode.lanterna.gui2.Label;
|
||||
import com.googlecode.lanterna.gui2.LinearLayout;
|
||||
import com.googlecode.lanterna.gui2.Panel;
|
||||
import com.googlecode.lanterna.gui2.WindowBasedTextGUI;
|
||||
import java.util.function.Consumer;
|
||||
import ru.project.student.Student;
|
||||
import ru.project.student.StudentBuilder;
|
||||
import ru.project.ui.base.BaseModalWindow;
|
||||
import ru.project.ui.common.InputValueWindow;
|
||||
import ru.project.ui.common.MessageWindow;
|
||||
|
||||
public class OccurrenceStudentSettingsWindow extends BaseModalWindow {
|
||||
|
||||
private final StudentBuilder studentBuilder;
|
||||
private final Consumer<Student> onApply;
|
||||
|
||||
private String groupNumber;
|
||||
private Double averageGrade;
|
||||
private Integer recordBookNumber;
|
||||
|
||||
private final Label groupNumberLabel;
|
||||
private final Label averageGradeLabel;
|
||||
private final Label recordBookNumberLabel;
|
||||
|
||||
public OccurrenceStudentSettingsWindow(WindowBasedTextGUI gui, Consumer<Student> onApply) {
|
||||
|
||||
super("Настройка элемента для поиска", gui);
|
||||
|
||||
this.studentBuilder = new StudentBuilder();
|
||||
this.onApply = onApply;
|
||||
|
||||
Panel panel = new Panel();
|
||||
panel.setLayoutManager(new LinearLayout());
|
||||
|
||||
groupNumberLabel = new Label("Номер группы: не задан");
|
||||
|
||||
averageGradeLabel = new Label("Средний балл: не задан");
|
||||
|
||||
recordBookNumberLabel = new Label("Номер зачётной книжки: не задан");
|
||||
|
||||
panel.addComponent(groupNumberLabel);
|
||||
panel.addComponent(averageGradeLabel);
|
||||
panel.addComponent(recordBookNumberLabel);
|
||||
|
||||
panel.addComponent(new Button("Задать номер группы...", this::setGroupNumber));
|
||||
|
||||
panel.addComponent(new Button("Задать средний балл...", this::setAverageGrade));
|
||||
|
||||
panel.addComponent(new Button("Задать номер зачётной книжки...", this::setRecordBookNumber));
|
||||
|
||||
panel.addComponent(new Button("Применить", this::apply));
|
||||
|
||||
panel.addComponent(new Button("Выйти", this::close));
|
||||
|
||||
setComponent(panel);
|
||||
}
|
||||
|
||||
private void setGroupNumber() {
|
||||
InputValueWindow window =
|
||||
new InputValueWindow(
|
||||
gui,
|
||||
"Номер группы",
|
||||
"Введите номер группы (например, A12):",
|
||||
groupNumber,
|
||||
value -> {
|
||||
if (!value.matches(Student.getGroupNumberPattern())) {
|
||||
|
||||
MessageWindow.showModal(gui, "Номер группы должен соответствовать формату A12.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
groupNumber = value;
|
||||
studentBuilder.setGroupNumber(value);
|
||||
|
||||
groupNumberLabel.setText("Номер группы: " + groupNumber);
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
window.showModal();
|
||||
}
|
||||
|
||||
private void setAverageGrade() {
|
||||
InputValueWindow window =
|
||||
new InputValueWindow(
|
||||
gui,
|
||||
"Средний балл",
|
||||
"Введите средний балл от 0.0 до 5.0:",
|
||||
averageGrade == null ? null : String.valueOf(averageGrade),
|
||||
value -> {
|
||||
try {
|
||||
double parsedValue = Double.parseDouble(value);
|
||||
|
||||
if (parsedValue < Student.getMinAverageGrade()
|
||||
|| parsedValue > Student.getMaxAverageGrade()) {
|
||||
|
||||
MessageWindow.showModal(gui, "Средний балл должен быть от 0.0 до 5.0.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
averageGrade = parsedValue;
|
||||
studentBuilder.setAverageGrade(parsedValue);
|
||||
|
||||
averageGradeLabel.setText("Средний балл: " + averageGrade);
|
||||
|
||||
return true;
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
MessageWindow.showModal(gui, "Введите корректное число.");
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
window.showModal();
|
||||
}
|
||||
|
||||
private void setRecordBookNumber() {
|
||||
InputValueWindow window =
|
||||
new InputValueWindow(
|
||||
gui,
|
||||
"Номер зачётной книжки",
|
||||
"Введите номер зачётной книжки:",
|
||||
recordBookNumber == null ? null : String.valueOf(recordBookNumber),
|
||||
value -> {
|
||||
try {
|
||||
int parsedValue = Integer.parseInt(value);
|
||||
|
||||
if (parsedValue < Student.getMinRecordBookNumber()) {
|
||||
|
||||
MessageWindow.showModal(gui, "Номер зачётной книжки должен быть положительным.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
recordBookNumber = parsedValue;
|
||||
studentBuilder.setRecordBookNumber(parsedValue);
|
||||
|
||||
recordBookNumberLabel.setText("Номер зачётной книжки: " + recordBookNumber);
|
||||
|
||||
return true;
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
MessageWindow.showModal(gui, "Введите целое число.");
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
window.showModal();
|
||||
}
|
||||
|
||||
private void apply() {
|
||||
if (groupNumber == null || averageGrade == null || recordBookNumber == null) {
|
||||
|
||||
MessageWindow.showModal(gui, "Необходимо задать все поля элемента.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Student student = studentBuilder.build();
|
||||
|
||||
onApply.accept(student);
|
||||
|
||||
MessageWindow.showModal(gui, "Элемент для поиска успешно настроен.");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user