Add files via upload

This commit is contained in:
charlesbvll 2019-09-30 12:58:04 +02:00 committed by GitHub
parent 71807d6c36
commit f48ed32195
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 382 additions and 0 deletions

157
net/RemotePlayerClient.java Normal file
View File

@ -0,0 +1,157 @@
package ch.epfl.javass.net;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UncheckedIOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import ch.epfl.javass.jass.Card;
import ch.epfl.javass.jass.CardSet;
import ch.epfl.javass.jass.Player;
import ch.epfl.javass.jass.PlayerId;
import ch.epfl.javass.jass.Score;
import ch.epfl.javass.jass.TeamId;
import ch.epfl.javass.jass.Trick;
import ch.epfl.javass.jass.TurnState;
import ch.epfl.javass.jass.Card.Color;
import static ch.epfl.javass.net.StringSerializer.*;
/**
* A player that plays on a remote server.
* @author Charles BEAUVILLE
* @author Celia HOUSSIAUX
*
*/
public final class RemotePlayerClient implements Player, AutoCloseable{
private final static int PORT_NUMBER = 5108;
private final Socket s;
private final BufferedReader r;
private final BufferedWriter w;
/**
* Creates a player that plays on a given host server.
* @param host a string the adress of the host server.
* @throws UnknownHostException if the host ip is wrong.
* @throws IOException if the signal has been interrupted.
*/
public RemotePlayerClient(String host) throws UnknownHostException, IOException {
this.s = new Socket(host, PORT_NUMBER);
this.r =
new BufferedReader(
new InputStreamReader(s.getInputStream(),
StandardCharsets.UTF_8));
this.w =
new BufferedWriter(
new OutputStreamWriter(s.getOutputStream(),
StandardCharsets.UTF_8));
}
@Override
public void setPlayers(PlayerId ownId, Map<PlayerId, String> playerNames) {
String cmd = JassCommand.PLRS.toString();
String id = serializeInt(ownId.ordinal());
String[] names = new String[PlayerId.COUNT];
for (int i = 0; i < names.length; i++)
names[i] = serializeString(playerNames.get(PlayerId.ALL.get(i)));
String combinedNames = combine(',', names);
String[] msg = new String[]{cmd, id, combinedNames};
sendMsg(combineMsg(msg));
}
@Override
public void setWinningTeam(TeamId winningTeam) {
String cmd = JassCommand.WINR.toString();
String winningTeamIndex = serializeInt(winningTeam.ordinal());
String[] msg = new String[]{cmd, winningTeamIndex};
sendMsg(combineMsg(msg));
}
@Override
public void setTrump(Color trump) {
String cmd = JassCommand.TRMP.toString();
String trumpIndex = serializeInt(trump.ordinal());
String[] msg = new String[]{cmd, trumpIndex};
sendMsg(combineMsg(msg));
}
@Override
public void updateHand(CardSet newHand) {
String cmd = JassCommand.HAND.toString();
String hand = serializeLong(newHand.packed());
String[] msg = new String[]{cmd, hand};
sendMsg(combineMsg(msg));
}
@Override
public void updateScore(Score score) {
String cmd = JassCommand.SCOR.toString();
String s = serializeLong(score.packed());
String[] msg = new String[]{cmd, s};
sendMsg(combineMsg(msg));
}
@Override
public void updateTrick(Trick newTrick) {
String cmd = JassCommand.TRCK.toString();
String trick = serializeInt(newTrick.packed());
String[] msg = new String[]{cmd, trick};
sendMsg(combineMsg(msg));
}
@Override
public Card cardToPlay(TurnState state, CardSet hand) {
String cmd = JassCommand.CARD.toString();
String s = combine(',', new String[]{serializeLong(state.packedScore()), serializeLong(state.packedUnplayedCards()), serializeInt(state.packedTrick())});
String h = serializeLong(hand.packed());
String[] msg = new String[]{cmd, s, h};
String c = "0";
sendMsg(combineMsg(msg));
try {
c = r.readLine();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
return Card.ofPacked(deserializeInt(c));
}
@Override
public void close() throws Exception {
w.close();
r.close();
s.close();
}
private String combineMsg(String[] strings) {
return combine(' ', strings);
}
private void sendMsg(String msg) {
try {
w.write(msg);
w.newLine();
w.flush();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}

132
net/RemotePlayerServer.java Normal file
View File

@ -0,0 +1,132 @@
package ch.epfl.javass.net;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import static ch.epfl.javass.net.StringSerializer.*;
import ch.epfl.javass.jass.Card;
import ch.epfl.javass.jass.Card.Color;
import ch.epfl.javass.jass.CardSet;
import ch.epfl.javass.jass.Player;
import ch.epfl.javass.jass.PlayerId;
import ch.epfl.javass.jass.Score;
import ch.epfl.javass.jass.TeamId;
import ch.epfl.javass.jass.Trick;
import ch.epfl.javass.jass.TurnState;
/**
* Connects to a remote client and executes functions according to the data
* sent.
*
* @author Charles BEAUVILLE
* @author Celia HOUSSIAUX
*
*/
public final class RemotePlayerServer {
private static final int PORT_NUMBER = 5108;
private static final int COMMAND_INDEX = 0;
private static final int ARG_0_INDEX = 0;
private static final int ARG_1_INDEX = 1;
private static final int ARG_2_INDEX = 2;
private Player localPlayer;
/**
* Connects to a remote client and executes functions of the given player
* according to the data sent.
*
* @param p
* the underlying player.
*/
public RemotePlayerServer(Player p) {
this.localPlayer = p;
}
/**
* Runs the server on the port number.
* @throws IOException
*/
public void run() throws IOException {
@SuppressWarnings("resource")
//Listens for a connection on the port number.
ServerSocket s0 = new ServerSocket(PORT_NUMBER);
Socket s = s0.accept();
//Sets up the buffers to read and to write on the socket.
BufferedReader r = new BufferedReader(new InputStreamReader(
s.getInputStream(), StandardCharsets.UTF_8));
BufferedWriter w = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream(), StandardCharsets.UTF_8));
String command;
//Reads the commands wrote on the socket line per line
while ((command = r.readLine()) != null) {
String[] msg = split(' ', command);
switch (JassCommand.valueOf(msg[COMMAND_INDEX])) {
case PLRS:
//Creates the players map with the arguments and calls the setPlayers function of the underlyingPlayer.
Map<PlayerId, String> players = new HashMap<>();
for (int i = 0; i < PlayerId.COUNT; i++) {
players.put(PlayerId.ALL.get(i),
deserializeString(split(',', msg[ARG_2_INDEX])[i]));
}
localPlayer.setPlayers(PlayerId.ALL.get(deserializeInt(msg[ARG_1_INDEX])),
players);
break;
case CARD:
//Calls the cardToPlay function of the underlying function with the arguments of the message.
String[] st = split(',', msg[ARG_1_INDEX]);
TurnState state = TurnState.ofPackedComponents(
deserializeLong(st[ARG_0_INDEX]), deserializeLong(st[ARG_1_INDEX]),
deserializeInt(st[ARG_2_INDEX]));
Card c = localPlayer.cardToPlay(state,
CardSet.ofPacked(deserializeLong(msg[ARG_2_INDEX])));
w.write(serializeInt(c.packed()));
w.newLine();
w.flush();
break;
case HAND:
localPlayer
.updateHand(CardSet.ofPacked(deserializeLong(msg[ARG_1_INDEX])));
break;
case TRMP:
localPlayer.setTrump(Color.ALL.get(deserializeInt(msg[ARG_1_INDEX])));
break;
case SCOR:
localPlayer
.updateScore(Score.ofPacked(deserializeLong(msg[ARG_1_INDEX])));
break;
case TRCK:
localPlayer.updateTrick(Trick.ofPacked(deserializeInt(msg[ARG_1_INDEX])));
break;
case WINR:
localPlayer
.setWinningTeam(TeamId.ALL.get(deserializeInt(msg[ARG_1_INDEX])));
break;
default:
}
}
}
}

93
net/StringSerializer.java Normal file
View File

@ -0,0 +1,93 @@
package ch.epfl.javass.net;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
/**
* Methods to serialize object into byte sequences to transmit them in a network.
* @author Charles BEAUVILLE
* @author Celia HOUSSIAUX
*
*/
public final class StringSerializer {
private static final int HEX_RADIX = 16;
private StringSerializer() {}
/**
* Serializes a given {@link Integer} into its base 16 textual representation.
* @param i the {@link Integer} to serialize
* @return a {@link String} the base 16 representation of the given int.
*/
public static String serializeInt(int i) {
return Integer.toUnsignedString(i, HEX_RADIX);
}
/**
* Takes a the string representation of an int and returns the actual {@link Integer}.
* @param s the string that needs to be deserialized into an {@link Integer}.
* @return the {@link Integer} represented by the string.
*/
public static int deserializeInt(String s) {
return Integer.parseUnsignedInt(s, HEX_RADIX);
}
/**
* Serializes a given {@link Long} into its base 16 textual representation.
* @param l the {@link Long} to serialize.
* @return a {@link String} the base 16 representation of the given long.
*/
public static String serializeLong(long l) {
return Long.toUnsignedString(l, HEX_RADIX);
}
/**
* Takes a the string representation of an int and returns the actual {@link Long}.
* @param s the string that needs to be deserialized into an {@link Long}.
* @return the {@link Long} represented by the string.
*/
public static long deserializeLong(String s) {
return Long.parseLong(s, HEX_RADIX);
}
/**
* Encodes the given string to base 64.
* @param s the string to encode.
* @return the encoded string.
*/
public static String serializeString(String s) {
Base64.Encoder e = Base64.getEncoder();
return e.encodeToString(s.getBytes(StandardCharsets.UTF_8));
}
/**
* Decodes the given string from base 64.
* @param s the string to decode.
* @return the decoded string.
*/
public static String deserializeString(String s) {
Base64.Decoder d = Base64.getDecoder();
return new String(d.decode(s), StandardCharsets.UTF_8);
}
/**
* Combines the strings given in the array, separated by the given character.
* @param c the character to separate the strings.
* @param strings the array of strings to be combined.
* @return a string constiting of the strings of the array separated by the given character.
*/
public static String combine(char c, String[] strings) {
return String.join(String.valueOf(c), strings);
}
/**
* Splits at the given character a string into an array of strings.
* @param c the character that separates the strings.
* @param s the string to be split.
* @return the array of the strings in between the given character.
*/
public static String[] split(char c, String s) {
return s.split(String.valueOf(c));
}
}