FIx: Fixed Coverage Screenshots And htmlRepot.
This commit is contained in:
@@ -0,0 +1,335 @@
|
||||
|
||||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html id="htmlId">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
|
||||
<title>Coverage Report > ServerLauncher</title>
|
||||
<style type="text/css">
|
||||
@import "../../css/coverage.css";
|
||||
@import "../../css/idea.min.css";
|
||||
</style>
|
||||
<script type="text/javascript" src="../../js/highlight.min.js"></script>
|
||||
<script type="text/javascript" src="../../js/highlightjs-line-numbers.min.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="content">
|
||||
<div class="breadCrumbs">
|
||||
Current scope: <a href="../../index.html">all classes</a>
|
||||
<span class="separator">|</span>
|
||||
<a href="../index.html">it.polimi.ingsw.gc14</a>
|
||||
</div>
|
||||
|
||||
<h1>Coverage Summary for Class: ServerLauncher (it.polimi.ingsw.gc14)</h1>
|
||||
|
||||
<table class="coverageStats">
|
||||
<tr>
|
||||
<th class="name">Class</th>
|
||||
<th class="coverageStat
|
||||
">
|
||||
Class, %
|
||||
</th>
|
||||
<th class="coverageStat
|
||||
">
|
||||
Method, %
|
||||
</th>
|
||||
<th class="coverageStat
|
||||
">
|
||||
Branch, %
|
||||
</th>
|
||||
<th class="coverageStat
|
||||
">
|
||||
Line, %
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name">ServerLauncher</td>
|
||||
<td class="coverageStat">
|
||||
<span class="percent">
|
||||
0%
|
||||
</span>
|
||||
<span class="absValue">
|
||||
(0/1)
|
||||
</span>
|
||||
</td>
|
||||
<td class="coverageStat">
|
||||
<span class="percent">
|
||||
0%
|
||||
</span>
|
||||
<span class="absValue">
|
||||
(0/8)
|
||||
</span>
|
||||
</td>
|
||||
<td class="coverageStat">
|
||||
<span class="percent">
|
||||
0%
|
||||
</span>
|
||||
<span class="absValue">
|
||||
(0/24)
|
||||
</span>
|
||||
</td>
|
||||
<td class="coverageStat">
|
||||
<span class="percent">
|
||||
0%
|
||||
</span>
|
||||
<span class="absValue">
|
||||
(0/71)
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
|
||||
<pre>
|
||||
<code class="sourceCode" id="sourceCode"> package it.polimi.ingsw.gc14;
|
||||
|
||||
import it.polimi.ingsw.gc14.Controller.GameController;
|
||||
import it.polimi.ingsw.gc14.Model.Game;
|
||||
import it.polimi.ingsw.gc14.Model.MiniModel;
|
||||
import it.polimi.ingsw.gc14.Model.Player;
|
||||
import it.polimi.ingsw.gc14.Network.CompositeClientBroadcaster;
|
||||
import it.polimi.ingsw.gc14.Network.NetworkEvent;
|
||||
import it.polimi.ingsw.gc14.Network.RMI.Server.RMIServer;
|
||||
import it.polimi.ingsw.gc14.Network.NetworkConfig;
|
||||
import it.polimi.ingsw.gc14.Network.TCP.Server.TCPServer;
|
||||
|
||||
import java.net.*;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Main server entry point.
|
||||
*
|
||||
* <p>Responsibilities of this class are intentionally limited to wiring:
|
||||
* it creates all components, connects them together, restores a previously
|
||||
* saved game if one exists, and starts the event-processing loop and the
|
||||
* network servers.
|
||||
*
|
||||
* <p>All game-logic and event-routing decisions are delegated to
|
||||
* {@link GameEventProcessor}; persistence is delegated to {@link SaveManager}.
|
||||
*
|
||||
* <p>The original {@code ServerLauncher} class is preserved and untouched.
|
||||
* This class is a clean replacement that uses the new component structure.
|
||||
*/
|
||||
public class ServerLauncher {
|
||||
|
||||
/** Drives the main game-event loop. */
|
||||
private final GameEventProcessor eventProcessor;
|
||||
|
||||
/**
|
||||
* Constructs a {@code ServerLauncherTest} and wires all components together.
|
||||
*
|
||||
* @param actionQueue the shared event queue.
|
||||
* @param gameController the server-side game controller.
|
||||
* @param playerList the shared player-status map.
|
||||
* @param broadcaster the broadcaster used to reach all connected clients.
|
||||
* @param saveManager the save manager used to persist game state.
|
||||
*/
|
||||
public ServerLauncher(
|
||||
BlockingQueue<NetworkEvent> actionQueue,
|
||||
GameController gameController,
|
||||
LimitedMap<String, Boolean> playerList,
|
||||
CompositeClientBroadcaster broadcaster,
|
||||
<b class="nc"> SaveManager saveManager) {</b>
|
||||
<b class="nc"> this.eventProcessor = new GameEventProcessor(</b>
|
||||
actionQueue, gameController, playerList, broadcaster, saveManager);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initializes all server components, wires them together, restores a saved
|
||||
* game if available, and starts the event-processing loop and both network
|
||||
* servers.
|
||||
*
|
||||
* @param args command-line arguments (unused).
|
||||
* @throws RemoteException if the RMI server cannot be created.
|
||||
*/
|
||||
static void main(String[] args) throws RemoteException {
|
||||
<b class="nc"> LimitedMap<String, Boolean> playerList = new LimitedMap<>(5, () -> {});</b>
|
||||
<b class="nc"> BlockingQueue<NetworkEvent> actionQueue = new LinkedBlockingQueue<>();</b>
|
||||
<b class="nc"> GameController gameController = new GameController();</b>
|
||||
|
||||
String ip;
|
||||
try {
|
||||
<b class="nc"> ip = chooseNetworkInterface(new Scanner(System.in));</b>
|
||||
<b class="nc"> System.out.println(ip);</b>
|
||||
} catch (Exception e) {
|
||||
<b class="nc"> throw new RuntimeException(e);</b>
|
||||
}
|
||||
<b class="nc"> System.setProperty("java.rmi.server.hostname", ip);</b>
|
||||
|
||||
<b class="nc"> RMIServer rmiServer = new RMIServer(gameController, NetworkConfig.RMI_PORT, actionQueue, playerList, ip);</b>
|
||||
<b class="nc"> TCPServer tcpServer = new TCPServer(gameController, NetworkConfig.TCP_PORT, NetworkConfig.HEARTBEAT_PORT, actionQueue, playerList);</b>
|
||||
<b class="nc"> CompositeClientBroadcaster broadcaster = new CompositeClientBroadcaster(rmiServer, tcpServer);</b>
|
||||
<b class="nc"> SaveManager saveManager = new SaveManager(ServerLauncher.class);</b>
|
||||
|
||||
<b class="nc"> restoreGameIfSaved(gameController, playerList, saveManager);</b>
|
||||
|
||||
<b class="nc"> ServerLauncher launcher = new ServerLauncher(</b>
|
||||
actionQueue, gameController, playerList, broadcaster, saveManager);
|
||||
|
||||
// When all required players have joined, broadcast the initial MiniModel.
|
||||
<b class="nc"> playerList.setAction(() -> new Thread(() -> {</b>
|
||||
MiniModel miniModel;
|
||||
<b class="nc"> synchronized (gameController) {</b>
|
||||
<b class="nc"> Game game = gameController.getModel();</b>
|
||||
<b class="nc"> miniModel = new MiniModel(</b>
|
||||
<b class="nc"> game.getSlotMap(), game.getOrderLogicCard(), game.getCurrentState(),</b>
|
||||
<b class="nc"> game.getPlayers(), game.getAvailableTotems(),</b>
|
||||
<b class="nc"> game.getUpperListTribeCards(), game.getLowerListTribeCards(),</b>
|
||||
<b class="nc"> game.getUpperListBuilding(), game.getLowerListBuilding(),</b>
|
||||
<b class="nc"> game.getDisconnectedPlayers().entrySet().stream()</b>
|
||||
<b class="nc"> .filter(Map.Entry::getValue)</b>
|
||||
<b class="nc"> .map(e -> e.getKey().getUserName())</b>
|
||||
<b class="nc"> .collect(Collectors.toCollection(ArrayList::new))</b>
|
||||
);
|
||||
<b class="nc"> }</b>
|
||||
<b class="nc"> broadcaster.notifyAll(miniModel);</b>
|
||||
<b class="nc"> }).start());</b>
|
||||
|
||||
<b class="nc"> new Thread(() -> {</b>
|
||||
<b class="nc"> try { launcher.run(); }</b>
|
||||
catch (Exception e) {
|
||||
<b class="nc"> System.out.println("Unexpected exception in game loop");</b>
|
||||
<b class="nc"> e.printStackTrace();</b>
|
||||
}
|
||||
<b class="nc"> }).start();</b>
|
||||
|
||||
<b class="nc"> rmiServer.start();</b>
|
||||
<b class="nc"> new Thread(() -> tcpServer.start()).start();</b>
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs the event-processing loop until the thread is interrupted.
|
||||
*
|
||||
* <p>A {@link ConcurrentModificationException} is caught and logged rather
|
||||
*/
|
||||
public void run() {
|
||||
while (true) {
|
||||
try {
|
||||
<b class="nc"> eventProcessor.doFirstEvent();</b>
|
||||
} catch (InterruptedException e) {
|
||||
<b class="nc"> Thread.currentThread().interrupt();</b>
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Attempts to restore a previously saved game.
|
||||
*
|
||||
* <p>The save is discarded if all but at most one player was offline at the
|
||||
* time of the crash, since there would be nobody to resume the game with.
|
||||
* Otherwise, the model is restored, the player-list limit is set, and each
|
||||
* player who was offline at crash time is pre-populated as offline so the
|
||||
* reconnection flow can handle them correctly.
|
||||
*
|
||||
* @param gameController the controller that will receive the restored model.
|
||||
* @param playerList the player-status map to populate.
|
||||
* @param saveManager the save manager to load from.
|
||||
*/
|
||||
private static void restoreGameIfSaved(
|
||||
GameController gameController,
|
||||
LimitedMap<String, Boolean> playerList,
|
||||
SaveManager saveManager) {
|
||||
|
||||
<b class="nc"> Game game = saveManager.load();</b>
|
||||
<b class="nc"> if (game == null) return;</b>
|
||||
|
||||
<b class="nc"> long disconnectedCount = game.getDisconnectedPlayers().entrySet().stream()</b>
|
||||
<b class="nc"> .filter(Map.Entry::getValue).count();</b>
|
||||
|
||||
<b class="nc"> if (disconnectedCount >= game.getNPlayers() - 1) {</b>
|
||||
<b class="nc"> saveManager.delete();</b>
|
||||
<b class="nc"> System.out.println("Save discarded: too many players were offline at crash time.");</b>
|
||||
return;
|
||||
}
|
||||
|
||||
<b class="nc"> gameController.setModel(game);</b>
|
||||
<b class="nc"> playerList.setLimit(game.getNPlayers());</b>
|
||||
|
||||
<b class="nc"> for (Map.Entry<Player, Boolean> entry : game.getDisconnectedPlayers().entrySet()) {</b>
|
||||
<b class="nc"> if (entry.getValue()) {</b>
|
||||
<b class="nc"> playerList.put(entry.getKey().getUserName(), false);</b>
|
||||
}
|
||||
}
|
||||
<b class="nc"> System.out.println("Game restored from save (" + game.getNPlayers() + " players).");</b>
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Lists active non-loopback IPv4 network interfaces and prompts the operator
|
||||
* to choose one. If only one interface is available it is selected automatically.
|
||||
*
|
||||
* @param scanner the scanner used to read the operator's choice.
|
||||
* @return the IPv4 address of the selected interface.
|
||||
* @throws Exception if no valid network interface is available.
|
||||
*/
|
||||
public static String chooseNetworkInterface(Scanner scanner) throws Exception {
|
||||
<b class="nc"> List<String> ips = new ArrayList<>();</b>
|
||||
|
||||
<b class="nc"> Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();</b>
|
||||
<b class="nc"> while (interfaces.hasMoreElements()) {</b>
|
||||
<b class="nc"> NetworkInterface ni = interfaces.nextElement();</b>
|
||||
<b class="nc"> if (!ni.isUp() || ni.isLoopback() || ni.isVirtual()) continue;</b>
|
||||
|
||||
<b class="nc"> Enumeration<InetAddress> addresses = ni.getInetAddresses();</b>
|
||||
<b class="nc"> while (addresses.hasMoreElements()) {</b>
|
||||
<b class="nc"> InetAddress addr = addresses.nextElement();</b>
|
||||
<b class="nc"> if (addr instanceof Inet4Address) {</b>
|
||||
<b class="nc"> System.out.println("[" + ips.size() + "] " + ni.getDisplayName()</b>
|
||||
<b class="nc"> + " -> " + addr.getHostAddress());</b>
|
||||
<b class="nc"> ips.add(addr.getHostAddress());</b>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<b class="nc"> if (ips.isEmpty()) throw new Exception("No active network interface available");</b>
|
||||
|
||||
<b class="nc"> if (ips.size() == 1) {</b>
|
||||
<b class="nc"> System.out.println("One interface found, using: " + ips.get(0));</b>
|
||||
<b class="nc"> return ips.get(0);</b>
|
||||
}
|
||||
|
||||
<b class="nc"> System.out.print("Choose interface: ");</b>
|
||||
<b class="nc"> int choice = Integer.parseInt(scanner.nextLine().trim());</b>
|
||||
<b class="nc"> return ips.get(choice);</b>
|
||||
}
|
||||
}
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
(function() {
|
||||
var msie = false, msie9 = false;
|
||||
/*@cc_on
|
||||
msie = true;
|
||||
@if (@_jscript_version >= 9)
|
||||
msie9 = true;
|
||||
@end
|
||||
@*/
|
||||
|
||||
if (!msie || msie && msie9) {
|
||||
hljs.highlightAll()
|
||||
hljs.initLineNumbersOnLoad();
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
<div class="footer">
|
||||
|
||||
<div style="float:right;">generated on 2026-06-19 22:53</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user