feat(sorting): add selectable sorting algorithms
- add bubble and merge sort algorithm selection - add SortStrategySelectionWindow - apply selected strategy to normal and parity sorting - use dedicated comparators for student fields - remove obsolete EvenOnlyMergeSortStrategy - update collection menu labels and TODO placeholders
This commit is contained in:
@@ -1,84 +0,0 @@
|
||||
package ru.project.sorting;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.function.ToIntFunction;
|
||||
import ru.project.collection.MyList;
|
||||
|
||||
public class EvenOnlyMergeSortStrategy<T> implements SortStrategy<T> {
|
||||
|
||||
private final ToIntFunction<T> valueExtractor;
|
||||
|
||||
public EvenOnlyMergeSortStrategy(ToIntFunction<T> valueExtractor) {
|
||||
this.valueExtractor = valueExtractor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sort(MyList<T> list, Comparator<T> comparator) {
|
||||
if (list == null || list.size() <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<Integer> evenIndices = new ArrayList<>();
|
||||
List<T> evenElements = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
T element = list.get(i);
|
||||
int value = valueExtractor.applyAsInt(element);
|
||||
if (value % 2 == 0) {
|
||||
evenIndices.add(i);
|
||||
evenElements.add(element);
|
||||
}
|
||||
}
|
||||
|
||||
if (evenElements.size() <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<T> sortedEven = mergeSort(evenElements, comparator);
|
||||
|
||||
for (int j = 0; j < evenIndices.size(); j++) {
|
||||
list.set(evenIndices.get(j), sortedEven.get(j));
|
||||
}
|
||||
}
|
||||
|
||||
private List<T> mergeSort(List<T> list, Comparator<T> comparator) {
|
||||
if (list.size() <= 1) {
|
||||
return list;
|
||||
}
|
||||
|
||||
int mid = list.size() / 2;
|
||||
List<T> left = mergeSort(list.subList(0, mid), comparator);
|
||||
List<T> right = mergeSort(list.subList(mid, list.size()), comparator);
|
||||
|
||||
return merge(left, right, comparator);
|
||||
}
|
||||
|
||||
private List<T> merge(List<T> left, List<T> right, Comparator<T> comparator) {
|
||||
List<T> result = new ArrayList<>();
|
||||
int i = 0, j = 0;
|
||||
|
||||
while (i < left.size() && j < right.size()) {
|
||||
if (comparator.compare(left.get(i), right.get(j)) <= 0) {
|
||||
result.add(left.get(i));
|
||||
i++;
|
||||
} else {
|
||||
result.add(right.get(j));
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
while (i < left.size()) {
|
||||
result.add(left.get(i));
|
||||
i++;
|
||||
}
|
||||
|
||||
while (j < right.size()) {
|
||||
result.add(right.get(j));
|
||||
j++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ import ru.project.ui.base.BaseModalWindow;
|
||||
import ru.project.ui.collection.sorting.SortCollectionMenu;
|
||||
import ru.project.ui.common.CollectionDisplayWindow;
|
||||
import ru.project.ui.common.CollectionFileSaveWindow;
|
||||
import ru.project.ui.common.MessageWindow;
|
||||
|
||||
public class CurrentCollectionMenu extends BaseModalWindow {
|
||||
|
||||
@@ -15,6 +14,9 @@ public class CurrentCollectionMenu extends BaseModalWindow {
|
||||
|
||||
private final SortCollectionMenu sortCollectionMenu;
|
||||
|
||||
// private final SearchCollectionMenu searchCollectionMenu;
|
||||
// private final CountOccurrencesMenu countOccurrencesMenu;
|
||||
|
||||
public CurrentCollectionMenu(WindowBasedTextGUI gui, AppState state) {
|
||||
|
||||
super("Меню текущей коллекции", gui);
|
||||
@@ -23,6 +25,9 @@ public class CurrentCollectionMenu extends BaseModalWindow {
|
||||
|
||||
this.sortCollectionMenu = new SortCollectionMenu(gui, state);
|
||||
|
||||
// this.searchCollectionMenu = new SearchCollectionMenu(gui, state);
|
||||
// this.countCollectionMenu = new CountOccurrencesMenu(gui, state);
|
||||
|
||||
ActionListBox menu = new ActionListBox();
|
||||
|
||||
menu.addItem("Показать коллекцию...", this::showCurrentCollection);
|
||||
@@ -53,12 +58,14 @@ public class CurrentCollectionMenu extends BaseModalWindow {
|
||||
}
|
||||
|
||||
private void searchCollection() {
|
||||
// TODO
|
||||
MessageWindow.showModal(gui, "Не реализовано.");
|
||||
// SearchCollectionMenu searchCollectionMenu = new SearchCollectionMenu(gui, state);
|
||||
//
|
||||
// searchCollectionMenu.showModal();
|
||||
}
|
||||
|
||||
private void countOccurrences() {
|
||||
// TODO
|
||||
MessageWindow.showModal(gui, "Не реализовано.");
|
||||
// CountOccurrencesMenu countOccurrencesMenu = new CountOccurrencesMenu(gui, state);
|
||||
//
|
||||
// countOccurrencesMenu.showModal();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package ru.project.ui.collection.sorting;
|
||||
|
||||
public enum SortAlgorithm {
|
||||
BUBBLE,
|
||||
MERGE
|
||||
}
|
||||
@@ -5,7 +5,16 @@ 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.Comparator;
|
||||
import ru.project.model.AppState;
|
||||
import ru.project.sorting.BubbleSortStrategy;
|
||||
import ru.project.sorting.EvenOnlySortStrategy;
|
||||
import ru.project.sorting.MergeSortStrategy;
|
||||
import ru.project.sorting.SortStrategy;
|
||||
import ru.project.sorting.StudentAverageGradeComparator;
|
||||
import ru.project.sorting.StudentGroupComparator;
|
||||
import ru.project.sorting.StudentRecordBookComparator;
|
||||
import ru.project.student.Student;
|
||||
import ru.project.ui.base.BaseModalWindow;
|
||||
import ru.project.ui.common.MessageWindow;
|
||||
|
||||
@@ -13,29 +22,37 @@ public class SortCollectionMenu extends BaseModalWindow {
|
||||
|
||||
private final AppState state;
|
||||
|
||||
private final Label sortMethodLabel;
|
||||
private final Label sortAlgorithmLabel;
|
||||
private final Label sortFieldLabel;
|
||||
private final Label sortMethodLabel;
|
||||
|
||||
private final SortMethodSelectionWindow sortMethodSelectionWindow;
|
||||
private final NormalSortSettingsWindow normalSortSettingsWindow;
|
||||
private final ParitySortSettingsWindow paritySortSettingsWindow;
|
||||
private final SortMethodSelectionWindow sortMethodSelectionWindow;
|
||||
private final SortStrategySelectionWindow sortStrategySelectionWindow;
|
||||
|
||||
private SortMethod selectedSortMethod;
|
||||
private SortAlgorithm selectedSortAlgorithm;
|
||||
private SortField selectedSortField;
|
||||
private SortMethod selectedSortMethod;
|
||||
|
||||
public SortCollectionMenu(WindowBasedTextGUI gui, AppState state) {
|
||||
|
||||
super("Меню сортировки текущей коллекции", gui);
|
||||
|
||||
this.state = state;
|
||||
this.selectedSortMethod = SortMethod.NORMAL;
|
||||
|
||||
this.selectedSortAlgorithm = SortAlgorithm.BUBBLE;
|
||||
this.selectedSortField = SortField.GROUP_NUMBER;
|
||||
this.selectedSortMethod = SortMethod.NORMAL;
|
||||
|
||||
Panel panel = new Panel();
|
||||
panel.setLayoutManager(new LinearLayout());
|
||||
|
||||
this.sortMethodLabel = new Label("Способ сортировки: " + getSortMethodName(selectedSortMethod));
|
||||
|
||||
this.sortAlgorithmLabel =
|
||||
new Label("Алгоритм сортировки: " + getSortAlgorithmName(selectedSortAlgorithm));
|
||||
|
||||
this.sortFieldLabel =
|
||||
new Label("Сортировать по: " + getSortFieldName(selectedSortMethod, selectedSortField));
|
||||
|
||||
@@ -52,6 +69,16 @@ public class SortCollectionMenu extends BaseModalWindow {
|
||||
"Сортировать по: " + getSortFieldName(selectedSortMethod, selectedSortField));
|
||||
});
|
||||
|
||||
this.sortStrategySelectionWindow =
|
||||
new SortStrategySelectionWindow(
|
||||
gui,
|
||||
sortAlgorithm -> {
|
||||
selectedSortAlgorithm = sortAlgorithm;
|
||||
|
||||
sortAlgorithmLabel.setText(
|
||||
"Алгоритм сортировки: " + getSortAlgorithmName(selectedSortAlgorithm));
|
||||
});
|
||||
|
||||
this.normalSortSettingsWindow =
|
||||
new NormalSortSettingsWindow(
|
||||
gui,
|
||||
@@ -66,11 +93,14 @@ public class SortCollectionMenu extends BaseModalWindow {
|
||||
|
||||
panel.addComponent(sortMethodLabel);
|
||||
panel.addComponent(sortFieldLabel);
|
||||
panel.addComponent(sortAlgorithmLabel);
|
||||
|
||||
panel.addComponent(new Button("Выбрать способ сортировки", this::selectSortMethod));
|
||||
panel.addComponent(new Button("Выбрать способ сортировки...", this::selectSortMethod));
|
||||
|
||||
panel.addComponent(new Button("Выбрать алгоритм сортировки...", this::selectSortAlgorithm));
|
||||
|
||||
panel.addComponent(
|
||||
new Button("Настроить текущий способ сортировки", this::setupCurrentSortMethod));
|
||||
new Button("Настроить текущий способ сортировки...", this::setupCurrentSortMethod));
|
||||
|
||||
panel.addComponent(new Button("Сортировать текущую коллекцию", this::sortCurrentCollection));
|
||||
|
||||
@@ -91,6 +121,10 @@ public class SortCollectionMenu extends BaseModalWindow {
|
||||
sortMethodSelectionWindow.showModal();
|
||||
}
|
||||
|
||||
private void selectSortAlgorithm() {
|
||||
sortStrategySelectionWindow.showModal();
|
||||
}
|
||||
|
||||
private void sortCurrentCollection() {
|
||||
if (state.getMainCollection() == null || state.getMainCollection().isEmpty()) {
|
||||
|
||||
@@ -107,25 +141,64 @@ public class SortCollectionMenu extends BaseModalWindow {
|
||||
}
|
||||
|
||||
private void sortNormally() {
|
||||
// TODO
|
||||
MessageWindow.showModal(gui, "Обычная сортировка не реализована.");
|
||||
SortStrategy<Student> sortStrategy = getSortStrategy();
|
||||
|
||||
Comparator<Student> comparator = getSortComparator();
|
||||
|
||||
sortStrategy.sort(state.getMainCollection(), comparator);
|
||||
|
||||
MessageWindow.showModal(gui, "Обычная сортировка успешно выполнена.");
|
||||
}
|
||||
|
||||
private void sortByParity() {
|
||||
// TODO
|
||||
MessageWindow.showModal(gui, "Сортировка по чётности не реализована.");
|
||||
SortStrategy<Student> sortStrategy =
|
||||
new EvenOnlySortStrategy<>(getSortStrategy(), Student::getRecordBookNumber);
|
||||
|
||||
Comparator<Student> comparator = new StudentRecordBookComparator();
|
||||
|
||||
sortStrategy.sort(state.getMainCollection(), comparator);
|
||||
|
||||
MessageWindow.showModal(gui, "Сортировка по чётности успешно выполнена.");
|
||||
}
|
||||
|
||||
private SortStrategy<Student> getSortStrategy() {
|
||||
return switch (selectedSortAlgorithm) {
|
||||
case BUBBLE -> new BubbleSortStrategy<>();
|
||||
|
||||
case MERGE -> new MergeSortStrategy<>();
|
||||
};
|
||||
}
|
||||
|
||||
private Comparator<Student> getSortComparator() {
|
||||
return switch (selectedSortField) {
|
||||
case GROUP_NUMBER -> new StudentGroupComparator();
|
||||
|
||||
case AVERAGE_GRADE -> new StudentAverageGradeComparator();
|
||||
|
||||
case RECORD_BOOK_NUMBER -> new StudentRecordBookComparator();
|
||||
};
|
||||
}
|
||||
|
||||
private String getSortMethodName(SortMethod sortMethod) {
|
||||
return switch (sortMethod) {
|
||||
case NORMAL -> "Обычная сортировка";
|
||||
|
||||
case PARITY -> "Сортировка по чётности";
|
||||
};
|
||||
}
|
||||
|
||||
private String getSortAlgorithmName(SortAlgorithm sortAlgorithm) {
|
||||
return switch (sortAlgorithm) {
|
||||
case BUBBLE -> "Сортировка пузырьком";
|
||||
|
||||
case MERGE -> "Сортировка слиянием";
|
||||
};
|
||||
}
|
||||
|
||||
private String getSortFieldName(SortMethod sortMethod, SortField sortField) {
|
||||
return switch (sortMethod) {
|
||||
case NORMAL -> getNormalSortFieldName(sortField);
|
||||
|
||||
case PARITY -> "номеру зачётной книжки";
|
||||
};
|
||||
}
|
||||
@@ -133,7 +206,9 @@ public class SortCollectionMenu extends BaseModalWindow {
|
||||
private String getNormalSortFieldName(SortField sortField) {
|
||||
return switch (sortField) {
|
||||
case GROUP_NUMBER -> "номеру группы";
|
||||
|
||||
case AVERAGE_GRADE -> "среднему баллу";
|
||||
|
||||
case RECORD_BOOK_NUMBER -> "номеру зачётной книжки";
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package ru.project.ui.collection.sorting;
|
||||
|
||||
import com.googlecode.lanterna.gui2.ActionListBox;
|
||||
import com.googlecode.lanterna.gui2.WindowBasedTextGUI;
|
||||
import java.util.function.Consumer;
|
||||
import ru.project.ui.base.BaseModalWindow;
|
||||
|
||||
public class SortStrategySelectionWindow extends BaseModalWindow {
|
||||
|
||||
private final Consumer<SortAlgorithm> onSortAlgorithmSelected;
|
||||
|
||||
public SortStrategySelectionWindow(
|
||||
WindowBasedTextGUI gui, Consumer<SortAlgorithm> onSortAlgorithmSelected) {
|
||||
|
||||
super("Выбор алгоритма сортировки", gui);
|
||||
|
||||
this.onSortAlgorithmSelected = onSortAlgorithmSelected;
|
||||
|
||||
ActionListBox menu = new ActionListBox();
|
||||
|
||||
menu.addItem("Сортировка пузырьком", () -> selectSortAlgorithm(SortAlgorithm.BUBBLE));
|
||||
|
||||
menu.addItem("Сортировка слиянием", () -> selectSortAlgorithm(SortAlgorithm.MERGE));
|
||||
|
||||
menu.addItem("Выйти", this::close);
|
||||
|
||||
setComponent(menu);
|
||||
}
|
||||
|
||||
private void selectSortAlgorithm(SortAlgorithm sortAlgorithm) {
|
||||
onSortAlgorithmSelected.accept(sortAlgorithm);
|
||||
close();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user