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.collection.sorting.SortCollectionMenu;
|
||||||
import ru.project.ui.common.CollectionDisplayWindow;
|
import ru.project.ui.common.CollectionDisplayWindow;
|
||||||
import ru.project.ui.common.CollectionFileSaveWindow;
|
import ru.project.ui.common.CollectionFileSaveWindow;
|
||||||
import ru.project.ui.common.MessageWindow;
|
|
||||||
|
|
||||||
public class CurrentCollectionMenu extends BaseModalWindow {
|
public class CurrentCollectionMenu extends BaseModalWindow {
|
||||||
|
|
||||||
@@ -15,6 +14,9 @@ public class CurrentCollectionMenu extends BaseModalWindow {
|
|||||||
|
|
||||||
private final SortCollectionMenu sortCollectionMenu;
|
private final SortCollectionMenu sortCollectionMenu;
|
||||||
|
|
||||||
|
// private final SearchCollectionMenu searchCollectionMenu;
|
||||||
|
// private final CountOccurrencesMenu countOccurrencesMenu;
|
||||||
|
|
||||||
public CurrentCollectionMenu(WindowBasedTextGUI gui, AppState state) {
|
public CurrentCollectionMenu(WindowBasedTextGUI gui, AppState state) {
|
||||||
|
|
||||||
super("Меню текущей коллекции", gui);
|
super("Меню текущей коллекции", gui);
|
||||||
@@ -23,6 +25,9 @@ public class CurrentCollectionMenu extends BaseModalWindow {
|
|||||||
|
|
||||||
this.sortCollectionMenu = new SortCollectionMenu(gui, state);
|
this.sortCollectionMenu = new SortCollectionMenu(gui, state);
|
||||||
|
|
||||||
|
// this.searchCollectionMenu = new SearchCollectionMenu(gui, state);
|
||||||
|
// this.countCollectionMenu = new CountOccurrencesMenu(gui, state);
|
||||||
|
|
||||||
ActionListBox menu = new ActionListBox();
|
ActionListBox menu = new ActionListBox();
|
||||||
|
|
||||||
menu.addItem("Показать коллекцию...", this::showCurrentCollection);
|
menu.addItem("Показать коллекцию...", this::showCurrentCollection);
|
||||||
@@ -53,12 +58,14 @@ public class CurrentCollectionMenu extends BaseModalWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void searchCollection() {
|
private void searchCollection() {
|
||||||
// TODO
|
// SearchCollectionMenu searchCollectionMenu = new SearchCollectionMenu(gui, state);
|
||||||
MessageWindow.showModal(gui, "Не реализовано.");
|
//
|
||||||
|
// searchCollectionMenu.showModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void countOccurrences() {
|
private void countOccurrences() {
|
||||||
// TODO
|
// CountOccurrencesMenu countOccurrencesMenu = new CountOccurrencesMenu(gui, state);
|
||||||
MessageWindow.showModal(gui, "Не реализовано.");
|
//
|
||||||
|
// 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.LinearLayout;
|
||||||
import com.googlecode.lanterna.gui2.Panel;
|
import com.googlecode.lanterna.gui2.Panel;
|
||||||
import com.googlecode.lanterna.gui2.WindowBasedTextGUI;
|
import com.googlecode.lanterna.gui2.WindowBasedTextGUI;
|
||||||
|
import java.util.Comparator;
|
||||||
import ru.project.model.AppState;
|
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.base.BaseModalWindow;
|
||||||
import ru.project.ui.common.MessageWindow;
|
import ru.project.ui.common.MessageWindow;
|
||||||
|
|
||||||
@@ -13,29 +22,37 @@ public class SortCollectionMenu extends BaseModalWindow {
|
|||||||
|
|
||||||
private final AppState state;
|
private final AppState state;
|
||||||
|
|
||||||
private final Label sortMethodLabel;
|
private final Label sortAlgorithmLabel;
|
||||||
private final Label sortFieldLabel;
|
private final Label sortFieldLabel;
|
||||||
|
private final Label sortMethodLabel;
|
||||||
|
|
||||||
private final SortMethodSelectionWindow sortMethodSelectionWindow;
|
|
||||||
private final NormalSortSettingsWindow normalSortSettingsWindow;
|
private final NormalSortSettingsWindow normalSortSettingsWindow;
|
||||||
private final ParitySortSettingsWindow paritySortSettingsWindow;
|
private final ParitySortSettingsWindow paritySortSettingsWindow;
|
||||||
|
private final SortMethodSelectionWindow sortMethodSelectionWindow;
|
||||||
|
private final SortStrategySelectionWindow sortStrategySelectionWindow;
|
||||||
|
|
||||||
private SortMethod selectedSortMethod;
|
private SortAlgorithm selectedSortAlgorithm;
|
||||||
private SortField selectedSortField;
|
private SortField selectedSortField;
|
||||||
|
private SortMethod selectedSortMethod;
|
||||||
|
|
||||||
public SortCollectionMenu(WindowBasedTextGUI gui, AppState state) {
|
public SortCollectionMenu(WindowBasedTextGUI gui, AppState state) {
|
||||||
|
|
||||||
super("Меню сортировки текущей коллекции", gui);
|
super("Меню сортировки текущей коллекции", gui);
|
||||||
|
|
||||||
this.state = state;
|
this.state = state;
|
||||||
this.selectedSortMethod = SortMethod.NORMAL;
|
|
||||||
|
this.selectedSortAlgorithm = SortAlgorithm.BUBBLE;
|
||||||
this.selectedSortField = SortField.GROUP_NUMBER;
|
this.selectedSortField = SortField.GROUP_NUMBER;
|
||||||
|
this.selectedSortMethod = SortMethod.NORMAL;
|
||||||
|
|
||||||
Panel panel = new Panel();
|
Panel panel = new Panel();
|
||||||
panel.setLayoutManager(new LinearLayout());
|
panel.setLayoutManager(new LinearLayout());
|
||||||
|
|
||||||
this.sortMethodLabel = new Label("Способ сортировки: " + getSortMethodName(selectedSortMethod));
|
this.sortMethodLabel = new Label("Способ сортировки: " + getSortMethodName(selectedSortMethod));
|
||||||
|
|
||||||
|
this.sortAlgorithmLabel =
|
||||||
|
new Label("Алгоритм сортировки: " + getSortAlgorithmName(selectedSortAlgorithm));
|
||||||
|
|
||||||
this.sortFieldLabel =
|
this.sortFieldLabel =
|
||||||
new Label("Сортировать по: " + getSortFieldName(selectedSortMethod, selectedSortField));
|
new Label("Сортировать по: " + getSortFieldName(selectedSortMethod, selectedSortField));
|
||||||
|
|
||||||
@@ -52,6 +69,16 @@ public class SortCollectionMenu extends BaseModalWindow {
|
|||||||
"Сортировать по: " + getSortFieldName(selectedSortMethod, selectedSortField));
|
"Сортировать по: " + getSortFieldName(selectedSortMethod, selectedSortField));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.sortStrategySelectionWindow =
|
||||||
|
new SortStrategySelectionWindow(
|
||||||
|
gui,
|
||||||
|
sortAlgorithm -> {
|
||||||
|
selectedSortAlgorithm = sortAlgorithm;
|
||||||
|
|
||||||
|
sortAlgorithmLabel.setText(
|
||||||
|
"Алгоритм сортировки: " + getSortAlgorithmName(selectedSortAlgorithm));
|
||||||
|
});
|
||||||
|
|
||||||
this.normalSortSettingsWindow =
|
this.normalSortSettingsWindow =
|
||||||
new NormalSortSettingsWindow(
|
new NormalSortSettingsWindow(
|
||||||
gui,
|
gui,
|
||||||
@@ -66,11 +93,14 @@ public class SortCollectionMenu extends BaseModalWindow {
|
|||||||
|
|
||||||
panel.addComponent(sortMethodLabel);
|
panel.addComponent(sortMethodLabel);
|
||||||
panel.addComponent(sortFieldLabel);
|
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(
|
panel.addComponent(
|
||||||
new Button("Настроить текущий способ сортировки", this::setupCurrentSortMethod));
|
new Button("Настроить текущий способ сортировки...", this::setupCurrentSortMethod));
|
||||||
|
|
||||||
panel.addComponent(new Button("Сортировать текущую коллекцию", this::sortCurrentCollection));
|
panel.addComponent(new Button("Сортировать текущую коллекцию", this::sortCurrentCollection));
|
||||||
|
|
||||||
@@ -91,6 +121,10 @@ public class SortCollectionMenu extends BaseModalWindow {
|
|||||||
sortMethodSelectionWindow.showModal();
|
sortMethodSelectionWindow.showModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void selectSortAlgorithm() {
|
||||||
|
sortStrategySelectionWindow.showModal();
|
||||||
|
}
|
||||||
|
|
||||||
private void sortCurrentCollection() {
|
private void sortCurrentCollection() {
|
||||||
if (state.getMainCollection() == null || state.getMainCollection().isEmpty()) {
|
if (state.getMainCollection() == null || state.getMainCollection().isEmpty()) {
|
||||||
|
|
||||||
@@ -107,25 +141,64 @@ public class SortCollectionMenu extends BaseModalWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void sortNormally() {
|
private void sortNormally() {
|
||||||
// TODO
|
SortStrategy<Student> sortStrategy = getSortStrategy();
|
||||||
MessageWindow.showModal(gui, "Обычная сортировка не реализована.");
|
|
||||||
|
Comparator<Student> comparator = getSortComparator();
|
||||||
|
|
||||||
|
sortStrategy.sort(state.getMainCollection(), comparator);
|
||||||
|
|
||||||
|
MessageWindow.showModal(gui, "Обычная сортировка успешно выполнена.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sortByParity() {
|
private void sortByParity() {
|
||||||
// TODO
|
SortStrategy<Student> sortStrategy =
|
||||||
MessageWindow.showModal(gui, "Сортировка по чётности не реализована.");
|
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) {
|
private String getSortMethodName(SortMethod sortMethod) {
|
||||||
return switch (sortMethod) {
|
return switch (sortMethod) {
|
||||||
case NORMAL -> "Обычная сортировка";
|
case NORMAL -> "Обычная сортировка";
|
||||||
|
|
||||||
case PARITY -> "Сортировка по чётности";
|
case PARITY -> "Сортировка по чётности";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getSortAlgorithmName(SortAlgorithm sortAlgorithm) {
|
||||||
|
return switch (sortAlgorithm) {
|
||||||
|
case BUBBLE -> "Сортировка пузырьком";
|
||||||
|
|
||||||
|
case MERGE -> "Сортировка слиянием";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private String getSortFieldName(SortMethod sortMethod, SortField sortField) {
|
private String getSortFieldName(SortMethod sortMethod, SortField sortField) {
|
||||||
return switch (sortMethod) {
|
return switch (sortMethod) {
|
||||||
case NORMAL -> getNormalSortFieldName(sortField);
|
case NORMAL -> getNormalSortFieldName(sortField);
|
||||||
|
|
||||||
case PARITY -> "номеру зачётной книжки";
|
case PARITY -> "номеру зачётной книжки";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -133,7 +206,9 @@ public class SortCollectionMenu extends BaseModalWindow {
|
|||||||
private String getNormalSortFieldName(SortField sortField) {
|
private String getNormalSortFieldName(SortField sortField) {
|
||||||
return switch (sortField) {
|
return switch (sortField) {
|
||||||
case GROUP_NUMBER -> "номеру группы";
|
case GROUP_NUMBER -> "номеру группы";
|
||||||
|
|
||||||
case AVERAGE_GRADE -> "среднему баллу";
|
case AVERAGE_GRADE -> "среднему баллу";
|
||||||
|
|
||||||
case RECORD_BOOK_NUMBER -> "номеру зачётной книжки";
|
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