From e8fab927eb89c6ef9aca7a6e8aace5283d7dcde1 Mon Sep 17 00:00:00 2001 From: jez04 <david.jezek@post.cz> Date: Thu, 14 Mar 2024 11:43:14 +0100 Subject: [PATCH] feat: lab start code --- .../cz/vsb/fei/java2/lab04/AppController.java | 167 ---------- .../cz/vsb/fei/java2/lab04/ColorPoint.java | 47 --- .../java/cz/vsb/fei/java2/lab04/Point.java | 49 --- .../cz/vsb/fei/java2/lab04/{ => gui}/App.java | 2 +- .../fei/java2/lab04/gui/AppController.java | 297 ++++++++++++++++++ .../fei/java2/lab04/gui/LogarithmicAxis.java | 232 ++++++++++++++ .../java2/lab04/measurment/Measurment.java | 55 ++++ .../fei/java2/lab04/points/ColorPoint.java | 50 +++ .../cz/vsb/fei/java2/lab04/points/Point.java | 88 ++++++ src/main/java/module-info.java | 9 +- .../fei/java2/lab04/{ => gui}/AppWindow.fxml | 47 ++- .../fei/java2/lab04/{ => gui}/application.css | 0 12 files changed, 751 insertions(+), 292 deletions(-) delete mode 100644 src/main/java/cz/vsb/fei/java2/lab04/AppController.java delete mode 100644 src/main/java/cz/vsb/fei/java2/lab04/ColorPoint.java delete mode 100644 src/main/java/cz/vsb/fei/java2/lab04/Point.java rename src/main/java/cz/vsb/fei/java2/lab04/{ => gui}/App.java (97%) create mode 100644 src/main/java/cz/vsb/fei/java2/lab04/gui/AppController.java create mode 100644 src/main/java/cz/vsb/fei/java2/lab04/gui/LogarithmicAxis.java create mode 100644 src/main/java/cz/vsb/fei/java2/lab04/measurment/Measurment.java create mode 100644 src/main/java/cz/vsb/fei/java2/lab04/points/ColorPoint.java create mode 100644 src/main/java/cz/vsb/fei/java2/lab04/points/Point.java rename src/main/resources/cz/vsb/fei/java2/lab04/{ => gui}/AppWindow.fxml (77%) rename src/main/resources/cz/vsb/fei/java2/lab04/{ => gui}/application.css (100%) diff --git a/src/main/java/cz/vsb/fei/java2/lab04/AppController.java b/src/main/java/cz/vsb/fei/java2/lab04/AppController.java deleted file mode 100644 index b4c4b94..0000000 --- a/src/main/java/cz/vsb/fei/java2/lab04/AppController.java +++ /dev/null @@ -1,167 +0,0 @@ -package cz.vsb.fei.java2.lab04; - -import java.util.Arrays; -import java.util.List; -import java.util.Random; -import java.util.stream.Stream; - -import javafx.beans.binding.ObjectBinding; -import javafx.beans.value.ObservableValue; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.event.ActionEvent; -import javafx.fxml.FXML; -import javafx.scene.canvas.Canvas; -import javafx.scene.canvas.GraphicsContext; -import javafx.scene.chart.BarChart; -import javafx.scene.chart.XYChart; -import javafx.scene.chart.XYChart.Data; -import javafx.scene.control.SelectionMode; -import javafx.scene.control.TableColumn; -import javafx.scene.control.TableView; -import javafx.scene.control.cell.PropertyValueFactory; -import javafx.scene.layout.BorderPane; -import javafx.scene.paint.Color; - -public class AppController { - - private static final Random RANDOM = new Random(); - private static final List<Color> COLORS = Arrays.asList(Color.RED, Color.BLUE, Color.YELLOW, Color.BLACK, - Color.ORANGE, Color.PINK, Color.PURPLE); - - @FXML - private TableView<Point> table1; - private ObservableList<Point> points1 = FXCollections.observableArrayList(); - - private Canvas canvas = new Canvas() { - @Override - public boolean isResizable() { - return true; - } - }; - - @FXML - private BorderPane pane; - - @FXML - private BarChart<String, Long> chart; - - @FXML - public void initialize() { - table1.setItems(points1); - - initColumns(table1); - table1.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); - table1.getSelectionModel().selectedItemProperty() - .addListener((ObservableValue<? extends Point> observable, Point oldValue, Point newValue) -> draw()); - canvas.setWidth(200); - canvas.setHeight(200); - pane.setCenter(canvas); - pane.widthProperty() - .addListener((observer, oldValue, newValue) -> canvas.setWidth(newValue.doubleValue() * 0.9)); - pane.heightProperty() - .addListener((observer, oldValue, newValue) -> canvas.setHeight(newValue.doubleValue() * 0.9)); - canvas.boundsInLocalProperty().addListener((observable, oldValue, newValue) -> draw()); - draw(); - - } - - private void draw() { - GraphicsContext gc = canvas.getGraphicsContext2D(); - double maxX = canvas.getWidth(); - double maxY = canvas.getHeight(); - double centerX = maxX / 2; - double centerY = maxY / 2; - gc.setFill(Color.WHITE); - gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight()); - gc.setStroke(Color.BLACK); - gc.strokeLine(centerX, 0, centerX, maxY); - gc.strokeLine(0, centerY, maxX, centerY); - gc.setFill(Color.BLACK); - Point selectedPoint = table1.getSelectionModel().getSelectedItem(); - for (Point point : points1) { - if (point instanceof ColorPoint colorPoint) { - gc.setFill(colorPoint.getColor()); - gc.fillOval(centerX + colorPoint.getX() - 2, centerY + colorPoint.getY() - 2, 4, 4); - } else { - gc.strokeOval(centerX + point.getX() - 2, centerY + point.getY() - 2, 4, 4); - } - if (point.equals(selectedPoint)) { - gc.setStroke(Color.RED); - gc.strokeLine(centerX + point.getX() - 15, centerY + point.getY(), centerX + point.getX() - 6, - centerY + point.getY()); - gc.strokeLine(centerX + point.getX() + 6, centerY + point.getY(), centerX + point.getX() + 15, - centerY + point.getY()); - gc.strokeLine(centerX + point.getX(), centerY + point.getY() - 15, centerX + point.getX(), - centerY + point.getY() - 6); - gc.strokeLine(centerX + point.getX(), centerY + point.getY() + 6, centerX + point.getX(), - centerY + point.getY() + 15); - } - } - } - - private void initColumns(TableView<Point> tab) { - ((TableColumn<Point, Double>) tab.getColumns().get(0)).setCellValueFactory(new PropertyValueFactory<>("x")); - ((TableColumn<Point, Double>) tab.getColumns().get(1)).setCellValueFactory(new PropertyValueFactory<>("y")); - ((TableColumn<Point, Color>) tab.getColumns().get(2)).setCellValueFactory(param -> { - if (param.getValue() instanceof ColorPoint p) { - return new MyObservableValue<>(p.getColor()); - } - return null; - }); - ((TableColumn<Point, Integer>) tab.getColumns().get(3)) - .setCellValueFactory(param -> new MyObservableValue<>(System.identityHashCode(param.getValue()))); - } - - @FXML - private void generatePressed(ActionEvent event) { - Stream.generate(this::generate).limit(10).forEach(points1::add); - draw(); - } - - @FXML - private void clearPressed(ActionEvent event) { - table1.getSelectionModel().clearSelection(); - points1.clear(); - draw(); - } - - @FXML - private void measure(ActionEvent event) { - XYChart.Series<String, Long> containsSpeed = new XYChart.Series<>(); - containsSpeed.setName("Speed of method contains() for interface Set"); - int i=10; - while(i<=100000) { - containsSpeed.getData().add(new Data<>(Integer.toString(i), RANDOM.nextLong(i*100l))); - i*=2; - } - chart.getData().add(containsSpeed); - } - - private Point generate() { - if (RANDOM.nextBoolean()) { - return new Point(canvas.getWidth() / 2 - RANDOM.nextDouble(canvas.getWidth()), - canvas.getHeight() / 2 - RANDOM.nextDouble(canvas.getHeight())); - } else { - return new ColorPoint(canvas.getWidth() / 2 - RANDOM.nextDouble(canvas.getWidth()), - canvas.getHeight() / 2 - RANDOM.nextDouble(canvas.getHeight()), - COLORS.get(RANDOM.nextInt(COLORS.size()))); - } - } - - public static class MyObservableValue<T> extends ObjectBinding<T> { - - private T value; - - public MyObservableValue(T color) { - this.value = color; - } - - @Override - public T computeValue() { - return value; - } - - } - -} diff --git a/src/main/java/cz/vsb/fei/java2/lab04/ColorPoint.java b/src/main/java/cz/vsb/fei/java2/lab04/ColorPoint.java deleted file mode 100644 index 4dce08c..0000000 --- a/src/main/java/cz/vsb/fei/java2/lab04/ColorPoint.java +++ /dev/null @@ -1,47 +0,0 @@ -package cz.vsb.fei.java2.lab04; - -import java.util.Objects; - -import javafx.scene.paint.Color; - -public class ColorPoint extends Point { - - private Color color; - - public ColorPoint(double x, double y, Color color) { - super(x, y); - this.color = color; - } - - public Color getColor() { - return color; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + Objects.hash(color); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (!(obj instanceof ColorPoint)) - return false; - ColorPoint other = (ColorPoint) obj; - if (!other.canEqual(this)) { - return false; - } - return Objects.equals(color, other.color); - } - - @Override - public boolean canEqual(Point p) { - return p instanceof ColorPoint; - } -} diff --git a/src/main/java/cz/vsb/fei/java2/lab04/Point.java b/src/main/java/cz/vsb/fei/java2/lab04/Point.java deleted file mode 100644 index d493f9e..0000000 --- a/src/main/java/cz/vsb/fei/java2/lab04/Point.java +++ /dev/null @@ -1,49 +0,0 @@ -package cz.vsb.fei.java2.lab04; - -import java.util.Objects; - -public class Point { - - private double x; - - private double y; - - public Point(double x, double y) { - this.x = x; - this.y = y; - } - - public double getX() { - return x; - } - - public double getY() { - return y; - } - - @Override - public int hashCode() { - return Objects.hash(x, y); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof Point)) - return false; - Point other = (Point) obj; - if (!other.canEqual(this)) { - return false; - } - return Double.doubleToLongBits(x) == Double.doubleToLongBits(other.x) - && Double.doubleToLongBits(y) == Double.doubleToLongBits(other.y); - } - - public boolean canEqual(Point p) { - return p instanceof Point; - } - -} \ No newline at end of file diff --git a/src/main/java/cz/vsb/fei/java2/lab04/App.java b/src/main/java/cz/vsb/fei/java2/lab04/gui/App.java similarity index 97% rename from src/main/java/cz/vsb/fei/java2/lab04/App.java rename to src/main/java/cz/vsb/fei/java2/lab04/gui/App.java index d2abb16..e1e216e 100644 --- a/src/main/java/cz/vsb/fei/java2/lab04/App.java +++ b/src/main/java/cz/vsb/fei/java2/lab04/gui/App.java @@ -1,4 +1,4 @@ -package cz.vsb.fei.java2.lab04; +package cz.vsb.fei.java2.lab04.gui; import javafx.application.Application; import javafx.fxml.FXMLLoader; diff --git a/src/main/java/cz/vsb/fei/java2/lab04/gui/AppController.java b/src/main/java/cz/vsb/fei/java2/lab04/gui/AppController.java new file mode 100644 index 0000000..7f5f63e --- /dev/null +++ b/src/main/java/cz/vsb/fei/java2/lab04/gui/AppController.java @@ -0,0 +1,297 @@ +package cz.vsb.fei.java2.lab04.gui; + +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.Random; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import cz.vsb.fei.java2.lab04.measurment.Measurment; +import cz.vsb.fei.java2.lab04.measurment.Measurment.InsertContainsMeasurmentResult; +import cz.vsb.fei.java2.lab04.measurment.Measurment.ReleabilityMeasurmentResult; +import cz.vsb.fei.java2.lab04.points.ColorPoint; +import cz.vsb.fei.java2.lab04.points.Point; +import cz.vsb.fei.java2.lab04.points.Point.HashImpl; +import javafx.beans.binding.ObjectBinding; +import javafx.beans.value.ObservableValue; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.chart.BarChart; +import javafx.scene.chart.CategoryAxis; +import javafx.scene.chart.NumberAxis; +import javafx.scene.chart.XYChart; +import javafx.scene.chart.XYChart.Data; +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.Label; +import javafx.scene.control.SelectionMode; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.scene.control.cell.PropertyValueFactory; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.VBox; +import javafx.scene.paint.Color; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +public class AppController { + + private static final Random RANDOM = new Random(); + + @FXML + private TableView<Point> table1; + private ObservableList<Point> points1 = FXCollections.observableArrayList(); + + private Canvas canvas = new Canvas() { + @Override + public boolean isResizable() { + return true; + } + }; + + @FXML + private BorderPane pane; + + private BarChart<String, Double> insertTimeChart; + + private BarChart<String, Double> containsTimeCahrt; + private BarChart<String, Number> releabilityChart; + + @FXML + private VBox chartBox; + + @FXML + public void initialize() { + table1.setItems(points1); + + initColumns(table1); + table1.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); + table1.getSelectionModel().selectedItemProperty() + .addListener((ObservableValue<? extends Point> observable, Point oldValue, Point newValue) -> draw()); + canvas.setWidth(200); + canvas.setHeight(200); + pane.setCenter(canvas); + pane.widthProperty() + .addListener((observer, oldValue, newValue) -> canvas.setWidth(newValue.doubleValue() * 0.9)); + pane.heightProperty() + .addListener((observer, oldValue, newValue) -> canvas.setHeight(newValue.doubleValue() * 0.9)); + canvas.boundsInLocalProperty().addListener((observable, oldValue, newValue) -> draw()); + canvas.setOnMouseClicked(this::mouseClickedInDrawingArea); + draw(); + insertTimeChart = new BarChart<>(new CategoryAxis(), new LogarithmicAxis()); + containsTimeCahrt = new BarChart<>(new CategoryAxis(), new LogarithmicAxis()); + releabilityChart = new BarChart<>(new CategoryAxis(), new NumberAxis()); + chartBox.getChildren().add(new Label("Time of inserting points into set in seconds")); + chartBox.getChildren().add(insertTimeChart); + chartBox.getChildren().add(new Label("Average time (20 attempts) of method contains for set in seconds")); + chartBox.getChildren().add(containsTimeCahrt); + chartBox.getChildren().add(new Label("Releability of method contains (100 attempts) in percentage")); + chartBox.getChildren().add(releabilityChart); + + } + + private void draw() { + GraphicsContext gc = canvas.getGraphicsContext2D(); + double maxX = canvas.getWidth(); + double maxY = canvas.getHeight(); + double centerX = maxX / 2; + double centerY = maxY / 2; + gc.setFill(Color.WHITE); + gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight()); + gc.setStroke(Color.BLACK); + gc.strokeLine(centerX, 0, centerX, maxY); + gc.strokeLine(0, centerY, maxX, centerY); + gc.setFill(Color.BLACK); + Point selectedPoint = table1.getSelectionModel().getSelectedItem(); + for (Point point : points1) { + if (point instanceof ColorPoint colorPoint) { + gc.setFill(colorPoint.getColor()); + gc.fillOval(centerX + colorPoint.getX() - 2, centerY + colorPoint.getY() - 2, 4, 4); + } else { + gc.setStroke(Color.BLACK); + gc.strokeOval(centerX + point.getX() - 2, centerY + point.getY() - 2, 4, 4); + } + if (point.equals(selectedPoint)) { + drawCroshairAroundPoint(gc, point); + } + } + } + + private void drawCroshairAroundPoint(GraphicsContext gc, Point point) { + double maxX = canvas.getWidth(); + double maxY = canvas.getHeight(); + double centerX = maxX / 2; + double centerY = maxY / 2; + gc.setStroke(Color.RED); + gc.strokeLine(centerX + point.getX() - 15, centerY + point.getY(), centerX + point.getX() - 6, + centerY + point.getY()); + gc.strokeLine(centerX + point.getX() + 6, centerY + point.getY(), centerX + point.getX() + 15, + centerY + point.getY()); + gc.strokeLine(centerX + point.getX(), centerY + point.getY() - 15, centerX + point.getX(), + centerY + point.getY() - 6); + gc.strokeLine(centerX + point.getX(), centerY + point.getY() + 6, centerX + point.getX(), + centerY + point.getY() + 15); + } + + private void initColumns(TableView<Point> tab) { + ((TableColumn<Point, Double>) tab.getColumns().get(0)).setCellValueFactory(new PropertyValueFactory<>("x")); + ((TableColumn<Point, Double>) tab.getColumns().get(1)).setCellValueFactory(new PropertyValueFactory<>("y")); + ((TableColumn<Point, Color>) tab.getColumns().get(2)).setCellValueFactory(param -> { + if (param.getValue() instanceof ColorPoint p) { + return new MyObservableValue<>(p.getColor()); + } + return null; + }); + ((TableColumn<Point, Integer>) tab.getColumns().get(3)) + .setCellValueFactory(param -> new MyObservableValue<>(System.identityHashCode(param.getValue()))); + } + + @FXML + private void generatePressed(ActionEvent event) { + double maxX = canvas.getWidth(); + double maxY = canvas.getHeight(); + try { + Stream.generate(() -> Point.generateInRange(-maxX / 2, maxX / 2, -maxY / 2, maxY / 2)).limit(10) + .forEach(points1::add); + } catch (Exception ex) { + showErrorAlert(ex.getMessage()); + log.error("Error while generate points.", ex); + } + draw(); + } + + private void showErrorAlert(List<String> messages) { + String message = "Exception messages:\n\t" + messages.stream().collect(Collectors.joining("\n\t")); + Alert alert = new Alert(AlertType.ERROR); + alert.setTitle("ExceptionOccurred"); + Label text = new Label(message); + text.setWrapText(true); + Label header = new Label("Can We Implement It?\n\tYes We Can!!!"); + header.setWrapText(true); + alert.getDialogPane().setContent(text); + alert.getDialogPane().setHeader(header); + alert.show(); + } + + private void showErrorAlert(String message) { + Alert alert = new Alert(AlertType.ERROR); + alert.setTitle("ExceptionOccurred"); + Label text = new Label(message); + text.setWrapText(true); + Label header = new Label("Can We Implement It?\nYes We Can!!!"); + header.setWrapText(true); + alert.getDialogPane().setContent(text); + alert.getDialogPane().setHeader(header); + alert.show(); + } + + @FXML + private void generateInRadiusPressed(ActionEvent event) { + double radius = 10 + RANDOM.nextDouble(200); + final Point center = Optional.ofNullable(table1.getSelectionModel().getSelectedItem()).orElse(new Point(0, 0)); + try { + Stream.generate(() -> Point.generateInRadius(center, radius)).limit(30).forEach(points1::add); + } catch (Exception ex) { + showErrorAlert(ex.getMessage()); + log.error("Error while generate points in radius.", ex); + } + draw(); + } + + @FXML + private void mouseClickedInDrawingArea(MouseEvent event) { + double maxX = canvas.getWidth(); + double maxY = canvas.getHeight(); + double x = event.getX() - maxX / 2; + double y = event.getY() - maxY / 2; + points1.stream().filter(p -> Math.abs(p.getX() - x) < 5 && Math.abs(p.getY() - y) < 5).findFirst() + .ifPresent(p -> { + table1.selectionModelProperty().get().select(p); + table1.scrollTo(p); + }); + } + + @FXML + private void clearPressed(ActionEvent event) { + table1.getSelectionModel().clearSelection(); + points1.clear(); + draw(); + } + + @FXML + private void measure1000(ActionEvent event) { + measure(1000); + } + + @FXML + private void measure10000(ActionEvent event) { + measure(10000); + } + + @FXML + private void measure100000(ActionEvent event) { + measure(100000); + } + + private void measure(int maxCount) { + insertTimeChart.getData().clear(); + containsTimeCahrt.getData().clear(); + releabilityChart.getData().clear(); + XYChart.Series<String, Number> containsSameReleability = new XYChart.Series<>(); + XYChart.Series<String, Number> containsEqualReleability = new XYChart.Series<>(); + containsSameReleability.setName("for same instance."); + containsEqualReleability.setName("for equal instance."); + List<String> errorMessages =new LinkedList<String>(); + for (HashImpl hashImpl : HashImpl.values()) { + try { + Point.setHashImplTo(hashImpl); + XYChart.Series<String, Double> containsSpeed = new XYChart.Series<>(); + XYChart.Series<String, Double> insertSpeed = new XYChart.Series<>(); + containsSpeed.setName("implementation " + Point.getHashImpl()); + insertSpeed.setName("implementation " + Point.getHashImpl()); + int i = 10; + while (i <= maxCount) { + InsertContainsMeasurmentResult measureResult = Measurment.mesure(i); + Data<String, Double> d = new Data<>(Integer.toString(i), measureResult.containsDuration() / 1000000d); + containsSpeed.getData().add(d); + insertSpeed.getData().add(new Data<>(Integer.toString(i), measureResult.insertDuration() / 1000000d)); + i *= 10; + } + ReleabilityMeasurmentResult result = Measurment.mesureReleability(); + containsSameReleability.getData().add(new Data<>(hashImpl.toString(), result.countSameInstance())); + containsEqualReleability.getData().add(new Data<>(hashImpl.toString(), result.countEqualObject())); + insertTimeChart.getData().add(insertSpeed); + containsTimeCahrt.getData().add(containsSpeed); + } catch (Exception ex) { + errorMessages.add(ex.getMessage()); + log.error("Error while mesure speed." , ex); + } + } + releabilityChart.getData().addAll(containsSameReleability, containsEqualReleability); + if(!errorMessages.isEmpty()) { + showErrorAlert(errorMessages); + } + } + + public static class MyObservableValue<T> extends ObjectBinding<T> { + + private T value; + + public MyObservableValue(T color) { + this.value = color; + } + + @Override + public T computeValue() { + return value; + } + + } + +} diff --git a/src/main/java/cz/vsb/fei/java2/lab04/gui/LogarithmicAxis.java b/src/main/java/cz/vsb/fei/java2/lab04/gui/LogarithmicAxis.java new file mode 100644 index 0000000..90499d5 --- /dev/null +++ b/src/main/java/cz/vsb/fei/java2/lab04/gui/LogarithmicAxis.java @@ -0,0 +1,232 @@ +package cz.vsb.fei.java2.lab04.gui; + +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.List; + +import javafx.animation.KeyFrame; +import javafx.animation.KeyValue; +import javafx.animation.Timeline; +import javafx.beans.binding.DoubleBinding; +import javafx.beans.property.DoubleProperty; +import javafx.beans.property.SimpleDoubleProperty; +import javafx.scene.chart.ValueAxis; +import javafx.util.Duration; + +/** + * A logarithmic axis implementation for JavaFX 2 charts<br> + * <br> + * + * @author Kevin Senechal + * + */ +public class LogarithmicAxis extends ValueAxis<Double> { + + /** + * The time of animation in ms + */ + private static final double ANIMATION_TIME = 2000; + private final Timeline lowerRangeTimeline = new Timeline(); + private final Timeline upperRangeTimeline = new Timeline(); + + private final DoubleProperty logUpperBound = new SimpleDoubleProperty(); + private final DoubleProperty logLowerBound = new SimpleDoubleProperty(); + + public LogarithmicAxis() { + super(0.00001, 10); + bindLogBoundsToDefaultBounds(); + setAutoRanging(true); + } + + public LogarithmicAxis(double lowerBound, double upperBound) { + super(lowerBound, upperBound); + try { + validateBounds(lowerBound, upperBound); + bindLogBoundsToDefaultBounds(); + } catch (IllegalLogarithmicRangeException e) { + e.printStackTrace(); + } + } + + /** + * Bind our logarithmic bounds with the super class bounds, consider the base 10 logarithmic scale. + */ + private void bindLogBoundsToDefaultBounds() { + logLowerBound.bind(new DoubleBinding() { + + { + super.bind(lowerBoundProperty()); + } + + @Override + protected double computeValue() { + return Math.log10(lowerBoundProperty().get()); + } + }); + logUpperBound.bind(new DoubleBinding() { + + { + super.bind(upperBoundProperty()); + } + + @Override + protected double computeValue() { + return Math.log10(upperBoundProperty().get()); + } + }); + } + + /** + * Validate the bounds by throwing an exception if the values are not conform to the mathematics log interval: + * ]0,Double.MAX_VALUE] + * + * @param lowerBound + * @param upperBound + * @throws IllegalLogarithmicRangeException + */ + private void validateBounds(double lowerBound, double upperBound) throws IllegalLogarithmicRangeException { + if (lowerBound < 0 || upperBound < 0 || lowerBound > upperBound) { + throw new IllegalLogarithmicRangeException( + "The logarithmic range should be include to ]0,Double.MAX_VALUE] and the lowerBound should be less than the upperBound"); + } + } + + /** + * {@inheritDoc} + */ + @Override + protected List<Double> calculateMinorTickMarks() { + Number[] range = getRange(); + List<Double> minorTickMarksPositions = new ArrayList<>(); + if (range != null) { + + Number upperBound = range[1]; + double logUpperBound = Math.log10(upperBound.doubleValue()); + int minorTickMarkCount = getMinorTickCount(); + + for (double i = 0; i <= logUpperBound; i += 1) { + for (double j = 0; j <= 9; j += (1. / minorTickMarkCount)) { + double value = j * Math.pow(10, i); + minorTickMarksPositions.add(value); + } + } + } + return minorTickMarksPositions; + } + + /** + * {@inheritDoc} + */ + @Override + protected List<Double> calculateTickValues(double length, Object range) { + List<Double> tickPositions = new ArrayList<>(); + if (range != null) { + Number lowerBound = ((Number[]) range)[0]; + Number upperBound = ((Number[]) range)[1]; + double logLowerBound = Math.log10(lowerBound.doubleValue()); + double logUpperBound = Math.log10(upperBound.doubleValue()); + + for (double i = logLowerBound; i <= logUpperBound; i += 1) { + for (double j = 1; j <= 9; j++) { + double value = j * Math.pow(10, i); + tickPositions.add(value); + } + } + } + return tickPositions; + } + + @Override + protected Number[] getRange() { + return new Number[] { lowerBoundProperty().get(), upperBoundProperty().get() }; + } + + @Override + protected String getTickMarkLabel(Double value) { + NumberFormat formatter = NumberFormat.getInstance(); + formatter.setMaximumIntegerDigits(6); + formatter.setMinimumIntegerDigits(1); + formatter.setMaximumFractionDigits(5); + return formatter.format(value); + } + + /** + * {@inheritDoc} + */ + @Override + protected void setRange(Object range, boolean animate) { + if (range != null) { + Number lowerBound = ((Number[]) range)[0]; + Number upperBound = ((Number[]) range)[1]; + try { + validateBounds(lowerBound.doubleValue(), upperBound.doubleValue()); + } catch (IllegalLogarithmicRangeException e) { + e.printStackTrace(); + } + if (animate) { + try { + lowerRangeTimeline.getKeyFrames().clear(); + upperRangeTimeline.getKeyFrames().clear(); + + lowerRangeTimeline.getKeyFrames() + .addAll(new KeyFrame(Duration.ZERO, new KeyValue(lowerBoundProperty(), lowerBoundProperty() + .get())), + new KeyFrame(new Duration(ANIMATION_TIME), new KeyValue(lowerBoundProperty(), + lowerBound.doubleValue()))); + + upperRangeTimeline.getKeyFrames() + .addAll(new KeyFrame(Duration.ZERO, new KeyValue(upperBoundProperty(), upperBoundProperty() + .get())), + new KeyFrame(new Duration(ANIMATION_TIME), new KeyValue(upperBoundProperty(), + upperBound.doubleValue()))); + lowerRangeTimeline.play(); + upperRangeTimeline.play(); + } catch (Exception e) { + lowerBoundProperty().set(lowerBound.doubleValue()); + upperBoundProperty().set(upperBound.doubleValue()); + } + } + lowerBoundProperty().set(lowerBound.doubleValue()); + upperBoundProperty().set(upperBound.doubleValue()); + } + } + + + + @Override + protected Object autoRange(double minValue, double maxValue, double length, double labelSize) { + return new Number[] {minValue, maxValue}; + } + + @Override + public Double getValueForDisplay(double displayPosition) { + double delta = logUpperBound.get() - logLowerBound.get(); + if (getSide().isVertical()) { + return Math.pow(10, (((displayPosition - getHeight()) / -getHeight()) * delta) + logLowerBound.get()); + } else { + return Math.pow(10, (((displayPosition / getWidth()) * delta) + logLowerBound.get())); + } + } + + @Override + public double getDisplayPosition(Double value) { + double delta = logUpperBound.get() - logLowerBound.get(); + double deltaV = Math.log10(value.doubleValue()) - logLowerBound.get(); + if (getSide().isVertical()) { + return (1. - ((deltaV) / delta)) * getHeight(); + } else { + return ((deltaV) / delta) * getWidth(); + } + } + + public static class IllegalLogarithmicRangeException extends Exception { + + /** + * @param string + */ + public IllegalLogarithmicRangeException(String message) { + super(message); + } + + } +} diff --git a/src/main/java/cz/vsb/fei/java2/lab04/measurment/Measurment.java b/src/main/java/cz/vsb/fei/java2/lab04/measurment/Measurment.java new file mode 100644 index 0000000..cf9d8ef --- /dev/null +++ b/src/main/java/cz/vsb/fei/java2/lab04/measurment/Measurment.java @@ -0,0 +1,55 @@ +package cz.vsb.fei.java2.lab04.measurment; + +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Stream; + +import cz.vsb.fei.java2.lab04.points.Point; + +public class Measurment { + + public record InsertContainsMeasurmentResult(long insertDuration, long containsDuration) { + } + + public record ReleabilityMeasurmentResult(int countSameInstance, int countEqualObject) { + } + + public static InsertContainsMeasurmentResult mesure(int pointCollectionSize) { + //TODO: generate pointCollectionSize random points + List<Point> pointsToInsert = Collections.emptyList(); + //TODO: generate 20 random points + List<Point> pointsToTest = Collections.emptyList(); + + //TODO: create hash set + Set<Point> pointsSet = Collections.emptySet(); + + long start = System.nanoTime(); + //TODO: insert point to Set + long insertDuration = (System.nanoTime() - start) / pointsToInsert.size(); + + start = System.nanoTime(); + //TODO: call method Set.contains with all points in set pointsToTest + long containsDuration = (System.nanoTime() - start) / pointsToTest.size(); + + return new InsertContainsMeasurmentResult(insertDuration, containsDuration); + } + + public static ReleabilityMeasurmentResult mesureReleability() { + //TODO: generate 100 random points + List<Point> pointsToInsert = Collections.emptyList(); + //TODO: create hash set + Set<Point> pointsSet = Collections.emptySet(); + + //TODO:insert point to Set + + int countSameInstance = 0; + int countEqualObject = 0; + + //TODO: calculate for how many points in the list the method Set.contains method returns true (should be true for all) + + return new ReleabilityMeasurmentResult(countSameInstance, countEqualObject); + } + +} diff --git a/src/main/java/cz/vsb/fei/java2/lab04/points/ColorPoint.java b/src/main/java/cz/vsb/fei/java2/lab04/points/ColorPoint.java new file mode 100644 index 0000000..3560db2 --- /dev/null +++ b/src/main/java/cz/vsb/fei/java2/lab04/points/ColorPoint.java @@ -0,0 +1,50 @@ +package cz.vsb.fei.java2.lab04.points; + +import java.util.Objects; + +import javafx.scene.paint.Color; + +public class ColorPoint extends Point { + + private Color color; + + public ColorPoint(double x, double y, Color color) { + super(x, y); + this.color = color; + } + + @Override + public Point createCopy() { + return new ColorPoint(getX(), getY(), color); + } + + public Color getColor() { + return color; + } + + @Override + public int hashCode() { + return super.hashCode(); + //TODO: compute hash. Choose algorithm base on Point.hashImpl + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (!(obj instanceof ColorPoint)) + return false; + ColorPoint other = (ColorPoint) obj; + if (!other.canEqual(this)) { + return false; + } + return Objects.equals(color, other.color); + } + + @Override + public boolean canEqual(Point p) { + return p instanceof ColorPoint; + } +} diff --git a/src/main/java/cz/vsb/fei/java2/lab04/points/Point.java b/src/main/java/cz/vsb/fei/java2/lab04/points/Point.java new file mode 100644 index 0000000..ee382c7 --- /dev/null +++ b/src/main/java/cz/vsb/fei/java2/lab04/points/Point.java @@ -0,0 +1,88 @@ +package cz.vsb.fei.java2.lab04.points; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Random; + +import javafx.scene.paint.Color; + +public class Point { + + private static final List<Color> COLORS = Collections.unmodifiableList(Arrays.asList(Color.RED, Color.BLUE, Color.YELLOW, Color.BLACK, + Color.ORANGE, Color.PINK, Color.PURPLE)); + + public static final Random RANDOM = new Random(); + + protected static HashImpl hashImpl = HashImpl.SAME; + + public static void setHashImplTo(HashImpl hashImpl) { + Point.hashImpl = hashImpl; + } + public static HashImpl getHashImpl() { + return hashImpl; + } + + public static Point generateInRange(double minX, double maxX, double minY, double maxY) { + throw new UnsupportedOperationException("Method generateInRange not implemented yet!"); + //TODO: Generate random point with given constraints. Randomly choose to generate point or color point. + } + + public static Point generateInRadius(Point center, double radius) { + throw new UnsupportedOperationException("Method generateInRadius not implemented yet!"); + //TODO: Generate random point with given radius from center. Randomly choose to generate point or color point. + } + + private double x; + private double y; + + + public Point(double x, double y) { + this.x = x; + this.y = y; + } + + public Point createCopy() { + return new Point(x, y); + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + protected Integer hashCode = null; + + @Override + public int hashCode() { + return super.hashCode(); + //TODO: compute hash. Choose algorithm base on hashImpl + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof Point)) + return false; + Point other = (Point) obj; + if (!other.canEqual(this)) { + return false; + } + return Double.doubleToLongBits(x) == Double.doubleToLongBits(other.x) + && Double.doubleToLongBits(y) == Double.doubleToLongBits(other.y); + } + + public boolean canEqual(Point p) { + return p instanceof Point; + } + + public enum HashImpl { + SAME, FULL_RANDOM, RANDOM, STANDARD; + } +} \ No newline at end of file diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index c8f3b6f..edaaf74 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -1,8 +1,9 @@ module cz.vsb.fei.java2.lab04 { requires transitive javafx.controls; requires javafx.fxml; - requires lombok; - requires org.apache.logging.log4j; - opens cz.vsb.fei.java2.lab04 to javafx.fxml; - exports cz.vsb.fei.java2.lab04; + requires static lombok; + requires org.apache.logging.log4j; + + opens cz.vsb.fei.java2.lab04.gui to javafx.fxml,javafx.graphics; + opens cz.vsb.fei.java2.lab04.points to javafx.base; } \ No newline at end of file diff --git a/src/main/resources/cz/vsb/fei/java2/lab04/AppWindow.fxml b/src/main/resources/cz/vsb/fei/java2/lab04/gui/AppWindow.fxml similarity index 77% rename from src/main/resources/cz/vsb/fei/java2/lab04/AppWindow.fxml rename to src/main/resources/cz/vsb/fei/java2/lab04/gui/AppWindow.fxml index edc5e24..953051b 100644 --- a/src/main/resources/cz/vsb/fei/java2/lab04/AppWindow.fxml +++ b/src/main/resources/cz/vsb/fei/java2/lab04/gui/AppWindow.fxml @@ -33,11 +33,6 @@ --> <?import javafx.geometry.Insets?> -<?import javafx.scene.Cursor?> -<?import javafx.scene.canvas.Canvas?> -<?import javafx.scene.chart.BarChart?> -<?import javafx.scene.chart.CategoryAxis?> -<?import javafx.scene.chart.NumberAxis?> <?import javafx.scene.control.Button?> <?import javafx.scene.control.Tab?> <?import javafx.scene.control.TabPane?> @@ -45,9 +40,9 @@ <?import javafx.scene.control.TableView?> <?import javafx.scene.layout.BorderPane?> <?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.VBox?> - -<TabPane xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="cz.vsb.fei.java2.lab04.AppController"> +<TabPane prefHeight="522.0" prefWidth="715.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="cz.vsb.fei.java2.lab04.gui.AppController"> <tabs> <Tab text="Points"> <content> @@ -70,13 +65,6 @@ </HBox.margin> </TableView> <BorderPane fx:id="pane" prefHeight="200.0" prefWidth="200.0" HBox.hgrow="ALWAYS"> - <center> - <Canvas fx:id="canvas" height="163.0" width="174.0" BorderPane.alignment="CENTER"> - <cursor> - <Cursor fx:constant="CROSSHAIR" /> - </cursor> - </Canvas> - </center> <opaqueInsets> <Insets /> </opaqueInsets> @@ -97,6 +85,7 @@ <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> </HBox.margin> </Button> + <Button mnemonicParsing="false" onAction="#generateInRadiusPressed" text="Generate in radius" /> <Button mnemonicParsing="false" onAction="#clearPressed" text="Clear"> <HBox.margin> <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> @@ -116,23 +105,33 @@ <top> <BorderPane BorderPane.alignment="CENTER"> <center> - <Button fx:id="mesure" mnemonicParsing="false" onAction="#measure" text="Mesure"> + <HBox> <BorderPane.margin> <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> </BorderPane.margin> - </Button> + <children> + <Button fx:id="measure1" mnemonicParsing="false" onAction="#measure1000" text="Mesure to 1 000"> + <HBox.margin> + <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> + </HBox.margin> + </Button> + <Button fx:id="mesure2" mnemonicParsing="false" onAction="#measure10000" text="Mesure to 10 000"> + <HBox.margin> + <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> + </HBox.margin> + </Button> + <Button fx:id="mesure3" mnemonicParsing="false" onAction="#measure100000" text="Mesure to 100 000"> + <HBox.margin> + <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> + </HBox.margin> + </Button> + </children> + </HBox> </center> </BorderPane> </top> <center> - <BarChart fx:id="chart" BorderPane.alignment="CENTER"> - <xAxis> - <CategoryAxis side="BOTTOM" /> - </xAxis> - <yAxis> - <NumberAxis side="LEFT" /> - </yAxis> - </BarChart> + <VBox fx:id="chartBox" BorderPane.alignment="CENTER" /> </center> </BorderPane> </content> diff --git a/src/main/resources/cz/vsb/fei/java2/lab04/application.css b/src/main/resources/cz/vsb/fei/java2/lab04/gui/application.css similarity index 100% rename from src/main/resources/cz/vsb/fei/java2/lab04/application.css rename to src/main/resources/cz/vsb/fei/java2/lab04/gui/application.css -- GitLab