From 249c10030fe27ef6a3a0afcacf53d4024143a054 Mon Sep 17 00:00:00 2001 From: Andriy Cherniy Date: Sat, 8 Jun 2024 22:58:45 +0300 Subject: initial commit --- .../java/space/m0e/quga/oop/lab56maven/Main.java | 133 ++++++++ .../quga/oop/lab56maven/dialogs/ChangeDialog.java | 96 ++++++ .../quga/oop/lab56maven/dialogs/InsertDialog.java | 127 ++++++++ .../oop/lab56maven/entities/common/Ability.java | 5 + .../lab56maven/entities/common/Coordinates.java | 33 ++ .../oop/lab56maven/entities/macro/Fortress.java | 129 ++++++++ .../oop/lab56maven/entities/macro/ThroneRoom.java | 52 ++++ .../oop/lab56maven/entities/macro/Workstation.java | 57 ++++ .../quga/oop/lab56maven/entities/micro/Dwarf.java | 92 ++++++ .../oop/lab56maven/entities/micro/Immigrant.java | 333 +++++++++++++++++++++ .../quga/oop/lab56maven/entities/micro/Nobel.java | 19 ++ .../oop/lab56maven/threads/ImmigrantThread.java | 57 ++++ 12 files changed, 1133 insertions(+) create mode 100644 src/main/java/space/m0e/quga/oop/lab56maven/Main.java create mode 100644 src/main/java/space/m0e/quga/oop/lab56maven/dialogs/ChangeDialog.java create mode 100644 src/main/java/space/m0e/quga/oop/lab56maven/dialogs/InsertDialog.java create mode 100644 src/main/java/space/m0e/quga/oop/lab56maven/entities/common/Ability.java create mode 100644 src/main/java/space/m0e/quga/oop/lab56maven/entities/common/Coordinates.java create mode 100644 src/main/java/space/m0e/quga/oop/lab56maven/entities/macro/Fortress.java create mode 100644 src/main/java/space/m0e/quga/oop/lab56maven/entities/macro/ThroneRoom.java create mode 100644 src/main/java/space/m0e/quga/oop/lab56maven/entities/macro/Workstation.java create mode 100644 src/main/java/space/m0e/quga/oop/lab56maven/entities/micro/Dwarf.java create mode 100644 src/main/java/space/m0e/quga/oop/lab56maven/entities/micro/Immigrant.java create mode 100644 src/main/java/space/m0e/quga/oop/lab56maven/entities/micro/Nobel.java create mode 100644 src/main/java/space/m0e/quga/oop/lab56maven/threads/ImmigrantThread.java (limited to 'src/main/java/space/m0e/quga/oop/lab56maven') diff --git a/src/main/java/space/m0e/quga/oop/lab56maven/Main.java b/src/main/java/space/m0e/quga/oop/lab56maven/Main.java new file mode 100644 index 0000000..b337de8 --- /dev/null +++ b/src/main/java/space/m0e/quga/oop/lab56maven/Main.java @@ -0,0 +1,133 @@ +package space.m0e.quga.oop.lab56maven; + +import javafx.application.Application; +import javafx.application.Platform; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.scene.control.Alert; +import javafx.scene.control.Label; +import javafx.scene.input.KeyCode; +import javafx.scene.layout.BorderPane; +import javafx.scene.paint.Color; +import javafx.scene.shape.Rectangle; +import javafx.stage.Stage; +import space.m0e.quga.oop.lab56maven.dialogs.InsertDialog; +import space.m0e.quga.oop.lab56maven.entities.common.Ability; +import space.m0e.quga.oop.lab56maven.entities.macro.Fortress; +import space.m0e.quga.oop.lab56maven.entities.macro.ThroneRoom; +import space.m0e.quga.oop.lab56maven.entities.macro.Workstation; +import space.m0e.quga.oop.lab56maven.entities.micro.Dwarf; +import space.m0e.quga.oop.lab56maven.entities.micro.Immigrant; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +public class Main extends Application { + public static Group root = new Group(); + public static ArrayList immigrants = new ArrayList<>(); + public static ArrayList fortresses = new ArrayList<>(); + public static Label status = new Label(); + + @Override + public void start(Stage stage) throws IOException, InterruptedException { + Rectangle rect = new Rectangle(3000, 2000, Color.WHITE); + + root.getChildren().add(rect); + Fortress fortress = new Fortress("Eartha", 200, 200, new ArrayList<>(List.of(new Workstation("Torgrus"))), new ArrayList<>(List.of(new ThroneRoom("Halzorga")))); + fortresses.add(fortress); + + immigrants.add(new Immigrant("1", "0", 50, 0,0, Ability.MASONIST)); + immigrants.getFirst().setX(100); + immigrants.getFirst().setY(100); + +// BorderPane borderPane = new BorderPane(); +// borderPane.setCenter(root); +// borderPane.setTop(status); + +// root.setStyle("-fx-background-color:rgb(186,153,122,0.7);"); + root.getChildren().add(status); + Scene scene = new Scene(root, 1500, 700); + + scene.setOnKeyPressed(event -> { + switch (event.getCode()) { + case LEFT -> moveImmigrants(-10, 0); + case RIGHT -> moveImmigrants(10, 0); + case UP -> moveImmigrants(0, -10); + case DOWN -> moveImmigrants(0, 10); + case INSERT -> { + try { + InsertDialog.display(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + case DELETE -> { + Iterator iterator = immigrants.iterator(); + while (iterator.hasNext()) { + Immigrant immigrant = iterator.next(); + if (immigrant.isActive()) { + iterator.remove(); + root.getChildren().remove(immigrant.getGroup()); + } + } + processImmigrants(); + } + + case ESCAPE -> { + immigrants.forEach(immigrant -> { + immigrant.setActive(false); + }); + } + + case TAB -> { + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.setTitle("Object list"); + alert.setHeaderText("Object list"); + alert.setContentText(immigrants.stream().map(Immigrant::toString).collect(Collectors.joining("\n"))); + alert.showAndWait(); + } + } + }); + stage.setTitle("Hello!"); + stage.setScene(scene); + ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + scheduler.scheduleWithFixedDelay(() -> immigrants.forEach(immigrant -> { + immigrant.getThread().start(); + }), 1, 1, TimeUnit.SECONDS); + + + stage.show(); + + } + + private void moveImmigrants(double dx, double dy) { + immigrants.forEach(immigrant -> { + if (immigrant.isActive()) { + Platform.runLater(() -> { + immigrant.setX(immigrant.getX() + dx); + immigrant.setY(immigrant.getY() + dy); + }); + } + }); + } + + public static void processImmigrants() { + status.setText("Active:"); + immigrants.forEach(immigrant -> { + if (immigrant.isActive()) { + status.setText(status.getText() + " " + immigrant.getFullName()); + } + }); + } + + public static void main(String[] args) { + launch(); + } +} \ No newline at end of file diff --git a/src/main/java/space/m0e/quga/oop/lab56maven/dialogs/ChangeDialog.java b/src/main/java/space/m0e/quga/oop/lab56maven/dialogs/ChangeDialog.java new file mode 100644 index 0000000..1f005ab --- /dev/null +++ b/src/main/java/space/m0e/quga/oop/lab56maven/dialogs/ChangeDialog.java @@ -0,0 +1,96 @@ +package space.m0e.quga.oop.lab56maven.dialogs; + +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.*; +import javafx.stage.Modality; +import javafx.stage.Stage; +import space.m0e.quga.oop.lab56maven.entities.common.Ability; +import space.m0e.quga.oop.lab56maven.entities.micro.Immigrant; + +import java.io.IOException; +import java.net.URL; +import java.util.Arrays; +import java.util.Objects; +import java.util.ResourceBundle; + +public class ChangeDialog implements Initializable { + public static Stage window = null; + public static Scene scene; + public TextField firstName; + public TextField lastName; + public TextField age; + public TextField x; + public TextField y; + public ChoiceBox ability; + public Button submitButton; + + public static Immigrant obj; + + public static void display(Immigrant obj1) throws IOException { + obj = obj1; + Parent root = FXMLLoader.load(Objects.requireNonNull(ChangeDialog.class.getResource("change_dialog.fxml"))); + + window = new Stage(); + window.initModality(Modality.APPLICATION_MODAL); + window.setTitle("Insert New Dialog"); + + scene = new Scene(root, 440, 350); + window.setScene(scene); + window.showAndWait(); + } + + @Override + public void initialize(URL location, ResourceBundle resources) { + Arrays.stream(Ability.values()) + .forEach(a -> this.ability.getItems().add(a)); + firstName.setText(obj.getFirstName()); + lastName.setText(obj.getLastName()); + age.setText(String.valueOf(obj.getAge())); + x.setText(String.valueOf(obj.getX())); + y.setText(String.valueOf(obj.getY())); + ability.setValue(obj.getAbility().toString()); + } + + public void sendError(String title, String description) { + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setTitle("Error"); + alert.setHeaderText(title); + alert.setContentText(description); + alert.showAndWait(); + } + + @FXML + public void submitButtonHandler() { + if (age.getText().isEmpty() || + x.getText().isEmpty() || + y.getText().isEmpty() || + firstName.getText().isEmpty() || + lastName.getText().isEmpty() || + ability.getValue() == null + ) { + sendError("You must enter all the fields", null); + return; + } + int inputAge = Integer.parseInt(age.getText()); + double inputX = Double.parseDouble(x.getText()); + double inputY = Double.parseDouble(y.getText()); + Ability inputAbility = Ability.valueOf(ability.getValue().toString()); + if (inputAge < 0) { + sendError("You must enter a valid age", null); + return; + } + + obj.setX(inputX); + obj.setY(inputY); + obj.setAge(inputAge); + obj.setAbility(inputAbility); + obj.setFirstName(firstName.getText()); + obj.setLastName(lastName.getText()); + + window.close(); + } +} diff --git a/src/main/java/space/m0e/quga/oop/lab56maven/dialogs/InsertDialog.java b/src/main/java/space/m0e/quga/oop/lab56maven/dialogs/InsertDialog.java new file mode 100644 index 0000000..c0c72f3 --- /dev/null +++ b/src/main/java/space/m0e/quga/oop/lab56maven/dialogs/InsertDialog.java @@ -0,0 +1,127 @@ +package space.m0e.quga.oop.lab56maven.dialogs; + +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.geometry.Point2D; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.*; +import javafx.scene.control.Button; +import javafx.scene.control.TextField; +import javafx.stage.Modality; +import javafx.stage.Stage; +import space.m0e.quga.oop.lab56maven.Main; +import space.m0e.quga.oop.lab56maven.entities.common.Ability; +import space.m0e.quga.oop.lab56maven.entities.micro.Dwarf; +import space.m0e.quga.oop.lab56maven.entities.micro.Immigrant; +import space.m0e.quga.oop.lab56maven.entities.micro.Nobel; + +import java.awt.*; +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Objects; +import java.util.ResourceBundle; + +public class InsertDialog implements Initializable { + public static Stage window = null; + public static Scene scene; + public TextField firstName; + public TextField lastName; + public TextField age; + public TextField x; + public TextField y; + public ChoiceBox ability; + public CheckBox generateItems; + public Button submitButton; + public ChoiceBox classSelection; + + public static void display() throws IOException { + Parent root = FXMLLoader.load(Objects.requireNonNull(InsertDialog.class.getResource("insert_dialog.fxml"))); + + window = new Stage(); + window.initModality(Modality.APPLICATION_MODAL); + window.setTitle("Insert New Dialog"); + + scene = new Scene(root, 440, 350); + window.setScene(scene); + window.showAndWait(); + } + + @Override + public void initialize(URL location, ResourceBundle resources) { + Point p = MouseInfo.getPointerInfo().getLocation(); + Point2D local = Main.root.screenToLocal(p.x, p.y); + x.setText(String.valueOf(local.getX())); + y.setText(String.valueOf(local.getY())); + Arrays.stream(Ability.values()) + .forEach(a -> this.ability.getItems().add(a)); + generateItems.setSelected(true); + classSelection.getItems().addAll("Immigrant", "Dwarf", "Nobel"); + classSelection.setValue("Immigrant"); + } + + public void sendError(String title, String description) { + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setTitle("Error"); + alert.setHeaderText(title); + alert.setContentText(description); + alert.showAndWait(); + } + + @FXML + public void submitButtonHandler() { + if (age.getText().isEmpty() || + x.getText().isEmpty() || + y.getText().isEmpty() || + firstName.getText().isEmpty() || + lastName.getText().isEmpty() || + ability.getValue() == null || + classSelection.getValue() == null + ) { + sendError("You must enter all the fields", null); + return; + } + int inputAge = Integer.parseInt(age.getText()); + double inputX = Double.parseDouble(x.getText()); + double inputY = Double.parseDouble(y.getText()); + Ability inputAbility = Ability.valueOf(ability.getValue().toString()); + if (inputAge < 0) { + sendError("You must enter a valid age", null); + return; + } + + switch (classSelection.getValue().toString()) { + case "Immigrant" -> { + Immigrant immigrant = new Immigrant(firstName.getText(), lastName.getText(), inputAge, inputX, inputY, inputAbility); + if (!generateItems.isSelected()) { + immigrant.setItems(new ArrayList<>()); + } + immigrant.getThread().start(); + + Main.immigrants.add(immigrant); + } + case "Dwarf" -> { + Dwarf dwarf = new Dwarf(firstName.getText(), lastName.getText(), inputAge, inputX, inputY, inputAbility); + if (!generateItems.isSelected()) { + dwarf.setItems(new ArrayList<>()); + } + + Main.immigrants.add(dwarf); + } + + case "Nobel" -> { + Nobel nobel = new Nobel(firstName.getText(), lastName.getText(), inputAge, inputX, inputY, inputAbility); + if (!generateItems.isSelected()) { + nobel.setItems(new ArrayList<>()); + } + + Main.immigrants.add(nobel); + } + } + + window.close(); + } +} diff --git a/src/main/java/space/m0e/quga/oop/lab56maven/entities/common/Ability.java b/src/main/java/space/m0e/quga/oop/lab56maven/entities/common/Ability.java new file mode 100644 index 0000000..9fc2e68 --- /dev/null +++ b/src/main/java/space/m0e/quga/oop/lab56maven/entities/common/Ability.java @@ -0,0 +1,5 @@ +package space.m0e.quga.oop.lab56maven.entities.common; + +public enum Ability { + WOODCUTTER, MASONIST +} diff --git a/src/main/java/space/m0e/quga/oop/lab56maven/entities/common/Coordinates.java b/src/main/java/space/m0e/quga/oop/lab56maven/entities/common/Coordinates.java new file mode 100644 index 0000000..a68f178 --- /dev/null +++ b/src/main/java/space/m0e/quga/oop/lab56maven/entities/common/Coordinates.java @@ -0,0 +1,33 @@ +package space.m0e.quga.oop.lab56maven.entities.common; + + +import space.m0e.quga.oop.lab56maven.entities.micro.Immigrant; + +public class Coordinates { + private double x; + private double y; + public Coordinates(double x, double y) { + this.x = x; + this.y = y; + } + + public double getX() { + return x; + } + + public void setX(double x) { + this.x = x; + } + + public double getY() { + return y; + } + + public void setY(double y) { + this.y = y; + } + + public boolean isThere(Immigrant immigrant) { + return (int) immigrant.getX() == (int) this.x && (int) immigrant.getY() == (int) this.y; + } +} diff --git a/src/main/java/space/m0e/quga/oop/lab56maven/entities/macro/Fortress.java b/src/main/java/space/m0e/quga/oop/lab56maven/entities/macro/Fortress.java new file mode 100644 index 0000000..36911f7 --- /dev/null +++ b/src/main/java/space/m0e/quga/oop/lab56maven/entities/macro/Fortress.java @@ -0,0 +1,129 @@ +package space.m0e.quga.oop.lab56maven.entities.macro; + +import javafx.scene.control.Label; +import javafx.scene.image.Image; +import javafx.scene.layout.*; +import javafx.scene.paint.Color; +import space.m0e.quga.oop.lab56maven.Main; +import space.m0e.quga.oop.lab56maven.entities.micro.Dwarf; +import space.m0e.quga.oop.lab56maven.entities.micro.Immigrant; + +import java.util.ArrayList; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +public class Fortress { + private Image spriteImage = new Image(Objects.requireNonNull(Fortress.class.getResourceAsStream("fortress.jpeg")));; + private GridPane insideGroup = new GridPane(10, 10); + private Label nameLabel = new Label(); + private Label countLabel = new Label(); + + ArrayList workstations = new ArrayList<>(); + ArrayList throneRooms = new ArrayList<>(); + + ArrayList dwarves = new ArrayList<>(); + + private String name; + private double x; + private double y; + private VBox vBox = new VBox(); + + private GridPane dwarvesContainer = new GridPane(10, 10); + + public Fortress(String name, double x, double y, ArrayList workstations, ArrayList throneRooms) { + this.x = x; + this.y = y; + + nameLabel.setText(name); + countLabel.setText("0"); + + nameLabel.setStyle("-fx-text-fill: red; -fx-font-size: 16px;"); + + RowConstraints insideRow = new RowConstraints(); + insideRow.setPrefHeight(200); + ColumnConstraints insideColumn = new ColumnConstraints(); + insideColumn.setPrefWidth(200); + for (int i = 0; i < 3; i++) { + insideGroup.getRowConstraints().add(insideRow); + insideGroup.getColumnConstraints().add(insideColumn); + } + + insideGroup.setBackground(new Background(new BackgroundImage(spriteImage, BackgroundRepeat.REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.CENTER, BackgroundSize.DEFAULT))); + this.workstations = workstations; + this.throneRooms = throneRooms; + int col = 0; + int row = 0; + for (Workstation w : this.workstations) { + if (col > 3) { + col = 0; + row++; + } + insideGroup.add(w.getGroup(), col, row); + col++; + } + + for (ThroneRoom t : this.throneRooms) { + if (col > 3) { + col = 0; + row++; + } + insideGroup.add(t.getGroup(), col, row); + col++; + } + + insideGroup.add(dwarvesContainer, 2, 2); + + this.dwarvesContainer.setBorder(new Border(new BorderStroke(Color.RED, BorderStrokeStyle.SOLID, CornerRadii.EMPTY, new BorderWidths(3)))); +// dwarvesContainer.setMinSize(100 * 3, 100 * 3); + + vBox.setLayoutX(x); + vBox.setLayoutY(y); + vBox.getChildren().addAll(nameLabel, insideGroup, countLabel); + + this.vBox.setBorder(new Border(new BorderStroke(Color.RED, BorderStrokeStyle.SOLID, CornerRadii.EMPTY, new BorderWidths(3)))); + Main.root.getChildren().add(vBox); + }; + + public void add(Dwarf dwarf) { + dwarves.add(dwarf); + dwarvesContainer.add(dwarf.getGroup(), dwarves.size() % 3, dwarves.size() / 3); + } + + public void process() { + ArrayList migration = (ArrayList) Main.immigrants.stream().filter(immigrant -> immigrant.getClass().equals(Immigrant.class) && immigrant.getCoordinatesToFortress(this).isThere(immigrant)).collect(Collectors.toList()); + migration.forEach(immigrant -> { + Dwarf dwarf = new Dwarf(immigrant, this); + Main.immigrants.add(dwarf); + this.dwarves.add(dwarf); + Main.root.getChildren().remove(immigrant.getGroup()); + }); + Main.immigrants.removeAll(migration); + + countLabel.setText(String.valueOf(dwarves.size())); + + workstations.forEach(Workstation::process); + throneRooms.forEach(ThroneRoom::process); + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public ArrayList getWorkstations() { + return workstations; + } + + public VBox getGroup() { + return vBox; + } + + public ArrayList getDwarves() { + return dwarves; + } + +} diff --git a/src/main/java/space/m0e/quga/oop/lab56maven/entities/macro/ThroneRoom.java b/src/main/java/space/m0e/quga/oop/lab56maven/entities/macro/ThroneRoom.java new file mode 100644 index 0000000..7a51cb5 --- /dev/null +++ b/src/main/java/space/m0e/quga/oop/lab56maven/entities/macro/ThroneRoom.java @@ -0,0 +1,52 @@ +package space.m0e.quga.oop.lab56maven.entities.macro; + +import javafx.scene.control.Label; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.VBox; +import space.m0e.quga.oop.lab56maven.Main; +import space.m0e.quga.oop.lab56maven.entities.micro.Dwarf; +import space.m0e.quga.oop.lab56maven.entities.micro.Immigrant; +import space.m0e.quga.oop.lab56maven.entities.micro.Nobel; + +import java.util.ArrayList; +import java.util.Objects; +import java.util.Optional; + +public class ThroneRoom { + private Image spriteImage = new Image(Objects.requireNonNull(ThroneRoom.class.getResourceAsStream("throne_room.jpg")));; + private ImageView sprite = new ImageView(spriteImage); + private Label nameLabel = new Label(); + private Label countLabel = new Label(); + + private ArrayList nobels = new ArrayList<>(); + String name; + + private VBox vBox = new VBox(); + + public ThroneRoom(String name) { + this.name = name; + + sprite.setFitHeight(150); + sprite.setFitWidth(150); + nameLabel.setText(name); + + nameLabel.setStyle("-fx-text-fill: white; -fx-font-size: 16px; -fx-background-color: grey"); + countLabel.setStyle("-fx-text-fill: white; -fx-font-size: 16px; -fx-background-color: grey"); + + vBox.getChildren().addAll(nameLabel, sprite, countLabel); + Main.root.getChildren().add(vBox); + }; + + public void process() { + countLabel.setText(String.valueOf(nobels.size())); + } + + public ArrayList getNobels() { + return nobels; + } + + public VBox getGroup() { + return vBox; + } +} diff --git a/src/main/java/space/m0e/quga/oop/lab56maven/entities/macro/Workstation.java b/src/main/java/space/m0e/quga/oop/lab56maven/entities/macro/Workstation.java new file mode 100644 index 0000000..fe80a2b --- /dev/null +++ b/src/main/java/space/m0e/quga/oop/lab56maven/entities/macro/Workstation.java @@ -0,0 +1,57 @@ +package space.m0e.quga.oop.lab56maven.entities.macro; + +import javafx.scene.control.Label; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.VBox; +import javafx.scene.text.Font; +import space.m0e.quga.oop.lab56maven.Main; +import space.m0e.quga.oop.lab56maven.entities.micro.Dwarf; +import space.m0e.quga.oop.lab56maven.entities.micro.Immigrant; + +import java.util.ArrayList; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +public class Workstation { + private Image spriteImage = new Image(Objects.requireNonNull(Workstation.class.getResourceAsStream("workstation.png")));; + private ImageView sprite = new ImageView(spriteImage); + private Label nameLabel = new Label(); + private Label countLabel = new Label(); + + private ArrayList dwarves = new ArrayList<>(); + private String name; + + private VBox vBox = new VBox(); + + public Workstation(String name) { + this.name = name; + + sprite.setFitHeight(150); + sprite.setFitWidth(150); + nameLabel.setText(name); + + nameLabel.setStyle("-fx-text-fill: white; -fx-font-size: 16px; -fx-background-color: grey"); + countLabel.setStyle("-fx-text-fill: white; -fx-font-size: 16px; -fx-background-color: grey"); + + vBox.getChildren().addAll(nameLabel, sprite, countLabel); + Main.root.getChildren().add(vBox); + }; + + public void process() { + Optional entered = Main.immigrants.stream().filter(immigrant -> immigrant instanceof Dwarf && vBox.getBoundsInParent().contains(immigrant.getGroup().getBoundsInParent())).findFirst(); + entered.ifPresent(immigrant -> { + dwarves.add((Dwarf) immigrant); + }); + countLabel.setText(String.valueOf(dwarves.size())); + } + + public ArrayList getDwarves() { + return dwarves; + } + + public VBox getGroup() { + return vBox; + } +} diff --git a/src/main/java/space/m0e/quga/oop/lab56maven/entities/micro/Dwarf.java b/src/main/java/space/m0e/quga/oop/lab56maven/entities/micro/Dwarf.java new file mode 100644 index 0000000..d00f24f --- /dev/null +++ b/src/main/java/space/m0e/quga/oop/lab56maven/entities/micro/Dwarf.java @@ -0,0 +1,92 @@ +package space.m0e.quga.oop.lab56maven.entities.micro; + +import javafx.scene.image.Image; +import space.m0e.quga.oop.lab56maven.Main; +import space.m0e.quga.oop.lab56maven.entities.common.Ability; +import space.m0e.quga.oop.lab56maven.entities.common.Coordinates; +import space.m0e.quga.oop.lab56maven.entities.macro.Fortress; +import space.m0e.quga.oop.lab56maven.entities.macro.Workstation; + +import java.util.ArrayList; +import java.util.Objects; +import java.util.Optional; +import java.util.Random; +import java.util.stream.Collectors; + +public class Dwarf extends Immigrant { + private Fortress fortress = null; + private Workstation workstation = null; + public Image spriteImage = new Image(Objects.requireNonNull(Immigrant.class.getResourceAsStream("dwarf.png")));; + public Dwarf(String firstName, String lastName, int age, double x, double y, Ability ability) { + super(firstName, lastName, age, x, y, ability); + getSprite().setImage(spriteImage); + } + + public Dwarf() { + this("Edzul", "Èrithbesmar", 35, 0, 0, Ability.values()[new Random().nextInt(Ability.values().length)]); + } + + public Dwarf(Immigrant immigrant, Fortress fortress) { + this(immigrant.getFirstName(), immigrant.getLastName(), immigrant.getAge(), immigrant.getX(), immigrant.getY(), immigrant.getAbility()); + this.setItems((ArrayList) immigrant.getItems().clone()); + this.setHp(this.getHp()); + this.setMaxHp(this.getMaxHp()); + this.fortress = fortress; + } + + public Workstation findNearestWorkstation() { + ArrayList searchWorkstations = (ArrayList) fortress.getWorkstations().stream().filter(w -> w.getDwarves().isEmpty()).collect(Collectors.toList()); + searchWorkstations.sort((o1, o2) -> (int) ((Math.abs(o1.getGroup().getLayoutX() - this.getX()) + Math.abs(o1.getGroup().getLayoutY() - this.getY())) - ((Math.abs(o2.getGroup().getLayoutX() - this.getX()) + Math.abs(o2.getGroup().getLayoutY() - this.getY()))))); + if (searchWorkstations.isEmpty()) { + return null; + } else { + return searchWorkstations.get(0); + } + } + + public Coordinates getCoordinatesToWorkstation(Workstation workstation) { + double workstationX = workstation.getGroup().getLayoutX() + workstation.getGroup().getBoundsInParent().getWidth() - this.getGroup().getBoundsInParent().getWidth(); + double workstationY = workstation.getGroup().getLayoutX() + workstation.getGroup().getBoundsInParent().getHeight() - this.getGroup().getBoundsInParent().getHeight(); + return new Coordinates(workstationX, workstationY); + } + + @Override + public void moveAI() { + if (fortress == null) { + fortress = findNearestFortress(); + fortress.getDwarves().add(this); + } + if (!fortress.getGroup().getBoundsInParent().contains(this.getGroup().getBoundsInParent())) { + super.moveAI(); + } else { + if (workstation == null) { + workstation = findNearestWorkstation(); + if (workstation == null) { + super.moveAI(); + } else { + Coordinates workstationToMove = this.getCoordinatesToWorkstation(workstation); + if (!workstationToMove.isThere(this)) { + double workstationX = workstationToMove.getX(); + double workstationY = workstationToMove.getY(); + + if (workstationX > this.getX()) { + this.setX(this.getX() + 1); + } + + if (workstationX < this.getX()) { + this.setX(this.getX() - 1); + } + + if (workstationY > this.getY()) { + this.setY(this.getY() + 1); + } + + if (workstationY < this.getY()) { + this.setY(this.getY() - 1); + } + } + } + } + } + } +} diff --git a/src/main/java/space/m0e/quga/oop/lab56maven/entities/micro/Immigrant.java b/src/main/java/space/m0e/quga/oop/lab56maven/entities/micro/Immigrant.java new file mode 100644 index 0000000..f91d0c2 --- /dev/null +++ b/src/main/java/space/m0e/quga/oop/lab56maven/entities/micro/Immigrant.java @@ -0,0 +1,333 @@ +package space.m0e.quga.oop.lab56maven.entities.micro; + +import javafx.geometry.Pos; +import javafx.scene.control.Label; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.*; +import javafx.scene.paint.Color; +import javafx.scene.shape.Rectangle; +import space.m0e.quga.oop.lab56maven.dialogs.ChangeDialog; +import space.m0e.quga.oop.lab56maven.Main; +import space.m0e.quga.oop.lab56maven.entities.common.Ability; +import space.m0e.quga.oop.lab56maven.entities.common.Coordinates; +import space.m0e.quga.oop.lab56maven.entities.macro.Fortress; +import space.m0e.quga.oop.lab56maven.threads.ImmigrantThread; + +import java.io.IOException; +import java.util.*; +import java.util.concurrent.ForkJoinTask; +import java.util.stream.Collectors; + +public class Immigrant implements Comparable, Cloneable { + private String firstName; + private String lastName; + private int age; + private double x; + private double y; + private Ability ability; + + private ArrayList items = new ArrayList<>(); + private static final String[] availableItems = new String[]{"axe", "pickaxe", "shovel", "piece of coal", "wood log"}; + + private double hp; + private double maxHp; + private static final double hpCap; + + private boolean isActive = false; + + private final VBox vBox = new VBox(); + private final Label label; + + private final ImageView sprite; + private final Rectangle hpBar; + private static final Image spriteImage = new Image(Objects.requireNonNull(Immigrant.class.getResourceAsStream("immigrant.png"))); + + private ImmigrantThread thread = new ImmigrantThread(this); + + public Immigrant(String firstName, String lastName, int age, double x, double y, Ability ability) { + this.firstName = firstName; + this.lastName = lastName; + this.age = age; + this.x = x; + this.y = y; + this.ability = ability; + + this.label = new Label(firstName + " " + lastName); + this.sprite = new ImageView(spriteImage); + this.hpBar = new Rectangle(50, 10); + this.hpBar.widthProperty().multiply(this.hp/this.maxHp); + this.hpBar.setFill(Color.LIME); + this.vBox.setSpacing(5); + this.vBox.setLayoutX(this.x); + this.vBox.setLayoutY(this.y); + this.vBox.getChildren().addAll(label, sprite, hpBar); + this.vBox.setAlignment(Pos.CENTER); + this.vBox.setOnMouseClicked(event -> { + switch (event.getButton()) { + case PRIMARY -> { + this.setActive(!this.isActive); + } + case SECONDARY -> { + try { + ChangeDialog.display(this); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + }); + this.thread = new ImmigrantThread(this); + Main.root.getChildren().add(this.getGroup()); + } + + public Immigrant() { + this("Edzul", "Èrithbesmar", 35, 0, 0, Ability.values()[new Random().nextInt(Ability.values().length)]); + } + + public boolean isActive() { + return isActive; + } + + public VBox getGroup() { + return vBox; + } + + public ImageView getSprite() { + return sprite; + } + + public Ability getAbility() { + return ability; + } + + public void setAbility(Ability ability) { + this.ability = ability; + } + + public ArrayList getItems() { + return items; + } + + public void setItems(ArrayList items) { + this.items = items; + } + + static { + hpCap = 100 + new Random().nextInt(50); + } + + { + maxHp = 50 + new Random().nextInt(100); + hp = maxHp; + int itemCount = new Random().nextInt(1, availableItems.length); + ArrayList itemPick = new ArrayList(List.of(availableItems)); + Collections.shuffle(itemPick); + items = (ArrayList) itemPick.stream().limit(itemCount).collect(Collectors.toList()); + } + + public String getFullName() { + return this.firstName + " " + this.lastName; + } + + public String getFirstName() { + return this.firstName; + } + + public String getLastName() { + return this.lastName; + } + + public int getAge() { + return this.age; + } + + public double getX() { + return this.x; + } + + public double getY() { + return this.y; + } + + public double getHp() { + return this.hp; + } + + public double getMaxHp() { + return this.maxHp; + } + + public double getHpCap() { + return Immigrant.hpCap; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + this.label.setText(firstName + " " + this.lastName); + } + + public void setLastName(String lastName) { + this.lastName = lastName; + this.label.setText(firstName + " " + this.lastName); + } + + public void setAge(int age) { + this.age = age; + } + + public void setX(double x) { + this.x = x; + this.vBox.setLayoutX(this.x); + } + + public void setY(double y) { + this.y = y; + this.vBox.setLayoutY(this.y); + } + + public void setHp(double hp) { + this.hp = hp; + this.hpBar.widthProperty().multiply(this.hp / this.maxHp); + } + + public void setMaxHp(double maxHp) { + this.maxHp = maxHp; + if (this.maxHp > Immigrant.hpCap) { + this.maxHp = Immigrant.hpCap; + } + this.hpBar.widthProperty().multiply(this.hp / this.maxHp); + } + + @Override + public String toString() { + return String.format("%s{Name=%s, Age=%d, Ability=%s, HP: %f/%f, Items: [%s]}", this.getClass().getSimpleName(), this.getFullName(), this.age, this.ability, this.hp, this.maxHp, String.join(", ", this.items)); + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + Immigrant immigrant = (Immigrant) o; + + return Objects.equals(this.firstName, immigrant.firstName) && Objects.equals(this.lastName, immigrant.lastName); + } + + + public void setActive(boolean active) { + this.isActive = active; + if (this.isActive) { + this.vBox.setBorder(new Border(new BorderStroke(Color.RED, BorderStrokeStyle.SOLID, CornerRadii.EMPTY, new BorderWidths(3)))); + } else { + this.vBox.setBorder(null); + } + Main.processImmigrants(); + } + + + public void print() { + System.out.println(this); + } + + public void grow() { + this.age++; + if (age > 24) { + this.maxHp--; + if (this.hp > this.maxHp) { + this.hp = this.maxHp; + } + } else { + this.maxHp++; + this.hp++; + } + } + + public void hurt(double deltaHp) { + this.hp -= deltaHp; + if (this.hp < 0) { + this.hp = 0; + } + } + + public void heal(double deltaHp) { + this.hp += deltaHp; + if (this.hp > this.maxHp) { + this.hp = this.maxHp; + } + } + + public void attack(Immigrant immigrant) { + double deltaHp = new Random().nextDouble(maxHp); + immigrant.hurt(deltaHp); + + System.out.printf(""" + %s attacked %s (%f HP) + %s HP: %f/%f + """, + this.getFullName(), immigrant.getFullName(), deltaHp, + immigrant.getFullName(), immigrant.getHp(), immigrant.getMaxHp()); + } + + public Coordinates getCoordinatesToFortress(Fortress fortress) { + int dwarvesCount = fortress.getDwarves().size(); + + double fortressX = fortress.getX() + fortress.getGroup().getBoundsInParent().getWidth() / 2 - this.getGroup().getWidth() / 2; + double fortressY = fortress.getY() + fortress.getGroup().getBoundsInParent().getHeight() / 2 - this.getGroup().getHeight() / 2; + return new Coordinates(fortressX, fortressY); + } + + public Fortress findNearestFortress() { + ArrayList searchFortresses = (ArrayList) Main.fortresses.clone(); + searchFortresses.sort((o1, o2) -> { + return (int) ((Math.abs(o1.getX() - this.x) + Math.abs(o1.getY() - this.y)) - (Math.abs(o2.getX() - this.x) + Math.abs(o2.getY() - this.y))); + }); + return searchFortresses.stream().filter(f -> f.getDwarves().size() < 9).findFirst().orElse(null); + } + + public void moveAI() { + Fortress searchFortress = findNearestFortress(); + Coordinates fortressToMove = this.getCoordinatesToFortress(searchFortress); + } + + public void move(Coordinates coordinates) { + if (!coordinates.isThere(this)) { + double pointX = coordinates.getX(); + double pointY = coordinates.getY(); + + if (pointX > this.getX()) { + this.setX(this.getX() + 1); + } + + if (pointX < this.getX()) { + this.setX(this.getX() - 1); + } + + if (pointY > this.getY()) { + this.setY(this.getY() + 1); + } + + if (pointY < this.getY()) { + this.setY(this.getY() - 1); + } + } + } + + @Override + public int compareTo(Immigrant o) { + return (int) (this.hp - o.hp); + } + + @Override + public Immigrant clone() throws CloneNotSupportedException { + Immigrant immigrant = (Immigrant) super.clone(); + immigrant.setItems((ArrayList) this.items.clone()); + return immigrant; + } + + public ImmigrantThread getThread() { + return thread; + } +} diff --git a/src/main/java/space/m0e/quga/oop/lab56maven/entities/micro/Nobel.java b/src/main/java/space/m0e/quga/oop/lab56maven/entities/micro/Nobel.java new file mode 100644 index 0000000..ed9ba7a --- /dev/null +++ b/src/main/java/space/m0e/quga/oop/lab56maven/entities/micro/Nobel.java @@ -0,0 +1,19 @@ +package space.m0e.quga.oop.lab56maven.entities.micro; + +import javafx.scene.image.Image; +import space.m0e.quga.oop.lab56maven.entities.common.Ability; + +import java.util.Objects; +import java.util.Random; + +public class Nobel extends Immigrant { + public Image spriteImage = new Image(Objects.requireNonNull(Nobel.class.getResourceAsStream("nobel.png")));; + public Nobel(String firstName, String lastName, int age, double x, double y, Ability ability) { + super(firstName, lastName, age, x, y, ability); + getSprite().setImage(spriteImage); + } + + public Nobel() { + this("Edzul", "Èrithbesmar", 35, 0, 0, Ability.values()[new Random().nextInt(Ability.values().length)]); + } +} diff --git a/src/main/java/space/m0e/quga/oop/lab56maven/threads/ImmigrantThread.java b/src/main/java/space/m0e/quga/oop/lab56maven/threads/ImmigrantThread.java new file mode 100644 index 0000000..105f997 --- /dev/null +++ b/src/main/java/space/m0e/quga/oop/lab56maven/threads/ImmigrantThread.java @@ -0,0 +1,57 @@ +package space.m0e.quga.oop.lab56maven.threads; + +import javafx.application.Platform; +import space.m0e.quga.oop.lab56maven.Main; +import space.m0e.quga.oop.lab56maven.entities.common.Coordinates; +import space.m0e.quga.oop.lab56maven.entities.macro.Fortress; +import space.m0e.quga.oop.lab56maven.entities.micro.Dwarf; +import space.m0e.quga.oop.lab56maven.entities.micro.Immigrant; + +import java.util.concurrent.TimeUnit; + +public class ImmigrantThread extends Thread { + public Immigrant getImmigrant() { + return immigrant; + } + + public void setImmigrant(Immigrant immigrant) { + this.immigrant = immigrant; + } + + private Immigrant immigrant; + + public ImmigrantThread(Immigrant immigrant) { + super(); + this.setName(String.format("ImmigrantThread_%s", immigrant.getFullName())); + this.immigrant = immigrant; + } + + @Override + public void run() { + while (!isInterrupted()) { + if (immigrant != null && !immigrant.isActive()) { + try { + TimeUnit.MILLISECONDS.sleep(10); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + Fortress fortress = immigrant.findNearestFortress(); + if (fortress != null) { + Coordinates moveTo = immigrant.getCoordinatesToFortress(fortress); + immigrant.move(moveTo); + if (moveTo.isThere(immigrant)) { + Platform.runLater(() -> { + Dwarf dwarf = new Dwarf(immigrant, fortress); + Main.immigrants.add(dwarf); + fortress.add(dwarf); + Main.root.getChildren().remove(immigrant.getGroup()); + }); + this.interrupt(); + } + } + } + } + } + + +} -- cgit v1.3-3-ga95d