tarot-ens-info/app/src/main/java/fr/ynerant/tarot/Game.java

475 lines
11 KiB
Java

package fr.ynerant.tarot;
import android.annotation.SuppressLint;
import android.preference.PreferenceManager;
import androidx.annotation.NonNull;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import fr.ynerant.tarot.ui.games.GameInfoFragment;
public class Game {
private static final Gson GSON;
@SuppressLint("UseSparseArrays")
private static final Map<Integer, Game> GAMES = new HashMap<>();
@SuppressWarnings("unused")
private int id;
@SuppressWarnings("unused")
private Date date;
private GameType gameType;
@SuppressWarnings("unused")
private Player player1, player2, player3, player4, player5, player6;
private List<Player> players;
@SuppressWarnings("unused")
private int nb_players;
private Bet bet;
private Player attacker;
private Player follower;
private int attack_score;
// private boolean little_end, twenty_one, excuse;
private int ends;
@SuppressWarnings("unused")
private int handle1, handle2, handle3, handle4, handle5, handle6;
private List<Integer> handles;
@SuppressWarnings("unused")
private boolean misery1, misery2, misery3, misery4, misery5, misery6;
private List<Boolean> miseries;
private int little_end;
private boolean chelem_announced, chelem_realized;
@SuppressWarnings("unused")
private int score1, score2, score3, score4, score5, score6;
private List<Integer> points;
static {
GSON = new GsonBuilder().registerTypeAdapter(Player.class, new TypeAdapter<Player>() {
@Override
public void write(JsonWriter out, Player value) throws IOException {
if (value == null)
out.nullValue();
else
out.value(value.getId());
}
@Override
public Player read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
int id = in.nextInt();
if (id == 0)
return null;
return Player.getPlayerById(id);
}
}).registerTypeAdapter(Game.GameType.class, new TypeAdapter<Game.GameType>() {
@Override
public void write(JsonWriter out, GameType value) throws IOException {
if (value == null)
out.nullValue();
else
out.value(value.getNbPlayers());
}
@Override
public GameType read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
return Game.GameType.values()[3 + in.nextInt()];
}
}).registerTypeAdapter(Date.class, new TypeAdapter<Date>() {
@SuppressLint("SimpleDateFormat")
final DateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public void write(JsonWriter out, Date value) throws IOException {
if (value == null)
out.nullValue();
else
out.value(FORMAT.format(value));
}
@Override
public Date read(JsonReader in) throws IOException {
try {
return FORMAT.parse(in.nextString());
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}
}).create();
}
public int getId() {
return id;
}
public Date getDate() {
return date;
}
public GameType getGameType() {
return gameType;
}
public void setGameType(GameType gameType) {
this.gameType = gameType;
}
public List<Player> getPlayers() {
return players;
}
public void setPlayers(List<Player> players) {
this.players = players;
}
public Bet getBet() {
return bet;
}
public void setBet(Bet bet) {
this.bet = bet;
}
public Player getAttacker() {
return attacker;
}
public void setAttacker(Player attacker) {
this.attacker = attacker;
}
public Player getFollower() {
return follower;
}
public void setFollower(Player follower) {
this.follower = follower;
}
public int getAttackScore() {
return attack_score;
}
public void setAttackScore(int attack_score) {
this.attack_score = attack_score;
}
public int getEnds() {
return ends;
}
public void setEnds(int ends) {
this.ends = ends;
}
public int getHandle(Player player) {
return handles.get(players.indexOf(player));
}
public List<Integer> getHandles() {
return handles;
}
public void setHandles(List<Integer> handles) {
this.handles = handles;
}
public List<Boolean> getMiseries() {
return miseries;
}
public void setMiseries(List<Boolean> miseries) {
this.miseries = miseries;
}
public int getLittleEnd() {
return little_end;
}
public void setLittleEnd(int little_end) {
this.little_end = little_end;
}
public boolean isChelemAnnounced() {
return chelem_announced;
}
public void setChelemAnnounced(boolean chelem_announced) {
this.chelem_announced = chelem_announced;
}
public boolean isChelemRealized() {
return chelem_realized;
}
public void setChelemRealized(boolean chelem_realized) {
this.chelem_realized = chelem_realized;
}
public int getPoints(Player player) {
return points.get(players.indexOf(player));
}
public int getPoints(int i) {
return points.get(i);
}
public void calculateScores() {
// int ends = (little_end ? 1 : 0) + (twenty_one ? 1 : 0) + (excuse ? 1 : 0);
int bound = ends == 0 ? 56 : ends == 1 ? 51 : ends == 2 ? 41 : 36;
boolean win = attack_score >= bound;
int gain = Math.abs(attack_score - bound);
int score = 25;
score += gain;
score *= bet.getMultiplier();
for (int i = 0; i < getGameType().getNbPlayers(); ++i) {
Player player = getPlayers().get(i);
if (getHandle(player) > 0)
score += 10 * (getHandle(player) + 1);
}
if (!win)
score = -score;
if (little_end != 0 && (players.get(little_end - 1) == attacker || players.get(little_end - 1) == follower))
score += 10;
else if (little_end != 0)
score -= 10;
if (chelem_announced) {
if (chelem_realized)
score += 400;
else
score -= 200;
}
else if (chelem_realized)
score += 200;
Map<Player, Integer> scores = new HashMap<>();
for (int i = 0; i < getGameType().getNbPlayers(); ++i) {
Player p = players.get(i);
int playerScore = 0;
if (p != attacker && p != follower)
playerScore = -score;
else {
if (p == attacker && p == follower)
playerScore += (getGameType().getNbPlayers() - 1) * score;
else if (p == attacker)
playerScore += (getGameType().getNbPlayers() - 1 - (follower == null ? 0 : 2)) * score;
else
playerScore += score;
}
scores.put(p, playerScore);
}
for (int i = 0; i < getGameType().getNbPlayers(); ++i) {
if (getMiseries().get(i)) {
//noinspection ConstantConditions
scores.put(players.get(i), scores.get(players.get(i)) + 10 * (getGameType().getNbPlayers() - 1));
for (int j = 0; j < getGameType().getNbPlayers(); ++j) {
if (i == j)
continue;
//noinspection ConstantConditions
scores.put(players.get(j), scores.get(players.get(j)) - 10);
}
}
}
points = new ArrayList<>();
for (int i = 0; i < getGameType().getNbPlayers(); ++i) {
points.add(scores.get(players.get(i)));
}
}
public String toJson() {
return GSON.toJson(this);
}
@NonNull
@Override
public String toString() {
SimpleDateFormat format = new SimpleDateFormat("dd MMMM yyyy HH:mm:ss");
String str = "Partie à " + getGameType().getNbPlayers() + " joueurs : ";
for (Player player : getPlayers())
str += player.getName() + ", ";
str += getBet().toString() + " de " + getAttacker().getName() + " " + (getAttackScore() >= (ends == 0 ? 56 : ends == 1 ? 51 : ends == 2 ? 41 : 36) ? "gagnée" : "chutée") + ", ";
str += format.format(getDate());
return str;
}
public static Game getGameById(int id) {
return GAMES.get(id);
}
public static List<Game> getAllGames() {
List<Game> list = new ArrayList<>(GAMES.values());
list.sort(new Comparator<Game>() {
@Override
public int compare(Game o1, Game o2) {
return o2.getDate().compareTo(o1.getDate());
}
});
return list;
}
public static void updateGames() {
Executors.newSingleThreadExecutor().execute(new Runnable() {
@Override
public void run() {
try {
URL url = new URL("https://ynerant.fr/tarot/game.php");
final HttpURLConnection co = (HttpURLConnection) url.openConnection();
co.setRequestMethod("POST");
co.setRequestProperty("token", PreferenceManager.getDefaultSharedPreferences(MainActivity.INSTANCE).getString("token", null));
co.connect();
final List<Game> games = GSON.fromJson(new InputStreamReader(co.getInputStream()), new TypeToken<ArrayList<Game>>(){}.getType());
GAMES.clear();
for (Player p : Player.getAllPlayers()) {
for (GameType type : GameType.values())
p.setScore(type, 0);
}
for (Game g : games) {
GAMES.put(g.getId(), g);
g.setGameType(GameType.values()[g.nb_players - 3]);
g.players = new ArrayList<>();
g.getPlayers().add(g.player1);
g.getPlayers().add(g.player2);
g.getPlayers().add(g.player3);
if (g.player4 != null)
g.getPlayers().add(g.player4);
if (g.player5 != null)
g.getPlayers().add(g.player5);
if (g.player6 != null)
g.getPlayers().add(g.player6);
g.handles = new ArrayList<>();
g.getHandles().add(g.handle1);
g.getHandles().add(g.handle2);
g.getHandles().add(g.handle3);
if (g.player4 != null)
g.getHandles().add(g.handle4);
if (g.player5 != null)
g.getHandles().add(g.handle5);
if (g.player6 != null)
g.getHandles().add(g.handle6);
g.miseries = new ArrayList<>();
g.getMiseries().add(g.misery1);
g.getMiseries().add(g.misery2);
g.getMiseries().add(g.misery3);
if (g.player4 != null)
g.getMiseries().add(g.misery4);
if (g.player5 != null)
g.getMiseries().add(g.misery5);
if (g.player6 != null)
g.getMiseries().add(g.misery6);
g.calculateScores();
for (Player p : g.getPlayers())
p.addScore(g.getGameType(), g.getPoints(p));
}
}
catch (IOException ex) {
ex.printStackTrace();
}
}
});
}
public enum GameType {
THREE_PLAYERS, FOUR_PLAYERS, FIVE_PLAYERS, SIX_PLAYERS;
public int getNbPlayers() {
return ordinal() + 3;
}
public static GameType getGameType(int players) {
switch (players) {
case 3:
return THREE_PLAYERS;
case 4:
return FOUR_PLAYERS;
case 5:
return FIVE_PLAYERS;
case 6:
return SIX_PLAYERS;
default:
throw new IllegalArgumentException("A game must have between 3 and 6 players");
}
}
}
public enum Bet {
SMALL(1), GUARD(2), GUARD_WITHOUT(4), GUARD_AGAINST(6);
private final int multiplier;
Bet(int multiplier) {
this.multiplier = multiplier;
}
public int getMultiplier() {
return multiplier;
}
@NonNull
@Override
public String toString() {
switch (this) {
case SMALL:
return "Petite";
case GUARD:
return "Garde";
case GUARD_WITHOUT:
return "Garde sans";
case GUARD_AGAINST:
return "Garde contre";
default:
return "null";
}
}
}
}