diff --git a/pom.xml b/pom.xml index 126896849a92dc3c576607714909e86190031fb6..37ba4cf8f06b9b01aba7f038693c2f0ebc72bdf0 100644 --- a/pom.xml +++ b/pom.xml @@ -3,9 +3,9 @@ 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>java2-lab04-v2</artifactId> + <artifactId>java2-lab05-v2</artifactId> <version>0.0.1-SNAPHOST</version> - <name>java2-lab04-v2</name> + <name>java2-lab05-v2</name> <packaging>jar</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> @@ -58,7 +58,6 @@ <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>2.3.232</version> - <scope>runtime</scope> </dependency> <dependency> diff --git a/src/main/java/lab/Config.java b/src/main/java/lab/Config.java index 31ec69ddf7b454af26123c4545d46c16cdd63399..826635a2acde3cad1694b3a46589349f34dd3472 100644 --- a/src/main/java/lab/Config.java +++ b/src/main/java/lab/Config.java @@ -3,12 +3,17 @@ package lab; import lab.storage.DbConnector; import lab.storage.ScoreStorageInterface; import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; import lombok.Builder.Default; import lombok.Getter; +import lombok.ToString; @Getter +@Builder(toBuilder = true) +@EqualsAndHashCode +@ToString @AllArgsConstructor -@lombok.Builder(toBuilder = true) public class Config { @Getter diff --git a/src/main/java/lab/data/Level.java b/src/main/java/lab/data/Level.java new file mode 100644 index 0000000000000000000000000000000000000000..fc4e0318fc17ab7eb9863e7b4ae8ca4fb9e5154e --- /dev/null +++ b/src/main/java/lab/data/Level.java @@ -0,0 +1,5 @@ +package lab.data; + +public enum Level { + EASY, MEDIUM, HARD; +} diff --git a/src/main/java/lab/data/Score.java b/src/main/java/lab/data/Score.java index 71011021a0d6dabdb1ead49426440dab6cbd8797..435a6c2559cfa5925cad211374cdcd656a1f104b 100644 --- a/src/main/java/lab/data/Score.java +++ b/src/main/java/lab/data/Score.java @@ -3,6 +3,7 @@ package lab.data; import java.util.Random; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; @@ -13,15 +14,19 @@ import lombok.ToString; @AllArgsConstructor @EqualsAndHashCode @ToString +@Builder(toBuilder = true) public class Score { private static final Random RANDOM = new Random(); + private Long id; private String name; private int points; + private Level level; + public static Score generate() { - return new Score(getRandomNick(), RANDOM.nextInt(50, 300)); + return new Score(null, getRandomNick(), RANDOM.nextInt(50, 300), Level.values()[RANDOM.nextInt(Level.values().length)]); } public static final String[] nicks = { "CyberSurfer", "PixelPioneer", "SocialSavvy", "DigitalDynamo", "ByteBuddy", "InstaGuru", diff --git a/src/main/java/lab/gui/App.java b/src/main/java/lab/gui/App.java index 02d634aff8b9f0d456dea935c6145d80de463942..ef7d8e931e3c73628f8e0f5fb46fea3eb651b83e 100644 --- a/src/main/java/lab/gui/App.java +++ b/src/main/java/lab/gui/App.java @@ -2,9 +2,9 @@ package lab.gui; import java.io.IOException; import java.net.URL; +import java.sql.SQLException; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.h2.tools.Server; import javafx.application.Application; import javafx.fxml.FXMLLoader; @@ -13,6 +13,8 @@ import javafx.scene.Scene; import javafx.stage.Stage; import javafx.stage.WindowEvent; import lab.Config; +import lab.storage.JpaConnector; +import lombok.extern.log4j.Log4j2; /** * Class <b>App</b> - extends class Application and it is an entry point of the @@ -20,19 +22,34 @@ import lab.Config; * * @author Java I */ + +@Log4j2 public class App extends Application { - private static Logger log = LogManager.getLogger(App.class); private GameController gameController; private Stage primaryStage; public static void main(String[] args) { log.info("Application lauched"); - Config.configure(Config.getInstanceForHardcoreGame()); + Config.configure(Config.builder().scoreStorageInterface(new JpaConnector()).build()); + + startH2WebServerToInspectDb(); + launch(args); } + private static void startH2WebServerToInspectDb() { + //Start HTTP server for access H2 DB for look inside + try { + Server server = Server.createWebServer(); + log.info(server.getURL()); + server.start(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + @Override public void start(Stage primaryStage) { try { @@ -83,6 +100,7 @@ public class App extends Application { if(gameController != null) { gameController.stop(); } + Config.getInstance().getScoreStorageInterface().stop(); log.info("Exiting game"); System.exit(0); } diff --git a/src/main/java/lab/gui/MainScreenController.java b/src/main/java/lab/gui/MainScreenController.java index 45c849ad3e39027f6a0aa7f591c3f895b0077185..6ccdf7703b12c6f4e626b7497dee93fc7c11216c 100644 --- a/src/main/java/lab/gui/MainScreenController.java +++ b/src/main/java/lab/gui/MainScreenController.java @@ -1,14 +1,17 @@ package lab.gui; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import javafx.collections.ListChangeListener; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.Button; +import javafx.scene.control.SelectionMode; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.control.TextField; @@ -16,6 +19,7 @@ import javafx.scene.control.ToggleButton; import javafx.scene.control.ToggleGroup; import javafx.scene.control.cell.PropertyValueFactory; import lab.Config; +import lab.data.Level; import lab.data.Score; import lab.game.Difficult; @@ -34,6 +38,9 @@ public class MainScreenController { @FXML private Button btnLoadFirstTen; + + @FXML + private Button btnDelete; @FXML private TableView<Score> scores; @@ -44,6 +51,9 @@ public class MainScreenController { @FXML private TableColumn<Score, Integer> pointsColumn; + @FXML + private TableColumn<Score, Level> difficultColumn; + @FXML private ToggleGroup difficult; @@ -75,7 +85,7 @@ public class MainScreenController { void btnGenerateScoreAction(ActionEvent event) { Score score = Score.generate(); this.scores.getItems().add(score); - Config.getInstance().getScoreStorageInterface().insertScore(score); + Config.getInstance().getScoreStorageInterface().save(score); } @FXML @@ -88,7 +98,14 @@ public class MainScreenController { updateScoreTable(Config.getInstance().getScoreStorageInterface().getFirstTen()); } - private void updateScoreTable(List<Score> scores) { + @FXML + void btnDeleteAction(ActionEvent event) { + List<Score> selectedScores = new ArrayList<>(scores.getSelectionModel().getSelectedItems()); + Config.getInstance().getScoreStorageInterface().delete(selectedScores); + updateScoreTable(Config.getInstance().getScoreStorageInterface().getAll()); + } + + private void updateScoreTable(List<Score> scores) { this.scores.getItems().clear(); this.scores.getItems().addAll(scores); } @@ -103,12 +120,19 @@ public class MainScreenController { nickColumn.setCellValueFactory(new PropertyValueFactory<>("name")); pointsColumn.setCellValueFactory(new PropertyValueFactory<>("points")); - - initDB(); + difficultColumn.setCellValueFactory(new PropertyValueFactory<>("level")); + + btnDelete.setDisable(true); + scores.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); + scores.getSelectionModel().getSelectedItems() + .addListener((ListChangeListener.Change<? extends Score> change) -> + btnDelete.setDisable(change.getList().isEmpty())); + + initStorage(); log.info("Screeen initialized."); } - private void initDB() { + private void initStorage() { Config.getInstance().getScoreStorageInterface().init(); scores.getItems().addAll(Config.getInstance().getScoreStorageInterface().getAll()); } diff --git a/src/main/java/lab/storage/DbConnector.java b/src/main/java/lab/storage/DbConnector.java index 73cbefac399e59111cf39d0bb7271dc9423b5a1c..4b1e19084c83c05b136ef332e9addf755eb2b7b8 100644 --- a/src/main/java/lab/storage/DbConnector.java +++ b/src/main/java/lab/storage/DbConnector.java @@ -11,7 +11,6 @@ import java.util.List; import lab.data.Score; - public class DbConnector implements ScoreStorageInterface { private static final String JDBC_CONECTIN_STRING = "jdbc:h2:file:./scoreDB"; @@ -32,7 +31,7 @@ public class DbConnector implements ScoreStorageInterface { Statement stm = con.createStatement(); ResultSet rs = stm.executeQuery(query);) { while (rs.next()) { - result.add(new Score(rs.getString("nick"), rs.getInt("points"))); + result.add(new Score(null, rs.getString("nick"), rs.getInt("points"), null)); } } catch (SQLException e) { e.printStackTrace(); @@ -51,7 +50,7 @@ public class DbConnector implements ScoreStorageInterface { } @Override - public void insertScore(Score score) { + public Score save(Score score) { try (Connection con = DriverManager.getConnection(JDBC_CONECTIN_STRING); PreparedStatement stm = con.prepareStatement("INSERT INTO scores VALUES (?, ?)");) { stm.setString(1, score.getName()); @@ -60,5 +59,26 @@ public class DbConnector implements ScoreStorageInterface { } catch (SQLException e) { e.printStackTrace(); } + return score; + } + + @Override + public void delete(List<Score> scores) { + try (Connection con = DriverManager.getConnection(JDBC_CONECTIN_STRING); + PreparedStatement stm = con.prepareStatement("DELETE FROM scores WHERE nick=? AND points=?");) { + for (Score score : scores) { + stm.setString(1, score.getName()); + stm.setInt(2, score.getPoints()); + stm.executeUpdate(); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Override + public void stop() { + /*nothing to do*/ } + } diff --git a/src/main/java/lab/storage/FileStorage.java b/src/main/java/lab/storage/FileStorage.java index a3228c16a88a3dccaaecda85b3b38a1eb916f46f..828ca068af9f5b7539ab0dec4c62fedf417d4fc4 100644 --- a/src/main/java/lab/storage/FileStorage.java +++ b/src/main/java/lab/storage/FileStorage.java @@ -21,7 +21,7 @@ public class FileStorage implements ScoreStorageInterface { if (Files.exists(Paths.get(SCORE_FILE_NAME))) { try (Stream<String> lines = Files.lines(Paths.get(SCORE_FILE_NAME))) { List<Score> result = lines.map(line -> line.split(";")) - .map(parts -> new Score(parts[0], Integer.parseInt(parts[1]))).toList(); + .map(parts -> new Score(null, parts[0], Integer.parseInt(parts[1]), null)).toList(); return new ArrayList<>(result); } catch (IOException e) { e.printStackTrace(); @@ -43,14 +43,33 @@ public class FileStorage implements ScoreStorageInterface { } @Override - public void insertScore(Score score) { + public Score save(Score score) { List<Score> all = getAll(); all.add(score); + storeAll(all); + return score; + } + + private void storeAll(List<Score> all) { List<String> lines = all.stream().map(s -> String.format("%s;%d", s.getName(), s.getPoints())).toList(); try { - Files.write(Paths.get(SCORE_FILE_NAME), lines, StandardOpenOption.CREATE); + Files.write(Paths.get(SCORE_FILE_NAME), lines, StandardOpenOption.TRUNCATE_EXISTING); } catch (IOException e) { e.printStackTrace(); } } + + @Override + public void delete(List<Score> scores) { + List<Score> all = getAll(); + all.removeAll(scores); + storeAll(all); + + } + + @Override + public void stop() { + /*nothing to do*/ + } + } diff --git a/src/main/java/lab/storage/JpaConnector.java b/src/main/java/lab/storage/JpaConnector.java new file mode 100644 index 0000000000000000000000000000000000000000..b1f5bf10a6129abf829d8a7283603076b76a2e7d --- /dev/null +++ b/src/main/java/lab/storage/JpaConnector.java @@ -0,0 +1,54 @@ +package lab.storage; + +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; + +import lab.data.Score; + +public class JpaConnector implements ScoreStorageInterface { + + + public JpaConnector() { + } + + @Override + public List<Score> getAll() { + return Collections.emptyList(); + } + + @Override + public List<Score> getFirstTen() { + return Collections.emptyList(); + } + + @Override + public void init() { + } + + @Override + public Score save(Score score) { + return null; + } + + @Override + public void delete(List<Score> scores) { + } + + @Override + public void stop() { + } + + public Object getEntityManager() { + //return entity manager. Type Object is there because of compilation of empty task assignment + return null; + } + + public Score find(long id) { + return null; + } + + public void modifyNoPersistOrMerge(long id, Consumer<Score> motificator) { + } + +} diff --git a/src/main/java/lab/storage/ScoreStorageInterface.java b/src/main/java/lab/storage/ScoreStorageInterface.java index 67ee80d94e2662312f68642b923a0912aa5ae0fc..af8932ec4fbdf9ba3fe85d9649f2131f02edf461 100644 --- a/src/main/java/lab/storage/ScoreStorageInterface.java +++ b/src/main/java/lab/storage/ScoreStorageInterface.java @@ -12,6 +12,10 @@ public interface ScoreStorageInterface { void init(); - void insertScore(Score score); + Score save(Score score); + + void delete(List<Score> scores); + + void stop(); } \ No newline at end of file diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 3f19883afeb9b244845aa41b499a0f511f756af2..fd02eeaaf3377d964e9498062cafecd395c77bf0 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -5,6 +5,7 @@ module cz.vsb.fei.java2.lab03_module { requires java.sql; requires org.apache.logging.log4j; requires static lombok; + requires com.h2database; opens lab.gui to javafx.fxml; opens lab.data to javafx.base; diff --git a/src/main/resources/lab/gui/mainScreen.fxml b/src/main/resources/lab/gui/mainScreen.fxml index 768bc61a13c1ecf1e8135d1e077841f113433a7c..baafd114c23d33c64dbd87a7c20fd47c2f92c312 100644 --- a/src/main/resources/lab/gui/mainScreen.fxml +++ b/src/main/resources/lab/gui/mainScreen.fxml @@ -59,6 +59,7 @@ <columns> <TableColumn fx:id="nickColumn" prefWidth="75.0" text="Nick" /> <TableColumn fx:id="pointsColumn" prefWidth="75.0" text="Points" /> + <TableColumn fx:id="difficultColumn" prefWidth="75.0" text="Difficult" /> </columns> <columnResizePolicy> <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" /> @@ -67,6 +68,7 @@ <Button fx:id="btnGenerateScore" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#btnGenerateScoreAction" text="Generate new score" /> <Button fx:id="btnLoadAll" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#btnLoadAllAction" text="Load all from DB" /> <Button fx:id="btnLoadFirstTen" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#btnLoadFirstTenAction" text="Load first 10 from DB" /> + <Button fx:id="btnDelete" layoutX="10.0" layoutY="340.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#btnDeleteAction" text="Delete" /> </children> </VBox> </children>