add code to launch firemind worker from settings menu
parent
c01ecc37c3
commit
3ac35f4375
28
build.xml
28
build.xml
|
@ -9,15 +9,16 @@
|
|||
<property name="lib" value="release/lib" />
|
||||
<property name="groovy-version" value="2.3.4" />
|
||||
|
||||
<property name="out.dir" value="build/"/>
|
||||
|
||||
<path id="classpath">
|
||||
<pathelement path="build/" />
|
||||
<fileset dir="${lib}">
|
||||
<include name="*.jar" />
|
||||
<include name="**/*.jar" />
|
||||
</fileset>
|
||||
</path>
|
||||
|
||||
<taskdef name="bundleapp"
|
||||
classname="com.oracle.appbundler.AppBundlerTask"
|
||||
classpath="lib/appbundler-1.0.jar" />
|
||||
|
||||
|
||||
<!-- deps - Download dependencies -->
|
||||
<target name="deps" unless="skip.download">
|
||||
|
@ -40,6 +41,10 @@
|
|||
<get src="http://repo1.maven.org/maven2/org/pushingpixels/trident/1.3/trident-1.3.jar"
|
||||
dest="${lib}/trident-1.3.jar"
|
||||
skipexisting="true" />
|
||||
<echo message="downloading java json library to ${lib}"/>
|
||||
<get src="http://repo1.maven.org/maven2/org/json/json/20140107/json-20140107.jar"
|
||||
dest="${lib}/json.jar"
|
||||
skipexisting="true" />
|
||||
</target>
|
||||
|
||||
<!-- init - Create temporary directory to build the program -->
|
||||
|
@ -66,14 +71,18 @@
|
|||
</fileset>
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<manifestclasspath property="lib.list" jarfile="release/Magarena.jar">
|
||||
<classpath refid="classpath"/>
|
||||
</manifestclasspath>
|
||||
<!-- jar (default target) - Create .jar file -->
|
||||
<target depends="build" name="jar">
|
||||
<jar destfile="release/Magarena.jar" basedir="build" includes="**/*.*">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="magic.MagicMain" />
|
||||
<attribute name="SplashScreen-Image" value="magic/data/textures/logo.jpg" />
|
||||
<attribute name="Class-Path" value="lib/groovy-all-${groovy-version}.jar lib/miglayout-core-4.2.jar lib/miglayout-swing-4.2.jar lib/commons-io-2.4.jar lib/trident-1.3.jar" />
|
||||
<attribute name="Class-Path" value="lib/groovy-all-${groovy-version}.jar " />
|
||||
<attribute name="Class-Path" value="lib/groovy-all-${groovy-version}.jar lib/json.jar lib/jedis-2.1.0.jar lib/mysql-connector-java-5.1.25-bin.jar lib/activejdbc-1.4.6.jar lib/slf4j-api-1.6.4.jar lib/slf4j-simple-1.6.4.jar lib/javalite-common-1.4.6.jar lib/miglayout-core-4.2.jar lib/miglayout-swing-4.2.jar lib/commons-io-2.4.jar lib/trident-1.3.jar" />
|
||||
<attribute name="Class-Path" value="${lib.list}"/>
|
||||
</manifest>
|
||||
</jar>
|
||||
</target>
|
||||
|
@ -82,5 +91,12 @@
|
|||
<target name="javadoc">
|
||||
<javadoc sourcepath="src" destdir="javadoc" />
|
||||
</target>
|
||||
|
||||
<target name="instrument" depends="build">
|
||||
<java classname="org.javalite.instrumentation.Main">
|
||||
<sysproperty key="outputDirectory" value="${out.dir}"/>
|
||||
<classpath refid="classpath"/>
|
||||
</java>
|
||||
</target>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -0,0 +1,188 @@
|
|||
package magic;
|
||||
|
||||
import magic.ai.MagicAI;
|
||||
import magic.ai.MagicAIImpl;
|
||||
import magic.data.DeckUtils;
|
||||
import magic.data.DuelConfig;
|
||||
import magic.model.FiremindGameReport;
|
||||
import magic.model.MagicDuel;
|
||||
import magic.model.MagicGame;
|
||||
import magic.model.MagicGameLog;
|
||||
import magic.model.MagicRandom;
|
||||
import magic.ui.GameController;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.File;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.FileWriter;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Date;
|
||||
|
||||
import firemind.Duel;
|
||||
import firemind.FiremindClient;
|
||||
|
||||
public class FiremindQueueWorker {
|
||||
|
||||
private static int games;
|
||||
private static int str1 = 2;
|
||||
private static int str2 = 2;
|
||||
private static int life = 20;
|
||||
private static int seed;
|
||||
private static String deck1 = "";
|
||||
private static String deck2 = "";
|
||||
private static MagicAIImpl ai1 = MagicAIImpl.MCTS;
|
||||
private static MagicAIImpl ai2 = MagicAIImpl.MCTS;
|
||||
private static Duel currentDuel;
|
||||
private static String env;
|
||||
private static int gameCount = 0;
|
||||
|
||||
private static MagicDuel setupDuel() {
|
||||
// Set the random seed
|
||||
if (seed != 0) {
|
||||
MagicRandom.setRNGState(seed);
|
||||
seed = MagicRandom.nextRNGInt(Integer.MAX_VALUE) + 1;
|
||||
}
|
||||
|
||||
// Set number of games.
|
||||
final DuelConfig config = new DuelConfig();
|
||||
config.setNrOfGames(games);
|
||||
config.setStartLife(life);
|
||||
|
||||
// Set difficulty.
|
||||
final MagicDuel testDuel = new MagicDuel(config);
|
||||
testDuel.initialize();
|
||||
testDuel.setDifficulty(0, str1);
|
||||
testDuel.setDifficulty(1, str2);
|
||||
|
||||
// Set the AI
|
||||
testDuel.setAIs(new MagicAI[] { ai1.getAI(), ai2.getAI() });
|
||||
testDuel.getPlayer(0).setArtificial(true);
|
||||
testDuel.getPlayer(1).setArtificial(true);
|
||||
|
||||
// Set the deck.
|
||||
if (deck1.length() > 0) {
|
||||
DeckUtils.loadDeck(deck1, testDuel.getPlayer(0));
|
||||
}
|
||||
if (deck2.length() > 0) {
|
||||
DeckUtils.loadDeck(deck2, testDuel.getPlayer(1));
|
||||
}
|
||||
|
||||
return testDuel;
|
||||
}
|
||||
|
||||
public static void main(final String[] args) {
|
||||
// setup the handler for any uncaught exception
|
||||
try {
|
||||
if (java.net.InetAddress.getLocalHost().getHostName()
|
||||
.equals("mike-AndroidDev")) {
|
||||
env = "development";
|
||||
} else {
|
||||
env = "production";
|
||||
}
|
||||
} catch (UnknownHostException e1) {
|
||||
env = "production";
|
||||
}
|
||||
if (env == "production") {
|
||||
FiremindClient.setFiremindHost("https://www.firemind.ch");
|
||||
} else {
|
||||
FiremindClient.setFiremindHost("http://192.168.50.10");
|
||||
}
|
||||
MagicMain.initializeEngine();
|
||||
while (true) {
|
||||
Duel duel = FiremindClient.popDeckJob();
|
||||
if (duel != null) {
|
||||
final FiremindGameReport reporter = new FiremindGameReport(
|
||||
duel.id);
|
||||
Thread.setDefaultUncaughtExceptionHandler(reporter);
|
||||
System.out.println(duel.games_to_play + " Games to run");
|
||||
File theDir = new File("duels/" + duel.id);
|
||||
theDir.mkdir();
|
||||
|
||||
deck1 = saveDeckFile("duels/" + duel.id + "/" + "deck1",
|
||||
duel.deck1_text);
|
||||
deck2 = saveDeckFile("duels/" + duel.id + "/" + "deck2",
|
||||
duel.deck2_text);
|
||||
currentDuel = duel;
|
||||
games = duel.games_to_play;
|
||||
|
||||
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
|
||||
runDuel();
|
||||
if (gameCount > 25) {
|
||||
System.out
|
||||
.println("Exceeded max number of games. Shutting down.");
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
} else {
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("Woken");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static String saveDeckFile(String name, String content) {
|
||||
try {
|
||||
File deckFile = new File(name + ".dec");
|
||||
deckFile.getParentFile().mkdirs();
|
||||
deckFile.createNewFile();
|
||||
FileWriter fw = new FileWriter(deckFile.getAbsoluteFile());
|
||||
BufferedWriter bw = new BufferedWriter(fw);
|
||||
bw.write(content);
|
||||
bw.close();
|
||||
return deckFile.getPath();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private static void runDuel() {
|
||||
if (env == "production") {
|
||||
FiremindClient.setFiremindHost("https://www.firemind.ch");
|
||||
} else {
|
||||
FiremindClient.setFiremindHost("http://192.168.50.10");
|
||||
}
|
||||
int played = 0;
|
||||
int wins = 0;
|
||||
MagicGameLog.initialize();
|
||||
final MagicDuel testDuel = setupDuel();
|
||||
|
||||
Date baseDate = new Date();
|
||||
baseDate.setTime(0);
|
||||
long started = System.currentTimeMillis();
|
||||
while (testDuel.getGamesPlayed() < testDuel.getGamesTotal()) {
|
||||
final MagicGame game = testDuel.nextGame(false);
|
||||
game.setArtificial(true);
|
||||
final GameController controller = new GameController(game);
|
||||
|
||||
// maximum duration of a game is 60 minutes
|
||||
controller.setMaxTestGameDuration(3600000);
|
||||
|
||||
controller.runGame();
|
||||
if (testDuel.getGamesPlayed() > played) {
|
||||
gameCount++;
|
||||
played = testDuel.getGamesPlayed();
|
||||
long diff = System.currentTimeMillis() - started;
|
||||
String[] vers = MagicMain.VERSION.split("\\.");
|
||||
String log = MagicGameLog.getLogFileName();
|
||||
FiremindClient.postGame(currentDuel.id, played, new Date(
|
||||
baseDate.getTime() + diff),
|
||||
testDuel.getGamesWon() > wins, Integer
|
||||
.parseInt(vers[0]), Integer.parseInt(vers[1]),
|
||||
log);
|
||||
|
||||
wins = testDuel.getGamesWon();
|
||||
started = System.currentTimeMillis();
|
||||
MagicGameLog.initialize();
|
||||
}
|
||||
}
|
||||
System.out.println("Duel finished " + played + " of "
|
||||
+ testDuel.getGamesTotal() + " run");
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -52,6 +52,7 @@ public class GeneralConfig {
|
|||
private static final String ANIMATE_GAMEPLAY = "animateGameplay";
|
||||
private static final String DECK_FILE_MAX_LINES = "deckFileMaxLines";
|
||||
private static final String PROXY_SETTINGS = "proxySettings";
|
||||
private static final String FIREMIND_ACCESS_TOKEN = "firemindAccessToken";
|
||||
|
||||
// The most common size of card retrieved from http://mtgimage.com.
|
||||
public static final Dimension PREFERRED_CARD_SIZE = HIGH_QUALITY_IMAGE_SIZE;
|
||||
|
@ -123,7 +124,8 @@ public class GeneralConfig {
|
|||
private boolean animateGameplay = true;
|
||||
private int deckFileMaxLines = DEFAULT_DECK_FILE_MAX_LINES;
|
||||
private String proxySettings = DEFAULT_PROXY_SETTINGS;
|
||||
|
||||
private String firemindAccessToken;
|
||||
|
||||
private GeneralConfig() { }
|
||||
|
||||
public Proxy getProxy() {
|
||||
|
@ -300,6 +302,14 @@ public class GeneralConfig {
|
|||
public void setHighlight(final String highlight) {
|
||||
this.highlight = highlight;
|
||||
}
|
||||
|
||||
public String getFiremindAccessToken() {
|
||||
return firemindAccessToken;
|
||||
}
|
||||
|
||||
public void setFiremindAccessToken(final String firemindAccessToken) {
|
||||
this.firemindAccessToken = firemindAccessToken;
|
||||
}
|
||||
|
||||
public boolean getTextView() {
|
||||
return textView;
|
||||
|
@ -477,6 +487,7 @@ public class GeneralConfig {
|
|||
animateGameplay = Boolean.parseBoolean(properties.getProperty(ANIMATE_GAMEPLAY, "" + true));
|
||||
deckFileMaxLines = Integer.parseInt(properties.getProperty(DECK_FILE_MAX_LINES, ""+DEFAULT_DECK_FILE_MAX_LINES));
|
||||
proxySettings = properties.getProperty(PROXY_SETTINGS, "");
|
||||
firemindAccessToken = properties.getProperty(FIREMIND_ACCESS_TOKEN, "");
|
||||
}
|
||||
|
||||
public void load() {
|
||||
|
@ -517,6 +528,7 @@ public class GeneralConfig {
|
|||
properties.setProperty(CARD_IMAGES_PATH, cardImagesPath);
|
||||
properties.setProperty(ANIMATE_GAMEPLAY, String.valueOf(animateGameplay));
|
||||
properties.setProperty(PROXY_SETTINGS, proxySettings);
|
||||
properties.setProperty(FIREMIND_ACCESS_TOKEN, firemindAccessToken);
|
||||
}
|
||||
|
||||
public void save() {
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package firemind;
|
||||
public class Duel {
|
||||
|
||||
public Integer games_to_play;
|
||||
public Integer id;
|
||||
public String deck1_text;
|
||||
public String deck2_text;
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
package firemind;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Reader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Date;
|
||||
|
||||
import magic.data.GeneralConfig;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class FiremindClient {
|
||||
|
||||
protected static final GeneralConfig CONFIG = GeneralConfig.getInstance();
|
||||
static String firemindHost ;
|
||||
|
||||
public static Duel popDeckJob() {
|
||||
CONFIG.load();
|
||||
JSONObject obj;
|
||||
try {
|
||||
obj = readJsonFromUrl(firemindHost + "/api/v1/duel_jobs");
|
||||
|
||||
Duel d = new Duel();
|
||||
d.id = obj.getInt("id");
|
||||
d.games_to_play = obj.getInt("games_to_play");
|
||||
d.deck1_text = obj.getString("deck1_text");
|
||||
d.deck2_text = obj.getString("deck2_text");
|
||||
|
||||
return d;
|
||||
} catch (JSONException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} catch (FileNotFoundException e) {
|
||||
// No need to handle the 404 error
|
||||
return null;
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean postGame(Integer duel_id, Integer game_number,
|
||||
Date play_time, boolean win_deck1, Integer magarena_version_major,
|
||||
Integer magarena_version_minor, String logFile) {
|
||||
CONFIG.load();
|
||||
String url = firemindHost + "/api/v1/duel_jobs/" + duel_id + "/games";
|
||||
System.out.println("Posting game result "+game_number);
|
||||
URL object;
|
||||
try {
|
||||
object = new URL(url);
|
||||
HttpURLConnection con = (HttpURLConnection) object.openConnection();
|
||||
con.setRequestProperty("Content-Type", "application/json");
|
||||
con.setRequestProperty("Accept", "application/json");
|
||||
con.setRequestProperty("Authorization", "Token token="
|
||||
+ CONFIG.getFiremindAccessToken());
|
||||
con.setRequestMethod("POST");
|
||||
|
||||
JSONObject parent = new JSONObject();
|
||||
parent.put("game_number", game_number);
|
||||
parent.put("play_time", play_time);
|
||||
parent.put("win_deck1", win_deck1);
|
||||
parent.put("magarena_version_major", magarena_version_major);
|
||||
parent.put("magarena_version_minor", magarena_version_minor);
|
||||
parent.put("log", new String(Files.readAllBytes(Paths.get(logFile))));
|
||||
con.setDoOutput(true);
|
||||
|
||||
con.setDoInput(true);
|
||||
OutputStreamWriter wr = new OutputStreamWriter(
|
||||
con.getOutputStream());
|
||||
wr.write(parent.toString());
|
||||
wr.flush();
|
||||
int HttpResult = con.getResponseCode();
|
||||
if (HttpResult == HttpURLConnection.HTTP_OK) {
|
||||
return true;
|
||||
} else {
|
||||
System.err.println(con.getResponseMessage());
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean postFailure(Integer duel_id, String text) {
|
||||
System.err.println("POST ERROR STUB: "+text);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static JSONObject readJsonFromUrl(String url) throws IOException,
|
||||
JSONException {
|
||||
HttpURLConnection con = (HttpURLConnection) (new URL(url))
|
||||
.openConnection();
|
||||
con.setRequestProperty("Content-Type", "application/json");
|
||||
con.setRequestProperty("Accept", "application/json");
|
||||
con.setRequestProperty("Authorization", "Token token=" + CONFIG.getFiremindAccessToken());
|
||||
con.setRequestMethod("DELETE");
|
||||
con.setDoOutput(true);
|
||||
|
||||
con.setDoInput(true);
|
||||
|
||||
BufferedReader rd = new BufferedReader(new InputStreamReader(
|
||||
con.getInputStream(), Charset.forName("UTF-8")));
|
||||
String jsonText = readAll(rd);
|
||||
JSONObject json = new JSONObject(jsonText);
|
||||
return json;
|
||||
}
|
||||
|
||||
private static String readAll(Reader rd) throws IOException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int cp;
|
||||
while ((cp = rd.read()) != -1) {
|
||||
sb.append((char) cp);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static void setFiremindHost(String host) {
|
||||
firemindHost = host;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
package magic.model;
|
||||
|
||||
import magic.FiremindQueueWorker;
|
||||
import magic.MagicMain;
|
||||
import magic.data.FileIO;
|
||||
import magic.model.action.MagicAction;
|
||||
import magic.model.stack.MagicItemOnStack;
|
||||
import magic.utility.MagicFileSystem;
|
||||
import magic.utility.MagicFileSystem.DataPath;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.file.Path;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import firemind.Duel;
|
||||
import firemind.FiremindClient;
|
||||
|
||||
public class FiremindGameReport implements Thread.UncaughtExceptionHandler {
|
||||
Integer currentDuelId;
|
||||
|
||||
public FiremindGameReport(Integer duel_id) {
|
||||
super();
|
||||
this.currentDuelId = duel_id;
|
||||
}
|
||||
|
||||
public void uncaughtException(final Thread th, final Throwable ex) {
|
||||
FiremindGameReport.buildReport(MagicGame.getInstance(), th, ex);
|
||||
ex.printStackTrace();
|
||||
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
ex.printStackTrace(pw);
|
||||
FiremindClient.postFailure(currentDuelId, sw.toString());
|
||||
}
|
||||
|
||||
private static void buildCard(final MagicGame game, final String place,
|
||||
final MagicCard card, final StringBuilder report) {
|
||||
report.append(" - ").append(place).append(" : ")
|
||||
.append(card.getName()).append("\n");
|
||||
}
|
||||
|
||||
private static void buildPermanent(final MagicGame game,
|
||||
final MagicPermanent permanent, final StringBuilder report) {
|
||||
report.append(" - Permanent : ").append(permanent.getName());
|
||||
if (permanent.isCreature()) {
|
||||
final MagicPowerToughness pt = permanent.getPowerToughness();
|
||||
report.append(" Power : ").append(pt.power());
|
||||
report.append(" Toughness : ").append(pt.toughness());
|
||||
report.append(" Damage : ").append(permanent.getDamage());
|
||||
}
|
||||
if (permanent.hasState(MagicPermanentState.Tapped)) {
|
||||
report.append(" Tapped");
|
||||
}
|
||||
if (permanent.hasState(MagicPermanentState.Summoned)) {
|
||||
report.append(" Summoned");
|
||||
}
|
||||
report.append("\n");
|
||||
}
|
||||
|
||||
private static void buildPlayer(final MagicGame game,
|
||||
final MagicPlayer player, final StringBuilder report) {
|
||||
report.append(player.getIndex()).append("] ");
|
||||
report.append("Player : ").append(player.getName());
|
||||
report.append(" Life : ").append(player.getLife());
|
||||
report.append(" Delayed : ").append(player.getBuilderCost());
|
||||
report.append("\n");
|
||||
|
||||
for (final MagicCard card : player.getHand()) {
|
||||
buildCard(game, "Hand", card, report);
|
||||
}
|
||||
|
||||
for (final MagicCard card : player.getGraveyard()) {
|
||||
buildCard(game, "Graveyard", card, report);
|
||||
}
|
||||
|
||||
for (final MagicPermanent permanent : player.getPermanents()) {
|
||||
buildPermanent(game, permanent, report);
|
||||
}
|
||||
}
|
||||
|
||||
private static void buildStack(final MagicGame game,
|
||||
final StringBuilder report) {
|
||||
report.append("Stack : ").append(game.getStack().size()).append('\n');
|
||||
for (final MagicItemOnStack itemOnStack : game.getStack()) {
|
||||
report.append(" - Name : ");
|
||||
report.append(itemOnStack.getName());
|
||||
report.append(" Player : ");
|
||||
report.append(itemOnStack.getController().getName());
|
||||
report.append('\n');
|
||||
}
|
||||
}
|
||||
|
||||
private static void buildScore(final MagicGame game,
|
||||
final StringBuilder report) {
|
||||
int totalScore = 0;
|
||||
int count = 0;
|
||||
for (final MagicAction action : game.getActions()) {
|
||||
final int score = action.getScore(game.getScorePlayer());
|
||||
totalScore += score;
|
||||
final String text = action.toString();
|
||||
if (!text.isEmpty()) {
|
||||
report.append(++count).append(". ").append(text).append(" = ")
|
||||
.append(score).append("\n");
|
||||
}
|
||||
}
|
||||
report.append("Score = ").append(totalScore).append("\n");
|
||||
}
|
||||
|
||||
private static String buildReport(final MagicGame game) {
|
||||
final StringBuilder report = new StringBuilder();
|
||||
report.append("Turn : ").append(game.getTurn());
|
||||
report.append(" Phase : ").append(game.getPhase().getType());
|
||||
report.append(" Step : ").append(game.getStep());
|
||||
report.append(" Player : ").append(game.getTurnPlayer());
|
||||
report.append(" Score : ").append(game.getScore());
|
||||
report.append("\n");
|
||||
|
||||
for (final MagicPlayer player : game.getPlayers()) {
|
||||
buildPlayer(game, player, report);
|
||||
}
|
||||
|
||||
buildStack(game, report);
|
||||
buildScore(game, report);
|
||||
return report.toString();
|
||||
}
|
||||
|
||||
public static void buildReport(final MagicGame game, final Thread th,
|
||||
final Throwable ex) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("CRASH REPORT FOR MAGARENA THREAD " + th);
|
||||
sb.append('\n');
|
||||
sb.append("CREATED ON "
|
||||
+ (new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"))
|
||||
.format(new Date()));
|
||||
sb.append('\n');
|
||||
sb.append("MAGARENA VERSION " + MagicMain.VERSION);
|
||||
sb.append(", JRE " + System.getProperty("java.version"));
|
||||
sb.append(", OS " + System.getProperty("os.name"));
|
||||
sb.append("_" + System.getProperty("os.version"));
|
||||
sb.append(" " + System.getProperty("os.arch"));
|
||||
sb.append("\n\n");
|
||||
try {
|
||||
// buildReport might throw an exception
|
||||
if (game != null) {
|
||||
sb.append(buildReport(game));
|
||||
sb.append('\n');
|
||||
}
|
||||
} catch (final Throwable ex2) {
|
||||
sb.append("Exception from MagicGameReport.buildReport: "
|
||||
+ ex2.getMessage());
|
||||
sb.append('\n');
|
||||
final StringWriter result = new StringWriter();
|
||||
final PrintWriter printWriter = new PrintWriter(result);
|
||||
ex2.printStackTrace(printWriter);
|
||||
sb.append(result.toString());
|
||||
sb.append('\n');
|
||||
}
|
||||
sb.append("Exception from controller.runGame: " + ex.getMessage());
|
||||
sb.append('\n');
|
||||
final StringWriter result = new StringWriter();
|
||||
final PrintWriter printWriter = new PrintWriter(result);
|
||||
ex.printStackTrace(printWriter);
|
||||
sb.append(result.toString());
|
||||
sb.append('\n');
|
||||
|
||||
// print a copy to stderr
|
||||
System.err.println(sb.toString());
|
||||
|
||||
// save a copy to a crash log file
|
||||
final Path clog = MagicFileSystem.getDataPath(DataPath.LOGS).resolve(
|
||||
"crash.log");
|
||||
try {
|
||||
FileIO.toFile(clog.toFile(), sb.toString(), true);
|
||||
} catch (final IOException ex3) {
|
||||
System.err.println("Unable to save crash log");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,14 +10,17 @@ import magic.utility.MagicFileSystem.DataPath;
|
|||
|
||||
public class MagicGameLog {
|
||||
private MagicGameLog() {}
|
||||
|
||||
|
||||
private static final String gameLog = (System.getProperty("game.log") != null) ?
|
||||
System.getProperty("game.log") :
|
||||
MagicFileSystem.getDataPath(DataPath.LOGS).resolve("game.log").toString();
|
||||
|
||||
private static PrintWriter writer;
|
||||
|
||||
|
||||
public static String getLogFileName(){
|
||||
return gameLog;
|
||||
}
|
||||
|
||||
public static void initialize() {
|
||||
try {
|
||||
writer = new PrintWriter(gameLog);
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
package magic.ui.dialog;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.SwingConstants;
|
||||
|
||||
import magic.ui.*;
|
||||
import magic.ui.theme.Theme;
|
||||
import magic.ui.theme.ThemeFactory;
|
||||
import magic.ui.widget.FontsAndBorders;
|
||||
import magic.ui.widget.firemind.FiremindWorkerPanel;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class FiremindWorkerDialog extends JDialog implements ActionListener, PropertyChangeListener {
|
||||
|
||||
// not static so that it will reflect theme changes without restart.
|
||||
private final Theme THEME = ThemeFactory.getInstance().getCurrentTheme();
|
||||
private final JButton cancelButton = new JButton();
|
||||
private final JButton backgroundButton = new JButton();
|
||||
private final FiremindWorkerPanel firemindWorkerPanel = new FiremindWorkerPanel();
|
||||
|
||||
public FiremindWorkerDialog(final MagicFrame frame) {
|
||||
super(frame, true);
|
||||
|
||||
firemindWorkerPanel.addPropertyChangeListener("isRunning", this);
|
||||
setLookAndFeel();
|
||||
refreshLayout();
|
||||
setEscapeKeyAsCancelAction();
|
||||
this.setLocationRelativeTo(frame);
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
private JPanel getFieldsPanel() {
|
||||
final JPanel panel = new JPanel(new MigLayout("flowy, insets 8, gapy 10"));
|
||||
panel.add(firemindWorkerPanel, "w 100%");
|
||||
return panel;
|
||||
}
|
||||
|
||||
private void setEscapeKeyAsCancelAction() {
|
||||
final KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
|
||||
getRootPane().registerKeyboardAction(new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (!backgroundButton.isEnabled()) {
|
||||
doCancelAndClose();
|
||||
}
|
||||
}
|
||||
}, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
}
|
||||
|
||||
private void refreshLayout() {
|
||||
setLayout(new MigLayout("flowy, gapy 0, insets 0"));
|
||||
add(getDialogCaptionLabel(), "w 100%, h 26!");
|
||||
add(getFieldsPanel(), "w 100%");
|
||||
add(getButtonPanel(), "w 100%, aligny bottom, pushy");
|
||||
}
|
||||
|
||||
private JLabel getDialogCaptionLabel() {
|
||||
final JLabel lbl = new JLabel(getTitle());
|
||||
lbl.setOpaque(true);
|
||||
lbl.setBackground(THEME.getColor(Theme.COLOR_TITLE_BACKGROUND));
|
||||
lbl.setForeground(THEME.getColor(Theme.COLOR_TITLE_FOREGROUND));
|
||||
lbl.setFont(FontsAndBorders.FONT1.deriveFont(14f));
|
||||
lbl.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
return lbl;
|
||||
}
|
||||
|
||||
private void setLookAndFeel() {
|
||||
setTitle("Download Card Images");
|
||||
setResizable(false);
|
||||
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||
setSize(360, 460);
|
||||
setUndecorated(true);
|
||||
((JComponent)getContentPane()).setBorder(BorderFactory.createMatteBorder(0, 8, 8, 8, THEME.getColor(Theme.COLOR_TITLE_BACKGROUND)));
|
||||
//
|
||||
backgroundButton.setEnabled(false);
|
||||
}
|
||||
|
||||
|
||||
private void updateComponentState() {
|
||||
System.out.println("Update component state"+ (firemindWorkerPanel.isRunning() ? "true" : "false"));
|
||||
boolean isBackgroundButtonEnabled = false;
|
||||
final boolean isRunning = firemindWorkerPanel.isRunning();
|
||||
isBackgroundButtonEnabled = isBackgroundButtonEnabled || isRunning;
|
||||
backgroundButton.setEnabled(isBackgroundButtonEnabled);
|
||||
}
|
||||
|
||||
private JPanel getButtonPanel() {
|
||||
// cancel button
|
||||
cancelButton.setText("Cancel");
|
||||
cancelButton.setFocusable(false);
|
||||
cancelButton.addActionListener(this);
|
||||
// background button
|
||||
backgroundButton.setText("Run in background...");
|
||||
backgroundButton.setFocusable(false);
|
||||
backgroundButton.addActionListener(this);
|
||||
// layout
|
||||
final JPanel panel = new JPanel(new MigLayout());
|
||||
panel.add(backgroundButton, "w 100%, alignx left");
|
||||
panel.add(cancelButton, "w 100!, alignx right, pushx");
|
||||
return panel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(final ActionEvent event) {
|
||||
final Object source=event.getSource();
|
||||
if (source==cancelButton) {
|
||||
doCancelAndClose();
|
||||
} else if (source == backgroundButton) {
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void doCancelAndClose() {
|
||||
firemindWorkerPanel.doCancel();
|
||||
dispose();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if (evt.getPropertyName().equals("isRunning")) {
|
||||
updateComponentState();
|
||||
// final int progressValue = (int)evt.getNewValue();
|
||||
// progressBar.setIndeterminate(progressValue == 0 && importWorker.getProgressNote() != "");
|
||||
// progressBar.setValue(progressValue);
|
||||
// } else if (evt.getPropertyName().equalsIgnoreCase("state")) {
|
||||
// progressBar.setIndeterminate(!evt.getNewValue().toString().equalsIgnoreCase("done"));
|
||||
// } else if (evt.getPropertyName().equalsIgnoreCase("progressNote")) {
|
||||
// taskOutput.append(evt.getNewValue().toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
package magic.ui.screen;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import magic.ui.dialog.DownloadImagesDialog;
|
||||
import magic.ui.dialog.FiremindWorkerDialog;
|
||||
import magic.ui.dialog.ImportDialog;
|
||||
import magic.ui.screen.widget.MenuPanel;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
@ -12,6 +15,7 @@ import net.miginfocom.swing.MigLayout;
|
|||
public class SettingsMenuScreen extends AbstractScreen {
|
||||
|
||||
private static DownloadImagesDialog downloadDialog;
|
||||
private static FiremindWorkerDialog firemindWorkerDialog;
|
||||
|
||||
public SettingsMenuScreen() {
|
||||
setContent(getScreenContent());
|
||||
|
@ -49,6 +53,18 @@ public class SettingsMenuScreen extends AbstractScreen {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
menu.addMenuItem("Run Firemind Worker", new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(final ActionEvent e) {
|
||||
if (firemindWorkerDialog == null || !firemindWorkerDialog.isDisplayable()) {
|
||||
firemindWorkerDialog = new FiremindWorkerDialog(getFrame());
|
||||
} else {
|
||||
firemindWorkerDialog.setVisible(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
menu.addMenuItem("Toggle full-screen", new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(final ActionEvent e) {
|
||||
|
|
|
@ -0,0 +1,204 @@
|
|||
package magic.ui.widget.firemind;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.Proxy;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.SwingWorker;
|
||||
|
||||
import magic.FiremindQueueWorker;
|
||||
import magic.data.GeneralConfig;
|
||||
import magic.data.IconImages;
|
||||
import magic.utility.MagicFileSystem;
|
||||
import magic.utility.MagicFileSystem.DataPath;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class FiremindWorkerPanel extends JPanel {
|
||||
|
||||
protected final GeneralConfig CONFIG = GeneralConfig.getInstance();
|
||||
|
||||
private final JTextField accessKeyTextField = new JTextField();
|
||||
private final MigLayout migLayout = new MigLayout();
|
||||
protected final JLabel captionLabel = getCaptionLabel(getProgressCaption());
|
||||
private final JButton runButton = new JButton();
|
||||
private final JButton cancelButton = new JButton("Cancel");
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private boolean isCancelled = false;
|
||||
private SwingWorker<String, Void> firemindWorker;
|
||||
private boolean isRunning = false;
|
||||
protected SwingWorker<String, Void> getFiremindWorker(final Proxy proxy) {
|
||||
return new FiremindWorkerRunner(); //TODO (downloadList, CONFIG.getProxy());
|
||||
}
|
||||
protected String getProgressCaption(){
|
||||
if(isRunning){
|
||||
return "Running";
|
||||
}else{
|
||||
return "Not running";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected String getLogFilename() {
|
||||
return "fireindWorker.log";
|
||||
}
|
||||
|
||||
protected String getStartButtonCaption() {
|
||||
return "Start Firemind Worker";
|
||||
}
|
||||
|
||||
public FiremindWorkerPanel() {
|
||||
CONFIG.load();
|
||||
setLookAndFeel();
|
||||
refreshLayout();
|
||||
setActions();
|
||||
// buildDownloadImagesList();
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return this.isRunning;
|
||||
}
|
||||
|
||||
protected void saveDownloadLog(final List<String> downloadLog) {
|
||||
final Path logPath = MagicFileSystem.getDataPath(DataPath.LOGS).resolve(getLogFilename());
|
||||
System.out.println("saving log : " + logPath);
|
||||
try (final PrintWriter writer = new PrintWriter(logPath.toFile())) {
|
||||
for (String cardName : downloadLog) {
|
||||
writer.println(cardName);
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void setActions() {
|
||||
runButton.addActionListener(new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
CONFIG.setFiremindAccessToken(accessKeyTextField.getText().trim());
|
||||
CONFIG.save();
|
||||
|
||||
setRunningState();
|
||||
notifyStatusChanged(true);
|
||||
firemindWorker = getFiremindWorker(CONFIG.getProxy());
|
||||
firemindWorker.execute();
|
||||
}
|
||||
});
|
||||
cancelButton.addActionListener(new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
doCancelFiremindWorker();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void doCancel() {
|
||||
isCancelled = true;
|
||||
doCancelFiremindWorker();
|
||||
}
|
||||
|
||||
private void doCancelFiremindWorker() {
|
||||
if (firemindWorker != null && !firemindWorker.isCancelled() & !firemindWorker.isDone()) {
|
||||
firemindWorker.cancel(true);
|
||||
setButtonState(false);
|
||||
}
|
||||
}
|
||||
|
||||
// protected final void buildDownloadImagesList() {
|
||||
// if (!isCancelled) {
|
||||
// captionLabel.setIcon(IconImages.BUSY16);
|
||||
// captionLabel.setText(getProgressCaption());
|
||||
// imagesScanner = new ImagesScanner();
|
||||
// imagesScanner.execute();
|
||||
// downloadButton.setEnabled(false);
|
||||
// notifyStatusChanged(DownloaderState.SCANNING);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
protected void setButtonState(final boolean isRunning) {
|
||||
runButton.setVisible(!isRunning);
|
||||
cancelButton.setVisible(isRunning);
|
||||
refreshLayout();
|
||||
}
|
||||
|
||||
private void setRunningState() {
|
||||
setButtonState(true);
|
||||
captionLabel.setIcon(IconImages.BUSY16);
|
||||
}
|
||||
|
||||
private void refreshLayout() {
|
||||
removeAll();
|
||||
migLayout.setLayoutConstraints("flowy, insets 2, gapy 0");
|
||||
accessKeyTextField.setText(CONFIG.getFiremindAccessToken());
|
||||
add(accessKeyTextField, "w 100%");
|
||||
add(runButton.isVisible() ? runButton : cancelButton, "w 100%");
|
||||
}
|
||||
|
||||
private void setLookAndFeel() {
|
||||
// Layout manager.
|
||||
setLayout(migLayout);
|
||||
// download button
|
||||
runButton.setEnabled(true);
|
||||
runButton.setText(getStartButtonCaption());
|
||||
}
|
||||
|
||||
private JLabel getCaptionLabel(final String text) {
|
||||
final ImageIcon ii = IconImages.BUSY16;
|
||||
final JLabel lbl = new JLabel(ii);
|
||||
lbl.setText(text);
|
||||
lbl.setHorizontalAlignment(SwingConstants.LEFT);
|
||||
lbl.setHorizontalTextPosition(SwingConstants.LEADING);
|
||||
lbl.setOpaque(false);
|
||||
lbl.setFont(lbl.getFont().deriveFont(Font.BOLD));
|
||||
return lbl;
|
||||
}
|
||||
|
||||
protected void notifyStatusChanged(boolean newValue) {
|
||||
assert SwingUtilities.isEventDispatchThread();
|
||||
final boolean oldState = this.isRunning;
|
||||
this.isRunning = newValue;
|
||||
firePropertyChange("isRunning", oldState, newValue);
|
||||
}
|
||||
|
||||
private class FiremindWorkerRunner extends SwingWorker<String, Void> {
|
||||
@Override
|
||||
protected String doInBackground() throws Exception {
|
||||
String[] arguments = new String[]{""};
|
||||
FiremindQueueWorker.main(arguments);
|
||||
return "finished";
|
||||
}
|
||||
@Override
|
||||
protected void done() {
|
||||
// try {
|
||||
// files = get();
|
||||
// } catch (InterruptedException | ExecutionException ex) {
|
||||
// throw new RuntimeException(ex);
|
||||
// } catch (CancellationException ex) {
|
||||
//// System.out.println("ImagesScanner cancelled by user!");
|
||||
// }
|
||||
// if (!isCancelled) {
|
||||
// downloadButton.setEnabled(files.size() > 0);
|
||||
// captionLabel.setIcon(null);
|
||||
// captionLabel.setText(getProgressCaption() + files.size());
|
||||
// }
|
||||
// notifyStatusChanged(DownloaderState.STOPPED);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue