<commit_before>package es.ucm.fdi.tp.control.multiplayer;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import com.sun.istack.internal.NotNull;

import es.ucm.fdi.tp.basecode.bgame.control.Controller;
import es.ucm.fdi.tp.basecode.bgame.control.GameFactory;
import es.ucm.fdi.tp.basecode.bgame.control.Player;
import es.ucm.fdi.tp.basecode.bgame.control.commands.Command;
import es.ucm.fdi.tp.basecode.bgame.model.Board;
import es.ucm.fdi.tp.basecode.bgame.model.Game;
import es.ucm.fdi.tp.basecode.bgame.model.Game.State;
import es.ucm.fdi.tp.basecode.bgame.model.GameError;
import es.ucm.fdi.tp.basecode.bgame.model.GameObserver;
import es.ucm.fdi.tp.basecode.bgame.model.Piece;
import es.ucm.fdi.tp.control.multiplayer.Responses.*;

public class GameServer extends Controller implements GameObserver {
	
	private List<Connection> clients;
	volatile private ServerSocket server;
	private int port;
	
	private NetObserver view;
	
	volatile private boolean stopped;
	volatile private boolean gameOver;
	
	public static int REQUIRED_PLAYERS = 4;
	
	private int nPlayers = 0;
	private GameFactory gameFactorry;
	private List<Piece> pieces;
	
	public GameServer(GameFactory factory, List<Piece> pieces, int port) {
		super(new Game(factory.gameRules()), pieces);
		this.clients = new ArrayList<Connection>();
		
		this.gameFactorry = factory;
		this.pieces = pieces;
		
		this.port = port;
		
		game.addObserver(this);
	}
	
	private void startClientListener(Connection c) throws IOException {
		this.gameOver = false;
		c.sendObject(gameFactorry);
		c.sendObject(pieces);
		Thread t = new Thread() {
			@Override
			public void run() {
				while (!stopped && !gameOver) {
					try {
						Command cmd = (Command) c.getObject();
						cmd.execute(GameServer.this);
					} catch (ClassNotFoundException | ClassCastException | IOException e) {
						if (!stopped && !gameOver) {
							GameServer.this.stop();
						}
					}
				}
			}
		};
		
		t.start();
		
		view.onPlayerConnected(pieces.get(nPlayers-1));
	}
	
	public int playersConnected() {
		return nPlayers;
	}
	
	private void startServer()  {
		Socket soc;
		try {
			this.server = new ServerSocket(port);
			view.onServerOpened(game.gameDesc());
			this.stopped = false;
			
		} catch (IOException e) {
			view.log("Error opening the server");
			System.err.println("Error opening the server: " + e.getMessage());
			view.onServerClosed();
			this.stopped = true;
		}
		
		this.stopped = false;
		
		while(!this.stopped) {
			try {
				soc = server.accept();
				handleRequest(soc);
				
			} catch (IOException e) {
				if(!this.stopped){
					view.log("Error while waiting for a connection");
					System.err.println("Error while waiting for a connection: " + e.getMessage());
				}
			}
		}
		try {
			server.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private void handleRequest(Socket s) {
		try {
			Connection c = new Connection(s);
			Object clientRequest = c.getObject();
			
			if(!(clientRequest instanceof String) &&
					!((String) clientRequest).equalsIgnoreCase("Connect") ) {
				c.sendObject(new GameError("Invalid Request"));
				c.stop();
				return;
			}
			if(nPlayers >= REQUIRED_PLAYERS) {
				c.sendObject(new GameError("Room is already full"));
				c.stop();
				view.log("A client connection was refused: Maximum players connections reached ");
				return;
			}
			
			nPlayers++;
			clients.add(c);
			view.log("new player into to room");
			c.sendObject("OK");
			c.sendObject(this.gameFactorry);
			c.sendObject(this.pieces.get(nPlayers-1));
			if(nPlayers >= REQUIRED_PLAYERS)
				startGame();
			
			startClientListener(c);
			
		} catch (IOException | ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	private void startGame() {
		if(game.getState() == State.Starting)
			game.start(pieces);
		else
			game.restart();
	}
	
	public void setView(@NotNull NetObserver o) {
		this.view = o;
	}
	
	@Override
	public synchronized void makeMove(Player p) {
		try {
			super.makeMove(p);
		} catch (GameError e) {
			view.log(e.getMessage());
		}
	}
	
	@Override
	public synchronized void restart() {
		try {
			super.restart();
		} catch (GameError e) {
			view.log(e.getMessage());
		}
	}
	
	@Override
	public synchronized void stop() {
		try {
			this.gameOver = true;
			super.stop();
			
		} catch (GameError e) {
			view.log(e.getMessage());
		} catch(Exception e) {
			e.printStackTrace();
			
		} finally {
			for(Connection c : clients) {
				try {
					c.stop();
				} catch(IOException e) { e.printStackTrace(); }
			}
//		this.stop();<commit_msg>una pequeña errata corregida<commit_after>package es.ucm.fdi.tp.control.multiplayer;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import com.sun.istack.internal.NotNull;

import es.ucm.fdi.tp.basecode.bgame.control.Controller;
import es.ucm.fdi.tp.basecode.bgame.control.GameFactory;
import es.ucm.fdi.tp.basecode.bgame.control.Player;
import es.ucm.fdi.tp.basecode.bgame.control.commands.Command;
import es.ucm.fdi.tp.basecode.bgame.model.Board;
import es.ucm.fdi.tp.basecode.bgame.model.Game;
import es.ucm.fdi.tp.basecode.bgame.model.Game.State;
import es.ucm.fdi.tp.basecode.bgame.model.GameError;
import es.ucm.fdi.tp.basecode.bgame.model.GameObserver;
import es.ucm.fdi.tp.basecode.bgame.model.Piece;
import es.ucm.fdi.tp.control.multiplayer.Responses.*;

public class GameServer extends Controller implements GameObserver {
	
	private List<Connection> clients;
	volatile private ServerSocket server;
	private int port;
	
	private NetObserver view;
	
	volatile private boolean stopped;
	volatile private boolean gameOver;
	
	public static int REQUIRED_PLAYERS = 4;
	
	private int nPlayers = 0;
	private GameFactory gameFactorry;
	private List<Piece> pieces;
	
	public GameServer(GameFactory factory, List<Piece> pieces, int port) {
		super(new Game(factory.gameRules()), pieces);
		this.clients = new ArrayList<Connection>();
		
		this.gameFactorry = factory;
		this.pieces = pieces;
		
		this.port = port;
		
		game.addObserver(this);
	}
	
	private void startClientListener(Connection c) throws IOException {
		this.gameOver = false;
		c.sendObject(gameFactorry);
		c.sendObject(pieces);
		Thread t = new Thread() {
			@Override
			public void run() {
				while (!stopped && !gameOver) {
					try {
						Command cmd = (Command) c.getObject();
						cmd.execute(GameServer.this);
					} catch (ClassNotFoundException | ClassCastException | IOException e) {
						if (!stopped && !gameOver) {
							GameServer.this.stop();
						}
					}
				}
			}
		};
		
		t.start();
		
		view.onPlayerConnected(pieces.get(nPlayers-1));
	}
	
	public int playersConnected() {
		return nPlayers;
	}
	
	private void startServer()  {
		Socket soc;
		try {
			this.server = new ServerSocket(port);
			view.onServerOpened(game.gameDesc());
			this.stopped = false;
			
		} catch (IOException e) {
			view.log("Error opening the server");
			System.err.println("Error opening the server: " + e.getMessage());
			view.onServerClosed();
			this.stopped = true;
		}
		
		this.stopped = false;
		
		while(!this.stopped) {
			try {
				soc = server.accept();
				handleRequest(soc);
				
			} catch (IOException e) {
				if(!this.stopped){
					view.log("Error while waiting for a connection");
					System.err.println("Error while waiting for a connection: " + e.getMessage());
				}
			}
		}
		try {
			server.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private void handleRequest(Socket s) {
		try {
			Connection c = new Connection(s);
			Object clientRequest = c.getObject();
			
			if(!(clientRequest instanceof String) &&
					!((String) clientRequest).equalsIgnoreCase("Connect") ) {
				c.sendObject(new GameError("Invalid Request"));
				c.stop();
				return;
			}
			if(nPlayers >= REQUIRED_PLAYERS) {
				c.sendObject(new GameError("Room is already full"));
				c.stop();
				view.log("A client connection was refused: Maximum players connections reached ");
				return;
			}
			
			nPlayers++;
			clients.add(c);
			view.log("new player into to room");
			c.sendObject("OK");
			c.sendObject(this.gameFactorry);
			c.sendObject(this.pieces.get(nPlayers-1));
			if(nPlayers >= REQUIRED_PLAYERS)
				startGame();
			
			startClientListener(c);
			
		} catch (IOException | ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	private void startGame() {
		if(game.getState() == State.Starting)
			game.start(pieces);
		else
			game.restart();
	}
	
	public void setView(@NotNull NetObserver o) {
		this.view = o;
	}
	
	@Override
	public synchronized void makeMove(Player p) {
		try {
			super.makeMove(p);
		} catch (GameError e) {
			view.log(e.getMessage());
		}
	}
	
	@Override
	public synchronized void restart() {
		try {
			super.restart();
		} catch (GameError e) {
			view.log(e.getMessage());
		}
	}
	
	@Override
	public synchronized void stop() {
		try {
			this.gameOver = true;
			super.stop();
			
		} catch (GameError e) {
			view.log(e.getMessage());
		} catch(Exception e) {
			e.printStackTrace();
			
		} finally {
			for(Connection c : clients) {
				try {
					c.stop();
				} catch(IOException e) { e.printStackTrace(); }
			}
		this.stop();
{'fraction_non_alphanumeric': 0.13313515235162968, 'fraction_numerical': 0.0008493470644442085, 'mean_word_length': 3.3773234200743496, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2647714', 'n_tokens_mistral': 3723, 'n_tokens_neox': 3078, 'n_words': 654}