475 lines
11 KiB
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";
|
|
}
|
|
}
|
|
}
|
|
}
|