PIbd-12_Kuznetsov_D.V. LabWork08 Hard #10

Closed
ZakenChannel wants to merge 2 commits from Lab_8 into Lab_7
18 changed files with 536 additions and 128 deletions

View File

@ -19,17 +19,23 @@ import javafx.scene.paint.Color;
import javafx.stage.Stage;
import java.net.URL;
import java.util.Random;
import java.util.ResourceBundle;
public class FormPlaneConfig extends Application implements Initializable {
@FXML private Spinner<Integer> speed;
@FXML private Spinner<Double> weight;
@FXML private Spinner<Integer> countEngine;
@FXML private CheckBox checkBoxRockets;
@FXML private CheckBox checkBoxWings;
@FXML private Canvas canvas;
@FXML private Button buttonCancel;
@FXML
private Spinner<Integer> speed;
@FXML
private Spinner<Double> weight;
@FXML
private Spinner<Integer> countEngine;
@FXML
private CheckBox checkBoxRockets;
@FXML
private CheckBox checkBoxWings;
@FXML
private Canvas canvas;
@FXML
private Button buttonCancel;
private DrawningWarPlane plane;
private IDrawableExtras engine = null;
@ -197,12 +203,7 @@ public class FormPlaneConfig extends Application implements Initializable {
if (db.hasString()) {
String droppedText = db.getString();
if (engine == null) {
IDrawableExtras[] engineDrawings = {
new EllipticalEngineDrawing(),
new TriangleEngineDrawing(),
new RectangleEngineDrawing()
};
engine = engineDrawings[new Random().nextInt(engineDrawings.length)];
engine = new RectangleEngineDrawing();
engine.setCountEngines(countEngine.getValue());
}

View File

@ -1,9 +1,12 @@
package com.projectairfighter;
import com.projectairfighter.collectiongenericobjects.*;
import com.projectairfighter.drawnings.DrawningPlaneCompareByColor;
import com.projectairfighter.drawnings.DrawningPlaneCompareByType;
import com.projectairfighter.drawnings.DrawningWarPlane;
import com.projectairfighter.exceptions.CollectionOverflowException;
import com.projectairfighter.exceptions.ObjectNotFoundException;
import com.projectairfighter.exceptions.ObjectNotUniqueException;
import com.projectairfighter.exceptions.PositionOutOfCollectionException;
import javafx.application.Application;
import javafx.fxml.FXML;
@ -21,6 +24,7 @@ import org.apache.logging.log4j.Logger;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Comparator;
import java.util.ResourceBundle;
import java.util.Stack;
@ -38,8 +42,8 @@ public class FormWarPlaneCollection extends Application implements Initializable
@FXML private ListView<String> listViewCollection;
private static FormWarPlaneCollection formWarPlaneCollection;
private static final Logger userLogger = LogManager.getLogger("useractions");
private static final Logger errorsLogger = LogManager.getLogger("errors");
protected static final Logger userLogger = LogManager.getLogger("useractions");
protected static final Logger errorsLogger = LogManager.getLogger("errors");
public static void setFormWarPlaneCollection(FormWarPlaneCollection controller) {
formWarPlaneCollection = controller;
@ -74,6 +78,9 @@ public class FormWarPlaneCollection extends Application implements Initializable
} catch (CollectionOverflowException e) {
showError("Ошибка переполнения коллекции");
errorsLogger.warn("Ошибка: {}", e.getMessage());
} catch (ObjectNotUniqueException ex) {
showError("Такой объект уже присутствует в коллекции");
errorsLogger.warn("Ошибка: {}", ex.getMessage());
}
}
@ -278,7 +285,7 @@ public class FormWarPlaneCollection extends Application implements Initializable
File selectedFile = fileChooser.showSaveDialog(null);
if (selectedFile != null) {
try {
storageCollection.saveData(selectedFile.getAbsolutePath(), listViewCollection.getSelectionModel().getSelectedItem());
storageCollection.saveData(selectedFile.getAbsolutePath(), storageCollection.keys().get(listViewCollection.getSelectionModel().getSelectedIndex()).collectionType());
showAlert("Сохранение прошло успешно", "Результат", Alert.AlertType.INFORMATION);
userLogger.info("Сохранение в файл: {}", selectedFile.getName());
} catch (Exception ex) {
@ -315,8 +322,9 @@ public class FormWarPlaneCollection extends Application implements Initializable
private void refreshListBoxItems() {
listViewCollection.getItems().clear();
for (String colName : storageCollection.keys()) {
if (colName != null && !colName.isEmpty()) {
for (int i = 0; i < storageCollection.keys().size(); i++){
String colName = storageCollection.keys().get(i).name();
if (!colName.isEmpty()){
listViewCollection.getItems().add(colName);
}
}
@ -352,6 +360,25 @@ public class FormWarPlaneCollection extends Application implements Initializable
refreshListBoxItems();
}
@FXML
private void buttonSortByType() throws PositionOutOfCollectionException, ObjectNotFoundException {
comparePlanes(new DrawningPlaneCompareByType());
}
@FXML
private void buttonSortByColor() throws PositionOutOfCollectionException, ObjectNotFoundException {
comparePlanes(new DrawningPlaneCompareByColor());
}
private void comparePlanes(Comparator<DrawningWarPlane> comparator) throws PositionOutOfCollectionException, ObjectNotFoundException {
if (company == null) {
return;
}
company.sort(comparator);
company.show(canvasWarPlane);
}
private void showAlert(String message) {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle("Сообщение");

View File

@ -1,5 +1,6 @@
package com.projectairfighter.collectiongenericobjects;
import com.projectairfighter.drawnings.DrawningPlaneEquatables;
import com.projectairfighter.drawnings.DrawningWarPlane;
import com.projectairfighter.exceptions.CollectionOverflowException;
import com.projectairfighter.exceptions.ObjectNotFoundException;
@ -7,6 +8,7 @@ import com.projectairfighter.exceptions.PositionOutOfCollectionException;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import java.util.Comparator;
import java.util.Random;
public abstract class AbstractCompany {
@ -33,7 +35,8 @@ public abstract class AbstractCompany {
if (collection == null) {
return -1;
}
return collection.insert(plane);
return collection.insert(plane, new DrawningPlaneEquatables());
}
public DrawningWarPlane removePlane(int position) throws PositionOutOfCollectionException, ObjectNotFoundException {
@ -60,6 +63,10 @@ public abstract class AbstractCompany {
}
}
public void sort(Comparator<DrawningWarPlane> comparator){
collection.collectionSort(comparator);
}
protected abstract void drawBackground(GraphicsContext gc);
protected abstract void setObjectsPosition() throws PositionOutOfCollectionException, ObjectNotFoundException;

View File

@ -0,0 +1,50 @@
package com.projectairfighter.collectiongenericobjects;
import java.util.Objects;
/**
* Класс, хранящий информацию по коллекции
* @param name
* @param collectionType
* @param description
*/
public record CollectionInfo(String name, CollectionType collectionType, String description) {
private static final String SEPARATOR = "-";
public static CollectionInfo getCollectionInfo(String data) {
String[] strs = data.split(SEPARATOR);
if (strs.length < 1 || strs.length > 3) {
return null;
}
CollectionType collectionType;
try {
collectionType = CollectionType.valueOf(strs[1]);
} catch (IllegalArgumentException e) {
return null;
}
return new CollectionInfo(strs[0], collectionType, strs.length > 2 ? strs[2] : "");
}
@Override
public String toString() {
return name + SEPARATOR + collectionType + SEPARATOR + description;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
CollectionInfo that = (CollectionInfo) obj;
return Objects.equals(name, that.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}

View File

@ -4,6 +4,8 @@ import com.projectairfighter.exceptions.CollectionOverflowException;
import com.projectairfighter.exceptions.ObjectNotFoundException;
import com.projectairfighter.exceptions.PositionOutOfCollectionException;
import java.util.Comparator;
public interface ICollectionGenericObjects<T> {
/**
* Количество объектов в коллекции
@ -16,6 +18,23 @@ public interface ICollectionGenericObjects<T> {
int getMaxCount();
void setMaxCount(int value);
/**
* Добавление объекта в коллекцию
*
* @param obj Добавляемый объект
* @return 1 - вставка прошла удачно, 0 - вставка не удалась
*/
int insert(T obj, Comparator<T> comparator) throws CollectionOverflowException, PositionOutOfCollectionException;
/**
* Добавление объекта в коллекцию на конкретную позицию
*
* @param obj Добавляемый объект
* @param position Позиция
* @return 1 - вставка прошла удачно, 0 - вставка не удалась
*/
int insert(T obj, int position, Comparator<T> comparator) throws PositionOutOfCollectionException, CollectionOverflowException;
/**
* Добавление объекта в коллекцию
*
@ -64,5 +83,7 @@ public interface ICollectionGenericObjects<T> {
* @return Поэлементный вывод элементов коллекции.
*/
Iterable<T> getItems();
void collectionSort(Comparator<T> comparator);
}

View File

@ -1,12 +1,10 @@
package com.projectairfighter.collectiongenericobjects;
import com.projectairfighter.exceptions.CollectionOverflowException;
import com.projectairfighter.exceptions.ObjectNotUniqueException;
import com.projectairfighter.exceptions.PositionOutOfCollectionException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.*;
public class ListGenericObjects<T> implements ICollectionGenericObjects<T> {
private final List<T> collection;
@ -82,6 +80,58 @@ public class ListGenericObjects<T> implements ICollectionGenericObjects<T> {
};
}
@Override
public void collectionSort(Comparator<T> comparator) {
collection.sort(comparator);
}
@Override
public int insert(T obj, Comparator<T> comparator) throws CollectionOverflowException {
if (comparator == null) {
if (collection.contains(obj)) {
throw new ObjectNotUniqueException();
}
} else {
for (T item : collection) {
if (comparator.compare(item, obj) != 0) {
throw new ObjectNotUniqueException();
}
}
}
if (getCount() == maxCount) {
throw new CollectionOverflowException(collection.size());
}
collection.add(obj);
return getCount();
}
@Override
public int insert(T obj, int position, Comparator<T> comparator) throws PositionOutOfCollectionException, CollectionOverflowException {
if (comparator == null) {
if (collection.contains(obj)) {
throw new ObjectNotUniqueException(position);
}
} else {
for (T item : collection) {
if (comparator.compare(item, obj) != 0) {
throw new ObjectNotUniqueException(position);
}
}
}
if (position < 0 || position >= getCount()) {
throw new PositionOutOfCollectionException();
}
if (getCount() == maxCount) {
throw new CollectionOverflowException(collection.size());
}
collection.add(position, obj);
return position;
}
@Override
public int insert(T obj) throws CollectionOverflowException {
if (getCount() == maxCount) {
@ -97,7 +147,7 @@ public class ListGenericObjects<T> implements ICollectionGenericObjects<T> {
throw new PositionOutOfCollectionException();
}
if (getCount() == maxCount){
if (getCount() == maxCount) {
throw new CollectionOverflowException();
}

View File

@ -1,10 +1,13 @@
package com.projectairfighter.collectiongenericobjects;
import com.projectairfighter.drawnings.DrawningWarPlane;
import com.projectairfighter.exceptions.CollectionOverflowException;
import com.projectairfighter.exceptions.ObjectNotFoundException;
import com.projectairfighter.exceptions.ObjectNotUniqueException;
import com.projectairfighter.exceptions.PositionOutOfCollectionException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.NoSuchElementException;
@ -23,7 +26,7 @@ public class MassiveGenericObjects<T> implements ICollectionGenericObjects<T> {
@Override
@SuppressWarnings("unchecked")
public void setMaxCount(int value){
public void setMaxCount(int value) {
if (value < 0) return;
T[] newCollection = (T[]) new Object[value];
@ -43,8 +46,7 @@ public class MassiveGenericObjects<T> implements ICollectionGenericObjects<T> {
throw new PositionOutOfCollectionException();
}
if (collection[position] == null)
{
if (collection[position] == null) {
throw new ObjectNotFoundException(position);
}
@ -63,6 +65,46 @@ public class MassiveGenericObjects<T> implements ICollectionGenericObjects<T> {
return CollectionType.Massive;
}
@Override
public int insert(T obj, Comparator<T> comparator) throws PositionOutOfCollectionException, CollectionOverflowException {
return insert(obj, 0, comparator);
}
@Override
@SuppressWarnings("unchecked")
public int insert(T obj, int position, Comparator<T> comparator) throws PositionOutOfCollectionException, CollectionOverflowException {
if (position < 0 || position >= getCount()) {
throw new PositionOutOfCollectionException(position);
}
if (collection[position] == null) {
collection[position] = obj;
return position;
}
for (T item : collection) {
if (item instanceof DrawningWarPlane dwItem && obj instanceof DrawningWarPlane dwObj) {
if (comparator.compare((T) dwItem, (T) dwObj) > 0) {
throw new ObjectNotUniqueException(position);
}
}
}
for (int i = position + 1; i < getCount(); i++) {
if (collection[i] == null) {
collection[i] = obj;
return i;
}
}
for (int i = position - 1; i >= 0; i--) {
if (collection[i] == null) {
collection[i] = obj;
return i;
}
}
throw new CollectionOverflowException(collection.length);
}
@Override
public int insert(T obj) throws PositionOutOfCollectionException, CollectionOverflowException {
return insert(obj, 0);
@ -100,8 +142,7 @@ public class MassiveGenericObjects<T> implements ICollectionGenericObjects<T> {
throw new PositionOutOfCollectionException(position);
}
if (collection[position] == null)
{
if (collection[position] == null) {
throw new ObjectNotFoundException(position);
}
@ -134,5 +175,10 @@ public class MassiveGenericObjects<T> implements ICollectionGenericObjects<T> {
}
};
}
@Override
public void collectionSort(Comparator<T> comparator) {
Arrays.sort(collection, comparator);
}
}

View File

@ -20,7 +20,7 @@ public class StorageCollection<T extends DrawningWarPlane> {
/**
* Словарь (хранилище) с коллекциями.
*/
private final Map<String, ICollectionGenericObjects<T>> storages;
private final Map<CollectionInfo, ICollectionGenericObjects<T>> storages;
/**
* Ключевое слово, с которого должен начинаться файл
@ -58,8 +58,8 @@ public class StorageCollection<T extends DrawningWarPlane> {
*
* @return Список названий коллекций.
*/
public List<String> keys() {
return new ArrayList<>(storages.keySet());
public List<CollectionInfo> keys() {
return storages.keySet().stream().toList();
}
/**
@ -76,17 +76,18 @@ public class StorageCollection<T extends DrawningWarPlane> {
* @param collectionType Тип коллекции.
*/
public void addCollection(String name, CollectionType collectionType) {
if (name == null || storages.containsKey(name)) {
CollectionInfo collectionInfo = new CollectionInfo(name, collectionType, "");
if (name == null || storages.containsKey(collectionInfo)) {
return;
}
switch (collectionType) {
case None:
return;
case Massive:
storages.put(name, new MassiveGenericObjects<>());
storages.put(collectionInfo, new MassiveGenericObjects<>());
return;
case List:
storages.put(name, new ListGenericObjects<>());
storages.put(collectionInfo, new ListGenericObjects<>());
}
}
@ -96,10 +97,11 @@ public class StorageCollection<T extends DrawningWarPlane> {
* @param name Название коллекции.
*/
public void delCollection(String name) {
if (name == null || !storages.containsKey(name)) {
CollectionInfo collectionInfo = new CollectionInfo(name, CollectionType.None, "");
if (name == null || !storages.containsKey(collectionInfo)) {
return;
}
storages.remove(name);
storages.remove(collectionInfo);
}
/**
@ -109,10 +111,12 @@ public class StorageCollection<T extends DrawningWarPlane> {
* @return Коллекция или null, если коллекция с данным названием отсутствует.
*/
public ICollectionGenericObjects<T> get(String name) {
if (name == null || !storages.containsKey(name)) {
CollectionInfo collectionInfo = new CollectionInfo(name, CollectionType.None, "");
if (name == null || !storages.containsKey(collectionInfo)) {
return null;
}
return storages.get(name);
return storages.get(collectionInfo);
}
/**
@ -123,7 +127,8 @@ public class StorageCollection<T extends DrawningWarPlane> {
* @return Элемент коллекции или null, если коллекция с данным названием отсутствует или индекс некорректен.
*/
public T getElement(String name, int index) throws PositionOutOfCollectionException, ObjectNotFoundException {
return storages.get(name).get(index);
CollectionInfo collectionInfo = new CollectionInfo(name, CollectionType.None, "");
return storages.get(collectionInfo).get(index);
}
/**
@ -146,7 +151,7 @@ public class StorageCollection<T extends DrawningWarPlane> {
writer.write(COLLECTION_KEY);
writer.newLine();
for (Map.Entry<String, ICollectionGenericObjects<T>> entry : storages.entrySet()) {
for (Map.Entry<CollectionInfo, ICollectionGenericObjects<T>> entry : storages.entrySet()) {
if (entry.getValue().getCount() == 0) {
continue;
}
@ -154,8 +159,6 @@ public class StorageCollection<T extends DrawningWarPlane> {
StringBuilder sb = new StringBuilder();
sb.append(entry.getKey());
sb.append(SEPARATOR_FOR_KEY_VALUE_ALL_COL);
sb.append(entry.getValue().getCollectionType());
sb.append(SEPARATOR_FOR_KEY_VALUE_ALL_COL);
sb.append(entry.getValue().getMaxCount());
sb.append(SEPARATOR_FOR_KEY_VALUE_ALL_COL);
@ -181,9 +184,9 @@ public class StorageCollection<T extends DrawningWarPlane> {
* Сохранение в файл по имени коллекции
*
* @param path путь к файлу
* @param collection название коллекции для сохранения
* @param collectionType название коллекции для сохранения
*/
public void saveData(String path, String collection) throws IOException {
public void saveData(String path, CollectionType collectionType) throws IOException {
if (storages.isEmpty()) {
throw new IllegalArgumentException("В хранилище отсутствуют коллекции для сохранения");
}
@ -197,16 +200,14 @@ public class StorageCollection<T extends DrawningWarPlane> {
writer.write(COLLECTION_KEY_ONE_COL);
writer.newLine();
for (Map.Entry<String, ICollectionGenericObjects<T>> entry : storages.entrySet()) {
if ((entry.getValue().getCount() == 0) || !entry.getKey().equals(collection)) {
for (Map.Entry<CollectionInfo, ICollectionGenericObjects<T>> entry : storages.entrySet()) {
if ((entry.getValue().getCount() == 0) || entry.getKey().name().equals(collectionType.name())) {
continue;
}
StringBuilder sb = new StringBuilder();
sb.append(entry.getKey());
sb.append(SEPARATOR_FOR_KEY_VALUE_ONE_TYPE_COL);
sb.append(entry.getValue().getCollectionType());
sb.append(SEPARATOR_FOR_KEY_VALUE_ONE_TYPE_COL);
sb.append(entry.getValue().getMaxCount());
sb.append(SEPARATOR_FOR_KEY_VALUE_ONE_TYPE_COL);
@ -236,44 +237,45 @@ public class StorageCollection<T extends DrawningWarPlane> {
* @return результат обработки
*/
@SuppressWarnings("unchecked")
private boolean processRecord(String recordLine, String keyValueSeparator, String itemSeparator) throws CollectionOverflowException {
private boolean processRecord(String recordLine, String keyValueSeparator, String itemSeparator) throws Exception {
String[] record = recordLine.split(keyValueSeparator);
if (record.length != 4) {
if (record.length != 3) {
return false;
}
ICollectionGenericObjects<T> collection;
if (storages.containsKey(record[0])) {
storages.get(record[0]).clear();
collection = storages.get(record[0]);
CollectionInfo collectionInfo = Optional.ofNullable(CollectionInfo.getCollectionInfo(record[0]))
.orElseThrow(() -> new Exception("Не удалось определить информацию коллекции: " + record[0]));
if (storages.containsKey(collectionInfo)) {
storages.get(collectionInfo).clear();
collection = storages.get(collectionInfo);
} else {
CollectionType collectionType = CollectionType.valueOf(record[1]);
collection = StorageCollection.createCollection(collectionType);
collection = createCollection(collectionInfo.collectionType());
}
if (collection == null) {
throw new IllegalStateException("Не удалось определить тип коллекции:" + record[1]);
}
collection.setMaxCount(Integer.parseInt(record[2]));
collection.setMaxCount(Integer.parseInt(record[1]));
String[] items = record[3].split(itemSeparator, -1);
String[] items = record[2].split(itemSeparator, -1);
for (String elem : items) {
T ship = (T) createDrawingPlane(elem);
try
{
try {
if (ship != null && collection.insert(ship) == -1)
throw new IllegalStateException("Объект не удалось добавить в коллекцию: " + record[3]);
}
catch (CollectionOverflowException ex){
throw new IllegalStateException("Объект не удалось добавить в коллекцию: " + record[2]);
} catch (CollectionOverflowException ex) {
throw new CollectionOverflowException("Коллекция переполнена", ex);
} catch (PositionOutOfCollectionException ex) {
throw new CollectionOverflowException("Выход за пределы коллекции", ex);
}
}
storages.put(record[0], collection);
storages.put(collectionInfo, collection);
return true;
}
@ -281,7 +283,7 @@ public class StorageCollection<T extends DrawningWarPlane> {
/**
* Загрузка информации из файла
*/
public void loadData(String filename) throws IOException, CollectionOverflowException {
public void loadData(String filename) throws Exception {
File file = new File(filename);
if (!file.exists()) {
throw new FileNotFoundException("Файл не существует");
@ -316,10 +318,11 @@ public class StorageCollection<T extends DrawningWarPlane> {
/**
* Создание коллекции по типу
*/
@SuppressWarnings("unchecked")
private static <T> ICollectionGenericObjects<T> createCollection(CollectionType collectionType) {
return switch (collectionType) {
case Massive -> new MassiveGenericObjects<>();
case List -> new ListGenericObjects<>();
case Massive -> (ICollectionGenericObjects<T>) new MassiveGenericObjects<>();
case List -> (ICollectionGenericObjects<T>) new ListGenericObjects<>();
default -> null;
};
}

View File

@ -5,7 +5,12 @@ import com.projectairfighter.entities.EntityWarPlane;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
public class DrawningAirFighter extends DrawningWarPlane {
import java.util.Iterator;
import java.util.NoSuchElementException;
public class DrawningAirFighter extends DrawningWarPlane implements Iterator<Object>, Iterable<Object> {
private int currentIndex = 0;
public DrawningAirFighter(int speed, double weight, Color bodyColor, IDrawableExtras engineDrawing, Color
additionalColor, boolean bodyRockets, boolean additionalWings) {
super(speed, weight, bodyColor, engineDrawing);
@ -57,4 +62,60 @@ public class DrawningAirFighter extends DrawningWarPlane {
}
super.drawTransport(gc);
}
// Реализация методов Iterator
@Override
public boolean hasNext() {
return currentIndex < 6;
}
@Override
public Object next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return switch (currentIndex++) {
case 0 -> entityWarPlane;
case 1 -> pictureWidth;
case 2 -> pictureHeight;
case 3 -> startPosX;
case 4 -> startPosY;
case 5 -> new int[]{drawningAirFighterWidth, drawningAirFighterHeight};
default -> throw new NoSuchElementException();
};
}
// Метод для сброса итератора
public void reset() {
currentIndex = 0;
}
// Реализация методов Iterable
@Override
public Iterator<Object> iterator() {
return new Iterator<>() {
private int index = 0;
@Override
public boolean hasNext() {
return index < 6;
}
@Override
public Object next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return switch (index++) {
case 0 -> entityWarPlane;
case 1 -> pictureWidth;
case 2 -> pictureHeight;
case 3 -> startPosX;
case 4 -> startPosY;
case 5 -> new int[]{drawningAirFighterWidth, drawningAirFighterHeight};
default -> throw new NoSuchElementException();
};
}
};
}
}

View File

@ -0,0 +1,30 @@
package com.projectairfighter.drawnings;
import java.util.Comparator;
public class DrawningPlaneCompareByColor implements Comparator<DrawningWarPlane> {
@Override
public int compare(DrawningWarPlane x, DrawningWarPlane y) {
if (x == null || x.entityWarPlane == null) {
return 1;
}
if (y == null || y.entityWarPlane == null) {
return -1;
}
int bodyColorCompare = y.entityWarPlane.getBodyColor().toString().compareTo(x.entityWarPlane.getBodyColor().toString());
if (bodyColorCompare != 0) {
return bodyColorCompare;
}
int speedCompare = Integer.compare(y.entityWarPlane.getSpeed(), x.entityWarPlane.getSpeed());
if (speedCompare != 0) {
return speedCompare;
}
return Integer.compare((int) y.entityWarPlane.getWeight(), (int) x.entityWarPlane.getWeight());
}
}

View File

@ -0,0 +1,56 @@
package com.projectairfighter.drawnings;
import java.util.Comparator;
public class DrawningPlaneCompareByType implements Comparator<DrawningWarPlane> {
@Override
public int compare(DrawningWarPlane x, DrawningWarPlane y) {
if (x == null || x.entityWarPlane == null) {
return 1;
}
if (y == null || y.entityWarPlane == null) {
return -1;
}
if (!x.getClass().getName().equals(y.getClass().getName())) {
return y.getClass().getName().compareTo(x.getClass().getName());
}
int speedCompare = Integer.compare(y.entityWarPlane.getSpeed(), x.entityWarPlane.getSpeed());
if (speedCompare != 0) {
return speedCompare;
}
int weightCompare = Integer.compare((int) y.entityWarPlane.getWeight(), (int) x.entityWarPlane.getWeight());
if (weightCompare != 0) {
return weightCompare;
}
int engineCountCompare = Integer.compare(getEngineCount(y), getEngineCount(x));
if (engineCountCompare != 0) {
return engineCountCompare;
}
return getEngineType(x).compareTo(getEngineType(y));
}
private int getEngineCount(DrawningWarPlane plane) {
if (plane instanceof IDrawableExtras) {
return ((IDrawableExtras) plane).getCountEngines();
}
return 0;
}
private String getEngineType(DrawningWarPlane plane) {
if (plane.entityWarPlane.getEngineDrawing() instanceof RectangleEngineDrawing) {
return "Rectangle";
} else if (plane.entityWarPlane.getEngineDrawing() instanceof TriangleEngineDrawing) {
return "Triangle";
} else if (plane.entityWarPlane.getEngineDrawing() instanceof EllipticalEngineDrawing) {
return "Elliptical";
}
return "Unknown";
}
}

View File

@ -0,0 +1,38 @@
package com.projectairfighter.drawnings;
import com.projectairfighter.entities.EntityAirFighter;
import java.util.Comparator;
public class DrawningPlaneEquatables implements Comparator<DrawningWarPlane> {
@Override
public int compare(DrawningWarPlane x, DrawningWarPlane y) {
if (x.entityWarPlane == null || y.entityWarPlane == null) return 0;
if (!x.getClass().getName().equals(y.getClass().getName())) return 0;
if (x.entityWarPlane.getSpeed() != y.entityWarPlane.getSpeed()) return 0;
if (x.entityWarPlane.getWeight() != y.entityWarPlane.getWeight()) return 0;
if (x.entityWarPlane.getBodyColor() != y.entityWarPlane.getBodyColor()) return 0;
if ((x.entityWarPlane.getEngineDrawing().getCountEngines() != y.entityWarPlane.getEngineDrawing().getCountEngines()
|| !x.entityWarPlane.getEngineDrawing().getClass().getSimpleName().equals(y.entityWarPlane.getEngineDrawing().getClass().getSimpleName())))
return 0;
if (x instanceof DrawningAirFighter && y instanceof DrawningAirFighter) {
EntityAirFighter dx = (EntityAirFighter) x.entityWarPlane;
EntityAirFighter dy = (EntityAirFighter) y.entityWarPlane;
if (dx.getAdditionalColor() != dy.getAdditionalColor()) return 0;
if (dx.hasBodyRockets() != dy.hasBodyRockets()) return 0;
if (dx.hasAdditionalWings() != dy.hasAdditionalWings()) return 0;
}
return 1;
}
}

View File

@ -4,20 +4,24 @@ import com.projectairfighter.entities.EntityWarPlane;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
public class DrawningWarPlane {
import java.util.Iterator;
import java.util.NoSuchElementException;
public class DrawningWarPlane implements Iterator<Object>, Iterable<Object> {
// Сущность
public EntityWarPlane entityWarPlane;
// Ширина и высота окна
private Integer pictureWidth = 0;
private Integer pictureHeight = 0;
protected Integer pictureWidth = 0;
protected Integer pictureHeight = 0;
// Начальные координаты прорисовки истребителя
private Integer startPosX = null;
private Integer startPosY = null;
protected Integer startPosX = null;
protected Integer startPosY = null;
private int currentIndex = 0;
private final int drawningAirFighterWidth = 157;
private final int drawningAirFighterHeight = 140;
protected final int drawningAirFighterWidth = 157;
protected final int drawningAirFighterHeight = 140;
public Integer getPosX(){
return startPosX;
}
@ -145,4 +149,36 @@ public class DrawningWarPlane {
new double[]{startPosY + 79, startPosY + 133, startPosY + 133, startPosY + 79}, 4);
}
// Реализация методов Iterator
@Override
public boolean hasNext() {
return currentIndex < 6;
}
@Override
public Object next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return switch (currentIndex++) {
case 0 -> entityWarPlane;
case 1 -> pictureWidth;
case 2 -> pictureHeight;
case 3 -> startPosX;
case 4 -> startPosY;
case 5 -> new int[]{drawningAirFighterWidth, drawningAirFighterHeight};
default -> throw new NoSuchElementException();
};
}
// Метод для сброса итератора
public void reset() {
currentIndex = 0;
}
@Override
public Iterator<Object> iterator() {
return this;
}
}

View File

@ -37,6 +37,7 @@ public class EntityAirFighter extends EntityWarPlane {
return additionalWings;
}
// Конструктор
public EntityAirFighter(int speed, double weight, Color bodyColor, IDrawableExtras engineDrawing, Color
additionalColor, boolean bodyRockets, boolean additionalWings){

View File

@ -0,0 +1,19 @@
package com.projectairfighter.exceptions;
public class ObjectNotUniqueException extends RuntimeException {
public ObjectNotUniqueException() {
super("В коллекции уже есть такой элемент");
}
public ObjectNotUniqueException(String message) {
super(message);
}
public ObjectNotUniqueException(String message, Throwable cause) {
super(message, cause);
}
public ObjectNotUniqueException(int count) {
super("В коллекции содержится равный элемент: " + count);
}
}

View File

@ -34,13 +34,15 @@
<Button layoutX="6.0" layoutY="46.0" mnemonicParsing="false" onAction="#buttonCreateCompany" prefHeight="25.0" prefWidth="224.0" text="Создать компанию" />
</AnchorPane>
<AnchorPane disable="true" minHeight="0.0" minWidth="0.0" prefHeight="312.0" prefWidth="235.0">
<Button alignment="CENTER" contentDisplay="CENTER" layoutX="6.0" layoutY="48.0" mnemonicParsing="false" onAction="#buttonGoToFormCreate" prefHeight="35.0" prefWidth="224.0" text="Добавление самолета" />
<TextField fx:id="textBox" layoutX="6.0" layoutY="132.0" prefHeight="25.0" prefWidth="224.0" />
<Button alignment="CENTER" contentDisplay="CENTER" layoutX="6.0" layoutY="162.0" mnemonicParsing="false" onAction="#buttonRemovePlaneClicked" prefHeight="35.0" prefWidth="224.0" text="Удалить истребитель" />
<Button alignment="CENTER" contentDisplay="CENTER" layoutX="6.0" layoutY="215.0" mnemonicParsing="false" onAction="#buttonGoToCheck" prefHeight="35.0" prefWidth="224.0" text="Передать на тесты" />
<Button alignment="CENTER" contentDisplay="CENTER" layoutX="6.0" layoutY="300.0" mnemonicParsing="false" onAction="#buttonRefresh" prefHeight="35.0" prefWidth="224.0" text="Обновить" />
<Button alignment="CENTER" contentDisplay="CENTER" layoutX="6.0" layoutY="90.0" mnemonicParsing="false" onAction="#buttonGoFormConstructor" prefHeight="35.0" prefWidth="224.0" text="Добавить через конструктор" />
<Button layoutX="6.0" layoutY="257.0" mnemonicParsing="false" onAction="#buttonGoToFormWithDeleteObject" prefHeight="35.0" text="Передать на тесты удаленный объект" />
<Button alignment="CENTER" contentDisplay="CENTER" layoutX="6.0" layoutY="2.0" mnemonicParsing="false" onAction="#buttonGoToFormCreate" prefHeight="35.0" prefWidth="224.0" text="Добавление самолета" />
<TextField fx:id="textBox" layoutX="6.0" layoutY="86.0" prefHeight="25.0" prefWidth="224.0" />
<Button alignment="CENTER" contentDisplay="CENTER" layoutX="6.0" layoutY="116.0" mnemonicParsing="false" onAction="#buttonRemovePlaneClicked" prefHeight="35.0" prefWidth="224.0" text="Удалить истребитель" />
<Button alignment="CENTER" contentDisplay="CENTER" layoutX="6.0" layoutY="169.0" mnemonicParsing="false" onAction="#buttonGoToCheck" prefHeight="35.0" prefWidth="224.0" text="Передать на тесты" />
<Button alignment="CENTER" contentDisplay="CENTER" layoutX="6.0" layoutY="254.0" mnemonicParsing="false" onAction="#buttonRefresh" prefHeight="35.0" prefWidth="224.0" text="Обновить" />
<Button alignment="CENTER" contentDisplay="CENTER" layoutX="6.0" layoutY="44.0" mnemonicParsing="false" onAction="#buttonGoFormConstructor" prefHeight="35.0" prefWidth="224.0" text="Добавить через конструктор" />
<Button layoutX="6.0" layoutY="211.0" mnemonicParsing="false" onAction="#buttonGoToFormWithDeleteObject" prefHeight="35.0" text="Передать на тесты удаленный объект" />
<Button layoutX="6.0" layoutY="290.0" mnemonicParsing="false" onAction="#buttonSortByType" prefHeight="25.0" prefWidth="223.0" text="Сортировка по типу" />
<Button layoutX="6.0" layoutY="319.0" mnemonicParsing="false" onAction="#buttonSortByColor" prefHeight="25.0" prefWidth="223.0" text="Сортировка по цвету" />
</AnchorPane>
</SplitPane>
</AnchorPane>

View File

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<!-- Appender for user actions (INFO level) -->
<!-- Управление действиями пользователя (INFO level) -->
<File name="UserActionsFile" fileName="logs/user_actions.log">
<PatternLayout>
<pattern>%d{dd.MM.yyyy} - %msg%n</pattern>
</PatternLayout>
</File>
<!-- Appender for all errors (WARN, ERROR, FATAL) -->
<!-- Управление всеми ошибками (WARN, ERROR, FATAL) -->
<File name="ErrorFile" fileName="logs/errors.log">
<PatternLayout>
<pattern>%d{dd.MM.yyyy} [%level] - %msg%n</pattern>
@ -17,17 +17,17 @@
</Appenders>
<Loggers>
<!-- Logger for user actions (INFO level) -->
<!-- Логгер для пользователей (INFO level) -->
<Logger name="useractions" level="info" additivity="false">
<AppenderRef ref="UserActionsFile"/>
</Logger>
<!-- Logger for errors -->
<!-- Логгер для ошибок -->
<Logger name="errors" level="warn" additivity="false">
<AppenderRef ref="ErrorFile"/>
</Logger>
<!-- Root logger for all errors (WARN, ERROR, FATAL) -->
<!-- Логгер для всех ошибок (WARN, ERROR, FATAL) -->
<Root level="warn">
<AppenderRef ref="ErrorFile"/>
</Root>

View File

@ -1,40 +0,0 @@
<configuration>
<appender name="ACTIONS" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/actions.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/actions_%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%date{dd.MM.yyyy HH:mm:ss} [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<appender name="ERRORS" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/errors.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/errors_%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%date{dd.MM.yyyy HH:mm:ss} [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<!-- Logger для действий пользователя -->
<logger level="INFO" additivity="false">
<appender-ref ref="ACTIONS" />
</logger>
<!-- Logger для ошибок -->
<logger level="WARN" additivity="false">
<appender-ref ref="ERRORS" />
</logger>
<!-- Root logger для остальных сообщений -->
<root level="ERROR">
<appender-ref ref="ERRORS" />
</root>
</configuration>