Fix: full FA refactor
This commit is contained in:
@@ -210,7 +210,7 @@ public class GameController {
|
|||||||
* Ends the game due to forfeit: all remaining players are absent,
|
* Ends the game due to forfeit: all remaining players are absent,
|
||||||
* so the game is terminated and final scores are computed.
|
* so the game is terminated and final scores are computed.
|
||||||
*/
|
*/
|
||||||
public synchronized void endGameForFeit() {
|
public synchronized void endGameForfeit() {
|
||||||
model.endGameForFeit();
|
model.endGameForfeit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ import java.util.stream.Collectors;
|
|||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* <p>This class is not thread-safe by itself: it relies on the caller
|
* <p>This class is not thread-safe by itself: it relies on the caller
|
||||||
* (the game loop in {@code ServerLauncherTest}) to drive it from a single
|
* (the game loop in {@code ServerLauncher}) to drive it from a single
|
||||||
* thread via {@link #doFirstEvent()}.
|
* thread via {@link #doFirstEvent()}.
|
||||||
*/
|
*/
|
||||||
public class GameEventProcessor {
|
public class GameEventProcessor {
|
||||||
@@ -40,9 +40,13 @@ public class GameEventProcessor {
|
|||||||
private final CompositeClientBroadcaster broadcaster;
|
private final CompositeClientBroadcaster broadcaster;
|
||||||
private final SaveManager saveManager;
|
private final SaveManager saveManager;
|
||||||
|
|
||||||
/** Single-thread executor used exclusively for the forfeit timer. */
|
/** Single-thread executor used exclusively for the forfeit timer. Daemon so it does not block JVM shutdown. */
|
||||||
private final ScheduledExecutorService timerExecutor =
|
private final ScheduledExecutorService timerExecutor =
|
||||||
Executors.newSingleThreadScheduledExecutor();
|
Executors.newSingleThreadScheduledExecutor(r -> {
|
||||||
|
Thread t = new Thread(r, "forfeit-timer");
|
||||||
|
t.setDaemon(true);
|
||||||
|
return t;
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle to the running forfeit timer, or {@code null} when no timer is active.
|
* Handle to the running forfeit timer, or {@code null} when no timer is active.
|
||||||
@@ -267,7 +271,7 @@ public class GameEventProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
disconnectionTimer = timerExecutor.schedule(
|
disconnectionTimer = timerExecutor.schedule(
|
||||||
() -> endGameForFeit(game),
|
() -> endGameForfeit(game),
|
||||||
1, TimeUnit.MINUTES
|
1, TimeUnit.MINUTES
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -278,9 +282,9 @@ public class GameEventProcessor {
|
|||||||
*
|
*
|
||||||
* @param game the game model captured when the timer was scheduled.
|
* @param game the game model captured when the timer was scheduled.
|
||||||
*/
|
*/
|
||||||
private void endGameForFeit(Game game) {
|
private void endGameForfeit(Game game) {
|
||||||
synchronized (gameController) {
|
synchronized (gameController) {
|
||||||
gameController.endGameForFeit();
|
gameController.endGameForfeit();
|
||||||
EndedGame forfeitEnd = new EndedGame(
|
EndedGame forfeitEnd = new EndedGame(
|
||||||
game.getSlotMap(), game.getOrderLogicCard(),
|
game.getSlotMap(), game.getOrderLogicCard(),
|
||||||
game.getCurrentState(), game.getPlayerStanding()
|
game.getCurrentState(), game.getPlayerStanding()
|
||||||
@@ -363,7 +367,7 @@ public class GameEventProcessor {
|
|||||||
List<String> toRemove = playerList.entrySet().stream()
|
List<String> toRemove = playerList.entrySet().stream()
|
||||||
.filter(e -> !e.getValue())
|
.filter(e -> !e.getValue())
|
||||||
.map(Map.Entry::getKey)
|
.map(Map.Entry::getKey)
|
||||||
.collect(Collectors.toList());
|
.toList();
|
||||||
toRemove.forEach(playerList::remove);
|
toRemove.forEach(playerList::remove);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
package it.polimi.ingsw.gc14;
|
package it.polimi.ingsw.gc14;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link LinkedHashMap} with a configurable size limit and an associated action.
|
* A {@link ConcurrentHashMap}-backed map with a configurable size limit and an associated action.
|
||||||
* When the number of elements reaches or exceeds the limit, the specified action is automatically triggered.
|
* When the number of elements reaches or exceeds the limit, the specified action is automatically triggered.
|
||||||
* This implementation is thread-safe.
|
* This implementation is thread-safe for {@code put}; callers that need compound operations must synchronize externally.
|
||||||
*
|
*
|
||||||
* @param <K> the type of keys maintained by this map.
|
* @param <K> the type of keys maintained by this map.
|
||||||
* @param <V> the type of mapped values.
|
* @param <V> the type of mapped values.
|
||||||
@@ -63,7 +62,7 @@ public class LimitedMap<K, V> implements Map<K, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public V remove(Object key) { return map.remove(key); }
|
public synchronized V remove(Object key) { return map.remove(key); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public V get(Object key) { return map.get(key); }
|
public V get(Object key) { return map.get(key); }
|
||||||
@@ -112,7 +111,10 @@ public class LimitedMap<K, V> implements Map<K, V> {
|
|||||||
/**
|
/**
|
||||||
* Sets a new action to execute when the map size reaches or exceeds the limit.
|
* Sets a new action to execute when the map size reaches or exceeds the limit.
|
||||||
*
|
*
|
||||||
* @param action the new action to set.
|
* @param action the new action to set; must not be {@code null}.
|
||||||
*/
|
*/
|
||||||
public void setAction(Runnable action) { this.action = action; }
|
public void setAction(Runnable action) {
|
||||||
|
if (action == null) throw new IllegalArgumentException("action must not be null");
|
||||||
|
this.action = action;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1006,7 +1006,7 @@ public class Game implements Serializable {
|
|||||||
* in the first position of the final ranking. The remaining players are
|
* in the first position of the final ranking. The remaining players are
|
||||||
* ordered by prestige value and, in case of a tie, by food value.
|
* ordered by prestige value and, in case of a tie, by food value.
|
||||||
*/
|
*/
|
||||||
public synchronized void endGameForFeit() {
|
public synchronized void endGameForfeit() {
|
||||||
Player winner = playersList.stream()
|
Player winner = playersList.stream()
|
||||||
.filter(x -> !disconnectedPlayers.containsKey(x) || !disconnectedPlayers.get(x))
|
.filter(x -> !disconnectedPlayers.containsKey(x) || !disconnectedPlayers.get(x))
|
||||||
.findFirst().orElse(null);
|
.findFirst().orElse(null);
|
||||||
|
|||||||
@@ -2,7 +2,14 @@ package it.polimi.ingsw.gc14;
|
|||||||
|
|
||||||
import it.polimi.ingsw.gc14.Model.Game;
|
import it.polimi.ingsw.gc14.Model.Game;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.ObjectInputStream;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@@ -55,8 +62,8 @@ public class SaveManager {
|
|||||||
public boolean save(Game game) {
|
public boolean save(Game game) {
|
||||||
try {
|
try {
|
||||||
Files.createDirectories(filePath.getParent());
|
Files.createDirectories(filePath.getParent());
|
||||||
try (ObjectOutputStream oos =
|
try (ObjectOutputStream oos = new ObjectOutputStream(
|
||||||
new ObjectOutputStream(new FileOutputStream(filePath.toFile()))) {
|
new BufferedOutputStream(new FileOutputStream(filePath.toFile())))) {
|
||||||
oos.writeObject(game);
|
oos.writeObject(game);
|
||||||
System.out.println("Game saved to: " + filePath.toAbsolutePath());
|
System.out.println("Game saved to: " + filePath.toAbsolutePath());
|
||||||
return true;
|
return true;
|
||||||
@@ -76,8 +83,8 @@ public class SaveManager {
|
|||||||
* the classpath (indicates a deployment mismatch).
|
* the classpath (indicates a deployment mismatch).
|
||||||
*/
|
*/
|
||||||
public Game load() {
|
public Game load() {
|
||||||
try (ObjectInputStream ois =
|
try (ObjectInputStream ois = new ObjectInputStream(
|
||||||
new ObjectInputStream(new FileInputStream(filePath.toFile()))) {
|
new BufferedInputStream(new FileInputStream(filePath.toFile())))) {
|
||||||
return (Game) ois.readObject();
|
return (Game) ois.readObject();
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
return null;
|
return null;
|
||||||
@@ -97,8 +104,7 @@ public class SaveManager {
|
|||||||
*/
|
*/
|
||||||
public boolean delete() {
|
public boolean delete() {
|
||||||
try {
|
try {
|
||||||
Files.delete(filePath);
|
return Files.deleteIfExists(filePath);
|
||||||
return true;
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user