From c8eaea665bd7318fe1b99a877706c96f395b3a93 Mon Sep 17 00:00:00 2001
From: koz01 <koz01@PCFEIB104-008.msad.vsb.cz>
Date: Wed, 16 Nov 2022 12:14:07 +0100
Subject: [PATCH] solution

---
 pom.xml                               |   9 +-
 src/main/java/lab/GameController.java |  22 ++---
 src/main/java/lab/Score.java          |  19 +++-
 src/main/java/lab/ScoreDAO.java       | 128 ++++++++++++++++++++++++++
 src/main/java/module-info.java        |   1 +
 5 files changed, 158 insertions(+), 21 deletions(-)
 create mode 100644 src/main/java/lab/ScoreDAO.java

diff --git a/pom.xml b/pom.xml
index 6bd5f99..3f573e8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,6 +1,4 @@
-<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">
+<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>vsb-cs-java1</groupId>
 	<artifactId>lab08</artifactId>
@@ -12,6 +10,11 @@
 		<maven.compiler.target>17</maven.compiler.target>
 	</properties>
 	<dependencies>
+		<dependency>
+			<groupId>org.apache.derby</groupId>
+			<artifactId>derby</artifactId>
+			<version>10.16.1.1</version>
+		</dependency>
 		<dependency>
 			<groupId>org.openjfx</groupId>
 			<artifactId>javafx-controls</artifactId>
diff --git a/src/main/java/lab/GameController.java b/src/main/java/lab/GameController.java
index 2fee0eb..d06114d 100644
--- a/src/main/java/lab/GameController.java
+++ b/src/main/java/lab/GameController.java
@@ -1,10 +1,6 @@
 	package lab;
 
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.io.FileWriter;
 import java.io.IOException;
-import java.io.PrintWriter;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.LinkedList;
@@ -51,10 +47,13 @@ public class GameController {
 	
 	private AnimationTimer animationTimer;
 	
+	private ScoreDAO scoreDAO;
+	
 	public GameController() {
 	}
 	
 	public void startGame() {
+		scoreDAO = new ScoreDAO();
 		initScoreList();
 
 		this.world = new World(canvas.getWidth(), canvas.getHeight());
@@ -110,24 +109,15 @@ public class GameController {
 
 	@FXML
 	private void savePressed() throws IOException {
-		try(PrintWriter pw = new PrintWriter(new FileWriter("high_score.csv"))){
-			for(Score score: highScores) {
-				pw.printf("%s;%d\n", score.getName(), score.getScore());
-			}
-		}
+		scoreDAO.save(highScores);
 	}
 	
 	
 	@FXML
 	private void loadPressed() throws IOException{
 		highScores.clear();
-		try(BufferedReader br = new BufferedReader(new FileReader("high_score.csv"))){
-			String line;
-			while(null != (line = br.readLine())) {
-				String [] tokens = line.split(";");
-				highScores.add(new Score(Integer.parseInt(tokens[1]), tokens[0]));
-			}
-		}
+		highScores.addAll(scoreDAO.load());
+		sortScores();
 		initScoreList();
 	}
 
diff --git a/src/main/java/lab/Score.java b/src/main/java/lab/Score.java
index e7f8bc7..a64c2b3 100644
--- a/src/main/java/lab/Score.java
+++ b/src/main/java/lab/Score.java
@@ -5,11 +5,18 @@ import java.io.Serializable;
 public class Score implements Serializable{
 	
 	private static final long serialVersionUID = 712213568495641939L;
-	
+	private Integer id;
 	private final int score;
 	private final String name;
+	
+	
 	public Score(int score, String name) {
-		super();
+		this(null, score, name);
+	}
+
+
+	public Score(Integer id, int score, String name) {
+		this.id = id;
 		this.score = score;
 		this.name = name;
 	}
@@ -22,6 +29,14 @@ public class Score implements Serializable{
 	public int getScore() {
 		return score;
 	}
+	
+	public Integer getId() {
+		return id;
+	}
+	
+	public void setId(Integer id) {
+		this.id = id;
+	}
 
 	@Override
 	public String toString() {
diff --git a/src/main/java/lab/ScoreDAO.java b/src/main/java/lab/ScoreDAO.java
new file mode 100644
index 0000000..8bfdc72
--- /dev/null
+++ b/src/main/java/lab/ScoreDAO.java
@@ -0,0 +1,128 @@
+package lab;
+
+import static java.util.stream.Collectors.toSet;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class ScoreDAO {
+
+	public ScoreDAO() {
+		
+		try (Connection conn = getConnection()) {
+			createTable(conn);
+		} catch (SQLException e) {
+			e.printStackTrace();
+		} 
+	}
+	
+	public List<Score> load( ){
+		List<Score> result = new LinkedList<>();
+		try(Connection con = getConnection(); Statement stmt = con.createStatement()) {
+			try(ResultSet rs = stmt.executeQuery("SELECT id, value, name FROM score")) {
+				while (rs.next()) {
+					result.add(new Score(rs.getInt(1), rs.getInt(2), rs.getString(3)));
+				}
+			}
+		} catch (SQLException e) {
+			e.printStackTrace();
+		}
+		return result ;
+	}
+	
+	public void save(List<Score> scores) {
+		
+		/*Set<Integer> m = new HashSet<>();
+		for (Score score: scores) {
+			if (score.getId() == null) {
+				continue;
+			}
+			m.add(score.getId());
+		}*/
+		Set<Integer> m = scores.stream()
+							   .filter(s -> s.getId() != null)
+							   .map(Score::getId)
+							   .collect(toSet());
+		Set<Integer> d = load().stream().map(Score::getId).collect(Collectors.toSet());
+		d.removeAll(m);
+		Set<Integer> idsOnlyInDB = d;
+		removeByIDS(idsOnlyInDB);
+		List<Score> scoreSaved = new LinkedList<>();
+		try (Connection con = getConnection(); 
+			 PreparedStatement pstmt = con.prepareStatement("INSERT INTO score (value, name) VALUES (?, ?)"
+					                                        , Statement.RETURN_GENERATED_KEYS)) {
+			for (Score score: scores) {
+				if (score.getId() != null) {
+					continue;
+				}
+				pstmt.setInt(1, score.getScore());
+				pstmt.setString(2, score.getName());
+				pstmt.addBatch();
+				scoreSaved.add(score);
+			}
+			if (!scoreSaved.isEmpty()) {
+				pstmt.executeBatch();
+				ResultSet rs =  pstmt.getGeneratedKeys();
+				Iterator<Score> iter = scoreSaved.iterator();
+				while (rs.next()) {
+					Score score = iter.next();
+					score.setId(rs.getInt(1));
+				}
+			}
+			
+		} catch (SQLException e) {
+			e.printStackTrace();
+		}
+	}
+
+	private void removeByIDS(Set<Integer> idsOnlyInDB) {
+		try(Connection con = getConnection(); 
+				PreparedStatement pstmt = con.prepareStatement("DELETE FROM score WHERE id = ?")) {
+
+			for (Integer id: idsOnlyInDB) {
+				pstmt.setInt(1, id);
+				pstmt.addBatch();
+			}
+			pstmt.executeBatch();
+		} catch (SQLException e) {
+			e.printStackTrace();
+		}
+		
+	}
+
+	private void createTable(Connection conn) {
+		try  (Statement stmt = conn.createStatement()){
+			stmt.execute("CREATE TABLE score ("
+						+ "id INT NOT NULL GENERATED ALWAYS AS IDENTITY, "
+						+ "value INT NOT NULL, "
+						+ "name VARCHAR(255) NOT NULL, "
+						+ "PRIMARY KEY (id)"
+						+ ")");
+		} catch (SQLException e) {
+			if (e.getSQLState().equals("X0Y32")) {
+				//ignore this because table exists
+				return;
+			}
+			e.printStackTrace();
+		}
+		
+	}
+
+	private Connection getConnection() {
+		try {
+			return DriverManager.getConnection("jdbc:derby:scoreDB;create=true");
+		} catch (SQLException e) {
+			e.printStackTrace();
+			return null;
+		}
+	}
+}
diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java
index 7006c78..94ff2e3 100644
--- a/src/main/java/module-info.java
+++ b/src/main/java/module-info.java
@@ -1,6 +1,7 @@
 module lab01 {
     requires transitive javafx.controls;
     requires javafx.fxml;
+    requires java.sql;
     opens lab to javafx.fxml;
     exports lab;
 }
\ No newline at end of file
-- 
GitLab