Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
No results found
Show changes
Commits on Source (2)
Showing
with 1063 additions and 0 deletions
# Eclipse
.classpath
.project
.settings/
# Intellij
.idea/
*.iml
*.iws
# Mac
.DS_Store
# Maven
log/
target/
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cz.vsb.fei.java2</groupId>
<artifactId>lab04</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>lab04</name>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>21</maven.compiler.release>
<JavaFX.version>22-ea+16</JavaFX.version>
<JUnit.version>5.10.1</JUnit.version>
<log4j.version>2.22.1</log4j.version>
<lombok.version>1.18.30</lombok.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>${JUnit.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>${JavaFX.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>${JavaFX.version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.12.1</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.2.1</version>
</plugin>
</plugins>
</build>
</project>
package cz.vsb.fei.java2.lab04.gui;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.TabPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import lombok.extern.log4j.Log4j2;
/**
* Class <b>App</b> - extends class Application and it is an entry point of the program
* @author Java I
*/
@Log4j2
public class App extends Application {
public static void main(String[] args) {
log.info("Launching JavaFX application.");
launch(args);
}
private AppController controller;
@Override
public void start(Stage primaryStage) {
try {
//Construct a main window with a canvas.
FXMLLoader loader = new FXMLLoader(this.getClass().getResource("AppWindow.fxml"));
TabPane root = loader.load();
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.setTitle("Hello word app");
primaryStage.show();
controller = loader.getController();
//Exit program when main window is closed
primaryStage.setOnCloseRequest(this::exitProgram);
} catch (Exception e) {
e.printStackTrace();
}
}
private void exitProgram(WindowEvent evt) {
System.exit(0);
}
}
\ No newline at end of file
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;
}
}
}
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);
}
}
}
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);
}
}
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;
}
}
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
module cz.vsb.fei.java2.lab04 {
requires transitive javafx.controls;
requires javafx.fxml;
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
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2015, 2019, Gluon and/or its affiliates.
All rights reserved. Use is subject to license terms.
This file is available and licensed under the following license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
- Neither the name of Oracle Corporation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<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>
<BorderPane minHeight="400.0" minWidth="640.0" prefHeight="400.0" prefWidth="715.0">
<center>
<HBox prefHeight="100.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<children>
<TableView fx:id="table1" prefHeight="200.0" prefWidth="200.0" HBox.hgrow="ALWAYS">
<columns>
<TableColumn prefWidth="46.0" text="X" />
<TableColumn prefWidth="52.0" text="Y" />
<TableColumn prefWidth="75.0" text="Color" />
<TableColumn prefWidth="163.0" text="System identity&#10;HashCode" />
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
<HBox.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</HBox.margin>
</TableView>
<BorderPane fx:id="pane" prefHeight="200.0" prefWidth="200.0" HBox.hgrow="ALWAYS">
<opaqueInsets>
<Insets />
</opaqueInsets>
<HBox.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</HBox.margin>
</BorderPane>
</children>
</HBox>
</center>
<top>
<BorderPane BorderPane.alignment="CENTER">
<center>
<HBox alignment="CENTER" BorderPane.alignment="CENTER">
<children>
<Button mnemonicParsing="false" onAction="#generatePressed" text="Generate">
<HBox.margin>
<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" />
</HBox.margin>
</Button>
</children>
</HBox>
</center>
</BorderPane>
</top>
</BorderPane>
</content>
</Tab>
<Tab text="Speed Mesurment">
<content>
<BorderPane>
<top>
<BorderPane BorderPane.alignment="CENTER">
<center>
<HBox>
<BorderPane.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</BorderPane.margin>
<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>
<VBox fx:id="chartBox" BorderPane.alignment="CENTER" />
</center>
</BorderPane>
</content>
</Tab>
</tabs>
</TabPane>
/* JavaFX CSS - Leave this comment until you have at least create one rule which uses -fx-Property */
\ No newline at end of file
<Configuration>
<Appenders>
<Console name="Console">
<PatternLayout
pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
</Console>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console"></AppenderRef>
</Root>
</Loggers>
</Configuration>
package cz.vsb.fei.java2.lab04;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
/**
* Unit test for simple App.
*/
class AppTest {
/**
* Rigorous Test :-)
*/
@Test
void shouldAnswerWithTrue() {
assertTrue(true);
}
}