commit
71124dab2a
|
@ -4,36 +4,54 @@ import java.io.BufferedReader;
|
|||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CSVReader {
|
||||
|
||||
/**
|
||||
* Liest die CSV-Datei ein und gibt die enthaltenen Werte als zweidimensionales int-Array zurück.
|
||||
*
|
||||
* @param csvFile Pfad zur CSV-Datei
|
||||
* @return zweidimensionales Array, das die Zahlen aus der CSV enthält
|
||||
* @throws IOException wenn ein Fehler beim Lesen auftritt
|
||||
*/
|
||||
public int[][] readCsvToIntArray(String csvFile) throws IOException {
|
||||
ArrayList<int[]> rows = new ArrayList<>();
|
||||
public PuzzleData readPuzzleWithSolution(String csvFile) throws IOException {
|
||||
List<int[]> puzzleRows = new ArrayList<>();
|
||||
List<int[]> solutionCoordinates = new ArrayList<>();
|
||||
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(csvFile))) {
|
||||
String line;
|
||||
boolean inSolutionPart = false;
|
||||
|
||||
while ((line = br.readLine()) != null) {
|
||||
String[] tokens = line.split(",");
|
||||
int[] row = new int[tokens.length];
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
row[i] = Integer.parseInt(tokens[i].trim());
|
||||
line = line.trim();
|
||||
if (line.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (line.startsWith("//Lösung") || line.startsWith("//")) {
|
||||
inSolutionPart = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!inSolutionPart) {
|
||||
// Puzzle-Teil
|
||||
String[] tokens = line.split(",");
|
||||
int[] rowValues = new int[tokens.length];
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
rowValues[i] = Integer.parseInt(tokens[i].trim());
|
||||
}
|
||||
puzzleRows.add(rowValues);
|
||||
} else {
|
||||
// Lösungsteil
|
||||
String[] coords = line.split(",");
|
||||
if (coords.length == 2) {
|
||||
int row = Integer.parseInt(coords[0].trim());
|
||||
int col = Integer.parseInt(coords[1].trim());
|
||||
solutionCoordinates.add(new int[]{row, col});
|
||||
}
|
||||
}
|
||||
rows.add(row);
|
||||
}
|
||||
}
|
||||
|
||||
// ArrayList in 2D-Array umwandeln
|
||||
int[][] result = new int[rows.size()][];
|
||||
for (int i = 0; i < rows.size(); i++) {
|
||||
result[i] = rows.get(i);
|
||||
// puzzleRows -> 2D-Array
|
||||
int[][] puzzleArray = new int[puzzleRows.size()][];
|
||||
for (int i = 0; i < puzzleRows.size(); i++) {
|
||||
puzzleArray[i] = puzzleRows.get(i);
|
||||
}
|
||||
return result;
|
||||
|
||||
return new PuzzleData(puzzleArray, solutionCoordinates);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package de.deversmann.domain;
|
||||
|
||||
public class HighscoreEntry {
|
||||
|
||||
private final String playerName;
|
||||
private final long timeSeconds;
|
||||
private final int errorCount;
|
||||
|
||||
public HighscoreEntry(String playerName, long timeSeconds, int errorCount) {
|
||||
this.playerName = playerName;
|
||||
this.timeSeconds = timeSeconds;
|
||||
this.errorCount = errorCount;
|
||||
}
|
||||
|
||||
public String getPlayerName() {
|
||||
return playerName;
|
||||
}
|
||||
|
||||
public long getTimeSeconds() {
|
||||
return timeSeconds;
|
||||
}
|
||||
|
||||
public int getErrorCount() {
|
||||
return errorCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return playerName + " - " + timeSeconds + "s (Fehler: " + errorCount + ")";
|
||||
}
|
||||
}
|
|
@ -4,17 +4,99 @@ import java.io.*;
|
|||
import java.util.*;
|
||||
|
||||
public class HighscoreManager {
|
||||
private List<Integer> highscores
|
||||
|
||||
private Map<String, List<HighscoreEntry>> highscoreMap;
|
||||
|
||||
public HighscoreManager() {
|
||||
this.highscores = new ArrayList<>();
|
||||
this.highscoreMap = new HashMap<>();
|
||||
}
|
||||
|
||||
public void addHighscore(int score) {
|
||||
highscores.add(score);
|
||||
public void addHighscore(String puzzleName, String playerName, long timeSeconds, int errorCount) {
|
||||
highscoreMap.putIfAbsent(puzzleName, new ArrayList<>());
|
||||
highscoreMap.get(puzzleName).add(new HighscoreEntry(playerName, timeSeconds, errorCount));
|
||||
}
|
||||
|
||||
public List<Integer> getHighscores() {
|
||||
return new ArrayList<>(highscores);
|
||||
public List<HighscoreEntry> getHighscores(String puzzleName) {
|
||||
return highscoreMap.getOrDefault(puzzleName, Collections.emptyList());
|
||||
}
|
||||
|
||||
public double getAverageTime(String puzzleName) {
|
||||
List<HighscoreEntry> entries = highscoreMap.get(puzzleName);
|
||||
if (entries == null || entries.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
long sum = 0;
|
||||
for (HighscoreEntry e : entries) {
|
||||
sum += e.getTimeSeconds();
|
||||
}
|
||||
return (double) sum / entries.size();
|
||||
}
|
||||
|
||||
public void saveSinglePuzzle(String puzzleName, String filename) throws IOException {
|
||||
List<HighscoreEntry> entries = getHighscores(puzzleName);
|
||||
|
||||
entries.sort(Comparator
|
||||
.comparingInt(HighscoreEntry::getErrorCount)
|
||||
.thenComparingLong(HighscoreEntry::getTimeSeconds));
|
||||
|
||||
double avgTime = getAverageTime(puzzleName);
|
||||
|
||||
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filename))) {
|
||||
if (avgTime < 0) {
|
||||
writer.write("Durchschnittszeit: Keine Einträge");
|
||||
} else {
|
||||
writer.write(String.format("Durchschnittszeit: %.2f s", avgTime));
|
||||
}
|
||||
writer.newLine();
|
||||
writer.newLine();
|
||||
|
||||
writer.write(String.format("%-6s | %-5s | %-6s | %-15s",
|
||||
"Platz", "Zeit", "Fehler", "Name"));
|
||||
writer.newLine();
|
||||
writer.write("------------------------------------------------------------");
|
||||
writer.newLine();
|
||||
|
||||
int place = 1;
|
||||
for (HighscoreEntry e : entries) {
|
||||
writer.write(String.format("%-6s | %-5d | %-6d | %-15s",
|
||||
place + ".",
|
||||
e.getTimeSeconds(),
|
||||
e.getErrorCount(),
|
||||
e.getPlayerName()));
|
||||
writer.newLine();
|
||||
place++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void loadSinglePuzzle(String puzzleName, String filename) throws IOException {
|
||||
File file = new File(filename);
|
||||
if (!file.exists()) {
|
||||
System.out.println("Highscore-Datei " + filename + " existiert nicht; wird neu erstellt.");
|
||||
return;
|
||||
}
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
|
||||
// Durchschnittszeit und Header überspringen
|
||||
reader.readLine();
|
||||
reader.readLine();
|
||||
reader.readLine();
|
||||
reader.readLine();
|
||||
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
String[] parts = line.split("\\|");
|
||||
if (parts.length < 4) continue;
|
||||
|
||||
String timeStr = parts[1].trim();
|
||||
String errorStr = parts[2].trim();
|
||||
String nameStr = parts[3].trim();
|
||||
|
||||
long timeSeconds = Long.parseLong(timeStr);
|
||||
int errorCount = Integer.parseInt(errorStr);
|
||||
|
||||
addHighscore(puzzleName, nameStr, timeSeconds, errorCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package de.deversmann.domain;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PuzzleData {
|
||||
|
||||
private final int[][] puzzle;
|
||||
private final List<int[]> solutionCoordinates;
|
||||
|
||||
public PuzzleData(int[][] puzzle, List<int[]> solutionCoordinates) {
|
||||
this.puzzle = puzzle;
|
||||
this.solutionCoordinates = solutionCoordinates;
|
||||
}
|
||||
|
||||
public int[][] getPuzzle() {
|
||||
return puzzle;
|
||||
}
|
||||
|
||||
public List<int[]> getSolutionCoordinates() {
|
||||
return solutionCoordinates;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,101 @@
|
|||
package de.deversmann.facade;
|
||||
|
||||
import de.deversmann.domain.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
public class Facade {
|
||||
|
||||
private final CSVReader csvReader;
|
||||
private final HighscoreManager highscoreManager;
|
||||
private final Zeiterfassung zeiterfassung;
|
||||
|
||||
private PuzzleData currentPuzzleData;
|
||||
private String currentPuzzleName;
|
||||
private int currentErrorCount = 0;
|
||||
|
||||
public Facade() {
|
||||
this.csvReader = new CSVReader();
|
||||
this.highscoreManager = new HighscoreManager();
|
||||
this.zeiterfassung = new Zeiterfassung();
|
||||
}
|
||||
|
||||
public void ladeSpielfeld(String csvPfad) throws IOException {
|
||||
this.currentPuzzleData = csvReader.readPuzzleWithSolution(csvPfad);
|
||||
this.currentPuzzleName = csvPfad;
|
||||
this.currentErrorCount = 0;
|
||||
|
||||
zeiterfassung.stop();
|
||||
zeiterfassung.start();
|
||||
System.out.println("Neues Spielfeld geladen, Timer + Fehler=0");
|
||||
}
|
||||
|
||||
public long stopZeiterfassung() {
|
||||
zeiterfassung.stop();
|
||||
return zeiterfassung.getElapsedTimeInSeconds();
|
||||
}
|
||||
|
||||
public long getElapsedTimeSoFar() {
|
||||
return zeiterfassung.getElapsedTimeInSeconds();
|
||||
}
|
||||
|
||||
public int[][] getAktuellesPuzzle() {
|
||||
return (currentPuzzleData != null) ? currentPuzzleData.getPuzzle() : null;
|
||||
}
|
||||
|
||||
public List<int[]> getLoesungsKoordinaten() {
|
||||
return (currentPuzzleData != null) ? currentPuzzleData.getSolutionCoordinates() : null;
|
||||
}
|
||||
|
||||
// Fehler-Tracking
|
||||
public void incrementErrorCount() {
|
||||
currentErrorCount++;
|
||||
}
|
||||
|
||||
public int getCurrentErrorCount() {
|
||||
return currentErrorCount;
|
||||
}
|
||||
|
||||
// Highscore
|
||||
public void addHighscoreForCurrentPuzzle(String playerName, long timeSeconds, int errorCount) {
|
||||
if (currentPuzzleName != null && !currentPuzzleName.isEmpty()) {
|
||||
highscoreManager.addHighscore(currentPuzzleName, playerName, timeSeconds, errorCount);
|
||||
}
|
||||
}
|
||||
|
||||
public List<HighscoreEntry> getHighscoresForCurrentPuzzle() {
|
||||
if (currentPuzzleName == null) {
|
||||
return List.of();
|
||||
}
|
||||
return highscoreManager.getHighscores(currentPuzzleName);
|
||||
}
|
||||
|
||||
public double getAverageTimeForCurrentPuzzle() {
|
||||
if (currentPuzzleName == null) {
|
||||
return -1;
|
||||
}
|
||||
return highscoreManager.getAverageTime(currentPuzzleName);
|
||||
}
|
||||
|
||||
public String getCurrentPuzzleName() {
|
||||
return currentPuzzleName;
|
||||
}
|
||||
|
||||
public void saveCurrentPuzzleHighscoreToFile() throws IOException {
|
||||
if (currentPuzzleName == null) return;
|
||||
String base = currentPuzzleName.replaceAll(".*/", "");
|
||||
String shortName = base.replace(".csv", "") + "_highscore.txt";
|
||||
highscoreManager.saveSinglePuzzle(currentPuzzleName, shortName);
|
||||
System.out.println("Highscore zu " + base + " in " + shortName + " gespeichert.");
|
||||
}
|
||||
|
||||
|
||||
public void loadCurrentPuzzleHighscoreFromFile() throws IOException {
|
||||
if (currentPuzzleName == null) return;
|
||||
String base = currentPuzzleName.replaceAll(".*/", "");
|
||||
String shortName = base.replace(".csv", "") + "_highscore.txt";
|
||||
highscoreManager.loadSinglePuzzle(currentPuzzleName, shortName);
|
||||
System.out.println("Highscore zu " + base + " aus " + shortName + " geladen (falls existiert).");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue