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

290 lines
6.4 KiB
Java

package fr.ynerant.tarot;
import android.preference.PreferenceManager;
import android.util.SparseArray;
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.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
public class Game {
private static final Gson GSON;
private static final SparseArray<Game> GAMES = new SparseArray<>();
public int id;
public GameType gameType;
public List<Player> players;
public Bet bet;
public Player attacker;
public Player follower;
public int attackScore;
// public boolean little, twenty_one, excuse;
public int ends;
public int handle;
public List<Boolean> miseries;
public boolean littleForAttacker, littleForDefenser;
public boolean chelemAnnounced, chelemRealized;
public 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;
}
return Player.getPlayerById(in.nextInt());
}
}).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()];
}
}).create();
}
public int getId() {
return id;
}
public GameType getGameType() {
return gameType;
}
public List<Player> getPlayers() {
return players;
}
public Bet getBet() {
return bet;
}
public Player getAttacker() {
return attacker;
}
public Player getFollower() {
return follower;
}
public int getAttackScore() {
return attackScore;
}
public int getEnds() {
return ends;
}
public int getHandle() {
return handle;
}
public List<Boolean> getMiseries() {
return miseries;
}
public boolean isLittleForAttacker() {
return littleForAttacker;
}
public boolean isLittleForDefenser() {
return littleForDefenser;
}
public boolean isChelemAnnounced() {
return chelemAnnounced;
}
public boolean isChelemRealized() {
return chelemRealized;
}
public void calculateScores() {
// int ends = (little ? 1 : 0) + (twenty_one ? 1 : 0) + (excuse ? 1 : 0);
int bound = ends == 0 ? 56 : ends == 1 ? 51 : ends == 2 ? 41 : 36;
boolean win = attackScore >= bound;
int gain = Math.abs(attackScore - bound);
int score = 25;
score += gain;
score *= bet.getMultiplier();
if (handle != 0)
score += 10 * (Math.abs(handle) + 1);
if (!win)
score = -score;
if (littleForAttacker)
score += 10;
else if (littleForDefenser)
score -= 10;
if (chelemAnnounced) {
if (chelemRealized)
score += 400;
else
score -= 200;
}
else if (chelemRealized)
score += 200;
attackScore = score;
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)
playerScore += getGameType().getAttackMultiplier() * score;
if (p == follower)
playerScore += getGameType().getFollowMultiplier() * score;
}
scores.put(p, playerScore);
}
for (int i = 0; i < getGameType().getNbPlayers(); ++i) {
System.err.println(getMiseries());
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);
}
public enum GameType {
THREE_PLAYERS(2, 0), FOUR_PLAYERS(3, 0), FIVE_PLAYERS(2, 1), SIX_PLAYERS(3, 1);
private final int attackMultiplier;
private final int followMultiplier;
GameType(int attack, int follow) {
this.attackMultiplier = attack;
this.followMultiplier = follow;
}
public int getAttackMultiplier() {
return attackMultiplier;
}
public int getFollowMultiplier() {
return followMultiplier;
}
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;
}
}
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 (Game g : games) {
GAMES.put(g.getId(), g);
}
}
catch (IOException ex) {
ex.printStackTrace();
}
}
});
}
}